@tenphi/renderer 0.21.4 → 0.22.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/components/Card.styles.js +6 -3
- package/dist/components/Document.styles.js +5 -4
- package/dist/components/HeaderFrame.styles.js +2 -1
- package/dist/components/Hero.styles.js +3 -2
- package/dist/components/MainContent.styles.js +1 -1
- package/dist/components/MarkdownContent.styles.js +3 -1
- package/dist/components/MobileTableOfContents.styles.js +3 -2
- package/dist/components/PackageVersion.styles.js +1 -1
- package/dist/components/PageActions.styles.js +1 -1
- package/dist/components/Preview.styles.js +3 -1
- package/dist/components/Sidebar.styles.js +11 -7
- package/dist/components/SidebarList.astro +1 -5
- package/dist/components/SkipLink.styles.js +3 -2
- package/dist/components/TableOfContents.styles.js +2 -1
- package/dist/components/Tabs.styles.js +2 -1
- package/dist/components/ThemeSelect.styles.js +5 -3
- package/dist/components/TopNavigation.styles.js +3 -2
- package/dist/localization.d.ts.map +1 -1
- package/dist/localization.js +8 -2
- package/dist/localization.js.map +1 -1
- package/dist/navigation.d.ts +3 -1
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +30 -9
- package/dist/navigation.js.map +1 -1
- package/dist/route-context.d.ts +2 -10
- package/dist/route-context.d.ts.map +1 -1
- package/dist/route-context.js +4 -2
- package/dist/route-context.js.map +1 -1
- package/package.json +5 -5
|
@@ -16,7 +16,9 @@ export const CardRoot = defineComponent("Card", {
|
|
|
16
16
|
border: true,
|
|
17
17
|
radius: "1cr",
|
|
18
18
|
fill: "#surface-2",
|
|
19
|
-
shadow: "
|
|
19
|
+
"$resting-shadow-offset": "1px",
|
|
20
|
+
"$resting-shadow-blur": "2px",
|
|
21
|
+
shadow: "0 $resting-shadow-offset $resting-shadow-blur #shadow",
|
|
20
22
|
transition: "fill $transition, shadow $transition, translate $transition",
|
|
21
23
|
|
|
22
24
|
Heading2: {
|
|
@@ -52,12 +54,13 @@ export const CardLink = tasty(CardRoot, {
|
|
|
52
54
|
":active": "#surface-2-pressed",
|
|
53
55
|
},
|
|
54
56
|
shadow: {
|
|
55
|
-
"": "0
|
|
57
|
+
"": "0 $resting-shadow-offset $resting-shadow-blur #shadow",
|
|
56
58
|
":hover": "0 .75x 2x #shadow",
|
|
57
59
|
},
|
|
60
|
+
"$hover-offset": "-1px",
|
|
58
61
|
translate: {
|
|
59
62
|
"": "0",
|
|
60
|
-
":hover": "0 -
|
|
63
|
+
":hover": "0 $hover-offset",
|
|
61
64
|
":active": "0",
|
|
62
65
|
},
|
|
63
66
|
},
|
|
@@ -49,7 +49,7 @@ export default function DocumentStyles() {
|
|
|
49
49
|
"$docs-nav-gap": { "": "0.75rem", "@mobile": "0.5rem" },
|
|
50
50
|
"$docs-sidebar-pad-x": "1.5rem",
|
|
51
51
|
"$docs-content-pad-x": {
|
|
52
|
-
"": "clamp(1.5rem,
|
|
52
|
+
"": "clamp(1.5rem, calc((100% - $content-width) / 2), 4rem)",
|
|
53
53
|
"@mobile": "1rem",
|
|
54
54
|
},
|
|
55
55
|
"$docs-menu-button-size": { "": "2.5rem", "@mobile": "2.25rem" },
|
|
@@ -164,11 +164,12 @@ export default function DocumentStyles() {
|
|
|
164
164
|
},
|
|
165
165
|
ScreenReaderOnly: {
|
|
166
166
|
$: ".sr-only",
|
|
167
|
+
"$visually-hidden-size": "1px",
|
|
167
168
|
position: "absolute",
|
|
168
|
-
inlineSize: "
|
|
169
|
-
blockSize: "
|
|
169
|
+
inlineSize: "$visually-hidden-size",
|
|
170
|
+
blockSize: "$visually-hidden-size",
|
|
170
171
|
padding: "0",
|
|
171
|
-
margin: "-
|
|
172
|
+
margin: "($visually-hidden-size * -1)",
|
|
172
173
|
overflow: "hidden",
|
|
173
174
|
clip: "rect(0, 0, 0, 0)",
|
|
174
175
|
whiteSpace: "nowrap",
|
|
@@ -15,6 +15,7 @@ export const HeaderFrameRoot = defineComponent("HeaderFrame", {
|
|
|
15
15
|
padding: "0 $docs-nav-pad-x",
|
|
16
16
|
blockBorder: "$border-width solid #border end",
|
|
17
17
|
fill: "#header",
|
|
18
|
-
|
|
18
|
+
"$backdrop-blur": "16px",
|
|
19
|
+
backdropFilter: "blur($backdrop-blur)",
|
|
19
20
|
},
|
|
20
21
|
});
|
|
@@ -91,7 +91,7 @@ export const HeroRoot = defineComponent("Hero", {
|
|
|
91
91
|
gap: "$gap",
|
|
92
92
|
color: "#text",
|
|
93
93
|
border: true,
|
|
94
|
-
radius: "
|
|
94
|
+
radius: "round",
|
|
95
95
|
fill: "#surface-2",
|
|
96
96
|
preset: "navigation / strong",
|
|
97
97
|
textDecoration: "none",
|
|
@@ -99,8 +99,9 @@ export const HeroRoot = defineComponent("Hero", {
|
|
|
99
99
|
},
|
|
100
100
|
HoverAction: {
|
|
101
101
|
$: ".cookbook-link-button",
|
|
102
|
+
"$hover-offset": "-1px",
|
|
102
103
|
fill: { "": null, "@own(:hover)": "#surface-2-hover" },
|
|
103
|
-
translate: { "": null, "@own(:hover)": "0 -
|
|
104
|
+
translate: { "": null, "@own(:hover)": "0 $hover-offset" },
|
|
104
105
|
},
|
|
105
106
|
PrimaryAction: {
|
|
106
107
|
$: ".cookbook-link-button.primary",
|
|
@@ -18,7 +18,7 @@ export const MainContentRoot = defineComponent("MainContent", {
|
|
|
18
18
|
},
|
|
19
19
|
Container: {
|
|
20
20
|
$: ".content-panel > .cookbook-container",
|
|
21
|
-
inlineMargin:
|
|
21
|
+
inlineMargin: "auto",
|
|
22
22
|
inlineSize: "max $content-width",
|
|
23
23
|
},
|
|
24
24
|
Panel: {
|
|
@@ -130,13 +130,15 @@ export default function MarkdownStyles() {
|
|
|
130
130
|
},
|
|
131
131
|
Details: {
|
|
132
132
|
$: "details",
|
|
133
|
+
"$details-border-width": "2px",
|
|
133
134
|
inlinePadding: {
|
|
134
135
|
"": null,
|
|
135
136
|
"@own(!:is(.not-content *))": "($gap * 2) start",
|
|
136
137
|
},
|
|
137
138
|
inlineBorder: {
|
|
138
139
|
"": null,
|
|
139
|
-
"@own(!:is(.not-content *))":
|
|
140
|
+
"@own(!:is(.not-content *))":
|
|
141
|
+
"$details-border-width solid #border start",
|
|
140
142
|
},
|
|
141
143
|
// Change only color; border widths and styles belong to other rules or theme overrides.
|
|
142
144
|
// eslint-disable-next-line tasty/prefer-shorthand-property
|
|
@@ -24,11 +24,12 @@ export const MobileTableOfContentsRoot = defineComponent(
|
|
|
24
24
|
},
|
|
25
25
|
List: {
|
|
26
26
|
$: "ul",
|
|
27
|
+
"$item-gap": "2px",
|
|
27
28
|
listStyle: "none",
|
|
28
29
|
padding: "0",
|
|
29
30
|
margin: "0",
|
|
30
31
|
display: "grid",
|
|
31
|
-
gap: "
|
|
32
|
+
gap: "$item-gap",
|
|
32
33
|
},
|
|
33
34
|
NestedList: { $: "ul ul", inlinePadding: "($gap * 2) start" },
|
|
34
35
|
Item: { $: "li", listStyle: "none", margin: "0", padding: "0" },
|
|
@@ -51,7 +52,7 @@ export const MobileTableOfContentsRoot = defineComponent(
|
|
|
51
52
|
outline: {
|
|
52
53
|
"": null,
|
|
53
54
|
"@own(:is(a:focus-visible)) | @own(:is(summary:focus-visible))":
|
|
54
|
-
"
|
|
55
|
+
"$outline-width solid #focus / $outline-offset",
|
|
55
56
|
},
|
|
56
57
|
},
|
|
57
58
|
},
|
|
@@ -36,7 +36,7 @@ export const PageActionsRoot = defineComponent("PageActions", {
|
|
|
36
36
|
$: "button, a",
|
|
37
37
|
outline: {
|
|
38
38
|
"": null,
|
|
39
|
-
"@own(:focus-visible)": "
|
|
39
|
+
"@own(:focus-visible)": "$outline-width solid #focus / $outline-offset",
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
Pending: {
|
|
@@ -22,7 +22,9 @@ export const PreviewRoot = defineComponent("Preview", {
|
|
|
22
22
|
border: true,
|
|
23
23
|
radius: "1cr",
|
|
24
24
|
fill: "#surface",
|
|
25
|
-
shadow: "
|
|
25
|
+
"$resting-shadow-offset": "1px",
|
|
26
|
+
"$resting-shadow-blur": "2px",
|
|
27
|
+
shadow: "0 $resting-shadow-offset $resting-shadow-blur #shadow",
|
|
26
28
|
|
|
27
29
|
Caption: {
|
|
28
30
|
padding: "1.5x 2x",
|
|
@@ -198,6 +198,7 @@ export const SidebarRoot = defineComponent("Sidebar", {
|
|
|
198
198
|
display: "flex",
|
|
199
199
|
alignItems: "center",
|
|
200
200
|
inlineSize: "min 0",
|
|
201
|
+
flexGrow: "1",
|
|
201
202
|
gap: "0.25em",
|
|
202
203
|
},
|
|
203
204
|
GroupLabelText: {
|
|
@@ -291,14 +292,17 @@ export const SidebarRoot = defineComponent("Sidebar", {
|
|
|
291
292
|
},
|
|
292
293
|
},
|
|
293
294
|
Badge: {
|
|
294
|
-
$: "
|
|
295
|
+
$: "cookbook-sidebar Badge",
|
|
296
|
+
display: "inline-flex",
|
|
297
|
+
alignItems: "center",
|
|
295
298
|
flexShrink: "0",
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
radius: "
|
|
301
|
-
preset: "small",
|
|
299
|
+
inlineMargin: "auto start",
|
|
300
|
+
padding: "0.125em 0.625em",
|
|
301
|
+
color: "#accent-text",
|
|
302
|
+
fill: "#accent-surface-subtle",
|
|
303
|
+
radius: "round",
|
|
304
|
+
preset: "small / strong / tight",
|
|
305
|
+
whiteSpace: "nowrap",
|
|
302
306
|
},
|
|
303
307
|
TopLevelLink: {
|
|
304
308
|
$: "a.large",
|
|
@@ -27,11 +27,7 @@ const containsCurrent = (items: SidebarEntry[]): boolean =>
|
|
|
27
27
|
entry.type === "group" ? entry.entries.slice(groupLink ? 1 : 0) : [];
|
|
28
28
|
const open = Boolean(groupLink?.isCurrent) || containsCurrent(children);
|
|
29
29
|
const badge = entry.badge && (
|
|
30
|
-
<span
|
|
31
|
-
class:list={["sidebar-badge", entry.badge.variant, entry.badge.class]}
|
|
32
|
-
>
|
|
33
|
-
{entry.badge.text}
|
|
34
|
-
</span>
|
|
30
|
+
<span data-element="Badge">{entry.badge}</span>
|
|
35
31
|
);
|
|
36
32
|
const label = (
|
|
37
33
|
<span class="group-label">
|
|
@@ -7,6 +7,7 @@ export const SkipLinkRoot = defineComponent("SkipLink", {
|
|
|
7
7
|
as: "a",
|
|
8
8
|
"data-element": "SkipLink",
|
|
9
9
|
styles: {
|
|
10
|
+
"$visually-hidden-size": "1px",
|
|
10
11
|
zIndex: { "": null, ":focus": "20" },
|
|
11
12
|
color: { "": null, ":focus": "#accent-surface-text" },
|
|
12
13
|
fill: { "": null, ":focus": "#accent-surface" },
|
|
@@ -15,8 +16,8 @@ export const SkipLinkRoot = defineComponent("SkipLink", {
|
|
|
15
16
|
textDecoration: { "": null, ":focus": "none" },
|
|
16
17
|
position: "fixed",
|
|
17
18
|
inset: "($gap * 1.5) auto auto ($gap * 1.5)",
|
|
18
|
-
inlineSize: { "": "
|
|
19
|
-
blockSize: { "": "
|
|
19
|
+
inlineSize: { "": "$visually-hidden-size", ":focus": "auto" },
|
|
20
|
+
blockSize: { "": "$visually-hidden-size", ":focus": "auto" },
|
|
20
21
|
padding: { "": "0", ":focus": "$gap ($gap * 2)" },
|
|
21
22
|
overflow: { "": "hidden", ":focus": "visible" },
|
|
22
23
|
clip: { "": "rect(0, 0, 0, 0)", ":focus": "auto" },
|
|
@@ -19,10 +19,11 @@ export const TableOfContentsRoot = defineComponent("TableOfContents", {
|
|
|
19
19
|
},
|
|
20
20
|
List: {
|
|
21
21
|
$: "ul",
|
|
22
|
+
"$item-gap": "1px",
|
|
22
23
|
display: "grid",
|
|
23
24
|
gridColumns: "minmax(0, 1fr)",
|
|
24
25
|
inlineSize: "min 0",
|
|
25
|
-
gap: "
|
|
26
|
+
gap: "$item-gap",
|
|
26
27
|
margin: "0",
|
|
27
28
|
padding: "0",
|
|
28
29
|
listStyle: "none",
|
|
@@ -137,14 +137,16 @@ export const ThemeSelectRoot = defineComponent("ThemeSelect", {
|
|
|
137
137
|
$: "label",
|
|
138
138
|
outline: {
|
|
139
139
|
"": null,
|
|
140
|
-
"@own(:has(input:focus-visible))":
|
|
140
|
+
"@own(:has(input:focus-visible))":
|
|
141
|
+
"$outline-width solid #focus / ($outline-offset * -1)",
|
|
141
142
|
},
|
|
142
143
|
},
|
|
143
144
|
Input: {
|
|
144
145
|
$: "input",
|
|
146
|
+
"$visually-hidden-size": "1px",
|
|
145
147
|
position: "absolute",
|
|
146
|
-
inlineSize: "
|
|
147
|
-
blockSize: "0
|
|
148
|
+
inlineSize: "$visually-hidden-size",
|
|
149
|
+
blockSize: "0 $visually-hidden-size",
|
|
148
150
|
padding: "0",
|
|
149
151
|
margin: "0",
|
|
150
152
|
overflow: "hidden",
|
|
@@ -41,11 +41,12 @@ export const TopNavigationRoot = defineComponent("TopNavigation", {
|
|
|
41
41
|
// Tasty 3.9.3 appends @own states after pseudo-elements, producing invalid CSS.
|
|
42
42
|
// eslint-disable-next-line tasty/no-state-in-selector
|
|
43
43
|
$: 'a[aria-current="page"]::after',
|
|
44
|
+
"$indicator-height": "2px",
|
|
44
45
|
content: '""',
|
|
45
46
|
position: "absolute",
|
|
46
47
|
inset: "auto 0 0",
|
|
47
|
-
blockSize: "
|
|
48
|
-
radius: "
|
|
48
|
+
blockSize: "$indicator-height",
|
|
49
|
+
radius: "round",
|
|
49
50
|
fill: "#accent-surface",
|
|
50
51
|
},
|
|
51
52
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localization.d.ts","names":[],"sources":["../src/localization.ts"],"mappings":";;;;KAMK;EACH,UAAU;EACV,gBAAgB;EAChB,eAAe;;iBAGD,YAAY,cAAc,SAAS;;iBAMnC,gBACd,kBACA,cACA,SAAS;iBAWK,WAAW,cAAc,SAAS;iBAQlC,eACd,cACA,gBACA,SAAS;;iBASK,aACd,cACA,gBACA,QAAQ,aACR,SAAS;iBAoBK,WACd,cACA,qBACA,QAAQ,aACR,SAAS,eACT;;iBAec,oBACd,QAAQ,0BACR,QAAQ,aACR,qBACA,SAAS;EACN,QAAQ;EAA0B,QAAQ;;
|
|
1
|
+
{"version":3,"file":"localization.d.ts","names":[],"sources":["../src/localization.ts"],"mappings":";;;;KAMK;EACH,UAAU;EACV,gBAAgB;EAChB,eAAe;;iBAGD,YAAY,cAAc,SAAS;;iBAMnC,gBACd,kBACA,cACA,SAAS;iBAWK,WAAW,cAAc,SAAS;iBAQlC,eACd,cACA,gBACA,SAAS;;iBASK,aACd,cACA,gBACA,QAAQ,aACR,SAAS;iBAoBK,WACd,cACA,qBACA,QAAQ,aACR,SAAS,eACT;;iBAec,oBACd,QAAQ,0BACR,QAAQ,aACR,qBACA,SAAS;EACN,QAAQ;EAA0B,QAAQ;;iBAuH/B,iBACd,cACA,QAAQ,aACR,SAAS,gBACR;EAAQ;EAAc"}
|
package/dist/localization.js
CHANGED
|
@@ -66,9 +66,13 @@ function localizedNavigation(layout, routes, currentPath, options) {
|
|
|
66
66
|
const route = visibleRoutes.get(target);
|
|
67
67
|
return [{
|
|
68
68
|
label: typeof route.sidebar === "object" && route.sidebar.label ? route.sidebar.label : route.title,
|
|
69
|
-
link: target
|
|
69
|
+
link: target,
|
|
70
|
+
...typeof route.sidebar === "object" && route.sidebar.badge !== void 0 ? { badge: route.sidebar.badge } : {}
|
|
70
71
|
}];
|
|
71
72
|
}
|
|
73
|
+
const sidebar = fallback && target === fallback ? visibleRoutes.get(fallback)?.sidebar : void 0;
|
|
74
|
+
const badge = item.badge !== void 0 ? label(item.badge) : typeof sidebar === "object" ? sidebar.badge : void 0;
|
|
75
|
+
const presentation = badge !== void 0 ? { badge } : {};
|
|
72
76
|
if ("items" in item || "autogenerate" in item) {
|
|
73
77
|
const { link: _link, ...group } = item;
|
|
74
78
|
const children = "items" in item ? convert(item.items) : void 0;
|
|
@@ -76,6 +80,7 @@ function localizedNavigation(layout, routes, currentPath, options) {
|
|
|
76
80
|
return [{
|
|
77
81
|
...group,
|
|
78
82
|
label: label(group.label),
|
|
83
|
+
...presentation,
|
|
79
84
|
...target ? { link: target } : {},
|
|
80
85
|
..."items" in item ? { items: children } : { autogenerate: { directory: localePath(item.autogenerate.directory, options) } }
|
|
81
86
|
}];
|
|
@@ -83,7 +88,8 @@ function localizedNavigation(layout, routes, currentPath, options) {
|
|
|
83
88
|
return target ? [{
|
|
84
89
|
...item,
|
|
85
90
|
label: label(item.label),
|
|
86
|
-
link: target
|
|
91
|
+
link: target,
|
|
92
|
+
...presentation
|
|
87
93
|
}] : [];
|
|
88
94
|
});
|
|
89
95
|
return {
|
package/dist/localization.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localization.js","names":[],"sources":["../src/localization.ts"],"sourcesContent":["import type { DocsConfig, DocsRoute, NavigationItem } from \"@tenphi/docs\";\nimport {\n normalizeNavigationPath,\n type ResolvedNavigationLayout,\n} from \"./navigation.js\";\n\ntype LocaleOptions = {\n locales?: DocsConfig[\"locales\"] | undefined;\n defaultLocale?: DocsConfig[\"defaultLocale\"] | undefined;\n translations?: DocsConfig[\"translations\"] | undefined;\n};\n\nexport function routeLocale(path: string, options: LocaleOptions): string {\n const first = normalizeNavigationPath(path).split(\"/\")[1];\n return first && first !== \"root\" && options.locales?.[first] ? first : \"root\";\n}\n\n/** Author components can render before the page initializes route locals. */\nexport function requestLanguage(\n pathname: string,\n base: string,\n options: LocaleOptions,\n): string {\n const prefix = base.replace(/\\/$/, \"\");\n const path =\n prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))\n ? pathname.slice(prefix.length)\n : pathname;\n const locale = routeLocale(path, options);\n return options.locales?.[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n}\n\nexport function localePath(path: string, options: LocaleOptions): string {\n const route = normalizeNavigationPath(path);\n const locale = routeLocale(route, options);\n return locale === \"root\"\n ? route\n : normalizeNavigationPath(route.slice(locale.length + 1));\n}\n\nexport function localizedRoute(\n path: string,\n locale: string,\n options: LocaleOptions,\n): string {\n const suffix = localePath(path, options);\n return normalizeNavigationPath(\n `${locale === \"root\" ? \"\" : `/${locale}`}${suffix}`,\n );\n}\n\n/** Missing translations use a real default-language page, then a real locale home. */\nexport function localeTarget(\n path: string,\n locale: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): string | undefined {\n const visible = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const fallback =\n options.defaultLocale ??\n (options.locales?.root\n ? \"root\"\n : (Object.keys(options.locales ?? {})[0] ?? \"root\"));\n return [\n localizedRoute(path, locale, options),\n localizedRoute(path, fallback, options),\n localizedRoute(\"/\", locale, options),\n localizedRoute(\"/\", fallback, options),\n ].find((route) => visible.has(route));\n}\n\nexport function localeHref(\n link: string,\n currentPath: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n base = \"/\",\n): string {\n if (!link.startsWith(\"/\") || link.startsWith(\"//\")) return link;\n const suffix = /[?#].*$/.exec(link)?.[0] ?? \"\";\n const path = suffix ? link.slice(0, -suffix.length) : link;\n const target = options.locales\n ? localeTarget(path, routeLocale(currentPath, options), routes, options)\n : normalizeNavigationPath(path);\n return (\n `${base.replace(/\\/$/, \"\")}${target ?? normalizeNavigationPath(path)}${suffix}` ||\n \"/\"\n );\n}\n\n/** Resolve navigation against the current locale's available routes. */\nexport function localizedNavigation(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n currentPath: string,\n options: LocaleOptions,\n): { layout: ResolvedNavigationLayout; routes: DocsRoute[] } {\n if (!options.locales) return { layout, routes };\n const locale = routeLocale(currentPath, options);\n const language =\n options.locales[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n const label = (value: string) =>\n options.translations?.[language]?.[`navigation.${value}`] ??\n options.translations?.[language.split(\"-\")[0]!]?.[`navigation.${value}`] ??\n value;\n const localRoutes = routes\n .filter((route) => routeLocale(route.route, options) === locale)\n .map((route) => ({ ...route, route: localePath(route.route, options) }));\n const available = new Set(\n localRoutes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const visibleRoutes = new Map(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => [route.route, route]),\n );\n const fallbackLocale =\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!);\n const convert = (items: NavigationItem[]): NavigationItem[] =>\n items.flatMap((item): NavigationItem[] => {\n const link = typeof item === \"string\" ? item : item.link;\n const internal = link?.startsWith(\"/\") && !link.startsWith(\"//\");\n const translated = internal ? localePath(link!, options) : link;\n const fallback = internal\n ? localizedRoute(link!, fallbackLocale, options)\n : undefined;\n const target =\n !internal || available.has(translated!)\n ? translated\n : fallback && visibleRoutes.has(fallback)\n ? fallback\n : undefined;\n if (typeof item === \"string\") {\n if (!target) return [];\n if (!internal || available.has(translated!)) return [target];\n const route = visibleRoutes.get(target)!;\n return [\n {\n label:\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n link: target,\n },\n ];\n }\n if (\"items\" in item || \"autogenerate\" in item) {\n const { link: _link, ...group } = item;\n const children = \"items\" in item ? convert(item.items) : undefined;\n if (children?.length === 0 && !target) return [];\n return [\n {\n ...group,\n label: label(group.label),\n ...(target ? { link: target } : {}),\n ...(\"items\" in item\n ? { items: children! }\n : {\n autogenerate: {\n directory: localePath(item.autogenerate.directory, options),\n },\n }),\n },\n ];\n }\n return target\n ? [{ ...item, label: label(item.label), link: target }]\n : [];\n });\n return {\n layout: {\n ...layout,\n ...(layout.items ? { items: convert(layout.items) } : {}),\n tabs: layout.tabs.map((tab) => ({\n ...tab,\n label: label(tab.label),\n link:\n tab.link.startsWith(\"/\") && !tab.link.startsWith(\"//\")\n ? localePath(tab.link, options)\n : tab.link,\n ...(tab.items ? { items: convert(tab.items) } : {}),\n })),\n },\n routes: localRoutes,\n };\n}\n\nexport { ENGLISH_MESSAGES, messages, type MessageKey } from \"./messages.js\";\n\nexport function localeAlternates(\n path: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): Array<{ lang: string; route: string }> {\n const available = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n if (!options.locales || !available.has(path)) return [];\n const alternates = Object.entries(options.locales).flatMap(\n ([locale, config]) => {\n const route = localizedRoute(path, locale, options);\n return available.has(route)\n ? [{ lang: config.lang ?? locale, route }]\n : [];\n },\n );\n const fallback = localizedRoute(\n path,\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!),\n options,\n );\n if (available.has(fallback))\n alternates.push({ lang: \"x-default\", route: fallback });\n return alternates;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"localization.js","names":[],"sources":["../src/localization.ts"],"sourcesContent":["import type { DocsConfig, DocsRoute, NavigationItem } from \"@tenphi/docs\";\nimport {\n normalizeNavigationPath,\n type ResolvedNavigationLayout,\n} from \"./navigation.js\";\n\ntype LocaleOptions = {\n locales?: DocsConfig[\"locales\"] | undefined;\n defaultLocale?: DocsConfig[\"defaultLocale\"] | undefined;\n translations?: DocsConfig[\"translations\"] | undefined;\n};\n\nexport function routeLocale(path: string, options: LocaleOptions): string {\n const first = normalizeNavigationPath(path).split(\"/\")[1];\n return first && first !== \"root\" && options.locales?.[first] ? first : \"root\";\n}\n\n/** Author components can render before the page initializes route locals. */\nexport function requestLanguage(\n pathname: string,\n base: string,\n options: LocaleOptions,\n): string {\n const prefix = base.replace(/\\/$/, \"\");\n const path =\n prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))\n ? pathname.slice(prefix.length)\n : pathname;\n const locale = routeLocale(path, options);\n return options.locales?.[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n}\n\nexport function localePath(path: string, options: LocaleOptions): string {\n const route = normalizeNavigationPath(path);\n const locale = routeLocale(route, options);\n return locale === \"root\"\n ? route\n : normalizeNavigationPath(route.slice(locale.length + 1));\n}\n\nexport function localizedRoute(\n path: string,\n locale: string,\n options: LocaleOptions,\n): string {\n const suffix = localePath(path, options);\n return normalizeNavigationPath(\n `${locale === \"root\" ? \"\" : `/${locale}`}${suffix}`,\n );\n}\n\n/** Missing translations use a real default-language page, then a real locale home. */\nexport function localeTarget(\n path: string,\n locale: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): string | undefined {\n const visible = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const fallback =\n options.defaultLocale ??\n (options.locales?.root\n ? \"root\"\n : (Object.keys(options.locales ?? {})[0] ?? \"root\"));\n return [\n localizedRoute(path, locale, options),\n localizedRoute(path, fallback, options),\n localizedRoute(\"/\", locale, options),\n localizedRoute(\"/\", fallback, options),\n ].find((route) => visible.has(route));\n}\n\nexport function localeHref(\n link: string,\n currentPath: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n base = \"/\",\n): string {\n if (!link.startsWith(\"/\") || link.startsWith(\"//\")) return link;\n const suffix = /[?#].*$/.exec(link)?.[0] ?? \"\";\n const path = suffix ? link.slice(0, -suffix.length) : link;\n const target = options.locales\n ? localeTarget(path, routeLocale(currentPath, options), routes, options)\n : normalizeNavigationPath(path);\n return (\n `${base.replace(/\\/$/, \"\")}${target ?? normalizeNavigationPath(path)}${suffix}` ||\n \"/\"\n );\n}\n\n/** Resolve navigation against the current locale's available routes. */\nexport function localizedNavigation(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n currentPath: string,\n options: LocaleOptions,\n): { layout: ResolvedNavigationLayout; routes: DocsRoute[] } {\n if (!options.locales) return { layout, routes };\n const locale = routeLocale(currentPath, options);\n const language =\n options.locales[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n const label = (value: string) =>\n options.translations?.[language]?.[`navigation.${value}`] ??\n options.translations?.[language.split(\"-\")[0]!]?.[`navigation.${value}`] ??\n value;\n const localRoutes = routes\n .filter((route) => routeLocale(route.route, options) === locale)\n .map((route) => ({ ...route, route: localePath(route.route, options) }));\n const available = new Set(\n localRoutes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const visibleRoutes = new Map(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => [route.route, route]),\n );\n const fallbackLocale =\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!);\n const convert = (items: NavigationItem[]): NavigationItem[] =>\n items.flatMap((item): NavigationItem[] => {\n const link = typeof item === \"string\" ? item : item.link;\n const internal = link?.startsWith(\"/\") && !link.startsWith(\"//\");\n const translated = internal ? localePath(link!, options) : link;\n const fallback = internal\n ? localizedRoute(link!, fallbackLocale, options)\n : undefined;\n const target =\n !internal || available.has(translated!)\n ? translated\n : fallback && visibleRoutes.has(fallback)\n ? fallback\n : undefined;\n if (typeof item === \"string\") {\n if (!target) return [];\n if (!internal || available.has(translated!)) return [target];\n const route = visibleRoutes.get(target)!;\n return [\n {\n label:\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n link: target,\n ...(typeof route.sidebar === \"object\" &&\n route.sidebar.badge !== undefined\n ? { badge: route.sidebar.badge }\n : {}),\n },\n ];\n }\n const sidebar =\n fallback && target === fallback\n ? visibleRoutes.get(fallback)?.sidebar\n : undefined;\n const badge =\n item.badge !== undefined\n ? label(item.badge)\n : typeof sidebar === \"object\"\n ? sidebar.badge\n : undefined;\n const presentation = badge !== undefined ? { badge } : {};\n if (\"items\" in item || \"autogenerate\" in item) {\n const { link: _link, ...group } = item;\n const children = \"items\" in item ? convert(item.items) : undefined;\n if (children?.length === 0 && !target) return [];\n return [\n {\n ...group,\n label: label(group.label),\n ...presentation,\n ...(target ? { link: target } : {}),\n ...(\"items\" in item\n ? { items: children! }\n : {\n autogenerate: {\n directory: localePath(item.autogenerate.directory, options),\n },\n }),\n },\n ];\n }\n return target\n ? [\n {\n ...item,\n label: label(item.label),\n link: target,\n ...presentation,\n },\n ]\n : [];\n });\n return {\n layout: {\n ...layout,\n ...(layout.items ? { items: convert(layout.items) } : {}),\n tabs: layout.tabs.map((tab) => ({\n ...tab,\n label: label(tab.label),\n link:\n tab.link.startsWith(\"/\") && !tab.link.startsWith(\"//\")\n ? localePath(tab.link, options)\n : tab.link,\n ...(tab.items ? { items: convert(tab.items) } : {}),\n })),\n },\n routes: localRoutes,\n };\n}\n\nexport { ENGLISH_MESSAGES, messages, type MessageKey } from \"./messages.js\";\n\nexport function localeAlternates(\n path: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): Array<{ lang: string; route: string }> {\n const available = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n if (!options.locales || !available.has(path)) return [];\n const alternates = Object.entries(options.locales).flatMap(\n ([locale, config]) => {\n const route = localizedRoute(path, locale, options);\n return available.has(route)\n ? [{ lang: config.lang ?? locale, route }]\n : [];\n },\n );\n const fallback = localizedRoute(\n path,\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!),\n options,\n );\n if (available.has(fallback))\n alternates.push({ lang: \"x-default\", route: fallback });\n return alternates;\n}\n"],"mappings":"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"}
|
package/dist/navigation.d.ts
CHANGED
|
@@ -11,13 +11,15 @@ interface ResolvedNavigationLayout {
|
|
|
11
11
|
sectioned: boolean;
|
|
12
12
|
}
|
|
13
13
|
type PageSidebarItem = {
|
|
14
|
+
badge?: string;
|
|
15
|
+
} & ({
|
|
14
16
|
label: string;
|
|
15
17
|
link: string;
|
|
16
18
|
attrs?: Record<string, string>;
|
|
17
19
|
} | {
|
|
18
20
|
label: string;
|
|
19
21
|
items: PageSidebarItem[];
|
|
20
|
-
};
|
|
22
|
+
});
|
|
21
23
|
declare function resolveNavigationLayout(navigation: DocsConfig["navigation"]): ResolvedNavigationLayout;
|
|
22
24
|
declare function navigationItemsForPath(layout: ResolvedNavigationLayout, pathname: string): NavigationItem[] | undefined;
|
|
23
25
|
/** Build a sidebar for graph-backed custom pages. */
|
package/dist/navigation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","names":[],"sources":["../src/navigation.ts"],"mappings":";;UAOiB,8BAA8B;;EAE7C;;UAGe;EACf;EACA,QAAQ;EACR,MAAM;EACN;;KAGU;
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","names":[],"sources":["../src/navigation.ts"],"mappings":";;UAOiB,8BAA8B;;EAE7C;;UAGe;EACf;EACA,QAAQ;EACR,MAAM;EACN;;KAGU;EAAoB;;EAC1B;EAAe;EAAc,QAAQ;;EACrC;EAAe,OAAO;;iBAGZ,wBACd,YAAY,2BACX;iBAoBa,uBACd,QAAQ,0BACR,mBACC;;iBAQa,YACd,QAAQ,0BACR,QAAQ,cACP;;iBAmKa,oBACd,MAAM,iBACN;iBAoBc,eAAe,kBAAkB;iBAUjC,wBAAwB"}
|
package/dist/navigation.js
CHANGED
|
@@ -26,37 +26,56 @@ function pageSidebar(layout, routes) {
|
|
|
26
26
|
const rightOrder = typeof right.sidebar === "object" ? right.sidebar.order : void 0;
|
|
27
27
|
return (leftOrder ?? Number.POSITIVE_INFINITY) - (rightOrder ?? Number.POSITIVE_INFINITY) || left.route.localeCompare(right.route);
|
|
28
28
|
});
|
|
29
|
-
const
|
|
30
|
-
const
|
|
29
|
+
const pages = new Map(visibleRoutes.map((route) => [route.route, route]));
|
|
30
|
+
const badgeFor = (link) => {
|
|
31
|
+
const sidebar = pages.get(normalizeNavigationPath(link))?.sidebar;
|
|
32
|
+
return typeof sidebar === "object" ? sidebar.badge : void 0;
|
|
33
|
+
};
|
|
34
|
+
const labelFor = (link) => {
|
|
35
|
+
const path = normalizeNavigationPath(link);
|
|
36
|
+
const page = pages.get(path);
|
|
37
|
+
return (typeof page?.sidebar === "object" && page.sidebar.label ? page.sidebar.label : page?.title) ?? path.split("/").filter(Boolean).at(-1) ?? "Home";
|
|
38
|
+
};
|
|
31
39
|
const generatedItems = (directory) => {
|
|
32
40
|
const root = normalizeNavigationPath(directory);
|
|
33
41
|
return groupedRoutes(visibleRoutes.filter((route) => root === "/" || route.route === root || route.route.startsWith(`${root}/`)));
|
|
34
42
|
};
|
|
35
43
|
const convert = (item) => {
|
|
44
|
+
const link = typeof item === "string" ? item : item.link;
|
|
45
|
+
const badge = link ? badgeFor(link) : void 0;
|
|
36
46
|
if (typeof item === "string") return {
|
|
37
47
|
label: labelFor(item),
|
|
38
|
-
link: item
|
|
48
|
+
link: item,
|
|
49
|
+
...badge !== void 0 ? { badge } : {}
|
|
39
50
|
};
|
|
51
|
+
const resolvedBadge = item.badge ?? badge;
|
|
52
|
+
const presentation = resolvedBadge !== void 0 ? { badge: resolvedBadge } : {};
|
|
40
53
|
if ("items" in item || "autogenerate" in item) {
|
|
41
54
|
let children = "items" in item ? item.items.map(convert) : generatedItems(item.autogenerate.directory);
|
|
42
55
|
if (item.link) {
|
|
43
56
|
children = withoutRoute(children, item.link);
|
|
44
57
|
if (!children.length) return {
|
|
45
58
|
label: item.label,
|
|
46
|
-
link: item.link
|
|
59
|
+
link: item.link,
|
|
60
|
+
...presentation
|
|
47
61
|
};
|
|
48
62
|
children.unshift({
|
|
49
63
|
label: item.label,
|
|
50
64
|
link: item.link,
|
|
51
|
-
attrs: { "data-cookbook-group-link": "" }
|
|
65
|
+
attrs: { "data-cookbook-group-link": "" },
|
|
66
|
+
...presentation
|
|
52
67
|
});
|
|
53
68
|
}
|
|
54
69
|
return {
|
|
55
70
|
label: item.label,
|
|
56
|
-
items: children
|
|
71
|
+
items: children,
|
|
72
|
+
...presentation
|
|
57
73
|
};
|
|
58
74
|
}
|
|
59
|
-
return
|
|
75
|
+
return {
|
|
76
|
+
...item,
|
|
77
|
+
...presentation
|
|
78
|
+
};
|
|
60
79
|
};
|
|
61
80
|
const fallback = layout.items?.length ? layout.items.map(convert) : groupedRoutes(visibleRoutes);
|
|
62
81
|
const sidebar = !layout.sectioned ? fallback : [...layout.fallbackSidebarGroup !== void 0 ? [{
|
|
@@ -76,7 +95,8 @@ function withoutRoute(items, route) {
|
|
|
76
95
|
const first = children[0];
|
|
77
96
|
if (children.length === 1 && first && "link" in first && first.attrs?.["data-cookbook-group-link"] !== void 0) return [{
|
|
78
97
|
label: item.label,
|
|
79
|
-
link: first.link
|
|
98
|
+
link: first.link,
|
|
99
|
+
...item.badge !== void 0 ? { badge: item.badge } : {}
|
|
80
100
|
}];
|
|
81
101
|
return children.length ? [{
|
|
82
102
|
...item,
|
|
@@ -90,7 +110,8 @@ function groupedRoutes(routes) {
|
|
|
90
110
|
for (const route of routes) {
|
|
91
111
|
const item = {
|
|
92
112
|
label: typeof route.sidebar === "object" && route.sidebar.label ? route.sidebar.label : route.title,
|
|
93
|
-
link: route.route
|
|
113
|
+
link: route.route,
|
|
114
|
+
...typeof route.sidebar === "object" && route.sidebar.badge !== void 0 ? { badge: route.sidebar.badge } : {}
|
|
94
115
|
};
|
|
95
116
|
const group = typeof route.sidebar === "object" ? route.sidebar.group : void 0;
|
|
96
117
|
if (!group) {
|
package/dist/navigation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.js","names":[],"sources":["../src/navigation.ts"],"sourcesContent":["import type {\n DocsConfig,\n DocsRoute,\n NavigationItem,\n NavigationTab,\n} from \"@tenphi/docs\";\n\nexport interface ResolvedNavigationTab extends NavigationTab {\n /** Index of the tab's resolved sidebar group. */\n sidebarGroup?: number;\n}\n\nexport interface ResolvedNavigationLayout {\n fallbackSidebarGroup?: number;\n items?: NavigationItem[];\n tabs: ResolvedNavigationTab[];\n sectioned: boolean;\n}\n\nexport type PageSidebarItem =\n | { label: string; link: string; attrs?: Record<string, string> }\n | { label: string; items: PageSidebarItem[] };\n\nexport function resolveNavigationLayout(\n navigation: DocsConfig[\"navigation\"],\n): ResolvedNavigationLayout {\n const items = Array.isArray(navigation) ? navigation : navigation?.items;\n const configuredTabs = Array.isArray(navigation)\n ? []\n : (navigation?.tabs ?? []);\n const fallbackSidebarGroup = items !== undefined ? 0 : undefined;\n let sidebarGroup = fallbackSidebarGroup === undefined ? 0 : 1;\n const tabs = configuredTabs.map((tab) => ({\n ...tab,\n ...(tab.items !== undefined ? { sidebarGroup: sidebarGroup++ } : {}),\n }));\n\n return {\n ...(fallbackSidebarGroup !== undefined ? { fallbackSidebarGroup } : {}),\n ...(items !== undefined ? { items } : {}),\n tabs,\n sectioned: tabs.some((tab) => tab.sidebarGroup !== undefined),\n };\n}\n\nexport function navigationItemsForPath(\n layout: ResolvedNavigationLayout,\n pathname: string,\n): NavigationItem[] | undefined {\n const active = activeNavigationTab(layout.tabs, pathname);\n return active >= 0 && layout.tabs[active]?.items !== undefined\n ? layout.tabs[active].items\n : layout.items;\n}\n\n/** Build a sidebar for graph-backed custom pages. */\nexport function pageSidebar(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n): PageSidebarItem[] {\n const visibleRoutes = routes\n .filter((route) => route.sidebar !== false && route.discoverable !== false)\n .toSorted((left, right) => {\n const leftOrder =\n typeof left.sidebar === \"object\" ? left.sidebar.order : undefined;\n const rightOrder =\n typeof right.sidebar === \"object\" ? right.sidebar.order : undefined;\n return (\n (leftOrder ?? Number.POSITIVE_INFINITY) -\n (rightOrder ?? Number.POSITIVE_INFINITY) ||\n left.route.localeCompare(right.route)\n );\n });\n const titles = new Map(\n visibleRoutes.map((route) => [\n route.route,\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n ]),\n );\n const labelFor = (route: string) =>\n titles.get(normalizeNavigationPath(route)) ??\n normalizeNavigationPath(route).split(\"/\").filter(Boolean).at(-1) ??\n \"Home\";\n const generatedItems = (directory: string) => {\n const root = normalizeNavigationPath(directory);\n return groupedRoutes(\n visibleRoutes.filter(\n (route) =>\n root === \"/\" ||\n route.route === root ||\n route.route.startsWith(`${root}/`),\n ),\n );\n };\n const convert = (item: NavigationItem): PageSidebarItem => {\n if (typeof item === \"string\") {\n return { label: labelFor(item), link: item };\n }\n if (\"items\" in item || \"autogenerate\" in item) {\n let children =\n \"items\" in item\n ? item.items.map(convert)\n : generatedItems(item.autogenerate.directory);\n if (item.link) {\n children = withoutRoute(children, item.link);\n // Keep the parent in route resolution and pagination. The sidebar\n // promotes this marked entry into the group header.\n if (!children.length) return { label: item.label, link: item.link };\n children.unshift({\n label: item.label,\n link: item.link,\n attrs: { \"data-cookbook-group-link\": \"\" },\n });\n }\n return {\n label: item.label,\n items: children,\n };\n }\n return item;\n };\n const fallback = layout.items?.length\n ? layout.items.map(convert)\n : groupedRoutes(visibleRoutes);\n const sidebar = !layout.sectioned\n ? fallback\n : [\n ...(layout.fallbackSidebarGroup !== undefined\n ? [{ label: \"Documentation\", items: fallback }]\n : []),\n ...layout.tabs.flatMap((tab) =>\n tab.items !== undefined\n ? [{ label: tab.label, items: tab.items.map(convert) }]\n : [],\n ),\n ];\n return routes\n .filter((route) => route.discoverable === false)\n .reduce((items, route) => withoutRoute(items, route.route), sidebar);\n}\n\nfunction withoutRoute(\n items: PageSidebarItem[],\n route: string,\n): PageSidebarItem[] {\n const target = normalizeNavigationPath(route);\n return items.flatMap((item): PageSidebarItem[] => {\n if (\"link\" in item) {\n return !/^(?:[a-z][a-z\\d+.-]*:|\\/\\/|[?#])/i.test(item.link) &&\n normalizeNavigationPath(item.link) === target\n ? []\n : [item];\n }\n const children = withoutRoute(item.items, route);\n const first = children[0];\n if (\n children.length === 1 &&\n first &&\n \"link\" in first &&\n first.attrs?.[\"data-cookbook-group-link\"] !== undefined\n ) {\n return [{ label: item.label, link: first.link }];\n }\n return children.length ? [{ ...item, items: children }] : [];\n });\n}\n\nfunction groupedRoutes(routes: DocsRoute[]): PageSidebarItem[] {\n const items: PageSidebarItem[] = [];\n const groups = new Map<string, PageSidebarItem[]>();\n for (const route of routes) {\n const item = {\n label:\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n link: route.route,\n };\n const group =\n typeof route.sidebar === \"object\" ? route.sidebar.group : undefined;\n if (!group) {\n items.push(item);\n continue;\n }\n const grouped = groups.get(group) ?? [];\n grouped.push(item);\n groups.set(group, grouped);\n }\n return [\n ...items,\n ...Array.from(groups, ([label, grouped]) => ({ label, items: grouped })),\n ];\n}\n\n/** Pick one tab, preferring its own URL before routes owned by its sidebar. */\nexport function activeNavigationTab(\n tabs: NavigationTab[],\n pathname: string,\n): number {\n const current = normalizeNavigationPath(pathname);\n let winner = -1;\n let winningScore = -1;\n\n for (const [index, tab] of tabs.entries()) {\n const score = Math.max(\n linkMatchScore(tab.link, current, 30_000),\n navigationMatchScore(tab.items ?? [], current),\n );\n if (score > winningScore) {\n winner = index;\n winningScore = score;\n }\n }\n\n return winningScore >= 0 ? winner : -1;\n}\n\nexport function navigationPath(pathname: string, base = \"/\"): string {\n const normalizedBase = normalizeNavigationPath(base);\n const withoutBase =\n normalizedBase !== \"/\" &&\n (pathname === normalizedBase || pathname.startsWith(`${normalizedBase}/`))\n ? pathname.slice(normalizedBase.length) || \"/\"\n : pathname;\n return normalizeNavigationPath(withoutBase);\n}\n\nexport function normalizeNavigationPath(path: string): string {\n const clean = path.split(/[?#]/, 1)[0]?.replace(/\\\\/g, \"/\") ?? \"/\";\n const normalized = `/${clean.replace(/^\\/+|\\/+$/g, \"\")}`;\n return normalized === \"/\" ? normalized : normalized.replace(/\\/$/, \"\");\n}\n\nfunction navigationMatchScore(\n items: NavigationItem[],\n current: string,\n): number {\n let score = -1;\n for (const item of items) {\n if (typeof item === \"string\") {\n if (normalizeNavigationPath(item) === current)\n score = Math.max(score, 20_000);\n continue;\n }\n if (item.link) {\n score = Math.max(score, linkMatchScore(item.link, current, 20_000));\n }\n if (\"items\" in item) {\n score = Math.max(score, navigationMatchScore(item.items, current));\n continue;\n }\n if (\"autogenerate\" in item) {\n score = Math.max(\n score,\n directoryMatchScore(item.autogenerate.directory, current),\n );\n continue;\n }\n }\n return score;\n}\n\nfunction linkMatchScore(link: string, current: string, base: number): number {\n if (!link.startsWith(\"/\")) return -1;\n const target = normalizeNavigationPath(link);\n if (target === current) return base + 1_000 + target.length;\n if (target !== \"/\" && current.startsWith(`${target}/`)) {\n return base + target.length;\n }\n return -1;\n}\n\nfunction directoryMatchScore(directory: string, current: string): number {\n const target = normalizeNavigationPath(directory);\n if (target === \"/\") return 10_000;\n return current === target || current.startsWith(`${target}/`)\n ? 10_000 + target.length\n : -1;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"navigation.js","names":[],"sources":["../src/navigation.ts"],"sourcesContent":["import type {\n DocsConfig,\n DocsRoute,\n NavigationItem,\n NavigationTab,\n} from \"@tenphi/docs\";\n\nexport interface ResolvedNavigationTab extends NavigationTab {\n /** Index of the tab's resolved sidebar group. */\n sidebarGroup?: number;\n}\n\nexport interface ResolvedNavigationLayout {\n fallbackSidebarGroup?: number;\n items?: NavigationItem[];\n tabs: ResolvedNavigationTab[];\n sectioned: boolean;\n}\n\nexport type PageSidebarItem = { badge?: string } & (\n | { label: string; link: string; attrs?: Record<string, string> }\n | { label: string; items: PageSidebarItem[] }\n);\n\nexport function resolveNavigationLayout(\n navigation: DocsConfig[\"navigation\"],\n): ResolvedNavigationLayout {\n const items = Array.isArray(navigation) ? navigation : navigation?.items;\n const configuredTabs = Array.isArray(navigation)\n ? []\n : (navigation?.tabs ?? []);\n const fallbackSidebarGroup = items !== undefined ? 0 : undefined;\n let sidebarGroup = fallbackSidebarGroup === undefined ? 0 : 1;\n const tabs = configuredTabs.map((tab) => ({\n ...tab,\n ...(tab.items !== undefined ? { sidebarGroup: sidebarGroup++ } : {}),\n }));\n\n return {\n ...(fallbackSidebarGroup !== undefined ? { fallbackSidebarGroup } : {}),\n ...(items !== undefined ? { items } : {}),\n tabs,\n sectioned: tabs.some((tab) => tab.sidebarGroup !== undefined),\n };\n}\n\nexport function navigationItemsForPath(\n layout: ResolvedNavigationLayout,\n pathname: string,\n): NavigationItem[] | undefined {\n const active = activeNavigationTab(layout.tabs, pathname);\n return active >= 0 && layout.tabs[active]?.items !== undefined\n ? layout.tabs[active].items\n : layout.items;\n}\n\n/** Build a sidebar for graph-backed custom pages. */\nexport function pageSidebar(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n): PageSidebarItem[] {\n const visibleRoutes = routes\n .filter((route) => route.sidebar !== false && route.discoverable !== false)\n .toSorted((left, right) => {\n const leftOrder =\n typeof left.sidebar === \"object\" ? left.sidebar.order : undefined;\n const rightOrder =\n typeof right.sidebar === \"object\" ? right.sidebar.order : undefined;\n return (\n (leftOrder ?? Number.POSITIVE_INFINITY) -\n (rightOrder ?? Number.POSITIVE_INFINITY) ||\n left.route.localeCompare(right.route)\n );\n });\n const pages = new Map(visibleRoutes.map((route) => [route.route, route]));\n const badgeFor = (link: string) => {\n const sidebar = pages.get(normalizeNavigationPath(link))?.sidebar;\n return typeof sidebar === \"object\" ? sidebar.badge : undefined;\n };\n const labelFor = (link: string) => {\n const path = normalizeNavigationPath(link);\n const page = pages.get(path);\n return (\n (typeof page?.sidebar === \"object\" && page.sidebar.label\n ? page.sidebar.label\n : page?.title) ??\n path.split(\"/\").filter(Boolean).at(-1) ??\n \"Home\"\n );\n };\n const generatedItems = (directory: string) => {\n const root = normalizeNavigationPath(directory);\n return groupedRoutes(\n visibleRoutes.filter(\n (route) =>\n root === \"/\" ||\n route.route === root ||\n route.route.startsWith(`${root}/`),\n ),\n );\n };\n const convert = (item: NavigationItem): PageSidebarItem => {\n const link = typeof item === \"string\" ? item : item.link;\n const badge = link ? badgeFor(link) : undefined;\n if (typeof item === \"string\") {\n return {\n label: labelFor(item),\n link: item,\n ...(badge !== undefined ? { badge } : {}),\n };\n }\n const resolvedBadge = item.badge ?? badge;\n const presentation =\n resolvedBadge !== undefined ? { badge: resolvedBadge } : {};\n if (\"items\" in item || \"autogenerate\" in item) {\n let children =\n \"items\" in item\n ? item.items.map(convert)\n : generatedItems(item.autogenerate.directory);\n if (item.link) {\n children = withoutRoute(children, item.link);\n // Keep the parent in route resolution and pagination. The sidebar\n // promotes this marked entry into the group header.\n if (!children.length)\n return { label: item.label, link: item.link, ...presentation };\n children.unshift({\n label: item.label,\n link: item.link,\n attrs: { \"data-cookbook-group-link\": \"\" },\n ...presentation,\n });\n }\n return {\n label: item.label,\n items: children,\n ...presentation,\n };\n }\n return { ...item, ...presentation };\n };\n const fallback = layout.items?.length\n ? layout.items.map(convert)\n : groupedRoutes(visibleRoutes);\n const sidebar = !layout.sectioned\n ? fallback\n : [\n ...(layout.fallbackSidebarGroup !== undefined\n ? [{ label: \"Documentation\", items: fallback }]\n : []),\n ...layout.tabs.flatMap((tab) =>\n tab.items !== undefined\n ? [{ label: tab.label, items: tab.items.map(convert) }]\n : [],\n ),\n ];\n return routes\n .filter((route) => route.discoverable === false)\n .reduce((items, route) => withoutRoute(items, route.route), sidebar);\n}\n\nfunction withoutRoute(\n items: PageSidebarItem[],\n route: string,\n): PageSidebarItem[] {\n const target = normalizeNavigationPath(route);\n return items.flatMap((item): PageSidebarItem[] => {\n if (\"link\" in item) {\n return !/^(?:[a-z][a-z\\d+.-]*:|\\/\\/|[?#])/i.test(item.link) &&\n normalizeNavigationPath(item.link) === target\n ? []\n : [item];\n }\n const children = withoutRoute(item.items, route);\n const first = children[0];\n if (\n children.length === 1 &&\n first &&\n \"link\" in first &&\n first.attrs?.[\"data-cookbook-group-link\"] !== undefined\n ) {\n return [\n {\n label: item.label,\n link: first.link,\n ...(item.badge !== undefined ? { badge: item.badge } : {}),\n },\n ];\n }\n return children.length ? [{ ...item, items: children }] : [];\n });\n}\n\nfunction groupedRoutes(routes: DocsRoute[]): PageSidebarItem[] {\n const items: PageSidebarItem[] = [];\n const groups = new Map<string, PageSidebarItem[]>();\n for (const route of routes) {\n const item = {\n label:\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n link: route.route,\n ...(typeof route.sidebar === \"object\" && route.sidebar.badge !== undefined\n ? { badge: route.sidebar.badge }\n : {}),\n };\n const group =\n typeof route.sidebar === \"object\" ? route.sidebar.group : undefined;\n if (!group) {\n items.push(item);\n continue;\n }\n const grouped = groups.get(group) ?? [];\n grouped.push(item);\n groups.set(group, grouped);\n }\n return [\n ...items,\n ...Array.from(groups, ([label, grouped]) => ({ label, items: grouped })),\n ];\n}\n\n/** Pick one tab, preferring its own URL before routes owned by its sidebar. */\nexport function activeNavigationTab(\n tabs: NavigationTab[],\n pathname: string,\n): number {\n const current = normalizeNavigationPath(pathname);\n let winner = -1;\n let winningScore = -1;\n\n for (const [index, tab] of tabs.entries()) {\n const score = Math.max(\n linkMatchScore(tab.link, current, 30_000),\n navigationMatchScore(tab.items ?? [], current),\n );\n if (score > winningScore) {\n winner = index;\n winningScore = score;\n }\n }\n\n return winningScore >= 0 ? winner : -1;\n}\n\nexport function navigationPath(pathname: string, base = \"/\"): string {\n const normalizedBase = normalizeNavigationPath(base);\n const withoutBase =\n normalizedBase !== \"/\" &&\n (pathname === normalizedBase || pathname.startsWith(`${normalizedBase}/`))\n ? pathname.slice(normalizedBase.length) || \"/\"\n : pathname;\n return normalizeNavigationPath(withoutBase);\n}\n\nexport function normalizeNavigationPath(path: string): string {\n const clean = path.split(/[?#]/, 1)[0]?.replace(/\\\\/g, \"/\") ?? \"/\";\n const normalized = `/${clean.replace(/^\\/+|\\/+$/g, \"\")}`;\n return normalized === \"/\" ? normalized : normalized.replace(/\\/$/, \"\");\n}\n\nfunction navigationMatchScore(\n items: NavigationItem[],\n current: string,\n): number {\n let score = -1;\n for (const item of items) {\n if (typeof item === \"string\") {\n if (normalizeNavigationPath(item) === current)\n score = Math.max(score, 20_000);\n continue;\n }\n if (item.link) {\n score = Math.max(score, linkMatchScore(item.link, current, 20_000));\n }\n if (\"items\" in item) {\n score = Math.max(score, navigationMatchScore(item.items, current));\n continue;\n }\n if (\"autogenerate\" in item) {\n score = Math.max(\n score,\n directoryMatchScore(item.autogenerate.directory, current),\n );\n continue;\n }\n }\n return score;\n}\n\nfunction linkMatchScore(link: string, current: string, base: number): number {\n if (!link.startsWith(\"/\")) return -1;\n const target = normalizeNavigationPath(link);\n if (target === current) return base + 1_000 + target.length;\n if (target !== \"/\" && current.startsWith(`${target}/`)) {\n return base + target.length;\n }\n return -1;\n}\n\nfunction directoryMatchScore(directory: string, current: string): number {\n const target = normalizeNavigationPath(directory);\n if (target === \"/\") return 10_000;\n return current === target || current.startsWith(`${target}/`)\n ? 10_000 + target.length\n : -1;\n}\n"],"mappings":"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"}
|
package/dist/route-context.d.ts
CHANGED
|
@@ -7,20 +7,12 @@ type SidebarEntry = {
|
|
|
7
7
|
href: string;
|
|
8
8
|
isCurrent: boolean;
|
|
9
9
|
attrs: Record<string, string>;
|
|
10
|
-
badge?:
|
|
11
|
-
text: string;
|
|
12
|
-
variant?: string;
|
|
13
|
-
class?: string;
|
|
14
|
-
};
|
|
10
|
+
badge?: string;
|
|
15
11
|
} | {
|
|
16
12
|
type: "group";
|
|
17
13
|
label: string;
|
|
18
14
|
entries: SidebarEntry[];
|
|
19
|
-
badge?:
|
|
20
|
-
text: string;
|
|
21
|
-
variant?: string;
|
|
22
|
-
class?: string;
|
|
23
|
-
};
|
|
15
|
+
badge?: string;
|
|
24
16
|
};
|
|
25
17
|
interface TocItem {
|
|
26
18
|
slug: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-context.d.ts","names":[],"sources":["../src/route-context.ts"],"mappings":";;;KAoBY;EAEN;EACA;EACA;EACA;EACA,OAAO;EACP;
|
|
1
|
+
{"version":3,"file":"route-context.d.ts","names":[],"sources":["../src/route-context.ts"],"mappings":";;;KAoBY;EAEN;EACA;EACA;EACA;EACA,OAAO;EACP;;EAGA;EACA;EACA,SAAS;EACT;;UAGW;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;IAAS,MAAM;;EACf;IAAa;IAAc;IAAoB;;EAC/C,SAAS;EACT;IACE;MAAS;MAAc;;IACvB;MAAS;MAAc;;;EAEzB;IAAQ,OAAO;;EACf,MAAM;EACN;EACA,cAAc;;KAGX;EACH,QAAQ;EACR;EACA;IAAQ;IAAgB;;EACxB,UAAU;EACV;EACA,eAAe;EACf,kBAAkB;EAClB,OAAO;;iBAGO,mBAAmB;EACjC;EACA,aAAa;EACb,UAAU;EACV,QAAQ;EACR,SAAS;IACP"}
|
package/dist/route-context.js
CHANGED
|
@@ -59,13 +59,15 @@ function resolveSidebar(items, currentPath, content) {
|
|
|
59
59
|
label: item.label,
|
|
60
60
|
href,
|
|
61
61
|
isCurrent: href.startsWith("/") && !href.startsWith("//") && navigationPath(new URL(href, "https://cookbook.invalid").pathname, content.base) === currentPath,
|
|
62
|
-
attrs: item.attrs ?? {}
|
|
62
|
+
attrs: item.attrs ?? {},
|
|
63
|
+
...item.badge !== void 0 ? { badge: item.badge } : {}
|
|
63
64
|
};
|
|
64
65
|
}
|
|
65
66
|
return {
|
|
66
67
|
type: "group",
|
|
67
68
|
label: item.label,
|
|
68
|
-
entries: resolveSidebar(item.items, currentPath, content)
|
|
69
|
+
entries: resolveSidebar(item.items, currentPath, content),
|
|
70
|
+
...item.badge !== void 0 ? { badge: item.badge } : {}
|
|
69
71
|
};
|
|
70
72
|
});
|
|
71
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-context.js","names":[],"sources":["../src/route-context.ts"],"sourcesContent":["import type {\n DocsConfig,\n DocsHeading,\n DocsRoute,\n HeadConfig,\n} from \"@tenphi/docs\";\nimport {\n localeHref,\n localizedNavigation,\n requestLanguage,\n routeLocale,\n} from \"./localization.js\";\nimport {\n navigationPath,\n normalizeNavigationPath,\n pageSidebar,\n type ResolvedNavigationLayout,\n type PageSidebarItem,\n} from \"./navigation.js\";\n\nexport type SidebarEntry =\n | {\n type: \"link\";\n label: string;\n href: string;\n isCurrent: boolean;\n attrs: Record<string, string>;\n badge?: { text: string; variant?: string; class?: string };\n }\n | {\n type: \"group\";\n label: string;\n entries: SidebarEntry[];\n badge?: { text: string; variant?: string; class?: string };\n };\n\nexport interface TocItem {\n slug: string;\n text: string;\n children: TocItem[];\n}\n\nexport interface CookbookRoute {\n id: string;\n lang: string;\n dir: \"ltr\" | \"rtl\";\n hasSidebar: boolean;\n siteTitle: string;\n siteTitleHref: string;\n entry: { data: Record<string, any> };\n entryMeta: { lang: string; dir: \"ltr\" | \"rtl\"; locale: string };\n sidebar: SidebarEntry[];\n pagination: {\n prev?: { href: string; label: string };\n next?: { href: string; label: string };\n };\n toc?: { items: TocItem[] };\n head: HeadConfig[];\n editUrl?: string;\n lastUpdated?: Date;\n}\n\ntype Content = {\n routes: DocsRoute[];\n base: string;\n site: { title?: string; description?: string };\n locales?: DocsConfig[\"locales\"];\n defaultLocale?: string;\n translations?: DocsConfig[\"translations\"];\n tableOfContents?: DocsConfig[\"tableOfContents\"];\n head?: HeadConfig[];\n};\n\nexport function createRouteContext(input: {\n pathname: string;\n frontmatter: Record<string, any>;\n headings: DocsHeading[];\n layout: ResolvedNavigationLayout;\n content: Content;\n}): CookbookRoute {\n const { pathname, frontmatter, headings, layout, content } = input;\n const currentPath = navigationPath(pathname, content.base);\n const locale = routeLocale(currentPath, content);\n const lang = requestLanguage(pathname, content.base, content);\n const dir = content.locales?.[locale]?.dir ?? \"ltr\";\n const localized = localizedNavigation(\n layout,\n content.routes,\n currentPath,\n content,\n );\n const sidebar = resolveSidebar(\n pageSidebar(localized.layout, localized.routes),\n currentPath,\n content,\n );\n const links = flattenLinks(sidebar);\n const currentIndex = links.findIndex((link) => link.isCurrent);\n const previous = resolvePaginationLink(\n frontmatter.prev,\n currentIndex >= 0 ? links[currentIndex - 1] : undefined,\n content,\n currentPath,\n );\n const next = resolvePaginationLink(\n frontmatter.next,\n currentIndex >= 0 ? links[currentIndex + 1] : undefined,\n content,\n currentPath,\n );\n const pagination = {\n ...(previous ? { prev: previous } : {}),\n ...(next ? { next } : {}),\n };\n const toc = resolveToc(headings, frontmatter, content);\n const head: HeadConfig[] = [\n ...(content.head ?? []),\n ...(frontmatter.head ?? []),\n ...(frontmatter.description || content.site.description\n ? [\n {\n tag: \"meta\",\n attrs: {\n name: \"description\",\n content: frontmatter.description ?? content.site.description,\n },\n },\n ]\n : []),\n ];\n return {\n id: currentPath,\n lang,\n dir,\n hasSidebar: frontmatter.template !== \"splash\",\n siteTitle: content.site.title ?? \"Documentation\",\n siteTitleHref: content.base,\n entry: { data: frontmatter },\n entryMeta: { lang, dir, locale },\n sidebar,\n pagination,\n ...(toc ? { toc } : {}),\n head,\n ...(typeof frontmatter.editUrl === \"string\"\n ? { editUrl: frontmatter.editUrl }\n : {}),\n ...(frontmatter.lastUpdated instanceof Date\n ? { lastUpdated: frontmatter.lastUpdated }\n : {}),\n };\n}\n\nfunction resolveSidebar(\n items: PageSidebarItem[],\n currentPath: string,\n content: Content,\n): SidebarEntry[] {\n return items.map((item): SidebarEntry => {\n if (\"link\" in item) {\n const href = localeHref(\n item.link,\n currentPath,\n content.routes,\n content,\n content.base,\n );\n return {\n type: \"link\",\n label: item.label,\n href,\n isCurrent:\n href.startsWith(\"/\") &&\n !href.startsWith(\"//\") &&\n navigationPath(\n new URL(href, \"https://cookbook.invalid\").pathname,\n content.base,\n ) === currentPath,\n attrs: item.attrs ?? {},\n };\n }\n return {\n type: \"group\",\n label: item.label,\n entries: resolveSidebar(item.items, currentPath, content),\n };\n });\n}\n\nfunction flattenLinks(\n items: SidebarEntry[],\n): Extract<SidebarEntry, { type: \"link\" }>[] {\n return items.flatMap((item) =>\n item.type === \"link\" ? [item] : flattenLinks(item.entries),\n );\n}\n\nfunction resolvePaginationLink(\n configured: unknown,\n automatic: Extract<SidebarEntry, { type: \"link\" }> | undefined,\n content: Content,\n currentPath: string,\n): { href: string; label: string } | undefined {\n if (configured === false) return undefined;\n if (configured === undefined)\n return automatic && { href: automatic.href, label: automatic.label };\n const link =\n typeof configured === \"string\"\n ? configured\n : configured &&\n typeof configured === \"object\" &&\n \"link\" in configured &&\n typeof configured.link === \"string\"\n ? configured.link\n : automatic?.href;\n if (!link) return undefined;\n const label =\n configured &&\n typeof configured === \"object\" &&\n \"label\" in configured &&\n typeof configured.label === \"string\"\n ? configured.label\n : (content.routes.find(\n (route) =>\n normalizeNavigationPath(route.route) ===\n normalizeNavigationPath(link),\n )?.title ??\n automatic?.label ??\n link);\n return {\n href: localeHref(link, currentPath, content.routes, content, content.base),\n label,\n };\n}\n\nfunction resolveToc(\n headings: DocsHeading[],\n frontmatter: Record<string, any>,\n content: Content,\n): { items: TocItem[] } | undefined {\n const option =\n frontmatter.tableOfContents ??\n (frontmatter.template === \"splash\" ? false : content.tableOfContents);\n if (option === false) return undefined;\n const min = typeof option === \"object\" ? (option.minHeadingLevel ?? 2) : 2;\n const max = typeof option === \"object\" ? (option.maxHeadingLevel ?? 3) : 3;\n const roots: TocItem[] = [];\n const stack: Array<{ depth: number; item: TocItem }> = [];\n for (const heading of headings) {\n if (heading.depth < min || heading.depth > max) continue;\n const item: TocItem = {\n slug: heading.slug,\n text: heading.text,\n children: [],\n };\n while (stack.length && stack[stack.length - 1]!.depth >= heading.depth)\n stack.pop();\n if (stack.length) stack[stack.length - 1]!.item.children.push(item);\n else roots.push(item);\n stack.push({ depth: heading.depth, item });\n }\n return roots.length ? { items: roots } : undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"route-context.js","names":[],"sources":["../src/route-context.ts"],"sourcesContent":["import type {\n DocsConfig,\n DocsHeading,\n DocsRoute,\n HeadConfig,\n} from \"@tenphi/docs\";\nimport {\n localeHref,\n localizedNavigation,\n requestLanguage,\n routeLocale,\n} from \"./localization.js\";\nimport {\n navigationPath,\n normalizeNavigationPath,\n pageSidebar,\n type ResolvedNavigationLayout,\n type PageSidebarItem,\n} from \"./navigation.js\";\n\nexport type SidebarEntry =\n | {\n type: \"link\";\n label: string;\n href: string;\n isCurrent: boolean;\n attrs: Record<string, string>;\n badge?: string;\n }\n | {\n type: \"group\";\n label: string;\n entries: SidebarEntry[];\n badge?: string;\n };\n\nexport interface TocItem {\n slug: string;\n text: string;\n children: TocItem[];\n}\n\nexport interface CookbookRoute {\n id: string;\n lang: string;\n dir: \"ltr\" | \"rtl\";\n hasSidebar: boolean;\n siteTitle: string;\n siteTitleHref: string;\n entry: { data: Record<string, any> };\n entryMeta: { lang: string; dir: \"ltr\" | \"rtl\"; locale: string };\n sidebar: SidebarEntry[];\n pagination: {\n prev?: { href: string; label: string };\n next?: { href: string; label: string };\n };\n toc?: { items: TocItem[] };\n head: HeadConfig[];\n editUrl?: string;\n lastUpdated?: Date;\n}\n\ntype Content = {\n routes: DocsRoute[];\n base: string;\n site: { title?: string; description?: string };\n locales?: DocsConfig[\"locales\"];\n defaultLocale?: string;\n translations?: DocsConfig[\"translations\"];\n tableOfContents?: DocsConfig[\"tableOfContents\"];\n head?: HeadConfig[];\n};\n\nexport function createRouteContext(input: {\n pathname: string;\n frontmatter: Record<string, any>;\n headings: DocsHeading[];\n layout: ResolvedNavigationLayout;\n content: Content;\n}): CookbookRoute {\n const { pathname, frontmatter, headings, layout, content } = input;\n const currentPath = navigationPath(pathname, content.base);\n const locale = routeLocale(currentPath, content);\n const lang = requestLanguage(pathname, content.base, content);\n const dir = content.locales?.[locale]?.dir ?? \"ltr\";\n const localized = localizedNavigation(\n layout,\n content.routes,\n currentPath,\n content,\n );\n const sidebar = resolveSidebar(\n pageSidebar(localized.layout, localized.routes),\n currentPath,\n content,\n );\n const links = flattenLinks(sidebar);\n const currentIndex = links.findIndex((link) => link.isCurrent);\n const previous = resolvePaginationLink(\n frontmatter.prev,\n currentIndex >= 0 ? links[currentIndex - 1] : undefined,\n content,\n currentPath,\n );\n const next = resolvePaginationLink(\n frontmatter.next,\n currentIndex >= 0 ? links[currentIndex + 1] : undefined,\n content,\n currentPath,\n );\n const pagination = {\n ...(previous ? { prev: previous } : {}),\n ...(next ? { next } : {}),\n };\n const toc = resolveToc(headings, frontmatter, content);\n const head: HeadConfig[] = [\n ...(content.head ?? []),\n ...(frontmatter.head ?? []),\n ...(frontmatter.description || content.site.description\n ? [\n {\n tag: \"meta\",\n attrs: {\n name: \"description\",\n content: frontmatter.description ?? content.site.description,\n },\n },\n ]\n : []),\n ];\n return {\n id: currentPath,\n lang,\n dir,\n hasSidebar: frontmatter.template !== \"splash\",\n siteTitle: content.site.title ?? \"Documentation\",\n siteTitleHref: content.base,\n entry: { data: frontmatter },\n entryMeta: { lang, dir, locale },\n sidebar,\n pagination,\n ...(toc ? { toc } : {}),\n head,\n ...(typeof frontmatter.editUrl === \"string\"\n ? { editUrl: frontmatter.editUrl }\n : {}),\n ...(frontmatter.lastUpdated instanceof Date\n ? { lastUpdated: frontmatter.lastUpdated }\n : {}),\n };\n}\n\nfunction resolveSidebar(\n items: PageSidebarItem[],\n currentPath: string,\n content: Content,\n): SidebarEntry[] {\n return items.map((item): SidebarEntry => {\n if (\"link\" in item) {\n const href = localeHref(\n item.link,\n currentPath,\n content.routes,\n content,\n content.base,\n );\n return {\n type: \"link\",\n label: item.label,\n href,\n isCurrent:\n href.startsWith(\"/\") &&\n !href.startsWith(\"//\") &&\n navigationPath(\n new URL(href, \"https://cookbook.invalid\").pathname,\n content.base,\n ) === currentPath,\n attrs: item.attrs ?? {},\n ...(item.badge !== undefined ? { badge: item.badge } : {}),\n };\n }\n return {\n type: \"group\",\n label: item.label,\n entries: resolveSidebar(item.items, currentPath, content),\n ...(item.badge !== undefined ? { badge: item.badge } : {}),\n };\n });\n}\n\nfunction flattenLinks(\n items: SidebarEntry[],\n): Extract<SidebarEntry, { type: \"link\" }>[] {\n return items.flatMap((item) =>\n item.type === \"link\" ? [item] : flattenLinks(item.entries),\n );\n}\n\nfunction resolvePaginationLink(\n configured: unknown,\n automatic: Extract<SidebarEntry, { type: \"link\" }> | undefined,\n content: Content,\n currentPath: string,\n): { href: string; label: string } | undefined {\n if (configured === false) return undefined;\n if (configured === undefined)\n return automatic && { href: automatic.href, label: automatic.label };\n const link =\n typeof configured === \"string\"\n ? configured\n : configured &&\n typeof configured === \"object\" &&\n \"link\" in configured &&\n typeof configured.link === \"string\"\n ? configured.link\n : automatic?.href;\n if (!link) return undefined;\n const label =\n configured &&\n typeof configured === \"object\" &&\n \"label\" in configured &&\n typeof configured.label === \"string\"\n ? configured.label\n : (content.routes.find(\n (route) =>\n normalizeNavigationPath(route.route) ===\n normalizeNavigationPath(link),\n )?.title ??\n automatic?.label ??\n link);\n return {\n href: localeHref(link, currentPath, content.routes, content, content.base),\n label,\n };\n}\n\nfunction resolveToc(\n headings: DocsHeading[],\n frontmatter: Record<string, any>,\n content: Content,\n): { items: TocItem[] } | undefined {\n const option =\n frontmatter.tableOfContents ??\n (frontmatter.template === \"splash\" ? false : content.tableOfContents);\n if (option === false) return undefined;\n const min = typeof option === \"object\" ? (option.minHeadingLevel ?? 2) : 2;\n const max = typeof option === \"object\" ? (option.maxHeadingLevel ?? 3) : 3;\n const roots: TocItem[] = [];\n const stack: Array<{ depth: number; item: TocItem }> = [];\n for (const heading of headings) {\n if (heading.depth < min || heading.depth > max) continue;\n const item: TocItem = {\n slug: heading.slug,\n text: heading.text,\n children: [],\n };\n while (stack.length && stack[stack.length - 1]!.depth >= heading.depth)\n stack.pop();\n if (stack.length) stack[stack.length - 1]!.item.children.push(item);\n else roots.push(item);\n stack.push({ depth: heading.depth, item });\n }\n return roots.length ? { items: roots } : undefined;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenphi/renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "Astro renderer and Tasty theme for Cookbook",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"@fontsource-variable/jetbrains-mono": "^5.3.0",
|
|
62
62
|
"@fontsource-variable/onest": "^5.3.0",
|
|
63
63
|
"@pagefind/default-ui": "1.5.2",
|
|
64
|
-
"@tenphi/docs": "0.
|
|
65
|
-
"@tenphi/eslint-plugin-tasty": "1.
|
|
66
|
-
"@tenphi/glaze": "2.0.
|
|
67
|
-
"@tenphi/tasty": "3.9.
|
|
64
|
+
"@tenphi/docs": "0.22.1",
|
|
65
|
+
"@tenphi/eslint-plugin-tasty": "1.6.0",
|
|
66
|
+
"@tenphi/glaze": "2.0.1",
|
|
67
|
+
"@tenphi/tasty": "3.9.9",
|
|
68
68
|
"beautiful-mermaid": "^1.1.3",
|
|
69
69
|
"hast-util-from-html": "^2.0.3",
|
|
70
70
|
"pagefind": "1.5.2",
|