@refrakt-md/runes 0.34.0 → 0.35.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/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -7
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -10
- package/dist/index.js.map +1 -1
- package/dist/layouts/grid.d.ts +1 -1
- package/dist/lib/index.d.ts +28 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +47 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/resolver.d.ts.map +1 -1
- package/dist/lib/resolver.js +16 -1
- package/dist/lib/resolver.js.map +1 -1
- package/dist/lib/schema-table.d.ts +176 -0
- package/dist/lib/schema-table.d.ts.map +1 -0
- package/dist/lib/schema-table.js +427 -0
- package/dist/lib/schema-table.js.map +1 -0
- package/dist/reference.d.ts +33 -0
- package/dist/reference.d.ts.map +1 -1
- package/dist/reference.js +32 -1
- package/dist/reference.js.map +1 -1
- package/dist/rune.d.ts +0 -2
- package/dist/rune.d.ts.map +1 -1
- package/dist/rune.js +0 -1
- package/dist/rune.js.map +1 -1
- package/dist/schema-row.d.ts +89 -0
- package/dist/schema-row.d.ts.map +1 -0
- package/dist/schema-row.js +78 -0
- package/dist/schema-row.js.map +1 -0
- package/dist/seo.d.ts +9 -0
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +84 -7
- package/dist/seo.js.map +1 -1
- package/dist/tags/accordion.d.ts +58 -0
- package/dist/tags/accordion.d.ts.map +1 -1
- package/dist/tags/accordion.js +47 -15
- package/dist/tags/accordion.js.map +1 -1
- package/dist/tags/blog.d.ts.map +1 -1
- package/dist/tags/blog.js +9 -1
- package/dist/tags/blog.js.map +1 -1
- package/dist/tags/breadcrumb.d.ts +30 -0
- package/dist/tags/breadcrumb.d.ts.map +1 -1
- package/dist/tags/breadcrumb.js +28 -21
- package/dist/tags/breadcrumb.js.map +1 -1
- package/dist/tags/budget.d.ts.map +1 -1
- package/dist/tags/budget.js +7 -1
- package/dist/tags/budget.js.map +1 -1
- package/dist/tags/datatable.d.ts.map +1 -1
- package/dist/tags/datatable.js +6 -1
- package/dist/tags/datatable.js.map +1 -1
- package/dist/tags/embed.d.ts +8 -0
- package/dist/tags/embed.d.ts.map +1 -1
- package/dist/tags/embed.js +19 -6
- package/dist/tags/embed.js.map +1 -1
- package/dist/tags/figure.d.ts +7 -0
- package/dist/tags/figure.d.ts.map +1 -1
- package/dist/tags/figure.js +14 -5
- package/dist/tags/figure.js.map +1 -1
- package/dist/tags/gallery.d.ts.map +1 -1
- package/dist/tags/gallery.js +8 -1
- package/dist/tags/gallery.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import Markdoc from '@markdoc/markdoc';
|
|
2
|
+
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
|
3
|
+
declare const Tag: typeof Markdoc.Tag;
|
|
4
|
+
/**
|
|
5
|
+
* The declarative schema.org table, and the applier that realises it
|
|
6
|
+
* (SPEC-130 / WORK-565).
|
|
7
|
+
*
|
|
8
|
+
* ## Why this is data consulted at transform time, not engine config
|
|
9
|
+
*
|
|
10
|
+
* The obvious home is the identity transform engine, and it does not work.
|
|
11
|
+
* `packages/content/src/site.ts` never applies the engine — it runs
|
|
12
|
+
* `Markdoc.transform`, then `extractSeo`, and `collectJsonLd` *derives* the
|
|
13
|
+
* JSON-LD by walking that tree for `typeof`. The engine runs later, at render
|
|
14
|
+
* time, so schema emitted there would reach the HTML and never reach the
|
|
15
|
+
* JSON-LD.
|
|
16
|
+
*
|
|
17
|
+
* So the table is an option to `createContentModelSchema`, sitting beside the
|
|
18
|
+
* rune's other self-declarations (`sections`, `mediaSlots`, `provides`, `base`),
|
|
19
|
+
* and the applier runs on the rune's own output.
|
|
20
|
+
*
|
|
21
|
+
* ## Three resolution strategies, and why the third exists
|
|
22
|
+
*
|
|
23
|
+
* `createComponentRenderable` drops a property `<meta>` that no `schema:` map
|
|
24
|
+
* names — it is classified pure data and its value is already in the bag. Once
|
|
25
|
+
* runes stop declaring `schema:` themselves, those nodes are gone by the time
|
|
26
|
+
* the applier runs. The bag is the recovery:
|
|
27
|
+
*
|
|
28
|
+
* 1. **Stamp in place** — a named node that survives into the output.
|
|
29
|
+
* 2. **Rebuild from the bag** — a value-only source whose carrier was dropped.
|
|
30
|
+
* 3. **Synthesise an entity** — a nested span built from either of the above.
|
|
31
|
+
*
|
|
32
|
+
* That is why `createComponentRenderable` needs no knowledge of schema at all:
|
|
33
|
+
* it simply always treats property metas as pure data, which is what it already
|
|
34
|
+
* does when `schema:` is absent.
|
|
35
|
+
*
|
|
36
|
+
* ## Name resolution is attribute-agnostic, deliberately
|
|
37
|
+
*
|
|
38
|
+
* A source resolves whether it surfaces as `data-name` or `data-field`, and the
|
|
39
|
+
* applier never branches on which. SPEC-133 moves ~97 nodes between `properties`
|
|
40
|
+
* and `refs`; under this rule every one of those moves is a no-op for every
|
|
41
|
+
* table, because the table keys on a name in the rune's flat namespace
|
|
42
|
+
* (ADR-008), not on the attribute that happens to carry it.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Marks a `typeof` the **author** stated, which a parent may not overrule.
|
|
46
|
+
*
|
|
47
|
+
* D9's default stands: a parent's `children` row retypes its children, and a
|
|
48
|
+
* child that says nothing about its type gets the parent's. This is the narrow
|
|
49
|
+
* opt-out — a `{% track type="song" %}` inside a `{% playlist type="podcast" %}`
|
|
50
|
+
* stays a song, because saying so and being overruled anyway would make the
|
|
51
|
+
* attribute a lie.
|
|
52
|
+
*
|
|
53
|
+
* It has to be a marker because "no type stated" and "this exact type stated"
|
|
54
|
+
* are the same value by transform time, and Markdoc transforms bottom-up so a
|
|
55
|
+
* child cannot ask its parent. An own-property on the Tag rather than an
|
|
56
|
+
* attribute, so `JSON.parse(JSON.stringify(…))` at the serialize boundary drops
|
|
57
|
+
* it and it can never reach the HTML; the applier deletes it once read.
|
|
58
|
+
*/
|
|
59
|
+
export declare const SCHEMA_TYPE_EXPLICIT: unique symbol;
|
|
60
|
+
/** A source name in the rune's flat namespace, mapped to a schema.org property. */
|
|
61
|
+
export type PropertyMap = Record<string, string>;
|
|
62
|
+
/** A nested entity: its own type, the property that holds it, its own map. */
|
|
63
|
+
export interface EntityRow {
|
|
64
|
+
type: string;
|
|
65
|
+
/** The property on the parent that holds this entity. Required — see below. */
|
|
66
|
+
property: string;
|
|
67
|
+
properties?: PropertyMap;
|
|
68
|
+
/** Properties taking a node's own content, via an RDFa-conformant wrapper. */
|
|
69
|
+
text?: PropertyMap;
|
|
70
|
+
/** The wrapper element `text` emits. Defaults to `div`. */
|
|
71
|
+
textTag?: string;
|
|
72
|
+
/** Properties whose value is generated rather than read from content. */
|
|
73
|
+
generated?: Record<string, 'index'>;
|
|
74
|
+
}
|
|
75
|
+
/** One resolvable schema row: a type plus what it maps. */
|
|
76
|
+
export interface SchemaRow {
|
|
77
|
+
type?: string;
|
|
78
|
+
properties?: PropertyMap;
|
|
79
|
+
/**
|
|
80
|
+
* Properties taking a node's own content. The applier emits the
|
|
81
|
+
* RDFa-conformant wrapper; no rune hand-writes one.
|
|
82
|
+
*
|
|
83
|
+
* The wrapper is conformant, not a workaround. RDFa Core 1.1 §7.5 step 11:
|
|
84
|
+
* an element carrying both `property` and `typeof` has its object fixed to
|
|
85
|
+
* the typed resource, so its text is unreachable as a literal. Since
|
|
86
|
+
* SPEC-082 renders the SEO carriers inline, refrakt publishes RDFa *and*
|
|
87
|
+
* JSON-LD on the same page — dropping the wrapper would have the two
|
|
88
|
+
* channels assert different graphs on every accordion, recipe and how-to.
|
|
89
|
+
*/
|
|
90
|
+
text?: PropertyMap;
|
|
91
|
+
/**
|
|
92
|
+
* The wrapper element `text` emits. Defaults to `div`.
|
|
93
|
+
*
|
|
94
|
+
* It is a rendering choice, not a schema one — `how-to` and `recipe` wrap an
|
|
95
|
+
* `<li>`'s content in a `<p>`, and a `<div>` there would change the page's
|
|
96
|
+
* margins. Declared rather than fixed so the applier can reproduce what each
|
|
97
|
+
* rune already renders, byte for byte.
|
|
98
|
+
*/
|
|
99
|
+
textTag?: string;
|
|
100
|
+
entities?: Record<string, EntityRow>;
|
|
101
|
+
/** Properties whose value is generated. `index` is the only generator. */
|
|
102
|
+
generated?: Record<string, 'index'>;
|
|
103
|
+
/**
|
|
104
|
+
* Properties that always serialise as an array, however many items (D6).
|
|
105
|
+
*
|
|
106
|
+
* `readonly` so a table written the way every other one is — a single
|
|
107
|
+
* `as const` literal — type-checks; nothing here mutates it.
|
|
108
|
+
*/
|
|
109
|
+
lists?: readonly string[];
|
|
110
|
+
/** Per-child-rune type and property remapping. */
|
|
111
|
+
children?: Record<string, EntityRow>;
|
|
112
|
+
}
|
|
113
|
+
/** A rune's schema table: one row, or a row chosen by an attribute value. */
|
|
114
|
+
export interface SchemaTable extends SchemaRow {
|
|
115
|
+
/**
|
|
116
|
+
* Selects a row by the value of the named **attribute**.
|
|
117
|
+
*
|
|
118
|
+
* It names an attribute, not a modifier. `modifiers` is read by the engine,
|
|
119
|
+
* which has no part in this path — the row is picked here, from `attrs`.
|
|
120
|
+
* `validateSchemaTable` enforces that the named attribute is declared, so
|
|
121
|
+
* the ambiguity cannot ship silently.
|
|
122
|
+
*/
|
|
123
|
+
by?: string;
|
|
124
|
+
/** Rows keyed by attribute value, used with `by`. */
|
|
125
|
+
rows?: Record<string, SchemaRow>;
|
|
126
|
+
/** The row for when the `by` attribute is absent or unmatched. */
|
|
127
|
+
fallback?: SchemaRow;
|
|
128
|
+
}
|
|
129
|
+
/** A problem with a table, found at build time. */
|
|
130
|
+
export interface SchemaTableIssue {
|
|
131
|
+
path: string;
|
|
132
|
+
message: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check a table's internal consistency.
|
|
136
|
+
*
|
|
137
|
+
* Curation, not validation: nothing here checks a mapping against schema.org,
|
|
138
|
+
* because refrakt ships no ontology (D5). What it does check is the structural
|
|
139
|
+
* rule that cannot be got wrong safely — `collectJsonLd` nests a child entity
|
|
140
|
+
* only when the same node carries both `typeof` and `property`, so declaring a
|
|
141
|
+
* child's type without the property that holds it produces a detached
|
|
142
|
+
* top-level entity related to nothing. The table rejects that rather than
|
|
143
|
+
* emitting it.
|
|
144
|
+
*/
|
|
145
|
+
export declare function validateSchemaTable(table: SchemaTable, declaredAttributes?: string[]): SchemaTableIssue[];
|
|
146
|
+
/** Pick the row a set of attributes selects. */
|
|
147
|
+
export declare function selectRow(table: SchemaTable, attrs: Record<string, unknown>): SchemaRow;
|
|
148
|
+
type AnyTag = InstanceType<typeof Tag>;
|
|
149
|
+
/**
|
|
150
|
+
* Find a node by name, whichever attribute carries it.
|
|
151
|
+
*
|
|
152
|
+
* `data-name` and `data-field` are the two surfaces a name can appear on today,
|
|
153
|
+
* and SPEC-133 moves nodes between them. Checking both, in one pass, with no
|
|
154
|
+
* branch on which matched, is what makes those moves a no-op here.
|
|
155
|
+
*/
|
|
156
|
+
/**
|
|
157
|
+
* Every node bearing a name, in document order, within one rune.
|
|
158
|
+
*
|
|
159
|
+
* **The search stops at another rune's node.** ADR-008's flat namespace is
|
|
160
|
+
* unique *per rune*, so the same name means different things in a parent and in
|
|
161
|
+
* a child it contains: `character` names its title span `name`, and so does
|
|
162
|
+
* every `character-section` inside it. Reaching across that boundary published a
|
|
163
|
+
* character whose `name` was the character plus each of its section headings.
|
|
164
|
+
*/
|
|
165
|
+
export declare function findAllByName(root: RenderableTreeNode | RenderableTreeNode[], name: string): AnyTag[];
|
|
166
|
+
/** The first node bearing a name, within one rune — see `findAllByName`. */
|
|
167
|
+
export declare function findByName(root: RenderableTreeNode | RenderableTreeNode[], name: string): AnyTag | undefined;
|
|
168
|
+
/**
|
|
169
|
+
* Apply a rune's schema table to its transform output.
|
|
170
|
+
*
|
|
171
|
+
* Runs on the rune's own root, after its transform has built the tree and
|
|
172
|
+
* `createComponentRenderable` has written the field bag.
|
|
173
|
+
*/
|
|
174
|
+
export declare function applySchemaTable(output: RenderableTreeNode, table: SchemaTable, attrs: Record<string, unknown>): RenderableTreeNode;
|
|
175
|
+
export {};
|
|
176
|
+
//# sourceMappingURL=schema-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-table.d.ts","sourceRoot":"","sources":["../../src/lib/schema-table.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D,QAAA,MAAQ,GAAG,oBAAY,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,eAA2C,CAAC;AAE7E,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACrC;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC7C;;;;;;;OAOG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,WAAW,EAClB,kBAAkB,GAAE,MAAM,EAAO,GAC/B,gBAAgB,EAAE,CA6CpB;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKvF;AAID,KAAK,MAAM,GAAG,YAAY,CAAC,OAAO,GAAG,CAAC,CAAC;AAIvC;;;;;;GAMG;AACH;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC5B,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,EAC/C,IAAI,EAAE,MAAM,GACV,MAAM,EAAE,CA0BV;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CACzB,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,EAC/C,IAAI,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAEpB;AAyLD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,kBAAkB,CAkDpB"}
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import Markdoc from '@markdoc/markdoc';
|
|
2
|
+
import { SCHEMA_LISTS_ATTR } from '../seo.js';
|
|
3
|
+
const { Tag } = Markdoc;
|
|
4
|
+
/**
|
|
5
|
+
* The declarative schema.org table, and the applier that realises it
|
|
6
|
+
* (SPEC-130 / WORK-565).
|
|
7
|
+
*
|
|
8
|
+
* ## Why this is data consulted at transform time, not engine config
|
|
9
|
+
*
|
|
10
|
+
* The obvious home is the identity transform engine, and it does not work.
|
|
11
|
+
* `packages/content/src/site.ts` never applies the engine — it runs
|
|
12
|
+
* `Markdoc.transform`, then `extractSeo`, and `collectJsonLd` *derives* the
|
|
13
|
+
* JSON-LD by walking that tree for `typeof`. The engine runs later, at render
|
|
14
|
+
* time, so schema emitted there would reach the HTML and never reach the
|
|
15
|
+
* JSON-LD.
|
|
16
|
+
*
|
|
17
|
+
* So the table is an option to `createContentModelSchema`, sitting beside the
|
|
18
|
+
* rune's other self-declarations (`sections`, `mediaSlots`, `provides`, `base`),
|
|
19
|
+
* and the applier runs on the rune's own output.
|
|
20
|
+
*
|
|
21
|
+
* ## Three resolution strategies, and why the third exists
|
|
22
|
+
*
|
|
23
|
+
* `createComponentRenderable` drops a property `<meta>` that no `schema:` map
|
|
24
|
+
* names — it is classified pure data and its value is already in the bag. Once
|
|
25
|
+
* runes stop declaring `schema:` themselves, those nodes are gone by the time
|
|
26
|
+
* the applier runs. The bag is the recovery:
|
|
27
|
+
*
|
|
28
|
+
* 1. **Stamp in place** — a named node that survives into the output.
|
|
29
|
+
* 2. **Rebuild from the bag** — a value-only source whose carrier was dropped.
|
|
30
|
+
* 3. **Synthesise an entity** — a nested span built from either of the above.
|
|
31
|
+
*
|
|
32
|
+
* That is why `createComponentRenderable` needs no knowledge of schema at all:
|
|
33
|
+
* it simply always treats property metas as pure data, which is what it already
|
|
34
|
+
* does when `schema:` is absent.
|
|
35
|
+
*
|
|
36
|
+
* ## Name resolution is attribute-agnostic, deliberately
|
|
37
|
+
*
|
|
38
|
+
* A source resolves whether it surfaces as `data-name` or `data-field`, and the
|
|
39
|
+
* applier never branches on which. SPEC-133 moves ~97 nodes between `properties`
|
|
40
|
+
* and `refs`; under this rule every one of those moves is a no-op for every
|
|
41
|
+
* table, because the table keys on a name in the rune's flat namespace
|
|
42
|
+
* (ADR-008), not on the attribute that happens to carry it.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Marks a `typeof` the **author** stated, which a parent may not overrule.
|
|
46
|
+
*
|
|
47
|
+
* D9's default stands: a parent's `children` row retypes its children, and a
|
|
48
|
+
* child that says nothing about its type gets the parent's. This is the narrow
|
|
49
|
+
* opt-out — a `{% track type="song" %}` inside a `{% playlist type="podcast" %}`
|
|
50
|
+
* stays a song, because saying so and being overruled anyway would make the
|
|
51
|
+
* attribute a lie.
|
|
52
|
+
*
|
|
53
|
+
* It has to be a marker because "no type stated" and "this exact type stated"
|
|
54
|
+
* are the same value by transform time, and Markdoc transforms bottom-up so a
|
|
55
|
+
* child cannot ask its parent. An own-property on the Tag rather than an
|
|
56
|
+
* attribute, so `JSON.parse(JSON.stringify(…))` at the serialize boundary drops
|
|
57
|
+
* it and it can never reach the HTML; the applier deletes it once read.
|
|
58
|
+
*/
|
|
59
|
+
export const SCHEMA_TYPE_EXPLICIT = Symbol.for('refrakt.schemaTypeExplicit');
|
|
60
|
+
/**
|
|
61
|
+
* Check a table's internal consistency.
|
|
62
|
+
*
|
|
63
|
+
* Curation, not validation: nothing here checks a mapping against schema.org,
|
|
64
|
+
* because refrakt ships no ontology (D5). What it does check is the structural
|
|
65
|
+
* rule that cannot be got wrong safely — `collectJsonLd` nests a child entity
|
|
66
|
+
* only when the same node carries both `typeof` and `property`, so declaring a
|
|
67
|
+
* child's type without the property that holds it produces a detached
|
|
68
|
+
* top-level entity related to nothing. The table rejects that rather than
|
|
69
|
+
* emitting it.
|
|
70
|
+
*/
|
|
71
|
+
export function validateSchemaTable(table, declaredAttributes = []) {
|
|
72
|
+
const issues = [];
|
|
73
|
+
if (table.by !== undefined) {
|
|
74
|
+
if (declaredAttributes.length > 0 && !declaredAttributes.includes(table.by)) {
|
|
75
|
+
issues.push({
|
|
76
|
+
path: 'by',
|
|
77
|
+
message: `\`by: '${table.by}'\` names an attribute the rune does not declare. \`by\` selects a row from \`attrs\`, not from a modifier.`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (!table.rows || Object.keys(table.rows).length === 0) {
|
|
81
|
+
issues.push({ path: 'rows', message: '`by` needs `rows` to select from.' });
|
|
82
|
+
}
|
|
83
|
+
if (!table.fallback && !table.type) {
|
|
84
|
+
issues.push({
|
|
85
|
+
path: 'fallback',
|
|
86
|
+
message: '`by` needs an explicit `fallback` row for the absent or unmatched case.',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const checkEntities = (rows, path) => {
|
|
91
|
+
for (const [name, row] of Object.entries(rows ?? {})) {
|
|
92
|
+
if (!row.property) {
|
|
93
|
+
issues.push({
|
|
94
|
+
path: `${path}.${name}`,
|
|
95
|
+
message: `A child entity needs the \`property\` that holds it. Without one it floats up as a detached top-level entity: \`collectJsonLd\` nests a typed node only when it also carries \`property\`.`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (!row.type) {
|
|
99
|
+
issues.push({ path: `${path}.${name}`, message: 'A child entity needs a `type`.' });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const checkRow = (row, path) => {
|
|
104
|
+
checkEntities(row.entities, `${path}entities`);
|
|
105
|
+
checkEntities(row.children, `${path}children`);
|
|
106
|
+
};
|
|
107
|
+
checkRow(table, '');
|
|
108
|
+
for (const [value, row] of Object.entries(table.rows ?? {}))
|
|
109
|
+
checkRow(row, `rows.${value}.`);
|
|
110
|
+
if (table.fallback)
|
|
111
|
+
checkRow(table.fallback, 'fallback.');
|
|
112
|
+
return issues;
|
|
113
|
+
}
|
|
114
|
+
/** Pick the row a set of attributes selects. */
|
|
115
|
+
export function selectRow(table, attrs) {
|
|
116
|
+
if (!table.by)
|
|
117
|
+
return table;
|
|
118
|
+
const value = attrs[table.by];
|
|
119
|
+
const row = value === undefined ? undefined : table.rows?.[String(value)];
|
|
120
|
+
return row ?? table.fallback ?? table;
|
|
121
|
+
}
|
|
122
|
+
const isTag = (n) => Markdoc.Tag.isTag(n);
|
|
123
|
+
/**
|
|
124
|
+
* Find a node by name, whichever attribute carries it.
|
|
125
|
+
*
|
|
126
|
+
* `data-name` and `data-field` are the two surfaces a name can appear on today,
|
|
127
|
+
* and SPEC-133 moves nodes between them. Checking both, in one pass, with no
|
|
128
|
+
* branch on which matched, is what makes those moves a no-op here.
|
|
129
|
+
*/
|
|
130
|
+
/**
|
|
131
|
+
* Every node bearing a name, in document order, within one rune.
|
|
132
|
+
*
|
|
133
|
+
* **The search stops at another rune's node.** ADR-008's flat namespace is
|
|
134
|
+
* unique *per rune*, so the same name means different things in a parent and in
|
|
135
|
+
* a child it contains: `character` names its title span `name`, and so does
|
|
136
|
+
* every `character-section` inside it. Reaching across that boundary published a
|
|
137
|
+
* character whose `name` was the character plus each of its section headings.
|
|
138
|
+
*/
|
|
139
|
+
export function findAllByName(root, name) {
|
|
140
|
+
const kebab = name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
141
|
+
const out = [];
|
|
142
|
+
const visit = (node, top) => {
|
|
143
|
+
if (Array.isArray(node)) {
|
|
144
|
+
for (const c of node)
|
|
145
|
+
visit(c, top);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!isTag(node))
|
|
149
|
+
return;
|
|
150
|
+
const attrs = node.attributes ?? {};
|
|
151
|
+
if (!top && attrs['data-rune'] !== undefined)
|
|
152
|
+
return;
|
|
153
|
+
const named = attrs['data-name'] === name ||
|
|
154
|
+
attrs['data-name'] === kebab ||
|
|
155
|
+
attrs['data-field'] === name ||
|
|
156
|
+
attrs['data-field'] === kebab;
|
|
157
|
+
if (named) {
|
|
158
|
+
out.push(node);
|
|
159
|
+
// A name marks one node, not a subtree: descending into a match would
|
|
160
|
+
// find nothing new and risks a nested re-use of the same name.
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
for (const c of node.children ?? [])
|
|
164
|
+
visit(c, false);
|
|
165
|
+
};
|
|
166
|
+
visit(root, true);
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
/** The first node bearing a name, within one rune — see `findAllByName`. */
|
|
170
|
+
export function findByName(root, name) {
|
|
171
|
+
return findAllByName(root, name)[0];
|
|
172
|
+
}
|
|
173
|
+
/** The rune's field bag, as written by `createComponentRenderable`. */
|
|
174
|
+
function readBag(root) {
|
|
175
|
+
const raw = root.attributes?.['data-rune-fields'];
|
|
176
|
+
if (typeof raw !== 'string')
|
|
177
|
+
return {};
|
|
178
|
+
try {
|
|
179
|
+
return JSON.parse(raw);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return {};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Resolve one source to a carrier and stamp `property` on it.
|
|
187
|
+
*
|
|
188
|
+
* Returns the node that ended up carrying the property, or `undefined` when the
|
|
189
|
+
* source resolves to nothing — which is not an error: a rune legitimately omits
|
|
190
|
+
* optional content, and a row for absent content should emit nothing rather
|
|
191
|
+
* than an empty carrier.
|
|
192
|
+
*/
|
|
193
|
+
function stamp(root, bag, source, property, sink) {
|
|
194
|
+
// Every node bearing the name, not just the first. A name in the rune's flat
|
|
195
|
+
// namespace can be worn by a whole collection — `recipe` gives each of its
|
|
196
|
+
// ingredient `<li>`s `data-name="ingredient"` — and stamping one of six would
|
|
197
|
+
// publish a single ingredient and silently drop the rest.
|
|
198
|
+
const nodes = findAllByName(root, source);
|
|
199
|
+
if (nodes.length > 0) {
|
|
200
|
+
for (const node of nodes)
|
|
201
|
+
node.attributes.property = property;
|
|
202
|
+
return nodes[0];
|
|
203
|
+
}
|
|
204
|
+
const value = bag[source];
|
|
205
|
+
if (value === undefined || value === '')
|
|
206
|
+
return undefined;
|
|
207
|
+
const meta = new Tag('meta', { property, content: carry(value) });
|
|
208
|
+
sink.push(meta);
|
|
209
|
+
return meta;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Wrap a node's own content so its text is readable as a literal.
|
|
213
|
+
*
|
|
214
|
+
* See the note on `SchemaRow.text` — an element carrying both `property` and
|
|
215
|
+
* `typeof` cannot also contribute its text, so the value needs its own element.
|
|
216
|
+
*/
|
|
217
|
+
function applyText(root, source, property, tag = 'div') {
|
|
218
|
+
const node = findByName(root, source);
|
|
219
|
+
if (!node)
|
|
220
|
+
return;
|
|
221
|
+
const wrapper = new Tag(tag, { property }, node.children ?? []);
|
|
222
|
+
node.children = [wrapper];
|
|
223
|
+
}
|
|
224
|
+
/** Apply a row's own properties, entities and generated values to one node. */
|
|
225
|
+
function applyRow(node, row, bag, index) {
|
|
226
|
+
if (row.type)
|
|
227
|
+
node.attributes.typeof = row.type;
|
|
228
|
+
// D6 — travel the list declaration to `collectJsonLd`, which derives the
|
|
229
|
+
// graph and has no other way to know a one-item collection is still a list.
|
|
230
|
+
if (row.lists && row.lists.length > 0) {
|
|
231
|
+
node.attributes[SCHEMA_LISTS_ATTR] = JSON.stringify(row.lists);
|
|
232
|
+
}
|
|
233
|
+
const appended = [];
|
|
234
|
+
for (const [source, property] of Object.entries(row.properties ?? {})) {
|
|
235
|
+
stamp(node, bag, source, property, appended);
|
|
236
|
+
}
|
|
237
|
+
for (const [source, property] of Object.entries(row.text ?? {})) {
|
|
238
|
+
applyText(node, source, property, row.textTag);
|
|
239
|
+
}
|
|
240
|
+
for (const [property, generator] of Object.entries(row.generated ?? {})) {
|
|
241
|
+
// `index` is the one generator: a position exists nowhere in the content,
|
|
242
|
+
// so it cannot be resolved from a node or the bag.
|
|
243
|
+
if (generator === 'index' && index !== undefined) {
|
|
244
|
+
appended.push(new Tag('meta', { property, content: String(index + 1) }));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
for (const [name, entity] of Object.entries(row.entities ?? {})) {
|
|
248
|
+
const span = buildEntity(node, entity, bag);
|
|
249
|
+
if (span)
|
|
250
|
+
appended.push(span);
|
|
251
|
+
}
|
|
252
|
+
if (appended.length > 0)
|
|
253
|
+
node.children = [...(node.children ?? []), ...appended];
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Build a nested entity span, or nothing.
|
|
257
|
+
*
|
|
258
|
+
* D4 — an entity resolving to a bare `@type` with no properties emits nothing.
|
|
259
|
+
* Seven runes in the catalog assert a type and describe nothing; the table
|
|
260
|
+
* makes that a decision rather than an accident.
|
|
261
|
+
*/
|
|
262
|
+
function buildEntity(root, entity, bag) {
|
|
263
|
+
const carriers = [];
|
|
264
|
+
for (const [source, property] of Object.entries(entity.properties ?? {})) {
|
|
265
|
+
const node = findByName(root, source);
|
|
266
|
+
if (node) {
|
|
267
|
+
// The source survives in the output, so the entity takes a copy of its
|
|
268
|
+
// value rather than relocating the node — moving it would change the
|
|
269
|
+
// rendered HTML, which this mechanism must not do.
|
|
270
|
+
const text = textOf(node);
|
|
271
|
+
if (text)
|
|
272
|
+
carriers.push(new Tag('meta', { property, content: text }));
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const value = bag[source];
|
|
276
|
+
if (value !== undefined && value !== '') {
|
|
277
|
+
carriers.push(new Tag('meta', { property, content: carry(value) }));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (carriers.length === 0)
|
|
281
|
+
return undefined;
|
|
282
|
+
return new Tag('span', { typeof: entity.type, property: entity.property }, carriers);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Carry a bag value onto a `content` attribute without changing its type.
|
|
286
|
+
*
|
|
287
|
+
* `data-rune-fields` stores values typed, and `collectJsonLd` reads `content`
|
|
288
|
+
* straight through — so coercing here would turn a `ratingValue` of `5` into
|
|
289
|
+
* `"5"` in the published JSON-LD. Caught by the baseline: it was the only
|
|
290
|
+
* difference between the hand-built spans and the table.
|
|
291
|
+
*/
|
|
292
|
+
function carry(value) {
|
|
293
|
+
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string') {
|
|
294
|
+
return value;
|
|
295
|
+
}
|
|
296
|
+
return String(value);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Strip every `property=` stamp inside a child the parent is about to retype.
|
|
300
|
+
*
|
|
301
|
+
* Stops at a nested `typeof`: that subtree is its own entity and its properties
|
|
302
|
+
* belong to it, not to the child being retyped.
|
|
303
|
+
*/
|
|
304
|
+
function clearProperties(node) {
|
|
305
|
+
const kept = [];
|
|
306
|
+
for (const child of node.children ?? []) {
|
|
307
|
+
if (!isTag(child)) {
|
|
308
|
+
kept.push(child);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const tag = child;
|
|
312
|
+
const attrs = tag.attributes ?? {};
|
|
313
|
+
// A rebuilt carrier — a `<meta property=… content=…>` with no name — exists
|
|
314
|
+
// only to carry a schema value. Stripping its property would leave an inert
|
|
315
|
+
// `<meta>` in the markup, so it goes with the mapping that created it.
|
|
316
|
+
const isCarrier = tag.name === 'meta' &&
|
|
317
|
+
attrs.property !== undefined &&
|
|
318
|
+
attrs['data-name'] === undefined &&
|
|
319
|
+
attrs['data-field'] === undefined;
|
|
320
|
+
if (isCarrier)
|
|
321
|
+
continue;
|
|
322
|
+
if (attrs.property !== undefined)
|
|
323
|
+
delete tag.attributes.property;
|
|
324
|
+
if (attrs.typeof === undefined)
|
|
325
|
+
clearProperties(tag);
|
|
326
|
+
kept.push(child);
|
|
327
|
+
}
|
|
328
|
+
node.children = kept;
|
|
329
|
+
}
|
|
330
|
+
function textOf(node) {
|
|
331
|
+
if (typeof node === 'string')
|
|
332
|
+
return node;
|
|
333
|
+
if (Array.isArray(node))
|
|
334
|
+
return node.map(textOf).join('');
|
|
335
|
+
if (!isTag(node))
|
|
336
|
+
return '';
|
|
337
|
+
const content = node.attributes?.content;
|
|
338
|
+
if (content !== undefined)
|
|
339
|
+
return String(content);
|
|
340
|
+
return (node.children ?? []).map(textOf).join('');
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Apply a rune's schema table to its transform output.
|
|
344
|
+
*
|
|
345
|
+
* Runs on the rune's own root, after its transform has built the tree and
|
|
346
|
+
* `createComponentRenderable` has written the field bag.
|
|
347
|
+
*/
|
|
348
|
+
export function applySchemaTable(output, table, attrs) {
|
|
349
|
+
if (!isTag(output))
|
|
350
|
+
return output;
|
|
351
|
+
// `schema="none"` suppresses the whole subtree, not just the root: a child
|
|
352
|
+
// rune declares its own type independently, so stripping only the root would
|
|
353
|
+
// leave orphan typed nodes with no container (WORK-552).
|
|
354
|
+
if (attrs.schema === 'none')
|
|
355
|
+
return output;
|
|
356
|
+
const root = output;
|
|
357
|
+
const row = selectRow(table, attrs);
|
|
358
|
+
const bag = readBag(root);
|
|
359
|
+
applyRow(root, row, bag);
|
|
360
|
+
// Children are retyped by the parent, never by themselves (D9). Markdoc
|
|
361
|
+
// transforms bottom-up, so by now the children carry their own `typeof` and
|
|
362
|
+
// this rewrites them — and only the parent can supply the `property` that
|
|
363
|
+
// nests them.
|
|
364
|
+
for (const [childName, childRow] of Object.entries(row.children ?? {})) {
|
|
365
|
+
const items = findChildren(root, childName);
|
|
366
|
+
items.forEach((item, i) => {
|
|
367
|
+
// A type the *author* stated is the child's own and survives: a
|
|
368
|
+
// `{% track type="song" %}` inside a podcast stays a song, because
|
|
369
|
+
// saying so and being overruled would make the attribute a lie. A type
|
|
370
|
+
// that came from the child's fallback row is marked implicit, and the
|
|
371
|
+
// parent is the better authority on what an unlabelled child is.
|
|
372
|
+
const marked = item;
|
|
373
|
+
const ownType = Boolean(marked[SCHEMA_TYPE_EXPLICIT]);
|
|
374
|
+
delete marked[SCHEMA_TYPE_EXPLICIT];
|
|
375
|
+
if (ownType) {
|
|
376
|
+
// A child that kept its own type keeps its own property map with it —
|
|
377
|
+
// the two are one statement, and re-stamping the parent's over it
|
|
378
|
+
// would duplicate every value it already carries. What the parent
|
|
379
|
+
// still supplies is the containing property and anything positional,
|
|
380
|
+
// which only a parent can know.
|
|
381
|
+
applyRow(item, { type: undefined, generated: childRow.generated }, readBag(item), i);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
// The parent retypes, so the parent's map is the whole truth for this
|
|
385
|
+
// child. Clearing first is what makes a property that does not belong
|
|
386
|
+
// to the new type disappear rather than linger: `byArtist` on a
|
|
387
|
+
// `PodcastEpisode` is worse than the `MusicRecording` it replaced,
|
|
388
|
+
// which was at least coherently wrong.
|
|
389
|
+
if (childRow.properties)
|
|
390
|
+
clearProperties(item);
|
|
391
|
+
applyRow(item, childRow, readBag(item), i);
|
|
392
|
+
}
|
|
393
|
+
item.attributes.property = childRow.property;
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return output;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Every node the named child occupies, in document order.
|
|
400
|
+
*
|
|
401
|
+
* Matched on `data-rune` *or* a name, for the same reason `findByName` is
|
|
402
|
+
* attribute-agnostic: a parent may build some of a collection itself and receive
|
|
403
|
+
* the rest as authored child tags — `playlist` does exactly that, with markdown
|
|
404
|
+
* list items beside `{% track %}` children. Both populations belong to one
|
|
405
|
+
* collection and must take one row, or half of it would go unmapped.
|
|
406
|
+
*/
|
|
407
|
+
function findChildren(root, name) {
|
|
408
|
+
const out = [];
|
|
409
|
+
const visit = (node) => {
|
|
410
|
+
if (Array.isArray(node)) {
|
|
411
|
+
for (const c of node)
|
|
412
|
+
visit(c);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (!isTag(node))
|
|
416
|
+
return;
|
|
417
|
+
const attrs = node.attributes ?? {};
|
|
418
|
+
if (attrs['data-rune'] === name || attrs['data-name'] === name || attrs['data-field'] === name)
|
|
419
|
+
out.push(node);
|
|
420
|
+
for (const c of node.children ?? [])
|
|
421
|
+
visit(c);
|
|
422
|
+
};
|
|
423
|
+
for (const c of root.children ?? [])
|
|
424
|
+
visit(c);
|
|
425
|
+
return out;
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=schema-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-table.js","sourceRoot":"","sources":["../../src/lib/schema-table.ts"],"names":[],"mappings":"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"}
|
package/dist/reference.d.ts
CHANGED
|
@@ -185,12 +185,45 @@ export interface SerializedAttribute {
|
|
|
185
185
|
matches?: string[];
|
|
186
186
|
description?: string;
|
|
187
187
|
}
|
|
188
|
+
/** A rune's structured-data claims, ordered by schema.org property. */
|
|
189
|
+
export interface SerializedSchemaOrg {
|
|
190
|
+
type?: string;
|
|
191
|
+
/** The attribute a multi-row table selects on. */
|
|
192
|
+
by?: string;
|
|
193
|
+
/** Every schema.org property, with the source name that supplies it. */
|
|
194
|
+
properties: Array<{
|
|
195
|
+
property: string;
|
|
196
|
+
source: string;
|
|
197
|
+
kind: string;
|
|
198
|
+
entity?: string;
|
|
199
|
+
}>;
|
|
200
|
+
entities: Array<{
|
|
201
|
+
name: string;
|
|
202
|
+
type: string;
|
|
203
|
+
property: string;
|
|
204
|
+
}>;
|
|
205
|
+
children: Array<{
|
|
206
|
+
rune: string;
|
|
207
|
+
type: string;
|
|
208
|
+
property: string;
|
|
209
|
+
}>;
|
|
210
|
+
lists: string[];
|
|
211
|
+
/** Types this rune can emit, when the table selects a row by attribute. */
|
|
212
|
+
types: string[];
|
|
213
|
+
}
|
|
188
214
|
export interface SerializedRune {
|
|
189
215
|
name: string;
|
|
190
216
|
plugin: string;
|
|
191
217
|
aliases: string[];
|
|
192
218
|
description: string;
|
|
193
219
|
authoringHints?: string;
|
|
220
|
+
/**
|
|
221
|
+
* What this rune publishes as structured data — SPEC-130 / WORK-566.
|
|
222
|
+
*
|
|
223
|
+
* Nothing validates it against schema.org: refrakt ships no ontology (D5).
|
|
224
|
+
* Documenting it *is* the control, which is why it is here.
|
|
225
|
+
*/
|
|
226
|
+
schemaOrg?: SerializedSchemaOrg;
|
|
194
227
|
attributes: {
|
|
195
228
|
own: Record<string, SerializedAttribute>;
|
|
196
229
|
base?: {
|