@takazudo/zudo-doc 0.2.21 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/gen-z-index.mjs +164 -0
- package/bin/tags-audit-runner.ts +126 -0
- package/bin/tags-audit.mjs +64 -0
- package/bin/zudo-doc.mjs +83 -0
- package/dist/ai-chat-modal/index.d.ts +8 -0
- package/dist/ai-chat-modal/index.js +243 -0
- package/dist/body-foot-util/body-foot-util-area.d.ts +4 -8
- package/dist/body-foot-util/edit-link.d.ts +4 -8
- package/dist/body-foot-util/index.d.ts +4 -3
- package/dist/breadcrumb/breadcrumb.d.ts +5 -9
- package/dist/breadcrumb/find-path.d.ts +2 -5
- package/dist/breadcrumb/index.d.ts +4 -4
- package/dist/breadcrumb/types.d.ts +3 -5
- package/dist/category-nav/index.d.ts +86 -0
- package/dist/category-nav/index.js +44 -0
- package/dist/category-tree-nav/index.d.ts +65 -0
- package/dist/category-tree-nav/index.js +24 -0
- package/dist/code-group/index.d.ts +10 -0
- package/dist/code-group/index.js +37 -0
- package/dist/code-syntax/code-block-enhancer-script.d.ts +1 -3
- package/dist/code-syntax/code-block-enhancer.d.ts +3 -6
- package/dist/code-syntax/index.d.ts +9 -8
- package/dist/code-syntax/mermaid-init-script.d.ts +3 -5
- package/dist/code-syntax/mermaid-init.d.ts +4 -7
- package/dist/code-syntax/tabs-init-script.d.ts +1 -3
- package/dist/code-syntax/tabs-init.d.ts +3 -6
- package/dist/code-syntax/tabs.d.ts +4 -7
- package/dist/color-scheme-utils.d.ts +125 -0
- package/dist/color-scheme-utils.js +151 -0
- package/dist/compose-meta-title/index.d.ts +7 -0
- package/dist/compose-meta-title/index.js +10 -0
- package/dist/content/component-map.d.ts +13 -17
- package/dist/content/content-blockquote.d.ts +3 -6
- package/dist/content/content-code.d.ts +3 -6
- package/dist/content/content-code.js +1 -1
- package/dist/content/content-link.d.ts +3 -6
- package/dist/content/content-link.js +1 -1
- package/dist/content/content-ol.d.ts +3 -6
- package/dist/content/content-paragraph.d.ts +3 -6
- package/dist/content/content-strong.d.ts +3 -6
- package/dist/content/content-table.d.ts +3 -6
- package/dist/content/content-ul.d.ts +3 -6
- package/dist/content/heading-h2.d.ts +3 -6
- package/dist/content/heading-h3.d.ts +3 -6
- package/dist/content/heading-h4.d.ts +3 -6
- package/dist/content/index.d.ts +29 -13
- package/dist/content-admonition/index.d.ts +15 -0
- package/dist/content-admonition/index.js +14 -0
- package/dist/design-token-panel-bootstrap.d.ts +38 -0
- package/dist/design-token-panel-bootstrap.js +29 -0
- package/dist/desktop-sidebar-toggle-island/index.d.ts +5 -0
- package/dist/desktop-sidebar-toggle-island/index.js +62 -0
- package/dist/details/details.d.ts +3 -7
- package/dist/details/index.d.ts +2 -2
- package/dist/doc-body-end/index.d.ts +21 -0
- package/dist/doc-body-end/index.js +15 -0
- package/dist/doc-content-header/index.d.ts +69 -0
- package/dist/doc-content-header/index.js +49 -0
- package/dist/doc-history/index.d.ts +10 -0
- package/dist/doc-history/index.js +407 -0
- package/dist/doc-history-area/index.d.ts +84 -0
- package/dist/doc-history-area/index.js +76 -0
- package/dist/doc-metainfo-area/index.d.ts +46 -0
- package/dist/doc-metainfo-area/index.js +41 -0
- package/dist/doc-page-props/index.d.ts +93 -0
- package/dist/doc-page-props/index.js +0 -0
- package/dist/doc-page-renderer/index.d.ts +128 -0
- package/dist/doc-page-renderer/index.js +103 -0
- package/dist/doc-page-shell/index.d.ts +136 -0
- package/dist/doc-page-shell/index.js +127 -0
- package/dist/doc-pager/index.d.ts +25 -0
- package/dist/doc-pager/index.js +41 -0
- package/dist/doc-route-entries/index.d.ts +125 -0
- package/dist/doc-route-entries/index.js +76 -0
- package/dist/doc-route-paths/index.d.ts +54 -0
- package/dist/doc-route-paths/index.js +61 -0
- package/dist/doc-tags-area/index.d.ts +38 -0
- package/dist/doc-tags-area/index.js +30 -0
- package/dist/doclayout/anchors.d.ts +7 -9
- package/dist/doclayout/doc-layout-with-defaults.d.ts +16 -12
- package/dist/doclayout/doc-layout.d.ts +5 -9
- package/dist/doclayout/index.d.ts +6 -6
- package/dist/eject/index.d.ts +33 -0
- package/dist/eject/index.js +229 -0
- package/dist/extract-headings/index.d.ts +43 -0
- package/dist/extract-headings/index.js +111 -0
- package/dist/factory-context/index.d.ts +80 -0
- package/dist/factory-context/index.js +0 -0
- package/dist/features.css +882 -0
- package/dist/footer/footer.d.ts +4 -8
- package/dist/footer/index.d.ts +13 -3
- package/dist/footer/types.d.ts +4 -6
- package/dist/footer-with-defaults/index.d.ts +63 -0
- package/dist/footer-with-defaults/index.js +128 -0
- package/dist/frontmatter-preview-data/index.d.ts +26 -0
- package/dist/frontmatter-preview-data/index.js +23 -0
- package/dist/github-helpers/index.d.ts +17 -0
- package/dist/github-helpers/index.js +16 -0
- package/dist/head/doc-head.d.ts +3 -6
- package/dist/head/index.d.ts +9 -5
- package/dist/head/og-tags.d.ts +4 -7
- package/dist/head/twitter-card.d.ts +3 -6
- package/dist/head/types.d.ts +1 -3
- package/dist/head-with-defaults/index.d.ts +49 -0
- package/dist/head-with-defaults/index.js +62 -0
- package/dist/header/header.d.ts +6 -10
- package/dist/header/index.d.ts +16 -6
- package/dist/header/nav-active.d.ts +5 -7
- package/dist/header/nav-overflow-script.d.ts +1 -3
- package/dist/header/right-items.d.ts +3 -6
- package/dist/header/types.d.ts +10 -12
- package/dist/header-with-defaults/index.d.ts +77 -0
- package/dist/header-with-defaults/index.js +163 -0
- package/dist/html-preview-wrapper/dedent.d.ts +1 -3
- package/dist/html-preview-wrapper/highlighted-code.d.ts +3 -7
- package/dist/html-preview-wrapper/html-preview-wrapper.d.ts +6 -10
- package/dist/html-preview-wrapper/html-preview.d.ts +5 -9
- package/dist/html-preview-wrapper/index.d.ts +8 -5
- package/dist/html-preview-wrapper/preflight.d.ts +1 -3
- package/dist/html-preview-wrapper/preview-base.d.ts +4 -8
- package/dist/i18n-version/index.d.ts +7 -5
- package/dist/i18n-version/language-switcher.d.ts +5 -8
- package/dist/i18n-version/types.d.ts +3 -5
- package/dist/i18n-version/version-banner.d.ts +4 -8
- package/dist/i18n-version/version-switcher.d.ts +7 -10
- package/dist/icons/index.d.ts +9 -13
- package/dist/image-enlarge/index.d.ts +13 -0
- package/dist/image-enlarge/index.js +176 -0
- package/dist/index.d.ts +26 -2
- package/dist/inline-version-switcher/index.d.ts +31 -0
- package/dist/inline-version-switcher/index.js +44 -0
- package/dist/integrations/claude-resources/escape-for-mdx.d.ts +1 -3
- package/dist/integrations/claude-resources/generate.d.ts +2 -4
- package/dist/integrations/claude-resources/index.d.ts +7 -10
- package/dist/integrations/doc-history/index.d.ts +21 -24
- package/dist/integrations/doc-history/pre-build.d.ts +7 -9
- package/dist/integrations/llms-txt/dev-middleware.d.ts +7 -11
- package/dist/integrations/llms-txt/emit.d.ts +2 -7
- package/dist/integrations/llms-txt/generate.d.ts +3 -8
- package/dist/integrations/llms-txt/index.d.ts +33 -8
- package/dist/integrations/llms-txt/load.d.ts +3 -7
- package/dist/integrations/llms-txt/strip.d.ts +2 -6
- package/dist/integrations/llms-txt/types.d.ts +9 -13
- package/dist/integrations/search-index/build-emitter.d.ts +4 -7
- package/dist/integrations/search-index/collect.d.ts +2 -5
- package/dist/integrations/search-index/dev-middleware.d.ts +5 -8
- package/dist/integrations/search-index/index.d.ts +7 -5
- package/dist/integrations/search-index/types.d.ts +5 -7
- package/dist/island-types/index.d.ts +44 -0
- package/dist/island-types/index.js +12 -0
- package/dist/locale-merge/index.d.ts +114 -0
- package/dist/locale-merge/index.js +27 -0
- package/dist/math-block/index.d.ts +18 -0
- package/dist/math-block/index.js +29 -0
- package/dist/md-utils/index.d.ts +6 -8
- package/dist/md-utils/index.js +2 -1
- package/dist/mdx-components/index.d.ts +46 -0
- package/dist/mdx-components/index.js +161 -0
- package/dist/mermaid-enlarge/index.d.ts +11 -0
- package/dist/mermaid-enlarge/index.js +290 -0
- package/dist/metainfo/doc-metainfo.d.ts +5 -9
- package/dist/metainfo/doc-tags.d.ts +7 -11
- package/dist/metainfo/frontmatter-preview.d.ts +8 -12
- package/dist/metainfo/index.d.ts +6 -4
- package/dist/nav-data-prep/index.d.ts +72 -0
- package/dist/nav-data-prep/index.js +34 -0
- package/dist/nav-indexing/category-nav.d.ts +4 -8
- package/dist/nav-indexing/category-tree-nav.d.ts +4 -8
- package/dist/nav-indexing/doc-card-grid.d.ts +4 -8
- package/dist/nav-indexing/docs-sitemap.d.ts +4 -8
- package/dist/nav-indexing/index.d.ts +37 -10
- package/dist/nav-indexing/nav-card-grid.d.ts +4 -8
- package/dist/nav-indexing/site-tree-nav-demo.d.ts +4 -8
- package/dist/nav-indexing/tag-nav.d.ts +6 -10
- package/dist/nav-indexing/types.d.ts +6 -8
- package/dist/nav-indexing/versions-page-content.d.ts +4 -8
- package/dist/nav-scope/index.d.ts +41 -0
- package/dist/nav-scope/index.js +41 -0
- package/dist/nav-source-cache/index.d.ts +13 -0
- package/dist/nav-source-cache/index.js +28 -0
- package/dist/nav-source-docs/index.d.ts +169 -0
- package/dist/nav-source-docs/index.js +123 -0
- package/dist/page-loading/index.d.ts +1 -2
- package/dist/page-loading/page-loading-overlay.d.ts +4 -8
- package/dist/plugins/claude-resources.d.ts +3 -0
- package/dist/plugins/claude-resources.js +27 -0
- package/dist/plugins/connect-adapter.d.ts +31 -0
- package/dist/plugins/connect-adapter.js +78 -0
- package/dist/plugins/doc-history.d.ts +3 -0
- package/dist/plugins/doc-history.js +54 -0
- package/dist/plugins/llms-txt.d.ts +3 -0
- package/dist/plugins/llms-txt.js +48 -0
- package/dist/plugins/plugin-utils.d.ts +17 -0
- package/dist/plugins/plugin-utils.js +11 -0
- package/dist/plugins/routes.d.ts +2 -0
- package/dist/plugins/routes.js +100 -0
- package/dist/plugins/search-index.d.ts +3 -0
- package/dist/plugins/search-index.js +24 -0
- package/dist/preset.d.ts +198 -0
- package/dist/preset.js +185 -0
- package/dist/render-markdown/index.d.ts +5 -0
- package/dist/render-markdown/index.js +115 -0
- package/dist/robots.d.ts +36 -0
- package/dist/robots.js +17 -0
- package/dist/route-enumerators/index.d.ts +204 -0
- package/dist/route-enumerators/index.js +156 -0
- package/dist/routes/404.d.ts +7 -0
- package/dist/routes/404.js +47 -0
- package/dist/routes/_chrome.d.ts +32 -0
- package/dist/routes/_chrome.js +365 -0
- package/dist/routes/_context.d.ts +56 -0
- package/dist/routes/_context.js +222 -0
- package/dist/routes/_docs-helpers.d.ts +43 -0
- package/dist/routes/_docs-helpers.js +173 -0
- package/dist/routes/_virtual.d.js +0 -0
- package/dist/routes/api-ai-chat.d.ts +5 -0
- package/dist/routes/api-ai-chat.js +24 -0
- package/dist/routes/docs-slug.d.ts +21 -0
- package/dist/routes/docs-slug.js +26 -0
- package/dist/routes/docs-tags-index.d.ts +7 -0
- package/dist/routes/docs-tags-index.js +11 -0
- package/dist/routes/docs-tags-tag.d.ts +23 -0
- package/dist/routes/docs-tags-tag.js +19 -0
- package/dist/routes/docs-versions.d.ts +7 -0
- package/dist/routes/docs-versions.js +11 -0
- package/dist/routes/index.d.ts +7 -0
- package/dist/routes/index.js +117 -0
- package/dist/routes/locale-docs-slug.d.ts +27 -0
- package/dist/routes/locale-docs-slug.js +40 -0
- package/dist/routes/locale-docs-tags-index.d.ts +18 -0
- package/dist/routes/locale-docs-tags-index.js +15 -0
- package/dist/routes/locale-docs-tags-tag.d.ts +25 -0
- package/dist/routes/locale-docs-tags-tag.js +22 -0
- package/dist/routes/locale-docs-versions.d.ts +18 -0
- package/dist/routes/locale-docs-versions.js +15 -0
- package/dist/routes/locale-index.d.ts +24 -0
- package/dist/routes/locale-index.js +132 -0
- package/dist/routes/robots.txt.d.ts +3 -0
- package/dist/routes/robots.txt.js +8 -0
- package/dist/routes/sitemap.xml.d.ts +5 -0
- package/dist/routes/sitemap.xml.js +31 -0
- package/dist/routes/v-docs-slug.d.ts +27 -0
- package/dist/routes/v-docs-slug.js +34 -0
- package/dist/routes/v-locale-docs-slug.d.ts +31 -0
- package/dist/routes/v-locale-docs-slug.js +50 -0
- package/dist/safelist.css +1 -1
- package/dist/search-widget/index.d.ts +38 -0
- package/dist/search-widget/index.js +169 -0
- package/dist/search-widget-script/index.d.ts +18 -0
- package/dist/search-widget-script/index.js +465 -0
- package/dist/settings.d.ts +270 -0
- package/dist/settings.js +0 -0
- package/dist/sidebar/index.d.ts +21 -3
- package/dist/sidebar/sidebar.d.ts +5 -9
- package/dist/sidebar/types.d.ts +4 -6
- package/dist/sidebar-prepaint/index.d.ts +21 -0
- package/dist/sidebar-prepaint/index.js +23 -0
- package/dist/sidebar-resizer/index.d.ts +2 -6
- package/dist/sidebar-resizer/sidebar-resizer-init.d.ts +6 -10
- package/dist/sidebar-toggle-island/index.d.ts +13 -0
- package/dist/sidebar-toggle-island/index.js +122 -0
- package/dist/sidebar-tree/build-tree.d.ts +4 -8
- package/dist/sidebar-tree/category-meta.d.ts +3 -6
- package/dist/sidebar-tree/index.d.ts +18 -3
- package/dist/sidebar-tree/types.d.ts +6 -8
- package/dist/sidebar-tree-island/index.d.ts +13 -0
- package/dist/sidebar-tree-island/index.js +454 -0
- package/dist/sidebar-utils/index.d.ts +64 -0
- package/dist/sidebar-utils/index.js +88 -0
- package/dist/sidebar-with-defaults/index.d.ts +38 -0
- package/dist/sidebar-with-defaults/index.js +45 -0
- package/dist/site-tree-nav/index.d.ts +71 -0
- package/dist/site-tree-nav/index.js +36 -0
- package/dist/site-tree-nav-island/index.d.ts +11 -0
- package/dist/site-tree-nav-island/index.js +176 -0
- package/dist/slug/index.d.ts +4 -0
- package/dist/slug/index.js +19 -0
- package/dist/smart-break/index.d.ts +55 -0
- package/dist/{toc/smart-break.js → smart-break/index.js} +30 -3
- package/dist/tab-item/index.d.ts +2 -2
- package/dist/tab-item/tab-item.d.ts +6 -7
- package/dist/tag-helpers/index.d.ts +40 -0
- package/dist/tag-helpers/index.js +54 -0
- package/dist/tag-pages/index.d.ts +114 -0
- package/dist/tag-pages/index.js +146 -0
- package/dist/tags-audit.d.ts +107 -0
- package/dist/tags-audit.js +321 -0
- package/dist/theme/color-scheme-provider.d.ts +4 -8
- package/dist/theme/color-tweak-export-modal.d.ts +4 -7
- package/dist/theme/design-token-serde.d.ts +14 -17
- package/dist/theme/design-token-types.d.ts +4 -6
- package/dist/theme/iframe-bridge.d.ts +12 -14
- package/dist/theme/index.d.ts +7 -9
- package/dist/theme/theme-toggle.d.ts +3 -8
- package/dist/theme-toggle/color-scheme-sync.d.ts +5 -7
- package/dist/theme-toggle/index.d.ts +4 -8
- package/dist/toc/cx.d.ts +2 -3
- package/dist/toc/index.d.ts +8 -6
- package/dist/toc/mobile-toc.d.ts +5 -9
- package/dist/toc/mobile-toc.js +1 -1
- package/dist/toc/toc-title.d.ts +1 -3
- package/dist/toc/toc.d.ts +5 -9
- package/dist/toc/toc.js +1 -1
- package/dist/toc/types.d.ts +1 -3
- package/dist/toc/use-active-heading.d.ts +4 -7
- package/dist/transitions/index.d.ts +1 -1
- package/dist/transitions/page-events.d.ts +4 -6
- package/dist/tree-nav-shared/index.d.ts +22 -0
- package/dist/tree-nav-shared/index.js +66 -0
- package/dist/url-helpers/index.d.ts +37 -0
- package/dist/url-helpers/index.js +106 -0
- package/dist/url-normalizer/index.d.ts +39 -1
- package/dist/url-normalizer/normalize.d.ts +3 -5
- package/dist/use-modal-dialog/index.d.ts +70 -0
- package/dist/use-modal-dialog/index.js +73 -0
- package/dist/versions-page/index.d.ts +55 -0
- package/dist/versions-page/index.js +73 -0
- package/eject/breadcrumb/breadcrumb.tsx +194 -0
- package/eject/breadcrumb/find-path.ts +26 -0
- package/eject/breadcrumb/index.ts +4 -0
- package/eject/breadcrumb/types.ts +32 -0
- package/eject/code-group/index.tsx +78 -0
- package/eject/content-admonition/index.tsx +50 -0
- package/eject/details/details.tsx +34 -0
- package/eject/details/index.ts +4 -0
- package/eject/doc-pager/index.tsx +91 -0
- package/eject/footer/footer.tsx +167 -0
- package/eject/footer/index.ts +19 -0
- package/eject/footer/types.ts +60 -0
- package/eject/header/header.tsx +725 -0
- package/eject/header/index.ts +36 -0
- package/eject/header/nav-active.ts +122 -0
- package/eject/header/nav-overflow-script.ts +302 -0
- package/eject/header/right-items.ts +78 -0
- package/eject/header/types.ts +69 -0
- package/eject/page-loading/index.ts +10 -0
- package/eject/page-loading/page-loading-overlay.tsx +103 -0
- package/eject/sidebar/index.ts +27 -0
- package/eject/sidebar/sidebar.tsx +137 -0
- package/eject/sidebar/types.ts +73 -0
- package/eject/tab-item/index.ts +7 -0
- package/eject/tab-item/tab-item.tsx +70 -0
- package/eject/theme-toggle/color-scheme-sync.ts +73 -0
- package/eject/theme-toggle/index.tsx +120 -0
- package/eject/toc/cx.ts +38 -0
- package/eject/toc/index.ts +11 -0
- package/eject/toc/mobile-toc.tsx +133 -0
- package/eject/toc/toc-title.ts +33 -0
- package/eject/toc/toc.tsx +119 -0
- package/eject/toc/types.ts +14 -0
- package/eject/toc/use-active-heading.ts +162 -0
- package/package.json +371 -11
- package/routes-src/404.tsx +49 -0
- package/routes-src/_chrome.tsx +470 -0
- package/routes-src/_context.ts +314 -0
- package/routes-src/_docs-helpers.ts +284 -0
- package/routes-src/_virtual.d.ts +15 -0
- package/routes-src/api-ai-chat.tsx +46 -0
- package/routes-src/docs-slug.tsx +43 -0
- package/routes-src/docs-tags-index.tsx +14 -0
- package/routes-src/docs-tags-tag.tsx +29 -0
- package/routes-src/docs-versions.tsx +15 -0
- package/routes-src/index.tsx +134 -0
- package/routes-src/locale-docs-slug.tsx +69 -0
- package/routes-src/locale-docs-tags-index.tsx +23 -0
- package/routes-src/locale-docs-tags-tag.tsx +39 -0
- package/routes-src/locale-docs-versions.tsx +23 -0
- package/routes-src/locale-index.tsx +150 -0
- package/routes-src/robots.txt.tsx +13 -0
- package/routes-src/sitemap.xml.tsx +48 -0
- package/routes-src/v-docs-slug.tsx +64 -0
- package/routes-src/v-locale-docs-slug.tsx +85 -0
- package/dist/toc/smart-break.d.ts +0 -27
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
3
|
+
import { useState, useEffect, useCallback, useMemo, useRef } from "preact/compat";
|
|
4
|
+
import { SmartBreak } from "../smart-break/index.js";
|
|
5
|
+
import { History, Close, ArrowLeft } from "../icons/index.js";
|
|
6
|
+
import { AFTER_NAVIGATE_EVENT } from "../transitions/index.js";
|
|
7
|
+
import { useModalDialog } from "../use-modal-dialog/index.js";
|
|
8
|
+
function Spinner() {
|
|
9
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-vsp-xl", children: /* @__PURE__ */ jsx(
|
|
10
|
+
"span",
|
|
11
|
+
{
|
|
12
|
+
className: "inline-block box-border rounded-full animate-spin",
|
|
13
|
+
style: {
|
|
14
|
+
width: 48,
|
|
15
|
+
height: 48,
|
|
16
|
+
border: "5px solid var(--color-fg, #fff)",
|
|
17
|
+
borderBottomColor: "transparent"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
) });
|
|
21
|
+
}
|
|
22
|
+
function buildSideBySideRows(changes) {
|
|
23
|
+
const rows = [];
|
|
24
|
+
let leftNum = 0;
|
|
25
|
+
let rightNum = 0;
|
|
26
|
+
let i = 0;
|
|
27
|
+
while (i < changes.length) {
|
|
28
|
+
const change = changes[i];
|
|
29
|
+
if (!change) {
|
|
30
|
+
i++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!change.added && !change.removed) {
|
|
34
|
+
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
35
|
+
for (const line of lines) {
|
|
36
|
+
leftNum++;
|
|
37
|
+
rightNum++;
|
|
38
|
+
rows.push({ leftLine: line, rightLine: line, leftNum, rightNum, type: "context" });
|
|
39
|
+
}
|
|
40
|
+
i++;
|
|
41
|
+
} else if (change.removed && i + 1 < changes.length) {
|
|
42
|
+
const nextChange = changes[i + 1];
|
|
43
|
+
if (nextChange?.added) {
|
|
44
|
+
const removedLines = change.value.replace(/\n$/, "").split("\n");
|
|
45
|
+
const addedLines = nextChange.value.replace(/\n$/, "").split("\n");
|
|
46
|
+
const maxLen = Math.max(removedLines.length, addedLines.length);
|
|
47
|
+
for (let j = 0; j < maxLen; j++) {
|
|
48
|
+
const left = j < removedLines.length ? removedLines[j] ?? null : null;
|
|
49
|
+
const right = j < addedLines.length ? addedLines[j] ?? null : null;
|
|
50
|
+
if (left !== null) leftNum++;
|
|
51
|
+
if (right !== null) rightNum++;
|
|
52
|
+
rows.push({
|
|
53
|
+
leftLine: left,
|
|
54
|
+
rightLine: right,
|
|
55
|
+
leftNum: left !== null ? leftNum : null,
|
|
56
|
+
rightNum: right !== null ? rightNum : null,
|
|
57
|
+
type: "changed"
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
i += 2;
|
|
61
|
+
} else {
|
|
62
|
+
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
leftNum++;
|
|
65
|
+
rows.push({ leftLine: line, rightLine: null, leftNum, rightNum: null, type: "removed" });
|
|
66
|
+
}
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
} else if (change.removed) {
|
|
70
|
+
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
71
|
+
for (const line of lines) {
|
|
72
|
+
leftNum++;
|
|
73
|
+
rows.push({ leftLine: line, rightLine: null, leftNum, rightNum: null, type: "removed" });
|
|
74
|
+
}
|
|
75
|
+
i++;
|
|
76
|
+
} else {
|
|
77
|
+
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
rightNum++;
|
|
80
|
+
rows.push({ leftLine: null, rightLine: line, leftNum: null, rightNum, type: "added" });
|
|
81
|
+
}
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return rows;
|
|
86
|
+
}
|
|
87
|
+
const DIFF_CACHE_LIMIT = 32;
|
|
88
|
+
const diffCache = /* @__PURE__ */ new Map();
|
|
89
|
+
async function getCachedDiff(olderHash, newerHash, olderContent, newerContent) {
|
|
90
|
+
const key = `${olderHash}::${newerHash}`;
|
|
91
|
+
const hit = diffCache.get(key);
|
|
92
|
+
if (hit) {
|
|
93
|
+
diffCache.delete(key);
|
|
94
|
+
diffCache.set(key, hit);
|
|
95
|
+
return hit;
|
|
96
|
+
}
|
|
97
|
+
const { diffLines } = await import("diff");
|
|
98
|
+
const changes = diffLines(olderContent, newerContent);
|
|
99
|
+
diffCache.set(key, changes);
|
|
100
|
+
if (diffCache.size > DIFF_CACHE_LIMIT) {
|
|
101
|
+
const oldest = diffCache.keys().next().value;
|
|
102
|
+
if (oldest !== void 0) diffCache.delete(oldest);
|
|
103
|
+
}
|
|
104
|
+
return changes;
|
|
105
|
+
}
|
|
106
|
+
function DiffViewer({
|
|
107
|
+
selection,
|
|
108
|
+
onBack,
|
|
109
|
+
showBackButton
|
|
110
|
+
}) {
|
|
111
|
+
const [changes, setChanges] = useState(null);
|
|
112
|
+
const [diffError, setDiffError] = useState(null);
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
let cancelled = false;
|
|
115
|
+
setDiffError(null);
|
|
116
|
+
getCachedDiff(
|
|
117
|
+
selection.older.hash,
|
|
118
|
+
selection.newer.hash,
|
|
119
|
+
selection.older.content,
|
|
120
|
+
selection.newer.content
|
|
121
|
+
).then((result) => {
|
|
122
|
+
if (!cancelled) setChanges(result);
|
|
123
|
+
}).catch((e) => {
|
|
124
|
+
if (!cancelled) {
|
|
125
|
+
setDiffError(e instanceof Error ? e.message : "Failed to compute diff");
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return () => {
|
|
129
|
+
cancelled = true;
|
|
130
|
+
};
|
|
131
|
+
}, [selection.older.hash, selection.newer.hash]);
|
|
132
|
+
const rows = useMemo(
|
|
133
|
+
() => changes ? buildSideBySideRows(changes) : [],
|
|
134
|
+
[changes]
|
|
135
|
+
);
|
|
136
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-hsp-sm px-hsp-lg py-vsp-xs border-b border-muted", children: [
|
|
138
|
+
showBackButton && /* @__PURE__ */ jsx(
|
|
139
|
+
"button",
|
|
140
|
+
{
|
|
141
|
+
type: "button",
|
|
142
|
+
onClick: onBack,
|
|
143
|
+
className: "text-muted hover:text-fg lg:hidden",
|
|
144
|
+
"aria-label": "Back to revisions",
|
|
145
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-icon-sm w-icon-sm" })
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex", children: [
|
|
149
|
+
/* @__PURE__ */ jsx("div", { className: "w-1/2 text-small text-muted font-mono truncate pr-hsp-sm", children: selection.older.hash.slice(0, 7) }),
|
|
150
|
+
/* @__PURE__ */ jsx("div", { className: "w-1/2 text-small text-muted font-mono truncate pl-hsp-sm", children: selection.newer.hash.slice(0, 7) })
|
|
151
|
+
] })
|
|
152
|
+
] }),
|
|
153
|
+
diffError && /* @__PURE__ */ jsx("div", { className: "px-hsp-lg py-vsp-lg text-danger text-small", children: diffError }),
|
|
154
|
+
!changes && !diffError && /* @__PURE__ */ jsx(Spinner, {}),
|
|
155
|
+
/* @__PURE__ */ jsx("div", { className: `flex-1 overflow-auto${!changes ? " hidden" : ""}`, children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse", style: { tableLayout: "fixed" }, children: [
|
|
156
|
+
/* @__PURE__ */ jsxs("colgroup", { children: [
|
|
157
|
+
/* @__PURE__ */ jsx("col", { style: { width: "2.5rem" } }),
|
|
158
|
+
/* @__PURE__ */ jsx("col", {}),
|
|
159
|
+
/* @__PURE__ */ jsx("col", { style: { width: "2.5rem" } }),
|
|
160
|
+
/* @__PURE__ */ jsx("col", {})
|
|
161
|
+
] }),
|
|
162
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row, idx) => {
|
|
163
|
+
const leftBg = row.type === "removed" || row.type === "changed" ? "diff-line-removed" : "";
|
|
164
|
+
const rightBg = row.type === "added" || row.type === "changed" ? "diff-line-added" : "";
|
|
165
|
+
const leftEmpty = row.leftLine === null;
|
|
166
|
+
const rightEmpty = row.rightLine === null;
|
|
167
|
+
return /* @__PURE__ */ jsxs("tr", { className: "diff-row", children: [
|
|
168
|
+
/* @__PURE__ */ jsx("td", { className: `diff-line-num ${leftBg}`, children: row.leftNum ?? "" }),
|
|
169
|
+
/* @__PURE__ */ jsx("td", { className: `diff-line-content ${leftBg}${leftEmpty ? " diff-line-empty" : ""}`, children: row.leftLine ?? "" }),
|
|
170
|
+
/* @__PURE__ */ jsx("td", { className: `diff-line-num ${rightBg}`, children: row.rightNum ?? "" }),
|
|
171
|
+
/* @__PURE__ */ jsx("td", { className: `diff-line-content ${rightBg}${rightEmpty ? " diff-line-empty" : ""}`, children: row.rightLine ?? "" })
|
|
172
|
+
] }, idx);
|
|
173
|
+
}) })
|
|
174
|
+
] }) })
|
|
175
|
+
] });
|
|
176
|
+
}
|
|
177
|
+
function RevisionList({
|
|
178
|
+
entries,
|
|
179
|
+
onSelectDiff
|
|
180
|
+
}) {
|
|
181
|
+
const [selectedA, setSelectedA] = useState(1);
|
|
182
|
+
const [selectedB, setSelectedB] = useState(0);
|
|
183
|
+
if (entries.length === 0) {
|
|
184
|
+
return /* @__PURE__ */ jsx("div", { className: "px-hsp-lg py-vsp-lg text-muted text-small", children: "No revision history available." });
|
|
185
|
+
}
|
|
186
|
+
const canCompare = selectedA !== selectedB && selectedA >= 0 && selectedB >= 0 && selectedA < entries.length && selectedB < entries.length;
|
|
187
|
+
function handleCompare() {
|
|
188
|
+
if (!canCompare) return;
|
|
189
|
+
const idxOlder = Math.max(selectedA, selectedB);
|
|
190
|
+
const idxNewer = Math.min(selectedA, selectedB);
|
|
191
|
+
const olderEntry = entries[idxOlder];
|
|
192
|
+
const newerEntry = entries[idxNewer];
|
|
193
|
+
if (!olderEntry || !newerEntry) return;
|
|
194
|
+
onSelectDiff({
|
|
195
|
+
older: olderEntry,
|
|
196
|
+
newer: newerEntry
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
200
|
+
entries.length >= 2 && /* @__PURE__ */ jsxs("div", { className: "px-hsp-lg py-vsp-xs border-b border-muted flex items-center gap-hsp-sm", children: [
|
|
201
|
+
/* @__PURE__ */ jsx(
|
|
202
|
+
"button",
|
|
203
|
+
{
|
|
204
|
+
type: "button",
|
|
205
|
+
disabled: !canCompare,
|
|
206
|
+
onClick: handleCompare,
|
|
207
|
+
className: canCompare ? "px-hsp-md py-vsp-2xs text-small rounded bg-accent text-bg hover:bg-accent-hover" : "px-hsp-md py-vsp-2xs text-small rounded bg-surface text-muted cursor-not-allowed",
|
|
208
|
+
children: "Compare"
|
|
209
|
+
}
|
|
210
|
+
),
|
|
211
|
+
/* @__PURE__ */ jsx("span", { className: "text-caption text-muted", children: "Select two revisions (A / B)" })
|
|
212
|
+
] }),
|
|
213
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: entries.map((entry, idx) => {
|
|
214
|
+
const isA = selectedA === idx;
|
|
215
|
+
const isB = selectedB === idx;
|
|
216
|
+
const dateStr = formatDate(entry.date);
|
|
217
|
+
return /* @__PURE__ */ jsx(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
className: isA || isB ? "px-hsp-lg py-vsp-xs border-b border-muted bg-surface" : "px-hsp-lg py-vsp-xs border-b border-muted hover:bg-surface",
|
|
221
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-hsp-sm", children: [
|
|
222
|
+
entries.length >= 2 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-vsp-2xs pt-[2px] shrink-0", children: [
|
|
223
|
+
/* @__PURE__ */ jsx(
|
|
224
|
+
"button",
|
|
225
|
+
{
|
|
226
|
+
type: "button",
|
|
227
|
+
onClick: () => setSelectedA(idx),
|
|
228
|
+
className: isA ? "w-[1.5rem] h-[1.25rem] text-caption rounded flex items-center justify-center bg-accent text-bg" : "w-[1.5rem] h-[1.25rem] text-caption rounded flex items-center justify-center border border-muted text-muted hover:border-fg hover:text-fg",
|
|
229
|
+
"aria-label": `Select revision ${entry.hash.slice(0, 7)} as A`,
|
|
230
|
+
children: "A"
|
|
231
|
+
}
|
|
232
|
+
),
|
|
233
|
+
/* @__PURE__ */ jsx(
|
|
234
|
+
"button",
|
|
235
|
+
{
|
|
236
|
+
type: "button",
|
|
237
|
+
onClick: () => setSelectedB(idx),
|
|
238
|
+
className: isB ? "w-[1.5rem] h-[1.25rem] text-caption rounded flex items-center justify-center bg-accent text-bg" : "w-[1.5rem] h-[1.25rem] text-caption rounded flex items-center justify-center border border-muted text-muted hover:border-fg hover:text-fg",
|
|
239
|
+
"aria-label": `Select revision ${entry.hash.slice(0, 7)} as B`,
|
|
240
|
+
children: "B"
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
] }),
|
|
244
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
245
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-hsp-sm", children: [
|
|
246
|
+
/* @__PURE__ */ jsx("code", { className: "text-caption text-accent font-mono", children: entry.hash.slice(0, 7) }),
|
|
247
|
+
/* @__PURE__ */ jsx("span", { className: "text-caption text-muted", children: dateStr })
|
|
248
|
+
] }),
|
|
249
|
+
/* @__PURE__ */ jsx("div", { className: "text-small text-fg mt-vsp-2xs truncate", children: /* @__PURE__ */ jsx(SmartBreak, { children: entry.message }) }),
|
|
250
|
+
/* @__PURE__ */ jsx("div", { className: "text-caption text-muted", children: entry.author })
|
|
251
|
+
] })
|
|
252
|
+
] })
|
|
253
|
+
},
|
|
254
|
+
entry.hash
|
|
255
|
+
);
|
|
256
|
+
}) })
|
|
257
|
+
] });
|
|
258
|
+
}
|
|
259
|
+
function formatDate(dateStr) {
|
|
260
|
+
const d = new Date(dateStr);
|
|
261
|
+
if (isNaN(d.getTime())) return dateStr;
|
|
262
|
+
return d.toLocaleDateString(void 0, {
|
|
263
|
+
year: "numeric",
|
|
264
|
+
month: "short",
|
|
265
|
+
day: "numeric"
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function DocHistory({ slug, locale, basePath = "/" }) {
|
|
269
|
+
const [view, setView] = useState("closed");
|
|
270
|
+
const [data, setData] = useState(null);
|
|
271
|
+
const [loading, setLoading] = useState(false);
|
|
272
|
+
const [error, setError] = useState(null);
|
|
273
|
+
const [diffSelection, setDiffSelection] = useState(
|
|
274
|
+
null
|
|
275
|
+
);
|
|
276
|
+
const returnFocusRef = useRef(null);
|
|
277
|
+
const base = basePath.replace(/\/+$/, "");
|
|
278
|
+
const historySlug = slug === "" ? "index" : slug;
|
|
279
|
+
const fetchPath = locale ? `${base}/doc-history/${locale}/${historySlug}.json` : `${base}/doc-history/${historySlug}.json`;
|
|
280
|
+
const fetchHistory = useCallback(async () => {
|
|
281
|
+
if (data) return;
|
|
282
|
+
setLoading(true);
|
|
283
|
+
setError(null);
|
|
284
|
+
try {
|
|
285
|
+
const res = await fetch(fetchPath);
|
|
286
|
+
if (!res.ok) {
|
|
287
|
+
throw new Error(`Failed to load history (${res.status})`);
|
|
288
|
+
}
|
|
289
|
+
const json = await res.json();
|
|
290
|
+
if (!json || !Array.isArray(json.entries)) {
|
|
291
|
+
throw new Error("Malformed history response");
|
|
292
|
+
}
|
|
293
|
+
setData(json);
|
|
294
|
+
} catch (e) {
|
|
295
|
+
setError(e instanceof Error ? e.message : "Failed to load history");
|
|
296
|
+
} finally {
|
|
297
|
+
setLoading(false);
|
|
298
|
+
}
|
|
299
|
+
}, [data, fetchPath]);
|
|
300
|
+
function handleOpen(e) {
|
|
301
|
+
returnFocusRef.current = e.currentTarget;
|
|
302
|
+
setView("revisions");
|
|
303
|
+
fetchHistory();
|
|
304
|
+
}
|
|
305
|
+
const handleClose = useCallback(() => {
|
|
306
|
+
setView("closed");
|
|
307
|
+
setDiffSelection(null);
|
|
308
|
+
}, []);
|
|
309
|
+
function handleSelectDiff(selection) {
|
|
310
|
+
setDiffSelection(selection);
|
|
311
|
+
setView("diff");
|
|
312
|
+
}
|
|
313
|
+
function handleBackToRevisions() {
|
|
314
|
+
setDiffSelection(null);
|
|
315
|
+
setView("revisions");
|
|
316
|
+
}
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (view !== "closed") {
|
|
319
|
+
document.body.style.overflow = "hidden";
|
|
320
|
+
} else {
|
|
321
|
+
document.body.style.overflow = "";
|
|
322
|
+
}
|
|
323
|
+
return () => {
|
|
324
|
+
document.body.style.overflow = "";
|
|
325
|
+
};
|
|
326
|
+
}, [view]);
|
|
327
|
+
const isOpen = view !== "closed";
|
|
328
|
+
const hasDiff = view === "diff" && diffSelection;
|
|
329
|
+
const { dialogRef } = useModalDialog({
|
|
330
|
+
isOpen,
|
|
331
|
+
onClose: handleClose,
|
|
332
|
+
navigateEvent: AFTER_NAVIGATE_EVENT,
|
|
333
|
+
manageFocus: true,
|
|
334
|
+
returnFocusRef
|
|
335
|
+
});
|
|
336
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
337
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-end mt-vsp-xl", children: /* @__PURE__ */ jsxs(
|
|
338
|
+
"button",
|
|
339
|
+
{
|
|
340
|
+
type: "button",
|
|
341
|
+
onClick: handleOpen,
|
|
342
|
+
className: "doc-history-trigger flex items-center gap-hsp-xs px-hsp-md py-vsp-xs rounded-lg bg-surface border border-muted text-muted hover:text-fg hover:border-fg transition-colors",
|
|
343
|
+
"aria-label": "View document history",
|
|
344
|
+
children: [
|
|
345
|
+
/* @__PURE__ */ jsx(History, { className: "h-icon-md w-icon-md" }),
|
|
346
|
+
/* @__PURE__ */ jsx("span", { className: "text-small", children: "History" })
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
) }),
|
|
350
|
+
/* @__PURE__ */ jsxs(
|
|
351
|
+
"dialog",
|
|
352
|
+
{
|
|
353
|
+
ref: dialogRef,
|
|
354
|
+
"aria-label": "Document revision history",
|
|
355
|
+
className: "doc-history-panel z-modal fixed inset-0 m-0 h-full w-full max-h-full max-w-full bg-bg border-none p-0 backdrop:z-modal-backdrop backdrop:bg-bg/30",
|
|
356
|
+
style: { color: "var(--color-fg)" },
|
|
357
|
+
children: [
|
|
358
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-hsp-lg py-vsp-xs border-b border-muted", children: [
|
|
359
|
+
/* @__PURE__ */ jsx("h2", { className: "text-body font-semibold text-fg", children: view === "diff" ? "Diff" : "Revision History" }),
|
|
360
|
+
/* @__PURE__ */ jsx(
|
|
361
|
+
"button",
|
|
362
|
+
{
|
|
363
|
+
type: "button",
|
|
364
|
+
onClick: handleClose,
|
|
365
|
+
className: "text-muted hover:text-fg",
|
|
366
|
+
"aria-label": "Close history panel",
|
|
367
|
+
children: /* @__PURE__ */ jsx(Close, { className: "h-icon-md w-icon-md" })
|
|
368
|
+
}
|
|
369
|
+
)
|
|
370
|
+
] }),
|
|
371
|
+
/* @__PURE__ */ jsxs("div", { className: "h-[calc(100%-3rem)] overflow-hidden", children: [
|
|
372
|
+
loading && /* @__PURE__ */ jsx(Spinner, {}),
|
|
373
|
+
error && /* @__PURE__ */ jsx("div", { className: "px-hsp-lg py-vsp-lg text-danger text-small", children: error }),
|
|
374
|
+
!loading && !error && data && /* @__PURE__ */ jsxs("div", { className: "flex h-full", children: [
|
|
375
|
+
/* @__PURE__ */ jsx(
|
|
376
|
+
"div",
|
|
377
|
+
{
|
|
378
|
+
className: hasDiff ? "hidden lg:flex lg:flex-col lg:w-[clamp(16rem,25%,22rem)] shrink-0 border-r border-muted h-full" : "flex flex-col w-full h-full",
|
|
379
|
+
children: /* @__PURE__ */ jsx(
|
|
380
|
+
RevisionList,
|
|
381
|
+
{
|
|
382
|
+
entries: data.entries,
|
|
383
|
+
onSelectDiff: handleSelectDiff
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
}
|
|
387
|
+
),
|
|
388
|
+
hasDiff && /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0 h-full", children: /* @__PURE__ */ jsx(
|
|
389
|
+
DiffViewer,
|
|
390
|
+
{
|
|
391
|
+
selection: diffSelection,
|
|
392
|
+
onBack: handleBackToRevisions,
|
|
393
|
+
showBackButton: true
|
|
394
|
+
},
|
|
395
|
+
`${diffSelection.older.hash}:${diffSelection.newer.hash}`
|
|
396
|
+
) })
|
|
397
|
+
] })
|
|
398
|
+
] })
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
] });
|
|
403
|
+
}
|
|
404
|
+
DocHistory.displayName = "DocHistory";
|
|
405
|
+
export {
|
|
406
|
+
DocHistory
|
|
407
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
import type { VNode } from "preact";
|
|
4
|
+
/** Per-entry metadata shape from the doc-history manifest. */
|
|
5
|
+
export interface DocHistoryMetaEntry {
|
|
6
|
+
author: string;
|
|
7
|
+
createdDate: string;
|
|
8
|
+
updatedDate: string;
|
|
9
|
+
/** Source file extension (".mdx" | ".md") — optional in older manifests. */
|
|
10
|
+
ext?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Settings subset read by the DocHistoryArea factory. */
|
|
13
|
+
export interface DocHistoryAreaSettings {
|
|
14
|
+
docHistory: boolean;
|
|
15
|
+
bodyFootUtilArea: {
|
|
16
|
+
viewSourceLink?: boolean;
|
|
17
|
+
} | false | undefined;
|
|
18
|
+
base?: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* DocHistory component constructor type.
|
|
22
|
+
* Must match the interface of `@takazudo/zudo-doc/doc-history`'s DocHistory.
|
|
23
|
+
*/
|
|
24
|
+
export type DocHistoryComponent = (props: {
|
|
25
|
+
slug: string;
|
|
26
|
+
locale?: string;
|
|
27
|
+
basePath?: string;
|
|
28
|
+
}) => VNode;
|
|
29
|
+
/** Dependencies injected by the host stub. */
|
|
30
|
+
export interface DocHistoryAreaDeps {
|
|
31
|
+
settings: DocHistoryAreaSettings;
|
|
32
|
+
/** Default locale code (e.g. "en"). */
|
|
33
|
+
defaultLocale: string;
|
|
34
|
+
/** The parsed `#doc-history-meta` JSON manifest (host-side import). */
|
|
35
|
+
docHistoryMeta: Record<string, DocHistoryMetaEntry>;
|
|
36
|
+
/** Translate a UI string key for a locale. */
|
|
37
|
+
t: (key: string, locale: string) => string;
|
|
38
|
+
/** Convert a canonical route slug to a history slug (sentinel: "" → "index"). */
|
|
39
|
+
toHistorySlug: (slug: string) => string;
|
|
40
|
+
/**
|
|
41
|
+
* Build a view-source GitHub URL, or null when githubUrl is not set.
|
|
42
|
+
* Host passes a partially applied version binding `settings.githubUrl`.
|
|
43
|
+
*/
|
|
44
|
+
buildGitHubSourceUrl: (contentDir: string, entryId: string) => string | null;
|
|
45
|
+
/**
|
|
46
|
+
* The DocHistory island component (host-side — must be imported in the stub so
|
|
47
|
+
* zfb's scanner walks page → stub → DocHistory).
|
|
48
|
+
*/
|
|
49
|
+
DocHistory: DocHistoryComponent;
|
|
50
|
+
}
|
|
51
|
+
export interface DocHistoryAreaProps {
|
|
52
|
+
/** Page slug, e.g. "getting-started/intro". */
|
|
53
|
+
slug: string;
|
|
54
|
+
/** Active locale string, e.g. "en", "ja". */
|
|
55
|
+
locale: string;
|
|
56
|
+
/**
|
|
57
|
+
* Raw zfb entry slug (relative path without extension), e.g.
|
|
58
|
+
* "getting-started/intro" or "getting-started/index". Appended with
|
|
59
|
+
* the source extension from the build-time manifest (".mdx" fallback)
|
|
60
|
+
* to form the file path passed to buildGitHubSourceUrl.
|
|
61
|
+
* Omit for auto-index pages (no underlying MDX file) — sourceUrl
|
|
62
|
+
* will be suppressed automatically.
|
|
63
|
+
*/
|
|
64
|
+
entrySlug?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Content directory for the active locale, e.g. "src/content/docs"
|
|
67
|
+
* or "src/content/docs-ja". Combined with entrySlug to build the
|
|
68
|
+
* view-source GitHub URL. Omit to suppress the view-source link.
|
|
69
|
+
*/
|
|
70
|
+
contentDir?: string;
|
|
71
|
+
/**
|
|
72
|
+
* True when this locale page falls back to the base EN collection
|
|
73
|
+
* (i.e. the slug has no translation for the active locale). When true,
|
|
74
|
+
* the history data-path derivations use defaultLocale so the island
|
|
75
|
+
* fetches the correct bare-slug JSON and the SSR manifest lookup hits
|
|
76
|
+
* the bare key — both of which only exist for EN-origin files.
|
|
77
|
+
*/
|
|
78
|
+
isFallback?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a `DocHistoryArea` component bound to the host's settings and
|
|
82
|
+
* injected dependencies.
|
|
83
|
+
*/
|
|
84
|
+
export declare function createDocHistoryArea(deps: DocHistoryAreaDeps): (props: DocHistoryAreaProps) => VNode | null;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { Island } from "@takazudo/zfb";
|
|
3
|
+
import { BodyFootUtilArea } from "../body-foot-util/index.js";
|
|
4
|
+
function createDocHistoryArea(deps) {
|
|
5
|
+
const {
|
|
6
|
+
settings,
|
|
7
|
+
defaultLocale,
|
|
8
|
+
docHistoryMeta,
|
|
9
|
+
t,
|
|
10
|
+
toHistorySlug,
|
|
11
|
+
buildGitHubSourceUrl,
|
|
12
|
+
DocHistory
|
|
13
|
+
} = deps;
|
|
14
|
+
DocHistory.displayName = "DocHistory";
|
|
15
|
+
function DocHistoryArea({
|
|
16
|
+
slug,
|
|
17
|
+
locale,
|
|
18
|
+
entrySlug,
|
|
19
|
+
contentDir,
|
|
20
|
+
isFallback
|
|
21
|
+
}) {
|
|
22
|
+
if (!settings.docHistory) return null;
|
|
23
|
+
const historySlug = toHistorySlug(slug);
|
|
24
|
+
const effectiveHistoryLocale = isFallback ? defaultLocale : locale;
|
|
25
|
+
const composedSlug = effectiveHistoryLocale === defaultLocale ? historySlug : `${effectiveHistoryLocale}/${historySlug}`;
|
|
26
|
+
const meta = docHistoryMeta[composedSlug];
|
|
27
|
+
const createdLabel = t("doc.created", locale);
|
|
28
|
+
const updatedLabel = t("doc.updated", locale);
|
|
29
|
+
const historyLabel = t("doc.history", locale);
|
|
30
|
+
const docHistoryLocale = effectiveHistoryLocale === defaultLocale ? void 0 : effectiveHistoryLocale;
|
|
31
|
+
const docHistoryBasePath = settings.base ?? "/";
|
|
32
|
+
const author = meta?.author;
|
|
33
|
+
const createdDate = meta?.createdDate;
|
|
34
|
+
const updatedDate = meta?.updatedDate;
|
|
35
|
+
const fallback = /* @__PURE__ */ jsxs("div", { class: "sr-only", children: [
|
|
36
|
+
author && /* @__PURE__ */ jsx("span", { children: author }),
|
|
37
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
38
|
+
createdLabel,
|
|
39
|
+
createdDate ? `: ${createdDate}` : ""
|
|
40
|
+
] }),
|
|
41
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
42
|
+
updatedLabel,
|
|
43
|
+
updatedDate ? `: ${updatedDate}` : ""
|
|
44
|
+
] })
|
|
45
|
+
] });
|
|
46
|
+
const docHistoryIsland = Island({
|
|
47
|
+
when: "idle",
|
|
48
|
+
ssrFallback: fallback,
|
|
49
|
+
children: /* @__PURE__ */ jsx(
|
|
50
|
+
DocHistory,
|
|
51
|
+
{
|
|
52
|
+
slug: historySlug,
|
|
53
|
+
locale: docHistoryLocale,
|
|
54
|
+
basePath: docHistoryBasePath
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
});
|
|
58
|
+
const utilSettings = settings.bodyFootUtilArea;
|
|
59
|
+
const sourceExt = meta?.ext ?? ".mdx";
|
|
60
|
+
const sourceUrl = utilSettings && utilSettings.viewSourceLink && entrySlug && contentDir ? buildGitHubSourceUrl(contentDir, entrySlug + sourceExt) : null;
|
|
61
|
+
const viewSourceLabel = t("doc.viewSource", locale);
|
|
62
|
+
void historyLabel;
|
|
63
|
+
return /* @__PURE__ */ jsx(
|
|
64
|
+
BodyFootUtilArea,
|
|
65
|
+
{
|
|
66
|
+
docHistoryIsland,
|
|
67
|
+
sourceUrl,
|
|
68
|
+
viewSourceLabel
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return DocHistoryArea;
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
createDocHistoryArea
|
|
76
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
import type { VNode } from "preact";
|
|
4
|
+
/** Per-entry metadata shape from the doc-history manifest. */
|
|
5
|
+
export interface DocHistoryMetaEntry {
|
|
6
|
+
author: string;
|
|
7
|
+
createdDate: string;
|
|
8
|
+
updatedDate: string;
|
|
9
|
+
}
|
|
10
|
+
/** Settings subset read by the DocMetainfoArea factory. */
|
|
11
|
+
export interface DocMetainfoAreaSettings {
|
|
12
|
+
docMetainfo: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Dependencies injected by the host stub. */
|
|
15
|
+
export interface DocMetainfoAreaDeps {
|
|
16
|
+
settings: DocMetainfoAreaSettings;
|
|
17
|
+
/** Default locale code (e.g. "en"). */
|
|
18
|
+
defaultLocale: string;
|
|
19
|
+
/** The parsed `#doc-history-meta` JSON manifest (host-side import). */
|
|
20
|
+
docHistoryMeta: Record<string, DocHistoryMetaEntry>;
|
|
21
|
+
/** Translate a UI string key for a locale. */
|
|
22
|
+
t: (key: string, locale: string) => string;
|
|
23
|
+
/** Convert a canonical route slug to a history slug (sentinel: "" → "index"). */
|
|
24
|
+
toHistorySlug: (slug: string) => string;
|
|
25
|
+
}
|
|
26
|
+
export interface DocMetainfoAreaProps {
|
|
27
|
+
/** Page slug, e.g. "getting-started/intro". */
|
|
28
|
+
slug: string;
|
|
29
|
+
/** Active locale string, e.g. "en", "ja". */
|
|
30
|
+
locale: string;
|
|
31
|
+
/**
|
|
32
|
+
* True when this locale page falls back to the base EN collection
|
|
33
|
+
* (i.e. the slug has no translation for the active locale). When true,
|
|
34
|
+
* the manifest lookup uses defaultLocale so the visible block resolves
|
|
35
|
+
* the bare-slug key — the only key that exists for EN-origin files —
|
|
36
|
+
* matching the dropdown's `effectiveHistoryLocale` derivation in
|
|
37
|
+
* _doc-history-area.tsx. Display formatting (dates + labels) still uses
|
|
38
|
+
* the active locale so JA users see JA formatting on fallback pages.
|
|
39
|
+
*/
|
|
40
|
+
isFallback?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create a `DocMetainfoArea` component bound to the host's settings and
|
|
44
|
+
* injected dependencies.
|
|
45
|
+
*/
|
|
46
|
+
export declare function createDocMetainfoArea(deps: DocMetainfoAreaDeps): (props: DocMetainfoAreaProps) => VNode | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { DocMetainfo } from "../metainfo/index.js";
|
|
3
|
+
const LOCALE_TO_BCP47 = {
|
|
4
|
+
en: "en-US",
|
|
5
|
+
ja: "ja-JP",
|
|
6
|
+
de: "de-DE"
|
|
7
|
+
};
|
|
8
|
+
function formatDate(isoDate, locale) {
|
|
9
|
+
const d = new Date(isoDate);
|
|
10
|
+
if (isNaN(d.getTime())) return isoDate;
|
|
11
|
+
return d.toLocaleDateString(LOCALE_TO_BCP47[locale] ?? "en-US", {
|
|
12
|
+
year: "numeric",
|
|
13
|
+
month: "short",
|
|
14
|
+
day: "numeric"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function createDocMetainfoArea(deps) {
|
|
18
|
+
const { settings, defaultLocale, docHistoryMeta, t, toHistorySlug } = deps;
|
|
19
|
+
function DocMetainfoArea({ slug, locale, isFallback }) {
|
|
20
|
+
if (!settings.docMetainfo) return null;
|
|
21
|
+
const historySlug = toHistorySlug(slug);
|
|
22
|
+
const effectiveHistoryLocale = isFallback ? defaultLocale : locale;
|
|
23
|
+
const composedSlug = effectiveHistoryLocale === defaultLocale ? historySlug : `${effectiveHistoryLocale}/${historySlug}`;
|
|
24
|
+
const meta = docHistoryMeta[composedSlug];
|
|
25
|
+
if (!meta) return null;
|
|
26
|
+
return /* @__PURE__ */ jsx(
|
|
27
|
+
DocMetainfo,
|
|
28
|
+
{
|
|
29
|
+
createdAt: meta.createdDate ? formatDate(meta.createdDate, locale) : null,
|
|
30
|
+
updatedAt: meta.updatedDate ? formatDate(meta.updatedDate, locale) : null,
|
|
31
|
+
author: meta.author || null,
|
|
32
|
+
createdLabel: t("doc.created", locale),
|
|
33
|
+
updatedLabel: t("doc.updated", locale)
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return DocMetainfoArea;
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
createDocMetainfoArea
|
|
41
|
+
};
|