@takazudo/zudo-doc 1.3.0 → 2.0.1

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 (52) hide show
  1. package/dist/chrome/derive.d.ts +68 -0
  2. package/dist/chrome/derive.js +231 -0
  3. package/dist/chrome/index.d.ts +37 -0
  4. package/dist/chrome/index.js +43 -0
  5. package/dist/doc-body-end/index.d.ts +9 -11
  6. package/dist/doc-body-end/index.js +4 -2
  7. package/dist/doc-content-header/index.d.ts +10 -2
  8. package/dist/doc-content-header/index.js +8 -8
  9. package/dist/doc-history-area/index.d.ts +10 -25
  10. package/dist/doc-history-area/index.js +14 -10
  11. package/dist/doc-metainfo-area/index.d.ts +9 -15
  12. package/dist/doc-metainfo-area/index.js +6 -2
  13. package/dist/doc-page-renderer/index.d.ts +11 -2
  14. package/dist/doc-page-renderer/index.js +22 -15
  15. package/dist/doc-page-shell/index.d.ts +11 -3
  16. package/dist/doc-page-shell/index.js +21 -14
  17. package/dist/doc-pager/index.d.ts +6 -7
  18. package/dist/doc-pager/index.js +2 -2
  19. package/dist/doc-route-entries/index.d.ts +22 -46
  20. package/dist/doc-route-entries/index.js +15 -10
  21. package/dist/doc-tags-area/index.d.ts +9 -19
  22. package/dist/doc-tags-area/index.js +12 -2
  23. package/dist/factory-context/index.d.ts +163 -1
  24. package/dist/footer-with-defaults/index.d.ts +12 -13
  25. package/dist/footer-with-defaults/index.js +8 -10
  26. package/dist/head/types.d.ts +39 -0
  27. package/dist/head-with-defaults/index.d.ts +12 -16
  28. package/dist/head-with-defaults/index.js +93 -10
  29. package/dist/header-with-defaults/index.d.ts +10 -31
  30. package/dist/header-with-defaults/index.js +15 -18
  31. package/dist/nav-source-docs/index.d.ts +20 -54
  32. package/dist/nav-source-docs/index.js +9 -10
  33. package/dist/route-context/index.d.ts +24 -0
  34. package/dist/route-context/index.js +147 -0
  35. package/dist/route-enumerators/index.d.ts +25 -74
  36. package/dist/route-enumerators/index.js +17 -18
  37. package/dist/routes/_chrome.d.ts +6 -25
  38. package/dist/routes/_chrome.js +14 -387
  39. package/dist/routes/_context.d.ts +10 -43
  40. package/dist/routes/_context.js +29 -157
  41. package/dist/safelist.css +1 -1
  42. package/dist/settings.d.ts +54 -0
  43. package/dist/sidebar-with-defaults/index.d.ts +8 -15
  44. package/dist/sidebar-with-defaults/index.js +6 -10
  45. package/dist/tag-pages/index.d.ts +12 -3
  46. package/dist/tag-pages/index.js +24 -19
  47. package/dist/versions-page/index.d.ts +10 -3
  48. package/dist/versions-page/index.js +18 -14
  49. package/eject/doc-pager/index.tsx +8 -10
  50. package/package.json +13 -5
  51. package/routes-src/_chrome.tsx +31 -552
  52. package/routes-src/_context.ts +37 -269
@@ -3,6 +3,8 @@
3
3
  import type { JSX } from "preact";
4
4
  import type { HeadProps } from "../head/types.js";
5
5
  import type { ColorSchemeProviderColorMode } from "../theme/color-scheme-provider.js";
6
+ import type { ChromeContext } from "../factory-context/index.js";
7
+ import type { Settings } from "../settings.js";
6
8
  export interface HeadWithDefaultsProps {
7
9
  /** Page title forwarded to og:title. Required. */
8
10
  title: string;
@@ -14,7 +16,8 @@ export interface HeadWithDefaultsProps {
14
16
  */
15
17
  canonical?: string;
16
18
  }
17
- /** Settings subset read by {@link createHeadWithDefaults}. */
19
+ /** Settings subset read by {@link createHeadWithDefaults}. Retained for the
20
+ * `HeadProps`/`ColorSchemeProviderColorMode` type references it documents. */
18
21
  export interface HeadWithDefaultsSettings {
19
22
  metaTags: {
20
23
  description?: boolean | null;
@@ -29,21 +32,14 @@ export interface HeadWithDefaultsSettings {
29
32
  colorMode?: ColorSchemeProviderColorMode | null | false;
30
33
  sidebarResizer?: boolean;
31
34
  }
32
- /** Factory dependencies injected by the host stub. */
33
- export interface HeadWithDefaultsDeps {
34
- settings: HeadWithDefaultsSettings;
35
- composeMetaTitle: (title: string) => string;
36
- withBase: (path: string) => string;
37
- absoluteUrl: (pageUrl: string) => string | undefined;
38
- generateCssCustomProperties: () => string;
39
- generateLightDarkCssProperties: () => string;
40
- }
41
35
  /**
42
- * Create a `HeadWithDefaults` component bound to the host's settings and
43
- * URL helpers.
36
+ * Create a `HeadWithDefaults` component from the unified {@link ChromeContext}
37
+ * (epic Collapse Wiring Shells #2420, FACTORIES #2424 — breaking signature).
44
38
  *
45
- * The host stub calls this once with its concrete dependencies and re-exports
46
- * the result, mirroring the shape of `createComposeMetaTitle` (S1b) and
47
- * `createBuildFrontmatterPreviewEntries`.
39
+ * Derives its old `{ settings, composeMetaTitle, withBase, absoluteUrl,
40
+ * generate* }` bag from the context: `settings`/`withBase`/`absoluteUrl` are
41
+ * read directly, while `composeMetaTitle` and the color-scheme CSS generators
42
+ * are reconstructed from the context's `siteName` + `colorSchemes` payload via
43
+ * the shared `chrome/derive` helpers (identical to the pre-collapse wiring).
48
44
  */
49
- export declare function createHeadWithDefaults(deps: HeadWithDefaultsDeps): (props: HeadWithDefaultsProps) => JSX.Element;
45
+ export declare function createHeadWithDefaults<S extends Settings = Settings>(ctx: ChromeContext<S>): (props: HeadWithDefaultsProps) => JSX.Element;
@@ -2,15 +2,13 @@ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
2
  import { OgTags, TwitterCard } from "../head/index.js";
3
3
  import { SIDEBAR_RESIZER_RESTORE_SCRIPT } from "../sidebar-resizer/index.js";
4
4
  import ColorSchemeProvider from "../theme/color-scheme-provider.js";
5
- function createHeadWithDefaults(deps) {
6
- const {
7
- settings,
8
- composeMetaTitle,
9
- withBase,
10
- absoluteUrl,
11
- generateCssCustomProperties,
12
- generateLightDarkCssProperties
13
- } = deps;
5
+ import { deriveComposeMetaTitle, deriveColorSchemeGenerators } from "../chrome/derive.js";
6
+ function createHeadWithDefaults(ctx) {
7
+ const settings = ctx.settings;
8
+ const composeMetaTitle = deriveComposeMetaTitle(ctx);
9
+ const withBase = ctx.withBase;
10
+ const absoluteUrl = ctx.absoluteUrl;
11
+ const { generateCssCustomProperties, generateLightDarkCssProperties } = deriveColorSchemeGenerators(ctx);
14
12
  function HeadWithDefaults({
15
13
  title,
16
14
  description,
@@ -52,7 +50,92 @@ function createHeadWithDefaults(deps) {
52
50
  /* @__PURE__ */ jsx("link", { rel: "icon", href: withBase("/favicon.ico"), sizes: "any" }),
53
51
  /* @__PURE__ */ jsx("link", { rel: "icon", type: "image/png", sizes: "32x32", href: withBase("/favicon-32x32.png") }),
54
52
  /* @__PURE__ */ jsx("link", { rel: "icon", type: "image/png", sizes: "16x16", href: withBase("/favicon-16x16.png") }),
55
- canonical !== void 0 && /* @__PURE__ */ jsx("link", { rel: "canonical", href: canonical })
53
+ canonical !== void 0 && /* @__PURE__ */ jsx("link", { rel: "canonical", href: canonical }),
54
+ ctx.settings.head && /* @__PURE__ */ jsxs(Fragment, { children: [
55
+ ctx.settings.head.preconnect?.map((p, i) => /* @__PURE__ */ jsx(
56
+ "link",
57
+ {
58
+ rel: "preconnect",
59
+ href: p.href,
60
+ ...p.crossorigin ? { crossorigin: p.crossorigin } : {}
61
+ },
62
+ i
63
+ )),
64
+ ctx.settings.head.preload?.map((p, i) => /* @__PURE__ */ jsx(
65
+ "link",
66
+ {
67
+ rel: "preload",
68
+ as: p.as,
69
+ href: p.href,
70
+ ...p.type ? { type: p.type } : {},
71
+ ...p.crossorigin ? { crossorigin: p.crossorigin } : {}
72
+ },
73
+ i
74
+ )),
75
+ ctx.settings.head.stylesheets?.map(
76
+ (s, i) => s.async ? (
77
+ // Non-render-blocking async stylesheet:
78
+ // <link rel="stylesheet" href media="print" onload="this.media='all'">
79
+ // <noscript><link rel="stylesheet" href></noscript>
80
+ //
81
+ // SSR note: preact-render-to-string emits string-valued on* props as
82
+ // literal HTML attributes (only function-valued event handlers are
83
+ // stripped). We use `as any` to bypass Preact's JSX types, which
84
+ // expect a function for onload. The new unit test pins the exact
85
+ // emitted string to guard this contract.
86
+ /* @__PURE__ */ jsxs(Fragment, { children: [
87
+ /* @__PURE__ */ jsx(
88
+ "link",
89
+ {
90
+ rel: "stylesheet",
91
+ href: s.href,
92
+ ...s.crossorigin ? { crossorigin: s.crossorigin } : {},
93
+ media: "print",
94
+ ...{ onload: `this.media='${s.media ?? "all"}'` }
95
+ },
96
+ `${i}-link`
97
+ ),
98
+ /* @__PURE__ */ jsx(
99
+ "noscript",
100
+ {
101
+ dangerouslySetInnerHTML: {
102
+ __html: `<link rel="stylesheet" href="${s.href.replace(/"/g, "&quot;")}"${s.media ? ` media="${s.media}"` : ""}${s.crossorigin ? ` crossorigin="${s.crossorigin}"` : ""}>`
103
+ }
104
+ },
105
+ `${i}-noscript`
106
+ )
107
+ ] })
108
+ ) : /* @__PURE__ */ jsx(
109
+ "link",
110
+ {
111
+ rel: "stylesheet",
112
+ href: s.href,
113
+ ...s.media ? { media: s.media } : {},
114
+ ...s.crossorigin ? { crossorigin: s.crossorigin } : {}
115
+ },
116
+ i
117
+ )
118
+ ),
119
+ ctx.settings.head.alternateLinks?.map((a, i) => /* @__PURE__ */ jsx(
120
+ "link",
121
+ {
122
+ rel: a.rel,
123
+ href: a.href,
124
+ ...a.type ? { type: a.type } : {},
125
+ ...a.title ? { title: a.title } : {}
126
+ },
127
+ i
128
+ )),
129
+ ctx.settings.head.meta?.map((m, i) => /* @__PURE__ */ jsx(
130
+ "meta",
131
+ {
132
+ ...m.name ? { name: m.name } : {},
133
+ ...m.property ? { property: m.property } : {},
134
+ content: m.content
135
+ },
136
+ i
137
+ ))
138
+ ] })
56
139
  ] });
57
140
  }
58
141
  return HeadWithDefaults;
@@ -1,8 +1,8 @@
1
1
  /** @jsxRuntime automatic */
2
2
  /** @jsxImportSource preact */
3
3
  import type { JSX } from "preact";
4
- import type { SidebarNavNode, SidebarRootMenuItem } from "../sidebar/types.js";
5
- import type { LocaleLink } from "../url-helpers/index.js";
4
+ import type { ChromeContext } from "../factory-context/index.js";
5
+ import type { Settings } from "../settings.js";
6
6
  export interface HeaderWithDefaultsProps {
7
7
  /** Active locale; defaults to the configured defaultLocale. */
8
8
  lang?: string;
@@ -44,34 +44,13 @@ export interface HeaderWithDefaultsSettings {
44
44
  versions?: HeaderVersionEntry[] | false;
45
45
  githubUrl?: string | false;
46
46
  }
47
- /** Dependencies injected by the host stub. */
48
- export interface HeaderWithDefaultsDeps {
49
- settings: HeaderWithDefaultsSettings;
50
- defaultLocale: string;
51
- locales: readonly string[];
52
- t: (key: string, lang: string) => string;
53
- withBase: (path: string) => string;
54
- stripBase: (path: string) => string;
55
- docsUrl: (slug: string, lang: string) => string;
56
- navHref: (path: string, lang: string | undefined, version: string | undefined) => string;
57
- versionedDocsUrl: (slug: string, versionSlug: string, lang: string) => string;
58
- buildLocaleLinksForNav: (currentPath: string, lang: string, localeCount: number) => LocaleLink[] | undefined;
59
- buildRootMenuItems: (lang: string, currentVersion: string | undefined) => SidebarRootMenuItem[];
60
- buildSidebarNodes: (lang: string, navSection: string | undefined, currentVersion: string | undefined) => SidebarNavNode[];
61
- getThemeDefaultMode: () => "light" | "dark" | undefined;
62
- buildGitHubRepoUrl: () => string | null;
63
- SearchWidget: (props: {
64
- placeholderText: string;
65
- shortcutHint: string;
66
- resultCountTemplate: string;
67
- searchLabel: string;
68
- searchUnavailableText: string;
69
- loadingIndexText: string;
70
- noResultsText: string;
71
- }) => JSX.Element;
72
- }
73
47
  /**
74
- * Create a `HeaderWithDefaults` component bound to the host's settings
75
- * and data-prep utilities.
48
+ * Create a `HeaderWithDefaults` component from the unified {@link ChromeContext}
49
+ * (epic Collapse Wiring Shells #2420, FACTORIES #2424 — breaking signature).
50
+ *
51
+ * Derives its old wide deps bag from the context: the URL/i18n helpers
52
+ * (`t`/`withBase`/`docsUrl`/…) and `locales`/`defaultLocale` are read directly;
53
+ * the nav data-prep builders + SearchWidget slot come from the shared
54
+ * `chrome/derive` helpers; `buildGitHubRepoUrl` is bound to `settings.githubUrl`.
76
55
  */
77
- export declare function createHeaderWithDefaults(deps: HeaderWithDefaultsDeps): (props: HeaderWithDefaultsProps) => JSX.Element;
56
+ export declare function createHeaderWithDefaults<S extends Settings = Settings>(ctx: ChromeContext<S>): (props: HeaderWithDefaultsProps) => JSX.Element;
@@ -7,24 +7,21 @@ import {
7
7
  } from "../i18n-version/index.js";
8
8
  import { ThemeToggle } from "../theme-toggle/index.js";
9
9
  import { SidebarToggle } from "../sidebar-toggle-island/index.js";
10
- function createHeaderWithDefaults(deps) {
11
- const {
12
- settings,
13
- defaultLocale,
14
- locales,
15
- t,
16
- withBase,
17
- stripBase,
18
- docsUrl,
19
- navHref,
20
- versionedDocsUrl,
21
- buildLocaleLinksForNav,
22
- buildRootMenuItems,
23
- buildSidebarNodes,
24
- getThemeDefaultMode,
25
- buildGitHubRepoUrl,
26
- SearchWidget
27
- } = deps;
10
+ import { buildGitHubRepoUrl as buildGitHubRepoUrlBase } from "../github-helpers/index.js";
11
+ import { deriveNavDataPrep, deriveSearchWidgetSlot } from "../chrome/derive.js";
12
+ function createHeaderWithDefaults(ctx) {
13
+ const settings = ctx.settings;
14
+ const defaultLocale = ctx.defaultLocale;
15
+ const locales = ctx.locales;
16
+ const t = ctx.t;
17
+ const withBase = ctx.withBase;
18
+ const stripBase = ctx.stripBase;
19
+ const docsUrl = ctx.docsUrl;
20
+ const navHref = ctx.navHref;
21
+ const versionedDocsUrl = ctx.versionedDocsUrl;
22
+ const { buildRootMenuItems, buildLocaleLinksForNav, buildSidebarNodes, getThemeDefaultMode } = deriveNavDataPrep(ctx);
23
+ const buildGitHubRepoUrl = () => buildGitHubRepoUrlBase(ctx.settings.githubUrl);
24
+ const SearchWidget = deriveSearchWidgetSlot(ctx);
28
25
  function HeaderWithDefaults(props) {
29
26
  const {
30
27
  lang: langProp = defaultLocale,
@@ -1,5 +1,6 @@
1
1
  import type { CategoryMeta } from "../sidebar-tree/index.js";
2
2
  import type { DocPageEntry } from "../doc-page-props/index.js";
3
+ import type { Settings } from "../settings.js";
3
4
  export type { CategoryMeta, DocPageEntry };
4
5
  export interface NavSourceDocs {
5
6
  /** Full doc list (merged + draft-filtered; unlisted retained per options). */
@@ -41,58 +42,32 @@ export interface VersionConfigEntry {
41
42
  }>;
42
43
  }
43
44
  /**
44
- * Injected context for `createNavSourceDocs`.
45
+ * Context slice `createNavSourceDocs` derives its bag from (epic Collapse
46
+ * Wiring Shells #2420, FACTORIES #2424 — breaking signature). This is a
47
+ * STRUCTURAL SUBSET of the unified `RouteContext`/`ChromeContext`, so callers
48
+ * pass the whole context: `docsDir`/`getVersions` are read off `settings`,
49
+ * `loadCategoryMeta` is imported from the package directly (it is a pure,
50
+ * `@/`-free helper), and the rest are reconstructed callables on the context.
45
51
  *
46
- * All host-specific singletons are passed in so the package factory never
47
- * imports `@/` aliases. The host stub calls `createNavSourceDocs(ctx)` once
48
- * and re-exports the returned resolver functions.
52
+ * NB: `createRouteContext` builds the route context incrementally and calls
53
+ * this factory with the partial-but-sufficient base context every field
54
+ * below is present before the nav-source resolvers are assembled.
49
55
  */
50
56
  export interface NavSourceDocsContext {
51
- /**
52
- * Default locale code (served from the un-prefixed `/docs/...` routes).
53
- * E.g. `"en"`.
54
- */
57
+ /** The host's resolved settings object (reads `docsDir` + `versions`). */
58
+ settings: Settings;
59
+ /** Default locale code (un-prefixed `/docs/...` routes). E.g. `"en"`. */
55
60
  defaultLocale: string;
56
- /**
57
- * The configured docs content directory (e.g. `"src/content/docs"`).
58
- * Used as the base dir for `loadCategoryMeta`.
59
- */
60
- docsDir: string;
61
- /**
62
- * Getter for the configured versions list (or false if versioning is not
63
- * active). Called on every `resolveNavSource` invocation so test code that
64
- * mutates `settings.versions` between calls sees the updated value.
65
- * Structural equivalent of a getter for `settings.versions`.
66
- *
67
- * Pass `() => settings.versions` from the host stub.
68
- */
69
- getVersions: () => VersionConfigEntry[] | false | undefined;
70
- /**
71
- * Look up locale-specific config (dir, etc.) for a locale code.
72
- * Host passes `getLocaleConfig` from `@/config/i18n`.
73
- */
61
+ /** Per-locale config lookup (reconstructed on the context). */
74
62
  getLocaleConfig: (lang: string) => LocaleConfig | undefined;
75
- /**
76
- * Load category metadata for a content dir.
77
- * Host passes `loadCategoryMeta` from `@/utils/docs` (re-exported from
78
- * `@takazudo/zudo-doc/sidebar-tree`).
79
- */
80
- loadCategoryMeta: (dir: string) => Map<string, CategoryMeta>;
81
- /**
82
- * Filter predicate: true when a doc should appear in navigation.
83
- * Host passes `isNavVisible` from `@/utils/docs`.
84
- */
63
+ /** Filter predicate: true when a doc should appear in navigation. */
85
64
  isNavVisible: (doc: DocPageEntry) => boolean;
86
- /**
87
- * Returns true for paths that are only shown in the default locale.
88
- * Host passes `isDefaultLocaleOnlyPath` from `@/utils/base`.
89
- */
65
+ /** Returns true for paths that are only shown in the default locale. */
90
66
  isDefaultLocaleOnlyPath: (path: string) => boolean;
91
67
  /**
92
- * Identity-stable, draft-filtered docs array for a collection.
93
- * Host passes `stableDocs` from `pages/lib/_nav-source-cache.ts`.
94
- * The function must anchor memoization on the zfb snapshot so the SAME
95
- * array instance is returned on every call within one build.
68
+ * Identity-stable, draft-filtered docs array for a collection (the
69
+ * content-bridge handle). Anchors memoization on the zfb snapshot so the
70
+ * SAME array instance is returned on every call within one build.
96
71
  */
97
72
  stableDocs: (collectionName: string) => DocPageEntry[];
98
73
  }
@@ -154,16 +129,7 @@ export interface NavSourceDocsAPI {
154
129
  * loadNavSourceDocs,
155
130
  * stableMergeCategoryMeta,
156
131
  * stableNavDocs,
157
- * } = createNavSourceDocs({
158
- * defaultLocale,
159
- * docsDir: settings.docsDir,
160
- * getVersions: () => settings.versions,
161
- * getLocaleConfig,
162
- * loadCategoryMeta,
163
- * isNavVisible,
164
- * isDefaultLocaleOnlyPath,
165
- * stableDocs,
166
- * });
132
+ * } = createNavSourceDocs(routeContext);
167
133
  * ```
168
134
  */
169
135
  export declare function createNavSourceDocs(ctx: NavSourceDocsContext): NavSourceDocsAPI;
@@ -1,3 +1,4 @@
1
+ import { loadCategoryMeta as loadCategoryMetaImpl } from "../sidebar-tree/index.js";
1
2
  import { memoizeDerived } from "../nav-source-cache/index.js";
2
3
  import { mergeLocaleDocs } from "../locale-merge/index.js";
3
4
  function optionSig(o) {
@@ -5,16 +6,14 @@ function optionSig(o) {
5
6
  }
6
7
  const EMPTY_SLUG_SET = /* @__PURE__ */ new Set();
7
8
  function createNavSourceDocs(ctx) {
8
- const {
9
- defaultLocale,
10
- docsDir,
11
- getVersions,
12
- getLocaleConfig,
13
- loadCategoryMeta,
14
- isNavVisible,
15
- isDefaultLocaleOnlyPath,
16
- stableDocs
17
- } = ctx;
9
+ const defaultLocale = ctx.defaultLocale;
10
+ const docsDir = ctx.settings.docsDir;
11
+ const getVersions = () => ctx.settings.versions;
12
+ const getLocaleConfig = ctx.getLocaleConfig;
13
+ const loadCategoryMeta = loadCategoryMetaImpl;
14
+ const isNavVisible = ctx.isNavVisible;
15
+ const isDefaultLocaleOnlyPath = ctx.isDefaultLocaleOnlyPath;
16
+ const stableDocs = ctx.stableDocs;
18
17
  const mergedCategoryMetaCache = /* @__PURE__ */ new Map();
19
18
  function stableMergeCategoryMeta(baseDir, localeDir) {
20
19
  const key = `${baseDir}
@@ -0,0 +1,24 @@
1
+ import type { RouteContext, RouteContextPayload } from "../factory-context/index.js";
2
+ import type { Settings } from "../settings.js";
3
+ import type { DocPageEntry } from "../doc-page-props/index.js";
4
+ export type { RouteContext, RouteContextPayload, TagInfo, } from "../factory-context/index.js";
5
+ /** A content-bridge handle: identity-stable, draft-filtered docs loader. */
6
+ export type ContentBridge = (collectionName: string) => DocPageEntry[];
7
+ export interface CreateRouteContextOptions {
8
+ /**
9
+ * The content-bridge handle (`stableDocs`). Default: the package
10
+ * `stableDocs` from `routes/_docs-helpers` (reads `@takazudo/zfb/content`,
11
+ * snapshot-anchored for per-build identity stability). The host may inject
12
+ * its own content loader here.
13
+ */
14
+ stableDocs?: ContentBridge;
15
+ }
16
+ /**
17
+ * Reconstruct the full runtime route context from the serializable payload.
18
+ * Called ONCE per build (the route entrypoints share the returned singleton via
19
+ * the `routes/_context.ts` module), so the memoized closures inside
20
+ * (`createNavSourceDocs` / `createDocRouteEntries` / `createRouteEnumerators`)
21
+ * and the snapshot-anchored `stableDocs` keep array identity stable across all
22
+ * routes.
23
+ */
24
+ export declare function createRouteContext<S extends Settings = Settings>(payload: RouteContextPayload<S>, options?: CreateRouteContextOptions): RouteContext<S>;
@@ -0,0 +1,147 @@
1
+ import { makeUrlHelpers } from "../url-helpers/index.js";
2
+ import { loadCategoryMeta } from "../sidebar-tree/index.js";
3
+ import { extractHeadings as extractHeadingsBase } from "../extract-headings/index.js";
4
+ import { toRouteSlug, toSlugParams } from "../slug/index.js";
5
+ import { resolveTag } from "../tag-helpers/index.js";
6
+ import {
7
+ getCategoryOrder as getCategoryOrderBase,
8
+ getNavSectionForSlug as getNavSectionForSlugBase,
9
+ getNavSubtree as getNavSubtreeBase
10
+ } from "../nav-scope/index.js";
11
+ import { mergeLocaleDocs } from "../locale-merge/index.js";
12
+ import {
13
+ createNavSourceDocs
14
+ } from "../nav-source-docs/index.js";
15
+ import {
16
+ createDocRouteEntries
17
+ } from "../doc-route-entries/index.js";
18
+ import {
19
+ createRouteEnumerators
20
+ } from "../route-enumerators/index.js";
21
+ import {
22
+ stableDocs as defaultStableDocs,
23
+ isNavVisible,
24
+ buildNavTree,
25
+ buildBreadcrumbs,
26
+ collectAutoIndexNodes,
27
+ groupSatelliteNodes,
28
+ findNode,
29
+ firstRoutedHref
30
+ } from "../routes/_docs-helpers.js";
31
+ function createRouteContext(payload, options = {}) {
32
+ const settings = payload.settings;
33
+ const translations = payload.translations;
34
+ const tagVocabulary = payload.tagVocabulary;
35
+ const colorSchemes = payload.colorSchemes;
36
+ const stableDocs = options.stableDocs ?? defaultStableDocs;
37
+ const defaultLocale = settings.defaultLocale;
38
+ const locales = [
39
+ defaultLocale,
40
+ ...Object.keys(settings.locales)
41
+ ];
42
+ function getLocaleConfig(locale) {
43
+ return settings.locales[locale];
44
+ }
45
+ function getLocaleLabel(locale) {
46
+ if (locale === defaultLocale) return defaultLocale.toUpperCase();
47
+ return getLocaleConfig(locale)?.label ?? locale.toUpperCase();
48
+ }
49
+ function t(key, locale = defaultLocale) {
50
+ return translations[locale]?.[key] ?? translations[defaultLocale]?.[key] ?? key;
51
+ }
52
+ const i18n = { defaultLocale, locales, getLocaleLabel, t };
53
+ const urlHelpers = makeUrlHelpers(settings, i18n);
54
+ const { withBase, docsUrl, versionedDocsUrl, navHref, isDefaultLocaleOnlyPath } = urlHelpers;
55
+ function getCategoryOrder() {
56
+ return getCategoryOrderBase(settings.headerNav);
57
+ }
58
+ function getNavSectionForSlug(slug) {
59
+ return getNavSectionForSlugBase(slug, settings.headerNav);
60
+ }
61
+ function getNavSubtree(tree, categoryMatch) {
62
+ return getNavSubtreeBase(tree, categoryMatch, settings.headerNav);
63
+ }
64
+ function extractHeadings(body) {
65
+ return extractHeadingsBase(body, {
66
+ tocMinDepth: settings.tocMinDepth,
67
+ tocMaxDepth: settings.tocMaxDepth,
68
+ strategy: settings.headingIdStrategy
69
+ });
70
+ }
71
+ function getVocab() {
72
+ return settings.tagVocabulary ? tagVocabulary : false;
73
+ }
74
+ function resolveTagBound(raw) {
75
+ return resolveTag(raw, getVocab(), settings.tagGovernance);
76
+ }
77
+ function collectTags(entries, slugFn) {
78
+ const tagMap = /* @__PURE__ */ new Map();
79
+ for (const entry of entries) {
80
+ const rawTags = entry.data.tags ?? [];
81
+ const slug = slugFn(entry.id, entry.data);
82
+ const seen = /* @__PURE__ */ new Set();
83
+ for (const raw of rawTags) {
84
+ const resolved = resolveTagBound(raw);
85
+ if (resolved.deprecated) continue;
86
+ if (seen.has(resolved.canonical)) continue;
87
+ seen.add(resolved.canonical);
88
+ if (!tagMap.has(resolved.canonical)) {
89
+ tagMap.set(resolved.canonical, {
90
+ tag: resolved.canonical,
91
+ count: 0,
92
+ docs: []
93
+ });
94
+ }
95
+ const info = tagMap.get(resolved.canonical);
96
+ info.count++;
97
+ info.docs.push({
98
+ slug,
99
+ title: entry.data.title ?? "",
100
+ description: entry.data.description
101
+ });
102
+ }
103
+ }
104
+ return tagMap;
105
+ }
106
+ const base = {
107
+ settings,
108
+ colorSchemes,
109
+ i18n,
110
+ defaultLocale,
111
+ locales,
112
+ getLocaleConfig,
113
+ getLocaleLabel,
114
+ t,
115
+ urlHelpers,
116
+ ...urlHelpers,
117
+ getCategoryOrder,
118
+ getNavSectionForSlug,
119
+ getNavSubtree,
120
+ extractHeadings,
121
+ resolveTagBound,
122
+ collectTags,
123
+ buildNavTree,
124
+ groupSatelliteNodes,
125
+ findNode,
126
+ firstRoutedHref,
127
+ collectAutoIndexNodes,
128
+ isNavVisible,
129
+ stableDocs,
130
+ toRouteSlug,
131
+ toSlugParams
132
+ };
133
+ const navSourceDocs = createNavSourceDocs(base);
134
+ const docRouteEntries = createDocRouteEntries(base);
135
+ const baseWithNav = { ...base, ...navSourceDocs };
136
+ const routeEnumerators = createRouteEnumerators(
137
+ baseWithNav
138
+ );
139
+ return {
140
+ ...baseWithNav,
141
+ ...docRouteEntries,
142
+ ...routeEnumerators
143
+ };
144
+ }
145
+ export {
146
+ createRouteContext
147
+ };