@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.
Files changed (289) hide show
  1. package/dist/aggregate-resolve.d.ts.map +1 -1
  2. package/dist/aggregate-resolve.js +18 -4
  3. package/dist/aggregate-resolve.js.map +1 -1
  4. package/dist/attributes.d.ts +15 -0
  5. package/dist/attributes.d.ts.map +1 -1
  6. package/dist/attributes.js +22 -7
  7. package/dist/attributes.js.map +1 -1
  8. package/dist/collection-helpers.d.ts.map +1 -1
  9. package/dist/collection-helpers.js +1 -1
  10. package/dist/collection-helpers.js.map +1 -1
  11. package/dist/collection-resolve.d.ts.map +1 -1
  12. package/dist/collection-resolve.js +31 -8
  13. package/dist/collection-resolve.js.map +1 -1
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +195 -74
  16. package/dist/config.js.map +1 -1
  17. package/dist/data-adapters.d.ts.map +1 -1
  18. package/dist/data-adapters.js +28 -11
  19. package/dist/data-adapters.js.map +1 -1
  20. package/dist/data-emit.d.ts.map +1 -1
  21. package/dist/data-emit.js.map +1 -1
  22. package/dist/data-pipeline.d.ts.map +1 -1
  23. package/dist/data-pipeline.js +45 -12
  24. package/dist/data-pipeline.js.map +1 -1
  25. package/dist/data-projection.d.ts.map +1 -1
  26. package/dist/data-projection.js +4 -3
  27. package/dist/data-projection.js.map +1 -1
  28. package/dist/data-resolve.d.ts.map +1 -1
  29. package/dist/data-resolve.js +5 -2
  30. package/dist/data-resolve.js.map +1 -1
  31. package/dist/documents/page.d.ts.map +1 -1
  32. package/dist/documents/page.js.map +1 -1
  33. package/dist/drawer-pipeline.d.ts.map +1 -1
  34. package/dist/drawer-pipeline.js +3 -2
  35. package/dist/drawer-pipeline.js.map +1 -1
  36. package/dist/expand-pipeline.d.ts.map +1 -1
  37. package/dist/expand-pipeline.js +3 -3
  38. package/dist/expand-pipeline.js.map +1 -1
  39. package/dist/fence-escape.d.ts.map +1 -1
  40. package/dist/fence-escape.js +1 -3
  41. package/dist/fence-escape.js.map +1 -1
  42. package/dist/field-match.d.ts.map +1 -1
  43. package/dist/field-match.js.map +1 -1
  44. package/dist/file-ref-resolve.js +6 -4
  45. package/dist/file-ref-resolve.js.map +1 -1
  46. package/dist/fixtures.js +2 -2
  47. package/dist/fixtures.js.map +1 -1
  48. package/dist/functions.d.ts.map +1 -1
  49. package/dist/functions.js +16 -3
  50. package/dist/functions.js.map +1 -1
  51. package/dist/include-pipeline.d.ts.map +1 -1
  52. package/dist/include-pipeline.js +3 -1
  53. package/dist/include-pipeline.js.map +1 -1
  54. package/dist/index.d.ts +92 -37
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +281 -60
  57. package/dist/index.js.map +1 -1
  58. package/dist/interfaces.d.ts.map +1 -1
  59. package/dist/interfaces.js.map +1 -1
  60. package/dist/layouts/grid.d.ts +1 -1
  61. package/dist/layouts/grid.d.ts.map +1 -1
  62. package/dist/layouts/grid.js +4 -6
  63. package/dist/layouts/grid.js.map +1 -1
  64. package/dist/lib/component.d.ts.map +1 -1
  65. package/dist/lib/component.js +7 -7
  66. package/dist/lib/component.js.map +1 -1
  67. package/dist/lib/icon-resolve.d.ts.map +1 -1
  68. package/dist/lib/icon-resolve.js.map +1 -1
  69. package/dist/lib/image-schemes.js +2 -2
  70. package/dist/lib/image-schemes.js.map +1 -1
  71. package/dist/lib/index.d.ts +1 -1
  72. package/dist/lib/index.d.ts.map +1 -1
  73. package/dist/lib/index.js +251 -50
  74. package/dist/lib/index.js.map +1 -1
  75. package/dist/lib/node.d.ts.map +1 -1
  76. package/dist/lib/node.js +3 -2
  77. package/dist/lib/node.js.map +1 -1
  78. package/dist/lib/placeholder.d.ts.map +1 -1
  79. package/dist/lib/placeholder.js +6 -9
  80. package/dist/lib/placeholder.js.map +1 -1
  81. package/dist/lib/read-file.d.ts.map +1 -1
  82. package/dist/lib/read-file.js.map +1 -1
  83. package/dist/lib/renderable.d.ts.map +1 -1
  84. package/dist/lib/renderable.js +5 -5
  85. package/dist/lib/renderable.js.map +1 -1
  86. package/dist/lib/resolver.d.ts.map +1 -1
  87. package/dist/lib/resolver.js +26 -35
  88. package/dist/lib/resolver.js.map +1 -1
  89. package/dist/lib/svg.d.ts.map +1 -1
  90. package/dist/lib/svg.js.map +1 -1
  91. package/dist/nodes.d.ts.map +1 -1
  92. package/dist/nodes.js +9 -11
  93. package/dist/nodes.js.map +1 -1
  94. package/dist/outline-scope.js +1 -3
  95. package/dist/outline-scope.js.map +1 -1
  96. package/dist/plugins.d.ts.map +1 -1
  97. package/dist/plugins.js +13 -10
  98. package/dist/plugins.js.map +1 -1
  99. package/dist/reference.d.ts.map +1 -1
  100. package/dist/reference.js +28 -22
  101. package/dist/reference.js.map +1 -1
  102. package/dist/relationships-resolve.d.ts.map +1 -1
  103. package/dist/relationships-resolve.js +31 -7
  104. package/dist/relationships-resolve.js.map +1 -1
  105. package/dist/rune.d.ts.map +1 -1
  106. package/dist/rune.js.map +1 -1
  107. package/dist/sandbox-sources.js +6 -6
  108. package/dist/sandbox-sources.js.map +1 -1
  109. package/dist/seo.d.ts.map +1 -1
  110. package/dist/seo.js +4 -4
  111. package/dist/seo.js.map +1 -1
  112. package/dist/snippet-pipeline.d.ts.map +1 -1
  113. package/dist/snippet-pipeline.js +1 -1
  114. package/dist/snippet-pipeline.js.map +1 -1
  115. package/dist/tags/accordion.d.ts.map +1 -1
  116. package/dist/tags/accordion.js +23 -9
  117. package/dist/tags/accordion.js.map +1 -1
  118. package/dist/tags/aggregate.d.ts.map +1 -1
  119. package/dist/tags/aggregate.js +65 -10
  120. package/dist/tags/aggregate.js.map +1 -1
  121. package/dist/tags/annotate.d.ts.map +1 -1
  122. package/dist/tags/annotate.js +12 -9
  123. package/dist/tags/annotate.js.map +1 -1
  124. package/dist/tags/badge.d.ts.map +1 -1
  125. package/dist/tags/badge.js.map +1 -1
  126. package/dist/tags/bar.d.ts.map +1 -1
  127. package/dist/tags/bar.js +3 -7
  128. package/dist/tags/bar.js.map +1 -1
  129. package/dist/tags/bg.d.ts.map +1 -1
  130. package/dist/tags/bg.js +60 -12
  131. package/dist/tags/bg.js.map +1 -1
  132. package/dist/tags/blog.d.ts.map +1 -1
  133. package/dist/tags/blog.js +35 -10
  134. package/dist/tags/blog.js.map +1 -1
  135. package/dist/tags/breadcrumb.d.ts.map +1 -1
  136. package/dist/tags/breadcrumb.js +33 -11
  137. package/dist/tags/breadcrumb.js.map +1 -1
  138. package/dist/tags/budget.d.ts.map +1 -1
  139. package/dist/tags/budget.js +54 -16
  140. package/dist/tags/budget.js.map +1 -1
  141. package/dist/tags/card.d.ts.map +1 -1
  142. package/dist/tags/card.js +24 -6
  143. package/dist/tags/card.js.map +1 -1
  144. package/dist/tags/chart.d.ts.map +1 -1
  145. package/dist/tags/chart.js +33 -11
  146. package/dist/tags/chart.js.map +1 -1
  147. package/dist/tags/codegroup.d.ts.map +1 -1
  148. package/dist/tags/codegroup.js +39 -21
  149. package/dist/tags/codegroup.js.map +1 -1
  150. package/dist/tags/collection.d.ts.map +1 -1
  151. package/dist/tags/collection.js +55 -9
  152. package/dist/tags/collection.js.map +1 -1
  153. package/dist/tags/common.d.ts.map +1 -1
  154. package/dist/tags/common.js +34 -9
  155. package/dist/tags/common.js.map +1 -1
  156. package/dist/tags/compare.d.ts.map +1 -1
  157. package/dist/tags/compare.js +26 -14
  158. package/dist/tags/compare.js.map +1 -1
  159. package/dist/tags/conversation.d.ts.map +1 -1
  160. package/dist/tags/conversation.js +19 -17
  161. package/dist/tags/conversation.js.map +1 -1
  162. package/dist/tags/data.d.ts.map +1 -1
  163. package/dist/tags/data.js +67 -13
  164. package/dist/tags/data.js.map +1 -1
  165. package/dist/tags/datatable.d.ts.map +1 -1
  166. package/dist/tags/datatable.js +22 -8
  167. package/dist/tags/datatable.js.map +1 -1
  168. package/dist/tags/deflist.d.ts.map +1 -1
  169. package/dist/tags/deflist.js +5 -11
  170. package/dist/tags/deflist.js.map +1 -1
  171. package/dist/tags/details.d.ts.map +1 -1
  172. package/dist/tags/details.js +8 -5
  173. package/dist/tags/details.js.map +1 -1
  174. package/dist/tags/diagram.d.ts.map +1 -1
  175. package/dist/tags/diagram.js +9 -5
  176. package/dist/tags/diagram.js.map +1 -1
  177. package/dist/tags/diff.d.ts.map +1 -1
  178. package/dist/tags/diff.js +43 -24
  179. package/dist/tags/diff.js.map +1 -1
  180. package/dist/tags/drawer.d.ts.map +1 -1
  181. package/dist/tags/drawer.js +4 -6
  182. package/dist/tags/drawer.js.map +1 -1
  183. package/dist/tags/embed.d.ts.map +1 -1
  184. package/dist/tags/embed.js +10 -5
  185. package/dist/tags/embed.js.map +1 -1
  186. package/dist/tags/expand.d.ts.map +1 -1
  187. package/dist/tags/expand.js.map +1 -1
  188. package/dist/tags/figure.d.ts.map +1 -1
  189. package/dist/tags/figure.js +29 -9
  190. package/dist/tags/figure.js.map +1 -1
  191. package/dist/tags/file-ref.d.ts.map +1 -1
  192. package/dist/tags/file-ref.js.map +1 -1
  193. package/dist/tags/form.d.ts.map +1 -1
  194. package/dist/tags/form.js +52 -25
  195. package/dist/tags/form.js.map +1 -1
  196. package/dist/tags/gallery.d.ts.map +1 -1
  197. package/dist/tags/gallery.js +26 -12
  198. package/dist/tags/gallery.js.map +1 -1
  199. package/dist/tags/grid.d.ts.map +1 -1
  200. package/dist/tags/grid.js +57 -14
  201. package/dist/tags/grid.js.map +1 -1
  202. package/dist/tags/hint.d.ts.map +1 -1
  203. package/dist/tags/hint.js +9 -5
  204. package/dist/tags/hint.js.map +1 -1
  205. package/dist/tags/icon.d.ts.map +1 -1
  206. package/dist/tags/icon.js +5 -1
  207. package/dist/tags/icon.js.map +1 -1
  208. package/dist/tags/include.d.ts.map +1 -1
  209. package/dist/tags/include.js +1 -1
  210. package/dist/tags/include.js.map +1 -1
  211. package/dist/tags/juxtapose.d.ts.map +1 -1
  212. package/dist/tags/juxtapose.js +32 -14
  213. package/dist/tags/juxtapose.js.map +1 -1
  214. package/dist/tags/layout.d.ts.map +1 -1
  215. package/dist/tags/layout.js +7 -4
  216. package/dist/tags/layout.js.map +1 -1
  217. package/dist/tags/mediatext.d.ts.map +1 -1
  218. package/dist/tags/mediatext.js +19 -8
  219. package/dist/tags/mediatext.js.map +1 -1
  220. package/dist/tags/nav.d.ts.map +1 -1
  221. package/dist/tags/nav.js +43 -23
  222. package/dist/tags/nav.js.map +1 -1
  223. package/dist/tags/pagination.d.ts.map +1 -1
  224. package/dist/tags/pagination.js +27 -5
  225. package/dist/tags/pagination.js.map +1 -1
  226. package/dist/tags/progress.d.ts.map +1 -1
  227. package/dist/tags/progress.js +25 -5
  228. package/dist/tags/progress.js.map +1 -1
  229. package/dist/tags/pullquote.d.ts.map +1 -1
  230. package/dist/tags/pullquote.js +16 -9
  231. package/dist/tags/pullquote.js.map +1 -1
  232. package/dist/tags/region.d.ts.map +1 -1
  233. package/dist/tags/region.js +9 -4
  234. package/dist/tags/region.js.map +1 -1
  235. package/dist/tags/relationships.d.ts.map +1 -1
  236. package/dist/tags/relationships.js +55 -9
  237. package/dist/tags/relationships.js.map +1 -1
  238. package/dist/tags/reveal.d.ts.map +1 -1
  239. package/dist/tags/reveal.js +16 -7
  240. package/dist/tags/reveal.js.map +1 -1
  241. package/dist/tags/sandbox.d.ts.map +1 -1
  242. package/dist/tags/sandbox.js +104 -44
  243. package/dist/tags/sandbox.js.map +1 -1
  244. package/dist/tags/section.d.ts.map +1 -1
  245. package/dist/tags/section.js +13 -3
  246. package/dist/tags/section.js.map +1 -1
  247. package/dist/tags/showcase.d.ts.map +1 -1
  248. package/dist/tags/showcase.js +33 -11
  249. package/dist/tags/showcase.js.map +1 -1
  250. package/dist/tags/sidenote.d.ts.map +1 -1
  251. package/dist/tags/sidenote.js +9 -5
  252. package/dist/tags/sidenote.js.map +1 -1
  253. package/dist/tags/snippet.d.ts.map +1 -1
  254. package/dist/tags/snippet.js.map +1 -1
  255. package/dist/tags/tabs.d.ts.map +1 -1
  256. package/dist/tags/tabs.js +16 -9
  257. package/dist/tags/tabs.js.map +1 -1
  258. package/dist/tags/textblock.d.ts.map +1 -1
  259. package/dist/tags/textblock.js +9 -5
  260. package/dist/tags/textblock.js.map +1 -1
  261. package/dist/tags/tint.d.ts +1 -1
  262. package/dist/tags/tint.d.ts.map +1 -1
  263. package/dist/tags/tint.js +14 -2
  264. package/dist/tags/tint.js.map +1 -1
  265. package/dist/tags/toc.d.ts.map +1 -1
  266. package/dist/tags/toc.js +16 -7
  267. package/dist/tags/toc.js.map +1 -1
  268. package/dist/tags/xref.d.ts.map +1 -1
  269. package/dist/tags/xref.js.map +1 -1
  270. package/dist/universal-attributes.d.ts.map +1 -1
  271. package/dist/universal-attributes.js +28 -5
  272. package/dist/universal-attributes.js.map +1 -1
  273. package/dist/util.d.ts.map +1 -1
  274. package/dist/util.js +4 -4
  275. package/dist/util.js.map +1 -1
  276. package/dist/xref-patterns.js +1 -1
  277. package/dist/xref-patterns.js.map +1 -1
  278. package/dist/xref-preview-resolve.js +3 -4
  279. package/dist/xref-preview-resolve.js.map +1 -1
  280. package/dist/xref-resolve.d.ts.map +1 -1
  281. package/dist/xref-resolve.js +4 -4
  282. package/dist/xref-resolve.js.map +1 -1
  283. package/i18n/de.json +67 -67
  284. package/i18n/en.json +67 -67
  285. package/package.json +3 -3
  286. package/dist/tags/error.d.ts +0 -3
  287. package/dist/tags/error.d.ts.map +0 -1
  288. package/dist/tags/error.js +0 -34
  289. 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) && c.attributes?.['data-field'] === prop.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/([A-Z])([A-Z][a-z])/g, '$1-$2').toLowerCase()) {
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: { block: 'accordion', defaultDensity: 'full', sections: accordionSections, autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
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', parent: 'Accordion', requiresParent: 'Accordion',
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: '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`.',
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: { block: 'details', defaultElevation: 'flush', autoLabel: { summary: 'summary' }, editHints: { summary: 'inline', body: 'none' } },
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: { title: { source: 'meta', noBemClass: true }, overflow: { source: 'meta', default: 'scroll' } },
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: { block: 'breadcrumb-item', parent: 'Breadcrumb', requiresParent: 'Breadcrumb' },
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: { 'hero': 'in-hero', 'feature': 'in-feature' },
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: { block: 'conversation', defaultDensity: 'compact', defaultElevation: 'flush', editHints: { messages: 'none' } },
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 { ...child, attributes: { ...child.attributes, class: ['rf-nav-item__link', existing].filter(Boolean).join(' ') } };
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: { line: 'none', 'gutter-num': 'none', 'gutter-prefix': 'none', 'line-content': 'none' },
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: { block: 'tabs', interactive: true, defaultDensity: 'full', sections: tabGroupSections, autoLabel: pageSectionAutoLabel, editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline' } },
554
- Tab: { block: 'tab', parent: 'TabGroup', requiresParent: 'TabGroup', rootAttributes: { 'data-state': 'inactive' }, editHints: { name: 'inline' } },
555
- TabPanel: { block: 'tab-panel', parent: 'TabGroup', requiresParent: 'TabGroup', rootAttributes: { 'data-state': 'inactive' } },
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: { block: 'reveal-step', parent: 'Reveal', rootAttributes: { 'data-state': 'closed' }, editHints: { body: 'none' } },
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: { block: 'juxtapose-panel', parent: 'Juxtapose', requiresParent: 'Juxtapose', rootAttributes: { 'data-state': 'inactive' }, editHints: { body: 'none' } },
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({ rune: 'breadcrumb-item', schemaOrgType: 'ListItem',
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({ rune: 'breadcrumb-item', schemaOrgType: 'ListItem',
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({ rune: 'breadcrumb', schemaOrgType: 'BreadcrumbList',
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({ rune: 'nav-item',
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({ rune: 'nav',
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 = ['layout', 'data-layout', 'data-auto', 'data-source-path', 'data-collapsible', 'data-default-open'];
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.split(',').map(s => s.trim()).filter(Boolean)
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'] = (inDefault || matches) ? 'false' : 'true';
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' }, [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' }, [pageMeta.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 = ['', 'Did you mean one of:', ...suggestions.map(s => ` - ${s}`), '', 'Use a multi-segment slug (e.g. `section/page`) or an explicit `[Label](/path)` link.'];
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 ? String(prevLabelMeta.attributes.content ?? '') : undefined;
1642
- const nextLabel = nextLabelMeta ? String(nextLabelMeta.attributes.content ?? '') : undefined;
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' && typeof c.attributes?.href === 'string' && c.attributes.href.startsWith('__slug:')) {
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 ?? []).filter((x) => typeof x === 'string').join('');
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 { ...c, attributes: { ...c.attributes, href: resolvedUrl }, children: newChildren };
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', 'tint', 'tint-mode', 'tint-lock', 'slug', 'redirect',
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', 'id',
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 (includeChanged || snippetChanged || dataChanged) ? ast : undefined;
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 { pageTree, breadcrumbPaths, pagesByUrl, headingIndex, allPosts, registry, xrefPatterns, embedConfig, repoUrl, repoBranch };
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__'];