@refrakt-md/runes 0.38.0 → 0.40.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/attribute-presets.d.ts +3 -2
- package/dist/attribute-presets.d.ts.map +1 -1
- package/dist/attribute-presets.js +2 -1
- package/dist/attribute-presets.js.map +1 -1
- package/dist/collection-helpers.d.ts +21 -2
- package/dist/collection-helpers.d.ts.map +1 -1
- package/dist/collection-helpers.js +72 -15
- package/dist/collection-helpers.js.map +1 -1
- package/dist/composed-rune.d.ts +59 -0
- package/dist/composed-rune.d.ts.map +1 -0
- package/dist/composed-rune.js +129 -0
- package/dist/composed-rune.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +73 -40
- package/dist/config.js.map +1 -1
- package/dist/data-pipeline.d.ts +24 -10
- package/dist/data-pipeline.d.ts.map +1 -1
- package/dist/data-pipeline.js +34 -56
- package/dist/data-pipeline.js.map +1 -1
- package/dist/file-ref-resolve.js +9 -13
- package/dist/file-ref-resolve.js.map +1 -1
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/composition.d.ts +152 -0
- package/dist/lib/composition.d.ts.map +1 -0
- package/dist/lib/composition.js +1120 -0
- package/dist/lib/composition.js.map +1 -0
- package/dist/lib/index.d.ts +63 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +137 -8
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/preprocess.d.ts +64 -0
- package/dist/lib/preprocess.d.ts.map +1 -0
- package/dist/lib/preprocess.js +72 -0
- package/dist/lib/preprocess.js.map +1 -0
- package/dist/lib/registers.d.ts +132 -0
- package/dist/lib/registers.d.ts.map +1 -0
- package/dist/lib/registers.js +329 -0
- package/dist/lib/registers.js.map +1 -0
- package/dist/lib/resolver.d.ts +21 -1
- package/dist/lib/resolver.d.ts.map +1 -1
- package/dist/lib/resolver.js +41 -18
- package/dist/lib/resolver.js.map +1 -1
- package/dist/lib/schema-side-table.d.ts +26 -0
- package/dist/lib/schema-side-table.d.ts.map +1 -0
- package/dist/lib/schema-side-table.js +34 -0
- package/dist/lib/schema-side-table.js.map +1 -0
- package/dist/lib/schema-table.d.ts +59 -9
- package/dist/lib/schema-table.d.ts.map +1 -1
- package/dist/lib/schema-table.js +158 -22
- package/dist/lib/schema-table.js.map +1 -1
- package/dist/lib/slot-markers.d.ts +38 -0
- package/dist/lib/slot-markers.d.ts.map +1 -0
- package/dist/lib/slot-markers.js +105 -0
- package/dist/lib/slot-markers.js.map +1 -0
- package/dist/lib/slots.d.ts +99 -0
- package/dist/lib/slots.d.ts.map +1 -0
- package/dist/lib/slots.js +448 -0
- package/dist/lib/slots.js.map +1 -0
- package/dist/plugins.d.ts +3 -0
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +53 -4
- package/dist/plugins.js.map +1 -1
- package/dist/reference.d.ts +18 -0
- package/dist/reference.d.ts.map +1 -1
- package/dist/reference.js +34 -1
- package/dist/reference.js.map +1 -1
- package/dist/registers-pipeline.d.ts +51 -0
- package/dist/registers-pipeline.d.ts.map +1 -0
- package/dist/registers-pipeline.js +224 -0
- package/dist/registers-pipeline.js.map +1 -0
- package/dist/schema-row.d.ts +5 -0
- package/dist/schema-row.d.ts.map +1 -1
- package/dist/schema-row.js +1 -0
- package/dist/schema-row.js.map +1 -1
- package/dist/tags/data.d.ts +2 -2
- package/dist/tags/data.d.ts.map +1 -1
- package/dist/tags/data.js +6 -4
- package/dist/tags/data.js.map +1 -1
- package/dist/tags/figure.d.ts +10 -4
- package/dist/tags/figure.d.ts.map +1 -1
- package/dist/tags/figure.js +65 -20
- package/dist/tags/figure.js.map +1 -1
- package/dist/tags/include.d.ts +51 -7
- package/dist/tags/include.d.ts.map +1 -1
- package/dist/tags/include.js +216 -7
- package/dist/tags/include.js.map +1 -1
- package/dist/tags/sandbox.d.ts.map +1 -1
- package/dist/tags/sandbox.js +13 -3
- package/dist/tags/sandbox.js.map +1 -1
- package/dist/tags/snippet.d.ts +9 -10
- package/dist/tags/snippet.d.ts.map +1 -1
- package/dist/tags/snippet.js +213 -10
- package/dist/tags/snippet.js.map +1 -1
- package/dist/universal-attributes.d.ts +1 -1
- package/package.json +3 -3
- package/dist/include-pipeline.d.ts +0 -52
- package/dist/include-pipeline.d.ts.map +0 -1
- package/dist/include-pipeline.js +0 -206
- package/dist/include-pipeline.js.map +0 -1
- package/dist/snippet-pipeline.d.ts +0 -44
- package/dist/snippet-pipeline.d.ts.map +0 -1
- package/dist/snippet-pipeline.js +0 -307
- package/dist/snippet-pipeline.js.map +0 -1
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The slot declaration — SPEC-143.
|
|
3
|
+
*
|
|
4
|
+
* A rune whose every output slot comes from exactly one resolved field, wrapped
|
|
5
|
+
* but not restructured (D4), states that as data on `createContentModelSchema`
|
|
6
|
+
* instead of writing a `transform`:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* emits: {
|
|
10
|
+
* rune: 'work',
|
|
11
|
+
* tag: 'article',
|
|
12
|
+
* properties: { id: '', status: 'draft' },
|
|
13
|
+
* slots: {
|
|
14
|
+
* title: { as: 'region', el: 'header' },
|
|
15
|
+
* blurb: { from: 'description', as: 'region', omitWhenEmpty: true },
|
|
16
|
+
* body: { from: 'sections', as: 'region' },
|
|
17
|
+
* },
|
|
18
|
+
* },
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* `makeSlotTransform` turns that into an ordinary transform function — a closure
|
|
22
|
+
* over the declaration, built once when the schema is constructed — and the
|
|
23
|
+
* schema calls it at the same single call site a hand-written transform uses.
|
|
24
|
+
* Nothing downstream can tell the two apart, which is what makes the
|
|
25
|
+
* byte-identical migration gate (D7) a property of the construction rather than
|
|
26
|
+
* a hope.
|
|
27
|
+
*
|
|
28
|
+
* What the declaration may say, and nothing more (D2): a slot's name, the field
|
|
29
|
+
* (or attribute) it comes from, whether it is a single `value` or a `region` of
|
|
30
|
+
* nodes with a boundary element, and whether it is omitted when empty. It
|
|
31
|
+
* cannot nest one slot in another, order slots, or create containers — those
|
|
32
|
+
* belong to the engine's `layout`. Every value is data (D9), so the declaration
|
|
33
|
+
* round-trips through JSON unchanged.
|
|
34
|
+
*/
|
|
35
|
+
import Markdoc from '@markdoc/markdoc';
|
|
36
|
+
import { createComponentRenderable } from './component.js';
|
|
37
|
+
import { fieldMetas } from './field-metas.js';
|
|
38
|
+
import { selectStructuralModel } from './resolver.js';
|
|
39
|
+
const { Tag } = Markdoc;
|
|
40
|
+
/** The closed vocabulary of section roles — mirrors `SectionRole`. */
|
|
41
|
+
const SECTION_ROLES = [
|
|
42
|
+
'header',
|
|
43
|
+
'preamble',
|
|
44
|
+
'title',
|
|
45
|
+
'description',
|
|
46
|
+
'body',
|
|
47
|
+
'footer',
|
|
48
|
+
'media',
|
|
49
|
+
];
|
|
50
|
+
const EMITS_KEYS = new Set(['rune', 'tag', 'property', 'properties', 'slots']);
|
|
51
|
+
const SLOT_KEYS = new Set(['from', 'as', 'el', 'omitWhenEmpty', 'role']);
|
|
52
|
+
/** Keys that would make a slot structural. Named so the refusal can say why (D2). */
|
|
53
|
+
const STRUCTURE_KEYS = new Set([
|
|
54
|
+
'slots',
|
|
55
|
+
'children',
|
|
56
|
+
'nest',
|
|
57
|
+
'nested',
|
|
58
|
+
'into',
|
|
59
|
+
'parent',
|
|
60
|
+
'wrap',
|
|
61
|
+
'wrapper',
|
|
62
|
+
'container',
|
|
63
|
+
'group',
|
|
64
|
+
'order',
|
|
65
|
+
'position',
|
|
66
|
+
'before',
|
|
67
|
+
'after',
|
|
68
|
+
'layout',
|
|
69
|
+
]);
|
|
70
|
+
const ELEMENT = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
71
|
+
const SLOT_NAME = /^[a-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$/;
|
|
72
|
+
const RUNE_NAME = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
73
|
+
/**
|
|
74
|
+
* Reject anything that would not survive `JSON.parse(JSON.stringify(…))`
|
|
75
|
+
* unchanged — a function above all (D9), but also `undefined`, a non-finite
|
|
76
|
+
* number, or a class instance such as a `RegExp`.
|
|
77
|
+
*/
|
|
78
|
+
function assertPlainData(value, path, fail) {
|
|
79
|
+
if (typeof value === 'function') {
|
|
80
|
+
fail(`${path} is a function. The declaration is data only (SPEC-143 D9).`);
|
|
81
|
+
}
|
|
82
|
+
if (value === undefined) {
|
|
83
|
+
fail(`${path} is undefined, which does not survive a JSON round-trip — omit the key.`);
|
|
84
|
+
}
|
|
85
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
86
|
+
return;
|
|
87
|
+
if (typeof value === 'number') {
|
|
88
|
+
if (!Number.isFinite(value))
|
|
89
|
+
fail(`${path} is not a finite number.`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
value.forEach((v, i) => assertPlainData(v, `${path}[${i}]`, fail));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (typeof value === 'object') {
|
|
97
|
+
const proto = Object.getPrototypeOf(value);
|
|
98
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
99
|
+
fail(`${path} is a ${proto?.constructor?.name ?? 'class'} instance, not plain data.`);
|
|
100
|
+
}
|
|
101
|
+
for (const [k, v] of Object.entries(value)) {
|
|
102
|
+
assertPlainData(v, `${path}.${k}`, fail);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
fail(`${path} has unsupported type ${typeof value}.`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Every field the content model can resolve, across conditional branches. A
|
|
110
|
+
* model given as a function of attributes is sampled with no attributes —
|
|
111
|
+
* enough for a model that only varies its details, which is every model this
|
|
112
|
+
* declaration supports.
|
|
113
|
+
*/
|
|
114
|
+
function collectFields(model) {
|
|
115
|
+
const fields = new Map();
|
|
116
|
+
const unsupported = new Set();
|
|
117
|
+
const visit = (m) => {
|
|
118
|
+
if ('when' in m) {
|
|
119
|
+
m.when.forEach((b) => visit(b.model));
|
|
120
|
+
visit(m.default);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const s = m;
|
|
124
|
+
if (s.type === 'sequence' || s.type === 'sections') {
|
|
125
|
+
for (const f of s.fields ?? []) {
|
|
126
|
+
const prev = fields.get(f.name);
|
|
127
|
+
fields.set(f.name, { greedy: !!f.greedy || !!prev?.greedy, sections: false });
|
|
128
|
+
}
|
|
129
|
+
if (s.type === 'sections')
|
|
130
|
+
fields.set('sections', { greedy: true, sections: true });
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
unsupported.add(s.type);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
visit(typeof model === 'function' ? model({}) : model);
|
|
137
|
+
return { fields, unsupported };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check a declaration against the rune's content model and normalise it.
|
|
141
|
+
* Throws, naming the rune and the offending slot, rather than applying any part
|
|
142
|
+
* of a declaration it cannot honour.
|
|
143
|
+
*/
|
|
144
|
+
export function validateEmits(emits, contentModel) {
|
|
145
|
+
const runeLabel = emits && typeof emits === 'object' && typeof emits.rune === 'string'
|
|
146
|
+
? `"${emits.rune}"`
|
|
147
|
+
: '(unnamed)';
|
|
148
|
+
const fail = (msg) => {
|
|
149
|
+
throw new Error(`Rune ${runeLabel}: invalid \`emits\` declaration — ${msg}`);
|
|
150
|
+
};
|
|
151
|
+
if (!emits || typeof emits !== 'object' || Array.isArray(emits))
|
|
152
|
+
fail('must be an object.');
|
|
153
|
+
assertPlainData(emits, 'emits', fail);
|
|
154
|
+
for (const key of Object.keys(emits)) {
|
|
155
|
+
if (!EMITS_KEYS.has(key)) {
|
|
156
|
+
fail(STRUCTURE_KEYS.has(key)
|
|
157
|
+
? `\`${key}\` would declare structure. The declaration names slots only; nesting, ordering and containers are \`layout\`'s (SPEC-143 D2).`
|
|
158
|
+
: `unknown key \`${key}\` (expected ${[...EMITS_KEYS].join(', ')}).`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (typeof emits.rune !== 'string' || !RUNE_NAME.test(emits.rune)) {
|
|
162
|
+
fail('`rune` must be the kebab-case rune name.');
|
|
163
|
+
}
|
|
164
|
+
if (typeof emits.tag !== 'string' || !ELEMENT.test(emits.tag)) {
|
|
165
|
+
fail('`tag` must be an element name.');
|
|
166
|
+
}
|
|
167
|
+
if (emits.property !== undefined && typeof emits.property !== 'string') {
|
|
168
|
+
fail('`property` must be a string.');
|
|
169
|
+
}
|
|
170
|
+
const propertyKeys = new Set();
|
|
171
|
+
if (emits.properties !== undefined) {
|
|
172
|
+
if (typeof emits.properties !== 'object' || Array.isArray(emits.properties)) {
|
|
173
|
+
fail('`properties` must be an object.');
|
|
174
|
+
}
|
|
175
|
+
for (const [key, entry] of Object.entries(emits.properties)) {
|
|
176
|
+
propertyKeys.add(key);
|
|
177
|
+
if (typeof entry === 'string')
|
|
178
|
+
continue;
|
|
179
|
+
const ok = entry &&
|
|
180
|
+
typeof entry === 'object' &&
|
|
181
|
+
Array.isArray(entry.from) &&
|
|
182
|
+
entry.from.every((s) => typeof s === 'string' && /^(attrs|file)\.\S+$/.test(s)) &&
|
|
183
|
+
typeof entry.default === 'string' &&
|
|
184
|
+
Object.keys(entry).every((k) => k === 'from' || k === 'default');
|
|
185
|
+
if (!ok) {
|
|
186
|
+
fail(`property \`${key}\` must be a default string or { from: ["attrs.<name>" | "file.<name>", …], default: string }.`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!emits.slots || typeof emits.slots !== 'object' || Array.isArray(emits.slots)) {
|
|
191
|
+
fail('`slots` must be an object of slot entries.');
|
|
192
|
+
}
|
|
193
|
+
const slotNames = Object.keys(emits.slots);
|
|
194
|
+
if (slotNames.length === 0)
|
|
195
|
+
fail('`slots` declares no slot.');
|
|
196
|
+
const { fields, unsupported } = collectFields(contentModel);
|
|
197
|
+
const normalized = [];
|
|
198
|
+
for (const name of slotNames) {
|
|
199
|
+
const where = `slot \`${name}\``;
|
|
200
|
+
if (!SLOT_NAME.test(name))
|
|
201
|
+
fail(`${where}: not a valid data-name.`);
|
|
202
|
+
if (propertyKeys.has(name)) {
|
|
203
|
+
fail(`${where} is also a property. Properties and slots share one flat namespace (ADR-008), and the two would carry one name on two nodes.`);
|
|
204
|
+
}
|
|
205
|
+
const raw = emits.slots[name];
|
|
206
|
+
const decl = typeof raw === 'string' ? { as: raw } : raw;
|
|
207
|
+
if (!decl || typeof decl !== 'object' || Array.isArray(decl)) {
|
|
208
|
+
fail(`${where} must be "value", "region" or a slot declaration.`);
|
|
209
|
+
}
|
|
210
|
+
for (const key of Object.keys(decl)) {
|
|
211
|
+
if (SLOT_KEYS.has(key))
|
|
212
|
+
continue;
|
|
213
|
+
fail(STRUCTURE_KEYS.has(key)
|
|
214
|
+
? `${where}: \`${key}\` would nest, order or contain slots. A slot is flat — that is \`layout\`'s job (SPEC-143 D2).`
|
|
215
|
+
: `${where}: unknown key \`${key}\` (expected ${[...SLOT_KEYS].join(', ')}).`);
|
|
216
|
+
}
|
|
217
|
+
if (decl.as !== 'value' && decl.as !== 'region') {
|
|
218
|
+
fail(`${where}: \`as\` must be "value" or "region".`);
|
|
219
|
+
}
|
|
220
|
+
if (decl.el !== undefined && (typeof decl.el !== 'string' || !ELEMENT.test(decl.el))) {
|
|
221
|
+
fail(`${where}: \`el\` must be a single element name — a slot has one boundary, never a nested one (SPEC-143 D2).`);
|
|
222
|
+
}
|
|
223
|
+
if (decl.omitWhenEmpty !== undefined && typeof decl.omitWhenEmpty !== 'boolean') {
|
|
224
|
+
fail(`${where}: \`omitWhenEmpty\` must be a boolean.`);
|
|
225
|
+
}
|
|
226
|
+
if (decl.role !== undefined && !SECTION_ROLES.includes(decl.role)) {
|
|
227
|
+
fail(`${where}: \`role\` must be one of ${SECTION_ROLES.join(', ')}.`);
|
|
228
|
+
}
|
|
229
|
+
const from = decl.from ?? name;
|
|
230
|
+
if (typeof from !== 'string' || from === '')
|
|
231
|
+
fail(`${where}: \`from\` must be a string.`);
|
|
232
|
+
const slot = {
|
|
233
|
+
name,
|
|
234
|
+
kind: decl.as,
|
|
235
|
+
el: decl.el,
|
|
236
|
+
omitWhenEmpty: decl.omitWhenEmpty ?? false,
|
|
237
|
+
role: decl.role,
|
|
238
|
+
};
|
|
239
|
+
if (from.startsWith('attrs.')) {
|
|
240
|
+
slot.attr = from.slice('attrs.'.length);
|
|
241
|
+
if (!slot.attr)
|
|
242
|
+
fail(`${where}: \`from\` names no attribute.`);
|
|
243
|
+
if (decl.as !== 'value') {
|
|
244
|
+
fail(`${where}: an attribute is one value; it cannot be a region.`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
if (from.includes('.')) {
|
|
249
|
+
fail(`${where}: \`from\` is a content field name or "attrs.<name>", not "${from}".`);
|
|
250
|
+
}
|
|
251
|
+
const info = fields.get(from);
|
|
252
|
+
if (!info) {
|
|
253
|
+
const known = [...fields.keys()];
|
|
254
|
+
fail(unsupported.size > 0 && known.length === 0
|
|
255
|
+
? `${where}: the content model is ${[...unsupported].join(' / ')}, which the slot declaration does not read. Keep a \`transform\` (SPEC-143 D3).`
|
|
256
|
+
: `${where}: \`from: "${from}"\` names no field of the content model (fields: ${known.join(', ') || 'none'}).`);
|
|
257
|
+
}
|
|
258
|
+
slot.field = from;
|
|
259
|
+
if (decl.as === 'value') {
|
|
260
|
+
if (info.greedy) {
|
|
261
|
+
fail(`${where}: field \`${from}\` can resolve to several nodes, and a value slot names every node it emits — that is two nodes carrying data-name="${name}". Declare it \`as: "region"\`.`);
|
|
262
|
+
}
|
|
263
|
+
if (decl.el !== undefined) {
|
|
264
|
+
fail(`${where}: a value read from a field is already one node; there is nothing to wrap. Declare it \`as: "region"\` to give it a boundary.`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
normalized.push(slot);
|
|
269
|
+
}
|
|
270
|
+
return normalized;
|
|
271
|
+
}
|
|
272
|
+
function isRole(name) {
|
|
273
|
+
return name !== undefined && SECTION_ROLES.includes(name);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The `sections` join table a declaration implies — slot name → section role.
|
|
277
|
+
* A slot's role is the one it states, else its own name when that is a role,
|
|
278
|
+
* else its source field's name when that is one.
|
|
279
|
+
*/
|
|
280
|
+
export function slotSections(emits) {
|
|
281
|
+
const out = {};
|
|
282
|
+
for (const [name, raw] of Object.entries(emits.slots)) {
|
|
283
|
+
const decl = typeof raw === 'string' ? { as: raw } : raw;
|
|
284
|
+
const from = decl.from ?? name;
|
|
285
|
+
const role = decl.role ?? (isRole(name) ? name : isRole(from) ? from : undefined);
|
|
286
|
+
if (role)
|
|
287
|
+
out[name] = role;
|
|
288
|
+
}
|
|
289
|
+
return out;
|
|
290
|
+
}
|
|
291
|
+
function asNodes(value) {
|
|
292
|
+
if (Array.isArray(value))
|
|
293
|
+
return value;
|
|
294
|
+
if (value != null)
|
|
295
|
+
return [value];
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
function render(value, config) {
|
|
299
|
+
return Markdoc.transform(asNodes(value), config);
|
|
300
|
+
}
|
|
301
|
+
/** Heading text → `data-name` slug, for a section with no canonical slug. */
|
|
302
|
+
function slugify(text) {
|
|
303
|
+
return text
|
|
304
|
+
.toLowerCase()
|
|
305
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
306
|
+
.replace(/^-|-$/g, '');
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* One resolved section entry (a `sections` model without `emitTag`) as a
|
|
310
|
+
* `<section>` named by its slug: its heading, then its resolved fields.
|
|
311
|
+
*
|
|
312
|
+
* The slug is the entry's own identity — the known section's language-stable
|
|
313
|
+
* `$canonicalSlug` (SPEC-035), else the heading text slugified — and a known
|
|
314
|
+
* section's heading carries `data-known-section` so a table of contents can
|
|
315
|
+
* pick the known sections out. A top-level thematic break in the body is the
|
|
316
|
+
* author's separator between thoughts, not content, and is dropped.
|
|
317
|
+
*/
|
|
318
|
+
function renderSectionEntry(entry, config) {
|
|
319
|
+
const heading = entry.$heading ?? '';
|
|
320
|
+
const canonicalName = entry.$canonicalName;
|
|
321
|
+
const slug = entry.$canonicalSlug ?? slugify(heading);
|
|
322
|
+
const children = [];
|
|
323
|
+
const headingNode = entry.$headingNode;
|
|
324
|
+
if (headingNode) {
|
|
325
|
+
const renderedHeading = render([headingNode], config);
|
|
326
|
+
const first = renderedHeading[0];
|
|
327
|
+
if (canonicalName && Tag.isTag(first)) {
|
|
328
|
+
first.attributes['data-known-section'] = canonicalName;
|
|
329
|
+
}
|
|
330
|
+
children.push(...renderedHeading);
|
|
331
|
+
}
|
|
332
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
333
|
+
if (key.startsWith('$'))
|
|
334
|
+
continue;
|
|
335
|
+
children.push(...render(value, config).filter((n) => !(Tag.isTag(n) && n.name === 'hr')));
|
|
336
|
+
}
|
|
337
|
+
return new Tag('section', { 'data-name': slug }, children);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Build the transform a declaration describes. Called once, when the schema is
|
|
341
|
+
* constructed; the closure it returns has the signature of a hand-written
|
|
342
|
+
* transform and is called where one would be.
|
|
343
|
+
*/
|
|
344
|
+
export function makeSlotTransform(emits, contentModel) {
|
|
345
|
+
const slots = validateEmits(emits, contentModel);
|
|
346
|
+
const { rune, tag, property, properties } = emits;
|
|
347
|
+
return (resolved, attrs, config, node) => {
|
|
348
|
+
// D5 — whether sections arrive as resolved entries or as emitted child
|
|
349
|
+
// runes is the content model's `emitTag`; read it, per instance, from the
|
|
350
|
+
// branch the resolver actually took.
|
|
351
|
+
let structural;
|
|
352
|
+
const sectionsEmitTag = () => {
|
|
353
|
+
structural ??= selectStructuralModel(node.children, typeof contentModel === 'function' ? contentModel(attrs) : contentModel, attrs);
|
|
354
|
+
return structural.type === 'sections' ? structural.emitTag : undefined;
|
|
355
|
+
};
|
|
356
|
+
const refs = {};
|
|
357
|
+
const children = [];
|
|
358
|
+
for (const slot of slots) {
|
|
359
|
+
let out;
|
|
360
|
+
if (slot.attr !== undefined) {
|
|
361
|
+
const value = attrs[slot.attr];
|
|
362
|
+
if (slot.omitWhenEmpty && (value == null || value === ''))
|
|
363
|
+
continue;
|
|
364
|
+
out = new Tag(slot.el ?? 'span', {}, [value ?? '']);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
const field = slot.field;
|
|
368
|
+
let nodes;
|
|
369
|
+
if (field === 'sections' && sectionsEmitTag() === undefined) {
|
|
370
|
+
nodes = asNodes(resolved.sections).map((entry) => renderSectionEntry(entry, config));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
nodes = render(resolved[field], config);
|
|
374
|
+
}
|
|
375
|
+
if (slot.kind === 'value') {
|
|
376
|
+
if (nodes.length === 0)
|
|
377
|
+
continue;
|
|
378
|
+
const only = nodes[0];
|
|
379
|
+
if (nodes.length > 1 || !Tag.isTag(only)) {
|
|
380
|
+
throw new Error(`Rune "${rune}": value slot \`${slot.name}\` rendered ${nodes.length} node(s), not one element. A value slot names exactly one node.`);
|
|
381
|
+
}
|
|
382
|
+
out = only;
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
if (nodes.length === 0 && slot.omitWhenEmpty)
|
|
386
|
+
continue;
|
|
387
|
+
out = new Tag(slot.el ?? 'div', {}, nodes);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
refs[slot.name] = out;
|
|
391
|
+
children.push(out);
|
|
392
|
+
}
|
|
393
|
+
return createComponentRenderable({
|
|
394
|
+
rune,
|
|
395
|
+
tag: tag,
|
|
396
|
+
property,
|
|
397
|
+
properties: properties ? fieldMetas(attrs, config, properties) : undefined,
|
|
398
|
+
refs,
|
|
399
|
+
children,
|
|
400
|
+
});
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* A declaration with every default made explicit — what the generated transform
|
|
405
|
+
* will actually do, which is the thing a reviewer needs and the declaration's
|
|
406
|
+
* terseness hides.
|
|
407
|
+
*/
|
|
408
|
+
export function describeSlots(emits, contentModel) {
|
|
409
|
+
const roles = slotSections(emits);
|
|
410
|
+
let emitTag;
|
|
411
|
+
if (contentModel) {
|
|
412
|
+
const m = typeof contentModel === 'function' ? contentModel({}) : contentModel;
|
|
413
|
+
const s = 'when' in m ? m.default : m;
|
|
414
|
+
if ('type' in s && s.type === 'sections')
|
|
415
|
+
emitTag = s.emitTag;
|
|
416
|
+
}
|
|
417
|
+
return Object.entries(emits.slots).map(([name, raw]) => {
|
|
418
|
+
const decl = typeof raw === 'string' ? { as: raw } : raw;
|
|
419
|
+
const from = decl.from ?? name;
|
|
420
|
+
const fromAttr = from.startsWith('attrs.');
|
|
421
|
+
const el = decl.as === 'region' ? (decl.el ?? 'div') : fromAttr ? (decl.el ?? 'span') : undefined;
|
|
422
|
+
return {
|
|
423
|
+
name,
|
|
424
|
+
from,
|
|
425
|
+
as: decl.as,
|
|
426
|
+
...(el ? { el } : {}),
|
|
427
|
+
omitWhenEmpty: decl.omitWhenEmpty ?? false,
|
|
428
|
+
...(roles[name] ? { role: roles[name] } : {}),
|
|
429
|
+
...(from === 'sections' && contentModel
|
|
430
|
+
? { sections: emitTag ? 'child runes' : 'entries' }
|
|
431
|
+
: {}),
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
/** One line per slot, for the text surfaces. */
|
|
436
|
+
export function formatSlotLine(slot) {
|
|
437
|
+
const parts = [slot.as];
|
|
438
|
+
if (slot.el)
|
|
439
|
+
parts.push(`<${slot.el}>`);
|
|
440
|
+
if (slot.omitWhenEmpty)
|
|
441
|
+
parts.push('omitted when empty');
|
|
442
|
+
if (slot.role)
|
|
443
|
+
parts.push(`role: ${slot.role}`);
|
|
444
|
+
if (slot.sections)
|
|
445
|
+
parts.push(`sections arrive as ${slot.sections}`);
|
|
446
|
+
return `${slot.name} <- ${slot.from} (${parts.join(', ')})`;
|
|
447
|
+
}
|
|
448
|
+
//# sourceMappingURL=slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/lib/slots.ts"],"names":[],"mappings":"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"}
|
package/dist/plugins.d.ts
CHANGED
|
@@ -114,4 +114,7 @@ export declare function discoverPluginFixtureManifest(npmPackageName: string): P
|
|
|
114
114
|
* back to the first parsed). Backward-compatible with bare `<rune>.md` files.
|
|
115
115
|
*/
|
|
116
116
|
export declare function discoverPluginFixtures(npmPackageName: string): Promise<Record<string, string>>;
|
|
117
|
+
/** Validate a loaded Plugin has required fields. Each rune entry carries
|
|
118
|
+
* exactly one of `transform` or `template` (SPEC-153 D11). */
|
|
119
|
+
export declare function validatePlugin(pkg: Plugin, npmName: string): void;
|
|
117
120
|
//# sourceMappingURL=plugins.d.ts.map
|
package/dist/plugins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAExF,OAAO,EAAE,IAAI,EAA0B,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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"}
|
package/dist/plugins.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { selectLocaleBundle } from '@refrakt-md/transform';
|
|
2
2
|
import { defineRune, runeTagMap } from './rune.js';
|
|
3
|
+
import { checkComposedCatalog, composedPluginRune } from './composed-rune.js';
|
|
4
|
+
import { compositionFor, composedTypeName } from './lib/composition.js';
|
|
3
5
|
/** Reserved namespace names that cannot be used by user config or plugins. */
|
|
4
6
|
const RESERVED_FILE_ROOT_NAMESPACES = new Set(['site']);
|
|
5
7
|
/** Validate that a file-root namespace name is allowed. Throws on reserved
|
|
@@ -34,6 +36,23 @@ export async function loadPlugin(npmPackageName) {
|
|
|
34
36
|
const runes = {};
|
|
35
37
|
const fixtures = {};
|
|
36
38
|
for (const [runeName, entry] of Object.entries(pkg.runes)) {
|
|
39
|
+
if (entry.template !== undefined) {
|
|
40
|
+
// SPEC-153 D11 — a composed rune: its schema and its block-less
|
|
41
|
+
// config are both built from the definition.
|
|
42
|
+
const composed = composedPluginRune(runeName, entry);
|
|
43
|
+
runes[runeName] = defineRune({
|
|
44
|
+
...composed.rune,
|
|
45
|
+
name: runeName,
|
|
46
|
+
schema: composed.rune.schema,
|
|
47
|
+
description: entry.description ?? composed.rune.description,
|
|
48
|
+
aliases: entry.aliases ?? composed.rune.aliases,
|
|
49
|
+
seoType: entry.seoType,
|
|
50
|
+
authoringHints: entry.authoringHints,
|
|
51
|
+
});
|
|
52
|
+
if (entry.fixture)
|
|
53
|
+
fixtures[runeName] = entry.fixture;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
37
56
|
runes[runeName] = defineRune({
|
|
38
57
|
name: runeName,
|
|
39
58
|
schema: entry.transform,
|
|
@@ -198,6 +217,13 @@ export function mergePlugins(loaded, coreRuneNames, prefer) {
|
|
|
198
217
|
themeRunes[key] = value;
|
|
199
218
|
}
|
|
200
219
|
}
|
|
220
|
+
// SPEC-145 D2a — a composed rune's config is generated from its
|
|
221
|
+
// definition, never hand-written beside it.
|
|
222
|
+
for (const rune of Object.values(loadedPkg.runes)) {
|
|
223
|
+
const info = compositionFor(rune.schema);
|
|
224
|
+
if (info?.config && info.typeName)
|
|
225
|
+
themeRunes[info.typeName] = info.config;
|
|
226
|
+
}
|
|
201
227
|
if (loadedPkg.pkg.theme?.icons) {
|
|
202
228
|
for (const [group, icons] of Object.entries(loadedPkg.pkg.theme.icons)) {
|
|
203
229
|
themeIcons[group] = { ...themeIcons[group], ...icons };
|
|
@@ -209,6 +235,10 @@ export function mergePlugins(loaded, coreRuneNames, prefer) {
|
|
|
209
235
|
}
|
|
210
236
|
}
|
|
211
237
|
}
|
|
238
|
+
// SPEC-145 — the composition checks that need every rune: cycles (by name),
|
|
239
|
+
// a composed type placed over a peer type (D9), a placed rune missing its
|
|
240
|
+
// required parent (D12). Here, at assembly, rather than at render.
|
|
241
|
+
checkComposedCatalog(runes, themeRunes);
|
|
212
242
|
const extensions = {};
|
|
213
243
|
for (const loadedPkg of loaded) {
|
|
214
244
|
if (loadedPkg.pkg.extends) {
|
|
@@ -390,7 +420,9 @@ export async function discoverPluginFixtureManifest(npmPackageName) {
|
|
|
390
420
|
}
|
|
391
421
|
}
|
|
392
422
|
catch {
|
|
393
|
-
//
|
|
423
|
+
// `<pkg>/package.json` did not resolve — the package is not installed, or it declares an
|
|
424
|
+
// `exports` map without a `./package.json` entry (ERR_PACKAGE_PATH_NOT_EXPORTED). A
|
|
425
|
+
// workspace link resolves fine. Skip file fixtures.
|
|
394
426
|
}
|
|
395
427
|
return manifest;
|
|
396
428
|
}
|
|
@@ -436,8 +468,9 @@ function isPlugin(value) {
|
|
|
436
468
|
typeof obj.runes === 'object' &&
|
|
437
469
|
obj.runes !== null);
|
|
438
470
|
}
|
|
439
|
-
/** Validate a loaded Plugin has required fields
|
|
440
|
-
|
|
471
|
+
/** Validate a loaded Plugin has required fields. Each rune entry carries
|
|
472
|
+
* exactly one of `transform` or `template` (SPEC-153 D11). */
|
|
473
|
+
export function validatePlugin(pkg, npmName) {
|
|
441
474
|
if (!pkg.name) {
|
|
442
475
|
throw new Error(`Plugin "${npmName}" has an empty name field`);
|
|
443
476
|
}
|
|
@@ -448,9 +481,25 @@ function validatePlugin(pkg, npmName) {
|
|
|
448
481
|
throw new Error(`Plugin "${npmName}" defines no runes`);
|
|
449
482
|
}
|
|
450
483
|
for (const [name, entry] of Object.entries(pkg.runes)) {
|
|
484
|
+
if (entry.template !== undefined) {
|
|
485
|
+
if (entry.transform !== undefined) {
|
|
486
|
+
throw new Error(`Plugin "${npmName}" rune "${name}" carries both a \`transform\` and a composition \`template\`. ` +
|
|
487
|
+
`A rune has exactly one emit path (SPEC-145 D5, SPEC-153 D11): drop the transform to compose, or the template to build its own output.`);
|
|
488
|
+
}
|
|
489
|
+
if (typeof entry.template !== 'string') {
|
|
490
|
+
throw new Error(`Plugin "${npmName}" rune "${name}" has an invalid template. ` +
|
|
491
|
+
`Expected a composed rune definition: YAML frontmatter and a Markdoc template, as one string.`);
|
|
492
|
+
}
|
|
493
|
+
const configKey = composedTypeName(name);
|
|
494
|
+
if (pkg.theme?.runes?.[configKey] !== undefined) {
|
|
495
|
+
throw new Error(`Plugin "${npmName}" rune "${name}" is composed but also has a hand-written theme config (\`theme.runes.${configKey}\`). ` +
|
|
496
|
+
`A composed rune's config is generated from its definition, and it has no block and ships no CSS (SPEC-145 D2, D2a).`);
|
|
497
|
+
}
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
451
500
|
if (!entry.transform || typeof entry.transform !== 'object') {
|
|
452
501
|
throw new Error(`Plugin "${npmName}" rune "${name}" has an invalid transform. ` +
|
|
453
|
-
`Expected a Markdoc Schema object (created via createContentModelSchema())
|
|
502
|
+
`Expected a Markdoc Schema object (created via createContentModelSchema()), or a composition \`template\`.`);
|
|
454
503
|
}
|
|
455
504
|
}
|
|
456
505
|
}
|