@takazudo/zudo-doc 0.2.22 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/bin/zudo-doc.mjs +83 -0
  2. package/dist/eject/index.d.ts +33 -0
  3. package/dist/eject/index.js +229 -0
  4. package/dist/plugins/routes.d.ts +2 -0
  5. package/dist/plugins/routes.js +100 -0
  6. package/dist/preset.d.ts +47 -1
  7. package/dist/preset.js +29 -13
  8. package/dist/routes/404.d.ts +7 -0
  9. package/dist/routes/404.js +47 -0
  10. package/dist/routes/_chrome.d.ts +32 -0
  11. package/dist/routes/_chrome.js +365 -0
  12. package/dist/routes/_context.d.ts +56 -0
  13. package/dist/routes/_context.js +222 -0
  14. package/dist/routes/_docs-helpers.d.ts +43 -0
  15. package/dist/routes/_docs-helpers.js +173 -0
  16. package/dist/routes/_virtual.d.js +0 -0
  17. package/dist/routes/api-ai-chat.d.ts +5 -0
  18. package/dist/routes/api-ai-chat.js +24 -0
  19. package/dist/routes/docs-slug.d.ts +21 -0
  20. package/dist/routes/docs-slug.js +26 -0
  21. package/dist/routes/docs-tags-index.d.ts +7 -0
  22. package/dist/routes/docs-tags-index.js +11 -0
  23. package/dist/routes/docs-tags-tag.d.ts +23 -0
  24. package/dist/routes/docs-tags-tag.js +19 -0
  25. package/dist/routes/docs-versions.d.ts +7 -0
  26. package/dist/routes/docs-versions.js +11 -0
  27. package/dist/routes/index.d.ts +7 -0
  28. package/dist/routes/index.js +117 -0
  29. package/dist/routes/locale-docs-slug.d.ts +27 -0
  30. package/dist/routes/locale-docs-slug.js +40 -0
  31. package/dist/routes/locale-docs-tags-index.d.ts +18 -0
  32. package/dist/routes/locale-docs-tags-index.js +15 -0
  33. package/dist/routes/locale-docs-tags-tag.d.ts +25 -0
  34. package/dist/routes/locale-docs-tags-tag.js +22 -0
  35. package/dist/routes/locale-docs-versions.d.ts +18 -0
  36. package/dist/routes/locale-docs-versions.js +15 -0
  37. package/dist/routes/locale-index.d.ts +24 -0
  38. package/dist/routes/locale-index.js +132 -0
  39. package/dist/routes/robots.txt.d.ts +3 -0
  40. package/dist/routes/robots.txt.js +8 -0
  41. package/dist/routes/sitemap.xml.d.ts +5 -0
  42. package/dist/routes/sitemap.xml.js +31 -0
  43. package/dist/routes/v-docs-slug.d.ts +27 -0
  44. package/dist/routes/v-docs-slug.js +34 -0
  45. package/dist/routes/v-locale-docs-slug.d.ts +31 -0
  46. package/dist/routes/v-locale-docs-slug.js +50 -0
  47. package/dist/safelist.css +1 -1
  48. package/dist/settings.d.ts +15 -0
  49. package/eject/breadcrumb/breadcrumb.tsx +194 -0
  50. package/eject/breadcrumb/find-path.ts +26 -0
  51. package/eject/breadcrumb/index.ts +4 -0
  52. package/eject/breadcrumb/types.ts +32 -0
  53. package/eject/code-group/index.tsx +78 -0
  54. package/eject/content-admonition/index.tsx +50 -0
  55. package/eject/details/details.tsx +34 -0
  56. package/eject/details/index.ts +4 -0
  57. package/eject/doc-pager/index.tsx +91 -0
  58. package/eject/footer/footer.tsx +167 -0
  59. package/eject/footer/index.ts +19 -0
  60. package/eject/footer/types.ts +60 -0
  61. package/eject/header/header.tsx +725 -0
  62. package/eject/header/index.ts +36 -0
  63. package/eject/header/nav-active.ts +122 -0
  64. package/eject/header/nav-overflow-script.ts +302 -0
  65. package/eject/header/right-items.ts +78 -0
  66. package/eject/header/types.ts +69 -0
  67. package/eject/page-loading/index.ts +10 -0
  68. package/eject/page-loading/page-loading-overlay.tsx +103 -0
  69. package/eject/sidebar/index.ts +27 -0
  70. package/eject/sidebar/sidebar.tsx +137 -0
  71. package/eject/sidebar/types.ts +73 -0
  72. package/eject/tab-item/index.ts +7 -0
  73. package/eject/tab-item/tab-item.tsx +70 -0
  74. package/eject/theme-toggle/color-scheme-sync.ts +73 -0
  75. package/eject/theme-toggle/index.tsx +120 -0
  76. package/eject/toc/cx.ts +38 -0
  77. package/eject/toc/index.ts +11 -0
  78. package/eject/toc/mobile-toc.tsx +133 -0
  79. package/eject/toc/toc-title.ts +33 -0
  80. package/eject/toc/toc.tsx +119 -0
  81. package/eject/toc/types.ts +14 -0
  82. package/eject/toc/use-active-heading.ts +162 -0
  83. package/package.json +87 -7
  84. package/routes-src/404.tsx +49 -0
  85. package/routes-src/_chrome.tsx +470 -0
  86. package/routes-src/_context.ts +314 -0
  87. package/routes-src/_docs-helpers.ts +284 -0
  88. package/routes-src/_virtual.d.ts +15 -0
  89. package/routes-src/api-ai-chat.tsx +46 -0
  90. package/routes-src/docs-slug.tsx +43 -0
  91. package/routes-src/docs-tags-index.tsx +14 -0
  92. package/routes-src/docs-tags-tag.tsx +29 -0
  93. package/routes-src/docs-versions.tsx +15 -0
  94. package/routes-src/index.tsx +134 -0
  95. package/routes-src/locale-docs-slug.tsx +69 -0
  96. package/routes-src/locale-docs-tags-index.tsx +23 -0
  97. package/routes-src/locale-docs-tags-tag.tsx +39 -0
  98. package/routes-src/locale-docs-versions.tsx +23 -0
  99. package/routes-src/locale-index.tsx +150 -0
  100. package/routes-src/robots.txt.tsx +13 -0
  101. package/routes-src/sitemap.xml.tsx +48 -0
  102. package/routes-src/v-docs-slug.tsx +64 -0
  103. package/routes-src/v-locale-docs-slug.tsx +85 -0
@@ -0,0 +1,167 @@
1
+ /** @jsxRuntime automatic */
2
+ /** @jsxImportSource preact */
3
+
4
+ // Footer presentational shell for the documentation layout.
5
+ //
6
+ // The original template mixed data-prep (settings + getDocsCollection
7
+ // + tag-vocabulary lookups + locale overrides) with the presentational
8
+ // footer markup. Because v2 must stay decoupled from host-only helpers,
9
+ // only the presentational shell lives here: callers prepare the
10
+ // already-localized, already-resolved data upstream and feed it in via
11
+ // `linkColumns` / `tagColumns` / `copyright` props.
12
+ //
13
+ // Behaviour parity notes:
14
+ //
15
+ // - The `<footer>` shell is always rendered — even when all three slots
16
+ // are empty — so the contentinfo ARIA landmark is present on every
17
+ // page regardless of whether link columns or copyright are configured.
18
+ // (The original Astro template returned early when `!footer`; that
19
+ // guard lives in the host-side `FooterWithDefaults` wrapper in
20
+ // `pages/lib/footer-with-defaults.tsx` now.)
21
+ //
22
+ // - The link/tag column grid is only emitted when at least one column is
23
+ // present (mirrors the Astro `hasColumns &&` guard).
24
+ //
25
+ // - The copyright block is rendered as-is via `dangerouslySetInnerHTML`
26
+ // because the original template used `<Fragment set:html={copyright} />`
27
+ // to allow inline anchors. Callers are responsible for sanitising
28
+ // the string (the Astro version did the same — it trusted
29
+ // `settings.footer.copyright`).
30
+ //
31
+ // - When both columns and copyright exist, the copyright block is
32
+ // visually separated by a top border + spacing, identical to the
33
+ // `mt-vsp-lg border-t border-muted pt-vsp-md` that the Astro template
34
+ // applied via `class:list` conditional.
35
+
36
+ import type { VNode } from "preact";
37
+
38
+ import type { FooterLinkColumn, FooterTagColumn } from "./types.js";
39
+
40
+ export interface FooterProps {
41
+ /**
42
+ * Already-localized link columns. Each item's href should be
43
+ * base-prefixed and locale-aware; `isExternal` controls the
44
+ * target/rel attributes.
45
+ */
46
+ linkColumns?: FooterLinkColumn[];
47
+ /**
48
+ * Already-resolved tag columns. Empty array (or omitted) hides the
49
+ * taglist entirely. Each tag's href should already be base-prefixed.
50
+ */
51
+ tagColumns?: FooterTagColumn[];
52
+ /**
53
+ * Copyright HTML. Rendered via `dangerouslySetInnerHTML` so embedded
54
+ * anchors work. The caller is responsible for the contents.
55
+ */
56
+ copyright?: string;
57
+ /**
58
+ * When provided, adds `data-zfb-transition-persist` to the `<footer>`
59
+ * element. Use a locale-keyed value (e.g. `footer-en`, `footer-ja`) so
60
+ * cross-locale swaps discard the stale footer while same-locale swaps
61
+ * preserve DOM-node identity. See zudolab/zudo-doc#1546.
62
+ */
63
+ persistKey?: string;
64
+ }
65
+
66
+ /**
67
+ * Footer shell for the documentation layout.
68
+ *
69
+ * Always renders the `<footer>` shell so the contentinfo ARIA landmark
70
+ * is present on every page — even when no columns or copyright are
71
+ * configured. The inner content (link grid, copyright) is only emitted
72
+ * when the respective slots carry data.
73
+ */
74
+ export function Footer(props: FooterProps): VNode {
75
+ const linkColumns = props.linkColumns ?? [];
76
+ const tagColumns = props.tagColumns ?? [];
77
+ const copyright = props.copyright ?? "";
78
+ const persistKey = props.persistKey;
79
+
80
+ const hasColumns = linkColumns.length > 0 || tagColumns.length > 0;
81
+ const hasCopyright = copyright.length > 0;
82
+
83
+ const copyrightClass = hasColumns
84
+ ? "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline mt-vsp-lg border-t border-muted pt-vsp-md"
85
+ : "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline";
86
+
87
+ return (
88
+ <footer
89
+ class="border-t border-muted bg-surface"
90
+ // Strategy B: locale-keyed persist (zudolab/zudo-doc#1546).
91
+ // The footer's locale-aware bits (link labels, copyright) are SSR'd
92
+ // per locale; a locale-keyed persist key (`footer-en`, `footer-ja`)
93
+ // guarantees cross-locale swaps re-render the footer while
94
+ // same-locale swaps preserve DOM-node identity (safe — footer
95
+ // content is invariant page-to-page within a locale).
96
+ {...(persistKey
97
+ ? { "data-zfb-transition-persist": persistKey }
98
+ : {})}
99
+ >
100
+ <div class="mx-auto max-w-[clamp(50rem,75vw,90rem)] px-hsp-xl py-vsp-xl lg:px-hsp-2xl lg:py-vsp-2xl">
101
+ {hasColumns && (
102
+ <div class="grid grid-cols-1 gap-vsp-lg sm:grid-cols-2 lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))]">
103
+ {linkColumns.map((column, i) => (
104
+ <div key={`link-${i}-${column.title}`}>
105
+ <p class="text-small font-semibold text-fg mb-vsp-xs">
106
+ {column.title}
107
+ </p>
108
+ <ul class="list-none p-0">
109
+ {column.items.map((item, j) => (
110
+ <li
111
+ key={`item-${i}-${j}-${item.href}`}
112
+ class="mb-vsp-2xs"
113
+ >
114
+ <a
115
+ href={item.href}
116
+ class="text-caption text-muted hover:text-accent hover:underline focus-visible:underline"
117
+ {...(item.isExternal
118
+ ? {
119
+ target: "_blank",
120
+ rel: "noopener noreferrer",
121
+ }
122
+ : {})}
123
+ >
124
+ {item.label}
125
+ </a>
126
+ </li>
127
+ ))}
128
+ </ul>
129
+ </div>
130
+ ))}
131
+ {tagColumns.map((column, i) => (
132
+ <div
133
+ key={`tag-${i}-${column.group}`}
134
+ data-taglist-group={column.group}
135
+ >
136
+ <h2 class="text-small font-semibold text-fg mb-vsp-xs">
137
+ {column.title}
138
+ </h2>
139
+ <ul class="list-none p-0">
140
+ {column.tags.map(({ tag, count, href }) => (
141
+ <li key={`tag-item-${tag}`} class="mb-vsp-2xs">
142
+ <a
143
+ href={href}
144
+ class="text-caption text-muted hover:text-accent hover:underline focus-visible:underline"
145
+ >
146
+ #{tag}
147
+ <span class="opacity-60" aria-hidden="true">
148
+ &nbsp;({count})
149
+ </span>
150
+ </a>
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ </div>
155
+ ))}
156
+ </div>
157
+ )}
158
+ {hasCopyright && (
159
+ <div
160
+ class={copyrightClass}
161
+ dangerouslySetInnerHTML={{ __html: copyright }}
162
+ />
163
+ )}
164
+ </div>
165
+ </footer>
166
+ );
167
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Public entry for the framework-agnostic footer shell.
3
+ *
4
+ * Consumers import from `@takazudo/zudo-doc/footer`:
5
+ *
6
+ * import { Footer, type FooterProps } from "@takazudo/zudo-doc/footer";
7
+ *
8
+ * The shell is purely presentational — see `./types.ts` for the data
9
+ * shapes the host project assembles upstream.
10
+ */
11
+
12
+ export { Footer } from "./footer.js";
13
+ export type { FooterProps } from "./footer.js";
14
+ export type {
15
+ FooterLinkColumn,
16
+ FooterLinkItem,
17
+ FooterTagColumn,
18
+ FooterTagItem,
19
+ } from "./types.js";
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Public types for the framework-agnostic footer shell.
3
+ *
4
+ * The original footer template mixed three concerns:
5
+ * 1. Reading `settings.footer` and applying locale overrides.
6
+ * 2. Loading the docs collection + tag vocabulary to build the
7
+ * optional taglist columns.
8
+ * 3. Rendering the footer markup.
9
+ *
10
+ * Concerns (1) and (2) depend on host-side helpers (`@/config/settings`,
11
+ * `@/utils/get-docs-collection`, `tag-vocabulary`, etc.) that v2 must
12
+ * not reach into. So this package only ports concern (3): the
13
+ * presentational shell. Callers prepare the columns upstream and pass
14
+ * already-localized, already-resolved hrefs in.
15
+ */
16
+
17
+ /** A single link rendered inside a {@link FooterLinkColumn}. */
18
+ export interface FooterLinkItem {
19
+ /** Visible label (already locale-resolved by the caller). */
20
+ label: string;
21
+ /** Resolved href (already base-prefixed and locale-aware). */
22
+ href: string;
23
+ /**
24
+ * When true, the rendered anchor adds `target="_blank"` and
25
+ * `rel="noopener noreferrer"`. Callers compute this from their own
26
+ * external-href detector.
27
+ */
28
+ isExternal?: boolean;
29
+ }
30
+
31
+ /** One column in the footer's link grid. */
32
+ export interface FooterLinkColumn {
33
+ /** Visible heading for the column (already locale-resolved). */
34
+ title: string;
35
+ items: FooterLinkItem[];
36
+ }
37
+
38
+ /** A single tag rendered inside a {@link FooterTagColumn}. */
39
+ export interface FooterTagItem {
40
+ /** Canonical tag id (rendered as `#<tag>`). */
41
+ tag: string;
42
+ /** Document count shown next to the tag. */
43
+ count: number;
44
+ /** Resolved href to the tag's index page. */
45
+ href: string;
46
+ }
47
+
48
+ /** One column in the footer's tag grid. */
49
+ export interface FooterTagColumn {
50
+ /**
51
+ * Group identifier — usually a vocabulary group name like `"topic"`,
52
+ * or the literal `"__flat__"` sentinel for the ungrouped/flat column.
53
+ * Surfaced as `data-taglist-group` on the rendered column wrapper so
54
+ * downstream tests / e2e selectors keep working.
55
+ */
56
+ group: string;
57
+ /** Visible heading for the column (already locale-resolved). */
58
+ title: string;
59
+ tags: FooterTagItem[];
60
+ }