diff --git a/.gitignore b/.gitignore index 58fe583..e26d706 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ gh-pages/ /.clj-kondo/.cache /.clj-kondo/rewrite-clj /plugins/demo/resources/public/js/ +.portal +resources/public/test/scratch.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d34c2b..b2fff67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,18 +5,47 @@ - + -## v0.6.21 (2024-12-19) +- [#114](https://github.com/babashka/scittle/issues/114): Enable source maps ([@jeroenvandijk](https://github.com/jeroenvandijk)) +- [#140](https://github.com/babashka/scittle/issues/140): Enable customizing the nrepl websocket port ([@PEZ](https://github.com/PEZ)) -- [#99](https://github.com/babashka/babashka/issues/99): make `js/import` work +## v0.7.28 (2025-09-13) + +- [#137](https://github.com/babashka/scittle/issues/137): fix JS interop with reserved JS keyword (incorrectly munged) by bumping SCI + +## v0.7.27 (2025-08-21) + +- [#95](https://github.com/babashka/scittle/issues/121): support string requires + of `globalThis` js deps ([@chr15m](https://github.com/chr15m)). See + [docs](https://github.com/babashka/scittle/blob/main/doc/js-libraries.md). +- Potentially breaking: `(.-foo-bar {})` now behaves as `{}.foo_bar`, i.e. the property or method name is munged. + +## v0.7.26 (2025-08-20) + +- [#121](https://github.com/babashka/scittle/issues/121): add `cjohansen/dataspex` plugin ([@jeroenvandijk](https://github.com/jeroenvandijk)) +- [#118](https://github.com/babashka/scittle/issues/118): add `goog.string/format` ([@jeroenvandijk](https://github.com/jeroenvandijk)) +- Support alternative `(set! #js {} -a 1)` CLJS syntax (by bumping SCI) +- Add source maps to distribution +- Add dev versions of all modules in the `dev` folder of the distribution + a `dev/scitte.cljs-devtools.js` module + +## v0.7.23 (2025-06-18) + +- [#107](https://github.com/babashka/scittle/issues/107): add `replicant` plugin ([@jeroenvandijk](https://github.com/jeroenvandijk)) +- [#102](https://github.com/babashka/scittle/issues/102): add `applied-science/js-interop` plugin ([@chr15m](https://github.com/chr15m)) +- [#105](https://github.com/babashka/scittle/issues/105): add `goog.string/htmlEscape` ([@ikappaki](https://github.com/ikappaki) ) +- [#113](https://github.com/babashka/scittle/issues/113): add `unchecked-set` and `unchecked-get` + +## v0.6.22 (2024-12-19) + +- [#99](https://github.com/babashka/scittle/issues/99): make `js/import` work ## v0.6.20 (2024-11-24) -- [#55](https://github.com/babashka/babashka/issues/55): create gh-pages dir before using. -- [#89](https://github.com/babashka/babashka/issues/89): allow `evaluate_script_tags` to specify individual scripts. +- [#55](https://github.com/babashka/scittle/issues/55): create gh-pages dir before using. +- [#89](https://github.com/babashka/scittle/issues/89): allow `evaluate_script_tags` to specify individual scripts. - [#87](https://github.com/babashka/scittle/issues/87): prod build on fresh checkout fails ## v0.6.19 (2024-10-08) @@ -25,17 +54,17 @@ ## v0.6.18 (2024-04-30) -- [#77](https://github.com/babashka/babashka/issues/77): make dependency on browser (`js/document`) optional so scittle can run in webworkers, Node.js, etc. +- [#77](https://github.com/babashka/scittle/issues/77): make dependency on browser (`js/document`) optional so scittle can run in webworkers, Node.js, etc. ## v0.6.17 (2024-04-22) -- [#69](https://github.com/babashka/babashka/issues/69): executing script tag with src + whitespace doesn't work -- [#72](https://github.com/babashka/babashka/issues/72): add clojure 1.11 functions like `update-vals` -- [#75](https://github.com/babashka/babashka/issues/75): Support reader conditionals in source code +- [#69](https://github.com/babashka/scittle/issues/69): executing script tag with src + whitespace doesn't work +- [#72](https://github.com/babashka/scittle/issues/72): add clojure 1.11 functions like `update-vals` +- [#75](https://github.com/babashka/scittle/issues/75): Support reader conditionals in source code ## v0.6.16 (2023-05-04) -- [#58](https://github.com/babashka/babashka/issues/58): build system for creating scittle distribution with custom libraries. See [plugins/demo](plugins/demo). +- [#58](https://github.com/babashka/scittle/issues/58): build system for creating scittle distribution with custom libraries. See [plugins/demo](plugins/demo). - Use `window.location.hostname` for WebSocket connection instead of hardcoding `"localhost"` ([@pyrmont](https://github.com/pyrmont)) - Upgrade `sci.configs` to `"33bd51e53700b224b4cb5bda59eb21b62f962745"` - Update nREPL implementation: implement `eldoc` (`info`, `lookup`) ([@benjamin-asdf](https://github.com/benjamin-asdf)) diff --git a/README.md b/README.md index a276016..01e1607 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ babashka or Clojure JVM): See [doc/nrepl](doc/nrepl). +### Service worker + +See [doc/serviceworker.md](doc/serviceworker.md). + ## Tasks Run `bb tasks` to see all available tasks: @@ -46,6 +50,7 @@ release Updates Github pages with new release build. ## Credits Idea by Arne Brasseur a.k.a [plexus](https://github.com/plexus). +Name by Alessandra Sierra (the name occurs first in [this](https://stuartsierra.com/2019/12/21/clojure-start-time-in-2019/) blog post). ## License diff --git a/bb.edn b/bb.edn index bc4f02c..f76e437 100644 --- a/bb.edn +++ b/bb.edn @@ -44,9 +44,11 @@ :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")))} + (fs/create-dirs "dist/dev") + (run! (fn [f] (fs/copy f "dist" {:replace-existing true})) + (fs/glob "resources/public/js" "*.{js,js.map}")) + (run! (fn [f] (fs/copy f "dist/dev" {:replace-existing true})) + (fs/glob "resources/public/js/dev" "*.{js,js.map}")))} bump-version {:doc "Bumps package.json and pushes new git tag" :task (do (shell "npm version patch") diff --git a/build/src/scittle/build.clj b/build/src/scittle/build.clj index 1e17a37..02382e5 100644 --- a/build/src/scittle/build.clj +++ b/build/src/scittle/build.clj @@ -69,4 +69,15 @@ * :action - compile action, defaults to release, but may also be compile or watch" [{:keys [action args] :or {action "release"}}] - (build* (format "-M -m shadow.cljs.devtools.cli --force-spawn %s main %s" action (str/join " " args)))) + (build* (format "-M -m shadow.cljs.devtools.cli --force-spawn %s main %s" action (str/join " " args))) + (when (= "release" action) + (println "Also building dev release build") + (build* (format "-M -m shadow.cljs.devtools.cli --force-spawn %s main %s %s" + action + "--config-merge '{:compiler-options {:optimizations :simple + :pretty-print true + :pseudo-names true} + :output-dir \"resources/public/js/dev\" + :modules {:scittle.cljs-devtools {:entries [scittle.cljs-devtools] + :depends-on #{:scittle}}}}'" + (str/join " " args))))) diff --git a/deps.edn b/deps.edn index 7acfe46..f7a5121 100644 --- a/deps.edn +++ b/deps.edn @@ -1,16 +1,18 @@ {:paths ["src" "resources"] :deps - {org.clojure/clojure {:mvn/version "1.11.1"} - thheller/shadow-cljs {:mvn/version "2.20.15"} + {org.clojure/clojure {:mvn/version "1.12.2"} + thheller/shadow-cljs {:mvn/version "3.1.8"} org.babashka/sci {:git/url "https://github.com/babashka/sci" - :git/sha "ba8518a4e27bb65eca0453b54adc9243c6ab8ceb"} + :git/sha "6758ba028da559c536a06becbbedade7b0ba6448"} #_{:local/root "../babashka/sci"} reagent/reagent {:mvn/version "1.1.1"} + no.cjohansen/replicant {:mvn/version "2025.03.27"} 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"} + applied-science/js-interop {:mvn/version "0.4.2"} funcool/promesa {:mvn/version "11.0.678"} io.github.babashka/sci.nrepl #_{:local/root "../sci.nrepl"} @@ -19,7 +21,9 @@ io.github.babashka/sci.configs #_{:local/root "/Users/borkdude/dev/sci.configs"} {:git/url "https://github.com/babashka/sci.configs" - :git/sha "8253c69a537bcc82e8ff122e5f905fe9d1e303f0"}} + :git/sha "aa84a1b4f1fe45735e5b748769309fc842f737c1" + :exclusions [org.babashka/sci]} + binaryage/devtools {:mvn/version "1.0.7"}} :aliases {:dev {:extra-paths ["dev"] diff --git a/doc/dev.md b/doc/dev.md index 7a97eb1..b6bd354 100644 --- a/doc/dev.md +++ b/doc/dev.md @@ -90,20 +90,20 @@ 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.6.16 0.6.20` +- `bb replace-version 0.6.16 0.7.28` - Create Github release with updated links from `doc/links.md` - `bb gh-pages` - + - - + + - + diff --git a/doc/js-libraries.md b/doc/js-libraries.md new file mode 100644 index 0000000..72cafb8 --- /dev/null +++ b/doc/js-libraries.md @@ -0,0 +1,49 @@ +# Loading JS libraries + +Since `v0.7.28` scittle allows to load libraries from the global enviroment. +This means you can load a library in a ` + + + + + + +``` + +## ES modules + +The async nature of ES modules makes them a litte bit more difficult to work +with in scittle. You need to disable automatic evaluation of script tags first +using `scittle.core.disable_auto_eval()`. In a `module` type ` + + + + + + + +``` diff --git a/doc/links.md b/doc/links.md index f9fc5ef..0b4181a 100644 --- a/doc/links.md +++ b/doc/links.md @@ -1,7 +1,20 @@ -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.cljs-ajax.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.reagent.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.re-frame.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.promesa.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.pprint.js -https://cdn.jsdelivr.net/npm/scittle@0.6.20/dist/scittle.nrepl.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.js-interop.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.cljs-ajax.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.reagent.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.re-frame.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.replicant.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.promesa.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.pprint.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/scittle.nrepl.js + +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.js-interop.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.cljs-ajax.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.reagent.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.re-frame.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.replicant.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.promesa.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.pprint.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.nrepl.js +https://cdn.jsdelivr.net/npm/scittle@0.7.28/dist/dev/scittle.cljs-devtools.js diff --git a/doc/nrepl/README.md b/doc/nrepl/README.md index 9baecea..5541357 100644 --- a/doc/nrepl/README.md +++ b/doc/nrepl/README.md @@ -21,7 +21,7 @@ the normal routine: ``` html - + ``` Also include the CLJS file that you want to evaluate with nREPL: @@ -42,6 +42,16 @@ you should be able evaluate expressions in `playground.cljs`. See a demo Note that the nREPL server connection stays alive even after the browser window refreshes. +### Custom host address + +By default, the browser will connect to a websocket on the same host as it is loaded +from, using `window.location.hostname`. If you need something else you can specify +that setting the window variable `SCITTLE_NREPL_WEBSOCKET_HOST` like so: + +``` html + +``` + ### CIDER Choose `cider-connect-cljs`, select port `1339`, followed by the `nbb` REPL diff --git a/doc/nrepl/bb.edn b/doc/nrepl/bb.edn index e4cf885..fdd4518 100644 --- a/doc/nrepl/bb.edn +++ b/doc/nrepl/bb.edn @@ -1,5 +1,6 @@ {:deps {io.github.babashka/sci.nrepl - {:git/sha "2f8a9ed2d39a1b09d2b4d34d95494b56468f4a23"} + #_{:local/root "/Users/borkdude/dev/sci.nrepl"} + {:git/sha "4f7f6d652a71b5bdc0c110313a4908d956e7a97d"} io.github.babashka/http-server {:git/sha "b38c1f16ad2c618adae2c3b102a5520c261a7dd3"}} :tasks {http-server {:doc "Starts http server for serving static files" diff --git a/doc/nrepl/index.html b/doc/nrepl/index.html index 42ba9bd..5890a47 100644 --- a/doc/nrepl/index.html +++ b/doc/nrepl/index.html @@ -1,9 +1,9 @@ - + - + diff --git a/doc/serviceworker.md b/doc/serviceworker.md new file mode 100644 index 0000000..1048f77 --- /dev/null +++ b/doc/serviceworker.md @@ -0,0 +1,26 @@ +# Scittle in a service worker + +You can use Scittle to bootstrap a ClojureScript based service worker. + +Put the following code into e.g. `scittle-sw.js` to create a JavaScript based service worker, load Scittle, then fetch your script and eval it. + +```javascript +importScripts("scittle.min.js"); + +const request = await fetch("sw.cljs"); +const text = await request.text(); +const result = scittle.core.eval_string(text); +``` + +Then load `scittle-sw.js` in your HTML: + +```html + +``` + +This will load `sw.cljs` and eval it in the context of the service worker. + +A ready-made example can be found at [chr15m/scittle-template-serviceworker](https://github.com/chr15m/scittle-template-serviceworker). diff --git a/package-lock.json b/package-lock.json index 2593183..e5bd260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "react": "17.0.1", "react-dom": "17.0.1" }, - "version": "0.6.21" + "version": "0.7.28" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -129,5 +129,5 @@ } } }, - "version": "0.6.21" + "version": "0.7.28" } diff --git a/package.json b/package.json index d7d8688..ab333e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scittle", - "version": "0.6.21", + "version": "0.7.28", "files": [ "dist" ], diff --git a/plugins/datascript/deps.edn b/plugins/datascript/deps.edn index 1454ae1..467f4cd 100644 --- a/plugins/datascript/deps.edn +++ b/plugins/datascript/deps.edn @@ -1,3 +1,4 @@ {:deps {datascript/datascript {:mvn/version "1.3.12"} - io.github.babashka/sci.configs {:git/sha "33bd51e53700b224b4cb5bda59eb21b62f962745"}}} + io.github.babashka/sci.configs {:git/sha "aa84a1b4f1fe45735e5b748769309fc842f737c1" + :exclusions [org.babashka/sci]}}} diff --git a/plugins/dataspex/deps.edn b/plugins/dataspex/deps.edn new file mode 100644 index 0000000..badf11e --- /dev/null +++ b/plugins/dataspex/deps.edn @@ -0,0 +1,8 @@ +{:deps + {no.cjohansen/dataspex {:git/url "https://github.com/cjohansen/dataspex" + :git/sha "02112200651c2bd932907bb69fba1ff50b881741" + :exclusions [ring/ring-core + ring/ring-jetty-adapter + com.cognitect/transit-clj]} + io.github.babashka/sci.configs {:git/sha "aa84a1b4f1fe45735e5b748769309fc842f737c1" + :exclusions [org.babashka/sci]}}} diff --git a/plugins/dataspex/src/scittle/dataspex.cljs b/plugins/dataspex/src/scittle/dataspex.cljs new file mode 100644 index 0000000..66b3908 --- /dev/null +++ b/plugins/dataspex/src/scittle/dataspex.cljs @@ -0,0 +1,9 @@ +(ns scittle.dataspex + {:no-doc true} + (:require [sci.configs.cjohansen.dataspex :refer [config]] + [scittle.core :as scittle])) + +(defn init [] + (scittle/register-plugin! + ::dataspex + config)) diff --git a/plugins/dataspex/src/scittle_plugin.edn b/plugins/dataspex/src/scittle_plugin.edn new file mode 100644 index 0000000..af629e2 --- /dev/null +++ b/plugins/dataspex/src/scittle_plugin.edn @@ -0,0 +1,8 @@ +[{:name scittle/dataspex + :namespaces [dataspex.core] + :js "./scittle.dataspex.js" + :shadow-config + {:modules + {:scittle.dataspex {:init-fn scittle.dataspex/init + :depends-on #{:scittle :scittle.datascript} + :entries [dataspex.core]}}}}] diff --git a/plugins/demo/bb.edn b/plugins/demo/bb.edn index 86170d0..e7486c2 100644 --- a/plugins/demo/bb.edn +++ b/plugins/demo/bb.edn @@ -1,6 +1,7 @@ {:deps {io.github.babashka/scittle.build {:local/root "../../build"} ;; datascript plugin ; io.github.babashka/scittle.datascript {:local/root "../../plugins/datascript"} + io.github.babashka/scittle.dataspex {:local/root "../../plugins/dataspex"} io.github.babashka/scittle.javelin {:local/root "../../plugins/javelin"} io.github.babashka/scittle.hoplon {:local/root "../../plugins/hoplon"} io.github.babashka/http-server diff --git a/plugins/hoplon/deps.edn b/plugins/hoplon/deps.edn index e7aef52..0eab577 100644 --- a/plugins/hoplon/deps.edn +++ b/plugins/hoplon/deps.edn @@ -1,3 +1,4 @@ {:deps {hoplon/hoplon {:mvn/version "7.5.0"} - io.github.babashka/sci.configs {:git/sha "08bab21643bc0c63a5b99c65193c9d24888270b7"}}} + io.github.babashka/sci.configs {:git/sha "aa84a1b4f1fe45735e5b748769309fc842f737c1" + :exclusions [org.babashka/sci]}}} diff --git a/plugins/javelin/deps.edn b/plugins/javelin/deps.edn index 135f602..f4b4533 100644 --- a/plugins/javelin/deps.edn +++ b/plugins/javelin/deps.edn @@ -1,3 +1,4 @@ {:deps {hoplon/javelin {:mvn/version "3.9.3"} - io.github.babashka/sci.configs {:git/sha "08bab21643bc0c63a5b99c65193c9d24888270b7"}}} + io.github.babashka/sci.configs {:git/sha "aa84a1b4f1fe45735e5b748769309fc842f737c1" + :exclusions [org.babashka/sci]}}} diff --git a/resources/public/bookmarklet.html b/resources/public/bookmarklet.html index 15dce60..e2cc947 100644 --- a/resources/public/bookmarklet.html +++ b/resources/public/bookmarklet.html @@ -4,9 +4,8 @@ - - - + + diff --git a/resources/public/cljs/replicant_tictactoe/core.cljs b/resources/public/cljs/replicant_tictactoe/core.cljs new file mode 100644 index 0000000..b5ad81f --- /dev/null +++ b/resources/public/cljs/replicant_tictactoe/core.cljs @@ -0,0 +1,33 @@ +;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/core.cljs + +(ns replicant-tictactoe.core + (:require [replicant.dom :as r] + [replicant-tictactoe.game :as game] + [replicant-tictactoe.ui :as ui])) + +(defn start-new-game [store] + (reset! store (game/create-game {:size 3}))) + +(defn main [] + ;; Set up the atom + (let [store (atom nil) + el (js/document.getElementById "app")] + + ;; Globally handle DOM events + (r/set-dispatch! + (fn [_ [action & args]] + (case action + :tic (apply swap! store game/tic args) + :reset (start-new-game store)))) + + ;; Render on every change + (add-watch store ::render + (fn [_ _ _ game] + (->> (ui/game->ui-data game) + ui/render-game + (r/render el)))) + + ;; Trigger the first render by initializing the game. + (start-new-game store))) + +(main) diff --git a/resources/public/cljs/replicant_tictactoe/game.cljs b/resources/public/cljs/replicant_tictactoe/game.cljs new file mode 100644 index 0000000..9296baf --- /dev/null +++ b/resources/public/cljs/replicant_tictactoe/game.cljs @@ -0,0 +1,44 @@ +;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/game.cljs + +(ns replicant-tictactoe.game) + +(defn create-game [{:keys [size]}] + {:next-player :x + :size size}) + +(def next-player {:x :o, :o :x}) + +(defn winner? [tics path] + (when (= 1 (count (set (map tics path)))) + path)) + +(defn get-winning-path [{:keys [size tics]} y x] + (let [flip-y (fn [y] (- size 1 y))] + (or (winner? tics (mapv #(vector y %) (range 0 size))) + (winner? tics (mapv #(vector % x) (range 0 size))) + (when (= y x) + (winner? tics (mapv #(vector % %) (range 0 size)))) + (when (= (flip-y y) x) + (winner? tics (mapv #(vector (flip-y %) %) (range 0 size))))))) + +(defn maybe-conclude [game y x] + (if-let [path (get-winning-path game y x)] + (-> (dissoc game :next-player) + (assoc :over? true + :victory {:player (get-in game [:tics [y x]]) + :path path})) + (let [tie? (= (count (:tics game)) (* (:size game) (:size game)))] + (cond-> game + tie? (dissoc :next-player) + tie? (assoc :over? true))))) + +(defn tic [game y x] + (let [player (:next-player game)] + (if (or (get-in game [:tics [y x]]) + (<= (:size game) x) + (<= (:size game) y)) + game + (-> game + (assoc-in [:tics [y x]] player) + (assoc :next-player (next-player player)) + (maybe-conclude y x))))) \ No newline at end of file diff --git a/resources/public/cljs/replicant_tictactoe/style.css b/resources/public/cljs/replicant_tictactoe/style.css new file mode 100644 index 0000000..7ec052a --- /dev/null +++ b/resources/public/cljs/replicant_tictactoe/style.css @@ -0,0 +1,50 @@ +/* COPIED from https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/resources/public/styles.css */ +.cell { + aspect-ratio: 1 / 1; + background: rgba(255, 255, 255, 0.8); + border-radius: 6%; + border: none; + display: block; + flex: 1 1 0%; + outline: none; + position: relative; + width: 100%; +} + +.cell-content { + opacity: 1; + transition: opacity 0.25s; +} + +.transparent { + opacity: 0; +} + +.cell-dim { + background: rgba(249, 249, 240, 0.3); +} + +.cell-highlight { + background: #fcfcf3; +} + +.clickable { + cursor: pointer; +} + +.board { + --gap: 0.75rem; + background: #833ab4; + background: linear-gradient(90deg, #833ab4 0%, #fd1d1d 50%, #fcb045 100%); + display: flex; + flex-direction: column; + gap: var(--gap); + padding: var(--gap); + max-width: 80vh; +} + +.row { + display: flex; + flex-direction: row; + gap: var(--gap); +} \ No newline at end of file diff --git a/resources/public/cljs/replicant_tictactoe/ui.cljs b/resources/public/cljs/replicant_tictactoe/ui.cljs new file mode 100644 index 0000000..c53dc65 --- /dev/null +++ b/resources/public/cljs/replicant_tictactoe/ui.cljs @@ -0,0 +1,75 @@ +;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/ui.cljs + +(ns replicant-tictactoe.ui) + +(def mark-x + [:svg {:xmlns "http://www.w3.org/2000/svg" + :viewBox "0 -10 108 100"} + [:path + {:fill "currentColor" + :d "m1.753 69.19.36-1.08q.35-1.09 1.92-2.97 1.58-1.87 3.85-3.84 2.29-1.97 4.6-3.54 2.31-1.57 4.93-3.24 2.62-1.66 4.65-2.9 2.04-1.23 3.91-2.27 1.87-1.05 3.98-2.31 2.11-1.27 4.12-2.5 2.01-1.24 4.33-2.51l4.6-2.52q2.27-1.25 4.84-2.86 2.56-1.62 5.03-3.09 2.47-1.47 4.5-2.88 2.03-1.4 3.82-2.82t3.81-3.47q2.01-2.06 3.7-3.51 1.69-1.46 3.47-3.03 1.77-1.57 4.01-3.69 2.24-2.11 4.13-3.7 1.89-1.58 3.93-2.97 2.04-1.39 4.05-2.49 2.01-1.11 5.26-2.54 3.24-1.44 4.48-1.46 1.24-.01 2.42.37 1.18.37 2.18 1.11 1 .74 1.71 1.75.71 1.02 1.06 2.21.34 1.19.3 2.43-.05 1.24-.5 2.39-.44 1.16-1.23 2.12-.79.95-1.84 1.61-1.05.65-2.26.94-1.21.28-2.44.16-1.23-.11-2.37-.62-1.13-.5-2.04-1.34-.91-.84-1.51-1.93-.6-1.08-.81-2.3-.22-1.22-.04-2.45.18-1.23.75-2.33.56-1.1 1.45-1.97.89-.86 2.01-1.4 1.11-.54 2.35-.69 1.23-.15 2.44.1t2.29.87q1.07.63 1.88 1.56.82.93 1.29 2.08.48 1.14.56 2.38.09 1.24-.23 2.44-.31 1.19-.99 2.23-.68 1.04-1.66 1.8-.98.76-2.15 1.18l-1.16.41-2.28 1.17q-2.28 1.18-4.38 2.7-2.1 1.51-4.2 3.44-2.1 1.92-4.18 3.7-2.08 1.77-3.9 3.44-1.81 1.68-3.41 3.13-1.6 1.46-3.38 3.09-1.79 1.62-3.44 2.97-1.66 1.34-3.53 2.4-1.88 1.06-4.17 2.65-2.3 1.6-4.79 2.74-2.48 1.14-4.98 2.71-2.5 1.57-4.51 2.47-2.01.9-3.99 1.87-1.98.97-3.88 2.02-1.91 1.05-4.38 2.34-2.46 1.28-4.94 2.53-2.47 1.25-4.48 2.38-2 1.12-3.96 2.14-1.95 1.01-3.83 1.99-1.89.98-4.37 2.05-2.48 1.06-2.96 2.01-.48.96-.78 1.49-.3.53-.71.97-.41.44-.92.77-.51.34-1.09.54-.57.2-1.17.25-.6.06-1.2-.03t-1.16-.32q-.56-.23-1.05-.59-.49-.35-.89-.82-.39-.46-.65-1.01-.27-.54-.4-1.14-.13-.59-.12-1.19.02-.6.18-1.19l.16-.59Z"}] + [:path + {:fill "currentColor" + :d "m28.099 4.991 2.69 1.97q2.69 1.96 4.5 3.22 1.8 1.28 4.54 3.46 2.74 2.18 4.57 3.89t3.38 3.72q1.54 2.02 2.88 4.3 1.34 2.28 2.83 4.46 1.48 2.18 2.63 4.14 1.15 1.96 2.74 4.07 1.59 2.1 3.59 4.19 1.99 2.08 4.23 4.48 2.24 2.4 3.7 4.04 1.47 1.64 2.91 3.23 1.44 1.59 3.08 3.58 1.64 1.99 3.51 4.08 1.87 2.09 3.55 3.77 1.69 1.68 4.1 3.51 2.42 1.83 3.9 2.58 1.48.74 2.14 1.34.66.6 1.15 1.33.5.74.8 1.57.31.84.4 1.72.1.88-.02 1.76-.12.88-.44 1.71-.33.82-.84 1.55-.51.72-1.19 1.3-.67.58-1.46.98-.79.41-1.65.61-.87.2-1.76.19-.88-.01-1.74-.24-.86-.22-1.64-.64-.78-.42-2.27-2.72-1.48-2.3-1.52-3.49-.03-1.19.31-2.33.35-1.14 1.04-2.11.69-.97 1.66-1.67.96-.7 2.1-1.05 1.14-.35 2.33-.32 1.19.02 2.31.43t2.05 1.15q.93.75 1.58 1.75.64 1 .93 2.15.29 1.16.2 2.35-.09 1.18-.56 2.28-.47 1.1-1.26 1.99-.79.88-1.83 1.47t-2.2.82q-1.17.23-2.35.07-1.19-.16-2.25-.68-1.07-.53-1.92-1.37-.84-.84-1.37-1.9-.54-1.07-.7-2.25-.17-1.18.06-2.35.22-1.17.8-2.21.58-1.04 1.47-1.84.88-.79 1.98-1.27 1.09-.47 2.28-.57 1.18-.1 2.34.18 1.16.29 2.16.93 1.01.63 1.76 1.56.74.93-.33-.26-1.07-1.18-.41-.58.66.59 1.15 1.33.5.74.8 1.57.31.83.4 1.72.1.88-.02 1.76-.12.88-.44 1.7-.33.83-.84 1.55-.51.73-1.19 1.31-.67.58-1.46.98-.79.41-1.65.61-.87.2-1.75.19-.89-.01-1.75-.24-.86-.22-1.64-.64-.78-.42-2.73-1.57-1.95-1.14-4.26-2.95-2.31-1.8-3.87-3.43-1.57-1.62-3.17-3.29-1.6-1.66-3.55-4.05-1.95-2.39-3.33-4.15-1.39-1.76-2.77-3.4-1.38-1.64-3.07-3.56-1.7-1.91-3.91-4.13-2.2-2.22-3.74-4.1-1.54-1.88-2.79-3.75-1.24-1.87-2.4-4.33t-2.39-4.46q-1.23-2.01-2.4-4.59-1.17-2.59-2.53-5.01-1.36-2.43-3.35-4.44-1.99-2.02-4.52-4.27-2.54-2.25-5.33-4.04-2.81-1.79-3.28-2.21-.47-.41-.83-.92-.35-.51-.58-1.1-.22-.58-.3-1.2-.08-.62-.01-1.23.08-.62.29-1.21.22-.58.58-1.1.35-.51.81-.93.47-.42 1.02-.71t1.16-.45q.61-.15 1.23-.15t1.22.14q.61.15 1.17.44l.55.28Z"}]]) + +(def mark-o + [:svg {:xmlns "http://www.w3.org/2000/svg" + :viewBox "0 0 114 114"} + [:path + {:fill "none" + :stroke "currentColor" + :stroke-linecap "round" + :stroke-width "6" + :d "M74.616 8.935c7.73 2.38 15.96 9.34 21.58 16.04 5.63 6.69 10.57 15.46 12.18 24.11 1.6 8.65.74 19.67-2.53 27.77-3.27 8.11-10.12 15.37-17.09 20.88-6.98 5.51-16.07 10.81-24.76 12.17-8.7 1.35-19.32-.76-27.42-4.06-8.1-3.29-15.73-8.93-21.21-15.73-5.48-6.81-10.32-16.5-11.67-25.09-1.35-8.6.19-18.39 3.57-26.51 3.38-8.11 9.99-16.6 16.71-22.19 6.72-5.59 13.95-10.52 23.63-11.36 9.68-.84 28.04 4.34 34.45 6.32 6.42 1.97 4.37 4.6 4.04 5.55m-48.33-9.69c7.65-3.32 19.78-3.63 28.63-2.01 8.86 1.63 17.85 5.89 24.49 11.76 6.64 5.87 12.7 15.08 15.37 23.48 2.67 8.41 2.5 18.4.65 26.95-1.85 8.54-5.98 17.59-11.77 24.34-5.78 6.74-14.56 13.05-22.93 16.11-8.37 3.06-18.75 4.19-27.29 2.25-8.54-1.93-17.37-7.89-23.96-13.87-6.59-5.97-12.89-13.58-15.57-21.96-2.69-8.39-2.31-19.94-.56-28.34 1.75-8.4 5.21-15.74 11.06-22.09 5.85-6.35 19.92-13.32 24.04-16.01 4.12-2.7.37-1.1.67-.16"}]]) + +(defn render-cell [{:keys [content on-click dim? highlight? clickable?]}] + [:button.cell + {:on {:click on-click} + :class (cond-> [] + dim? (conj "cell-dim") + highlight? (conj "cell-highlight") + clickable? (conj "clickable"))} + (when content + [:div.cell-content + {:replicant/mounting {:class "transparent"} + :replicant/unmounting {:class "transparent"}} + content])]) + +(defn render-board [{:keys [rows]}] + [:div.board + (for [row rows] + [:div.row + (for [cell row] + (render-cell cell))])]) + +(defn render-game [{:keys [board button]}] + [:div + (render-board board) + (when button + [:button {:on {:click (:on-click button)} + :style {:margin-top 20 + :font-size 20}} + (:text button)])]) + +(def player->mark + {:x mark-x + :o mark-o}) + +(defn game->ui-data [{:keys [size tics victory over?]}] + (let [highlight? (set (:path victory))] + {:button (when over? + {:text "Start over" + :on-click [:reset]}) + :board + {:rows + (for [y (range size)] + (for [x (range size)] + (if-let [player (get tics [y x])] + (let [victorious? (highlight? [y x])] + (cond-> {:content (player->mark player)} + victorious? (assoc :highlight? true) + (and over? (not victorious?)) (assoc :dim? true))) + (if over? + {:dim? true} + {:clickable? true + :on-click [:tic y x]}))))}})) \ No newline at end of file diff --git a/resources/public/codemirror.html b/resources/public/codemirror.html index 0709699..800624b 100644 --- a/resources/public/codemirror.html +++ b/resources/public/codemirror.html @@ -1,13 +1,13 @@ - + - - - - - + + + + + - + + + - - + + - - - + + + + - - + + @@ -87,7 +87,7 @@ To embed scittle in your website, it is recommended to use the links published to - the releases + the releases page. Include scittle.js and write a script tag @@ -147,6 +147,25 @@ addition to scittle.js, you need to include scittle.pprint.js. + +

Target :scittle in cljc

+ You can target scittle in .cljc files (use a script tag to include the cljc file) with the :scittle reader conditional like this:
+ +

+    #?(:scittle
+       (js/console.log "In scittle")
+       :org.babashka/nbb
+       (js/console.log "In nbb")
+       :cljs
+       (js/console.log "In cljs"))
+    
+ + +

JS libraries

+ + To use JavaScript libraries with Scittle, + see README.md +

REPL

@@ -165,6 +184,7 @@ Babashka + scittle implementation of the Luminus guestbook.
  • Codemirror
  • +
  • Tic-tac-toe with Replicant
  • diff --git a/resources/public/index_text.html b/resources/public/index_text.html new file mode 100644 index 0000000..c5e58c0 --- /dev/null +++ b/resources/public/index_text.html @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/resources/public/replicant_tictactoe.html b/resources/public/replicant_tictactoe.html new file mode 100644 index 0000000..1f52895 --- /dev/null +++ b/resources/public/replicant_tictactoe.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + +

    Scittle tic-tac-toe built with Replicant

    +

    What is Scittle?

    +

    Read the main page for more details.

    +

    The game

    +
    +

    The following source was loaded and interpreted + from cljs/replicant_tictactoe/core.cljs using the + script tag: +

    
    +<script type="application/x-scittle" src="cljs/replicant_tictactoe/ui.cljs"></script>
    +<script type="application/x-scittle" src="cljs/replicant_tictactoe/game.cljs"></script>
    +<script type="application/x-scittle" src="cljs/replicant_tictactoe/core.cljs"></script>
    +
    +
    +

    +
    + + + diff --git a/resources/public/test/codemirror.html b/resources/public/test/codemirror.html index 04d7e30..8bf8299 100644 --- a/resources/public/test/codemirror.html +++ b/resources/public/test/codemirror.html @@ -4,8 +4,8 @@ - - + + diff --git a/resources/public/tictactoe.html b/resources/public/tictactoe.html index 5b62e74..4462881 100644 --- a/resources/public/tictactoe.html +++ b/resources/public/tictactoe.html @@ -3,9 +3,8 @@ - - - + + diff --git a/script/changelog.clj b/script/changelog.clj index f7810c6..1ef014a 100755 --- a/script/changelog.clj +++ b/script/changelog.clj @@ -7,7 +7,7 @@ replaced (str/replace changelog #" #(\d+)" (fn [[_ issue after]] - (format " [#%s](https://github.com/babashka/babashka/issues/%s)%s" + (format " [#%s](https://github.com/babashka/scittle/issues/%s)%s" issue issue (str after)))) replaced (str/replace replaced #"@([a-zA-Z0-9-_]+)([, \.)])" diff --git a/script/release.clj b/script/release.clj index 3a1591b..4835975 100755 --- a/script/release.clj +++ b/script/release.clj @@ -26,6 +26,9 @@ (fs/copy "resources/public/codemirror.html" "gh-pages" {:replace-existing true}) +(fs/copy "resources/public/replicant_tictactoe.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) @@ -62,6 +65,9 @@ {:replace-existing true})) (fs/glob cljs-source-dir "*.cljs")) +(println "Copying dir resources/public/cljs/replicant_tictactoe") +(fs/copy-tree (fs/file cljs-source-dir "replicant_tictactoe") (fs/file cljs-target-dir "replicant_tictactoe") {:replace-existing true}) + (run! (fn [f] (println "Copying" (str f)) (fs/copy f diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 47e5deb..4b0d654 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -6,7 +6,14 @@ :builds {:main - {:target :browser + {;:compiler-options {:source-map true} + ;; for dev build + #_#_ + :compiler-options {:optimizations :simple + :pretty-print true + :pseudo-names true + :source-map true} + :target :browser :js-options {:resolve {"react" {:target :global :global "React"} @@ -18,15 +25,20 @@ :depends-on #{:scittle}} :scittle.promesa {:entries [scittle.promesa] :depends-on #{:scittle}} + :scittle.js-interop {:entries [scittle.js-interop] + :depends-on #{:scittle}} :scittle.pprint {:entries [scittle.pprint] :depends-on #{:scittle}} :scittle.reagent {:entries [scittle.reagent] :depends-on #{:scittle}} + :scittle.replicant {:entries [scittle.replicant] + :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}}}} + :output-dir "resources/public/js" ;; + "/dev" for dev build + :devtools {:repl-pprint true} + }}} diff --git a/src/scittle/cljs_devtools.cljs b/src/scittle/cljs_devtools.cljs new file mode 100644 index 0000000..cbe2082 --- /dev/null +++ b/src/scittle/cljs_devtools.cljs @@ -0,0 +1,6 @@ +(ns scittle.cljs-devtools + (:require [devtools.core :as devtools])) + +(devtools/set-pref! :disable-advanced-mode-check true) + +(devtools/install!) diff --git a/src/scittle/core.cljs b/src/scittle/core.cljs index beaa32e..c603d9c 100644 --- a/src/scittle/core.cljs +++ b/src/scittle/core.cljs @@ -2,7 +2,8 @@ (:refer-clojure :exclude [time]) (:require [cljs.reader :refer [read-string]] [goog.object :as gobject] - [goog.string] + [goog.string :as gstring] + [goog.string.format] [sci.core :as sci] [sci.ctx-store :as store] [sci.impl.unrestrict] @@ -43,21 +44,31 @@ 'NaN? (sci/copy-var NaN? cljns) 'infinite? (sci/copy-var infinite? cljns) 'iteration (sci/copy-var iteration cljns) - 'abs (sci/copy-var abs cljns)} + 'abs (sci/copy-var abs cljns) + 'Cons cljs.core/Cons} 'goog.object {'set gobject/set 'get gobject/get} + 'goog.string {'format gstring/format + 'htmlEscape gstring/htmlEscape} + 'goog.string.format {} ;; For cljs compatibility 'sci.core {'stacktrace sci/stacktrace 'format-stacktrace sci/format-stacktrace}}) +(defn load-fn [{:keys [ctx] :as opts}] + (when-let [lib (and (string? (:namespace opts)) + (gobject/get js/globalThis (:namespace opts)))] + (sci/add-js-lib! ctx (:namespace opts) lib))) + (store/reset-ctx! (sci/init {:namespaces namespaces :classes {'js js/globalThis :allow :all 'Math js/Math} :ns-aliases {'clojure.pprint 'cljs.pprint} - :features #{:scittle :cljs}})) + :features #{:scittle :cljs} + :load-fn load-fn})) -(unchecked-set js/globalThis "import" (js/eval "(x) => import x")) +(unchecked-set js/globalThis "import" (js/eval "(x) => import(x)")) (def !last-ns (volatile! @sci/ns)) diff --git a/src/scittle/js_interop.cljs b/src/scittle/js_interop.cljs new file mode 100644 index 0000000..603b565 --- /dev/null +++ b/src/scittle/js_interop.cljs @@ -0,0 +1,8 @@ +(ns scittle.js-interop + (:require + [sci.configs.applied-science.js-interop :as j] + [scittle.core :as scittle])) + +(scittle/register-plugin! + ::js-interop + j/config) diff --git a/src/scittle/nrepl.cljs b/src/scittle/nrepl.cljs index bfea685..ec4c38c 100644 --- a/src/scittle/nrepl.cljs +++ b/src/scittle/nrepl.cljs @@ -8,10 +8,11 @@ (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")))) + (new js/WebSocket (ws-url (or (.-SCITTLE_NREPL_WEBSOCKET_HOST js/window) + (.-hostname (.-location js/window))) + ws-port "_nrepl")))) (when-let [ws (nrepl-server/nrepl-websocket)] - (prn :ws ws) (set! (.-onmessage ws) (fn [event] (nrepl-server/handle-nrepl-message (edn/read-string (.-data event))))) diff --git a/src/scittle/replicant.cljs b/src/scittle/replicant.cljs new file mode 100644 index 0000000..b1c9c7a --- /dev/null +++ b/src/scittle/replicant.cljs @@ -0,0 +1,8 @@ +(ns scittle.replicant + (:require + [sci.configs.cjohansen.replicant :refer [config]] + [scittle.core :as scittle])) + +(scittle/register-plugin! + ::replicant + config)