This commit is contained in:
polwex 2024-06-01 15:45:45 +07:00
commit d3efa52d29
47 changed files with 16842 additions and 0 deletions

120
app/ustj.hoon Normal file
View File

@ -0,0 +1,120 @@
/- *forum
/+ dbug, lib=forum, const=constants
/= router /web/router
|%
++ card card:agent:gall
+$ versioned-state
$% state-0
==
--
:: main agent core
%- agent:dbug
=| versioned-state
=* state -
^- agent:gall
=<
::
|_ =bowl:gall
+* this .
hd ~(. +> [state bowl])
++ on-fail |~(* `this)
++ on-leave |~(* `this)
++ on-save !>(state)
++ on-init
^- (quip card _this)
:_ this init-cards:hd
++ on-load |= old=vase
:_ this(state !<(versioned-state old)) ~
++ on-watch
|= =(pole knot)
?+ pole !!
[%http-response id=@ ~] `this
==
++ on-poke
|= [=mark =vase]
|^
?+ mark `this
%handle-http-request serve
%noun (on-poke-noun !<(* vase))
==
++ on-poke-noun
|= a=*
?: ?=(%print a) print
?: ?=(%seed a) seed
`this
++ print
~& > state=state
`this
++ seed
=/ authors=(list @p) :~
~zod
~polwex
~lagrev-nocfep
~lagrev-nocfep
==
=/ titles=(list @t)
:~
'Helldivers 2 has caused over 20k Steam accounts to be banned'
'UI elements with a hand-drawn, sketchy look'
'60 kHz (2022)'
'Show HN: Every mountain, building and tree shadow mapped for any date and time'
'Snowflake breach: Hacker confirms access through infostealer infection'
'Heroku Postgres is now based on AWS Aurora'
'Armor from Mycenaean Greece turns out to have been effective'
'Why is no Laravel/Rails in JavaScript? Will there be one?'
'Moving Beyond Type Systems'
'Japanese \'My Number Card\' Digital IDs Coming to Apple\'s Wallet App'
'How to copy a file from a 30-year-old laptop'
'(some) good corporate engineering blogs are written'
'Debian KDE: Right Linux distribution for professional digital painting in 2024'
'Go: Sentinel errors and errors.Is() slow your code down by 3000%'
'"Moveable Type" to end 17-year run in The New York Times\'s lobby'
'London\'s Evening Standard axes daily print edition'
==
=/ rng ~(. og eny.bowl)
|- ?~ titles `this
=^ r1 rng (rads:rng 1)
~& >> rng=rng
=/ r (rad:rng 3)
=/ =content ?: .=(0 r1)
[%link 'https://urbit.org'] [%text ~]
=/ author (snag r authors)
=/ date (sub now.bowl (mul ~h1 (rad:rng 500)))
=/ ted (build-thread:lib i.titles author date content)
=/ tally (new:si [(? r1) (rad:rng 1.000)])
=. ted ted(votes [tally ~])
=. threads (put:torm threads [author date] ted)
$(titles t.titles)
::
++ serve
^- (quip card _this)
~& eyre-poke=now.bowl
=/ order !<(order:router vase)
=/ address address.req.order
:: ?: (~(has in banned.admin) address) `this
:: ~& >>> malicious-request-alert=req.order `this
:_ this
%- route:router [order state bowl]
--
++ on-peek
|= =(pole knot) ~
++ on-agent
|= [=wire =sign:agent:gall] `this
++ on-arvo
|= [=(pole knot) =sign-arvo] `this
--
:: helper
|_ [s=versioned-state =bowl:gall]
++ cache-card |= [pathc=@t pl=simple-payload:http] ^- card
=/ entry=cache-entry:eyre [.n %payload pl]
[%pass /root %arvo %e %set-response pathc `entry]
++ root-path-card ^- card
[%pass /root %arvo %e %connect [~ /forum] dap.bowl]
++ init-cards ^- (list card)
:~ root-path-card
==
++ schedule-backup-card ^- card
[%pass /backup %arvo %b %wait (add now.bowl ~h6)]
--

2
desk.bill Normal file
View File

@ -0,0 +1,2 @@
:~ %ustj
==

10
desk.docket-0 Normal file
View File

@ -0,0 +1,10 @@
:~
title+'Urbit Systems Technical Journal'
info+'Urbit Systems Technical Journal'
color+0xfc.fe55
image+'https://s3.sortug.com/urbit/polwex/2024.3.1..7.11.49..e20c.49ba.5e35.3f7c-image.png'
version+[1 0 0]
website+'https://urbit.org/journal'
license+'MIT+NIGGER'
site+/
==

1
desk.ship Normal file
View File

@ -0,0 +1 @@
~sortug

3
lib/constants.hoon Normal file
View File

@ -0,0 +1,3 @@
|%
++ hi %hi
--

155
lib/dbug.hoon Normal file
View File

@ -0,0 +1,155 @@
:: dbug: agent wrapper for generic debugging tools
::
:: usage: %-(agent:dbug your-agent)
::
|%
+$ poke
$% [%bowl ~]
[%state grab=cord]
[%incoming =about]
[%outgoing =about]
==
::
+$ about
$@ ~
$% [%ship =ship]
[%path =path]
[%wire =wire]
[%term =term]
==
::
++ agent
|= =agent:gall
^- agent:gall
!.
|_ =bowl:gall
+* this .
ag ~(. agent bowl)
::
++ on-poke
|= [=mark =vase]
^- (quip card:agent:gall agent:gall)
?. ?=(%dbug mark)
=^ cards agent (on-poke:ag mark vase)
[cards this]
=/ dbug
!<(poke vase)
=; =tang
((%*(. slog pri 1) tang) [~ this])
?- -.dbug
%bowl [(sell !>(bowl))]~
::
%state
=? grab.dbug =('' grab.dbug) '-'
=; product=^vase
[(sell product)]~
=/ state=^vase
:: if the underlying app has implemented a /dbug/state scry endpoint,
:: use that vase in place of +on-save's.
::
=/ result=(each ^vase tang)
(mule |.(q:(need (need (on-peek:ag /x/dbug/state)))))
?:(?=(%& -.result) p.result on-save:ag)
%+ slap
(slop state !>([bowl=bowl ..zuse]))
(ream grab.dbug)
::
%incoming
=; =tang
?^ tang tang
[%leaf "no matching subscriptions"]~
%+ murn
%+ sort ~(tap by sup.bowl)
|= [[* a=[=ship =path]] [* b=[=ship =path]]]
(aor [path ship]:a [path ship]:b)
|= [=duct [=ship =path]]
^- (unit tank)
=; relevant=?
?. relevant ~
`>[path=path from=ship duct=duct]<
?: ?=(~ about.dbug) &
?- -.about.dbug
%ship =(ship ship.about.dbug)
%path ?=(^ (find path.about.dbug path))
%wire %+ lien duct
|=(=wire ?=(^ (find wire.about.dbug wire)))
%term !!
==
::
%outgoing
=; =tang
?^ tang tang
[%leaf "no matching subscriptions"]~
%+ murn
%+ sort ~(tap by wex.bowl)
|= [[[a=wire *] *] [[b=wire *] *]]
(aor a b)
|= [[=wire =ship =term] [acked=? =path]]
^- (unit tank)
=; relevant=?
?. relevant ~
`>[wire=wire agnt=[ship term] path=path ackd=acked]<
?: ?=(~ about.dbug) &
?- -.about.dbug
%ship =(ship ship.about.dbug)
%path ?=(^ (find path.about.dbug path))
%wire ?=(^ (find wire.about.dbug wire))
%term =(term term.about.dbug)
==
==
::
++ on-peek
|= =path
^- (unit (unit cage))
?. ?=([@ %dbug *] path)
(on-peek:ag path)
?+ path [~ ~]
[%u %dbug ~] ``noun+!>(&)
[%x %dbug %state ~] ``noun+!>(on-save:ag)
[%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl)
==
::
++ on-init
^- (quip card:agent:gall agent:gall)
=^ cards agent on-init:ag
[cards this]
::
++ on-save on-save:ag
::
++ on-load
|= old-state=vase
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-load:ag old-state)
[cards this]
::
++ on-watch
|= =path
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-watch:ag path)
[cards this]
::
++ on-leave
|= =path
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-leave:ag path)
[cards this]
::
++ on-agent
|= [=wire =sign:agent:gall]
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-agent:ag wire sign)
[cards this]
::
++ on-arvo
|= [=wire =sign-arvo]
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-arvo:ag wire sign-arvo)
[cards this]
::
++ on-fail
|= [=term =tang]
^- (quip card:agent:gall agent:gall)
=^ cards agent (on-fail:ag term tang)
[cards this]
--
--

223
lib/docket.hoon Normal file
View File

@ -0,0 +1,223 @@
/- *docket
|%
::
++ mime
|%
+$ draft
$: title=(unit @t)
info=(unit @t)
color=(unit @ux)
glob-http=(unit [=url hash=@uvH])
glob-ames=(unit [=ship hash=@uvH])
base=(unit term)
site=(unit path)
image=(unit url)
version=(unit version)
website=(unit url)
license=(unit cord)
==
::
++ finalize
|= =draft
^- (unit docket)
?~ title.draft ~
?~ info.draft ~
?~ color.draft ~
?~ version.draft ~
?~ website.draft ~
?~ license.draft ~
=/ href=(unit href)
?^ site.draft `[%site u.site.draft]
?~ base.draft ~
?^ glob-http.draft
`[%glob u.base hash.u.glob-http %http url.u.glob-http]:draft
?~ glob-ames.draft
~
`[%glob u.base hash.u.glob-ames %ames ship.u.glob-ames]:draft
?~ href ~
=, draft
:- ~
:* %1
u.title
u.info
u.color
u.href
image
u.version
u.website
u.license
==
::
++ from-clauses
=| =draft
|= cls=(list clause)
^- (unit docket)
=* loop $
?~ cls (finalize draft)
=* clause i.cls
=. draft
?- -.clause
%title draft(title `title.clause)
%info draft(info `info.clause)
%color draft(color `color.clause)
%glob-http draft(glob-http `[url hash]:clause)
%glob-ames draft(glob-ames `[ship hash]:clause)
%base draft(base `base.clause)
%site draft(site `path.clause)
%image draft(image `url.clause)
%version draft(version `version.clause)
%website draft(website `website.clause)
%license draft(license `license.clause)
==
loop(cls t.cls)
::
++ to-clauses
|= d=docket
^- (list clause)
%- zing
:~ :~ title+title.d
info+info.d
color+color.d
version+version.d
website+website.d
license+license.d
==
?~ image.d ~ ~[image+u.image.d]
?: ?=(%site -.href.d) ~[site+path.href.d]
=/ ref=glob-reference glob-reference.href.d
:~ base+base.href.d
?- -.location.ref
%http [%glob-http url.location.ref hash.ref]
%ames [%glob-ames ship.location.ref hash.ref]
== == ==
::
++ spit-clause
|= =clause
^- tape
%+ weld " {(trip -.clause)}+"
?+ -.clause "'{(trip +.clause)}'"
%color (scow %ux color.clause)
%site (spud path.clause)
::
%glob-http
"['{(trip url.clause)}' {(scow %uv hash.clause)}]"
::
%glob-ames
"[{(scow %p ship.clause)} {(scow %uv hash.clause)}]"
::
%version
=, version.clause
"[{(scow %ud major)} {(scow %ud minor)} {(scow %ud patch)}]"
==
::
++ spit-docket
|= dock=docket
^- tape
;: welp
":~\0a"
`tape`(zing (join "\0a" (turn (to-clauses dock) spit-clause)))
"\0a=="
==
--
::
++ enjs
=, enjs:format
|%
::
++ charge-update
|= u=^charge-update
^- json
%+ frond -.u
^- json
?- -.u
%del-charge s+desk.u
::
%initial
%- pairs
%+ turn ~(tap by initial.u)
|=([=desk c=^charge] [desk (charge c)])
::
%add-charge
%- pairs
:~ desk+s+desk.u
charge+(charge charge.u)
==
==
::
++ num
|= a=@u
^- ^tape
=/ p=json (numb a)
?> ?=(%n -.p)
(trip p.p)
::
++ version
|= v=^version
^- json
:- %s
%- crip
"{(num major.v)}.{(num minor.v)}.{(num patch.v)}"
::
++ merge
|= [a=json b=json]
^- json
?> &(?=(%o -.a) ?=(%o -.b))
[%o (~(uni by p.a) p.b)]
::
++ href
|= h=^href
%+ frond -.h
?- -.h
%site s+(spat path.h)
%glob
%- pairs
:~ base+s+base.h
glob-reference+(glob-reference glob-reference.h)
==
==
::
++ glob-reference
|= ref=^glob-reference
%- pairs
:~ hash+s+(scot %uv hash.ref)
location+(glob-location location.ref)
==
::
++ glob-location
|= loc=^glob-location
^- json
%+ frond -.loc
?- -.loc
%http s+url.loc
%ames s+(scot %p ship.loc)
==
::
++ charge
|= c=^charge
%+ merge (docket docket.c)
%- pairs
:~ chad+(chad chad.c)
==
::
++ docket
|= d=^docket
^- json
%- pairs
:~ title+s+title.d
info+s+info.d
color+s+(scot %ux color.d)
href+(href href.d)
image+?~(image.d ~ s+u.image.d)
version+(version version.d)
license+s+license.d
website+s+website.d
==
::
++ chad
|= c=^chad
%+ frond -.c
?+ -.c ~
%hung s+err.c
==
--
--

98
lib/forum.hoon Normal file
View File

@ -0,0 +1,98 @@
/- sur=forum, tp=post
/+ sr=sortug, parser
|%
:: fetching
++ get-thread |= [=pid:tp =state:sur] ^- (unit thread:sur)
(get:torm:sur threads.state pid)
++ get-thread-page |= [pag=@ud =state:sur] ^- (list thread:sur)
=/ teds (tap:torm:sur threads.state)
=/ start ?: .=(pag 0) 0 (dec pag)
=/ end (add start 9)
=| i=@ud
=| res=(list thread:sur)
|- ?~ teds (flop res)
?: (gte i end) (flop res)
?: (lth i start) $(i +(i), teds t.teds)
=. res [+.i.teds res]
$(i +(i), teds t.teds)
:: ++ tally
:: |= votes=(map @p ?) ^- [tup=@ud tdo=@ud]
:: %- ~(rep by votes) |= [[s=@p v=?] [tup=@ud tdo=@ud]]
:: ?: v
:: [+(tup) tdo]
:: [tup +(tdo)]
:: ++ updown |= [tup=@ud tdo=@ud] ^- (unit [? @ud])
:: ?: .=(tup tod) ~
:: %- some
:: ?: (gte tup tod) [.y tup] [.n tod]
:: ++ rank-algo
:: |= [=thread:sur now=@da]
:: =/ tally (tally leger.votes.thread)
:: =/ score (sum:si (new:si .y -.tally) (new:si .n +.tally))
:: =/ ago (sub now +.pid.thread)
:: =/ hours (add 2 (div ago ~h1))
:: =/ bunbo (pow (sun:rs hours) .1.8)
:: =/ bunshi (san:rs (sum:si score (new:si .n 1)))
:: (div:rs bunshi bunbo)
:: from lagoon
:: ++ pow-n
:: |= [x=@rs n=@rs] ^- @rs
:: ?: =(n .0) .1
:: ?> &((gth n .0) (is-int n))
:: =/ p x
:: |- ^- @rs
:: ?: (lth n .2)
:: p
:: $(n (sub n .1), p (mul p x))
:: ++ pow
:: =, rs
:: |= [x=@rs n=@rs] ^- @rs
:: :: fall through on integers (faster)
:: ?: =(n (san (need (toi n)))) (pow-n x (san (need (toi n))))
:: (exp (mul n (log x)))
:: post builders
++ build-thread
|= [title=@t author=@p date=@da =content:sur] ^- thread:sur
=| t=thread:sur
%= t
pid [author date]
title title
content content
==
++ build-comment
|= [contents=content-list:tp =bowl:gall thread=pid:tp]
^- comment:tp
=/ p *comment:tp
%= p
id now.bowl
thread thread
author src.bowl
contents contents
==
:: ++ build-content
:: |= [text=@t poll=(unit poll:pols)] ^- content-list:tp
:: =/ contents (tokenize:ui u.text)
:: ?~ contents ~
:: contents
++ post-date-ago
|= [d=@da now=@da length=?(%tam %yau)] ^- tape
=/ diff=@dr (sub now d)
?: (lth diff ~m1) %+ weld (scow %ud (div diff ~s1))
?: ?=(%tam length) "m" " seconds"
?: (lth diff ~h1) %+ weld (scow %ud (div diff ~m1))
?: ?=(%tam length) "m" " minutes"
?: (lth diff ~d1) %+ weld (scow %ud (div diff ~h1))
?: ?=(%tam length) "h" " hours"
?: (lth diff ~d30) %+ weld (scow %ud (div diff ~d1))
?: ?=(%tam length) "d" " days"
?: (lth diff ~d365) %+ weld (scow %ud (div diff ~d30))
?: ?=(%tam length) "mo" " months"
%+ weld (scow %ud (div diff ~d365))
?: ?=(%tam length) "y" " years"
--

211
lib/parser.hoon Normal file
View File

@ -0,0 +1,211 @@
/- tp=post
/+ sr=sortug
|%
:: tape -> post:trill, parsing user input from Sail
+$ heading $?(%h1 %h2 %h3 %h4 %h5 %h6)
++ parse :: Markdown parser. Actually udon parser but it'll do
|= s=tape ^- (unit marl:hoot) :: finally
:: Annoying it requires a line break but then parses it as a space wtf
=, vast
(rust s cram:(sail .y))
++ tokenize
|= s=@t ^- content-list:tp
=/ t (weld (trip s) "\0a")
=/ parsed (parse t)
:: =/ parsed2 (parse:md t)
:: ~& > diary-parser=parsed2
:: \0a can't be followed by a space. ever. those are the rules
?~ parsed ~& error-parsing-markdown=t ~
(marl-to-cl u.parsed)
++ marl-to-cl
|= =marl:hoot ^- content-list:tp
%- flop
%+ roll marl
|= [=tuna:hoot acc=content-list:tp]
:: man this is an annoying type if I ever saw one
?@ -.tuna acc
=/ blk (manx-to-block tuna)
?~ blk acc :_ acc u.blk
++ manx-to-block
|= =manx:hoot ^- (unit block:tp)
?+ n.g.manx ~
heading %- some [%heading (phead n.g.manx c.manx)]
%p %- some [%paragraph (inline-list c.manx)]
%blockquote %- some [%blockquote (inline-list c.manx)]
%pre %- some [%codeblock (pre c.manx)]
%hr %- some [%paragraph ~[[%break ~]]]
%ul %- some [%list (list-items c.manx) .n]
%ol %- some [%list (list-items c.manx) .y]
:: %table %- some (table-rows c.manx)
==
++ list-items
|= =marl:hoot ^- (list li:clist:tp)
%- flop
%+ roll marl |= [=tuna:hoot acc=(list li:clist:tp)]
?@ -.tuna acc
?. ?=(%li n.g.tuna) acc :_ acc (marl-to-cl c.tuna)
++ phead
|= [h=heading c=marl:hoot] ^- [p=cord q=heading]
:- (get-tag-text c) h
++ inline-list
|= c=marl:hoot ^- (list inline:tp)
%- flop
%+ roll c
|= [=tuna:hoot acc=(list inline:tp)]
?@ -.tuna acc :_ acc (inline tuna)
++ inline
|= =manx:hoot ^- inline:tp
?: ?=(%$ n.g.manx) [%text (get-attrs-text a.g.manx)]
=/ text=@t (get-tag-text c.manx)
?+ n.g.manx [%text text]
%i [%italic text]
%b [%bold text]
%code [%codespan text]
%br [%break ~]
%a :+ %link (get-attrs-text a.g.manx) (get-tag-text c.manx)
%img :+ %link (get-attr-text a.g.manx %src) (get-attr-text a.g.manx %alt)
==
::
++ reduce-block
|= c=marl:hoot ^- @t
%+ roll c
|= [=tuna:hoot acc=@t]
?@ -.tuna acc
?+ n.g.tuna acc
%p (get-tag-text c.tuna)
==
++ get-attr-text
|= [a=mart:hoot attr=@tas] ^- @t
%- crip %- flop
%+ roll a
|= [[n=mane v=(list beer:hoot)] acc=tape]
?. .=(attr n) acc
%+ roll v
|= [b=beer:hoot acc=tape]
?^ b acc [b acc]
++ get-attrs-text :: this assumes we don't care about which attr, which we usually don't
|= a=mart:hoot ^- @t
:: ?: (gte (lent a) 1)
%- crip %- flop
%+ roll a
|= [[n=mane v=(list beer:hoot)] acc=tape]
%+ roll v
|= [b=beer:hoot acc=tape]
?^ b acc [b acc]
++ get-tag-text
|= c=marl:hoot ^- @t
:: there's only really one child in these things
%+ roll c
|= [=tuna:hoot acc=@t]
?@ -.tuna acc
%- crip
%- flop
%+ roll a.g.tuna
|= [[n=mane v=(list beer:hoot)] acc=tape]
%+ roll v
|= [b=beer:hoot acc=tape]
?^ b acc [b acc]
++ pre
|= c=marl:hoot ^- [cord cord]
:_ '' :: lang not supported, duh
%+ roll c
|= [=tuna:hoot acc=@t]
?@ -.tuna acc
(get-attrs-text a.g.tuna)
++ parse-tags
|= t=@t ^- (unit (set @t))
=/ lst (rush t (csplit:sr com))
?~ lst ~ (some (sy u.lst))
:: post:trill -> (markdown) tape for display on sail
++ block-to-md
|= b=block:tp ^- tape
?+ -.b ""
%paragraph
%^ foldi:sr p.b "" |= [in=@ud i=inline:tp acc=tape]
=/ il (inline-to-tape i)
?: .=(+(in) (lent p.b))
"{acc}{il}"
"{acc}{il} "
%blockquote
%+ weld "> "
%^ foldi:sr p.b "" |= [in=@ud i=inline:tp acc=tape]
=/ il (inline-to-tape i)
?: .=(+(in) (lent p.b))
"{acc}{il}"
"{acc}{il} "
%list
%^ foldi:sr p.b "" |= [in=@ud =li:tp acc=tape]
=/ li-tape (content-list-to-md li)
=/ line ?: ordered.b
"{<+(in)>}. {li-tape}"
"- {li-tape}"
?: .=(+(in) (lent p.b))
"{acc}{line}"
"{acc}{line}\0a"
%media
?+ -.media.b "![{(trip p.media.b)}]({(trip p.media.b)})"
%images %^ foldi:sr p.media.b "" |= [i=@ud [url=@t caption=@t] acc=tape]
=/ line "![{(trip caption)}]({(trip url)})"
?: .=(+(i) (lent p.media.b))
"{acc}{line}"
"{acc}{line}\0a"
==
%codeblock
"""
```
{(trip code.b)}
```
"""
%heading =/ dashes=tape ?- q.b
%h1 "# "
%h2 "## "
%h3 "### "
%h4 "#### "
%h5 "##### "
%h6 "###### "
== "{dashes}{(trip p.b)}"
%tasklist "" ::TODO
::
:: %table acc
:: %eval acc
:: %ref acc
:: %json acc
==
++ content-list-to-md
|= =content-list:tp ^- tape
%^ foldi:sr content-list "" |= [i=@ud b=block:tp acc=tape]
=/ block-tape (block-to-md b)
?: .=(+(i) (lent content-list))
"{acc}{block-tape}"
"{acc}{block-tape}\0a\0a"
++ inline-to-tape
|= i=inline:tp ^- tape
?- -.i
%text (trip p.i)
%italic "_{(trip p.i)}_"
%bold "*{(trip p.i)}*"
%strike "~~{(trip p.i)}~~"
%ship (scow %p p.i)
%codespan "`{(trip p.i)}`"
%link "[{(trip show.i)}]({(trip href.i)})"
%break "\0a"
:: TODO custom syntax
%date
=/ t (time:enjs:format p.i)
?. ?=(%n -.t) "" (trip p.t)
%note "" :: TODO
%underline (trip p.i)
%sup (trip p.i)
%sub (trip p.i)
%ruby (trip p.i)
==
++ tags-to-tape
|= t=(set @t) ^- tape
%^ foldi:sr ~(tap in t) "" |= [i=@ud c=@t acc=tape]
?: .=(+(i) ~(wyt in t))
"{acc}{(trip c)}"
"{acc}{(trip c)},"
--

174
lib/server.hoon Normal file
View File

@ -0,0 +1,174 @@
=, eyre
|%
+$ request-line
$: [ext=(unit @ta) site=(list @t)]
args=(list [key=@t value=@t])
==
:: +parse-request-line: take a cord and parse out a url
::
++ parse-request-line
|= url=@t
^- request-line
(fall (rush url ;~(plug apat:de-purl:html yque:de-purl:html)) [[~ ~] ~])
::
++ manx-to-octs
|= man=manx
^- octs
(as-octt:mimes:html (en-xml:html man))
::
++ json-to-octs
|= jon=json
^- octs
(as-octs:mimes:html (en:json:html jon))
::
++ app
|%
::
:: +require-authorization:
:: redirect to the login page when unauthenticated
:: otherwise call handler on inbound request
::
++ require-authorization
|= $: =inbound-request:eyre
handler=$-(inbound-request:eyre simple-payload:http)
==
^- simple-payload:http
::
?: authenticated.inbound-request
~! this
~! +:*handler
(handler inbound-request)
::
=- [[307 ['location' -]~] ~]
%^ cat 3
'/~/login?redirect='
url.request.inbound-request
::
:: +require-authorization-simple:
:: redirect to the login page when unauthenticated
:: otherwise pass through simple-paylod
::
++ require-authorization-simple
|= [=inbound-request:eyre =simple-payload:http]
^- simple-payload:http
::
?: authenticated.inbound-request
~! this
simple-payload
::
=- [[307 ['location' -]~] ~]
%^ cat 3
'/~/login?redirect='
url.request.inbound-request
::
++ give-simple-payload
|= [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]] ~]
==
--
++ core
|%
++ gate
=| opt=@
|= a=@ opt
:: ++ try gate(opt 5)
++ try2
=/ g gate
g(opt 5)
--
++ gen
|%
::
++ max-1-da ['cache-control' 'max-age=86400']
:: ++ max-1-wk ['cache-control' 'max-age=604800']
++ max-1-wk ['cache-control' 'no-cache, no-store, must-revalidate']
++ no-cache ['cache-control' 'no-cache, no-store, must-revalidate']
::
++ lol
=| lmao=?
|= a=* %lol
++ html-response
=| cache=?
|= =octs
^- simple-payload:http
:_ `octs
[200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]]
::
++ css-response
=| cache=?
|= =octs
^- simple-payload:http
:_ `octs
[200 [['content-type' 'text/css'] ?:(cache [max-1-wk ~] ~)]]
::
++ js-response
=| cache=?
|= =octs
^- simple-payload:http
:_ `octs
[200 [['content-type' 'text/javascript'] ?:(cache [max-1-wk ~] ~)]]
::
++ png-response
=| cache=?
|= =octs
^- simple-payload:http
:_ `octs
[200 [['content-type' 'image/png'] ?:(cache [max-1-wk ~] ~)]]
::
++ svg-response
=| cache=?
|= =octs
^- simple-payload:http
:_ `octs
[200 [['content-type' 'image/svg+xml'] ?:(cache [max-1-wk ~] ~)]]
::
++ ico-response
|= =octs
^- simple-payload:http
[[200 [['content-type' 'image/x-icon'] max-1-wk ~]] `octs]
::
++ woff2-response
=| cache=?
|= =octs
^- simple-payload:http
[[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs]
::
++ json-response
=| cache=_|
|= =json
^- simple-payload:http
:_ `(json-to-octs json)
[200 [['content-type' 'application/json'] ?:(cache [max-1-da ~] ~)]]
::
++ manx-response
=| cache=_|
|= man=manx
^- simple-payload:http
:_ `(manx-to-octs man)
[200 [['content-type' 'text/html'] ?:(cache [max-1-da ~] ~)]]
::
++ not-found
^- simple-payload:http
[[404 ~] ~]
::
++ login-redirect
|= =request:http
^- simple-payload:http
=- [[307 ['location' -]~] ~]
%^ cat 3
'/~/login?redirect='
url.request
::
++ redirect
|= redirect=cord
^- simple-payload:http
[[307 ['location' redirect]~] ~]
--
--

227
lib/sigil/sigil.hoon Normal file
View File

@ -0,0 +1,227 @@
:: sigil: @p svg generation
::
:: usage: do a named import, then invoke as a function:
:: (sigil ~zod)
::
:: optionally modify configuration parameters:
:: %. ~paldev
:: %_ sigil
:: size 25
:: fg "black"
:: bg "#2aa779"
:: margin |
:: icon &
:: ==
::
::NOTE svg construction logic is coupled to the symbols definitions.
:: the symbols' elements assume they live in a space of 128x128.
:: what we do here is assume an svg _canvas_ of 128x128, draw the
:: symbols at their original sizes, and then scale them down to fit.
::
/+ sigil-symbols
::
:: config
::
=/ fg=tape "white"
=/ bg=tape "black"
=/ size=@ud 128
=/ margin=? &
=/ icon=? |
::
::
~% %sigil ..part ~
=/ who=ship ~zod
=/ syc=@ud 1
|^ |= =ship
^- manx
::
=. who ship
=/ syz (simp who)
=. syc (lent syz)
:: shift the sigil to account for the margin
:: scale the sigil to account for the amount of symbols
::
=/ sire=@rd (sun:rd size)
=/ tr=tape
::TODO render transform inside +sigil:svg?
%+ transform:svg
?. margin ~
=+ grid:pos
`[(gird:pos x) (gird:pos y)]
`span:pos
::
=/ sw=@rd ::TODO
?: icon .~0.8 ::TODO scale with size?
(add:rd .~0.33 (div:rd sire .~128))
::
%- outer:svg
%+ sigil:svg
[tr sw]
(symbols:svg syz)
::
++ pos
|%
++ span :: symbol scale (relative to full canvas)
^- @rd
::TODO accounting for margin here feels a bit ugly?
?+ (max grid) !!
%1 ?:(margin .~0.4 .~1)
%2 ?:(margin .~0.4 .~0.5)
%4 ?:(margin .~0.2 .~0.25)
==
::
++ grid :: size in symbols
^- [x=@ud y=@ud]
?+ syc !!
%16 [4 4]
%8 [4 4]
%4 [2 2]
%2 [2 1]
%1 [1 1]
==
::
++ gird :: calculate margin
|= n=@ud
^- @rd
=- (div:rd - .~2) :: / both sides
%+ sub:rd .~128 :: canvas size -
%+ mul:rd (sun:rd n) :: symbols *
%+ mul:rd span:pos :: symbol scale *
.~128 :: symbol size
::
++ plan :: as position on symbol grid
|= i=@ud
^- [x=@ud y=@ud]
?+ [syc i] !!
[%16 *] [(mod i 4) (div i 4)]
::
[%8 %0] [0 0]
[%8 %1] [3 0]
[%8 %2] [0 3]
[%8 %3] [3 3]
[%8 %4] [1 1]
[%8 %5] [2 1]
[%8 %6] [1 2]
[%8 %7] [2 2]
::
[%4 *] [(mod i 2) (div i 2)]
[%2 *] [i 0]
[%1 *] [0 0]
==
--
::
++ svg
|%
++ outer
|= inner=manx
^- manx
=/ s=tape ((d-co:co 1) size)
;svg
=style "display: block; width: {s}px; height: {s}px;" :: prevent bottom margin on svg tag
=width s
=height s
=viewBox "0 0 128 128"
=version "1.1"
=xmlns "http://www.w3.org/2000/svg"
::TODO additional attributes from config arg?
;rect
=fill bg
=width "128"
=height "128";
;+ inner
==
::
::TODO should it be possible to get these svg elements out of this lib?
++ sigil
|= [[tr=tape sw=@rd] symbols=(list manx)]
^- manx
;g
=transform tr
=stroke-width (say-rd sw)
=stroke-linecap "square"
=fill fg
=stroke bg
::NOTE unfortunately, vector-effect cannot be inherited,
:: so it gets inlined in the symbol elements instead
:: =vector-effect "non-scaling-stroke"
;* symbols
==
::
++ symbols
|= noms=(list @t)
^- (list manx)
=| i=@ud
=/ l=@ud (lent noms)
|-
?~ noms ~
:_ $(noms t.noms, i +(i))
::TODO exclude if both 0
=+ (plan:pos i)
;g(transform (transform `[(sun:rd (mul x 128)) (sun:rd (mul y 128))] ~))
;* =+ ((symbol i.noms) fg bg)
?.(icon - (scag 1 -))
==
::
++ symbol ~(got by sigil-symbols)
::
++ transform ::TODO take manx instead so we can omit attr entirely?
|= [translate=(unit [x=@rd y=@rd]) scale=(unit @rd)]
^- tape
%- zing
^- (list tape)
::TODO make cleaner
=- ?: ?=(?(~ [* ~]) -) -
(join " " `(list tape)`-)
^- (list tape)
:~ ?~ translate ~
?: =([0 0] u.translate) ~
"translate({(say-rd x.u.translate)} {(say-rd y.u.translate)})"
::
?~ scale ~
"scale({(say-rd u.scale)})"
==
--
::
++ simp
|= =ship
^- (list @t)
:: split into phonemes
::
=/ noms=(list @t)
=/ nom=@t
(rsh 3 (scot %p ship))
|- ?~ nom ~
|- ?: =('-' (end 3 nom))
$(nom (rsh 3 nom))
:- (end 3^3 nom)
^$(nom (rsh 3^3 nom))
:: fill leading empties with 'zod'
::
=/ left=@ud
=- (sub - (lent noms))
%- bex
?- (clan:title ship)
%czar 0
%king 1
%duke 2
%earl 3
%pawn 4
==
|-
?: =(0 left) noms
$(noms ['zod' noms], left (dec left))
::
++ rd ~(. ^rd %n)
++ say-rd
|= n=@rd
^- tape
=/ =dn (drg:rd n)
?> ?=(%d -.dn)
=/ [s=? m=@ud] (old:si e.dn)
=/ x=@ud (pow 10 m)
%+ weld
%- (d-co:co 1)
?:(s (mul a.dn x) (div a.dn x))
?: s ~
['.' ((d-co:co m) (mod a.dn x))]
--

14332
lib/sigil/symbols.hoon Normal file

File diff suppressed because it is too large Load Diff

33
lib/sortug.hoon Normal file
View File

@ -0,0 +1,33 @@
:: Painstakingly built utility functions by Sortug Development Ltd.
:: There's more where it came from
:: Parsing
|%
++ b64 (bass 64 (plus siw:ab))
++ b16 (bass 16 (plus six:ab))
++ scow
|= [mod=@tas a=@] ^- tape
?+ mod ""
%ud (a-co:co a)
%ux ((x-co:co 0) a)
%uv ((v-co:co 0) a)
%uw ((w-co:co 0) a)
==
++ slaw
|= [mod=@tas txt=@t] ^- (unit @)
?+ mod ~
%ud (rush txt dem)
%ux (rush txt b16)
%uv (rush txt vum:ag)
%uw (rush txt b64)
==
++ csplit |* =rule
(more rule (cook crip (star ;~(less rule next))))
:: List utils
++ foldi
|* [a=(list) b=* c=_|=(^ +<+)]
=| i=@ud
|- ^+ b
?~ a b
=/ nb (c i i.a b)
$(a t.a, b nb, i +(i))
--

34
mar/bill.hoon Normal file
View File

@ -0,0 +1,34 @@
|_ bil=(list dude:gall)
++ grow
|%
++ mime `^mime`[/text/x-bill (as-octs:mimes:html hoon)]
++ noun bil
++ hoon
^- @t
|^ (crip (of-wall:format (wrap-lines (spit-duz bil))))
::
++ wrap-lines
|= taz=wall
^- wall
?~ taz ["~"]~
:- (weld ":~ " i.taz)
%- snoc :_ "=="
(turn t.taz |=(t=tape (weld " " t)))
::
++ spit-duz
|= duz=(list dude:gall)
^- wall
(turn duz |=(=dude:gall ['%' (trip dude)]))
--
++ txt (to-wain:format hoon)
--
++ grab
|%
++ noun (list dude:gall)
++ mime
|= [=mite len=@ud tex=@]
~_ tex
!<((list dude:gall) (slap !>(~) (ream tex)))
--
++ grad %noun
--

25
mar/css.hoon Normal file
View File

@ -0,0 +1,25 @@
::
:::: /hoon/css/mar
::
/? 310
=, eyre
=, mimes:html
|_ mud=@t
++ grow :: convert to
|%
++ mime [/text/css (as-octs mud)] :: convert to %mime
++ hymn :: convert to %hymn
|^ html
++ style ;style
;- (trip mud)
==
++ html ;html:(head:"{style}" body)
--
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (@t q.q))
++ noun @t :: clam from %noun
--
++ grad %mime
--

25
mar/docket-0.hoon Normal file
View File

@ -0,0 +1,25 @@
/+ dock=docket
|_ =docket:dock
++ grow
|%
++ mime
^- ^mime
[/text/x-docket (as-octt:mimes:html (spit-docket:mime:dock docket))]
++ noun docket
++ json (docket:enjs:dock docket)
--
++ grab
|%
::
++ mime
|= [=mite len=@ud tex=@]
^- docket:dock
%- need
%- from-clauses:mime:dock
!<((list clause:dock) (slap !>(~) (ream tex)))
::
++ noun docket:dock
--
++ grad %noun
--

36
mar/hoon.hoon Normal file
View File

@ -0,0 +1,36 @@
:::: /hoon/hoon/mar
::
/? 310
::
=, eyre
|_ own=@t
::
++ grow :: convert to
|%
++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime
++ hymn
;html
;head
;title:"Source"
;script@"//cdnjs.cloudflare.com/ajax/libs/codemirror/4.3.0/codemirror.js";
;script@"/lib/syntax/hoon.js";
;link(rel "stylesheet", href "//cdnjs.cloudflare.com/ajax/libs/".
"codemirror/4.3.0/codemirror.min.css");
;link/"/lib/syntax/codemirror.css"(rel "stylesheet");
==
;body
;textarea#src:"{(trip own)}"
;script:'CodeMirror.fromTextArea(src, {lineNumbers:true, readOnly:true})'
==
==
++ txt
(to-wain:format own)
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] q.q)
++ noun @t :: clam from %noun
++ txt of-wain:format
--
++ grad %txt
--

12
mar/ico.hoon Normal file
View File

@ -0,0 +1,12 @@
|_ dat=@
++ grow
|%
++ mime [/image/x-icon (as-octs:mimes:html dat)]
--
++ grab
|%
++ mime |=([p=mite q=octs] q.q)
++ noun @
--
++ grad %mime
--

25
mar/js.hoon Normal file
View File

@ -0,0 +1,25 @@
::
:::: /hoon/js/mar
::
/? 310
::
=, eyre
|_ mud=@
++ grow
|%
++ mime [/application/javascript (as-octs:mimes:html (@t mud))]
++ hymn :: convert to %hymn
|^ html
++ script ;script
;- (trip (@t mud))
==
++ html ;html:(head:"{script}" body)
--
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (@t q.q))
++ noun cord :: clam from %noun
--
++ grad %mime
--

26
mar/json.hoon Normal file
View File

@ -0,0 +1,26 @@
::
:::: /hoon/json/mar
::
/? 310
::
:::: compute
::
=, eyre
=, format
=, html
|_ jon=^json
::
++ grow :: convert to
|%
++ mime [/application/json (as-octs:mimes -:txt)] :: convert to %mime
++ txt [(en:json jon)]~
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (fall (de:json (@t q.q)) *^json))
++ noun ^json :: clam from %noun
++ numb numb:enjs
++ time time:enjs
--
++ grad %mime
--

56
mar/kaji.hoon Normal file
View File

@ -0,0 +1,56 @@
::
:::: /hoon/kaji/mar
::
/? 310
/+ kaji
:::: A kaji html string mark
|_ efs=(list effect:kaji) :: this only affects +grow
++ grab |%
++ noun @
++ json |= jon=^json
=/ mp ((om:dejs:format so:dejs:format) jon)
=/ action ~| 'action not set by web input' (~(got by mp) 'action')
:- action (~(del by mp) 'action')
--
++ grow |%
++ noun efs
:: for scries
:: ++ mime [/application/x-urb-jam (as-octs:mimes:html (crip (en-xml:html *manx)))]
:: for facts
++ json =, enjs:format
|^ :- %a %+ turn efs |= e=effect:kaji %+ frond -.e
?- -.e
%refresh ~
%redi [%s url.e]
%focus [%s sel.e]
%scroll [%s sel.e]
%url [%s url.e]
%custom %- pairs
:~ [%manx %s (crip (en-xml:html manx.e))]
[%event data.e]
==
%modal %+ frond %manx [%s (crip (en-xml:html manx.e))]
%alert %- pairs
:~ [%manx %s (crip (en-xml:html manx.e))]
[%duration (numb dur.e)]
==
%swap %- pairs
:~ [%manx %s (crip (en-xml:html manx.e))]
[%sel %s sel.e]
[%inner %b inner.e]
==
%add %- pairs
:~ [%manx %s (crip (en-xml:html manx.e))]
[%container %s container.e]
[%where (en-where where.e)]
==
==
++ en-where |= w=where.kaji %+ frond -.w
?- -.w
%top ~
%bottom ~
%before [%s sibling.w]
==
--
--
--

28
mar/kelvin.hoon Normal file
View File

@ -0,0 +1,28 @@
|_ kal=waft:clay
++ grow
|%
++ mime `^mime`[/text/x-kelvin (as-octs:mimes:html hoon)]
++ noun kal
++ hoon
%+ rap 3
%+ turn
%+ sort
~(tap in (waft-to-wefts:clay kal))
|= [a=weft b=weft]
?: =(lal.a lal.b)
(gte num.a num.b)
(gte lal.a lal.b)
|= =weft
(rap 3 '[%' (scot %tas lal.weft) ' ' (scot %ud num.weft) ']\0a' ~)
::
++ txt (to-wain:format hoon)
--
++ grab
|%
++ noun waft:clay
++ mime
|= [=mite len=@ud tex=@]
(cord-to-waft:clay tex)
--
++ grad %noun
--

32
mar/mime.hoon Normal file
View File

@ -0,0 +1,32 @@
::
:::: /hoon/mime/mar
::
/? 310
::
|_ own=mime
++ grow
^?
|%
++ jam `@`q.q.own
--
::
++ grab :: convert from
^?
|%
++ noun mime :: clam from %noun
++ tape
|=(a=_"" [/application/x-urb-unknown (as-octt:mimes:html a)])
--
++ grad
^?
|%
++ form %mime
++ diff |=(mime +<)
++ pact |=(mime +<)
++ join |=([mime mime] `(unit mime)`~)
++ mash
|= [[ship desk mime] [ship desk mime]]
^- mime
~|(%mime-mash !!)
--
--

22
mar/noun.hoon Normal file
View File

@ -0,0 +1,22 @@
::
:::: /hoon/noun/mar
::
/? 310
!:
:::: A minimal noun mark
|_ non=*
++ grab |%
++ noun *
--
++ grow |%
++ mime [/application/x-urb-jam (as-octs:mimes:html (jam non))]
--
++ grad
|%
++ form %noun
++ diff |=(* +<)
++ pact |=(* +<)
++ join |=([* *] *(unit *))
++ mash |=([[ship desk *] [ship desk *]] `*`~|(%noun-mash !!))
--
--

12
mar/png.hoon Normal file
View File

@ -0,0 +1,12 @@
|_ dat=@
++ grow
|%
++ mime [/image/png (as-octs:mimes:html dat)]
--
++ grab
|%
++ mime |=([p=mite q=octs] q.q)
++ noun @
--
++ grad %mime
--

25
mar/sh.hoon Normal file
View File

@ -0,0 +1,25 @@
::
:::: /hoon/js/mar
::
/? 310
::
=, eyre
|_ mud=@
++ grow
|%
++ mime [/application/javascript (as-octs:mimes:html (@t mud))]
++ hymn :: convert to %hymn
|^ html
++ script ;script
;- (trip (@t mud))
==
++ html ;html:(head:"{script}" body)
--
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (@t q.q))
++ noun cord :: clam from %noun
--
++ grad %mime
--

20
mar/ship.hoon Normal file
View File

@ -0,0 +1,20 @@
|_ s=ship
++ grad %noun
++ grow
|%
++ noun s
++ json s+(scot %p s)
++ mime
^- ^mime
[/text/x-ship (as-octt:mimes:html (scow %p s))]
--
++ grab
|%
++ noun ship
++ json (su:dejs:format ;~(pfix sig fed:ag))
++ mime
|= [=mite len=@ tex=@]
(slav %p (snag 0 (to-wain:format tex)))
--
--

12
mar/svg.hoon Normal file
View File

@ -0,0 +1,12 @@
|_ dat=@
++ grow
|%
++ mime [/image/'svg+xml' (as-octs:mimes:html dat)]
--
++ grab
|%
++ mime |=([p=mite q=octs] q.q)
++ noun @
--
++ grad %mime
--

274
mar/txt.hoon Normal file
View File

@ -0,0 +1,274 @@
::
:::: /hoon/txt/mar
::
/? 310
::
=, clay
=, differ
=, format
=, mimes:html
|_ txt=wain
::
++ grab :: convert from
|%
++ mime |=((pair mite octs) (to-wain q.q))
++ noun wain :: clam from %noun
--
++ grow
=> v=.
|%
++ mime => v [/text/plain (as-octs (of-wain txt))]
--
++ grad
|%
++ form %txt-diff
++ diff
|= tyt=wain
^- (urge cord)
(lusk txt tyt (loss txt tyt))
::
++ pact
|= dif=(urge cord)
~| [%pacting dif]
^- wain
(lurk txt dif)
::
++ join
|= [ali=(urge cord) bob=(urge cord)]
^- (unit (urge cord))
|^
=. ali (clean ali)
=. bob (clean bob)
|- ^- (unit (urge cord))
?~ ali `bob
?~ bob `ali
?- -.i.ali
%&
?- -.i.bob
%&
?: =(p.i.ali p.i.bob)
%+ bind $(ali t.ali, bob t.bob)
|=(cud=(urge cord) [i.ali cud])
?: (gth p.i.ali p.i.bob)
%+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)
|=(cud=(urge cord) [i.bob cud])
%+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))
|=(cud=(urge cord) [i.ali cud])
::
%|
?: =(p.i.ali (lent p.i.bob))
%+ bind $(ali t.ali, bob t.bob)
|=(cud=(urge cord) [i.bob cud])
?: (gth p.i.ali (lent p.i.bob))
%+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)
|=(cud=(urge cord) [i.bob cud])
~
==
::
%|
?- -.i.bob
%|
?. =(i.ali i.bob)
~
%+ bind $(ali t.ali, bob t.bob)
|=(cud=(urge cord) [i.ali cud])
::
%&
?: =(p.i.bob (lent p.i.ali))
%+ bind $(ali t.ali, bob t.bob)
|=(cud=(urge cord) [i.ali cud])
?: (gth p.i.bob (lent p.i.ali))
%+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))
|=(cud=(urge cord) [i.ali cud])
~
==
==
++ clean :: clean
|= wig=(urge cord)
^- (urge cord)
?~ wig ~
?~ t.wig wig
?: ?=(%& -.i.wig)
?: ?=(%& -.i.t.wig)
$(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
[i.wig $(wig t.wig)]
?: ?=(%| -.i.t.wig)
$(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
[i.wig $(wig t.wig)]
--
::
++ mash
|= $: [als=ship ald=desk ali=(urge cord)]
[bos=ship bod=desk bob=(urge cord)]
==
^- (urge cord)
|^
=. ali (clean ali)
=. bob (clean bob)
|- ^- (urge cord)
?~ ali bob
?~ bob ali
?- -.i.ali
%&
?- -.i.bob
%&
?: =(p.i.ali p.i.bob)
[i.ali $(ali t.ali, bob t.bob)]
?: (gth p.i.ali p.i.bob)
[i.bob $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)]
[i.ali $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))]
::
%|
?: =(p.i.ali (lent p.i.bob))
[i.bob $(ali t.ali, bob t.bob)]
?: (gth p.i.ali (lent p.i.bob))
[i.bob $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)]
=/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
(resolve ali bob)
[fic $(ali ali, bob bob)]
:: ~ :: here, alice is good for a while, but not for the whole
== :: length of bob's changes
::
%|
?- -.i.bob
%|
=/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
(resolve ali bob)
[fic $(ali ali, bob bob)]
::
%&
?: =(p.i.bob (lent p.i.ali))
[i.ali $(ali t.ali, bob t.bob)]
?: (gth p.i.bob (lent p.i.ali))
[i.ali $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))]
=/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
(resolve ali bob)
[fic $(ali ali, bob bob)]
==
==
::
++ annotate :: annotate conflict
|= $: ali=(list @t)
bob=(list @t)
bas=(list @t)
==
^- (list @t)
%- zing
^- (list (list @t))
%- flop
^- (list (list @t))
:- :_ ~
%^ cat 3 '<<<<<<<<<<<<'
%^ cat 3 ' '
%^ cat 3 `@t`(scot %p bos)
%^ cat 3 '/'
bod
:- bob
:- ~['------------']
:- bas
:- ~['++++++++++++']
:- ali
:- :_ ~
%^ cat 3 '>>>>>>>>>>>>'
%^ cat 3 ' '
%^ cat 3 `@t`(scot %p als)
%^ cat 3 '/'
ald
~
::
++ clean :: clean
|= wig=(urge cord)
^- (urge cord)
?~ wig ~
?~ t.wig wig
?: ?=(%& -.i.wig)
?: ?=(%& -.i.t.wig)
$(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
[i.wig $(wig t.wig)]
?: ?=(%| -.i.t.wig)
$(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
[i.wig $(wig t.wig)]
::
++ resolve
|= [ali=(urge cord) bob=(urge cord)]
^- [fic=[%| p=(list cord) q=(list cord)] ali=(urge cord) bob=(urge cord)]
=- [[%| bac (annotate alc boc bac)] ali bob]
|- ^- $: $: bac=(list cord)
alc=(list cord)
boc=(list cord)
==
ali=(urge cord)
bob=(urge cord)
==
?~ ali [[~ ~ ~] ali bob]
?~ bob [[~ ~ ~] ali bob]
?- -.i.ali
%&
?- -.i.bob
%& [[~ ~ ~] ali bob] :: no conflict
%|
=+ lob=(lent p.i.bob)
?: =(lob p.i.ali)
[[p.i.bob p.i.bob q.i.bob] t.ali t.bob]
?: (lth lob p.i.ali)
[[p.i.bob p.i.bob q.i.bob] [[%& (sub p.i.ali lob)] t.ali] t.bob]
=+ wat=(scag (sub lob p.i.ali) p.i.bob)
=+ ^= res
%= $
ali t.ali
bob [[%| (scag (sub lob p.i.ali) p.i.bob) ~] t.bob]
==
:* :* (welp bac.res wat)
(welp alc.res wat)
(welp boc.res q.i.bob)
==
ali.res
bob.res
==
==
::
%|
?- -.i.bob
%&
=+ loa=(lent p.i.ali)
?: =(loa p.i.bob)
[[p.i.ali q.i.ali p.i.ali] t.ali t.bob]
?: (lth loa p.i.bob)
[[p.i.ali q.i.ali p.i.ali] t.ali [[%& (sub p.i.bob loa)] t.bob]]
=+ wat=(slag (sub loa p.i.bob) p.i.ali)
=+ ^= res
%= $
ali [[%| (scag (sub loa p.i.bob) p.i.ali) ~] t.ali]
bob t.bob
==
:* :* (welp bac.res wat)
(welp alc.res q.i.ali)
(welp boc.res wat)
==
ali.res
bob.res
==
::
%|
=+ loa=(lent p.i.ali)
=+ lob=(lent p.i.bob)
?: =(loa lob)
[[p.i.ali q.i.ali q.i.bob] t.ali t.bob]
=+ ^= res
?: (gth loa lob)
$(ali [[%| (scag (sub loa lob) p.i.ali) ~] t.ali], bob t.bob)
~& [%scagging loa=loa pibob=p.i.bob slag=(scag loa p.i.bob)]
$(ali t.ali, bob [[%| (scag (sub lob loa) p.i.bob) ~] t.bob])
:* :* (welp bac.res ?:((gth loa lob) p.i.bob p.i.ali))
(welp alc.res q.i.ali)
(welp boc.res q.i.bob)
==
ali.res
bob.res
==
==
==
--
--
--

12
mar/webmanifest.hoon Normal file
View File

@ -0,0 +1,12 @@
|_ dat=@
++ grow
|%
++ mime [/image/png (as-octs:mimes:html dat)]
--
++ grab
|%
++ mime |=([p=mite q=octs] q.q)
++ noun @
--
++ grad %mime
--

82
sur/docket.hoon Normal file
View File

@ -0,0 +1,82 @@
|%
::
+$ version
[major=@ud minor=@ud patch=@ud]
::
+$ glob (map path mime)
::
+$ url cord
:: $glob-location: How to retrieve a glob
::
+$ glob-reference
[hash=@uvH location=glob-location]
::
+$ glob-location
$% [%http =url]
[%ames =ship]
==
:: $href: Where a tile links to
::
+$ href
$% [%glob base=term =glob-reference]
[%site =path]
==
:: $chad: State of a docket
::
+$ chad
$~ [%install ~]
$% :: Done
[%glob =glob]
[%site ~]
:: Waiting
[%install ~]
[%suspend glob=(unit glob)]
:: Error
[%hung err=cord]
==
::
:: $charge: A realized $docket
::
+$ charge
$: =docket
=chad
==
::
:: $clause: A key and value, as part of a docket
::
:: Only used to parse $docket
::
+$ clause
$% [%title title=@t]
[%info info=@t]
[%color color=@ux]
[%glob-http url=cord hash=@uvH]
[%glob-ames =ship hash=@uvH]
[%image =url]
[%site =path]
[%base base=term]
[%version =version]
[%website website=url]
[%license license=cord]
==
::
:: $docket: A description of JS bundles for a desk
::
+$ docket
$: %1
title=@t
info=@t
color=@ux
=href
image=(unit url)
=version
website=url
license=cord
==
::
+$ charge-update
$% [%initial initial=(map desk charge)]
[%add-charge =desk =charge]
[%del-charge =desk]
==
--

37
sur/forum.hoon Normal file
View File

@ -0,0 +1,37 @@
/- tp=post
|%
+$ state
$% state-0
==
+$ state-0
$: %0
=threads
popular=pfeed
comments=gfeed:tp
karma=(map @p @ud)
::
mods=(set @p)
admins=(set @p)
==
+$ threads ((mop pid:tp thread) ggth:tp)
++ torm ((on pid:tp thread) ggth:tp)
+$ pfeed ((mop sd pid:tp) cmp)
++ porm ((on sd pid:tp) cmp)
+$ sd [s=? d=@ud]
++ cmp |= [a=sd b=sd] ?: .=(s.a s.b) (gte d.a d.b) s.a
+$ thread-page
$: page=@ud
threads=(list thread)
==
+$ thread
$: =pid:tp
title=@t
=content
replies=(list pid:tp) :: key should be the head of this list
=votes:tp
==
+$ content
$% [%link @t]
[%text content-list:tp]
==
--

81
sur/post.hoon Normal file
View File

@ -0,0 +1,81 @@
|%
+$ id @da
+$ pid [=ship =id]
:: anon post type?
:: instead of using this I'm just gonna jam old names
+$ votes
$: tally=@sd
leger=(map @p ?)
==
+$ gfeed ((mop pid comment) ggth)
++ gorm ((on pid comment) ggth)
++ ggth |=([[shipa=@p a=time] [shipb=@p b=time]] (gth a b))
+$ comment
$: =id
author=ship
thread=pid
parent=(unit pid)
children=(set pid)
contents=content-list
=votes
==
+$ full-node [p=comment children=$~(~ full-graph)]
+$ full-graph ((mop pid full-node) ggth)
++ form ((on pid full-node) ggth)
:: content
+$ content-list (list block)
+$ block
$% [%paragraph p=paragraph]
[%blockquote p=paragraph]
:: table
clist
[%heading p=cord q=heading]
[%media =media]
[%codeblock code=cord lang=cord]
[%eval hoon=cord]
[%tasklist p=(list task)]
::
[%ref app=term =ship =path]
[%json origin=term content=@t]
==
+$ heading $?(%h1 %h2 %h3 %h4 %h5 %h6)
+$ paragraph (list inline)
:: man tables are a rabbit hole. we'll get to it
++ table
|^ [%table headers=(list cell) rows=(list row)]
+$ row (list cell)
+$ cell content-list
--
+$ clist [%list p=(list li) ordered=?]
+$ li content-list
+$ task [p=paragraph q=?]
+$ poll-opt [option=cord votes=@]
+$ media
$% [%images p=(list [url=@t caption=@t])]
[%video p=cord]
[%audio p=cord]
==
+$ inline
$% [%text p=cord]
[%italic p=cord]
[%bold p=cord]
[%strike p=cord]
[%codespan p=cord]
[%link href=cord show=cord]
[%break ~]
:: not strictly markdown
[%ship p=ship]
[%date p=@da]
[%note id=cord text=(list inline)] :: footnotes and so on
[%underline p=cord]
[%sup p=cord]
[%sub p=cord]
[%ruby p=cord q=cord]
==
--

2
sys.kelvin Normal file
View File

@ -0,0 +1,2 @@
[%zuse 412]
[%zuse 411]

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
web/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

0
web/assets/script.js Normal file
View File

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

1
web/assets/spinner.svg Normal file
View File

@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_0XTQ{transform-origin:center;animation:spinner_y6GP .75s linear infinite}@keyframes spinner_y6GP{100%{transform:rotate(360deg)}}</style><path class="spinner_0XTQ" d="M12,23a9.63,9.63,0,0,1-8-9.5,9.51,9.51,0,0,1,6.79-9.1A1.66,1.66,0,0,0,12,2.81h0a1.67,1.67,0,0,0-1.94-1.64A11,11,0,0,0,12,23Z"/></svg>

After

Width:  |  Height:  |  Size: 398 B

149
web/assets/style.css Normal file
View File

@ -0,0 +1,149 @@
@font-face {
font-family: Urbit Sans;
src: url(https://media.urbit.org/fonts/UrbitSans/UrbitSansVFWeb-Regular.woff2) format("woff2");
font-weight: 100 700;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-UltraThin.otf);
font-weight: 100;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Thin.otf);
font-weight: 200;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Light.otf);
font-weight: 300;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Regular.otf);
font-weight: 400;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Medium.otf);
font-weight: 500;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-SemiBold.otf);
font-weight: 600;
font-style: normal
}
@font-face {
font-family: "Urbit Serif Italic";
src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Bold.otf);
font-weight: 700;
font-style: normal
}
body,
html {
font-family: Urbit Sans
}
/* utility */
.f {
display: flex;
}
.fs {
display: flex;
justify-content: space-between;
}
.g1 {
gap: 0.5rem;
}
.g2 {
gap: 1rem;
}
/* base */
:root {
--black: #141A14;
--white: #FFFFFF;
--primary: #FFF450;
--muted: #B9B13D;
}
* {
background-color: var(--primary);
color: var(--black);
}
/* nav */
nav {
padding: 1rem;
}
#nav-main {
background-color: var(--black);
color: var(--primary);
cursor: pointer;
}
/* index */
main {
padding: 1rem 2rem;
}
#index-top {
margin-bottom: 1.5rem;
font-size: 1.4rem;
font-weight: 600;
div {
opacity: 0.5;
cursor: pointer;
}
& .active {
opacity: 1;
}
}
.thread-preview {
padding: 0.5rem 0;
border-bottom: 2px solid black;
&:first-child {
border-top: 2px solid black;
}
& .num {
font-size: 1.5rem;
}
& a {
font-size: 1.1rem;
text-decoration: none;
font-weight: 500;
}
& .meta {
opacity: 0.5;
}
}

View File

@ -0,0 +1,28 @@
/+ sig=sigil-sigil
|_ =bowl:gall
++ login
?- (clan:title src.bowl)
%czar sigil
%king sigil
%duke sigil
%earl sigil
%pawn ;a/"/~/login":"Log In"
++ sigil
:: ;+ (sig(size 48) src.bowl)
=/ (scow %p src.bowl)
;a/"/":"{p}"
++ $
;nav.fs.g2
;div.fg2
;div#nav-main.fs
;a/"/":"~ Technical Journal"
;div#nav-dropdown:"↓"
==
;div#nav-links
;a:/"/information":"Information"
;a:/"/Forum":"Forum"
==
==
;+ login
==
--

20
web/layout.hoon Normal file
View File

@ -0,0 +1,20 @@
|_ children=marl
++ $
;html
;head
;meta(charset "utf-8");
;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
;title:"Urbit Systems Technical Journal Forum"
;link/"/forum/imgs/favicon.ico"(rel "icon", type "image/png");
;link/"/forum/imgs/favicon-32x32.png"(rel "icon", type "image/png", sizes "32x32");
;link/"/forum/imgs/favicon-16x16.png"(rel "icon", type "image/png", sizes "16x16");
;link/"/forum/imgs/apple-touch-icon.png"(rel "apple-touch-icon", type "image/png", sizes "180x180");
;link/"/forum/site.webmanifest"(rel "manifest");
;link/"/forum/style.css"(rel "stylesheet");
==
;body
;* children
==
==
--

82
web/pages/index.hoon Normal file
View File

@ -0,0 +1,82 @@
/- sur=forum, tp=post
/+ lib=forum, sr=sortug
|_ [thp=thread-page:sur =bowl:gall]
++ $ ^- manx
;main
;div#index-top.f.g1
;div:"Popular"
;div.active:"Latest"
==
;div.thread-list
;* thread-list
==
;+ moar
==
++ thread-list ^- marl
=/ tl threads.thp
=/ i 1
=| res=marl
|- ?~ tl (flop res)
=/ ted (thread i i.tl)
=. res [ted res]
$(i +(i), tl t.tl)
++ thread |= [num=@ud t=thread:sur] ^- manx
=/ thread-link (scow:sr %uw (jam pid.t))
=/ titlet (trip title.t)
=/ numt (scow %ud num)
=/ link ?. ?=(%link -.content.t) ~
;+ (link-div +.content.t)
=/ ago (post-date-ago:lib id.pid.t now.bowl %yau)
=/ author (scow %p ship.pid.t)
=/ comments ?~ replies.t ~
;+ ;div:"{(scow %ud (lent replies.t))} comments"
;div.thread-preview.f.g2
;div.num:"{numt}."
;div.preview
;div.title.f.g1
;a/"/forum/ted/{thread-link}":"{titlet}"
;* link
==
;div.meta.f.g2
;+ (votes votes.t)
;div:"{author}"
;div:"{ago} ago"
;* comments
==
==
==
++ votes |= v=votes:tp
=/ old (old:si tally.v)
=/ img ?: -.old
;img@"/up.svg";
;img@"/down.svg";
;div.f.g0
;+ img
;div:"{(scow %ud +.old)}"
==
++ link-div |= l=@t
=/ url (de-purl:html l)
=/ dom ""
=/ domain ?~ url dom
=/ host r.p.u.url
?. -.host dom
?: ?=(@if +.host) dom
=/ parts=(list @t) +.host
=/ parts (flop parts)
|- ?~ parts dom
=/ el (trip i.parts)
=. dom
?: .=(~ dom) "{el}" "{dom}.{el}"
$(parts t.parts)
;div.out-link
;a/"{(trip l)}":"({domain})"
;img@"/imgs/outlink.svg";
==
++ moar
=/ page-num (add 1 page.thp)
;a/"/forum/p/{(scow %ud page-num)}":"More"
--

5
web/pages/thread.hoon Normal file
View File

@ -0,0 +1,5 @@
/- sur=forum
|_ [ted=thread:sur =bowl:gall]
++ $
;div:"lmao"
--

89
web/router.hoon Normal file
View File

@ -0,0 +1,89 @@
/- sur=forum, tp=post
/+ lib=forum, sr=sortug
/+ server
::
/= layout /web/layout
/= index /web/pages/index
/= thread /web/pages/thread
:: /* sw %noun /web/sw/js
:: /* manifest %noun /web/manifest/json
:: assets
/* css %css /web/assets/style/css
/* spinner %noun /web/assets/spinner/svg
/* favicon %noun /web/assets/favicon/ico
/* favicon1 %noun /web/assets/favicon-32x32/png
/* favicon2 %noun /web/assets/favicon-16x16/png
|%
+$ order [id=@ta req=inbound-request:eyre]
++ pbail
%- html-response:gen:server
%- manx-to-octs:server
manx-bail
++ manx-bail ^- manx ;div:"404"
++ route
|= [=order =state:sur =bowl:gall] ^- (list card:agent:gall)
=/ rl (parse-request-line:server url.request.req.order)
=. site.rl ?~ site.rl ~ t.site.rl
=/ met method.request.req.order
=/ fpath=(pole knot) [met site.rl]
~& > rl=fpath
=/ bail %+ give-simple-payload:app:server id.order pbail
|^
:: if file extension assume its asset
?. ?=(~ ext.rl) (serve-assets rl)
?+ fpath bail
[%'GET' rest=*] (serve-get rl(site rest.fpath))
[%'POST' rest=*] (serve-post rl(site rest.fpath))
==
::
++ serve-assets
|= rl=request-line:server
~& >> assets=rl
=/ pl
?+ [site ext]:rl pbail
[[%style ~] [~ %css]] (css-response:gen:server (as-octs:mimes:html css))
:: [[%spinner ~] [~ %svg]] [%full (serve-other:kaji %svg spinner)]
:: [[%sw ~] [~ %js]] [%mime /text/javascript sw]
:: [[%manifest ~] [~ %json]] [%mime /application/json manifest]
==
(give-simple-payload:app:server id.order pl)
++ serve-get
|= rl=request-line:server
=/ pl %- html-response:gen:server %- manx-to-octs:server
^- manx
=/ p=(pole knot) site.rl ::?. mob.rl pat.rl [%m pat.rl]
?: ?=([%f rest=*] p) (fragment rest.p)
%- layout ^- marl :_ ~
?+ p manx-bail
~ (serve-index '1')
[%p p=@t ~] (serve-index p.p)
[%ted ted=@t ~] (serve-thread ted.p)
==
(give-simple-payload:app:server id.order pl)
++ serve-index |= t=@t ^- manx
=/ pag (slaw %ud t) ?~ pag manx-bail
=/ threads (get-thread-page:lib u.pag state)
(index [u.pag threads] bowl)
++ serve-thread |= uidt=@t ^- manx
=/ uid (slaw:sr %uw uidt) ?~ uid manx-bail
=/ cued (cue u.uid)
=/ pid %- (soft pid:tp) cued
?~ pid manx-bail
=/ ted (get-thread:lib u.pid state)
?~ ted manx-bail
(thread u.ted bowl)
++ fragment
|= p=(pole knot)
?+ p manx-bail
~ manx-bail
==
++ serve-post
|= rl=request-line:server ~
--
--