@refrakt-md/runes 0.14.4 → 0.15.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 +40 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +154 -88
- package/dist/config.js.map +1 -1
- package/dist/drawer-pipeline.d.ts +33 -0
- package/dist/drawer-pipeline.d.ts.map +1 -0
- package/dist/drawer-pipeline.js +206 -0
- package/dist/drawer-pipeline.js.map +1 -0
- package/dist/expand-pipeline.d.ts +51 -0
- package/dist/expand-pipeline.d.ts.map +1 -0
- package/dist/expand-pipeline.js +305 -0
- package/dist/expand-pipeline.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -3
- package/dist/index.js.map +1 -1
- package/dist/lang-map.d.ts +32 -0
- package/dist/lang-map.d.ts.map +1 -0
- package/dist/lang-map.js +76 -0
- package/dist/lang-map.js.map +1 -0
- package/dist/lib/read-file.d.ts +78 -0
- package/dist/lib/read-file.d.ts.map +1 -0
- package/dist/lib/read-file.js +166 -0
- package/dist/lib/read-file.js.map +1 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +12 -1
- package/dist/nodes.js.map +1 -1
- package/dist/outline-scope.d.ts +29 -0
- package/dist/outline-scope.d.ts.map +1 -0
- package/dist/outline-scope.js +149 -0
- package/dist/outline-scope.js.map +1 -0
- package/dist/plugins.d.ts +13 -0
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +65 -1
- package/dist/plugins.js.map +1 -1
- package/dist/snippet-pipeline.d.ts +42 -0
- package/dist/snippet-pipeline.d.ts.map +1 -0
- package/dist/snippet-pipeline.js +219 -0
- package/dist/snippet-pipeline.js.map +1 -0
- package/dist/tags/drawer.d.ts +26 -0
- package/dist/tags/drawer.d.ts.map +1 -0
- package/dist/tags/drawer.js +134 -0
- package/dist/tags/drawer.js.map +1 -0
- package/dist/tags/expand.d.ts +22 -0
- package/dist/tags/expand.d.ts.map +1 -0
- package/dist/tags/expand.js +76 -0
- package/dist/tags/expand.js.map +1 -0
- package/dist/tags/snippet.d.ts +19 -0
- package/dist/tags/snippet.d.ts.map +1 -0
- package/dist/tags/snippet.js +49 -0
- package/dist/tags/snippet.js.map +1 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +35 -0
- package/dist/util.js.map +1 -1
- package/dist/xref-patterns.d.ts +57 -0
- package/dist/xref-patterns.d.ts.map +1 -0
- package/dist/xref-patterns.js +140 -0
- package/dist/xref-patterns.js.map +1 -0
- package/dist/xref-resolve.d.ts +22 -5
- package/dist/xref-resolve.d.ts.map +1 -1
- package/dist/xref-resolve.js +203 -79
- package/dist/xref-resolve.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drawer pipeline hooks (SPEC-060, WORK-257).
|
|
3
|
+
*
|
|
4
|
+
* - **Register** walks each page's renderable for drawer tags
|
|
5
|
+
* (`data-rune="drawer"`), and adds each as a page-scoped entity
|
|
6
|
+
* (`type: 'drawer'`, `scope: 'page'`, `sourceUrl: "${pageUrl}#drawer-${id}"`).
|
|
7
|
+
* Page scope means two pages can both declare `id="auth"` without
|
|
8
|
+
* colliding in the site-wide registry (WORK-256).
|
|
9
|
+
*
|
|
10
|
+
* - **postProcess** resolves drawer title heading levels for drawers that
|
|
11
|
+
* were authored without an explicit `headingLevel`. The title carries
|
|
12
|
+
* a `data-drawer-title-auto` marker emitted by the schema; the walk
|
|
13
|
+
* tracks document outline depth (the most recent `<h{n}>` seen) and
|
|
14
|
+
* rewrites the marked tag to `h{n+1}` (clamped 1..6, default h2 when
|
|
15
|
+
* no preceding heading exists).
|
|
16
|
+
*/
|
|
17
|
+
import Markdoc from '@markdoc/markdoc';
|
|
18
|
+
import { DRAWER_TITLE_AUTO_MARKER } from './tags/drawer.js';
|
|
19
|
+
const { Tag } = Markdoc;
|
|
20
|
+
const HEADING_TAG_RE = /^h([1-6])$/;
|
|
21
|
+
/** Read a `data-*` attribute from a tag, treating undefined as undefined. */
|
|
22
|
+
function readDataAttr(tag, key) {
|
|
23
|
+
const v = tag.attributes?.[key];
|
|
24
|
+
return typeof v === 'string' ? v : undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Read the `content` of a property meta tag (`<meta data-field="...">`)
|
|
27
|
+
* immediately under the drawer tag. The schema emits side/size/shortcut as
|
|
28
|
+
* meta tags; the identity-transform engine consumes them later and stamps
|
|
29
|
+
* them as `data-side` etc. on the wrapper. The register hook runs before
|
|
30
|
+
* the engine, so we have to read directly from the meta tags. */
|
|
31
|
+
function readPropertyMeta(drawerTag, field) {
|
|
32
|
+
for (const child of drawerTag.children ?? []) {
|
|
33
|
+
if (!Tag.isTag(child))
|
|
34
|
+
continue;
|
|
35
|
+
const c = child;
|
|
36
|
+
if (c.name !== 'meta')
|
|
37
|
+
continue;
|
|
38
|
+
if (c.attributes?.['data-field'] !== field)
|
|
39
|
+
continue;
|
|
40
|
+
const content = c.attributes?.['content'];
|
|
41
|
+
return typeof content === 'string' ? content : undefined;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Walk the renderable tree of every page and register each drawer rune
|
|
47
|
+
* as a page-scoped entity. Each drawer surfaces in the registry as
|
|
48
|
+
* `{ type: 'drawer', id, scope: 'page', sourceUrl: '<pageUrl>#drawer-<id>' }`
|
|
49
|
+
* with `data.title`, `data.side`, `data.size`, `data.shortcut` for
|
|
50
|
+
* downstream consumers (xref resolver, registry-driven tooling).
|
|
51
|
+
*/
|
|
52
|
+
export function registerDrawers(pages, registry, ctx) {
|
|
53
|
+
for (const page of pages) {
|
|
54
|
+
const drawersOnPage = [];
|
|
55
|
+
const seenIds = new Set();
|
|
56
|
+
walkForDrawers(page.renderable, (tag) => {
|
|
57
|
+
const id = readDataAttr(tag, 'data-drawer-id');
|
|
58
|
+
if (!id) {
|
|
59
|
+
ctx.error('drawer rune is missing required `id` attribute', page.url);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (seenIds.has(id)) {
|
|
63
|
+
ctx.warn(`drawer id="${id}" is declared more than once on this page — last declaration wins`, page.url);
|
|
64
|
+
}
|
|
65
|
+
seenIds.add(id);
|
|
66
|
+
drawersOnPage.push({
|
|
67
|
+
id,
|
|
68
|
+
title: extractTitleText(tag),
|
|
69
|
+
side: readPropertyMeta(tag, 'side') ?? 'right',
|
|
70
|
+
size: readPropertyMeta(tag, 'size') ?? 'md',
|
|
71
|
+
shortcut: readPropertyMeta(tag, 'shortcut'),
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
for (const d of drawersOnPage) {
|
|
75
|
+
registry.register({
|
|
76
|
+
type: 'drawer',
|
|
77
|
+
id: d.id,
|
|
78
|
+
scope: 'page',
|
|
79
|
+
sourceUrl: `${page.url}#drawer-${d.id}`,
|
|
80
|
+
data: {
|
|
81
|
+
title: d.title,
|
|
82
|
+
side: d.side,
|
|
83
|
+
size: d.size,
|
|
84
|
+
shortcut: d.shortcut,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Walk the renderable looking for drawer-rune tags. Visits each drawer's
|
|
91
|
+
* shell exactly once (we don't recurse into a drawer's body, drawer-in-drawer
|
|
92
|
+
* is out of scope). */
|
|
93
|
+
function walkForDrawers(node, visit) {
|
|
94
|
+
if (Array.isArray(node)) {
|
|
95
|
+
for (const c of node)
|
|
96
|
+
walkForDrawers(c, visit);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!Tag.isTag(node))
|
|
100
|
+
return;
|
|
101
|
+
const tag = node;
|
|
102
|
+
if (tag.attributes?.['data-rune'] === 'drawer') {
|
|
103
|
+
visit(tag);
|
|
104
|
+
// Don't recurse — drawer-in-drawer isn't supported and skipping the
|
|
105
|
+
// body avoids treating a future inner-drawer descendant as a sibling
|
|
106
|
+
// of the outer one.
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!tag.children)
|
|
110
|
+
return;
|
|
111
|
+
for (const c of tag.children)
|
|
112
|
+
walkForDrawers(c, visit);
|
|
113
|
+
}
|
|
114
|
+
/** Pull the drawer's title text out of its header → title element. Returns
|
|
115
|
+
* `undefined` when the drawer has no title (the rune renders headerless
|
|
116
|
+
* in that case). String concatenation of leaf text nodes is good enough —
|
|
117
|
+
* drawer titles are short. */
|
|
118
|
+
function extractTitleText(drawerTag) {
|
|
119
|
+
const titleTag = findByDataName(drawerTag, 'title');
|
|
120
|
+
if (!titleTag)
|
|
121
|
+
return undefined;
|
|
122
|
+
const text = collectText(titleTag);
|
|
123
|
+
return text.length > 0 ? text : undefined;
|
|
124
|
+
}
|
|
125
|
+
function findByDataName(root, name) {
|
|
126
|
+
if (root.attributes?.['data-name'] === name) {
|
|
127
|
+
return root;
|
|
128
|
+
}
|
|
129
|
+
for (const c of root.children ?? []) {
|
|
130
|
+
if (Tag.isTag(c)) {
|
|
131
|
+
const hit = findByDataName(c, name);
|
|
132
|
+
if (hit)
|
|
133
|
+
return hit;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
function collectText(node) {
|
|
139
|
+
if (typeof node === 'string')
|
|
140
|
+
return node;
|
|
141
|
+
if (Array.isArray(node))
|
|
142
|
+
return node.map(collectText).join('');
|
|
143
|
+
if (Tag.isTag(node)) {
|
|
144
|
+
const tag = node;
|
|
145
|
+
return (tag.children ?? []).map(collectText).join('');
|
|
146
|
+
}
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* postProcess walk: rewrite each `data-drawer-title-auto` heading to the
|
|
151
|
+
* level computed from the outline depth at that position on the page.
|
|
152
|
+
* Returns the same renderable identity when no drawer titles needed
|
|
153
|
+
* rewriting, so downstream postProcess steps can skip a no-op pass.
|
|
154
|
+
*/
|
|
155
|
+
export function resolveAutoDrawerTitleLevels(renderable) {
|
|
156
|
+
const state = { lastHeadingLevel: 0, mutated: false };
|
|
157
|
+
const next = walkAndRewriteTitles(renderable, state);
|
|
158
|
+
return state.mutated ? next : renderable;
|
|
159
|
+
}
|
|
160
|
+
function walkAndRewriteTitles(node, state) {
|
|
161
|
+
if (typeof node === 'string' || typeof node === 'number' || node == null)
|
|
162
|
+
return node;
|
|
163
|
+
if (Array.isArray(node)) {
|
|
164
|
+
let mutated = false;
|
|
165
|
+
const next = node.map((c) => {
|
|
166
|
+
const w = walkAndRewriteTitles(c, state);
|
|
167
|
+
if (w !== c)
|
|
168
|
+
mutated = true;
|
|
169
|
+
return w;
|
|
170
|
+
});
|
|
171
|
+
return mutated ? next : node;
|
|
172
|
+
}
|
|
173
|
+
if (!Tag.isTag(node))
|
|
174
|
+
return node;
|
|
175
|
+
const tag = node;
|
|
176
|
+
const headingMatch = HEADING_TAG_RE.exec(tag.name);
|
|
177
|
+
// Auto-title placeholder: rewrite this node's tag name based on the
|
|
178
|
+
// last heading level we saw. Default to h2 when no heading has been
|
|
179
|
+
// encountered yet (the page-title h1 lives in layout, so the next
|
|
180
|
+
// reasonable level inside the body is h2).
|
|
181
|
+
const isAutoTitle = tag.attributes?.[DRAWER_TITLE_AUTO_MARKER] === 'true';
|
|
182
|
+
if (isAutoTitle) {
|
|
183
|
+
const base = state.lastHeadingLevel === 0 ? 1 : state.lastHeadingLevel;
|
|
184
|
+
const targetLevel = Math.min(6, Math.max(1, base + 1));
|
|
185
|
+
state.mutated = true;
|
|
186
|
+
const newAttrs = { ...tag.attributes };
|
|
187
|
+
delete newAttrs[DRAWER_TITLE_AUTO_MARKER];
|
|
188
|
+
return new Tag(`h${targetLevel}`, newAttrs, tag.children);
|
|
189
|
+
}
|
|
190
|
+
if (headingMatch) {
|
|
191
|
+
state.lastHeadingLevel = Number(headingMatch[1]);
|
|
192
|
+
}
|
|
193
|
+
if (!tag.children || tag.children.length === 0)
|
|
194
|
+
return tag;
|
|
195
|
+
let mutated = false;
|
|
196
|
+
const newChildren = tag.children.map((c) => {
|
|
197
|
+
const w = walkAndRewriteTitles(c, state);
|
|
198
|
+
if (w !== c)
|
|
199
|
+
mutated = true;
|
|
200
|
+
return w;
|
|
201
|
+
});
|
|
202
|
+
if (!mutated)
|
|
203
|
+
return tag;
|
|
204
|
+
return new Tag(tag.name, tag.attributes, newChildren);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=drawer-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawer-pipeline.js","sourceRoot":"","sources":["../src/drawer-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expand pipeline (SPEC-066, WORK-260).
|
|
3
|
+
*
|
|
4
|
+
* Post-process resolver that finds `{% expand %}` placeholder tags
|
|
5
|
+
* (`data-rune="expand-pending"`) in a page's renderable tree, looks
|
|
6
|
+
* each up in the registry, reads + parses the entity's `sourceFile`
|
|
7
|
+
* (cached per build), calls the plugin's `extract()` to grab the
|
|
8
|
+
* embeddable AST subtree, optionally shifts heading levels, transforms
|
|
9
|
+
* the subtree using the build's full tags+nodes config, and substitutes
|
|
10
|
+
* the result in place wrapped in `<section class="rf-expand"
|
|
11
|
+
* data-rune="expand" data-outline-scope="${id}">`.
|
|
12
|
+
*
|
|
13
|
+
* The wrapper's `data-outline-scope` attribute is picked up by the
|
|
14
|
+
* WORK-259 walkers — heading IDs inside get prefixed, TOC items
|
|
15
|
+
* pointing at them get dropped — without expand needing to coordinate.
|
|
16
|
+
*
|
|
17
|
+
* Per-build caches:
|
|
18
|
+
* - `sourceFile → parsedAst` (one parse per file regardless of how
|
|
19
|
+
* many pages embed it)
|
|
20
|
+
*
|
|
21
|
+
* Per-page state:
|
|
22
|
+
* - resolution stack (`(type, id)` tuples) for cycle detection
|
|
23
|
+
*/
|
|
24
|
+
import type { Node } from '@markdoc/markdoc';
|
|
25
|
+
import type { EntityRegistry, PipelineContext } from '@refrakt-md/types';
|
|
26
|
+
import type { CompiledXrefPattern } from './xref-patterns.js';
|
|
27
|
+
export interface ExpandResolveContext {
|
|
28
|
+
pageUrl: string;
|
|
29
|
+
registry: Readonly<EntityRegistry>;
|
|
30
|
+
patterns: CompiledXrefPattern[];
|
|
31
|
+
embedConfig?: {
|
|
32
|
+
tags: Record<string, unknown>;
|
|
33
|
+
nodes: Record<string, unknown>;
|
|
34
|
+
projectRoot?: string;
|
|
35
|
+
};
|
|
36
|
+
ctx: PipelineContext;
|
|
37
|
+
/** Per-build source-file cache. Shared across calls within one build,
|
|
38
|
+
* so a file embedded on twenty pages is parsed once. */
|
|
39
|
+
parseCache: Map<string, Node>;
|
|
40
|
+
}
|
|
41
|
+
/** Reset the per-build cache. Tests call this between cases; production
|
|
42
|
+
* builds rely on the cache living for the build's lifetime (each build
|
|
43
|
+
* starts fresh because the runes package is imported anew). */
|
|
44
|
+
export declare function __resetExpandCache(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Walk a renderable tree, replace every `expand-pending` placeholder
|
|
47
|
+
* with the substituted entity content. Returns the same renderable
|
|
48
|
+
* reference when no placeholders were found.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveExpands(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry>, patterns: CompiledXrefPattern[], embedConfig: ExpandResolveContext['embedConfig'], ctx: PipelineContext): unknown;
|
|
51
|
+
//# sourceMappingURL=expand-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expand-pipeline.d.ts","sourceRoot":"","sources":["../src/expand-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG7F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAI9D,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACnC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,GAAG,EAAE,eAAe,CAAC;IACrB;6DACyD;IACzD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC9B;AAOD;;gEAEgE;AAChE,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,EAClC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,WAAW,EAAE,oBAAoB,CAAC,aAAa,CAAC,EAChD,GAAG,EAAE,eAAe,GAClB,OAAO,CAUT"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expand pipeline (SPEC-066, WORK-260).
|
|
3
|
+
*
|
|
4
|
+
* Post-process resolver that finds `{% expand %}` placeholder tags
|
|
5
|
+
* (`data-rune="expand-pending"`) in a page's renderable tree, looks
|
|
6
|
+
* each up in the registry, reads + parses the entity's `sourceFile`
|
|
7
|
+
* (cached per build), calls the plugin's `extract()` to grab the
|
|
8
|
+
* embeddable AST subtree, optionally shifts heading levels, transforms
|
|
9
|
+
* the subtree using the build's full tags+nodes config, and substitutes
|
|
10
|
+
* the result in place wrapped in `<section class="rf-expand"
|
|
11
|
+
* data-rune="expand" data-outline-scope="${id}">`.
|
|
12
|
+
*
|
|
13
|
+
* The wrapper's `data-outline-scope` attribute is picked up by the
|
|
14
|
+
* WORK-259 walkers — heading IDs inside get prefixed, TOC items
|
|
15
|
+
* pointing at them get dropped — without expand needing to coordinate.
|
|
16
|
+
*
|
|
17
|
+
* Per-build caches:
|
|
18
|
+
* - `sourceFile → parsedAst` (one parse per file regardless of how
|
|
19
|
+
* many pages embed it)
|
|
20
|
+
*
|
|
21
|
+
* Per-page state:
|
|
22
|
+
* - resolution stack (`(type, id)` tuples) for cycle detection
|
|
23
|
+
*/
|
|
24
|
+
import Markdoc from '@markdoc/markdoc';
|
|
25
|
+
import { EXPAND_PLACEHOLDER_MARKER } from './tags/expand.js';
|
|
26
|
+
import { readWholeSandboxedFile, SnippetSandboxError } from './lib/read-file.js';
|
|
27
|
+
const { Tag } = Markdoc;
|
|
28
|
+
/** Per-build source-file parse cache. Lives outside the resolve context
|
|
29
|
+
* so a single build's runs reuse the same instance — the resolver is
|
|
30
|
+
* invoked per page, but the cache is per build. */
|
|
31
|
+
const buildParseCache = new Map();
|
|
32
|
+
/** Reset the per-build cache. Tests call this between cases; production
|
|
33
|
+
* builds rely on the cache living for the build's lifetime (each build
|
|
34
|
+
* starts fresh because the runes package is imported anew). */
|
|
35
|
+
export function __resetExpandCache() {
|
|
36
|
+
buildParseCache.clear();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Walk a renderable tree, replace every `expand-pending` placeholder
|
|
40
|
+
* with the substituted entity content. Returns the same renderable
|
|
41
|
+
* reference when no placeholders were found.
|
|
42
|
+
*/
|
|
43
|
+
export function resolveExpands(renderable, pageUrl, registry, patterns, embedConfig, ctx) {
|
|
44
|
+
const rc = {
|
|
45
|
+
pageUrl,
|
|
46
|
+
registry,
|
|
47
|
+
patterns,
|
|
48
|
+
embedConfig,
|
|
49
|
+
ctx,
|
|
50
|
+
parseCache: buildParseCache,
|
|
51
|
+
};
|
|
52
|
+
return walk(renderable, rc, []);
|
|
53
|
+
}
|
|
54
|
+
function walk(node, rc, stack) {
|
|
55
|
+
if (Array.isArray(node)) {
|
|
56
|
+
let mutated = false;
|
|
57
|
+
const next = node.map((c) => {
|
|
58
|
+
const w = walk(c, rc, stack);
|
|
59
|
+
if (w !== c)
|
|
60
|
+
mutated = true;
|
|
61
|
+
return w;
|
|
62
|
+
});
|
|
63
|
+
return mutated ? next : node;
|
|
64
|
+
}
|
|
65
|
+
if (!Tag.isTag(node))
|
|
66
|
+
return node;
|
|
67
|
+
const tag = node;
|
|
68
|
+
const dataRune = tag.attributes?.['data-rune'];
|
|
69
|
+
if (dataRune === EXPAND_PLACEHOLDER_MARKER) {
|
|
70
|
+
return resolveOnePlaceholder(tag, rc, stack);
|
|
71
|
+
}
|
|
72
|
+
if (!tag.children || tag.children.length === 0)
|
|
73
|
+
return tag;
|
|
74
|
+
let mutated = false;
|
|
75
|
+
const newChildren = tag.children.map((c) => {
|
|
76
|
+
const w = walk(c, rc, stack);
|
|
77
|
+
if (w !== c)
|
|
78
|
+
mutated = true;
|
|
79
|
+
return w;
|
|
80
|
+
});
|
|
81
|
+
if (!mutated)
|
|
82
|
+
return tag;
|
|
83
|
+
return new Tag(tag.name, tag.attributes, newChildren);
|
|
84
|
+
}
|
|
85
|
+
function resolveOnePlaceholder(tag, rc, stack) {
|
|
86
|
+
const attrs = tag.attributes;
|
|
87
|
+
const id = String(attrs['data-expand-id'] ?? '');
|
|
88
|
+
const typeHint = attrs['data-expand-type'];
|
|
89
|
+
const levelAttr = attrs['data-expand-level'];
|
|
90
|
+
const canonical = attrs['data-expand-canonical'] === 'true';
|
|
91
|
+
const authoredLabel = attrs['data-expand-label'];
|
|
92
|
+
if (!id) {
|
|
93
|
+
rc.ctx.error(`expand placeholder is missing \`primary\`/id attribute on ${rc.pageUrl}`, rc.pageUrl);
|
|
94
|
+
return errorNode(id, 'missing id attribute');
|
|
95
|
+
}
|
|
96
|
+
const level = levelAttr !== undefined ? Number(levelAttr) : undefined;
|
|
97
|
+
const entity = findEmbeddableEntity(rc.registry, id, rc.pageUrl, typeHint);
|
|
98
|
+
if (!entity) {
|
|
99
|
+
rc.ctx.error(`expand "${id}" on ${rc.pageUrl} — entity not found`, rc.pageUrl);
|
|
100
|
+
return errorNode(id, 'entity not found');
|
|
101
|
+
}
|
|
102
|
+
if (!entity.sourceFile || !entity.extract) {
|
|
103
|
+
rc.ctx.error(`expand "${id}" on ${rc.pageUrl} — entity type "${entity.type}" does not support embedding (no sourceFile/extract)`, rc.pageUrl);
|
|
104
|
+
return errorNode(id, `entity type "${entity.type}" does not support embedding`);
|
|
105
|
+
}
|
|
106
|
+
// Cycle detection. The stack is per-page-render — embedding the same
|
|
107
|
+
// entity on two different pages is fine; embedding it inside itself
|
|
108
|
+
// transitively is the bug we catch.
|
|
109
|
+
if (stack.some(s => s.type === entity.type && s.id === entity.id)) {
|
|
110
|
+
const cyclePath = [...stack, { type: entity.type, id: entity.id }]
|
|
111
|
+
.map(s => `${s.id} (${s.type})`)
|
|
112
|
+
.join(' → ');
|
|
113
|
+
rc.ctx.error(`expand cycle detected on ${rc.pageUrl}. Cycle: ${cyclePath}`, rc.pageUrl);
|
|
114
|
+
return errorNode(id, 'cycle detected');
|
|
115
|
+
}
|
|
116
|
+
const projectRoot = rc.embedConfig?.projectRoot;
|
|
117
|
+
if (!projectRoot) {
|
|
118
|
+
rc.ctx.error(`expand "${id}" — no project root configured (embedConfig.projectRoot is unset)`, rc.pageUrl);
|
|
119
|
+
return errorNode(id, 'no project root configured');
|
|
120
|
+
}
|
|
121
|
+
let parsed;
|
|
122
|
+
try {
|
|
123
|
+
parsed = parseSourceFile(entity.sourceFile, projectRoot, rc.parseCache);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const msg = err instanceof SnippetSandboxError ? err.message : err.message;
|
|
127
|
+
rc.ctx.error(`expand "${id}" — failed to read source file "${entity.sourceFile}": ${msg}`, rc.pageUrl);
|
|
128
|
+
return errorNode(id, msg);
|
|
129
|
+
}
|
|
130
|
+
const extracted = entity.extract(parsed);
|
|
131
|
+
if (!extracted) {
|
|
132
|
+
rc.ctx.error(`expand "${id}" — extractor returned no content; "${entity.sourceFile}" may have been edited out-of-sync with the registry`, rc.pageUrl);
|
|
133
|
+
return errorNode(id, 'extractor returned no content');
|
|
134
|
+
}
|
|
135
|
+
// Heading processing — `level=N` shifts headings by `N - 1`. Without
|
|
136
|
+
// `level=` the embed stays in peer-document mode; the outline-scope
|
|
137
|
+
// walkers (WORK-259) handle ID namespacing + TOC isolation downstream.
|
|
138
|
+
let processed = extracted;
|
|
139
|
+
if (level !== undefined && level !== 1) {
|
|
140
|
+
const shift = level - 1;
|
|
141
|
+
const clampedHeadings = [];
|
|
142
|
+
processed = shiftHeadings(extracted, shift, clampedHeadings);
|
|
143
|
+
if (clampedHeadings.length > 0) {
|
|
144
|
+
rc.ctx.warn(`expand "${id}" at ${rc.pageUrl} — heading demotion (level=${level}) would push ${clampedHeadings.length} heading(s) past H6. Clamped to H6: ${clampedHeadings.map(t => `"${t}"`).join(', ')}`, rc.pageUrl);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (!rc.embedConfig) {
|
|
148
|
+
rc.ctx.error(`expand "${id}" — no embedConfig threaded through the pipeline`, rc.pageUrl);
|
|
149
|
+
return errorNode(id, 'no embed transform config');
|
|
150
|
+
}
|
|
151
|
+
// Transform the extracted subtree using the build's full tags+nodes
|
|
152
|
+
// config so embedded plan runes (or any other plugin-contributed
|
|
153
|
+
// schemas) execute normally. A nested walk handles any expand placeholders
|
|
154
|
+
// inside the embedded content (e.g. an embedded spec that references
|
|
155
|
+
// other specs).
|
|
156
|
+
const childStack = [...stack, { type: entity.type, id: entity.id }];
|
|
157
|
+
const transformed = Markdoc.transform(processed, rc.embedConfig);
|
|
158
|
+
const recursivelyResolved = walk(transformed, rc, childStack);
|
|
159
|
+
// Canonical-link affordance — resolve via the same chain xref uses.
|
|
160
|
+
const canonicalHref = resolveCanonicalHref(entity, rc.patterns);
|
|
161
|
+
// The engine's identity transform adds `class="rf-expand"` from the
|
|
162
|
+
// `Expand: { block: 'expand' }` config entry; don't set it here or it
|
|
163
|
+
// renders duplicated.
|
|
164
|
+
const wrapperAttrs = {
|
|
165
|
+
'data-rune': 'expand',
|
|
166
|
+
'data-entity-id': entity.id,
|
|
167
|
+
'data-entity-type': entity.type,
|
|
168
|
+
'data-source': 'registry',
|
|
169
|
+
};
|
|
170
|
+
// Outline-scope marker only when `level=` is unset (peer-document mode).
|
|
171
|
+
if (level === undefined) {
|
|
172
|
+
wrapperAttrs['data-outline-scope'] = entity.id;
|
|
173
|
+
}
|
|
174
|
+
if (canonicalHref) {
|
|
175
|
+
wrapperAttrs['data-canonical-href'] = canonicalHref;
|
|
176
|
+
}
|
|
177
|
+
const children = [];
|
|
178
|
+
if (Array.isArray(recursivelyResolved)) {
|
|
179
|
+
children.push(...recursivelyResolved);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
children.push(recursivelyResolved);
|
|
183
|
+
}
|
|
184
|
+
if (canonical) {
|
|
185
|
+
const label = authoredLabel || canonicalLinkDefault(entity);
|
|
186
|
+
const linkAttrs = {
|
|
187
|
+
class: canonicalHref
|
|
188
|
+
? 'rf-expand__canonical-link'
|
|
189
|
+
: 'rf-expand__canonical-link rf-xref--unresolved',
|
|
190
|
+
};
|
|
191
|
+
if (canonicalHref)
|
|
192
|
+
linkAttrs.href = canonicalHref;
|
|
193
|
+
children.push(new Tag('a', linkAttrs, [label]));
|
|
194
|
+
}
|
|
195
|
+
return new Tag('section', wrapperAttrs, children);
|
|
196
|
+
}
|
|
197
|
+
/** Resolve an entity by id and (optional) type hint. Uses the same
|
|
198
|
+
* registry surface as xref. */
|
|
199
|
+
function findEmbeddableEntity(registry, id, pageUrl, typeHint) {
|
|
200
|
+
const types = typeHint ? [typeHint] : registry.getTypes();
|
|
201
|
+
for (const type of types) {
|
|
202
|
+
const e = registry.getById(type, id, pageUrl);
|
|
203
|
+
if (e)
|
|
204
|
+
return e;
|
|
205
|
+
}
|
|
206
|
+
// Name-match fallback (same algorithm as xref).
|
|
207
|
+
const idLower = id.toLowerCase();
|
|
208
|
+
for (const type of types) {
|
|
209
|
+
for (const e of registry.getAll(type)) {
|
|
210
|
+
const name = e.data.name ?? '';
|
|
211
|
+
const title = e.data.title ?? '';
|
|
212
|
+
if (name.toLowerCase() === idLower || title.toLowerCase() === idLower)
|
|
213
|
+
return e;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
/** Resolve an entity's canonical URL using the same chain as xref: the
|
|
219
|
+
* registered `sourceUrl` first, then pattern matching against the id. */
|
|
220
|
+
function resolveCanonicalHref(entity, patterns) {
|
|
221
|
+
const sourceUrl = entity.sourceUrl;
|
|
222
|
+
const dataUrl = entity.data.url;
|
|
223
|
+
const baseUrl = dataUrl || sourceUrl;
|
|
224
|
+
if (baseUrl) {
|
|
225
|
+
const headingId = entity.data.headingId;
|
|
226
|
+
return headingId ? `${baseUrl}#${headingId}` : baseUrl;
|
|
227
|
+
}
|
|
228
|
+
for (const p of patterns) {
|
|
229
|
+
const m = p.match.exec(entity.id);
|
|
230
|
+
if (!m)
|
|
231
|
+
continue;
|
|
232
|
+
const groups = (m.groups ?? {});
|
|
233
|
+
const PLACEHOLDER_RE = /\{([a-zA-Z_$][a-zA-Z0-9_$]*)\}/g;
|
|
234
|
+
return p.template.replace(PLACEHOLDER_RE, (_match, name) => {
|
|
235
|
+
const value = name === 'id' ? entity.id : (groups[name] ?? '');
|
|
236
|
+
return value.split('/').map(encodeURIComponent).join('/');
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
function canonicalLinkDefault(entity) {
|
|
242
|
+
const title = entity.data.title;
|
|
243
|
+
const name = entity.data.name;
|
|
244
|
+
if (title)
|
|
245
|
+
return `View ${entity.type}: ${title}`;
|
|
246
|
+
if (name)
|
|
247
|
+
return `View ${entity.type}: ${name}`;
|
|
248
|
+
return `View ${entity.type} ${entity.id}`;
|
|
249
|
+
}
|
|
250
|
+
/** Parse a source file, caching per build. The path is resolved through
|
|
251
|
+
* the same sandbox as snippet so absolute paths and traversal escapes
|
|
252
|
+
* are rejected. File-system access lives behind a helper in
|
|
253
|
+
* `lib/read-file.ts` so the `node:fs` import stays out of this module
|
|
254
|
+
* and Vite can tree-shake it from browser bundles. */
|
|
255
|
+
function parseSourceFile(sourceFile, projectRoot, cache) {
|
|
256
|
+
const cached = cache.get(sourceFile);
|
|
257
|
+
if (cached)
|
|
258
|
+
return cached;
|
|
259
|
+
const raw = readWholeSandboxedFile({ relativePath: sourceFile, projectRoot });
|
|
260
|
+
const ast = Markdoc.parse(raw);
|
|
261
|
+
cache.set(sourceFile, ast);
|
|
262
|
+
return ast;
|
|
263
|
+
}
|
|
264
|
+
/** Recursively shift heading levels in a Markdoc AST subtree. Tracks
|
|
265
|
+
* headings that would push past H6 so the caller can warn. */
|
|
266
|
+
function shiftHeadings(node, shift, clampedHeadings) {
|
|
267
|
+
if (node.type === 'heading') {
|
|
268
|
+
const originalLevel = node.attributes.level;
|
|
269
|
+
const newLevel = originalLevel + shift;
|
|
270
|
+
if (newLevel > 6) {
|
|
271
|
+
const text = collectHeadingText(node);
|
|
272
|
+
clampedHeadings.push(text);
|
|
273
|
+
node.attributes.level = 6;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
node.attributes.level = newLevel;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
for (const child of node.children ?? []) {
|
|
280
|
+
shiftHeadings(child, shift, clampedHeadings);
|
|
281
|
+
}
|
|
282
|
+
return node;
|
|
283
|
+
}
|
|
284
|
+
function collectHeadingText(node) {
|
|
285
|
+
const parts = [];
|
|
286
|
+
for (const child of node.walk()) {
|
|
287
|
+
if (child.type === 'text' && typeof child.attributes.content === 'string') {
|
|
288
|
+
parts.push(child.attributes.content);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return parts.join('');
|
|
292
|
+
}
|
|
293
|
+
/** Build a visible error placeholder for an expand resolution that
|
|
294
|
+
* failed. The build also surfaces the error via `ctx.error` — the
|
|
295
|
+
* inline rendering exists so the failure shows up on the page. */
|
|
296
|
+
function errorNode(id, message) {
|
|
297
|
+
// Engine adds `rf-expand` from the block config. Error variant gets a
|
|
298
|
+
// static modifier via the engine config; we only set the data attrs.
|
|
299
|
+
return new Tag('section', {
|
|
300
|
+
'data-rune': 'expand',
|
|
301
|
+
'data-entity-id': id,
|
|
302
|
+
'data-expand-error': message,
|
|
303
|
+
}, [`expand "${id}" — ${message}`]);
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=expand-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expand-pipeline.js","sourceRoot":"","sources":["../src/expand-pipeline.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,8 @@ export type { DeprecationRule, ContentModelSchemaOptions } from './lib/index.js'
|
|
|
9
9
|
export { resolve, resolveSequence, resolveDelimited, resolveContentModel, resolveListItems, evaluateCondition, matchesType } from './lib/resolver.js';
|
|
10
10
|
export { linkItem, pageSectionProperties, buildLayoutMetas, extractMediaImage, unwrapParagraphImages, name as nameHelper, description as descriptionHelper, SplitablePageSectionModel, SplitLayoutModel, splitLayoutAttributes } from './tags/common.js';
|
|
11
11
|
export type { LayoutMetas } from './tags/common.js';
|
|
12
|
-
export { extractHeadings, headingsToList } from './util.js';
|
|
12
|
+
export { extractHeadings, firstH1, headingsToList } from './util.js';
|
|
13
|
+
export { LANG_MAP, FALLBACK_LANG, inferLanguage } from './lang-map.js';
|
|
13
14
|
export type { HeadingInfo } from './util.js';
|
|
14
15
|
export { extractSeo, collectJsonLd, textContent } from './seo.js';
|
|
15
16
|
export type { PageSeo, OgMeta } from './seo.js';
|
|
@@ -19,9 +20,9 @@ export { describeRune, renderContentModel, serializeContentModel, stripContentMo
|
|
|
19
20
|
export type { RuneInfo, RuneBasePresetInfo, RuneLike, HydrateOptions, ReferenceContext, ReferenceGroup, RenderReferenceOptions, SerializedAttribute, SerializedRune, SerializedContentModel, SerializedSequenceModel, SerializedSectionsModel, SerializedDelimitedModel, SerializedCustomModel, SerializedContentField, SerializedDelimitedZone, SerializedHeadingExtractField, SerializedKnownSection, } from './reference.js';
|
|
20
21
|
export { registerAttributePreset, lookupAttributePreset, schemaBasePresets, UNIVERSAL_ATTRIBUTE_NAMES, } from './attribute-presets.js';
|
|
21
22
|
export type { AttributePresetMetadata } from './attribute-presets.js';
|
|
22
|
-
export { loadPlugin, mergePlugins, applyAliases, loadLocalRunes, discoverPluginFixtures } from './plugins.js';
|
|
23
|
+
export { loadPlugin, mergePlugins, applyAliases, loadLocalRunes, discoverPluginFixtures, assertFileRootNamespaceAllowed } from './plugins.js';
|
|
23
24
|
export type { LoadedPlugin, MergedPluginResult } from './plugins.js';
|
|
24
|
-
export { coreConfig, baseConfig, corePipelineHooks, resolveCoreSentinels, type PageTreeNode } from './config.js';
|
|
25
|
+
export { coreConfig, baseConfig, corePipelineHooks, createCorePipelineHooks, resolveCoreSentinels, type PageTreeNode, type CorePipelineHooksOptions } from './config.js';
|
|
25
26
|
export { BREADCRUMB_AUTO_SENTINEL } from './tags/breadcrumb.js';
|
|
26
27
|
export { NAV_AUTO_SENTINEL } from './tags/nav.js';
|
|
27
28
|
export { PAGINATION_AUTO_SENTINEL } from './tags/pagination.js';
|
|
@@ -29,6 +30,8 @@ export { TINT_TOKENS } from './tags/tint.js';
|
|
|
29
30
|
export type { TintToken } from './tags/tint.js';
|
|
30
31
|
export { XREF_RUNE_MARKER } from './tags/xref.js';
|
|
31
32
|
export { resolveXrefs } from './xref-resolve.js';
|
|
33
|
+
export { compileXrefPatterns } from './xref-patterns.js';
|
|
34
|
+
export type { CompiledXrefPattern, CompiledXrefPatternsResult } from './xref-patterns.js';
|
|
32
35
|
export { escapeFenceTags } from './fence-escape.js';
|
|
33
36
|
export type { AccordionItemProps, AccordionProps, AnnotateNoteProps, AnnotateProps, BlogProps, BreadcrumbItemProps, BreadcrumbProps, BudgetLineItemProps, BudgetCategoryProps, BudgetProps, ChartProps, CodeGroupProps, CompareProps, ConversationMessageProps, ConversationProps, DataTableProps, DetailsProps, DiagramProps, DiffProps, EmbedProps, ErrorProps, FigureProps, FormProps, GalleryProps, GridProps, HintProps, JuxtaposePanelProps, JuxtaposeProps, MediaTextProps, NavItemProps, NavGroupProps, NavProps, PullQuoteProps, RevealStepProps, RevealProps, SandboxProps, ShowcaseProps, SidenoteProps, TabProps, TabPanelProps, TabGroupProps, TextBlockProps, TableOfContentsProps, } from './props.js';
|
|
34
37
|
export declare const documents: {
|
|
@@ -45,6 +48,7 @@ export declare const runes: {
|
|
|
45
48
|
tab: import("./rune.js").Rune;
|
|
46
49
|
tabs: import("./rune.js").Rune;
|
|
47
50
|
details: import("./rune.js").Rune;
|
|
51
|
+
drawer: import("./rune.js").Rune;
|
|
48
52
|
figure: import("./rune.js").Rune;
|
|
49
53
|
gallery: import("./rune.js").Rune;
|
|
50
54
|
accordion: import("./rune.js").Rune;
|
|
@@ -59,6 +63,7 @@ export declare const runes: {
|
|
|
59
63
|
compare: import("./rune.js").Rune;
|
|
60
64
|
datatable: import("./rune.js").Rune;
|
|
61
65
|
diff: import("./rune.js").Rune;
|
|
66
|
+
snippet: import("./rune.js").Rune;
|
|
62
67
|
chart: import("./rune.js").Rune;
|
|
63
68
|
diagram: import("./rune.js").Rune;
|
|
64
69
|
sidenote: import("./rune.js").Rune;
|
|
@@ -81,6 +86,7 @@ export declare const runes: {
|
|
|
81
86
|
bg: import("./rune.js").Rune;
|
|
82
87
|
blog: import("./rune.js").Rune;
|
|
83
88
|
xref: import("./rune.js").Rune;
|
|
89
|
+
expand: import("./rune.js").Rune;
|
|
84
90
|
badge: import("./rune.js").Rune;
|
|
85
91
|
};
|
|
86
92
|
/** Markdoc-compatible tags map derived from runes + Markdoc built-in tags */
|