@graview/core 0.1.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/LICENSE +96 -0
- package/README.md +35 -0
- package/dist/app.d.ts +294 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +49 -0
- package/dist/app.js.map +1 -0
- package/dist/arrange.d.ts +185 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +456 -0
- package/dist/arrange.js.map +1 -0
- package/dist/beginning.d.ts +65 -0
- package/dist/beginning.d.ts.map +1 -0
- package/dist/beginning.js +94 -0
- package/dist/beginning.js.map +1 -0
- package/dist/bind.d.ts +42 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +26 -0
- package/dist/bind.js.map +1 -0
- package/dist/city.d.ts +93 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +160 -0
- package/dist/city.js.map +1 -0
- package/dist/cli/check/arrangement.d.ts +13 -0
- package/dist/cli/check/arrangement.d.ts.map +1 -0
- package/dist/cli/check/arrangement.js +63 -0
- package/dist/cli/check/arrangement.js.map +1 -0
- package/dist/cli/check/beginnings.d.ts +16 -0
- package/dist/cli/check/beginnings.d.ts.map +1 -0
- package/dist/cli/check/beginnings.js +53 -0
- package/dist/cli/check/beginnings.js.map +1 -0
- package/dist/cli/check/brand.d.ts +17 -0
- package/dist/cli/check/brand.d.ts.map +1 -0
- package/dist/cli/check/brand.js +153 -0
- package/dist/cli/check/brand.js.map +1 -0
- package/dist/cli/check/city.d.ts +17 -0
- package/dist/cli/check/city.d.ts.map +1 -0
- package/dist/cli/check/city.js +58 -0
- package/dist/cli/check/city.js.map +1 -0
- package/dist/cli/check/context.d.ts +50 -0
- package/dist/cli/check/context.d.ts.map +1 -0
- package/dist/cli/check/context.js +37 -0
- package/dist/cli/check/context.js.map +1 -0
- package/dist/cli/check/fields.d.ts +16 -0
- package/dist/cli/check/fields.d.ts.map +1 -0
- package/dist/cli/check/fields.js +237 -0
- package/dist/cli/check/fields.js.map +1 -0
- package/dist/cli/check/index.d.ts +14 -0
- package/dist/cli/check/index.d.ts.map +1 -0
- package/dist/cli/check/index.js +14 -0
- package/dist/cli/check/index.js.map +1 -0
- package/dist/cli/check/intelligence.d.ts +17 -0
- package/dist/cli/check/intelligence.d.ts.map +1 -0
- package/dist/cli/check/intelligence.js +136 -0
- package/dist/cli/check/intelligence.js.map +1 -0
- package/dist/cli/check/lenses.d.ts +17 -0
- package/dist/cli/check/lenses.d.ts.map +1 -0
- package/dist/cli/check/lenses.js +239 -0
- package/dist/cli/check/lenses.js.map +1 -0
- package/dist/cli/check/migrations.d.ts +16 -0
- package/dist/cli/check/migrations.d.ts.map +1 -0
- package/dist/cli/check/migrations.js +43 -0
- package/dist/cli/check/migrations.js.map +1 -0
- package/dist/cli/check/modules.d.ts +16 -0
- package/dist/cli/check/modules.d.ts.map +1 -0
- package/dist/cli/check/modules.js +123 -0
- package/dist/cli/check/modules.js.map +1 -0
- package/dist/cli/check/policy.d.ts +16 -0
- package/dist/cli/check/policy.d.ts.map +1 -0
- package/dist/cli/check/policy.js +90 -0
- package/dist/cli/check/policy.js.map +1 -0
- package/dist/cli/check/relations.d.ts +29 -0
- package/dist/cli/check/relations.d.ts.map +1 -0
- package/dist/cli/check/relations.js +279 -0
- package/dist/cli/check/relations.js.map +1 -0
- package/dist/cli/check/routes.d.ts +16 -0
- package/dist/cli/check/routes.d.ts.map +1 -0
- package/dist/cli/check/routes.js +31 -0
- package/dist/cli/check/routes.js.map +1 -0
- package/dist/cli/check/settings.d.ts +16 -0
- package/dist/cli/check/settings.d.ts.map +1 -0
- package/dist/cli/check/settings.js +81 -0
- package/dist/cli/check/settings.js.map +1 -0
- package/dist/cli/check.d.ts +36 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +76 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/create.d.ts +20 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +251 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/describe.d.ts +35 -0
- package/dist/cli/describe.d.ts.map +1 -0
- package/dist/cli/describe.js +230 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/docs.d.ts +11 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/docs.js +152 -0
- package/dist/cli/docs.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extend.d.ts +23 -0
- package/dist/extend.d.ts.map +1 -0
- package/dist/extend.js +53 -0
- package/dist/extend.js.map +1 -0
- package/dist/graph/diff.d.ts +31 -0
- package/dist/graph/diff.d.ts.map +1 -0
- package/dist/graph/diff.js +71 -0
- package/dist/graph/diff.js.map +1 -0
- package/dist/graph/graph.d.ts +69 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +284 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/primitives.d.ts +52 -0
- package/dist/graph/primitives.d.ts.map +1 -0
- package/dist/graph/primitives.js +62 -0
- package/dist/graph/primitives.js.map +1 -0
- package/dist/graph/tracked.d.ts +31 -0
- package/dist/graph/tracked.d.ts.map +1 -0
- package/dist/graph/tracked.js +69 -0
- package/dist/graph/tracked.js.map +1 -0
- package/dist/graph/types.d.ts +34 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +0 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +112 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +193 -0
- package/dist/installation.js.map +1 -0
- package/dist/intelligence-bridge.d.ts +73 -0
- package/dist/intelligence-bridge.d.ts.map +1 -0
- package/dist/intelligence-bridge.js +31 -0
- package/dist/intelligence-bridge.js.map +1 -0
- package/dist/invariants/engine.d.ts +36 -0
- package/dist/invariants/engine.d.ts.map +1 -0
- package/dist/invariants/engine.js +88 -0
- package/dist/invariants/engine.js.map +1 -0
- package/dist/invariants/types.d.ts +75 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +2 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/modules.d.ts +75 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +87 -0
- package/dist/modules.js.map +1 -0
- package/dist/mutations/decidable.d.ts +26 -0
- package/dist/mutations/decidable.d.ts.map +1 -0
- package/dist/mutations/decidable.js +39 -0
- package/dist/mutations/decidable.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts +32 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -0
- package/dist/mutations/define-mutation.js +181 -0
- package/dist/mutations/define-mutation.js.map +1 -0
- package/dist/mutations/derive-edits.d.ts +75 -0
- package/dist/mutations/derive-edits.d.ts.map +1 -0
- package/dist/mutations/derive-edits.js +240 -0
- package/dist/mutations/derive-edits.js.map +1 -0
- package/dist/mutations/form.d.ts +63 -0
- package/dist/mutations/form.d.ts.map +1 -0
- package/dist/mutations/form.js +113 -0
- package/dist/mutations/form.js.map +1 -0
- package/dist/mutations/node-ref.d.ts +83 -0
- package/dist/mutations/node-ref.d.ts.map +1 -0
- package/dist/mutations/node-ref.js +113 -0
- package/dist/mutations/node-ref.js.map +1 -0
- package/dist/mutations/types.d.ts +136 -0
- package/dist/mutations/types.d.ts.map +1 -0
- package/dist/mutations/types.js +2 -0
- package/dist/mutations/types.js.map +1 -0
- package/dist/ops/log.d.ts +35 -0
- package/dist/ops/log.d.ts.map +1 -0
- package/dist/ops/log.js +103 -0
- package/dist/ops/log.js.map +1 -0
- package/dist/ops/types.d.ts +52 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +2 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/undo.d.ts +33 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +65 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/permissions/policy.d.ts +68 -0
- package/dist/permissions/policy.d.ts.map +1 -0
- package/dist/permissions/policy.js +191 -0
- package/dist/permissions/policy.js.map +1 -0
- package/dist/permissions/types.d.ts +78 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/persistence/memory.d.ts +6 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +31 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +59 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +22 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/presence.d.ts +38 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +50 -0
- package/dist/presence.js.map +1 -0
- package/dist/scaffold/domain.d.ts +8 -0
- package/dist/scaffold/domain.d.ts.map +1 -0
- package/dist/scaffold/domain.js +331 -0
- package/dist/scaffold/domain.js.map +1 -0
- package/dist/scaffold/index.d.ts +66 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +142 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lens.d.ts +31 -0
- package/dist/scaffold/lens.d.ts.map +1 -0
- package/dist/scaffold/lens.js +176 -0
- package/dist/scaffold/lens.js.map +1 -0
- package/dist/scaffold/names.d.ts +44 -0
- package/dist/scaffold/names.d.ts.map +1 -0
- package/dist/scaffold/names.js +69 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +41 -0
- package/dist/scaffold/project.d.ts.map +1 -0
- package/dist/scaffold/project.js +604 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/ui.d.ts +15 -0
- package/dist/scaffold/ui.d.ts.map +1 -0
- package/dist/scaffold/ui.js +536 -0
- package/dist/scaffold/ui.js.map +1 -0
- package/dist/schema/define-node.d.ts +132 -0
- package/dist/schema/define-node.d.ts.map +1 -0
- package/dist/schema/define-node.js +254 -0
- package/dist/schema/define-node.js.map +1 -0
- package/dist/schema/figures.d.ts +42 -0
- package/dist/schema/figures.d.ts.map +1 -0
- package/dist/schema/figures.js +220 -0
- package/dist/schema/figures.js.map +1 -0
- package/dist/schema/json-schema.d.ts +39 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +74 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +43 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +102 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/search.d.ts +215 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/settings.d.ts +30 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +284 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +660 -0
- package/dist/store.js.map +1 -0
- package/dist/studio-door.d.ts +187 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +20 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync/conflict.d.ts +37 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +56 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/engine.d.ts +118 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +341 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/google-calendar.d.ts +54 -0
- package/dist/sync/google-calendar.d.ts.map +1 -0
- package/dist/sync/google-calendar.js +167 -0
- package/dist/sync/google-calendar.js.map +1 -0
- package/dist/sync/types.d.ts +125 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/temporal/effectivity.d.ts +75 -0
- package/dist/temporal/effectivity.d.ts.map +1 -0
- package/dist/temporal/effectivity.js +89 -0
- package/dist/temporal/effectivity.js.map +1 -0
- package/dist/testing.d.ts +63 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +194 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contrast.d.ts +47 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +172 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/derive.d.ts +81 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +171 -0
- package/dist/theme/derive.js.map +1 -0
- package/dist/theme/kit.d.ts +106 -0
- package/dist/theme/kit.d.ts.map +1 -0
- package/dist/theme/kit.js +84 -0
- package/dist/theme/kit.js.map +1 -0
- package/dist/theme/palettes.d.ts +32 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +96 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/types.d.ts +131 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +23 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/views/types.d.ts +89 -0
- package/dist/views/types.d.ts.map +1 -0
- package/dist/views/types.js +88 -0
- package/dist/views/types.js.map +1 -0
- package/dist/watched.d.ts +33 -0
- package/dist/watched.d.ts.map +1 -0
- package/dist/watched.js +50 -0
- package/dist/watched.js.map +1 -0
- package/dist/who.d.ts +26 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +20 -0
- package/dist/who.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single declaration everything else derives from. Views, agent tool
|
|
3
|
+
* schemas, drag legality, aggregate contents and accessibility labels all
|
|
4
|
+
* read this — nothing is sealed, every derived value stays inspectable.
|
|
5
|
+
*/
|
|
6
|
+
export function defineNode(kind, spec) {
|
|
7
|
+
return {
|
|
8
|
+
...spec,
|
|
9
|
+
kind,
|
|
10
|
+
edges: (spec.edges ?? {}),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Whether a node is CURRENT under its kind's declared lifecycle.
|
|
15
|
+
*
|
|
16
|
+
* True when the kind declares no lifecycle — currency is opt-in, and a kind
|
|
17
|
+
* that never retires anything should not pay for the concept. `today` is
|
|
18
|
+
* injectable so a test (or a view pinned to a survey date) can ask about a
|
|
19
|
+
* different day; it defaults to the real one.
|
|
20
|
+
*/
|
|
21
|
+
export function isCurrent(definition, node, today = new Date().toISOString().slice(0, 10)) {
|
|
22
|
+
const lifecycle = definition?.lifecycle;
|
|
23
|
+
if (!lifecycle)
|
|
24
|
+
return true;
|
|
25
|
+
const value = node[lifecycle.field];
|
|
26
|
+
if (lifecycle.retired === "date") {
|
|
27
|
+
// No date means no expiry: an open-ended node is current for ever.
|
|
28
|
+
if (typeof value !== "string" || value.length === 0)
|
|
29
|
+
return true;
|
|
30
|
+
return value >= today;
|
|
31
|
+
}
|
|
32
|
+
return !lifecycle.retired.includes(value);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* WHAT TELLS TWO SAME-NAMED THINGS APART, among the nodes a person is
|
|
36
|
+
* choosing from. A single and its album are both "Blue Hour", and every
|
|
37
|
+
* picker, every ask and the Find strip listed "Blue Hour, Blue Hour": a
|
|
38
|
+
* choice nobody could make. For each node whose name another in the list
|
|
39
|
+
* shares, the first fact that differs between them — "single" and "album",
|
|
40
|
+
* or the dates — else its kind, else its id. Nodes with a name of their
|
|
41
|
+
* own get nothing.
|
|
42
|
+
*/
|
|
43
|
+
export function tellApart(nodes, definitionOf) {
|
|
44
|
+
const apart = new Map();
|
|
45
|
+
const byName = new Map();
|
|
46
|
+
for (const node of nodes) {
|
|
47
|
+
const name = labelOf(definitionOf(node.kind), node).trim().toLowerCase();
|
|
48
|
+
byName.set(name, [...(byName.get(name) ?? []), node]);
|
|
49
|
+
}
|
|
50
|
+
for (const same of byName.values()) {
|
|
51
|
+
if (same.length < 2)
|
|
52
|
+
continue;
|
|
53
|
+
const byKind = new Map();
|
|
54
|
+
for (const node of same)
|
|
55
|
+
byKind.set(node.kind, [...(byKind.get(node.kind) ?? []), node]);
|
|
56
|
+
for (const [kind, alike] of byKind) {
|
|
57
|
+
// One of its kind among namesakes of other kinds: the kind is what differs.
|
|
58
|
+
if (alike.length === 1) {
|
|
59
|
+
apart.set(alike[0].id, nounOf(definitionOf(kind), kind));
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const facts = alike.map((node) => new Map(readableFields(node, definitionOf(node.kind)).map((field) => [field.key, field.alone])));
|
|
63
|
+
const keys = [...new Set(facts.flatMap((fact) => [...fact.keys()]))];
|
|
64
|
+
// A word before a number: "single" and "album" say more than two dates.
|
|
65
|
+
const wordy = (key) => facts.every((fact) => !/\d/.test(fact.get(key) ?? ""));
|
|
66
|
+
const ordered = [...keys.filter(wordy), ...keys.filter((key) => !wordy(key))];
|
|
67
|
+
const telling = ordered.find((key) => new Set(facts.map((fact) => fact.get(key) ?? "")).size === alike.length);
|
|
68
|
+
alike.forEach((node, at) => {
|
|
69
|
+
const fact = telling ? facts[at].get(telling) : undefined;
|
|
70
|
+
apart.set(node.id, fact ?? node.id);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return apart;
|
|
75
|
+
}
|
|
76
|
+
/** Resolves a node's display label, honouring the declaration's override. */
|
|
77
|
+
export function labelOf(definition, node) {
|
|
78
|
+
if (definition?.label) {
|
|
79
|
+
return definition.label(node);
|
|
80
|
+
}
|
|
81
|
+
const own = node["label"];
|
|
82
|
+
return typeof own === "string" && own.length > 0 ? own : node.id;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Prose, shortened to a length, at a WORD BOUNDARY.
|
|
86
|
+
*
|
|
87
|
+
* Every app here had `text.slice(0, 60)` in its label function, and every one
|
|
88
|
+
* of them produced headings like "Hold the banked hour for a night s" — cut
|
|
89
|
+
* mid-word, with no ellipsis, in the largest type on the page. It is the
|
|
90
|
+
* obvious thing to write and it is wrong every time, so the framework should
|
|
91
|
+
* own it rather than leaving each app to discover it.
|
|
92
|
+
*
|
|
93
|
+
* A single word longer than the limit is still cut, because the alternative
|
|
94
|
+
* is a heading that ignores the limit it was given.
|
|
95
|
+
*/
|
|
96
|
+
export function summarise(text, max = 60) {
|
|
97
|
+
const clean = text.trim().replace(/\s+/g, " ");
|
|
98
|
+
if (clean.length <= max)
|
|
99
|
+
return clean;
|
|
100
|
+
const cut = clean.slice(0, max);
|
|
101
|
+
const boundary = cut.lastIndexOf(" ");
|
|
102
|
+
// A trailing comma or full stop before the ellipsis reads as a typo.
|
|
103
|
+
return `${(boundary > max * 0.5 ? cut.slice(0, boundary) : cut).replace(/[\s,.;:]+$/, "")}…`;
|
|
104
|
+
}
|
|
105
|
+
/** Resolves a node's prose description, used for a11y and tool text. */
|
|
106
|
+
export function describeNode(definition, node) {
|
|
107
|
+
if (definition?.describe) {
|
|
108
|
+
return definition.describe(node);
|
|
109
|
+
}
|
|
110
|
+
return `${node.kind} ${labelOf(definition, node)}`;
|
|
111
|
+
}
|
|
112
|
+
/** Never shown: identity and the name, which the heading already is. */
|
|
113
|
+
const NOT_A_FIELD = new Set(["id", "kind", "label"]);
|
|
114
|
+
/** `effectiveFrom` shown to a person is a schema leaking through a surface. */
|
|
115
|
+
export function humaniseField(field) {
|
|
116
|
+
const spaced = field
|
|
117
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
118
|
+
.replace(/[_-]+/g, " ")
|
|
119
|
+
.trim()
|
|
120
|
+
.toLowerCase();
|
|
121
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* A field in words, as the declaration says it: its `display.labels` entry,
|
|
125
|
+
* else the key spoken. Every sentence that names a field — "Nothing
|
|
126
|
+
* declared writes the planned time", a tooltip, a refusal — reads it here,
|
|
127
|
+
* so `plannedAt` never reaches a person from one surface while another says
|
|
128
|
+
* "Planned at".
|
|
129
|
+
*/
|
|
130
|
+
export function fieldWords(definition, key) {
|
|
131
|
+
return definition?.display?.labels?.[key] ?? humaniseField(key);
|
|
132
|
+
}
|
|
133
|
+
/*
|
|
134
|
+
* "a item" is the sound of generated prose.
|
|
135
|
+
*
|
|
136
|
+
* Every surface here writes sentences about a kind the author named —
|
|
137
|
+
* "Add a item", "Nothing you may do with a item", "from a item it is
|
|
138
|
+
* captioned" — and a kind is as likely to begin with a vowel as not. The
|
|
139
|
+
* article is therefore never a literal: it is derived from the word, in one
|
|
140
|
+
* place, so that the scaffolder, the checker and the strip cannot disagree.
|
|
141
|
+
*
|
|
142
|
+
* Sound, not spelling, decides it, and the two disagree in exactly two small
|
|
143
|
+
* families that domain vocabulary is full of: "a user", "a unit" (the "yoo"
|
|
144
|
+
* sound), and "an hour", "an heir" (the silent h). Both are listed rather
|
|
145
|
+
* than guessed at.
|
|
146
|
+
*/
|
|
147
|
+
const SOUNDS_LIKE_YOU = /^(u[nt]i|use|usu|uti|ubiq|eu|ewe|one|once)/;
|
|
148
|
+
const SILENT_H = /^(hour|honest|hono[ur]r?|heir)/;
|
|
149
|
+
/** "a" or "an", by how the word SOUNDS. */
|
|
150
|
+
export function article(word) {
|
|
151
|
+
const first = humaniseField(word).toLowerCase();
|
|
152
|
+
if (SILENT_H.test(first))
|
|
153
|
+
return "an";
|
|
154
|
+
if (SOUNDS_LIKE_YOU.test(first))
|
|
155
|
+
return "a";
|
|
156
|
+
return /^[aeiou]/.test(first) ? "an" : "a";
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* A kind in words, with its article: "an item", "a work order".
|
|
160
|
+
*
|
|
161
|
+
* Takes the declared id and speaks it — the hyphen in `work-order` is a
|
|
162
|
+
* identifier's punctuation, not a word's.
|
|
163
|
+
*/
|
|
164
|
+
export function withArticle(word) {
|
|
165
|
+
return `${article(word)} ${humaniseField(word).toLowerCase()}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* What one of a kind is called: its declared `noun`, else its id spoken.
|
|
169
|
+
* Every sentence about ONE of them — "Change the staff member", "a staff
|
|
170
|
+
* member called …", "Remove the staff member" — reads this, never the id.
|
|
171
|
+
*/
|
|
172
|
+
export function nounOf(definition, kind) {
|
|
173
|
+
return definition?.noun ?? humaniseField(kind).toLowerCase();
|
|
174
|
+
}
|
|
175
|
+
/** Whether `line` carries `value` as whole words: "2027 Subaru Forester" says "Subaru" and "2027", not "Sub". */
|
|
176
|
+
function saysAsWords(line, value) {
|
|
177
|
+
if (value.length === 0)
|
|
178
|
+
return false;
|
|
179
|
+
const escaped = value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
180
|
+
return new RegExp(`(^|[\\s·,(/])${escaped}($|[\\s·,)/])`).test(line);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* WHICH of a node's fields a person sees, and HOW each one reads.
|
|
184
|
+
*
|
|
185
|
+
* One implementation, because there were two: the record on a page and the
|
|
186
|
+
* summary on a card each decided this for themselves, and every rule — hide an
|
|
187
|
+
* ordering key, format minutes as a time, render a boolean as a word, drop a
|
|
188
|
+
* value the heading already said — had to be written into both and kept in
|
|
189
|
+
* step by hand. They diverged the day the second one was written, which is how
|
|
190
|
+
* a summary card ended up showing a list's ordering key as a chip reading "0"
|
|
191
|
+
* while the page beside it did not.
|
|
192
|
+
*
|
|
193
|
+
* `said` is what the surrounding view has already put on screen. A value the
|
|
194
|
+
* heading already carries is not information twice, it is the same sentence
|
|
195
|
+
* twice — and where the heading is a SHORTENED form of a field, an exact
|
|
196
|
+
* comparison never catches it, so the summary's stem is compared too.
|
|
197
|
+
*/
|
|
198
|
+
export function readableFields(node, definition, options = {}) {
|
|
199
|
+
const display = definition?.display;
|
|
200
|
+
const skip = new Set([...NOT_A_FIELD, ...(display?.hide ?? [])]);
|
|
201
|
+
const said = (options.said ?? []).filter((text) => Boolean(text));
|
|
202
|
+
const stems = said
|
|
203
|
+
.filter((text) => text.endsWith("…"))
|
|
204
|
+
.map((text) => text.replace(/…$/, "").trim())
|
|
205
|
+
.filter((stem) => stem.length > 12);
|
|
206
|
+
const fields = [];
|
|
207
|
+
for (const [key, value] of Object.entries(node)) {
|
|
208
|
+
if (skip.has(key) || value === undefined || value === null)
|
|
209
|
+
continue;
|
|
210
|
+
const format = display?.format?.[key];
|
|
211
|
+
/*
|
|
212
|
+
* A NESTED OBJECT HAS NO ONE-LINE RENDERING, and inventing one is worse
|
|
213
|
+
* than leaving it to a view that knows what it is.
|
|
214
|
+
*
|
|
215
|
+
* That was true of an object and was not checked of an ARRAY of them,
|
|
216
|
+
* which fell through to `join(", ")` — so a piece of ground with a
|
|
217
|
+
* five-corner outline had a field on its record reading "[object
|
|
218
|
+
* Object], [object Object], [object Object], [object Object]". Nobody
|
|
219
|
+
* wrote that; nobody could have read it. The shape is drawn on the map
|
|
220
|
+
* and belongs there, not in a list of words.
|
|
221
|
+
*
|
|
222
|
+
* A declaration that HAS a one-line rendering says so with `format`,
|
|
223
|
+
* and then it is the declaration's sentence rather than this one's
|
|
224
|
+
* guess — "5 corners" is a useful thing to say and only the app knows
|
|
225
|
+
* that the numbers are corners.
|
|
226
|
+
*/
|
|
227
|
+
const nested = typeof value === "object" &&
|
|
228
|
+
(!Array.isArray(value) || value.some((one) => typeof one === "object" && one !== null));
|
|
229
|
+
if (nested && format === undefined)
|
|
230
|
+
continue;
|
|
231
|
+
const text = format
|
|
232
|
+
? format(value)
|
|
233
|
+
: Array.isArray(value)
|
|
234
|
+
? value.join(", ")
|
|
235
|
+
: typeof value === "boolean"
|
|
236
|
+
? // Nobody says "false". A boolean is a state, and the words for a
|
|
237
|
+
// state are words.
|
|
238
|
+
value
|
|
239
|
+
? "Yes"
|
|
240
|
+
: "No"
|
|
241
|
+
: String(value);
|
|
242
|
+
if (said.includes(text) || stems.some((stem) => text.startsWith(stem)))
|
|
243
|
+
continue;
|
|
244
|
+
if (options.glance && (typeof value === "string" || typeof value === "number") && said.some((line) => saysAsWords(line, text)))
|
|
245
|
+
continue;
|
|
246
|
+
const label = fieldWords(definition, key);
|
|
247
|
+
const alone = typeof value === "number" ? `${label} ${text}` : typeof value === "boolean" ? `${label}: ${text.toLowerCase()}` : text;
|
|
248
|
+
fields.push({ key, label, value: text, alone });
|
|
249
|
+
if (fields.length >= (options.limit ?? 10))
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
return fields;
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=define-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-node.js","sourceRoot":"","sources":["../../src/schema/define-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** A kind's figure: inline SVG, or the name of one from the shipped set. */
|
|
2
|
+
export type Figure = string;
|
|
3
|
+
/**
|
|
4
|
+
* THE SHIPPED SET — a small vocabulary, so a first app has something true
|
|
5
|
+
* to point at before anybody draws anything.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately few and deliberately generic: the things almost every domain
|
|
8
|
+
* turns out to have. A kind that is none of these declares its own, and the
|
|
9
|
+
* agent draws it (see `graview figure`).
|
|
10
|
+
*
|
|
11
|
+
* Each is drawn on a 24-unit box at the same three-quarter angle, in a
|
|
12
|
+
* single stroke weight, with no fill: the isometric city's own language,
|
|
13
|
+
* so twelve of them on one screen read as one drawing rather than as
|
|
14
|
+
* twelve clip-art imports.
|
|
15
|
+
*/
|
|
16
|
+
export declare const FIGURES: Readonly<Record<string, string>>;
|
|
17
|
+
export declare const FIGURE_NAMES: string[];
|
|
18
|
+
/** The SVG a figure names, or the figure itself when it is already one. */
|
|
19
|
+
export declare function figureSvg(figure: Figure | undefined): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* What is wrong with a figure, in the words of somebody about to fix it.
|
|
22
|
+
*
|
|
23
|
+
* Art with no `viewBox` cannot be sized by anything that draws it, a
|
|
24
|
+
* literal colour ignores the scheme and the kind's hue, a `fill` that is
|
|
25
|
+
* not `none` turns a line drawing into a blob at chip size, a name that is
|
|
26
|
+
* not in the shipped set is a silent blank — and anything in the markup
|
|
27
|
+
* that is not a drawing is not a figure at all.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* THE BRIEF A FIGURE IS DRAWN FROM — the rules, in the words somebody draws
|
|
31
|
+
* to, with a shipped figure beside them as the style.
|
|
32
|
+
*
|
|
33
|
+
* The shipped set is nine, deliberately generic, and any domain that is not
|
|
34
|
+
* an abstract tracker runs out of it immediately: an outdoors product needed
|
|
35
|
+
* eleven figures and had to draw ten. Growing the set would move the wall
|
|
36
|
+
* rather than remove it, so the authoring loop is the answer — and it works
|
|
37
|
+
* through the door every app has, which is a prompt to copy and an answer to
|
|
38
|
+
* paste. No key, no vendor, no seam the CLI has no business holding.
|
|
39
|
+
*/
|
|
40
|
+
export declare function figureBrief(kind: string, from: string): string;
|
|
41
|
+
export declare function figureFaults(figure: Figure): readonly string[];
|
|
42
|
+
//# sourceMappingURL=figures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figures.d.ts","sourceRoot":"","sources":["../../src/schema/figures.ts"],"names":[],"mappings":"AAuBA,4EAA4E;AAC5E,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyEpD,CAAC;AAEF,eAAO,MAAM,YAAY,UAAuB,CAAC;AAEjD,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGxE;AA4BD;;;;;;;;GAQG;AACH;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAuB9D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAuC9D"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A KIND HAS A FIGURE: a drawing of the THING, not an emblem for it.
|
|
3
|
+
*
|
|
4
|
+
* Every kind is drawn the same way today — a coloured dot on its chips, a
|
|
5
|
+
* plural on its district, an isometric block at altitude, a heading on its
|
|
6
|
+
* page. The picture would say far more if a kind carried a drawing of what
|
|
7
|
+
* it represents: a person's silhouette, a plot of ground, a vehicle, a
|
|
8
|
+
* cleat. The scene, the Graview and, where it fits, the pages then draw it
|
|
9
|
+
* wherever the kind is drawn, from one declaration.
|
|
10
|
+
*
|
|
11
|
+
* HONEST GEOMETRY, and it is the whole rule here. A figure is line art of
|
|
12
|
+
* the thing — single weight, drawn from the isometric city's own three-
|
|
13
|
+
* quarter angle, no fill but the ground's. It is never a decorative badge, a
|
|
14
|
+
* rounded-square app icon, or a shape chosen because it filled the space.
|
|
15
|
+
* A kind whose figure is a circle with a smaller circle in it has learnt
|
|
16
|
+
* nothing about itself and taught the reader nothing.
|
|
17
|
+
*
|
|
18
|
+
* Everything is `currentColor`, so a figure takes the scheme, the kind's own
|
|
19
|
+
* hue and the brand's ink without being redrawn; one `viewBox`, so every
|
|
20
|
+
* surface can size it; and it must read at twenty pixels, because that is
|
|
21
|
+
* the size a chip gives it.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* THE SHIPPED SET — a small vocabulary, so a first app has something true
|
|
25
|
+
* to point at before anybody draws anything.
|
|
26
|
+
*
|
|
27
|
+
* Deliberately few and deliberately generic: the things almost every domain
|
|
28
|
+
* turns out to have. A kind that is none of these declares its own, and the
|
|
29
|
+
* agent draws it (see `graview figure`).
|
|
30
|
+
*
|
|
31
|
+
* Each is drawn on a 24-unit box at the same three-quarter angle, in a
|
|
32
|
+
* single stroke weight, with no fill: the isometric city's own language,
|
|
33
|
+
* so twelve of them on one screen read as one drawing rather than as
|
|
34
|
+
* twelve clip-art imports.
|
|
35
|
+
*/
|
|
36
|
+
export const FIGURES = {
|
|
37
|
+
/**
|
|
38
|
+
* Somebody, STANDING. Head, torso, arms, legs — a figure on the ground.
|
|
39
|
+
*
|
|
40
|
+
* It was a head and shoulders, and at chip size that read as a person the
|
|
41
|
+
* way any shape does when it is four pixels tall. Standing a district on
|
|
42
|
+
* it showed what it actually was: two crescents, one over an open arc,
|
|
43
|
+
* because a head drawn as two arcs is a circle only while it is too small
|
|
44
|
+
* to see. A figure has to be the thing at every size it is drawn.
|
|
45
|
+
*/
|
|
46
|
+
person: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
47
|
+
'<circle cx="11.6" cy="5.4" r="2.5"/>' +
|
|
48
|
+
'<path d="M7.9 12.4c0-2.1 1.7-3.8 3.7-3.8s3.7 1.7 3.7 3.8v3.2H7.9z"/>' +
|
|
49
|
+
'<path d="M8 12.6 6.4 17.2"/><path d="M15.2 12.6 16.8 17.2"/>' +
|
|
50
|
+
'<path d="M9.8 15.6v5"/><path d="M13.4 15.6v5"/></svg>',
|
|
51
|
+
/** A piece of ground, seen from above and to the side. */
|
|
52
|
+
plot: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
53
|
+
'<path d="M2.6 9.4 12 4.6l9.4 4.8-9.4 4.8z"/><path d="M2.6 9.4v4.4l9.4 4.8 9.4-4.8V9.4"/>' +
|
|
54
|
+
'<path d="M12 14.2v4.4"/><path d="M7 11.9v3"/><path d="M17 11.9v3"/></svg>',
|
|
55
|
+
/** A thing with a lid, standing on the ground: a box, a crate, a case. */
|
|
56
|
+
box: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
57
|
+
'<path d="M3.4 7.9 12 3.6l8.6 4.3-8.6 4.3z"/><path d="M3.4 7.9v8.2L12 20.4l8.6-4.3V7.9"/>' +
|
|
58
|
+
'<path d="M12 12.2v8.2"/></svg>',
|
|
59
|
+
/** Something to be done: a card with a line struck across its corner. */
|
|
60
|
+
task: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
61
|
+
'<path d="M4.4 6.6 12 2.9l7.6 3.7v9.5L12 19.8 4.4 16.1z"/><path d="M12 12.4v7.4"/>' +
|
|
62
|
+
'<path d="M4.4 6.6 12 10.3l7.6-3.7"/><path d="M8 9.6l2.4 2.4L16 8.4"/></svg>',
|
|
63
|
+
/** A stretch of time: a block with its hours ruled across it. */
|
|
64
|
+
shift: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
65
|
+
'<path d="M3.2 8.2 12 4l8.8 4.2-8.8 4.2z"/><path d="M3.2 8.2v7.2L12 19.6l8.8-4.2V8.2"/>' +
|
|
66
|
+
'<path d="M12 12.4v7.2"/><path d="M6.6 10.8v3.4"/><path d="M9.3 12v3.4"/></svg>',
|
|
67
|
+
/** A place things live: a tray, open at the front. */
|
|
68
|
+
list: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
69
|
+
'<path d="M2.8 10.4 12 6l9.2 4.4-9.2 4.4z"/><path d="M2.8 10.4v3.2L12 18l9.2-4.4v-3.2"/>' +
|
|
70
|
+
'<path d="M6.6 8.6 15.8 13"/><path d="M9.4 7.2 18.6 11.6"/></svg>',
|
|
71
|
+
/** Something to drive: a body on wheels, seen from three-quarters. */
|
|
72
|
+
vehicle: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
73
|
+
'<path d="M2.8 14.2 5 9.4l8.6-1.6 5.4 3-1 3.6z"/><path d="M2.8 14.2v2.2h2.4"/>' +
|
|
74
|
+
'<path d="M18 16.4h1.9l.1-2.2"/><circle cx="7.6" cy="16.6" r="1.9"/><circle cx="16.1" cy="16.6" r="1.9"/>' +
|
|
75
|
+
'<path d="M8.6 8.2 9.8 12l7.2-1"/></svg>',
|
|
76
|
+
/**
|
|
77
|
+
* A rule: a set square STANDING on the ground, graduated up its upright.
|
|
78
|
+
*
|
|
79
|
+
* It was a ruler lying across the box on the diagonal, which is a flat
|
|
80
|
+
* thing floating at an angle — fine as a glyph, nothing at all as a
|
|
81
|
+
* building. A standard is an object you stand a thing against.
|
|
82
|
+
*/
|
|
83
|
+
rule: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
84
|
+
'<path d="M5.4 19.4V6.6l12 12.8z"/>' +
|
|
85
|
+
'<path d="M5.4 6.6 7.6 5.5l12 12.8-2.2 1.1"/>' +
|
|
86
|
+
'<path d="M5.4 19.4 7.6 18.3h12"/>' +
|
|
87
|
+
'<path d="M5.4 10.1h1.7"/><path d="M5.4 13.3h1.7"/><path d="M5.4 16.5h1.7"/></svg>',
|
|
88
|
+
/**
|
|
89
|
+
* A note somebody left: a leaf of paper standing up, seen from three
|
|
90
|
+
* quarters, its corner turned and two lines written on it.
|
|
91
|
+
*
|
|
92
|
+
* It was a flat document icon — the one figure in the set drawn square to
|
|
93
|
+
* the page while everything around it stood in the city's own projection,
|
|
94
|
+
* which is exactly the clip-art import the house style forbids.
|
|
95
|
+
*/
|
|
96
|
+
note: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">' +
|
|
97
|
+
'<path d="M6.2 6.2 14.8 10.5v9L6.2 15.2z"/>' +
|
|
98
|
+
'<path d="M12.4 9.3 14.8 10.5l-.6 2.3"/>' +
|
|
99
|
+
'<path d="M8.2 10.6 12.8 12.9"/><path d="M8.2 13.2 11.4 14.8"/></svg>',
|
|
100
|
+
};
|
|
101
|
+
export const FIGURE_NAMES = Object.keys(FIGURES);
|
|
102
|
+
/** The SVG a figure names, or the figure itself when it is already one. */
|
|
103
|
+
export function figureSvg(figure) {
|
|
104
|
+
if (!figure)
|
|
105
|
+
return undefined;
|
|
106
|
+
return FIGURES[figure] ?? (figure.trimStart().startsWith("<svg") ? figure : undefined);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A FIGURE IS LINE ART, and these are the only things line art is made of.
|
|
110
|
+
*
|
|
111
|
+
* Everything drawn here is declared in code the bundle already runs — until
|
|
112
|
+
* a figure arrives from somewhere else. A model asked to draw a kind can
|
|
113
|
+
* answer with an `<svg>` carrying a `<script>`, an `onload`, or a remote
|
|
114
|
+
* `href`, and a drawing is inserted as markup wherever it is shown; a check
|
|
115
|
+
* of the house style alone would have passed all three, because none of
|
|
116
|
+
* them is a colour or a viewBox. So the vocabulary is closed: these
|
|
117
|
+
* elements, these attributes, and anything else is a fault with a name.
|
|
118
|
+
*
|
|
119
|
+
* It is one judgement rather than a second sanitiser beside the first,
|
|
120
|
+
* because the surfaces that draw a figure already ask this function's
|
|
121
|
+
* caller — `graview check`, `graview figure`, the agent that draws one —
|
|
122
|
+
* whether the drawing is any good.
|
|
123
|
+
*/
|
|
124
|
+
const DRAWING_ELEMENTS = new Set([
|
|
125
|
+
"svg", "g", "title", "desc", "path", "circle", "ellipse", "rect", "line", "polyline", "polygon",
|
|
126
|
+
]);
|
|
127
|
+
const DRAWING_ATTRIBUTES = new Set([
|
|
128
|
+
"viewbox", "xmlns", "width", "height", "fill", "fill-rule", "clip-rule", "stroke", "stroke-width",
|
|
129
|
+
"stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "stroke-miterlimit",
|
|
130
|
+
"opacity", "fill-opacity", "stroke-opacity", "vector-effect", "transform", "d", "cx", "cy", "r",
|
|
131
|
+
"rx", "ry", "x", "y", "x1", "y1", "x2", "y2", "points", "role", "aria-hidden", "focusable",
|
|
132
|
+
]);
|
|
133
|
+
/**
|
|
134
|
+
* What is wrong with a figure, in the words of somebody about to fix it.
|
|
135
|
+
*
|
|
136
|
+
* Art with no `viewBox` cannot be sized by anything that draws it, a
|
|
137
|
+
* literal colour ignores the scheme and the kind's hue, a `fill` that is
|
|
138
|
+
* not `none` turns a line drawing into a blob at chip size, a name that is
|
|
139
|
+
* not in the shipped set is a silent blank — and anything in the markup
|
|
140
|
+
* that is not a drawing is not a figure at all.
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* THE BRIEF A FIGURE IS DRAWN FROM — the rules, in the words somebody draws
|
|
144
|
+
* to, with a shipped figure beside them as the style.
|
|
145
|
+
*
|
|
146
|
+
* The shipped set is nine, deliberately generic, and any domain that is not
|
|
147
|
+
* an abstract tracker runs out of it immediately: an outdoors product needed
|
|
148
|
+
* eleven figures and had to draw ten. Growing the set would move the wall
|
|
149
|
+
* rather than remove it, so the authoring loop is the answer — and it works
|
|
150
|
+
* through the door every app has, which is a prompt to copy and an answer to
|
|
151
|
+
* paste. No key, no vendor, no seam the CLI has no business holding.
|
|
152
|
+
*/
|
|
153
|
+
export function figureBrief(kind, from) {
|
|
154
|
+
return [
|
|
155
|
+
`Draw a figure for a node kind called "${kind}": ${from}.`,
|
|
156
|
+
"",
|
|
157
|
+
"It is line art of the THING, not an emblem for it — never a badge, never a",
|
|
158
|
+
"rounded-square app icon, never a shape chosen because it filled the space.",
|
|
159
|
+
"Draw it from a three-quarter isometric angle, the same angle as a city seen",
|
|
160
|
+
"from above and to the side, so a dozen of them on one screen read as one",
|
|
161
|
+
"drawing rather than as twelve clip-art imports.",
|
|
162
|
+
"",
|
|
163
|
+
"Answer with the SVG and nothing else. It must:",
|
|
164
|
+
' - be one <svg> with viewBox="0 0 24 24" and no width or height;',
|
|
165
|
+
' - stroke with currentColor, fill="none", stroke-width 1.4,',
|
|
166
|
+
" stroke-linecap and stroke-linejoin round;",
|
|
167
|
+
" - use only path, circle, ellipse, rect, line, polyline, polygon and g;",
|
|
168
|
+
" - carry no literal colour anywhere, no class, no style, no id;",
|
|
169
|
+
" - READ AT TWENTY PIXELS, because that is the size a chip gives it.",
|
|
170
|
+
"",
|
|
171
|
+
"This is the shipped figure for a person, as the style to match:",
|
|
172
|
+
FIGURES["person"] ?? "",
|
|
173
|
+
"",
|
|
174
|
+
`Then: graview figure <entry> --kind ${kind} --judge <the file you saved it in>`,
|
|
175
|
+
].join("\n");
|
|
176
|
+
}
|
|
177
|
+
export function figureFaults(figure) {
|
|
178
|
+
if (!figure.trimStart().startsWith("<svg")) {
|
|
179
|
+
return FIGURE_NAMES.includes(figure)
|
|
180
|
+
? []
|
|
181
|
+
: [`"${figure}" is not one of the shipped figures (${FIGURE_NAMES.join(", ")}).`];
|
|
182
|
+
}
|
|
183
|
+
const faults = [];
|
|
184
|
+
const box = /viewBox\s*=\s*"([^"]+)"/.exec(figure);
|
|
185
|
+
if (!box)
|
|
186
|
+
faults.push("it has no viewBox, so nothing that draws it can size it.");
|
|
187
|
+
else if (box[1].trim().split(/\s+/).length !== 4) {
|
|
188
|
+
faults.push(`its viewBox "${box[1]}" is not four numbers.`);
|
|
189
|
+
}
|
|
190
|
+
/*
|
|
191
|
+
* A literal colour anywhere. `currentColor` is what lets one drawing take
|
|
192
|
+
* the scheme, the kind's hue and the brand's ink without being redrawn —
|
|
193
|
+
* and a figure that hard-codes #333 is invisible in one of the two
|
|
194
|
+
* schemes, which nobody notices until somebody switches.
|
|
195
|
+
*/
|
|
196
|
+
const literal = /(?:stroke|fill)\s*=\s*"(?!none|currentColor)([^"]+)"/.exec(figure);
|
|
197
|
+
if (literal) {
|
|
198
|
+
faults.push(`it paints with "${literal[1]}" — use currentColor so it takes the scheme and the kind's hue.`);
|
|
199
|
+
}
|
|
200
|
+
if (!/stroke\s*=\s*"currentColor"/.test(figure)) {
|
|
201
|
+
faults.push('nothing in it is stroked with currentColor, so it will not be drawn in the kind\'s ink.');
|
|
202
|
+
}
|
|
203
|
+
/*
|
|
204
|
+
* THE VOCABULARY IS CLOSED. Named rather than stripped: a drawing with a
|
|
205
|
+
* script in it is not a drawing with a fixable blemish, and whoever is
|
|
206
|
+
* about to keep it should be told what was in it.
|
|
207
|
+
*/
|
|
208
|
+
for (const [, element] of figure.matchAll(/<\s*\/?\s*([a-zA-Z][\w:-]*)/g)) {
|
|
209
|
+
const name = (element ?? "").toLowerCase();
|
|
210
|
+
if (!DRAWING_ELEMENTS.has(name))
|
|
211
|
+
faults.push(`it contains <${element}>, which is not something a line drawing is made of.`);
|
|
212
|
+
}
|
|
213
|
+
for (const [, attribute] of figure.matchAll(/[\s"']([a-zA-Z][\w:-]*)\s*=/g)) {
|
|
214
|
+
const name = (attribute ?? "").toLowerCase();
|
|
215
|
+
if (!DRAWING_ATTRIBUTES.has(name))
|
|
216
|
+
faults.push(`it carries ${attribute}, which is not a drawing attribute.`);
|
|
217
|
+
}
|
|
218
|
+
return [...new Set(faults)];
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=figures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figures.js","sourceRoot":"","sources":["../../src/schema/figures.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { AnySchema } from "./schema.js";
|
|
3
|
+
import type { AnyNodeDefinition } from "./types.js";
|
|
4
|
+
export type JsonSchema = Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* One source, three outputs: the same Zod declaration produces runtime
|
|
7
|
+
* validation, TypeScript inference, and the JSON Schema an agent tool
|
|
8
|
+
* definition needs. Nothing is written twice, so nothing drifts.
|
|
9
|
+
*/
|
|
10
|
+
export declare function toJsonSchema(schema: z.ZodType): JsonSchema;
|
|
11
|
+
/** JSON Schema for one node kind, including its id and kind discriminator. */
|
|
12
|
+
export declare function nodeJsonSchema(definition: AnyNodeDefinition): JsonSchema;
|
|
13
|
+
export interface MutationToolSchema {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly title?: string;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
readonly inputSchema: JsonSchema;
|
|
18
|
+
/** Arguments that name graph nodes, and the kinds each accepts. */
|
|
19
|
+
readonly nodeRefs: readonly {
|
|
20
|
+
name: string;
|
|
21
|
+
kinds: readonly string[];
|
|
22
|
+
optional: boolean;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Derives an agent-facing tool schema from a mutation declaration. The
|
|
27
|
+
* `nodeRefs` metadata travels alongside so a caller can resolve "a person"
|
|
28
|
+
* to real ids without the agent guessing.
|
|
29
|
+
*/
|
|
30
|
+
export declare function mutationToolSchema(mutation: {
|
|
31
|
+
name: string;
|
|
32
|
+
title?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
input: z.ZodType;
|
|
35
|
+
creates?: readonly string[];
|
|
36
|
+
}): MutationToolSchema;
|
|
37
|
+
/** Every node kind's JSON Schema, keyed by kind. */
|
|
38
|
+
export declare function schemaJson(schema: AnySchema): Record<string, JsonSchema>;
|
|
39
|
+
//# sourceMappingURL=json-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../../src/schema/json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,UAAU,CAU1D;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,UAAU,EAAE,iBAAiB,GAAG,UAAU,CAOxE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC7F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,GAAG,kBAAkB,CAkCrB;AAED,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAMxE"}
|