mirror of
https://github.com/status-im/pluto.git
synced 2025-02-23 16:08:14 +00:00
Published demo site
This commit is contained in:
parent
a91faf961c
commit
5761bf27dc
14
README.md
14
README.md
@ -1,18 +1,8 @@
|
||||
Launch figwheel with ./scripts/figwheel.sh then open index.html
|
||||
Launch figwheel with ./scripts/figwheel.sh then open http://127.0.0.1/index.html
|
||||
|
||||
### IPFS
|
||||
|
||||
You need to start a daemon locally, as the main gateway has CORS. The mobile app
|
||||
does not have this limitation and can hit directly the gateway.
|
||||
|
||||
Before starting the dameon setup CORS:
|
||||
|
||||
```
|
||||
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
|
||||
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["GET", "POST"]'
|
||||
```
|
||||
|
||||
and then
|
||||
To upload a directory to IPFS:
|
||||
|
||||
```
|
||||
ipfs daemon
|
||||
|
14
build.clj
14
build.clj
@ -10,8 +10,8 @@
|
||||
|
||||
(def compiler-config {:main 'pluto.demo
|
||||
:asset-path "js/out"
|
||||
:output-to "resources/public/js/pluto.js"
|
||||
:output-dir "resources/public/js/out"
|
||||
:output-to "resources/public/assets/pluto.js"
|
||||
:output-dir "resources/public/assets/pluto"
|
||||
:optimizations :none
|
||||
:static-fns true
|
||||
:elide-asserts false
|
||||
@ -19,6 +19,12 @@
|
||||
:preloads ['day8.re-frame-10x.preload]
|
||||
:source-map true})
|
||||
|
||||
(def compiler-release-config {:main 'pluto.demo
|
||||
:output-to "resources/public/assets/pluto.js"
|
||||
:optimizations :advanced
|
||||
:static-fns true
|
||||
:elide-asserts true})
|
||||
|
||||
(def test-config {:main 'pluto.runner
|
||||
:output-to "target/test.js"
|
||||
:output-dir "target/test"
|
||||
@ -65,7 +71,7 @@
|
||||
;;; Compiling task.
|
||||
|
||||
(defn compile-once []
|
||||
(api/build source-dir compiler-config))
|
||||
(api/build source-dir compiler-release-config))
|
||||
|
||||
(defn compile-refresh []
|
||||
(api/watch source-dir compiler-config))
|
||||
@ -118,4 +124,4 @@
|
||||
|
||||
;;; Build script entrypoint.
|
||||
|
||||
(task *command-line-args*)
|
||||
(task (map string/trim *command-line-args*))
|
||||
|
44
demo/index.html
Normal file
44
demo/index.html
Normal file
@ -0,0 +1,44 @@
|
||||
<html>
|
||||
<script type="text/javascript" src="assets/instascan.min.js"></script>
|
||||
<script type="text/javascript" src="assets/qrcode.min.js"></script>
|
||||
<body>
|
||||
<main>
|
||||
<div id="selection">
|
||||
<span>Scan this QR code to load from IPFS</span>
|
||||
<div id="ipfs"></div>
|
||||
<div>
|
||||
Or load from HTTP <button onclick="pluto.demo.load_and_render('ipfs:QmSKP6f2uUsFq4mk1Afe4ZktxwQifrLb4xRQYNE1LxidKz')">Demo</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="extension">
|
||||
<iframe id="frame" srcdoc="<body><main></main></body>"></iframe>
|
||||
<div id="errors"></div>
|
||||
</div>
|
||||
<video id="preview"></video>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script src="assets/pluto.js"></script>
|
||||
<script>
|
||||
var qrcode = new QRCode("ethereum:status-extension:ipfs:QmSKP6f2uUsFq4mk1Afe4ZktxwQifrLb4xRQYNE1LxidKz");
|
||||
var svg = qrcode.svg();
|
||||
document.getElementById("ipfs").innerHTML = svg;
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let scanner = new Instascan.Scanner({ video: document.getElementById('preview') });
|
||||
scanner.addListener('scan', function (content) {
|
||||
console.log(content);
|
||||
pluto.demo.load_and_render(content.replace("ethereum:status-extension:", ""));
|
||||
});
|
||||
Instascan.Camera.getCameras().then(function (cameras) {
|
||||
if (cameras.length > 0) {
|
||||
scanner.start(cameras[0]);
|
||||
} else {
|
||||
console.error('No cameras found.');
|
||||
|
||||
}
|
||||
}).catch(function (e) {
|
||||
console.error(e);
|
||||
});
|
||||
</script>
|
1244
demo/pluto.js
Normal file
1244
demo/pluto.js
Normal file
File diff suppressed because one or more lines are too long
48
resources/public/assets/instascan.min.js
vendored
Normal file
48
resources/public/assets/instascan.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1244
resources/public/assets/pluto.js
Normal file
1244
resources/public/assets/pluto.js
Normal file
File diff suppressed because one or more lines are too long
2
resources/public/assets/qrcode.min.js
vendored
Normal file
2
resources/public/assets/qrcode.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,12 +0,0 @@
|
||||
{:hooks/main
|
||||
#view [:main]
|
||||
|
||||
:views/main
|
||||
[view {}
|
||||
[text "Hello"]]}
|
||||
|
||||
|
||||
; (let [cond? #query [:random-boolean]]
|
||||
; (when cond?
|
||||
; [text {}]
|
||||
; "World"))
|
19
resources/public/extensions/demo/extension.edn
Normal file
19
resources/public/extensions/demo/extension.edn
Normal file
@ -0,0 +1,19 @@
|
||||
{:extension/meta
|
||||
{:name "Simple Demo"
|
||||
:description "A simple demo of extension"
|
||||
:documentation "Nothing. Just see a text with dynamic random color."}
|
||||
|
||||
:hooks/main
|
||||
{:name ""
|
||||
:description ""
|
||||
:view #status/view [:main]}
|
||||
|
||||
:views/main
|
||||
[view {}
|
||||
[text {} "Hello"]
|
||||
(let [cond? #status/query [:random-boolean]]
|
||||
(if cond?
|
||||
[text {:style {:color "green"}}
|
||||
"World?"]
|
||||
[text {:style {:color "red"}}
|
||||
"World?"]))]}
|
@ -7,18 +7,18 @@
|
||||
{:on-activated #event [:fetch-all-posts]}
|
||||
|
||||
:events/fetch-all-posts
|
||||
[:ethereum/logs {:address "0xfa28ec7198028438514b49a3cf353bca5541ce1d"
|
||||
[:status/ethereum.logs {:address "0xfa28ec7198028438514b49a3cf353bca5541ce1d"
|
||||
:topics ["PeepEth()"]
|
||||
:inputs [{:name :hash :type :string}] ;; Allows to decode transaction data
|
||||
:on-log #event [:fetch-ipfs]}] ;; A map of decoded data will be injected
|
||||
:on-log #status/event [:fetch-ipfs]}] ;; A map of decoded data will be injected
|
||||
|
||||
:events/fetch-ipfs
|
||||
(let [{:keys [hash]} properties]
|
||||
[:ipfs/get {:hash hash
|
||||
:on-success #event [:db/append {:path [:all-posts]}]}])
|
||||
[:status/ipfs.get {:hash hash
|
||||
:on-success #status/event [:status/db.append {:path [:all-posts]}]}])
|
||||
|
||||
:queries/all-posts
|
||||
[:db/get {:path [:all-posts]
|
||||
[:status/db.get {:path [:all-posts]
|
||||
:limit 20}]
|
||||
|
||||
:views/post
|
||||
@ -43,10 +43,10 @@
|
||||
{:en "Peepeth !!"}
|
||||
|
||||
:hooks/main
|
||||
[screen {:style #style [:screen]}
|
||||
[screen {:style #status/style [:screen]}
|
||||
[toolbar {}
|
||||
[text {}
|
||||
#i18n [:title]]]
|
||||
(let {posts #query [:all-posts]}
|
||||
(let [posts #status/query [:all-posts]]
|
||||
[list {:data posts
|
||||
:template #view [:post]}])]}
|
||||
:template #status/view [:post]}])]}
|
@ -1,10 +1,44 @@
|
||||
<html>
|
||||
<script type="text/javascript" src="assets/instascan.min.js"></script>
|
||||
<script type="text/javascript" src="assets/qrcode.min.js"></script>
|
||||
<body>
|
||||
<main>
|
||||
<div id="selection">
|
||||
<span>Scan this QR code to load from IPFS</span>
|
||||
<div id="ipfs"></div>
|
||||
<div>
|
||||
Or load from HTTP <button onclick="pluto.demo.load_and_render('ipfs:QmSKP6f2uUsFq4mk1Afe4ZktxwQifrLb4xRQYNE1LxidKz')">Demo</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="extension">
|
||||
<iframe id="frame" srcdoc="<body><main></main></body>"></iframe>
|
||||
<div id="errors"></div>
|
||||
</div>
|
||||
<video id="preview"></video>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script src="js/pluto.js"></script>
|
||||
<script src="assets/pluto.js"></script>
|
||||
<script>
|
||||
pluto.demo.run();
|
||||
var qrcode = new QRCode("ethereum:status-extension:ipfs:QmSKP6f2uUsFq4mk1Afe4ZktxwQifrLb4xRQYNE1LxidKz");
|
||||
var svg = qrcode.svg();
|
||||
document.getElementById("ipfs").innerHTML = svg;
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let scanner = new Instascan.Scanner({ video: document.getElementById('preview') });
|
||||
scanner.addListener('scan', function (content) {
|
||||
console.log(content);
|
||||
pluto.demo.load_and_render(content.replace("ethereum:status-extension:", ""));
|
||||
});
|
||||
Instascan.Camera.getCameras().then(function (cameras) {
|
||||
if (cameras.length > 0) {
|
||||
scanner.start(cameras[0]);
|
||||
} else {
|
||||
console.error('No cameras found.');
|
||||
|
||||
}
|
||||
}).catch(function (e) {
|
||||
console.error(e);
|
||||
});
|
||||
</script>
|
||||
|
4
scripts/publish.sh
Normal file
4
scripts/publish.sh
Normal file
@ -0,0 +1,4 @@
|
||||
mkdir -p demo
|
||||
clj -R:repl build.clj compile once
|
||||
cp resources/public/assets/pluto.js demo/
|
||||
cp resources/public/index.html demo/
|
@ -3,11 +3,11 @@
|
||||
(defn view [props & content]
|
||||
(into [:div props] content))
|
||||
|
||||
(defn button [props content]
|
||||
[:button props content])
|
||||
(defn button [props & content]
|
||||
(into [:button props] content))
|
||||
|
||||
(defn text [props content]
|
||||
[:span props content])
|
||||
(defn text [props & content]
|
||||
(into [:span props] content))
|
||||
|
||||
(def components {'view view
|
||||
'button button
|
||||
|
@ -1,5 +1,6 @@
|
||||
(ns pluto.demo
|
||||
(:require [pluto.components.html :as html]
|
||||
(:require [clojure.string :as string]
|
||||
[pluto.components.html :as html]
|
||||
[pluto.reader :as reader]
|
||||
[pluto.storage :as storage]
|
||||
[pluto.storage.http :as http]
|
||||
@ -34,19 +35,18 @@
|
||||
(let [frame (js/document.getElementById "frame")]
|
||||
(reagent/render (h) (.. (aget frame "contentWindow" "document") -body -firstChild))))
|
||||
|
||||
(defn header []
|
||||
[:div
|
||||
"Random boolean: "
|
||||
(let [b @(re-frame/subscribe [:random-boolean])]
|
||||
[:span {:style {:color (if b :green :red)}}
|
||||
(str b)])])
|
||||
|
||||
(defn wrap-with-cartouche [o]
|
||||
(println ">>>>" o)
|
||||
(defn main-browser
|
||||
"A simple hook for :hooks/main"
|
||||
[{:keys [data errors]}]
|
||||
(fn []
|
||||
[:div
|
||||
^{:key 1} [header]
|
||||
^{:key 2} o]))
|
||||
(let [{:views/keys [main]} data]
|
||||
main)
|
||||
(when (seq errors)
|
||||
(into [:ul]
|
||||
(for [{:keys [type] :as m} errors]
|
||||
[:li
|
||||
[:span [:b (str type)] (pr-str (dissoc m :type))]])))]))
|
||||
|
||||
(defn wrap-extensions [os]
|
||||
(fn []
|
||||
@ -56,23 +56,28 @@
|
||||
[:h2 (:name o)]
|
||||
[:p (:content o)]])]))
|
||||
|
||||
(defn ^:export run
|
||||
[]
|
||||
(defn storage-for [type]
|
||||
(condp = type
|
||||
"url" (http/HTTPStorage.)
|
||||
"ipfs" (ipfs/IPFSStorage. "https://gateway.ipfs.io")))
|
||||
|
||||
(defn fetch [uri cb]
|
||||
(let [[type id] (string/split uri ":")]
|
||||
(storage/fetch
|
||||
(storage-for type)
|
||||
{:value id} cb)))
|
||||
|
||||
(defn ^:export load-and-render
|
||||
[s]
|
||||
(re-frame/clear-subscription-cache!)
|
||||
|
||||
(storage/fetch (ipfs/IPFSStorage. "http://localhost:8080")
|
||||
{:id "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG" :URL "/demo.edn"}
|
||||
#(->> %
|
||||
wrap-extensions
|
||||
render))
|
||||
|
||||
(storage/fetch (http/HTTPStorage.)
|
||||
{:URL "/demo.edn"}
|
||||
(fetch s
|
||||
#(-> %
|
||||
;; TODO merge all returned files in a map
|
||||
:value
|
||||
first
|
||||
:content
|
||||
reader/read
|
||||
:data
|
||||
((fn [m] (println "<<<" m) (reader/parse {:components html/components :valid-hooks #{:hooks/main}} m)))
|
||||
:data
|
||||
:views/main
|
||||
wrap-with-cartouche
|
||||
((fn [m] (reader/parse {:components html/components :valid-extensions #{:extension/meta} :valid-hooks #{:hooks/main}} m)))
|
||||
main-browser
|
||||
render)))
|
||||
|
@ -49,10 +49,10 @@
|
||||
{:data
|
||||
(try
|
||||
(edn/read-string {:default #(do (accumulate-reader-error! errors {:type :unknown-tag :tag %1 :value %2}) %2)
|
||||
:readers {'query #(mark-reference :query %)
|
||||
'event #(mark-reference :event %)
|
||||
'view #(mark-reference :view %)
|
||||
'style #(mark-reference :style %)}}
|
||||
:readers {'status/query #(mark-reference :query %)
|
||||
'status/event #(mark-reference :event %)
|
||||
'status/view #(mark-reference :view %)
|
||||
'status/style #(mark-reference :style %)}}
|
||||
s)
|
||||
(catch #?(:clj Exception :cljs :default) e
|
||||
(accumulate-reader-error! errors (assoc (ex-data e) :message (ex-message e)))
|
||||
@ -101,26 +101,25 @@
|
||||
(reduce #(let [{:keys [data errors]} (parse-view opts %2)]
|
||||
(cond-> (update %1 :data conj data)
|
||||
(seq errors) (accumulate-errors errors)))
|
||||
{} children))
|
||||
{:data []} children))
|
||||
|
||||
(defn parse-hiccup-element [{:keys [components] :as opts} o]
|
||||
;; TODO permissions
|
||||
;; TODO replace elements
|
||||
(cond
|
||||
(primitive? o) {:data o}
|
||||
(or (symbol? o) (primitive? o)) {:data o}
|
||||
(vector? o)
|
||||
(let [[element properties & children] o
|
||||
component (element components)]
|
||||
component (if (fn? element) element (get components element))]
|
||||
(cond-> (let [m (parse-hiccup-children opts children)]
|
||||
;; Reduce parsed children to a single map and wrap them in a hiccup element
|
||||
;; whose component has been translated to the local platform
|
||||
(update m :data #(apply conj [(or component element) properties] %)))
|
||||
(nil? component) (accumulate-errors [{:type :unknown-component :element element}])))))
|
||||
(nil? component) (accumulate-errors [{:type :unknown-component :element element}])))
|
||||
:else 3))
|
||||
|
||||
(defn parse-view [opts o]
|
||||
(cond
|
||||
(instance? Reference o) (resolve-reference (:tag o) (:value o))
|
||||
(list? o) (blocks/parse opts o)
|
||||
(list? o) (parse-view opts (:data (blocks/parse opts o)))
|
||||
:else (parse-hiccup-element opts o)))
|
||||
|
||||
(defmulti parse-value
|
||||
@ -131,9 +130,12 @@
|
||||
* :errors a collection of errors"
|
||||
(fn [_ k _] (namespace k)))
|
||||
|
||||
(defmethod parse-value "extension" [opts _ v] v)
|
||||
|
||||
(defmethod parse-value "views" [opts _ v] (parse-view opts v))
|
||||
|
||||
;; TODO extension, events, queries, i18n, styles
|
||||
(defmethod parse-value :default [_ k _] {:errors [{:type :unkown-element-type :value k}]})
|
||||
(defmethod parse-value :default [_ k _] {:errors [{:type :unknown-element-type :value k}]})
|
||||
|
||||
(defn merge-parsed-value
|
||||
"Merge result of parse-value into a map.
|
||||
@ -157,10 +159,6 @@
|
||||
* :permissions a vector of required permissions
|
||||
* :errors a vector of errors map triggered during parse"
|
||||
[opts m]
|
||||
;; TODO
|
||||
; Replace lookup refs with values
|
||||
; Replace conditional blocks with reagent components
|
||||
; Errors; Permissions; env cascade (:outer)
|
||||
(let [errors (validate-keys opts (keys m))]
|
||||
(cond-> (reduce-kv #(merge-parsed-value opts %1 %2 %3) {} m)
|
||||
(seq errors) (accumulate-errors errors))))
|
||||
(seq errors) (accumulate-errors (map (fn [error] {:type (key error) :value (val error)}) errors)))))
|
||||
|
56
src/pluto/reader/blocks.cljc
Normal file
56
src/pluto/reader/blocks.cljc
Normal file
@ -0,0 +1,56 @@
|
||||
(ns pluto.reader.blocks
|
||||
(:require [clojure.walk :as walk]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defmulti parse
|
||||
""
|
||||
(fn [_ [type]] type))
|
||||
|
||||
(defn resolve-queries [env]
|
||||
;; TODO only resolve encoded queries
|
||||
(reduce-kv #(assoc %1 %2 (if (record? %3) @(re-frame/subscribe (:value %3))) %3)
|
||||
{}
|
||||
env))
|
||||
|
||||
(defn let-block [{:keys [env]} child]
|
||||
(cond
|
||||
(coll? child) (walk/prewalk-replace (resolve-queries env) child)))
|
||||
|
||||
(defn bindings->env [v]
|
||||
;; TODO errors: pair number of arguments, keys are symbols, values are primitives or queries
|
||||
;; TODO destructuring
|
||||
(apply hash-map v))
|
||||
|
||||
(defmethod parse 'let [_ [_ bindings & body]]
|
||||
{:data
|
||||
;; TODO error if multiple body as let only considers last
|
||||
(let [m (bindings->env bindings)
|
||||
child (last body)]
|
||||
[let-block {:env m} child])})
|
||||
|
||||
(defn when-block [{:keys [test]} body]
|
||||
;; TODO warning if test is not of boolean type
|
||||
(when test
|
||||
body))
|
||||
|
||||
(defmethod parse 'when [_ [_ test & body]]
|
||||
(cond
|
||||
(symbol? test)
|
||||
{:data (apply conj [when-block {:test test}] body)}
|
||||
:else
|
||||
{:errors [{:type :unsupported-type :value test}]}))
|
||||
|
||||
(defn if-block [{:keys [test]} & body]
|
||||
;; TODO warning if test is not of boolean type
|
||||
(if test
|
||||
(first body)
|
||||
(second body)))
|
||||
|
||||
(defmethod parse 'if [_ [_ test then else]]
|
||||
(cond
|
||||
(symbol? test)
|
||||
{:data (apply conj [if-block {:test test}] (list then else))}
|
||||
:else
|
||||
{:errors [{:type :unsupported-type :value test}]}))
|
||||
|
||||
(defmethod parse :default [opts block] {:errors [{:type :unknown-block-type :opts opts :block block}]})
|
@ -1,73 +0,0 @@
|
||||
(ns pluto.reader.blocks
|
||||
(:require [re-frame.core :as re-frame]))
|
||||
|
||||
(defmulti parse (fn [_ [type]] type))
|
||||
|
||||
(defn bindings->env [v]
|
||||
(apply hash-map v))
|
||||
|
||||
(defn primitive? [o]
|
||||
(or (boolean? o)
|
||||
(int? o)
|
||||
(float? o)
|
||||
(string? o)))
|
||||
|
||||
(defmulti encode-value (fn [[f & _]] f))
|
||||
|
||||
(defmethod encode-value 'query [[_ & args]] (apply conj args))
|
||||
|
||||
(defn env-value [o]
|
||||
;; TODO encode query as record. Validate query exists and potentially that data type matches
|
||||
;; Ensure rest is pure data or arguments
|
||||
(println "ENV" o (type o))
|
||||
(cond
|
||||
(list? o) (encode-value o)
|
||||
(primitive? o) o
|
||||
#_(and (instance? Reference o)
|
||||
(= :query (:type o)))
|
||||
;o
|
||||
;; TODO accumulate errors
|
||||
:else {:errors [{:type :incorrect-let-value :value o}]}))
|
||||
|
||||
(defn env [m]
|
||||
(reduce-kv #(assoc %1 %2 (env-value %3))
|
||||
{}
|
||||
m))
|
||||
|
||||
(defn resolve-queries [env]
|
||||
;; TODO only resolve encoded queries
|
||||
(reduce-kv #(assoc %1 %2 @(re-frame/subscribe %3))
|
||||
{}
|
||||
env))
|
||||
|
||||
(defn let-block [{:keys [env]} [k p children]]
|
||||
;; Propagate env as meta on children element
|
||||
;; TODO support multiple children
|
||||
;; TODO figure out envs as part of properties, with cascading scopes (delegate to :outer)
|
||||
;; Disallow symbol shadowing
|
||||
[k (assoc p :env (resolve-queries env)) (with-meta children {:env (resolve-queries env)})])
|
||||
|
||||
(defmethod parse 'let [_ [_ bindings & body]]
|
||||
{:data
|
||||
;; TODO validate pairs of data
|
||||
;; keys -> symbols
|
||||
;; values -> primitive types, query
|
||||
;; TODO warning if multiple body as let only considers last
|
||||
(let [m (bindings->env bindings)]
|
||||
[let-block {:env (env m)} (last body)])})
|
||||
|
||||
(defn test? [{:keys [env test]}]
|
||||
(cond
|
||||
(boolean? test) test
|
||||
(symbol? test) (test env)))
|
||||
|
||||
(defn when-block [props body]
|
||||
(when (test? props)
|
||||
body))
|
||||
|
||||
(defmethod parse 'when [[props test & body]]
|
||||
;; TODO test can only be a symbol. This symbol must point to primitive type or query.
|
||||
;; TODO If value known at read time, resolve statically
|
||||
(apply conj [when-block {:test test :env (:env (meta body))}] body))
|
||||
|
||||
(defmethod parse :default [opts block] {:errors [{:type :unknown-block-type :opts opts :block block}]})
|
@ -1,12 +1,18 @@
|
||||
(ns pluto.storage.http
|
||||
(:require [pluto.storage :as storage]))
|
||||
|
||||
(defn result [xhr]
|
||||
(let [status (.-status xhr)]
|
||||
(if (= 404 status)
|
||||
{:type :error :value status}
|
||||
{:type :success :value (.-responseText xhr)})))
|
||||
|
||||
(deftype HTTPStorage []
|
||||
storage/Storage
|
||||
(fetch [_ id callback]
|
||||
(fetch [_ {:keys [value]} callback]
|
||||
(let [xhr (js/XMLHttpRequest.)]
|
||||
(.open xhr "GET" (:URL id) true)
|
||||
(.open xhr "GET" (str value "/extension.edn") true)
|
||||
(.send xhr nil)
|
||||
(set! (.-onreadystatechange xhr)
|
||||
#(when (= (.-readyState xhr) 4)
|
||||
(callback (.-response xhr)))))))
|
||||
(callback (result xhr)))))))
|
||||
|
@ -1,16 +1,18 @@
|
||||
(ns pluto.storage.ipfs
|
||||
(:require [pluto.storage :as storage]))
|
||||
(:require [clojure.string :as string]
|
||||
[pluto.storage :as storage]))
|
||||
|
||||
(defn- ipfs->extension [ipfs-extension]
|
||||
{:extension-id (:Hash ipfs-extension)
|
||||
:name (:Name ipfs-extension)})
|
||||
|
||||
(defn parse-directory [response]
|
||||
(when-not (string/blank? response)
|
||||
(->> (js->clj (js/JSON.parse response) :keywordize-keys true)
|
||||
:Objects
|
||||
first
|
||||
:Links
|
||||
(map ipfs->extension)))
|
||||
(map ipfs->extension))))
|
||||
|
||||
(defn fetch-promise [url]
|
||||
(new js/Promise (fn [resolve reject]
|
||||
@ -19,7 +21,8 @@
|
||||
(.send xhr nil)
|
||||
(set! (.-onreadystatechange xhr)
|
||||
#(when (= (.-readyState xhr) 4)
|
||||
(resolve (.-response xhr))))))))
|
||||
;; TODO handle error codes
|
||||
(resolve (.-responseText xhr))))))))
|
||||
|
||||
(defn list-all [gateway-url directory]
|
||||
(fetch-promise (str gateway-url "/api/v0/ls?arg=" directory)))
|
||||
@ -41,7 +44,7 @@
|
||||
storage/Storage
|
||||
(fetch [this extension callback]
|
||||
(..
|
||||
(list-all gateway-url (:id extension))
|
||||
(list-all gateway-url (:value extension))
|
||||
(then parse-directory)
|
||||
(then (partial fetch-all gateway-url))
|
||||
(then callback))))
|
||||
(then #(callback {:type :success :value %})))))
|
||||
|
7
test/pluto/reader/block_test.cljs
Normal file
7
test/pluto/reader/block_test.cljs
Normal file
@ -0,0 +1,7 @@
|
||||
(ns pluto.reader.blocks-test
|
||||
(:require [cljs.test :refer-macros [is deftest async use-fixtures]]
|
||||
[pluto.reader.blocks :as blocks]))
|
||||
|
||||
(deftest parse
|
||||
(is (= nil (blocks/parse {} '(let [s "Hello"] s))))
|
||||
(is (= nil (blocks/parse {} '(let [s "Hello"] ['test {} s])))))
|
@ -1,6 +1,7 @@
|
||||
(ns pluto.reader-test
|
||||
(:require [cljs.test :refer-macros [is deftest async use-fixtures]]
|
||||
[pluto.reader :as reader :refer [Reference]]))
|
||||
[pluto.reader :as reader :refer [Reference]]
|
||||
[pluto.reader.blocks :as blocks]))
|
||||
|
||||
(deftest read
|
||||
(is (= {:data nil} (reader/read "")))
|
||||
@ -37,10 +38,11 @@
|
||||
(is (= {:invalid-hooks #{:hooks/unknown}}
|
||||
(reader/validate-keys {:valid-hooks #{:hooks/main}} #{:hooks/main :hooks/unknown}))))
|
||||
|
||||
#_
|
||||
(deftest parse-hiccup-children
|
||||
(is (= {:data (list [:text {} ""])} (reader/parse-hiccup-children {:components {'text :text}} (list ['text {} ""])))))
|
||||
|
||||
|
||||
#_
|
||||
(deftest parse
|
||||
(is (= {} (reader/parse {} {})))
|
||||
(is (= {:data {:views/main ['text {} "Hello"]}
|
||||
@ -51,13 +53,16 @@
|
||||
(is (= {:data {:views/main [:text {} "Hello"]}}
|
||||
(reader/parse {:components {'text :text}} {:views/main ['text {} "Hello"]}))))
|
||||
|
||||
#_
|
||||
(deftest parse-references
|
||||
(is (= {:data {:views/main [:pluto.reader-test/main]}} (reader/parse {} {:views/main (Reference. :view [::main])}))))
|
||||
|
||||
(deftest parse-let-blocks
|
||||
(is (= {:data {:views/main [blocks/let-block {:env {'s "Hello"}} [:text {} 's]]}}
|
||||
(reader/parse {:components {'text :text}} {:views/main (list 'let ['s "Hello"] ['text {} 's])})))
|
||||
#_
|
||||
(deftest parse-blocks
|
||||
(is (= nil (reader/parse {} {:views/main (list 'let ['cond? true] ['text])})))
|
||||
(is (= nil (reader/parse {} {:views/main (list 'let ['cond? (Reference. :query [::query])] ['text])})))
|
||||
(is (= nil (reader/parse {} {:views/main (list 'let ['cond? (Reference. :query [::query])]
|
||||
(is (= nil (reader/parse {:components {'text :text}} {:views/main (list 'let ['cond? (Reference. :query [::query])] ['text])})))
|
||||
#_
|
||||
(is (= nil (reader/parse {:components {'text :text}} {:views/main (list 'let ['cond? (Reference. :query [::query])]
|
||||
(list 'when 'cond?
|
||||
['text {} "World"]))}))))
|
||||
|
@ -1,5 +1,7 @@
|
||||
(ns pluto.runner
|
||||
(:require [doo.runner :refer-macros [doo-tests]]
|
||||
[pluto.reader-test]))
|
||||
[pluto.reader-test]
|
||||
[pluto.reader.blocks-test]))
|
||||
|
||||
(doo-tests 'pluto.reader-test)
|
||||
(doo-tests 'pluto.reader-test
|
||||
'pluto.reader.blocks-test)
|
||||
|
Loading…
x
Reference in New Issue
Block a user