@astryxdesign/cli 0.6.3 → 0.6.4-canary.06c8fa3
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 +194 -0
- package/README.md +121 -85
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/_adapter.d.mts +50 -0
- package/api/build/_adapter.mjs +60 -0
- package/api/build/build.doc.mjs +16 -9
- package/api/build/build.test.mjs +197 -8
- package/api/build/build.type.d.mts +91 -2
- package/api/build/build.type.mjs +52 -8
- package/api/build/help/help.d.mts +12 -5
- package/api/build/help/help.mjs +69 -6
- package/api/build/kit/kit.d.mts +4 -1
- package/api/build/kit/kit.mjs +165 -49
- package/api/build/kit/rank.d.mts +44 -0
- package/api/build/kit/rank.mjs +432 -0
- package/api/build/kit/rank.test.mjs +196 -0
- package/api/component/_adapter.d.mts +31 -12
- package/api/component/_adapter.mjs +79 -15
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +36 -13
- package/api/component/component.mjs +339 -22
- package/api/component/component.test.mjs +38 -0
- package/api/component/component.type.d.mts +47 -11
- package/api/component/component.type.mjs +76 -24
- package/api/component/detail/blocks/blocks.d.mts +2 -1
- package/api/component/detail/blocks/blocks.mjs +4 -3
- package/api/component/list/list.d.mts +0 -5
- package/api/component/list/list.mjs +40 -11
- 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 +62 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +150 -11
- package/api/discover/discover.type.mjs +107 -17
- 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 +272 -41
- package/api/docs/_adapter.mjs +985 -108
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +22 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +54 -19
- package/api/docs/detail/section/section.test.mjs +50 -0
- package/api/docs/docs.d.mts +10 -3
- package/api/docs/docs.doc.mjs +55 -16
- package/api/docs/docs.mjs +53 -10
- package/api/docs/docs.test.mjs +166 -4
- package/api/docs/docs.type.d.mts +221 -5
- package/api/docs/docs.type.mjs +153 -11
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +40 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +114 -8
- package/api/docs/list/list.mjs +28 -12
- package/api/docs/node/node.d.mts +43 -0
- package/api/docs/node/node.mjs +192 -0
- package/api/docs/reference-blocks.test.mjs +406 -0
- package/api/doctor/doctor.d.mts +104 -1
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +635 -7
- package/api/doctor/doctor.test.mjs +732 -11
- package/api/gap-report/gap-report.doc.mjs +8 -4
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +2 -2
- package/api/hook/list/list.mjs +69 -17
- package/api/index.d.mts +2 -3
- package/api/index.mjs +5 -4
- package/api/init/init.doc.mjs +6 -1
- package/api/init/init.test.mjs +41 -1
- package/api/init/remove/remove.mjs +1 -1
- package/api/init/run/run.mjs +20 -10
- package/api/integration/add-contribution.component-names.test.mjs +120 -0
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +130 -15
- package/api/integration/add-contribution.test.mjs +258 -7
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.mjs +138 -28
- package/api/integration/authoring-checks.test.mjs +179 -7
- package/api/integration/authoring-checks.type.mjs +6 -1
- package/api/integration/integration-authoring.type.d.mts +3 -1
- package/api/integration/integration-authoring.type.mjs +2 -0
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +14 -4
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +2 -1
- package/api/integration/integrationAddDoc.doc.mjs +8 -1
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +2 -1
- package/api/integration/integrationPackCheck.doc.mjs +2 -1
- package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
- package/api/integration/pack-check.lifecycle-output.test.mjs +105 -0
- package/api/integration/pack-check.mjs +111 -10
- package/api/integration/pack-check.test.mjs +387 -47
- package/api/integration/pack-check.type.d.mts +26 -2
- package/api/integration/pack-check.type.mjs +14 -1
- package/api/integration/summarizeIssues.doc.mjs +1 -0
- package/api/integration/template-conflict-compatibility.test.mjs +73 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +52 -102
- package/api/integration/validate-integration.test.mjs +179 -26
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +3 -2
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/envelope-types.test.mjs +76 -0
- package/api/json/index.ts +2 -1
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +3 -2
- package/api/search/search-return-type.test.mjs +54 -0
- package/api/search/search.d.mts +62 -11
- package/api/search/search.doc.mjs +8 -2
- package/api/search/search.mjs +471 -83
- package/api/search/search.test.mjs +142 -1
- package/api/search/search.type.d.mts +15 -3
- package/api/search/search.type.mjs +5 -2
- package/api/swizzle/copy/copy.mjs +28 -11
- package/api/swizzle/swizzle.doc.mjs +2 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/copy/copy.mjs +17 -23
- package/api/template/copy/copy.test.mjs +17 -0
- package/api/template/list/list.mjs +1 -0
- package/api/template/table-floating-bulk-actions.test.mjs +66 -0
- package/api/template/template-integration.test.mjs +1008 -3
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +30 -8
- package/api/template/template.mjs +46 -9
- package/api/template/template.type.d.mts +12 -14
- package/api/template/template.type.mjs +15 -14
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +84 -0
- package/api/theme/add/add.mjs +31 -22
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +83 -0
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +140 -59
- package/api/theme/build/build.public-component-vars.test.mjs +1 -1
- package/api/theme/build/build.receipt-doc.test.mjs +111 -0
- package/api/theme/build/build.rollback.test.mjs +148 -0
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/build/font-warning.mjs +3 -3
- package/api/theme/build/font-warning.test.mjs +5 -2
- package/api/theme/generateTonalPalette.doc.mjs +1 -0
- package/api/theme/integration-themes.test.mjs +39 -28
- package/api/theme/list/list.test.mjs +19 -20
- package/api/theme/listThemes.doc.mjs +6 -5
- package/api/theme/palette/generate/generate.mjs +8 -3
- package/api/theme/palette/generate/generate.test.mjs +96 -0
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +15 -4
- package/api/theme/palette/generate/generator.test.mjs +10 -0
- package/api/theme/template/template.mjs +11 -2
- package/api/theme/template/template.test.mjs +20 -0
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +8 -4
- package/api/theme/themeList.doc.mjs +6 -3
- package/api/theme/themeListAvailable.doc.mjs +5 -3
- package/api/theme/themePaletteGenerate.doc.mjs +1 -0
- package/api/theme/themeTargets.doc.mjs +1 -0
- package/api/theme/themeTemplate.doc.mjs +6 -2
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +139 -22
- package/api/upgrade/list/list.mjs +2 -1
- package/api/upgrade/list/list.test.mjs +73 -0
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +359 -60
- package/api/upgrade/status/status.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +12 -5
- package/api/upgrade/upgrade.type.d.mts +43 -5
- package/api/upgrade/upgrade.type.mjs +29 -13
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/__tests__/runner.test.mjs +332 -8
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-discovery.mjs +48 -4
- package/assets/codemods/integration-discovery.test.mjs +73 -0
- package/assets/codemods/integration-runner.mjs +59 -7
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +353 -104
- package/assets/codemods/term-log.mjs +32 -8
- package/assets/codemods/term-log.test.mjs +19 -1
- package/assets/codemods/transform-prop.mjs +109 -0
- package/assets/codemods/transform-prop.test.mjs +95 -0
- package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
- package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
- package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
- package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
- package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
- package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
- package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/internationalization.doc.mjs +7 -5
- package/assets/docs/layout.doc.dense.mjs +2 -2
- package/assets/docs/layout.doc.mjs +1 -1
- package/assets/docs/principles.doc.mjs +6 -6
- package/assets/docs/styling-libraries.doc.mjs +4 -4
- package/assets/docs/styling.doc.mjs +4 -4
- package/assets/docs/theme.doc.mjs +5 -5
- package/assets/docs/tokens.doc.mjs +1 -1
- package/assets/docs/tree/api.doc.mjs +30 -0
- package/assets/docs/tree/cli.doc.mjs +23 -0
- package/assets/docs/tree/commands.doc.mjs +25 -0
- package/assets/docs/tree/component-lookups.doc.mjs +149 -0
- package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/working-with-ai.doc.mjs +4 -4
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
- package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
- package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
- package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
- package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
- package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
- package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
- package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
- package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
- package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
- package/assets/templates/pages/table-tree/page.tsx +1704 -0
- package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
- package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
- package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
- package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
- package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
- package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
- package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
- package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +7 -2
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +11 -3
- package/authoring/config/debug-composition.test.mjs +92 -0
- package/authoring/config/parse.d.mts +15 -13
- package/authoring/config/parse.mjs +27 -8
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +31 -8
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +8 -8
- package/authoring/debug/parse.mjs +3 -3
- 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 +790 -23
- package/authoring/doctypes/_schema.mjs +543 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
- package/authoring/doctypes/base/type.ts +41 -0
- package/authoring/doctypes/command/command.doc.mjs +5 -4
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +6 -5
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +6 -5
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +4 -2
- package/authoring/doctypes/function/function.doc.mjs +7 -2
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +9 -4
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +5 -4
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +233 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +163 -0
- package/authoring/doctypes/namespace/type.ts +74 -0
- package/authoring/doctypes/parse.d.mts +22 -18
- package/authoring/doctypes/parse.mjs +22 -11
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +48 -6
- package/authoring/doctypes/reference/type.ts +70 -7
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +4 -4
- package/authoring/doctypes/template/parse.d.mts +94 -1
- package/authoring/doctypes/template/parse.mjs +40 -2
- package/authoring/doctypes/template/parse.test.mjs +26 -2
- package/authoring/doctypes/template/template.doc.mjs +13 -3
- package/authoring/doctypes/template/type.ts +13 -2
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +12 -10
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +3 -0
- package/authoring/index.d.ts +62 -17
- package/authoring/index.mjs +4 -1
- package/authoring/integration/integration.doc.mjs +15 -8
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +19 -8
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/command-load-failure.test.mjs +83 -0
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/blog.mjs +23 -8
- package/clients/cli/commands/blog.test.mjs +42 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
- package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
- package/clients/cli/commands/build-theme.mjs +16 -50
- package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
- package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
- package/clients/cli/commands/build.doc.mjs +16 -8
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
- package/clients/cli/commands/build.mjs +137 -114
- package/clients/cli/commands/build.playbook.test.mjs +75 -0
- package/clients/cli/commands/build.text-fields.test.mjs +81 -0
- package/clients/cli/commands/component/index.mjs +153 -61
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +92 -3
- package/clients/cli/commands/component-package.test.mjs +46 -0
- package/clients/cli/commands/component-resolution.test.mjs +21 -0
- package/clients/cli/commands/component.doc.mjs +24 -7
- package/clients/cli/commands/component.test.mjs +19 -0
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/detail-levels.test.mjs +2 -2
- package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
- package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
- package/clients/cli/commands/discover.doc.mjs +55 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
- package/clients/cli/commands/docs.doc.mjs +28 -6
- package/clients/cli/commands/docs.mjs +240 -26
- package/clients/cli/commands/docs.test.mjs +222 -1
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
- package/clients/cli/commands/doctor-integration.test.mjs +90 -8
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +59 -32
- package/clients/cli/commands/doctor.test.mjs +42 -0
- package/clients/cli/commands/gap-report.doc.mjs +17 -6
- package/clients/cli/commands/gap-report.test.mjs +72 -0
- package/clients/cli/commands/hook/index.mjs +7 -17
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
- package/clients/cli/commands/init.doc.mjs +20 -9
- package/clients/cli/commands/init.flag-help.test.mjs +153 -0
- package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
- package/clients/cli/commands/integration-add.doc.mjs +32 -6
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/integration-pack.doc.mjs +1 -1
- package/clients/cli/commands/integration-real-world.test.mjs +3 -9
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/integration.mjs +1 -0
- package/clients/cli/commands/interactive-guard.test.mjs +101 -24
- package/clients/cli/commands/json-contract.test.mjs +33 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
- package/clients/cli/commands/search.doc.mjs +7 -4
- package/clients/cli/commands/search.mjs +28 -9
- package/clients/cli/commands/search.test.mjs +75 -0
- package/clients/cli/commands/setup-nudge.test.mjs +6 -0
- package/clients/cli/commands/swizzle.doc.mjs +3 -2
- package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
- package/clients/cli/commands/template.doc.mjs +52 -13
- package/clients/cli/commands/template.flag-help.test.mjs +117 -0
- package/clients/cli/commands/template.mjs +4 -91
- package/clients/cli/commands/template.path-help.test.mjs +40 -0
- package/clients/cli/commands/text-json-parity.test.mjs +702 -0
- package/clients/cli/commands/theme-add.doc.mjs +4 -3
- package/clients/cli/commands/theme-build.doc.mjs +8 -7
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
- package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
- package/clients/cli/commands/theme-template.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
- package/clients/cli/commands/upgrade.doc.mjs +22 -10
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
- package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +164 -1
- package/clients/cli/formatters/index.test.mjs +97 -0
- package/clients/cli/index.mjs +21 -34
- package/clients/cli/latest-version-env.test.mjs +50 -0
- package/clients/cli/lib/cli-error.test.mjs +7 -0
- package/clients/cli/lib/component-format.mjs +9 -9
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +32 -6
- package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
- package/clients/cli/lib/exit-codes.test.mjs +90 -0
- package/clients/cli/lib/hook-format.mjs +19 -10
- package/clients/cli/lib/json-shim.mjs +62 -16
- package/clients/cli/lib/json-shim.test.mjs +69 -0
- package/clients/cli/lib/manifest.d.ts +2 -0
- package/clients/cli/lib/manifest.mjs +39 -10
- package/clients/cli/lib/manifest.test.mjs +22 -2
- package/clients/cli/lib/parse-error-format.test.mjs +81 -0
- package/foundation/agent-docs/agent-docs.d.mts +7 -2
- package/foundation/agent-docs/agent-docs.mjs +82 -12
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
- package/foundation/agent-docs/agent-docs.test.mjs +19 -1
- package/foundation/config/integration-debug.test.mjs +28 -3
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +20 -11
- package/foundation/config/project.mjs +263 -91
- package/foundation/config/project.test.mjs +270 -21
- package/foundation/discovery/authoring-self-docs.d.mts +87 -0
- package/foundation/discovery/authoring-self-docs.mjs +237 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
- package/foundation/discovery/authoring-surface.d.mts +74 -0
- package/foundation/discovery/authoring-surface.mjs +525 -0
- package/foundation/discovery/authoring-surface.test.mjs +392 -0
- package/foundation/discovery/cli-self-docs.d.mts +119 -0
- package/foundation/discovery/cli-self-docs.mjs +490 -0
- package/foundation/discovery/cli-self-docs.test.mjs +375 -0
- package/foundation/discovery/component-discovery.d.mts +39 -1
- package/foundation/discovery/component-discovery.mjs +50 -1
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +119 -11
- package/foundation/discovery/docs-discovery.mjs +423 -108
- package/foundation/discovery/docs-discovery.test.mjs +365 -20
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +116 -0
- package/foundation/discovery/docs-section-key.mjs +322 -0
- package/foundation/discovery/docs-section-key.test.mjs +246 -0
- package/foundation/discovery/template-adapter.d.mts +113 -11
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
- package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
- package/foundation/discovery/template-adapter.mjs +775 -84
- package/foundation/discovery/template-adapter.test.mjs +57 -0
- package/foundation/discovery/template-conflict-release.d.mts +13 -0
- package/foundation/discovery/template-conflict-release.mjs +40 -0
- package/foundation/discovery/template-conflict-release.test.mjs +40 -0
- package/foundation/discovery/theme-discovery.d.mts +67 -7
- package/foundation/discovery/theme-discovery.mjs +916 -186
- package/foundation/discovery/theme-discovery.test.mjs +613 -219
- package/foundation/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/bundle.d.mts +47 -0
- package/foundation/doc-compiler/bundle.mjs +278 -0
- package/foundation/doc-compiler/bundle.test.mjs +266 -0
- package/foundation/doc-compiler/compile.d.mts +343 -0
- package/foundation/doc-compiler/compile.mjs +558 -0
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +305 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +1630 -0
- package/foundation/doc-compiler/import.d.mts +24 -0
- package/foundation/doc-compiler/import.mjs +59 -0
- package/foundation/doc-compiler/inputs.d.mts +102 -0
- package/foundation/doc-compiler/inputs.mjs +291 -0
- package/foundation/doc-compiler/inputs.test.mjs +299 -0
- package/foundation/doc-compiler/ir.d.mts +22 -0
- package/foundation/doc-compiler/ir.mjs +471 -0
- package/foundation/doc-compiler/lenses.d.mts +36 -0
- package/foundation/doc-compiler/lenses.mjs +173 -0
- package/foundation/doc-compiler/links.d.mts +162 -0
- package/foundation/doc-compiler/links.mjs +294 -0
- package/foundation/doc-compiler/links.test.mjs +192 -0
- package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
- package/foundation/doc-compiler/overlays.d.mts +37 -0
- package/foundation/doc-compiler/overlays.mjs +206 -0
- package/foundation/doc-compiler/parse-readable.d.mts +9 -0
- package/foundation/doc-compiler/parse-readable.mjs +29 -0
- package/foundation/doc-compiler/read.d.mts +127 -0
- package/foundation/doc-compiler/read.mjs +325 -0
- package/foundation/doc-compiler/read.test.mjs +313 -0
- package/foundation/doc-compiler/source.d.mts +33 -0
- package/foundation/doc-compiler/source.mjs +128 -0
- package/foundation/doc-compiler/tree.d.mts +288 -0
- package/foundation/doc-compiler/tree.mjs +876 -0
- package/foundation/doc-compiler/tree.test.mjs +606 -0
- package/foundation/fs/file-protection.d.mts +33 -0
- package/foundation/fs/file-protection.mjs +825 -0
- package/foundation/fs/file-protection.test.mjs +250 -0
- package/foundation/fs/module-loader.d.mts +1 -0
- package/foundation/fs/module-loader.mjs +50 -1
- package/foundation/fs/module-loader.stdout.test.mjs +332 -0
- package/foundation/fs/path-safety.d.mts +3 -2
- package/foundation/fs/path-safety.mjs +49 -19
- package/foundation/fs/path-safety.test.mjs +50 -0
- package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -45
- package/foundation/integrations/autolink.test.mjs +1 -1
- package/foundation/integrations/cli-requirement.d.mts +45 -0
- package/foundation/integrations/cli-requirement.mjs +154 -0
- package/foundation/integrations/cli-requirement.test.mjs +84 -0
- package/foundation/integrations/contribution-fixes.d.mts +145 -0
- package/foundation/integrations/contribution-fixes.mjs +1284 -0
- package/foundation/integrations/contribution-inventory.d.mts +3 -2
- package/foundation/integrations/contribution-inventory.mjs +27 -24
- package/foundation/integrations/contribution-inventory.test.mjs +86 -27
- package/foundation/integrations/integration-warnings.d.mts +9 -2
- package/foundation/integrations/integration-warnings.mjs +52 -21
- package/foundation/integrations/integration-warnings.test.mjs +74 -1
- package/foundation/integrations/integrations.d.mts +63 -3
- package/foundation/integrations/integrations.mjs +122 -9
- package/foundation/integrations/integrations.test.mjs +415 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +131 -29
- package/foundation/response/base.d.ts +8 -4
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +13 -4
- package/foundation/response/error-codes.mjs +8 -2
- package/foundation/response/error-codes.test.mjs +137 -10
- package/foundation/response/json-contract.test.mjs +57 -17
- package/foundation/response/json.d.mts +4 -2
- package/foundation/response/json.mjs +8 -10
- package/foundation/response/response-types.doc.d.mts +5 -1
- package/foundation/response/response-types.doc.mjs +46 -38
- package/foundation/response/response-types.doc.test.mjs +181 -0
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.d.mts +8 -0
- package/foundation/text/string-utils.mjs +40 -10
- package/foundation/xle/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.d.mts +2 -0
- package/foundation/xle/expand.mjs +6 -5
- package/foundation/xle/expand.test.mjs +54 -0
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +10 -11
- package/api/layout/_adapter.d.mts +0 -34
- package/api/layout/_adapter.mjs +0 -133
- package/api/layout/check/check.d.mts +0 -16
- package/api/layout/check/check.mjs +0 -40
- package/api/layout/expand/expand.d.mts +0 -22
- package/api/layout/expand/expand.mjs +0 -153
- package/api/layout/grammar/grammar.d.mts +0 -13
- package/api/layout/grammar/grammar.mjs +0 -86
- package/api/layout/layout.d.mts +0 -6
- package/api/layout/layout.mjs +0 -17
- package/api/layout/layout.test.mjs +0 -297
- package/api/layout/layout.type.d.mts +0 -89
- package/api/layout/layout.type.mjs +0 -103
- package/api/layout/layoutCheck.doc.d.mts +0 -11
- package/api/layout/layoutCheck.doc.mjs +0 -84
- package/api/layout/layoutExpand.doc.d.mts +0 -11
- package/api/layout/layoutExpand.doc.mjs +0 -106
- package/api/layout/layoutGrammar.doc.d.mts +0 -11
- package/api/layout/layoutGrammar.doc.mjs +0 -56
- package/assets/templates/themes/manifest.json +0 -95
- package/clients/cli/commands/layout-check.doc.mjs +0 -54
- package/clients/cli/commands/layout-expand.doc.mjs +0 -66
- package/clients/cli/commands/layout-grammar.doc.mjs +0 -30
- package/clients/cli/commands/layout.doc.mjs +0 -34
- package/clients/cli/commands/layout.error-codes.test.mjs +0 -66
- package/clients/cli/commands/layout.exit-parity.test.mjs +0 -41
- package/clients/cli/commands/layout.mjs +0 -263
- package/clients/cli/lib/update-check.mjs +0 -83
- package/clients/cli/lib/update-check.test.mjs +0 -137
- package/clients/cli/update-hint-commands.test.mjs +0 -54
package/api/search/search.mjs
CHANGED
|
@@ -17,21 +17,31 @@
|
|
|
17
17
|
* component fuzzy resolver in lib/string-utils.mjs:
|
|
18
18
|
*
|
|
19
19
|
* 100 exact name match
|
|
20
|
+
* 95 name is the term's plural or stem form ("buttons" -> Button)
|
|
20
21
|
* 90 exact keyword match
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* 88 keyword is the term's plural or stem form
|
|
23
|
+
* 80 name Levenshtein distance 1 (one-word lookups, words of 5+ letters)
|
|
24
|
+
* 70 keyword word prefix / distance 1 (distance: one-word lookups, 5+ letters)
|
|
25
|
+
* 60 name word prefix (>=4 chars, >=50% coverage)
|
|
24
26
|
* 60 exact weak-keyword match
|
|
25
27
|
* 50 description / prose mentions the term
|
|
26
28
|
* 45 usage guidance mentions the term
|
|
27
|
-
* 40 name Levenshtein distance 2
|
|
28
|
-
* 40 weak-keyword
|
|
29
|
-
* 30 keyword Levenshtein distance 2
|
|
30
|
-
* 20 name Levenshtein distance 3
|
|
29
|
+
* 40 name Levenshtein distance 2 (one-word lookups, 8+ letters)
|
|
30
|
+
* 40 weak-keyword word prefix
|
|
31
|
+
* 30 keyword Levenshtein distance 2 (one-word lookups, 8+ letters)
|
|
32
|
+
* 20 name Levenshtein distance 3 (one-word lookups, 11+ letters)
|
|
31
33
|
*
|
|
32
34
|
* Name + keyword signals always outweigh description/prose, so an exact match
|
|
33
35
|
* sorts above an incidental mention.
|
|
34
36
|
*
|
|
37
|
+
* A term matches inside a name or keyword only at the start of one of its
|
|
38
|
+
* words: "dash" finds "dashboard" and "input" finds "TextInput", but "file"
|
|
39
|
+
* does not find "profile". Edit distance is typo tolerance, so it applies only
|
|
40
|
+
* to a one-word lookup, where a typo is the likely explanation, and only to
|
|
41
|
+
* words long enough that one edit rarely makes another real word. In a
|
|
42
|
+
* sentence, a near miss is usually a different word: "site" is not "side",
|
|
43
|
+
* "cable" is not "table".
|
|
44
|
+
*
|
|
35
45
|
* Description and guidance are separate tiers on purpose. A component's own
|
|
36
46
|
* one-line description saying "notification" is a claim about what it IS; the
|
|
37
47
|
* same word inside another component's best-practice advice is a passing
|
|
@@ -50,11 +60,11 @@
|
|
|
50
60
|
* queries they have nothing to do with.
|
|
51
61
|
*/
|
|
52
62
|
|
|
53
|
-
import {
|
|
63
|
+
import {readDocView} from '../../foundation/doc-compiler/read.mjs';
|
|
54
64
|
import {findCoreDir} from '../../foundation/fs/paths.mjs';
|
|
55
65
|
import {
|
|
56
66
|
discoverComponents,
|
|
57
|
-
|
|
67
|
+
discoverValidIntegrationComponents,
|
|
58
68
|
findComponentReadme,
|
|
59
69
|
resolveImportPath,
|
|
60
70
|
resolveIntegrationImportPath,
|
|
@@ -66,7 +76,20 @@ import {
|
|
|
66
76
|
import {loadIntegrationsSafely} from '../component/_adapter.mjs';
|
|
67
77
|
import {levenshteinDistance} from '../../foundation/text/string-utils.mjs';
|
|
68
78
|
import {discoverTemplates, extractComponents} from '../template/template.mjs';
|
|
69
|
-
import {
|
|
79
|
+
import {templateLookupIds} from '../../foundation/discovery/template-adapter.mjs';
|
|
80
|
+
import {
|
|
81
|
+
guideEntry,
|
|
82
|
+
loadDocsCatalog,
|
|
83
|
+
lowerTopic,
|
|
84
|
+
projectTree,
|
|
85
|
+
holdsOwnName,
|
|
86
|
+
} from '../docs/_adapter.mjs';
|
|
87
|
+
import {unlinkText} from '../../foundation/doc-compiler/links.mjs';
|
|
88
|
+
import {nodeView} from '../docs/node/node.mjs';
|
|
89
|
+
import {
|
|
90
|
+
sectionKey,
|
|
91
|
+
sectionSummary,
|
|
92
|
+
} from '../../foundation/discovery/docs-section-key.mjs';
|
|
70
93
|
import {AstryxError} from '../error.mjs';
|
|
71
94
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
72
95
|
import {setResultCoverage} from './coverage.mjs';
|
|
@@ -84,17 +107,28 @@ import {setResultCoverage} from './coverage.mjs';
|
|
|
84
107
|
* @property {string[]} [guidance]
|
|
85
108
|
* @property {string} [_import]
|
|
86
109
|
* @property {string} [_title]
|
|
110
|
+
* @property {string} [_topic] - A doc result's topic or docs-tree route.
|
|
111
|
+
* @property {string} [_section] - A doc result's section key, when it is one section.
|
|
112
|
+
* @property {string} [_command] - The command that reads exactly this doc part.
|
|
113
|
+
* @property {string} [_parent] - The command that opens the level above a doc
|
|
114
|
+
* part: its topic's section list, or the docs-tree namespace it sits in.
|
|
115
|
+
* @property {string} [_package] - The npm package that authored a docs-tree
|
|
116
|
+
* doc part. Flat topics carry none: an extension's sections can come from
|
|
117
|
+
* another package.
|
|
87
118
|
* @property {string} [_displayName]
|
|
88
119
|
* @property {'page'|'block'} [_kind]
|
|
120
|
+
* @property {string} [_resultName]
|
|
121
|
+
* @property {string} [_commandName]
|
|
89
122
|
*/
|
|
90
123
|
|
|
91
124
|
/**
|
|
92
125
|
* Synonym / intent map: product-language terms an agent is likely to type,
|
|
93
126
|
* expanded to the catalog's vocabulary so oblique queries still rank. Keys and
|
|
94
127
|
* values are matched bidirectionally (typing any value also pulls in the key
|
|
95
|
-
* and its siblings). Lowercase, single words or short phrases.
|
|
128
|
+
* and its siblings). Lowercase, single words or short phrases. Exported for
|
|
129
|
+
* `build`, whose page ranker expands a query with the same vocabulary.
|
|
96
130
|
*/
|
|
97
|
-
const SYNONYMS = {
|
|
131
|
+
export const SYNONYMS = {
|
|
98
132
|
dashboard: [
|
|
99
133
|
'overview',
|
|
100
134
|
'analytics',
|
|
@@ -166,14 +200,90 @@ export function stem(w) {
|
|
|
166
200
|
return s;
|
|
167
201
|
}
|
|
168
202
|
|
|
203
|
+
/**
|
|
204
|
+
* The forms of a word that count as the same word: itself, its stem, and its
|
|
205
|
+
* singular when it ends in a plural suffix — so "tables" is "table",
|
|
206
|
+
* "statuses" is "status", and "filtering" is "filter".
|
|
207
|
+
* @param {string} w - Lowercase word.
|
|
208
|
+
* @returns {Set<string>}
|
|
209
|
+
*/
|
|
210
|
+
function wordForms(w) {
|
|
211
|
+
const forms = new Set([w, stem(w)]);
|
|
212
|
+
if (w.length > 3 && w.endsWith('s')) forms.add(w.slice(0, -1));
|
|
213
|
+
if (w.length > 4 && w.endsWith('es')) forms.add(w.slice(0, -2));
|
|
214
|
+
if (w.length > 4 && w.endsWith('ies')) forms.add(w.slice(0, -3) + 'y');
|
|
215
|
+
return forms;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Whether two lowercase words are the same word, up to plural and stem form.
|
|
220
|
+
* @param {string} a
|
|
221
|
+
* @param {string} b
|
|
222
|
+
* @returns {boolean}
|
|
223
|
+
*/
|
|
224
|
+
export function sameWord(a, b) {
|
|
225
|
+
if (a === b) return true;
|
|
226
|
+
const forms = wordForms(a);
|
|
227
|
+
for (const f of wordForms(b)) if (forms.has(f)) return true;
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The lowercase words of a name or keyword: split at non-alphanumerics and at
|
|
233
|
+
* camelCase boundaries, so "TextInput" is ["text", "input"] and
|
|
234
|
+
* "Dashboard - Analytics" is ["dashboard", "analytics"].
|
|
235
|
+
* @param {string} text
|
|
236
|
+
* @returns {string[]}
|
|
237
|
+
*/
|
|
238
|
+
function wordsOf(text) {
|
|
239
|
+
return String(text)
|
|
240
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
241
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
|
|
242
|
+
.toLowerCase()
|
|
243
|
+
.split(/[^a-z0-9]+/)
|
|
244
|
+
.filter(Boolean);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Whether a term is found inside a name or keyword: it is one of its words, or
|
|
249
|
+
* the start of one (a truncation), and covers at least half of the whole
|
|
250
|
+
* string. Four letters minimum, so a short term never matches by accident.
|
|
251
|
+
* @param {string} term - Lowercase term.
|
|
252
|
+
* @param {string} text - The name or keyword as authored.
|
|
253
|
+
* @returns {boolean}
|
|
254
|
+
*/
|
|
255
|
+
function startsAWordOf(term, text) {
|
|
256
|
+
if (term.length < 4) return false;
|
|
257
|
+
if (term.length / String(text).length < 0.5) return false;
|
|
258
|
+
return wordsOf(text).some(w => w.startsWith(term) || sameWord(term, w));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The fewest letters both words need before an edit distance counts as a
|
|
263
|
+
* typo, by distance. Below them, one edit usually makes a different word.
|
|
264
|
+
*/
|
|
265
|
+
const TYPO_MIN_LENGTH = {1: 5, 2: 8, 3: 11};
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @param {string} a
|
|
269
|
+
* @param {string} b
|
|
270
|
+
* @param {number} dist
|
|
271
|
+
*/
|
|
272
|
+
const isTypo = (a, b, dist) =>
|
|
273
|
+
dist > 0 &&
|
|
274
|
+
dist <= 3 &&
|
|
275
|
+
Math.min(a.length, b.length) >=
|
|
276
|
+
TYPO_MIN_LENGTH[/** @type {1 | 2 | 3} */ (dist)];
|
|
277
|
+
|
|
169
278
|
/** Valid domain filters for `--type`. */
|
|
170
279
|
export const SEARCH_DOMAINS = ['component', 'hook', 'doc', 'template'];
|
|
171
280
|
|
|
172
281
|
/**
|
|
173
282
|
* Filler words stripped from multi-word queries so natural-language phrasing
|
|
174
283
|
* ("a page where you can see business stats") ranks on its content words.
|
|
284
|
+
* Exported for `build`, whose page ranker strips the same words.
|
|
175
285
|
*/
|
|
176
|
-
const STOPWORDS = new Set([
|
|
286
|
+
export const STOPWORDS = new Set([
|
|
177
287
|
'a',
|
|
178
288
|
'an',
|
|
179
289
|
'the',
|
|
@@ -285,14 +395,15 @@ const MIN_TOKEN_SCORE = 50;
|
|
|
285
395
|
* (synonym hits are discounted so a direct hit always wins).
|
|
286
396
|
* @param {string} tok
|
|
287
397
|
* @param {Candidate} candidate
|
|
398
|
+
* @param {{fuzzy?: boolean}} [opts]
|
|
288
399
|
* @returns {{score: number, reason: string} | null}
|
|
289
400
|
*/
|
|
290
|
-
function bestForToken(tok, candidate) {
|
|
291
|
-
let best = scoreCandidate(tok, candidate);
|
|
401
|
+
function bestForToken(tok, candidate, opts = {}) {
|
|
402
|
+
let best = scoreCandidate(tok, candidate, opts);
|
|
292
403
|
const syns = SYNONYM_INDEX.get(tok);
|
|
293
404
|
if (syns) {
|
|
294
405
|
for (const s of syns) {
|
|
295
|
-
const h = scoreCandidate(s, candidate);
|
|
406
|
+
const h = scoreCandidate(s, candidate, opts);
|
|
296
407
|
if (h) {
|
|
297
408
|
const score = Math.round(h.score * 0.85);
|
|
298
409
|
if (!best || score > best.score)
|
|
@@ -322,14 +433,17 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
322
433
|
matched: total,
|
|
323
434
|
total,
|
|
324
435
|
});
|
|
325
|
-
|
|
436
|
+
// Typo tolerance is for one-word lookups. In a multi-word query a near miss
|
|
437
|
+
// is usually a different word, not a typo.
|
|
438
|
+
const fuzzy = tokens.length <= 1;
|
|
439
|
+
const full = scoreCandidate(term, candidate, {fuzzy});
|
|
326
440
|
|
|
327
441
|
// 0–1 content tokens: keep whole-phrase fuzzy matching (typo tolerance for
|
|
328
442
|
// single words), but if stopwords left exactly one DIFFERENT token (e.g.
|
|
329
443
|
// "pricing page" → "pricing"), score that token too and take the stronger.
|
|
330
444
|
if (tokens.length <= 1) {
|
|
331
445
|
const single =
|
|
332
|
-
tokens.length === 1 ? bestForToken(tokens[0], candidate) : null;
|
|
446
|
+
tokens.length === 1 ? bestForToken(tokens[0], candidate, {fuzzy}) : null;
|
|
333
447
|
if (full && (!single || full.score >= single.score)) return asFull(full);
|
|
334
448
|
return single ? asFull(single) : null;
|
|
335
449
|
}
|
|
@@ -356,7 +470,7 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
356
470
|
/** @type {string[]} */
|
|
357
471
|
const hitTerms = [];
|
|
358
472
|
for (const tok of tokens) {
|
|
359
|
-
const h = bestForToken(tok, candidate);
|
|
473
|
+
const h = bestForToken(tok, candidate, {fuzzy});
|
|
360
474
|
if (h && h.score >= MIN_TOKEN_SCORE) {
|
|
361
475
|
if (h.score > strongest) strongest = h.score;
|
|
362
476
|
matched++;
|
|
@@ -409,6 +523,7 @@ export function scoreQuery(term, tokens, candidate) {
|
|
|
409
523
|
* @param {string} [candidate.description]
|
|
410
524
|
* @param {string[]} [candidate.prose] - Extra free-text blobs (doc section text, best practices).
|
|
411
525
|
* @param {string[]} [candidate.guidance] - Usage guidance (features, best practices) — scored a tier below description.
|
|
526
|
+
* @param {{fuzzy?: boolean}} [opts] - `fuzzy`: allow edit-distance (typo) matches. Default true; multi-word queries pass false.
|
|
412
527
|
* @returns {{score: number, reason: string} | null}
|
|
413
528
|
*/
|
|
414
529
|
export function scoreCandidate(
|
|
@@ -421,6 +536,7 @@ export function scoreCandidate(
|
|
|
421
536
|
prose = [],
|
|
422
537
|
guidance = [],
|
|
423
538
|
},
|
|
539
|
+
{fuzzy = true} = {},
|
|
424
540
|
) {
|
|
425
541
|
let best = 0;
|
|
426
542
|
let reason = '';
|
|
@@ -441,20 +557,20 @@ export function scoreCandidate(
|
|
|
441
557
|
if (nameLower === term) {
|
|
442
558
|
consider(100, 'exact name');
|
|
443
559
|
} else {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
560
|
+
if (sameWord(term, nameLower)) consider(95, `name "${name}"`);
|
|
561
|
+
// The term is a word of the name, or starts one: "input" in TextInput.
|
|
562
|
+
else if (startsAWordOf(term, name)) {
|
|
563
|
+
consider(60, `name contains "${term}"`);
|
|
564
|
+
}
|
|
565
|
+
if (fuzzy) {
|
|
566
|
+
const dist = levenshteinDistance(term, nameLower);
|
|
567
|
+
if (isTypo(term, nameLower, dist)) {
|
|
568
|
+
consider(
|
|
569
|
+
dist === 1 ? 80 : dist === 2 ? 40 : 20,
|
|
570
|
+
`similar name (distance ${dist})`,
|
|
571
|
+
);
|
|
572
|
+
}
|
|
453
573
|
}
|
|
454
|
-
const dist = levenshteinDistance(term, nameLower);
|
|
455
|
-
if (dist === 1) consider(80, `similar name (distance ${dist})`);
|
|
456
|
-
else if (dist === 2) consider(40, `similar name (distance ${dist})`);
|
|
457
|
-
else if (dist === 3) consider(20, `similar name (distance ${dist})`);
|
|
458
574
|
}
|
|
459
575
|
|
|
460
576
|
// ── Keyword signals ─────────────────────────────────────────────
|
|
@@ -464,14 +580,17 @@ export function scoreCandidate(
|
|
|
464
580
|
consider(90, `keyword "${kw}"`);
|
|
465
581
|
continue;
|
|
466
582
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
583
|
+
if (sameWord(term, kwLower)) {
|
|
584
|
+
consider(88, `keyword "${kw}"`);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
if (startsAWordOf(term, kw)) consider(70, `keyword "${kw}"`);
|
|
588
|
+
if (fuzzy) {
|
|
589
|
+
const dist = levenshteinDistance(term, kwLower);
|
|
590
|
+
if (isTypo(term, kwLower, dist) && dist <= 2) {
|
|
591
|
+
consider(dist === 1 ? 70 : 30, `keyword "${kw}" (distance ${dist})`);
|
|
592
|
+
}
|
|
471
593
|
}
|
|
472
|
-
const dist = levenshteinDistance(term, kwLower);
|
|
473
|
-
if (dist === 1) consider(70, `keyword "${kw}" (distance ${dist})`);
|
|
474
|
-
else if (dist === 2) consider(30, `keyword "${kw}" (distance ${dist})`);
|
|
475
594
|
}
|
|
476
595
|
|
|
477
596
|
// ── Weak keyword signals (derived, not authored) ─────────────────
|
|
@@ -481,15 +600,11 @@ export function scoreCandidate(
|
|
|
481
600
|
// No Levenshtein tier — fuzzy matching a derived signal is pure noise.
|
|
482
601
|
for (const kw of weakKeywords) {
|
|
483
602
|
const kwLower = String(kw).toLowerCase();
|
|
484
|
-
if (kwLower === term) {
|
|
603
|
+
if (kwLower === term || sameWord(term, kwLower)) {
|
|
485
604
|
consider(60, `renders ${kw}`);
|
|
486
605
|
continue;
|
|
487
606
|
}
|
|
488
|
-
|
|
489
|
-
const l = term.length < kwLower.length ? kwLower : term;
|
|
490
|
-
if (s.length >= 4 && l.includes(s) && s.length / l.length >= 0.5) {
|
|
491
|
-
consider(40, `renders ${kw}`);
|
|
492
|
-
}
|
|
607
|
+
if (startsAWordOf(term, kw)) consider(40, `renders ${kw}`);
|
|
493
608
|
}
|
|
494
609
|
|
|
495
610
|
// ── Prose / description / guidance signals (stem-tolerant whole word) ──
|
|
@@ -528,16 +643,26 @@ export function scoreCandidate(
|
|
|
528
643
|
}
|
|
529
644
|
|
|
530
645
|
/**
|
|
531
|
-
*
|
|
646
|
+
* A component or hook doc, compiled, or null when it cannot be read.
|
|
532
647
|
* @param {string} docPath
|
|
533
648
|
* @param {string} [exportName]
|
|
649
|
+
* @param {'components' | 'hooks'} [root]
|
|
534
650
|
* @returns {Promise<any>}
|
|
535
651
|
*/
|
|
536
|
-
async function loadModuleDoc(
|
|
652
|
+
async function loadModuleDoc(
|
|
653
|
+
docPath,
|
|
654
|
+
exportName = 'docs',
|
|
655
|
+
root = 'components',
|
|
656
|
+
) {
|
|
537
657
|
try {
|
|
538
|
-
const mod = await import(pathToFileURL(docPath).href);
|
|
539
658
|
// Support both the stamped default export and the legacy named export.
|
|
540
|
-
return
|
|
659
|
+
return (
|
|
660
|
+
(await readDocView(docPath, {
|
|
661
|
+
root,
|
|
662
|
+
loader: 'native',
|
|
663
|
+
exports: ['default', exportName],
|
|
664
|
+
})) ?? null
|
|
665
|
+
);
|
|
541
666
|
} catch {
|
|
542
667
|
return null;
|
|
543
668
|
}
|
|
@@ -637,7 +762,8 @@ async function gatherIntegrationComponents(cwd) {
|
|
|
637
762
|
/** @type {Candidate[]} */
|
|
638
763
|
const candidates = [];
|
|
639
764
|
for (const integration of loadedIntegrations) {
|
|
640
|
-
|
|
765
|
+
const {components} = await discoverValidIntegrationComponents(integration);
|
|
766
|
+
for (const rec of components) {
|
|
641
767
|
const doc = await loadModuleDoc(rec.docPath);
|
|
642
768
|
candidates.push({
|
|
643
769
|
domain: 'component',
|
|
@@ -701,7 +827,7 @@ async function gatherHooks(coreDir) {
|
|
|
701
827
|
let description = '';
|
|
702
828
|
let importPath = '@astryxdesign/core/hooks';
|
|
703
829
|
if (docPath) {
|
|
704
|
-
const doc = await loadModuleDoc(docPath);
|
|
830
|
+
const doc = await loadModuleDoc(docPath, 'docs', 'hooks');
|
|
705
831
|
if (doc) {
|
|
706
832
|
keywords = Array.isArray(doc.keywords) ? doc.keywords : [];
|
|
707
833
|
description = doc.usage?.description || doc.description || '';
|
|
@@ -720,7 +846,11 @@ async function gatherHooks(coreDir) {
|
|
|
720
846
|
}
|
|
721
847
|
|
|
722
848
|
/**
|
|
723
|
-
* Build doc
|
|
849
|
+
* Build doc candidates at the grain a reader reads them: each section of a
|
|
850
|
+
* topic, whose command reads just that section; each topic as a whole, whose
|
|
851
|
+
* command lists its sections; and each docs-tree node by its route. The tree's
|
|
852
|
+
* guides split into sections like topics, and its typed docs also match by
|
|
853
|
+
* their own name, so `assertResponse` finds `cli/api/functions/assert-response`.
|
|
724
854
|
*
|
|
725
855
|
* Reads the project's catalog rather than the CLI's own docs directory, so a
|
|
726
856
|
* topic an integration contributed (or replaced) is searchable exactly like a
|
|
@@ -732,44 +862,274 @@ async function gatherHooks(coreDir) {
|
|
|
732
862
|
async function gatherDocs(cwd) {
|
|
733
863
|
/** @type {Candidate[]} */
|
|
734
864
|
const candidates = [];
|
|
735
|
-
let
|
|
865
|
+
let catalog;
|
|
736
866
|
try {
|
|
737
|
-
|
|
867
|
+
catalog = await loadDocsCatalog(cwd);
|
|
738
868
|
} catch {
|
|
739
869
|
return candidates;
|
|
740
870
|
}
|
|
741
|
-
|
|
742
|
-
|
|
871
|
+
let tree = null;
|
|
872
|
+
try {
|
|
873
|
+
tree = await projectTree(catalog);
|
|
874
|
+
} catch {
|
|
875
|
+
// `astryx doctor` reports a tree that fails to build; search still
|
|
876
|
+
// indexes the topics.
|
|
877
|
+
}
|
|
878
|
+
for (const entry of catalog.entries()) {
|
|
879
|
+
// A topic whose name opens another doc (spec:AST-046 FR11) is not
|
|
880
|
+
// offered: every hit's command must open the hit.
|
|
881
|
+
if (tree && !holdsOwnName(tree, catalog, entry)) continue;
|
|
882
|
+
let lowered = null;
|
|
743
883
|
try {
|
|
744
|
-
|
|
884
|
+
lowered = await lowerTopic(catalog, entry);
|
|
745
885
|
} catch {
|
|
746
886
|
// A topic that cannot be loaded is reported by the commands that own
|
|
747
887
|
// integration issues; search just cannot index it.
|
|
748
888
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
}
|
|
889
|
+
const doc = lowered?.doc ?? null;
|
|
890
|
+
// A flat topic lives in the Unorganized level; its hits say so, and name
|
|
891
|
+
// the package each section came from.
|
|
892
|
+
const home = tree?.get(entry.name);
|
|
893
|
+
const placed = home?.ref?.flatTopic === entry.name ? home : null;
|
|
894
|
+
/** @type {Map<string, string>} */
|
|
895
|
+
const packages = new Map([
|
|
896
|
+
[entry.providerId ?? entry.package, entry.package],
|
|
897
|
+
...entry.extensions.map(
|
|
898
|
+
ext => /** @type {[string, string]} */ ([ext.providerId ?? ext.package, ext.package]),
|
|
899
|
+
),
|
|
900
|
+
]);
|
|
901
|
+
candidates.push(
|
|
902
|
+
...topicCandidates(
|
|
903
|
+
entry.name,
|
|
904
|
+
doc,
|
|
905
|
+
entry.title,
|
|
906
|
+
'',
|
|
907
|
+
placed && tree
|
|
908
|
+
? [
|
|
909
|
+
...tree.ancestors(placed).map(a => a.title),
|
|
910
|
+
doc?.title || entry.title || entry.name,
|
|
911
|
+
].join(' › ')
|
|
912
|
+
: undefined,
|
|
913
|
+
placed ? `astryx docs ${placed.parent}` : undefined,
|
|
914
|
+
entry.package,
|
|
915
|
+
key =>
|
|
916
|
+
packages.get(lowered?.sectionProviders?.[key] ?? '') ?? entry.package,
|
|
917
|
+
),
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
if (tree == null) return candidates;
|
|
921
|
+
for (const node of tree.nodes.values()) {
|
|
922
|
+
// A flat topic is indexed above, as a topic.
|
|
923
|
+
if (node.ref?.flatTopic) continue;
|
|
924
|
+
// A tree hit names where it lives: its ancestors' titles, then its own.
|
|
925
|
+
const path = [...tree.ancestors(node).map(a => a.title), node.title];
|
|
926
|
+
if (node.kind === 'generic') {
|
|
927
|
+
let doc = null;
|
|
928
|
+
try {
|
|
929
|
+
doc = (await lowerTopic(catalog, guideEntry(node))).doc;
|
|
930
|
+
} catch {
|
|
931
|
+
// As above: the owning commands report it.
|
|
759
932
|
}
|
|
933
|
+
candidates.push(
|
|
934
|
+
...topicCandidates(
|
|
935
|
+
node.route,
|
|
936
|
+
doc,
|
|
937
|
+
node.title,
|
|
938
|
+
node.summary,
|
|
939
|
+
path.join(' › '),
|
|
940
|
+
node.parent == null ? undefined : `astryx docs ${node.parent}`,
|
|
941
|
+
node.provider,
|
|
942
|
+
),
|
|
943
|
+
);
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
const selfDoc = /** @type {any} */ (node.ref)?.selfDoc;
|
|
947
|
+
// A typed doc's content is what `astryx docs <route>` prints. The first
|
|
948
|
+
// column of its tables names what the doc defines (an error code, an
|
|
949
|
+
// option, a parameter), so each is a keyword the doc answers to.
|
|
950
|
+
/** @type {any[]} */
|
|
951
|
+
const content = (await nodeView(catalog, tree, node)).content ?? [];
|
|
952
|
+
/** @type {string[]} */
|
|
953
|
+
const defined = [];
|
|
954
|
+
for (const block of content) {
|
|
955
|
+
if (block.type !== 'table' || !Array.isArray(block.rows)) continue;
|
|
956
|
+
for (const row of block.rows)
|
|
957
|
+
if (row[0] != null) defined.push(plain(row[0]));
|
|
760
958
|
}
|
|
761
959
|
candidates.push({
|
|
762
960
|
domain: 'doc',
|
|
763
|
-
name:
|
|
764
|
-
keywords: [
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
961
|
+
name: node.name,
|
|
962
|
+
keywords: [
|
|
963
|
+
node.route.slice(node.route.lastIndexOf('/') + 1),
|
|
964
|
+
...(Array.isArray(selfDoc?.keywords) ? selfDoc.keywords : []),
|
|
965
|
+
...defined,
|
|
966
|
+
...codeTerms({content}),
|
|
967
|
+
],
|
|
968
|
+
description: node.summary || '',
|
|
969
|
+
prose: sectionProse({title: node.title, content}),
|
|
970
|
+
_topic: node.route,
|
|
971
|
+
_title: path.join(' › '),
|
|
972
|
+
_command: `astryx docs ${node.route}`,
|
|
973
|
+
_parent: node.parent == null ? 'astryx docs' : `astryx docs ${node.parent}`,
|
|
974
|
+
_package: node.provider,
|
|
768
975
|
});
|
|
769
976
|
}
|
|
770
977
|
return candidates;
|
|
771
978
|
}
|
|
772
979
|
|
|
980
|
+
/**
|
|
981
|
+
* The words one section says: its prose, headings, and list items.
|
|
982
|
+
* @param {any} section
|
|
983
|
+
* @returns {string[]}
|
|
984
|
+
*/
|
|
985
|
+
function sectionProse(section) {
|
|
986
|
+
/** @type {string[]} */
|
|
987
|
+
const prose = [];
|
|
988
|
+
if (section?.title) prose.push(section.title);
|
|
989
|
+
for (const block of section?.content || []) {
|
|
990
|
+
if ((block.type === 'prose' || block.type === 'heading') && block.text) {
|
|
991
|
+
prose.push(block.text);
|
|
992
|
+
} else if (block.type === 'list' && Array.isArray(block.items)) {
|
|
993
|
+
for (const item of block.items) {
|
|
994
|
+
const text = typeof item === 'string' ? item : item?.text;
|
|
995
|
+
if (typeof text === 'string') prose.push(text);
|
|
996
|
+
}
|
|
997
|
+
} else if (block.type === 'table' && Array.isArray(block.rows)) {
|
|
998
|
+
for (const row of block.rows) prose.push(row.map(plain).join(' '));
|
|
999
|
+
} else if (block.type === 'code' && typeof block.code === 'string') {
|
|
1000
|
+
prose.push([block.label, block.code].filter(Boolean).join(' '));
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
return prose;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* The identifiers a doc part names in code ticks (`token-ref`,
|
|
1008
|
+
* `ERR_UNKNOWN_SECTION`). Each is a keyword: a reader who types one exactly
|
|
1009
|
+
* wants the part that defines or explains it.
|
|
1010
|
+
* @param {any} part - a section, or `{content}` of a typed doc
|
|
1011
|
+
* @returns {string[]}
|
|
1012
|
+
*/
|
|
1013
|
+
function codeTerms(part) {
|
|
1014
|
+
/** @type {Set<string>} */
|
|
1015
|
+
const terms = new Set();
|
|
1016
|
+
/** @param {unknown} text */
|
|
1017
|
+
const scan = text => {
|
|
1018
|
+
for (const m of String(text ?? '').matchAll(/`([^`\s]{2,40})`/g)) {
|
|
1019
|
+
terms.add(m[1]);
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
for (const block of part?.content || []) {
|
|
1023
|
+
if (block.type === 'prose') scan(block.text);
|
|
1024
|
+
else if (block.type === 'list' && Array.isArray(block.items)) {
|
|
1025
|
+
for (const item of block.items) {
|
|
1026
|
+
scan(typeof item === 'string' ? item : item?.text);
|
|
1027
|
+
}
|
|
1028
|
+
} else if (block.type === 'table' && Array.isArray(block.rows)) {
|
|
1029
|
+
for (const row of block.rows) for (const cell of row) scan(cell);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
return [...terms];
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* The headings inside a section. Each names a subsection, so a query that
|
|
1037
|
+
* names one should find the section as surely as one that names its title.
|
|
1038
|
+
* @param {any} section
|
|
1039
|
+
* @returns {string[]}
|
|
1040
|
+
*/
|
|
1041
|
+
function headings(section) {
|
|
1042
|
+
return (section?.content || [])
|
|
1043
|
+
.filter(
|
|
1044
|
+
(/** @type {any} */ block) => block.type === 'heading' && block.text,
|
|
1045
|
+
)
|
|
1046
|
+
.map((/** @type {any} */ block) => String(block.text));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* A table cell as plain words, without its code ticks.
|
|
1051
|
+
* @param {unknown} cell
|
|
1052
|
+
* @returns {string}
|
|
1053
|
+
*/
|
|
1054
|
+
function plain(cell) {
|
|
1055
|
+
return unlinkText(String(cell ?? '')).replaceAll('`', '');
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* The candidates one topic yields: the topic itself, and one per section when
|
|
1060
|
+
* it has more than one. A topic's command lists its sections, and a section's
|
|
1061
|
+
* command reads only that section, so a hit never costs a whole-topic read.
|
|
1062
|
+
* @param {string} name - the topic name, or a placed guide's route
|
|
1063
|
+
* @param {any} doc - the lowered topic, or null when it did not load
|
|
1064
|
+
* @param {string} [title]
|
|
1065
|
+
* @param {string} [summary]
|
|
1066
|
+
* @param {string} [path] - where the topic lives in the docs tree, as titles
|
|
1067
|
+
* joined by ` › `; a flat topic is its own title
|
|
1068
|
+
* @param {string} [parent] - the command that opens the level above the
|
|
1069
|
+
* topic: its namespace, or the Unorganized level for a flat topic
|
|
1070
|
+
* @param {string} [pkg] - the npm package that authored the topic
|
|
1071
|
+
* @param {(key: string) => string} [sectionPackage] - the npm package a
|
|
1072
|
+
* section came from: an extension's section names the extension's package
|
|
1073
|
+
* @returns {Candidate[]}
|
|
1074
|
+
*/
|
|
1075
|
+
function topicCandidates(
|
|
1076
|
+
name,
|
|
1077
|
+
doc,
|
|
1078
|
+
title,
|
|
1079
|
+
summary = '',
|
|
1080
|
+
path,
|
|
1081
|
+
parent,
|
|
1082
|
+
pkg,
|
|
1083
|
+
sectionPackage,
|
|
1084
|
+
) {
|
|
1085
|
+
/** @type {any[]} */
|
|
1086
|
+
const sections = doc?.sections ?? [];
|
|
1087
|
+
const docTitle = path || doc?.title || title || name;
|
|
1088
|
+
const split = sections.length > 1;
|
|
1089
|
+
/** @type {Candidate[]} */
|
|
1090
|
+
const out = [
|
|
1091
|
+
{
|
|
1092
|
+
domain: 'doc',
|
|
1093
|
+
name,
|
|
1094
|
+
keywords: [
|
|
1095
|
+
...(doc?.title || title ? [doc?.title || title] : []),
|
|
1096
|
+
...(Array.isArray(doc?.keywords) ? doc.keywords : []),
|
|
1097
|
+
],
|
|
1098
|
+
description: doc?.description || summary,
|
|
1099
|
+
prose: split
|
|
1100
|
+
? sections.map(section => section.title).filter(Boolean)
|
|
1101
|
+
: sections.flatMap(sectionProse),
|
|
1102
|
+
_topic: name,
|
|
1103
|
+
_title: docTitle,
|
|
1104
|
+
_command: split ? `astryx docs ${name} --index` : `astryx docs ${name}`,
|
|
1105
|
+
...(parent ? {_parent: parent} : {}),
|
|
1106
|
+
...(pkg ? {_package: pkg} : {}),
|
|
1107
|
+
},
|
|
1108
|
+
];
|
|
1109
|
+
if (!split) return out;
|
|
1110
|
+
for (const section of sections) {
|
|
1111
|
+
const key = sectionKey(section);
|
|
1112
|
+
out.push({
|
|
1113
|
+
domain: 'doc',
|
|
1114
|
+
name: key,
|
|
1115
|
+
keywords: [
|
|
1116
|
+
...(section.title ? [section.title] : []),
|
|
1117
|
+
...headings(section),
|
|
1118
|
+
...codeTerms(section),
|
|
1119
|
+
],
|
|
1120
|
+
description: sectionSummary(section),
|
|
1121
|
+
prose: sectionProse(section),
|
|
1122
|
+
_topic: name,
|
|
1123
|
+
_section: key,
|
|
1124
|
+
_title: `${docTitle} › ${section.title}`,
|
|
1125
|
+
_command: `astryx docs ${name} ${key}`,
|
|
1126
|
+
_parent: `astryx docs ${name} --index`,
|
|
1127
|
+
...((sectionPackage?.(key) ?? pkg) ? {_package: sectionPackage?.(key) ?? pkg} : {}),
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return out;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
773
1133
|
/**
|
|
774
1134
|
* Build template candidates (page + block) from the template discovery API.
|
|
775
1135
|
* @param {string} cwd
|
|
@@ -783,6 +1143,13 @@ async function gatherTemplates(cwd) {
|
|
|
783
1143
|
return [];
|
|
784
1144
|
}
|
|
785
1145
|
return templates.map(t => {
|
|
1146
|
+
// A replacement's target is its canonical unqualified lookup id. Keep the
|
|
1147
|
+
// integration-owned id as a keyword and response label, but score and print
|
|
1148
|
+
// commands against the id that `template()` resolves back to this entry.
|
|
1149
|
+
// This matters for replacement chains: one replacement's own id can be the
|
|
1150
|
+
// target of another, so using that shadowed id as the command would select
|
|
1151
|
+
// the other template.
|
|
1152
|
+
const commandName = t.replaces ?? t.dirName;
|
|
786
1153
|
// Blocks ship an authored componentsUsed; page templates don't, so derive
|
|
787
1154
|
// them from the source. Category words (e.g. "Dashboard - Analytics") are
|
|
788
1155
|
// strong intent signal for pages, which otherwise only index on name +
|
|
@@ -795,6 +1162,7 @@ async function gatherTemplates(cwd) {
|
|
|
795
1162
|
const keywords = Array.isArray(t.componentsUsed)
|
|
796
1163
|
? [...t.componentsUsed]
|
|
797
1164
|
: [];
|
|
1165
|
+
keywords.push(...templateLookupIds(t).filter(id => id !== commandName));
|
|
798
1166
|
/** @type {string[]} */
|
|
799
1167
|
let weakKeywords = [];
|
|
800
1168
|
if (t.type === 'page') {
|
|
@@ -810,12 +1178,14 @@ async function gatherTemplates(cwd) {
|
|
|
810
1178
|
}
|
|
811
1179
|
return {
|
|
812
1180
|
domain: 'template',
|
|
813
|
-
name:
|
|
1181
|
+
name: commandName,
|
|
814
1182
|
keywords,
|
|
815
1183
|
weakKeywords,
|
|
816
1184
|
description: t.description || '',
|
|
817
1185
|
_displayName: t.name,
|
|
818
1186
|
_kind: t.type, // 'page' | 'block'
|
|
1187
|
+
_resultName: t.dirName,
|
|
1188
|
+
_commandName: commandName,
|
|
819
1189
|
};
|
|
820
1190
|
});
|
|
821
1191
|
}
|
|
@@ -834,7 +1204,7 @@ async function gatherTemplates(cwd) {
|
|
|
834
1204
|
function toResult(c, score, reason, matchedTerms, queryTerms) {
|
|
835
1205
|
const base = {
|
|
836
1206
|
domain: c.domain,
|
|
837
|
-
name: c.name,
|
|
1207
|
+
name: c._resultName ?? c.name,
|
|
838
1208
|
score,
|
|
839
1209
|
reason,
|
|
840
1210
|
description: c.description || '',
|
|
@@ -856,10 +1226,16 @@ function toResult(c, score, reason, matchedTerms, queryTerms) {
|
|
|
856
1226
|
};
|
|
857
1227
|
break;
|
|
858
1228
|
case 'doc':
|
|
1229
|
+
// A doc result names its topic or route, plus the section when the
|
|
1230
|
+
// hit is one section; its command reads exactly that part.
|
|
859
1231
|
result = {
|
|
860
1232
|
...base,
|
|
1233
|
+
name: c._topic ?? c.name,
|
|
1234
|
+
...(c._section ? {section: c._section} : {}),
|
|
861
1235
|
title: c._title,
|
|
862
|
-
command: `astryx docs ${c.name}`,
|
|
1236
|
+
command: c._command ?? `astryx docs ${c.name}`,
|
|
1237
|
+
...(c._parent ? {parent: c._parent} : {}),
|
|
1238
|
+
...(c._package ? {package: c._package} : {}),
|
|
863
1239
|
};
|
|
864
1240
|
break;
|
|
865
1241
|
case 'template':
|
|
@@ -867,7 +1243,7 @@ function toResult(c, score, reason, matchedTerms, queryTerms) {
|
|
|
867
1243
|
...base,
|
|
868
1244
|
displayName: c._displayName,
|
|
869
1245
|
kind: c._kind,
|
|
870
|
-
command: `astryx template ${c.name}`,
|
|
1246
|
+
command: `astryx template ${c._commandName ?? c.name} --type ${c._kind}`,
|
|
871
1247
|
};
|
|
872
1248
|
break;
|
|
873
1249
|
default:
|
|
@@ -884,7 +1260,7 @@ function toResult(c, score, reason, matchedTerms, queryTerms) {
|
|
|
884
1260
|
* @param {string} [options.cwd]
|
|
885
1261
|
* @param {'component'|'hook'|'doc'|'template'} [options.type] - Restrict to one domain.
|
|
886
1262
|
* @param {number} [options.limit] - Max results (default 20).
|
|
887
|
-
* @returns {Promise<
|
|
1263
|
+
* @returns {Promise<import('./search.type.mjs').SearchResponse>}
|
|
888
1264
|
*/
|
|
889
1265
|
export async function search(query, options = {}) {
|
|
890
1266
|
const {cwd = process.cwd(), type, limit = 20} = options;
|
|
@@ -919,17 +1295,26 @@ export async function search(query, options = {}) {
|
|
|
919
1295
|
const term = String(query).trim().toLowerCase();
|
|
920
1296
|
const tokens = tokenizeQuery(term);
|
|
921
1297
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1298
|
+
// `astryx docs` reads docs without @astryxdesign/core, so a docs-only
|
|
1299
|
+
// search must too. Every other domain reads core.
|
|
1300
|
+
const docsOnly = type === 'doc';
|
|
1301
|
+
const coreDir = docsOnly ? null : findCoreDir(cwd);
|
|
1302
|
+
if (!docsOnly && !coreDir) {
|
|
1303
|
+
throw new AstryxError(
|
|
1304
|
+
'Could not find @astryxdesign/core package',
|
|
1305
|
+
undefined,
|
|
1306
|
+
ERROR_CODES.ERR_CORE_NOT_FOUND,
|
|
1307
|
+
);
|
|
925
1308
|
}
|
|
926
1309
|
|
|
927
1310
|
// Gather candidates from each requested domain in parallel.
|
|
928
1311
|
/** @param {string} d */
|
|
929
1312
|
const wants = d => !type || type === d;
|
|
930
1313
|
const [components, hooks, docTopics, templates] = await Promise.all([
|
|
931
|
-
wants('component')
|
|
932
|
-
|
|
1314
|
+
wants('component')
|
|
1315
|
+
? gatherComponents(/** @type {string} */ (coreDir), cwd)
|
|
1316
|
+
: [],
|
|
1317
|
+
wants('hook') ? gatherHooks(/** @type {string} */ (coreDir)) : [],
|
|
933
1318
|
wants('doc') ? gatherDocs(cwd) : [],
|
|
934
1319
|
wants('template') ? gatherTemplates(cwd) : [],
|
|
935
1320
|
]);
|
|
@@ -971,7 +1356,10 @@ export async function search(query, options = {}) {
|
|
|
971
1356
|
data: {
|
|
972
1357
|
query: String(query).trim(),
|
|
973
1358
|
matchCount: scored.length,
|
|
974
|
-
|
|
1359
|
+
// toResult gives every domain its command and domain fields.
|
|
1360
|
+
results: /** @type {import('./search.type.mjs').SearchResultEntry[]} */ (
|
|
1361
|
+
limited
|
|
1362
|
+
),
|
|
975
1363
|
},
|
|
976
1364
|
};
|
|
977
1365
|
}
|