@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,465 @@
|
|
|
1
|
+
import { AFTER_NAVIGATE_EVENT } from "../transitions/index.js";
|
|
2
|
+
const SEARCH_WIDGET_SCRIPT = (
|
|
3
|
+
/* javascript */
|
|
4
|
+
`(function () {
|
|
5
|
+
if (customElements.get("site-search")) return; // guard double-registration
|
|
6
|
+
|
|
7
|
+
var PAGE_SIZE = 10;
|
|
8
|
+
|
|
9
|
+
// Allowlist-based href sanitizer: only relative paths and http(s) URLs are
|
|
10
|
+
// permitted. Anything else (e.g. javascript:, data:) falls back to "#" so a
|
|
11
|
+
// malicious entry in search-index.json cannot turn a result link into a
|
|
12
|
+
// script-injection vector.
|
|
13
|
+
function safeHref(url) {
|
|
14
|
+
if (!url) return "#";
|
|
15
|
+
var s = String(url);
|
|
16
|
+
if (s.startsWith("/") || s.startsWith("http://") || s.startsWith("https://")) {
|
|
17
|
+
return s;
|
|
18
|
+
}
|
|
19
|
+
return "#";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function escapeHtml(text) {
|
|
23
|
+
return String(text)
|
|
24
|
+
.replace(/&/g, "&")
|
|
25
|
+
.replace(/</g, "<")
|
|
26
|
+
.replace(/>/g, ">")
|
|
27
|
+
.replace(/"/g, """)
|
|
28
|
+
.replace(/'/g, "'");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function escapeRegExp(text) {
|
|
32
|
+
return text.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseTerms(query) {
|
|
36
|
+
return query.trim().split(/\\s+/).filter(Boolean);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// scoreEntry reads pre-lowercased fields (_titleLc, _descLc, _bodyLc)
|
|
40
|
+
// set by prepareLc() at index-load time. Terms arrive already lowercased
|
|
41
|
+
// from search() so no per-call toLowerCase() is needed.
|
|
42
|
+
function scoreEntry(entry, terms) {
|
|
43
|
+
var score = 0;
|
|
44
|
+
var titleLc = entry._titleLc;
|
|
45
|
+
var descLc = entry._descLc;
|
|
46
|
+
var bodyLc = entry._bodyLc;
|
|
47
|
+
for (var i = 0; i < terms.length; i++) {
|
|
48
|
+
var t = terms[i];
|
|
49
|
+
if (titleLc.indexOf(t) !== -1) score += 3;
|
|
50
|
+
if (descLc.indexOf(t) !== -1) score += 2;
|
|
51
|
+
if (bodyLc.indexOf(t) !== -1) score += 1;
|
|
52
|
+
}
|
|
53
|
+
return score;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Pre-lowercase the searched fields on each entry once at load time so that
|
|
57
|
+
// scoreEntry() does not re-lowercase the entire ~162 KB index on every
|
|
58
|
+
// debounced keystroke. Original-case fields are preserved for display.
|
|
59
|
+
function prepareLc(entries) {
|
|
60
|
+
for (var i = 0; i < entries.length; i++) {
|
|
61
|
+
var e = entries[i];
|
|
62
|
+
e._titleLc = (e.title || "").toLowerCase();
|
|
63
|
+
e._descLc = (e.description || "").toLowerCase();
|
|
64
|
+
e._bodyLc = (e.body || "").toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function highlightTerms(text, terms) {
|
|
69
|
+
if (!terms.length) return escapeHtml(text);
|
|
70
|
+
var escaped = terms.map(function(t) { return escapeRegExp(t); });
|
|
71
|
+
var pattern = new RegExp("(" + escaped.join("|") + ")", "gi");
|
|
72
|
+
return text.split(pattern).map(function(seg, i) {
|
|
73
|
+
return i % 2 === 1
|
|
74
|
+
? "<mark>" + escapeHtml(seg) + "</mark>"
|
|
75
|
+
: escapeHtml(seg);
|
|
76
|
+
}).join("");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function truncate(text, query, max) {
|
|
80
|
+
max = max || 200;
|
|
81
|
+
if (text.length <= max) return text;
|
|
82
|
+
var terms = parseTerms(query);
|
|
83
|
+
var lower = text.toLowerCase();
|
|
84
|
+
var best = -1;
|
|
85
|
+
for (var i = 0; i < terms.length; i++) {
|
|
86
|
+
var idx = lower.indexOf(terms[i].toLowerCase());
|
|
87
|
+
if (idx !== -1 && (best === -1 || idx < best)) best = idx;
|
|
88
|
+
}
|
|
89
|
+
if (best === -1) return text.slice(0, max) + "\\u2026";
|
|
90
|
+
var half = Math.floor(max / 2);
|
|
91
|
+
var start = Math.max(0, best - half);
|
|
92
|
+
var end = start + max;
|
|
93
|
+
if (end > text.length) { end = text.length; start = Math.max(0, end - max); }
|
|
94
|
+
var result = text.slice(start, end);
|
|
95
|
+
if (start > 0) result = "\\u2026" + result;
|
|
96
|
+
if (end < text.length) result += "\\u2026";
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
customElements.define("site-search", class SiteSearch extends HTMLElement {
|
|
101
|
+
constructor() {
|
|
102
|
+
super();
|
|
103
|
+
this._dialog = null;
|
|
104
|
+
this._openBtn = null;
|
|
105
|
+
this._closeBtn = null;
|
|
106
|
+
this._input = null;
|
|
107
|
+
this._results = null;
|
|
108
|
+
this._countWide = null;
|
|
109
|
+
this._countNarrow = null;
|
|
110
|
+
this._entries = null;
|
|
111
|
+
this._loading = false;
|
|
112
|
+
this._indexUnavailable = false;
|
|
113
|
+
this._debounce = null;
|
|
114
|
+
this._currentQuery = "";
|
|
115
|
+
this._allResults = [];
|
|
116
|
+
this._shownCount = 0;
|
|
117
|
+
this._shortcut = "";
|
|
118
|
+
this._resultCountTemplate = "";
|
|
119
|
+
// Locale-aware status strings (threaded from the SSR component via
|
|
120
|
+
// data-* attributes, same mechanism as _resultCountTemplate). English
|
|
121
|
+
// literals below in connectedCallback are fallbacks only.
|
|
122
|
+
this._searchUnavailable = "";
|
|
123
|
+
this._loadingIndex = "";
|
|
124
|
+
this._noResults = "";
|
|
125
|
+
this._keydownHandler = null;
|
|
126
|
+
// Delegated click handler on the results container: closing the dialog
|
|
127
|
+
// when a result link is activated (epic #2148). Held so disconnectedCallback
|
|
128
|
+
// can detach it on body swap.
|
|
129
|
+
this._resultsClickHandler = null;
|
|
130
|
+
this._observer = null;
|
|
131
|
+
this._sentinel = null;
|
|
132
|
+
this._isLoadingBatch = false;
|
|
133
|
+
// Snapshot of the initial results-area HTML (includes SSR placeholder).
|
|
134
|
+
// Captured in connectedCallback so we can restore it on input-clear
|
|
135
|
+
// without re-querying the DOM (the placeholder node is replaced once
|
|
136
|
+
// search results are rendered).
|
|
137
|
+
this._placeholderHtml = "";
|
|
138
|
+
// Held so we can remove the document-level after-navigate listener
|
|
139
|
+
// in disconnectedCallback. zudolab/zudo-doc#1523 \u2014 under Strategy B
|
|
140
|
+
// SPA navigation a non-persisted <site-search> element would leak
|
|
141
|
+
// one document listener per nav without this hook.
|
|
142
|
+
this._afterNavHandler = null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
connectedCallback() {
|
|
146
|
+
this._dialog = this.querySelector("[data-search-dialog]");
|
|
147
|
+
this._openBtn = this.querySelector("[data-open-search]");
|
|
148
|
+
this._closeBtn = this.querySelector("[data-close-search]");
|
|
149
|
+
this._input = this.querySelector("[data-search-input]");
|
|
150
|
+
this._results = this.querySelector("[data-search-results]");
|
|
151
|
+
this._countWide = this.querySelector("[data-search-count]");
|
|
152
|
+
this._countNarrow = this.querySelector("[data-search-count-narrow]");
|
|
153
|
+
this._resultCountTemplate = this.dataset.resultCountTemplate || "{count} results";
|
|
154
|
+
this._searchUnavailable = this.dataset.searchUnavailable || "Search unavailable";
|
|
155
|
+
this._loadingIndex = this.dataset.loadingIndex || "Loading search index\\u2026";
|
|
156
|
+
this._noResults = this.dataset.noResults || "No results found.";
|
|
157
|
+
// Snapshot the placeholder HTML before any search renders overwrite it.
|
|
158
|
+
this._placeholderHtml = this._results ? this._results.innerHTML : "";
|
|
159
|
+
|
|
160
|
+
// Platform keyboard-shortcut label \u2014 injected into [data-kbd-shortcut]
|
|
161
|
+
var nav = navigator;
|
|
162
|
+
var isMac = /Mac|iPhone|iPad|iPod/.test(
|
|
163
|
+
(nav.userAgentData && nav.userAgentData.platform) || nav.userAgent
|
|
164
|
+
);
|
|
165
|
+
this._shortcut = isMac ? "\\u2318K" : "Ctrl+K";
|
|
166
|
+
var kbdEl = this.querySelector("[data-kbd-shortcut]");
|
|
167
|
+
if (kbdEl) kbdEl.textContent = this._shortcut;
|
|
168
|
+
|
|
169
|
+
// Wire open/close handlers
|
|
170
|
+
var self = this;
|
|
171
|
+
if (this._openBtn) {
|
|
172
|
+
this._openBtn.addEventListener("click", function() { self.openDialog(); });
|
|
173
|
+
}
|
|
174
|
+
if (this._closeBtn) {
|
|
175
|
+
this._closeBtn.addEventListener("click", function() { self.closeDialog(); });
|
|
176
|
+
}
|
|
177
|
+
if (this._dialog) {
|
|
178
|
+
this._dialog.addEventListener("close", function() {
|
|
179
|
+
document.documentElement.style.overflow = "";
|
|
180
|
+
});
|
|
181
|
+
this._dialog.addEventListener("click", function(e) {
|
|
182
|
+
if (e.target === self._dialog) self.closeDialog();
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (this._input) {
|
|
186
|
+
this._input.addEventListener("input", function() { self.handleInput(); });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Close-on-result-click (epic #2148): result links are created dynamically
|
|
190
|
+
// in renderResult(), so use one delegated listener on the results container
|
|
191
|
+
// instead of per-link handlers. We do NOT preventDefault \u2014 the link's own
|
|
192
|
+
// navigation (zfb Strategy-B SPA swap or a plain load) must still proceed;
|
|
193
|
+
// we only close the <dialog> so it does not linger over the swapped page.
|
|
194
|
+
// closeDialog() runs synchronously before navigation; the dialog's close
|
|
195
|
+
// restores documentElement overflow via the existing "close" listener.
|
|
196
|
+
if (this._results) {
|
|
197
|
+
this._resultsClickHandler = function(e) {
|
|
198
|
+
var t = e.target;
|
|
199
|
+
while (t && t !== self._results) {
|
|
200
|
+
if (t.tagName === "A") { self.closeDialog(); return; }
|
|
201
|
+
t = t.parentNode;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
this._results.addEventListener("click", this._resultsClickHandler);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Global keyboard shortcut (\u2318K / Ctrl+K to open)
|
|
208
|
+
this._keydownHandler = function(e) {
|
|
209
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
|
210
|
+
e.preventDefault();
|
|
211
|
+
self.openDialog();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
document.addEventListener("keydown", this._keydownHandler);
|
|
215
|
+
|
|
216
|
+
// View-Transitions compat: re-run on the v2 after-navigate event.
|
|
217
|
+
// Stored on the instance so disconnectedCallback can detach it on
|
|
218
|
+
// body swap when this element is NOT persisted via
|
|
219
|
+
// data-zfb-transition-persist (zudolab/zudo-doc#1523).
|
|
220
|
+
this._afterNavHandler = function() {
|
|
221
|
+
// Backstop for the original bug (epic #2148): if the dialog is somehow
|
|
222
|
+
// still open after an SPA body swap (e.g. a nav path that bypassed the
|
|
223
|
+
// result-click handler), close it so it does not linger / flash over the
|
|
224
|
+
// newly-swapped page. Safe no-op when already closed.
|
|
225
|
+
if (self._dialog && self._dialog.open) self.closeDialog();
|
|
226
|
+
var kbdEl2 = self.querySelector("[data-kbd-shortcut]");
|
|
227
|
+
if (kbdEl2) kbdEl2.textContent = self._shortcut;
|
|
228
|
+
};
|
|
229
|
+
document.addEventListener(${JSON.stringify(AFTER_NAVIGATE_EVENT)}, this._afterNavHandler);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
disconnectedCallback() {
|
|
233
|
+
if (this._keydownHandler) {
|
|
234
|
+
document.removeEventListener("keydown", this._keydownHandler);
|
|
235
|
+
this._keydownHandler = null;
|
|
236
|
+
}
|
|
237
|
+
if (this._afterNavHandler) {
|
|
238
|
+
document.removeEventListener(${JSON.stringify(AFTER_NAVIGATE_EVENT)}, this._afterNavHandler);
|
|
239
|
+
this._afterNavHandler = null;
|
|
240
|
+
}
|
|
241
|
+
if (this._resultsClickHandler && this._results) {
|
|
242
|
+
this._results.removeEventListener("click", this._resultsClickHandler);
|
|
243
|
+
this._resultsClickHandler = null;
|
|
244
|
+
}
|
|
245
|
+
this.teardownSentinel();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
openDialog() {
|
|
249
|
+
if (!this._dialog) return;
|
|
250
|
+
document.documentElement.style.overflow = "hidden";
|
|
251
|
+
this._dialog.showModal();
|
|
252
|
+
if (this._input) {
|
|
253
|
+
this._input.focus();
|
|
254
|
+
this._input.select();
|
|
255
|
+
}
|
|
256
|
+
if (!this._entries && !this._loading) {
|
|
257
|
+
this.loadIndex();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
closeDialog() {
|
|
262
|
+
if (!this._dialog) return;
|
|
263
|
+
this._dialog.close();
|
|
264
|
+
document.documentElement.style.overflow = "";
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
handleInput() {
|
|
268
|
+
var self = this;
|
|
269
|
+
if (this._debounce) clearTimeout(this._debounce);
|
|
270
|
+
this._debounce = setTimeout(function() { self.search(); }, 150);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
loadIndex() {
|
|
274
|
+
if (this._loading) return;
|
|
275
|
+
this._loading = true;
|
|
276
|
+
var self = this;
|
|
277
|
+
var base = this.dataset.base || "/";
|
|
278
|
+
fetch(base + "search-index.json")
|
|
279
|
+
.then(function(r) {
|
|
280
|
+
if (!r.ok) throw new Error("HTTP " + r.status);
|
|
281
|
+
return r.json();
|
|
282
|
+
})
|
|
283
|
+
.then(function(data) {
|
|
284
|
+
self._entries = Array.isArray(data) ? data : (data.entries || []);
|
|
285
|
+
prepareLc(self._entries);
|
|
286
|
+
self._loading = false;
|
|
287
|
+
// Clear the unavailable flag BEFORE re-running search so a successful
|
|
288
|
+
// retry (e.g. via the openDialog() reload path) fully recovers (#2062).
|
|
289
|
+
self._indexUnavailable = false;
|
|
290
|
+
// If user already typed, search now
|
|
291
|
+
if (self._input && self._input.value.trim()) {
|
|
292
|
+
self.search();
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
.catch(function() {
|
|
296
|
+
self._loading = false;
|
|
297
|
+
self._indexUnavailable = true;
|
|
298
|
+
if (self._results) {
|
|
299
|
+
self._results.innerHTML = "<p class=\\"text-small text-muted\\">" + escapeHtml(self._searchUnavailable) + "</p>";
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
search() {
|
|
305
|
+
var query = this._input ? this._input.value.trim() : "";
|
|
306
|
+
this._currentQuery = query;
|
|
307
|
+
|
|
308
|
+
if (!query) {
|
|
309
|
+
this.teardownSentinel();
|
|
310
|
+
this._allResults = [];
|
|
311
|
+
this._shownCount = 0;
|
|
312
|
+
if (this._results) this._results.innerHTML = this.placeholderHtml();
|
|
313
|
+
this.updateCount();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (!this._entries) {
|
|
318
|
+
// Index failed to load: show the terminal "Search unavailable" state and
|
|
319
|
+
// stop \u2014 do NOT show "Loading search index\u2026" or refetch on every
|
|
320
|
+
// keystroke (#2062). The openDialog() reload path is the intended retry
|
|
321
|
+
// trigger. Clear any stale result state/count/sentinel first.
|
|
322
|
+
if (this._indexUnavailable) {
|
|
323
|
+
this.teardownSentinel();
|
|
324
|
+
this._allResults = [];
|
|
325
|
+
this._shownCount = 0;
|
|
326
|
+
if (this._results) {
|
|
327
|
+
this._results.innerHTML = "<p class=\\"text-small text-muted\\">" + escapeHtml(this._searchUnavailable) + "</p>";
|
|
328
|
+
}
|
|
329
|
+
this.updateCount();
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (this._results) {
|
|
333
|
+
this._results.innerHTML = "<p class=\\"text-small text-muted\\">" + escapeHtml(this._loadingIndex) + "</p>";
|
|
334
|
+
}
|
|
335
|
+
if (!this._loading) this.loadIndex();
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Lowercase the query terms once here so scoreEntry() can do plain
|
|
340
|
+
// indexOf() against pre-lowercased entry fields without repeating
|
|
341
|
+
// toLowerCase() across the entire index on every keystroke.
|
|
342
|
+
var terms = parseTerms(query).map(function(t) { return t.toLowerCase(); });
|
|
343
|
+
var scored = [];
|
|
344
|
+
for (var i = 0; i < this._entries.length; i++) {
|
|
345
|
+
var s = scoreEntry(this._entries[i], terms);
|
|
346
|
+
if (s > 0) scored.push({ entry: this._entries[i], score: s });
|
|
347
|
+
}
|
|
348
|
+
scored.sort(function(a, b) { return b.score - a.score; });
|
|
349
|
+
this._allResults = scored;
|
|
350
|
+
this._shownCount = 0;
|
|
351
|
+
this.teardownSentinel();
|
|
352
|
+
this.updateCount();
|
|
353
|
+
|
|
354
|
+
if (!scored.length) {
|
|
355
|
+
if (this._results) {
|
|
356
|
+
this._results.innerHTML = "<p class=\\"text-small text-muted\\">" + escapeHtml(this._noResults) + "</p>";
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (this._results) this._results.innerHTML = "";
|
|
362
|
+
this.loadMore();
|
|
363
|
+
if (this._shownCount < this._allResults.length) {
|
|
364
|
+
this.setupSentinel();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
loadMore() {
|
|
369
|
+
if (this._isLoadingBatch) return;
|
|
370
|
+
if (this._shownCount >= this._allResults.length) return;
|
|
371
|
+
this._isLoadingBatch = true;
|
|
372
|
+
try {
|
|
373
|
+
var batch = this._allResults.slice(this._shownCount, this._shownCount + PAGE_SIZE);
|
|
374
|
+
var self = this;
|
|
375
|
+
for (var i = 0; i < batch.length; i++) {
|
|
376
|
+
var article = self.renderResult(batch[i].entry);
|
|
377
|
+
if (self._sentinel && self._sentinel.parentNode === self._results) {
|
|
378
|
+
self._results.insertBefore(article, self._sentinel);
|
|
379
|
+
} else if (self._results) {
|
|
380
|
+
self._results.appendChild(article);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
this._shownCount += batch.length;
|
|
384
|
+
if (this._shownCount >= this._allResults.length) {
|
|
385
|
+
this.teardownSentinel();
|
|
386
|
+
}
|
|
387
|
+
} finally {
|
|
388
|
+
this._isLoadingBatch = false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
setupSentinel() {
|
|
393
|
+
this.teardownSentinel();
|
|
394
|
+
if (!this._results) return;
|
|
395
|
+
var sentinel = document.createElement("div");
|
|
396
|
+
sentinel.setAttribute("data-search-sentinel", "");
|
|
397
|
+
sentinel.setAttribute("aria-hidden", "true");
|
|
398
|
+
sentinel.style.height = "1px";
|
|
399
|
+
sentinel.style.width = "100%";
|
|
400
|
+
this._results.appendChild(sentinel);
|
|
401
|
+
this._sentinel = sentinel;
|
|
402
|
+
var self = this;
|
|
403
|
+
this._observer = new IntersectionObserver(function(entries) {
|
|
404
|
+
for (var i = 0; i < entries.length; i++) {
|
|
405
|
+
if (entries[i].isIntersecting) self.loadMore();
|
|
406
|
+
}
|
|
407
|
+
}, { root: this._results, rootMargin: "200px 0px" });
|
|
408
|
+
this._observer.observe(sentinel);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
teardownSentinel() {
|
|
412
|
+
if (this._observer) { this._observer.disconnect(); this._observer = null; }
|
|
413
|
+
if (this._sentinel) { this._sentinel.remove(); this._sentinel = null; }
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
updateCount() {
|
|
417
|
+
var count = this._allResults.length;
|
|
418
|
+
var template = this._resultCountTemplate;
|
|
419
|
+
var text = count > 0 ? template.replace("{count}", String(count)) : "";
|
|
420
|
+
var show = !!text;
|
|
421
|
+
if (this._countWide) {
|
|
422
|
+
this._countWide.textContent = text;
|
|
423
|
+
this._countWide.classList.toggle("hidden", !show);
|
|
424
|
+
}
|
|
425
|
+
if (this._countNarrow) {
|
|
426
|
+
this._countNarrow.textContent = text;
|
|
427
|
+
this._countNarrow.classList.toggle("hidden", !show);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
placeholderHtml() {
|
|
432
|
+
return this._placeholderHtml;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
renderResult(entry) {
|
|
436
|
+
var article = document.createElement("article");
|
|
437
|
+
article.className = "-mx-hsp-lg border-b border-muted";
|
|
438
|
+
var link = document.createElement("a");
|
|
439
|
+
link.href = safeHref(entry.url);
|
|
440
|
+
link.className =
|
|
441
|
+
"group block px-hsp-lg py-vsp-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent";
|
|
442
|
+
var title = document.createElement("span");
|
|
443
|
+
title.className =
|
|
444
|
+
"font-semibold text-fg group-hover:text-accent group-hover:underline group-focus-visible:underline";
|
|
445
|
+
var terms = parseTerms(this._currentQuery);
|
|
446
|
+
title.innerHTML = highlightTerms(entry.title || "", terms);
|
|
447
|
+
link.appendChild(title);
|
|
448
|
+
var text = entry.description || entry.body;
|
|
449
|
+
if (text) {
|
|
450
|
+
var excerpt = document.createElement("p");
|
|
451
|
+
excerpt.className =
|
|
452
|
+
"mt-vsp-2xs text-caption text-muted leading-relaxed group-hover:underline group-focus-visible:underline decoration-muted";
|
|
453
|
+
var truncated = truncate(text, this._currentQuery, 200);
|
|
454
|
+
excerpt.innerHTML = highlightTerms(truncated, terms);
|
|
455
|
+
link.appendChild(excerpt);
|
|
456
|
+
}
|
|
457
|
+
article.appendChild(link);
|
|
458
|
+
return article;
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
})();`
|
|
462
|
+
);
|
|
463
|
+
export {
|
|
464
|
+
SEARCH_WIDGET_SCRIPT
|
|
465
|
+
};
|