@takazudo/zudo-doc 3.2.0 → 4.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/CHANGELOG.md +61 -0
- package/README.md +2 -2
- package/bin/tag-cli-config.ts +126 -0
- package/bin/tags-audit-runner.ts +60 -76
- package/bin/tags-audit.mjs +17 -36
- package/bin/tags-suggest-runner.ts +429 -0
- package/bin/tags-suggest.mjs +30 -0
- package/bin/zudo-doc.mjs +78 -25
- package/dist/breadcrumb/breadcrumb.d.ts +4 -4
- package/dist/breadcrumb/find-path.d.ts +2 -2
- package/dist/breadcrumb/index.d.ts +1 -1
- package/dist/breadcrumb/types.d.ts +0 -5
- package/dist/chrome/derive.d.ts +16 -4
- package/dist/chrome/derive.js +64 -4
- package/dist/chrome/index.d.ts +13 -10
- package/dist/chrome/index.js +12 -6
- package/dist/chrome/primary-slots.d.ts +21 -0
- package/dist/chrome/primary-slots.js +59 -0
- package/dist/chrome-bindings.d.ts +227 -0
- package/dist/chrome-bindings.js +6 -0
- package/dist/code-syntax/code-block-enhancer-script.d.ts +4 -0
- package/dist/code-syntax/code-block-enhancer-script.js +7 -4
- package/dist/code-syntax/code-block-enhancer.d.ts +2 -2
- package/dist/code-syntax/code-block-enhancer.js +1 -3
- package/dist/code-syntax/index.d.ts +5 -5
- package/dist/code-syntax/index.js +4 -13
- package/dist/code-syntax/mermaid-init-script.d.ts +1 -22
- package/dist/code-syntax/mermaid-init-script.js +0 -2
- package/dist/code-syntax/mermaid-init.d.ts +0 -1
- package/dist/code-syntax/mermaid-init.js +3 -4
- package/dist/code-syntax/tabs-init.d.ts +0 -1
- package/dist/code-syntax/tabs-init.js +1 -3
- package/dist/code-syntax/tabs.d.ts +0 -1
- package/dist/code-syntax/tabs.js +1 -3
- package/dist/color-scheme-utils.d.ts +72 -4
- package/dist/color-scheme-utils.js +137 -0
- package/dist/color-schemes-defaults/index.d.ts +23 -0
- package/dist/color-schemes-defaults/index.js +134 -0
- package/dist/config.d.ts +459 -0
- package/dist/config.js +125 -0
- package/dist/content/component-map.d.ts +0 -16
- package/dist/content/component-map.js +2 -4
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +2 -3
- package/dist/content.css +1 -1
- package/dist/design-token-panel-bootstrap.d.ts +82 -27
- package/dist/design-token-panel-bootstrap.js +110 -21
- package/dist/design-token-panel-config/index.d.ts +49 -0
- package/dist/design-token-panel-config/index.js +211 -0
- package/dist/design-token-panel-config/manifest.d.ts +46 -0
- package/dist/design-token-panel-config/manifest.js +105 -0
- package/dist/directive-vocabulary-defaults/index.d.ts +16 -0
- package/dist/directive-vocabulary-defaults/index.js +12 -0
- package/dist/doc-body-end-islands/design-token-panel-island.d.ts +15 -0
- package/dist/doc-body-end-islands/design-token-panel-island.js +31 -0
- package/dist/doc-body-end-islands/index.d.ts +52 -7
- package/dist/doc-body-end-islands/index.js +19 -0
- package/dist/doc-body-end-islands/theme-pack-switcher-island.d.ts +37 -0
- package/dist/doc-body-end-islands/theme-pack-switcher-island.js +18 -0
- package/dist/doc-content-header/index.js +1 -1
- package/dist/doc-history-area/index.d.ts +10 -4
- package/dist/doc-history-area/index.js +3 -2
- package/dist/doc-metainfo-area/index.d.ts +1 -0
- package/dist/doc-page-props/index.d.ts +7 -23
- package/dist/doc-page-renderer/index.d.ts +1 -0
- package/dist/doc-page-renderer/index.js +1 -0
- package/dist/doc-page-shell/index.js +19 -12
- package/dist/doc-pager/index.js +1 -1
- package/dist/doc-route-entries/index.d.ts +2 -2
- package/dist/doclayout/doc-layout-with-defaults.js +4 -4
- package/dist/doclayout/doc-layout.d.ts +8 -0
- package/dist/doclayout/doc-layout.js +10 -1
- package/dist/docs-schema/index.d.ts +67 -0
- package/dist/docs-schema/index.js +43 -0
- package/dist/eject/index.d.ts +16 -0
- package/dist/eject/index.js +122 -28
- package/dist/extract-headings/index.d.ts +5 -8
- package/dist/extract-headings/index.js +2 -9
- package/dist/factory-context/index.d.ts +56 -4
- package/dist/features.css +65 -43
- package/dist/find-in-page/find-bar.d.ts +9 -0
- package/dist/find-in-page/find-bar.js +114 -0
- package/dist/find-in-page/find-in-page.d.ts +17 -0
- package/dist/find-in-page/find-in-page.js +131 -0
- package/dist/find-in-page/index.d.ts +11 -0
- package/dist/find-in-page/index.js +49 -0
- package/dist/footer/footer.js +1 -0
- package/dist/frontmatter-preview-defaults/index.d.ts +16 -0
- package/dist/frontmatter-preview-defaults/index.js +25 -0
- package/dist/head-with-defaults/index.d.ts +2 -0
- package/dist/head-with-defaults/index.js +16 -0
- package/dist/header/header.d.ts +10 -5
- package/dist/header/header.js +45 -5
- package/dist/header/index.d.ts +1 -1
- package/dist/header/types.d.ts +30 -1
- package/dist/header-with-defaults/index.js +1 -0
- package/dist/home-page/index.d.ts +2 -0
- package/dist/home-page/index.js +11 -5
- package/dist/home-page/prepare-home-data.js +1 -1
- package/dist/i18n-defaults/index.d.ts +22 -0
- package/dist/i18n-defaults/index.js +167 -0
- package/dist/locale-merge/index.d.ts +9 -14
- package/dist/locale-merge/index.js +6 -4
- package/dist/mdx-components/index.js +4 -4
- package/dist/plugins/claude-resources.d.ts +1 -0
- package/dist/plugins/claude-resources.js +4 -2
- package/dist/plugins/doc-history.js +1 -1
- package/dist/{integrations → plugins/internal}/claude-resources/index.d.ts +1 -16
- package/dist/{integrations → plugins/internal}/claude-resources/index.js +0 -9
- package/dist/{integrations → plugins/internal}/doc-history/index.d.ts +0 -17
- package/dist/{integrations → plugins/internal}/doc-history/index.js +0 -4
- package/dist/{integrations → plugins/internal}/doc-history/pre-build.d.ts +2 -4
- package/dist/plugins/internal/llms-txt/index.d.ts +7 -0
- package/dist/{integrations → plugins/internal}/llms-txt/load.d.ts +1 -1
- package/dist/{integrations → plugins/internal}/llms-txt/load.js +2 -2
- package/dist/{integrations → plugins/internal}/llms-txt/strip.d.ts +2 -3
- package/dist/{integrations → plugins/internal}/llms-txt/strip.js +1 -1
- package/dist/{integrations → plugins/internal}/llms-txt/types.d.ts +13 -22
- package/dist/{integrations → plugins/internal}/search-index/collect.js +1 -1
- package/dist/plugins/internal/theme-packs/copy.d.ts +32 -0
- package/dist/plugins/internal/theme-packs/copy.js +45 -0
- package/dist/plugins/internal/theme-packs/dev-middleware.d.ts +22 -0
- package/dist/plugins/internal/theme-packs/dev-middleware.js +80 -0
- package/dist/plugins/internal/theme-packs/index.d.ts +6 -0
- package/dist/plugins/internal/theme-packs/index.js +9 -0
- package/dist/plugins/internal/theme-packs/resolve.d.ts +17 -0
- package/dist/plugins/internal/theme-packs/resolve.js +17 -0
- package/dist/plugins/internal/theme-packs/types.d.ts +22 -0
- package/dist/plugins/internal/theme-packs/types.js +0 -0
- package/dist/plugins/llms-txt.js +1 -1
- package/dist/plugins/routes.js +55 -21
- package/dist/plugins/search-index.js +1 -1
- package/dist/plugins/theme-packs.d.ts +3 -0
- package/dist/plugins/theme-packs.js +40 -0
- package/dist/preset.d.ts +28 -14
- package/dist/preset.js +24 -9
- package/dist/route-context/index.js +4 -6
- package/dist/route-enumerators/index.d.ts +6 -18
- package/dist/route-enumerators/index.js +8 -6
- package/dist/routes/404.js +3 -1
- package/dist/routes/_chrome.js +3 -2
- package/dist/routes/_context.d.ts +7 -3
- package/dist/routes/_context.js +2 -0
- package/dist/routes/_docs-helpers.js +9 -21
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +64 -12
- package/dist/sidebar-tree/build-tree.d.ts +3 -4
- package/dist/sidebar-tree/build-tree.js +4 -3
- package/dist/sidebar-tree/index.d.ts +2 -2
- package/dist/sidebar-tree/types.d.ts +6 -17
- package/dist/site-tree-nav-island/index.d.ts +3 -1
- package/dist/site-tree-nav-island/index.js +17 -5
- package/dist/site-tree-nav-island/state.d.ts +4 -0
- package/dist/site-tree-nav-island/state.js +10 -0
- package/dist/tag-helpers/index.d.ts +6 -13
- package/dist/tag-helpers/index.js +5 -23
- package/dist/tag-pages/index.d.ts +8 -21
- package/dist/tag-pages/index.js +14 -10
- package/dist/tags-audit.d.ts +16 -44
- package/dist/tags-audit.js +9 -172
- package/dist/theme/color-scheme-provider.d.ts +2 -3
- package/dist/theme/color-scheme-provider.js +2 -10
- package/dist/theme/index.d.ts +1 -4
- package/dist/theme/index.js +2 -30
- package/dist/theme/theme-pack-provider.d.ts +42 -0
- package/dist/theme/theme-pack-provider.js +75 -0
- package/dist/theme-cli/apply.d.ts +16 -0
- package/dist/theme-cli/apply.js +61 -0
- package/dist/theme-cli/config-io.d.ts +15 -0
- package/dist/theme-cli/config-io.js +51 -0
- package/dist/theme-cli/config-rewriter.d.ts +21 -0
- package/dist/theme-cli/config-rewriter.js +141 -0
- package/dist/theme-cli/config-scanner.d.ts +63 -0
- package/dist/theme-cli/config-scanner.js +288 -0
- package/dist/theme-cli/index.d.ts +7 -0
- package/dist/theme-cli/index.js +38 -0
- package/dist/theme-cli/list.d.ts +27 -0
- package/dist/theme-cli/list.js +64 -0
- package/dist/theme-cli/provenance.d.ts +17 -0
- package/dist/theme-cli/provenance.js +35 -0
- package/dist/theme-cli/registry.d.ts +14 -0
- package/dist/theme-cli/registry.js +13 -0
- package/dist/theme-pack-dialog/dialog-state.d.ts +25 -0
- package/dist/theme-pack-dialog/dialog-state.js +40 -0
- package/dist/theme-pack-dialog/index.d.ts +5 -0
- package/dist/theme-pack-dialog/index.js +152 -0
- package/dist/theme-pack-dialog/theme-pack-card.d.ts +25 -0
- package/dist/theme-pack-dialog/theme-pack-card.js +72 -0
- package/dist/theme-pack-switcher/index.d.ts +49 -0
- package/dist/theme-pack-switcher/index.js +205 -0
- package/dist/theme-pack-switcher/switcher-state.d.ts +56 -0
- package/dist/theme-pack-switcher/switcher-state.js +43 -0
- package/dist/theme-pack-switcher/theme-pack-sync.d.ts +85 -0
- package/dist/theme-pack-switcher/theme-pack-sync.js +121 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-400-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-700-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-400-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-700-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/OFL.txt +94 -0
- package/dist/theme-packs/beacon/meta.json +37 -0
- package/dist/theme-packs/beacon/pack.css +442 -0
- package/dist/theme-packs/broadsheet/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/OFL.txt +95 -0
- package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-italic-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/SourceSerif4-italic-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/SourceSerif4-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/meta.json +38 -0
- package/dist/theme-packs/broadsheet/pack.css +448 -0
- package/dist/theme-packs/brutalist/fonts/ArchivoBlack-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/OFL.txt +95 -0
- package/dist/theme-packs/brutalist/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/meta.json +38 -0
- package/dist/theme-packs/brutalist/pack.css +546 -0
- package/dist/theme-packs/default/meta.json +37 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-italic-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/OFL.txt +93 -0
- package/dist/theme-packs/drift/meta.json +37 -0
- package/dist/theme-packs/drift/pack.css +478 -0
- package/dist/theme-packs/fjord/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/OFL.txt +94 -0
- package/dist/theme-packs/fjord/meta.json +37 -0
- package/dist/theme-packs/fjord/pack.css +375 -0
- package/dist/theme-packs/foundry/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/foundry/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/foundry/fonts/OFL.txt +93 -0
- package/dist/theme-packs/foundry/meta.json +37 -0
- package/dist/theme-packs/foundry/pack.css +202 -0
- package/dist/theme-packs/futura-editorial/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/NotoSans-italic-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/NotoSans-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/OFL.txt +95 -0
- package/dist/theme-packs/futura-editorial/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/meta.json +38 -0
- package/dist/theme-packs/futura-editorial/pack.css +313 -0
- package/dist/theme-packs/hearth/fonts/Fraunces-italic-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/Fraunces-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/Nunito-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/OFL.txt +95 -0
- package/dist/theme-packs/hearth/fonts/SplineSansMono-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/meta.json +38 -0
- package/dist/theme-packs/hearth/pack.css +385 -0
- package/dist/theme-packs/hollow/fonts/OFL.txt +94 -0
- package/dist/theme-packs/hollow/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-400-italic-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/meta.json +37 -0
- package/dist/theme-packs/hollow/pack.css +428 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext-italic.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-italic.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/OFL.txt +94 -0
- package/dist/theme-packs/ledger/meta.json +37 -0
- package/dist/theme-packs/ledger/pack.css +463 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/EBGaramond-latin-italic.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/EBGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/OFL.txt +94 -0
- package/dist/theme-packs/manuscript/meta.json +37 -0
- package/dist/theme-packs/manuscript/pack.css +376 -0
- package/dist/theme-packs/matcha/fonts/MPLUS1Code-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/OFL.txt +95 -0
- package/dist/theme-packs/matcha/fonts/ShipporiMincho-500-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ShipporiMincho-700-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/meta.json +38 -0
- package/dist/theme-packs/matcha/pack.css +409 -0
- package/dist/theme-packs/nocturne/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/CormorantGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/Manrope-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/OFL.txt +95 -0
- package/dist/theme-packs/nocturne/meta.json +38 -0
- package/dist/theme-packs/nocturne/pack.css +502 -0
- package/dist/theme-packs/observatory/fonts/JosefinSans-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/Jost-italic-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/OFL.txt +95 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/meta.json +38 -0
- package/dist/theme-packs/observatory/pack.css +728 -0
- package/dist/theme-packs/onyx/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/CormorantGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/OFL.txt +95 -0
- package/dist/theme-packs/onyx/meta.json +38 -0
- package/dist/theme-packs/onyx/pack.css +497 -0
- package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/OFL.txt +94 -0
- package/dist/theme-packs/phosphor/fonts/VT323-latin-ext.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/VT323-latin.woff2 +0 -0
- package/dist/theme-packs/phosphor/meta.json +38 -0
- package/dist/theme-packs/phosphor/pack.css +493 -0
- package/dist/theme-packs/solar/fonts/OFL.txt +94 -0
- package/dist/theme-packs/solar/fonts/SourceCodePro-italic-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceCodePro-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceSans3-italic-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceSans3-latin.woff2 +0 -0
- package/dist/theme-packs/solar/meta.json +37 -0
- package/dist/theme-packs/solar/pack.css +380 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/OFL.txt +95 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-600-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-700-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-800-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/meta.json +38 -0
- package/dist/theme-packs/sumi/pack.css +502 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-600-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/InterTight-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/OFL.txt +95 -0
- package/dist/theme-packs/swissgrid/meta.json +38 -0
- package/dist/theme-packs/swissgrid/pack.css +518 -0
- package/dist/theme-packs/washi/fonts/MPlus1Code-400-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/MPlus1Code-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/OFL.txt +95 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-600-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-700-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-700-latin.woff2 +0 -0
- package/dist/theme-packs/washi/meta.json +38 -0
- package/dist/theme-packs/washi/pack.css +479 -0
- package/dist/theme-packs-registry/index.d.ts +5 -0
- package/dist/theme-packs-registry/index.js +30 -0
- package/dist/theme-packs-registry/load-registry.d.ts +23 -0
- package/dist/theme-packs-registry/load-registry.js +64 -0
- package/dist/theme-packs-registry/meta-schema.d.ts +70 -0
- package/dist/theme-packs-registry/meta-schema.js +38 -0
- package/dist/theme-packs-registry/resolve-enabled-packs.d.ts +25 -0
- package/dist/theme-packs-registry/resolve-enabled-packs.js +43 -0
- package/dist/theme-packs-registry/token-manifest.d.ts +19 -0
- package/dist/theme-packs-registry/token-manifest.js +57 -0
- package/dist/theme-packs-registry/validator.d.ts +35 -0
- package/dist/theme-packs-registry/validator.js +284 -0
- package/dist/theme-toggle/color-scheme-sync.d.ts +2 -4
- package/dist/theme.css +319 -0
- package/dist/versions-page/index.d.ts +2 -2
- package/dist/versions-page/index.js +8 -8
- package/dist/z-index-defaults/index.d.ts +45 -0
- package/dist/z-index-defaults/index.js +34 -0
- package/eject/breadcrumb/breadcrumb.tsx +4 -4
- package/eject/breadcrumb/find-path.ts +2 -2
- package/eject/breadcrumb/index.ts +1 -1
- package/eject/breadcrumb/types.ts +0 -6
- package/eject/code-group/index.tsx +2 -2
- package/eject/doc-history/index.tsx +1 -1
- package/eject/doc-pager/index.tsx +1 -1
- package/eject/footer/footer.tsx +1 -0
- package/eject/header/header.tsx +86 -21
- package/eject/header/index.ts +3 -0
- package/eject/header/types.ts +39 -1
- package/eject/site-tree-nav-island/index.tsx +15 -3
- package/eject/site-tree-nav-island/state.ts +9 -0
- package/eject/theme-toggle/color-scheme-sync.ts +2 -4
- package/package.json +82 -29
- package/routes-src/404.tsx +4 -1
- package/routes-src/_chrome.tsx +31 -8
- package/routes-src/_context.ts +4 -0
- package/routes-src/_docs-helpers.ts +9 -29
- package/routes-src/_virtual.d.ts +38 -2
- package/tsconfig.base.json +29 -0
- package/virtual-modules.d.ts +83 -0
- package/zfb-config-shim.d.ts +210 -0
- package/dist/integrations/llms-txt/index.d.ts +0 -33
- package/dist/theme/color-tweak-export-modal.d.ts +0 -16
- package/dist/theme/color-tweak-export-modal.js +0 -138
- package/dist/theme/design-token-serde.d.ts +0 -183
- package/dist/theme/design-token-serde.js +0 -346
- package/dist/theme/design-token-types.d.ts +0 -13
- package/dist/theme/design-token-types.js +0 -6
- package/dist/theme/iframe-bridge.d.ts +0 -42
- package/dist/theme/iframe-bridge.js +0 -72
- /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.js +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/generate.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/generate.js +0 -0
- /package/dist/{integrations → plugins/internal}/doc-history/pre-build.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/emit.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/emit.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/generate.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/generate.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/index.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/types.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/build-emitter.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/build-emitter.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/collect.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/index.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/index.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/types.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/types.js +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const THEME_PACK_SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
3
|
+
const DEFAULT_THEME_PACK_SLUG = "default";
|
|
4
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
|
|
5
|
+
const themePackSwatchesSchema = z.object({
|
|
6
|
+
bg: z.string().min(1),
|
|
7
|
+
fg: z.string().min(1),
|
|
8
|
+
accent: z.string().min(1),
|
|
9
|
+
syntax: z.object({
|
|
10
|
+
keyword: z.string().min(1),
|
|
11
|
+
string: z.string().min(1),
|
|
12
|
+
comment: z.string().min(1),
|
|
13
|
+
callable: z.string().min(1)
|
|
14
|
+
})
|
|
15
|
+
});
|
|
16
|
+
const themePackMetaSchema = z.object({
|
|
17
|
+
schemaVersion: z.literal(1),
|
|
18
|
+
slug: z.string().regex(THEME_PACK_SLUG_RE, "must match [a-z0-9][a-z0-9-]*"),
|
|
19
|
+
name: z.string().min(1),
|
|
20
|
+
description: z.string().min(1),
|
|
21
|
+
mode: z.enum(["light", "dark"]),
|
|
22
|
+
version: z.string().regex(SEMVER_RE, "must be a semver string, e.g. 1.0.0"),
|
|
23
|
+
fonts: z.object({
|
|
24
|
+
sans: z.string().min(1),
|
|
25
|
+
mono: z.string().min(1),
|
|
26
|
+
display: z.string().min(1).optional(),
|
|
27
|
+
loaded: z.array(z.string().min(1))
|
|
28
|
+
}),
|
|
29
|
+
preview: z.object({
|
|
30
|
+
light: themePackSwatchesSchema,
|
|
31
|
+
dark: themePackSwatchesSchema
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
export {
|
|
35
|
+
DEFAULT_THEME_PACK_SLUG,
|
|
36
|
+
THEME_PACK_SLUG_RE,
|
|
37
|
+
themePackMetaSchema
|
|
38
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ThemePackRegistry } from "./load-registry.js";
|
|
2
|
+
/** The subset of settings this resolver reads. */
|
|
3
|
+
export interface ResolveEnabledPacksSettings {
|
|
4
|
+
/** Active pack slug — must end up a member of the resolved list. */
|
|
5
|
+
themePack?: string;
|
|
6
|
+
/** Explicit enabled-pack order, or `undefined` for the canonical default
|
|
7
|
+
* order (`"default"` first, then the rest alphabetically). */
|
|
8
|
+
themePacks?: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the ENABLED, ORDERED subset of `registry` per `settings.themePacks`
|
|
12
|
+
* / `settings.themePack` (Decision 7):
|
|
13
|
+
*
|
|
14
|
+
* - `themePacks` omitted → every bundled pack, `"default"` first, then the
|
|
15
|
+
* rest in canonical (alphabetical-by-slug) order.
|
|
16
|
+
* - `themePacks` an explicit array → authoritative: may omit `"default"`,
|
|
17
|
+
* reorder freely. Duplicate or unknown slugs throw loudly.
|
|
18
|
+
* - `themePack` (the active slug, default `"default"`) must be a member of
|
|
19
|
+
* the resolved list — an unknown/excluded active slug throws loudly,
|
|
20
|
+
* naming the bad slug and the available ones.
|
|
21
|
+
*
|
|
22
|
+
* Pure — throws synchronously on misconfiguration; never returns a partial
|
|
23
|
+
* or silently-corrected result.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveEnabledPacks(registry: ThemePackRegistry, settings: ResolveEnabledPacksSettings): ThemePackRegistry;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DEFAULT_THEME_PACK_SLUG } from "./meta-schema.js";
|
|
2
|
+
function resolveEnabledPacks(registry, settings) {
|
|
3
|
+
const bySlug = new Map(registry.map((entry) => [entry.slug, entry]));
|
|
4
|
+
const availableSlugs = registry.map((e) => e.slug);
|
|
5
|
+
let orderedSlugs;
|
|
6
|
+
if (settings.themePacks === void 0) {
|
|
7
|
+
const hasDefault = bySlug.has(DEFAULT_THEME_PACK_SLUG);
|
|
8
|
+
const rest = availableSlugs.filter((s) => s !== DEFAULT_THEME_PACK_SLUG).sort();
|
|
9
|
+
orderedSlugs = hasDefault ? [DEFAULT_THEME_PACK_SLUG, ...rest] : rest;
|
|
10
|
+
} else {
|
|
11
|
+
const requested = settings.themePacks;
|
|
12
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13
|
+
const duplicates = [];
|
|
14
|
+
const unknown = [];
|
|
15
|
+
for (const slug of requested) {
|
|
16
|
+
if (seen.has(slug)) duplicates.push(slug);
|
|
17
|
+
seen.add(slug);
|
|
18
|
+
if (!bySlug.has(slug)) unknown.push(slug);
|
|
19
|
+
}
|
|
20
|
+
if (duplicates.length > 0) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`zudo-doc: settings.themePacks contains duplicate slug(s): ${[...new Set(duplicates)].join(", ")}.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (unknown.length > 0) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`zudo-doc: settings.themePacks references unknown theme pack slug(s): ${unknown.join(", ")}. Available packs: ${availableSlugs.join(", ") || "(none)"}.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
orderedSlugs = [...requested];
|
|
31
|
+
}
|
|
32
|
+
const enabled = orderedSlugs.map((slug) => bySlug.get(slug));
|
|
33
|
+
const activeSlug = settings.themePack ?? DEFAULT_THEME_PACK_SLUG;
|
|
34
|
+
if (!enabled.some((e) => e.slug === activeSlug)) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`zudo-doc: settings.themePack "${activeSlug}" is not one of the enabled theme packs. Enabled packs: ${enabled.map((e) => e.slug).join(", ") || "(none)"}.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return enabled;
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
resolveEnabledPacks
|
|
43
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The full closed set of custom-property names a `pack.css` may declare —
|
|
3
|
+
* every `--zd-*` semantic + syntax role, every `--zdc-*` component token,
|
|
4
|
+
* the allowed `--font-*` family tokens, and the `--zfb-hi-*` bridge. Anything
|
|
5
|
+
* else (a typo'd `--zd-syntx-keyword`, or a net-new invented property) fails
|
|
6
|
+
* the validator's known-token-name check.
|
|
7
|
+
*/
|
|
8
|
+
export declare const KNOWN_THEME_PACK_TOKEN_NAMES: ReadonlySet<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Commercial type-face names that may never appear in a pack's `@font-face`
|
|
11
|
+
* `src`/`local()` list or any `font-family` stack (ADR Decision 5 — a
|
|
12
|
+
* commercial face is never load-bearing; the pack's actual loaded face is
|
|
13
|
+
* always a designated OFL substitute, e.g. Jost for Futura). Case-insensitive
|
|
14
|
+
* substring match.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMMERCIAL_FONT_DENYLIST: readonly string[];
|
|
17
|
+
/** Soft budget for total pack payload (css + font bytes) — Decision 6.7 /
|
|
18
|
+
* Decision 5 "Budget (soft)". Exceeding it is a WARNING, not an error. */
|
|
19
|
+
export declare const THEME_PACK_SOFT_BUDGET_BYTES: number;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SEMANTIC_CSS_NAMES, SYNTAX_CSS_NAMES } from "../color-scheme-utils.js";
|
|
2
|
+
import { COMPONENT_TOKENS } from "../config/component-tokens.js";
|
|
3
|
+
const ZD_BASE_ROLE_NAMES = [
|
|
4
|
+
"--zd-bg",
|
|
5
|
+
"--zd-fg",
|
|
6
|
+
"--zd-selection-bg",
|
|
7
|
+
"--zd-selection-fg"
|
|
8
|
+
];
|
|
9
|
+
const FONT_TOKEN_NAMES = ["--font-sans", "--font-mono", "--font-display"];
|
|
10
|
+
const ZFB_HI_BRIDGE_NAMES = [
|
|
11
|
+
"--zfb-hi-fg",
|
|
12
|
+
"--zfb-hi-bg",
|
|
13
|
+
"--zfb-hi-esc",
|
|
14
|
+
"--zfb-hi-op",
|
|
15
|
+
"--zfb-hi-com",
|
|
16
|
+
"--zfb-hi-str",
|
|
17
|
+
"--zfb-hi-num",
|
|
18
|
+
"--zfb-hi-const",
|
|
19
|
+
"--zfb-hi-kw",
|
|
20
|
+
"--zfb-hi-fn",
|
|
21
|
+
"--zfb-hi-ty",
|
|
22
|
+
"--zfb-hi-ns",
|
|
23
|
+
"--zfb-hi-prop",
|
|
24
|
+
"--zfb-hi-var",
|
|
25
|
+
"--zfb-hi-tag",
|
|
26
|
+
"--zfb-hi-attr",
|
|
27
|
+
"--zfb-hi-punct",
|
|
28
|
+
"--zfb-hi-ins",
|
|
29
|
+
"--zfb-hi-ins-bg",
|
|
30
|
+
"--zfb-hi-del",
|
|
31
|
+
"--zfb-hi-del-bg",
|
|
32
|
+
"--zfb-hi-hd"
|
|
33
|
+
];
|
|
34
|
+
const KNOWN_THEME_PACK_TOKEN_NAMES = /* @__PURE__ */ new Set([
|
|
35
|
+
...ZD_BASE_ROLE_NAMES,
|
|
36
|
+
...Object.values(SEMANTIC_CSS_NAMES),
|
|
37
|
+
...Object.values(SYNTAX_CSS_NAMES),
|
|
38
|
+
...COMPONENT_TOKENS.map((t) => t.cssVar),
|
|
39
|
+
...FONT_TOKEN_NAMES,
|
|
40
|
+
...ZFB_HI_BRIDGE_NAMES
|
|
41
|
+
]);
|
|
42
|
+
const COMMERCIAL_FONT_DENYLIST = [
|
|
43
|
+
"Futura",
|
|
44
|
+
"Helvetica Neue",
|
|
45
|
+
"Helvetica",
|
|
46
|
+
"Avenir",
|
|
47
|
+
"Gill Sans",
|
|
48
|
+
"Univers",
|
|
49
|
+
"Frutiger",
|
|
50
|
+
"Garamond Premier"
|
|
51
|
+
];
|
|
52
|
+
const THEME_PACK_SOFT_BUDGET_BYTES = 250 * 1024;
|
|
53
|
+
export {
|
|
54
|
+
COMMERCIAL_FONT_DENYLIST,
|
|
55
|
+
KNOWN_THEME_PACK_TOKEN_NAMES,
|
|
56
|
+
THEME_PACK_SOFT_BUDGET_BYTES
|
|
57
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ThemePackMeta } from "./meta-schema.js";
|
|
2
|
+
export type ThemePackValidationSeverity = "error" | "warning";
|
|
3
|
+
export interface ThemePackValidationIssue {
|
|
4
|
+
/** Short machine-readable rule id, e.g. `"scoping"` or `"known-token-names"`. */
|
|
5
|
+
rule: string;
|
|
6
|
+
message: string;
|
|
7
|
+
severity: ThemePackValidationSeverity;
|
|
8
|
+
}
|
|
9
|
+
export interface ThemePackValidationInput {
|
|
10
|
+
/** The pack's directory name (used for slug/dir-name parity). */
|
|
11
|
+
dirName: string;
|
|
12
|
+
/** `JSON.parse`-d `meta.json` content, pre-schema-validation. */
|
|
13
|
+
metaRaw: unknown;
|
|
14
|
+
/** `pack.css` text content, or `null` when the file is absent. */
|
|
15
|
+
cssContent: string | null;
|
|
16
|
+
/** Basenames of every file inside the pack's `fonts/` directory (`[]` when
|
|
17
|
+
* the directory is absent or empty). */
|
|
18
|
+
fontFiles: string[];
|
|
19
|
+
/** Optional total payload size (css + font bytes) for the soft budget
|
|
20
|
+
* check. Omit to skip that check entirely. */
|
|
21
|
+
totalPayloadBytes?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ThemePackValidationResult {
|
|
24
|
+
/** `true` iff no issue has `severity: "error"`. */
|
|
25
|
+
valid: boolean;
|
|
26
|
+
issues: ThemePackValidationIssue[];
|
|
27
|
+
/** The schema-parsed meta, present iff the schema check passed. */
|
|
28
|
+
meta?: ThemePackMeta;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validate a single theme pack against every Decision 6.7 authoring-
|
|
32
|
+
* convention rule. Filesystem-free — pass in the raw content the caller
|
|
33
|
+
* already read from disk (or, in a test, constructed directly).
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateThemePack(input: ThemePackValidationInput): ThemePackValidationResult;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import {
|
|
2
|
+
themePackMetaSchema,
|
|
3
|
+
THEME_PACK_SLUG_RE,
|
|
4
|
+
DEFAULT_THEME_PACK_SLUG
|
|
5
|
+
} from "./meta-schema.js";
|
|
6
|
+
import {
|
|
7
|
+
KNOWN_THEME_PACK_TOKEN_NAMES,
|
|
8
|
+
COMMERCIAL_FONT_DENYLIST,
|
|
9
|
+
THEME_PACK_SOFT_BUDGET_BYTES
|
|
10
|
+
} from "./token-manifest.js";
|
|
11
|
+
function stripComments(css) {
|
|
12
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
13
|
+
}
|
|
14
|
+
function parseTopLevelRules(css) {
|
|
15
|
+
const text = stripComments(css);
|
|
16
|
+
const rules = [];
|
|
17
|
+
const n = text.length;
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < n) {
|
|
20
|
+
const braceIdx = text.indexOf("{", i);
|
|
21
|
+
if (braceIdx === -1) break;
|
|
22
|
+
const preludeRaw = text.slice(i, braceIdx).replace(/@[a-zA-Z-]+[^{;]*;/g, "");
|
|
23
|
+
const prelude = preludeRaw.trim();
|
|
24
|
+
let depth = 1;
|
|
25
|
+
let j = braceIdx + 1;
|
|
26
|
+
while (j < n && depth > 0) {
|
|
27
|
+
const ch = text[j];
|
|
28
|
+
if (ch === "{") depth++;
|
|
29
|
+
else if (ch === "}") depth--;
|
|
30
|
+
j++;
|
|
31
|
+
}
|
|
32
|
+
const body = text.slice(braceIdx + 1, Math.max(braceIdx + 1, j - 1));
|
|
33
|
+
if (prelude.length > 0) rules.push({ prelude, body });
|
|
34
|
+
i = j;
|
|
35
|
+
}
|
|
36
|
+
return rules;
|
|
37
|
+
}
|
|
38
|
+
function isFontFaceRule(rule) {
|
|
39
|
+
return /^@font-face\b/i.test(rule.prelude);
|
|
40
|
+
}
|
|
41
|
+
function extractFontFaceFamilies(cssContent) {
|
|
42
|
+
const families = [];
|
|
43
|
+
for (const rule of parseTopLevelRules(cssContent)) {
|
|
44
|
+
if (!isFontFaceRule(rule)) continue;
|
|
45
|
+
const m = rule.body.match(/font-family\s*:\s*([^;]+);/i);
|
|
46
|
+
if (!m) continue;
|
|
47
|
+
const raw = m[1].trim();
|
|
48
|
+
families.push(raw.replace(/^["']|["']$/g, ""));
|
|
49
|
+
}
|
|
50
|
+
return families;
|
|
51
|
+
}
|
|
52
|
+
function checkSlugAndDirParity(dirName, meta, issues) {
|
|
53
|
+
if (!THEME_PACK_SLUG_RE.test(dirName)) {
|
|
54
|
+
issues.push({
|
|
55
|
+
rule: "slug-dir-parity",
|
|
56
|
+
severity: "error",
|
|
57
|
+
message: `directory name "${dirName}" does not match the required slug pattern [a-z0-9][a-z0-9-]*`
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (meta && meta.slug !== dirName) {
|
|
61
|
+
issues.push({
|
|
62
|
+
rule: "slug-dir-parity",
|
|
63
|
+
severity: "error",
|
|
64
|
+
message: `meta.json "slug" ("${meta.slug}") must equal the directory name ("${dirName}")`
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function checkCssPresence(dirName, cssContent, issues) {
|
|
69
|
+
if (dirName === DEFAULT_THEME_PACK_SLUG) {
|
|
70
|
+
if (cssContent !== null) {
|
|
71
|
+
issues.push({
|
|
72
|
+
rule: "css-presence",
|
|
73
|
+
severity: "error",
|
|
74
|
+
message: `the reserved "${DEFAULT_THEME_PACK_SLUG}" pack must NOT ship pack.css (it is the no-op stock look)`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (cssContent === null || cssContent.trim().length === 0) {
|
|
80
|
+
issues.push({
|
|
81
|
+
rule: "css-presence",
|
|
82
|
+
severity: "error",
|
|
83
|
+
message: `pack "${dirName}" must ship a non-empty pack.css`
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function checkScoping(slug, cssContent, issues) {
|
|
88
|
+
const prefix = `html[data-theme-pack="${slug}"]`;
|
|
89
|
+
for (const rule of parseTopLevelRules(cssContent)) {
|
|
90
|
+
if (isFontFaceRule(rule)) continue;
|
|
91
|
+
for (const rawBranch of rule.prelude.split(",")) {
|
|
92
|
+
const branch = rawBranch.trim();
|
|
93
|
+
if (branch.length === 0) continue;
|
|
94
|
+
if (!branch.startsWith(prefix)) {
|
|
95
|
+
issues.push({
|
|
96
|
+
rule: "scoping",
|
|
97
|
+
severity: "error",
|
|
98
|
+
message: `selector "${branch}" is not scoped under ${prefix}`
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function checkKnownTokenNames(cssContent, issues) {
|
|
105
|
+
const re = /--([a-zA-Z0-9-]+)\s*:/g;
|
|
106
|
+
const text = stripComments(cssContent);
|
|
107
|
+
const reported = /* @__PURE__ */ new Set();
|
|
108
|
+
let m;
|
|
109
|
+
while ((m = re.exec(text)) !== null) {
|
|
110
|
+
const name = `--${m[1]}`;
|
|
111
|
+
if (reported.has(name) || KNOWN_THEME_PACK_TOKEN_NAMES.has(name)) continue;
|
|
112
|
+
reported.add(name);
|
|
113
|
+
issues.push({
|
|
114
|
+
rule: "known-token-names",
|
|
115
|
+
severity: "error",
|
|
116
|
+
message: `unknown custom property "${name}" \u2014 not part of the --zd-*/--zdc-*/--font-*/--zfb-hi-* token contract (possible typo)`
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function checkImportantAllowlist(cssContent, issues) {
|
|
121
|
+
const text = stripComments(cssContent);
|
|
122
|
+
const re = /([a-zA-Z-]+)\s*:\s*[^;{}]*!important[^;{}]*;/g;
|
|
123
|
+
let m;
|
|
124
|
+
while ((m = re.exec(text)) !== null) {
|
|
125
|
+
const prop = m[1].toLowerCase();
|
|
126
|
+
if (prop !== "border-image") {
|
|
127
|
+
issues.push({
|
|
128
|
+
rule: "important-allowlist",
|
|
129
|
+
severity: "error",
|
|
130
|
+
message: `"!important" is only allowed on a "border-image" declaration (the h2\u2013h4 heading-rule gradient carve-out, Decision 6.6) \u2014 found on "${prop}"`
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function checkNoColorScheme(cssContent, issues) {
|
|
136
|
+
const text = stripComments(cssContent);
|
|
137
|
+
if (/(^|[;{}\s])color-scheme\s*:/.test(text)) {
|
|
138
|
+
issues.push({
|
|
139
|
+
rule: "no-color-scheme",
|
|
140
|
+
severity: "error",
|
|
141
|
+
message: `pack.css must not declare "color-scheme:" \u2014 mode is exclusively owned by the light/dark toggle machinery`
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function checkNoDataThemeSelector(cssContent, issues) {
|
|
146
|
+
const text = stripComments(cssContent);
|
|
147
|
+
if (/\[data-theme(?:=|\])/.test(text)) {
|
|
148
|
+
issues.push({
|
|
149
|
+
rule: "no-data-theme-selector",
|
|
150
|
+
severity: "error",
|
|
151
|
+
message: `pack.css must not select on "[data-theme]" \u2014 that attribute is owned by the light/dark mode toggle, not theme packs`
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function checkFontFaceParity(cssContent, meta, issues) {
|
|
156
|
+
const declaredFamilies = new Set(cssContent ? extractFontFaceFamilies(cssContent) : []);
|
|
157
|
+
const loadedFamilies = new Set(meta.fonts.loaded);
|
|
158
|
+
for (const loaded of loadedFamilies) {
|
|
159
|
+
if (!declaredFamilies.has(loaded)) {
|
|
160
|
+
issues.push({
|
|
161
|
+
rule: "font-face-parity",
|
|
162
|
+
severity: "error",
|
|
163
|
+
message: `fonts.loaded lists "${loaded}" but pack.css has no matching @font-face`
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const declared of declaredFamilies) {
|
|
168
|
+
if (!loadedFamilies.has(declared)) {
|
|
169
|
+
issues.push({
|
|
170
|
+
rule: "font-face-parity",
|
|
171
|
+
severity: "error",
|
|
172
|
+
message: `pack.css declares @font-face for "${declared}" but fonts.loaded does not list it`
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function isPlainColorValue(value) {
|
|
178
|
+
const v = value.trim();
|
|
179
|
+
if (/var\(|light-dark\(/i.test(v)) return false;
|
|
180
|
+
if (/^#[0-9a-f]{3,8}$/i.test(v)) return true;
|
|
181
|
+
if (/^(oklch|oklab|rgb|rgba|hsl|hsla|lab|lch|color)\(/i.test(v)) return true;
|
|
182
|
+
if (/^[a-z]+$/i.test(v)) return true;
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
function checkPreviewSwatches(meta, issues) {
|
|
186
|
+
for (const mode of ["light", "dark"]) {
|
|
187
|
+
const sw = meta.preview[mode];
|
|
188
|
+
const entries = [
|
|
189
|
+
["bg", sw.bg],
|
|
190
|
+
["fg", sw.fg],
|
|
191
|
+
["accent", sw.accent],
|
|
192
|
+
["syntax.keyword", sw.syntax.keyword],
|
|
193
|
+
["syntax.string", sw.syntax.string],
|
|
194
|
+
["syntax.comment", sw.syntax.comment],
|
|
195
|
+
["syntax.callable", sw.syntax.callable]
|
|
196
|
+
];
|
|
197
|
+
for (const [key, value] of entries) {
|
|
198
|
+
if (!isPlainColorValue(value)) {
|
|
199
|
+
issues.push({
|
|
200
|
+
rule: "preview-swatch-color",
|
|
201
|
+
severity: "error",
|
|
202
|
+
message: `preview.${mode}.${key} ("${value}") is not a plain resolved CSS color \u2014 var()/light-dark() are not allowed`
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function checkCommercialDenylist(cssContent, meta, issues) {
|
|
209
|
+
const scannedCss = (cssContent ?? "").replace(/\[data-theme-pack="[^"]*"\]/g, "");
|
|
210
|
+
const haystack = [
|
|
211
|
+
scannedCss,
|
|
212
|
+
meta.fonts.sans,
|
|
213
|
+
meta.fonts.mono,
|
|
214
|
+
meta.fonts.display ?? "",
|
|
215
|
+
...meta.fonts.loaded
|
|
216
|
+
].join("\n").toLowerCase();
|
|
217
|
+
for (const denied of COMMERCIAL_FONT_DENYLIST) {
|
|
218
|
+
if (haystack.includes(denied.toLowerCase())) {
|
|
219
|
+
issues.push({
|
|
220
|
+
rule: "commercial-font-denylist",
|
|
221
|
+
severity: "error",
|
|
222
|
+
message: `commercial typeface "${denied}" must not appear in pack.css or meta.json fonts \u2014 ship a self-hosted OFL substitute instead`
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function checkOflPresence(fontFiles, issues) {
|
|
228
|
+
const hasFontBinary = fontFiles.some((f) => /\.(woff2?|ttf|otf)$/i.test(f));
|
|
229
|
+
const hasOfl = fontFiles.some((f) => f.toUpperCase() === "OFL.TXT");
|
|
230
|
+
if (hasFontBinary && !hasOfl) {
|
|
231
|
+
issues.push({
|
|
232
|
+
rule: "ofl-required",
|
|
233
|
+
severity: "error",
|
|
234
|
+
message: `fonts/ ships font binaries but no OFL.txt license file (OFL redistribution requirement)`
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function checkPayloadBudget(totalPayloadBytes, issues) {
|
|
239
|
+
if (typeof totalPayloadBytes === "number" && totalPayloadBytes > THEME_PACK_SOFT_BUDGET_BYTES) {
|
|
240
|
+
issues.push({
|
|
241
|
+
rule: "payload-budget",
|
|
242
|
+
severity: "warning",
|
|
243
|
+
message: `total pack payload (~${Math.round(totalPayloadBytes / 1024)} KB) exceeds the ~250 KB soft budget`
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function validateThemePack(input) {
|
|
248
|
+
const issues = [];
|
|
249
|
+
const metaParseResult = themePackMetaSchema.safeParse(input.metaRaw);
|
|
250
|
+
let meta;
|
|
251
|
+
if (!metaParseResult.success) {
|
|
252
|
+
for (const issue of metaParseResult.error.issues) {
|
|
253
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
254
|
+
issues.push({
|
|
255
|
+
rule: "meta-schema",
|
|
256
|
+
severity: "error",
|
|
257
|
+
message: `meta.json "${path}": ${issue.message}`
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
meta = metaParseResult.data;
|
|
262
|
+
}
|
|
263
|
+
checkSlugAndDirParity(input.dirName, meta, issues);
|
|
264
|
+
checkCssPresence(input.dirName, input.cssContent, issues);
|
|
265
|
+
if (input.cssContent) {
|
|
266
|
+
checkScoping(input.dirName, input.cssContent, issues);
|
|
267
|
+
checkKnownTokenNames(input.cssContent, issues);
|
|
268
|
+
checkImportantAllowlist(input.cssContent, issues);
|
|
269
|
+
checkNoColorScheme(input.cssContent, issues);
|
|
270
|
+
checkNoDataThemeSelector(input.cssContent, issues);
|
|
271
|
+
}
|
|
272
|
+
if (meta) {
|
|
273
|
+
checkFontFaceParity(input.cssContent, meta, issues);
|
|
274
|
+
checkPreviewSwatches(meta, issues);
|
|
275
|
+
checkCommercialDenylist(input.cssContent, meta, issues);
|
|
276
|
+
}
|
|
277
|
+
checkOflPresence(input.fontFiles, issues);
|
|
278
|
+
checkPayloadBudget(input.totalPayloadBytes, issues);
|
|
279
|
+
const valid = !issues.some((i) => i.severity === "error");
|
|
280
|
+
return { valid, issues, ...meta ? { meta } : {} };
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
validateThemePack
|
|
284
|
+
};
|
|
@@ -13,10 +13,8 @@ export declare function readColorSchemeFromDom(defaultMode: ColorSchemeMode): Co
|
|
|
13
13
|
* `color-scheme-changed` window event.
|
|
14
14
|
*
|
|
15
15
|
* Tweak-state reconciliation is intentionally NOT done here (#2037). The zdtp
|
|
16
|
-
* panel owns its own storage lifecycle
|
|
17
|
-
*
|
|
18
|
-
* `zudo-doc-tweak-state-v3` / `-v2` / `zudo-doc-tweak-state` (v1) keys into
|
|
19
|
-
* it), and its own `color-scheme-changed` listener clears applied inline
|
|
16
|
+
* panel owns its own storage lifecycle and current persisted-state contract;
|
|
17
|
+
* its own `color-scheme-changed` listener clears applied inline
|
|
20
18
|
* styles and re-seeds the color slice from the newly active scheme. An
|
|
21
19
|
* earlier version of this function deleted `zudo-doc-tweak-state` + `-v2` on
|
|
22
20
|
* every toggle, which (a) targeted stale keys after zdtp moved to v3 — so it
|