@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,328 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fluff in docs: padding phrases that add words and no meaning, and guides
|
|
5
|
+
* whose prose is mostly function words. Docs are read by people and agents
|
|
6
|
+
* with a budget, so every word should carry something.
|
|
7
|
+
*
|
|
8
|
+
* Only prose is read (the same strings copied passages compare), and inline
|
|
9
|
+
* code and quoted text are set aside, so a phrase inside a command, or one
|
|
10
|
+
* quoted as an example, never counts.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
|
|
15
|
+
import {builtinGuideFiles} from './docs-discovery.mjs';
|
|
16
|
+
import {
|
|
17
|
+
contentWords,
|
|
18
|
+
fileWords,
|
|
19
|
+
lineAtOffset,
|
|
20
|
+
locateWords,
|
|
21
|
+
loadQuietly,
|
|
22
|
+
proseStrings,
|
|
23
|
+
passageWords,
|
|
24
|
+
textWords,
|
|
25
|
+
} from './copied-passages.mjs';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Padding phrases: each can be cut, or replaced by a shorter word, without
|
|
29
|
+
* losing meaning. Only phrases that are padding in every use are listed;
|
|
30
|
+
* words such as "just", "simply" or "really", and phrases such as "whether or
|
|
31
|
+
* not" or "keep in mind", which carry meaning in a correct sentence ("not
|
|
32
|
+
* simply a wrapper", "regardless of whether"), are not.
|
|
33
|
+
*/
|
|
34
|
+
export const FILLER_PHRASES = [
|
|
35
|
+
"it's important to note",
|
|
36
|
+
'it is important to note',
|
|
37
|
+
'important to note that',
|
|
38
|
+
"it's worth noting",
|
|
39
|
+
'it is worth noting',
|
|
40
|
+
'worth noting that',
|
|
41
|
+
'it should be noted',
|
|
42
|
+
'please note',
|
|
43
|
+
'note that',
|
|
44
|
+
'as mentioned above',
|
|
45
|
+
'as mentioned earlier',
|
|
46
|
+
'as mentioned before',
|
|
47
|
+
'as noted above',
|
|
48
|
+
'as you can see',
|
|
49
|
+
'needless to say',
|
|
50
|
+
'in order to',
|
|
51
|
+
'due to the fact that',
|
|
52
|
+
'for the purpose of',
|
|
53
|
+
'at this point in time',
|
|
54
|
+
'in other words',
|
|
55
|
+
'basically',
|
|
56
|
+
'essentially',
|
|
57
|
+
'obviously',
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
/** What to write instead, where a phrase is not simply cut. */
|
|
61
|
+
const INSTEAD = {
|
|
62
|
+
'in order to': 'to',
|
|
63
|
+
'due to the fact that': 'because',
|
|
64
|
+
'for the purpose of': 'to or for',
|
|
65
|
+
'at this point in time': 'now',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** A guide shorter than this many prose words is not scored for density. */
|
|
69
|
+
export const DENSITY_MIN_WORDS = 80;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A guide whose share of content words is below this is mostly glue. Core's
|
|
73
|
+
* own guides score from about 0.51 up, with a median near 0.62.
|
|
74
|
+
*/
|
|
75
|
+
export const MIN_DENSITY = 0.5;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} phrase
|
|
79
|
+
* @returns {RegExp}
|
|
80
|
+
*/
|
|
81
|
+
function phrasePattern(phrase) {
|
|
82
|
+
const escaped = phrase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
83
|
+
// "note that" is padding as a sentence opener ("Note that X"), not inside
|
|
84
|
+
// one ("a note that explains").
|
|
85
|
+
return phrase === 'note that'
|
|
86
|
+
? new RegExp(`(?:^|[.;:!?]\\s+)${escaped}\\b`, 'gi')
|
|
87
|
+
: // A hyphen joins words ("non-obviously"), so it bounds no phrase.
|
|
88
|
+
new RegExp(`(?<![a-z'-])${escaped}(?![a-z-])`, 'gi');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const PATTERNS = FILLER_PHRASES.map(phrase => ({
|
|
92
|
+
phrase,
|
|
93
|
+
pattern: phrasePattern(phrase),
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A prose string with what is not prose blanked out, length kept: `{@link}`
|
|
98
|
+
* pointers, inline code, and quoted text. A quoted phrase is mentioned, not
|
|
99
|
+
* used ("cut 'in order to'").
|
|
100
|
+
*
|
|
101
|
+
* @param {string} text
|
|
102
|
+
* @returns {string}
|
|
103
|
+
*/
|
|
104
|
+
export function maskProse(text) {
|
|
105
|
+
// A quoted phrase is mentioned, not used ("cut 'in order to'"), so quotes
|
|
106
|
+
// are set aside along with inline code. Each mask keeps the text's length,
|
|
107
|
+
// so an offset in the masked text is an offset in the text.
|
|
108
|
+
const blank = (/** @type {string} */ span) => ' '.repeat(span.length);
|
|
109
|
+
return (
|
|
110
|
+
text
|
|
111
|
+
// A pointer names a doc, and its target is no prose ("{@link
|
|
112
|
+
// generic:obviously-fast}").
|
|
113
|
+
.replace(/\{@link\s[^}]*\}/g, blank)
|
|
114
|
+
.replace(/`[^`]*`/g, blank)
|
|
115
|
+
.replace(/"[^"]*"|“[^”]*”|‘[^’]*’/g, blank)
|
|
116
|
+
.replace(/’/g, "'")
|
|
117
|
+
// A single-quoted span opens and closes beside a non-letter, so the
|
|
118
|
+
// apostrophe in "don't" or "it's" opens nothing.
|
|
119
|
+
.replace(/(?<![A-Za-z])'[^']*'(?![A-Za-z])/g, blank)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Each padding phrase in a text, outside inline code and quotes, in order,
|
|
125
|
+
* with its offset in the text.
|
|
126
|
+
*
|
|
127
|
+
* `thatAfter` is true when the phrase is followed by a "that" a reader cuts
|
|
128
|
+
* with it ("It is worth noting that the cache is shared").
|
|
129
|
+
*
|
|
130
|
+
* @param {string} text
|
|
131
|
+
* @returns {{phrase: string, at: number, thatAfter: boolean}[]}
|
|
132
|
+
*/
|
|
133
|
+
export function fillerAt(text) {
|
|
134
|
+
const prose = maskProse(text);
|
|
135
|
+
/** @type {{phrase: string, at: number, thatAfter: boolean}[]} */
|
|
136
|
+
const found = [];
|
|
137
|
+
for (const {phrase, pattern} of PATTERNS) {
|
|
138
|
+
for (const match of prose.matchAll(pattern)) {
|
|
139
|
+
// A phrase inside a longer listed one ("note that" in "worth noting
|
|
140
|
+
// that") is the longer one's.
|
|
141
|
+
const at = match.index + match[0].toLowerCase().indexOf(phrase);
|
|
142
|
+
if (
|
|
143
|
+
!found.some(each => at >= each.at && at < each.at + each.phrase.length)
|
|
144
|
+
) {
|
|
145
|
+
found.push({
|
|
146
|
+
phrase,
|
|
147
|
+
at,
|
|
148
|
+
// Only a phrase that ends in note or noting leads into a "that"
|
|
149
|
+
// clause the reader cuts with it; "Obviously that works" and "As
|
|
150
|
+
// noted above that flag" keep their "that".
|
|
151
|
+
thatAfter:
|
|
152
|
+
/\bnot(?:e|ed|ing)$/.test(phrase) &&
|
|
153
|
+
!phrase.endsWith('that') &&
|
|
154
|
+
/^\s+that\b/i.test(prose.slice(at + phrase.length)),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return found.sort((a, b) => a.at - b.at);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Each padding phrase in a text, outside inline code and quotes, in order.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} text
|
|
166
|
+
* @returns {string[]}
|
|
167
|
+
*/
|
|
168
|
+
export function fillerIn(text) {
|
|
169
|
+
return fillerAt(text).map(each => each.phrase);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The share of a doc's prose words that are content words.
|
|
174
|
+
*
|
|
175
|
+
* @param {{word: string}[]} words
|
|
176
|
+
* @returns {number}
|
|
177
|
+
*/
|
|
178
|
+
export function density(words) {
|
|
179
|
+
if (words.length === 0) return 1;
|
|
180
|
+
let content = 0;
|
|
181
|
+
for (let i = 0; i < words.length; i++) {
|
|
182
|
+
if (contentWords(words, i, 1) === 1) content++;
|
|
183
|
+
}
|
|
184
|
+
return content / words.length;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* A number rounded down to `places` decimals, so a share under the floor
|
|
189
|
+
* never reads as the floor.
|
|
190
|
+
*
|
|
191
|
+
* @param {number} value
|
|
192
|
+
* @param {number} places
|
|
193
|
+
* @returns {number}
|
|
194
|
+
*/
|
|
195
|
+
export function floorTo(value, places) {
|
|
196
|
+
const scale = 10 ** places;
|
|
197
|
+
return Math.floor(value * scale + 1e-9) / scale;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* A share as a percent with one decimal, rounded down ("49.5%").
|
|
202
|
+
*
|
|
203
|
+
* @param {number} share
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
export function sharePercent(share) {
|
|
207
|
+
return `${floorTo(share * 100, 1).toFixed(1)}%`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The words a topic's density is measured on: its prose, without what the
|
|
212
|
+
* phrase check also leaves unread (links, inline code, quoted text).
|
|
213
|
+
*
|
|
214
|
+
* @param {unknown} doc
|
|
215
|
+
* @returns {{word: string}[]}
|
|
216
|
+
*/
|
|
217
|
+
export function densityWords(doc) {
|
|
218
|
+
return proseStrings(doc).flatMap(({text}) =>
|
|
219
|
+
passageWords(maskProse(text)).map(word => ({word})),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The median density of Core's own guides of at least
|
|
225
|
+
* {@link DENSITY_MIN_WORDS} words.
|
|
226
|
+
*
|
|
227
|
+
* @returns {Promise<number>}
|
|
228
|
+
*/
|
|
229
|
+
export async function coreDensityMedian() {
|
|
230
|
+
// Core's guides are measured the way a package's topics are.
|
|
231
|
+
/** @type {number[]} */
|
|
232
|
+
const scores = [];
|
|
233
|
+
for (const file of builtinGuideFiles()) {
|
|
234
|
+
const doc = await loadQuietly(file);
|
|
235
|
+
if (typeof doc?.name !== 'string') continue;
|
|
236
|
+
const words = densityWords(doc);
|
|
237
|
+
if (words.length >= DENSITY_MIN_WORDS) scores.push(density(words));
|
|
238
|
+
}
|
|
239
|
+
scores.sort((a, b) => a - b);
|
|
240
|
+
return scores.length === 0 ? 0 : scores[Math.floor(scores.length / 2)];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Fluff in a package's topics: every padding phrase, with its section and
|
|
245
|
+
* file line, and every topic of at least {@link DENSITY_MIN_WORDS} words
|
|
246
|
+
* whose density is below {@link MIN_DENSITY}.
|
|
247
|
+
*
|
|
248
|
+
* @param {{records: {name: string, path: string}[], guides?: {name: string, ref?: {topicFile?: string}}[]}} discovered
|
|
249
|
+
* the package's docs, as discoverIntegrationDocs returns them
|
|
250
|
+
* @returns {Promise<import('../../api/integration/authoring-checks.type.mjs').DocFluff[]>}
|
|
251
|
+
*/
|
|
252
|
+
export async function findFluff(discovered) {
|
|
253
|
+
const topics = [
|
|
254
|
+
...discovered.records.map(record => ({
|
|
255
|
+
name: record.name,
|
|
256
|
+
file: record.path,
|
|
257
|
+
})),
|
|
258
|
+
...(discovered.guides ?? []).map(guide => ({
|
|
259
|
+
name: guide.name,
|
|
260
|
+
file: guide.ref?.topicFile,
|
|
261
|
+
})),
|
|
262
|
+
];
|
|
263
|
+
/** @type {import('../../api/integration/authoring-checks.type.mjs').DocFluff[]} */
|
|
264
|
+
const found = [];
|
|
265
|
+
/** @type {number | null} */
|
|
266
|
+
let median = null;
|
|
267
|
+
for (const {name, file} of topics) {
|
|
268
|
+
const doc = file ? await loadQuietly(file) : null;
|
|
269
|
+
if (!doc || !file) continue;
|
|
270
|
+
/** @type {{word: string, line: number}[]} */
|
|
271
|
+
let source = [];
|
|
272
|
+
try {
|
|
273
|
+
source = fileWords(fs.readFileSync(file, 'utf8'));
|
|
274
|
+
} catch {
|
|
275
|
+
// No line numbers; each finding still names its section.
|
|
276
|
+
}
|
|
277
|
+
// Each string is found by its whole run of words, from where the last
|
|
278
|
+
// one was found, so two strings that open alike keep their own lines.
|
|
279
|
+
let cursor = 0;
|
|
280
|
+
for (const {text, section} of proseStrings(doc)) {
|
|
281
|
+
const words = textWords(text);
|
|
282
|
+
let index = locateWords(source, words, cursor);
|
|
283
|
+
if (index < 0) index = locateWords(source, words);
|
|
284
|
+
if (index >= 0) cursor = index + words.length;
|
|
285
|
+
for (const {phrase, at, thatAfter} of fillerAt(text)) {
|
|
286
|
+
const line = index < 0 ? null : lineAtOffset(source, index, words, at);
|
|
287
|
+
const where = section ? ` (section "${section}")` : '';
|
|
288
|
+
const instead = /** @type {Record<string, string>} */ (INSTEAD)[phrase];
|
|
289
|
+
found.push({
|
|
290
|
+
topic: name,
|
|
291
|
+
kind: 'phrase',
|
|
292
|
+
phrase,
|
|
293
|
+
section,
|
|
294
|
+
file,
|
|
295
|
+
line,
|
|
296
|
+
density: null,
|
|
297
|
+
message:
|
|
298
|
+
`"${name}"${where} pads its prose with "${phrase}"` +
|
|
299
|
+
`${line == null ? '' : ` (line ${line})`}. ` +
|
|
300
|
+
(instead
|
|
301
|
+
? `Write "${instead}" instead.`
|
|
302
|
+
: thatAfter
|
|
303
|
+
? 'Cut it and the "that" after it; the sentence says the same without them.'
|
|
304
|
+
: 'Cut it; the sentence says the same without it.'),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const words = densityWords(doc);
|
|
309
|
+
if (words.length < DENSITY_MIN_WORDS) continue;
|
|
310
|
+
const score = density(words);
|
|
311
|
+
if (score >= MIN_DENSITY) continue;
|
|
312
|
+
median ??= await coreDensityMedian();
|
|
313
|
+
found.push({
|
|
314
|
+
topic: name,
|
|
315
|
+
kind: 'density',
|
|
316
|
+
phrase: null,
|
|
317
|
+
section: null,
|
|
318
|
+
file,
|
|
319
|
+
line: null,
|
|
320
|
+
density: floorTo(score, 3),
|
|
321
|
+
message:
|
|
322
|
+
`"${name}" is mostly glue: ${sharePercent(score)} of its ${words.length} prose words carry content, ` +
|
|
323
|
+
`under the ${Math.round(MIN_DENSITY * 100)}% floor (Core's guides have a median of ${Math.round(median * 100)}%). ` +
|
|
324
|
+
'Cut filler and restated context until each sentence states one thing.',
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
return found;
|
|
328
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
density,
|
|
7
|
+
densityWords,
|
|
8
|
+
fillerAt,
|
|
9
|
+
fillerIn,
|
|
10
|
+
floorTo,
|
|
11
|
+
sharePercent,
|
|
12
|
+
} from './doc-fluff.mjs';
|
|
13
|
+
import {passageWords} from './copied-passages.mjs';
|
|
14
|
+
|
|
15
|
+
const words = (/** @type {string} */ text) =>
|
|
16
|
+
passageWords(text).map(word => ({word}));
|
|
17
|
+
|
|
18
|
+
describe('fillerIn', () => {
|
|
19
|
+
it('finds padding phrases in order, the longest one only', () => {
|
|
20
|
+
expect(
|
|
21
|
+
fillerIn(
|
|
22
|
+
'In order to start, it is worth noting that you basically run it. Note that it builds.',
|
|
23
|
+
),
|
|
24
|
+
).toEqual(['in order to', 'it is worth noting', 'basically', 'note that']);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('leaves inline code, quotes, a noun "note", and ambiguous words alone', () => {
|
|
28
|
+
expect(
|
|
29
|
+
fillerIn(
|
|
30
|
+
'Run `basically --in order to`. Cut "in order to" and “basically”. Add a note that explains it. Copy just this one file; it really is the source.',
|
|
31
|
+
),
|
|
32
|
+
).toEqual([]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('sets aside single-quoted text, but not an apostrophe', () => {
|
|
36
|
+
expect(
|
|
37
|
+
fillerIn(
|
|
38
|
+
"Avoid ‘basically’ and ‘obviously’. Don't write 'it is worth noting that' in a guide.",
|
|
39
|
+
),
|
|
40
|
+
).toEqual([]);
|
|
41
|
+
expect(fillerIn("Don't pad: it's important to note the order.")).toEqual([
|
|
42
|
+
"it's important to note",
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('lists no phrase that carries meaning in a correct sentence', () => {
|
|
47
|
+
expect(
|
|
48
|
+
fillerIn(
|
|
49
|
+
'It is not simply a wrapper. Every app gets a theme whether or not anyone picks one. Keep in mind the order. Feel free to skip it.',
|
|
50
|
+
),
|
|
51
|
+
).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('reads a curly apostrophe like a straight one', () => {
|
|
55
|
+
expect(fillerIn('It’s important to note the order.')).toEqual([
|
|
56
|
+
"it's important to note",
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('fillerAt', () => {
|
|
62
|
+
it('reads no phrase inside a link target or a hyphenated word', () => {
|
|
63
|
+
expect(
|
|
64
|
+
fillerIn(
|
|
65
|
+
'Read {@link generic:obviously-fast} before you tune the build.',
|
|
66
|
+
),
|
|
67
|
+
).toEqual([]);
|
|
68
|
+
expect(fillerIn('A non-obviously slow build still passes.')).toEqual([]);
|
|
69
|
+
expect(fillerIn('It is obviously slow.')).toEqual(['obviously']);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('marks a "that" the reader cuts with the phrase', () => {
|
|
73
|
+
expect(
|
|
74
|
+
fillerAt('It is worth noting that the cache is shared.').map(
|
|
75
|
+
each => each.thatAfter,
|
|
76
|
+
),
|
|
77
|
+
).toEqual([true]);
|
|
78
|
+
expect(
|
|
79
|
+
fillerAt('Basically, the cache is shared.').map(each => each.thatAfter),
|
|
80
|
+
).toEqual([false]);
|
|
81
|
+
// Only a note or noting phrase leads a clause the reader cuts.
|
|
82
|
+
expect(
|
|
83
|
+
fillerAt('Obviously that works only in a browser.').map(
|
|
84
|
+
each => each.thatAfter,
|
|
85
|
+
),
|
|
86
|
+
).toEqual([false]);
|
|
87
|
+
expect(
|
|
88
|
+
fillerAt('As noted above that flag is required.').map(
|
|
89
|
+
each => each.thatAfter,
|
|
90
|
+
),
|
|
91
|
+
).toEqual([false]);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('densityWords', () => {
|
|
96
|
+
it('measures prose only, not quoted text, inline code or links', () => {
|
|
97
|
+
const doc = {
|
|
98
|
+
sections: [
|
|
99
|
+
{
|
|
100
|
+
title: 'Overview',
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: 'prose',
|
|
104
|
+
text: 'Theme tokens set colors. Write "it is in the" or `of the` as {@link generic:theme} shows.',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
expect(densityWords(doc).map(each => each.word)).toEqual([
|
|
111
|
+
'theme',
|
|
112
|
+
'tokens',
|
|
113
|
+
'set',
|
|
114
|
+
'colors.',
|
|
115
|
+
'write',
|
|
116
|
+
'or',
|
|
117
|
+
'as',
|
|
118
|
+
'shows.',
|
|
119
|
+
]);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('share rounding', () => {
|
|
124
|
+
it('rounds a share under the floor down, never up to it', () => {
|
|
125
|
+
expect(floorTo(0.4995, 3)).toBe(0.499);
|
|
126
|
+
expect(sharePercent(0.4995)).toBe('49.9%');
|
|
127
|
+
expect(sharePercent(0.5)).toBe('50.0%');
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('density', () => {
|
|
132
|
+
it('scores a padded sentence well below a dense one', () => {
|
|
133
|
+
const padded = words(
|
|
134
|
+
'So that is why it is the one that you would want to use if you can.',
|
|
135
|
+
);
|
|
136
|
+
const dense = words(
|
|
137
|
+
'Name each codemod folder after the Core version whose upgrade runs it.',
|
|
138
|
+
);
|
|
139
|
+
expect(density(padded)).toBeLessThan(0.3);
|
|
140
|
+
expect(density(dense)).toBeGreaterThan(0.6);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
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
|
+
* Check each doc file's values against the published authoring types.
|
|
6
|
+
* @param {DocFile[]} files
|
|
7
|
+
* @param {{packageDir: string, resolveFrom: Array<string | null | undefined>, core?: boolean}} options
|
|
8
|
+
* `core`: the docs are Core's own, so templates are held to TemplateDoc
|
|
9
|
+
* @returns {Promise<DocTypesReport>}
|
|
10
|
+
*/
|
|
11
|
+
export function checkDocTypes(files: DocFile[], options: {
|
|
12
|
+
packageDir: string;
|
|
13
|
+
resolveFrom: Array<string | null | undefined>;
|
|
14
|
+
core?: boolean;
|
|
15
|
+
}): Promise<DocTypesReport>;
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {'components' | 'hooks' | 'templates' | 'docs' | 'docs-overlay' | 'themes'} DocRoot
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {object} DocFile
|
|
21
|
+
* @property {string} path absolute path to the doc file
|
|
22
|
+
* @property {DocRoot} root the contribution root it was found in
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {'unknown_field' | 'missing_field' | 'wrong_type'} DocTypeProblem
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {object} DocTypeFinding
|
|
29
|
+
* @property {string} doc the doc file, relative to the package root
|
|
30
|
+
* @property {number} line 1-based line of the field (or of the doc value)
|
|
31
|
+
* @property {string} export the export checked (`default`, `docs`, `docsZh`, …)
|
|
32
|
+
* @property {string} type the authoring type it was checked against
|
|
33
|
+
* @property {string} field the field's path in the doc, such as
|
|
34
|
+
* `usage.bestPractices[2].guidance`; empty for the doc value as a whole
|
|
35
|
+
* @property {DocTypeProblem} problem
|
|
36
|
+
* @property {'warning'} severity
|
|
37
|
+
* @property {string} message what TypeScript reports, shortened
|
|
38
|
+
* @property {string} fix what to change
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {object} DocTypesUnchecked
|
|
42
|
+
* @property {string} doc the doc file, relative to the package root
|
|
43
|
+
* @property {string} reason why it was not checked
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {object} DocTypesReport
|
|
47
|
+
* @property {'checked' | 'skipped'} status `skipped` means nothing was checked,
|
|
48
|
+
* and `reason` says why
|
|
49
|
+
* @property {string} [reason]
|
|
50
|
+
* @property {string} [typescript] the version of the compiler that checked
|
|
51
|
+
* @property {number} docs how many doc values were checked
|
|
52
|
+
* @property {DocTypeFinding[]} findings
|
|
53
|
+
* @property {DocTypesUnchecked[]} unchecked doc files with nothing to check,
|
|
54
|
+
* or not fully checked
|
|
55
|
+
*/
|
|
56
|
+
/** The line both surfaces print when the compiler is missing. */
|
|
57
|
+
export const DOC_TYPES_TYPESCRIPT_MISSING_REASON: "TypeScript is not installed in this project, so docs were not checked against the authoring types. On TypeScript 7, add its TypeScript 6 API package (`npm install -D @typescript/typescript6`); otherwise install TypeScript 5.0 through 6 (`npm install -D typescript@6`). Then run this check again.";
|
|
58
|
+
export type DocRoot = "components" | "hooks" | "templates" | "docs" | "docs-overlay" | "themes";
|
|
59
|
+
export type DocFile = {
|
|
60
|
+
/**
|
|
61
|
+
* absolute path to the doc file
|
|
62
|
+
*/
|
|
63
|
+
path: string;
|
|
64
|
+
/**
|
|
65
|
+
* the contribution root it was found in
|
|
66
|
+
*/
|
|
67
|
+
root: DocRoot;
|
|
68
|
+
};
|
|
69
|
+
export type DocTypeProblem = "unknown_field" | "missing_field" | "wrong_type";
|
|
70
|
+
export type DocTypeFinding = {
|
|
71
|
+
/**
|
|
72
|
+
* the doc file, relative to the package root
|
|
73
|
+
*/
|
|
74
|
+
doc: string;
|
|
75
|
+
/**
|
|
76
|
+
* 1-based line of the field (or of the doc value)
|
|
77
|
+
*/
|
|
78
|
+
line: number;
|
|
79
|
+
/**
|
|
80
|
+
* the export checked (`default`, `docs`, `docsZh`, …)
|
|
81
|
+
*/
|
|
82
|
+
export: string;
|
|
83
|
+
/**
|
|
84
|
+
* the authoring type it was checked against
|
|
85
|
+
*/
|
|
86
|
+
type: string;
|
|
87
|
+
/**
|
|
88
|
+
* the field's path in the doc, such as
|
|
89
|
+
* `usage.bestPractices[2].guidance`; empty for the doc value as a whole
|
|
90
|
+
*/
|
|
91
|
+
field: string;
|
|
92
|
+
problem: DocTypeProblem;
|
|
93
|
+
severity: "warning";
|
|
94
|
+
/**
|
|
95
|
+
* what TypeScript reports, shortened
|
|
96
|
+
*/
|
|
97
|
+
message: string;
|
|
98
|
+
/**
|
|
99
|
+
* what to change
|
|
100
|
+
*/
|
|
101
|
+
fix: string;
|
|
102
|
+
};
|
|
103
|
+
export type DocTypesUnchecked = {
|
|
104
|
+
/**
|
|
105
|
+
* the doc file, relative to the package root
|
|
106
|
+
*/
|
|
107
|
+
doc: string;
|
|
108
|
+
/**
|
|
109
|
+
* why it was not checked
|
|
110
|
+
*/
|
|
111
|
+
reason: string;
|
|
112
|
+
};
|
|
113
|
+
export type DocTypesReport = {
|
|
114
|
+
/**
|
|
115
|
+
* `skipped` means nothing was checked,
|
|
116
|
+
* and `reason` says why
|
|
117
|
+
*/
|
|
118
|
+
status: "checked" | "skipped";
|
|
119
|
+
reason?: string | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* the version of the compiler that checked
|
|
122
|
+
*/
|
|
123
|
+
typescript?: string | undefined;
|
|
124
|
+
/**
|
|
125
|
+
* how many doc values were checked
|
|
126
|
+
*/
|
|
127
|
+
docs: number;
|
|
128
|
+
findings: DocTypeFinding[];
|
|
129
|
+
/**
|
|
130
|
+
* doc files with nothing to check,
|
|
131
|
+
* or not fully checked
|
|
132
|
+
*/
|
|
133
|
+
unchecked: DocTypesUnchecked[];
|
|
134
|
+
};
|
|
135
|
+
export type Target = {
|
|
136
|
+
exportName: string;
|
|
137
|
+
/**
|
|
138
|
+
* the doc value's expression
|
|
139
|
+
*/
|
|
140
|
+
node: any;
|
|
141
|
+
/**
|
|
142
|
+
* the authoring type, as a type expression
|
|
143
|
+
*/
|
|
144
|
+
typeExpr: string;
|
|
145
|
+
/**
|
|
146
|
+
* how findings name that type
|
|
147
|
+
*/
|
|
148
|
+
typeName: string;
|
|
149
|
+
/**
|
|
150
|
+
* nodes whose leading JSDoc annotations are blanked
|
|
151
|
+
*/
|
|
152
|
+
blank: any[];
|
|
153
|
+
/**
|
|
154
|
+
* source ranges to blank
|
|
155
|
+
*/
|
|
156
|
+
blankRanges: Array<[number, number]>;
|
|
157
|
+
};
|