Simplify exporting
This commit is contained in:
parent
c90b358c62
commit
01fb5d679f
|
@ -5,8 +5,8 @@
|
|||
<script src="js/sci-script-tag-plugin-reagent.js" type="application/javascript"></script>
|
||||
|
||||
<script type="application/x-sci">
|
||||
(defn my-alert []
|
||||
(js/alert "alert!"))
|
||||
(defn ^:export my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
|
||||
(require '[reagent.core :as r]
|
||||
'[reagent.dom :as rdom])
|
||||
|
@ -23,11 +23,14 @@
|
|||
</script>
|
||||
|
||||
<script src="cljs/script.cljs" type="application/x-sci"></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>SCI script tag</h1>
|
||||
<h2>What is this</h2>
|
||||
<h2>What is this?</h2>
|
||||
<p>This project exposes the <a href="https://github.com/borkdude/sci">Small Clojure Interpreter</a> in the
|
||||
browser in such a way that you can use it with the <tt>script</tt> tag.</p>
|
||||
<h2>Project status</h2>
|
||||
|
@ -43,56 +46,67 @@
|
|||
|
||||
<h2><a href="#usage">Usage</a></h2>
|
||||
|
||||
Include <tt>sci-script-tag.js</tt> and write a <tt>script</tt> tag
|
||||
where <tt>type</tt> is set
|
||||
to <tt>application/x-sci</tt>. Use <tt>:export</tt> to make the function
|
||||
available in the JavaScript environment. The name is processed
|
||||
using <tt>munge</tt>.
|
||||
|
||||
<pre>
|
||||
<head>
|
||||
<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!"))
|
||||
</script>
|
||||
</head>
|
||||
<code class="html"><head>
|
||||
<script src="https://borkdude.github.io/sci-script-tag/js/sci-script-tag.js"
|
||||
type="application/javascript">
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<button onclick="user.myAlert()">
|
||||
Click me!
|
||||
</button>
|
||||
</body>
|
||||
</pre>
|
||||
<script type="application/x-sci">
|
||||
(defn ^:export my-alert []
|
||||
(js/alert "You clicked!"))
|
||||
</script>
|
||||
|
||||
<button onclick="user.myAlert()">
|
||||
Click me
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
</body></code></pre>
|
||||
|
||||
<script type="text/javascript">hljs.highlightAll();</script>
|
||||
|
||||
<button onclick="my_alert()">
|
||||
Click me!
|
||||
</button>
|
||||
|
||||
<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>
|
||||
<script src="cljs/script.cljs" type="application/x-sci"></script>
|
||||
</pre>
|
||||
<pre><code class="html">
|
||||
<script src="cljs/script.cljs" type="application/x-sci"></script>
|
||||
</code></pre>
|
||||
|
||||
<h2><a href="#reagent">Reagent plugin<a/></h2>
|
||||
|
||||
To enable <a href="https://github.com/reagent-project/reagent">reagent</a>,
|
||||
in addition to <tt>sci-script-tag.js</tt>, you need to include <tt>sci-script-tag-plugin-reagent.js</tt>.
|
||||
|
||||
<pre>
|
||||
<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])
|
||||
<pre><code class="html">
|
||||
<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}))
|
||||
(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!"]]])
|
||||
(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>
|
||||
</pre>
|
||||
(rdom/render [my-component] (.getElementById js/document "app"))
|
||||
</script>
|
||||
</code></pre>
|
||||
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
|
|
@ -1,50 +1,59 @@
|
|||
(ns sci.script-tag
|
||||
(:require [clojure.string :as str]
|
||||
(:refer-clojure :exclude [defn])
|
||||
(:require [clojure.core :as c]
|
||||
[clojure.string :as str]
|
||||
[goog.object :as gobject]
|
||||
[goog.string]
|
||||
[sci.core :as sci]))
|
||||
|
||||
(defn kebab->camel [s]
|
||||
(str/replace s #"-[a-zA-Z0-9]"
|
||||
(fn [s]
|
||||
(str/upper-case (.charAt s 1)))))
|
||||
(c/defmacro defn [fn-name & args]
|
||||
(let [ns-sym (gensym "ns")]
|
||||
`(let [~ns-sym (ns-name *ns*)]
|
||||
(clojure.core/defn ~fn-name ~@args)
|
||||
~(when (:export (meta fn-name))
|
||||
`(sci.script-tag/-export ~fn-name (str ~ns-sym "." '~fn-name))))))
|
||||
|
||||
(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))))
|
||||
(c/defn -export [f k]
|
||||
(let [k (munge k)
|
||||
parts (str/split k #"\.")]
|
||||
(loop [parts parts
|
||||
prev js/window]
|
||||
(let [fpart (first parts)]
|
||||
(cond (= "user" fpart)
|
||||
(recur (rest parts) prev)
|
||||
(= 1 (count parts))
|
||||
(gobject/set prev fpart f)
|
||||
:else
|
||||
(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)))
|
||||
|
||||
(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}}
|
||||
(def stns (sci/create-ns 'sci.script-tag nil))
|
||||
|
||||
(def namespaces
|
||||
{'sci.script-tag
|
||||
{'defn (sci/copy-var defn stns)
|
||||
'-export (sci/copy-var -export stns)}
|
||||
'clojure.core {'println (sci/copy-var println stns)
|
||||
'prn (sci/copy-var prn stns)}})
|
||||
|
||||
(def ctx (atom (sci/init {:namespaces namespaces
|
||||
:classes {'js js/window
|
||||
:allow :all}})))
|
||||
|
||||
(defn eval-string [s]
|
||||
(c/defn eval-string [s]
|
||||
(sci/eval-string* @ctx
|
||||
(str "(require '[sci.script-tag :refer :all])"
|
||||
s)))
|
||||
|
||||
(defn merge-ctx [opts]
|
||||
(c/defn merge-ctx [opts]
|
||||
(swap! ctx sci/merge-opts opts))
|
||||
|
||||
(defn- load-contents [script-tags]
|
||||
(c/defn- load-contents [script-tags]
|
||||
(when-first [tag script-tags]
|
||||
(if-let [text (not-empty (gobject/get tag "textContent"))]
|
||||
(do (eval-string text)
|
||||
|
|
Loading…
Reference in a new issue