summaryrefslogtreecommitdiff
path: root/desk/lib/kaji.hoon
diff options
context:
space:
mode:
Diffstat (limited to 'desk/lib/kaji.hoon')
-rw-r--r--desk/lib/kaji.hoon379
1 files changed, 379 insertions, 0 deletions
diff --git a/desk/lib/kaji.hoon b/desk/lib/kaji.hoon
new file mode 100644
index 0000000..113fd84
--- /dev/null
+++ b/desk/lib/kaji.hoon
@@ -0,0 +1,379 @@
+/+ sr=sortug
+/* kaji-js %js /lib/kaji-min/js
+/* kaji-css %css /lib/kaji/css
+|%
++$ kbowl
+ $: src=@p
+ now=@da
+ mob=?
+ ==
++$ eyre-order [id=@ta req=inbound-request:eyre]
++$ req-line
+ $: pat=(pole knot) :: path
+ ext=(unit @ta) :: extension
+ par=(map @t @t) :: params
+ mob=? :: is-mobile
+ ==
++$ form-data [action=@t input=(map @t @t)]
+++ enc |= a=* ^- tape (scow:parsing:sr %uw (jam a))
+++ dec |* [a=@t m=mold] ^- (unit m)
+ =/ hash (slaw:parsing:sr %uw a)
+ ?~ hash ~
+ ((soft m) (cue u.hash))
+++ dec-i |* [i=(map @t @t) key=@t =mold] ^- (unit mold)
+ =/ val (~(get by i) key) ?~ val ~
+ =/ atm (slaw:parsing:sr %uw u.val) ?~ atm ~
+ ((soft mold) (cue u.atm))
+
+
+:: ++ dec-form |* [=form-data d=(list [key=@t =mold])]
+:: =| res=*
+:: |-
+:: ?~ d res
+:: =/ val (~(get by in) key.i.d)
+:: ?~ val ~
+:: =/ uw (scow %uw u.val)
+:: ?~ uw
+:: =/ is-t ((sane @t) (crip u.val))
+:: ?. is-t ~| "%kaji.- passed value {u.val} of wrong format" ~
+:: it's a @t
+:: ${res [res (crip u.val), d t.d]
+:: =/ dec-res ((soft mold.i.d) (cue u.uw))
+:: ?~ dec-res ~| "Failed to decode {(trip key.i.d)}" ~
+:: =/ nr [res u.dec-res]
+:: $(res nr, d t.d)
+
+:: =df |* wer=(list [key=@t =mold])
+:: |= in=(map @t @t)
+:: ?~ wer ~
+:: :_ ((df t.wer) in)
+:: =/ val (~(get by in) key.i.wer)
+:: ?~ val ~| "key {(trip key.i.wer)} not found in map" ~
+:: =/ uw (slaw %uw u.val) ?~ uw
+:: ~& uw=uw
+:: =/ is-t ((sane %t) u.val)
+:: ~& is-t=is-t
+:: ?. is-t ~| "%kaji.- passed value {u.val} of wrong format" ~
+:: u.val
+:: =/ dec-res ((soft mold.i.wer) (cue u.uw))
+:: ?~ dec-res ~| "Failed to decode {(trip key.i.wer)}" ~
+:: u.dec-res
+
+:: =df |* [in=(map @t @t) d=(list [key=@t =mold])]
+:: =| res=(unit)
+:: |-
+:: ~& res=res
+:: ?~ d res
+:: ~& key=key.i.d
+:: =/ val (~(get by in) key.i.d)
+:: ~& val=val
+:: ?~ val ~
+:: =/ uw (slaw %uw u.val) ?~ uw
+:: ~& uw=uw
+:: =/ is-t ((sane %t) u.val)
+:: ~& is-t=is-t
+:: ?. is-t ~| "%kaji.- passed value {u.val} of wrong format" ~
+:: =/ nr ?~ res (some u.val) (some [(need res) u.val])
+:: $(res nr, d t.d)
+:: =/ dec-res ((soft mold.i.d) (cue u.uw))
+:: ~& dec-res=dec-res
+:: ?~ dec-res ~| "Failed to decode {(trip key.i.d)}" ~
+:: =/ nr ?~ res (some u.dec-res) (some [(need res) u.dec-res])
+:: $(res nr, d t.d)
+
+:: =m (malt `(list [@t @t])`~[['a' 'alpha'] ['b' (scot %uw (jam [our now]))]])
+:: =d `(list [@t mold])`~[['a' @] ['b' ,[@p @da]]]
+
+
+
+
++$ kaji-res
+$% [%res eyre-res]
+ [%sse sse-res]
+==
++$ sse-res
+ $: wire=kaji-wire
+ e=(list effect)
+ ==
++$ kaji-wire
+ $% [%tab ~]
+ [%custom p=(list wire)]
+ [%all ~]
+ ==
++$ eyre-res
+ $% [%full p=simple-payload:http]
+ [%page p=manx]
+ [%html p=manx] :: fragment
+ [%mime type=path p=@t]
+ [%glob p=mime]
+ ==
++$ where
+ $% [%top ~]
+ [%bottom ~]
+ [%before sibling=@t]
+ ==
++$ effect
+$% [%redi url=@t] :: redirects; will replace the whole html of the site and update the tab history
+ [%swap =manx sel=@t inner=?] :: swaps a selector
+ [%add =manx container=@t =where] :: adds marl to a div
+ [%focus sel=@t] :: focuses on some selector
+ [%scroll sel=@t] :: scrolls to some selector
+ [%url url=@t] :: updates the url bar
+ [%modal =manx] :: opens a modal
+ [%alert =manx dur=@ud] :: opens an alert for given duration in ms
+ [%refresh ~]
+ [%custom =manx data=json] :: custom, you can set a handle for the 'kaji-fact' event in JS
+==
++$ sse-card [%give %fact (list path) [%kaji vase]]
+
+++ ui-fact
+|= [tab=@t res=(list effect)] ^- sse-card
+=/ wire /sse/[tab]
+[%give %fact ~[wire] [%kaji !>(res)]]
+
+++ live-fact
+|= res=(list effect) ^- sse-card
+[%give %fact ~[/ui] [%kaji !>(res)]]
+
+++ give-fact
+|= [wires=(list path) res=(list effect)] ^- sse-card
+[%give %fact wires [%kaji !>(res)]]
+
+
+:: sse templates
+++ ui
+ |_ tab-id=@t
+ ++ fact
+ |= res=(list effect) (ui-fact tab-id res)
+ ++ alert
+ =/ dur 2.000
+ |= a=tape
+ =/ manx ;span:"{a}"
+ %+ ui-fact tab-id [%alert manx dur]^~
+ ++ refresh-card :: wipe browser cache
+ %+ ui-fact tab-id [%refresh ~]^~
+ --
+::
+:: response builders
+:: eyre responses
+++ error-response
+|= code=@ud ^- eyre-res
+ :- %html (error-page code)
+:: inline sse commands
+
+:: some helpers
+:: manx builders
+++ wrap-marl
+|= m=marl ^- manx
+;div
+ ;* m
+==
+++ error-page
+|= code=@ud
+ ;html
+ ;body
+ ;p:"Error {<code>}"
+ ==
+ ==
+++ fetch
+|= pat=path
+;div(kaji "fetch", src "{(trip (spat pat))}");
+
+
+++ add-error
+|= m=manx ^- manx
+=. a.g.m (snoc a.g.m [%kaji-error "true"])
+m
+++ hide-manx
+|= m=manx ^- manx
+=. a.g.m :_ a.g.m [n=%hidden v=""]
+m
+++ modal
+|= children=marl ^- manx
+;div#kaji-modal-bg
+ ;div#kaji-modal-fg
+ ;* children
+ ==
+==
+::
+
+++ parse-formdata
+ |= body=(unit octs) ^- (unit (list [key=@t val=@t]))
+ ?~ body ~
+ (rush q.u.body yquy:de-purl:html)
+
+++ get-redirect
+ |= redirect=cord
+ ^- simple-payload:http
+ [[303 ['location' redirect]~] ~]
+
+++ doctype "<!DOCTYPE html>"
+
+++ is-mobile
+ |= req=inbound-request:eyre ^- ?
+ =/ headers (malt header-list.request.req)
+ =/ ua (~(get by headers) 'user-agent')
+ =/ swidth (~(get by headers) 'x-kaji-vw')
+ ?~ ua ?~ swidth .n
+ =/ width (rush u.swidth dem) ?~ width .n
+ (lte u.width 800)
+
+ ?| (cfind:sr 'android' u.ua .n)
+ (cfind:sr 'iphone' u.ua .n)
+ :: (cfind:sr 'ipad' u.ua .n)
+ ==
+
+:: core functionality
++$ request-line-s
+ $: [ext=(unit @ta) site=(list @t)]
+ args=(list [key=@t value=@t])
+ ==
+++ parse-req
+|= req=inbound-request:eyre ^- req-line
+ =/ rl=(unit request-line-s) (rush url.request.req ;~(plug apat:de-purl:html yque:de-purl:html))
+ ?~ rl
+ ~& >>> url-parsing-failed=url.request.req
+ !!
+ =/ is-mob (is-mobile req)
+ [path=site.u.rl ext.u.rl (malt args.u.rl) is-mob]
+
+++ manx-to-cord
+ |= [is-fragment=? =manx] ^- @t
+ %- crip
+ ?. is-fragment
+ %- en-xml:html manx
+ ::
+ %+ weld doctype
+ %- en-xml:html manx
+
+++ send-eyre-res
+ |= [eyre-id=@ta =simple-payload:http]
+ ^- (list card:agent:gall)
+ =/ header-cage
+ [%http-response-header !>(response-header.simple-payload)]
+ =/ data-cage
+ [%http-response-data !>(data.simple-payload)]
+ :~ [%give %fact ~[/http-response/[eyre-id]] header-cage]
+ [%give %fact ~[/http-response/[eyre-id]] data-cage]
+ [%give %kick ~[/http-response/[eyre-id]] ~]
+ ==
+
+++ glob-payload
+ =| cache=_|
+ |= =mime ^- simple-payload:http
+ =/ content-type (rsh 3 (crip <p.mime>))
+ =/ cache-header ?: cache
+ ['cache-control' 'max-age=86400']
+ ['cache-control' 'no-cache, no-store, must-revalidate']
+ :: ~& >>> ends-in=`@t`(swp 3 (end [3 5] (swp 3 q.q.mime)))
+ :_ `q.mime
+ [200 [['content-type' content-type] cache-header ~]]
+
+++ http-payload
+ =| cache=_|
+ |= [mime-type=path t=@t] ^- simple-payload:http
+ =/ content-type (rsh 3 (crip <mime-type>))
+ =/ octs (as-octs:mimes:html t)
+ =/ cache-header ?: cache
+ ['cache-control' 'max-age=86400']
+ ['cache-control' 'no-cache, no-store, must-revalidate']
+ :_ `octs
+ [200 [['content-type' content-type] cache-header ~]]
+::
+++ js
+|%
+ ++ collapsible ^~ %- trip
+ '''
+ function createCollapsible(el){
+ console.log("creating collapsible")
+ const targetID = el.getAttribute("target");
+ const targetEl = document.getElementById(targetID);
+ targetEl.classList.toggle("hide");
+ let show = false;
+ el.addEventListener('click', () => {
+ console.log(show, "clicked on toggle")
+ console.log(targetID)
+ console.log(targetEl)
+ show = !show;
+ // el.classList.toggle("") TODO would need to toggle the button itself
+ targetEl.classList.toggle("not-hide")
+ targetEl.classList.toggle("hide")
+ })
+ }
+ document.querySelectorAll(".toggle").forEach(createCollapsible)
+ console.log(document.querySelectorAll(".toggle"))
+ '''
+--
+++ payload-bail ^- simple-payload:http
+%+ http-payload /text/plain 'Error'
+
+++ init
+|* [=bowl:gall app-state=mold kaji-req=mold]
+|%
+ +$ request
+ $% [%eyre p=eyre-order]
+ [%kaji tab=@t req=kaji-req]
+ ==
+ +$ router $-([request bowl:gall app-state] kaji-res)
+ ++ route
+ |= [=router r=request state=app-state]
+ |^ ^- (list card:agent:gall)
+ ?- -.r
+ %eyre
+ =/ =req-line (parse-req req.p.r)
+ %+ send-eyre-res id.p.r
+ ?+ [pat ext]:req-line
+ :: default case
+ =/ resp (router r bowl state)
+ ?. ?=(%res -.resp) payload-bail
+ ?- +<.resp
+ %full p.resp
+ %page (http-payload /text/html (manx-to-cord .n (inject-head p.resp)))
+ %html (http-payload /text/html (manx-to-cord .y p.resp))
+ %mime (http-payload type.resp p.resp)
+ %glob (glob-payload p.resp)
+ ==
+ [[%session ~] [~ %js]] (http-payload /text/javascript docket-session-js)
+ [[%kaji-session ~] [~ %js]] (http-payload /text/javascript session-js)
+ [[%kaji ~] [~ %js]] (http-payload /text/javascript kaji-js)
+ [[%kaji ~] [~ %css]] (http-payload /text/css kaji-css)
+
+ ==
+ %kaji
+ =/ resp (router r bowl state)
+ ?. ?=(%sse -.resp) ~ :_ ~
+ ?- -.wire.resp
+ %all (live-fact e.resp)
+ %tab (ui-fact tab.r e.resp)
+ %custom (give-fact p.wire.resp e.resp)
+ ==
+ ==
+ ++ inject-head
+ |= m=manx ^- manx
+ =/ sip (scow %p src.bowl)
+ =/ dap (trip dap.bowl)
+ =/ tags=marl :~
+ ;link/"/kaji.css"(rel "stylesheet");
+ ;script@"/kaji.js";
+ ;script@"/kaji-session.js?ship={sip}&dap={dap}";
+ ==
+ |-
+ ?~ c.m m
+ ?: .=(%head n.g.i.c.m)
+ =. c.i.c.m (weld c.i.c.m tags) m
+ $(c.m t.c.m)
+ ++ docket-session-js ^~
+ (rap 3 'window.ship = "' (rsh 3 (scot %p our.bowl)) '";' ~)
+
+ ++ session-js ^~ %- crip
+ =/ ship (scow %p our.bowl)
+ =/ app (trip dap.bowl)
+ =/ live-ui "/ui"
+ """
+ window.ship = '{ship}'
+ window.app = '{app}'
+ window.liveUI = '{live-ui}';
+ """
+ --
+--
+--