@graview/core 0.1.8 → 0.1.10

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.
Files changed (151) hide show
  1. package/README.md +8 -2
  2. package/dist/app.d.ts +41 -2
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js.map +1 -1
  5. package/dist/capabilities.js +1 -1
  6. package/dist/capabilities.js.map +1 -1
  7. package/dist/city.d.ts +29 -0
  8. package/dist/city.d.ts.map +1 -1
  9. package/dist/city.js +66 -0
  10. package/dist/city.js.map +1 -1
  11. package/dist/cli/check/arrangement.d.ts.map +1 -1
  12. package/dist/cli/check/arrangement.js +3 -2
  13. package/dist/cli/check/arrangement.js.map +1 -1
  14. package/dist/cli/check/computed.d.ts +14 -0
  15. package/dist/cli/check/computed.d.ts.map +1 -0
  16. package/dist/cli/check/computed.js +34 -0
  17. package/dist/cli/check/computed.js.map +1 -0
  18. package/dist/cli/check/index.d.ts +1 -0
  19. package/dist/cli/check/index.d.ts.map +1 -1
  20. package/dist/cli/check/index.js +1 -0
  21. package/dist/cli/check/index.js.map +1 -1
  22. package/dist/cli/check/lenses.d.ts +10 -0
  23. package/dist/cli/check/lenses.d.ts.map +1 -1
  24. package/dist/cli/check/lenses.js +37 -19
  25. package/dist/cli/check/lenses.js.map +1 -1
  26. package/dist/cli/check/relations.d.ts.map +1 -1
  27. package/dist/cli/check/relations.js +2 -1
  28. package/dist/cli/check/relations.js.map +1 -1
  29. package/dist/cli/check/views.d.ts.map +1 -1
  30. package/dist/cli/check/views.js +8 -2
  31. package/dist/cli/check/views.js.map +1 -1
  32. package/dist/cli/check.d.ts.map +1 -1
  33. package/dist/cli/check.js +4 -1
  34. package/dist/cli/check.js.map +1 -1
  35. package/dist/cli/describe.d.ts.map +1 -1
  36. package/dist/cli/describe.js +54 -1
  37. package/dist/cli/describe.js.map +1 -1
  38. package/dist/cli/index.d.ts +1 -1
  39. package/dist/cli/index.d.ts.map +1 -1
  40. package/dist/cli/index.js +21 -1
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/describe.d.ts +3 -0
  43. package/dist/describe.d.ts.map +1 -0
  44. package/dist/describe.js +12 -0
  45. package/dist/describe.js.map +1 -0
  46. package/dist/document/blocks.d.ts +182 -0
  47. package/dist/document/blocks.d.ts.map +1 -0
  48. package/dist/document/blocks.js +382 -0
  49. package/dist/document/blocks.js.map +1 -0
  50. package/dist/document/compile.d.ts.map +1 -1
  51. package/dist/document/compile.js +57 -15
  52. package/dist/document/compile.js.map +1 -1
  53. package/dist/document/computed-values.d.ts +33 -0
  54. package/dist/document/computed-values.d.ts.map +1 -0
  55. package/dist/document/computed-values.js +60 -0
  56. package/dist/document/computed-values.js.map +1 -0
  57. package/dist/document/computed.d.ts +42 -0
  58. package/dist/document/computed.d.ts.map +1 -0
  59. package/dist/document/computed.js +173 -0
  60. package/dist/document/computed.js.map +1 -0
  61. package/dist/document/describe-place.d.ts +95 -0
  62. package/dist/document/describe-place.d.ts.map +1 -0
  63. package/dist/document/describe-place.js +257 -0
  64. package/dist/document/describe-place.js.map +1 -0
  65. package/dist/document/diff.d.ts.map +1 -1
  66. package/dist/document/diff.js +72 -3
  67. package/dist/document/diff.js.map +1 -1
  68. package/dist/document/edit.d.ts +1 -1
  69. package/dist/document/edit.d.ts.map +1 -1
  70. package/dist/document/edit.js +816 -103
  71. package/dist/document/edit.js.map +1 -1
  72. package/dist/document/expr/analyze.d.ts +22 -0
  73. package/dist/document/expr/analyze.d.ts.map +1 -1
  74. package/dist/document/expr/analyze.js +49 -3
  75. package/dist/document/expr/analyze.js.map +1 -1
  76. package/dist/document/expr/evaluate.d.ts +7 -1
  77. package/dist/document/expr/evaluate.d.ts.map +1 -1
  78. package/dist/document/expr/evaluate.js +95 -6
  79. package/dist/document/expr/evaluate.js.map +1 -1
  80. package/dist/document/expr/index.d.ts +1 -1
  81. package/dist/document/expr/index.d.ts.map +1 -1
  82. package/dist/document/expr/index.js +1 -1
  83. package/dist/document/expr/index.js.map +1 -1
  84. package/dist/document/index.d.ts +10 -2
  85. package/dist/document/index.d.ts.map +1 -1
  86. package/dist/document/index.js +5 -1
  87. package/dist/document/index.js.map +1 -1
  88. package/dist/document/rules.d.ts +2 -1
  89. package/dist/document/rules.d.ts.map +1 -1
  90. package/dist/document/rules.js +5 -1
  91. package/dist/document/rules.js.map +1 -1
  92. package/dist/document/schema.d.ts +35 -3
  93. package/dist/document/schema.d.ts.map +1 -1
  94. package/dist/document/schema.js +22 -2
  95. package/dist/document/schema.js.map +1 -1
  96. package/dist/document/template.d.ts +17 -2
  97. package/dist/document/template.d.ts.map +1 -1
  98. package/dist/document/template.js +136 -16
  99. package/dist/document/template.js.map +1 -1
  100. package/dist/document/thumbnail.d.ts +34 -0
  101. package/dist/document/thumbnail.d.ts.map +1 -0
  102. package/dist/document/thumbnail.js +165 -0
  103. package/dist/document/thumbnail.js.map +1 -0
  104. package/dist/document/to-document.d.ts.map +1 -1
  105. package/dist/document/to-document.js +4 -1
  106. package/dist/document/to-document.js.map +1 -1
  107. package/dist/document/views.d.ts +47 -3
  108. package/dist/document/views.d.ts.map +1 -1
  109. package/dist/document/views.js +289 -21
  110. package/dist/document/views.js.map +1 -1
  111. package/dist/index.d.ts +11 -3
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +6 -1
  114. package/dist/index.js.map +1 -1
  115. package/dist/places.d.ts +186 -0
  116. package/dist/places.d.ts.map +1 -0
  117. package/dist/places.js +358 -0
  118. package/dist/places.js.map +1 -0
  119. package/dist/scaffold/project.d.ts.map +1 -1
  120. package/dist/scaffold/project.js +9 -0
  121. package/dist/scaffold/project.js.map +1 -1
  122. package/dist/scaffold/ui.d.ts.map +1 -1
  123. package/dist/scaffold/ui.js +13 -10
  124. package/dist/scaffold/ui.js.map +1 -1
  125. package/dist/scene-districts.d.ts +24 -0
  126. package/dist/scene-districts.d.ts.map +1 -0
  127. package/dist/scene-districts.js +27 -0
  128. package/dist/scene-districts.js.map +1 -0
  129. package/dist/schema/define-node.d.ts +3 -0
  130. package/dist/schema/define-node.d.ts.map +1 -1
  131. package/dist/schema/define-node.js +3 -1
  132. package/dist/schema/define-node.js.map +1 -1
  133. package/dist/schema/types.d.ts +17 -0
  134. package/dist/schema/types.d.ts.map +1 -1
  135. package/dist/theme/layers.d.ts +82 -0
  136. package/dist/theme/layers.d.ts.map +1 -0
  137. package/dist/theme/layers.js +79 -0
  138. package/dist/theme/layers.js.map +1 -0
  139. package/dist/theme/look.d.ts +96 -0
  140. package/dist/theme/look.d.ts.map +1 -0
  141. package/dist/theme/look.js +110 -0
  142. package/dist/theme/look.js.map +1 -0
  143. package/dist/version.d.ts +1 -1
  144. package/dist/version.d.ts.map +1 -1
  145. package/dist/version.js +1 -1
  146. package/dist/version.js.map +1 -1
  147. package/dist/views/types.d.ts +19 -0
  148. package/dist/views/types.d.ts.map +1 -1
  149. package/dist/views/types.js +14 -0
  150. package/dist/views/types.js.map +1 -1
  151. package/package.json +5 -1
@@ -0,0 +1,382 @@
1
+ import { fieldWords, valueWords } from "../schema/define-node.js";
2
+ import { evaluateExpr, NodeSet } from "./expr/evaluate.js";
3
+ import { parseExpr } from "./expr/parse.js";
4
+ import { formatValue, parseTemplate } from "./template.js";
5
+ import { fieldSpecOf } from "./to-document.js";
6
+ import { FIGURE_FORMATS, LIST_AS, MAX_LIST_LIMIT, VIEW_FIELD_FORMATS, VIEW_TONES } from "./views.js";
7
+ const safely = (f) => {
8
+ try {
9
+ return f();
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ };
15
+ const isTone = (value) => typeof value === "string" && VIEW_TONES.includes(value);
16
+ function toneOf(tone) {
17
+ if (tone === undefined)
18
+ return undefined;
19
+ if (isTone(tone))
20
+ return tone;
21
+ if (tone && typeof tone === "object" && typeof tone.expr === "string")
22
+ return { expr: safely(() => parseExpr(tone.expr)) };
23
+ // A tone outside the kit is the check's to refuse; drawn, it is quiet.
24
+ return "neutral";
25
+ }
26
+ const MAX_DEPTH = 4;
27
+ /**
28
+ * A LIST, PARSED (FR-81, FR-82). Its order by a key is the language's own
29
+ * `sort(…)` around its source, so it is judged under the same budget as
30
+ * every other expression; an order by a choice field's declared choices is
31
+ * done after, from the declaration.
32
+ */
33
+ function listOf(block) {
34
+ const source = typeof block["list"] === "string" ? safely(() => parseExpr(block["list"])) : null;
35
+ const sort = block["sort"];
36
+ const by = typeof sort === "string" ? sort : sort && typeof sort === "object" && typeof sort.by === "string" ? sort.by : undefined;
37
+ const direction = sort && typeof sort === "object" ? sort.direction : undefined;
38
+ let ordered = source;
39
+ let choiceOrder;
40
+ if (source && by !== undefined) {
41
+ if (direction === "choices")
42
+ choiceOrder = by;
43
+ else {
44
+ const key = safely(() => parseExpr(by));
45
+ ordered = key ? { t: "call", fn: "sort", args: [source, key, { t: "lit", value: direction === "desc" ? "desc" : "asc", at: 0 }], at: 0 } : null;
46
+ }
47
+ }
48
+ const limit = typeof block["limit"] === "number" && Number.isInteger(block["limit"]) && block["limit"] >= 1 ? Math.min(block["limit"], MAX_LIST_LIMIT) : undefined;
49
+ const group = block["group"];
50
+ const groupBy = typeof group === "string" ? group : group && typeof group === "object" && typeof group.by === "string" ? group.by : undefined;
51
+ const headings = group && typeof group === "object" && group.headings && typeof group.headings === "object" ? group.headings : {};
52
+ return {
53
+ t: "list",
54
+ source: ordered,
55
+ ...(choiceOrder ? { choiceOrder } : {}),
56
+ ...(limit ? { limit } : {}),
57
+ ...(groupBy ? { group: { by: groupBy, headings: Object.fromEntries(Object.entries(headings).filter((entry) => typeof entry[1] === "string")) } } : {}),
58
+ ...(typeof block["empty"] === "string" ? { empty: block["empty"] } : {}),
59
+ as: block["as"] === "card" ? "card" : "row",
60
+ };
61
+ }
62
+ /**
63
+ * Parse a spec's blocks. A spec `graview check` passed parses cleanly; a
64
+ * part that does not is said as "—", and a block outside the vocabulary is
65
+ * not drawn at all.
66
+ */
67
+ export function compileBlocks(blocks, depth = 1) {
68
+ if (!Array.isArray(blocks) || depth > MAX_DEPTH)
69
+ return [];
70
+ return blocks.flatMap((raw) => {
71
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
72
+ return [];
73
+ const block = raw;
74
+ const template = (source) => (typeof source === "string" ? safely(() => parseTemplate(source)) : null);
75
+ const expr = (source) => (typeof source === "string" ? safely(() => parseExpr(source)) : null);
76
+ const tone = toneOf(block["tone"]);
77
+ const label = typeof block["label"] === "string" ? block["label"] : undefined;
78
+ const has = (key) => Object.prototype.hasOwnProperty.call(block, key);
79
+ // A list first: its `group` is how it is grouped, not a group block.
80
+ if (has("list"))
81
+ return [listOf(block)];
82
+ if (has("headline"))
83
+ return [{ t: "headline", parts: template(block["headline"]) }];
84
+ if (has("figure") && typeof block["figure"] === "string") {
85
+ const as = FIGURE_FORMATS.includes(block["as"]) ? block["as"] : undefined;
86
+ const currency = typeof block["currency"] === "string" && /^[A-Z]{3}$/.test(block["currency"]) ? block["currency"] : undefined;
87
+ return [{ t: "number", value: expr(block["figure"]), ...(as ? { as } : {}), ...(currency ? { currency } : {}), ...(label ? { label } : {}) }];
88
+ }
89
+ if (has("title"))
90
+ return [{ t: "title", parts: template(block["title"]) }];
91
+ if (has("text"))
92
+ return [{ t: "text", parts: template(block["text"]), ...(tone ? { tone } : {}) }];
93
+ if (has("badge"))
94
+ return [{ t: "badge", parts: template(block["badge"]), ...(tone ? { tone } : {}) }];
95
+ if (has("field")) {
96
+ const as = VIEW_FIELD_FORMATS.includes(block["as"]) ? block["as"] : undefined;
97
+ return [{ t: "field", field: String(block["field"]), ...(as ? { as } : {}), ...(label ? { label } : {}) }];
98
+ }
99
+ if (has("progress")) {
100
+ const p = (block["progress"] ?? {});
101
+ return [{ t: "progress", value: expr(p.value), max: expr(p.max), ...(label ? { label } : {}) }];
102
+ }
103
+ if (has("group"))
104
+ return [{ t: "group", blocks: compileBlocks(block["group"], depth + 1), direction: block["direction"] === "row" ? "row" : "column" }];
105
+ if (has("when"))
106
+ return [{ t: "when", when: expr(block["when"]), show: compileBlocks(block["show"], depth + 1) }];
107
+ if (has("divider"))
108
+ return [{ t: "divider" }];
109
+ if (has("figure"))
110
+ return [{ t: "figure" }];
111
+ return [];
112
+ });
113
+ }
114
+ const NOTHING = "—";
115
+ /** The allowance a card's template gets: a card is drawn many times a frame. */
116
+ const BUDGET = 500;
117
+ const EMPTY_GRAPH = {
118
+ getNode: () => undefined,
119
+ allNodes: () => [],
120
+ allEdges: () => [],
121
+ nodesOfKind: () => [],
122
+ edgesOfKind: () => [],
123
+ out: () => [],
124
+ in: () => [],
125
+ neighbors: () => [],
126
+ has: () => false,
127
+ };
128
+ function judge(expr, ctx) {
129
+ if (!expr)
130
+ return { ok: false, problem: "an expression that does not parse" };
131
+ try {
132
+ return { ok: true, value: evaluateExpr(expr, { graph: ctx.graph ?? EMPTY_GRAPH, subject: ctx.node, kinds: ctx.kinds, today: ctx.today, budget: ctx.budget ?? BUDGET }) };
133
+ }
134
+ catch (e) {
135
+ return { ok: false, problem: e instanceof Error ? e.message : String(e) };
136
+ }
137
+ }
138
+ /** A template's words, each part judged as `renderTemplate` judges it — and what could not be, said. */
139
+ function say(parts, ctx) {
140
+ if (!parts)
141
+ return { text: NOTHING, problem: "a template that does not parse" };
142
+ let problem;
143
+ const text = parts
144
+ .map((part) => {
145
+ if (part.text !== undefined)
146
+ return part.text;
147
+ const judged = judge(part.expr ?? null, ctx);
148
+ if (!judged.ok) {
149
+ problem ??= `{${part.source ?? ""}}: ${judged.problem}`;
150
+ return NOTHING;
151
+ }
152
+ return formatValue(judged.value, part.format, ctx.today, part.formatArgs);
153
+ })
154
+ .join("");
155
+ return problem ? { text, problem } : { text };
156
+ }
157
+ function toneWord(tone, ctx) {
158
+ if (tone === undefined)
159
+ return undefined;
160
+ if (typeof tone === "string")
161
+ return tone;
162
+ const judged = judge(tone.expr, ctx);
163
+ return judged.ok && isTone(judged.value) ? judged.value : "neutral";
164
+ }
165
+ /** Only http(s) is ever a link; anything else — `javascript:`, `data:`, a typo — is shown as words. */
166
+ export function safeHref(value) {
167
+ if (typeof value !== "string")
168
+ return undefined;
169
+ try {
170
+ const url = new URL(value);
171
+ return url.protocol === "http:" || url.protocol === "https:" ? url.href : undefined;
172
+ }
173
+ catch {
174
+ return undefined;
175
+ }
176
+ }
177
+ function fieldText(key, value, ctx, as) {
178
+ if (value === null || value === undefined || value === "")
179
+ return NOTHING;
180
+ if (typeof value === "boolean")
181
+ return value ? "yes" : "no";
182
+ if (as)
183
+ return formatValue(value, as, ctx.today);
184
+ const spec = ctx.fields[key];
185
+ if (ctx.definition?.display?.format?.[key])
186
+ return valueWords(ctx.definition, key, value);
187
+ if (spec?.type === "date")
188
+ return formatValue(value, "date", ctx.today);
189
+ if (spec?.type === "enum" && typeof value === "string")
190
+ return valueWords(ctx.definition, key, value);
191
+ if (typeof value === "number")
192
+ return value.toLocaleString("en-US");
193
+ if (Array.isArray(value))
194
+ return value.map((one) => String(one)).join(", ");
195
+ if (typeof value === "object")
196
+ return NOTHING;
197
+ return String(value);
198
+ }
199
+ /** A figure's words: a number in figures, money (in a currency when it names one) or a fraction as a percent. */
200
+ export function sayNumber(value, as, currency, today) {
201
+ if (typeof value !== "number")
202
+ return String(value);
203
+ if (as === "money" && currency) {
204
+ return safely(() => value.toLocaleString("en-US", { style: "currency", currency, maximumFractionDigits: Number.isInteger(value) ? 0 : 2, minimumFractionDigits: Number.isInteger(value) ? 0 : 2 })) ?? formatValue(value, "money", today);
205
+ }
206
+ if (as === "money" || as === "percent")
207
+ return formatValue(value, as, today);
208
+ return value.toLocaleString("en-US", { maximumFractionDigits: 2 });
209
+ }
210
+ const withProblem = (block, problem) => (problem ? { ...block, problem } : block);
211
+ function resolveOne(block, ctx, first) {
212
+ switch (block.t) {
213
+ case "title": {
214
+ const said = say(block.parts, ctx);
215
+ return withProblem({ t: "title", text: said.text }, said.problem);
216
+ }
217
+ case "text": {
218
+ const said = say(block.parts, ctx);
219
+ const tone = toneWord(block.tone, ctx);
220
+ return withProblem({ t: "text", text: said.text, ...(tone ? { tone } : {}) }, said.problem);
221
+ }
222
+ case "badge": {
223
+ const said = say(block.parts, ctx);
224
+ return withProblem({ t: "badge", text: said.text, tone: toneWord(block.tone, ctx) ?? "neutral" }, said.problem);
225
+ }
226
+ case "field": {
227
+ const label = block.label ?? fieldWords(ctx.definition, block.field);
228
+ // About no one record, there is no field to show (the check says so).
229
+ if (!ctx.node)
230
+ return { t: "field", field: block.field, label, text: NOTHING, problem: `"${block.field}" names a field, and these blocks are about no one record` };
231
+ // A computed field is worked out like any expression, under the same budget (FR-83); else an OWN field only: a name on the prototype is not a field of the record.
232
+ const worked = ctx.kinds.get(ctx.node.kind)?.computed?.has(block.field);
233
+ let raw;
234
+ let problem;
235
+ if (worked) {
236
+ const judged = judge({ t: "ident", name: block.field, at: 0 }, ctx);
237
+ if (!judged.ok)
238
+ problem = judged.problem;
239
+ else
240
+ raw = judged.value !== null && typeof judged.value === "object" ? formatValue(judged.value, undefined, ctx.today) : judged.value;
241
+ }
242
+ else
243
+ raw = Object.prototype.hasOwnProperty.call(ctx.node, block.field) ? ctx.node[block.field] : undefined;
244
+ const href = ctx.fields[block.field]?.type === "url" && block.as === undefined ? safeHref(raw) : undefined;
245
+ const text = safely(() => fieldText(block.field, raw, ctx, block.as)) ?? NOTHING;
246
+ return withProblem({ t: "field", field: block.field, label, text, ...(href ? { href } : {}) }, problem);
247
+ }
248
+ case "progress": {
249
+ const value = judge(block.value, ctx);
250
+ const max = judge(block.max, ctx);
251
+ const label = block.label ?? "Progress";
252
+ const problem = !value.ok ? value.problem : !max.ok ? max.problem : undefined;
253
+ if (!(value.ok && max.ok && typeof value.value === "number" && typeof max.value === "number" && Number.isFinite(value.value) && Number.isFinite(max.value) && max.value > 0)) {
254
+ return withProblem({ t: "progress", label, text: NOTHING }, problem);
255
+ }
256
+ return { t: "progress", label, value: value.value, max: max.value, text: `${formatValue(value.value, undefined, ctx.today)} of ${formatValue(max.value, undefined, ctx.today)}` };
257
+ }
258
+ case "group":
259
+ return { t: "group", direction: block.direction, blocks: resolveBlocks(block.blocks, ctx) };
260
+ case "when": {
261
+ // A condition that cannot be judged hides what it guards, like a rule's `when`.
262
+ const judged = judge(block.when, ctx);
263
+ const shown = judged.ok && judged.value === true;
264
+ return withProblem({ t: "when", shown, blocks: shown ? resolveBlocks(block.show, ctx) : [] }, judged.ok ? undefined : judged.problem);
265
+ }
266
+ case "divider":
267
+ return { t: "divider" };
268
+ case "figure":
269
+ return { t: "figure" };
270
+ case "headline": {
271
+ const said = say(block.parts, ctx);
272
+ const level = Math.min(6, Math.max(1, (first ? ctx.firstHeading : undefined) ?? ctx.heading ?? 3));
273
+ return withProblem({ t: "headline", level, text: said.text }, said.problem);
274
+ }
275
+ case "number": {
276
+ const judged = judge(block.value, ctx);
277
+ const text = !judged.ok || judged.value === null || typeof judged.value === "object" ? NOTHING : sayNumber(judged.value, block.as, block.currency, ctx.today);
278
+ return withProblem({ t: "number", text, ...(block.label ? { label: block.label } : {}) }, judged.ok ? undefined : judged.problem);
279
+ }
280
+ case "list":
281
+ return resolveList(block, ctx);
282
+ }
283
+ }
284
+ /** Blocks worked out for one record — or for none. Pure: everything they read is in `ctx`. */
285
+ export function resolveBlocks(blocks, ctx) {
286
+ const first = blocks.findIndex((block) => block.t === "headline");
287
+ return blocks.map((block, i) => resolveOne(block, ctx, i === first));
288
+ }
289
+ /**
290
+ * A LIST OF RECORDS: the records its expression names — the kinds swept,
291
+ * or a walk from the record (`out('includes')`, `in('answers')`) — in their
292
+ * order, a few, grouped by a choice in its declared order. Read from the
293
+ * graph the context is handed, which for a seat is what that seat may see
294
+ * (FR-55): a record it may not see is not listed, not counted, and opens no
295
+ * group of its own.
296
+ */
297
+ function resolveList(block, ctx) {
298
+ const headingLevel = Math.min(6, (ctx.heading ?? 3) + 1);
299
+ const judged = judge(block.source, ctx);
300
+ if (!judged.ok)
301
+ return { t: "list", as: block.as, failed: true, members: [], headingLevel, more: 0, problem: judged.problem };
302
+ const value = judged.value;
303
+ let nodes = value instanceof NodeSet ? value.nodes : value !== null && typeof value === "object" && !Array.isArray(value) ? [value] : [];
304
+ if (block.choiceOrder && ctx.schema)
305
+ nodes = inChoiceOrder(nodes, block.choiceOrder, ctx.schema);
306
+ const all = nodes.length;
307
+ nodes = nodes.slice(0, block.limit ?? MAX_LIST_LIMIT);
308
+ const more = block.limit === undefined ? all - nodes.length : 0;
309
+ return {
310
+ t: "list",
311
+ as: block.as,
312
+ failed: false,
313
+ members: nodes,
314
+ ...(block.group && ctx.schema && nodes.length > 0 ? { groups: groupsOf(nodes, block.group, ctx.schema) } : {}),
315
+ headingLevel,
316
+ ...(nodes.length === 0 && block.empty ? { empty: block.empty } : {}),
317
+ more,
318
+ };
319
+ }
320
+ /** A choice field's choices on a kind, in the order they are declared; empty when it is not one. */
321
+ function choicesOf(schema, kind, field) {
322
+ const shape = schema.tryDefinition(kind)?.fields?.shape;
323
+ const spec = shape && Object.prototype.hasOwnProperty.call(shape, field) ? fieldSpecOf(shape[field]) : undefined;
324
+ return spec?.type === "enum" ? (spec.options ?? []) : [];
325
+ }
326
+ const valueOf = (node, field) => (Object.prototype.hasOwnProperty.call(node, field) ? node[field] : undefined);
327
+ /** Records in the order a choice field's choices are declared; a value among none of them last, in the order given. */
328
+ function inChoiceOrder(nodes, field, schema) {
329
+ const rank = (node) => {
330
+ const at = choicesOf(schema, node.kind, field).indexOf(String(valueOf(node, field)));
331
+ return at < 0 ? Number.MAX_SAFE_INTEGER : at;
332
+ };
333
+ return nodes.map((node, i) => ({ node, i, rank: rank(node) })).sort((a, b) => a.rank - b.rank || a.i - b.i).map((one) => one.node);
334
+ }
335
+ const sentenceCase = (words) => words.charAt(0).toUpperCase() + words.slice(1);
336
+ /**
337
+ * The records under a heading per choice, in the declared order; a choice
338
+ * with no record here has no heading at all, so a heading never says that
339
+ * something the reader cannot see exists. A value among no choice goes
340
+ * last, unheaded.
341
+ */
342
+ function groupsOf(nodes, group, schema) {
343
+ const order = [];
344
+ for (const node of nodes)
345
+ for (const choice of choicesOf(schema, node.kind, group.by))
346
+ if (!order.includes(choice))
347
+ order.push(choice);
348
+ const out = [];
349
+ for (const choice of order) {
350
+ const members = nodes.filter((node) => valueOf(node, group.by) === choice);
351
+ if (members.length === 0)
352
+ continue;
353
+ const definition = schema.tryDefinition(members[0].kind);
354
+ out.push({ value: choice, heading: group.headings[choice] ?? sentenceCase(valueWords(definition, group.by, choice)), members });
355
+ }
356
+ const rest = nodes.filter((node) => !order.includes(String(valueOf(node, group.by))));
357
+ if (rest.length > 0)
358
+ out.push({ value: null, members: rest });
359
+ return out;
360
+ }
361
+ /** Whether a block takes more than one line: a list, a headline or a figure, or a group or condition holding one. */
362
+ export function isTallBlock(block) {
363
+ if (block.t === "list" || block.t === "headline" || block.t === "number")
364
+ return true;
365
+ if (block.t === "group")
366
+ return block.blocks.some(isTallBlock);
367
+ if (block.t === "when")
368
+ return block.show.some(isTallBlock);
369
+ return false;
370
+ }
371
+ /** A kind's declared fields in the document's words, read from its schema. */
372
+ export function fieldSpecsOf(schema, kind) {
373
+ const shape = schema.tryDefinition(kind)?.fields?.shape ?? {};
374
+ const read = {};
375
+ for (const [key, field] of Object.entries(shape)) {
376
+ const spec = fieldSpecOf(field);
377
+ if (spec)
378
+ read[key] = spec;
379
+ }
380
+ return read;
381
+ }
382
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/document/blocks.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/document/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAcL,KAAK,UAAU,EAMhB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgD,KAAK,SAAS,EAAc,MAAM,oBAAoB,CAAC;AAE9G,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AAiBrB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;CACrC;AAKD,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,CAoCzH;AA2BD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAS5E;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,GAAG,SAAS,UAAU,EAAE,CAmBxF;AA6QD,cAAM,OAAQ,SAAQ,KAAK;CAAG;AAE9B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAY9G;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAsS1H;AAwBD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/document/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAcL,KAAK,UAAU,EAMhB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgD,KAAK,SAAS,EAAc,MAAM,oBAAoB,CAAC;AAE9G,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AAkBrB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;CACrC;AAKD,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,CAoCzH;AA2BD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAW5E;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,GAAG,SAAS,UAAU,EAAE,CAmBxF;AAySD,cAAM,OAAQ,SAAQ,KAAK;CAAG;AAE9B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAc9G;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAgT1H;AAwBD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,CAAC"}
@@ -9,7 +9,8 @@ import { error, hasErrors, warning } from "./findings.js";
9
9
  import { DocumentSpec, MAX_DOCUMENT_BYTES, } from "./schema.js";
10
10
  import { parseTemplate, renderTemplate, TemplateError } from "./template.js";
11
11
  import { upgradeDocument } from "./upgrade.js";
12
- import { validateViews } from "./views.js";
12
+ import { homeOf, validateViews, viewsOf } from "./views.js";
13
+ import { computedOf, parsedComputed, validateComputed, workedOutAlone } from "./computed.js";
13
14
  const BUILTIN_REFS = new Set(["subject", "now", "today"]);
14
15
  const SUBJECT_ARG = "id";
15
16
  /** Parse and validate without compiling — the document's own sentences, before the framework's. */
@@ -74,9 +75,11 @@ function edgeIndex(document) {
74
75
  export function kindShapes(document) {
75
76
  const shapes = new Map();
76
77
  for (const [kind, spec] of Object.entries(document.kinds)) {
78
+ const computed = parsedComputed(spec);
77
79
  shapes.set(kind, {
78
80
  fields: new Set(Object.keys(spec.fields)),
79
81
  edges: new Map(Object.entries(spec.edges ?? {}).map(([name, e]) => [name, e.cardinality ?? "many"])),
82
+ ...(computed ? { computed } : {}),
80
83
  });
81
84
  }
82
85
  return shapes;
@@ -159,9 +162,11 @@ function validate(document) {
159
162
  }
160
163
  if (spec.lifecycle && !spec.fields[spec.lifecycle.field])
161
164
  findings.push(error("lifecycle-field", `${at}.lifecycle.field`, `${kind} has no field "${spec.lifecycle.field}"`));
165
+ // A glance may say a computed field: the surfaces that draw a glance work it out over the seat's graph (FR-83).
166
+ const computedHere = (name) => spec.computed !== undefined && Object.prototype.hasOwnProperty.call(spec.computed, name);
162
167
  for (const field of spec.glance ?? []) {
163
- if (!spec.fields[field])
164
- findings.push(error("glance-field", `${at}.glance`, `a glance at ${kind} is to say "${field}", and ${kind} has no field called that`, `use one of: ${Object.keys(spec.fields).join(", ")}`));
168
+ if (!spec.fields[field] && !computedHere(field))
169
+ findings.push(error("glance-field", `${at}.glance`, `a glance at ${kind} is to say "${field}", and ${kind} has no field or computed field called that`, `use one of: ${[...Object.keys(spec.fields), ...Object.keys(spec.computed ?? {})].join(", ")}`));
165
170
  }
166
171
  for (const key of ["label", "describe"]) {
167
172
  const source = spec[key];
@@ -172,8 +177,15 @@ function validate(document) {
172
177
  if (!part.expr)
173
178
  continue;
174
179
  for (const name of analyzeExpr(part.expr).names) {
175
- if (!spec.fields[name])
176
- findings.push(error("template-field", `${at}.${key}`, `${kind} has no field "${name}" for its ${key} to show`, key === "label" ? "a label can only show the record's own fields" : undefined));
180
+ if (spec.fields[name])
181
+ continue;
182
+ // A computed field worked out from the record alone is said like a field; one that reads beyond it cannot be, with no graph in hand.
183
+ if (computedHere(name)) {
184
+ if (!workedOutAlone(spec, name))
185
+ findings.push(error("template-field", `${at}.${key}`, `${kind}'s ${name} is worked out from beyond the record, and a ${key} is said with no graph to read`, `show it in a view instead, or name a computed field worked out from ${kind}'s own fields`));
186
+ continue;
187
+ }
188
+ findings.push(error("template-field", `${at}.${key}`, `${kind} has no field "${name}" for its ${key} to show`, key === "label" ? "a label can only show the record's own fields and what they work out" : undefined));
177
189
  }
178
190
  }
179
191
  }
@@ -191,9 +203,14 @@ function validate(document) {
191
203
  const subjectKinds = asArray(act.on);
192
204
  const effects = effectsOf(act, document);
193
205
  if (act.creates && act.on === undefined && act.writes && kinds.has(act.creates)) {
194
- for (const field of act.writes)
195
- if (!document.kinds[act.creates].fields[field])
206
+ for (const field of act.writes) {
207
+ if (document.kinds[act.creates].fields[field])
208
+ continue;
209
+ if (document.kinds[act.creates].computed?.[field] !== undefined)
210
+ findings.push(error("computed-written", `${at}.writes`, `${act.creates}'s ${field} is worked out, not written: no act can set it`, "write the stored fields it is worked out from"));
211
+ else
196
212
  findings.push(error("act-field", `${at}.writes`, `${act.creates} has no field "${field}"`));
213
+ }
197
214
  }
198
215
  if (effects.length === 0)
199
216
  findings.push(error("act-empty", at, `"${name}" does nothing`, "give it effects or a shorthand such as sets or creates"));
@@ -204,10 +221,16 @@ function validate(document) {
204
221
  if ("create" in effect) {
205
222
  if (!kinds.has(effect.create))
206
223
  findings.push(error("act-kind", `${where}.create`, `"${effect.create}" is not a kind this document declares`));
207
- else
208
- for (const field of Object.keys(effect.set ?? {}))
209
- if (!document.kinds[effect.create].fields[field])
224
+ else {
225
+ for (const field of Object.keys(effect.set ?? {})) {
226
+ if (document.kinds[effect.create].fields[field])
227
+ continue;
228
+ if (document.kinds[effect.create].computed?.[field] !== undefined)
229
+ findings.push(error("computed-written", `${where}.set.${field}`, `${effect.create}'s ${field} is worked out, not written: no act can set it`, "set the stored fields it is worked out from"));
230
+ else
210
231
  findings.push(error("act-field", `${where}.set.${field}`, `${effect.create} has no field "${field}"`));
232
+ }
233
+ }
211
234
  if (effect.as)
212
235
  created.set(effect.as, effect.create);
213
236
  }
@@ -224,9 +247,14 @@ function validate(document) {
224
247
  if (target === "subject" && subjectKinds.length === 0)
225
248
  findings.push(error("act-subject", `${at}.on`, `"${name}" changes "$subject" but does not say which kinds it is "on"`));
226
249
  for (const field of Object.keys(effect.set)) {
227
- for (const kind of targetKinds)
228
- if (kinds.has(kind) && !document.kinds[kind].fields[field])
250
+ for (const kind of targetKinds) {
251
+ if (!kinds.has(kind) || document.kinds[kind].fields[field])
252
+ continue;
253
+ if (document.kinds[kind].computed?.[field] !== undefined)
254
+ findings.push(error("computed-written", `${where}.set.${field}`, `${kind}'s ${field} is worked out, not written: no act can set it`, "set the stored fields it is worked out from"));
255
+ else
229
256
  findings.push(error("act-field", `${where}.set.${field}`, `${kind} has no field "${field}"`));
257
+ }
230
258
  }
231
259
  }
232
260
  else if ("remove" in effect) {
@@ -260,7 +288,7 @@ function validate(document) {
260
288
  for (const n of shape.names) {
261
289
  if (rule.over === "graph")
262
290
  findings.push(error("rule-name", `${at}.${key}`, `"${n}" means nothing in a rule over the whole graph`, "name a kind in \"over\", or use all('kind')"));
263
- else if (spec && !spec.fields[n] && !spec.edges?.[n]) {
291
+ else if (spec && !spec.fields[n] && !spec.edges?.[n] && spec.computed?.[n] === undefined) {
264
292
  const hyphenated = Object.keys(spec.edges ?? {}).find((e) => e.includes("-") && e.split("-").includes(n));
265
293
  findings.push(error("rule-name", `${at}.${key}`, `${rule.over} has no field or relation called "${n}"`, hyphenated ? `"${hyphenated}" reads as a subtraction in a rule; rename the relation to one camelCase word, like "${hyphenated.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())}"` : undefined));
266
294
  }
@@ -305,6 +333,7 @@ function validate(document) {
305
333
  });
306
334
  }
307
335
  findings.push(...validateViews(document));
336
+ findings.push(...validateComputed(new Map(Object.entries(document.kinds).map(([kind, spec]) => [kind, { fields: new Set(Object.keys(spec.fields)), edges: new Set(Object.keys(spec.edges ?? {})), computed: computedOf(spec) }])), (kind, name) => `kinds.${kind}.computed.${name}`));
308
337
  return findings;
309
338
  }
310
339
  /*
@@ -442,6 +471,9 @@ export function compileDocument(raw, options = {}) {
442
471
  const check = checkApp(app);
443
472
  for (const f of check.findings) {
444
473
  const finding = { severity: f.severity === "error" ? "error" : f.severity === "warning" ? "warning" : "note", code: `check:${f.code}`, path: frameworkPath(f.where, document), message: f.message, ...(f.fix ? { fix: f.fix } : {}) };
474
+ // The document already said it, at the same path (a blocks lens's words are held by both): once is enough.
475
+ if (compiled.findings.some((said) => said.code === f.code && said.path === finding.path))
476
+ continue;
445
477
  findings.push(f.code === "glance-unchosen" ? inDocumentWords(finding, f.where, document) : finding);
446
478
  }
447
479
  if (hasErrors(findings))
@@ -475,7 +507,12 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
475
507
  const labelSource = spec.label ?? (defaultLabelField(spec) ? `{${defaultLabelField(spec)}}` : undefined);
476
508
  const labelParts = labelSource ? parseTemplate(labelSource) : undefined;
477
509
  const describeParts = spec.describe ? parseTemplate(spec.describe) : undefined;
478
- const labels = Object.fromEntries(Object.entries(spec.fields).filter(([, f]) => f.label).map(([n, f]) => [n, f.label]));
510
+ const computed = computedOf(spec);
511
+ // A computed field's words are said like a field's: its label, where it has one.
512
+ const labels = Object.fromEntries([
513
+ ...Object.entries(spec.fields).filter(([, f]) => f.label).map(([n, f]) => [n, f.label]),
514
+ ...[...computed].filter(([, c]) => c.label).map(([n, c]) => [n, c.label]),
515
+ ]);
479
516
  // Defaults stay out of the zod schema (hydration must not invent values) and ride beside it, for a repair to read.
480
517
  const defaults = Object.fromEntries(Object.entries(spec.fields).filter(([, f]) => f.default !== undefined).map(([n, f]) => [n, f.default]));
481
518
  const edgeDecls = Object.fromEntries(Object.entries(spec.edges ?? {}).map(([n, e]) => [
@@ -498,6 +535,7 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
498
535
  ...(describeParts ? { describe: (node) => renderTemplate(describeParts, { node: node, kinds: shapes, today: today() }) } : {}),
499
536
  ...(spec.lifecycle ? { lifecycle: { field: spec.lifecycle.field, retired: spec.lifecycle.retired } } : {}),
500
537
  ...(spec.figure ? { figure: spec.figure } : {}),
538
+ ...(spec.computed && Object.keys(spec.computed).length > 0 ? { computed: spec.computed } : {}),
501
539
  ...(Object.keys(labels).length > 0 || spec.glance ? { display: { ...(Object.keys(labels).length > 0 ? { labels } : {}), ...(spec.glance ? { glance: [...spec.glance] } : {}) } } : {}),
502
540
  ...(Object.keys(defaults).length > 0 ? { defaults } : {}),
503
541
  });
@@ -774,9 +812,13 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
774
812
  ...(brand ? { brand } : {}),
775
813
  ...(document.modules ? { modules: document.modules } : {}),
776
814
  ...(document.lenses ? { lenses: document.lenses } : {}),
815
+ // The arrangement is the app's (FR-80): every face reads it beside the places.
816
+ ...(document.pages ? { pages: document.pages } : {}),
777
817
  ...(document.settings ? { settings: document.settings } : {}),
778
818
  // The document's views are the declaration's view specs (FR-03): data the framework draws.
779
- ...(document.views && Object.keys(document.views).length > 0 ? { viewSpecs: document.views } : {}),
819
+ ...(Object.keys(viewsOf(document)).length > 0 ? { viewSpecs: viewsOf(document) } : {}),
820
+ // And its home view, about no one record, is the app's home (FR-81).
821
+ ...(homeOf(document) ? { home: homeOf(document) } : {}),
780
822
  version: document.version ?? 1,
781
823
  };
782
824
  // `toDocument(app)` gives this document back, byte for byte.