From d8fef42c64dafbc835d7f645de3b1051df45ec9d Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 23 May 2021 16:31:05 +0200 Subject: [PATCH] Reagent --- deps.edn | 12 +-- package-lock.json | 119 +++++++++++++++++++++++++ package.json | 6 ++ resources/public/index.html | 50 +++++++++-- script/release.clj | 19 ++-- shadow-cljs.edn | 5 +- src/sci/script_tag.cljs | 46 +++++----- src/sci/script_tag/plugin_reagent.cljs | 20 +++++ 8 files changed, 238 insertions(+), 39 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/sci/script_tag/plugin_reagent.cljs diff --git a/deps.edn b/deps.edn index 3061875..a24fda8 100644 --- a/deps.edn +++ b/deps.edn @@ -3,13 +3,13 @@ :deps {org.clojure/clojure {:mvn/version "1.10.3"} borkdude/sci {:git/url "https://github.com/borkdude/sci" - :sha "4de7c78024bfdb5c52e273be372144d46228939a"}} + :sha "4de7c78024bfdb5c52e273be372144d46228939a"} + reagent/reagent {:mvn/version "1.0.0"} + cljsjs/react {:mvn/version "17.0.2-0"} + cljsjs/react-dom {:mvn/version "17.0.2-0"} + cljsjs/react-dom-server {:mvn/version "17.0.2-0"}} :aliases {:dev {:extra-paths ["dev"] - :extra-deps {thheller/shadow-cljs {:mvn/version "2.12.5"}}} - - :test - {:extra-paths ["test"] - :extra-deps {lambdaisland/kaocha {:mvn/version "1.0.829"}}}}} + :extra-deps {thheller/shadow-cljs {:mvn/version "2.12.5"}}}}} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c4c5d52 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,119 @@ +{ + "name": "sci-script-tag", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "react": "17.0.1", + "react-dom": "17.0.1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", + "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.1" + }, + "peerDependencies": { + "react": "17.0.1" + } + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "react": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", + "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-dom": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.1" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4b98f1c --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "react": "17.0.1", + "react-dom": "17.0.1" + } +} diff --git a/resources/public/index.html b/resources/public/index.html index e84a33e..cc3a31f 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -1,13 +1,28 @@ - + + +

SCI script tag

@@ -20,16 +35,16 @@ bound to happen. Feedback is welcome on Github.

You can get a copy - of sci_script_tag.js here. If - you want a pinned version of sci_script_tag.js, your best bet is to + of sci-script-tag.js here. If + you want a pinned version of sci-script-tag.js, your best bet is to download your own copy and host it yourself.

-

Example usage

+

Usage

       <head>
-        <script src="https://borkdude.github.io/sci-script-tag/js/sci_script_tag.js" type="application/javascript"></script>
+        <script src="https://borkdude.github.io/sci-script-tag/js/sci-script-tag.js" type="application/javascript"></script>
         <script type="application/x-sci">
           (defn my-alert []
            (js/alert "alert!"))
@@ -46,5 +61,30 @@
     
+
+    

Reagent plugin

+ + To enable reagent, + in addition to sci-script-tag.js, you need to include sci-script-tag-plugin-reagent.js. + +
+        <script src="https://borkdude.github.io/sci-script-tag/js/sci-script-tag-plugin-reagent.js" type="application/javascript"></script>
+        <script type="application/x-sci">
+          (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>
+    
+ +
diff --git a/script/release.clj b/script/release.clj index 6010e64..6086fe9 100755 --- a/script/release.clj +++ b/script/release.clj @@ -1,18 +1,23 @@ #!/usr/bin/env bb (require '[babashka.fs :as fs] - '[babashka.tasks :refer [shell]] - '[clojure.string :as str]) + '[babashka.tasks :refer [shell]]) (fs/copy "resources/public/index.html" "gh-pages" {:replace-existing true}) (shell "clojure -M:dev -m shadow.cljs.devtools.cli release main") (def index-file (fs/file "gh-pages" "index.html")) -(spit index-file (str/replace (slurp index-file) "main.js" "sci_script_tag.js")) -(fs/create-dirs (fs/file "gh-pages" "js")) -(fs/copy (fs/file "resources" "public" "js" "main.js") - (fs/file "gh-pages" "js" "sci_script_tag.js") - {: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) + +(run! (fn [f] + (println "Copying" (str f)) + (fs/copy f + js-target-dir + {:replace-existing true})) + (fs/glob js-source-dir "sci-script-tag*.js")) (def with-gh-pages (partial shell {:dir "gh-pages"})) (with-gh-pages "git add .") diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 729240b..03ab8ba 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -7,6 +7,9 @@ :builds {:main {:target :browser - :modules {:main {:entries [sci.script-tag]}} + :modules + {:sci-script-tag {:entries [sci.script-tag]} + :sci-script-tag-plugin-reagent {:entries [sci.script-tag.plugin-reagent] + :depends-on #{:sci-script-tag}}} :output-dir "resources/public/js" :devtools {:repl-pprint true}}}} diff --git a/src/sci/script_tag.cljs b/src/sci/script_tag.cljs index 55e63ba..c421aa9 100644 --- a/src/sci/script_tag.cljs +++ b/src/sci/script_tag.cljs @@ -9,35 +9,41 @@ (fn [s] (str/upper-case (.charAt s 1))))) -(defn defn-macro [_ _ fn-name & args] +(defn- defn-macro [_ _ fn-name & args] `(let [ns# (ns-name *ns*)] (clojure.core/defn ~fn-name ~@args) (sci.script-tag/-export ~fn-name (str ns# "." '~fn-name)))) -(def ctx (sci/init {:namespaces {'sci.script-tag - {'defn (with-meta defn-macro - {:sci/macro true}) - '-export (fn [f k] - (let [parts (str/split k #"\.")] - (loop [parts parts - prev js/window] - (let [fpart (first parts) - fpart (kebab->camel fpart)] - (if (= 1 (count parts)) - (gobject/set prev fpart f) - (do (gobject/set prev fpart #js {}) - (recur (rest parts) - (gobject/get prev fpart)))))) - (gobject/set js/window k f)))} - 'clojure.core {'println println}} - :classes {'js js/window - :allow :all}})) +(def ctx (atom (sci/init {:namespaces {'sci.script-tag + {'defn (with-meta defn-macro + {:sci/macro true}) + '-export (fn [f k] + (let [parts (str/split k #"\.")] + (loop [parts parts + prev js/window] + (let [fpart (first parts) + fpart (kebab->camel fpart)] + (if (= 1 (count parts)) + (gobject/set prev fpart f) + (if-let [obj (gobject/get prev fpart)] + (recur (rest parts) obj) + (let [obj #js {}] + (gobject/set prev fpart obj) + (recur (rest parts) + obj)))))) + (gobject/set js/window k f)))} + 'clojure.core {'println println}} + :classes {'js js/window + :allow :all}}))) (defn eval-string [s] - (sci/eval-string* ctx + (sci/eval-string* @ctx (str "(require '[sci.script-tag :refer :all])" s))) +(defn merge-ctx [opts] + (swap! ctx sci/merge-opts opts)) + (js/document.addEventListener "DOMContentLoaded" (fn [] diff --git a/src/sci/script_tag/plugin_reagent.cljs b/src/sci/script_tag/plugin_reagent.cljs new file mode 100644 index 0000000..24eb83a --- /dev/null +++ b/src/sci/script_tag/plugin_reagent.cljs @@ -0,0 +1,20 @@ +(ns sci.script-tag.plugin-reagent + (:require [reagent.core :as r] + [reagent.dom :as rdom] + [sci.core :as sci] + [sci.script-tag :as st])) + +(def rns (sci/create-ns 'reagent.core nil)) + +(def reagent-namespace + {'atom (sci/copy-var r/atom rns)}) + +(def rdns (sci/create-ns 'reagent.dom nil)) + +(def reagent-dom-namespace + {'render (sci/copy-var rdom/render rdns)}) + +(println :merging) +(st/merge-ctx {:namespaces {'reagent.core reagent-namespace + 'reagent.dom reagent-dom-namespace}}) +(println :done-merging)