@refrakt-md/runes 0.14.4 → 0.15.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 (64) hide show
  1. package/dist/config.d.ts +40 -4
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +154 -88
  4. package/dist/config.js.map +1 -1
  5. package/dist/drawer-pipeline.d.ts +33 -0
  6. package/dist/drawer-pipeline.d.ts.map +1 -0
  7. package/dist/drawer-pipeline.js +206 -0
  8. package/dist/drawer-pipeline.js.map +1 -0
  9. package/dist/expand-pipeline.d.ts +51 -0
  10. package/dist/expand-pipeline.d.ts.map +1 -0
  11. package/dist/expand-pipeline.js +305 -0
  12. package/dist/expand-pipeline.js.map +1 -0
  13. package/dist/index.d.ts +9 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +32 -3
  16. package/dist/index.js.map +1 -1
  17. package/dist/lang-map.d.ts +32 -0
  18. package/dist/lang-map.d.ts.map +1 -0
  19. package/dist/lang-map.js +76 -0
  20. package/dist/lang-map.js.map +1 -0
  21. package/dist/lib/read-file.d.ts +78 -0
  22. package/dist/lib/read-file.d.ts.map +1 -0
  23. package/dist/lib/read-file.js +166 -0
  24. package/dist/lib/read-file.js.map +1 -0
  25. package/dist/nodes.d.ts.map +1 -1
  26. package/dist/nodes.js +12 -1
  27. package/dist/nodes.js.map +1 -1
  28. package/dist/outline-scope.d.ts +29 -0
  29. package/dist/outline-scope.d.ts.map +1 -0
  30. package/dist/outline-scope.js +149 -0
  31. package/dist/outline-scope.js.map +1 -0
  32. package/dist/plugins.d.ts +13 -0
  33. package/dist/plugins.d.ts.map +1 -1
  34. package/dist/plugins.js +65 -1
  35. package/dist/plugins.js.map +1 -1
  36. package/dist/snippet-pipeline.d.ts +42 -0
  37. package/dist/snippet-pipeline.d.ts.map +1 -0
  38. package/dist/snippet-pipeline.js +219 -0
  39. package/dist/snippet-pipeline.js.map +1 -0
  40. package/dist/tags/drawer.d.ts +26 -0
  41. package/dist/tags/drawer.d.ts.map +1 -0
  42. package/dist/tags/drawer.js +134 -0
  43. package/dist/tags/drawer.js.map +1 -0
  44. package/dist/tags/expand.d.ts +22 -0
  45. package/dist/tags/expand.d.ts.map +1 -0
  46. package/dist/tags/expand.js +76 -0
  47. package/dist/tags/expand.js.map +1 -0
  48. package/dist/tags/snippet.d.ts +19 -0
  49. package/dist/tags/snippet.d.ts.map +1 -0
  50. package/dist/tags/snippet.js +49 -0
  51. package/dist/tags/snippet.js.map +1 -0
  52. package/dist/util.d.ts +11 -0
  53. package/dist/util.d.ts.map +1 -1
  54. package/dist/util.js +35 -0
  55. package/dist/util.js.map +1 -1
  56. package/dist/xref-patterns.d.ts +57 -0
  57. package/dist/xref-patterns.d.ts.map +1 -0
  58. package/dist/xref-patterns.js +140 -0
  59. package/dist/xref-patterns.js.map +1 -0
  60. package/dist/xref-resolve.d.ts +22 -5
  61. package/dist/xref-resolve.d.ts.map +1 -1
  62. package/dist/xref-resolve.js +203 -79
  63. package/dist/xref-resolve.js.map +1 -1
  64. package/package.json +3 -3
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ThemeConfig } from '@refrakt-md/transform';
2
2
  import type { PluginPipelineHooks, EntityRegistry, PipelineContext } from '@refrakt-md/types';
3
+ import type { CompiledXrefPattern } from './xref-patterns.js';
3
4
  /** Core theme configuration — universal rune-to-BEM-block mappings shared by all themes.
4
5
  * Icons are empty; themes provide their own icon SVGs via mergeThemeConfig. */
5
6
  export declare const coreConfig: ThemeConfig;
@@ -40,16 +41,51 @@ export declare function resolveCoreSentinels(renderable: unknown, pageUrl: strin
40
41
  }>;
41
42
  allPosts: BlogPostData[];
42
43
  registry: Readonly<EntityRegistry>;
44
+ /** Compiled xref patterns from `refrakt.config.json#/xrefs`. Empty
45
+ * array when no patterns are configured (the resolver's
46
+ * "patterns step" then matches nothing and falls through to
47
+ * unresolved). */
48
+ xrefPatterns?: CompiledXrefPattern[];
43
49
  }, ctx: PipelineContext,
44
50
  /** Extra trees (e.g. layout regions + page content) to scan when looking
45
51
  * for nav sequences during auto-pagination. Required when calling against
46
52
  * a layout region where the sidebar nav lives in a different region. */
47
53
  navSearchScope?: unknown[]): unknown;
54
+ /** Options accepted by {@link createCorePipelineHooks}. */
55
+ export interface CorePipelineHooksOptions {
56
+ /** Compiled xref patterns from `refrakt.config.json#/xrefs`. Threaded
57
+ * through `aggregate` into the postProcess `coreData` shape so the xref
58
+ * resolver can use them as a URL-resolution fallback. */
59
+ xrefPatterns?: CompiledXrefPattern[];
60
+ /** Merged Markdoc transform config (tags + nodes from core + every
61
+ * loaded plugin) plus the project root. Threaded through `aggregate`
62
+ * so the expand postProcess (SPEC-066) can re-transform embedded
63
+ * AST subtrees using the same rune schemas the host page used,
64
+ * and read source files with the same sandbox boundary as snippet. */
65
+ embedConfig?: {
66
+ tags: Record<string, unknown>;
67
+ nodes: Record<string, unknown>;
68
+ projectRoot?: string;
69
+ };
70
+ }
48
71
  /**
49
- * Core cross-page pipeline hooks.
50
- * Run for every site, before any plugin hooks.
51
- * Registers page and heading entities, aggregates the page tree and breadcrumb paths,
52
- * and resolves blog post listings.
72
+ * Build core cross-page pipeline hooks parameterized by build-time options.
73
+ *
74
+ * Most callers (existing adapters, tests) use the {@link corePipelineHooks}
75
+ * default below equivalent to `createCorePipelineHooks()` with no patterns
76
+ * configured. The content-loader bootstrap passes compiled
77
+ * {@link CompiledXrefPattern}s when `refrakt.config.json#/xrefs` is set.
78
+ */
79
+ export declare function createCorePipelineHooks(opts?: CorePipelineHooksOptions): PluginPipelineHooks;
80
+ /**
81
+ * Core cross-page pipeline hooks (no xref patterns configured).
82
+ *
83
+ * Equivalent to `createCorePipelineHooks()`. The content loader bootstrap
84
+ * uses {@link createCorePipelineHooks} directly when
85
+ * `refrakt.config.json#/xrefs` is configured so the resolver can use the
86
+ * compiled patterns as a URL-resolution fallback. Run for every site,
87
+ * before any plugin hooks. Registers page and heading entities, aggregates
88
+ * the page tree and breadcrumb paths, and resolves blog post listings.
53
89
  */
54
90
  export declare const corePipelineHooks: PluginPipelineHooks;
55
91
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAkB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAiF/H;gFACgF;AAChF,eAAO,MAAM,UAAU,EAAE,WAitBxB,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,UAAU,aAAa,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AA0vCD,UAAU,YAAY;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAiLD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IACT,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChI,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;CACnC,EACD,GAAG,EAAE,eAAe;AACpB;;yEAEyE;AACzE,cAAc,CAAC,EAAE,OAAO,EAAE,GACxB,OAAO,CAqBT;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,mBAgK/B,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAkB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAS/H,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA6E9D;gFACgF;AAChF,eAAO,MAAM,UAAU,EAAE,WAwuBxB,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,UAAU,aAAa,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AA0vCD,UAAU,YAAY;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAiLD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IACT,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChI,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACnC;;;uBAGmB;IACnB,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACrC,EACD,GAAG,EAAE,eAAe;AACpB;;yEAEyE;AACzE,cAAc,CAAC,EAAE,OAAO,EAAE,GACxB,OAAO,CAqBT;AAED,2DAA2D;AAC3D,MAAM,WAAW,wBAAwB;IACxC;;8DAE0D;IAC1D,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC;;;;2EAIuE;IACvE,WAAW,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACF;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,wBAA6B,GAAG,mBAAmB,CAoNhG;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,mBAA+C,CAAC"}
package/dist/config.js CHANGED
@@ -6,6 +6,10 @@ import { BREADCRUMB_AUTO_SENTINEL } from './tags/breadcrumb.js';
6
6
  import { NAV_AUTO_SENTINEL, NAV_COLLAPSED_AUTO } from './tags/nav.js';
7
7
  import { PAGINATION_AUTO_SENTINEL } from './tags/pagination.js';
8
8
  import { resolveXrefs } from './xref-resolve.js';
9
+ import { preprocessSnippets, wrapStandaloneSnippets } from './snippet-pipeline.js';
10
+ import { registerDrawers, resolveAutoDrawerTitleLevels } from './drawer-pipeline.js';
11
+ import { applyOutlineScopeWalkers } from './outline-scope.js';
12
+ import { resolveExpands } from './expand-pipeline.js';
9
13
  // ─── Budget postTransform helpers ───
10
14
  const BUDGET_CURRENCY_SYMBOLS = {
11
15
  USD: '$', EUR: '€', GBP: '£', JPY: '¥', CNY: '¥',
@@ -134,6 +138,18 @@ export const coreConfig = {
134
138
  },
135
139
  PageSection: { block: 'page-section' },
136
140
  TableOfContents: { block: 'toc' },
141
+ /* Snippet doesn't have a normal schema transform — its preprocess
142
+ * hook replaces the tag with a `fence` node, and the standalone
143
+ * wrap step adds `<figure class="rf-snippet">` post-transform.
144
+ * The engine never sees a `Snippet` tag, but we still need an
145
+ * entry in the theme config so `computeUsedCssBlocks` includes
146
+ * `snippet.css` in CSS tree-shaking when the figure is rendered. */
147
+ Snippet: { block: 'snippet' },
148
+ /* Expand emits a placeholder during transform; the postProcess hook
149
+ * substitutes the entity content wrapped in `<section
150
+ * class="rf-expand" data-rune="expand">`. Engine config provides the
151
+ * block name for CSS tree-shaking. */
152
+ Expand: { block: 'expand' },
137
153
  Embed: {
138
154
  block: 'embed',
139
155
  defaultDensity: 'compact',
@@ -307,6 +323,17 @@ export const coreConfig = {
307
323
  },
308
324
  },
309
325
  },
326
+ Drawer: {
327
+ block: 'drawer',
328
+ defaultDensity: 'compact',
329
+ modifiers: {
330
+ side: { source: 'meta', default: 'right' },
331
+ size: { source: 'meta', default: 'md' },
332
+ shortcut: { source: 'meta', noBemClass: true },
333
+ },
334
+ sections: { header: 'header', body: 'body' },
335
+ editHints: { title: 'inline', body: 'none', close: 'none' },
336
+ },
310
337
  Figure: {
311
338
  block: 'figure',
312
339
  defaultDensity: 'compact',
@@ -2006,101 +2033,140 @@ navSearchScope) {
2006
2033
  // item href set is final.
2007
2034
  result = applyNavActiveState(result, pageUrl);
2008
2035
  result = resolveBlogPosts(result, coreData.allPosts, ctx, pageUrl);
2009
- result = resolveXrefs(result, pageUrl, coreData.registry, ctx);
2036
+ result = resolveXrefs(result, pageUrl, coreData.registry, coreData.xrefPatterns ?? [], ctx);
2010
2037
  return result;
2011
2038
  }
2012
2039
  /**
2013
- * Core cross-page pipeline hooks.
2014
- * Run for every site, before any plugin hooks.
2015
- * Registers page and heading entities, aggregates the page tree and breadcrumb paths,
2016
- * and resolves blog post listings.
2040
+ * Build core cross-page pipeline hooks parameterized by build-time options.
2041
+ *
2042
+ * Most callers (existing adapters, tests) use the {@link corePipelineHooks}
2043
+ * default below equivalent to `createCorePipelineHooks()` with no patterns
2044
+ * configured. The content-loader bootstrap passes compiled
2045
+ * {@link CompiledXrefPattern}s when `refrakt.config.json#/xrefs` is set.
2017
2046
  */
2018
- export const corePipelineHooks = {
2019
- register(pages, registry, ctx) {
2020
- for (const page of pages) {
2021
- const parentUrl = deriveParentUrl(page.url);
2022
- const existingPage = registry.getById('page', page.url);
2023
- if (existingPage && existingPage.sourceUrl !== page.url) {
2024
- ctx.warn(`Page '${page.url}' already registered from '${existingPage.sourceUrl}'`, page.url);
2025
- }
2026
- registry.register({
2027
- type: 'page',
2028
- id: page.url,
2029
- sourceUrl: page.url,
2030
- data: {
2031
- title: page.title,
2032
- url: page.url,
2033
- parentUrl,
2034
- draft: page.frontmatter.draft ?? false,
2035
- description: page.frontmatter.description,
2036
- date: page.frontmatter.date,
2037
- order: page.frontmatter.order,
2038
- icon: page.frontmatter.icon,
2039
- },
2040
- });
2041
- for (const h of page.headings) {
2042
- const headingId = `${page.url}#${h.id}`;
2043
- const existingHeading = registry.getById('heading', headingId);
2044
- if (existingHeading && existingHeading.sourceUrl !== page.url) {
2045
- ctx.warn(`Heading '${headingId}' already registered from '${existingHeading.sourceUrl}'`, page.url);
2047
+ export function createCorePipelineHooks(opts = {}) {
2048
+ const xrefPatterns = opts.xrefPatterns ?? [];
2049
+ const embedConfig = opts.embedConfig;
2050
+ return {
2051
+ preprocess: preprocessSnippets,
2052
+ register(pages, registry, ctx) {
2053
+ for (const page of pages) {
2054
+ const parentUrl = deriveParentUrl(page.url);
2055
+ const existingPage = registry.getById('page', page.url);
2056
+ if (existingPage && existingPage.sourceUrl !== page.url) {
2057
+ ctx.warn(`Page '${page.url}' already registered from '${existingPage.sourceUrl}'`, page.url);
2046
2058
  }
2047
2059
  registry.register({
2048
- type: 'heading',
2049
- id: headingId,
2060
+ type: 'page',
2061
+ id: page.url,
2050
2062
  sourceUrl: page.url,
2051
- data: { level: h.level, text: h.text, headingId: h.id, url: page.url },
2063
+ data: {
2064
+ title: page.title,
2065
+ url: page.url,
2066
+ parentUrl,
2067
+ draft: page.frontmatter.draft ?? false,
2068
+ description: page.frontmatter.description,
2069
+ date: page.frontmatter.date,
2070
+ order: page.frontmatter.order,
2071
+ icon: page.frontmatter.icon,
2072
+ },
2052
2073
  });
2074
+ for (const h of page.headings) {
2075
+ const headingId = `${page.url}#${h.id}`;
2076
+ const existingHeading = registry.getById('heading', headingId);
2077
+ if (existingHeading && existingHeading.sourceUrl !== page.url) {
2078
+ ctx.warn(`Heading '${headingId}' already registered from '${existingHeading.sourceUrl}'`, page.url);
2079
+ }
2080
+ registry.register({
2081
+ type: 'heading',
2082
+ id: headingId,
2083
+ sourceUrl: page.url,
2084
+ data: { level: h.level, text: h.text, headingId: h.id, url: page.url },
2085
+ });
2086
+ }
2053
2087
  }
2054
- }
2055
- },
2056
- aggregate(registry, ctx) {
2057
- const pageEntities = registry.getAll('page');
2058
- const pages = pageEntities.map(e => ({
2059
- url: e.data.url,
2060
- title: e.data.title,
2061
- parentUrl: e.data.parentUrl,
2062
- description: e.data.description,
2063
- icon: e.data.icon,
2064
- order: e.data.order,
2065
- }));
2066
- const pageTree = buildPageTree(pages);
2067
- const breadcrumbPaths = buildBreadcrumbPaths(pages);
2068
- // Quick lookup: url → { url, title } for postProcess use
2069
- const pagesByUrl = new Map(pages.map(p => [p.url, p]));
2070
- // Build heading index: "url#id"heading data
2071
- const headingIndex = new Map();
2072
- for (const h of registry.getAll('heading')) {
2073
- headingIndex.set(h.id, h.data);
2074
- }
2075
- // Blog: collect all pages as potential blog posts
2076
- const allPosts = pageEntities.map(e => ({
2077
- title: e.data.title || '',
2078
- url: e.data.url || e.id,
2079
- date: e.data.date || '',
2080
- description: e.data.description || '',
2081
- draft: e.data.draft || false,
2082
- frontmatter: e.data,
2083
- }));
2084
- return { pageTree, breadcrumbPaths, pagesByUrl, headingIndex, allPosts, registry };
2085
- },
2086
- postProcess(page, aggregated, ctx) {
2087
- const coreData = aggregated['__core__'];
2088
- if (!coreData)
2089
- return page;
2090
- let renderable = resolveAutoBreadcrumbs(page.renderable, page.url, coreData.breadcrumbPaths, coreData.pagesByUrl, ctx);
2091
- renderable = resolveAutoNavs(renderable, page.url, coreData.pagesByUrl, ctx);
2092
- // SPEC-055 build-time slug resolution (see note in resolveCoreSentinels).
2093
- renderable = resolveNavSlugs(renderable, coreData.pagesByUrl, ctx, page.url);
2094
- renderable = resolveCollapsibleNavs(renderable, page.url, coreData.pagesByUrl);
2095
- renderable = resolveCardsNavs(renderable, page.url, coreData.pagesByUrl);
2096
- renderable = resolveAutoPagination(renderable, page.url, coreData.pagesByUrl, renderable);
2097
- // SPEC-055 build-time active state.
2098
- renderable = applyNavActiveState(renderable, page.url);
2099
- renderable = resolveBlogPosts(renderable, coreData.allPosts, ctx, page.url);
2100
- renderable = resolveXrefs(renderable, page.url, coreData.registry, ctx);
2101
- if (renderable === page.renderable)
2102
- return page;
2103
- return { ...page, renderable };
2104
- },
2105
- };
2088
+ // SPEC-060 — register every drawer rune as a page-scoped entity so
2089
+ // `{% ref "drawer-id" /%}` resolves to the drawer's address.
2090
+ registerDrawers(pages, registry, ctx);
2091
+ },
2092
+ aggregate(registry, ctx) {
2093
+ const pageEntities = registry.getAll('page');
2094
+ const pages = pageEntities.map(e => ({
2095
+ url: e.data.url,
2096
+ title: e.data.title,
2097
+ parentUrl: e.data.parentUrl,
2098
+ description: e.data.description,
2099
+ icon: e.data.icon,
2100
+ order: e.data.order,
2101
+ }));
2102
+ const pageTree = buildPageTree(pages);
2103
+ const breadcrumbPaths = buildBreadcrumbPaths(pages);
2104
+ // Quick lookup: url → { url, title } for postProcess use
2105
+ const pagesByUrl = new Map(pages.map(p => [p.url, p]));
2106
+ // Build heading index: "url#id" → heading data
2107
+ const headingIndex = new Map();
2108
+ for (const h of registry.getAll('heading')) {
2109
+ headingIndex.set(h.id, h.data);
2110
+ }
2111
+ // Blog: collect all pages as potential blog posts
2112
+ const allPosts = pageEntities.map(e => ({
2113
+ title: e.data.title || '',
2114
+ url: e.data.url || e.id,
2115
+ date: e.data.date || '',
2116
+ description: e.data.description || '',
2117
+ draft: e.data.draft || false,
2118
+ frontmatter: e.data,
2119
+ }));
2120
+ return { pageTree, breadcrumbPaths, pagesByUrl, headingIndex, allPosts, registry, xrefPatterns, embedConfig };
2121
+ },
2122
+ postProcess(page, aggregated, ctx) {
2123
+ const coreData = aggregated['__core__'];
2124
+ if (!coreData)
2125
+ return page;
2126
+ let renderable = resolveAutoBreadcrumbs(page.renderable, page.url, coreData.breadcrumbPaths, coreData.pagesByUrl, ctx);
2127
+ renderable = resolveAutoNavs(renderable, page.url, coreData.pagesByUrl, ctx);
2128
+ // SPEC-055 build-time slug resolution (see note in resolveCoreSentinels).
2129
+ renderable = resolveNavSlugs(renderable, coreData.pagesByUrl, ctx, page.url);
2130
+ renderable = resolveCollapsibleNavs(renderable, page.url, coreData.pagesByUrl);
2131
+ renderable = resolveCardsNavs(renderable, page.url, coreData.pagesByUrl);
2132
+ renderable = resolveAutoPagination(renderable, page.url, coreData.pagesByUrl, renderable);
2133
+ // SPEC-055 build-time active state.
2134
+ renderable = applyNavActiveState(renderable, page.url);
2135
+ renderable = resolveBlogPosts(renderable, coreData.allPosts, ctx, page.url);
2136
+ // SPEC-060 — rewrite `data-drawer-title-auto` placeholders to the
2137
+ // appropriate `h{n}` based on outline depth. Runs before xref
2138
+ // resolution so the rewritten title doesn't carry the sentinel
2139
+ // attribute into the rendered HTML.
2140
+ renderable = resolveAutoDrawerTitleLevels(renderable);
2141
+ // SPEC-066 expand resolution — substitutes embedded entity content
2142
+ // before xref runs so refs inside substituted content are resolved
2143
+ // by the same pass as host-page refs.
2144
+ renderable = resolveExpands(renderable, page.url, coreData.registry, coreData.xrefPatterns ?? [], coreData.embedConfig, ctx);
2145
+ renderable = resolveXrefs(renderable, page.url, coreData.registry, coreData.xrefPatterns ?? [], ctx);
2146
+ // SPEC-062 standalone snippet wrap: turn `<pre data-snippet-source>`
2147
+ // into `<figure class="rf-snippet">` when not inside a fence-consuming
2148
+ // container (codegroup, diff). The wrap is a no-op when the page
2149
+ // has no snippet-derived fences.
2150
+ const wrappedPage = wrapStandaloneSnippets(renderable === page.renderable ? page : { ...page, renderable }, aggregated, ctx);
2151
+ // SPEC-066 outline-scope walkers: prefix heading IDs and drop TOC
2152
+ // items inside any `data-outline-scope` subtree. Generic — any rune
2153
+ // can set the attribute and get the behaviour. Runs last so it can
2154
+ // see the final tree (including expand-substituted content once
2155
+ // that lands in v0.15.0).
2156
+ applyOutlineScopeWalkers(wrappedPage.renderable);
2157
+ return wrappedPage;
2158
+ },
2159
+ };
2160
+ }
2161
+ /**
2162
+ * Core cross-page pipeline hooks (no xref patterns configured).
2163
+ *
2164
+ * Equivalent to `createCorePipelineHooks()`. The content loader bootstrap
2165
+ * uses {@link createCorePipelineHooks} directly when
2166
+ * `refrakt.config.json#/xrefs` is configured so the resolver can use the
2167
+ * compiled patterns as a URL-resolution fallback. Run for every site,
2168
+ * before any plugin hooks. Registers page and heading entities, aggregates
2169
+ * the page tree and breadcrumb paths, and resolves blog post listings.
2170
+ */
2171
+ export const corePipelineHooks = createCorePipelineHooks();
2106
2172
  //# sourceMappingURL=config.js.map