@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.
- package/dist/chrome/derive.d.ts +68 -0
- package/dist/chrome/derive.js +231 -0
- package/dist/chrome/index.d.ts +37 -0
- package/dist/chrome/index.js +43 -0
- package/dist/doc-body-end/index.d.ts +9 -11
- package/dist/doc-body-end/index.js +4 -2
- package/dist/doc-content-header/index.d.ts +10 -2
- package/dist/doc-content-header/index.js +8 -8
- package/dist/doc-history-area/index.d.ts +10 -25
- package/dist/doc-history-area/index.js +14 -10
- package/dist/doc-metainfo-area/index.d.ts +9 -15
- package/dist/doc-metainfo-area/index.js +6 -2
- package/dist/doc-page-renderer/index.d.ts +11 -2
- package/dist/doc-page-renderer/index.js +22 -15
- package/dist/doc-page-shell/index.d.ts +11 -3
- package/dist/doc-page-shell/index.js +21 -14
- package/dist/doc-pager/index.d.ts +6 -7
- package/dist/doc-pager/index.js +2 -2
- package/dist/doc-route-entries/index.d.ts +22 -46
- package/dist/doc-route-entries/index.js +15 -10
- package/dist/doc-tags-area/index.d.ts +9 -19
- package/dist/doc-tags-area/index.js +12 -2
- package/dist/factory-context/index.d.ts +163 -1
- package/dist/footer-with-defaults/index.d.ts +12 -13
- package/dist/footer-with-defaults/index.js +8 -10
- package/dist/head/types.d.ts +39 -0
- package/dist/head-with-defaults/index.d.ts +12 -16
- package/dist/head-with-defaults/index.js +93 -10
- package/dist/header-with-defaults/index.d.ts +10 -31
- package/dist/header-with-defaults/index.js +15 -18
- package/dist/nav-source-docs/index.d.ts +20 -54
- package/dist/nav-source-docs/index.js +9 -10
- package/dist/route-context/index.d.ts +24 -0
- package/dist/route-context/index.js +147 -0
- package/dist/route-enumerators/index.d.ts +25 -74
- package/dist/route-enumerators/index.js +17 -18
- package/dist/routes/_chrome.d.ts +6 -25
- package/dist/routes/_chrome.js +14 -387
- package/dist/routes/_context.d.ts +10 -43
- package/dist/routes/_context.js +29 -157
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +54 -0
- package/dist/sidebar-with-defaults/index.d.ts +8 -15
- package/dist/sidebar-with-defaults/index.js +6 -10
- package/dist/tag-pages/index.d.ts +12 -3
- package/dist/tag-pages/index.js +24 -19
- package/dist/versions-page/index.d.ts +10 -3
- package/dist/versions-page/index.js +18 -14
- package/eject/doc-pager/index.tsx +8 -10
- package/package.json +13 -5
- package/routes-src/_chrome.tsx +31 -552
- 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
|
|
43
|
-
*
|
|
36
|
+
* Create a `HeadWithDefaults` component from the unified {@link ChromeContext}
|
|
37
|
+
* (epic Collapse Wiring Shells #2420, FACTORIES #2424 — breaking signature).
|
|
44
38
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `
|
|
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(
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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, """)}"${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 {
|
|
5
|
-
import type {
|
|
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
|
|
75
|
-
*
|
|
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(
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
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
|
-
|
|
53
|
-
|
|
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
|
-
*
|
|
94
|
-
*
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
+
};
|