@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2
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 +119 -0
- package/README.md +175 -154
- package/api/build/_adapter.d.mts +8 -0
- package/api/build/_adapter.mjs +12 -1
- package/api/build/build.doc.mjs +4 -0
- package/api/build/help/help.mjs +1 -1
- package/api/build/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +72 -1
- package/api/component/_adapter.mjs +212 -18
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +82 -15
- package/api/component/component.test.mjs +80 -0
- package/api/component/doc-links.test.mjs +386 -0
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/discover/_adapter.d.mts +132 -12
- package/api/discover/_adapter.mjs +488 -27
- package/api/discover/_adapter.test.mjs +599 -17
- package/api/discover/_catalog-view.d.mts +16 -5
- package/api/discover/_catalog-view.mjs +32 -8
- package/api/discover/detail/doc/doc.mjs +9 -1
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +9 -7
- package/api/discover/discover.mjs +121 -19
- package/api/discover/discover.type.d.mts +20 -7
- package/api/discover/discover.type.mjs +17 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +74 -0
- package/api/docs/_adapter.mjs +553 -16
- package/api/docs/docs.doc.mjs +2 -1
- package/api/docs/docs.mjs +2 -1
- package/api/docs/docs.test.mjs +5 -2
- package/api/docs/integration-tree.test.mjs +22 -0
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/docs/list/list.mjs +12 -2
- package/api/docs/reference-blocks.test.mjs +1 -3
- package/api/doctor/_adapter.d.mts +108 -0
- package/api/doctor/_adapter.mjs +223 -4
- package/api/doctor/doctor.d.mts +199 -0
- package/api/doctor/doctor.doc.mjs +3 -2
- package/api/doctor/doctor.mjs +530 -34
- package/api/doctor/doctor.test.mjs +180 -14
- package/api/doctor/release-checks.test.mjs +156 -0
- package/api/doctor/theme-checks.mjs +17 -4
- package/api/doctor/theme-checks.test.mjs +223 -7
- package/api/error.d.mts +10 -0
- package/api/error.mjs +25 -0
- package/api/gap-report/gap-report.d.mts +3 -0
- package/api/gap-report/gap-report.doc.mjs +11 -3
- package/api/gap-report/gap-report.mjs +219 -52
- package/api/gap-report/gap-report.test.mjs +233 -0
- package/api/gap-report/gap-report.type.d.mts +41 -0
- package/api/gap-report/gap-report.type.mjs +18 -0
- package/api/hook/_adapter.mjs +3 -11
- package/api/hook/hook.doc.mjs +4 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/_adapter.d.mts +22 -0
- package/api/init/_adapter.mjs +59 -0
- package/api/init/init.d.mts +7 -5
- package/api/init/init.doc.mjs +28 -7
- package/api/init/init.mjs +28 -4
- package/api/init/init.type.d.mts +48 -3
- package/api/init/init.type.mjs +37 -3
- package/api/init/run/run.d.mts +1 -1
- package/api/init/run/run.mjs +17 -6
- package/api/init/user/user.d.mts +14 -0
- package/api/init/user/user.mjs +87 -0
- package/api/init/user/user.test.mjs +232 -0
- package/api/integration/_adapter.d.mts +45 -0
- package/api/integration/_adapter.mjs +112 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +110 -6
- package/api/integration/authoring-checks.test.mjs +808 -0
- package/api/integration/authoring-checks.type.d.mts +143 -0
- package/api/integration/authoring-checks.type.mjs +74 -2
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +364 -120
- package/api/integration/pack-check.test.mjs +730 -10
- package/api/integration/validate-integration-fixes.test.mjs +67 -0
- package/api/integration/validate-integration.d.mts +8 -0
- package/api/integration/validate-integration.mjs +63 -9
- package/api/integration/validate-integration.test.mjs +88 -8
- package/api/integration/validate-integration.type.d.mts +16 -0
- package/api/integration/validate-integration.type.mjs +14 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +82 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +645 -64
- package/api/search/search.test.mjs +179 -1
- package/api/search/search.type.d.mts +14 -1
- package/api/search/search.type.mjs +6 -1
- package/api/swizzle/_adapter.mjs +2 -2
- package/api/swizzle/copy/copy.mjs +29 -15
- package/api/template/template-integration.test.mjs +1 -1
- package/api/template/template.test.mjs +120 -3
- package/api/theme/_adapter.d.mts +16 -0
- package/api/theme/_adapter.mjs +32 -5
- package/api/theme/build/build.d.mts +2 -1
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +250 -38
- package/api/theme/build/build.packed-old-core.test.mjs +20 -3
- package/api/theme/build/font-warning.mjs +5 -3
- package/api/theme/build/font-warning.test.mjs +2 -1
- package/api/theme/remove/remove.test.mjs +2 -2
- package/api/theme/targets/targets.mjs +3 -10
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/theme/themeTargets.doc.mjs +4 -0
- package/api/theme/use/use.test.mjs +1 -1
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +118 -5
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +35 -2
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +6 -3
- package/api/upgrade/upgrade.mjs +5 -1
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +3 -3
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +26 -6
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +2 -2
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +22 -2
- package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
- package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
- package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +4 -0
- package/assets/docs/tree/check-the-props.doc.mjs +201 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
- package/assets/docs/tree/checks.doc.mjs +32 -24
- package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
- package/assets/docs/tree/cli-command.doc.mjs +142 -0
- package/assets/docs/tree/cli.doc.mjs +6 -0
- package/assets/docs/tree/codemods.doc.mjs +17 -7
- package/assets/docs/tree/commands.doc.mjs +7 -1
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +21 -3
- package/assets/docs/tree/components.doc.mjs +7 -1
- package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
- package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
- package/assets/docs/tree/configuration.doc.mjs +7 -3
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
- package/assets/docs/tree/docs.doc.mjs +9 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
- package/assets/docs/tree/global-integrations.doc.mjs +124 -0
- package/assets/docs/tree/global.doc.mjs +131 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
- package/assets/docs/tree/install-once.doc.mjs +105 -0
- package/assets/docs/tree/integrations.doc.mjs +13 -1
- package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
- package/assets/docs/tree/layout.doc.mjs +6 -6
- package/assets/docs/tree/links.doc.mjs +7 -6
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/monorepos.doc.mjs +84 -0
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/problems.doc.mjs +205 -0
- package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
- package/assets/docs/tree/publishing.doc.mjs +6 -6
- package/assets/docs/tree/quick-start.doc.mjs +53 -27
- package/assets/docs/tree/reference.doc.mjs +192 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
- package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
- package/assets/docs/tree/scaffold.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
- package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +18 -8
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +2 -2
- package/assets/docs/tree/templates.doc.mjs +7 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
- package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
- package/assets/docs/tree/themes.doc.mjs +4 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/uninstall.doc.mjs +109 -0
- package/assets/docs/tree/updates.doc.mjs +92 -0
- package/assets/docs/tree/upgrading.doc.mjs +6 -6
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
- package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +10 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +66 -13
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/discover/discover.doc.mjs +7 -1
- package/authoring/doctypes/_schema.d.mts +8 -3
- package/authoring/doctypes/_schema.mjs +1 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +20 -12
- package/authoring/doctypes/command/type.ts +14 -0
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +21 -8
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/hook/type.ts +4 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +12 -11
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +2 -0
- package/authoring/integration/integration.doc.mjs +30 -6
- package/authoring/integration/parse.test.mjs +21 -0
- package/authoring/integration/schema.d.mts +16 -3
- package/authoring/integration/schema.mjs +34 -2
- package/authoring/integration/type.ts +12 -0
- package/clients/cli/bin/astryx.mjs +20 -3
- package/clients/cli/cli-command.test.mjs +166 -0
- package/clients/cli/commands/blog.doc.mjs +1 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +26 -13
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/build.doc.mjs +1 -0
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/component.doc.mjs +1 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
- package/clients/cli/commands/discover.doc.mjs +9 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +448 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/docs.doc.mjs +1 -0
- package/clients/cli/commands/docs.mjs +49 -19
- package/clients/cli/commands/docs.test.mjs +2 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
- package/clients/cli/commands/doctor-integration.test.mjs +888 -3
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +292 -7
- package/clients/cli/commands/doctor.test.mjs +10 -4
- package/clients/cli/commands/gap-report.doc.mjs +15 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/hook.doc.mjs +1 -0
- package/clients/cli/commands/init.behavior.test.mjs +5 -0
- package/clients/cli/commands/init.doc.mjs +29 -3
- package/clients/cli/commands/integration-add.doc.mjs +7 -0
- package/clients/cli/commands/integration-authoring.test.mjs +49 -3
- package/clients/cli/commands/integration-check.doc.mjs +93 -0
- package/clients/cli/commands/integration-check.test.mjs +441 -0
- package/clients/cli/commands/integration-pack.doc.mjs +8 -1
- package/clients/cli/commands/integration-verify.doc.mjs +8 -1
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +119 -7
- package/clients/cli/commands/json-contract.test.mjs +11 -2
- package/clients/cli/commands/manifest.doc.mjs +1 -0
- package/clients/cli/commands/outside-project.test.mjs +774 -0
- package/clients/cli/commands/search.doc.mjs +1 -0
- package/clients/cli/commands/search.mjs +16 -11
- package/clients/cli/commands/search.test.mjs +429 -296
- package/clients/cli/commands/setup-nudge.test.mjs +102 -2
- package/clients/cli/commands/swizzle.doc.mjs +7 -0
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
- package/clients/cli/commands/template.doc.mjs +1 -0
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
- package/clients/cli/commands/theme-add.doc.mjs +8 -1
- package/clients/cli/commands/theme-build.doc.mjs +3 -2
- package/clients/cli/commands/theme-eject.doc.mjs +1 -0
- package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
- package/clients/cli/commands/theme-list.doc.mjs +1 -0
- package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
- package/clients/cli/commands/theme-remove.doc.mjs +7 -0
- package/clients/cli/commands/theme-targets.doc.mjs +1 -0
- package/clients/cli/commands/theme-template.doc.mjs +1 -0
- package/clients/cli/commands/theme-use.doc.mjs +7 -0
- package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +22 -1
- package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
- package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +112 -16
- package/clients/cli/lib/cli-error.mjs +4 -1
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +2 -2
- package/clients/cli/lib/json-shim.mjs +3 -1
- package/clients/cli/lib/manifest.d.ts +9 -0
- package/clients/cli/lib/manifest.mjs +17 -1
- package/clients/cli/lib/manifest.test.mjs +25 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
- package/foundation/agent-docs/agent-doc-state.mjs +66 -6
- package/foundation/agent-docs/agent-docs.d.mts +4 -3
- package/foundation/agent-docs/agent-docs.mjs +11 -9
- package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
- package/foundation/agent-docs/computer-agent-text.mjs +623 -0
- package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
- package/foundation/config/project.d.mts +35 -3
- package/foundation/config/project.mjs +226 -7
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +20 -1
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +216 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-consistency.d.mts +34 -0
- package/foundation/discovery/doc-consistency.mjs +513 -0
- package/foundation/discovery/doc-consistency.test.mjs +347 -0
- package/foundation/discovery/doc-fluff.d.mts +112 -0
- package/foundation/discovery/doc-fluff.mjs +328 -0
- package/foundation/discovery/doc-fluff.test.mjs +142 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1231 -0
- package/foundation/discovery/doc-types.test.mjs +744 -0
- package/foundation/discovery/docs-discovery.d.mts +88 -0
- package/foundation/discovery/docs-discovery.mjs +83 -2
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +32 -0
- package/foundation/discovery/project-typescript.mjs +89 -0
- package/foundation/discovery/prop-drift.d.mts +297 -0
- package/foundation/discovery/prop-drift.mjs +2428 -0
- package/foundation/discovery/prop-drift.test.mjs +2337 -0
- package/foundation/discovery/runner-allowlist.d.mts +40 -0
- package/foundation/discovery/runner-allowlist.mjs +53 -0
- package/foundation/discovery/stray-pointers.d.mts +52 -0
- package/foundation/discovery/stray-pointers.mjs +293 -0
- package/foundation/discovery/stray-pointers.test.mjs +86 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/template-needs.mjs +5 -2
- package/foundation/discovery/theme-imports.mjs +8 -4
- package/foundation/discovery/theme-imports.test.mjs +1 -1
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
- package/foundation/doc-compiler/inputs.mjs +27 -1
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +41 -5
- package/foundation/doc-compiler/links.mjs +167 -28
- package/foundation/doc-compiler/links.test.mjs +97 -4
- package/foundation/doc-compiler/read.d.mts +1 -1
- package/foundation/doc-compiler/tree.mjs +30 -1
- package/foundation/doc-compiler/tree.test.mjs +8 -1
- package/foundation/env/cli-command.d.mts +83 -0
- package/foundation/env/cli-command.mjs +152 -0
- package/foundation/env/cli-command.test.mjs +129 -0
- package/foundation/env/node-version.test.mjs +15 -3
- package/foundation/env/package-manager.d.mts +93 -9
- package/foundation/env/package-manager.global.test.mjs +66 -0
- package/foundation/env/package-manager.mjs +184 -13
- package/foundation/env/package-manager.test.mjs +341 -15
- package/foundation/env/project-scope.d.mts +9 -0
- package/foundation/env/project-scope.mjs +33 -0
- package/foundation/env/search-path.d.mts +42 -0
- package/foundation/env/search-path.mjs +205 -0
- package/foundation/env/search-path.test.mjs +122 -0
- package/foundation/env/user-dirs.d.mts +39 -0
- package/foundation/env/user-dirs.mjs +93 -0
- package/foundation/env/user-dirs.test.mjs +72 -0
- package/foundation/env/user-settings.d.mts +46 -0
- package/foundation/env/user-settings.mjs +106 -0
- package/foundation/env/user-settings.test.mjs +64 -0
- package/foundation/fs/file-protection.mjs +15 -1
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.stdout.test.mjs +3 -2
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/fs/path-compare.d.mts +33 -0
- package/foundation/fs/path-compare.mjs +73 -0
- package/foundation/fs/paths.d.mts +57 -1
- package/foundation/fs/paths.mjs +131 -3
- package/foundation/fs/paths.test.mjs +10 -1
- package/foundation/integrations/computer-integrations.d.mts +78 -0
- package/foundation/integrations/computer-integrations.mjs +316 -0
- package/foundation/integrations/computer-integrations.test.mjs +292 -0
- package/foundation/integrations/contribution-inventory.d.mts +11 -0
- package/foundation/integrations/contribution-inventory.mjs +56 -3
- package/foundation/integrations/integration-warnings.mjs +3 -2
- package/foundation/integrations/integration-warnings.test.mjs +8 -9
- package/foundation/integrations/integrations.d.mts +25 -1
- package/foundation/integrations/integrations.mjs +46 -3
- package/foundation/integrations/issue.ts +6 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +41 -1
- package/foundation/release/agent-text-worker.d.mts +4 -0
- package/foundation/release/agent-text-worker.mjs +52 -0
- package/foundation/release/cache.d.mts +310 -0
- package/foundation/release/cache.mjs +1216 -0
- package/foundation/release/cache.test.mjs +920 -0
- package/foundation/release/choose.d.mts +207 -0
- package/foundation/release/choose.mjs +677 -0
- package/foundation/release/choose.test.mjs +427 -0
- package/foundation/release/core-worker.d.mts +4 -0
- package/foundation/release/core-worker.mjs +38 -0
- package/foundation/release/global-state.d.mts +259 -0
- package/foundation/release/global-state.mjs +472 -0
- package/foundation/release/global-state.test.mjs +381 -0
- package/foundation/release/handoff.d.mts +60 -0
- package/foundation/release/handoff.e2e.test.mjs +278 -0
- package/foundation/release/handoff.mjs +357 -0
- package/foundation/release/lock-lease.d.mts +23 -0
- package/foundation/release/lock-lease.mjs +80 -0
- package/foundation/release/notices.d.mts +253 -0
- package/foundation/release/notices.mjs +596 -0
- package/foundation/release/notices.test.mjs +565 -0
- package/foundation/release/npm-guard.d.mts +4 -0
- package/foundation/release/npm-guard.mjs +126 -0
- package/foundation/release/project.d.mts +141 -0
- package/foundation/release/project.mjs +466 -0
- package/foundation/release/project.test.mjs +288 -0
- package/foundation/release/refresh-worker.d.mts +4 -0
- package/foundation/release/refresh-worker.mjs +27 -0
- package/foundation/release/run-context.d.mts +47 -0
- package/foundation/release/run-context.mjs +149 -0
- package/foundation/release/update-notice-env.d.mts +28 -0
- package/foundation/release/update-notice-env.mjs +39 -0
- package/foundation/response/base.d.ts +26 -3
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.doc.mjs +12 -0
- package/foundation/response/error-codes.mjs +17 -0
- package/foundation/response/error-codes.test.mjs +2 -0
- package/foundation/response/json-contract.test.mjs +7 -2
- package/foundation/response/json.mjs +4 -1
- package/foundation/response/response-types.doc.mjs +22 -11
- package/foundation/response/response-types.doc.test.mjs +46 -0
- package/foundation/response/response.doc.mjs +3 -3
- package/foundation/xle/browser-imports.test.mjs +74 -0
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file Where a runner may stand in front of an Astryx command in Astryx's own
|
|
6
|
+
* docs. Docs write commands bare (`astryx <command>`): the CLI prefixes each
|
|
7
|
+
* one with the reader's command when it prints a doc, and the docsite with
|
|
8
|
+
* `npx @astryxdesign/cli`. A few files show a runner on purpose, and some files
|
|
9
|
+
* are not docs at all. The rules, checked by test/runner-commands.test.mjs:
|
|
10
|
+
*
|
|
11
|
+
* - npx (or another download runner) with the unscoped name `astryx` is never
|
|
12
|
+
* written outside `skip`: it fetches an unrelated npm package.
|
|
13
|
+
* - In a doc (`*.doc.mjs`, and Core's docs.mjs), no runner precedes an Astryx
|
|
14
|
+
* command, except in `runnerExamples`, where `npx @astryxdesign/cli …` and a
|
|
15
|
+
* project's runner may (still never the unscoped name through npx).
|
|
16
|
+
*
|
|
17
|
+
* TODO(doctor-runner-check): the Doctor lane's integration-docs runner check
|
|
18
|
+
* (foundation/discovery/runner-commands.mjs) becomes the single rule; then the
|
|
19
|
+
* repo test runs that check over Core's and the CLI's own docs with this
|
|
20
|
+
* allowlist.
|
|
21
|
+
*
|
|
22
|
+
* @input nothing
|
|
23
|
+
* @output the allowlist
|
|
24
|
+
* @position packages/cli/foundation/discovery — data shared by the repo test
|
|
25
|
+
* and the Doctor runner check
|
|
26
|
+
*/
|
|
27
|
+
export const RUNNER_COMMAND_ALLOWLIST: Readonly<{
|
|
28
|
+
/** Files never scanned: release notes, tests, and the helpers that build runner forms. */
|
|
29
|
+
skip: readonly RegExp[];
|
|
30
|
+
/** Docs that show a runner on purpose, and why. */
|
|
31
|
+
runnerExamples: Readonly<{
|
|
32
|
+
'packages/core/docs.mjs': "Core's setup banner, for a project that has no CLI installed yet";
|
|
33
|
+
'packages/cli/assets/docs/tree/updates.doc.mjs': "quotes the CLI's own update notice, which names the project's runner";
|
|
34
|
+
'packages/cli/assets/docs/tree/cli-command.doc.mjs': "explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them";
|
|
35
|
+
'packages/cli/assets/docs/tree/who-answers.doc.mjs': "explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them";
|
|
36
|
+
'packages/cli/assets/docs/tree/project-global-or-both.doc.mjs': "compares running the CLI with npx to installing it, and is found by searching for that command";
|
|
37
|
+
'packages/cli/assets/docs/tree/install-once.doc.mjs': "names a pinned release, `npx @astryxdesign/cli@<version>`, which answers as that version";
|
|
38
|
+
'packages/cli/clients/cli/commands/upgrade.doc.mjs': "quotes the command upgrade prints when the CLI is older than Core, pinned to the matching release";
|
|
39
|
+
}>;
|
|
40
|
+
}>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Where a runner may stand in front of an Astryx command in Astryx's own
|
|
5
|
+
* docs. Docs write commands bare (`astryx <command>`): the CLI prefixes each
|
|
6
|
+
* one with the reader's command when it prints a doc, and the docsite with
|
|
7
|
+
* `npx @astryxdesign/cli`. A few files show a runner on purpose, and some files
|
|
8
|
+
* are not docs at all. The rules, checked by test/runner-commands.test.mjs:
|
|
9
|
+
*
|
|
10
|
+
* - npx (or another download runner) with the unscoped name `astryx` is never
|
|
11
|
+
* written outside `skip`: it fetches an unrelated npm package.
|
|
12
|
+
* - In a doc (`*.doc.mjs`, and Core's docs.mjs), no runner precedes an Astryx
|
|
13
|
+
* command, except in `runnerExamples`, where `npx @astryxdesign/cli …` and a
|
|
14
|
+
* project's runner may (still never the unscoped name through npx).
|
|
15
|
+
*
|
|
16
|
+
* TODO(doctor-runner-check): the Doctor lane's integration-docs runner check
|
|
17
|
+
* (foundation/discovery/runner-commands.mjs) becomes the single rule; then the
|
|
18
|
+
* repo test runs that check over Core's and the CLI's own docs with this
|
|
19
|
+
* allowlist.
|
|
20
|
+
*
|
|
21
|
+
* @input nothing
|
|
22
|
+
* @output the allowlist
|
|
23
|
+
* @position packages/cli/foundation/discovery — data shared by the repo test
|
|
24
|
+
* and the Doctor runner check
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export const RUNNER_COMMAND_ALLOWLIST = Object.freeze({
|
|
28
|
+
/** Files never scanned: release notes, tests, and the helpers that build runner forms. */
|
|
29
|
+
skip: Object.freeze([
|
|
30
|
+
/(^|\/)CHANGELOG\.md$/u,
|
|
31
|
+
/\.test\.[cm]?[jt]sx?$/u,
|
|
32
|
+
/(^|\/)__tests__\//u,
|
|
33
|
+
/^packages\/cli\/test\//u,
|
|
34
|
+
/^packages\/cli\/foundation\/env\/package-manager\.mjs$/u,
|
|
35
|
+
]),
|
|
36
|
+
/** Docs that show a runner on purpose, and why. */
|
|
37
|
+
runnerExamples: Object.freeze({
|
|
38
|
+
'packages/core/docs.mjs':
|
|
39
|
+
"Core's setup banner, for a project that has no CLI installed yet",
|
|
40
|
+
'packages/cli/assets/docs/tree/updates.doc.mjs':
|
|
41
|
+
"quotes the CLI's own update notice, which names the project's runner",
|
|
42
|
+
'packages/cli/assets/docs/tree/cli-command.doc.mjs':
|
|
43
|
+
'explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them',
|
|
44
|
+
'packages/cli/assets/docs/tree/who-answers.doc.mjs':
|
|
45
|
+
'explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them',
|
|
46
|
+
'packages/cli/assets/docs/tree/project-global-or-both.doc.mjs':
|
|
47
|
+
'compares running the CLI with npx to installing it, and is found by searching for that command',
|
|
48
|
+
'packages/cli/assets/docs/tree/install-once.doc.mjs':
|
|
49
|
+
'names a pinned release, `npx @astryxdesign/cli@<version>`, which answers as that version',
|
|
50
|
+
'packages/cli/clients/cli/commands/upgrade.doc.mjs':
|
|
51
|
+
'quotes the command upgrade prints when the CLI is older than Core, pinned to the matching release',
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The strings of a doc the CLI resolves links in (spec:AST-047 FR9). In a
|
|
6
|
+
* topic: its description and summary, then the text of prose and heading
|
|
7
|
+
* blocks, list items, and table cells in each section's content, with the
|
|
8
|
+
* section's title. In a component doc (any doc with no sections): every text
|
|
9
|
+
* field, such as its description, usage, best practices, and each prop's and
|
|
10
|
+
* example's description, with the field's path. Code is never read.
|
|
11
|
+
*
|
|
12
|
+
* @param {unknown} doc an authored doc object
|
|
13
|
+
* @returns {{text: string, section: string | null, field: string | null}[]}
|
|
14
|
+
*/
|
|
15
|
+
export function linkableStrings(doc: unknown): {
|
|
16
|
+
text: string;
|
|
17
|
+
section: string | null;
|
|
18
|
+
field: string | null;
|
|
19
|
+
}[];
|
|
20
|
+
/**
|
|
21
|
+
* Every pointer span in one prose string, in order.
|
|
22
|
+
* @param {string} text
|
|
23
|
+
* @returns {string[]} the doc name each one points at
|
|
24
|
+
*/
|
|
25
|
+
export function pointersIn(text: string): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Each stray pointer in a package's topics and component docs.
|
|
28
|
+
*
|
|
29
|
+
* @param {{records: {name: string, path: string}[], guides?: {name: string, ref?: {topicFile?: string}}[], namespaces?: {doc?: {name?: string}}[], components?: {name: string, file: string}[]}} discovered
|
|
30
|
+
* @returns {Promise<import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]>}
|
|
31
|
+
*/
|
|
32
|
+
export function findStrayPointers(discovered: {
|
|
33
|
+
records: {
|
|
34
|
+
name: string;
|
|
35
|
+
path: string;
|
|
36
|
+
}[];
|
|
37
|
+
guides?: {
|
|
38
|
+
name: string;
|
|
39
|
+
ref?: {
|
|
40
|
+
topicFile?: string;
|
|
41
|
+
};
|
|
42
|
+
}[];
|
|
43
|
+
namespaces?: {
|
|
44
|
+
doc?: {
|
|
45
|
+
name?: string;
|
|
46
|
+
};
|
|
47
|
+
}[];
|
|
48
|
+
components?: {
|
|
49
|
+
name: string;
|
|
50
|
+
file: string;
|
|
51
|
+
}[];
|
|
52
|
+
}): Promise<import("../../api/integration/authoring-checks.type.mjs").StrayPointer[]>;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Stray doc pointers (architecture:cli-surface DEC-8): a code span in
|
|
5
|
+
* prose that is exactly `astryx docs <name>` for a doc that exists. The doc's
|
|
6
|
+
* `{@link}` prints the command that opens the doc and is checked by doctor's
|
|
7
|
+
* link check, so a written command is a pointer nothing checks.
|
|
8
|
+
*
|
|
9
|
+
* @input the docs a package ships, as discoverIntegrationDocs returns them
|
|
10
|
+
* @output each stray pointer, with the link that replaces it
|
|
11
|
+
* @position foundation/discovery, called through api/integration/_adapter.mjs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
|
|
16
|
+
import {textFields} from '../doc-compiler/links.mjs';
|
|
17
|
+
import {builtinGuideFiles} from './docs-discovery.mjs';
|
|
18
|
+
import {
|
|
19
|
+
fileWords,
|
|
20
|
+
lineAtOffset,
|
|
21
|
+
loadQuietly,
|
|
22
|
+
locateWords,
|
|
23
|
+
textWords,
|
|
24
|
+
} from './copied-passages.mjs';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A code span that is exactly the command opening one doc. A command with
|
|
28
|
+
* more words, a flag, or a route is a walkthrough, not a pointer. A name holds
|
|
29
|
+
* what a topic name may (letters, digits, `_` and `-`), never opening with `-`.
|
|
30
|
+
*/
|
|
31
|
+
const POINTER = /`astryx docs ([A-Za-z0-9_][A-Za-z0-9_-]*)`/g;
|
|
32
|
+
|
|
33
|
+
/** @type {Promise<Map<string, string>> | undefined} */
|
|
34
|
+
let coreKinds;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The CLI's own docs by name, each with the kind a link names it by: a
|
|
38
|
+
* namespace doc as `namespace`, a topic or guide as `generic`.
|
|
39
|
+
* @returns {Promise<Map<string, string>>}
|
|
40
|
+
*/
|
|
41
|
+
function loadCoreKinds() {
|
|
42
|
+
coreKinds ??= (async () => {
|
|
43
|
+
const kinds = new Map();
|
|
44
|
+
for (const file of builtinGuideFiles()) {
|
|
45
|
+
const doc = await loadQuietly(file);
|
|
46
|
+
if (typeof doc?.name === 'string') {
|
|
47
|
+
kinds.set(doc.name, doc.type === 'namespace' ? 'namespace' : 'generic');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return kinds;
|
|
51
|
+
})();
|
|
52
|
+
return coreKinds;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The strings of a doc the CLI resolves links in (spec:AST-047 FR9). In a
|
|
57
|
+
* topic: its description and summary, then the text of prose and heading
|
|
58
|
+
* blocks, list items, and table cells in each section's content, with the
|
|
59
|
+
* section's title. In a component doc (any doc with no sections): every text
|
|
60
|
+
* field, such as its description, usage, best practices, and each prop's and
|
|
61
|
+
* example's description, with the field's path. Code is never read.
|
|
62
|
+
*
|
|
63
|
+
* @param {unknown} doc an authored doc object
|
|
64
|
+
* @returns {{text: string, section: string | null, field: string | null}[]}
|
|
65
|
+
*/
|
|
66
|
+
export function linkableStrings(doc) {
|
|
67
|
+
/** @type {{text: string, section: string | null, field: string | null}[]} */
|
|
68
|
+
const strings = [];
|
|
69
|
+
if (doc == null || typeof doc !== 'object') return strings;
|
|
70
|
+
const top = /** @type {Record<string, any>} */ (doc);
|
|
71
|
+
if (!Array.isArray(top.sections)) {
|
|
72
|
+
for (const {field, text} of textFields(doc)) {
|
|
73
|
+
strings.push({text, section: null, field});
|
|
74
|
+
}
|
|
75
|
+
return strings;
|
|
76
|
+
}
|
|
77
|
+
for (const field of ['description', 'summary']) {
|
|
78
|
+
if (typeof top[field] === 'string') {
|
|
79
|
+
strings.push({text: top[field], section: null, field});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @param {unknown} value
|
|
84
|
+
* @param {string | null} section
|
|
85
|
+
*/
|
|
86
|
+
const walk = (value, section) => {
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
for (const item of value) walk(item, section);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (value == null || typeof value !== 'object') return;
|
|
92
|
+
const record = /** @type {Record<string, any>} */ (value);
|
|
93
|
+
const title = typeof record.title === 'string' ? record.title : section;
|
|
94
|
+
if (Array.isArray(record.sections)) walk(record.sections, section);
|
|
95
|
+
if (!Array.isArray(record.content)) return;
|
|
96
|
+
for (const block of record.content) {
|
|
97
|
+
const add = (/** @type {unknown} */ text) => {
|
|
98
|
+
if (typeof text === 'string') {
|
|
99
|
+
strings.push({text, section: title, field: null});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
switch (block?.type) {
|
|
103
|
+
case 'prose':
|
|
104
|
+
case 'heading':
|
|
105
|
+
add(block.text);
|
|
106
|
+
break;
|
|
107
|
+
case 'list':
|
|
108
|
+
(block.items ?? []).forEach(add);
|
|
109
|
+
break;
|
|
110
|
+
case 'table':
|
|
111
|
+
(block.headers ?? []).forEach(add);
|
|
112
|
+
for (const row of block.rows ?? []) row.forEach(add);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
walk(block, title);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
walk(doc, null);
|
|
120
|
+
return strings;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Every pointer span in one prose string, in order.
|
|
125
|
+
* @param {string} text
|
|
126
|
+
* @returns {string[]} the doc name each one points at
|
|
127
|
+
*/
|
|
128
|
+
export function pointersIn(text) {
|
|
129
|
+
return [...text.matchAll(POINTER)].map(match => match[1]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Where a string's words start among a file's words, from `from` on. A
|
|
134
|
+
* one-line string the file holds as a quoted literal is found at that
|
|
135
|
+
* literal, so a list item that is only `astryx docs theme` is not placed at a
|
|
136
|
+
* summary or code block that writes the same words.
|
|
137
|
+
*
|
|
138
|
+
* @param {string[]} lines the file's lines
|
|
139
|
+
* @param {{word: string, line: number}[]} file the file's words
|
|
140
|
+
* @param {string} text
|
|
141
|
+
* @param {{word: string}[]} words the string's words
|
|
142
|
+
* @param {number} from
|
|
143
|
+
* @returns {number}
|
|
144
|
+
*/
|
|
145
|
+
function locateString(lines, file, text, words, from) {
|
|
146
|
+
/** @type {number[]} */
|
|
147
|
+
const starts = [];
|
|
148
|
+
for (let at = locateWords(file, words); at >= 0;) {
|
|
149
|
+
starts.push(at);
|
|
150
|
+
at = locateWords(file, words, at + 1);
|
|
151
|
+
}
|
|
152
|
+
if (starts.length === 0) return -1;
|
|
153
|
+
const literals = text.includes('\n')
|
|
154
|
+
? []
|
|
155
|
+
: [`'${text}'`, `"${text}"`, `'${text.replace(/'/g, "\\'")}'`];
|
|
156
|
+
const quoted = starts.filter(at =>
|
|
157
|
+
literals.some(literal => lines[file[at].line - 1]?.includes(literal)),
|
|
158
|
+
);
|
|
159
|
+
const pool = quoted.length > 0 ? quoted : starts;
|
|
160
|
+
return pool.find(at => at >= from) ?? pool[0];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Each stray pointer in a package's topics and component docs.
|
|
165
|
+
*
|
|
166
|
+
* @param {{records: {name: string, path: string}[], guides?: {name: string, ref?: {topicFile?: string}}[], namespaces?: {doc?: {name?: string}}[], components?: {name: string, file: string}[]}} discovered
|
|
167
|
+
* @returns {Promise<import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]>}
|
|
168
|
+
*/
|
|
169
|
+
export async function findStrayPointers(discovered) {
|
|
170
|
+
/** @type {{name: string, file: string | undefined, kind: 'topic' | 'component'}[]} */
|
|
171
|
+
const topics = [
|
|
172
|
+
...discovered.records.map(record => ({
|
|
173
|
+
name: record.name,
|
|
174
|
+
file: record.path,
|
|
175
|
+
kind: /** @type {const} */ ('topic'),
|
|
176
|
+
})),
|
|
177
|
+
...(discovered.guides ?? []).map(guide => ({
|
|
178
|
+
name: guide.name,
|
|
179
|
+
file: guide.ref?.topicFile,
|
|
180
|
+
kind: /** @type {const} */ ('topic'),
|
|
181
|
+
})),
|
|
182
|
+
];
|
|
183
|
+
/** @type {Map<string, string>} */
|
|
184
|
+
const own = new Map(topics.map(topic => [topic.name, 'generic']));
|
|
185
|
+
for (const namespace of discovered.namespaces ?? []) {
|
|
186
|
+
const name = namespace?.doc?.name;
|
|
187
|
+
if (typeof name === 'string' && !own.has(name)) own.set(name, 'namespace');
|
|
188
|
+
}
|
|
189
|
+
for (const component of discovered.components ?? []) {
|
|
190
|
+
topics.push({
|
|
191
|
+
name: component.name,
|
|
192
|
+
file: component.file,
|
|
193
|
+
kind: 'component',
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const core = await loadCoreKinds();
|
|
197
|
+
// A topic that extends another has no route of its own: a link to it names
|
|
198
|
+
// the page it shows on, the topic it extends.
|
|
199
|
+
/** @type {Map<string, string>} */
|
|
200
|
+
const extendsOf = new Map();
|
|
201
|
+
for (const topic of topics) {
|
|
202
|
+
if (!topic.file) continue;
|
|
203
|
+
const doc = /** @type {any} */ (await loadQuietly(topic.file));
|
|
204
|
+
if (typeof doc?.extends === 'string')
|
|
205
|
+
extendsOf.set(topic.name, doc.extends);
|
|
206
|
+
}
|
|
207
|
+
/** @param {string} target */
|
|
208
|
+
const linkFor = target => {
|
|
209
|
+
const page = extendsOf.get(target);
|
|
210
|
+
if (page != null) {
|
|
211
|
+
if (own.has(page) && !extendsOf.has(page)) {
|
|
212
|
+
return `{@link ${own.get(page)}:${page}}`;
|
|
213
|
+
}
|
|
214
|
+
return core.has(page)
|
|
215
|
+
? `{@link @astryxdesign/cli:${core.get(page)}:${page}}`
|
|
216
|
+
: null;
|
|
217
|
+
}
|
|
218
|
+
return own.has(target)
|
|
219
|
+
? `{@link ${own.get(target)}:${target}}`
|
|
220
|
+
: core.has(target)
|
|
221
|
+
? `{@link @astryxdesign/cli:${core.get(target)}:${target}}`
|
|
222
|
+
: null;
|
|
223
|
+
};
|
|
224
|
+
/** @type {import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]} */
|
|
225
|
+
const found = [];
|
|
226
|
+
for (const topic of topics) {
|
|
227
|
+
if (!topic.file) continue;
|
|
228
|
+
const doc = await loadQuietly(topic.file);
|
|
229
|
+
if (!doc) continue;
|
|
230
|
+
/** @type {{word: string, line: number}[]} */
|
|
231
|
+
let source = [];
|
|
232
|
+
/** @type {string[]} */
|
|
233
|
+
let lines = [];
|
|
234
|
+
try {
|
|
235
|
+
const raw = fs.readFileSync(topic.file, 'utf8');
|
|
236
|
+
source = fileWords(raw);
|
|
237
|
+
lines = raw.split('\n');
|
|
238
|
+
} catch {
|
|
239
|
+
// No line numbers; the finding still names the section.
|
|
240
|
+
}
|
|
241
|
+
// A component doc is named by its own name: a family doc by the family.
|
|
242
|
+
const name =
|
|
243
|
+
topic.kind === 'component' && typeof doc.name === 'string'
|
|
244
|
+
? doc.name
|
|
245
|
+
: topic.name;
|
|
246
|
+
const label =
|
|
247
|
+
topic.kind === 'component' ? `component "${name}"` : `"${name}"`;
|
|
248
|
+
// Each string is found by its whole run of words, from where the last
|
|
249
|
+
// one was found, so two strings that open alike keep their own lines.
|
|
250
|
+
let cursor = 0;
|
|
251
|
+
for (const {text, section, field} of linkableStrings(doc)) {
|
|
252
|
+
const words = textWords(text);
|
|
253
|
+
const index = locateString(lines, source, text, words, cursor);
|
|
254
|
+
if (index >= 0) cursor = index + words.length;
|
|
255
|
+
for (const match of text.matchAll(POINTER)) {
|
|
256
|
+
const target = match[1];
|
|
257
|
+
const link = linkFor(target);
|
|
258
|
+
if (!link) continue;
|
|
259
|
+
const command = `astryx docs ${target}`;
|
|
260
|
+
const line =
|
|
261
|
+
index < 0
|
|
262
|
+
? null
|
|
263
|
+
: lineAtOffset(
|
|
264
|
+
source,
|
|
265
|
+
index,
|
|
266
|
+
words,
|
|
267
|
+
/** @type {number} */ (match.index) + 1,
|
|
268
|
+
);
|
|
269
|
+
const where = [
|
|
270
|
+
section ? `section "${section}"` : null,
|
|
271
|
+
field ? `field ${field}` : null,
|
|
272
|
+
line == null ? null : `line ${line}`,
|
|
273
|
+
]
|
|
274
|
+
.filter(Boolean)
|
|
275
|
+
.join(', ');
|
|
276
|
+
found.push({
|
|
277
|
+
topic: name,
|
|
278
|
+
kind: topic.kind,
|
|
279
|
+
section,
|
|
280
|
+
field,
|
|
281
|
+
file: topic.file,
|
|
282
|
+
line,
|
|
283
|
+
pointer: command,
|
|
284
|
+
link,
|
|
285
|
+
message:
|
|
286
|
+
`${label}${where ? ` (${where})` : ''} points at a doc with the written command \`${command}\`. ` +
|
|
287
|
+
`Replace \`${command}\`, code ticks included, with ${link}: the CLI prints the command that opens the doc, and doctor checks the link.`,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return found;
|
|
293
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
|
|
5
|
+
import {linkableStrings, pointersIn} from './stray-pointers.mjs';
|
|
6
|
+
|
|
7
|
+
describe('pointersIn', () => {
|
|
8
|
+
it('finds a code span that is exactly the command opening one doc', () => {
|
|
9
|
+
expect(
|
|
10
|
+
pointersIn(
|
|
11
|
+
'Read `astryx docs theme`, then `astryx docs layout-spacing`.',
|
|
12
|
+
),
|
|
13
|
+
).toEqual(['theme', 'layout-spacing']);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('leaves a walkthrough alone: more words, a flag, or a route', () => {
|
|
17
|
+
expect(
|
|
18
|
+
pointersIn(
|
|
19
|
+
'Run `astryx docs theme overview`, `astryx docs --json`, `astryx docs cli/integrations`, or `astryx docs`.',
|
|
20
|
+
),
|
|
21
|
+
).toEqual([]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('leaves the bare name and a runner-written command alone', () => {
|
|
25
|
+
expect(
|
|
26
|
+
pointersIn('See astryx docs theme, or `pnpm astryx docs theme`.'),
|
|
27
|
+
).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('linkableStrings', () => {
|
|
32
|
+
it("reads a topic's description and summary, then prose, headings, list items and table cells, not code", () => {
|
|
33
|
+
const strings = linkableStrings({
|
|
34
|
+
name: 'acme',
|
|
35
|
+
description: 'Read `astryx docs theme`.',
|
|
36
|
+
summary: 'In short.',
|
|
37
|
+
sections: [
|
|
38
|
+
{
|
|
39
|
+
title: 'Use it',
|
|
40
|
+
content: [
|
|
41
|
+
{type: 'prose', text: 'prose'},
|
|
42
|
+
{type: 'heading', level: 3, text: 'heading'},
|
|
43
|
+
{type: 'list', style: 'unordered', items: ['item']},
|
|
44
|
+
{type: 'table', headers: ['head'], rows: [['cell']]},
|
|
45
|
+
{type: 'code', lang: 'bash', code: 'astryx docs theme'},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
expect(strings).toEqual([
|
|
51
|
+
{text: 'Read `astryx docs theme`.', section: null, field: 'description'},
|
|
52
|
+
{text: 'In short.', section: null, field: 'summary'},
|
|
53
|
+
{text: 'prose', section: 'Use it', field: null},
|
|
54
|
+
{text: 'heading', section: 'Use it', field: null},
|
|
55
|
+
{text: 'item', section: 'Use it', field: null},
|
|
56
|
+
{text: 'head', section: 'Use it', field: null},
|
|
57
|
+
{text: 'cell', section: 'Use it', field: null},
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("reads a component doc's text fields, not its names, types, defaults, or code", () => {
|
|
62
|
+
const strings = linkableStrings({
|
|
63
|
+
type: 'component',
|
|
64
|
+
name: 'AcmeButton',
|
|
65
|
+
displayName: 'Acme Button',
|
|
66
|
+
usage: {
|
|
67
|
+
description: 'usage',
|
|
68
|
+
bestPractices: [{guidance: true, description: 'practice'}],
|
|
69
|
+
},
|
|
70
|
+
props: [
|
|
71
|
+
{name: 'tone', type: 'string', default: "'a'", description: 'prop'},
|
|
72
|
+
],
|
|
73
|
+
examples: [{label: 'example', code: 'astryx docs theme'}],
|
|
74
|
+
});
|
|
75
|
+
expect(strings).toEqual([
|
|
76
|
+
{text: 'usage', section: null, field: 'usage.description'},
|
|
77
|
+
{
|
|
78
|
+
text: 'practice',
|
|
79
|
+
section: null,
|
|
80
|
+
field: 'usage.bestPractices[0].description',
|
|
81
|
+
},
|
|
82
|
+
{text: 'prop', section: null, field: 'props[0].description'},
|
|
83
|
+
{text: 'example', section: null, field: 'examples[0].label'},
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* needs it: `Project` assembles templates from it. While this sat in api/, that
|
|
16
16
|
* made a cycle across the layer boundary — Project reached up for discovery and
|
|
17
17
|
* this module imported Project back. Nothing here depends on api/; every import
|
|
18
|
-
* is node:*, jiti, foundation/*, or authoring
|
|
18
|
+
* is node:*, jiti, foundation/*, or authoring/*, plus a lazily required
|
|
19
|
+
* @babel/parser for extractComponents' local-declaration scan.
|
|
19
20
|
*
|
|
20
21
|
* @position packages/cli/foundation/discovery — shared template discovery/IO;
|
|
21
22
|
* consumed by Project and by the api/template leaves.
|
|
@@ -512,6 +513,19 @@ function expressionUse(source, open, close) {
|
|
|
512
513
|
return null;
|
|
513
514
|
}
|
|
514
515
|
|
|
516
|
+
/** @type {typeof import('@babel/parser') | undefined} */
|
|
517
|
+
let babelParser;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* The template source parser, loaded on first use so listing templates
|
|
521
|
+
* never pays for it.
|
|
522
|
+
* @returns {typeof import('@babel/parser')}
|
|
523
|
+
*/
|
|
524
|
+
function templateSourceParser() {
|
|
525
|
+
babelParser ??= require('@babel/parser');
|
|
526
|
+
return /** @type {typeof import('@babel/parser')} */ (babelParser);
|
|
527
|
+
}
|
|
528
|
+
|
|
515
529
|
/**
|
|
516
530
|
* The [start, end) range of every comment in `source`, or none when it does
|
|
517
531
|
* not parse as TSX.
|
|
@@ -520,8 +534,7 @@ function expressionUse(source, open, close) {
|
|
|
520
534
|
*/
|
|
521
535
|
function commentRanges(source) {
|
|
522
536
|
try {
|
|
523
|
-
const {
|
|
524
|
-
const {comments} = parse(source, {
|
|
537
|
+
const {comments} = templateSourceParser().parse(source, {
|
|
525
538
|
sourceType: 'module',
|
|
526
539
|
plugins: ['jsx', 'typescript'],
|
|
527
540
|
});
|
|
@@ -1267,7 +1280,8 @@ export async function discoverIntegrationTemplatesForOne(integration) {
|
|
|
1267
1280
|
template: id,
|
|
1268
1281
|
message: `Template "${id}" is missing a "type" of "page" or "block". Stamp the default export with type: 'page' or type: 'block'.`,
|
|
1269
1282
|
});
|
|
1270
|
-
const declared =
|
|
1283
|
+
const declared =
|
|
1284
|
+
doc?.replaces ?? (await declaredReplacement(docPath, id));
|
|
1271
1285
|
if (declared != null) {
|
|
1272
1286
|
errors.push({
|
|
1273
1287
|
code: 'invalid_template_replacement',
|
|
@@ -1423,6 +1437,51 @@ const UBIQUITOUS = new Set([
|
|
|
1423
1437
|
'Icon',
|
|
1424
1438
|
]);
|
|
1425
1439
|
|
|
1440
|
+
/**
|
|
1441
|
+
* Names bound by top-level `function`, `class`, `const`, `let` or `var`
|
|
1442
|
+
* declarations (exported or not). Returns an empty set when the source does
|
|
1443
|
+
* not parse, so a parse failure never drops a real component.
|
|
1444
|
+
*
|
|
1445
|
+
* @param {string} src
|
|
1446
|
+
* @returns {Set<string>}
|
|
1447
|
+
*/
|
|
1448
|
+
function topLevelBindingNames(src) {
|
|
1449
|
+
/** @type {Set<string>} */
|
|
1450
|
+
const names = new Set();
|
|
1451
|
+
let program;
|
|
1452
|
+
try {
|
|
1453
|
+
program = templateSourceParser().parse(src, {
|
|
1454
|
+
sourceType: 'module',
|
|
1455
|
+
plugins: ['jsx', 'typescript'],
|
|
1456
|
+
errorRecovery: true,
|
|
1457
|
+
}).program;
|
|
1458
|
+
} catch {
|
|
1459
|
+
return names;
|
|
1460
|
+
}
|
|
1461
|
+
for (const statement of program.body) {
|
|
1462
|
+
const node =
|
|
1463
|
+
statement.type === 'ExportNamedDeclaration' ||
|
|
1464
|
+
statement.type === 'ExportDefaultDeclaration'
|
|
1465
|
+
? statement.declaration
|
|
1466
|
+
: statement;
|
|
1467
|
+
if (node == null) continue;
|
|
1468
|
+
if (
|
|
1469
|
+
(node.type === 'FunctionDeclaration' ||
|
|
1470
|
+
node.type === 'ClassDeclaration') &&
|
|
1471
|
+
node.id
|
|
1472
|
+
) {
|
|
1473
|
+
names.add(node.id.name);
|
|
1474
|
+
} else if (node.type === 'VariableDeclaration') {
|
|
1475
|
+
for (const declarator of node.declarations) {
|
|
1476
|
+
if (declarator.id.type === 'Identifier') {
|
|
1477
|
+
names.add(declarator.id.name);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return names;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1426
1485
|
/**
|
|
1427
1486
|
* @param {string} pagePath
|
|
1428
1487
|
* @returns {string[]}
|
|
@@ -1449,14 +1508,24 @@ export function extractComponents(pagePath) {
|
|
|
1449
1508
|
while ((m = tagRegex.exec(src)) !== null) {
|
|
1450
1509
|
matches.push(m[2]);
|
|
1451
1510
|
}
|
|
1511
|
+
|
|
1512
|
+
// Exclude names bound by a top-level declaration in the same file: those are
|
|
1513
|
+
// page-local helpers (e.g. `function TimelineSection()`), not components a
|
|
1514
|
+
// builder can import. Read real bindings from the syntax tree so comments,
|
|
1515
|
+
// strings and type annotations cannot add or hide a name.
|
|
1516
|
+
const localDeclNames = topLevelBindingNames(src);
|
|
1517
|
+
|
|
1452
1518
|
return [
|
|
1453
1519
|
...new Set(
|
|
1454
1520
|
matches
|
|
1521
|
+
.filter(n => !localDeclNames.has(n))
|
|
1455
1522
|
.filter(n => !['Theme', 'ThemeProvider'].includes(n))
|
|
1456
1523
|
.filter(n => !UBIQUITOUS.has(n))
|
|
1457
1524
|
.map(n =>
|
|
1458
1525
|
n.replace(
|
|
1459
|
-
|
|
1526
|
+
// Strip only when a stem remains, so a bare `<Section>` keeps its
|
|
1527
|
+
// own name instead of emptying out.
|
|
1528
|
+
/(?<=.)(Item|Section|Header|Content|Footer|Panel|Heading|CollapseButton|Column|Sortable|Selection|Group|Source)$/,
|
|
1460
1529
|
'',
|
|
1461
1530
|
),
|
|
1462
1531
|
)
|
|
@@ -20,7 +20,10 @@ import * as path from 'node:path';
|
|
|
20
20
|
import module from 'node:module';
|
|
21
21
|
import {CLI_ROOT} from '../fs/paths.mjs';
|
|
22
22
|
import {detectStylingSystem} from '../agent-docs/agent-docs.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
decidePackageManagerIn,
|
|
25
|
+
formatCliCommand,
|
|
26
|
+
} from '../env/package-manager.mjs';
|
|
24
27
|
|
|
25
28
|
// ── Known packages that a template may import without the user installing them.
|
|
26
29
|
// react and react-dom are the framework; @astryxdesign/* is the design system
|
|
@@ -230,7 +233,7 @@ export function analyzeTemplateNeeds(source, cwd) {
|
|
|
230
233
|
}
|
|
231
234
|
if (stylexCompilerNeeded) {
|
|
232
235
|
notes.push(
|
|
233
|
-
|
|
236
|
+
`This template uses StyleX. Your project needs a StyleX compiler plugin \u2014 see \`${formatCliCommand('docs styling-overview')}\` for setup steps.`,
|
|
234
237
|
);
|
|
235
238
|
}
|
|
236
239
|
|