@refrakt-md/runes 0.8.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +193 -23
- package/dist/config.js.map +1 -1
- package/dist/fence-escape.d.ts +19 -0
- package/dist/fence-escape.d.ts.map +1 -0
- package/dist/fence-escape.js +53 -0
- package/dist/fence-escape.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +2 -1
- package/dist/nodes.js.map +1 -1
- package/dist/registry.d.ts +2 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +2 -0
- package/dist/registry.js.map +1 -1
- package/dist/sandbox-sources.d.ts +34 -0
- package/dist/sandbox-sources.d.ts.map +1 -0
- package/dist/sandbox-sources.js +204 -0
- package/dist/sandbox-sources.js.map +1 -0
- package/dist/schema/xref.d.ts +5 -0
- package/dist/schema/xref.d.ts.map +1 -0
- package/dist/schema/xref.js +7 -0
- package/dist/schema/xref.js.map +1 -0
- package/dist/tags/common.d.ts +27 -0
- package/dist/tags/common.d.ts.map +1 -1
- package/dist/tags/common.js +53 -0
- package/dist/tags/common.js.map +1 -1
- package/dist/tags/sandbox.d.ts.map +1 -1
- package/dist/tags/sandbox.js +56 -9
- package/dist/tags/sandbox.js.map +1 -1
- package/dist/tags/xref.d.ts +18 -0
- package/dist/tags/xref.d.ts.map +1 -0
- package/dist/tags/xref.js +54 -0
- package/dist/tags/xref.js.map +1 -0
- package/package.json +3 -3
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,oBAAoB,EAAoE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,oBAAoB,EAAoE,MAAM,mBAAmB,CAAC;AAgFhI;gFACgF;AAChF,eAAO,MAAM,UAAU,EAAE,WAqrBxB,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,UAAU,aAAa,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AA4kBD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,oBA8H/B,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createComponentRenderable } from './lib/index.js';
|
|
|
5
5
|
import { schema } from './registry.js';
|
|
6
6
|
import { BREADCRUMB_AUTO_SENTINEL } from './tags/breadcrumb.js';
|
|
7
7
|
import { NAV_AUTO_SENTINEL } from './tags/nav.js';
|
|
8
|
+
import { XREF_RUNE_MARKER } from './tags/xref.js';
|
|
8
9
|
// ─── Budget postTransform helpers ───
|
|
9
10
|
const BUDGET_CURRENCY_SYMBOLS = {
|
|
10
11
|
USD: '$', EUR: '€', GBP: '£', JPY: '¥', CNY: '¥',
|
|
@@ -68,7 +69,7 @@ function readPropText(node, prop) {
|
|
|
68
69
|
}
|
|
69
70
|
/** autoLabel entries shared by all PageSection-based runes */
|
|
70
71
|
const pageSectionAutoLabel = {
|
|
71
|
-
header: '
|
|
72
|
+
header: 'preamble', // <header> wrapper element → data-name="preamble"
|
|
72
73
|
eyebrow: 'eyebrow', // property="eyebrow"
|
|
73
74
|
headline: 'headline', // property="headline"
|
|
74
75
|
blurb: 'blurb', // property="blurb"
|
|
@@ -82,11 +83,12 @@ export const coreConfig = {
|
|
|
82
83
|
icons: {},
|
|
83
84
|
runes: {
|
|
84
85
|
// ─── Simple runes (block name only, engine adds BEM classes) ───
|
|
85
|
-
Accordion: { block: 'accordion', autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
|
|
86
|
-
AccordionItem: { block: 'accordion-item', parent: 'Accordion', autoLabel: { name: 'header' }, editHints: { header: 'inline', body: 'none' } },
|
|
87
|
-
Details: { block: 'details', autoLabel: { summary: 'summary' }, editHints: { summary: 'inline', body: 'none' } },
|
|
86
|
+
Accordion: { block: 'accordion', defaultDensity: 'full', sections: { preamble: 'preamble', headline: 'title', blurb: 'description' }, autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
|
|
87
|
+
AccordionItem: { block: 'accordion-item', parent: 'Accordion', rootAttributes: { 'data-state': 'closed' }, autoLabel: { name: 'header' }, editHints: { header: 'inline', body: 'none' } },
|
|
88
|
+
Details: { block: 'details', defaultDensity: 'compact', sections: { summary: 'title' }, autoLabel: { summary: 'summary' }, editHints: { summary: 'inline', body: 'none' } },
|
|
88
89
|
Grid: {
|
|
89
90
|
block: 'grid',
|
|
91
|
+
defaultDensity: 'full',
|
|
90
92
|
modifiers: {
|
|
91
93
|
mode: { source: 'meta', default: 'columns' },
|
|
92
94
|
collapse: { source: 'meta', noBemClass: true },
|
|
@@ -108,6 +110,7 @@ export const coreConfig = {
|
|
|
108
110
|
},
|
|
109
111
|
CodeGroup: {
|
|
110
112
|
block: 'codegroup',
|
|
113
|
+
defaultDensity: 'compact',
|
|
111
114
|
modifiers: { title: { source: 'meta' }, overflow: { source: 'meta', default: 'scroll' } },
|
|
112
115
|
structure: {
|
|
113
116
|
topbar: {
|
|
@@ -120,12 +123,14 @@ export const coreConfig = {
|
|
|
120
123
|
],
|
|
121
124
|
},
|
|
122
125
|
},
|
|
126
|
+
sections: { topbar: 'header', title: 'title' },
|
|
123
127
|
editHints: { panel: 'code', title: 'none' },
|
|
124
128
|
},
|
|
125
129
|
PageSection: { block: 'page-section' },
|
|
126
130
|
TableOfContents: { block: 'toc' },
|
|
127
131
|
Embed: {
|
|
128
132
|
block: 'embed',
|
|
133
|
+
defaultDensity: 'compact',
|
|
129
134
|
editHints: { fallback: 'none' },
|
|
130
135
|
postTransform(node) {
|
|
131
136
|
const block = node.attributes.class?.split(' ')[0] || 'rf-embed';
|
|
@@ -166,10 +171,12 @@ export const coreConfig = {
|
|
|
166
171
|
};
|
|
167
172
|
},
|
|
168
173
|
},
|
|
169
|
-
Breadcrumb: { block: 'breadcrumb', editHints: { items: 'none' } },
|
|
174
|
+
Breadcrumb: { block: 'breadcrumb', defaultDensity: 'minimal', sections: { items: 'body' }, editHints: { items: 'none' } },
|
|
170
175
|
BreadcrumbItem: { block: 'breadcrumb-item', parent: 'Breadcrumb' },
|
|
171
176
|
Blog: {
|
|
172
177
|
block: 'blog',
|
|
178
|
+
defaultDensity: 'full',
|
|
179
|
+
sections: { preamble: 'preamble', headline: 'title', blurb: 'description', content: 'body' },
|
|
173
180
|
contentWrapper: { tag: 'div', ref: 'content' },
|
|
174
181
|
modifiers: {
|
|
175
182
|
layout: { source: 'meta', default: 'list' },
|
|
@@ -183,6 +190,8 @@ export const coreConfig = {
|
|
|
183
190
|
},
|
|
184
191
|
Budget: {
|
|
185
192
|
block: 'budget',
|
|
193
|
+
defaultDensity: 'full',
|
|
194
|
+
sections: { header: 'header', title: 'title', footer: 'footer' },
|
|
186
195
|
editHints: { title: 'none', meta: 'none', 'meta-item': 'none' },
|
|
187
196
|
modifiers: {
|
|
188
197
|
title: { source: 'meta' },
|
|
@@ -202,9 +211,9 @@ export const coreConfig = {
|
|
|
202
211
|
{
|
|
203
212
|
tag: 'div', ref: 'meta',
|
|
204
213
|
children: [
|
|
205
|
-
{ tag: 'span', ref: 'meta-item', metaText: 'currency', condition: 'currency' },
|
|
206
|
-
{ tag: 'span', ref: 'meta-item', metaText: 'travelers',
|
|
207
|
-
{ tag: 'span', ref: 'meta-item', metaText: 'duration',
|
|
214
|
+
{ tag: 'span', ref: 'meta-item', metaText: 'currency', condition: 'currency', metaType: 'category', metaRank: 'primary' },
|
|
215
|
+
{ tag: 'span', ref: 'meta-item', metaText: 'travelers', label: 'Travelers:', condition: 'travelers', metaType: 'quantity', metaRank: 'primary' },
|
|
216
|
+
{ tag: 'span', ref: 'meta-item', metaText: 'duration', label: 'Duration:', condition: 'duration', metaType: 'temporal', metaRank: 'secondary' },
|
|
208
217
|
],
|
|
209
218
|
},
|
|
210
219
|
],
|
|
@@ -282,8 +291,10 @@ export const coreConfig = {
|
|
|
282
291
|
// ─── Runes with modifier meta tags ───
|
|
283
292
|
Hint: {
|
|
284
293
|
block: 'hint',
|
|
294
|
+
defaultDensity: 'compact',
|
|
285
295
|
modifiers: { hintType: { source: 'meta', default: 'note' } },
|
|
286
296
|
contextModifiers: { 'hero': 'in-hero', 'feature': 'in-feature' },
|
|
297
|
+
sections: { header: 'header' },
|
|
287
298
|
editHints: { icon: 'none', title: 'none' },
|
|
288
299
|
structure: {
|
|
289
300
|
header: {
|
|
@@ -297,14 +308,17 @@ export const coreConfig = {
|
|
|
297
308
|
},
|
|
298
309
|
Figure: {
|
|
299
310
|
block: 'figure',
|
|
311
|
+
defaultDensity: 'compact',
|
|
300
312
|
modifiers: {
|
|
301
313
|
size: { source: 'meta', default: 'default' },
|
|
302
314
|
align: { source: 'meta', default: 'center' },
|
|
303
315
|
},
|
|
316
|
+
sections: { caption: 'description' },
|
|
304
317
|
editHints: { caption: 'inline' },
|
|
305
318
|
},
|
|
306
319
|
Gallery: {
|
|
307
320
|
block: 'gallery',
|
|
321
|
+
defaultDensity: 'full',
|
|
308
322
|
modifiers: {
|
|
309
323
|
layout: { source: 'meta', default: 'grid' },
|
|
310
324
|
lightbox: { source: 'meta', default: 'true', noBemClass: true },
|
|
@@ -319,15 +333,18 @@ export const coreConfig = {
|
|
|
319
333
|
},
|
|
320
334
|
Sidenote: {
|
|
321
335
|
block: 'sidenote',
|
|
336
|
+
defaultDensity: 'minimal',
|
|
322
337
|
modifiers: { variant: { source: 'meta', default: 'sidenote' } },
|
|
338
|
+
sections: { body: 'body' },
|
|
323
339
|
editHints: { body: 'inline' },
|
|
324
340
|
},
|
|
325
341
|
Compare: {
|
|
326
342
|
block: 'compare',
|
|
343
|
+
defaultDensity: 'full',
|
|
327
344
|
modifiers: { layout: { source: 'meta', default: 'side-by-side' } },
|
|
328
345
|
editHints: { panels: 'none' },
|
|
329
346
|
},
|
|
330
|
-
Conversation: { block: 'conversation', editHints: { messages: 'none' } },
|
|
347
|
+
Conversation: { block: 'conversation', defaultDensity: 'compact', editHints: { messages: 'none' } },
|
|
331
348
|
ConversationMessage: {
|
|
332
349
|
block: 'conversation-message',
|
|
333
350
|
parent: 'Conversation',
|
|
@@ -336,12 +353,15 @@ export const coreConfig = {
|
|
|
336
353
|
},
|
|
337
354
|
Annotate: {
|
|
338
355
|
block: 'annotate',
|
|
356
|
+
defaultDensity: 'full',
|
|
339
357
|
modifiers: { variant: { source: 'meta', default: 'margin' } },
|
|
358
|
+
sections: { body: 'body' },
|
|
340
359
|
editHints: { body: 'none', notes: 'none' },
|
|
341
360
|
},
|
|
342
361
|
AnnotateNote: { block: 'annotate-note', parent: 'Annotate', editHints: { body: 'inline' } },
|
|
343
362
|
Nav: {
|
|
344
363
|
block: 'nav',
|
|
364
|
+
defaultDensity: 'compact',
|
|
345
365
|
postTransform(node) {
|
|
346
366
|
return { ...node, name: 'rf-nav' };
|
|
347
367
|
},
|
|
@@ -377,11 +397,13 @@ export const coreConfig = {
|
|
|
377
397
|
},
|
|
378
398
|
Diff: {
|
|
379
399
|
block: 'diff',
|
|
400
|
+
defaultDensity: 'compact',
|
|
380
401
|
modifiers: { mode: { source: 'meta', default: 'unified' } },
|
|
381
402
|
editHints: { line: 'none', 'gutter-num': 'none', 'gutter-prefix': 'none', 'line-content': 'none' },
|
|
382
403
|
},
|
|
383
404
|
Chart: {
|
|
384
405
|
block: 'chart',
|
|
406
|
+
defaultDensity: 'compact',
|
|
385
407
|
editHints: { data: 'none' },
|
|
386
408
|
postTransform(node) {
|
|
387
409
|
const block = node.attributes.class?.split(' ')[0] || 'rf-chart';
|
|
@@ -495,33 +517,42 @@ export const coreConfig = {
|
|
|
495
517
|
// ─── Text formatting & layout runes ───
|
|
496
518
|
PullQuote: {
|
|
497
519
|
block: 'pullquote',
|
|
520
|
+
defaultDensity: 'compact',
|
|
498
521
|
modifiers: {
|
|
499
522
|
align: { source: 'meta', default: 'center' },
|
|
500
523
|
variant: { source: 'meta', default: 'default' },
|
|
501
524
|
},
|
|
525
|
+
sections: { body: 'body' },
|
|
502
526
|
editHints: { body: 'inline' },
|
|
503
527
|
},
|
|
504
528
|
TextBlock: {
|
|
505
529
|
block: 'textblock',
|
|
530
|
+
defaultDensity: 'full',
|
|
506
531
|
modifiers: {
|
|
507
532
|
dropcap: { source: 'meta' },
|
|
508
533
|
columns: { source: 'meta' },
|
|
509
534
|
lead: { source: 'meta' },
|
|
510
535
|
align: { source: 'meta', default: 'left' },
|
|
511
536
|
},
|
|
537
|
+
sections: { body: 'body' },
|
|
512
538
|
editHints: { body: 'none' },
|
|
513
539
|
},
|
|
514
540
|
MediaText: {
|
|
515
541
|
block: 'mediatext',
|
|
542
|
+
defaultDensity: 'full',
|
|
516
543
|
modifiers: {
|
|
517
544
|
align: { source: 'meta', default: 'left' },
|
|
518
545
|
ratio: { source: 'meta', default: '1:1' },
|
|
519
546
|
wrap: { source: 'meta' },
|
|
520
547
|
},
|
|
548
|
+
sections: { body: 'body', media: 'media' },
|
|
549
|
+
mediaSlots: { media: 'cover' },
|
|
521
550
|
editHints: { media: 'image', body: 'none' },
|
|
522
551
|
},
|
|
523
552
|
Showcase: {
|
|
524
553
|
block: 'showcase',
|
|
554
|
+
defaultDensity: 'compact',
|
|
555
|
+
sections: { viewport: 'body' },
|
|
525
556
|
modifiers: {
|
|
526
557
|
shadow: { source: 'meta', default: 'none' },
|
|
527
558
|
bleed: { source: 'meta', default: 'none' },
|
|
@@ -547,11 +578,13 @@ export const coreConfig = {
|
|
|
547
578
|
},
|
|
548
579
|
},
|
|
549
580
|
// ─── Interactive runes (still get BEM classes, components add behavior) ───
|
|
550
|
-
TabGroup: { block: 'tabs', autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
|
|
551
|
-
Tab: { block: 'tab', parent: 'TabGroup', editHints: { name: 'inline' } },
|
|
552
|
-
TabPanel: { block: 'tab-panel', parent: 'TabGroup' },
|
|
581
|
+
TabGroup: { block: 'tabs', defaultDensity: 'full', sections: { preamble: 'preamble', headline: 'title', blurb: 'description' }, autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
|
|
582
|
+
Tab: { block: 'tab', parent: 'TabGroup', rootAttributes: { 'data-state': 'inactive' }, editHints: { name: 'inline' } },
|
|
583
|
+
TabPanel: { block: 'tab-panel', parent: 'TabGroup', rootAttributes: { 'data-state': 'inactive' } },
|
|
553
584
|
DataTable: {
|
|
554
585
|
block: 'datatable',
|
|
586
|
+
defaultDensity: 'compact',
|
|
587
|
+
sections: { table: 'body' },
|
|
555
588
|
modifiers: {
|
|
556
589
|
searchable: { source: 'meta', default: 'false' },
|
|
557
590
|
sortable: { source: 'meta' },
|
|
@@ -562,6 +595,8 @@ export const coreConfig = {
|
|
|
562
595
|
},
|
|
563
596
|
Form: {
|
|
564
597
|
block: 'form',
|
|
598
|
+
defaultDensity: 'full',
|
|
599
|
+
sections: { body: 'body' },
|
|
565
600
|
modifiers: {
|
|
566
601
|
variant: { source: 'meta', default: 'stacked' },
|
|
567
602
|
action: { source: 'meta' },
|
|
@@ -581,15 +616,18 @@ export const coreConfig = {
|
|
|
581
616
|
},
|
|
582
617
|
Reveal: {
|
|
583
618
|
block: 'reveal',
|
|
619
|
+
defaultDensity: 'full',
|
|
584
620
|
modifiers: {
|
|
585
621
|
mode: { source: 'meta', default: 'click' },
|
|
586
622
|
},
|
|
623
|
+
sections: { preamble: 'preamble', headline: 'title', blurb: 'description' },
|
|
587
624
|
autoLabel: pageSectionAutoLabel,
|
|
588
625
|
editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline', steps: 'none' },
|
|
589
626
|
},
|
|
590
|
-
RevealStep: { block: 'reveal-step', parent: 'Reveal', editHints: { body: 'none' } },
|
|
627
|
+
RevealStep: { block: 'reveal-step', parent: 'Reveal', rootAttributes: { 'data-state': 'closed' }, editHints: { body: 'none' } },
|
|
591
628
|
Juxtapose: {
|
|
592
629
|
block: 'juxtapose',
|
|
630
|
+
defaultDensity: 'compact',
|
|
593
631
|
modifiers: {
|
|
594
632
|
variant: { source: 'meta', default: 'slider' },
|
|
595
633
|
orientation: { source: 'meta', default: 'vertical', noBemClass: true },
|
|
@@ -602,9 +640,10 @@ export const coreConfig = {
|
|
|
602
640
|
},
|
|
603
641
|
editHints: { panels: 'none' },
|
|
604
642
|
},
|
|
605
|
-
JuxtaposePanel: { block: 'juxtapose-panel', parent: 'Juxtapose', editHints: { body: 'none' } },
|
|
643
|
+
JuxtaposePanel: { block: 'juxtapose-panel', parent: 'Juxtapose', rootAttributes: { 'data-state': 'inactive' }, editHints: { body: 'none' } },
|
|
606
644
|
Diagram: {
|
|
607
645
|
block: 'diagram',
|
|
646
|
+
defaultDensity: 'compact',
|
|
608
647
|
editHints: { source: 'code' },
|
|
609
648
|
postTransform(node) {
|
|
610
649
|
const block = node.attributes.class?.split(' ')[0] || 'rf-diagram';
|
|
@@ -638,6 +677,7 @@ export const coreConfig = {
|
|
|
638
677
|
Region: { block: 'region', parent: 'Layout' },
|
|
639
678
|
Sandbox: {
|
|
640
679
|
block: 'sandbox',
|
|
680
|
+
defaultDensity: 'compact',
|
|
641
681
|
editHints: { source: 'code' },
|
|
642
682
|
postTransform(node) {
|
|
643
683
|
// Read meta values
|
|
@@ -647,14 +687,23 @@ export const coreConfig = {
|
|
|
647
687
|
const label = readMeta(node, 'label') || '';
|
|
648
688
|
const height = readMeta(node, 'height') || 'auto';
|
|
649
689
|
const designTokens = readMeta(node, 'design-tokens') || '';
|
|
650
|
-
// Keep non-meta children (fallback pre
|
|
651
|
-
const fallbackChildren =
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
if (child
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
690
|
+
// Keep non-meta children (fallback pre) and extract source panels
|
|
691
|
+
const fallbackChildren = [];
|
|
692
|
+
const sourcePanelOrigins = [];
|
|
693
|
+
for (const child of node.children) {
|
|
694
|
+
if (!isTag(child)) {
|
|
695
|
+
fallbackChildren.push(child);
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
if (child.name === 'meta') {
|
|
699
|
+
// Collect origin data from source panels
|
|
700
|
+
if (child.attributes?.['data-field'] === 'source-panel' && child.attributes?.['data-origin']) {
|
|
701
|
+
sourcePanelOrigins.push(`${child.attributes['data-label'] || ''}\t${child.attributes['data-origin']}`);
|
|
702
|
+
}
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
fallbackChildren.push(child);
|
|
706
|
+
}
|
|
658
707
|
// Add hidden content div for web component
|
|
659
708
|
const children = [
|
|
660
709
|
...fallbackChildren,
|
|
@@ -671,6 +720,7 @@ export const coreConfig = {
|
|
|
671
720
|
...(label ? { 'data-label': label } : {}),
|
|
672
721
|
'data-height': height,
|
|
673
722
|
...(designTokens ? { 'data-design-tokens': designTokens } : {}),
|
|
723
|
+
...(sourcePanelOrigins.length > 0 ? { 'data-source-origins': sourcePanelOrigins.join('\n') } : {}),
|
|
674
724
|
},
|
|
675
725
|
children,
|
|
676
726
|
};
|
|
@@ -1004,6 +1054,125 @@ function resolveBlogPosts(renderable, allPosts, ctx, pageUrl) {
|
|
|
1004
1054
|
});
|
|
1005
1055
|
return modified ? result : renderable;
|
|
1006
1056
|
}
|
|
1057
|
+
// ─── Xref resolution helpers ───
|
|
1058
|
+
/**
|
|
1059
|
+
* Find an entity by exact ID across all types in the registry.
|
|
1060
|
+
* If typeHint is provided, only search that type.
|
|
1061
|
+
*/
|
|
1062
|
+
function findEntityById(registry, id, typeHint) {
|
|
1063
|
+
const types = typeHint ? [typeHint] : registry.getTypes();
|
|
1064
|
+
for (const type of types) {
|
|
1065
|
+
const entity = registry.getById(type, id);
|
|
1066
|
+
if (entity)
|
|
1067
|
+
return { entity, ambiguous: false };
|
|
1068
|
+
}
|
|
1069
|
+
return undefined;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Find entities by name/title match (case-insensitive) across all types.
|
|
1073
|
+
* If typeHint is provided, only search that type.
|
|
1074
|
+
*/
|
|
1075
|
+
function findEntitiesByName(registry, name, typeHint) {
|
|
1076
|
+
const nameLower = name.toLowerCase();
|
|
1077
|
+
const types = typeHint ? [typeHint] : registry.getTypes();
|
|
1078
|
+
const matches = [];
|
|
1079
|
+
for (const type of types) {
|
|
1080
|
+
for (const entity of registry.getAll(type)) {
|
|
1081
|
+
const entityName = entity.data.name ?? '';
|
|
1082
|
+
const entityTitle = entity.data.title ?? '';
|
|
1083
|
+
if (entityName.toLowerCase() === nameLower || entityTitle.toLowerCase() === nameLower) {
|
|
1084
|
+
matches.push(entity);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return matches;
|
|
1089
|
+
}
|
|
1090
|
+
/** Resolve an entity's URL for use as an href */
|
|
1091
|
+
function resolveEntityHref(entity) {
|
|
1092
|
+
const baseUrl = entity.data.url || entity.sourceUrl;
|
|
1093
|
+
const headingId = entity.data.headingId;
|
|
1094
|
+
if (headingId)
|
|
1095
|
+
return `${baseUrl}#${headingId}`;
|
|
1096
|
+
return baseUrl;
|
|
1097
|
+
}
|
|
1098
|
+
/** Walk a Markdoc renderable tree, resolving any xref placeholders */
|
|
1099
|
+
function resolveXrefs(renderable, pageUrl, registry, ctx) {
|
|
1100
|
+
if (!Tag.isTag(renderable)) {
|
|
1101
|
+
if (Array.isArray(renderable)) {
|
|
1102
|
+
const newChildren = renderable.map(c => resolveXrefs(c, pageUrl, registry, ctx));
|
|
1103
|
+
if (newChildren.every((c, i) => c === renderable[i]))
|
|
1104
|
+
return renderable;
|
|
1105
|
+
return newChildren;
|
|
1106
|
+
}
|
|
1107
|
+
return renderable;
|
|
1108
|
+
}
|
|
1109
|
+
const tag = renderable;
|
|
1110
|
+
// Check if this is an xref placeholder
|
|
1111
|
+
if (tag.attributes?.['data-rune'] === XREF_RUNE_MARKER) {
|
|
1112
|
+
const id = tag.attributes['data-xref-id'];
|
|
1113
|
+
const label = tag.attributes['data-xref-label'];
|
|
1114
|
+
const typeHint = tag.attributes['data-xref-type'];
|
|
1115
|
+
// Try exact ID match first
|
|
1116
|
+
const idMatch = findEntityById(registry, id, typeHint);
|
|
1117
|
+
if (idMatch) {
|
|
1118
|
+
const entity = idMatch.entity;
|
|
1119
|
+
const href = resolveEntityHref(entity);
|
|
1120
|
+
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
1121
|
+
if (entity.sourceUrl === pageUrl) {
|
|
1122
|
+
ctx.info(`xref "${id}" on ${pageUrl} — references itself`, pageUrl);
|
|
1123
|
+
}
|
|
1124
|
+
return new Tag('a', {
|
|
1125
|
+
class: `rf-xref rf-xref--${entity.type}`,
|
|
1126
|
+
href,
|
|
1127
|
+
'data-entity-type': entity.type,
|
|
1128
|
+
'data-entity-id': entity.id,
|
|
1129
|
+
}, [text]);
|
|
1130
|
+
}
|
|
1131
|
+
// Try name/title match
|
|
1132
|
+
const nameMatches = findEntitiesByName(registry, id, typeHint);
|
|
1133
|
+
if (nameMatches.length === 1) {
|
|
1134
|
+
const entity = nameMatches[0];
|
|
1135
|
+
const href = resolveEntityHref(entity);
|
|
1136
|
+
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
1137
|
+
if (entity.sourceUrl === pageUrl) {
|
|
1138
|
+
ctx.info(`xref "${id}" on ${pageUrl} — references itself`, pageUrl);
|
|
1139
|
+
}
|
|
1140
|
+
return new Tag('a', {
|
|
1141
|
+
class: `rf-xref rf-xref--${entity.type}`,
|
|
1142
|
+
href,
|
|
1143
|
+
'data-entity-type': entity.type,
|
|
1144
|
+
'data-entity-id': entity.id,
|
|
1145
|
+
}, [text]);
|
|
1146
|
+
}
|
|
1147
|
+
if (nameMatches.length > 1) {
|
|
1148
|
+
const matchList = nameMatches
|
|
1149
|
+
.map(e => `${e.type} "${e.data.title || e.data.name || e.id}" on ${e.sourceUrl}`)
|
|
1150
|
+
.join(', ');
|
|
1151
|
+
ctx.warn(`xref "${id}" on ${pageUrl} — matches ${nameMatches.length} entities (${matchList}). Add type hint to disambiguate.`, pageUrl);
|
|
1152
|
+
// Use first match
|
|
1153
|
+
const entity = nameMatches[0];
|
|
1154
|
+
const href = resolveEntityHref(entity);
|
|
1155
|
+
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
1156
|
+
return new Tag('a', {
|
|
1157
|
+
class: `rf-xref rf-xref--${entity.type}`,
|
|
1158
|
+
href,
|
|
1159
|
+
'data-entity-type': entity.type,
|
|
1160
|
+
'data-entity-id': entity.id,
|
|
1161
|
+
}, [text]);
|
|
1162
|
+
}
|
|
1163
|
+
// No match — unresolved
|
|
1164
|
+
ctx.warn(`xref "${id}" on ${pageUrl} — entity not found`, pageUrl);
|
|
1165
|
+
return new Tag('span', {
|
|
1166
|
+
class: 'rf-xref rf-xref--unresolved',
|
|
1167
|
+
'data-entity-id': id,
|
|
1168
|
+
}, [label || id]);
|
|
1169
|
+
}
|
|
1170
|
+
// Recurse into children
|
|
1171
|
+
const newChildren = (tag.children ?? []).map((c) => resolveXrefs(c, pageUrl, registry, ctx));
|
|
1172
|
+
if (newChildren.every((c, i) => c === tag.children[i]))
|
|
1173
|
+
return tag;
|
|
1174
|
+
return { ...tag, children: newChildren };
|
|
1175
|
+
}
|
|
1007
1176
|
/**
|
|
1008
1177
|
* Core cross-page pipeline hooks.
|
|
1009
1178
|
* Run for every site, before any community package hooks.
|
|
@@ -1072,7 +1241,7 @@ export const corePipelineHooks = {
|
|
|
1072
1241
|
draft: e.data.draft || false,
|
|
1073
1242
|
frontmatter: e.data,
|
|
1074
1243
|
}));
|
|
1075
|
-
return { pageTree, breadcrumbPaths, pagesByUrl, headingIndex, allPosts };
|
|
1244
|
+
return { pageTree, breadcrumbPaths, pagesByUrl, headingIndex, allPosts, registry };
|
|
1076
1245
|
},
|
|
1077
1246
|
postProcess(page, aggregated, ctx) {
|
|
1078
1247
|
const coreData = aggregated['__core__'];
|
|
@@ -1081,6 +1250,7 @@ export const corePipelineHooks = {
|
|
|
1081
1250
|
let renderable = resolveAutoBreadcrumbs(page.renderable, page.url, coreData.breadcrumbPaths, coreData.pagesByUrl, ctx);
|
|
1082
1251
|
renderable = resolveAutoNavs(renderable, page.url, coreData.pagesByUrl, ctx);
|
|
1083
1252
|
renderable = resolveBlogPosts(renderable, coreData.allPosts, ctx, page.url);
|
|
1253
|
+
renderable = resolveXrefs(renderable, page.url, coreData.registry, ctx);
|
|
1084
1254
|
if (renderable === page.renderable)
|
|
1085
1255
|
return page;
|
|
1086
1256
|
return { ...page, renderable };
|