Merge branch 'release/next-userspace' into la/deep-graph

This commit is contained in:
Matilde Park 2021-05-24 19:02:44 -04:00
commit e859f2a5e8
51 changed files with 13795 additions and 743 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7b7cf24e56ab078cf1dcb82e4e7744f188c5221c08772d6cfb15f59ce81aaa5
size 11198219
oid sha256:c505cb659a4e37fcfa85c3e81fc09c9ca4229a925a64a3371c1cf2db4e6940c8
size 11569940

View File

@ -875,7 +875,7 @@
%ge (dy-run-generator (dy-cage p.p.p.bil) q.p.bil)
%sa
=+ .^(=dais:clay cb+(en-beam he-beak /[p.bil]))
(dy-hand p.bil bunt:dais)
(dy-hand p.bil *vale:dais)
::
%as
=/ cag=cage (dy-cage p.q.bil)

View File

@ -5,7 +5,7 @@
/- glob
/+ default-agent, verb, dbug
|%
++ hash 0v2.rvlfs.f97fq.hjrpe.d3h68.n54sj
++ hash 0v2.3mphd.voocg.covr7.iv5la.kkk8h
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
+$ all-states
$% state-0

View File

@ -1,6 +1,5 @@
:: graph-store [landscape]
::
::
/+ store=graph-store, sigs=signatures, res=resource, default-agent, dbug, verb
~% %graph-store-top ..part ~
|%

View File

@ -24,6 +24,6 @@
<div id="portal-root"></div>
<script src="/~landscape/js/channel.js"></script>
<script src="/~landscape/js/session.js"></script>
<script src="/~landscape/js/bundle/index.a6842e8d167b4e66a4e0.js"></script>
<script src="/~landscape/js/bundle/index.31fd4ffe12da870b6215.js"></script>
</body>
</html>

View File

@ -0,0 +1,15 @@
:: Kiln: Fuse local desk from (optionally-)foreign sources
::
:::: /hoon/fuse/hood/gen
::
/* help-text %txt /gen/hood/fuse/help/txt
=, clay
::
::::
::
:- %say
|= [[now=@da eny=@uvJ bec=beak] [arg=[?(~ [des=desk bas=beak con=(list [beak germ]) ~])]] ~]
:- %kiln-fuse
?~ arg
((slog (turn `wain`help-text |=(=@t leaf+(trip t)))) ~)
[des bas con]:arg

View File

@ -0,0 +1,8 @@
Usage:
|fuse %destination-desk base-beak ~[[source-beak %some-germ] [another-beak %another-germ]]
A fuse replaces the contents of %destination-desk with the merge of the
specified beaks according to their merge strategies. This has no dependence
on the previous state of %destination-desk so any commits/work there will
be overwritten.

View File

@ -55,6 +55,12 @@
cas=case ::
gim=?(%auto germ) ::
==
+$ kiln-fuse
$@ ~
$: syd=desk
bas=beak
con=(list [beak germ])
==
--
|= [bowl:gall state]
?> =(src our)
@ -381,6 +387,11 @@
?~ +< abet
abet:abet:(merge:(work syd) ali sud cas gim)
::
++ poke-fuse
|= k=kiln-fuse
?~ k abet
abet:(emit [%pass /kiln/fuse/[syd.k] %arvo %c [%fuse syd.k bas.k con.k]])
::
++ poke-cancel
|= a=@tas
abet:(emit %pass /cancel %arvo %c [%drop a])
@ -430,6 +441,7 @@
%kiln-info =;(f (f !<(_+<.f vase)) poke-info)
%kiln-label =;(f (f !<(_+<.f vase)) poke-label)
%kiln-merge =;(f (f !<(_+<.f vase)) poke-merge)
%kiln-fuse =;(f (f !<(_+<.f vase)) poke-fuse)
%kiln-mount =;(f (f !<(_+<.f vase)) poke-mount)
%kiln-ota =;(f (f !<(_+<.f vase)) poke:update)
%kiln-ota-info =;(f (f !<(_+<.f vase)) poke-ota-info)
@ -489,6 +501,8 @@
++ take |=(way=wire ?>(?=([@ ~] way) (work i.way))) :: general handler
++ take-mere ::
|= [way=wire are=(each (set path) (pair term tang))]
?. ?=([@ ~] way)
abet
abet:abet:(mere:(take way) are)
::
++ take-coup-fancy ::

View File

@ -490,7 +490,7 @@
=/ m (strand ,vase)
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %b case /[mak])
(warp ship desk ~ %sing %e case /[mak])
?~ riot
(strand-fail %build-nave >arg< ~)
?> =(%nave p.r.u.riot)

View File

@ -33,7 +33,7 @@
++ grab
|%
++ noun
|= p=*
|: p=`*`%*(. *indexed-post index.p [0 ~])
=/ ip ;;(indexed-post p)
?> ?=([@ ~] index.p.ip)
ip

View File

@ -49,7 +49,7 @@
++ grab
|%
++ noun
|= p=*
|: p=`*`%*(. *indexed-post index.p [0 0 ~])
=/ ip ;;(indexed-post p)
?+ index.p.ip ~|(index+index.p.ip !!)
:: top-level link post; title and url

View File

@ -43,7 +43,7 @@
:: +noun: validate post
::
++ noun
|= p=*
|: p=`*`%*(. *indexed-post contents.p [%text '']~)
=/ ip ;;(indexed-post p)
?> ?=(^ contents.p.ip)
ip

View File

@ -58,7 +58,7 @@
:: +noun: validate publish note
::
++ noun
|= p=*
|: p=`*`%*(. *indexed-post index.p [0 ~])
=/ ip ;;(indexed-post p)
?+ index.p.ip !!
:: top level post must have no content

View File

@ -762,6 +762,11 @@
her=@p dem=desk cas=case :: source
how=germ :: method
== ::
$: %fuse :: merge many
des=desk :: target desk
bas=beak :: base desk
con=(list [beak germ]) :: merges
==
[%mont pot=term bem=beam] :: mount to unix
[%dirk des=desk] :: mark mount dirty
[%ogre pot=$@(desk beam)] :: delete mount point
@ -957,7 +962,6 @@
$_
^?
|%
++ bunt *typ
++ diff |~([old=typ new=typ] *dif)
++ form *mark
++ join |~([a=dif b=dif] *(unit (unit dif)))
@ -972,7 +976,6 @@
+$ dais
$_ ^|
|_ sam=vase
++ bunt sam
++ diff |~(new=_sam *vase)
++ form *mark
++ join |~([a=vase b=vase] *(unit (unit vase)))

View File

@ -59,6 +59,12 @@
::
+$ cult (jug wove duct)
::
:: State for ongoing %fuse merges. `con` maintains the ordering,
:: `sto` stores the data needed to merge, and `bas` is the base
:: beak for the merge.
::
+$ melt [bas=beak con=(list [beak germ]) sto=(map beak (unit dome:clay))]
::
:: Domestic desk state.
::
:: Includes subscriber list, dome (desk content), possible commit state (for
@ -69,6 +75,7 @@
dom=dome :: desk state
per=regs :: read perms per path
pew=regs :: write perms per path
fiz=melt :: state for mega merges
==
::
:: Desk state.
@ -212,6 +219,7 @@
dom=dome :: revision state
per=regs :: read perms per path
pew=regs :: write perms per path
fiz=melt :: domestic mega merges
== ::
::
:: Foreign request manager.
@ -303,6 +311,7 @@
$: %c :: to %clay
$> $? %info :: internal edit
%merg :: merge desks
%fuse :: merge many
%pork ::
%warp ::
%werp ::
@ -564,7 +573,6 @@
=/ dif diff:deg
^- (nave typ dif)
|%
++ bunt +<.cor
++ diff
|= [old=typ new=typ]
^- dif
@ -586,7 +594,6 @@
=/ dif _*diff:grad:cor
^- (nave:clay typ dif)
|%
++ bunt +<.cor
++ diff |=([old=typ new=typ] (diff:~(grad cor old) new))
++ form form:grad:cor
++ join
@ -627,7 +634,6 @@
:_ nub
^- dais
|_ sam=vase
++ bunt (slap nav limb/%bunt)
++ diff
|= new=vase
(slam (slap nav limb/%diff) (slop sam new))
@ -654,7 +660,7 @@
|= diff=vase
(slam (slap nav limb/%pact) (slop sam diff))
++ vale
|= =noun
|: noun=q:(slap nav !,(*hoon *vale))
(slam (slap nav limb/%vale) noun/noun)
--
:: +build-cast: produce gate to convert mark .a to, statically typed
@ -1110,12 +1116,12 @@
~
=/ rus rus:(~(gut by hoy.ruf) her *rung)
%+ ~(gut by rus) syd
[lim=~2000.1.1 ref=`*rind qyx=~ dom=*dome per=~ pew=~]
[lim=~2000.1.1 ref=`*rind qyx=~ dom=*dome per=~ pew=~ fiz=*melt]
:: administrative duct, domestic +rede
::
:+ ~ `hun.rom.ruf
=/ jod (~(gut by dos.rom.ruf) syd *dojo)
[lim=now ref=~ [qyx dom per pew]:jod]
[lim=now ref=~ [qyx dom per pew fiz]:jod]
::
=* red=rede ->+
|%
@ -1132,7 +1138,7 @@
::
%= ruf
hun.rom (need hun)
dos.rom (~(put by dos.rom.ruf) syd [qyx dom per pew]:red)
dos.rom (~(put by dos.rom.ruf) syd [qyx dom per pew fiz]:red)
==
::
:: Handle `%sing` requests
@ -2058,32 +2064,178 @@
=/ =wire /merge/[syd]/(scot %p ali-ship)/[ali-desk]/[germ]
(emit hen %pass wire %c %warp ali-ship ali-desk `[%sing %v case /])
::
++ make-melt
|= [bas=beak con=(list [beak germ])]
^- melt
:+ bas con
%- ~(gas by *(map beak (unit dome:clay)))
:- [bas *(unit dome:clay)]
(turn con |=(a=[beak germ] [-.a *(unit dome:clay)]))
::
++ start-fuse
|= [bas=beak con=(list [beak germ])]
^+ ..start-fuse
=/ moves=(list move)
%+ turn
[[bas *germ] con]
|= [bec=beak germ]
^- move
=/ wir=wire /fuse/[syd]/(scot %p p.bec)/[q.bec]/(scot r.bec)
[hen %pass wir %c %warp p.bec q.bec `[%sing %v r.bec /]]
::
:: We also want to clear the state (fiz) associated with this
:: merge and print a warning if it's non trivial i.e. we're
:: starting a new fuse before the previous one terminated.
::
=/ err=tang
?~ con.fiz
~
=/ discarded=tang
%+ turn
~(tap in sto.fiz)
|= [k=beak v=(unit dome:clay)]
^- tank
=/ received=tape ?~(v "missing" "received")
leaf+"{<k>} {received}"
:_ discarded
leaf+"fusing into {<syd>} from {<bas>} {<con>} - overwriting prior fuse"
=. fiz (make-melt bas con)
((slog err) (emil moves))
::
++ take-fuse
|^
::
|= [bec=beak =riot]
^+ ..take-fuse
?~ riot
::
:: By setting fiz to *melt the merge is aborted - any further
:: responses we get for the merge will cause take-fuse to crash
::
=. fiz *melt
((slog [leaf+"clay: fuse failed, missing {<bec>}"]~) ..take-fuse)
?> (~(has by sto.fiz) bec)
=. fiz
:+ bas.fiz con.fiz
(~(put by sto.fiz) bec `!<(dome:clay q.r.u.riot))
=/ all-done=flag
%- ~(all by sto.fiz)
|= res=(unit dome:clay)
^- flag
!=(res ~)
?. all-done
..take-fuse
=| rag=rang
=/ clean-state ..take-fuse
=/ initial-dome=dome:clay (need (~(got by sto.fiz) bas.fiz))
=/ continuation-yaki=yaki
(~(got by hut.ran) (~(got by hit.initial-dome) let.initial-dome))
=/ parents=(list tako) ~[(~(got by hit.initial-dome) let.initial-dome)]
=/ merges con.fiz
|-
^+ ..take-fuse
?~ merges
=/ t=tang [leaf+"{<syd>} fused from {<bas.fiz>} {<con.fiz>}" ~]
=. ..take-fuse (done-fuse clean-state %& ~)
(park | [%| continuation-yaki(p (flop parents))] rag)
=/ [bec=beak g=germ] i.merges
=/ ali-dom=dome:clay (need (~(got by sto.fiz) bec))
=/ result (merge-helper p.bec q.bec g ali-dom `continuation-yaki)
?- -.result
%|
(done-fuse clean-state %| %fuse-merge-failed p.result)
::
%&
=/ merge-result=(unit merge-result) +.result
?~ merge-result
::
:: This merge was a no-op, just continue
::
$(merges t.merges)
?^ conflicts.u.merge-result
::
:: If there are merge conflicts send the error and abort the merge
::
(done-fuse clean-state %& conflicts.u.merge-result)
=/ merged-yaki=yaki
?- -.new.u.merge-result
%|
+.new.u.merge-result
::
%&
::
:: Convert the yuki to yaki
::
=/ yuk=yuki +.new.u.merge-result
=/ lobes=(map path lobe)
%- ~(run by q.yuk)
|= val=(each page lobe)
^- lobe
?- -.val
%& (page-to-lobe +.val)
%| +.val
==
(make-yaki p.yuk lobes now)
==
%= $
continuation-yaki merged-yaki
merges t.merges
hut.ran (~(put by hut.ran) r.merged-yaki merged-yaki)
lat.rag (~(uni by lat.rag) lat.u.merge-result)
parents [(~(got by hit.ali-dom) let.ali-dom) parents]
==
==
:: +done-fuse: restore state after a fuse is attempted, whether it
:: succeeds or fails.
::
++ done-fuse
|= [to-restore=_..take-fuse result=(each (set path) (pair term tang))]
^+ ..take-fuse
=. fiz.to-restore *melt
(done:to-restore result)
--
::
++ done
|= result=(each (set path) (pair term tang))
^+ ..merge
(emit hen %give %mere result)
::
++ merge
|= [=ali=ship =ali=desk =germ =riot]
^+ ..merge
|^
?~ riot
(done %| %ali-unavailable >[ali-ship ali-desk germ]< ~)
(done %| %ali-unavailable ~[>[ali-ship ali-desk germ]<])
=/ ali-dome=dome:clay !<(dome:clay q.r.u.riot)
=/ result=(each (unit merge-result) (pair term tang))
(merge-helper ali-ship ali-desk germ ali-dome ~)
?- -.result
%|
(done %| +.result)
::
%&
=/ mr=(unit merge-result) +.result
?~ mr
(done %& ~)
=. ..merge (done %& conflicts.u.mr)
(park | new.u.mr ~ lat.u.mr)
==
::
+$ merge-result [conflicts=(set path) new=yoki lat=(map lobe blob)]
::
++ merge-helper
|= [=ali=ship =ali=desk =germ ali-dome=dome:clay continuation-yaki=(unit yaki)]
^- (each (unit merge-result) [term tang])
|^
^- (each (unit merge-result) [term tang])
=/ ali-yaki=yaki (~(got by hut.ran) (~(got by hit.ali-dome) let.ali-dome))
=/ bob-yaki=(unit yaki)
?~ let.dom
~
(~(get by hut.ran) (~(got by hit.dom) let.dom))
=/ merge-result (merge-by-germ ali-yaki bob-yaki)
?: ?=(%| -.merge-result)
(done %| p.merge-result)
?~ p.merge-result
(done %& ~)
=. ..merge (done %& conflicts.u.p.merge-result)
(park | new.u.p.merge-result ~ lat.u.p.merge-result)
?~ continuation-yaki
?~ let.dom
~
(~(get by hut.ran) (~(got by hit.dom) let.dom))
continuation-yaki
(merge-by-germ ali-yaki bob-yaki)
::
++ done
|= result=(each (set path) (pair term tang))
^+ ..merge
(emit hen %give %mere result)
::
+$ merge-result [conflicts=(set path) new=yoki lat=(map lobe blob)]
++ merge-by-germ
|= [=ali=yaki bob-yaki=(unit yaki)]
^- (each (unit merge-result) [term tang])
@ -2101,16 +2253,13 @@
?- germ
::
:: If this is a %only-this merge, we check to see if ali's and bob's
:: commits are the same, in which case we're done. Otherwise, we
:: check to see if ali's commit is in the ancestry of bob's, in
:: which case we're done. Otherwise, we create a new commit with
:: bob's data plus ali and bob as parents.
:: commits are the same, in which case we're done.
:: Otherwise, we create a new commit with bob's data plus ali and
:: bob as parents.
::
%only-this
?: =(r.ali-yaki r.bob-yaki)
&+~
?: (~(has in (reachable-takos:ze r.bob-yaki)) r.ali-yaki)
&+~
:* %& ~
conflicts=~
new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki q.bob-yaki)]
@ -2138,8 +2287,6 @@
%take-this
?: =(r.ali-yaki r.bob-yaki)
&+~
?: (~(has in (reachable-takos:ze r.bob-yaki)) r.ali-yaki)
&+~
=/ new-data (~(uni by q.ali-yaki) q.bob-yaki)
:* %& ~
conflicts=~
@ -2409,7 +2556,7 @@
=+ (slag (dec (lent path)) path)
?~(- %$ i.-)
=/ =dais (get-dais mark)
=/ res=(unit (unit vase)) (~(join dais bunt:dais) q.cal q.cob)
=/ res=(unit (unit vase)) (~(join dais *vale:dais) q.cal q.cob)
?~ res
`[form:dais q.cob]
?~ u.res
@ -3503,12 +3650,29 @@
|-
?: =(b let.dom)
hit.dom
:: del everything after b
$(hit.dom (~(del by hit.dom) let.dom), let.dom (dec let.dom))
b
?: =(0 b)
[~ ~]
(data-twixt-takos =(0 ver) (~(get by hit.dom) a) (aeon-to-tako b))
::
=/ excludes=(set tako)
=| acc=(set tako)
=/ lower=@ud 1
|-
:: a should be excluded, so wait until we're past it
?: =(lower +(a))
acc
=/ res=(set tako) (reachable-takos (~(got by hit.dom) lower))
$(acc (~(uni in acc) res), lower +(lower))
=/ includes=(set tako)
=| acc=(set tako)
=/ upper=@ud b
|-
?: =(upper a)
acc
=/ res=(set tako) (reachable-takos (~(got by hit.dom) upper))
$(acc (~(uni in acc) res), upper (dec upper))
[(~(run in (~(dif in includes) excludes)) tako-to-yaki) ~]
:: Traverse parentage and find all ancestor hashes
::
++ reachable-takos :: reachable
@ -3527,30 +3691,6 @@
=. s ^$(p i.p.y)
$(p.y t.p.y)
::
:: Gets the data between two commit hashes, assuming the first is an
:: ancestor of the second.
::
:: Get all the takos before `a`, then get all takos before `b` except the
:: ones we found before `a`. Then convert the takos to yakis and also get
:: all the data in all the yakis.
::
:: What happens if you run an %init merge on a desk that already
:: had a commit?
::
++ data-twixt-takos
|= [plops=? a=(unit tako) b=tako]
^- [(set yaki) (set plop)]
=+ old=?~(a ~ (reachable-takos u.a))
=/ yal=(set tako)
%- silt
%+ skip
~(tap in (reachable-takos b))
|=(tak=tako (~(has in old) tak))
:- (silt (turn ~(tap in yal) tako-to-yaki))
?. plops
~
(silt (turn ~(tap in (new-lobes (new-lobes ~ old) yal)) lobe-to-blob))
::
:: Get all the lobes that are referenced in `a` except those that are
:: already in `b`.
::
@ -3640,11 +3780,11 @@
[[~ ~] fod.dom]
=/ cached=(unit [=vase *]) (~(get by naves.fod.dom) i.path)
?^ cached
:_(fod.dom [~ ~ %& %nave !>(vase.u.cached)])
:_(fod.dom [~ ~ %& %nave vase.u.cached])
=^ =vase fod.dom
%- wrap:fusion
(build-nave:(ford:fusion static-ford-args) i.path)
:_(fod.dom [~ ~ %& %nave !>(vase)])
:_(fod.dom [~ ~ %& %nave vase])
::
++ read-f
!.
@ -4070,7 +4210,7 @@
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
=| :: instrument state
$: ver=%7 :: vane version
$: ver=%8 :: vane version
ruf=raft :: revision tree
== ::
|= [now=@da eny=@uvJ rof=roof] :: current invocation
@ -4188,6 +4328,14 @@
=/ den ((de now rof hen ruf) our des.req)
abet:(start-merge:den her.req dem.req cas.req how.req)
[mos ..^$]
::
%fuse
?: =(%$ des.req)
~&(%fuse-no-desk !!)
=^ mos ruf
=/ den ((de now rof hen ruf) our des.req)
abet:(start-fuse:den bas.req con.req)
[mos ..^$]
::
%mont
=. hez.ruf ?^(hez.ruf hez.ruf `[[%$ %sync ~] ~])
@ -4316,11 +4464,41 @@
++ load
=> |%
+$ raft-any
$% [%7 raft-7]
$% [%8 raft-8]
[%7 raft-7]
[%6 raft-6]
==
+$ raft-7 raft
+$ dojo-7 dojo
+$ raft-8 raft
+$ raft-7
$: rom=room-7
hoy=(map ship rung-7)
ran=rang
mon=(map term beam)
hez=(unit duct)
cez=(map @ta crew)
pud=(unit [=desk =yoki])
==
+$ room-7
$: hun=duct
dos=(map desk dojo-7)
==
+$ rung-7
$: rus=(map desk rede-7)
==
+$ dojo-7
$: qyx=cult
dom=dome
per=regs
pew=regs
==
+$ rede-7
$: lim=@da
ref=(unit rind)
qyx=cult
dom=dome
per=regs
pew=regs
==
+$ ford-cache-7 ford-cache
+$ raft-6
$: rom=room-6 :: domestic
@ -4363,7 +4541,8 @@
|= old=raft-any
|^
=? old ?=(%6 -.old) 7+(raft-6-to-7 +.old)
?> ?=(%7 -.old)
=? old ?=(%7 -.old) 8+(raft-7-to-8 +.old)
?> ?=(%8 -.old)
..^^$(ruf +.old)
:: +raft-6-to-7: delete stale ford caches (they could all be invalid)
::
@ -4384,6 +4563,26 @@
|= =rede-6
rede-6(dom dom.rede-6(fod *ford-cache-7))
==
:: +raft-7-to-8: create bunted melts in each dojo/rede
::
++ raft-7-to-8
|= raf=raft-7
^- raft-8
%= raf
dos.rom
%- ~(run by dos.rom.raf)
|= doj=dojo-7
^- dojo
[qyx.doj dom.doj per.doj pew.doj *melt]
::
hoy
%- ~(run by hoy.raf)
|= =rung-7
%- ~(run by rus.rung-7)
|= r=rede-7
^- rede
[lim.r ref.r qyx.r dom.r per.r pew.r *melt]
==
--
::
++ scry :: inspect
@ -4466,6 +4665,18 @@
abet:(merge:den ali-ship ali-desk germ p.hin)
[mos ..^$]
::
?: ?=([%fuse @ @ @ @ ~] tea)
?> ?=(%writ +<.hin)
=* syd i.t.tea
=/ ali-ship=@p (slav %p i.t.t.tea)
=* ali-desk=desk i.t.t.t.tea
=/ ali-case (rash i.t.t.t.t.tea nuck:so)
?> ?=([%$ *] ali-case)
=^ mos ruf
=/ den ((de now rof hen ruf) our i.t.tea)
abet:(take-fuse:den [ali-ship ali-desk (case +.ali-case)] p.hin)
[mos ..^$]
::
?: ?=([%foreign-warp *] tea)
?> ?=(%writ +<.hin)
:_ ..^$

View File

@ -112,7 +112,7 @@
;: weld
%+ expect-eq
!>(*mime)
(slap res limb/%bunt)
(slap res !,(*hoon *vale))
::
%+ expect-eq
!> (~(gas in *(set [? path])) |^/mar/mime/hoon ~)
@ -139,7 +139,7 @@
;: weld
%+ expect-eq
!>(*@t)
(slap res limb/%bunt)
(slap res !,(*hoon *vale))
::
%+ expect-eq
!> (~(gas in *(set [? path])) |^/mar/udon/hoon |^/lib/cram/hoon ~)
@ -170,7 +170,7 @@
=/ changes
%- my
:~ [/mar/mime/hoon &+hoon+mar-mime]
[/lib/foo/hoon &+hoon+'/% moo %mime\0abunt:moo']
[/lib/foo/hoon &+hoon+'/% moo %mime\0a*vale:moo']
==
=/ ford
%: ford:fusion

View File

@ -2353,7 +2353,6 @@
:^ ~ ~ %dais
!> ^- dais:clay
|_ sam=vase
++ bunt !!
++ diff !!
++ form !!
++ join !!

1
pkg/interface/.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-checkout.\n"; exit 2; }
git lfs post-checkout "$@"

View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-commit.\n"; exit 2; }
git lfs post-commit "$@"

View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-merge.\n"; exit 2; }
git lfs post-merge "$@"

View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd pkg/interface && npx lint-staged

3
pkg/interface/.husky/pre-push Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/pre-push.\n"; exit 2; }
git lfs pre-push "$@"

View File

@ -0,0 +1,10 @@
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials"
]
}

View File

@ -0,0 +1,133 @@
import dark from '@tlon/indigo-dark';
import light from '@tlon/indigo-light';
import { Reset } from '@tlon/indigo-react';
import { BrowserRouter } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import useGraphState from '~/logic/state/graph';
import useMetadataState from '~/logic/state/metadata';
import '~/views/landscape/css/custom.css';
import '~/views/css/fonts.css';
import '~/views/apps/chat/css/custom.css';
import '~/views/css/indigo-static.css';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global Theme for components',
defaultValue: 'light',
toolbar: {
icon: 'circlehollow',
items: ['light', 'dark'],
},
},
};
export const decorators = [
(Story, context) => {
const theme = context.globals.theme === 'light' ? light : dark;
useMetadataState.setState({
associations: {
groups: {
'/ship/~bitbet-bolbel/urbit-community': {
metadata: {
preview: false,
vip: '',
title: 'Urbit Community',
description: 'World hub, help desk, meet and greet, etc.',
creator: '~bitbet-bolbel',
picture:
'https://fabled-faster.nyc3.digitaloceanspaces.com/fabled-faster/2021.4.02..21.52.41-UC.png',
hidden: false,
config: {
group: {
'app-name': 'graph',
resource: '/ship/~bitbet-bolbel/urbit-community-5.963',
},
},
'date-created': '~2020.6.25..21.39.35..2fd2',
color: '0x8f.9c9d',
},
'app-name': 'groups',
resource: '/ship/~bitbet-bolbel/urbit-community',
group: '/ship/~bitbet-bolbel/urbit-community',
},
},
graph: {
'/ship/~darrux-landes/development': {
metadata: {
preview: false,
vip: '',
title: 'Development',
description:
'Urbit Development Mailing List: https://groups.google.com/a/urbit.org/forum/#!forum/dev',
creator: '~darrux-landes',
picture: '',
hidden: false,
config: {
graph: 'chat',
},
'date-created': '~2020.4.6..21.53.30..dc68',
color: '0x0',
},
'app-name': 'graph',
resource: '/ship/~darrux-landes/development',
group: '/ship/~bitbet-bolbel/urbit-community',
},
},
},
});
useGraphState.setState({
looseNodes: {
'darrux-landes/development': {
'/170141184505059416342852185329797955584': {
post: {
index: '/170141184505059416342852185329797955584',
author: 'sipfyn-pidmex',
'time-sent': 1621275183241,
signatures: [
{
signature:
'0x3.9e41.4f04.3cac.786e.30c1.f4cc.8db3.9a78.0401.d16f.6301.94d0.a08a.0695.5008.02bf.0e07.a7a9.3d87.85f7.6334.e598.4ed3.5dee.58a7.cbd3.30e6.d65b.1fc9.ac62.162a.daf0.ff14.9cca.4a93.8177.0755.7b74.9d52.c0a6.b27f.9001',
life: 2,
ship: 'sipfyn-pidmex',
},
],
contents: [
{
text:
'is there a way to get a bunt of a specific instantance of a tagged union? i.e. if you have `$%([%a =atom] [%b =cell])`, can you get a bunt of specifically subtype `%a`?',
},
],
hash: '0xe790.53c1.0f2b.1e1b.8c30.7d33.236c.e69e',
},
children: {
root: {},
cachedIter: null,
},
},
},
},
});
return (
<ThemeProvider theme={theme}>
<BrowserRouter>
<Story />
<div id="portal-root" />
</BrowserRouter>
</ThemeProvider>
);
},
];

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
"@react-spring/web": "^9.1.1",
"@tlon/indigo-dark": "^1.0.6",
"@tlon/indigo-light": "^1.0.7",
"@tlon/indigo-react": "^1.2.22",
"@tlon/indigo-react": "^1.2.23",
"@tlon/sigil-js": "^1.4.3",
"@urbit/api": "file:../npm/api",
"any-ascii": "^0.1.7",
@ -67,6 +67,10 @@
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "^7.12.7",
"@storybook/addon-actions": "^6.2.9",
"@storybook/addon-essentials": "^6.2.9",
"@storybook/addon-links": "^6.2.9",
"@storybook/react": "^6.2.9",
"@types/lodash": "^4.14.168",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
@ -75,6 +79,7 @@
"@types/styled-system": "^5.1.10",
"@types/yup": "^0.29.11",
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.24.0",
"@urbit/eslint-config": "file:../npm/eslint-config",
"@welldone-software/why-did-you-render": "^6.1.0",
"babel-eslint": "^10.1.0",
@ -83,10 +88,13 @@
"babel-plugin-root-import": "^6.6.0",
"clean-webpack-plugin": "^3.0.0",
"cross-env": "^7.0.3",
"eslint": "^7.19.0",
"eslint": "^7.26.0",
"eslint-plugin-react": "^7.22.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^4.5.1",
"husky": "^6.0.0",
"lint-staged": "^11.0.0",
"loki": "^0.28.1",
"moment-locales-webpack-plugin": "^1.2.0",
"react-hot-loader": "^4.13.0",
"sass": "^1.32.5",
@ -106,8 +114,14 @@
"build:dev": "cross-env NODE_ENV=development webpack --config config/webpack.dev.js",
"build:prod": "cd ../npm/api && npm ci && cd ../../interface && cross-env NODE_ENV=production webpack --config config/webpack.prod.js",
"start": "webpack-dev-server --config config/webpack.dev.js",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "cd ../.. && husky install pkg/interface/.husky",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"author": "",
"license": "MIT"
"license": "MIT",
"lint-staged": {
"*.{js,ts,tsx}": "eslint --cache --fix"
}
}

View File

@ -328,6 +328,7 @@ export default class GraphApi extends BaseApi<StoreState> {
async getNewest(ship: string, resource: string, count: number, index = '') {
const data = await this.scry<any>('graph-store', `/newest/${ship}/${resource}/${count}${index}`);
data['graph-update'].fetch = true;
this.store.handleEvent({ data });
}
@ -335,7 +336,7 @@ export default class GraphApi extends BaseApi<StoreState> {
const idx = index.split('/').map(decToUd).join('/');
const data = await this.scry<any>('graph-store',
`/node-siblings/older/${ship}/${resource}/${count}${idx}`
);
);
this.store.handleEvent({ data });
}

View File

@ -285,9 +285,15 @@ const addNodes = (json, state) => {
const resource = data.resource.ship + '/' + data.resource.name;
if (!(resource in state.graphs)) {
state.graphs[resource] = new BigIntOrderedMap();
if(json.fetch) {
state.graphs[resource] = new BigIntOrderedMap();
} else {
// ignore updates until we load backlog deliberately, to avoid
// unnecessary memory usage
return state;
}
}
if (!(resource in state.graphTimesentMap)) {
state.graphTimesentMap[resource] = {};
}

View File

@ -1,8 +1,8 @@
import f from 'lodash/fp';
import { RemoteContentPolicy, LeapCategories, leapCategories } from "~/types/local-update";
import { RemoteContentPolicy, LeapCategories, leapCategories } from '~/types/local-update';
import { useShortcut as usePlainShortcut } from '~/logic/lib/shortcutContext';
import { BaseState, createState } from '~/logic/state/base';
import {useCallback} from 'react';
import { useCallback } from 'react';
export interface ShortcutMapping {
cycleForward: string;
@ -12,7 +12,6 @@ export interface ShortcutMapping {
hideSidebar: string;
}
export interface SettingsState extends BaseState<SettingsState> {
display: {
backgroundType: 'none' | 'url' | 'color';
@ -76,7 +75,7 @@ const useSettingsState = createState<SettingsState>('Settings', {
keyboard: {
cycleForward: 'ctrl+\'',
cycleBack: 'ctrl+;',
navForward: 'ctrl+[',
navForward: 'ctrl+]',
navBack: 'ctrl+[',
hideSidebar: 'ctrl+\\'
}

View File

@ -0,0 +1,120 @@
import React from 'react';
import { Story, Meta } from '@storybook/react';
import { Box } from '@tlon/indigo-react';
import {
GraphContent,
GraphContentProps
} from '~/views/landscape/components/Graph/GraphContent';
export default {
title: 'Graph/ContentTall',
component: GraphContent
} as Meta;
const fakeApi = {} as any;
const Template: Story<GraphContentProps> = args => (
<Box
maxWidth="500px"
backgroundColor="white"
overflowY="auto"
width="100%"
height="100%"
>
<GraphContent
tall
m="3"
maxWidth="100%"
{...args}
api={fakeApi}
showOurContact
/>
</Box>
);
export const Omnibus = Template.bind({});
Omnibus.args = {
contents: [
{
text: `# Structure of Document
Document is organized by Symptom, Diagnosis and Mitigation. Symptoms are user-level difficulties, problems, etc. this section also includes the differential diagnosis (ie, is a ship unavailable because its down or because eyre is not responding). Diagnosis is the root cause of the symptom. Mitigation includes steps that can be taken to fix the users problem. It also will define who can take certain mitigation steps.
There are presumed to be 3 roles of support:
- **Kenny**: has normal web access but no GCP Permissions
- **Jose**: Has GCP Permissions and can perform common procedures using the ylem tooling
## Second Heading [and a link](https://urbit.org)
This demonstration text includes an inline mention here
`
},
{ mention: '~hastuc-dibtux' },
{
text: `
to demonstrate text reflowing around inline elements. However, several elements do not flow inline, for example links.
`
},
{ url: 'https://www.youtube.com/watch?v=M04AKTCDavc&t=1s' },
{
text: 'Links can also be images, where they\'ll be embedded with the content'
},
{ url: 'http://media.urbit.org/site/sea30-poster.jpg' },
{
text: `
A link should stand alone to allow for the expansion of embedded content. Another element that does not flow inline is the permalink`
},
{
reference: {
graph: {
index: '/170141184505059416342852185329797955584',
graph: '/ship/~darrux-landes/development',
group: '/ship/~bitbet-bolbel/urbit-community'
}
}
},
{
text: `
A permalink does not flow inline to ensure that it can be embedded in the flow of the content. Also available in the tall rendering mode are unordered and ordered lists.
### TODO (heading 3)
1. Write nock
2. Write hoon
3. Write arvo
4. Write landscape
5. ???
6. Profile
As well as tables, which are written in the standard markdown style.
| Key | Value |
|---------------|---------------|
| Nock | 4K |
| Hoon | 140K |
| Arvo | 420K |
GraphContentTall also supports inline links, like [this](https://tlon.io). These can be used if the user does not wish to highlight the linked content, for example as a footnote. Another element type is the
>blockquote
>which renders like this
>it's created by prefixing the line with a \`>\`
Additionally, GraphContent also supports code rendering \`inline code rendering\` and block code rendering, like so
\`\`\`
function fibonacci(num: number) {
if(num < 2) {
return 1;
} else {
return fibonacci(num - 1) + fibonacci(num - 2);
}
}
\`\`\`
`
}
]
};

View File

@ -0,0 +1,60 @@
import React from 'react';
import { Box } from '@tlon/indigo-react';
import { Story, Meta } from '@storybook/react';
import {
GraphContent,
GraphContentProps
} from '~/views/landscape/components/Graph/GraphContent';
export default {
title: 'Graph/ContentWide',
component: GraphContent
} as Meta;
const fakeApi = {} as any;
const Template: Story<GraphContentProps> = (args) => {
return (
<Box
backgroundColor="white"
p="2"
maxWidth="500px"
width="100%"
position="relative"
>
<GraphContent width="100%" {...args} api={fakeApi} showOurContact />
</Box>
);
};
export const Omnibus = Template.bind({});
Omnibus.args = {
contents: [
{ text: 'as for @H, I literally just miscounted' },
{
url:
'https://github.com/urbit/urbit/blob/master/pkg/arvo/ted/eth-watcher.hoon'
},
{
text:
'Text in landscape chats support *bolding* **italics** and ~~strikeouts~~ `code snippets`'
},
{ mention: '~fabled-faster' },
{
reference: {
graph: {
index: '/170141184505059416342852185329797955584',
graph: '/ship/~darrux-landes/development',
group: '/ship/~bitbet-bolbel/urbit-community'
}
}
},
{ text: ' ' },
{ mention: 'sipfyn-pidmex' },
{ text: `: you can always use a pattern like this
> blockquote demo
should not be quoted` }
]
};

View File

@ -58,7 +58,7 @@ export default function Groups(props: GroupsProps & Parameters<typeof Box>[0]) {
const notCount = graphNotifications(path);
return (
<Group
key={group.metadata.title}
key={group?.group}
updates={notCount}
first={index === 0}
unreads={unreadCount}

View File

@ -1,3 +1,5 @@
/* eslint-disable no-case-declarations */
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import { Anchor, Box, Col, Icon, Row, Text } from '@tlon/indigo-react';
import { Association, GraphConfig, GraphNode, Group, Post, ReferenceContent, TextContent, UrlContent } from '@urbit/api';
import bigInt from 'big-integer';
@ -33,7 +35,7 @@ function TranscludedLinkNode(props: {
>
<Text gray>This link has been deleted.</Text>
</Box>
)
);
}
switch (idx.length) {
@ -49,6 +51,7 @@ function TranscludedLinkNode(props: {
<Author
pt='12px'
pl='12px'
mt='6px'
size={24}
sigilPadding='6'
showImage
@ -57,7 +60,7 @@ function TranscludedLinkNode(props: {
/>
<Box
borderRadius='2'
mt='1'
mt='3'
ml='44px'
mr='3'
p='2'
@ -110,7 +113,7 @@ function TranscludedComment(props: {
>
<Text gray>This comment has been deleted.</Text>
</Box>
)
);
}
const group = useGroupForAssoc(assoc)!;
@ -121,6 +124,7 @@ function TranscludedComment(props: {
<Author
pt='12px'
pl='12px'
mt='6px'
size={24}
sigilPadding='6'
showImage
@ -128,7 +132,7 @@ function TranscludedComment(props: {
date={comment.post?.['time-sent']}
group={group}
/>
<Box pl="44px" pt='1'>
<Box pl="44px" pt='2'>
<GraphContent
api={api}
transcluded={transcluded}
@ -150,7 +154,6 @@ function TranscludedPublishNode(props: {
const group = useGroupForAssoc(assoc)!;
if (typeof node?.post === 'string') {
console.log(node)
return (
<Box
mx="12px"
@ -171,10 +174,11 @@ function TranscludedPublishNode(props: {
?.get(bigInt.one)
?.children?.peekLargest()?.[1]!;
return (
<Col color="black" gapY={2}>
<Col color="black">
<Author
pl='12px'
pt='12px'
mt='6px'
size={24}
sigilPadding='6'
showImage
@ -182,7 +186,7 @@ function TranscludedPublishNode(props: {
date={post.post?.['time-sent']}
group={group}
/>
<Text pl='44px' fontSize="2" fontWeight="medium">
<Text mt='3' pl='44px' fontSize="2" fontWeight="medium">
{(post.post.contents[0] as TextContent)?.text}
</Text>
<Box pl="44px" pr='3'>
@ -227,7 +231,7 @@ export function TranscludedPost(props: {
>
<Text gray>This post has been deleted.</Text>
</Box>
)
);
}
return (
@ -235,6 +239,7 @@ export function TranscludedPost(props: {
<Author
pt='12px'
pl='12px'
mt='6px'
size={24}
sigilPadding='6'
showImage
@ -242,7 +247,7 @@ export function TranscludedPost(props: {
date={post?.['time-sent']}
group={group}
/>
<Box pl='44px' pt='2' pr='3'>
<Box pl='44px' pt='3' pr='3'>
<MentionText
api={api}
transcluded={transcluded}
@ -272,8 +277,8 @@ export function TranscludedNode(props: {
const group = useGroupForAssoc(assoc)!;
if (
typeof node?.post === "string" &&
(assoc.metadata.config as GraphConfig).graph === "chat"
typeof node?.post === 'string' &&
(assoc.metadata.config as GraphConfig).graph === 'chat'
) {
return (
<Box

View File

@ -14,7 +14,7 @@ interface ResourceRouteProps {
name: string;
}
export function PermalinkRoutes(props: {}) {
export function PermalinkRoutes(props: unknown) {
const groups = useGroupState(s => s.groups);
const { query, toQuery } = useQuery();
@ -70,7 +70,7 @@ function GroupRoutes(props: { group: string; url: string }) {
<Route
path={makePath('/graph/:ship/:name')}
render={({ match, location }) => {
const { ship, name } = match.params as ResourceRouteProps;
const { ship, name } = match.params as unknown as ResourceRouteProps;
const path = `/ship/${ship}/${name}`;
const association = associations.graph[path];
const { url: routeUrl } = match;

View File

@ -1,17 +1,59 @@
import { BaseAnchor, Box, Center, Col, Icon, Row, Text } from "@tlon/indigo-react";
import { BaseAnchor, Box, Center, Col, Icon, Row, Text } from '@tlon/indigo-react';
import { Association, GraphNode, resourceFromPath, GraphConfig } from '@urbit/api';
import React, { useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from 'react';
import _ from 'lodash';
import { useHistory, useLocation } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import {
getPermalinkForGraph, GraphPermalink as IGraphPermalink, parsePermalink
} from '~/logic/lib/permalinks';
import { getModuleIcon, GraphModule } from "~/logic/lib/util";
import { useVirtualResizeProp } from "~/logic/lib/virtualContext";
import useGraphState from "~/logic/state/graph";
import useMetadataState from "~/logic/state/metadata";
import { GroupLink } from "~/views/components/GroupLink";
import { TranscludedNode } from "./TranscludedNode";
import { getModuleIcon, GraphModule } from '~/logic/lib/util';
import { useVirtualResizeProp } from '~/logic/lib/virtualContext';
import useGraphState from '~/logic/state/graph';
import useMetadataState from '~/logic/state/metadata';
import { GroupLink } from '~/views/components/GroupLink';
import { TranscludedNode } from './TranscludedNode';
function Placeholder(type) {
const lines = (type) => {
switch (type) {
case 'publish':
return 5;
case 'post':
return 3;
default:
return 1;
}
};
return (
<Box p='12px 12px 6px'>
<Row mb='6px' height="4">
<Box
backgroundColor="washedGray"
size="4"
marginRight="2"
borderRadius="2"
/>
<Box
backgroundColor="washedGray"
height="4"
width="25%"
borderRadius="2"
/>
</Row>
{_.times(lines(type), i => (
<Row margin="6px" ml='32px' height="4">
<Box
backgroundColor="washedGray"
height="4"
width="100%"
borderRadius="2"
/>
</Row>
))}
</Box>
);
}
function GroupPermalink(props: { group: string; api: GlobalApi }) {
const { group, api } = props;
@ -36,7 +78,7 @@ function GraphPermalink(
full?: boolean;
}
) {
const { full = false, showOurContact, pending, link, graph, group, index, api, transcluded } = props;
const { full = false, showOurContact, pending, graph, group, index, api, transcluded } = props;
const history = useHistory();
const location = useLocation();
const { ship, name } = resourceFromPath(graph);
@ -47,6 +89,7 @@ function GraphPermalink(
])
);
const [errored, setErrored] = useState(false);
const [loading, setLoading] = useState(false);
const association = useMetadataState(
useCallback(s => s.associations.graph[graph] as Association | null, [
graph
@ -60,9 +103,12 @@ function GraphPermalink(
return;
}
try {
setLoading(true);
await api.graph.getNode(ship, name, index);
setLoading(false);
} catch (e) {
console.log(e);
setLoading(false);
setErrored(true);
}
})();
@ -99,8 +145,8 @@ function GraphPermalink(
<Col
width="100%"
bg="white"
maxWidth={full ? null : "500px"}
border={full ? null : "1"}
maxWidth={full ? null : '500px'}
border={full ? null : '1'}
borderColor="lightGray"
borderRadius={2}
cursor="pointer"
@ -108,7 +154,8 @@ function GraphPermalink(
navigate(e);
}}
>
{showTransclusion && index && (
{loading && association && !errored && Placeholder((association.metadata.config as GraphConfig).graph)}
{showTransclusion && index && !loading && (
<TranscludedNode
api={api}
transcluded={transcluded + 1}
@ -117,7 +164,7 @@ function GraphPermalink(
showOurContact={showOurContact}
/>
)}
{association && !isInSameResource && (
{association && !isInSameResource && !loading && (
<PermalinkDetails
known
showTransclusion={showTransclusion}
@ -126,7 +173,7 @@ function GraphPermalink(
permalink={permalink}
/>
)}
{association && isInSameResource && transcluded === 2 && (
{association && isInSameResource && transcluded === 2 && !loading && (
<PermalinkDetails
known
showTransclusion={showTransclusion}
@ -135,8 +182,8 @@ function GraphPermalink(
permalink={permalink}
/>
)}
{isInSameResource && transcluded !== 2 && <Row height="12px" />}
{!association && (
{isInSameResource && transcluded !== 2 && !loading && <Row height='2' />}
{!association && !loading && (
<PermalinkDetails
icon="Groups"
showDetails={false}
@ -156,7 +203,7 @@ function PermalinkDetails(props: {
showDetails?: boolean;
known?: boolean;
}) {
const { title, icon, permalink, known, showTransclusion } = props;
const { title, icon, known, showTransclusion } = props;
const rowTransclusionStyle = showTransclusion
? { p: '12px 12px 11px 11px' }
: { p: '12px' };

View File

@ -114,7 +114,7 @@ return;
<SidebarItem icon='Upload' text='Remote Storage' hash='s3' />
<SidebarItem icon='LeapArrow' text='Leap' hash='leap' />
<SidebarItem icon='Node' text='CalmEngine' hash='calm' />
<SidebarItem icon='Keyboard' text='Shortcuts' hash='shortcuts' />
<SidebarItem icon='EastCarat' text='Shortcuts' hash='shortcuts' />
<SidebarItem
icon='Locked'
text='Devices + Security'

View File

@ -22,6 +22,7 @@ type RemoteContentProps = VirtualContextProps & {
style?: any;
transcluded?: any;
className?: string;
tall?: boolean;
}
interface RemoteContentState {
@ -131,9 +132,10 @@ return;
}
wrapInLink(contents, textOnly = false, unfold = false, unfoldEmbed = null, embedContainer = null, flushPadding = false, noOp = false) {
const { style } = this.props;
const { style, tall = false } = this.props;
const maxWidth = tall ? '100%' : 'min(500px, 100%)';
return (
<Box borderRadius={1} backgroundColor="washedGray" maxWidth="min(100%, 20rem)">
<Box borderRadius={1} backgroundColor="washedGray" maxWidth={maxWidth}>
<Row
alignItems="center"
gapX={1}
@ -159,7 +161,7 @@ return;
textOverflow="ellipsis"
minWidth={0}
width={textOnly ? 'calc(100% - 24px)' : 'fit-content'}
maxWidth="min(500px, 100%)"
maxWidth={maxWidth}
style={{ color: 'inherit', textDecoration: 'none', ...style }}
target="_blank"
rel="noopener noreferrer"
@ -367,4 +369,4 @@ return;
}
}
export default withState(withVirtual(RemoteContent), [[useSettingsState, ['remoteContentPolicy']]]);
export default withState(withVirtual(RemoteContent), [[useSettingsState, ['remoteContentPolicy']]]) as React.ComponentType<Omit<RemoteContentProps, 'save' | 'restore' | 'remoteContentPolicy'> & { ref?: any }>;

View File

@ -1,27 +1,31 @@
import {
Anchor, Box,
Col, H1,
Anchor,
Box,
H1,
H2,
H3,
H4, Text
H4,
Text,
Li,
Ol,
Ul,
Table,
Tr,
Td
} from '@tlon/indigo-react';
import { Content, ReferenceContent } from '@urbit/api';
import { Content } from '@urbit/api';
import _ from 'lodash';
import {
BlockContent, Content as AstContent, Parent, Root
} from 'ts-mdast';
import { BlockContent, Content as AstContent, Parent, Root } from 'ts-mdast';
import React from 'react';
import GlobalApi from '~/logic/api/global';
import { referenceToPermalink } from '~/logic/lib/permalinks';
import { PropFunc } from '~/types';
import { PermalinkEmbed } from '~/views/apps/permalinks/embed';
import Dot from '~/views/components/Dot';
import { Mention } from '~/views/components/MentionText';
import RemoteContent from '~/views/components/RemoteContent';
import CodeContent from './content/code';
import { parseTall, parseWide } from './parse';
type StitchMode = 'merge' | 'block' | 'inline';
// XX make better
@ -31,28 +35,20 @@ interface GraphMentionNode {
type: 'graph-mention';
ship: string;
}
interface GraphRefereceNode {
type: 'graph-reference';
reference: ReferenceContent;
}
interface GraphUrl {
type: 'graph-url';
url: string;
}
const codeToMdAst = (content: CodeContent) => {
return {
type: 'root',
children: [
{
type: 'code',
value: content.code.expression,
value: content.code.expression
},
{
type: 'code',
value: (content.code.output || []).join('\n'),
},
],
value: (content.code.output || []).join('\n')
}
]
};
};
@ -60,9 +56,15 @@ const contentToMdAst = (tall: boolean) => (
content: Content
): [StitchMode, any] => {
if ('text' in content) {
if (content.text.toString().trim().length === 0) {
return [
'merge',
{ type: 'root', children: [{ type: 'paragraph', children: [] }] }
];
}
return [
'merge',
tall ? parseTall(content.text) : parseWide(content.text),
tall ? parseTall(content.text) : parseWide(content.text)
] as [StitchMode, any];
} else if ('code' in content) {
return ['block', codeToMdAst(content)];
@ -74,10 +76,10 @@ const contentToMdAst = (tall: boolean) => (
children: [
{
type: 'graph-reference',
reference: content.reference,
},
],
},
reference: content.reference
}
]
}
];
} else if ('url' in content) {
return [
@ -87,10 +89,10 @@ const contentToMdAst = (tall: boolean) => (
children: [
{
type: 'graph-url',
url: content.url,
},
],
},
url: content.url
}
]
}
];
} else if ('mention' in content) {
return [
@ -100,18 +102,18 @@ const contentToMdAst = (tall: boolean) => (
children: [
{
type: 'graph-mention',
ship: content.mention,
},
],
},
ship: content.mention
}
]
}
];
}
return [
'inline',
{
type: 'root',
children: [],
},
children: []
}
];
};
@ -127,8 +129,8 @@ function stitchInline(a: any, b: any) {
children: [
...a.children.slice(0, lastParaIdx),
stitchInline(last, b),
...a.children.slice(lastParaIdx + 1),
],
...a.children.slice(lastParaIdx + 1)
]
};
return ros;
}
@ -140,9 +142,9 @@ function last<T>(arr: T[]) {
return arr[arr.length - 1];
}
function getChildren<T extends {}>(node: T): AstContent[] {
function getChildren<T extends Record<string, unknown>>(node: T): AstContent[] {
if ('children' in node) {
// @ts-ignore
// @ts-ignore TODO @liam-fitzgerald
return node.children;
}
return [];
@ -166,11 +168,11 @@ function stitchMerge(a: Root, b: Root) {
const bGrandchild = getChildren(bChildren[0]);
const mergedPara = {
...last(aChildren),
children: [...aGrandchild, ...bGrandchild],
children: [...aGrandchild, ...bGrandchild]
};
return {
...a,
children: [...aChildren.slice(0, -1), mergedPara, ...bChildren.slice(1)],
children: [...aChildren.slice(0, -1), mergedPara, ...bChildren.slice(1)]
};
}
return { ...a, children: [...aChildren, ...bChildren] };
@ -183,20 +185,20 @@ function stitchBlock(a: Root, b: AstContent[]) {
function stitchInlineAfterBlock(a: Root, b: GraphMentionNode[]) {
return {
...a,
children: [...a.children, { type: 'paragraph', children: b }],
children: [...a.children, { type: 'paragraph', children: b }]
};
}
function stitchAsts(asts: [StitchMode, GraphAstNode][]) {
return _.reduce(
asts.slice(1),
asts,
([prevMode, ast], [mode, val]): [StitchMode, GraphAstNode] => {
if (prevMode === 'block') {
if (mode === 'inline') {
return [mode, stitchInlineAfterBlock(ast, val?.children ?? [])];
}
if (mode === 'merge') {
return [mode, stitchBlock(ast, val?.children ?? [])];
return [mode, stitchMerge(ast, val)];
}
if (mode === 'block') {
return [mode, stitchBlock(ast, val?.children ?? [])];
@ -213,7 +215,7 @@ function stitchAsts(asts: [StitchMode, GraphAstNode][]) {
}
return [mode, ast];
},
asts[0]
['block', { type: 'root', children: [] }] as [StitchMode, GraphAstNode]
);
}
const header = ({ children, depth, ...rest }) => {
@ -234,7 +236,7 @@ const header = ({ children, depth, ...rest }) => {
const renderers = {
heading: header,
break: () => {
return <Box display="block" width="100%" height={2}></Box>;
return <br />;
},
thematicBreak: () => {
return <Box display="block" width="100%" height={2}></Box>;
@ -253,18 +255,13 @@ const renderers = {
);
},
strong: ({ children }) => {
return (
<Text fontWeight="bold" lineHeight="1">
{children}
</Text>
);
return <b>{children}</b>;
},
emphasis: ({ children }) => {
return (
<Text fontStyle="italic" fontSize={1} lineHeight="tall">
{children}
</Text>
);
return <i>{children}</i>;
},
delete: ({ children }) => {
return <del> {children}</del>;
},
blockquote: ({ children, depth, tall, ...rest }) => {
if (depth > 1) {
@ -278,8 +275,7 @@ const renderers = {
borderLeft="1px solid"
color="black"
paddingLeft={2}
py={1}
mb={1}
my={1}
>
{children}
</Text>
@ -287,29 +283,26 @@ const renderers = {
},
paragraph: ({ children }) => {
return (
<Text fontSize={1} lineHeight="tall">
{children}
</Text>
);
},
listItem: ({ children }) => {
return (
<Box position="relative" alignItems="center">
<Dot
top="7px"
position="absolute"
left="0px"
mr={1}
height="20px"
width="20px"
/>
<Box ml={2}>{children}</Box>
<Box display="block">
<Text fontSize={1} lineHeight="tall" style={{ 'overflowWrap': 'break-word' }}>
{children}
</Text>
</Box>
);
},
table: ({ children }) => <Table>{children}</Table>,
tableRow: ({ children }) => <Tr>{children}</Tr>,
tableCell: ({ children }) => (
<Td>
<Text fontSize="1" lineHeight="tall">
{children}
</Text>
</Td>
),
listItem: ({ children }) => {
return <Li>{children}</Li>;
},
code: ({ language, tall, value, ...rest }) => {
console.log(rest);
const inner = (
<Text
p={1}
@ -333,6 +326,8 @@ const renderers = {
display="inline"
href={props.url}
borderBottom="1"
fontSize="inherit"
fontWeight="inherit"
color="black"
target="_blank"
>
@ -340,34 +335,32 @@ const renderers = {
</Anchor>
);
},
list: ({ depth, children }) => {
return (
<Col ml={3} gapY={2} my={2}>
{children}
</Col>
);
list: ({ depth, ordered, children }) => {
return ordered ? <Ol>{children}</Ol> : <Ul>{children}</Ul>;
},
'graph-mention': ({ ship }) => <Mention api={{} as any} ship={ship} />,
image: ({ url }) => (
image: ({ url, tall }) => (
<Box mt="1" mb="2" flexShrink={0}>
<RemoteContent
// @ts-ignore RemoteContent weirdness
key={url} url={url}
key={url}
url={url}
tall={tall}
/>
</Box>
),
'graph-url': ({ url }) => (
'graph-url': ({ url, tall }) => (
<Box mt={1} mb={2} flexShrink={0}>
<RemoteContent
// @ts-ignore RemoteContent weirdness
key={url} url={url}
key={url}
url={url}
tall={tall}
/>
</Box>
),
'graph-reference': ({ api, reference, transcluded }) => {
const { link } = referenceToPermalink({ reference });
return (
<Box mb={2} flexShrink={0}>
<Box my={2} flexShrink={0}>
<PermalinkEmbed
api={api}
link={link}
@ -397,7 +390,7 @@ const renderers = {
</React.Fragment>
))}
</>
),
)
};
export function Graphdown<T extends {} = {}>(
@ -425,6 +418,7 @@ export function Graphdown<T extends {} = {}>(
key={idx}
transcluded={transcluded}
depth={depth + 1}
tall={tall}
{...rest}
ast={c}
/>
@ -433,21 +427,21 @@ export function Graphdown<T extends {} = {}>(
);
}
export const GraphContent = React.memo(function GraphContent(
props: {
tall?: boolean;
transcluded?: number;
contents: Content[];
api: GlobalApi;
showOurContact: boolean;
} & PropFunc<typeof Box>
) {
export type GraphContentProps = PropFunc<typeof Box> & {
tall?: boolean;
transcluded?: number;
contents: Content[];
api: GlobalApi;
showOurContact: boolean;
};
export const GraphContent = React.memo((
props: GraphContentProps
) => {
const {
post,
contents,
tall = false,
transcluded = 0,
showOurContact,
api,
...rest
} = props;

View File

@ -0,0 +1,124 @@
/** pulled from remark-parse
*
* critical change is that blockquotes require a newline to be continued, see
* the `if(!prefixed) conditional
*/
'use strict'
var trim = require('trim')
var interrupt = require('remark-parse/lib/util/interrupt')
module.exports = blockquote
var lineFeed = '\n'
var tab = '\t'
var space = ' '
var greaterThan = '>'
function blockquote(eat, value, silent) {
var self = this
var offsets = self.offset
var tokenizers = self.blockTokenizers
var interruptors = self.interruptBlockquote
var now = eat.now()
var currentLine = now.line
var length = value.length
var values = []
var contents = []
var indents = []
var add
var index = 0
var character
var rest
var nextIndex
var content
var line
var startIndex
var prefixed
var exit
while (index < length) {
character = value.charAt(index)
if (character !== space && character !== tab) {
break
}
index++
}
if (value.charAt(index) !== greaterThan) {
return
}
if (silent) {
return true
}
index = 0
while (index < length) {
nextIndex = value.indexOf(lineFeed, index)
startIndex = index
prefixed = false
if (nextIndex === -1) {
nextIndex = length
}
while (index < length) {
character = value.charAt(index)
if (character !== space && character !== tab) {
break
}
index++
}
if (value.charAt(index) === greaterThan) {
index++
prefixed = true
if (value.charAt(index) === space) {
index++
}
} else {
index = startIndex
}
content = value.slice(index, nextIndex)
if (!prefixed && !trim(content)) {
index = startIndex
break
}
if (!prefixed) {
break;
}
line = startIndex === index ? content : value.slice(startIndex, nextIndex)
indents.push(index - startIndex)
values.push(line)
contents.push(content)
index = nextIndex + 1
}
index = -1
length = indents.length
add = eat(values.join(lineFeed))
while (++index < length) {
offsets[currentLine] = (offsets[currentLine] || 0) + indents[index]
currentLine++
}
exit = self.enterBlock()
contents = self.tokenizeBlock(contents.join(lineFeed), now)
exit()
return add({type: 'blockquote', children: contents})
}

View File

@ -1,6 +1,14 @@
import remark from 'remark';
import RemarkDisableTokenizers from 'remark-disable-tokenizers';
import RemarkBreaks from 'remark-breaks';
import ResumeParse from './resume';
import newlines from './remark-break';
export interface ParserSettings {
inList: boolean;
inBlock: boolean;
inLink: boolean;
}
const DISABLED_BLOCK_TOKENS = [
'indentedCode',
@ -28,8 +36,7 @@ const wideParser = remark()
inline: DISABLED_INLINE_TOKENS,
},
],
RemarkBreaks,
newlines
])
.freeze();
export const parseWide = (text: string) => wideParser.parse(text);

View File

@ -0,0 +1,24 @@
import blockquote from './blockquote';
function lineBreak(eat, value: string, silent) {
let index = -1;
let character: string | null;
while(++index < length ) {
character = value.charAt(index);
if(character === '\n') {
eat(character)({ type : 'break' });
} else {
return;
}
}
}
lineBreak.locator = function(value, fromIndex) {
return value.indexOf('\n', fromIndex);
};
export default function plugin() {
this.Parser.prototype.blockTokenizers.break = lineBreak;
this.Parser.prototype.inlineTokenizers.break = lineBreak;
this.Parser.prototype.blockTokenizers.blockquote = blockquote;
}

View File

@ -0,0 +1,10 @@
export default function ResumeParse(settings) {
let parser = {};
function create() {
parser.current = this.Parser;
Object.assign(this.Parser, settings);
}
return [parser, create]
}

View File

@ -43,7 +43,7 @@ function RecentGroups(props: { recent: string[] }) {
</Box>
{props.recent.filter((e) => {
return (e in associations?.groups);
}).slice(1, 5).map((g) => {
}).slice(0, 4).map((g) => {
const assoc = associations.groups[g];
const color = uxToHex(assoc?.metadata?.color || '0x0');
return (

View File

@ -53,7 +53,9 @@ export function GroupsPane(props: GroupsPaneProps) {
if (workspace.type !== 'group') {
return;
}
setRecentGroups(gs => _.uniq([workspace.group, ...gs]));
return () => {
setRecentGroups(gs => _.uniq([workspace.group, ...gs]));
}
}, [workspace]);
if (!(associations && (groupPath ? groupPath in groups : true))) {

View File

@ -21,3 +21,9 @@ a * {
text-decoration-color: none;
text-decoration-line: none;
}
ol, ul {
margin-block-start: 0;
margin-block-end: 0;
}

View File

@ -25,9 +25,9 @@
"dev": true
},
"@types/lodash": {
"version": "4.14.168",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q=="
"version": "4.14.169",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.169.tgz",
"integrity": "sha512-DvmZHoHTFJ8zhVYwCLWbQ7uAbYQEk52Ev2/ZiQ7Y7gQGeV9pjBqjnQpECMHfKS1rCYAhMI7LHVxwyZLZinJgdw=="
},
"@urbit/eslint-config": {
"version": "1.0.0",

View File

@ -14,7 +14,15 @@ const rules = {
}
],
"arrow-spacing": "error",
"ban-ts-comment": "allow-with-description",
"@typescript-eslint/ban-ts-comment": [2,
{
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
'ts-check': 'allow-with-description',
minimumDescriptionLength: 3,
}],
"@typescript-eslint/ban-types": "off",
"block-spacing": ["error", "always"],
"brace-style": ["error", "1tbs"],
"camelcase": [
@ -25,6 +33,7 @@ const rules = {
],
"comma-dangle": ["error", "never"],
"eol-last": ["error", "always"],
"@typescript-eslint/explicit-module-boundary-types": "off",
"func-name-matching": "error",
"indent": [
"off",
@ -49,7 +58,7 @@ const rules = {
"handle-callback-err": "off",
"linebreak-style": ["error", "unix"],
"max-lines": [
"error",
"warn",
{
"max": 300,
"skipBlankLines": true,
@ -79,6 +88,8 @@ const rules = {
"new-parens": "error",
"no-buffer-constructor": "error",
"no-console": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off",
"no-extra-semi": "off",
"no-fallthrough": "off",
"no-func-assign": "off",
@ -90,7 +101,7 @@ const rules = {
"max": 1
}
],
"no-nested-ternary": "error",
"no-nested-ternary": "warn",
"no-param-reassign": "off",
"no-return-assign": "error",
"no-return-await": "off",
@ -129,6 +140,7 @@ const rules = {
],
"prefer-template": "off",
"quotes": ["error", "single"],
"react/display-name": "off",
"semi": ["error", "always"],
"spaced-comment": [
"error",

File diff suppressed because it is too large Load Diff

View File

@ -13,13 +13,11 @@
},
"author": "",
"license": "MIT",
"peerDependencies": {
"eslint": ">= 3"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.15.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.26.0",
"eslint-plugin-react": "^7.22.0",
"typescript": "^4.1.5"
}

View File

@ -20,20 +20,20 @@
"dev": true
},
"@babel/core": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.0.tgz",
"integrity": "sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.3.tgz",
"integrity": "sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.0",
"@babel/generator": "^7.14.3",
"@babel/helper-compilation-targets": "^7.13.16",
"@babel/helper-module-transforms": "^7.14.0",
"@babel/helper-module-transforms": "^7.14.2",
"@babel/helpers": "^7.14.0",
"@babel/parser": "^7.14.0",
"@babel/parser": "^7.14.3",
"@babel/template": "^7.12.13",
"@babel/traverse": "^7.14.0",
"@babel/types": "^7.14.0",
"@babel/traverse": "^7.14.2",
"@babel/types": "^7.14.2",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@ -43,12 +43,12 @@
}
},
"@babel/generator": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz",
"integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==",
"dev": true,
"requires": {
"@babel/types": "^7.14.1",
"@babel/types": "^7.14.2",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
@ -75,28 +75,28 @@
}
},
"@babel/helper-create-class-features-plugin": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.1.tgz",
"integrity": "sha512-r8rsUahG4ywm0QpGcCrLaUSOuNAISR3IZCg4Fx05Ozq31aCUrQsTLH6KPxy0N5ULoQ4Sn9qjNdGNtbPWAC6hYg==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.3.tgz",
"integrity": "sha512-BnEfi5+6J2Lte9LeiL6TxLWdIlEv9Woacc1qXzXBgbikcOzMRM2Oya5XGg/f/ngotv1ej2A/b+3iJH8wbS1+lQ==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.12.13",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-function-name": "^7.14.2",
"@babel/helper-member-expression-to-functions": "^7.13.12",
"@babel/helper-optimise-call-expression": "^7.12.13",
"@babel/helper-replace-supers": "^7.13.12",
"@babel/helper-replace-supers": "^7.14.3",
"@babel/helper-split-export-declaration": "^7.12.13"
}
},
"@babel/helper-function-name": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
"integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.12.13",
"@babel/template": "^7.12.13",
"@babel/types": "^7.12.13"
"@babel/types": "^7.14.2"
}
},
"@babel/helper-get-function-arity": {
@ -127,9 +127,9 @@
}
},
"@babel/helper-module-transforms": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz",
"integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz",
"integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.13.12",
@ -138,8 +138,8 @@
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/template": "^7.12.13",
"@babel/traverse": "^7.14.0",
"@babel/types": "^7.14.0"
"@babel/traverse": "^7.14.2",
"@babel/types": "^7.14.2"
}
},
"@babel/helper-optimise-call-expression": {
@ -158,15 +158,15 @@
"dev": true
},
"@babel/helper-replace-supers": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz",
"integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.3.tgz",
"integrity": "sha512-Rlh8qEWZSTfdz+tgNV/N4gz1a0TMNwCUcENhMjHTHKp3LseYH5Jha0NSlyTQWMnjbYcwFt+bqAMqSLHVXkQ6UA==",
"dev": true,
"requires": {
"@babel/helper-member-expression-to-functions": "^7.13.12",
"@babel/helper-optimise-call-expression": "^7.12.13",
"@babel/traverse": "^7.13.0",
"@babel/types": "^7.13.12"
"@babel/traverse": "^7.14.2",
"@babel/types": "^7.14.2"
}
},
"@babel/helper-simple-access": {
@ -231,9 +231,9 @@
}
},
"@babel/parser": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==",
"dev": true
},
"@babel/plugin-proposal-class-properties": {
@ -247,22 +247,22 @@
}
},
"@babel/plugin-proposal-object-rest-spread": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz",
"integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz",
"integrity": "sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.13.8",
"@babel/helper-compilation-targets": "^7.13.8",
"@babel/compat-data": "^7.14.0",
"@babel/helper-compilation-targets": "^7.13.16",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-transform-parameters": "^7.13.0"
"@babel/plugin-transform-parameters": "^7.14.2"
}
},
"@babel/plugin-proposal-optional-chaining": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz",
"integrity": "sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz",
"integrity": "sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.13.0",
@ -298,21 +298,21 @@
}
},
"@babel/plugin-transform-parameters": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz",
"integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz",
"integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.13.0"
}
},
"@babel/plugin-transform-typescript": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz",
"integrity": "sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.3.tgz",
"integrity": "sha512-G5Bb5pY6tJRTC4ag1visSgiDoGgJ1u1fMUgmc2ijLkcIdzP83Q1qyZX4ggFQ/SkR+PNOatkaYC+nKcTlpsX4ag==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.13.0",
"@babel/helper-create-class-features-plugin": "^7.14.3",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/plugin-syntax-typescript": "^7.12.13"
}
@ -348,25 +348,25 @@
}
},
"@babel/traverse": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz",
"integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.0",
"@babel/helper-function-name": "^7.12.13",
"@babel/generator": "^7.14.2",
"@babel/helper-function-name": "^7.14.2",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.0",
"@babel/types": "^7.14.0",
"@babel/parser": "^7.14.2",
"@babel/types": "^7.14.2",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
@ -417,10 +417,13 @@
}
},
"@types/anymatch": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
"dev": true
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-3.0.0.tgz",
"integrity": "sha512-qLChUo6yhpQ9k905NwL74GU7TxH+9UODwwQ6ICNI+O6EDMExqH/Cv9NsbmcZ7yC/rRXJ/AHCzfgjsFRY5fKjYw==",
"dev": true,
"requires": {
"anymatch": "*"
}
},
"@types/browser-or-node": {
"version": "1.3.0",
@ -483,9 +486,9 @@
"dev": true
},
"@types/node": {
"version": "15.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz",
"integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==",
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz",
"integrity": "sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==",
"dev": true
},
"@types/prop-types": {
@ -582,13 +585,13 @@
}
},
"@typescript-eslint/eslint-plugin": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz",
"integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.24.0.tgz",
"integrity": "sha512-qbCgkPM7DWTsYQGjx9RTuQGswi+bEt0isqDBeo+CKV0953zqI0Tp7CZ7Fi9ipgFA6mcQqF4NOVNwS/f2r6xShw==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "4.22.1",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/experimental-utils": "4.24.0",
"@typescript-eslint/scope-manager": "4.24.0",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"lodash": "^4.17.15",
@ -609,55 +612,55 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz",
"integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.24.0.tgz",
"integrity": "sha512-IwTT2VNDKH1h8RZseMH4CcYBz6lTvRoOLDuuqNZZoThvfHEhOiZPQCow+5El3PtyxJ1iDr6UXZwYtE3yZQjhcw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.24.0",
"@typescript-eslint/types": "4.24.0",
"@typescript-eslint/typescript-estree": "4.24.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz",
"integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.24.0.tgz",
"integrity": "sha512-dj1ZIh/4QKeECLb2f/QjRwMmDArcwc2WorWPRlB8UNTZlY1KpTVsbX7e3ZZdphfRw29aTFUSNuGB8w9X5sS97w==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.24.0",
"@typescript-eslint/types": "4.24.0",
"@typescript-eslint/typescript-estree": "4.24.0",
"debug": "^4.1.1"
}
},
"@typescript-eslint/scope-manager": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz",
"integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.24.0.tgz",
"integrity": "sha512-9+WYJGDnuC9VtYLqBhcSuM7du75fyCS/ypC8c5g7Sdw7pGL4NDTbeH38eJPfzIydCHZDoOgjloxSAA3+4l/zsA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1"
"@typescript-eslint/types": "4.24.0",
"@typescript-eslint/visitor-keys": "4.24.0"
}
},
"@typescript-eslint/types": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz",
"integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.24.0.tgz",
"integrity": "sha512-tkZUBgDQKdvfs8L47LaqxojKDE+mIUmOzdz7r+u+U54l3GDkTpEbQ1Jp3cNqqAU9vMUCBA1fitsIhm7yN0vx9Q==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz",
"integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.24.0.tgz",
"integrity": "sha512-kBDitL/by/HK7g8CYLT7aKpAwlR8doshfWz8d71j97n5kUa5caHWvY0RvEUEanL/EqBJoANev8Xc/mQ6LLwXGA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1",
"@typescript-eslint/types": "4.24.0",
"@typescript-eslint/visitor-keys": "4.24.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-glob": "^4.0.1",
@ -677,12 +680,12 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz",
"integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==",
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.24.0.tgz",
"integrity": "sha512-4ox1sjmGHIxjEDBnMCtWFFhErXtKA1Ec0sBpuz0fqf3P+g3JFGyTxxbF06byw0FRsPnnbq44cKivH7Ks1/0s6g==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/types": "4.24.0",
"eslint-visitor-keys": "^2.0.0"
}
},
@ -699,34 +702,232 @@
"dependencies": {
"@babel/runtime": {
"version": "7.14.0",
"bundled": true,
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@blakeembrey/deque": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@blakeembrey/deque/-/deque-1.0.5.tgz",
"integrity": "sha512-6xnwtvp9DY1EINIKdTfvfeAtCYw4OqBZJhtiqkT3ivjnEfa25VQ3TsKvaFfKm8MyGIEfE95qLe+bNEt3nB0Ylg=="
},
"@blakeembrey/template": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@blakeembrey/template/-/template-1.0.0.tgz",
"integrity": "sha512-J6WGZqCLdRMHUkyRG6fBSIFJ0rL60/nsQNh5rQvsYZ5u0PsKw6XQcJcA3DWvd9cN3j/IQx5yB1fexhCafwwUUw=="
},
"@types/lodash": {
"version": "4.14.168",
"bundled": true
"version": "4.14.169",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.169.tgz",
"integrity": "sha512-DvmZHoHTFJ8zhVYwCLWbQ7uAbYQEk52Ev2/ZiQ7Y7gQGeV9pjBqjnQpECMHfKS1rCYAhMI7LHVxwyZLZinJgdw=="
},
"@urbit/eslint-config": {
"version": "1.0.0",
"bundled": true
"resolved": "https://registry.npmjs.org/@urbit/eslint-config/-/eslint-config-1.0.0.tgz",
"integrity": "sha512-Xmzb6MvM7KorlPJEq/hURZZ4BHSVy/7CoQXWogsBSTv5MOZnMqwNKw6yt24k2AO/2UpHwjGptimaNLqFfesJbw=="
},
"anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
},
"big-integer": {
"version": "1.6.48",
"bundled": true
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
},
"ignore": {
"version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
},
"immer": {
"version": "9.0.2",
"bundled": true
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.2.tgz",
"integrity": "sha512-mkcmzLtIfSp40vAqteRr1MbWNSoI7JE+/PB36FNPoSfJ9RQRmNKuTYCjKkyXyuq3Dgn07HuJBrwJd4ZSk2yUbw=="
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"lodash": {
"version": "4.17.21",
"bundled": true
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"onchange": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/onchange/-/onchange-7.1.0.tgz",
"integrity": "sha512-ZJcqsPiWUAUpvmnJri5TPBooqJOPmC0ttN65juhN15Q8xA+Nbg3BaxBHXQ45EistKKlKElb0edmbPWnKSBkvMg==",
"requires": {
"@blakeembrey/deque": "^1.0.5",
"@blakeembrey/template": "^1.0.0",
"arg": "^4.1.3",
"chokidar": "^3.3.1",
"cross-spawn": "^7.0.1",
"ignore": "^5.1.4",
"tree-kill": "^1.2.2"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"picomatch": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
"integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg=="
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"requires": {
"picomatch": "^2.2.1"
}
},
"regenerator-runtime": {
"version": "0.13.7",
"bundled": true
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
},
"tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
}
}
},
@ -1333,9 +1534,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001222",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001222.tgz",
"integrity": "sha512-rPmwUK0YMjfMlZVmH6nVB5U3YJ5Wnx3vmT5lnRO3nIKO8bJ+TRWMbGuuiSugDJqESy/lz+1hSrlQEagCtoOAWQ==",
"version": "1.0.30001228",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
"dev": true
},
"chalk": {
@ -1765,9 +1966,9 @@
"dev": true
},
"detect-node": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.5.tgz",
"integrity": "sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true
},
"dir-glob": {
@ -1811,9 +2012,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.3.727",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.727.tgz",
"integrity": "sha512-Mfz4FIB4FSvEwBpDfdipRIrwd6uo8gUDoRDF4QEYb4h4tSuI3ov594OrjU6on042UlFHouIJpClDODGkPcBSbg==",
"version": "1.3.730",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.730.tgz",
"integrity": "sha512-1Tr3h09wXhmqXnvDyrRe6MFgTeU0ZXy3+rMJWTrOHh/HNesWwBBrKnMxRJWZ86dzs8qQdw2c7ZE1/qeGHygImA==",
"dev": true
},
"emoji-regex": {
@ -1844,9 +2045,9 @@
}
},
"enhanced-resolve": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.0.tgz",
"integrity": "sha512-Sl3KRpJA8OpprrtaIswVki3cWPiPKxXuFxJXBp+zNb6s6VwNWwFRUdtmzd2ReUut8n+sCPx7QCtQ7w5wfJhSgQ==",
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz",
"integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==",
"dev": true,
"requires": {
"graceful-fs": "^4.2.4",
@ -2513,9 +2714,9 @@
}
},
"follow-redirects": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.0.tgz",
"integrity": "sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"dev": true
},
"for-in": {
@ -2615,9 +2816,9 @@
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
@ -3210,12 +3411,12 @@
}
},
"is-boolean-object": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
"integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
"dev": true,
"requires": {
"call-bind": "^1.0.0"
"call-bind": "^1.0.2"
}
},
"is-buffer": {
@ -3251,9 +3452,9 @@
}
},
"is-date-object": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.3.tgz",
"integrity": "sha512-tDpEUInNcy2Yw3lNSepK3Wdw1RnXLcIVienz6Ou631Acl15cJyRWK4dgA1vCmOEgIbtOV0W7MHg+AR2Gdg1NXQ==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
"integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
"dev": true
},
"is-descriptor": {
@ -3294,9 +3495,9 @@
"dev": true
},
"is-generator-function": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz",
"integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==",
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==",
"dev": true
},
"is-glob": {
@ -3321,9 +3522,9 @@
"dev": true
},
"is-number-object": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
"integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
"dev": true
},
"is-path-cwd": {
@ -3360,13 +3561,13 @@
}
},
"is-regex": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
"integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-symbols": "^1.0.1"
"has-symbols": "^1.0.2"
}
},
"is-stream": {
@ -3376,18 +3577,18 @@
"dev": true
},
"is-string": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
"integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
"dev": true
},
"is-symbol": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"requires": {
"has-symbols": "^1.0.1"
"has-symbols": "^1.0.2"
}
},
"is-typed-array": {
@ -3826,9 +4027,9 @@
"dev": true
},
"node-releases": {
"version": "1.1.71",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz",
"integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==",
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
"dev": true
},
"normalize-path": {
@ -3892,9 +4093,9 @@
}
},
"object-inspect": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz",
"integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==",
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
"integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
"dev": true
},
"object-is": {
@ -5059,9 +5260,9 @@
}
},
"terser-webpack-plugin": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz",
"integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.2.tgz",
"integrity": "sha512-6QhDaAiVHIQr5Ab3XUWZyDmrIPCHMiqJVljMF91YKyqwKkL5QHnYMkrMBy96v9Z7ev1hGhSEw1HQZc2p/s5Z8Q==",
"dev": true,
"requires": {
"jest-worker": "^26.6.2",
@ -5069,7 +5270,7 @@
"schema-utils": "^3.0.0",
"serialize-javascript": "^5.0.1",
"source-map": "^0.6.1",
"terser": "^5.5.1"
"terser": "^5.7.0"
},
"dependencies": {
"p-limit": {
@ -5392,9 +5593,9 @@
}
},
"webpack": {
"version": "5.36.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.36.2.tgz",
"integrity": "sha512-XJumVnnGoH2dV+Pk1VwgY4YT6AiMKpVoudUFCNOXMIVrEKPUgEwdIfWPjIuGLESAiS8EdIHX5+TiJz/5JccmRg==",
"version": "5.37.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.37.0.tgz",
"integrity": "sha512-yvdhgcI6QkQkDe1hINBAJ1UNevqNGTVaCkD2SSJcB8rcrNNl922RI8i2DXUAuNfANoxwsiXXEA4ZPZI9q2oGLA==",
"dev": true,
"requires": {
"@types/eslint-scope": "^3.7.0",