aontu 0.62.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/agentsmd.js +0 -27
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.js +0 -92
- package/dist/allow.js.map +1 -1
- package/dist/aontu.d.ts +3 -3
- package/dist/aontu.js +4 -84
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +27 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/casing.d.ts +5 -0
- package/dist/casing.js +90 -0
- package/dist/casing.js.map +1 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +228 -935
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +13 -203
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.js +2 -2
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +57 -55
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +17 -915
- package/dist/lang.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -149
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +16 -131
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/profile.d.ts +9 -0
- package/dist/profile.js +28 -0
- package/dist/profile.js.map +1 -0
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.js +0 -61
- package/dist/relation.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trace.d.ts +21 -0
- package/dist/trace.js +107 -0
- package/dist/trace.js.map +1 -0
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +13 -248
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.d.ts +2 -0
- package/dist/val/CmpFuncVal.js +49 -72
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.js +0 -3
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +0 -11
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +0 -60
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +18 -54
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +3 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.js +1 -3
- package/dist/val/TranslateFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +0 -11
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.js +0 -61
- package/dist/val/caserange.js.map +1 -1
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.js +0 -461
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +8 -6
- package/grammar/aontu.gbnf +4 -4
- package/grammar/aontu.lark +4 -4
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/skill/tasks.md +9 -7
- package/src/agentsmd.ts +0 -35
- package/src/alias.ts +0 -39
- package/src/allow.ts +1 -96
- package/src/aontu.ts +4 -116
- package/src/aontumodel.ts +26 -0
- package/src/casing.ts +95 -0
- package/src/cli.ts +258 -1024
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +14 -257
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +2 -2
- package/src/hints.ts +69 -57
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +19 -931
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -169
- package/src/mod-tool.ts +18 -159
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/profile.ts +42 -0
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +0 -84
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trace.ts +157 -0
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +14 -257
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +68 -184
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +0 -40
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +0 -12
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +0 -60
- package/src/val/NomFuncVal.ts +10 -99
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +4 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +1 -51
- package/src/val/UpperFuncVal.ts +0 -12
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +0 -62
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +1 -582
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/lower.d.ts +0 -23
- package/dist/lower.js +0 -578
- package/dist/lower.js.map +0 -1
- package/dist/render.d.ts +0 -53
- package/dist/render.js +0 -547
- package/dist/render.js.map +0 -1
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -672
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/dist/val/NamerFuncVal.d.ts +0 -12
- package/dist/val/NamerFuncVal.js +0 -176
- package/dist/val/NamerFuncVal.js.map +0 -1
- package/src/lower.ts +0 -636
- package/src/render.ts +0 -732
- package/src/std.ts +0 -683
package/src/view.ts
CHANGED
|
@@ -1,45 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// THE VIEWS (docs/design/VIEWS.0.md and VIEWS-ORDER.0.md): figures of
|
|
4
|
-
// an evaluated document, drawn as deterministic text a golden diff can
|
|
5
|
-
// check. Nine kinds:
|
|
6
|
-
//
|
|
7
|
-
// doc the shape of the document itself
|
|
8
|
-
// lattice the language's value lattice, with the document's own
|
|
9
|
-
// values placed on it
|
|
10
|
-
// tree the dependency tree of one relation
|
|
11
|
-
// matrix the dependency matrix over one relation, in canon or
|
|
12
|
-
// partition order, with closure and the unmirrored mark
|
|
13
|
-
// graph the node-link drawing, as Mermaid, DOT or an ER diagram
|
|
14
|
-
// layer the architecture layers: stacked bands, one per value of
|
|
15
|
-
// a field, with the relation's upward edges called out
|
|
16
|
-
// sets the set-intersection panel over a named set family
|
|
17
|
-
// layers which document contributed which path (provenance)
|
|
18
|
-
// ladder the meet ladder at one path (the `why` record, drawn)
|
|
19
|
-
// poset the subsumption order over a set of documents
|
|
20
|
-
//
|
|
21
|
-
// A view consumes a REPORT, never the Val tree: the edge set `graphOf`
|
|
22
|
-
// derives (ts/src/graph.ts), the relation declarations, the generated
|
|
23
|
-
// value, the provenance record, the subsumption verdict. That is what
|
|
24
|
-
// keeps the two ports at parity -- Go's exported Val interface is five
|
|
25
|
-
// methods, and a Val-walking view would be TypeScript-only on the day
|
|
26
|
-
// it landed.
|
|
27
|
-
//
|
|
28
|
-
// Everything here is deterministic: nodes and edges are sorted by code
|
|
29
|
-
// point before emission, nothing iterates a map in insertion order, no
|
|
30
|
-
// coordinate is computed and no number is formatted beyond its decimal
|
|
31
|
-
// digits. The Go twin is go/view.go; what the two ports must agree on
|
|
32
|
-
// -- the rendered text, the loss report and the refusals -- is
|
|
33
|
-
// test/spec/view.tsv.
|
|
34
|
-
//
|
|
35
|
-
// EVERY RUN CARRIES A LOSS REPORT: what the figure could not draw, or
|
|
36
|
-
// drew differently from the model, aggregated by code with a count.
|
|
37
|
-
// Three codes are informational -- `edges_deduped` (several written
|
|
38
|
-
// positions, one fact), `inverse_suppressed` (a declared mirror,
|
|
39
|
-
// implied by the edge drawn) and `crossings` (a property of the
|
|
40
|
-
// emitted order, not of the model) -- and leave the verdict `rendered`. Every
|
|
41
|
-
// other code makes it `lossy`, which `--strict` refuses: a figure that
|
|
42
|
-
// quietly omits things is the failure this capability exists to avoid.
|
|
43
3
|
|
|
44
4
|
import { basename, dirname, isAbsolute, relative, resolve } from 'node:path'
|
|
45
5
|
|
|
@@ -71,52 +31,14 @@ export type ViewProfile = 'text' | 'mermaid' | 'dot' | 'er' | 'svg'
|
|
|
71
31
|
|
|
72
32
|
export type ViewOrder = 'canon' | 'partition'
|
|
73
33
|
|
|
74
|
-
// Which of the relation's edges the layer figure DRAWS. The bands
|
|
75
|
-
// already say which way every edge goes, so the default shows the ones
|
|
76
|
-
// that break the rule: `upward`. `all` draws the relation over the
|
|
77
|
-
// bands -- what a reader tracing one module's dependencies wants --
|
|
78
|
-
// and `none` leaves the bands alone. The default is `all` for a
|
|
79
|
-
// profile that lays edges out itself (mermaid) and `upward` for the
|
|
80
|
-
// fixed grids (text, svg), which is what each drew before the option
|
|
81
|
-
// existed.
|
|
82
34
|
export type ViewEdges = 'upward' | 'all' | 'none'
|
|
83
35
|
|
|
84
|
-
// STYLING (VIEWS.0.md, "7. Styling"), which amends that note's colour
|
|
85
|
-
// boundary. Every mark a figure makes already has a reason the
|
|
86
|
-
// extractor established -- a cell is `direct` because the edge is
|
|
87
|
-
// declared, an arrow is `upward` because it runs against the bands --
|
|
88
|
-
// and the SVG profile has published those reasons as classes since it
|
|
89
|
-
// landed, because an SVG cannot be drawn without saying what each
|
|
90
|
-
// shape is. This declares the same vocabulary for the text profile and
|
|
91
|
-
// adds the one thing missing: a way to turn it on at the call.
|
|
92
|
-
//
|
|
93
|
-
// NEITHER MECHANISM STATES A COLOUR, which is what keeps the boundary
|
|
94
|
-
// intact. SGR 31 does not mean red; it means the colour the reader's
|
|
95
|
-
// terminal calls red, which the reader chose. A CSS class states
|
|
96
|
-
// nothing at all, and the stylesheet reads `var(--av-closure, ...)` so
|
|
97
|
-
// a host page's palette wins. A hex triple is the thing that cannot
|
|
98
|
-
// follow a theme, and it stays refused -- no truecolour escape, no
|
|
99
|
-
// 256-colour escape, no `classDef`.
|
|
100
36
|
export type ViewRole =
|
|
101
37
|
'label' | 'muted' | 'rule' | 'direct' | 'closure' | 'unmirrored'
|
|
102
38
|
| 'upward' | 'repeat' | 'bar' | 'hole'
|
|
103
39
|
|
|
104
|
-
// `none` is plain characters, and an SVG carrying its classes but not
|
|
105
|
-
// the embedded stylesheet -- what a host page wants once it has bound
|
|
106
|
-
// the variables and is embedding eight figures. `ansi` is the text
|
|
107
|
-
// profile's mechanism and `css` the SVG's; asking for either on the
|
|
108
|
-
// wrong profile is a usage error.
|
|
109
|
-
//
|
|
110
|
-
// `auto` IS NOT HERE ON PURPOSE. Resolving it means knowing whether
|
|
111
|
-
// the destination is a terminal, which err.ts already settles for the
|
|
112
|
-
// error frames: a library cannot see its destination and a caller who
|
|
113
|
-
// can is the only one who may decide. The CLI maps `auto`; `viewOf`
|
|
114
|
-
// takes a resolved value, so every shared-spec row is deterministic.
|
|
115
40
|
export type ViewStyle = 'none' | 'ansi' | 'css'
|
|
116
41
|
|
|
117
|
-
// The text profile's mechanism: the eight named colours, `bold` and
|
|
118
|
-
// `dim`, and nothing else. `label` is unstyled -- an entity's own name
|
|
119
|
-
// is the figure's content, not a mark about it.
|
|
120
42
|
const SGR: Record<ViewRole, string> = {
|
|
121
43
|
label: '', muted: '2', rule: '2', direct: '1', closure: '36',
|
|
122
44
|
unmirrored: '33', upward: '31', repeat: '2', bar: '36', hole: '2',
|
|
@@ -135,10 +57,6 @@ const ANSI: Paint = (role, text) =>
|
|
|
135
57
|
|
|
136
58
|
const painter = (style: ViewStyle): Paint => 'ansi' === style ? ANSI : PLAIN
|
|
137
59
|
|
|
138
|
-
// The style a figure gets when the caller named none. An SVG carries
|
|
139
|
-
// its stylesheet, which is what makes it standalone and what every
|
|
140
|
-
// pinned golden holds; everything else carries no mechanism, since a
|
|
141
|
-
// library cannot see whether its output is a terminal.
|
|
142
60
|
const styleOf = (
|
|
143
61
|
style: ViewStyle | undefined, as: ViewProfile
|
|
144
62
|
): ViewStyle => style ?? ('svg' === as ? 'css' : 'none')
|
|
@@ -205,7 +123,6 @@ export type ViewSetReport = {
|
|
|
205
123
|
|
|
206
124
|
|
|
207
125
|
export type ViewOptions = {
|
|
208
|
-
// The figure to draw. Absent means `tree`.
|
|
209
126
|
kind?: ViewKind
|
|
210
127
|
// The target grammar. Absent means the kind's first profile.
|
|
211
128
|
as?: ViewProfile
|
|
@@ -215,20 +132,11 @@ export type ViewOptions = {
|
|
|
215
132
|
// The include capability this document evaluates under
|
|
216
133
|
// (docs/trust.md).
|
|
217
134
|
trust?: TrustOptions
|
|
218
|
-
// The extensions an include additionally reads as text (the CLI's
|
|
219
|
-
// --text-ext). It rides WITH the capability everywhere, never beside
|
|
220
|
-
// it: both answer "what may an include read", and a verb that
|
|
221
|
-
// threads one and not the other refuses under a flag the bare
|
|
222
|
-
// command honours -- which is exactly what this verb did.
|
|
223
135
|
textExt?: string[]
|
|
224
136
|
// Restrict the figure to nodes (or paths) under this path. For the
|
|
225
137
|
// ladder it is the path drawn, and required; for the poset it is
|
|
226
138
|
// where the documents are compared.
|
|
227
139
|
at?: string
|
|
228
|
-
// Refuse a figure with more than this many rows (matrix rows, graph
|
|
229
|
-
// and tree nodes, set rows, poset nodes, ladder rungs). Absent means
|
|
230
|
-
// sixty. A REFUSAL, not a truncation: a view that quietly omits
|
|
231
|
-
// things is the failure this capability exists to avoid.
|
|
232
140
|
maxRows?: number
|
|
233
141
|
|
|
234
142
|
// tree, matrix: draw OVER THIS RELATION. The tree draws every
|
|
@@ -268,7 +176,6 @@ export type ViewOptions = {
|
|
|
268
176
|
// means three, which is the depth at which a model's shape is
|
|
269
177
|
// legible and its data is not yet enumerated.
|
|
270
178
|
depth?: number
|
|
271
|
-
// sets: drop intersections below this degree.
|
|
272
179
|
minDegree?: number
|
|
273
180
|
// sets, layers: elide columns beyond this many, counted in the loss
|
|
274
181
|
// report.
|
|
@@ -286,12 +193,6 @@ export type ViewOptions = {
|
|
|
286
193
|
// document, only once every figure of the set rendered.
|
|
287
194
|
out?: string
|
|
288
195
|
|
|
289
|
-
// How the figure is styled (VIEWS.0.md, "7. Styling"). Absent means
|
|
290
|
-
// `none`: plain characters, and an SVG carrying its classes without
|
|
291
|
-
// the embedded stylesheet. THE CALLER RESOLVES `auto` -- see
|
|
292
|
-
// ViewStyle. A figure written to a file is written plain whatever
|
|
293
|
-
// this says, which the CLI enforces: a pinned golden with terminal
|
|
294
|
-
// escapes in it is not a golden anybody can read.
|
|
295
196
|
style?: ViewStyle
|
|
296
197
|
|
|
297
198
|
// The VIEW DOCUMENT (VIEWS.0.md, "6. The view document"): the path of
|
|
@@ -352,11 +253,6 @@ function finding(
|
|
|
352
253
|
}
|
|
353
254
|
|
|
354
255
|
|
|
355
|
-
// A relation that draws nothing is a typo, and is refused for the same
|
|
356
|
-
// reason a misspelled root is: an empty figure and a misspelled name
|
|
357
|
-
// are the same file on disk, so the one that means nothing must not be
|
|
358
|
-
// renderable. NOT `refer_unresolved`: a relation name is not an
|
|
359
|
-
// address.
|
|
360
256
|
function relationFinding(relation: string, have: string[]): VetFinding {
|
|
361
257
|
return finding('view_relation_unknown', 'reference', '$',
|
|
362
258
|
`${relation} names no relation with edges in this document.`,
|
|
@@ -364,10 +260,6 @@ function relationFinding(relation: string, have: string[]): VetFinding {
|
|
|
364
260
|
}
|
|
365
261
|
|
|
366
262
|
|
|
367
|
-
// A root is a node of the DRAWN graph, the rule the node set follows:
|
|
368
|
-
// a path that exists in the document but takes no part in the relation
|
|
369
|
-
// is not in the drawing, and a root naming it is refused rather than
|
|
370
|
-
// drawn as an empty tree.
|
|
371
263
|
function rootFinding(
|
|
372
264
|
root: string, relation: string | undefined, nodes: string[]): VetFinding {
|
|
373
265
|
return finding('refer_unresolved', 'reference', '$',
|
|
@@ -412,20 +304,6 @@ function under(path: string, at: string | undefined): boolean {
|
|
|
412
304
|
}
|
|
413
305
|
|
|
414
306
|
|
|
415
|
-
// The deduplicated edge set, with the hidden contributions and the
|
|
416
|
-
// out-of-scope edges removed and the loss report told.
|
|
417
|
-
//
|
|
418
|
-
// `graphOf` emits one edge per WRITTEN POSITION by design, because each
|
|
419
|
-
// `at` is an editable site, and an identity-merged model declares each
|
|
420
|
-
// entity at two positions. Deduplication is part of the extraction
|
|
421
|
-
// contract, not a renderer's private cleverness, and the count is
|
|
422
|
-
// reported so nobody has to guess which number they are looking at.
|
|
423
|
-
//
|
|
424
|
-
// A HIDDEN edge -- one written inside a `hide()`-marked subtree -- is
|
|
425
|
-
// not drawn. A figure is committed to a repository, so anything drawn
|
|
426
|
-
// is disclosed, and the subtree's whole purpose is to say "not
|
|
427
|
-
// output". It is reported with its path instead, and `--strict`
|
|
428
|
-
// refuses the figure.
|
|
429
307
|
function triplesOf(
|
|
430
308
|
graph: Graph, at: string | undefined, loss: ViewLoss[]): Triple[] {
|
|
431
309
|
const edges = graph.edges
|
|
@@ -450,10 +328,6 @@ function triplesOf(
|
|
|
450
328
|
detail: hidden.sort(cmpCodePoint),
|
|
451
329
|
})
|
|
452
330
|
}
|
|
453
|
-
// A link under an UNRESOLVED DISJUNCTION is not an edge (ADR-007),
|
|
454
|
-
// and the figure says so rather than dropping it in silence: the
|
|
455
|
-
// document has not decided, and a drawing that quietly picked an arm
|
|
456
|
-
// would be inventing the decision.
|
|
457
331
|
const undecided = (graph.disjunct ?? []).filter((p) => under(p, at))
|
|
458
332
|
if (0 < undecided.length) {
|
|
459
333
|
loss.push({
|
|
@@ -491,21 +365,6 @@ function nodesOf(triples: { from: string, to: string }[]): string[] {
|
|
|
491
365
|
}
|
|
492
366
|
|
|
493
367
|
|
|
494
|
-
// THE SHORTEST SUFFIX THAT IS STILL UNIQUE, as a node's visible label.
|
|
495
|
-
//
|
|
496
|
-
// A node's name IS its path (ADR-014), and the paths in a real model
|
|
497
|
-
// are long: eight nodes labelled `$.catalog.domains.identity.services.auth`
|
|
498
|
-
// and its siblings is a correct diagram nobody can read. The label is
|
|
499
|
-
// therefore the fewest trailing segments that still tell this node from
|
|
500
|
-
// every other in the same drawing -- `auth` where that is unambiguous,
|
|
501
|
-
// `identity.auth` where it is not.
|
|
502
|
-
//
|
|
503
|
-
// The rule is a function of the node SET, so a drawing is deterministic
|
|
504
|
-
// while two drawings of different slices may label the same node
|
|
505
|
-
// differently -- which is correct, because uniqueness is a property of
|
|
506
|
-
// the set being drawn. The search is unbounded on purpose: at the full
|
|
507
|
-
// segment count the candidate is the whole path, which no other node
|
|
508
|
-
// shares, so it always ends.
|
|
509
368
|
function labelsOf(nodes: string[]): Map<string, string> {
|
|
510
369
|
const segs = new Map<string, string[]>(
|
|
511
370
|
nodes.map((n) => [n, n.replace(/^\$\.?/, '').split('.')]))
|
|
@@ -568,13 +427,6 @@ const widest = (ss: string[]): number =>
|
|
|
568
427
|
// ---------------------------------------------------------------------
|
|
569
428
|
// Identifiers and escapes (VIEWS.0.md, "The renderers and the profiles")
|
|
570
429
|
|
|
571
|
-
// Injective by construction, with two disjoint prefixes and one
|
|
572
|
-
// predicate: `n_` + the name when its first code point is an ASCII
|
|
573
|
-
// letter and every code point is an ASCII letter, digit or `_`;
|
|
574
|
-
// otherwise `nq_` + the name with every other code point replaced by
|
|
575
|
-
// `_` and its lower-case hex. A code-point class test, not a regular
|
|
576
|
-
// expression: pattern matching is the one subsystem with a stated
|
|
577
|
-
// RE2-versus-RegExp divergence, and an encoder runs on every name.
|
|
578
430
|
function ident(name: string): string {
|
|
579
431
|
const letter = (c: number): boolean =>
|
|
580
432
|
(65 <= c && c <= 90) || (97 <= c && c <= 122)
|
|
@@ -594,11 +446,6 @@ function ident(name: string): string {
|
|
|
594
446
|
}
|
|
595
447
|
|
|
596
448
|
|
|
597
|
-
// One pass, per code point, from a table keyed by DECIMAL CODE POINT.
|
|
598
|
-
// Mermaid: numeric entities only, never HTML names, so there is no
|
|
599
|
-
// name table to diverge; 124 is in it because `|` is the edge-label
|
|
600
|
-
// delimiter. DOT: the two escapes that also make it impossible for user
|
|
601
|
-
// text to forge DOT's own `\n` / `\l` / `\r` justification escapes.
|
|
602
449
|
const MERMAID_ESC: Record<number, string> = {
|
|
603
450
|
34: '#34;', 35: '#35;', 38: '#38;', 60: '#60;', 62: '#62;',
|
|
604
451
|
123: '#123;', 124: '#124;', 125: '#125;',
|
|
@@ -614,24 +461,11 @@ function escape(text: string, table: Record<number, string>): string {
|
|
|
614
461
|
return out
|
|
615
462
|
}
|
|
616
463
|
|
|
617
|
-
// U+000A, U+000D, U+2028 and U+2029: the four code points that end a
|
|
618
|
-
// line somewhere.
|
|
619
464
|
function hasLineBreak(text: string): boolean {
|
|
620
465
|
return /[\n\r\u2028\u2029]/.test(text)
|
|
621
466
|
}
|
|
622
467
|
|
|
623
468
|
|
|
624
|
-
// ---------------------------------------------------------------------
|
|
625
|
-
// SVG (VIEWS.0.md, "No SVG in v1" -- the phase after the text kinds)
|
|
626
|
-
//
|
|
627
|
-
// The cell-based kinds draw into SVG under the INTEGER RULE: every
|
|
628
|
-
// coordinate is a whole number of a fixed cell -- 8 units per
|
|
629
|
-
// character, 20 per line -- from the same counts that lay the text
|
|
630
|
-
// figure out, so no font is measured and both ports emit the same
|
|
631
|
-
// bytes. The reader's browser shapes the text; the geometry is ours.
|
|
632
|
-
// A figure is standalone (its own style block, with default colours)
|
|
633
|
-
// and themeable (every colour a CSS variable a host page can set).
|
|
634
|
-
|
|
635
469
|
const CH = 8
|
|
636
470
|
const LH = 20
|
|
637
471
|
const PAD = 8
|
|
@@ -663,11 +497,6 @@ const svgEsc = (s: string): string => escape(s, SVG_ESC)
|
|
|
663
497
|
function svgDoc(
|
|
664
498
|
w: number, h: number, about: string, parts: string[], style: ViewStyle
|
|
665
499
|
): string {
|
|
666
|
-
// The CLASSES are structure and are always written -- a rect that
|
|
667
|
-
// does not say whether it is a direct cell or a closure cell is not
|
|
668
|
-
// a figure. What `--style none` drops is the STYLESHEET, for a host
|
|
669
|
-
// page that has already bound the variables and would otherwise
|
|
670
|
-
// carry one copy of these rules per embedded figure.
|
|
671
500
|
return [
|
|
672
501
|
`<svg xmlns="http://www.w3.org/2000/svg" class="av" viewBox="0 0 ${w} ${h}" ` +
|
|
673
502
|
`width="${w}" height="${h}" role="img" aria-label="${svgEsc(about)}">`,
|
|
@@ -700,25 +529,11 @@ function svgPath(d: string, cls: string): string {
|
|
|
700
529
|
}
|
|
701
530
|
|
|
702
531
|
|
|
703
|
-
// ---------------------------------------------------------------------
|
|
704
|
-
// The tree
|
|
705
|
-
|
|
706
532
|
// One edge as the tree draws it: a declared inverse pair collapsed to
|
|
707
533
|
// one edge, and the label the branch carries.
|
|
708
534
|
type Drawn = { from: string, to: string, label: string }
|
|
709
535
|
|
|
710
536
|
|
|
711
|
-
// THE EDGE SET WITH DECLARED INVERSE PAIRS COLLAPSED to one logical
|
|
712
|
-
// edge, the tree's way: a relation with a declared inverse arrives
|
|
713
|
-
// twice -- once per direction -- and drawing it raw doubles every such
|
|
714
|
-
// relation.
|
|
715
|
-
//
|
|
716
|
-
// WHAT IS NOT COLLAPSED IS A MUTUAL RELATION: `a dependsOn b` and `b
|
|
717
|
-
// dependsOn a` are two facts under ONE key, and folding them into a
|
|
718
|
-
// single undirected edge erases the shortest cycle a model can have.
|
|
719
|
-
// The collapse is therefore per KEY PAIR rather than per node pair --
|
|
720
|
-
// two keys facing each other are an inverse, one key facing itself is
|
|
721
|
-
// a loop -- which is what makes `acyclic()`'s refusal drawable.
|
|
722
537
|
function collapse(triples: Triple[], relation: string | undefined): Drawn[] {
|
|
723
538
|
const pairs = new Map<string, Triple[]>()
|
|
724
539
|
for (const e of triples) {
|
|
@@ -734,15 +549,6 @@ function collapse(triples: Triple[], relation: string | undefined): Drawn[] {
|
|
|
734
549
|
|
|
735
550
|
const out: Drawn[] = []
|
|
736
551
|
for (const group of pairs.values()) {
|
|
737
|
-
// ONE KEY WINS THE PAIR, and every edge written under it stands.
|
|
738
|
-
// The named relation wins; otherwise the code-point-least key,
|
|
739
|
-
// which is arbitrary but stable. Keeping every edge under the
|
|
740
|
-
// winner is what preserves a MUTUAL relation, while the losing keys
|
|
741
|
-
// are the declared inverses, implied by the winner and not drawn
|
|
742
|
-
// again. With a relation named, its inverse is implied and naming
|
|
743
|
-
// both would double the label; without one, every key is shown,
|
|
744
|
-
// because picking silently would hide that two predicates are in
|
|
745
|
-
// play.
|
|
746
552
|
const keys = keysOf(group)
|
|
747
553
|
const named = undefined !== relation && keys.includes(relation)
|
|
748
554
|
const winner = named ? (relation as string) : keys[0]
|
|
@@ -765,27 +571,6 @@ type Kid = { to: string, label: string }
|
|
|
765
571
|
type Figure = { text?: string, errors?: VetFinding[] }
|
|
766
572
|
|
|
767
573
|
|
|
768
|
-
// THE DEPENDENCY TREE: the drawn edges, walked from each root, indented.
|
|
769
|
-
//
|
|
770
|
-
// A dependency graph is a DAG and not a tree -- two modules may share a
|
|
771
|
-
// dependency, and drawing that shared node once under each parent is
|
|
772
|
-
// what makes `cargo tree` and `npm ls` readable rather than
|
|
773
|
-
// exponential. So this is a SPANNING WALK with two honest marks: `(*)`
|
|
774
|
-
// where a subtree is elided because the node was expanded earlier, and
|
|
775
|
-
// `(cycle)` where an edge closes a loop. The first is routine in a
|
|
776
|
-
// correct model -- a diamond is good engineering, not a fault. The
|
|
777
|
-
// second cannot arise from a model whose relation declares
|
|
778
|
-
// `acyclic()`, and is drawn rather than thrown because a renderer that
|
|
779
|
-
// hangs on a hostile input is a renderer that cannot be pointed at one.
|
|
780
|
-
//
|
|
781
|
-
// Which nodes are roots is DERIVED, not asked for: a root is a node
|
|
782
|
-
// nothing depends on. `roots` overrides that to draw named subtrees.
|
|
783
|
-
// The order of everything -- roots, children, the choice of which
|
|
784
|
-
// occurrence of a shared node is the expanded one -- follows the label
|
|
785
|
-
// sort, so the drawing is a function of the model alone.
|
|
786
|
-
// One drawn row of the tree, for the SVG: its depth, its text, the
|
|
787
|
-
// mark after it, and the row of its parent (-1 for a root). A blank
|
|
788
|
-
// separator between roots is `null`.
|
|
789
574
|
type TreeRow = { depth: number, text: string, mark: string, parent: number }
|
|
790
575
|
|
|
791
576
|
|
|
@@ -794,11 +579,6 @@ function drawTree(
|
|
|
794
579
|
as: ViewProfile, style: ViewStyle
|
|
795
580
|
): Figure {
|
|
796
581
|
const paint = painter(style)
|
|
797
|
-
// With a relation named, the tree is OVER THAT RELATION. A node-link
|
|
798
|
-
// diagram can label each edge and so draw every relation at once; a
|
|
799
|
-
// tree cannot without becoming unreadable, and walking two relations
|
|
800
|
-
// as though they were one would draw a containment the model does
|
|
801
|
-
// not state.
|
|
802
582
|
const kept = undefined === relation
|
|
803
583
|
? all : all.filter((e) => e.label === relation)
|
|
804
584
|
|
|
@@ -827,10 +607,6 @@ function drawTree(
|
|
|
827
607
|
list.sort((x, y) => cmpCodePoint(label(x.to), label(y.to)))
|
|
828
608
|
}
|
|
829
609
|
|
|
830
|
-
// The relation is named on the branch only where more than one is
|
|
831
|
-
// drawn. Naming the single relation on every line of a tree that has
|
|
832
|
-
// exactly one is noise; leaving it off where there are two would
|
|
833
|
-
// hide which edge was walked.
|
|
834
610
|
const many = 1 < new Set(kept.map((e) => e.label)).size
|
|
835
611
|
const byLabel = (a: string, b: string): number =>
|
|
836
612
|
cmpCodePoint(label(a), label(b))
|
|
@@ -844,10 +620,6 @@ function drawTree(
|
|
|
844
620
|
named = [...new Set(roots)].sort(byLabel)
|
|
845
621
|
}
|
|
846
622
|
else {
|
|
847
|
-
// A root is a node nothing depends on. A SELF-EDGE does not make a
|
|
848
|
-
// node depended upon for this purpose: a module that names itself
|
|
849
|
-
// would otherwise stop being a root and take its whole subtree out
|
|
850
|
-
// of the drawing.
|
|
851
623
|
const depended = new Set(
|
|
852
624
|
kept.filter((e) => e.to !== e.from).map((e) => e.to))
|
|
853
625
|
named = nodes.filter((n) => !depended.has(n)).sort(byLabel)
|
|
@@ -866,11 +638,6 @@ function drawTree(
|
|
|
866
638
|
rows.push({ depth: 0, text: label(root), mark: '', parent: rows.length })
|
|
867
639
|
expanded.add(root)
|
|
868
640
|
|
|
869
|
-
// ITERATIVE, with the ancestor chain carried as a set that is added
|
|
870
|
-
// to on the way down and removed from on the way up. A recursive
|
|
871
|
-
// walk is O(depth) stack frames and a deep dependency chain is a
|
|
872
|
-
// real shape, so the drawing of a model must not depend on how deep
|
|
873
|
-
// the interpreter lets it go.
|
|
874
641
|
const chain = new Set<string>([root])
|
|
875
642
|
const stack: { node: string, prefix: string, at: number, row: number }[] =
|
|
876
643
|
[{ node: root, prefix: '', at: 0, row: rows.length - 1 }]
|
|
@@ -910,13 +677,6 @@ function drawTree(
|
|
|
910
677
|
draw(root)
|
|
911
678
|
}
|
|
912
679
|
|
|
913
|
-
// EVERY NODE IS DRAWN. A component whose nodes all depend on each
|
|
914
|
-
// other has no node nothing depends on, so the derived roots miss it
|
|
915
|
-
// entirely -- and a graph with roots elsewhere would drop it in
|
|
916
|
-
// silence, which is the one thing a drawing must not do. The
|
|
917
|
-
// least-labelled node left is taken as a root of its own, until
|
|
918
|
-
// nothing is left. An explicitly named root is a request for one
|
|
919
|
-
// subtree and is left alone.
|
|
920
680
|
if (0 === roots.length) {
|
|
921
681
|
for (const n of nodes) {
|
|
922
682
|
if (!expanded.has(n)) {
|
|
@@ -933,10 +693,6 @@ function drawTree(
|
|
|
933
693
|
}
|
|
934
694
|
|
|
935
695
|
|
|
936
|
-
// The tree as SVG: one line per row, each node indented one unit per
|
|
937
|
-
// depth, joined to its parent by a path that drops from the parent's
|
|
938
|
-
// row and turns in to the child. The marks are muted text after the
|
|
939
|
-
// label.
|
|
940
696
|
function treeSvg(
|
|
941
697
|
rows: (TreeRow | null)[], about: string, style: ViewStyle
|
|
942
698
|
): string {
|
|
@@ -966,42 +722,7 @@ function treeSvg(
|
|
|
966
722
|
// ---------------------------------------------------------------------
|
|
967
723
|
// The document tree
|
|
968
724
|
|
|
969
|
-
// THE SHAPE OF THE MODEL ITSELF, which no other kind draws. Every
|
|
970
|
-
// other figure here reads a REPORT -- the edge set, the provenance
|
|
971
|
-
// record, the subsumption order -- and so can only draw a document
|
|
972
|
-
// that has links, contributions or peers. A reader meeting a model for
|
|
973
|
-
// the first time wants the plainer thing first: what is in it, and how
|
|
974
|
-
// it is arranged.
|
|
975
|
-
//
|
|
976
|
-
// This is `get --keys --types` as a picture, and it reads the same
|
|
977
|
-
// walk: map keys in code-point order, list indices in order, and a
|
|
978
|
-
// leaf's KIND rather than its value -- the canon of a scalar's type,
|
|
979
|
-
// not the scalar. Values are what the document is for; the shape is
|
|
980
|
-
// what a reader needs before any of them mean anything.
|
|
981
|
-
//
|
|
982
|
-
// DEPTH IS A BOUND, NOT AN ELISION MARK. Below it the subtree is not
|
|
983
|
-
// drawn and the row says how many keys were not drawn, because a tree
|
|
984
|
-
// that stops without saying so is the one thing a structural drawing
|
|
985
|
-
// must not be.
|
|
986
725
|
|
|
987
|
-
// ---------------------------------------------------------------------
|
|
988
|
-
// THE VALUE LATTICE, and where this document's values sit on it.
|
|
989
|
-
//
|
|
990
|
-
// THE SCAFFOLD IS THE LANGUAGE'S, NOT THE DOCUMENT'S: `top` at the
|
|
991
|
-
// join, the four kind families under it, `path()` under `string`, the
|
|
992
|
-
// four numeric leaves under `number`, and `nil` at the meet. Every
|
|
993
|
-
// Aontu document is drawn against the SAME shape, which is what makes
|
|
994
|
-
// two of these figures comparable -- and what makes this a view of the
|
|
995
|
-
// language that a document annotates, rather than a picture assembled
|
|
996
|
-
// out of whatever the document happened to contain.
|
|
997
|
-
//
|
|
998
|
-
// See docs/unification.md for what the ordering means.
|
|
999
|
-
|
|
1000
|
-
// The scaffold: each kind and the one above it. The ENGINE decides
|
|
1001
|
-
// which kind sits under which -- kindParent in ts/src/val/ScalarKindVal.ts,
|
|
1002
|
-
// and its twin in go/scalar.go -- and a test in each port holds this
|
|
1003
|
-
// table to it, so adding a kind to the engine makes the figure grow a
|
|
1004
|
-
// node rather than quietly leave one out.
|
|
1005
726
|
const LATTICE_PARENT: [string, string][] = [
|
|
1006
727
|
['string', 'top'],
|
|
1007
728
|
['path()', 'string'],
|
|
@@ -1014,12 +735,6 @@ const LATTICE_PARENT: [string, string][] = [
|
|
|
1014
735
|
['null', 'top'],
|
|
1015
736
|
]
|
|
1016
737
|
|
|
1017
|
-
// The columns, left to right: the MINIMAL kinds, the ones with nothing
|
|
1018
|
-
// under them. Everything else is drawn centred over the columns it
|
|
1019
|
-
// covers, so this list alone fixes the figure's horizontal order -- and
|
|
1020
|
-
// it puts the kinds that reach the bottom from higher up (`boolean`,
|
|
1021
|
-
// `null`) on the outside, where their lines pass the numeric fan
|
|
1022
|
-
// rather than crossing it.
|
|
1023
738
|
const LATTICE_COLS =
|
|
1024
739
|
['path()', 'integer', 'float', 'biginteger', 'bigdecimal', 'boolean',
|
|
1025
740
|
'null']
|
|
@@ -1050,10 +765,6 @@ function latticeAncestors(name: string): string[] {
|
|
|
1050
765
|
return out
|
|
1051
766
|
}
|
|
1052
767
|
|
|
1053
|
-
// The columns one node covers: its own if it is minimal, otherwise
|
|
1054
|
-
// every column beneath it. `nil` is beneath everything and above
|
|
1055
|
-
// nothing, so the walk finds no column under it and the whole width is
|
|
1056
|
-
// its span -- which is where it belongs.
|
|
1057
768
|
function latticeSpan(name: string): number[] {
|
|
1058
769
|
const own = LATTICE_COLS.indexOf(name)
|
|
1059
770
|
if (-1 !== own) {
|
|
@@ -1065,10 +776,6 @@ function latticeSpan(name: string): number[] {
|
|
|
1065
776
|
return 0 === under.length ? LATTICE_COLS.map((_, i) => i) : under
|
|
1066
777
|
}
|
|
1067
778
|
|
|
1068
|
-
// True when `parent` is immediately above `child`. NIL IS COVERED BY
|
|
1069
|
-
// EVERY MINIMAL KIND: it is the meet of all of them, and the only node
|
|
1070
|
-
// the parent table does not name, because nothing in the engine ever
|
|
1071
|
-
// answers `nil` as a superior.
|
|
1072
779
|
function latticeCovers(parent: string, child: string): boolean {
|
|
1073
780
|
return 'nil' === child
|
|
1074
781
|
? -1 !== LATTICE_COLS.indexOf(parent)
|
|
@@ -1076,18 +783,6 @@ function latticeCovers(parent: string, child: string): boolean {
|
|
|
1076
783
|
}
|
|
1077
784
|
|
|
1078
785
|
|
|
1079
|
-
// WHERE ONE VALUE SITS, or undefined for a value that is not at a
|
|
1080
|
-
// single point. The answers are the kinds of thing a document holds:
|
|
1081
|
-
//
|
|
1082
|
-
// a CONCRETE scalar sits at its kind -- `8080` is an `integer`, and
|
|
1083
|
-
// `superior()` is the lattice's own answer to which;
|
|
1084
|
-
// a KIND MARKER sits AT that kind -- `integer` written as a schema
|
|
1085
|
-
// is the node itself, not a value under it;
|
|
1086
|
-
// everything else -- a constraint, an unresolved disjunction, a
|
|
1087
|
-
// reference -- is not one point. `integer & min(1)` is a REGION of
|
|
1088
|
-
// the lattice and `*8080 | integer` is two places at once, so
|
|
1089
|
-
// drawing either at a node would be a claim the figure cannot
|
|
1090
|
-
// support. Both are counted into the loss report instead.
|
|
1091
786
|
function latticePoint(v: any): string | undefined {
|
|
1092
787
|
const node: any = throughDoc(v)
|
|
1093
788
|
if (true === node?.isNil) {
|
|
@@ -1096,10 +791,6 @@ function latticePoint(v: any): string | undefined {
|
|
|
1096
791
|
if (true === node?.isTop) {
|
|
1097
792
|
return 'top'
|
|
1098
793
|
}
|
|
1099
|
-
// A kind marker names its own node; a concrete scalar names the node
|
|
1100
|
-
// above it. Either way the name has to BE one of the figure's: a
|
|
1101
|
-
// kind the scaffold does not draw has nowhere to go, and saying so
|
|
1102
|
-
// through the loss report is the only honest answer.
|
|
1103
794
|
const name: string = true === node?.isScalarKind ? String(node.canon)
|
|
1104
795
|
: true === node?.isScalar ? String(node.superior?.().canon) : ''
|
|
1105
796
|
return LATTICE_NODES.includes(name) ? name : undefined
|
|
@@ -1151,22 +842,11 @@ function latticeCensus(root: any, at: string):
|
|
|
1151
842
|
}
|
|
1152
843
|
|
|
1153
844
|
|
|
1154
|
-
// What one node is written as: its name, and the count of the
|
|
1155
|
-
// document's values that landed on it. A node with nothing at it is
|
|
1156
|
-
// still drawn -- the shape is the language's, and a figure that left
|
|
1157
|
-
// the empty nodes out would be a different lattice for every document.
|
|
1158
845
|
function latticeCell(counts: Map<string, string[]>, name: string): string {
|
|
1159
846
|
const n = (counts.get(name) ?? []).length
|
|
1160
847
|
return 0 === n ? name : `${name} (${n})`
|
|
1161
848
|
}
|
|
1162
849
|
|
|
1163
|
-
// The horizontal layout, in characters: one column per minimal kind,
|
|
1164
|
-
// each as wide as the widest cell drawn over it plus a gutter, and the
|
|
1165
|
-
// centre of each. The spanning nodes are narrower than the span they
|
|
1166
|
-
// cover, so none of them needs a width of its own. The gutter is THREE
|
|
1167
|
-
// because the SVG draws a box a character wider than its text: two of
|
|
1168
|
-
// those characters are the box's own padding and the third is the gap
|
|
1169
|
-
// between one box and the next.
|
|
1170
850
|
const LATTICE_GUTTER = 3
|
|
1171
851
|
|
|
1172
852
|
function latticeCols(counts: Map<string, string[]>):
|
|
@@ -1194,13 +874,6 @@ function latticeAt(name: string, cx: number[]): number {
|
|
|
1194
874
|
}
|
|
1195
875
|
|
|
1196
876
|
|
|
1197
|
-
// The box-drawing glyph for one column of a rule, from the four facts
|
|
1198
|
-
// that meet there: whether the rule continues left and right, and
|
|
1199
|
-
// whether a stem leaves upward and downward. Deciding it this way is
|
|
1200
|
-
// what lets `number` -- which is BOTH one of the many under `top` and
|
|
1201
|
-
// the one above the numeric leaves -- come out as the join it is,
|
|
1202
|
-
// without a case written for it. The table is total, so no column has
|
|
1203
|
-
// to be asked whether it has a glyph.
|
|
1204
877
|
const LATTICE_GLYPH: Record<string, string> = {
|
|
1205
878
|
'....': '─', '...d': '│', '..u.': '│', '..ud': '│',
|
|
1206
879
|
'.r..': '─', '.r.d': '┌', '.ru.': '└', '.rud': '├',
|
|
@@ -1208,10 +881,6 @@ const LATTICE_GLYPH: Record<string, string> = {
|
|
|
1208
881
|
'lr..': '─', 'lr.d': '┬', 'lru.': '┴', 'lrud': '┼',
|
|
1209
882
|
}
|
|
1210
883
|
|
|
1211
|
-
// The figure is PAINTED rather than assembled from padded strings: the
|
|
1212
|
-
// nodes have to line up with the rules that join them, and a count
|
|
1213
|
-
// changes a cell's width -- so the geometry is settled first, in
|
|
1214
|
-
// columns, and every glyph is then written at a place already known.
|
|
1215
884
|
function latticeText(counts: Map<string, string[]>, style: ViewStyle): string {
|
|
1216
885
|
const paint = painter(style)
|
|
1217
886
|
const { cx, width } = latticeCols(counts)
|
|
@@ -1227,9 +896,6 @@ function latticeText(counts: Map<string, string[]>, style: ViewStyle): string {
|
|
|
1227
896
|
roles[y][x + i] = role
|
|
1228
897
|
}
|
|
1229
898
|
}
|
|
1230
|
-
// A cell is its name and, where the document reached it, the count:
|
|
1231
|
-
// two roles, so a terminal can mute the second without touching the
|
|
1232
|
-
// first.
|
|
1233
899
|
const cell = (y: number, name: string) => {
|
|
1234
900
|
const text = latticeCell(counts, name)
|
|
1235
901
|
const left = latticeAt(name, cx) - Math.floor(text.length / 2)
|
|
@@ -1256,9 +922,6 @@ function latticeText(counts: Map<string, string[]>, style: ViewStyle): string {
|
|
|
1256
922
|
stems(y, by)
|
|
1257
923
|
}
|
|
1258
924
|
|
|
1259
|
-
// Four node rows and three joins. `open` is every node whose line
|
|
1260
|
-
// downward has not been drawn yet, which is what carries `boolean`
|
|
1261
|
-
// and `null` past the numeric row to the bottom rule.
|
|
1262
925
|
let open: string[] = []
|
|
1263
926
|
let y = 0
|
|
1264
927
|
for (let r = 0; r < LATTICE_ROWS.length; r++) {
|
|
@@ -1296,14 +959,6 @@ function latticeText(counts: Map<string, string[]>, style: ViewStyle): string {
|
|
|
1296
959
|
}
|
|
1297
960
|
|
|
1298
961
|
|
|
1299
|
-
// The same figure as SVG, off the same column layout, so the two
|
|
1300
|
-
// profiles are one drawing in two grammars rather than two drawings.
|
|
1301
|
-
// A node the document REACHES is drawn with the ordinary rule stroke
|
|
1302
|
-
// (`av-box`) and one it does not with the faint one (`av-cell`),
|
|
1303
|
-
// because every node is drawn whether this document reaches it or not
|
|
1304
|
-
// and a reader has to see which is which without counting. NO NEW
|
|
1305
|
-
// CLASS: those two already mean a box and a faint box, so a host page
|
|
1306
|
-
// that themed the other figures gets this one for nothing.
|
|
1307
962
|
function latticeSvg(
|
|
1308
963
|
counts: Map<string, string[]>, at: string, style: ViewStyle
|
|
1309
964
|
): string {
|
|
@@ -1317,11 +972,6 @@ function latticeSvg(
|
|
|
1317
972
|
const y = (name: string): number =>
|
|
1318
973
|
PAD + BOXH / 2 + (rowOf.get(name) as number) * ROWH
|
|
1319
974
|
|
|
1320
|
-
// Edges first, so a box always sits over the lines that reach it.
|
|
1321
|
-
// The horizontal jog is placed just above the CHILD rather than
|
|
1322
|
-
// halfway down, which is what keeps `boolean` and `null` -- three
|
|
1323
|
-
// rows from `top` to `nil` with nothing between -- clear of the
|
|
1324
|
-
// numeric row they pass.
|
|
1325
975
|
const edges: [string, string][] = [...LATTICE_PARENT,
|
|
1326
976
|
...LATTICE_COLS.map((col): [string, string] => ['nil', col])]
|
|
1327
977
|
for (const [child, parent] of edges) {
|
|
@@ -1335,9 +985,6 @@ function latticeSvg(
|
|
|
1335
985
|
const w = (text.length + 2) * CH
|
|
1336
986
|
parts.push(svgRect(x(name) - w / 2, y(name) - BOXH / 2, w, BOXH,
|
|
1337
987
|
name === text ? 'av-cell' : 'av-box'))
|
|
1338
|
-
// The name and the count in ONE text element, as the tree does it:
|
|
1339
|
-
// two runs on one baseline, so the count is muted without the
|
|
1340
|
-
// figure having to place it.
|
|
1341
988
|
parts.push(`<text x="${x(name)}" y="${y(name) + 5}" text-anchor="middle">` +
|
|
1342
989
|
`<tspan class="av-t">${svgEsc(name)}</tspan>` +
|
|
1343
990
|
`<tspan class="av-m">${svgEsc(text.slice(name.length))}</tspan></text>`)
|
|
@@ -1350,11 +997,6 @@ function latticeSvg(
|
|
|
1350
997
|
}
|
|
1351
998
|
|
|
1352
999
|
|
|
1353
|
-
// The figure. The row count is fixed -- the lattice is the language's,
|
|
1354
|
-
// and no option makes it smaller -- so `--max-rows` below it is still a
|
|
1355
|
-
// refusal, because a figure that quietly overran a stated bound is the
|
|
1356
|
-
// thing every other kind here refuses to be; the message says raise
|
|
1357
|
-
// rather than narrow.
|
|
1358
1000
|
const LATTICE_LINES = 3 * LATTICE_ROWS.length - 2
|
|
1359
1001
|
|
|
1360
1002
|
function drawLattice(
|
|
@@ -1406,13 +1048,6 @@ const DEFAULT_DOC_DEPTH = 3
|
|
|
1406
1048
|
function docKids(v: any): string[] {
|
|
1407
1049
|
const node: any = throughDoc(v)
|
|
1408
1050
|
if (true === node?.isMap) {
|
|
1409
|
-
// AN ALIAS DECLARATION IS NOT PART OF THE DOCUMENT
|
|
1410
|
-
// (docs/reference-language.md, "Aliases"): it does not generate
|
|
1411
|
-
// and it does not appear in canon. It IS a key of the root map in
|
|
1412
|
-
// the value tree, which `get --keys` reports and this does not --
|
|
1413
|
-
// a figure of the document's shape that showed `%Cents` beside
|
|
1414
|
-
// `customers` would be drawing the declaration as data
|
|
1415
|
-
// (use-cases/BUGS.md 74).
|
|
1416
1051
|
return Object.keys(node.peg)
|
|
1417
1052
|
.filter((k) => !k.startsWith('%')).sort(cmpCodePoint)
|
|
1418
1053
|
}
|
|
@@ -1437,13 +1072,6 @@ function throughDoc(v: any): any {
|
|
|
1437
1072
|
// is the constraint and for a scalar its value. Long canons are cut,
|
|
1438
1073
|
// since the figure is the shape and not the data.
|
|
1439
1074
|
function docLeaf(v: any): string {
|
|
1440
|
-
// A CONTAINER WITH NOTHING IN IT IS NOT A LEAF, and calling it one
|
|
1441
|
-
// by writing nothing after the key would make it read as a value the
|
|
1442
|
-
// figure declined to describe. Its canon says what it is -- `{}`,
|
|
1443
|
-
// `[]`, or a template a spread wrote and no member filled.
|
|
1444
|
-
//
|
|
1445
|
-
// `canon` is a string on every Val, so there is no other-type arm to
|
|
1446
|
-
// take; the cut is the only decision here.
|
|
1447
1075
|
const canon: string = throughDoc(v).canon
|
|
1448
1076
|
return 32 < canon.length ? canon.slice(0, 29) + '...' : canon
|
|
1449
1077
|
}
|
|
@@ -1492,11 +1120,6 @@ function drawDoc(
|
|
|
1492
1120
|
const child = throughDoc(throughDoc(frame.node).peg[key])
|
|
1493
1121
|
const kids = docKids(child)
|
|
1494
1122
|
const under = stack.length < depth
|
|
1495
|
-
// A container the depth bound stops at says how many keys are not
|
|
1496
|
-
// drawn; a leaf says what it is.
|
|
1497
|
-
// A leaf says what it is and a stopped container says how many
|
|
1498
|
-
// keys it holds; both are written after the key with one space,
|
|
1499
|
-
// and neither is ever empty (a canon has at least one character).
|
|
1500
1123
|
const mark = 0 === kids.length ? ' ' + docLeaf(child)
|
|
1501
1124
|
: under ? '' : ` (${kids.length})`
|
|
1502
1125
|
if (0 < kids.length && !under) {
|
|
@@ -1533,15 +1156,6 @@ function drawDoc(
|
|
|
1533
1156
|
// ---------------------------------------------------------------------
|
|
1534
1157
|
// The matrix (Ghoniem et al. 2004; Sangal et al. 2005)
|
|
1535
1158
|
|
|
1536
|
-
// THE PARTITION ORDER: leaves first. Repeatedly take every unplaced
|
|
1537
|
-
// node whose every successor is placed, in label order, as the next
|
|
1538
|
-
// layer. That is a topological sort with a canonical tiebreak, and on
|
|
1539
|
-
// an acyclic relation it yields a perfect lower triangle -- which IS
|
|
1540
|
-
// the acyclicity proof, in the picture's own shape. Where nothing can
|
|
1541
|
-
// be placed the relation has a cycle: the least unplaced node is
|
|
1542
|
-
// placed alone, the strongly connected component it sits in is
|
|
1543
|
-
// reported as `cycle_block`, and the walk continues -- the cycle's
|
|
1544
|
-
// above-diagonal cell is then the acyclicity violation, drawn.
|
|
1545
1159
|
function partition(
|
|
1546
1160
|
nodes: string[], succ: Map<string, string[]>,
|
|
1547
1161
|
reach: Map<string, Set<string>>, label: (n: string) => string,
|
|
@@ -1576,9 +1190,6 @@ function partition(
|
|
|
1576
1190
|
}
|
|
1577
1191
|
|
|
1578
1192
|
|
|
1579
|
-
// The relation a matrix draws: the one named, else the only one with
|
|
1580
|
-
// edges, else a refusal -- a matrix over two predicates at once would
|
|
1581
|
-
// draw a containment the model does not state.
|
|
1582
1193
|
function pickRelation(
|
|
1583
1194
|
relation: string | undefined, keys: string[]
|
|
1584
1195
|
): { relation?: string, error?: VetFinding } {
|
|
@@ -1696,11 +1307,6 @@ const CELL_CLASS: Record<string, string> = {
|
|
|
1696
1307
|
'.': 'av-cell', '\\': 'av-cell',
|
|
1697
1308
|
}
|
|
1698
1309
|
|
|
1699
|
-
// The same five states as ROLES, for the text profile. One table per
|
|
1700
|
-
// mechanism rather than one shared one, because the two vocabularies
|
|
1701
|
-
// are not in step: SVG needs a class for the empty cell (it draws a
|
|
1702
|
-
// rect there) and the text profile has nothing to say about a `.`
|
|
1703
|
-
// beyond that it is not a mark.
|
|
1704
1310
|
const CELL_ROLE: Record<string, ViewRole> = {
|
|
1705
1311
|
X: 'direct', '!': 'unmirrored', '+': 'closure',
|
|
1706
1312
|
'.': 'muted', '\\': 'rule',
|
|
@@ -1863,9 +1469,6 @@ function drawGraph(
|
|
|
1863
1469
|
|| cmpCodePoint(node(a.to).label, node(b.to).label)
|
|
1864
1470
|
|| cmpCodePoint(a.key, b.key))
|
|
1865
1471
|
|
|
1866
|
-
// Crossings in the emitted order: two edges cross when their spans
|
|
1867
|
-
// interleave. A count, not a layout -- the consumer lays the picture
|
|
1868
|
-
// out, and this says how tangled the order it is handed is.
|
|
1869
1472
|
let crossings = 0
|
|
1870
1473
|
const span = (e: GEdge): [number, number] => {
|
|
1871
1474
|
const a = at.get(e.from) as number
|
|
@@ -1923,14 +1526,6 @@ function drawGraph(
|
|
|
1923
1526
|
out.push('}')
|
|
1924
1527
|
}
|
|
1925
1528
|
else {
|
|
1926
|
-
// Entity relationships, as Mermaid's own erDiagram. Cardinality is
|
|
1927
|
-
// not something the model states, so every relationship is drawn
|
|
1928
|
-
// many-to-many and the label carries the predicate: drawing a
|
|
1929
|
-
// cardinality the model does not assert would be an invention. An
|
|
1930
|
-
// erDiagram has no separate label -- the identifier IS what the
|
|
1931
|
-
// reader sees -- so it is the encoded label, unique by the label
|
|
1932
|
-
// rule. Every node is in some relationship, since the node set is
|
|
1933
|
-
// what the edges connect.
|
|
1934
1529
|
const esc = (s: string): string => escape(s, MERMAID_ESC)
|
|
1935
1530
|
out.push('erDiagram')
|
|
1936
1531
|
for (const e of drawn) {
|
|
@@ -1947,19 +1542,6 @@ function drawGraph(
|
|
|
1947
1542
|
type Band = { name: string, nodes: GNode[] }
|
|
1948
1543
|
|
|
1949
1544
|
|
|
1950
|
-
// THE LAYER DIAGRAM every architecture document has a hand-drawn
|
|
1951
|
-
// version of: one band per layer, the layers stacked with the one
|
|
1952
|
-
// nothing depends on at the top, each module in its band, and the
|
|
1953
|
-
// rule -- dependencies point DOWN -- read off the bands. The band a
|
|
1954
|
-
// node belongs to is the value of `--group-by`; the order of the
|
|
1955
|
-
// bands is DERIVED from the relation, as the partition order over the
|
|
1956
|
-
// layer-level graph (a layer depends on the layers its modules depend
|
|
1957
|
-
// on), so it is a function of the model and not of a list somebody has
|
|
1958
|
-
// to keep in step with it -- unless the model has an upward edge, when
|
|
1959
|
-
// the layer graph is cyclic and no order is derivable, which is what
|
|
1960
|
-
// `--layers` (top first) is for. A sideways edge (within one band) is
|
|
1961
|
-
// ordinary engineering and counted; an UPWARD edge is the violation
|
|
1962
|
-
// the drawing exists to show, and is named under the figure.
|
|
1963
1545
|
function drawLayer(
|
|
1964
1546
|
triples: Triple[], root: any,
|
|
1965
1547
|
o: {
|
|
@@ -2082,9 +1664,6 @@ function drawLayer(
|
|
|
2082
1664
|
}
|
|
2083
1665
|
const out: string[] = []
|
|
2084
1666
|
if ('svg' === o.as) {
|
|
2085
|
-
// The description says WHAT WAS DRAWN, because two layer figures of
|
|
2086
|
-
// one model on one page differ by exactly that, and a reader who
|
|
2087
|
-
// cannot see them has only this to tell them apart.
|
|
2088
1667
|
const drew = 'all' === edges
|
|
2089
1668
|
? `${shown.length} edges drawn, ${upward} of them upward`
|
|
2090
1669
|
: 'none' === edges
|
|
@@ -2146,14 +1725,6 @@ function drawLayer(
|
|
|
2146
1725
|
type Drawing = { edge: GEdge, way: 'downward' | 'sideways' | 'upward' }
|
|
2147
1726
|
|
|
2148
1727
|
|
|
2149
|
-
// The layers as SVG: one band per row, its modules as boxes laid left
|
|
2150
|
-
// to right, and every SHOWN edge drawn between them -- an upward one
|
|
2151
|
-
// dashed and alert-coloured, because it is the violation the bands
|
|
2152
|
-
// cannot show on their own; a downward one straight down from the
|
|
2153
|
-
// bottom of its box to the top of the one it names; a sideways one
|
|
2154
|
-
// dipped below the boxes, since two modules of one band sit on the
|
|
2155
|
-
// same line and a straight edge between them would cross whatever
|
|
2156
|
-
// stands between.
|
|
2157
1728
|
function layerSvg(
|
|
2158
1729
|
bands: Band[], shown: Drawing[], footer: string[], about: string,
|
|
2159
1730
|
style: ViewStyle
|
|
@@ -2514,20 +2085,10 @@ function drawLayers(
|
|
|
2514
2085
|
},
|
|
2515
2086
|
max: number, loss: ViewLoss[]
|
|
2516
2087
|
): Figure {
|
|
2517
|
-
// Every path something met at AND THE DOCUMENT HAS A VALUE AT,
|
|
2518
|
-
// mapped to the documents that met there. A meet can happen at a
|
|
2519
|
-
// position the finished document does not have -- a template's own
|
|
2520
|
-
// child, folded into each key it is spread over -- and the panel is
|
|
2521
|
-
// about the document, so only its paths are rows. A path is shown
|
|
2522
|
-
// as `a.b.c`; the root as `$`.
|
|
2523
2088
|
const members = new Map<string, Set<string>>()
|
|
2524
2089
|
const paths: string[] = []
|
|
2525
2090
|
const atParts = undefined === o.at ? [] : pathParts(o.at)
|
|
2526
2091
|
for (const [key, rec] of prov.paths) {
|
|
2527
|
-
// A record at a position the document does not have is the Go
|
|
2528
|
-
// recorder's template ghost (use-cases/BUGS.md 70); this port's
|
|
2529
|
-
// recorder does not write one, and the two ports must skip the
|
|
2530
|
-
// same rows.
|
|
2531
2092
|
if (0 === rec.conjuncts.length || null == anchorAt(root, '$.' + key)) {
|
|
2532
2093
|
continue
|
|
2533
2094
|
}
|
|
@@ -2578,13 +2139,6 @@ function drawLayers(
|
|
|
2578
2139
|
// ---------------------------------------------------------------------
|
|
2579
2140
|
// The meet ladder (VIEWS-ORDER.0.md)
|
|
2580
2141
|
|
|
2581
|
-
// The descent from `top` through each contribution to the resolved
|
|
2582
|
-
// value, one rung per conjunct. Where the contributions are ranked
|
|
2583
|
-
// preferences the ladder IS the arbitration: fewer stars win, so the
|
|
2584
|
-
// rungs read weakest-first and the winner is the last before the
|
|
2585
|
-
// value. `why`'s record is in source order, which is not rank order,
|
|
2586
|
-
// so the rungs are SORTED -- an emitter that trusted the record would
|
|
2587
|
-
// draw an arbitration that did not happen.
|
|
2588
2142
|
function drawLadder(
|
|
2589
2143
|
src: string, options: ViewOptions, as: ViewProfile, max: number
|
|
2590
2144
|
): Figure {
|
|
@@ -2653,17 +2207,6 @@ type Doc = ViewPosetDoc
|
|
|
2653
2207
|
type Cls = { members: number[], label: string }
|
|
2654
2208
|
|
|
2655
2209
|
|
|
2656
|
-
// The order over a document set, in the design's five steps: the
|
|
2657
|
-
// verdict matrix; the quotient by MUTUAL subsumption (two documents
|
|
2658
|
-
// that subsume each other are one node -- mandatory, since without it
|
|
2659
|
-
// the relation is not antisymmetric and the cover relation is
|
|
2660
|
-
// undefined); the closure, then the cover relation over the closure;
|
|
2661
|
-
// and a canonical order, so the result does not depend on the order the
|
|
2662
|
-
// files were given.
|
|
2663
|
-
// One pairwise comparison: does the general document admit everything
|
|
2664
|
-
// the specific one does? `subsume`, with the poset's anchor and
|
|
2665
|
-
// profile; a parameter so a test can hand the drawing a verdict matrix
|
|
2666
|
-
// the checker cannot be made to produce.
|
|
2667
2210
|
export type ViewCompare = (
|
|
2668
2211
|
general: Doc, specific: Doc, options: ViewOptions
|
|
2669
2212
|
) => { verdict: string, code: string }
|
|
@@ -2749,11 +2292,6 @@ function drawPoset(
|
|
|
2749
2292
|
if (!closure[lo][hi]) {
|
|
2750
2293
|
continue
|
|
2751
2294
|
}
|
|
2752
|
-
// A pair the closure implies but the checker measured as
|
|
2753
|
-
// `does_not_subsume` is reported rather than absorbed: the
|
|
2754
|
-
// measured relation is a conservative under-approximation, and
|
|
2755
|
-
// an under-approximation of a transitive relation need not be
|
|
2756
|
-
// transitive.
|
|
2757
2295
|
if ('does_not_subsume' === verdict[rep(hi)][rep(lo)]) {
|
|
2758
2296
|
intransitive.push(`${classes[lo].label} < ${classes[hi].label}`)
|
|
2759
2297
|
}
|
|
@@ -2931,12 +2469,6 @@ export function view(
|
|
|
2931
2469
|
`profiles: ${profiles.join(', ')}`)],
|
|
2932
2470
|
})
|
|
2933
2471
|
}
|
|
2934
|
-
// ONE MECHANISM PER PROFILE (VIEWS.0.md, "7. Styling"). `ansi` is
|
|
2935
|
-
// the text profile's and `css` the SVG's; asking for one on a
|
|
2936
|
-
// profile that has no way to carry it is a usage error rather than a
|
|
2937
|
-
// silent no-op, so a script that asks for colour and gets none is
|
|
2938
|
-
// told why. `none` is always available -- it is the absence of a
|
|
2939
|
-
// mechanism.
|
|
2940
2472
|
const style: ViewStyle = styleOf(options.style, as)
|
|
2941
2473
|
const carrier: Record<string, ViewProfile> = { ansi: 'text', css: 'svg' }
|
|
2942
2474
|
if (undefined !== carrier[style] && carrier[style] !== as) {
|
|
@@ -2980,13 +2512,6 @@ export function view(
|
|
|
2980
2512
|
}
|
|
2981
2513
|
|
|
2982
2514
|
|
|
2983
|
-
// THE KINDS THAT DRAW FROM A LOADED MODEL, so a view document can load
|
|
2984
|
-
// once and draw N figures from the one evaluation. `gen` is the
|
|
2985
|
-
// generated value where the caller already holds it -- a view document
|
|
2986
|
-
// reads its own declarations out of one -- and undefined where the set
|
|
2987
|
-
// panel must generate its own. It is a BOX rather than the value, so
|
|
2988
|
-
// that a document generating `undefined` is still a value the panel
|
|
2989
|
-
// has rather than one it must recompute.
|
|
2990
2515
|
function drawLoaded(
|
|
2991
2516
|
root: any, ctx: any, gen: { value: any } | undefined,
|
|
2992
2517
|
prov: Provenance | undefined,
|
|
@@ -3066,20 +2591,6 @@ export function viewTree(src: string, opts?: ViewOptions): ViewReport {
|
|
|
3066
2591
|
}
|
|
3067
2592
|
|
|
3068
2593
|
|
|
3069
|
-
// ---------------------------------------------------------------------
|
|
3070
|
-
// The view document (VIEWS.0.md, "6. The view document")
|
|
3071
|
-
//
|
|
3072
|
-
// A projection that runs in CI belongs in a file. A view document is an
|
|
3073
|
-
// ORDINARY document that includes the model and declares its figures as
|
|
3074
|
-
// data; `views` is the AUTHOR's key and nothing here knows the name
|
|
3075
|
-
// (ADR-010), which is why `--views` names the path.
|
|
3076
|
-
//
|
|
3077
|
-
// The declaration keys ARE the library's option names, which are the
|
|
3078
|
-
// CLI's flag names without the dashes: one vocabulary, three doors. A
|
|
3079
|
-
// declaration must name its `kind` and its `out` -- a figure in a file
|
|
3080
|
-
// that a review reads should say what it draws and where it goes,
|
|
3081
|
-
// rather than inheriting a default from whoever ran the verb.
|
|
3082
|
-
|
|
3083
2594
|
const DECL_TEXT = [
|
|
3084
2595
|
'kind', 'as', 'out', 'at', 'relation', 'order', 'groupBy', 'label',
|
|
3085
2596
|
'sets', 'member', 'universe', 'edges',
|
|
@@ -3105,9 +2616,6 @@ function documentFinding(path: string, message: string, note?: string): VetFindi
|
|
|
3105
2616
|
}
|
|
3106
2617
|
|
|
3107
2618
|
|
|
3108
|
-
// One validated declaration: everything the drawing needs, decided
|
|
3109
|
-
// before any figure is drawn, so a document with three bad
|
|
3110
|
-
// declarations reports three faults rather than the first.
|
|
3111
2619
|
type Plan = {
|
|
3112
2620
|
name: string
|
|
3113
2621
|
kind: ViewKind
|
|
@@ -3183,9 +2691,6 @@ function planOf(name: string, decl: any, at: string): {
|
|
|
3183
2691
|
'kinds: ' + Object.keys(PROFILES).join(', ')))
|
|
3184
2692
|
}
|
|
3185
2693
|
else if ('poset' === kind) {
|
|
3186
|
-
// The poset is an order over SEVERAL documents, and a view document
|
|
3187
|
-
// declares figures of the one it includes. `aontu view poset` draws
|
|
3188
|
-
// it, naming the documents on the command line.
|
|
3189
2694
|
errors.push(documentFinding(`${where}.kind`,
|
|
3190
2695
|
'A view document draws figures of one document; ' +
|
|
3191
2696
|
'the poset compares several.'))
|
|
@@ -3219,13 +2724,6 @@ function planOf(name: string, decl: any, at: string): {
|
|
|
3219
2724
|
}
|
|
3220
2725
|
|
|
3221
2726
|
|
|
3222
|
-
// N FIGURES OF ONE DOCUMENT. The document is evaluated ONCE, with the
|
|
3223
|
-
// provenance recorder on, and every figure but the ladder draws from
|
|
3224
|
-
// that one root; the ladder re-runs `why` by construction.
|
|
3225
|
-
//
|
|
3226
|
-
// The caller writes the files, and only when the whole set rendered:
|
|
3227
|
-
// N figures of one model are only meaningful together, so a set whose
|
|
3228
|
-
// third figure refuses must not leave the first two on disk.
|
|
3229
2727
|
export function viewSet(
|
|
3230
2728
|
src: string, opts?: ViewOptions, hooks?: ViewHooks
|
|
3231
2729
|
): ViewSetReport {
|
|
@@ -3238,11 +2736,6 @@ export function viewSet(
|
|
|
3238
2736
|
'the map that declares the figures; name it with --views.')],
|
|
3239
2737
|
}
|
|
3240
2738
|
}
|
|
3241
|
-
// ONE EVALUATION, and it is INSTRUMENTED: the layers panel reads the
|
|
3242
|
-
// provenance record, which is written during unification, so a set
|
|
3243
|
-
// that declares one would otherwise need a second run. Recording it
|
|
3244
|
-
// always costs a little and makes the one-evaluation claim true for
|
|
3245
|
-
// every kind but the ladder, which re-runs `why` by construction.
|
|
3246
2739
|
const prov = (hooks?.provenance ?? (() => new Provenance()))()
|
|
3247
2740
|
const loaded = load(src, options.path, options, prov)
|
|
3248
2741
|
if (undefined !== loaded.errors) {
|