mirror of
https://github.com/yungcalibri/prism.git
synced 2024-10-05 23:08:02 +03:00
Compare commits
18 Commits
8f0bb718eb
...
f9423d0a64
Author | SHA1 | Date | |
---|---|---|---|
|
f9423d0a64 | ||
|
7337f74e5c | ||
|
fef352b073 | ||
|
10615eeaf1 | ||
|
b0f6563536 | ||
|
625f2707de | ||
|
ba7ef21a5a | ||
|
a976552b3a | ||
|
6d174ef6c6 | ||
|
c541bccb6f | ||
|
bec28eaf04 | ||
|
c659e29402 | ||
|
2eeb641c92 | ||
|
b7d177f13c | ||
|
e8965306e1 | ||
|
50db71b442 | ||
|
574d0dfd64 | ||
|
5bd3544579 |
@ -13,6 +13,12 @@ Use `direct` to create a redirect.
|
||||
dojo> :prism|direct ~.dev 'https://developers.urbit.org/'
|
||||
```
|
||||
|
||||
Use `divert` to create a redirect from a random path (drawn from the set
|
||||
of stars, eg `/apps/prism/ronfeb`).
|
||||
```
|
||||
dojo> :prism|divert 'https://newgrounds.com/'
|
||||
```
|
||||
|
||||
Use `defect` to disable an existing redirect.
|
||||
```
|
||||
dojo> :prism|defect ~.dev
|
||||
|
@ -4,6 +4,14 @@
|
||||
+$ card card:agent:gall
|
||||
+$ versioned-state
|
||||
$% state-0
|
||||
state-1
|
||||
==
|
||||
+$ state-1
|
||||
$: %1
|
||||
=paths
|
||||
=steps
|
||||
=brats
|
||||
=snoop
|
||||
==
|
||||
+$ state-0
|
||||
$: %0
|
||||
@ -13,7 +21,7 @@
|
||||
:: slate=@ta :: next randomly generated URL fragment
|
||||
==
|
||||
--
|
||||
=| state-0
|
||||
=| state-1
|
||||
=* state -
|
||||
%- agent:dbug
|
||||
%+ verb |
|
||||
@ -21,6 +29,7 @@
|
||||
=<
|
||||
|_ =bowl:gall
|
||||
+* this .
|
||||
hc ~(. ^hc bowl)
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
++ on-init
|
||||
^- (quip card _this)
|
||||
@ -37,8 +46,29 @@
|
||||
|= old-state=vase
|
||||
^- (quip card _this)
|
||||
=/ old !<(versioned-state old-state)
|
||||
?- -.old
|
||||
%0 [~ this(state old)]
|
||||
?- -.old
|
||||
%1
|
||||
[~ this(state old)]
|
||||
::
|
||||
%0
|
||||
:: we don't have order info for the old paths, so we have to start by
|
||||
:: just assigning an order arbitrarily. the UI must allow the
|
||||
:: user to reorder.
|
||||
=/ spout=(pair (list [wright @ud]) @ud)
|
||||
%^ spin ~(tap in ~(key by paths.old))
|
||||
1
|
||||
|=([=wright ord=@ud] [[wright ord] (add 2 ord)])
|
||||
:: spin produces a pair of a list and a noun, and we only want
|
||||
:: the former.
|
||||
=/ order=^steps (malt p.spout)
|
||||
=/ new=state-1
|
||||
:* %1
|
||||
paths.old
|
||||
order
|
||||
brats.old
|
||||
snoop.old
|
||||
==
|
||||
[~ this(state new)]
|
||||
==
|
||||
::
|
||||
++ on-poke
|
||||
@ -49,11 +79,10 @@
|
||||
%prism-action
|
||||
?> =(src.bowl our.bowl)
|
||||
=^ cards state
|
||||
(handle-action !<(prism-action vase))
|
||||
(handle-action:hc !<(prism-action vase))
|
||||
[cards this]
|
||||
::
|
||||
%handle-http-request
|
||||
?> =(src.bowl our.bowl)
|
||||
=/ req !<([eyre-id=@ta =inbound-request:eyre] vase)
|
||||
:: ehh. is it worth feeding this into handle-http?
|
||||
:: or is that pointless?
|
||||
@ -63,16 +92,16 @@
|
||||
=^ cards state
|
||||
^- (quip card _state)
|
||||
:: unauthenticated requests are all handled by the pub arm.
|
||||
?. authenticated.inbound-request.req
|
||||
~(pub handle-http req)
|
||||
?. =(src.bowl our.bowl)
|
||||
~(pub handle-http:hc req)
|
||||
:: authenticated requests are handled by the arm matching
|
||||
:: the request method.
|
||||
?+ method.request.inbound-request.req dump
|
||||
%'GET'
|
||||
~(get handle-http req)
|
||||
~(get handle-http:hc req)
|
||||
::
|
||||
%'POST'
|
||||
~(pot handle-http req)
|
||||
~(pot handle-http:hc req)
|
||||
==
|
||||
[cards this]
|
||||
==
|
||||
@ -94,156 +123,258 @@
|
||||
--
|
||||
|%
|
||||
::
|
||||
++ handle-http
|
||||
|_ [eyre-id=@ta =inbound-request:eyre]
|
||||
+* req (parse-request-line:server url.request.inbound-request)
|
||||
body body.request.inbound-request
|
||||
send (cury response:schooner eyre-id)
|
||||
beth (cury update-breath inbound-request)
|
||||
dump [(send [404 ~ [%none ~]]) state]
|
||||
derp [(send [500 ~ [%stock ~]]) state]
|
||||
:: all public requests
|
||||
++ pub
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site dump
|
||||
::
|
||||
[%apps %prism @t ~] :: /apps/prism/{path in paths.state}
|
||||
:: it has to be a valid @ta or it won't go in paths.state
|
||||
?. ((sane %ta) i.t.t.site) dump
|
||||
:: "M-path", maybe path
|
||||
=/ empath `@ta`i.t.t.site
|
||||
:: dump if it doesn't exist
|
||||
?. (~(has by paths.state) empath) dump
|
||||
:: dump if it's disabled
|
||||
?: (~(has in brats.state) empath) dump
|
||||
:: get the breath for this wright, pull relevant
|
||||
:: parameters, update snoop.state with new breath, and
|
||||
:: redirect the request.
|
||||
=/ new-snoop
|
||||
(~(jab by snoop.state) empath beth)
|
||||
:_ state(snoop new-snoop)
|
||||
(send [302 ~ [%redirect (~(got by paths.state) empath)]])
|
||||
==
|
||||
:: authenticated GET
|
||||
++ get
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site pub
|
||||
::
|
||||
[%apps %prism ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(home view state)]])
|
||||
::
|
||||
[%apps %prism %shortlinks ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(shortlinks view state)]])
|
||||
==
|
||||
:: authenticated POST
|
||||
++ pot
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site dump
|
||||
++ hc
|
||||
|_ =bowl:gall
|
||||
::
|
||||
++ handle-http
|
||||
|_ [eyre-id=@ta =inbound-request:eyre]
|
||||
+* req (parse-request-line:server url.request.inbound-request)
|
||||
body body.request.inbound-request
|
||||
send (cury response:schooner eyre-id)
|
||||
beth (cury update-breath inbound-request)
|
||||
dump [(send [404 ~ [%none ~]]) state]
|
||||
derp [(send [500 ~ [%stock ~]]) state]
|
||||
:: all public requests
|
||||
++ pub
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site dump
|
||||
::
|
||||
[%apps %prism %direct ~]
|
||||
?~ body.request.inbound-request derp
|
||||
=/ jon=(unit json)
|
||||
(de:json:html q.u.body.request.inbound-request)
|
||||
?~ jon derp
|
||||
=/ act=prism-action (dejs-direct +.jon)
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action act)
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [200 ~ [%manx ~(shortlinks view +.u.scat)]])
|
||||
[%apps %prism @t ~] :: /apps/prism/{path in paths.state}
|
||||
:: it has to be a valid @ta or it won't go in paths.state
|
||||
?. ((sane %ta) i.t.t.site) dump
|
||||
:: "M-path", maybe path
|
||||
=/ empath `@ta`i.t.t.site
|
||||
:: dump if it doesn't exist
|
||||
?. (~(has by paths.state) empath) dump
|
||||
:: dump if it's disabled
|
||||
?: (~(has in brats.state) empath) dump
|
||||
:: get the breath for this wright, pull relevant
|
||||
:: parameters, update snoop.state with new breath, and
|
||||
:: redirect the request.
|
||||
=/ new-snoop
|
||||
(~(jab by snoop.state) empath beth)
|
||||
:_ state(snoop new-snoop)
|
||||
(send [302 ~ [%redirect (~(got by paths.state) empath)]])
|
||||
==
|
||||
:: authenticated GET
|
||||
++ get
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site pub
|
||||
::
|
||||
[%apps %prism @t %defect ~]
|
||||
:: attempt to handle the %defect action
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%defect i.t.t.site])
|
||||
:: if applying the defect action failed, send 500
|
||||
?~ scat derp
|
||||
:: otherwise add our response card to the list of effects.
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [200 ~ [%manx ~(shortlinks view +.u.scat)]])
|
||||
[%apps %prism ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(shortlinks view state)]])
|
||||
::
|
||||
[%apps %prism %shortlinks ~]
|
||||
:_ state
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
::
|
||||
[%apps %prism %direct ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(direct view state)]])
|
||||
::
|
||||
[%apps %prism %divert ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(divert view state)]])
|
||||
::
|
||||
[%apps %prism %about ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(about view state)]])
|
||||
::
|
||||
[%apps %prism %updates ~]
|
||||
:_ state
|
||||
(send [200 ~ [%manx ~(updates view state)]])
|
||||
==
|
||||
:: authenticated POST
|
||||
++ pot
|
||||
^- (quip card _state)
|
||||
=/ site site.req
|
||||
?+ site dump
|
||||
::
|
||||
[%apps %prism %direct ~]
|
||||
?~ body.request.inbound-request derp
|
||||
=/ jon=(unit json)
|
||||
(de:json:html q.u.body.request.inbound-request)
|
||||
?~ jon derp
|
||||
=/ act=prism-action (dejs-direct +.jon)
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action act)
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
::
|
||||
[%apps %prism %validate %unique ~]
|
||||
:: check whether the shortlink is unique
|
||||
?~ body.request.inbound-request derp
|
||||
=/ jon=(unit json)
|
||||
(de:json:html q.u.body.request.inbound-request)
|
||||
?~ jon derp
|
||||
:: same inputs as the direct action, just use dejs-direct
|
||||
=/ act=prism-action (dejs-direct +.jon)
|
||||
:: satisfy the type checker by insisting that this is a %direct
|
||||
?. ?=([%direct *] act) derp
|
||||
:_ state
|
||||
?. (~(has by paths) wright.act)
|
||||
(send [200 ~ [%none ~]])
|
||||
(send [200 ~ [%plain "{(trip wright.act)} is already bound!"]])
|
||||
::
|
||||
[%apps %prism %divert ~]
|
||||
?~ body.request.inbound-request derp
|
||||
=/ jon=(unit json)
|
||||
(de:json:html q.u.body.request.inbound-request)
|
||||
?~ jon derp
|
||||
=/ act=prism-action (dejs-divert +.jon)
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action act)
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
::
|
||||
[%apps %prism @t %defect ~]
|
||||
:: attempt to handle the %defect action
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%defect i.t.t.site])
|
||||
:: if applying the defect action failed, send 500
|
||||
?~ scat derp
|
||||
:: otherwise add our response card to the list of effects.
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
::
|
||||
[%apps %prism @t %renege ~]
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%renege i.t.t.site])
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
::
|
||||
[%apps %prism @t %delete ~]
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%delete i.t.t.site])
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [303 ~ [%redirect '/apps/prism']])
|
||||
==
|
||||
--
|
||||
::
|
||||
++ handle-action
|
||||
|= act=prism-action
|
||||
^- (quip card _state)
|
||||
:: the last number we added to $steps is the highest number. we
|
||||
:: don't always minimize the keys in steps (when deleting, for
|
||||
:: instance), so it makes sense to derive this on demand rather
|
||||
:: than keeping it in state.
|
||||
=/ max-step=@ud
|
||||
(~(rep by steps) |=([[* ord=@ud] acc=@ud] (max ord acc)))
|
||||
:: the next step is the next odd integer.
|
||||
=/ next-step=@ud (add 2 max-step)
|
||||
?- -.act
|
||||
%direct
|
||||
:: ensure we got a valid @ta in the action (this will
|
||||
:: be a url segment, so we have to be strict)
|
||||
?. ((sane %ta) wright.act)
|
||||
~|("Invalid path segment {<wright.act>}" !!)
|
||||
:: ensure we don't already have a redirect at this path
|
||||
?: (~(has by paths) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} already assigned" !!)
|
||||
:: ensure toward is a properly formed URL
|
||||
?~ (de-purl:html toward.act)
|
||||
~|('URL is invalid' !!)
|
||||
:- ~
|
||||
:: add the path, initialize its entry in our snoop.state
|
||||
%= state
|
||||
paths (~(put by paths) wright.act toward.act)
|
||||
steps (~(put by steps) wright.act next-step)
|
||||
snoop (~(put by snoop) wright.act *breath)
|
||||
==
|
||||
::
|
||||
[%apps %prism @t %renege ~]
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%renege i.t.t.site])
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [200 ~ [%manx ~(shortlinks view +.u.scat)]])
|
||||
%divert
|
||||
:: generate a random path segment for this redirect
|
||||
?~ (de-purl:html toward.act)
|
||||
~|('URL is invalid' !!)
|
||||
:: random number generation starts from 0, so we need to
|
||||
:: find the largest two-segment @p, i.e. `@p`(pow 2 16),
|
||||
:: and then subtract the smallest two-segment patp,
|
||||
:: which is (pow 2 8, then add one less again.
|
||||
:: this gives us a random four-segment patp.
|
||||
=/ scope=@ud (sub (pow 2 16) (pow 2 8))
|
||||
=/ shift=@ud (sub (pow 2 8) 1)
|
||||
:: generate a segment we don't already have
|
||||
=/ segment=@ta
|
||||
:: start with some random patp
|
||||
=/ pat=@p `@p`(add (~(rad og eny.bowl) scope) shift)
|
||||
|-
|
||||
:: strip the sig from the front of our random patp
|
||||
=/ strip=@ta
|
||||
^- @ta
|
||||
%- crip
|
||||
:: interpolate pat into a string, and take its tail,
|
||||
:: which doesn't include the sig
|
||||
=< +.. "{<pat>}"
|
||||
:: if we already have a path like this, add 1 until we find a
|
||||
:: unique path. there are 64.000 stars, so we will never
|
||||
:: do this, but still, better safe than sorry!
|
||||
?: (~(has by paths) strip)
|
||||
%= $
|
||||
pat `@p`(add pat 1)
|
||||
==
|
||||
strip
|
||||
::
|
||||
~& "/apps/prism/{(trip `@t`segment)} -> {(trip toward.act)}"
|
||||
:- ~
|
||||
%= state
|
||||
paths (~(put by paths) segment toward.act)
|
||||
steps (~(put by steps) segment next-step)
|
||||
snoop (~(put by snoop) segment *breath)
|
||||
==
|
||||
::
|
||||
[%apps %prism @t %delete ~]
|
||||
=/ scat=(unit (quip card _state))
|
||||
%- mole
|
||||
|. (handle-action `prism-action`[%delete i.t.t.site])
|
||||
?~ scat derp
|
||||
:_ +.u.scat
|
||||
%+ weld
|
||||
-.u.scat
|
||||
(send [200 ~ [%manx ~(shortlinks view +.u.scat)]])
|
||||
%defect
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?: (~(has in brats) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} is already disabled" !!)
|
||||
[~ state(brats (~(put in brats) wright.act))]
|
||||
::
|
||||
%renege
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?. (~(has in brats) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} is already enabled" !!)
|
||||
[~ state(brats (~(del in brats) wright.act))]
|
||||
::
|
||||
%delete
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?> (~(has by snoop) wright.act)
|
||||
:: remove the deleted entry from brats, if it was there.
|
||||
=/ clean-brats
|
||||
?: (~(has in brats) wright.act)
|
||||
(~(del in brats) wright.act)
|
||||
brats
|
||||
:- ~
|
||||
%= state
|
||||
paths (~(del by paths) wright.act)
|
||||
steps (~(del by steps) wright.act)
|
||||
snoop (~(del by snoop) wright.act)
|
||||
brats clean-brats
|
||||
==
|
||||
==
|
||||
--
|
||||
::
|
||||
++ handle-action
|
||||
|= act=prism-action
|
||||
^- (quip card _state)
|
||||
?- -.act
|
||||
%direct
|
||||
:: ensure we got a valid @ta in the action (this will
|
||||
:: be a url segment, so we have to be strict)
|
||||
?. ((sane %ta) wright.act)
|
||||
~|("Invalid path segment {<wright.act>}" !!)
|
||||
:: ensure we don't already have a redirect at this path
|
||||
?: (~(has by paths) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} already assigned" !!)
|
||||
:: ensure toward is a properly formed URL
|
||||
?~ (de-purl:html toward.act)
|
||||
~|('URL is invalid' !!)
|
||||
:- ~
|
||||
:: add the path, initialize its entry in our snoop.state
|
||||
%= state
|
||||
paths (~(put by paths) wright.act toward.act)
|
||||
snoop (~(put by snoop) wright.act *breath)
|
||||
==
|
||||
::
|
||||
%defect
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?: (~(has in brats) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} is already disabled" !!)
|
||||
[~ state(brats (~(put in brats) wright.act))]
|
||||
::
|
||||
%renege
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?. (~(has in brats) wright.act)
|
||||
~|("Path /apps/prism/{<wright.act>} is already enabled" !!)
|
||||
[~ state(brats (~(del in brats) wright.act))]
|
||||
::
|
||||
%delete
|
||||
?. (~(has by paths) wright.act)
|
||||
~|("There is no forward from /apps/prism/{<wright.act>}" !!)
|
||||
?> (~(has by snoop) wright.act)
|
||||
=/ clean-brats
|
||||
?: (~(has in brats) wright.act)
|
||||
(~(del in brats) wright.act)
|
||||
brats
|
||||
:- ~
|
||||
%= state
|
||||
paths (~(del by paths) wright.act)
|
||||
snoop (~(del by snoop) wright.act)
|
||||
brats clean-brats
|
||||
==
|
||||
==
|
||||
--
|
||||
|
@ -2,7 +2,7 @@
|
||||
[%info 'A URL shortener for your urbit']
|
||||
[%color 0xff.ffff]
|
||||
[%image 'https://f004.backblazeb2.com/file/demiurge/normul-postem/counter.gif']
|
||||
[%version [0 6 2]]
|
||||
[%version [0 7 0]]
|
||||
[%website 'https://github.com/yungcalibri/prism']
|
||||
[%license 'MIT']
|
||||
[%site /apps/prism]
|
||||
|
8
desk/gen/prism/divert.hoon
Normal file
8
desk/gen/prism/divert.hoon
Normal file
@ -0,0 +1,8 @@
|
||||
:: to add a new redirect with a random path
|
||||
:: :prism|divert 'https://vienna.earth/'
|
||||
:- %say
|
||||
|= $: ^
|
||||
[toward=@t ~]
|
||||
~
|
||||
==
|
||||
[%prism-action [%divert toward]]
|
@ -1,5 +1,16 @@
|
||||
/- *prism
|
||||
|_ [%0 =paths =brats =snoop]
|
||||
/* docket %docket-0 /desk/docket-0
|
||||
|_ [%1 =paths =steps =brats =snoop]
|
||||
::
|
||||
++ version
|
||||
^- tape
|
||||
=/ vex version.docket
|
||||
"v{<major.vex>}.{<minor.vex>}.{<patch.vex>}"
|
||||
::
|
||||
++ version-json
|
||||
^- tape
|
||||
=/ vex version.docket
|
||||
"{<major.vex>}.{<minor.vex>}.{<patch.vex>}"
|
||||
::
|
||||
++ page
|
||||
|= kid=marl
|
||||
@ -46,30 +57,31 @@
|
||||
=integrity "sha384-39Mph3QgxUJ4Ou1dsJkb8LY0baiOtTwuW7LYX/pqchlr1glQOp1X8LL1LAkTlv5N"
|
||||
=src "https://unpkg.com/@yungcalibri/layout@0.1.5/dist/bundle.js";
|
||||
;script
|
||||
=async ""
|
||||
=crossorigin "anonymous"
|
||||
=integrity "sha384-aOxz9UdWG0yBiyrTwPeMibmaoq07/d3a96GCbb9x60f3mOt5zwkjdbcHFnKH8qls"
|
||||
=src "https://unpkg.com/htmx.org@1.9.0";
|
||||
;script
|
||||
=async ""
|
||||
=crossorigin "anonymous"
|
||||
=integrity "sha384-nRnAvEUI7N/XvvowiMiq7oEI04gOXMCqD3Bidvedw+YNbj7zTQACPlRI3Jt3vYM4"
|
||||
=src "https://unpkg.com/htmx.org@1.9.0/dist/ext/json-enc.js";
|
||||
;script
|
||||
=async ""
|
||||
=crossorigin "anonymous"
|
||||
=integrity "sha384-8IQLVSa8SPeOEPFM9W1QHw0NcfoMataSHwhy8Nn9YBopVPLyDPnmR3+LnmZe0c+Q"
|
||||
=src "https://unpkg.com/htmx.org@1.9.0/dist/ext/include-vals.js";
|
||||
;script
|
||||
=crossorigin "anonymous"
|
||||
=integrity "sha384-rxmVjgE5bq1dIwkIxiYTYvnbO8P5U3eqfC/7oVtfj6sKu8M0P6Tozd2uZcmGNgNj"
|
||||
=src "https://unpkg.com/compare-versions@6.1.0/lib/umd/index.js";
|
||||
;script
|
||||
=async ""
|
||||
=crossorigin "anonymous"
|
||||
=integrity "sha384-SWTvl6gg9wW7CzNqGD9/s3vxwaaKN2g8/eYyu0yT+rkQ/Rb/6NmjnbTi9lYNrpZ1"
|
||||
=src "https://unpkg.com/hyperscript.org@0.9.11";
|
||||
;script:"htmx.logAll();"
|
||||
;script(type "text/hyperscript"):"on load set localStorage['prism-version'] to '[0,6,2]'"
|
||||
;script: {page-script}
|
||||
;style: {style}
|
||||
==
|
||||
;body(hx-ext "json-enc,include-vals")
|
||||
;body(hx-boost "true", hx-ext "json-enc,include-vals")
|
||||
::
|
||||
;* kid
|
||||
::
|
||||
@ -94,15 +106,25 @@
|
||||
==
|
||||
==
|
||||
;hr;
|
||||
;nav(class "justify-content:end")
|
||||
;nav
|
||||
=class "justify-content:end"
|
||||
=data-script "on load call updateNotification() then if localStorage['prism-updated'] then add .glow to #updates"
|
||||
;stack-l(space "var(--s0)", style "align-items: stretch;")
|
||||
;a/"/apps/prism": About Prism
|
||||
;a/"/apps/prism/shortlinks": Shortlinks
|
||||
;a/"/apps/prism": Shortlinks
|
||||
;a/"/apps/prism/about": About Prism
|
||||
;a
|
||||
=id "updates"
|
||||
=href "/apps/prism/updates"
|
||||
=data-script "on click remove .glow from me then call localStorage.removeItem('prism-updated')"
|
||||
; Latest Updates
|
||||
==
|
||||
==
|
||||
==
|
||||
;hr;
|
||||
;footer(class "position:sticky bottom:0")
|
||||
;cluster-l(class "justify-content:end")
|
||||
;footer(class "position:sticky bottom:0", style "padding-bottom: 1rem;")
|
||||
;cluster-l(class "justify-content:end", space "var(--s-1)")
|
||||
;small
|
||||
;+ ;/ version:.
|
||||
==
|
||||
;a/"https://github.com/yungcalibri/prism": Prism on Github
|
||||
==
|
||||
==
|
||||
@ -129,8 +151,8 @@
|
||||
==
|
||||
:: end content
|
||||
==
|
||||
:: +home: home page (for the beta, anyway) with details about Prism
|
||||
++ home
|
||||
:: +about: details about Prism
|
||||
++ about
|
||||
^- manx
|
||||
%- page
|
||||
;* ;=
|
||||
@ -201,6 +223,39 @@
|
||||
:: end content
|
||||
==
|
||||
::
|
||||
:: +updates: latest updates
|
||||
++ updates
|
||||
^- manx
|
||||
%- page
|
||||
;* ;=
|
||||
:: begin content
|
||||
;h2: v0.7.0
|
||||
;p
|
||||
; Quality-of-life improvements!
|
||||
;ul
|
||||
;li: The shortlinks page is now the main page for the app.
|
||||
;li
|
||||
; By default, the web UI will now randomly generate
|
||||
; a shortlink URL drawn from the star namespace.
|
||||
; This behavior is available in the terminal as well;
|
||||
; see
|
||||
;code:":prism|divert"
|
||||
; under
|
||||
;a/"#usage": Usage.
|
||||
==
|
||||
;li
|
||||
; New links will now be shown in the order in which
|
||||
; they were added. (Since there was no order
|
||||
; information before, links added before v0.7.0 will
|
||||
; appear in the same order they used to.
|
||||
; Reordering from the UI will be possible in a future
|
||||
; version.)
|
||||
==
|
||||
==
|
||||
==
|
||||
:: end content
|
||||
==
|
||||
::
|
||||
++ usage
|
||||
^- manx
|
||||
;aside#usage
|
||||
@ -224,6 +279,20 @@
|
||||
==
|
||||
;div:"to create a redirect from /apps/prism/fragment to https://urbit.org."
|
||||
==
|
||||
;div
|
||||
;pre
|
||||
;code
|
||||
;span:":prism|"
|
||||
;em:"divert"
|
||||
;span:" 'https://newgrounds.com'"
|
||||
==
|
||||
==
|
||||
;div
|
||||
; to create a redirect from a random path to https://newgrounds.com.
|
||||
; The random path will be drawn from the set of stars, e.g.:
|
||||
; /apps/prism/ronfeb
|
||||
==
|
||||
==
|
||||
;div
|
||||
;pre
|
||||
;code
|
||||
@ -260,6 +329,11 @@
|
||||
:: (eventually) provides controls to manage them.
|
||||
++ shortlinks
|
||||
^- manx
|
||||
=/ sorted-paths=(list (pair wright @t))
|
||||
%+ sort
|
||||
~(tap by paths)
|
||||
|= [[a=wright *] [b=wright *]]
|
||||
(gth (~(got by steps) a) (~(got by steps) b))
|
||||
%- page
|
||||
;* ;=
|
||||
:: begin content
|
||||
@ -269,8 +343,10 @@
|
||||
;/ "No shortlinks created yet"
|
||||
==
|
||||
;stack-l(space "var(--s0)")
|
||||
;+ divert:.
|
||||
;hr;
|
||||
;* %+ turn
|
||||
~(tap by paths)
|
||||
sorted-paths
|
||||
|= [wright=@ta toward=@t]
|
||||
=/ beth=breath (~(got by snoop) wright)
|
||||
=/ hits (~(gut bi beth) '' '' 0)
|
||||
@ -292,7 +368,10 @@
|
||||
==
|
||||
;div
|
||||
; To:
|
||||
;a/"{(trip toward)}"
|
||||
;a
|
||||
=target "_blank"
|
||||
=rel "noopener noreferer"
|
||||
=href "{(trip toward)}"
|
||||
;code: {(trip toward)}
|
||||
==
|
||||
==
|
||||
@ -320,55 +399,132 @@
|
||||
==
|
||||
==
|
||||
==
|
||||
;hr;
|
||||
;section(class "shortlink new")
|
||||
;stack-l
|
||||
;h3: New shortlink
|
||||
;form#new-shortlink
|
||||
=hx-post "/apps/prism/direct"
|
||||
=hx-target "#content"
|
||||
=hx-select "#content"
|
||||
;sidebar-l(side "right", sideWidth "5em")
|
||||
;stack-l(space "var(--s-2)")
|
||||
;label
|
||||
; From:
|
||||
;br;
|
||||
;code: /apps/prism/
|
||||
;input
|
||||
=name "wright"
|
||||
=type "text"
|
||||
=pattern "[a-zA-Z-._~]+"
|
||||
=required ""
|
||||
=placeholder "vienna"
|
||||
=style "color: #f95";
|
||||
==
|
||||
;label
|
||||
; To:
|
||||
;br;
|
||||
;input
|
||||
=name "toward"
|
||||
=type "url"
|
||||
=required ""
|
||||
=placeholder "https://vienna.earth/";
|
||||
==
|
||||
==
|
||||
:: end content
|
||||
==
|
||||
::
|
||||
++ direct
|
||||
^- manx
|
||||
;section(class "shortlink new", data-prism-action "direct")
|
||||
;stack-l
|
||||
;h3: New shortlink
|
||||
;form#new-shortlink
|
||||
=hx-post "/apps/prism/direct"
|
||||
=hx-target "#content"
|
||||
=hx-select "#content"
|
||||
;sidebar-l(side "right", sideWidth "5em")
|
||||
;div
|
||||
;label(for "direct-toward")
|
||||
; To:
|
||||
==
|
||||
;stack-l(class "justify-content:end")
|
||||
;button: Create
|
||||
;br;
|
||||
;input#direct-toward
|
||||
=name "toward"
|
||||
=type "url"
|
||||
=required ""
|
||||
=placeholder "https://vienna.earth/";
|
||||
;br;
|
||||
;br;
|
||||
;label(for "direct-wright")
|
||||
; From:
|
||||
==
|
||||
;div(style "display: block-inline")
|
||||
;code(style "display: inline"): /apps/prism/
|
||||
;input#direct-wright
|
||||
=hx-post "/apps/prism/validate/unique"
|
||||
=hx-trigger "keyup changed delay:300ms"
|
||||
=hx-target "next .error"
|
||||
=hx-select "unset"
|
||||
=name "wright"
|
||||
=type "text"
|
||||
=required ""
|
||||
=placeholder "vienna"
|
||||
=style "color: #f95";
|
||||
==
|
||||
;div(style "display: flex;")
|
||||
;div(style "font-family: 'Cousine'; width: 13ch;");
|
||||
;div.error;
|
||||
==
|
||||
==
|
||||
;stack-l(class "justify-content:end")
|
||||
;button: Create
|
||||
==
|
||||
==
|
||||
==
|
||||
==
|
||||
==
|
||||
:: end content
|
||||
::
|
||||
++ divert
|
||||
^- manx
|
||||
;section(class "shortlink new", data-prism-action "divert")
|
||||
;stack-l
|
||||
;h3: New shortlink
|
||||
;form#new-shortlink
|
||||
=hx-post "/apps/prism/divert"
|
||||
=hx-target "#content"
|
||||
=hx-select "#content"
|
||||
;sidebar-l(side "right", sideWidth "5em")
|
||||
;div
|
||||
;label(for "divert-toward")
|
||||
; To:
|
||||
==
|
||||
;br;
|
||||
;input#divert-toward
|
||||
=name "toward"
|
||||
=type "url"
|
||||
=required ""
|
||||
=placeholder "https://vienna.earth/";
|
||||
;br;
|
||||
;p
|
||||
; A URL segment will be generated automatically.
|
||||
; You can also
|
||||
;a
|
||||
=href ""
|
||||
=hx-get "/apps/prism/direct"
|
||||
=hx-target "closest .shortlink.new"
|
||||
=hx-swap "outerHTML"
|
||||
=hx-select "unset"
|
||||
; configure a custom path for this redirect.
|
||||
==
|
||||
==
|
||||
==
|
||||
;stack-l(class "justify-content:end")
|
||||
;button: Create
|
||||
==
|
||||
==
|
||||
==
|
||||
==
|
||||
==
|
||||
::
|
||||
++ page-script
|
||||
"""
|
||||
function updateNotification() \{
|
||||
if (localStorage['prism-updated']) \{
|
||||
return true;
|
||||
}
|
||||
const latest = {<version-json>};
|
||||
const previous = localStorage.getItem('prism-version');
|
||||
if (
|
||||
!previous ||
|
||||
previous === "[0,6,2]" ||
|
||||
window.compareVersions.compare(latest, previous, '>')
|
||||
) \{
|
||||
localStorage.setItem('prism-version', latest);
|
||||
localStorage.setItem('prism-updated', true);
|
||||
console.log("Looks like there's a new version in town.");
|
||||
} else \{
|
||||
console.log("No new updates. Yippie-ki-yay.");
|
||||
}
|
||||
}
|
||||
"""
|
||||
::
|
||||
++ style
|
||||
^~
|
||||
%- trip
|
||||
'''
|
||||
:root {
|
||||
--measure: 80ch;
|
||||
--glow-color: dodgerblue;
|
||||
}
|
||||
body {
|
||||
font-family: 'Castoro', serif;
|
||||
@ -499,5 +655,32 @@
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.error {
|
||||
color: #a32;
|
||||
font-size: 80%;
|
||||
min-height: 1.5lh;
|
||||
padding-block: 0.25lh;
|
||||
}
|
||||
.glow {
|
||||
position: relative;
|
||||
}
|
||||
.glow::before {
|
||||
content: "◈";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: var(--glow-color);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
animation: pulse 3s infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
'''
|
||||
--
|
||||
|
@ -10,6 +10,14 @@
|
||||
%. jon
|
||||
(ot ~[wright+so toward+so])
|
||||
::
|
||||
++ dejs-divert
|
||||
|= jon=json
|
||||
=, dejs:format
|
||||
^- prism-action
|
||||
:- %divert
|
||||
%. jon
|
||||
(ot ~[toward+so])
|
||||
::
|
||||
++ utm-parameters
|
||||
^~
|
||||
^- (set @t)
|
||||
@ -114,5 +122,5 @@
|
||||
%+ gasp-referer
|
||||
req
|
||||
spyr
|
||||
:: ++ dejs-action
|
||||
::
|
||||
--
|
||||
|
@ -39,7 +39,7 @@
|
||||
:- :- http-status
|
||||
%+ weld headers
|
||||
['content-type'^'application/json']~
|
||||
`(as-octt:mimes:html (en-json:html j.resource))
|
||||
`(as-octs:mimes:html (en:json:html j.resource))
|
||||
::
|
||||
%html
|
||||
:- :- http-status
|
||||
|
@ -19,7 +19,7 @@
|
||||
++ json-to-octs
|
||||
|= jon=json
|
||||
^- octs
|
||||
(as-octt:mimes:html (en-json:html jon))
|
||||
(as-octs:mimes:html (en:json:html jon))
|
||||
::
|
||||
++ app
|
||||
|%
|
||||
|
@ -16,6 +16,10 @@
|
||||
:: redirect url.
|
||||
+$ paths (map wright @t)
|
||||
::
|
||||
:: $steps: maps path segments to the order in which they
|
||||
:: should be rendered in the UI. odd integers.
|
||||
+$ steps (map wright @ud)
|
||||
::
|
||||
:: $brats: set of all disabled wrights.
|
||||
+$ brats (set wright)
|
||||
::
|
||||
@ -27,10 +31,12 @@
|
||||
::
|
||||
+$ prism-action
|
||||
:: %direct: add a new wright
|
||||
:: %divert: add a new redirect, generating a random path for the link
|
||||
:: %defect: disable an existing wright
|
||||
:: %renege: re-enable a wright
|
||||
:: %delete: delete a wright
|
||||
$% [%direct =wright toward=@t]
|
||||
[%divert toward=@t]
|
||||
[%defect =wright]
|
||||
[%renege =wright]
|
||||
[%delete =wright]
|
||||
|
@ -1 +1 @@
|
||||
[%zuse 413]
|
||||
[%zuse 412]
|
||||
|
Loading…
Reference in New Issue
Block a user