@refrakt-md/runes 0.16.0 → 0.16.1
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 +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -4
- package/dist/config.js.map +1 -1
- package/dist/drawer-pipeline.d.ts +72 -1
- package/dist/drawer-pipeline.d.ts.map +1 -1
- package/dist/drawer-pipeline.js +242 -1
- package/dist/drawer-pipeline.js.map +1 -1
- package/dist/file-ref-resolve.d.ts +22 -0
- package/dist/file-ref-resolve.d.ts.map +1 -0
- package/dist/file-ref-resolve.js +233 -0
- package/dist/file-ref-resolve.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +62 -8
- package/dist/nodes.js.map +1 -1
- package/dist/snippet-pipeline.d.ts +7 -5
- package/dist/snippet-pipeline.d.ts.map +1 -1
- package/dist/snippet-pipeline.js +32 -13
- package/dist/snippet-pipeline.js.map +1 -1
- package/dist/tags/codegroup.d.ts.map +1 -1
- package/dist/tags/codegroup.js +37 -1
- package/dist/tags/codegroup.js.map +1 -1
- package/dist/tags/diff.d.ts.map +1 -1
- package/dist/tags/diff.js +85 -18
- package/dist/tags/diff.js.map +1 -1
- package/dist/tags/drawer.d.ts.map +1 -1
- package/dist/tags/drawer.js +32 -2
- package/dist/tags/drawer.js.map +1 -1
- package/dist/tags/file-ref.d.ts +21 -0
- package/dist/tags/file-ref.d.ts.map +1 -0
- package/dist/tags/file-ref.js +88 -0
- package/dist/tags/file-ref.js.map +1 -0
- package/dist/tags/snippet.d.ts.map +1 -1
- package/dist/tags/snippet.js +10 -0
- package/dist/tags/snippet.js.map +1 -1
- package/dist/tags/xref.d.ts.map +1 -1
- package/dist/tags/xref.js +9 -0
- package/dist/tags/xref.js.map +1 -1
- package/dist/xref-preview-resolve.d.ts +35 -0
- package/dist/xref-preview-resolve.d.ts.map +1 -0
- package/dist/xref-preview-resolve.js +188 -0
- package/dist/xref-preview-resolve.js.map +1 -0
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Drawer pipeline hooks (SPEC-060, WORK-257).
|
|
2
|
+
* Drawer pipeline hooks (SPEC-060, WORK-257; preview hoist SPEC-078, WORK-300).
|
|
3
3
|
*
|
|
4
4
|
* - **Register** walks each page's renderable for drawer tags
|
|
5
5
|
* (`data-rune="drawer"`), and adds each as a page-scoped entity
|
|
@@ -13,8 +13,23 @@
|
|
|
13
13
|
* tracks document outline depth (the most recent `<h{n}>` seen) and
|
|
14
14
|
* rewrites the marked tag to `h{n+1}` (clamped 1..6, default h2 when
|
|
15
15
|
* no preceding heading exists).
|
|
16
|
+
*
|
|
17
|
+
* - **postProcess (hoist)** turns inline `preview="drawer"` references
|
|
18
|
+
* into hoisted drawer sections at the page root. Reference runes
|
|
19
|
+
* (file-ref, xref) emit a `<meta data-field="hoist-drawer">` sentinel
|
|
20
|
+
* next to their inline `<a>` link; the hoist pass collects these,
|
|
21
|
+
* dedups by target id, detects collisions with author-declared
|
|
22
|
+
* drawers (author wins, hoist defers), and appends a `<section
|
|
23
|
+
* class="rf-drawer">` per unique reference to the end of the page
|
|
24
|
+
* renderable. The drawer's body and footer content is built by a
|
|
25
|
+
* source-specific builder that the consuming rune registers via
|
|
26
|
+
* `registerHoistBuilder` at module load time, so this file knows
|
|
27
|
+
* nothing about file paths, entity ids, or rune-specific rendering.
|
|
16
28
|
*/
|
|
29
|
+
import Markdoc from '@markdoc/markdoc';
|
|
17
30
|
import type { EntityRegistry, PipelineContext, TransformedPage } from '@refrakt-md/types';
|
|
31
|
+
declare const Tag: typeof Markdoc.Tag;
|
|
32
|
+
type TagNode = InstanceType<typeof Tag>;
|
|
18
33
|
/**
|
|
19
34
|
* Walk the renderable tree of every page and register each drawer rune
|
|
20
35
|
* as a page-scoped entity. Each drawer surfaces in the registry as
|
|
@@ -30,4 +45,60 @@ export declare function registerDrawers(pages: readonly TransformedPage[], regis
|
|
|
30
45
|
* rewriting, so downstream postProcess steps can skip a no-op pass.
|
|
31
46
|
*/
|
|
32
47
|
export declare function resolveAutoDrawerTitleLevels(renderable: unknown): unknown;
|
|
48
|
+
/** Sentinel `data-field` value emitted by reference runes on the meta tag
|
|
49
|
+
* that carries the drawer payload. The hoist pass collects these and
|
|
50
|
+
* removes them from the rendered tree. */
|
|
51
|
+
export declare const HOIST_DRAWER_SENTINEL = "hoist-drawer";
|
|
52
|
+
/** Per-page context handed to source-specific hoist builders so they can
|
|
53
|
+
* read the entity registry (for xref), resolve file paths against the
|
|
54
|
+
* project root (for file-ref), or emit pipeline messages. */
|
|
55
|
+
export interface HoistBuildContext {
|
|
56
|
+
pageUrl: string;
|
|
57
|
+
registry: Readonly<EntityRegistry> | undefined;
|
|
58
|
+
projectRoot: string | undefined;
|
|
59
|
+
ctx: PipelineContext;
|
|
60
|
+
}
|
|
61
|
+
/** Builder for a single hoist source (`file-ref`, `xref`, …). Reads
|
|
62
|
+
* the sentinel's `data-*` attributes (payload) and returns a complete
|
|
63
|
+
* hoisted drawer subtree — a `<section class="rf-drawer">` ready to be
|
|
64
|
+
* appended to the page root. Returning `null` skips the hoist (used
|
|
65
|
+
* when the source can't render anything meaningful, e.g. xref with an
|
|
66
|
+
* unresolvable entity id). */
|
|
67
|
+
export type HoistBuilder = (payload: Record<string, string>, context: HoistBuildContext) => TagNode | null;
|
|
68
|
+
/** Register a hoist builder for a given `source` value. Called by
|
|
69
|
+
* reference runes at module load (e.g. `file-ref.ts` calls
|
|
70
|
+
* `registerHoistBuilder('file-ref', …)`). Re-registration overwrites,
|
|
71
|
+
* which lets tests stub out a builder per case. */
|
|
72
|
+
export declare function registerHoistBuilder(source: string, builder: HoistBuilder): void;
|
|
73
|
+
/** Get the registered builder for a `source`, or undefined when none is
|
|
74
|
+
* registered. Exposed for diagnostics / tests. */
|
|
75
|
+
export declare function getHoistBuilder(source: string): HoistBuilder | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Walk a page's renderable, collect every `<meta data-field="hoist-drawer">`
|
|
78
|
+
* sentinel, dedup by `data-target-id`, build a hoisted `<section>` per
|
|
79
|
+
* unique target via the registered source builder, and return a new
|
|
80
|
+
* renderable with the sentinels stripped and the hoisted drawers
|
|
81
|
+
* appended at the page root.
|
|
82
|
+
*
|
|
83
|
+
* Rules:
|
|
84
|
+
* - **Dedup**: N mentions of the same target id collapse to one drawer.
|
|
85
|
+
* - **Collision with author-declared drawer**: if the page already
|
|
86
|
+
* declares `{% drawer id="X" %}` block-level and a hoist would emit
|
|
87
|
+
* the same id, the author drawer wins — the hoist defers, no new
|
|
88
|
+
* `<section>` is emitted, and an info-level pipeline message names
|
|
89
|
+
* both sources.
|
|
90
|
+
* - **Nested preview**: a hoist sentinel inside another drawer's body
|
|
91
|
+
* still hoists (we don't block it), but emits an info-level note so
|
|
92
|
+
* authors can spot it in CI output.
|
|
93
|
+
*/
|
|
94
|
+
export declare function hoistPreviewDrawers(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry> | undefined, projectRoot: string | undefined, ctx: PipelineContext): unknown;
|
|
95
|
+
/** Derive a drawer slug for a `file-ref` target. Encodes both path and
|
|
96
|
+
* lines so different ranges of the same path produce distinct ids.
|
|
97
|
+
*
|
|
98
|
+
* Examples:
|
|
99
|
+
* - `pathToSlug('packages/types/src/token-contract.ts')` → `'packages-types-src-token-contract-ts'`
|
|
100
|
+
* - `pathToSlug('packages/types/src/token-contract.ts', '42-58')` → `'packages-types-src-token-contract-ts-L42-L58'`
|
|
101
|
+
* - `pathToSlug('docs/My File.md', '12')` → `'docs-my-file-md-L12'` */
|
|
102
|
+
export declare function pathToSlug(path: string, lines?: string): string;
|
|
103
|
+
export {};
|
|
33
104
|
//# sourceMappingURL=drawer-pipeline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer-pipeline.d.ts","sourceRoot":"","sources":["../src/drawer-pipeline.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"drawer-pipeline.d.ts","sourceRoot":"","sources":["../src/drawer-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG1F,QAAA,MAAQ,GAAG,oBAAY,CAAC;AACxB,KAAK,OAAO,GAAG,YAAY,CAAC,OAAO,GAAG,CAAC,CAAC;AA2BxC;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,SAAS,eAAe,EAAE,EACjC,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,eAAe,GAClB,IAAI,CAqDN;AA+DD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAIzE;AAsDD;;2CAE2C;AAC3C,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AAEpD;;8DAE8D;AAC9D,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAC/C,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,GAAG,EAAE,eAAe,CAAC;CACrB;AAED;;;;;+BAK+B;AAC/B,MAAM,MAAM,YAAY,GAAG,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,EAAE,iBAAiB,KACtB,OAAO,GAAG,IAAI,CAAC;AAIpB;;;oDAGoD;AACpD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAEhF;AAED;mDACmD;AACnD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAExE;AAgBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,SAAS,EAC9C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,GAAG,EAAE,eAAe,GAClB,OAAO,CAuDT;AAkHD;;;;;;wEAMwE;AACxE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAe/D"}
|
package/dist/drawer-pipeline.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Drawer pipeline hooks (SPEC-060, WORK-257).
|
|
2
|
+
* Drawer pipeline hooks (SPEC-060, WORK-257; preview hoist SPEC-078, WORK-300).
|
|
3
3
|
*
|
|
4
4
|
* - **Register** walks each page's renderable for drawer tags
|
|
5
5
|
* (`data-rune="drawer"`), and adds each as a page-scoped entity
|
|
@@ -13,6 +13,18 @@
|
|
|
13
13
|
* tracks document outline depth (the most recent `<h{n}>` seen) and
|
|
14
14
|
* rewrites the marked tag to `h{n+1}` (clamped 1..6, default h2 when
|
|
15
15
|
* no preceding heading exists).
|
|
16
|
+
*
|
|
17
|
+
* - **postProcess (hoist)** turns inline `preview="drawer"` references
|
|
18
|
+
* into hoisted drawer sections at the page root. Reference runes
|
|
19
|
+
* (file-ref, xref) emit a `<meta data-field="hoist-drawer">` sentinel
|
|
20
|
+
* next to their inline `<a>` link; the hoist pass collects these,
|
|
21
|
+
* dedups by target id, detects collisions with author-declared
|
|
22
|
+
* drawers (author wins, hoist defers), and appends a `<section
|
|
23
|
+
* class="rf-drawer">` per unique reference to the end of the page
|
|
24
|
+
* renderable. The drawer's body and footer content is built by a
|
|
25
|
+
* source-specific builder that the consuming rune registers via
|
|
26
|
+
* `registerHoistBuilder` at module load time, so this file knows
|
|
27
|
+
* nothing about file paths, entity ids, or rune-specific rendering.
|
|
16
28
|
*/
|
|
17
29
|
import Markdoc from '@markdoc/markdoc';
|
|
18
30
|
import { DRAWER_TITLE_AUTO_MARKER } from './tags/drawer.js';
|
|
@@ -203,4 +215,233 @@ function walkAndRewriteTitles(node, state) {
|
|
|
203
215
|
return tag;
|
|
204
216
|
return new Tag(tag.name, tag.attributes, newChildren);
|
|
205
217
|
}
|
|
218
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
219
|
+
// Hoist preview drawers (SPEC-078, WORK-300)
|
|
220
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
221
|
+
/** Sentinel `data-field` value emitted by reference runes on the meta tag
|
|
222
|
+
* that carries the drawer payload. The hoist pass collects these and
|
|
223
|
+
* removes them from the rendered tree. */
|
|
224
|
+
export const HOIST_DRAWER_SENTINEL = 'hoist-drawer';
|
|
225
|
+
const hoistBuilders = new Map();
|
|
226
|
+
/** Register a hoist builder for a given `source` value. Called by
|
|
227
|
+
* reference runes at module load (e.g. `file-ref.ts` calls
|
|
228
|
+
* `registerHoistBuilder('file-ref', …)`). Re-registration overwrites,
|
|
229
|
+
* which lets tests stub out a builder per case. */
|
|
230
|
+
export function registerHoistBuilder(source, builder) {
|
|
231
|
+
hoistBuilders.set(source, builder);
|
|
232
|
+
}
|
|
233
|
+
/** Get the registered builder for a `source`, or undefined when none is
|
|
234
|
+
* registered. Exposed for diagnostics / tests. */
|
|
235
|
+
export function getHoistBuilder(source) {
|
|
236
|
+
return hoistBuilders.get(source);
|
|
237
|
+
}
|
|
238
|
+
/** Internal: read every `data-*` attribute off a sentinel meta tag into
|
|
239
|
+
* a plain string-string record. Non-string attribute values are
|
|
240
|
+
* ignored. */
|
|
241
|
+
function readPayload(meta) {
|
|
242
|
+
const out = {};
|
|
243
|
+
const attrs = meta.attributes;
|
|
244
|
+
if (!attrs)
|
|
245
|
+
return out;
|
|
246
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
247
|
+
if (!k.startsWith('data-'))
|
|
248
|
+
continue;
|
|
249
|
+
if (typeof v === 'string')
|
|
250
|
+
out[k.slice('data-'.length)] = v;
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Walk a page's renderable, collect every `<meta data-field="hoist-drawer">`
|
|
256
|
+
* sentinel, dedup by `data-target-id`, build a hoisted `<section>` per
|
|
257
|
+
* unique target via the registered source builder, and return a new
|
|
258
|
+
* renderable with the sentinels stripped and the hoisted drawers
|
|
259
|
+
* appended at the page root.
|
|
260
|
+
*
|
|
261
|
+
* Rules:
|
|
262
|
+
* - **Dedup**: N mentions of the same target id collapse to one drawer.
|
|
263
|
+
* - **Collision with author-declared drawer**: if the page already
|
|
264
|
+
* declares `{% drawer id="X" %}` block-level and a hoist would emit
|
|
265
|
+
* the same id, the author drawer wins — the hoist defers, no new
|
|
266
|
+
* `<section>` is emitted, and an info-level pipeline message names
|
|
267
|
+
* both sources.
|
|
268
|
+
* - **Nested preview**: a hoist sentinel inside another drawer's body
|
|
269
|
+
* still hoists (we don't block it), but emits an info-level note so
|
|
270
|
+
* authors can spot it in CI output.
|
|
271
|
+
*/
|
|
272
|
+
export function hoistPreviewDrawers(renderable, pageUrl, registry, projectRoot, ctx) {
|
|
273
|
+
// First pass: collect author-declared drawer ids so collisions can
|
|
274
|
+
// be detected before any hoist work runs.
|
|
275
|
+
const authorIds = collectAuthorDrawerIds(renderable);
|
|
276
|
+
// Second pass: walk the tree, strip hoist sentinels, collect their
|
|
277
|
+
// payloads (deduped, collision-checked, nesting-checked).
|
|
278
|
+
const payloads = new Map();
|
|
279
|
+
const seenIds = new Set();
|
|
280
|
+
const state = {
|
|
281
|
+
payloads,
|
|
282
|
+
seenIds,
|
|
283
|
+
authorIds,
|
|
284
|
+
drawerDepth: 0,
|
|
285
|
+
pageUrl,
|
|
286
|
+
ctx,
|
|
287
|
+
mutated: false,
|
|
288
|
+
};
|
|
289
|
+
const stripped = walkStripSentinels(renderable, state);
|
|
290
|
+
if (payloads.size === 0)
|
|
291
|
+
return state.mutated ? stripped : renderable;
|
|
292
|
+
// Third pass: build hoisted drawer sections via source-specific
|
|
293
|
+
// builders and append to the page renderable root.
|
|
294
|
+
const buildContext = { pageUrl, registry, projectRoot, ctx };
|
|
295
|
+
const drawers = [];
|
|
296
|
+
for (const payload of payloads.values()) {
|
|
297
|
+
const source = payload.source;
|
|
298
|
+
if (!source) {
|
|
299
|
+
ctx.warn(`hoist drawer payload is missing required \`source\` attribute (target-id=${payload['target-id'] ?? '?'})`, pageUrl);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const builder = hoistBuilders.get(source);
|
|
303
|
+
if (!builder) {
|
|
304
|
+
ctx.warn(`hoist drawer source "${source}" has no registered builder — skipping target-id=${payload['target-id'] ?? '?'}`, pageUrl);
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
const node = builder(payload, buildContext);
|
|
308
|
+
if (node)
|
|
309
|
+
drawers.push(node);
|
|
310
|
+
}
|
|
311
|
+
if (drawers.length === 0)
|
|
312
|
+
return stripped;
|
|
313
|
+
if (Array.isArray(stripped))
|
|
314
|
+
return [...stripped, ...drawers];
|
|
315
|
+
if (Tag.isTag(stripped)) {
|
|
316
|
+
const t = stripped;
|
|
317
|
+
return new Tag(t.name, t.attributes, [...(t.children ?? []), ...drawers]);
|
|
318
|
+
}
|
|
319
|
+
return [stripped, ...drawers];
|
|
320
|
+
}
|
|
321
|
+
function collectAuthorDrawerIds(renderable) {
|
|
322
|
+
const ids = new Set();
|
|
323
|
+
const walk = (node) => {
|
|
324
|
+
if (Array.isArray(node)) {
|
|
325
|
+
for (const c of node)
|
|
326
|
+
walk(c);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (!Tag.isTag(node))
|
|
330
|
+
return;
|
|
331
|
+
const tag = node;
|
|
332
|
+
if (tag.attributes?.['data-rune'] === 'drawer') {
|
|
333
|
+
const id = tag.attributes?.['data-drawer-id'];
|
|
334
|
+
if (typeof id === 'string')
|
|
335
|
+
ids.add(id);
|
|
336
|
+
return; // don't recurse into a drawer's body — drawer-in-drawer is its own concern
|
|
337
|
+
}
|
|
338
|
+
for (const c of tag.children ?? [])
|
|
339
|
+
walk(c);
|
|
340
|
+
};
|
|
341
|
+
walk(renderable);
|
|
342
|
+
return ids;
|
|
343
|
+
}
|
|
344
|
+
function walkStripSentinels(node, state) {
|
|
345
|
+
if (Array.isArray(node)) {
|
|
346
|
+
let mutated = false;
|
|
347
|
+
const out = [];
|
|
348
|
+
for (const c of node) {
|
|
349
|
+
const w = walkStripSentinels(c, state);
|
|
350
|
+
if (w !== c)
|
|
351
|
+
mutated = true;
|
|
352
|
+
if (w !== STRIP)
|
|
353
|
+
out.push(w);
|
|
354
|
+
}
|
|
355
|
+
if (!mutated)
|
|
356
|
+
return node;
|
|
357
|
+
state.mutated = true;
|
|
358
|
+
return out;
|
|
359
|
+
}
|
|
360
|
+
if (!Tag.isTag(node))
|
|
361
|
+
return node;
|
|
362
|
+
const tag = node;
|
|
363
|
+
// Strip the sentinel meta itself.
|
|
364
|
+
if (tag.name === 'meta'
|
|
365
|
+
&& tag.attributes?.['data-field'] === HOIST_DRAWER_SENTINEL) {
|
|
366
|
+
const payload = readPayload(tag);
|
|
367
|
+
const targetId = payload['target-id'];
|
|
368
|
+
if (!targetId) {
|
|
369
|
+
state.ctx.warn(`hoist drawer sentinel is missing required \`data-target-id\` attribute`, state.pageUrl);
|
|
370
|
+
return STRIP;
|
|
371
|
+
}
|
|
372
|
+
// Collision with author-declared drawer? Author wins; hoist defers.
|
|
373
|
+
if (state.authorIds.has(targetId)) {
|
|
374
|
+
state.ctx.info(`Hoist preview "${targetId}" (source=${payload.source ?? '?'}) collides with an author-declared {% drawer id="${targetId}" %} on this page — author drawer wins, hoist defers.`, state.pageUrl);
|
|
375
|
+
return STRIP;
|
|
376
|
+
}
|
|
377
|
+
// Nested preview inside another drawer's body? Still hoist, but
|
|
378
|
+
// flag it — dialog stacking handles it but the shape is awkward.
|
|
379
|
+
if (state.drawerDepth > 0) {
|
|
380
|
+
state.ctx.info(`Hoist preview "${targetId}" (source=${payload.source ?? '?'}) appears inside another drawer's body — nested previews stack on modern browsers, consider not nesting.`, state.pageUrl);
|
|
381
|
+
}
|
|
382
|
+
// Dedup: keep the first occurrence's payload.
|
|
383
|
+
if (!state.seenIds.has(targetId)) {
|
|
384
|
+
state.payloads.set(targetId, payload);
|
|
385
|
+
state.seenIds.add(targetId);
|
|
386
|
+
}
|
|
387
|
+
return STRIP;
|
|
388
|
+
}
|
|
389
|
+
const isDrawer = tag.attributes?.['data-rune'] === 'drawer';
|
|
390
|
+
if (isDrawer)
|
|
391
|
+
state.drawerDepth++;
|
|
392
|
+
if (!tag.children || tag.children.length === 0) {
|
|
393
|
+
if (isDrawer)
|
|
394
|
+
state.drawerDepth--;
|
|
395
|
+
return tag;
|
|
396
|
+
}
|
|
397
|
+
let mutated = false;
|
|
398
|
+
const newChildren = [];
|
|
399
|
+
for (const c of tag.children) {
|
|
400
|
+
const w = walkStripSentinels(c, state);
|
|
401
|
+
if (w !== c)
|
|
402
|
+
mutated = true;
|
|
403
|
+
if (w !== STRIP)
|
|
404
|
+
newChildren.push(w);
|
|
405
|
+
}
|
|
406
|
+
if (isDrawer)
|
|
407
|
+
state.drawerDepth--;
|
|
408
|
+
if (!mutated)
|
|
409
|
+
return tag;
|
|
410
|
+
state.mutated = true;
|
|
411
|
+
return new Tag(tag.name, tag.attributes, newChildren);
|
|
412
|
+
}
|
|
413
|
+
/** Sentinel value returned by `walkStripSentinels` for elements that
|
|
414
|
+
* should be removed from their position in the tree. Using a symbol
|
|
415
|
+
* lets the array-walk path tell "removed" apart from "replaced with
|
|
416
|
+
* another node". */
|
|
417
|
+
const STRIP = Symbol('hoist-strip');
|
|
418
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
419
|
+
// Slug derivation helpers — used by reference runes when emitting
|
|
420
|
+
// sentinels and re-derived here so tests can lock the shape.
|
|
421
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
422
|
+
/** Derive a drawer slug for a `file-ref` target. Encodes both path and
|
|
423
|
+
* lines so different ranges of the same path produce distinct ids.
|
|
424
|
+
*
|
|
425
|
+
* Examples:
|
|
426
|
+
* - `pathToSlug('packages/types/src/token-contract.ts')` → `'packages-types-src-token-contract-ts'`
|
|
427
|
+
* - `pathToSlug('packages/types/src/token-contract.ts', '42-58')` → `'packages-types-src-token-contract-ts-L42-L58'`
|
|
428
|
+
* - `pathToSlug('docs/My File.md', '12')` → `'docs-my-file-md-L12'` */
|
|
429
|
+
export function pathToSlug(path, lines) {
|
|
430
|
+
const base = path
|
|
431
|
+
.toLowerCase()
|
|
432
|
+
// keep [a-z0-9._-]; turn everything else (including `/`, ` `, parens) into `-`.
|
|
433
|
+
.replace(/[^a-z0-9.]+/g, '-')
|
|
434
|
+
// collapse repeated dashes and trim ends.
|
|
435
|
+
.replace(/-+/g, '-')
|
|
436
|
+
.replace(/^-|-$/g, '');
|
|
437
|
+
if (!lines)
|
|
438
|
+
return base;
|
|
439
|
+
const trimmed = lines.trim();
|
|
440
|
+
const dash = trimmed.indexOf('-');
|
|
441
|
+
if (dash < 0)
|
|
442
|
+
return `${base}-L${trimmed}`;
|
|
443
|
+
const start = trimmed.slice(0, dash).trim();
|
|
444
|
+
const end = trimmed.slice(dash + 1).trim();
|
|
445
|
+
return end ? `${base}-L${start}-L${end}` : `${base}-L${start}`;
|
|
446
|
+
}
|
|
206
447
|
//# sourceMappingURL=drawer-pipeline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer-pipeline.js","sourceRoot":"","sources":["../src/drawer-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AAExB,MAAM,cAAc,GAAG,YAAY,CAAC;AAEpC,6EAA6E;AAC7E,SAAS,YAAY,CAAC,GAA6B,EAAE,GAAW;IAC/D,MAAM,CAAC,GAAI,GAAG,CAAC,UAAkD,EAAE,CAAC,GAAG,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED;;;;kEAIkE;AAClE,SAAS,gBAAgB,CAAC,SAAmC,EAAE,KAAa;IAC3E,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC9C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAc,CAAC;YAAE,SAAS;QACzC,MAAM,CAAC,GAAG,KAAiC,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAChC,IAAK,CAAC,CAAC,UAAkD,EAAE,CAAC,YAAY,CAAC,KAAK,KAAK;YAAE,SAAS;QAC9F,MAAM,OAAO,GAAI,CAAC,CAAC,UAAkD,EAAE,CAAC,SAAS,CAAC,CAAC;QACnF,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC9B,KAAiC,EACjC,QAAwB,EACxB,GAAoB;IAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,aAAa,GAMd,EAAE,CAAC;QAER,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAElC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE;YACvC,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;YAC/C,IAAI,CAAC,EAAE,EAAE,CAAC;gBACT,GAAG,CAAC,KAAK,CACR,gDAAgD,EAChD,IAAI,CAAC,GAAG,CACR,CAAC;gBACF,OAAO;YACR,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACrB,GAAG,CAAC,IAAI,CACP,cAAc,EAAE,mEAAmE,EACnF,IAAI,CAAC,GAAG,CACR,CAAC;YACH,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAEhB,aAAa,CAAC,IAAI,CAAC;gBAClB,EAAE;gBACF,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC;gBAC5B,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO;gBAC9C,IAAI,EAAE,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI;gBAC3C,QAAQ,EAAE,gBAAgB,CAAC,GAAG,EAAE,UAAU,CAAC;aAC3C,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;YAC/B,QAAQ,CAAC,QAAQ,CAAC;gBACjB,IAAI,EAAE,QAAQ;gBACd,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,KAAK,EAAE,MAAM;gBACb,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,EAAE;gBACvC,IAAI,EAAE;oBACL,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;iBACpB;aACD,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;AACF,CAAC;AAED;;wBAEwB;AACxB,SAAS,cAAc,CACtB,IAAa,EACb,KAAoD;IAEpD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO;IACR,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAa,CAAC;QAAE,OAAO;IACtC,MAAM,GAAG,GAAG,IAAgC,CAAC;IAC7C,IAAK,GAAG,CAAC,UAAkD,EAAE,CAAC,WAAW,CAAC,KAAK,QAAQ,EAAE,CAAC;QACzF,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,oEAAoE;QACpE,qEAAqE;QACrE,oBAAoB;QACpB,OAAO;IACR,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO;IAC1B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ;QAAE,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACxD,CAAC;AAED;;;+BAG+B;AAC/B,SAAS,gBAAgB,CAAC,SAAmC;IAC5D,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CACtB,IAA8B,EAC9B,IAAY;IAEZ,IAAK,IAAI,CAAC,UAAkD,EAAE,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;QACtF,OAAO,IAAI,CAAC;IACb,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACrC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,cAAc,CAAC,CAA6B,EAAE,IAAI,CAAC,CAAC;YAChE,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACrB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IACjC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/D,IAAI,GAAG,CAAC,KAAK,CAAC,IAAa,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAgC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAmB;IAC/D,MAAM,KAAK,GAAG,EAAE,gBAAgB,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,oBAAoB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACrD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;AAC1C,CAAC;AAED,SAAS,oBAAoB,CAC5B,IAAa,EACb,KAAqD;IAErD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtF,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3B,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,GAAG,IAAI,CAAC;YAC5B,OAAO,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAgC,CAAC;IAE7C,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnD,oEAAoE;IACpE,oEAAoE;IACpE,kEAAkE;IAClE,2CAA2C;IAC3C,MAAM,WAAW,GAAI,GAAG,CAAC,UAAkD,EAAE,CAAC,wBAAwB,CAAC,KAAK,MAAM,CAAC;IACnH,IAAI,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,KAAK,CAAC,gBAAgB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;QACvE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACvD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,MAAM,QAAQ,GAA4B,EAAE,GAAI,GAAG,CAAC,UAAsC,EAAE,CAAC;QAC7F,OAAO,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QAC1C,OAAO,IAAI,GAAG,CAAC,IAAI,WAAW,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QAClB,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAE3D,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1C,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,GAAG,IAAI,CAAC;QAC5B,OAAO,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC;IACzB,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,WAAsB,CAAC,CAAC;AAClE,CAAC"}
|
|
1
|
+
{"version":3,"file":"drawer-pipeline.js","sourceRoot":"","sources":["../src/drawer-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* file-ref postProcess resolver (SPEC-078, WORK-301).
|
|
3
|
+
*
|
|
4
|
+
* Walks the rendered page, finds `file-ref` sentinels, binds each inline
|
|
5
|
+
* `<a>` to the canonical GitHub URL built from the site's `repoUrl` /
|
|
6
|
+
* `repoBranch`, and (when `preview="drawer"` is set) emits a
|
|
7
|
+
* `hoist-drawer` sentinel that the drawer pipeline picks up to render a
|
|
8
|
+
* preview drawer containing the file's snippet + a "View source on
|
|
9
|
+
* GitHub →" footer link.
|
|
10
|
+
*/
|
|
11
|
+
import type { PipelineContext } from '@refrakt-md/types';
|
|
12
|
+
/**
|
|
13
|
+
* Resolve every `file-ref` sentinel on the page: bind the inline `<a>` to
|
|
14
|
+
* the GitHub URL (or in-page anchor when `preview="drawer"`), emit a
|
|
15
|
+
* sibling hoist sentinel for the drawer pipeline when previewing, and
|
|
16
|
+
* strip the file-ref metas from the rendered tree.
|
|
17
|
+
*
|
|
18
|
+
* Re-entrant per page — the "missing repoUrl" build warning fires at most
|
|
19
|
+
* once per page even when many file-refs share the gap.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveFileRefs(renderable: unknown, pageUrl: string, repoUrl: string | undefined, repoBranch: string | undefined, ctx: PipelineContext): unknown;
|
|
22
|
+
//# sourceMappingURL=file-ref-resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-ref-resolve.d.ts","sourceRoot":"","sources":["../src/file-ref-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAyDzD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC9B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,GAAG,EAAE,eAAe,GAClB,OAAO,CA6BT"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* file-ref postProcess resolver (SPEC-078, WORK-301).
|
|
3
|
+
*
|
|
4
|
+
* Walks the rendered page, finds `file-ref` sentinels, binds each inline
|
|
5
|
+
* `<a>` to the canonical GitHub URL built from the site's `repoUrl` /
|
|
6
|
+
* `repoBranch`, and (when `preview="drawer"` is set) emits a
|
|
7
|
+
* `hoist-drawer` sentinel that the drawer pipeline picks up to render a
|
|
8
|
+
* preview drawer containing the file's snippet + a "View source on
|
|
9
|
+
* GitHub →" footer link.
|
|
10
|
+
*/
|
|
11
|
+
import Markdoc from '@markdoc/markdoc';
|
|
12
|
+
import { buildGithubBlobUrl } from '@refrakt-md/transform';
|
|
13
|
+
import { HOIST_DRAWER_SENTINEL, pathToSlug, registerHoistBuilder, } from './drawer-pipeline.js';
|
|
14
|
+
import { FILE_REF_SENTINEL } from './tags/file-ref.js';
|
|
15
|
+
import { readSnippetFile, SnippetSandboxError } from './lib/read-file.js';
|
|
16
|
+
import { inferLanguage } from './lang-map.js';
|
|
17
|
+
const { Tag } = Markdoc;
|
|
18
|
+
function isTag(node) {
|
|
19
|
+
return Tag.isTag(node);
|
|
20
|
+
}
|
|
21
|
+
function metaContent(tag, field) {
|
|
22
|
+
for (const child of tag.children ?? []) {
|
|
23
|
+
if (isTag(child) && child.name === 'meta' && child.attributes['data-field'] === field) {
|
|
24
|
+
return String(child.attributes.content ?? '');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
function hasSentinel(tag) {
|
|
30
|
+
return (tag.children ?? []).some(c => isTag(c) && c.name === 'meta' && c.attributes['data-field'] === FILE_REF_SENTINEL);
|
|
31
|
+
}
|
|
32
|
+
function readQuery(tag) {
|
|
33
|
+
return {
|
|
34
|
+
path: metaContent(tag, 'file-ref-path'),
|
|
35
|
+
lines: metaContent(tag, 'file-ref-lines'),
|
|
36
|
+
label: metaContent(tag, 'file-ref-label'),
|
|
37
|
+
preview: metaContent(tag, 'file-ref-preview'),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function defaultLabel(path) {
|
|
41
|
+
if (!path)
|
|
42
|
+
return '';
|
|
43
|
+
const trimmed = path.endsWith('/') ? path.slice(0, -1) : path;
|
|
44
|
+
const slash = trimmed.lastIndexOf('/');
|
|
45
|
+
return slash >= 0 ? trimmed.slice(slash + 1) : trimmed;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve every `file-ref` sentinel on the page: bind the inline `<a>` to
|
|
49
|
+
* the GitHub URL (or in-page anchor when `preview="drawer"`), emit a
|
|
50
|
+
* sibling hoist sentinel for the drawer pipeline when previewing, and
|
|
51
|
+
* strip the file-ref metas from the rendered tree.
|
|
52
|
+
*
|
|
53
|
+
* Re-entrant per page — the "missing repoUrl" build warning fires at most
|
|
54
|
+
* once per page even when many file-refs share the gap.
|
|
55
|
+
*/
|
|
56
|
+
export function resolveFileRefs(renderable, pageUrl, repoUrl, repoBranch, ctx) {
|
|
57
|
+
// Reset the per-page "missing repoUrl" warning gate.
|
|
58
|
+
const localWarned = { value: false };
|
|
59
|
+
const walk = (node) => {
|
|
60
|
+
if (Array.isArray(node)) {
|
|
61
|
+
let mutated = false;
|
|
62
|
+
const out = node.map(c => {
|
|
63
|
+
const w = walk(c);
|
|
64
|
+
if (w !== c)
|
|
65
|
+
mutated = true;
|
|
66
|
+
return w;
|
|
67
|
+
});
|
|
68
|
+
return mutated ? out : node;
|
|
69
|
+
}
|
|
70
|
+
if (!isTag(node))
|
|
71
|
+
return node;
|
|
72
|
+
const tag = node;
|
|
73
|
+
if (tag.attributes?.['data-rune'] === 'file-ref' && hasSentinel(tag)) {
|
|
74
|
+
return resolveOne(tag, pageUrl, repoUrl, repoBranch, ctx, localWarned);
|
|
75
|
+
}
|
|
76
|
+
if (!tag.children || tag.children.length === 0)
|
|
77
|
+
return tag;
|
|
78
|
+
let mutated = false;
|
|
79
|
+
const next = tag.children.map(c => {
|
|
80
|
+
const w = walk(c);
|
|
81
|
+
if (w !== c)
|
|
82
|
+
mutated = true;
|
|
83
|
+
return w;
|
|
84
|
+
});
|
|
85
|
+
if (!mutated)
|
|
86
|
+
return tag;
|
|
87
|
+
return new Tag(tag.name, tag.attributes, next);
|
|
88
|
+
};
|
|
89
|
+
return walk(renderable);
|
|
90
|
+
}
|
|
91
|
+
function resolveOne(tag, pageUrl, repoUrl, repoBranch, ctx, localWarned) {
|
|
92
|
+
const q = readQuery(tag);
|
|
93
|
+
const label = q.label || defaultLabel(q.path) || q.path;
|
|
94
|
+
const slug = pathToSlug(q.path, q.lines);
|
|
95
|
+
const previewDrawer = q.preview === 'drawer';
|
|
96
|
+
const githubUrl = buildGithubBlobUrl(repoUrl, repoBranch, q.path, q.lines);
|
|
97
|
+
if (!githubUrl && !localWarned.value) {
|
|
98
|
+
ctx.warn(`file-ref on this page has no GitHub URL — site config is missing \`repoUrl\` (path="${q.path}"). Configure \`SiteConfig.repoUrl\` to render canonical "View source" links.`, pageUrl);
|
|
99
|
+
localWarned.value = true;
|
|
100
|
+
}
|
|
101
|
+
// Build the inline anchor. With preview, it points at the hoist anchor;
|
|
102
|
+
// without preview, it points at the GitHub URL (or has no href when
|
|
103
|
+
// repoUrl is absent).
|
|
104
|
+
const anchorAttrs = {};
|
|
105
|
+
if (previewDrawer) {
|
|
106
|
+
anchorAttrs.href = `#drawer-${slug}`;
|
|
107
|
+
anchorAttrs['aria-controls'] = `drawer-${slug}`;
|
|
108
|
+
anchorAttrs['aria-expanded'] = 'false';
|
|
109
|
+
anchorAttrs['data-target-type'] = 'drawer';
|
|
110
|
+
}
|
|
111
|
+
else if (githubUrl) {
|
|
112
|
+
anchorAttrs.href = githubUrl;
|
|
113
|
+
}
|
|
114
|
+
const anchor = new Tag('a', anchorAttrs, [label]);
|
|
115
|
+
const children = [anchor];
|
|
116
|
+
if (previewDrawer) {
|
|
117
|
+
// Emit the hoist sentinel as a sibling of the inline link. The
|
|
118
|
+
// drawer pipeline (WORK-300) picks this up, builds the drawer via
|
|
119
|
+
// the registered builder, and strips this meta from the tree.
|
|
120
|
+
const sentinel = new Tag('meta', {
|
|
121
|
+
'data-field': HOIST_DRAWER_SENTINEL,
|
|
122
|
+
'data-source': 'file-ref',
|
|
123
|
+
'data-target-id': slug,
|
|
124
|
+
'data-title': label,
|
|
125
|
+
'data-path': q.path,
|
|
126
|
+
'data-lines': q.lines,
|
|
127
|
+
'data-github-url': githubUrl ?? '',
|
|
128
|
+
});
|
|
129
|
+
children.push(sentinel);
|
|
130
|
+
}
|
|
131
|
+
// Preserve the outer span (carrying `data-rune="file-ref"`) so the
|
|
132
|
+
// engine's BEM class on it survives; replace the children with the
|
|
133
|
+
// resolved anchor + (when previewing) hoist sentinel.
|
|
134
|
+
return new Tag(tag.name, tag.attributes, children);
|
|
135
|
+
}
|
|
136
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
137
|
+
// Hoist builder — registered with the drawer pipeline so it can build
|
|
138
|
+
// preview drawers for `file-ref preview="drawer"` references.
|
|
139
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
140
|
+
function buildFileRefHoist(payload, context) {
|
|
141
|
+
const filePath = payload.path;
|
|
142
|
+
const lines = payload.lines;
|
|
143
|
+
const title = payload.title || defaultLabel(filePath);
|
|
144
|
+
const targetId = payload['target-id'];
|
|
145
|
+
const githubUrl = payload['github-url'];
|
|
146
|
+
if (!filePath || !targetId) {
|
|
147
|
+
context.ctx.warn(`file-ref hoist payload missing required path or target-id`, context.pageUrl);
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if (!context.projectRoot) {
|
|
151
|
+
context.ctx.error(`file-ref hoist for "${filePath}" requires a project root in the pipeline; none was threaded through. Drawer body will be empty.`, context.pageUrl);
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
// Read the file (same sandbox as snippet). Errors surface as build
|
|
155
|
+
// errors naming the resolved path and the referencing page.
|
|
156
|
+
let fileContent = '';
|
|
157
|
+
let lang = 'text';
|
|
158
|
+
try {
|
|
159
|
+
const result = readSnippetFile({
|
|
160
|
+
pathAttr: filePath,
|
|
161
|
+
projectRoot: context.projectRoot,
|
|
162
|
+
lines: lines || undefined,
|
|
163
|
+
referencingPage: context.pageUrl,
|
|
164
|
+
});
|
|
165
|
+
fileContent = result.content;
|
|
166
|
+
lang = inferLanguage(result.relativePath);
|
|
167
|
+
for (const w of result.warnings)
|
|
168
|
+
context.ctx.warn(`file-ref ${filePath}: ${w}`, context.pageUrl);
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
const msg = err instanceof SnippetSandboxError
|
|
172
|
+
? err.message
|
|
173
|
+
: `file-ref ${filePath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
174
|
+
context.ctx.error(msg, context.pageUrl);
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
// Drawer body — a figure.rf-snippet wrapping a `<pre data-language>`
|
|
178
|
+
// so the existing snippet CSS + highlight transform pick it up.
|
|
179
|
+
// `data-language` lives on BOTH the <pre> (for snippet CSS hooks +
|
|
180
|
+
// the highlight transform's color-scheme stamping pass) AND on the
|
|
181
|
+
// <code> with text children — the highlight walker only highlights
|
|
182
|
+
// nodes whose children are text, so the <code> is the actual hit.
|
|
183
|
+
const codeBlock = new Tag('pre', {
|
|
184
|
+
'data-language': lang,
|
|
185
|
+
'data-codeblock': 'true',
|
|
186
|
+
}, [new Tag('code', { 'data-language': lang, 'data-codeblock': 'true' }, [fileContent])]);
|
|
187
|
+
const snippetFigure = new Tag('figure', {
|
|
188
|
+
class: 'rf-snippet',
|
|
189
|
+
'data-rune': 'snippet',
|
|
190
|
+
'data-source-path': filePath,
|
|
191
|
+
...(lines ? { 'data-lines': lines } : {}),
|
|
192
|
+
}, [codeBlock]);
|
|
193
|
+
const body = new Tag('div', { 'data-name': 'body', class: 'rf-drawer__body' }, [snippetFigure]);
|
|
194
|
+
// Header — title + close button (close hidden until the behavior
|
|
195
|
+
// layer reveals it, same as authored drawers).
|
|
196
|
+
const titleHeading = new Tag('h3', { 'data-name': 'title', class: 'rf-drawer__title' }, [title]);
|
|
197
|
+
const closeButton = new Tag('button', {
|
|
198
|
+
type: 'button',
|
|
199
|
+
'aria-label': 'Close',
|
|
200
|
+
hidden: true,
|
|
201
|
+
'data-name': 'close',
|
|
202
|
+
class: 'rf-drawer__close',
|
|
203
|
+
}, ['×']);
|
|
204
|
+
const header = new Tag('header', {
|
|
205
|
+
'data-name': 'header',
|
|
206
|
+
class: 'rf-drawer__header',
|
|
207
|
+
}, [titleHeading, closeButton]);
|
|
208
|
+
// Footer — "View source on GitHub →" link. Hides when no
|
|
209
|
+
// repoUrl is configured (githubUrl will be empty in the payload).
|
|
210
|
+
const footerChildren = [];
|
|
211
|
+
if (githubUrl) {
|
|
212
|
+
const arrow = ' →';
|
|
213
|
+
footerChildren.push(new Tag('a', { href: githubUrl, rel: 'external noopener', target: '_blank' }, [`View source on GitHub${arrow}`]));
|
|
214
|
+
}
|
|
215
|
+
const footer = footerChildren.length > 0
|
|
216
|
+
? new Tag('footer', { 'data-name': 'footer', class: 'rf-drawer__footer' }, footerChildren)
|
|
217
|
+
: null;
|
|
218
|
+
const drawerChildren = [header, body];
|
|
219
|
+
if (footer)
|
|
220
|
+
drawerChildren.push(footer);
|
|
221
|
+
const section = new Tag('section', {
|
|
222
|
+
id: `drawer-${targetId}`,
|
|
223
|
+
class: 'rf-drawer',
|
|
224
|
+
'data-rune': 'drawer',
|
|
225
|
+
'data-drawer-id': targetId,
|
|
226
|
+
'data-side': 'right',
|
|
227
|
+
'data-size': 'md',
|
|
228
|
+
}, drawerChildren);
|
|
229
|
+
return section;
|
|
230
|
+
}
|
|
231
|
+
// Register the builder when this module is imported.
|
|
232
|
+
registerHoistBuilder('file-ref', buildFileRefHoist);
|
|
233
|
+
//# sourceMappingURL=file-ref-resolve.js.map
|