@refrakt-md/runes 0.14.4 → 0.16.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/aggregate-resolve.d.ts +4 -0
- package/dist/aggregate-resolve.d.ts.map +1 -0
- package/dist/aggregate-resolve.js +209 -0
- package/dist/aggregate-resolve.js.map +1 -0
- package/dist/collection-helpers.d.ts +101 -0
- package/dist/collection-helpers.d.ts.map +1 -0
- package/dist/collection-helpers.js +206 -0
- package/dist/collection-helpers.js.map +1 -0
- package/dist/collection-resolve.d.ts +5 -0
- package/dist/collection-resolve.d.ts.map +1 -0
- package/dist/collection-resolve.js +209 -0
- package/dist/collection-resolve.js.map +1 -0
- package/dist/config.d.ts +46 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +208 -88
- package/dist/config.js.map +1 -1
- package/dist/deferred-body.d.ts +19 -0
- package/dist/deferred-body.d.ts.map +1 -0
- package/dist/deferred-body.js +70 -0
- package/dist/deferred-body.js.map +1 -0
- 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 +314 -0
- package/dist/expand-pipeline.js.map +1 -0
- package/dist/field-match.d.ts +43 -0
- package/dist/field-match.d.ts.map +1 -0
- package/dist/field-match.js +121 -0
- package/dist/field-match.js.map +1 -0
- package/dist/functions.d.ts +36 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +74 -0
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +34 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -4
- 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/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -1
- 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 +18 -2
- package/dist/nodes.js.map +1 -1
- package/dist/outline-scope.d.ts +46 -0
- package/dist/outline-scope.d.ts.map +1 -0
- package/dist/outline-scope.js +208 -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/relationships-resolve.d.ts +4 -0
- package/dist/relationships-resolve.d.ts.map +1 -0
- package/dist/relationships-resolve.js +180 -0
- package/dist/relationships-resolve.js.map +1 -0
- 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/aggregate.d.ts +19 -0
- package/dist/tags/aggregate.d.ts.map +1 -0
- package/dist/tags/aggregate.js +59 -0
- package/dist/tags/aggregate.js.map +1 -0
- package/dist/tags/card.d.ts +25 -0
- package/dist/tags/card.d.ts.map +1 -0
- package/dist/tags/card.js +138 -0
- package/dist/tags/card.js.map +1 -0
- package/dist/tags/collection.d.ts +10 -0
- package/dist/tags/collection.d.ts.map +1 -0
- package/dist/tags/collection.js +54 -0
- package/dist/tags/collection.js.map +1 -0
- package/dist/tags/conversation.d.ts.map +1 -1
- package/dist/tags/conversation.js +26 -6
- package/dist/tags/conversation.js.map +1 -1
- 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/progress.d.ts +9 -0
- package/dist/tags/progress.d.ts.map +1 -0
- package/dist/tags/progress.js +96 -0
- package/dist/tags/progress.js.map +1 -0
- package/dist/tags/relationships.d.ts +12 -0
- package/dist/tags/relationships.d.ts.map +1 -0
- package/dist/tags/relationships.js +62 -0
- package/dist/tags/relationships.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,49 @@
|
|
|
1
|
+
import { createContentModelSchema } from '../lib/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The `snippet` rune — embed a file's contents as a syntax-highlighted code
|
|
4
|
+
* block (SPEC-062).
|
|
5
|
+
*
|
|
6
|
+
* Implementation note: snippet is implemented as an **AST preprocessor**
|
|
7
|
+
* rather than a transform-time rune. Every `{% snippet %}` tag is replaced
|
|
8
|
+
* by a Markdoc `fence` node before the schema-driven transform runs (see
|
|
9
|
+
* `corePipelineHooks.preprocess` in `../config.ts`). By the time the transform
|
|
10
|
+
* reaches the AST, no snippet tags exist — only fences. So this schema's
|
|
11
|
+
* `transform` function is **unreachable in normal operation**.
|
|
12
|
+
*
|
|
13
|
+
* The schema still exists for tooling: `refrakt inspect snippet`, the
|
|
14
|
+
* contracts generator, attribute validation, and the rune-catalog docs all
|
|
15
|
+
* read from it. If the transform ever does execute (e.g., the core preprocess
|
|
16
|
+
* hook isn't registered for some reason), it throws a clear error pointing
|
|
17
|
+
* the user at the registration site.
|
|
18
|
+
*/
|
|
19
|
+
export const snippet = createContentModelSchema({
|
|
20
|
+
attributes: {
|
|
21
|
+
path: {
|
|
22
|
+
type: String,
|
|
23
|
+
required: true,
|
|
24
|
+
description: 'Path to the source file, relative to the project root. Rejected if it escapes the root.',
|
|
25
|
+
},
|
|
26
|
+
lines: {
|
|
27
|
+
type: String,
|
|
28
|
+
required: false,
|
|
29
|
+
description: 'Line range. Formats: "10-25", "10-" (to EOF), "-20" (from start), "10" (single line). 1-indexed, inclusive.',
|
|
30
|
+
},
|
|
31
|
+
lang: {
|
|
32
|
+
type: String,
|
|
33
|
+
required: false,
|
|
34
|
+
description: 'Syntax-highlighting language hint. Overrides the extension-based inference.',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
contentModel: { type: 'sequence', fields: [] },
|
|
38
|
+
transform(_resolved, _attrs) {
|
|
39
|
+
// Unreachable in normal operation — corePipelineHooks.preprocess
|
|
40
|
+
// replaces snippet tags with fence nodes before the transform runs.
|
|
41
|
+
// If you see this error, ensure your content pipeline runs the
|
|
42
|
+
// preprocess phase (call sites: packages/content/src/site.ts and the
|
|
43
|
+
// hook set assembled via createCorePipelineHooks).
|
|
44
|
+
throw new Error('snippet rune reached the transform phase — its preprocess hook was not wired through. ' +
|
|
45
|
+
'Ensure the content pipeline runs registered `preprocess` hooks before `Markdoc.transform` ' +
|
|
46
|
+
'(snippet pre-resolves to a Markdoc `fence` node; see SPEC-062 § Composition).');
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=snippet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet.js","sourceRoot":"","sources":["../../src/tags/snippet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,wBAAwB,CAAC;IAC/C,UAAU,EAAE;QACX,IAAI,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,yFAAyF;SACtG;QACD,KAAK,EAAE;YACN,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,6GAA6G;SAC1H;QACD,IAAI,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,6EAA6E;SAC1F;KACD;IACD,YAAY,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE;IAC9C,SAAS,CAAC,SAAS,EAAE,MAAM;QAC1B,iEAAiE;QACjE,oEAAoE;QACpE,+DAA+D;QAC/D,qEAAqE;QACrE,mDAAmD;QACnD,MAAM,IAAI,KAAK,CACd,wFAAwF;YACxF,4FAA4F;YAC5F,+EAA+E,CAC/E,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
|
package/dist/util.d.ts
CHANGED
|
@@ -19,5 +19,16 @@ export interface HeadingInfo {
|
|
|
19
19
|
* IDs using the same algorithm as nodes.ts heading transform.
|
|
20
20
|
*/
|
|
21
21
|
export declare function extractHeadings(node: Node): HeadingInfo[];
|
|
22
|
+
/**
|
|
23
|
+
* Find the text content of the first H1 heading in an AST.
|
|
24
|
+
*
|
|
25
|
+
* Walks depth-first, descending into both regular nodes and tag (rune)
|
|
26
|
+
* children. The first `heading` node with `level: 1` wins. Used by the
|
|
27
|
+
* content pipeline to derive `$page.title` when frontmatter doesn't set
|
|
28
|
+
* one — matches the author mental model of "the page's title is the H1
|
|
29
|
+
* the reader sees," including the common case where an H1 is wrapped in
|
|
30
|
+
* a layout rune (hero etc.).
|
|
31
|
+
*/
|
|
32
|
+
export declare function firstH1(node: Node): string | undefined;
|
|
22
33
|
export declare function headingsToList(options?: HeadingsToListOptions): (nodes: Node[]) => Markdoc.Node[];
|
|
23
34
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAoB7D;AAED,wBAAiB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAShE;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,EAAE,CA+BzD;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,IAIpD,OAAO,IAAI,EAAE,oBAkCtB"}
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAoB7D;AAED,wBAAiB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAShE;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,EAAE,CA+BzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAyBtD;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,IAIpD,OAAO,IAAI,EAAE,oBAkCtB"}
|
package/dist/util.js
CHANGED
|
@@ -62,6 +62,41 @@ export function extractHeadings(node) {
|
|
|
62
62
|
walk(node);
|
|
63
63
|
return headings;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Find the text content of the first H1 heading in an AST.
|
|
67
|
+
*
|
|
68
|
+
* Walks depth-first, descending into both regular nodes and tag (rune)
|
|
69
|
+
* children. The first `heading` node with `level: 1` wins. Used by the
|
|
70
|
+
* content pipeline to derive `$page.title` when frontmatter doesn't set
|
|
71
|
+
* one — matches the author mental model of "the page's title is the H1
|
|
72
|
+
* the reader sees," including the common case where an H1 is wrapped in
|
|
73
|
+
* a layout rune (hero etc.).
|
|
74
|
+
*/
|
|
75
|
+
export function firstH1(node) {
|
|
76
|
+
let found;
|
|
77
|
+
function walk(n) {
|
|
78
|
+
if (n.type === 'heading' && n.attributes.level === 1) {
|
|
79
|
+
const textParts = [];
|
|
80
|
+
for (const child of n.walk()) {
|
|
81
|
+
if (child.type === 'text' && child.attributes.content) {
|
|
82
|
+
textParts.push(child.attributes.content);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Text nodes already carry their own surrounding whitespace, so joining
|
|
86
|
+
// with `''` (rather than `' '`) avoids doubling spaces when a heading
|
|
87
|
+
// contains inline formatting like `# Hello **strong** world`.
|
|
88
|
+
found = textParts.join('');
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
for (const child of n.children) {
|
|
92
|
+
if (walk(child))
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
walk(node);
|
|
98
|
+
return found;
|
|
99
|
+
}
|
|
65
100
|
export function headingsToList(options) {
|
|
66
101
|
const explicitLevel = options?.level;
|
|
67
102
|
const include = options?.include;
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-reference pattern compilation.
|
|
3
|
+
*
|
|
4
|
+
* Compiles user-authored `XrefPattern` config entries from `refrakt.config.json`
|
|
5
|
+
* into validated, ready-to-use `CompiledXrefPattern` objects. The runtime
|
|
6
|
+
* resolver (in `xref-resolve.ts`) consumes the compiled forms to turn
|
|
7
|
+
* unresolved xref IDs into URLs.
|
|
8
|
+
*
|
|
9
|
+
* Validation rules (per SPEC-065):
|
|
10
|
+
* - `match` must compile as a JavaScript regex; anchored to whole-string match
|
|
11
|
+
* by default (`^` and `$` auto-applied unless explicit anchors are present
|
|
12
|
+
* at the start/end of the pattern).
|
|
13
|
+
* - `template` placeholders must each be `id` or a named group of the regex.
|
|
14
|
+
* - `type` defaults to `"external"`. The value `"unresolved"` is reserved.
|
|
15
|
+
* - `label` defaults to `"{id}"` and uses the same placeholder syntax as
|
|
16
|
+
* `template`.
|
|
17
|
+
* - Duplicate `match` strings across entries are flagged as a warning (not an
|
|
18
|
+
* error; first-wins ordering still produces deterministic behaviour).
|
|
19
|
+
*/
|
|
20
|
+
import type { XrefPattern } from '@refrakt-md/types';
|
|
21
|
+
/** A pattern entry compiled and ready to be matched against an xref ID at
|
|
22
|
+
* resolve time. Authored {@link XrefPattern}s in `refrakt.config.json` are
|
|
23
|
+
* turned into this shape once per build via {@link compileXrefPatterns}. */
|
|
24
|
+
export interface CompiledXrefPattern {
|
|
25
|
+
/** The compiled regex (already wrapped in whole-string anchors if needed). */
|
|
26
|
+
match: RegExp;
|
|
27
|
+
/** URL template — same string the author wrote, ready for placeholder
|
|
28
|
+
* substitution by the resolver. */
|
|
29
|
+
template: string;
|
|
30
|
+
/** CSS modifier class value. Defaulted to `"external"` if the author
|
|
31
|
+
* omitted it. */
|
|
32
|
+
type: string;
|
|
33
|
+
/** Link-text template. Defaulted to `"{id}"` if the author omitted it. */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Named groups declared in the regex, in declaration order. The resolver
|
|
36
|
+
* uses these (plus the implicit `{id}`) to validate template placeholders
|
|
37
|
+
* at match time. */
|
|
38
|
+
groupNames: string[];
|
|
39
|
+
}
|
|
40
|
+
/** Diagnostics produced by {@link compileXrefPatterns}. Compilation never
|
|
41
|
+
* throws — fatal cases (invalid regex, unknown placeholder, reserved type)
|
|
42
|
+
* are surfaced via `errors`; soft diagnostics (duplicate `match`) via
|
|
43
|
+
* `warnings`. Adapters decide how to render them. */
|
|
44
|
+
export interface CompiledXrefPatternsResult {
|
|
45
|
+
patterns: CompiledXrefPattern[];
|
|
46
|
+
errors: string[];
|
|
47
|
+
warnings: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compile a list of authored xref patterns into runtime-ready form.
|
|
51
|
+
*
|
|
52
|
+
* Returns the compiled patterns alongside errors and warnings — callers
|
|
53
|
+
* (typically the content-loader bootstrap) decide whether errors should
|
|
54
|
+
* throw, log, or be passed back to the user.
|
|
55
|
+
*/
|
|
56
|
+
export declare function compileXrefPatterns(patterns: XrefPattern[] | undefined): CompiledXrefPatternsResult;
|
|
57
|
+
//# sourceMappingURL=xref-patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xref-patterns.d.ts","sourceRoot":"","sources":["../src/xref-patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;6EAE6E;AAC7E,MAAM,WAAW,mBAAmB;IACnC,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;wCACoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB;sBACkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd;;yBAEqB;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;sDAGsD;AACtD,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AA+CD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,WAAW,EAAE,GAAG,SAAS,GACjC,0BAA0B,CA8E5B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-reference pattern compilation.
|
|
3
|
+
*
|
|
4
|
+
* Compiles user-authored `XrefPattern` config entries from `refrakt.config.json`
|
|
5
|
+
* into validated, ready-to-use `CompiledXrefPattern` objects. The runtime
|
|
6
|
+
* resolver (in `xref-resolve.ts`) consumes the compiled forms to turn
|
|
7
|
+
* unresolved xref IDs into URLs.
|
|
8
|
+
*
|
|
9
|
+
* Validation rules (per SPEC-065):
|
|
10
|
+
* - `match` must compile as a JavaScript regex; anchored to whole-string match
|
|
11
|
+
* by default (`^` and `$` auto-applied unless explicit anchors are present
|
|
12
|
+
* at the start/end of the pattern).
|
|
13
|
+
* - `template` placeholders must each be `id` or a named group of the regex.
|
|
14
|
+
* - `type` defaults to `"external"`. The value `"unresolved"` is reserved.
|
|
15
|
+
* - `label` defaults to `"{id}"` and uses the same placeholder syntax as
|
|
16
|
+
* `template`.
|
|
17
|
+
* - Duplicate `match` strings across entries are flagged as a warning (not an
|
|
18
|
+
* error; first-wins ordering still produces deterministic behaviour).
|
|
19
|
+
*/
|
|
20
|
+
/** Reserved `type` values that cannot be used in pattern entries. */
|
|
21
|
+
const RESERVED_TYPES = new Set(['unresolved']);
|
|
22
|
+
/** Match `(?<name>` declarations in a regex source. Used to enumerate named
|
|
23
|
+
* groups statically (JS `RegExp` instances don't expose group names without
|
|
24
|
+
* a successful match). */
|
|
25
|
+
const NAMED_GROUP_RE = /\(\?<([a-zA-Z_$][a-zA-Z0-9_$]*)>/g;
|
|
26
|
+
/** Match `{name}` placeholders in template / label strings. */
|
|
27
|
+
const PLACEHOLDER_RE = /\{([a-zA-Z_$][a-zA-Z0-9_$]*)\}/g;
|
|
28
|
+
/** Apply whole-string anchoring to the pattern source. If the author already
|
|
29
|
+
* added `^` and `$` (at the very start and end), the source is used as-is.
|
|
30
|
+
* Otherwise the source is wrapped in `^(?:...)$`. Stripping any partial
|
|
31
|
+
* anchors first avoids double-anchoring like `^^...$$`. */
|
|
32
|
+
function anchorPatternSource(source) {
|
|
33
|
+
if (source.startsWith('^') && source.endsWith('$'))
|
|
34
|
+
return source;
|
|
35
|
+
let inner = source;
|
|
36
|
+
if (inner.startsWith('^'))
|
|
37
|
+
inner = inner.slice(1);
|
|
38
|
+
if (inner.endsWith('$'))
|
|
39
|
+
inner = inner.slice(0, -1);
|
|
40
|
+
return `^(?:${inner})$`;
|
|
41
|
+
}
|
|
42
|
+
/** Extract named-group names from a regex source, in declaration order. */
|
|
43
|
+
function extractGroupNames(source) {
|
|
44
|
+
const names = [];
|
|
45
|
+
NAMED_GROUP_RE.lastIndex = 0;
|
|
46
|
+
let match;
|
|
47
|
+
while ((match = NAMED_GROUP_RE.exec(source)) !== null) {
|
|
48
|
+
names.push(match[1]);
|
|
49
|
+
}
|
|
50
|
+
return names;
|
|
51
|
+
}
|
|
52
|
+
/** Find placeholder names used in a template/label string, deduplicated. */
|
|
53
|
+
function extractPlaceholders(template) {
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
PLACEHOLDER_RE.lastIndex = 0;
|
|
56
|
+
let match;
|
|
57
|
+
while ((match = PLACEHOLDER_RE.exec(template)) !== null) {
|
|
58
|
+
seen.add(match[1]);
|
|
59
|
+
}
|
|
60
|
+
return [...seen];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Compile a list of authored xref patterns into runtime-ready form.
|
|
64
|
+
*
|
|
65
|
+
* Returns the compiled patterns alongside errors and warnings — callers
|
|
66
|
+
* (typically the content-loader bootstrap) decide whether errors should
|
|
67
|
+
* throw, log, or be passed back to the user.
|
|
68
|
+
*/
|
|
69
|
+
export function compileXrefPatterns(patterns) {
|
|
70
|
+
const result = {
|
|
71
|
+
patterns: [],
|
|
72
|
+
errors: [],
|
|
73
|
+
warnings: [],
|
|
74
|
+
};
|
|
75
|
+
if (!patterns || patterns.length === 0)
|
|
76
|
+
return result;
|
|
77
|
+
const seenMatches = new Set();
|
|
78
|
+
patterns.forEach((entry, idx) => {
|
|
79
|
+
const ref = `xrefs[${idx}]`;
|
|
80
|
+
// Validate required fields up front.
|
|
81
|
+
if (typeof entry?.match !== 'string' || entry.match.length === 0) {
|
|
82
|
+
result.errors.push(`${ref}: \`match\` is required and must be a non-empty string`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (typeof entry.template !== 'string' || entry.template.length === 0) {
|
|
86
|
+
result.errors.push(`${ref}: \`template\` is required and must be a non-empty string`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Reserved type rejection.
|
|
90
|
+
const type = entry.type ?? 'external';
|
|
91
|
+
if (RESERVED_TYPES.has(type)) {
|
|
92
|
+
result.errors.push(`${ref}: \`type\` value "${type}" is reserved`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Duplicate match warning (doesn't fail; first-wins ordering is stable).
|
|
96
|
+
if (seenMatches.has(entry.match)) {
|
|
97
|
+
result.warnings.push(`${ref}: duplicate \`match\` "${entry.match}" — earlier entry wins`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
seenMatches.add(entry.match);
|
|
101
|
+
}
|
|
102
|
+
// Compile the regex with whole-string anchoring.
|
|
103
|
+
const sourceAnchored = anchorPatternSource(entry.match);
|
|
104
|
+
let regex;
|
|
105
|
+
try {
|
|
106
|
+
regex = new RegExp(sourceAnchored);
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
result.errors.push(`${ref}: invalid regex (${e.message})`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Enumerate named groups so the resolver can validate matches.
|
|
113
|
+
const groupNames = extractGroupNames(entry.match);
|
|
114
|
+
// Validate template + label placeholders against the available names
|
|
115
|
+
// (`id` is implicit; everything else must be a captured group).
|
|
116
|
+
const allowed = new Set(['id', ...groupNames]);
|
|
117
|
+
const label = entry.label ?? '{id}';
|
|
118
|
+
const templatePlaceholders = extractPlaceholders(entry.template);
|
|
119
|
+
const labelPlaceholders = extractPlaceholders(label);
|
|
120
|
+
const unknown = [];
|
|
121
|
+
for (const name of [...templatePlaceholders, ...labelPlaceholders]) {
|
|
122
|
+
if (!allowed.has(name))
|
|
123
|
+
unknown.push(name);
|
|
124
|
+
}
|
|
125
|
+
if (unknown.length > 0) {
|
|
126
|
+
const dedup = [...new Set(unknown)];
|
|
127
|
+
result.errors.push(`${ref}: unknown placeholder${dedup.length === 1 ? '' : 's'} ${dedup.map(n => `{${n}}`).join(', ')} (must be \`{id}\` or a named group of the regex)`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
result.patterns.push({
|
|
131
|
+
match: regex,
|
|
132
|
+
template: entry.template,
|
|
133
|
+
type,
|
|
134
|
+
label,
|
|
135
|
+
groupNames,
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=xref-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xref-patterns.js","sourceRoot":"","sources":["../src/xref-patterns.ts"],"names":[],"mappings":"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"}
|
package/dist/xref-resolve.d.ts
CHANGED
|
@@ -2,14 +2,31 @@
|
|
|
2
2
|
* Xref (cross-reference) resolution utilities.
|
|
3
3
|
*
|
|
4
4
|
* Walks a Markdoc renderable tree and converts xref placeholder spans
|
|
5
|
-
* (produced by the xref/ref tag transform) into resolved `<a>` links
|
|
6
|
-
*
|
|
5
|
+
* (produced by the xref/ref tag transform) into resolved `<a>` links.
|
|
6
|
+
*
|
|
7
|
+
* Resolution model (SPEC-065):
|
|
8
|
+
*
|
|
9
|
+
* 1. **Entity lookup** — find the entity in the registry (exact ID, then
|
|
10
|
+
* case-insensitive name/title). Captures metadata (label, type) for use
|
|
11
|
+
* in rendering even if the URL ends up coming from a pattern.
|
|
12
|
+
* 2. **URL resolution** — if the matched entity has a usable `sourceUrl`,
|
|
13
|
+
* that's the href (`data-xref-source="registry"`). Otherwise iterate
|
|
14
|
+
* configured patterns (compiled via `compileXrefPatterns`); first regex
|
|
15
|
+
* that matches the ID provides the URL (`data-xref-source="pattern"`).
|
|
16
|
+
* 3. **Unresolved fallback** — if neither the entity nor any pattern produces
|
|
17
|
+
* a URL, render `rf-xref--unresolved` with a build warning.
|
|
18
|
+
*
|
|
19
|
+
* The separation lets entity-lookup and URL-resolution succeed independently.
|
|
20
|
+
* SPEC-064 plan content registered without a `sourceUrl` (because it isn't
|
|
21
|
+
* published to any site) still resolves correctly: the registry provides
|
|
22
|
+
* label and type; user-configured patterns provide the URL.
|
|
7
23
|
*/
|
|
8
24
|
import type { EntityRegistry, PipelineContext } from '@refrakt-md/types';
|
|
25
|
+
import type { CompiledXrefPattern } from './xref-patterns.js';
|
|
9
26
|
/**
|
|
10
27
|
* Walk a Markdoc renderable tree, resolving any xref placeholders into
|
|
11
|
-
* clickable links using the entity registry
|
|
12
|
-
* styled spans with an `rf-xref--unresolved` class.
|
|
28
|
+
* clickable links using the entity registry and configured patterns.
|
|
29
|
+
* Unresolved xrefs become styled spans with an `rf-xref--unresolved` class.
|
|
13
30
|
*/
|
|
14
|
-
export declare function resolveXrefs(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry>, ctx: PipelineContext): unknown;
|
|
31
|
+
export declare function resolveXrefs(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry>, patterns: CompiledXrefPattern[], ctx: PipelineContext): unknown;
|
|
15
32
|
//# sourceMappingURL=xref-resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xref-resolve.d.ts","sourceRoot":"","sources":["../src/xref-resolve.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"xref-resolve.d.ts","sourceRoot":"","sources":["../src/xref-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE7F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA+Q9D;;;;GAIG;AACH,wBAAgB,YAAY,CAC3B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,EAClC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,GAAG,EAAE,eAAe,GAClB,OAAO,CAGT"}
|