@astryxdesign/cli 0.6.4 → 0.6.5-canary.00f1ed9
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 +56 -0
- package/README.md +103 -95
- package/api/build/_adapter.d.mts +36 -2
- package/api/build/_adapter.mjs +41 -10
- package/api/build/build.doc.mjs +8 -3
- package/api/build/build.test.mjs +60 -2
- package/api/build/kit/kit.mjs +109 -26
- package/api/build/kit/rank.d.mts +24 -8
- package/api/build/kit/rank.mjs +277 -97
- package/api/build/kit/rank.test.mjs +231 -48
- package/api/component/_adapter.d.mts +25 -0
- package/api/component/_adapter.mjs +59 -5
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +37 -17
- package/api/component/component.mjs +249 -9
- package/api/component/component.type.d.mts +25 -0
- package/api/component/component.type.mjs +44 -0
- package/api/discover/_adapter.d.mts +114 -6
- package/api/discover/_adapter.mjs +372 -17
- package/api/discover/_adapter.test.mjs +215 -0
- package/api/discover/_catalog-view.d.mts +115 -0
- package/api/discover/_catalog-view.mjs +203 -0
- package/api/discover/_catalog-view.test.mjs +128 -0
- package/api/discover/detail/detail.d.mts +18 -6
- package/api/discover/detail/detail.mjs +67 -13
- package/api/discover/detail/detail.test.mjs +85 -0
- package/api/discover/detail/item/item.d.mts +26 -0
- package/api/discover/detail/item/item.mjs +78 -0
- package/api/discover/detail/item/item.test.mjs +73 -0
- package/api/discover/discover.d.mts +3 -9
- package/api/discover/discover.doc.mjs +61 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +147 -8
- package/api/discover/discover.type.mjs +102 -12
- package/api/discover/list/list.d.mts +20 -6
- package/api/discover/list/list.mjs +45 -12
- package/api/discover/list/list.test.mjs +46 -0
- package/api/discover/search/search.d.mts +18 -16
- package/api/discover/search/search.mjs +102 -56
- package/api/discover/search/search.test.mjs +144 -10
- package/api/docs/_adapter.d.mts +8 -3
- package/api/docs/_adapter.mjs +14 -6
- package/api/docs/docOverlays.test.mjs +27 -1
- package/api/docs/docs.doc.mjs +2 -2
- package/api/docs/docs.test.mjs +54 -18
- package/api/docs/integration-tree.test.mjs +17 -0
- package/api/docs/integrationDocs.test.mjs +27 -5
- package/api/doctor/doctor.d.mts +8 -3
- package/api/doctor/doctor.doc.mjs +17 -8
- package/api/doctor/doctor.mjs +90 -9
- package/api/doctor/doctor.test.mjs +122 -10
- package/api/doctor/doctor.type.d.mts +1 -1
- package/api/doctor/doctor.type.mjs +1 -1
- package/api/error.d.mts +22 -0
- package/api/error.mjs +42 -0
- package/api/gap-report/gap-report.doc.mjs +19 -10
- package/api/hook/hook.doc.mjs +6 -3
- package/api/index.d.mts +1 -0
- package/api/index.mjs +5 -3
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +7 -3
- package/api/integration/add-contribution.test.mjs +3 -3
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- package/api/integration/add-theme.mjs +266 -23
- package/api/integration/add-theme.test.mjs +247 -0
- package/api/integration/authoring-checks.mjs +12 -9
- package/api/integration/authoring-checks.type.d.mts +8 -0
- package/api/integration/authoring-checks.type.mjs +7 -3
- package/api/integration/integration-authoring.type.d.mts +4 -1
- package/api/integration/integration-authoring.type.mjs +6 -1
- package/api/integration/integrationAdd.doc.mjs +6 -0
- package/api/integration/integrationAddTheme.doc.mjs +10 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -1
- package/api/integration/integrationDocConflicts.doc.mjs +1 -1
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/integrationTemplateConflicts.doc.mjs +1 -1
- package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
- package/api/integration/pack-check.mjs +92 -10
- package/api/integration/pack-check.test.mjs +140 -1
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/integration/validate-integration.d.mts +4 -2
- package/api/integration/validate-integration.mjs +7 -2
- package/api/integration/validate-integration.test.mjs +55 -0
- package/api/integration/validate-integration.type.d.mts +5 -0
- package/api/integration/validate-integration.type.mjs +5 -1
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/expand/expand.mjs +12 -7
- package/api/layout/expand/expand.receipt.test.mjs +74 -0
- package/api/layout/layout.type.d.mts +1 -0
- package/api/layout/layout.type.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +1 -1
- package/api/search/search.d.mts +51 -1
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +299 -17
- package/api/search/search.test.mjs +216 -18
- package/api/swizzle/copy/copy.mjs +66 -3
- package/api/swizzle/swizzle.doc.mjs +11 -5
- package/api/template/copy/copy.mjs +15 -9
- package/api/template/copy/copy.receipt.test.mjs +77 -0
- package/api/template/copy/copy.test.mjs +9 -0
- package/api/template/show/show.mjs +15 -4
- package/api/template/show/show.test.mjs +76 -0
- package/api/template/template-integration.test.mjs +14 -0
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +8 -3
- package/api/template/template.mjs +1 -0
- package/api/template/template.type.d.mts +2 -0
- package/api/template/template.type.mjs +2 -0
- package/api/theme/add/add.mjs +17 -25
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +40 -23
- package/api/theme/build/build.d.mts +24 -0
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +243 -26
- package/api/theme/build/build.project-core.test.mjs +165 -0
- package/api/theme/build/build.rollback.test.mjs +148 -0
- package/api/theme/generateTonalPalette.doc.mjs +1 -2
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +9 -10
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +2 -1
- package/api/theme/themePaletteGenerate.doc.mjs +15 -8
- package/api/theme/themeTargets.doc.mjs +3 -2
- package/api/theme/themeTemplate.doc.mjs +2 -1
- package/api/upgrade/run/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +25 -6
- package/api/upgrade/run/run.test.mjs +45 -1
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/api/upgrade/upgrade.type.d.mts +1 -0
- package/api/upgrade/upgrade.type.mjs +3 -2
- package/assets/codemods/__tests__/runner.test.mjs +3 -1
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +5 -4
- package/assets/docs/README.md +4 -2
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +8 -2
- package/assets/docs/elevation.doc.mjs +6 -4
- package/assets/docs/getting-started.doc.mjs +5 -16
- package/assets/docs/icons.doc.mjs +3 -21
- package/assets/docs/illustrations.doc.mjs +7 -15
- package/assets/docs/internationalization.doc.mjs +7 -5
- package/assets/docs/layout.doc.dense.mjs +130 -82
- package/assets/docs/layout.doc.mjs +133 -77
- package/assets/docs/migration.doc.mjs +19 -21
- package/assets/docs/motion.doc.mjs +16 -3
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +8 -0
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +8 -3
- package/assets/docs/spacing.doc.mjs +7 -2
- package/assets/docs/styling-libraries.doc.mjs +6 -2
- package/assets/docs/styling.doc.mjs +19 -23
- package/assets/docs/theme.doc.dense.mjs +58 -18
- package/assets/docs/theme.doc.mjs +57 -47
- package/assets/docs/theme.doc.zh.mjs +9 -8
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +389 -8
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/add-a-component.doc.mjs +75 -0
- package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
- package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
- package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
- package/assets/docs/tree/block-template.doc.mjs +130 -0
- package/assets/docs/tree/build-the-template.doc.mjs +28 -0
- package/assets/docs/tree/building-blocks.doc.mjs +46 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
- package/assets/docs/tree/checks.doc.mjs +119 -0
- package/assets/docs/tree/codemods.doc.mjs +147 -0
- package/assets/docs/tree/component-family.doc.mjs +113 -0
- package/assets/docs/tree/component-imports.doc.mjs +69 -0
- package/assets/docs/tree/component-lookups.doc.mjs +149 -0
- package/assets/docs/tree/components.doc.mjs +23 -0
- package/assets/docs/tree/configuration.doc.mjs +23 -0
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
- package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
- package/assets/docs/tree/docs.doc.mjs +21 -0
- package/assets/docs/tree/document-the-template.doc.mjs +28 -0
- package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
- package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
- package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
- package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
- package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
- package/assets/docs/tree/help.doc.mjs +16 -0
- package/assets/docs/tree/integrations.doc.mjs +25 -451
- package/assets/docs/tree/links.doc.mjs +98 -0
- package/assets/docs/tree/package-and-test.doc.mjs +32 -0
- package/assets/docs/tree/page-template.doc.mjs +71 -0
- package/assets/docs/tree/publishing.doc.mjs +111 -0
- package/assets/docs/tree/quick-start.doc.mjs +272 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
- package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
- package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
- package/assets/docs/tree/ship.doc.mjs +16 -0
- package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
- package/assets/docs/tree/single-component.doc.mjs +165 -0
- package/assets/docs/tree/start-a-template.doc.mjs +143 -0
- package/assets/docs/tree/subcomponent.doc.mjs +115 -0
- package/assets/docs/tree/template-assets.doc.mjs +64 -0
- package/assets/docs/tree/template-doc-overview.doc.mjs +121 -0
- package/assets/docs/tree/template-fonts.doc.mjs +102 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
- package/assets/docs/tree/template-icons.doc.mjs +97 -0
- package/assets/docs/tree/template-images-media.doc.mjs +127 -0
- package/assets/docs/tree/template-styles.doc.mjs +93 -0
- package/assets/docs/tree/templates.doc.mjs +34 -0
- package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
- package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
- package/assets/docs/tree/themes.doc.mjs +39 -0
- package/assets/docs/tree/troubleshooting.doc.mjs +153 -0
- package/assets/docs/tree/upgrading.doc.mjs +103 -0
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
- package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
- package/assets/docs/tree/versioning.doc.mjs +162 -0
- package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
- package/assets/docs/typography.doc.mjs +24 -4
- package/assets/docs/working-with-ai.doc.mjs +30 -22
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/assets/templates/pages/ai-chat/template.doc.mjs +16 -1
- package/assets/templates/pages/ai-chat-landing/template.doc.mjs +9 -1
- package/assets/templates/pages/blank/template.doc.mjs +3 -1
- package/assets/templates/pages/canvas-editor/template.doc.mjs +9 -1
- package/assets/templates/pages/centered-hero/template.doc.mjs +3 -1
- package/assets/templates/pages/checkout-wizard/template.doc.mjs +1 -0
- package/assets/templates/pages/classic-gallery/template.doc.mjs +3 -1
- package/assets/templates/pages/contact-form/template.doc.mjs +16 -1
- package/assets/templates/pages/dashboard/template.doc.mjs +15 -1
- package/assets/templates/pages/dashboard-alert-rail/template.doc.mjs +23 -1
- package/assets/templates/pages/dashboard-cohort-funnel/template.doc.mjs +10 -1
- package/assets/templates/pages/dashboard-comparison/template.doc.mjs +9 -1
- package/assets/templates/pages/dashboard-composition/template.doc.mjs +10 -1
- package/assets/templates/pages/dashboard-progress/template.doc.mjs +17 -1
- package/assets/templates/pages/dashboard-scorecard/template.doc.mjs +2 -1
- package/assets/templates/pages/detail-page/template.doc.mjs +8 -0
- package/assets/templates/pages/documentation/template.doc.mjs +10 -1
- package/assets/templates/pages/documentation-design/template.doc.mjs +10 -1
- package/assets/templates/pages/documentation-technical/template.doc.mjs +10 -1
- package/assets/templates/pages/editor/template.doc.mjs +9 -1
- package/assets/templates/pages/file-explorer/template.doc.mjs +3 -1
- package/assets/templates/pages/form-two-column/template.doc.mjs +17 -1
- package/assets/templates/pages/form-wizard/template.doc.mjs +14 -1
- package/assets/templates/pages/form-wizard-dialog/template.doc.mjs +1 -0
- package/assets/templates/pages/gallery-hero/template.doc.mjs +10 -1
- package/assets/templates/pages/ide/template.doc.mjs +9 -1
- package/assets/templates/pages/incident-console/template.doc.mjs +10 -1
- package/assets/templates/pages/kanban-board/template.doc.mjs +11 -1
- package/assets/templates/pages/library/template.doc.mjs +15 -1
- package/assets/templates/pages/login/template.doc.mjs +10 -1
- package/assets/templates/pages/login-card/template.doc.mjs +11 -1
- package/assets/templates/pages/login-split/template.doc.mjs +10 -1
- package/assets/templates/pages/login-sso/template.doc.mjs +10 -1
- package/assets/templates/pages/messaging-shell/template.doc.mjs +11 -1
- package/assets/templates/pages/mixed-gallery/template.doc.mjs +10 -1
- package/assets/templates/pages/payment-form/template.doc.mjs +3 -1
- package/assets/templates/pages/product-detail/template.doc.mjs +9 -1
- package/assets/templates/pages/product-gallery/template.doc.mjs +10 -1
- package/assets/templates/pages/settings/template.doc.mjs +3 -1
- package/assets/templates/pages/settings-dialog/template.doc.mjs +9 -1
- package/assets/templates/pages/settings-sidebar/template.doc.mjs +9 -1
- package/assets/templates/pages/shell-nav/template.doc.mjs +10 -1
- package/assets/templates/pages/shell-side-nav/template.doc.mjs +14 -1
- package/assets/templates/pages/shell-top-nav/template.doc.mjs +11 -1
- package/assets/templates/pages/side-gallery/template.doc.mjs +3 -1
- package/assets/templates/pages/table/template.doc.mjs +11 -1
- package/assets/templates/pages/table-filter/template.doc.mjs +21 -1
- package/assets/templates/pages/table-grouped/template.doc.mjs +15 -1
- package/assets/templates/pages/table-inbox/template.doc.mjs +18 -6
- package/assets/templates/pages/table-page/template.doc.mjs +20 -1
- package/assets/templates/pages/table-tree/template.doc.mjs +14 -1
- package/assets/templates/pages/theme-showcase/template.doc.mjs +10 -1
- package/assets/templates/pages/work-item-detail/template.doc.mjs +10 -0
- package/assets/templates/themes/butter/icons.tsx +2 -0
- package/assets/templates/themes/chocolate/icons.tsx +2 -0
- package/assets/templates/themes/gothic/icons.tsx +2 -0
- package/assets/templates/themes/matcha/icons.tsx +2 -0
- package/assets/templates/themes/neutral/icons.tsx +2 -0
- package/assets/templates/themes/stone/icons.tsx +2 -0
- package/assets/templates/themes/y2k/icons.tsx +2 -0
- package/authoring/config/config.doc.mjs +9 -1
- package/authoring/config/parse.d.mts +2 -0
- package/authoring/config/parse.mjs +19 -0
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +11 -0
- package/authoring/discover/discover.doc.d.mts +13 -0
- package/authoring/discover/discover.doc.mjs +138 -0
- package/authoring/discover/parse.d.mts +24 -0
- package/authoring/discover/parse.mjs +128 -0
- package/authoring/discover/parse.test.mjs +124 -0
- package/authoring/discover/type.ts +87 -0
- package/authoring/doctypes/_schema.d.mts +3 -2
- package/authoring/doctypes/_schema.mjs +6 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +4 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -0
- package/authoring/doctypes/component/type.ts +8 -0
- package/authoring/doctypes/reference/reference.doc.mjs +7 -0
- package/authoring/doctypes/reference/type.ts +5 -0
- package/authoring/doctypes/schema/schema.doc.mjs +2 -2
- package/authoring/doctypes/template/parse.d.mts +2 -0
- package/authoring/doctypes/template/parse.mjs +1 -0
- package/authoring/doctypes/template/parse.test.mjs +21 -0
- package/authoring/doctypes/template/template.doc.mjs +7 -1
- package/authoring/doctypes/template/type.ts +12 -2
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +10 -0
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +12 -10
- package/clients/cli/commands/component/index.mjs +152 -55
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +89 -0
- package/clients/cli/commands/component.doc.mjs +27 -9
- package/clients/cli/commands/discover.doc.mjs +53 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +60 -17
- package/clients/cli/commands/docs.test.mjs +113 -24
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
- package/clients/cli/commands/doctor-integration.test.mjs +53 -0
- package/clients/cli/commands/doctor.doc.mjs +3 -1
- package/clients/cli/commands/doctor.mjs +53 -9
- package/clients/cli/commands/gap-report.doc.mjs +10 -9
- package/clients/cli/commands/init.doc.mjs +9 -6
- package/clients/cli/commands/integration-add.doc.mjs +17 -7
- package/clients/cli/commands/integration-authoring.test.mjs +70 -9
- package/clients/cli/commands/integration-pack.doc.mjs +5 -9
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration-verify.doc.mjs +22 -0
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +76 -43
- package/clients/cli/commands/layout-expand.doc.mjs +3 -1
- package/clients/cli/commands/layout.expand-receipt.test.mjs +94 -0
- package/clients/cli/commands/layout.mjs +16 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +10 -3
- package/clients/cli/commands/search.mjs +21 -2
- package/clients/cli/commands/search.test.mjs +21 -4
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.copy-receipt.test.mjs +60 -0
- package/clients/cli/commands/template.doc.mjs +1 -1
- package/clients/cli/commands/template.mjs +19 -5
- package/clients/cli/commands/template.show-media.test.mjs +62 -0
- package/clients/cli/commands/text-json-parity.test.mjs +7 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
- package/clients/cli/commands/theme-palette.doc.mjs +1 -2
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +2 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +14 -0
- package/clients/cli/commands/upgrade.doc.mjs +62 -3
- package/clients/cli/commands/write-failure.test.mjs +175 -0
- package/clients/cli/index.mjs +28 -6
- package/clients/cli/lib/define-command.mjs +28 -4
- package/clients/cli/lib/define-command.test.mjs +54 -0
- package/clients/cli/lib/exit-codes.test.mjs +17 -1
- package/clients/cli/lib/json-shim.mjs +24 -14
- package/clients/cli/lib/manifest.mjs +48 -156
- package/clients/cli/lib/manifest.test.mjs +103 -9
- package/clients/cli/lib/parse-error-format.test.mjs +81 -0
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/agent-docs/agent-docs.test.mjs +3 -2
- package/foundation/discovery/authoring-self-docs.mjs +1 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
- package/foundation/discovery/cli-self-docs.mjs +16 -2
- package/foundation/discovery/cli-self-docs.test.mjs +20 -0
- package/foundation/discovery/docs-discovery.mjs +5 -1
- package/foundation/discovery/docs-discovery.test.mjs +21 -0
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.d.mts +14 -0
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +37 -1
- package/foundation/discovery/template-adapter.mjs +21 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +5 -4
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/tree.d.mts +4 -0
- package/foundation/doc-compiler/tree.mjs +6 -1
- package/foundation/doc-compiler/tree.test.mjs +65 -14
- package/foundation/integrations/cli-requirement.d.mts +75 -11
- package/foundation/integrations/cli-requirement.mjs +120 -23
- package/foundation/integrations/cli-requirement.test.mjs +141 -9
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +14 -1
- package/foundation/integrations/integrations.mjs +41 -1
- package/foundation/integrations/integrations.test.mjs +31 -0
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- package/foundation/response/error-codes.doc.mjs +6 -8
- package/foundation/response/error-codes.test.mjs +30 -5
- package/foundation/response/response-types.doc.d.mts +5 -4
- package/foundation/response/response-types.doc.mjs +49 -19
- package/foundation/response/response-types.doc.test.mjs +23 -0
- package/foundation/response/response.doc.mjs +11 -10
- package/package.json +9 -9
- package/assets/docs/tree/integrations.test.mjs +0 -62
- package/assets/docs/tree/writing-docs.doc.mjs +0 -286
package/api/search/search.mjs
CHANGED
|
@@ -42,6 +42,18 @@
|
|
|
42
42
|
* sentence, a near miss is usually a different word: "site" is not "side",
|
|
43
43
|
* "cable" is not "table".
|
|
44
44
|
*
|
|
45
|
+
* A multi-word query has a reserved top tier (see {@link scoreQuery}): the
|
|
46
|
+
* whole query as a candidate's name or keyword (190-200), then the whole query
|
|
47
|
+
* as a phrase inside a doc's title or one of its headings (170), then a whole
|
|
48
|
+
* title of two words or more inside the query (160-169), then a candidate that
|
|
49
|
+
* matches every word of the query, at least one of them by name or keyword
|
|
50
|
+
* (151-159). Below those sits everything else: a partial match, or every word
|
|
51
|
+
* matched only in prose or through the components a page renders. A section titled "Light/Dark Mode" answers `dark
|
|
52
|
+
* mode` better than any doc that merely names `mode` in code, however exactly;
|
|
53
|
+
* "Dark mode" answers `how do I add dark mode`; and a guide whose title and
|
|
54
|
+
* description hold both words of `troubleshoot integration` answers it better
|
|
55
|
+
* than a doc named `integration`.
|
|
56
|
+
*
|
|
45
57
|
* Description and guidance are separate tiers on purpose. A component's own
|
|
46
58
|
* one-line description saying "notification" is a claim about what it IS; the
|
|
47
59
|
* same word inside another component's best-practice advice is a passing
|
|
@@ -105,6 +117,9 @@ import {setResultCoverage} from './coverage.mjs';
|
|
|
105
117
|
* @property {string} [description]
|
|
106
118
|
* @property {string[]} [prose]
|
|
107
119
|
* @property {string[]} [guidance]
|
|
120
|
+
* @property {string[]} [titles] - A doc's title and the headings inside it:
|
|
121
|
+
* the lines a reader scans to pick it. The whole query standing in one of
|
|
122
|
+
* them, or one of them standing whole in the query, is a top-tier match.
|
|
108
123
|
* @property {string} [_import]
|
|
109
124
|
* @property {string} [_title]
|
|
110
125
|
* @property {string} [_topic] - A doc result's topic or docs-tree route.
|
|
@@ -414,6 +429,120 @@ function bestForToken(tok, candidate, opts = {}) {
|
|
|
414
429
|
return best;
|
|
415
430
|
}
|
|
416
431
|
|
|
432
|
+
/**
|
|
433
|
+
* The score of a whole-query phrase inside a doc's title or heading: a keyword
|
|
434
|
+
* substring hit (70) promoted by the same 100 as the exact tier. Below an
|
|
435
|
+
* exact name or keyword (190-200), above the token-sum path (~151 at most).
|
|
436
|
+
*/
|
|
437
|
+
const TITLE_PHRASE_SCORE = 170;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* The score of a whole title inside a longer query, before its coverage bonus:
|
|
441
|
+
* one step below {@link TITLE_PHRASE_SCORE}. The bonus (one per query term the
|
|
442
|
+
* candidate matches, at most 9) orders the sections that share a common title,
|
|
443
|
+
* so "best practices for spacing" puts Spacing's Best Practices first.
|
|
444
|
+
*/
|
|
445
|
+
const TITLE_IN_QUERY_SCORE = 160;
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* The score of a candidate that matches every content word of a multi-word
|
|
449
|
+
* query, before a bonus of up to 8 for how strong its strongest match is: just
|
|
450
|
+
* above anything that matches only some of the words. The token-sum path tops
|
|
451
|
+
* out near 150 for a partial match (a 100 on one word, the per-word bonus, and
|
|
452
|
+
* the coverage term), so an AND-match with one keyword-strength hit (see
|
|
453
|
+
* {@link STRONG_TOKEN_SCORE}) always outranks an OR-match, and stays below the
|
|
454
|
+
* title tiers.
|
|
455
|
+
*/
|
|
456
|
+
const FULL_COVERAGE_SCORE = 151;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* The strongest single-word hit an every-word match needs to take that tier: a
|
|
460
|
+
* keyword substring. Two passing mentions in prose, or the components a page
|
|
461
|
+
* happens to render, are breadth, not relevance; they stay on the token sum,
|
|
462
|
+
* below an exact name or keyword hit on one of the words.
|
|
463
|
+
*/
|
|
464
|
+
const STRONG_TOKEN_SCORE = 70;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* The words of a title or query, lowercased, without punctuation or code ticks.
|
|
468
|
+
* @param {string} text
|
|
469
|
+
* @returns {string[]}
|
|
470
|
+
*/
|
|
471
|
+
function phraseWords(text) {
|
|
472
|
+
return unlinkText(text).toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Whether two words are the same word, allowing a plural on either side, so
|
|
477
|
+
* `data attributes selector` still reads "Data attribute selectors".
|
|
478
|
+
* @param {string} a
|
|
479
|
+
* @param {string} b
|
|
480
|
+
*/
|
|
481
|
+
function samePhraseWord(a, b) {
|
|
482
|
+
return (
|
|
483
|
+
a === b ||
|
|
484
|
+
`${a}s` === b ||
|
|
485
|
+
`${b}s` === a ||
|
|
486
|
+
`${a}es` === b ||
|
|
487
|
+
`${b}es` === a
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Whether `plural` is the plural of `word`: `integrations` of `integration`,
|
|
493
|
+
* `boxes` of `box`. `es` only follows s, x, z, ch, or sh, so `notes` is not a
|
|
494
|
+
* plural of `not`.
|
|
495
|
+
* @param {string} plural
|
|
496
|
+
* @param {string} word
|
|
497
|
+
*/
|
|
498
|
+
function pluralOf(plural, word) {
|
|
499
|
+
if (word.length < 3) return false;
|
|
500
|
+
if (plural === `${word}s`) return true;
|
|
501
|
+
return /(?:s|x|z|ch|sh)$/.test(word) && plural === `${word}es`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* The first title or heading that holds every word of the query, in order and
|
|
506
|
+
* side by side, or null.
|
|
507
|
+
* @param {string} term - Lowercased full query.
|
|
508
|
+
* @param {string[] | undefined} titles
|
|
509
|
+
* @returns {string | null}
|
|
510
|
+
*/
|
|
511
|
+
export function headingWithPhrase(term, titles) {
|
|
512
|
+
const query = phraseWords(term);
|
|
513
|
+
if (query.length < 2 || !titles) return null;
|
|
514
|
+
for (const title of titles) {
|
|
515
|
+
const words = phraseWords(String(title ?? ''));
|
|
516
|
+
for (let i = 0; i + query.length <= words.length; i++) {
|
|
517
|
+
if (query.every((word, j) => samePhraseWord(words[i + j], word)))
|
|
518
|
+
return title;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* The first title or heading of two words or more that the query holds whole,
|
|
526
|
+
* in order and side by side, or null. A question such as "how do I add dark
|
|
527
|
+
* mode" names the "Dark mode" section outright, around words no title has.
|
|
528
|
+
* @param {string} term - Lowercased full query.
|
|
529
|
+
* @param {string[] | undefined} titles
|
|
530
|
+
* @returns {string | null}
|
|
531
|
+
*/
|
|
532
|
+
export function titleInQuery(term, titles) {
|
|
533
|
+
const query = phraseWords(term);
|
|
534
|
+
if (!titles) return null;
|
|
535
|
+
for (const title of titles) {
|
|
536
|
+
const words = phraseWords(String(title ?? ''));
|
|
537
|
+
if (words.length < 2 || words.length > query.length) continue;
|
|
538
|
+
for (let i = 0; i + words.length <= query.length; i++) {
|
|
539
|
+
if (words.every((word, j) => samePhraseWord(query[i + j], word)))
|
|
540
|
+
return title;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
|
|
417
546
|
/**
|
|
418
547
|
* @param {string} term - Lowercased full query.
|
|
419
548
|
* @param {string[]} tokens - Content tokens from tokenizeQuery(term).
|
|
@@ -437,16 +566,22 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
437
566
|
// is usually a different word, not a typo.
|
|
438
567
|
const fuzzy = tokens.length <= 1;
|
|
439
568
|
const full = scoreCandidate(term, candidate, {fuzzy});
|
|
569
|
+
// A query of several words keeps its phrase tiers below even when stopwords
|
|
570
|
+
// leave one content word: "make an integration" is still the phrase an
|
|
571
|
+
// author declares as a keyword, and "build an integration" still names a
|
|
572
|
+
// title outright, though each tokenizes to `integration` alone.
|
|
573
|
+
const phrase = phraseWords(term).length >= 2;
|
|
440
574
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
575
|
+
/** 0–1 content tokens: whole-phrase fuzzy matching (typo tolerance for
|
|
576
|
+
* single words), but if stopwords left exactly one DIFFERENT token (e.g.
|
|
577
|
+
* "pricing page" → "pricing"), score that token too and take the stronger. */
|
|
578
|
+
const fewTokens = () => {
|
|
445
579
|
const single =
|
|
446
580
|
tokens.length === 1 ? bestForToken(tokens[0], candidate, {fuzzy}) : null;
|
|
447
581
|
if (full && (!single || full.score >= single.score)) return asFull(full);
|
|
448
582
|
return single ? asFull(single) : null;
|
|
449
|
-
}
|
|
583
|
+
};
|
|
584
|
+
if (tokens.length <= 1 && !phrase) return fewTokens();
|
|
450
585
|
|
|
451
586
|
// The full (untokenized) query matching a candidate's name or a declared
|
|
452
587
|
// keyword VERBATIM — full.score 90 or 100, the only two scoreCandidate
|
|
@@ -463,6 +598,22 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
463
598
|
return asFull({score: full.score + 100, reason: full.reason});
|
|
464
599
|
}
|
|
465
600
|
|
|
601
|
+
// The whole query standing as a phrase in a doc's title or one of its
|
|
602
|
+
// headings is the next tier down, and still above the token-sum path. The
|
|
603
|
+
// reader named what the section is about, in order: `dark mode` is the
|
|
604
|
+
// "Light/Dark Mode" section. Without this, the title scores a keyword
|
|
605
|
+
// substring (70) and loses to a doc that happens to name `mode` exactly in
|
|
606
|
+
// a code tick (90 on one token, 98 with coverage), so API enum docs outrank
|
|
607
|
+
// the guide section.
|
|
608
|
+
const heading = headingWithPhrase(term, candidate.titles);
|
|
609
|
+
if (heading != null) {
|
|
610
|
+
return asFull({
|
|
611
|
+
score: TITLE_PHRASE_SCORE,
|
|
612
|
+
reason: `title "${heading}" holds the whole query`,
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
if (tokens.length <= 1) return fewTokens();
|
|
616
|
+
|
|
466
617
|
// Multi-word natural language: score each content token, counting only
|
|
467
618
|
// strong hits, then reward coverage so candidates matching more terms win.
|
|
468
619
|
let strongest = 0;
|
|
@@ -477,8 +628,42 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
477
628
|
hitTerms.push(tok);
|
|
478
629
|
}
|
|
479
630
|
}
|
|
631
|
+
// The reverse of the title tier, a step lower: the query holds a whole title
|
|
632
|
+
// of two words or more, so the reader asked a question around the section's
|
|
633
|
+
// name ("how do I add dark mode"). Coverage breaks ties between sections
|
|
634
|
+
// that share a title such as "Best Practices".
|
|
635
|
+
const named = titleInQuery(term, candidate.titles);
|
|
636
|
+
if (named != null) {
|
|
637
|
+
return {
|
|
638
|
+
score: TITLE_IN_QUERY_SCORE + Math.min(matched, 9),
|
|
639
|
+
reason: `the query names the title "${named}"`,
|
|
640
|
+
matched,
|
|
641
|
+
total,
|
|
642
|
+
};
|
|
643
|
+
}
|
|
480
644
|
if (matched === 0) return full ? asFull(full) : null;
|
|
481
645
|
|
|
646
|
+
const reason = `matches ${matched}/${tokens.length} terms: ${hitTerms.join(', ')}`;
|
|
647
|
+
|
|
648
|
+
// Every word matched is its own tier. Summed per word, a doc that matches
|
|
649
|
+
// both words of `troubleshoot integration` in its title and description
|
|
650
|
+
// (50 + bonus + coverage = 77) lost to thirty docs that each match
|
|
651
|
+
// `integration` alone, by name or in a code tick (98-108). The reader asked for
|
|
652
|
+
// both; a candidate that has both comes first, ordered among its peers by
|
|
653
|
+
// how strong its strongest match is. It needs one keyword-strength hit:
|
|
654
|
+
// every word mentioned in prose, or rendered by a page, is breadth, and
|
|
655
|
+
// stays on the token sum below an exact hit on one word.
|
|
656
|
+
if (matched === tokens.length && strongest >= STRONG_TOKEN_SCORE) {
|
|
657
|
+
return {
|
|
658
|
+
score:
|
|
659
|
+
FULL_COVERAGE_SCORE +
|
|
660
|
+
Math.floor((strongest - MIN_TOKEN_SCORE) / 6.25),
|
|
661
|
+
reason,
|
|
662
|
+
matched,
|
|
663
|
+
total,
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
|
|
482
667
|
// Base the score on the STRONGEST concept that matched, plus a bonus per
|
|
483
668
|
// additional matched concept and a coverage term.
|
|
484
669
|
//
|
|
@@ -500,14 +685,8 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
500
685
|
const tokenScore = Math.round(
|
|
501
686
|
strongest + Math.min(matched - 1, 3) * 12 + coverage * 15,
|
|
502
687
|
);
|
|
503
|
-
|
|
504
688
|
if (full && full.score >= tokenScore) return asFull(full);
|
|
505
|
-
return {
|
|
506
|
-
score: tokenScore,
|
|
507
|
-
reason: `matches ${matched}/${tokens.length} terms: ${hitTerms.join(', ')}`,
|
|
508
|
-
matched,
|
|
509
|
-
total,
|
|
510
|
-
};
|
|
689
|
+
return {score: tokenScore, reason, matched, total};
|
|
511
690
|
}
|
|
512
691
|
|
|
513
692
|
/**
|
|
@@ -518,6 +697,8 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
518
697
|
* @param {string} term - Lowercased search term.
|
|
519
698
|
* @param {object} candidate
|
|
520
699
|
* @param {string} candidate.name - Primary identifier (component/hook name, topic, template name).
|
|
700
|
+
* @param {string} [candidate.domain] - A component, hook, or template name
|
|
701
|
+
* also matches typed as words: `command palette` is CommandPalette.
|
|
521
702
|
* @param {string[]} [candidate.keywords] - Authored intent (componentsUsed, category words).
|
|
522
703
|
* @param {string[]} [candidate.weakKeywords] - Derived signal (components a page renders).
|
|
523
704
|
* @param {string} [candidate.description]
|
|
@@ -530,6 +711,7 @@ export function scoreCandidate(
|
|
|
530
711
|
term,
|
|
531
712
|
{
|
|
532
713
|
name,
|
|
714
|
+
domain,
|
|
533
715
|
keywords = [],
|
|
534
716
|
weakKeywords = [],
|
|
535
717
|
description = '',
|
|
@@ -552,10 +734,26 @@ export function scoreCandidate(
|
|
|
552
734
|
};
|
|
553
735
|
|
|
554
736
|
const nameLower = name.toLowerCase();
|
|
737
|
+
// A placed guide's name is its route, and the route's last segment is its
|
|
738
|
+
// name too, as a flat topic's is: `codemods` is cli/integrations/codemods.
|
|
739
|
+
const leafLower = nameLower.slice(nameLower.lastIndexOf('/') + 1);
|
|
555
740
|
|
|
556
741
|
// ── Name signals ────────────────────────────────────────────────
|
|
557
|
-
|
|
742
|
+
// A plural of the name is the name: `integration` is the `integrations`
|
|
743
|
+
// guides, `tab` the `tabs` doc.
|
|
744
|
+
// A component, hook, or template name typed as words is its name:
|
|
745
|
+
// `command palette` is CommandPalette. A doc's name is a route or key,
|
|
746
|
+
// matched as written.
|
|
747
|
+
const spelled =
|
|
748
|
+
domain !== 'doc' &&
|
|
749
|
+
!/[\s_-]/.test(nameLower) &&
|
|
750
|
+
nameLower === term.replace(/\s+/g, '');
|
|
751
|
+
if (nameLower === term || leafLower === term || spelled) {
|
|
558
752
|
consider(100, 'exact name');
|
|
753
|
+
} else if (pluralOf(nameLower, term) || pluralOf(term, nameLower)) {
|
|
754
|
+
// One point under the exact spelling, so the doc named `tokens` still
|
|
755
|
+
// outranks the Token component for `tokens`.
|
|
756
|
+
consider(99, 'plural of the name');
|
|
559
757
|
} else {
|
|
560
758
|
if (sameWord(term, nameLower)) consider(95, `name "${name}"`);
|
|
561
759
|
// The term is a word of the name, or starts one: "input" in TextInput.
|
|
@@ -809,6 +1007,64 @@ async function gatherComponents(coreDir, cwd) {
|
|
|
809
1007
|
return [...core, ...integrations];
|
|
810
1008
|
}
|
|
811
1009
|
|
|
1010
|
+
/**
|
|
1011
|
+
* The components each search response was scored against, by response:
|
|
1012
|
+
* `build` reads them to tell a part of a page from a page without gathering
|
|
1013
|
+
* them again. Module-private, so they never enter search's JSON.
|
|
1014
|
+
* @type {WeakMap<object, {name: string, keywords: string[]}[]>}
|
|
1015
|
+
*/
|
|
1016
|
+
const searchedComponentsOf = new WeakMap();
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* The components (name and keywords) a search response was scored against, or
|
|
1020
|
+
* null when that search was narrowed away from components.
|
|
1021
|
+
* @param {object} response
|
|
1022
|
+
* @returns {{name: string, keywords: string[]}[] | null}
|
|
1023
|
+
*/
|
|
1024
|
+
export function searchedComponents(response) {
|
|
1025
|
+
return searchedComponentsOf.get(response) ?? null;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Every component the project can use, Core's and its integrations', with the
|
|
1030
|
+
* keywords its own doc declares: the discovery and doc reads search's own
|
|
1031
|
+
* candidates use, without the import paths and prose a result carries. `build`
|
|
1032
|
+
* reads it to tell a part of a page from a page when its search was narrowed
|
|
1033
|
+
* away from components.
|
|
1034
|
+
* @param {string} coreDir
|
|
1035
|
+
* @param {string} cwd
|
|
1036
|
+
* @returns {Promise<{name: string, keywords: string[]}[]>}
|
|
1037
|
+
*/
|
|
1038
|
+
export async function componentKeywords(coreDir, cwd) {
|
|
1039
|
+
/** @param {any} doc */
|
|
1040
|
+
const keywordsOf = doc => (Array.isArray(doc?.keywords) ? doc.keywords : []);
|
|
1041
|
+
const core = Object.values(discoverComponents(coreDir))
|
|
1042
|
+
.flat()
|
|
1043
|
+
.map(async name => {
|
|
1044
|
+
const readme = findComponentReadme(coreDir, name);
|
|
1045
|
+
const doc =
|
|
1046
|
+
readme && readme.endsWith('.doc.mjs')
|
|
1047
|
+
? await loadModuleDoc(readme)
|
|
1048
|
+
: null;
|
|
1049
|
+
return {name, keywords: keywordsOf(doc)};
|
|
1050
|
+
});
|
|
1051
|
+
const integrations = (await loadIntegrationsSafely(cwd)).map(
|
|
1052
|
+
async integration => {
|
|
1053
|
+
const {components} = await discoverValidIntegrationComponents(integration);
|
|
1054
|
+
return Promise.all(
|
|
1055
|
+
components.map(async rec => ({
|
|
1056
|
+
name: rec.name,
|
|
1057
|
+
keywords: keywordsOf(await loadModuleDoc(rec.docPath)),
|
|
1058
|
+
})),
|
|
1059
|
+
);
|
|
1060
|
+
},
|
|
1061
|
+
);
|
|
1062
|
+
return [
|
|
1063
|
+
...(await Promise.all(core)),
|
|
1064
|
+
...(await Promise.all(integrations)).flat(),
|
|
1065
|
+
];
|
|
1066
|
+
}
|
|
1067
|
+
|
|
812
1068
|
/**
|
|
813
1069
|
* Build hook candidates: name + keywords + usage/description from the hook's
|
|
814
1070
|
* .doc.mjs.
|
|
@@ -962,11 +1218,14 @@ async function gatherDocs(cwd) {
|
|
|
962
1218
|
keywords: [
|
|
963
1219
|
node.route.slice(node.route.lastIndexOf('/') + 1),
|
|
964
1220
|
...(Array.isArray(selfDoc?.keywords) ? selfDoc.keywords : []),
|
|
1221
|
+
// A namespace doc's own keywords, which it declares for search.
|
|
1222
|
+
...(Array.isArray(node.keywords) ? node.keywords : []),
|
|
965
1223
|
...defined,
|
|
966
1224
|
...codeTerms({content}),
|
|
967
1225
|
],
|
|
968
1226
|
description: node.summary || '',
|
|
969
1227
|
prose: sectionProse({title: node.title, content}),
|
|
1228
|
+
titles: [node.title],
|
|
970
1229
|
_topic: node.route,
|
|
971
1230
|
_title: path.join(' › '),
|
|
972
1231
|
_command: `astryx docs ${node.route}`,
|
|
@@ -1086,12 +1345,16 @@ function topicCandidates(
|
|
|
1086
1345
|
const sections = doc?.sections ?? [];
|
|
1087
1346
|
const docTitle = path || doc?.title || title || name;
|
|
1088
1347
|
const split = sections.length > 1;
|
|
1348
|
+
// A placed guide also answers to its last route segment's words:
|
|
1349
|
+
// `quick start` is cli/integrations/quick-start.
|
|
1350
|
+
const leaf = name.slice(name.lastIndexOf('/') + 1);
|
|
1089
1351
|
/** @type {Candidate[]} */
|
|
1090
1352
|
const out = [
|
|
1091
1353
|
{
|
|
1092
1354
|
domain: 'doc',
|
|
1093
1355
|
name,
|
|
1094
1356
|
keywords: [
|
|
1357
|
+
...(leaf !== name ? [leaf.replaceAll('-', ' ')] : []),
|
|
1095
1358
|
...(doc?.title || title ? [doc?.title || title] : []),
|
|
1096
1359
|
...(Array.isArray(doc?.keywords) ? doc.keywords : []),
|
|
1097
1360
|
],
|
|
@@ -1099,6 +1362,11 @@ function topicCandidates(
|
|
|
1099
1362
|
prose: split
|
|
1100
1363
|
? sections.map(section => section.title).filter(Boolean)
|
|
1101
1364
|
: sections.flatMap(sectionProse),
|
|
1365
|
+
titles: [
|
|
1366
|
+
doc?.title || title || name,
|
|
1367
|
+
// A topic read whole answers for the headings inside it.
|
|
1368
|
+
...(split ? [] : sections.flatMap(s => [s.title, ...headings(s)])),
|
|
1369
|
+
].filter(Boolean),
|
|
1102
1370
|
_topic: name,
|
|
1103
1371
|
_title: docTitle,
|
|
1104
1372
|
_command: split ? `astryx docs ${name} --index` : `astryx docs ${name}`,
|
|
@@ -1119,6 +1387,7 @@ function topicCandidates(
|
|
|
1119
1387
|
],
|
|
1120
1388
|
description: sectionSummary(section),
|
|
1121
1389
|
prose: sectionProse(section),
|
|
1390
|
+
titles: [section.title, ...headings(section)].filter(Boolean),
|
|
1122
1391
|
_topic: name,
|
|
1123
1392
|
_section: key,
|
|
1124
1393
|
_title: `${docTitle} › ${section.title}`,
|
|
@@ -1182,6 +1451,10 @@ async function gatherTemplates(cwd) {
|
|
|
1182
1451
|
keywords,
|
|
1183
1452
|
weakKeywords,
|
|
1184
1453
|
description: t.description || '',
|
|
1454
|
+
// A template's own keywords name the many ideas it serves, so they score
|
|
1455
|
+
// as its prose does, not as a name: one of them matching one word of a
|
|
1456
|
+
// short idea is not a direct match.
|
|
1457
|
+
prose: t.keywords ?? [],
|
|
1185
1458
|
_displayName: t.name,
|
|
1186
1459
|
_kind: t.type, // 'page' | 'block'
|
|
1187
1460
|
_resultName: t.dirName,
|
|
@@ -1296,10 +1569,11 @@ export async function search(query, options = {}) {
|
|
|
1296
1569
|
const tokens = tokenizeQuery(term);
|
|
1297
1570
|
|
|
1298
1571
|
// `astryx docs` reads docs without @astryxdesign/core, so a docs-only
|
|
1299
|
-
// search must too. Every other domain reads core
|
|
1572
|
+
// search must too. Every other domain reads core: asked for by name, it is
|
|
1573
|
+
// an error without core; an open search then covers the docs alone.
|
|
1300
1574
|
const docsOnly = type === 'doc';
|
|
1301
1575
|
const coreDir = docsOnly ? null : findCoreDir(cwd);
|
|
1302
|
-
if (!docsOnly && !coreDir) {
|
|
1576
|
+
if (type && !docsOnly && !coreDir) {
|
|
1303
1577
|
throw new AstryxError(
|
|
1304
1578
|
'Could not find @astryxdesign/core package',
|
|
1305
1579
|
undefined,
|
|
@@ -1309,7 +1583,7 @@ export async function search(query, options = {}) {
|
|
|
1309
1583
|
|
|
1310
1584
|
// Gather candidates from each requested domain in parallel.
|
|
1311
1585
|
/** @param {string} d */
|
|
1312
|
-
const wants = d => !type || type === d;
|
|
1586
|
+
const wants = d => (!type && (coreDir != null || d === 'doc')) || type === d;
|
|
1313
1587
|
const [components, hooks, docTopics, templates] = await Promise.all([
|
|
1314
1588
|
wants('component')
|
|
1315
1589
|
? gatherComponents(/** @type {string} */ (coreDir), cwd)
|
|
@@ -1351,7 +1625,8 @@ export async function search(query, options = {}) {
|
|
|
1351
1625
|
// 57 things and one matching exactly 20 would be indistinguishable.
|
|
1352
1626
|
const limited = scored.slice(0, limit);
|
|
1353
1627
|
|
|
1354
|
-
|
|
1628
|
+
/** @type {import('./search.type.mjs').SearchResponse} */
|
|
1629
|
+
const response = {
|
|
1355
1630
|
type: 'search',
|
|
1356
1631
|
data: {
|
|
1357
1632
|
query: String(query).trim(),
|
|
@@ -1362,4 +1637,11 @@ export async function search(query, options = {}) {
|
|
|
1362
1637
|
),
|
|
1363
1638
|
},
|
|
1364
1639
|
};
|
|
1640
|
+
if (wants('component')) {
|
|
1641
|
+
searchedComponentsOf.set(
|
|
1642
|
+
response,
|
|
1643
|
+
components.map(c => ({name: c.name, keywords: c.keywords ?? []})),
|
|
1644
|
+
);
|
|
1645
|
+
}
|
|
1646
|
+
return response;
|
|
1365
1647
|
}
|