remove everything except codemirror stuff
This commit is contained in:
parent
6e61c58fe3
commit
beebf60369
39 changed files with 1 additions and 1512 deletions
71
bb.edn
71
bb.edn
|
|
@ -1,71 +0,0 @@
|
|||
{:deps {io.github.babashka/sci.nrepl
|
||||
#_{:local/root "../sci.nrepl"}
|
||||
{:git/sha "2f8a9ed2d39a1b09d2b4d34d95494b56468f4a23"}
|
||||
io.github.babashka/http-server
|
||||
{:git/sha "b38c1f16ad2c618adae2c3b102a5520c261a7dd3"}}
|
||||
|
||||
:tasks
|
||||
{:requires ([babashka.fs :as fs]
|
||||
[cheshire.core :as json]
|
||||
[babashka.process :as p :refer [process]])
|
||||
|
||||
clean {:doc "Start from clean slate."
|
||||
:task (do (run! fs/delete (fs/list-dir (fs/file "resources" "public" "js") "**.*"))
|
||||
(fs/delete-tree ".cpcache")
|
||||
(fs/delete-tree ".shadow-cljs"))}
|
||||
|
||||
shadow:watch {:doc "Development build. Starts webserver and watches for changes."
|
||||
:task (clojure {:extra-env {"SCI_ELIDE_VARS" "true"}}
|
||||
"-M:dev -m shadow.cljs.devtools.cli watch main")}
|
||||
|
||||
http-server {:doc "Starts http server for serving static files"
|
||||
:requires ([babashka.http-server :as http])
|
||||
:task (do (http/serve {:port 1341 :dir "resources/public"})
|
||||
(println "Serving static assets at http://localhost:1341"))}
|
||||
|
||||
browser-nrepl {:doc "Start browser nREPL"
|
||||
:requires ([sci.nrepl.browser-server :as bp])
|
||||
:task (bp/start! {})}
|
||||
|
||||
-dev {:depends [shadow:watch browser-nrepl http-server]}
|
||||
|
||||
dev {:doc "Development build. Starts webserver and watches for changes."
|
||||
:task (do (run '-dev {:parallel true})
|
||||
(deref (promise)))}
|
||||
|
||||
prod {:doc "Builds production artifacts."
|
||||
:task (clojure {:extra-env {"SCI_ELIDE_VARS" "true"}}
|
||||
"-M:dev -m shadow.cljs.devtools.cli release main")}
|
||||
|
||||
dist {:doc "Prepare dist folder for npm package"
|
||||
:depends [prod]
|
||||
:task (do
|
||||
(fs/delete-tree "dist")
|
||||
(fs/create-dirs "dist")
|
||||
(run! (fn [f] (fs/copy f "dist"))
|
||||
(fs/glob "resources/public/js" "*.js")))}
|
||||
|
||||
bump-version {:doc "Bumps package.json and pushes new git tag"
|
||||
:task (do (shell "npm version patch")
|
||||
(shell "git push --atomic origin main"
|
||||
(str "v" (:version (json/parse-string (slurp "package.json") true)))))}
|
||||
|
||||
npm-publish {:doc "Updates NPM ibrary"
|
||||
:task (do (run 'dist)
|
||||
(run 'bump-version)
|
||||
(shell "npm publish"))}
|
||||
|
||||
replace-version {:doc "Ported from bash one-liners. Expects two versions.
|
||||
TODO: port to Clojure.
|
||||
TODO: skip changelog.md
|
||||
"
|
||||
:task
|
||||
(let [[prev next] *command-line-args*]
|
||||
(-> (process ["bash" "-c"
|
||||
(format "rg %s --files-with-matches | xargs sed -i '' 's/%s/%s/g'"
|
||||
prev prev next)]
|
||||
{:inherit true})
|
||||
p/check))}
|
||||
|
||||
gh-pages {:doc "Updates Github pages with new release build."
|
||||
:task (shell "script/release.clj")}}}
|
||||
26
deps.edn
26
deps.edn
|
|
@ -1,26 +0,0 @@
|
|||
{:paths ["src" "resources"]
|
||||
|
||||
:deps
|
||||
{org.clojure/clojure {:mvn/version "1.11.1"}
|
||||
org.babashka/sci {:git/url "https://github.com/babashka/sci"
|
||||
:git/sha "a85c488ee45700bcbe67bc01ab1c27407fff7887"}
|
||||
#_{:local/root "../babashka/sci"}
|
||||
reagent/reagent {:mvn/version "1.1.1"}
|
||||
re-frame/re-frame {:mvn/version "1.3.0"}
|
||||
cljsjs/react {:mvn/version "18.2.0-1"}
|
||||
cljsjs/react-dom {:mvn/version "18.2.0-1"}
|
||||
cljsjs/react-dom-server {:mvn/version "18.2.0-1"}
|
||||
cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}
|
||||
funcool/promesa {:mvn/version "10.0.575"}
|
||||
io.github.babashka/sci.nrepl
|
||||
#_{:local/root "../sci.nrepl"}
|
||||
{:git/url "https://github.com/babashka/sci.nrepl"
|
||||
:git/sha "2f8a9ed2d39a1b09d2b4d34d95494b56468f4a23"}
|
||||
io.github.babashka/sci.configs
|
||||
#_{:local/root "/Users/borkdude/dev/sci.configs"}
|
||||
{:git/url "https://github.com/babashka/sci.configs"
|
||||
:git/sha "bf8d209e4aeabb92cb1be04e3d8f789583d5f449"}}
|
||||
:aliases
|
||||
{:dev
|
||||
{:extra-paths ["dev"]
|
||||
:extra-deps {thheller/shadow-cljs {:mvn/version "2.20.15"}}}}}
|
||||
109
doc/dev.md
109
doc/dev.md
|
|
@ -1,109 +0,0 @@
|
|||
# Dev
|
||||
|
||||
## Workflow
|
||||
|
||||
### Start with an issue before writing code
|
||||
|
||||
Before writing any code, please create an issue first that describes the problem
|
||||
you are trying to solve with alternatives that you have considered. A little bit
|
||||
of prior communication can save a lot of time on coding. Keep the problem as
|
||||
small as possible. If there are two problems, make two issues. We discuss the
|
||||
issue and if we reach an agreement on the approach, it's time to move on to a
|
||||
PR.
|
||||
|
||||
### Follow up with a pull request
|
||||
|
||||
Post a corresponding PR with the smallest change possible to address the
|
||||
issue. Then we discuss the PR, make changes as needed and if we reach an
|
||||
agreement, the PR will be merged.
|
||||
|
||||
<!-- ### Tests -->
|
||||
|
||||
<!-- Each bug fix, change or new feature should be tested well to prevent future -->
|
||||
<!-- regressions. -->
|
||||
|
||||
### Force-push
|
||||
|
||||
Please do not use `git push --force` on your PR branch for the following
|
||||
reasons:
|
||||
|
||||
- It makes it more difficult for others to contribute to your branch if needed.
|
||||
- It makes it harder to review incremental commits.
|
||||
- Links (in e.g. e-mails and notifications) go stale and you're confronted with:
|
||||
this code isn't here anymore, when clicking on them.
|
||||
- CircleCI doesn't play well with it: it might try to fetch a commit which
|
||||
doesn't exist anymore.
|
||||
- Your PR will be squashed anyway.
|
||||
|
||||
## Developing
|
||||
|
||||
Run `bb dev` to start shadow-cljs compilation in watch mode.
|
||||
|
||||
<!-- ## Testing -->
|
||||
|
||||
<!-- You can run tests using `bb run-tests` and `bb run-integration-tests`. -->
|
||||
|
||||
## Release
|
||||
|
||||
Static files including compiled JS are hosted on Github. This is set up like
|
||||
described
|
||||
[here](https://medium.com/linagora-engineering/deploying-your-js-app-to-github-pages-the-easy-way-or-not-1ef8c48424b7):
|
||||
|
||||
All the commands below assume that you already have a git project initialized and that you are in its root folder.
|
||||
|
||||
```
|
||||
# Create an orphan branch named gh-pages
|
||||
git checkout --orphan gh-pages
|
||||
# Remove all files from staging
|
||||
git rm -rf .
|
||||
# Create an empty commit so that you will be able to push on the branch next
|
||||
git commit --allow-empty -m "Init empty branch"
|
||||
# Push the branch
|
||||
git push origin gh-pages
|
||||
```
|
||||
|
||||
Now that the branch is created and pushed to origin, let’s configure the worktree correctly:
|
||||
|
||||
```
|
||||
# Come back to master
|
||||
git checkout main
|
||||
# Add gh-pages to .gitignore
|
||||
echo "gh-pages/" >> .gitignore
|
||||
git worktree add gh-pages gh-pages
|
||||
```
|
||||
|
||||
After cloning this repo to a new dir:
|
||||
|
||||
```
|
||||
git fetch origin gh-pages
|
||||
git worktree prune
|
||||
git worktree add gh-pages gh-pages
|
||||
```
|
||||
|
||||
To deploy to Github Pages:
|
||||
|
||||
```
|
||||
script/release.clj
|
||||
```
|
||||
|
||||
To create a new NPM release:
|
||||
|
||||
- Prepare version `package.json`, except patch (if anything should change here)
|
||||
- Run `bb npm-publish`: this will compile, bump patch version, create tag and and push to npm and Github
|
||||
- `bb replace-version 0.4.11 0.5.14`
|
||||
- Create Github release with updated links from `doc/links.md`
|
||||
- `bb gh-pages`
|
||||
|
||||
To upgrade examples:
|
||||
|
||||
```
|
||||
rg '0.0.1' --files-with-matches | xargs sed -i '' 's/0.0.5.14.1.0/g'
|
||||
bb release
|
||||
cd gh-pages
|
||||
git checkout -b v0.5.14
|
||||
git push --set-upstream origin v0.5.14
|
||||
git checkout gh-pages
|
||||
cd ..
|
||||
```
|
||||
|
||||
Then make a new release on Github with the `v0.5.14` tag.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.cljs-ajax.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.reagent.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.re-frame.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.promesa.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.pprint.js
|
||||
https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.nrepl.js
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# nREPL
|
||||
|
||||
To connect to a Scittle nREPL server from your editor, follow these steps. The
|
||||
setup described here, can be found in this directory.
|
||||
|
||||
In babashka or Clojure JVM, use the
|
||||
[sci.nrepl](https://github.com/babashka/sci.nrepl) dependency and run:
|
||||
|
||||
``` clojure
|
||||
(require '[sci.nrepl.browser-server :as nrepl])
|
||||
(nrepl/start! {:nrepl-port 1339 :websocket-port 1340})
|
||||
```
|
||||
|
||||
This will run an nREPL server on port 1339 and a websocket server on port 1340.
|
||||
Your editor's nREPL client will connect to port 1339 and your browser, running
|
||||
scittle, will connect to port 1340. The nREPL server forwards messages to the
|
||||
browser via the websocket connection.
|
||||
|
||||
In your scittle website, you will need to include the following, in addition to
|
||||
the normal routine:
|
||||
|
||||
``` html
|
||||
<script>var SCITTLE_NREPL_WEBSOCKET_PORT = 1340;</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.nrepl.js" type="application/javascript"></script>
|
||||
```
|
||||
|
||||
Also include the CLJS file that you want to evaluate with nREPL:
|
||||
|
||||
``` html
|
||||
<script src="playground.cljs" type="application/x-scittle"></script>
|
||||
```
|
||||
|
||||
Then visit `playground.cljs` in your editor and connect to the nREPL server,
|
||||
and start evaluating!
|
||||
|
||||
See the `index.html` file for an example.
|
||||
|
||||
When you run `bb dev` in this directory, and then open `http://localhost:1341`
|
||||
you should be able evaluate expressions in `playground.cljs`. See a demo
|
||||
[here](https://twitter.com/borkdude/status/1526285565343281159).
|
||||
|
||||
Note that the nREPL server connection stays alive even after the browser window
|
||||
refreshes.
|
||||
|
||||
### CIDER
|
||||
|
||||
Currently when connecting from CIDER, you need to use this snippet:
|
||||
|
||||
``` elisp
|
||||
(cider-register-cljs-repl-type 'sci-js "(+ 1 2 3)")
|
||||
|
||||
(defun mm/cider-connected-hook ()
|
||||
(when (eq 'sci-js cider-cljs-repl-type)
|
||||
(setq-local cider-show-error-buffer nil)
|
||||
(cider-set-repl-type 'cljs)))
|
||||
|
||||
(add-hook 'cider-connected-hook #'mm/cider-connected-hook)
|
||||
```
|
||||
|
||||
Then choose `cider-connect-cljs`, select port `1339`, followed by the `sci-js`
|
||||
REPL type.
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{:deps {io.github.babashka/sci.nrepl
|
||||
{:git/sha "2f8a9ed2d39a1b09d2b4d34d95494b56468f4a23"}
|
||||
io.github.babashka/http-server
|
||||
{:git/sha "b38c1f16ad2c618adae2c3b102a5520c261a7dd3"}}
|
||||
:tasks {http-server {:doc "Starts http server for serving static files"
|
||||
:requires ([babashka.http-server :as http])
|
||||
:task (do (http/serve {:port 1341 :dir "."})
|
||||
(println "Serving static assets at http://localhost:1341"))}
|
||||
|
||||
browser-nrepl {:doc "Start browser nREPL"
|
||||
:requires ([sci.nrepl.browser-server :as bp])
|
||||
:task (bp/start! {})}
|
||||
|
||||
-dev {:depends [http-server browser-nrepl]}
|
||||
|
||||
dev {:task (do (run '-dev {:parallel true})
|
||||
(deref (promise)))}}}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.js" type="application/javascript"></script>
|
||||
<script>var SCITTLE_NREPL_WEBSOCKET_PORT = 1340;</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.nrepl.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle" src="playground.cljs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle</h1>
|
||||
<h2>What is this?</h2>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
(ns playground)
|
||||
|
||||
(+ 1 2 3)
|
||||
|
||||
(->
|
||||
(js/document.getElementsByTagName "body")
|
||||
first
|
||||
(.append
|
||||
(doto (js/document.createElement "p")
|
||||
(.append
|
||||
(js/document.createTextNode "there")))))
|
||||
|
||||
(defn foo [])
|
||||
|
||||
(js/alert "Isn't this cool? :)")
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
scittle.core.eval_script_tags();
|
||||
</script>
|
||||
|
||||
<script type="application/x-scittle" src="cljs/codemirror.cljs"></script>
|
||||
<script type="application/x-scittle" src="src/codemirror.cljs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle">
|
||||
(defn my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
|
||||
(set! (.-my_alert js/window) my-alert)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle</h1>
|
||||
|
||||
<pre>
|
||||
<code class="html">
|
||||
<head>
|
||||
<script src="https://babashka.github.io/scittle/js/scittle.js" type="application/javascript"></script>
|
||||
|
||||
<script type="application/x-scittle">
|
||||
(defn my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
|
||||
;; export function to use from JavaScript:
|
||||
(set! (.-my_alert js/window) my-alert)
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
</body></code></pre>
|
||||
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="https://babashka.github.io/scittle/js/scittle.js" type="application/javascript"></script>
|
||||
|
||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://babashka.github.io/scittle/js/scittle.reagent.js" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js" type="text/javascript"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/languages/clojure.min.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/zenburn.min.css" integrity="sha512-JPxjD2t82edI35nXydY/erE9jVPpqxEJ++6nYEoZEpX2TRsmp2FpZuQqZa+wBCen5U16QZOkMadGXHCfp+tUdg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle Bookmarklet creator</h1>
|
||||
<h2>What is Scittle?</h2>
|
||||
<p>Read <a href="index.html">the main page</a> for more details.</p>
|
||||
<h2>The bookmarklet editor</h2>
|
||||
<div id="app"></div>
|
||||
<p>The following source was loaded and interpreted
|
||||
from <a href="cljs/bookmarklet.cljs"><tt>cljs/bookmarklet.cljs</tt></a> using the
|
||||
script tag:
|
||||
<pre><code class="html">
|
||||
<script type="application/x-scittle" src="cljs/bookmarklet.cljs"></script>
|
||||
|
||||
</code></pre>
|
||||
</p>
|
||||
<pre><code class="language-clojure" id="cljs"></code></pre>
|
||||
<script type="application/x-scittle">
|
||||
(defn set-text [progress-event]
|
||||
(let [elt (.getElementById js/document "cljs")]
|
||||
(set! (.-innerHTML elt) (.. progress-event -srcElement -responseText))
|
||||
(.highlightAll js/hljs)))
|
||||
(def oreq (js/XMLHttpRequest.))
|
||||
(.addEventListener oreq "load" set-text)
|
||||
(.open oreq "GET" "cljs/bookmarklet.cljs")
|
||||
(.send oreq)
|
||||
</script>
|
||||
|
||||
<script type="application/x-scittle" src="cljs/bookmarklet.cljs"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
(ns bookmarklet
|
||||
(:require [reagent.core :as r]
|
||||
[reagent.dom :as rdom]))
|
||||
|
||||
(defn append-tag [tag {:keys [body onload onerror] :as attributes}]
|
||||
(str "var s=document.createElement('" (name tag) "');"
|
||||
(clojure.string/join ";" (map (fn [[k v]] (str "s.setAttribute('" (name k) "','" (name v) "')")) (dissoc attributes :body :onload :onerror)))
|
||||
(when body
|
||||
(str ";s.innerText=" body))
|
||||
(when onload
|
||||
(str ";s.onload=" onload))
|
||||
(when onerror
|
||||
(str ";s.onerror=" onerror))
|
||||
";document.body.appendChild(s);"))
|
||||
|
||||
(defn pr-code [code-str]
|
||||
(pr-str (str "#_CODE_" code-str "#_CODE_")))
|
||||
|
||||
(defn read-code [code-str]
|
||||
(when-let [raw-code (second (re-find #"#_CODE_(.+)#_CODE_" code-str))]
|
||||
;; Use read-string to undo escaping of characters by pr-str (e.g. newlines)
|
||||
(read-string (str "\"" raw-code "\""))))
|
||||
|
||||
(defn load-gist [gist callback]
|
||||
(let [set-content (fn [progress-event]
|
||||
(callback (.. progress-event -srcElement -responseText)))
|
||||
oreq (js/XMLHttpRequest.)]
|
||||
(.addEventListener oreq "load" set-content)
|
||||
(.open oreq "GET" (str "https://gist.githubusercontent.com/" gist "/raw"))
|
||||
(.send oreq)))
|
||||
|
||||
|
||||
(defn bookmarklet-href [code-str]
|
||||
(str "javascript:(function(){"
|
||||
"var runCode = function() {
|
||||
try {
|
||||
scittle.core.eval_string(" (pr-code code-str) ")
|
||||
} catch (error) {
|
||||
console.log('Error in code', error);
|
||||
alert('Error running code, see console')
|
||||
}
|
||||
};"
|
||||
"if(typeof scittle === 'undefined'){"
|
||||
(append-tag :script {:src "https://babashka.github.io/scittle/js/scittle.js"
|
||||
:onerror "function(){alert('Error loading ' + this.src)}"
|
||||
:onload "runCode"})
|
||||
"} else {
|
||||
runCode() }"
|
||||
"})();"))
|
||||
|
||||
(defn query-params []
|
||||
(let [query-str (.substring js/window.location.search 1)]
|
||||
(into {}
|
||||
(map (fn [pair]
|
||||
(let [[k v] (.split pair "=" 2)]
|
||||
[(keyword (js/decodeURIComponent k))
|
||||
(js/decodeURIComponent v)])))
|
||||
(.split query-str "&"))))
|
||||
|
||||
|
||||
(def *initial-name (r/atom nil))
|
||||
(def *initial-code (r/atom nil))
|
||||
|
||||
;; Initialize code
|
||||
(let [{:keys [gist code name]} (query-params)]
|
||||
(cond gist
|
||||
(do
|
||||
(reset! *initial-name "---")
|
||||
(reset! *initial-code ";; loading from gist")
|
||||
(load-gist gist (fn [content]
|
||||
(let [[code meta-str] (reverse (clojure.string/split content #";;---+\n"))
|
||||
{bookmark-name :name} (when meta-str
|
||||
(read-string meta-str))]
|
||||
(when bookmark-name
|
||||
(reset! *initial-name bookmark-name))
|
||||
(reset! *initial-code code)))))
|
||||
code
|
||||
(do
|
||||
(reset! *initial-name (or name "My first bookmarklet"))
|
||||
(reset! *initial-code code))
|
||||
:else
|
||||
(do
|
||||
(reset! *initial-name "My first bookmarklet")
|
||||
(reset! *initial-code (str "; This is the code of your bookmarklet\n"
|
||||
(pr-str '(js/alert "Hello")))))))
|
||||
|
||||
(defn bookmark-name-field [initial-name *bookmark-name]
|
||||
(let [*name (r/atom initial-name)]
|
||||
[(fn []
|
||||
[:input {:type "text"
|
||||
:placeholder "The name of the Bookmarklet"
|
||||
:value @*name
|
||||
:on-change (fn [e]
|
||||
(let [v (.. e -target -value)]
|
||||
(reset! *name v)
|
||||
(reset! *bookmark-name
|
||||
(if (clojure.string/blank? v)
|
||||
(str "Bookmarklet " (rand-int 1000))
|
||||
v))))}])]))
|
||||
|
||||
(defn editor [*code]
|
||||
[:textarea
|
||||
{:rows 10 :cols 80
|
||||
:value @*code
|
||||
:on-drop (fn [e]
|
||||
(let [bookmarklet (js/decodeURIComponent (.. e -dataTransfer (getData "text")))
|
||||
cljs-snippet (read-code bookmarklet)
|
||||
new-code (if cljs-snippet
|
||||
(str "; Extracted snippet\n" cljs-snippet)
|
||||
(str "; Failed to extract snippet\n" bookmarklet))]
|
||||
(js/console.log "Dropped" bookmarklet)
|
||||
(set! (.. e -target -value) new-code)
|
||||
(reset! *code new-code)
|
||||
(.preventDefault e)))
|
||||
:on-change (fn [e] (reset! *code (.. e -target -value)))}])
|
||||
|
||||
|
||||
|
||||
(defn workspace []
|
||||
(let [value @*initial-code
|
||||
*code (r/atom value)
|
||||
bookmark-name @*initial-name
|
||||
*bookmark-name (r/atom bookmark-name)]
|
||||
[:div
|
||||
[bookmark-name-field bookmark-name *bookmark-name]
|
||||
[:br]
|
||||
[editor *code]
|
||||
[:br]
|
||||
[:br]
|
||||
"Click the following link or drag it to the bookmarks bar: "
|
||||
[(fn []
|
||||
[(fn [] [:a {:href (bookmarklet-href @*code)} @*bookmark-name])])
|
||||
*code]
|
||||
[:br]
|
||||
[(fn []
|
||||
[:a {:href (str "?name=" (js/encodeURIComponent @*bookmark-name)
|
||||
"&code=" (js/encodeURIComponent @*code)
|
||||
"%20")} "Copy this link to share ⤴️"])]]))
|
||||
|
||||
(rdom/render [workspace] (.getElementById js/document "app"))
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
(ns nrepl-playground)
|
||||
|
||||
(+ 1 2 3)
|
||||
|
||||
(->
|
||||
(js/document.getElementsByTagName "body")
|
||||
first
|
||||
(.append
|
||||
(doto (js/document.createElement "p")
|
||||
(.append
|
||||
(js/document.createTextNode "there")))))
|
||||
|
||||
(defn foo [])
|
||||
|
||||
(js/alert "Isn't this cool? :)")
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
(defn my-alert2 []
|
||||
(js/alert "My alert 2!"))
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
(ns tictactoe
|
||||
"Ported from https://github.com/borkdude/tictactoe-cljs"
|
||||
(:require [reagent.core :as r]
|
||||
[reagent.dom :as rdom]))
|
||||
|
||||
(def empty-board [[\- \- \-]
|
||||
[\- \- \-]
|
||||
[\- \- \-]])
|
||||
|
||||
(def state (r/atom {:board empty-board :player \X}))
|
||||
|
||||
(defn get-board-cell
|
||||
([board row col]
|
||||
(get-in board [row col])))
|
||||
|
||||
(defn get-player [app-state]
|
||||
(-> app-state :game-state :player))
|
||||
|
||||
(defn other-player [player]
|
||||
(if (= player \X) \O \X))
|
||||
|
||||
(defn winner-in-rows? [board player]
|
||||
(boolean (some (fn [row] (every? (fn [c] (= c player)) row)) board)))
|
||||
|
||||
(defn transposed-board [board]
|
||||
(vec (apply map vector board)))
|
||||
|
||||
(defn winner-in-cols? [board player]
|
||||
(winner-in-rows? (transposed-board board) player))
|
||||
|
||||
(defn winner-in-diagonals? [board player]
|
||||
(let [diag-coords [[[0 0] [1 1] [2 2]]
|
||||
[[0 2] [1 1] [2 0]]]]
|
||||
(boolean (some (fn [coords]
|
||||
(every? (fn [coord]
|
||||
(= player (apply get-board-cell board coord)))
|
||||
coords))
|
||||
diag-coords))))
|
||||
|
||||
(defn winner?
|
||||
"checks if there is a winner. when called with no args, checks for player X and player O.
|
||||
returns the character for the winning player, nil if there is no winner"
|
||||
([board]
|
||||
(boolean (or (winner? board \X)
|
||||
(winner? board \O))))
|
||||
([board player]
|
||||
(when (or (winner-in-rows? board player)
|
||||
(winner-in-cols? board player)
|
||||
(winner-in-diagonals? board player))
|
||||
player)))
|
||||
|
||||
(defn full-board?
|
||||
[board]
|
||||
(let [all-cells (apply concat board)]
|
||||
(not-any? #(= % \-) all-cells)))
|
||||
|
||||
(defn new-state [old-state row col]
|
||||
(if (and (= (get-board-cell (:board old-state) row col) \-)
|
||||
(not (winner? (:board old-state))))
|
||||
{:board (assoc-in (:board old-state) [row col] (:player old-state))
|
||||
:player (other-player (:player old-state))}
|
||||
old-state))
|
||||
|
||||
(defn tictactoe []
|
||||
[:div
|
||||
(if (winner? (:board @state))
|
||||
(str "The winner is " (other-player (:player @state)))
|
||||
(if (full-board? (:board @state))
|
||||
"It's a draw"
|
||||
(str "Your turn, player " (:player @state))))
|
||||
(let [board (-> @state :board)]
|
||||
[:table
|
||||
[:tbody
|
||||
(map-indexed
|
||||
(fn [i row]
|
||||
^{:key i}
|
||||
[:tr
|
||||
(map-indexed (fn [j elt]
|
||||
^{:key j}
|
||||
[:td {:on-click (fn []
|
||||
(swap! state new-state i j))}elt])
|
||||
row)])
|
||||
board)]])])
|
||||
|
||||
(rdom/render [tictactoe] (.getElementById js/document "app"))
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
div#app
|
||||
{
|
||||
color:#666;
|
||||
font-family: Arial;
|
||||
}
|
||||
|
||||
div#app td
|
||||
{
|
||||
width:50px;
|
||||
height:50px;
|
||||
border:1px solid #dedede;
|
||||
background:#fff;
|
||||
margin:1px;
|
||||
color:#666;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
div#app td:hover
|
||||
{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
<script>scittle.core.disable_auto_eval()</script>
|
||||
<!-- to do the same as scittle does by default: -->
|
||||
<!-- <script>scittle.core.eval_string("(.addEventListener js/document \"DOMContentLoaded\" js/scittle.core.eval_script_tags false)")</script> -->
|
||||
<script type="application/x-scittle">
|
||||
(defn my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
|
||||
(set! (.-my_alert js/window) my-alert)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle</h1>
|
||||
<p>On this page, auto-eval is disabled.</p>
|
||||
<p><button onclick="scittle.core.eval_script_tags()">
|
||||
Click me to evaluate script tags!
|
||||
</button></p>
|
||||
<p><button onclick="my_alert()">
|
||||
Click me to run evaluated function!
|
||||
</button></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.js" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.cljs-ajax.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle">
|
||||
(require '[ajax.core :refer [GET]])
|
||||
|
||||
(defn handler [response]
|
||||
(js/alert (str response)))
|
||||
|
||||
(defn make-request []
|
||||
(GET "html/cljs-ajax.html" {:handler handler}))
|
||||
|
||||
;; export function to use from JavaScript:
|
||||
(set! (.-make_request js/window) make-request)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="make_request()">
|
||||
Click me!
|
||||
</button>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle">
|
||||
(defn my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
;; export function to use from JavaScript:
|
||||
(set! (.-my_alert js/window) my-alert)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="../js/scittle.js" type="application/javascript"></script>
|
||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
|
||||
<script src="../js/scittle.reagent.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle">
|
||||
(defn f [x]
|
||||
(inc n))
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.js" type="application/javascript"></script>
|
||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/scittle@0.5.14/dist/scittle.reagent.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle">
|
||||
(require '[reagent.core :as r]
|
||||
'[reagent.dom :as rdom])
|
||||
|
||||
(def state (r/atom {:clicks 0}))
|
||||
|
||||
(defn my-component []
|
||||
[:div
|
||||
[:p "Clicks: " (:clicks @state)]
|
||||
[:p [:button {:on-click #(swap! state update :clicks inc)}
|
||||
"Click me!"]]])
|
||||
|
||||
(rdom/render [my-component] (.getElementById js/document "app"))
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
||||
<script src="js/scittle.reagent.js" type="application/javascript"></script>
|
||||
<!-- <script src="js/scittle.re-frame.js" type="application/javascript"></script> -->
|
||||
<script src="js/scittle.cljs-ajax.js" type="application/javascript"></script>
|
||||
<script src="js/scittle.pprint.js" type="application/javascript"></script>
|
||||
|
||||
<script type="application/x-scittle">
|
||||
(defn my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
|
||||
(set! (.-my_alert js/window) my-alert)
|
||||
|
||||
(require '[reagent.core :as r]
|
||||
'[reagent.dom :as rdom])
|
||||
|
||||
(def state (r/atom {:clicks 0}))
|
||||
|
||||
#_(require '[re-frame.core :as rf]
|
||||
'[reagent.dom :as rdom])
|
||||
#_(rf/reg-event-fx ::click (fn [{:keys [db]} [_]] {:db (update db :clicks (fnil inc 0))}))
|
||||
#_(rf/reg-sub ::clicks (fn [db _] (:clicks db)))
|
||||
|
||||
(defn my-component []
|
||||
[:div
|
||||
[:p "Clicks: " (:clicks @state)]
|
||||
[:p [:button {:on-click #(do (swap! state update :clicks inc)
|
||||
#_(rf/dispatch [::click]))}
|
||||
"Click me!"]]])
|
||||
|
||||
#_(defn re-frame-component []
|
||||
(let [clicks (rf/subscribe [::clicks])]
|
||||
[:div "Clicks:" @clicks]))
|
||||
|
||||
(rdom/render [my-component] (.getElementById js/document "app"))
|
||||
|
||||
#_(rdom/render [re-frame-component] (.getElementById js/document "re-frame"))
|
||||
|
||||
(require '[ajax.core :refer [GET]])
|
||||
|
||||
(defn handler [response]
|
||||
(js/alert (str response)))
|
||||
|
||||
(defn make-request []
|
||||
(GET "html/cljs-ajax.html" {:handler handler}))
|
||||
|
||||
;; export function to use from JavaScript:
|
||||
(set! (.-make_request js/window) make-request)
|
||||
|
||||
(def code-tags (.querySelectorAll js/document "code[data-type='scittle']"))
|
||||
|
||||
(require '[goog.object :as gobject])
|
||||
(doseq [code code-tags]
|
||||
(let [src (.getAttribute code "data-src")
|
||||
req (js/XMLHttpRequest.)]
|
||||
(.open req "GET" src true)
|
||||
(set! (.-onload req)
|
||||
(fn []
|
||||
(let [response (gobject/get req "response")]
|
||||
(set! (.-innerText code) response)
|
||||
(.highlightElement js/hljs code))))
|
||||
(.send req)))
|
||||
|
||||
</script>
|
||||
|
||||
<script src="cljs/script.cljs" type="application/x-scittle"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/zenburn.min.css" integrity="sha512-JPxjD2t82edI35nXydY/erE9jVPpqxEJ++6nYEoZEpX2TRsmp2FpZuQqZa+wBCen5U16QZOkMadGXHCfp+tUdg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div style="float: right;">
|
||||
<a href="https://gitHub.com/babashka/scittle"><img src="https://img.shields.io/github/stars/babashka/scittle.svg?style=social&label=Star"></a></div>
|
||||
|
||||
<h1>Scittle</h1>
|
||||
<h2>What is this?</h2>
|
||||
<p>This project exposes the <a href="https://github.com/babashka/sci">Small Clojure Interpreter</a> in the
|
||||
browser in such a way that you can use it with the <tt>script</tt> tag.</p>
|
||||
|
||||
<a name="usage"></a>
|
||||
<h2><a href="#usage">Usage</a></h2>
|
||||
|
||||
To embed scittle in your website, it is recommended to use the links
|
||||
published to
|
||||
the <a href="https://github.com/babashka/scittle/releases/tag/v0.5.14">releases
|
||||
page</a>.
|
||||
|
||||
Include <tt>scittle.js</tt> and write a <tt>script</tt> tag
|
||||
where <tt>type</tt> is set
|
||||
to <tt>application/x-scittle</tt>.
|
||||
|
||||
<pre><code data-type="scittle" data-src="html/export.html" class="html"></code></pre>
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
|
||||
<a name="src"></a>
|
||||
<h2><a href="#src">Source from file</a></h2>
|
||||
|
||||
When you have a file on your server, say <tt>cljs/script.cljs</tt>, you can load it using the <tt>src</tt> attribute:
|
||||
|
||||
<pre><code id="scittle-tag-example" class="html">
|
||||
<script src="cljs/script.cljs" type="application/x-scittle"></script>
|
||||
</code></pre>
|
||||
|
||||
<script type="text/javascript">hljs.highlightElement(document.getElementById("scittle-tag-example"));</script>
|
||||
|
||||
<a name="reagent"></a>
|
||||
<h2><a href="#reagent">Reagent plugin</a></h2>
|
||||
|
||||
To enable <a href="https://github.com/reagent-project/reagent">reagent</a>,
|
||||
in addition to <tt>scittle.js</tt>, you need to include React
|
||||
and <tt>scittle.reagent.js</tt>:
|
||||
|
||||
<pre><code data-type="scittle" data-src="html/reagent.html" class="html"></code></pre>
|
||||
|
||||
<div id="app"></div>
|
||||
|
||||
|
||||
<a name="re-frame"></a>
|
||||
<h2><a href="#re-frame">Re-frame plugin</a></h2>
|
||||
|
||||
To enable <a href="https://github.com/day8/re-frame">re-frame</a>,
|
||||
in addition to the files needed for reagent, you need to include <tt>scittle.re-frame.js</tt>.
|
||||
Also see the <a href="codemirror.html">codemirror</a> playground.
|
||||
|
||||
<a name="cljs-ajax"></a>
|
||||
<h2><a href="#cljs-ajax">Cljs-ajax plugin</a></h2>
|
||||
|
||||
To enable <a href="https://github.com/JulianBirch/cljs-ajax">cljs-ajax</a>,
|
||||
in addition to <tt>scittle.js</tt>, you need to include <tt>scittle.cljs-ajax.js</tt>:
|
||||
|
||||
<pre><code data-type="scittle" data-src="html/cljs-ajax.html" class="html"></code></pre>
|
||||
|
||||
<button onclick="make_request()">
|
||||
Click me!
|
||||
</button>
|
||||
|
||||
<a name="pprint"></a>
|
||||
<h2><a href="#pprint">cljs.pprint plugin</a></h2> To
|
||||
enable <a href="https://cljs.github.io/api/cljs.pprint/">cljs.pprint</a>, in
|
||||
addition to <tt>scittle.js</tt>, you need to
|
||||
include <tt>scittle.pprint.js</tt>.
|
||||
|
||||
<a name="repl"></a>
|
||||
<h2><a href="#nrepl">REPL</a></h2>
|
||||
|
||||
To connect to a REPL with Scittle,
|
||||
see <a href="https://github.com/babashka/scittle/blob/main/README.md#repl">README.md</a>
|
||||
|
||||
<a name="examples"></a>
|
||||
<h2><a href="#examples">Examples</a></h2>
|
||||
<ul>
|
||||
<li>Scittle on <a href="https://codepen.io/Prestance/pen/PoOdZQw">CodePen</a></li>
|
||||
<li><a href="tictactoe.html">Tic-tac-toe</a></li>
|
||||
<li><a href="bookmarklet.html">Bookmarklet</a></li>
|
||||
<li><a href="wordle.html">Wordle</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/kloimhardt/babashka-scittle-guestbook">
|
||||
Babashka + scittle implementation of the Luminus guestbook.
|
||||
</a></li>
|
||||
<li><a href="codemirror.html">Codemirror</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
<script>var SCITTLE_NREPL_WEBSOCKET_PORT = 1340;</script>
|
||||
<script src="js/scittle.nrepl.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle" src="cljs/nrepl_playground.cljs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle</h1>
|
||||
<h2>What is this?</h2>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
|
||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
|
||||
<script src="js/scittle.reagent.js" type="application/javascript"></script>
|
||||
|
||||
<script type="application/x-scittle" src="cljs/tictactoe.cljs"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js" type="text/javascript"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/languages/clojure.min.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/zenburn.min.css" integrity="sha512-JPxjD2t82edI35nXydY/erE9jVPpqxEJ++6nYEoZEpX2TRsmp2FpZuQqZa+wBCen5U16QZOkMadGXHCfp+tUdg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>Scittle tic-tac-toe</h1>
|
||||
<h2>What is Scittle?</h2>
|
||||
<p>Read <a href="index.html">the main page</a> for more details.</p>
|
||||
<h2>The game</h2>
|
||||
<div id="app"></div>
|
||||
<p>The following source was loaded and interpreted
|
||||
from <a href="cljs/tictactoe.cljs"><tt>cljs/tictactoe.cljs</tt></a> using the
|
||||
script tag:
|
||||
<pre><code class="html">
|
||||
<script type="application/x-scittle" src="cljs/tictactoe.cljs"></script>
|
||||
|
||||
</code></pre>
|
||||
</p>
|
||||
<pre><code class="language-clojure" id="cljs"></code></pre>
|
||||
<script type="application/x-scittle">
|
||||
(defn set-text [progress-event]
|
||||
(let [elt (.getElementById js/document "cljs")]
|
||||
(set! (.-innerHTML elt) (.. progress-event -srcElement -responseText))
|
||||
(.highlightAll js/hljs)))
|
||||
(def oreq (js/XMLHttpRequest.))
|
||||
(.addEventListener oreq "load" set-text)
|
||||
(.open oreq "GET" "cljs/tictactoe.cljs")
|
||||
(.send oreq)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Wordle!</title>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta content="utf-8" http-equiv="encoding">
|
||||
<script src="js/scittle.js" type="application/javascript"></script>
|
||||
<script type="application/x-scittle" src="https://raw.githubusercontent.com/oxalorg/wordle-clojurescript/main/src/wordle/core2.cljs"></script>
|
||||
<style type="text/css">
|
||||
#app {
|
||||
background-color: #121212;
|
||||
}
|
||||
#app .board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 60px);
|
||||
}
|
||||
#app .cell {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.5rem;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 10px;
|
||||
border: 2px solid gray;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p class="board">Wordle by <a href="https://github.com/oxalorg/wordle-clojurescript">@oxalorg</a>.
|
||||
Play the game by typing letters and then hit return. The source code is loaded from <a href="https://raw.githubusercontent.com/oxalorg/wordle-clojurescript/main/src/wordle/core2.cljs">here</a>.
|
||||
</p>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#!/usr/bin/env bb
|
||||
|
||||
(require '[babashka.fs :as fs]
|
||||
'[babashka.tasks :refer [shell]])
|
||||
|
||||
(fs/copy "resources/public/index.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/base.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/tictactoe.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/bookmarklet.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/wordle.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/disable_auto_eval.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(fs/copy "resources/public/codemirror.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(def html-source-dir (fs/file "resources" "public" "html"))
|
||||
(def html-target-dir (fs/file "gh-pages" "html"))
|
||||
(fs/create-dirs html-target-dir)
|
||||
(doseq [html ["export.html" "reagent.html" "cljs-ajax.html"]]
|
||||
(fs/copy (fs/file html-source-dir html) html-target-dir
|
||||
{:replace-existing true}))
|
||||
|
||||
(def style-source-dir (fs/file "resources" "public" "css"))
|
||||
(def style-target-dir (fs/file "gh-pages" "css"))
|
||||
(fs/create-dirs style-target-dir)
|
||||
(fs/copy "resources/public/css/style.css" style-target-dir
|
||||
{:replace-existing true})
|
||||
|
||||
(def js-source-dir (fs/file "resources" "public" "js"))
|
||||
(def js-target-dir (fs/file "gh-pages" "js"))
|
||||
(fs/create-dirs js-target-dir)
|
||||
|
||||
(println "Compiling CLJS")
|
||||
(shell "bb prod")
|
||||
|
||||
(fs/copy "resources/public/js/report.html" "gh-pages"
|
||||
{:replace-existing true})
|
||||
|
||||
(def index-file (fs/file "gh-pages" "index.html"))
|
||||
|
||||
(def cljs-source-dir (fs/file "resources" "public" "cljs"))
|
||||
(def cljs-target-dir (fs/file "gh-pages" "cljs"))
|
||||
(fs/create-dirs cljs-target-dir)
|
||||
|
||||
(run! (fn [f]
|
||||
(println "Copying" (str f))
|
||||
(fs/copy f
|
||||
cljs-target-dir
|
||||
{:replace-existing true}))
|
||||
(fs/glob cljs-source-dir "*.cljs"))
|
||||
|
||||
(run! (fn [f]
|
||||
(println "Copying" (str f))
|
||||
(fs/copy f
|
||||
js-target-dir
|
||||
{:replace-existing true}))
|
||||
(fs/glob js-source-dir "scittle*.js"))
|
||||
|
||||
(def with-gh-pages (partial shell {:dir "gh-pages"}))
|
||||
(with-gh-pages "git add .")
|
||||
(with-gh-pages "git commit -m 'update build'")
|
||||
(with-gh-pages "git push origin gh-pages")
|
||||
|
||||
nil
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
clojure -M:dev -m shadow.cljs.devtools.cli release main
|
||||
cp resources/public/index.html gh-pages
|
||||
sed -i 's/main.js/sci_script_tag.js/' gh-pages/index.html
|
||||
|
||||
mkdir -p gh-pages/js
|
||||
cp resources/public/js/main.js gh-pages/js/sci_script_tag.js
|
||||
|
||||
cd gh-pages
|
||||
git add .
|
||||
git commit -m "update build"
|
||||
git push origin gh-pages
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
{:deps
|
||||
{:aliases [:dev]}
|
||||
|
||||
:dev-http
|
||||
{8000 "classpath:public"}
|
||||
|
||||
:builds
|
||||
{:main
|
||||
{:target :browser
|
||||
:js-options
|
||||
{:resolve {"react" {:target :global
|
||||
:global "React"}
|
||||
"react-dom" {:target :global
|
||||
:global "ReactDOM"}}}
|
||||
:modules
|
||||
{:scittle {:entries [scittle.core]}
|
||||
:scittle.nrepl {:entries [scittle.nrepl]
|
||||
:depends-on #{:scittle}}
|
||||
:scittle.promesa {:entries [scittle.promesa]
|
||||
:depends-on #{:scittle}}
|
||||
:scittle.pprint {:entries [scittle.pprint]
|
||||
:depends-on #{:scittle}}
|
||||
:scittle.reagent {:entries [scittle.reagent]
|
||||
:depends-on #{:scittle}}
|
||||
:scittle.re-frame {:entries [scittle.re-frame]
|
||||
:depends-on #{:scittle.reagent
|
||||
:scittle}}
|
||||
:scittle.cljs-ajax {:entries [scittle.cljs-ajax]
|
||||
:depends-on #{:scittle}}}
|
||||
:build-hooks [(shadow.cljs.build-report/hook)]
|
||||
:output-dir "resources/public/js"
|
||||
:devtools {:repl-pprint true}}}}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
(ns scittle.cljs-ajax
|
||||
(:require [ajax.core]
|
||||
[sci.core :as sci]
|
||||
[scittle.core :as scittle]))
|
||||
|
||||
(def ans (sci/create-ns 'ajax.core nil))
|
||||
|
||||
(def ajax-namespace
|
||||
(sci/copy-ns ajax.core ans))
|
||||
|
||||
(scittle/register-plugin!
|
||||
::ajax
|
||||
{:namespaces {'ajax.core ajax-namespace}})
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
(ns scittle.core
|
||||
(:refer-clojure :exclude [time])
|
||||
(:require [cljs.reader :refer [read-string]]
|
||||
[goog.object :as gobject]
|
||||
[goog.string]
|
||||
[sci.core :as sci]
|
||||
[sci.impl.unrestrict]
|
||||
[scittle.impl.common :refer [cljns]]
|
||||
[scittle.impl.error :as error]))
|
||||
|
||||
(set! sci.impl.unrestrict/*unrestricted* true)
|
||||
|
||||
(clojure.core/defmacro time
|
||||
"Evaluates expr and prints the time it took. Returns the value of expr."
|
||||
[expr]
|
||||
`(let [start# (cljs.core/system-time)
|
||||
ret# ~expr]
|
||||
(prn (cljs.core/str "Elapsed time: "
|
||||
(.toFixed (- (system-time) start#) 6)
|
||||
" msecs"))
|
||||
ret#))
|
||||
|
||||
(def stns (sci/create-ns 'sci.script-tag nil))
|
||||
(def rns (sci/create-ns 'cljs.reader nil))
|
||||
|
||||
(def namespaces
|
||||
{'clojure.core
|
||||
{'time (sci/copy-var time cljns)
|
||||
'system-time (sci/copy-var system-time cljns)
|
||||
'random-uuid random-uuid
|
||||
'read-string (sci/copy-var read-string rns)}
|
||||
'goog.object {'set gobject/set
|
||||
'get gobject/get}
|
||||
'sci.core {'stacktrace sci/stacktrace
|
||||
'format-stacktrace sci/format-stacktrace}})
|
||||
|
||||
(def !sci-ctx
|
||||
(atom (sci/init {:namespaces namespaces
|
||||
:classes {'js js/globalThis
|
||||
:allow :all
|
||||
'Math js/Math}
|
||||
:ns-aliases {'clojure.pprint 'cljs.pprint}})))
|
||||
|
||||
(def !last-ns (volatile! @sci/ns))
|
||||
|
||||
(defn- -eval-string [s]
|
||||
(sci/binding [sci/ns @!last-ns]
|
||||
(let [rdr (sci/reader s)]
|
||||
(loop [res nil]
|
||||
(let [form (sci/parse-next @!sci-ctx rdr)]
|
||||
(if (= :sci.core/eof form)
|
||||
(do
|
||||
(vreset! !last-ns @sci/ns)
|
||||
res)
|
||||
(recur (sci/eval-form @!sci-ctx form))))))))
|
||||
|
||||
(defn ^:export eval-string [s]
|
||||
(try (-eval-string s)
|
||||
(catch :default e
|
||||
(error/error-handler e (:src @!sci-ctx))
|
||||
(throw e))))
|
||||
|
||||
(defn register-plugin! [_plug-in-name sci-opts]
|
||||
(swap! !sci-ctx sci/merge-opts sci-opts))
|
||||
|
||||
(defn- eval-script-tags* [script-tags]
|
||||
(when-let [tag (first script-tags)]
|
||||
(if-let [text (not-empty (gobject/get tag "textContent"))]
|
||||
(let [scittle-id (str (gensym "scittle-tag-"))]
|
||||
(gobject/set tag "scittle_id" scittle-id)
|
||||
(swap! !sci-ctx assoc-in [:src scittle-id] text)
|
||||
(sci/binding [sci/file scittle-id]
|
||||
(eval-string text))
|
||||
(eval-script-tags* (rest script-tags)))
|
||||
(let [src (.getAttribute tag "src")
|
||||
req (js/XMLHttpRequest.)
|
||||
_ (.open req "GET" src true)
|
||||
_ (gobject/set req "onload"
|
||||
(fn [] (this-as this
|
||||
(let [response (gobject/get this "response")]
|
||||
(gobject/set tag "scittle_id" src)
|
||||
;; save source for error messages
|
||||
(swap! !sci-ctx assoc-in [:src src] response)
|
||||
(sci/binding [sci/file src]
|
||||
(eval-string response)))
|
||||
(eval-script-tags* (rest script-tags)))))]
|
||||
(.send req)))))
|
||||
|
||||
(defn ^:export eval-script-tags []
|
||||
(let [script-tags (js/document.querySelectorAll "script[type='application/x-scittle']")]
|
||||
(eval-script-tags* script-tags)))
|
||||
|
||||
(def auto-load-disabled? (volatile! false))
|
||||
|
||||
(defn ^:export disable-auto-eval
|
||||
"By default, scittle evaluates script nodes on the DOMContentLoaded
|
||||
event using the eval-script-tags function. This function disables
|
||||
that behavior."
|
||||
[]
|
||||
(vreset! auto-load-disabled? true))
|
||||
|
||||
(js/document.addEventListener
|
||||
"DOMContentLoaded"
|
||||
(fn [] (when-not @auto-load-disabled? (eval-script-tags))), false)
|
||||
|
||||
(enable-console-print!)
|
||||
(sci/alter-var-root sci/print-fn (constantly *print-fn*))
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
(ns scittle.impl.common
|
||||
(:require [sci.core :as sci]))
|
||||
|
||||
(def cljns (sci/create-ns 'clojure.core nil))
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
(ns scittle.impl.error
|
||||
(:refer-clojure :exclude [println])
|
||||
(:require [clojure.string :as str]
|
||||
[sci.core :as sci]))
|
||||
|
||||
(defn println [& strs]
|
||||
(.error js/console (str/join " " strs)))
|
||||
|
||||
(defn ruler [title]
|
||||
(println (apply str "----- " title " " (repeat (- 50 7 (count title)) \-))))
|
||||
|
||||
(defn split-stacktrace [stacktrace verbose?]
|
||||
(if verbose? [stacktrace]
|
||||
(let [stack-count (count stacktrace)]
|
||||
(if (<= stack-count 10)
|
||||
[stacktrace]
|
||||
[(take 5 stacktrace)
|
||||
(drop (- stack-count 5) stacktrace)]))))
|
||||
|
||||
(defn print-stacktrace
|
||||
[stacktrace {:keys [:verbose?]}]
|
||||
(let [stacktrace (sci/format-stacktrace stacktrace)
|
||||
segments (split-stacktrace stacktrace verbose?)
|
||||
[fst snd] segments]
|
||||
(run! #(print % "\n") fst)
|
||||
(when snd
|
||||
(print "...\n")
|
||||
(run! #(print % "\n") snd))))
|
||||
|
||||
(defn error-context [ex src-map]
|
||||
(let [{:keys [:file :line :column]} (ex-data ex)]
|
||||
(when (and file line)
|
||||
(when-let [content (get src-map file)]
|
||||
(let [matching-line (dec line)
|
||||
start-line (max (- matching-line 4) 0)
|
||||
end-line (+ matching-line 6)
|
||||
[before after] (->>
|
||||
(str/split-lines content)
|
||||
(map-indexed list)
|
||||
(drop start-line)
|
||||
(take (- end-line start-line))
|
||||
(split-at (inc (- matching-line start-line))))
|
||||
snippet-lines (concat before
|
||||
[[nil (str (str/join "" (repeat (dec column) " "))
|
||||
(str "^--- " (ex-message ex)))]]
|
||||
after)
|
||||
indices (map first snippet-lines)
|
||||
max-size (reduce max 0 (map (comp count str) indices))
|
||||
snippet-lines (map (fn [[idx line]]
|
||||
(if idx
|
||||
(let [line-number (inc idx)]
|
||||
(str (.padStart (str line-number) max-size "0") " " line))
|
||||
(str (str/join (repeat (+ 2 max-size) " ")) line)))
|
||||
snippet-lines)]
|
||||
(str "\n" (str/join "\n" snippet-lines)))))))
|
||||
|
||||
(defn right-pad [s n]
|
||||
(let [n (- n (count s))]
|
||||
(str s (str/join (repeat n " ")))))
|
||||
|
||||
(defn error-handler [e src-map]
|
||||
(let [d (ex-data e)
|
||||
sci-error? (isa? (:type d) :sci/error)
|
||||
stacktrace (sci/stacktrace e)]
|
||||
(ruler "Scittle error")
|
||||
(when-let [name (.-name e)]
|
||||
(when-not (= "Error" name)
|
||||
(println "Type: " name)))
|
||||
(when-let [m (.-message e)]
|
||||
(println (str "Message: " m)))
|
||||
(when-let [d (ex-data (ex-cause e) #_(.getCause e))]
|
||||
(println (str "Data: ")
|
||||
(pr-str d)))
|
||||
(let [{:keys [:file :line :column]} d]
|
||||
(when line
|
||||
(println (str "Location: "
|
||||
(when file (str file ":"))
|
||||
line ":" column""))))
|
||||
(when-let [phase (:phase d)]
|
||||
(println "Phase: " phase))
|
||||
(when-let [ec (when sci-error?
|
||||
(error-context e src-map))]
|
||||
(ruler "Context")
|
||||
(println ec))
|
||||
(when sci-error?
|
||||
(when-let
|
||||
[st (let [st (with-out-str
|
||||
(when stacktrace
|
||||
(print-stacktrace stacktrace src-map)))]
|
||||
(when-not (str/blank? st) st))]
|
||||
(ruler "Stack trace")
|
||||
(println st)))))
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
(ns scittle.nrepl
|
||||
(:require
|
||||
[clojure.edn :as edn]
|
||||
[sci.nrepl.completions :refer [completions]]
|
||||
[sci.nrepl.info :refer [info]]
|
||||
[scittle.core :refer [!last-ns eval-string !sci-ctx]]))
|
||||
|
||||
(defn nrepl-websocket []
|
||||
(.-ws_nrepl js/window))
|
||||
|
||||
(defn nrepl-reply [{:keys [id session]} {:keys [ns] :as payload}]
|
||||
(.send (nrepl-websocket)
|
||||
(str
|
||||
(let [ns (or ns (str @!last-ns))]
|
||||
(assoc payload :id id :session session :ns ns)))))
|
||||
|
||||
(defn handle-nrepl-eval [{:keys [code] :as msg}]
|
||||
(let [[kind val] (try [::success (eval-string code)]
|
||||
(catch :default e
|
||||
[::error (str e)]))]
|
||||
(case kind
|
||||
::success
|
||||
(do (nrepl-reply msg {:value (pr-str val)})
|
||||
(nrepl-reply msg {:status ["done"]}))
|
||||
::error
|
||||
(do
|
||||
(nrepl-reply msg {:err (pr-str val)})
|
||||
(nrepl-reply msg {:ex (pr-str val)
|
||||
:status ["error" "done"]})))))
|
||||
|
||||
(defn handle-nrepl-info [msg]
|
||||
(let [info (info (assoc msg :ctx @!sci-ctx))]
|
||||
(nrepl-reply msg info)))
|
||||
|
||||
(declare ops)
|
||||
|
||||
(defn
|
||||
handle-describe
|
||||
[msg]
|
||||
(nrepl-reply
|
||||
msg
|
||||
{:versions {"scittle-nrepl" {"major" "0"
|
||||
"minor" "0"
|
||||
"incremental" "1"}}
|
||||
:ops (zipmap
|
||||
(map
|
||||
name
|
||||
(concat
|
||||
(keys ops)
|
||||
;; sci.nrepl browser_server.clj handles:
|
||||
#{:clone :load-file}
|
||||
;; we are lying about close?
|
||||
#{"close"}))
|
||||
(repeat {}))
|
||||
:status ["done"]}))
|
||||
|
||||
(def ops
|
||||
"Operations supported by the nrepl server."
|
||||
{:eval handle-nrepl-eval
|
||||
:info handle-nrepl-info
|
||||
:eldoc handle-nrepl-info
|
||||
:lookup handle-nrepl-info
|
||||
:describe handle-describe
|
||||
:complete (fn [msg] (let [completions (completions (assoc msg :ctx @!sci-ctx))]
|
||||
(nrepl-reply msg completions)))})
|
||||
|
||||
(defn handle-nrepl-message [msg]
|
||||
(if-let [handler (ops (:op msg))]
|
||||
(handler msg)
|
||||
(nrepl-reply (merge msg {:status ["error" "done"] :err "unkown-op"}) (assoc msg :ctx @!sci-ctx))))
|
||||
|
||||
(defn ws-url [host port path]
|
||||
(str "ws://" host ":" port "/" path))
|
||||
|
||||
(when-let [ws-port (.-SCITTLE_NREPL_WEBSOCKET_PORT js/window)]
|
||||
(set! (.-ws_nrepl js/window)
|
||||
(new js/WebSocket (ws-url (.-hostname (.-location js/window)) ws-port "_nrepl"))))
|
||||
|
||||
(when-let [ws (nrepl-websocket)]
|
||||
(prn :ws ws)
|
||||
(set! (.-onmessage ws)
|
||||
(fn [event]
|
||||
(handle-nrepl-message (edn/read-string (.-data event)))))
|
||||
(set! (.-onerror ws)
|
||||
(fn [event]
|
||||
(js/console.log event))))
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
(ns scittle.pprint
|
||||
(:require
|
||||
[sci.configs.cljs.pprint :refer [config]]
|
||||
[scittle.core :as scittle]))
|
||||
|
||||
(scittle/register-plugin!
|
||||
::pprint
|
||||
config)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
(ns scittle.promesa
|
||||
(:require
|
||||
[sci.configs.funcool.promesa :as p]
|
||||
[scittle.core :as scittle]))
|
||||
|
||||
(scittle/register-plugin!
|
||||
::promesa
|
||||
p/config)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
(ns scittle.re-frame
|
||||
(:require
|
||||
[sci.configs.re-frame.re-frame :as rf]
|
||||
[scittle.core :as scittle]))
|
||||
|
||||
(scittle/register-plugin!
|
||||
::re-frame
|
||||
rf/config)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
(ns scittle.reagent
|
||||
(:require
|
||||
[reagent.dom :as rdom]
|
||||
[sci.configs.reagent.reagent :refer [reagent-debug-namespace
|
||||
reagent-namespace reagent-ratom-namespace]]
|
||||
[sci.core :as sci]
|
||||
[scittle.core :as scittle]))
|
||||
|
||||
(def rdns (sci/create-ns 'reagent.dom nil))
|
||||
|
||||
(def reagent-dom-namespace
|
||||
{'render (sci/copy-var rdom/render rdns)})
|
||||
|
||||
(scittle/register-plugin!
|
||||
::reagent
|
||||
{:namespaces {'reagent.core reagent-namespace
|
||||
'reagent.dom reagent-dom-namespace
|
||||
'reagent.ratom reagent-ratom-namespace
|
||||
'reagent.debug reagent-debug-namespace}})
|
||||
Loading…
Add table
Add a link
Reference in a new issue