@refrakt-md/runes 0.33.0 → 0.34.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.map +1 -1
- package/dist/aggregate-resolve.js +18 -4
- package/dist/aggregate-resolve.js.map +1 -1
- package/dist/attributes.d.ts +15 -0
- package/dist/attributes.d.ts.map +1 -1
- package/dist/attributes.js +22 -7
- package/dist/attributes.js.map +1 -1
- package/dist/collection-helpers.d.ts.map +1 -1
- package/dist/collection-helpers.js +1 -1
- package/dist/collection-helpers.js.map +1 -1
- package/dist/collection-resolve.d.ts.map +1 -1
- package/dist/collection-resolve.js +31 -8
- package/dist/collection-resolve.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +195 -74
- package/dist/config.js.map +1 -1
- package/dist/data-adapters.d.ts.map +1 -1
- package/dist/data-adapters.js +28 -11
- package/dist/data-adapters.js.map +1 -1
- package/dist/data-emit.d.ts.map +1 -1
- package/dist/data-emit.js.map +1 -1
- package/dist/data-pipeline.d.ts.map +1 -1
- package/dist/data-pipeline.js +45 -12
- package/dist/data-pipeline.js.map +1 -1
- package/dist/data-projection.d.ts.map +1 -1
- package/dist/data-projection.js +4 -3
- package/dist/data-projection.js.map +1 -1
- package/dist/data-resolve.d.ts.map +1 -1
- package/dist/data-resolve.js +5 -2
- package/dist/data-resolve.js.map +1 -1
- package/dist/documents/page.d.ts.map +1 -1
- package/dist/documents/page.js.map +1 -1
- package/dist/drawer-pipeline.d.ts.map +1 -1
- package/dist/drawer-pipeline.js +3 -2
- package/dist/drawer-pipeline.js.map +1 -1
- package/dist/expand-pipeline.d.ts.map +1 -1
- package/dist/expand-pipeline.js +3 -3
- package/dist/expand-pipeline.js.map +1 -1
- package/dist/fence-escape.d.ts.map +1 -1
- package/dist/fence-escape.js +1 -3
- package/dist/fence-escape.js.map +1 -1
- package/dist/field-match.d.ts.map +1 -1
- package/dist/field-match.js.map +1 -1
- package/dist/file-ref-resolve.js +6 -4
- package/dist/file-ref-resolve.js.map +1 -1
- package/dist/fixtures.js +2 -2
- package/dist/fixtures.js.map +1 -1
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +16 -3
- package/dist/functions.js.map +1 -1
- package/dist/include-pipeline.d.ts.map +1 -1
- package/dist/include-pipeline.js +3 -1
- package/dist/include-pipeline.js.map +1 -1
- package/dist/index.d.ts +92 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +281 -60
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/layouts/grid.d.ts +1 -1
- package/dist/layouts/grid.d.ts.map +1 -1
- package/dist/layouts/grid.js +4 -6
- package/dist/layouts/grid.js.map +1 -1
- package/dist/lib/component.d.ts.map +1 -1
- package/dist/lib/component.js +7 -7
- package/dist/lib/component.js.map +1 -1
- package/dist/lib/icon-resolve.d.ts.map +1 -1
- package/dist/lib/icon-resolve.js.map +1 -1
- package/dist/lib/image-schemes.js +2 -2
- package/dist/lib/image-schemes.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +251 -50
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/node.d.ts.map +1 -1
- package/dist/lib/node.js +3 -2
- package/dist/lib/node.js.map +1 -1
- package/dist/lib/placeholder.d.ts.map +1 -1
- package/dist/lib/placeholder.js +6 -9
- package/dist/lib/placeholder.js.map +1 -1
- package/dist/lib/read-file.d.ts.map +1 -1
- package/dist/lib/read-file.js.map +1 -1
- package/dist/lib/renderable.d.ts.map +1 -1
- package/dist/lib/renderable.js +5 -5
- package/dist/lib/renderable.js.map +1 -1
- package/dist/lib/resolver.d.ts.map +1 -1
- package/dist/lib/resolver.js +26 -35
- package/dist/lib/resolver.js.map +1 -1
- package/dist/lib/svg.d.ts.map +1 -1
- package/dist/lib/svg.js.map +1 -1
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +9 -11
- package/dist/nodes.js.map +1 -1
- package/dist/outline-scope.js +1 -3
- package/dist/outline-scope.js.map +1 -1
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +13 -10
- package/dist/plugins.js.map +1 -1
- package/dist/reference.d.ts.map +1 -1
- package/dist/reference.js +28 -22
- package/dist/reference.js.map +1 -1
- package/dist/relationships-resolve.d.ts.map +1 -1
- package/dist/relationships-resolve.js +31 -7
- package/dist/relationships-resolve.js.map +1 -1
- package/dist/rune.d.ts.map +1 -1
- package/dist/rune.js.map +1 -1
- package/dist/sandbox-sources.js +6 -6
- package/dist/sandbox-sources.js.map +1 -1
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +4 -4
- package/dist/seo.js.map +1 -1
- package/dist/snippet-pipeline.d.ts.map +1 -1
- package/dist/snippet-pipeline.js +1 -1
- package/dist/snippet-pipeline.js.map +1 -1
- package/dist/tags/accordion.d.ts.map +1 -1
- package/dist/tags/accordion.js +23 -9
- package/dist/tags/accordion.js.map +1 -1
- package/dist/tags/aggregate.d.ts.map +1 -1
- package/dist/tags/aggregate.js +65 -10
- package/dist/tags/aggregate.js.map +1 -1
- package/dist/tags/annotate.d.ts.map +1 -1
- package/dist/tags/annotate.js +12 -9
- package/dist/tags/annotate.js.map +1 -1
- package/dist/tags/badge.d.ts.map +1 -1
- package/dist/tags/badge.js.map +1 -1
- package/dist/tags/bar.d.ts.map +1 -1
- package/dist/tags/bar.js +3 -7
- package/dist/tags/bar.js.map +1 -1
- package/dist/tags/bg.d.ts.map +1 -1
- package/dist/tags/bg.js +60 -12
- package/dist/tags/bg.js.map +1 -1
- package/dist/tags/blog.d.ts.map +1 -1
- package/dist/tags/blog.js +35 -10
- package/dist/tags/blog.js.map +1 -1
- package/dist/tags/breadcrumb.d.ts.map +1 -1
- package/dist/tags/breadcrumb.js +33 -11
- package/dist/tags/breadcrumb.js.map +1 -1
- package/dist/tags/budget.d.ts.map +1 -1
- package/dist/tags/budget.js +54 -16
- package/dist/tags/budget.js.map +1 -1
- package/dist/tags/card.d.ts.map +1 -1
- package/dist/tags/card.js +24 -6
- package/dist/tags/card.js.map +1 -1
- package/dist/tags/chart.d.ts.map +1 -1
- package/dist/tags/chart.js +33 -11
- package/dist/tags/chart.js.map +1 -1
- package/dist/tags/codegroup.d.ts.map +1 -1
- package/dist/tags/codegroup.js +39 -21
- package/dist/tags/codegroup.js.map +1 -1
- package/dist/tags/collection.d.ts.map +1 -1
- package/dist/tags/collection.js +55 -9
- package/dist/tags/collection.js.map +1 -1
- package/dist/tags/common.d.ts.map +1 -1
- package/dist/tags/common.js +34 -9
- package/dist/tags/common.js.map +1 -1
- package/dist/tags/compare.d.ts.map +1 -1
- package/dist/tags/compare.js +26 -14
- package/dist/tags/compare.js.map +1 -1
- package/dist/tags/conversation.d.ts.map +1 -1
- package/dist/tags/conversation.js +19 -17
- package/dist/tags/conversation.js.map +1 -1
- package/dist/tags/data.d.ts.map +1 -1
- package/dist/tags/data.js +67 -13
- package/dist/tags/data.js.map +1 -1
- package/dist/tags/datatable.d.ts.map +1 -1
- package/dist/tags/datatable.js +22 -8
- package/dist/tags/datatable.js.map +1 -1
- package/dist/tags/deflist.d.ts.map +1 -1
- package/dist/tags/deflist.js +5 -11
- package/dist/tags/deflist.js.map +1 -1
- package/dist/tags/details.d.ts.map +1 -1
- package/dist/tags/details.js +8 -5
- package/dist/tags/details.js.map +1 -1
- package/dist/tags/diagram.d.ts.map +1 -1
- package/dist/tags/diagram.js +9 -5
- package/dist/tags/diagram.js.map +1 -1
- package/dist/tags/diff.d.ts.map +1 -1
- package/dist/tags/diff.js +43 -24
- package/dist/tags/diff.js.map +1 -1
- package/dist/tags/drawer.d.ts.map +1 -1
- package/dist/tags/drawer.js +4 -6
- package/dist/tags/drawer.js.map +1 -1
- package/dist/tags/embed.d.ts.map +1 -1
- package/dist/tags/embed.js +10 -5
- package/dist/tags/embed.js.map +1 -1
- package/dist/tags/expand.d.ts.map +1 -1
- package/dist/tags/expand.js.map +1 -1
- package/dist/tags/figure.d.ts.map +1 -1
- package/dist/tags/figure.js +29 -9
- package/dist/tags/figure.js.map +1 -1
- package/dist/tags/file-ref.d.ts.map +1 -1
- package/dist/tags/file-ref.js.map +1 -1
- package/dist/tags/form.d.ts.map +1 -1
- package/dist/tags/form.js +52 -25
- package/dist/tags/form.js.map +1 -1
- package/dist/tags/gallery.d.ts.map +1 -1
- package/dist/tags/gallery.js +26 -12
- package/dist/tags/gallery.js.map +1 -1
- package/dist/tags/grid.d.ts.map +1 -1
- package/dist/tags/grid.js +57 -14
- package/dist/tags/grid.js.map +1 -1
- package/dist/tags/hint.d.ts.map +1 -1
- package/dist/tags/hint.js +9 -5
- package/dist/tags/hint.js.map +1 -1
- package/dist/tags/icon.d.ts.map +1 -1
- package/dist/tags/icon.js +5 -1
- package/dist/tags/icon.js.map +1 -1
- package/dist/tags/include.d.ts.map +1 -1
- package/dist/tags/include.js +1 -1
- package/dist/tags/include.js.map +1 -1
- package/dist/tags/juxtapose.d.ts.map +1 -1
- package/dist/tags/juxtapose.js +32 -14
- package/dist/tags/juxtapose.js.map +1 -1
- package/dist/tags/layout.d.ts.map +1 -1
- package/dist/tags/layout.js +7 -4
- package/dist/tags/layout.js.map +1 -1
- package/dist/tags/mediatext.d.ts.map +1 -1
- package/dist/tags/mediatext.js +19 -8
- package/dist/tags/mediatext.js.map +1 -1
- package/dist/tags/nav.d.ts.map +1 -1
- package/dist/tags/nav.js +43 -23
- package/dist/tags/nav.js.map +1 -1
- package/dist/tags/pagination.d.ts.map +1 -1
- package/dist/tags/pagination.js +27 -5
- package/dist/tags/pagination.js.map +1 -1
- package/dist/tags/progress.d.ts.map +1 -1
- package/dist/tags/progress.js +25 -5
- package/dist/tags/progress.js.map +1 -1
- package/dist/tags/pullquote.d.ts.map +1 -1
- package/dist/tags/pullquote.js +16 -9
- package/dist/tags/pullquote.js.map +1 -1
- package/dist/tags/region.d.ts.map +1 -1
- package/dist/tags/region.js +9 -4
- package/dist/tags/region.js.map +1 -1
- package/dist/tags/relationships.d.ts.map +1 -1
- package/dist/tags/relationships.js +55 -9
- package/dist/tags/relationships.js.map +1 -1
- package/dist/tags/reveal.d.ts.map +1 -1
- package/dist/tags/reveal.js +16 -7
- package/dist/tags/reveal.js.map +1 -1
- package/dist/tags/sandbox.d.ts.map +1 -1
- package/dist/tags/sandbox.js +104 -44
- package/dist/tags/sandbox.js.map +1 -1
- package/dist/tags/section.d.ts.map +1 -1
- package/dist/tags/section.js +13 -3
- package/dist/tags/section.js.map +1 -1
- package/dist/tags/showcase.d.ts.map +1 -1
- package/dist/tags/showcase.js +33 -11
- package/dist/tags/showcase.js.map +1 -1
- package/dist/tags/sidenote.d.ts.map +1 -1
- package/dist/tags/sidenote.js +9 -5
- package/dist/tags/sidenote.js.map +1 -1
- package/dist/tags/snippet.d.ts.map +1 -1
- package/dist/tags/snippet.js.map +1 -1
- package/dist/tags/tabs.d.ts.map +1 -1
- package/dist/tags/tabs.js +16 -9
- package/dist/tags/tabs.js.map +1 -1
- package/dist/tags/textblock.d.ts.map +1 -1
- package/dist/tags/textblock.js +9 -5
- package/dist/tags/textblock.js.map +1 -1
- package/dist/tags/tint.d.ts +1 -1
- package/dist/tags/tint.d.ts.map +1 -1
- package/dist/tags/tint.js +14 -2
- package/dist/tags/tint.js.map +1 -1
- package/dist/tags/toc.d.ts.map +1 -1
- package/dist/tags/toc.js +16 -7
- package/dist/tags/toc.js.map +1 -1
- package/dist/tags/xref.d.ts.map +1 -1
- package/dist/tags/xref.js.map +1 -1
- package/dist/universal-attributes.d.ts.map +1 -1
- package/dist/universal-attributes.js +28 -5
- package/dist/universal-attributes.js.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +4 -4
- package/dist/util.js.map +1 -1
- package/dist/xref-patterns.js +1 -1
- package/dist/xref-patterns.js.map +1 -1
- package/dist/xref-preview-resolve.js +3 -4
- package/dist/xref-preview-resolve.js.map +1 -1
- package/dist/xref-resolve.d.ts.map +1 -1
- package/dist/xref-resolve.js +4 -4
- package/dist/xref-resolve.js.map +1 -1
- package/i18n/de.json +67 -67
- package/i18n/en.json +67 -67
- package/package.json +3 -3
- package/dist/tags/error.d.ts +0 -3
- package/dist/tags/error.d.ts.map +0 -1
- package/dist/tags/error.js +0 -34
- package/dist/tags/error.js.map +0 -1
package/dist/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isTag, readField, resolveGap, ratioToFr, resolveValign } from '@refrakt-md/transform';
|
|
1
|
+
import { isTag, readField, resolveGap, ratioToFr, resolveValign, } from '@refrakt-md/transform';
|
|
2
2
|
import Markdoc from '@markdoc/markdoc';
|
|
3
3
|
const { Tag } = Markdoc;
|
|
4
4
|
import { createComponentRenderable } from './lib/index.js';
|
|
@@ -9,7 +9,7 @@ import { resolveXrefs } from './xref-resolve.js';
|
|
|
9
9
|
import { preprocessSnippets, wrapStandaloneSnippets } from './snippet-pipeline.js';
|
|
10
10
|
import { preprocessData } from './data-pipeline.js';
|
|
11
11
|
import { preprocessIncludes } from './include-pipeline.js';
|
|
12
|
-
import { registerDrawers, resolveAutoDrawerTitleLevels, hoistPreviewDrawers } from './drawer-pipeline.js';
|
|
12
|
+
import { registerDrawers, resolveAutoDrawerTitleLevels, hoistPreviewDrawers, } from './drawer-pipeline.js';
|
|
13
13
|
import { resolveFileRefs } from './file-ref-resolve.js';
|
|
14
14
|
import { resolveXrefPreviews } from './xref-preview-resolve.js';
|
|
15
15
|
import { applyOutlineScopeWalkers, harvestHeadingsFromRenderable } from './outline-scope.js';
|
|
@@ -44,7 +44,12 @@ import { tabGroupSections } from './tags/tabs.js';
|
|
|
44
44
|
/** Read text content from a property span child */
|
|
45
45
|
function readPropText(node, prop) {
|
|
46
46
|
for (const c of node.children) {
|
|
47
|
-
if (isTag(c) &&
|
|
47
|
+
if (isTag(c) &&
|
|
48
|
+
c.attributes?.['data-field'] ===
|
|
49
|
+
prop
|
|
50
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
51
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
52
|
+
.toLowerCase()) {
|
|
48
53
|
return c.children.filter((ch) => typeof ch === 'string').join('');
|
|
49
54
|
}
|
|
50
55
|
}
|
|
@@ -66,22 +71,35 @@ export const coreConfig = {
|
|
|
66
71
|
icons: {},
|
|
67
72
|
runes: {
|
|
68
73
|
// ─── Simple runes (block name only, engine adds BEM classes) ───
|
|
69
|
-
Accordion: {
|
|
74
|
+
Accordion: {
|
|
75
|
+
block: 'accordion',
|
|
76
|
+
defaultDensity: 'full',
|
|
77
|
+
sections: accordionSections,
|
|
78
|
+
autoLabel: pageSectionAutoLabel,
|
|
79
|
+
editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' },
|
|
80
|
+
},
|
|
70
81
|
// SPEC-125 Phase 1 — the answer panel is the item's `body` role, so
|
|
71
82
|
// `reading` / `dropcap` land on it. The header decision is recorded in
|
|
72
83
|
// `sectionRoleExceptions` so it travels with the rune.
|
|
73
84
|
AccordionItem: {
|
|
74
|
-
block: 'accordion-item',
|
|
85
|
+
block: 'accordion-item',
|
|
86
|
+
parent: 'Accordion',
|
|
87
|
+
requiresParent: 'Accordion',
|
|
75
88
|
rootAttributes: { 'data-state': 'closed' },
|
|
76
89
|
autoLabel: { name: 'header' },
|
|
77
90
|
sections: accordionItemSections,
|
|
78
91
|
provides: ['prose'],
|
|
79
92
|
sectionRoleExceptions: {
|
|
80
|
-
header:
|
|
93
|
+
header: "The `header` slot is the <summary> disclosure control, not a page-section header. `header` would inherit the chrome-row rhythm (a 3rem margin under every summary); `title` would tighten every summary's line-height while leaving `prominence` inert anyway, since `.rf-accordion-item__header` pins the control's font size on purpose. The parent Accordion already holds `title`.",
|
|
81
94
|
},
|
|
82
95
|
editHints: { header: 'inline', body: 'none' },
|
|
83
96
|
},
|
|
84
|
-
Details: {
|
|
97
|
+
Details: {
|
|
98
|
+
block: 'details',
|
|
99
|
+
defaultElevation: 'flush',
|
|
100
|
+
autoLabel: { summary: 'summary' },
|
|
101
|
+
editHints: { summary: 'inline', body: 'none' },
|
|
102
|
+
},
|
|
85
103
|
Grid: {
|
|
86
104
|
block: 'grid',
|
|
87
105
|
defaultDensity: 'full',
|
|
@@ -110,7 +128,10 @@ export const coreConfig = {
|
|
|
110
128
|
interactive: true,
|
|
111
129
|
defaultDensity: 'compact',
|
|
112
130
|
defaultElevation: 'flat',
|
|
113
|
-
modifiers: {
|
|
131
|
+
modifiers: {
|
|
132
|
+
title: { source: 'meta', noBemClass: true },
|
|
133
|
+
overflow: { source: 'meta', default: 'scroll' },
|
|
134
|
+
},
|
|
114
135
|
// The window chrome (three dots) is pure decoration — drawn in CSS
|
|
115
136
|
// on `.rf-codegroup__topbar`. The only metadata is the optional
|
|
116
137
|
// filename `title`, a bare monospace field in the topbar bar.
|
|
@@ -263,7 +284,11 @@ export const coreConfig = {
|
|
|
263
284
|
separator: { prop: '--separator', template: '"{}"' },
|
|
264
285
|
},
|
|
265
286
|
},
|
|
266
|
-
BreadcrumbItem: {
|
|
287
|
+
BreadcrumbItem: {
|
|
288
|
+
block: 'breadcrumb-item',
|
|
289
|
+
parent: 'Breadcrumb',
|
|
290
|
+
requiresParent: 'Breadcrumb',
|
|
291
|
+
},
|
|
267
292
|
Blog: {
|
|
268
293
|
block: 'blog',
|
|
269
294
|
defaultDensity: 'full',
|
|
@@ -327,7 +352,7 @@ export const coreConfig = {
|
|
|
327
352
|
defaultDensity: 'compact',
|
|
328
353
|
defaultElevation: 'sunken',
|
|
329
354
|
modifiers: { hintType: { source: 'meta', default: 'note' } },
|
|
330
|
-
contextModifiers: {
|
|
355
|
+
contextModifiers: { hero: 'in-hero', feature: 'in-feature' },
|
|
331
356
|
sections: hintSections,
|
|
332
357
|
// SPEC-035 Zone 6 — the hintType value doubles as the visible title
|
|
333
358
|
// (CSS capitalizes it). Declaring it as an enum lets `core.hint.<value>`
|
|
@@ -401,7 +426,12 @@ export const coreConfig = {
|
|
|
401
426
|
modifiers: { layout: { source: 'meta', default: 'side-by-side' } },
|
|
402
427
|
editHints: { panels: 'none' },
|
|
403
428
|
},
|
|
404
|
-
Conversation: {
|
|
429
|
+
Conversation: {
|
|
430
|
+
block: 'conversation',
|
|
431
|
+
defaultDensity: 'compact',
|
|
432
|
+
defaultElevation: 'flush',
|
|
433
|
+
editHints: { messages: 'none' },
|
|
434
|
+
},
|
|
405
435
|
ConversationMessage: {
|
|
406
436
|
block: 'conversation-message',
|
|
407
437
|
parent: 'Conversation',
|
|
@@ -444,7 +474,7 @@ export const coreConfig = {
|
|
|
444
474
|
// Extract slug from span[property="slug"] child → data-slug attribute
|
|
445
475
|
// Keep slug text as visible fallback for SSR; web component replaces with <a> links
|
|
446
476
|
let slug = '';
|
|
447
|
-
const children = node.children.filter(child => {
|
|
477
|
+
const children = node.children.filter((child) => {
|
|
448
478
|
if (isTag(child) && child.name === 'span' && child.attributes['data-field'] === 'slug') {
|
|
449
479
|
slug = child.children.filter((c) => typeof c === 'string').join('');
|
|
450
480
|
return false; // remove slug span from DOM
|
|
@@ -461,10 +491,16 @@ export const coreConfig = {
|
|
|
461
491
|
};
|
|
462
492
|
}
|
|
463
493
|
// Explicit link item: add nav-item__link class to <a> tags for styling
|
|
464
|
-
const styledChildren = children.map(child => {
|
|
494
|
+
const styledChildren = children.map((child) => {
|
|
465
495
|
if (isTag(child) && child.name === 'a') {
|
|
466
496
|
const existing = child.attributes.class || '';
|
|
467
|
-
return {
|
|
497
|
+
return {
|
|
498
|
+
...child,
|
|
499
|
+
attributes: {
|
|
500
|
+
...child.attributes,
|
|
501
|
+
class: ['rf-nav-item__link', existing].filter(Boolean).join(' '),
|
|
502
|
+
},
|
|
503
|
+
};
|
|
468
504
|
}
|
|
469
505
|
return child;
|
|
470
506
|
});
|
|
@@ -474,7 +510,12 @@ export const coreConfig = {
|
|
|
474
510
|
Diff: {
|
|
475
511
|
block: 'diff',
|
|
476
512
|
modifiers: { mode: { source: 'meta', default: 'unified' } },
|
|
477
|
-
editHints: {
|
|
513
|
+
editHints: {
|
|
514
|
+
line: 'none',
|
|
515
|
+
'gutter-num': 'none',
|
|
516
|
+
'gutter-prefix': 'none',
|
|
517
|
+
'line-content': 'none',
|
|
518
|
+
},
|
|
478
519
|
},
|
|
479
520
|
Chart: {
|
|
480
521
|
block: 'chart',
|
|
@@ -550,9 +591,27 @@ export const coreConfig = {
|
|
|
550
591
|
editHints: { viewport: 'none' },
|
|
551
592
|
},
|
|
552
593
|
// ─── Interactive runes (still get BEM classes, components add behavior) ───
|
|
553
|
-
TabGroup: {
|
|
554
|
-
|
|
555
|
-
|
|
594
|
+
TabGroup: {
|
|
595
|
+
block: 'tabs',
|
|
596
|
+
interactive: true,
|
|
597
|
+
defaultDensity: 'full',
|
|
598
|
+
sections: tabGroupSections,
|
|
599
|
+
autoLabel: pageSectionAutoLabel,
|
|
600
|
+
editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' },
|
|
601
|
+
},
|
|
602
|
+
Tab: {
|
|
603
|
+
block: 'tab',
|
|
604
|
+
parent: 'TabGroup',
|
|
605
|
+
requiresParent: 'TabGroup',
|
|
606
|
+
rootAttributes: { 'data-state': 'inactive' },
|
|
607
|
+
editHints: { name: 'inline' },
|
|
608
|
+
},
|
|
609
|
+
TabPanel: {
|
|
610
|
+
block: 'tab-panel',
|
|
611
|
+
parent: 'TabGroup',
|
|
612
|
+
requiresParent: 'TabGroup',
|
|
613
|
+
rootAttributes: { 'data-state': 'inactive' },
|
|
614
|
+
},
|
|
556
615
|
DataTable: {
|
|
557
616
|
block: 'datatable',
|
|
558
617
|
interactive: true,
|
|
@@ -601,7 +660,12 @@ export const coreConfig = {
|
|
|
601
660
|
autoLabel: pageSectionAutoLabel,
|
|
602
661
|
editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline', steps: 'none' },
|
|
603
662
|
},
|
|
604
|
-
RevealStep: {
|
|
663
|
+
RevealStep: {
|
|
664
|
+
block: 'reveal-step',
|
|
665
|
+
parent: 'Reveal',
|
|
666
|
+
rootAttributes: { 'data-state': 'closed' },
|
|
667
|
+
editHints: { body: 'none' },
|
|
668
|
+
},
|
|
605
669
|
Section: {
|
|
606
670
|
block: 'section',
|
|
607
671
|
modifiers: {
|
|
@@ -627,7 +691,13 @@ export const coreConfig = {
|
|
|
627
691
|
},
|
|
628
692
|
editHints: { panels: 'none' },
|
|
629
693
|
},
|
|
630
|
-
JuxtaposePanel: {
|
|
694
|
+
JuxtaposePanel: {
|
|
695
|
+
block: 'juxtapose-panel',
|
|
696
|
+
parent: 'Juxtapose',
|
|
697
|
+
requiresParent: 'Juxtapose',
|
|
698
|
+
rootAttributes: { 'data-state': 'inactive' },
|
|
699
|
+
editHints: { body: 'none' },
|
|
700
|
+
},
|
|
631
701
|
Diagram: {
|
|
632
702
|
block: 'diagram',
|
|
633
703
|
defaultDensity: 'compact',
|
|
@@ -712,7 +782,7 @@ function deriveParentUrl(url) {
|
|
|
712
782
|
function resolveAutoBreadcrumbs(renderable, pageUrl, breadcrumbPaths, pagesByUrl, ctx) {
|
|
713
783
|
if (!Tag.isTag(renderable)) {
|
|
714
784
|
if (Array.isArray(renderable)) {
|
|
715
|
-
const newChildren = renderable.map(c => resolveAutoBreadcrumbs(c, pageUrl, breadcrumbPaths, pagesByUrl, ctx));
|
|
785
|
+
const newChildren = renderable.map((c) => resolveAutoBreadcrumbs(c, pageUrl, breadcrumbPaths, pagesByUrl, ctx));
|
|
716
786
|
// Return original if nothing changed
|
|
717
787
|
if (newChildren.every((c, i) => c === renderable[i]))
|
|
718
788
|
return renderable;
|
|
@@ -752,7 +822,9 @@ function buildAutoBreadcrumb(originalTag, pageUrl, breadcrumbPaths, pagesByUrl,
|
|
|
752
822
|
continue;
|
|
753
823
|
const nameSpan = new Tag('span', { hidden: true }, [ancestorPage.title]);
|
|
754
824
|
const urlLink = new Tag('a', { href: ancestorUrl }, [ancestorPage.title]);
|
|
755
|
-
listItems.push(createComponentRenderable({
|
|
825
|
+
listItems.push(createComponentRenderable({
|
|
826
|
+
rune: 'breadcrumb-item',
|
|
827
|
+
schemaOrgType: 'ListItem',
|
|
756
828
|
tag: 'li',
|
|
757
829
|
properties: { name: nameSpan, url: urlLink },
|
|
758
830
|
children: [nameSpan, urlLink],
|
|
@@ -762,14 +834,18 @@ function buildAutoBreadcrumb(originalTag, pageUrl, breadcrumbPaths, pagesByUrl,
|
|
|
762
834
|
const currentPage = pagesByUrl.get(pageUrl);
|
|
763
835
|
const currentTitle = currentPage?.title ?? pageUrl;
|
|
764
836
|
const currentSpan = new Tag('span', {}, [currentTitle]);
|
|
765
|
-
listItems.push(createComponentRenderable({
|
|
837
|
+
listItems.push(createComponentRenderable({
|
|
838
|
+
rune: 'breadcrumb-item',
|
|
839
|
+
schemaOrgType: 'ListItem',
|
|
766
840
|
tag: 'li',
|
|
767
841
|
properties: { name: currentSpan },
|
|
768
842
|
children: [currentSpan],
|
|
769
843
|
}));
|
|
770
844
|
const newSeparatorMeta = new Tag('meta', { content: separator });
|
|
771
845
|
const itemsList = new Tag('ol', {}, listItems);
|
|
772
|
-
return createComponentRenderable({
|
|
846
|
+
return createComponentRenderable({
|
|
847
|
+
rune: 'breadcrumb',
|
|
848
|
+
schemaOrgType: 'BreadcrumbList',
|
|
773
849
|
tag: 'nav',
|
|
774
850
|
properties: { separator: newSeparatorMeta },
|
|
775
851
|
refs: { items: itemsList },
|
|
@@ -780,7 +856,7 @@ function buildAutoBreadcrumb(originalTag, pageUrl, breadcrumbPaths, pagesByUrl,
|
|
|
780
856
|
function resolveAutoNavs(renderable, pageUrl, pagesByUrl, ctx) {
|
|
781
857
|
if (!Tag.isTag(renderable)) {
|
|
782
858
|
if (Array.isArray(renderable)) {
|
|
783
|
-
const newChildren = renderable.map(c => resolveAutoNavs(c, pageUrl, pagesByUrl, ctx));
|
|
859
|
+
const newChildren = renderable.map((c) => resolveAutoNavs(c, pageUrl, pagesByUrl, ctx));
|
|
784
860
|
if (newChildren.every((c, i) => c === renderable[i]))
|
|
785
861
|
return renderable;
|
|
786
862
|
return newChildren;
|
|
@@ -808,21 +884,23 @@ function resolveAutoNavs(renderable, pageUrl, pagesByUrl, ctx) {
|
|
|
808
884
|
* declared. */
|
|
809
885
|
function buildAutoNav(pageUrl, pagesByUrl, ctx, originalTag) {
|
|
810
886
|
// Find direct children: pages whose parentUrl is this page's URL (excluding self)
|
|
811
|
-
const children = Array.from(pagesByUrl.values()).filter(p => p.parentUrl === pageUrl && p.url !== pageUrl);
|
|
887
|
+
const children = Array.from(pagesByUrl.values()).filter((p) => p.parentUrl === pageUrl && p.url !== pageUrl);
|
|
812
888
|
if (children.length === 0) {
|
|
813
889
|
ctx.warn(`Nav auto: page '${pageUrl}' has no registered child pages`, pageUrl);
|
|
814
890
|
}
|
|
815
|
-
const listItems = children.map(child => {
|
|
891
|
+
const listItems = children.map((child) => {
|
|
816
892
|
const titleSpan = new Tag('span', { 'data-field': 'slug' }, [child.title]);
|
|
817
893
|
const link = new Tag('a', { href: child.url }, [titleSpan]);
|
|
818
|
-
return createComponentRenderable({
|
|
894
|
+
return createComponentRenderable({
|
|
895
|
+
rune: 'nav-item',
|
|
819
896
|
tag: 'li',
|
|
820
897
|
properties: { slug: titleSpan },
|
|
821
898
|
children: [link],
|
|
822
899
|
});
|
|
823
900
|
});
|
|
824
901
|
const itemsList = new Tag('ul', {}, listItems);
|
|
825
|
-
const newNav = createComponentRenderable({
|
|
902
|
+
const newNav = createComponentRenderable({
|
|
903
|
+
rune: 'nav',
|
|
826
904
|
tag: 'nav',
|
|
827
905
|
properties: {
|
|
828
906
|
group: [],
|
|
@@ -832,7 +910,14 @@ function buildAutoNav(pageUrl, pagesByUrl, ctx, originalTag) {
|
|
|
832
910
|
});
|
|
833
911
|
// Preserve contextual attributes from the original nav so layout / auto /
|
|
834
912
|
// source-path survive sentinel replacement.
|
|
835
|
-
const carry = [
|
|
913
|
+
const carry = [
|
|
914
|
+
'layout',
|
|
915
|
+
'data-layout',
|
|
916
|
+
'data-auto',
|
|
917
|
+
'data-source-path',
|
|
918
|
+
'data-collapsible',
|
|
919
|
+
'data-default-open',
|
|
920
|
+
];
|
|
836
921
|
for (const k of carry) {
|
|
837
922
|
const v = originalTag?.attributes?.[k];
|
|
838
923
|
if (v !== undefined) {
|
|
@@ -920,7 +1005,7 @@ function findNavSlugSuggestions(slug, baseDir, pagesByUrl) {
|
|
|
920
1005
|
}
|
|
921
1006
|
sameSlug.sort();
|
|
922
1007
|
typoMatches.sort((a, b) => a.distance - b.distance || a.url.localeCompare(b.url));
|
|
923
|
-
const suggestions = [...sameSlug, ...typoMatches.map(t => t.url)];
|
|
1008
|
+
const suggestions = [...sameSlug, ...typoMatches.map((t) => t.url)];
|
|
924
1009
|
return suggestions.slice(0, 3);
|
|
925
1010
|
}
|
|
926
1011
|
/** SPEC-055 nav-location-relative slug resolution.
|
|
@@ -960,15 +1045,14 @@ function sharedPrefixLength(a, b) {
|
|
|
960
1045
|
* been migrated to use pre-resolved hrefs yet. SPEC-055's
|
|
961
1046
|
* `resolveNavSlug` is the canonical resolver for new code. */
|
|
962
1047
|
function resolveSlugToUrl(slug, pagesByUrl, currentUrl) {
|
|
963
|
-
const candidates = Array.from(pagesByUrl.values()).filter(p => p.url.endsWith('/' + slug) || p.url === '/' + slug);
|
|
1048
|
+
const candidates = Array.from(pagesByUrl.values()).filter((p) => p.url.endsWith('/' + slug) || p.url === '/' + slug);
|
|
964
1049
|
if (candidates.length === 0)
|
|
965
1050
|
return null;
|
|
966
1051
|
if (candidates.length === 1)
|
|
967
1052
|
return candidates[0].url;
|
|
968
1053
|
return candidates
|
|
969
1054
|
.slice()
|
|
970
|
-
.sort((a, b) => sharedPrefixLength(b.url, currentUrl) - sharedPrefixLength(a.url, currentUrl))[0]
|
|
971
|
-
.url;
|
|
1055
|
+
.sort((a, b) => sharedPrefixLength(b.url, currentUrl) - sharedPrefixLength(a.url, currentUrl))[0].url;
|
|
972
1056
|
}
|
|
973
1057
|
/** Read a NavItem's slug from either `data-slug` (post-engine) or a nested
|
|
974
1058
|
* `<span data-field="slug">` (pre-engine, e.g. layout regions). */
|
|
@@ -1084,7 +1168,7 @@ function urlMatchesGroup(currentUrl, itemUrls) {
|
|
|
1084
1168
|
function resolveCollapsibleNavs(renderable, pageUrl, pagesByUrl) {
|
|
1085
1169
|
if (!Tag.isTag(renderable)) {
|
|
1086
1170
|
if (Array.isArray(renderable)) {
|
|
1087
|
-
const newChildren = renderable.map(c => resolveCollapsibleNavs(c, pageUrl, pagesByUrl));
|
|
1171
|
+
const newChildren = renderable.map((c) => resolveCollapsibleNavs(c, pageUrl, pagesByUrl));
|
|
1088
1172
|
if (newChildren.every((c, i) => c === renderable[i]))
|
|
1089
1173
|
return renderable;
|
|
1090
1174
|
return newChildren;
|
|
@@ -1092,11 +1176,13 @@ function resolveCollapsibleNavs(renderable, pageUrl, pagesByUrl) {
|
|
|
1092
1176
|
return renderable;
|
|
1093
1177
|
}
|
|
1094
1178
|
const tag = renderable;
|
|
1095
|
-
if (tag.attributes?.['data-rune'] === 'nav' &&
|
|
1096
|
-
tag.attributes?.['data-collapsible'] === 'true') {
|
|
1179
|
+
if (tag.attributes?.['data-rune'] === 'nav' && tag.attributes?.['data-collapsible'] === 'true') {
|
|
1097
1180
|
const defaultOpenRaw = String(tag.attributes?.['data-default-open'] ?? '');
|
|
1098
1181
|
const defaultOpen = defaultOpenRaw
|
|
1099
|
-
? defaultOpenRaw
|
|
1182
|
+
? defaultOpenRaw
|
|
1183
|
+
.split(',')
|
|
1184
|
+
.map((s) => s.trim())
|
|
1185
|
+
.filter(Boolean)
|
|
1100
1186
|
: [];
|
|
1101
1187
|
const groups = [];
|
|
1102
1188
|
const findGroups = (node) => {
|
|
@@ -1116,7 +1202,7 @@ function resolveCollapsibleNavs(renderable, pageUrl, pagesByUrl) {
|
|
|
1116
1202
|
const inDefault = title && defaultOpen.includes(title);
|
|
1117
1203
|
const itemUrls = collectGroupItemUrls(group, pagesByUrl, pageUrl);
|
|
1118
1204
|
const matches = urlMatchesGroup(pageUrl, itemUrls);
|
|
1119
|
-
group.attributes['data-collapsed'] =
|
|
1205
|
+
group.attributes['data-collapsed'] = inDefault || matches ? 'false' : 'true';
|
|
1120
1206
|
}
|
|
1121
1207
|
const newChildren = (tag.children ?? []).map((c) => resolveCollapsibleNavs(c, pageUrl, pagesByUrl));
|
|
1122
1208
|
if (newChildren.every((c, i) => c === tag.children[i]))
|
|
@@ -1139,7 +1225,9 @@ function enrichNavItemAsCard(item, pageMeta, itemUrl) {
|
|
|
1139
1225
|
}
|
|
1140
1226
|
linkChildren.push(new Tag('span', { 'data-name': 'title', class: 'rf-nav-item__title' }, [titleText]));
|
|
1141
1227
|
if (description) {
|
|
1142
|
-
linkChildren.push(new Tag('span', { 'data-name': 'description', class: 'rf-nav-item__description' }, [
|
|
1228
|
+
linkChildren.push(new Tag('span', { 'data-name': 'description', class: 'rf-nav-item__description' }, [
|
|
1229
|
+
description,
|
|
1230
|
+
]));
|
|
1143
1231
|
}
|
|
1144
1232
|
const link = href
|
|
1145
1233
|
? new Tag('a', { href, class: 'rf-nav-item__link' }, linkChildren)
|
|
@@ -1206,7 +1294,9 @@ function augmentNavItemFromFrontmatter(item, pageMeta) {
|
|
|
1206
1294
|
newLinkChildren.unshift(new Tag('rf-icon', { name: pageMeta.icon, 'data-name': 'icon', class: 'rf-nav-item__icon' }, []));
|
|
1207
1295
|
}
|
|
1208
1296
|
if (pageMeta.description && !hasDescription) {
|
|
1209
|
-
newLinkChildren.push(new Tag('span', { 'data-name': 'description', class: 'rf-nav-item__description' }, [
|
|
1297
|
+
newLinkChildren.push(new Tag('span', { 'data-name': 'description', class: 'rf-nav-item__description' }, [
|
|
1298
|
+
pageMeta.description,
|
|
1299
|
+
]));
|
|
1210
1300
|
}
|
|
1211
1301
|
return { ...t, children: newLinkChildren };
|
|
1212
1302
|
});
|
|
@@ -1215,7 +1305,7 @@ function augmentNavItemFromFrontmatter(item, pageMeta) {
|
|
|
1215
1305
|
function resolveCardsNavs(renderable, pageUrl, pagesByUrl) {
|
|
1216
1306
|
if (!Tag.isTag(renderable)) {
|
|
1217
1307
|
if (Array.isArray(renderable)) {
|
|
1218
|
-
const newChildren = renderable.map(c => resolveCardsNavs(c, pageUrl, pagesByUrl));
|
|
1308
|
+
const newChildren = renderable.map((c) => resolveCardsNavs(c, pageUrl, pagesByUrl));
|
|
1219
1309
|
if (newChildren.every((c, i) => c === renderable[i]))
|
|
1220
1310
|
return renderable;
|
|
1221
1311
|
return newChildren;
|
|
@@ -1291,7 +1381,13 @@ function formatNavResolutionError(slug, sourcePath, attemptedUrl, suggestions) {
|
|
|
1291
1381
|
const head = `Nav item \`${slug}\`${where} cannot be resolved (no page at \`${attemptedUrl}\`).`;
|
|
1292
1382
|
if (suggestions.length === 0)
|
|
1293
1383
|
return head;
|
|
1294
|
-
const lines = [
|
|
1384
|
+
const lines = [
|
|
1385
|
+
'',
|
|
1386
|
+
'Did you mean one of:',
|
|
1387
|
+
...suggestions.map((s) => ` - ${s}`),
|
|
1388
|
+
'',
|
|
1389
|
+
'Use a multi-segment slug (e.g. `section/page`) or an explicit `[Label](/path)` link.',
|
|
1390
|
+
];
|
|
1295
1391
|
return head + '\n' + lines.join('\n');
|
|
1296
1392
|
}
|
|
1297
1393
|
/** Walk a nav subtree, resolve every NavItem's `data-slug` to a real `<a href>`
|
|
@@ -1354,7 +1450,7 @@ function resolveNavItemsInSubtree(navTag, pagesByUrl, ctx, pageUrl) {
|
|
|
1354
1450
|
function resolveNavSlugs(renderable, pagesByUrl, ctx, pageUrl) {
|
|
1355
1451
|
if (!Tag.isTag(renderable)) {
|
|
1356
1452
|
if (Array.isArray(renderable)) {
|
|
1357
|
-
const next = renderable.map(c => resolveNavSlugs(c, pagesByUrl, ctx, pageUrl));
|
|
1453
|
+
const next = renderable.map((c) => resolveNavSlugs(c, pagesByUrl, ctx, pageUrl));
|
|
1358
1454
|
return next.every((c, i) => c === renderable[i]) ? renderable : next;
|
|
1359
1455
|
}
|
|
1360
1456
|
return renderable;
|
|
@@ -1570,10 +1666,10 @@ function getSiblingPages(currentUrl, pagesByUrl, scope) {
|
|
|
1570
1666
|
cursor = parent;
|
|
1571
1667
|
}
|
|
1572
1668
|
const prefix = sectionRoot.endsWith('/') ? sectionRoot : sectionRoot + '/';
|
|
1573
|
-
candidates = pages.filter(p => p.url === sectionRoot || p.url.startsWith(prefix));
|
|
1669
|
+
candidates = pages.filter((p) => p.url === sectionRoot || p.url.startsWith(prefix));
|
|
1574
1670
|
}
|
|
1575
1671
|
else {
|
|
1576
|
-
candidates = pages.filter(p => p.parentUrl === current.parentUrl);
|
|
1672
|
+
candidates = pages.filter((p) => p.parentUrl === current.parentUrl);
|
|
1577
1673
|
}
|
|
1578
1674
|
// Sort by frontmatter order (asc, missing → end), tie-break by URL.
|
|
1579
1675
|
candidates.sort((a, b) => {
|
|
@@ -1583,7 +1679,7 @@ function getSiblingPages(currentUrl, pagesByUrl, scope) {
|
|
|
1583
1679
|
return ao - bo;
|
|
1584
1680
|
return a.url.localeCompare(b.url);
|
|
1585
1681
|
});
|
|
1586
|
-
return candidates.map(p => ({ url: p.url, title: p.title }));
|
|
1682
|
+
return candidates.map((p) => ({ url: p.url, title: p.title }));
|
|
1587
1683
|
}
|
|
1588
1684
|
function pickPrevNextFromSequence(sequence, currentUrl, pagesByUrl) {
|
|
1589
1685
|
const idx = sequence.indexOf(currentUrl);
|
|
@@ -1620,7 +1716,7 @@ function buildPaginationLink(target, direction, label) {
|
|
|
1620
1716
|
function resolveAutoPagination(renderable, pageUrl, pagesByUrl, rootRenderable) {
|
|
1621
1717
|
if (!Tag.isTag(renderable)) {
|
|
1622
1718
|
if (Array.isArray(renderable)) {
|
|
1623
|
-
const newChildren = renderable.map(c => resolveAutoPagination(c, pageUrl, pagesByUrl, rootRenderable));
|
|
1719
|
+
const newChildren = renderable.map((c) => resolveAutoPagination(c, pageUrl, pagesByUrl, rootRenderable));
|
|
1624
1720
|
if (newChildren.every((c, i) => c === renderable[i]))
|
|
1625
1721
|
return renderable;
|
|
1626
1722
|
return newChildren;
|
|
@@ -1638,10 +1734,14 @@ function resolveAutoPagination(renderable, pageUrl, pagesByUrl, rootRenderable)
|
|
|
1638
1734
|
const scope = (scopeValue === 'section' ? 'section' : 'siblings');
|
|
1639
1735
|
const prevLabelMeta = (tag.children ?? []).find((c) => Tag.isTag(c) && c.attributes?.['data-field'] === 'prev-label');
|
|
1640
1736
|
const nextLabelMeta = (tag.children ?? []).find((c) => Tag.isTag(c) && c.attributes?.['data-field'] === 'next-label');
|
|
1641
|
-
const prevLabel = prevLabelMeta
|
|
1642
|
-
|
|
1737
|
+
const prevLabel = prevLabelMeta
|
|
1738
|
+
? String(prevLabelMeta.attributes.content ?? '')
|
|
1739
|
+
: undefined;
|
|
1740
|
+
const nextLabel = nextLabelMeta
|
|
1741
|
+
? String(nextLabelMeta.attributes.content ?? '')
|
|
1742
|
+
: undefined;
|
|
1643
1743
|
// Skip when current page is a section index (has children)
|
|
1644
|
-
const hasChildren = Array.from(pagesByUrl.values()).some(p => p.parentUrl === pageUrl && p.url !== pageUrl);
|
|
1744
|
+
const hasChildren = Array.from(pagesByUrl.values()).some((p) => p.parentUrl === pageUrl && p.url !== pageUrl);
|
|
1645
1745
|
if (hasChildren) {
|
|
1646
1746
|
return { ...tag, children: [] };
|
|
1647
1747
|
}
|
|
@@ -1662,7 +1762,7 @@ function resolveAutoPagination(renderable, pageUrl, pagesByUrl, rootRenderable)
|
|
|
1662
1762
|
else {
|
|
1663
1763
|
// 2. Sibling pages by frontmatter order → directory order
|
|
1664
1764
|
const siblings = getSiblingPages(pageUrl, pagesByUrl, scope);
|
|
1665
|
-
const idx = siblings.findIndex(s => s.url === pageUrl);
|
|
1765
|
+
const idx = siblings.findIndex((s) => s.url === pageUrl);
|
|
1666
1766
|
if (idx !== -1) {
|
|
1667
1767
|
prev = idx > 0 ? siblings[idx - 1] : null;
|
|
1668
1768
|
next = idx < siblings.length - 1 ? siblings[idx + 1] : null;
|
|
@@ -1689,7 +1789,9 @@ function resolveAutoPagination(renderable, pageUrl, pagesByUrl, rootRenderable)
|
|
|
1689
1789
|
const newChildren = (tag.children ?? []).map((c) => {
|
|
1690
1790
|
if (!Tag.isTag(c))
|
|
1691
1791
|
return c;
|
|
1692
|
-
if (c.name === 'a' &&
|
|
1792
|
+
if (c.name === 'a' &&
|
|
1793
|
+
typeof c.attributes?.href === 'string' &&
|
|
1794
|
+
c.attributes.href.startsWith('__slug:')) {
|
|
1693
1795
|
const slug = c.attributes.href.slice('__slug:'.length);
|
|
1694
1796
|
const resolvedUrl = resolveSlugToUrl(slug, pagesByUrl, pageUrl);
|
|
1695
1797
|
if (resolvedUrl) {
|
|
@@ -1698,14 +1800,20 @@ function resolveAutoPagination(renderable, pageUrl, pagesByUrl, rootRenderable)
|
|
|
1698
1800
|
// Replace label text if user didn't override (label child has same text as slug)
|
|
1699
1801
|
const newChildren = (c.children ?? []).map((child) => {
|
|
1700
1802
|
if (Tag.isTag(child) && child.attributes?.['data-name'] === 'label') {
|
|
1701
|
-
const currentLabel = (child.children ?? [])
|
|
1803
|
+
const currentLabel = (child.children ?? [])
|
|
1804
|
+
.filter((x) => typeof x === 'string')
|
|
1805
|
+
.join('');
|
|
1702
1806
|
if (currentLabel === slug) {
|
|
1703
1807
|
return { ...child, children: [newLabel] };
|
|
1704
1808
|
}
|
|
1705
1809
|
}
|
|
1706
1810
|
return child;
|
|
1707
1811
|
});
|
|
1708
|
-
return {
|
|
1812
|
+
return {
|
|
1813
|
+
...c,
|
|
1814
|
+
attributes: { ...c.attributes, href: resolvedUrl },
|
|
1815
|
+
children: newChildren,
|
|
1816
|
+
};
|
|
1709
1817
|
}
|
|
1710
1818
|
}
|
|
1711
1819
|
return c;
|
|
@@ -1724,7 +1832,7 @@ function walkBlogTags(node, fn) {
|
|
|
1724
1832
|
walkBlogTags(child, fn);
|
|
1725
1833
|
}
|
|
1726
1834
|
else if (Array.isArray(node)) {
|
|
1727
|
-
node.forEach(n => walkBlogTags(n, fn));
|
|
1835
|
+
node.forEach((n) => walkBlogTags(n, fn));
|
|
1728
1836
|
}
|
|
1729
1837
|
}
|
|
1730
1838
|
function mapBlogTags(node, fn) {
|
|
@@ -1732,12 +1840,12 @@ function mapBlogTags(node, fn) {
|
|
|
1732
1840
|
const mapped = fn(node);
|
|
1733
1841
|
if (mapped !== node)
|
|
1734
1842
|
return mapped;
|
|
1735
|
-
const newChildren = node.children.map(c => mapBlogTags(c, fn));
|
|
1843
|
+
const newChildren = node.children.map((c) => mapBlogTags(c, fn));
|
|
1736
1844
|
const changed = newChildren.some((c, i) => c !== node.children[i]);
|
|
1737
1845
|
return changed ? new Tag(node.name, node.attributes, newChildren) : node;
|
|
1738
1846
|
}
|
|
1739
1847
|
if (Array.isArray(node))
|
|
1740
|
-
return node.map(n => mapBlogTags(n, fn));
|
|
1848
|
+
return node.map((n) => mapBlogTags(n, fn));
|
|
1741
1849
|
return node;
|
|
1742
1850
|
}
|
|
1743
1851
|
/** Normalise folder path for prefix matching: ensure leading slash and trailing slash */
|
|
@@ -1761,7 +1869,7 @@ function isInFolder(pageUrl, folder) {
|
|
|
1761
1869
|
function parseBlogFilter(filter) {
|
|
1762
1870
|
if (!filter || !filter.trim())
|
|
1763
1871
|
return [];
|
|
1764
|
-
return filter.split(',').map(part => {
|
|
1872
|
+
return filter.split(',').map((part) => {
|
|
1765
1873
|
const colonIdx = part.indexOf(':');
|
|
1766
1874
|
if (colonIdx === -1)
|
|
1767
1875
|
return { field: part.trim(), value: '' };
|
|
@@ -1780,7 +1888,7 @@ function matchesBlogFilter(post, filters) {
|
|
|
1780
1888
|
return false;
|
|
1781
1889
|
}
|
|
1782
1890
|
else if (Array.isArray(fmValue)) {
|
|
1783
|
-
if (!fmValue.some(v => String(v).toLowerCase() === value.toLowerCase()))
|
|
1891
|
+
if (!fmValue.some((v) => String(v).toLowerCase() === value.toLowerCase()))
|
|
1784
1892
|
return false;
|
|
1785
1893
|
}
|
|
1786
1894
|
else {
|
|
@@ -1812,9 +1920,7 @@ function sortBlogPosts(posts, sort) {
|
|
|
1812
1920
|
}
|
|
1813
1921
|
/** Build an <article> Tag for a single blog post entry */
|
|
1814
1922
|
function createBlogPostTag(post) {
|
|
1815
|
-
const titleTag = new Tag('h3', {}, [
|
|
1816
|
-
new Tag('a', { href: post.url }, [post.title]),
|
|
1817
|
-
]);
|
|
1923
|
+
const titleTag = new Tag('h3', {}, [new Tag('a', { href: post.url }, [post.title])]);
|
|
1818
1924
|
const children = [titleTag];
|
|
1819
1925
|
if (post.date) {
|
|
1820
1926
|
children.push(new Tag('time', { datetime: post.date }, [post.date]));
|
|
@@ -1843,7 +1949,7 @@ function resolveBlogPosts(renderable, allPosts, ctx, pageUrl) {
|
|
|
1843
1949
|
}
|
|
1844
1950
|
const normalised = normaliseFolderPath(folder);
|
|
1845
1951
|
const filters = parseBlogFilter(filterStr);
|
|
1846
|
-
let posts = allPosts.filter(post => {
|
|
1952
|
+
let posts = allPosts.filter((post) => {
|
|
1847
1953
|
if (post.draft)
|
|
1848
1954
|
return false;
|
|
1849
1955
|
if (!isInFolder(post.url, normalised))
|
|
@@ -1890,9 +1996,7 @@ navSearchScope) {
|
|
|
1890
1996
|
result = resolveNavSlugs(result, coreData.pagesByUrl, ctx, pageUrl);
|
|
1891
1997
|
result = resolveCollapsibleNavs(result, pageUrl, coreData.pagesByUrl);
|
|
1892
1998
|
result = resolveCardsNavs(result, pageUrl, coreData.pagesByUrl);
|
|
1893
|
-
const searchRoot = navSearchScope && navSearchScope.length > 0
|
|
1894
|
-
? [result, ...navSearchScope]
|
|
1895
|
-
: result;
|
|
1999
|
+
const searchRoot = navSearchScope && navSearchScope.length > 0 ? [result, ...navSearchScope] : result;
|
|
1896
2000
|
result = resolveAutoPagination(result, pageUrl, coreData.pagesByUrl, searchRoot);
|
|
1897
2001
|
// SPEC-055 — mark aria-current / data-active="ancestor" on resolved nav
|
|
1898
2002
|
// links per page. Runs after slug + auto-pagination resolution so the
|
|
@@ -1918,9 +2022,15 @@ navSearchScope) {
|
|
|
1918
2022
|
* any custom field.
|
|
1919
2023
|
*/
|
|
1920
2024
|
const RESERVED_PAGE_FRONTMATTER = new Set([
|
|
1921
|
-
'layout',
|
|
2025
|
+
'layout',
|
|
2026
|
+
'tint',
|
|
2027
|
+
'tint-mode',
|
|
2028
|
+
'tint-lock',
|
|
2029
|
+
'slug',
|
|
2030
|
+
'redirect',
|
|
1922
2031
|
// entity-declaration keys (SPEC-092 Layer 2) — meta, not queryable content
|
|
1923
|
-
'type',
|
|
2032
|
+
'type',
|
|
2033
|
+
'id',
|
|
1924
2034
|
]);
|
|
1925
2035
|
export function createCorePipelineHooks(opts = {}) {
|
|
1926
2036
|
const xrefPatterns = opts.xrefPatterns ?? [];
|
|
@@ -1941,7 +2051,7 @@ export function createCorePipelineHooks(opts = {}) {
|
|
|
1941
2051
|
const includeChanged = preprocessIncludes(ast, page, ctx);
|
|
1942
2052
|
const snippetChanged = preprocessSnippets(ast, page, ctx);
|
|
1943
2053
|
const dataChanged = preprocessData(ast, page, ctx);
|
|
1944
|
-
return
|
|
2054
|
+
return includeChanged || snippetChanged || dataChanged ? ast : undefined;
|
|
1945
2055
|
},
|
|
1946
2056
|
register(pages, registry, ctx) {
|
|
1947
2057
|
for (const page of pages) {
|
|
@@ -1995,7 +2105,7 @@ export function createCorePipelineHooks(opts = {}) {
|
|
|
1995
2105
|
},
|
|
1996
2106
|
aggregate(registry, ctx) {
|
|
1997
2107
|
const pageEntities = registry.getAll('page');
|
|
1998
|
-
const pages = pageEntities.map(e => ({
|
|
2108
|
+
const pages = pageEntities.map((e) => ({
|
|
1999
2109
|
url: e.data.url,
|
|
2000
2110
|
title: e.data.title,
|
|
2001
2111
|
parentUrl: e.data.parentUrl,
|
|
@@ -2006,14 +2116,14 @@ export function createCorePipelineHooks(opts = {}) {
|
|
|
2006
2116
|
const pageTree = buildPageTree(pages);
|
|
2007
2117
|
const breadcrumbPaths = buildBreadcrumbPaths(pages);
|
|
2008
2118
|
// Quick lookup: url → { url, title } for postProcess use
|
|
2009
|
-
const pagesByUrl = new Map(pages.map(p => [p.url, p]));
|
|
2119
|
+
const pagesByUrl = new Map(pages.map((p) => [p.url, p]));
|
|
2010
2120
|
// Build heading index: "url#id" → heading data
|
|
2011
2121
|
const headingIndex = new Map();
|
|
2012
2122
|
for (const h of registry.getAll('heading')) {
|
|
2013
2123
|
headingIndex.set(h.id, h.data);
|
|
2014
2124
|
}
|
|
2015
2125
|
// Blog: collect all pages as potential blog posts
|
|
2016
|
-
const allPosts = pageEntities.map(e => ({
|
|
2126
|
+
const allPosts = pageEntities.map((e) => ({
|
|
2017
2127
|
title: e.data.title || '',
|
|
2018
2128
|
url: e.data.url || e.id,
|
|
2019
2129
|
date: e.data.date || '',
|
|
@@ -2021,7 +2131,18 @@ export function createCorePipelineHooks(opts = {}) {
|
|
|
2021
2131
|
draft: e.data.draft || false,
|
|
2022
2132
|
frontmatter: e.data,
|
|
2023
2133
|
}));
|
|
2024
|
-
return {
|
|
2134
|
+
return {
|
|
2135
|
+
pageTree,
|
|
2136
|
+
breadcrumbPaths,
|
|
2137
|
+
pagesByUrl,
|
|
2138
|
+
headingIndex,
|
|
2139
|
+
allPosts,
|
|
2140
|
+
registry,
|
|
2141
|
+
xrefPatterns,
|
|
2142
|
+
embedConfig,
|
|
2143
|
+
repoUrl,
|
|
2144
|
+
repoBranch,
|
|
2145
|
+
};
|
|
2025
2146
|
},
|
|
2026
2147
|
postProcess(page, aggregated, ctx) {
|
|
2027
2148
|
const coreData = aggregated['__core__'];
|