@astryxdesign/cli 0.6.4-canary.06c8fa3 → 0.6.4-canary.0e1fbdb
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/README.md +49 -40
- package/api/build/build.doc.mjs +6 -1
- package/api/build/build.test.mjs +22 -0
- package/api/build/kit/kit.mjs +44 -5
- package/api/component/component.doc.mjs +14 -7
- package/api/docs/_adapter.d.mts +8 -3
- package/api/docs/_adapter.mjs +14 -6
- package/api/docs/docOverlays.test.mjs +27 -1
- package/api/docs/docs.doc.mjs +2 -2
- package/api/doctor/doctor.doc.mjs +17 -8
- package/api/doctor/doctor.type.d.mts +1 -1
- package/api/doctor/doctor.type.mjs +1 -1
- package/api/gap-report/gap-report.doc.mjs +19 -10
- package/api/hook/hook.doc.mjs +6 -3
- package/api/index.d.mts +2 -0
- package/api/index.mjs +3 -1
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-theme.mjs +22 -1
- package/api/integration/add-theme.test.mjs +34 -0
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.lifecycle-output.test.mjs +2 -0
- package/api/integration/pack-check.mjs +54 -6
- package/api/integration/pack-check.test.mjs +90 -0
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/index.ts +1 -0
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/_adapter.d.mts +34 -0
- package/api/layout/_adapter.mjs +148 -0
- package/api/layout/check/check.d.mts +16 -0
- package/api/layout/check/check.mjs +40 -0
- package/api/layout/expand/expand.d.mts +22 -0
- package/api/layout/expand/expand.mjs +155 -0
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.d.mts +13 -0
- package/api/layout/grammar/grammar.mjs +87 -0
- package/api/layout/layout.d.mts +6 -0
- package/api/layout/layout.mjs +17 -0
- package/api/layout/layout.test.mjs +297 -0
- package/api/layout/layout.type.d.mts +89 -0
- package/api/layout/layout.type.mjs +103 -0
- package/api/layout/layoutCheck.doc.d.mts +11 -0
- package/api/layout/layoutCheck.doc.mjs +85 -0
- package/api/layout/layoutExpand.doc.d.mts +11 -0
- package/api/layout/layoutExpand.doc.mjs +107 -0
- package/api/layout/layoutGrammar.doc.d.mts +11 -0
- package/api/layout/layoutGrammar.doc.mjs +57 -0
- package/api/search/search.d.mts +27 -1
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +228 -16
- package/api/swizzle/swizzle.doc.mjs +7 -5
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +9 -0
- package/api/template/template-integration.test.mjs +65 -1
- package/api/template/template.doc.mjs +2 -1
- package/api/template/template.mjs +1 -1
- package/api/theme/generateTonalPalette.doc.mjs +1 -2
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +9 -10
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +2 -1
- package/api/theme/themePaletteGenerate.doc.mjs +15 -8
- package/api/theme/themeTargets.doc.mjs +3 -2
- package/api/theme/themeTemplate.doc.mjs +2 -1
- package/api/upgrade/run/run.mjs +1 -1
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/assets/docs/README.md +4 -2
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +8 -2
- package/assets/docs/elevation.doc.mjs +6 -4
- package/assets/docs/getting-started.doc.mjs +5 -16
- package/assets/docs/icons.doc.mjs +2 -21
- package/assets/docs/illustrations.doc.mjs +7 -15
- package/assets/docs/layout.doc.dense.mjs +130 -82
- package/assets/docs/layout.doc.mjs +133 -77
- package/assets/docs/migration.doc.mjs +19 -21
- package/assets/docs/motion.doc.mjs +16 -3
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +8 -0
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +8 -3
- package/assets/docs/spacing.doc.mjs +7 -2
- package/assets/docs/styling-libraries.doc.mjs +6 -2
- package/assets/docs/styling.doc.mjs +19 -23
- package/assets/docs/theme.doc.dense.mjs +58 -18
- package/assets/docs/theme.doc.mjs +56 -46
- package/assets/docs/theme.doc.zh.mjs +9 -8
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +389 -8
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/add-a-component.doc.mjs +75 -0
- package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
- package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
- package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
- package/assets/docs/tree/block-template.doc.mjs +130 -0
- package/assets/docs/tree/build-the-template.doc.mjs +28 -0
- package/assets/docs/tree/building-blocks.doc.mjs +46 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
- package/assets/docs/tree/checks.doc.mjs +119 -0
- package/assets/docs/tree/codemods.doc.mjs +147 -0
- package/assets/docs/tree/component-family.doc.mjs +113 -0
- package/assets/docs/tree/component-imports.doc.mjs +69 -0
- package/assets/docs/tree/components.doc.mjs +23 -0
- package/assets/docs/tree/configuration.doc.mjs +23 -0
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
- package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
- package/assets/docs/tree/docs.doc.mjs +21 -0
- package/assets/docs/tree/document-the-template.doc.mjs +28 -0
- package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
- package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
- package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
- package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
- package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
- package/assets/docs/tree/help.doc.mjs +16 -0
- package/assets/docs/tree/integrations.doc.mjs +25 -470
- package/assets/docs/tree/links.doc.mjs +98 -0
- package/assets/docs/tree/package-and-test.doc.mjs +32 -0
- package/assets/docs/tree/page-template.doc.mjs +71 -0
- package/assets/docs/tree/publishing.doc.mjs +111 -0
- package/assets/docs/tree/quick-start.doc.mjs +272 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
- package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
- package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
- package/assets/docs/tree/ship.doc.mjs +16 -0
- package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
- package/assets/docs/tree/single-component.doc.mjs +165 -0
- package/assets/docs/tree/start-a-template.doc.mjs +143 -0
- package/assets/docs/tree/subcomponent.doc.mjs +115 -0
- package/assets/docs/tree/template-assets.doc.mjs +64 -0
- package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
- package/assets/docs/tree/template-fonts.doc.mjs +102 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
- package/assets/docs/tree/template-icons.doc.mjs +97 -0
- package/assets/docs/tree/template-images-media.doc.mjs +127 -0
- package/assets/docs/tree/template-styles.doc.mjs +93 -0
- package/assets/docs/tree/templates.doc.mjs +34 -0
- package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
- package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
- package/assets/docs/tree/themes.doc.mjs +39 -0
- package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
- package/assets/docs/tree/upgrading.doc.mjs +103 -0
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
- package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
- package/assets/docs/tree/versioning.doc.mjs +161 -0
- package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
- package/assets/docs/typography.doc.mjs +24 -4
- package/assets/docs/working-with-ai.doc.mjs +30 -22
- package/authoring/config/config.doc.mjs +2 -2
- package/authoring/config/type.ts +2 -2
- package/authoring/doctypes/_schema.d.mts +3 -2
- package/authoring/doctypes/_schema.mjs +6 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +4 -2
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/component.doc.mjs +6 -0
- package/authoring/doctypes/component/type.ts +8 -0
- package/authoring/doctypes/reference/reference.doc.mjs +7 -0
- package/authoring/doctypes/reference/type.ts +5 -0
- package/authoring/doctypes/schema/schema.doc.mjs +2 -2
- package/authoring/doctypes/template/template.doc.mjs +1 -1
- package/authoring/doctypes/template/type.ts +2 -2
- package/authoring/integration/integration.doc.mjs +12 -10
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/component.doc.mjs +4 -3
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +60 -17
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
- package/clients/cli/commands/doctor-integration.test.mjs +53 -0
- package/clients/cli/commands/doctor.doc.mjs +3 -1
- package/clients/cli/commands/doctor.mjs +49 -5
- package/clients/cli/commands/gap-report.doc.mjs +10 -9
- package/clients/cli/commands/init.doc.mjs +9 -6
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +61 -10
- package/clients/cli/commands/integration-pack.doc.mjs +5 -9
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration-verify.doc.mjs +22 -0
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +74 -43
- package/clients/cli/commands/layout-check.doc.mjs +65 -0
- package/clients/cli/commands/layout-expand.doc.mjs +83 -0
- package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
- package/clients/cli/commands/layout.doc.mjs +34 -0
- package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
- package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
- package/clients/cli/commands/layout.mjs +275 -0
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +10 -3
- package/clients/cli/commands/search.mjs +21 -2
- package/clients/cli/commands/search.test.mjs +21 -4
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.doc.mjs +1 -1
- package/clients/cli/commands/text-json-parity.test.mjs +24 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
- package/clients/cli/commands/theme-palette.doc.mjs +1 -2
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +62 -3
- package/clients/cli/index.mjs +32 -6
- package/clients/cli/lib/define-command.mjs +28 -4
- package/clients/cli/lib/define-command.test.mjs +54 -0
- package/clients/cli/lib/exit-codes.test.mjs +25 -2
- package/clients/cli/lib/json-shim.test.mjs +20 -6
- package/clients/cli/lib/manifest.mjs +23 -5
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
- package/foundation/discovery/cli-self-docs.mjs +16 -2
- package/foundation/discovery/cli-self-docs.test.mjs +20 -0
- package/foundation/discovery/docs-discovery.mjs +5 -1
- package/foundation/discovery/docs-discovery.test.mjs +21 -0
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +15 -2
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/tree.d.mts +4 -0
- package/foundation/doc-compiler/tree.mjs +6 -1
- package/foundation/integrations/cli-requirement.d.mts +26 -6
- package/foundation/integrations/cli-requirement.mjs +46 -11
- package/foundation/integrations/cli-requirement.test.mjs +7 -2
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/response/error-codes.doc.mjs +6 -8
- package/foundation/response/error-codes.test.mjs +30 -5
- package/foundation/response/response-types.doc.d.mts +4 -3
- package/foundation/response/response-types.doc.mjs +42 -6
- package/foundation/response/response.doc.mjs +11 -10
- package/foundation/xle/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.mjs +2 -2
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/package.json +9 -9
- package/api/docs/docs.test.mjs +0 -245
- package/api/docs/integration-tree.test.mjs +0 -555
- package/api/docs/integrationDocs.test.mjs +0 -314
- package/api/search/search.test.mjs +0 -530
- package/assets/docs/tree/integrations.test.mjs +0 -62
- package/assets/docs/tree/writing-docs.doc.mjs +0 -286
- package/clients/cli/commands/docs.test.mjs +0 -323
- package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
- package/foundation/doc-compiler/tree.test.mjs +0 -606
|
@@ -1,555 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Integration docs in the docs tree (spec:AST-046, spec:AST-047): an
|
|
5
|
-
* integration's namespace docs and placed guides join the CLI's tree with the
|
|
6
|
-
* same moves, links, search, and doctor checks, named by its provider id.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import * as fs from 'node:fs';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
|
-
import {afterEach, beforeEach, describe, expect, it} from 'vitest';
|
|
12
|
-
import {docs} from './docs.mjs';
|
|
13
|
-
import {loadDocsCatalog} from './_adapter.mjs';
|
|
14
|
-
import {search} from '../search/search.mjs';
|
|
15
|
-
import {checkDocsTree} from '../doctor/doctor.mjs';
|
|
16
|
-
import {integrationDocConflicts} from '../integration/authoring-checks.mjs';
|
|
17
|
-
|
|
18
|
-
const SLOW = 60_000;
|
|
19
|
-
|
|
20
|
-
/** @type {string} */
|
|
21
|
-
let tmpDir;
|
|
22
|
-
|
|
23
|
-
const NAMESPACE = {
|
|
24
|
-
type: 'namespace',
|
|
25
|
-
name: 'acme',
|
|
26
|
-
title: 'Acme',
|
|
27
|
-
summary: 'Everything about the Acme kit.',
|
|
28
|
-
slots: {guides: {title: 'Guides', accepts: {kinds: ['generic']}}},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* A guide placed in the acme namespace.
|
|
33
|
-
* @param {string} name
|
|
34
|
-
* @param {object} [fields]
|
|
35
|
-
*/
|
|
36
|
-
function guide(name, fields = {}) {
|
|
37
|
-
return {
|
|
38
|
-
type: 'generic',
|
|
39
|
-
name,
|
|
40
|
-
title: `Acme ${name}`,
|
|
41
|
-
description: `How to ${name} the Acme kit.`,
|
|
42
|
-
placement: {parent: 'namespace:acme', slot: 'guides'},
|
|
43
|
-
sections: [
|
|
44
|
-
{title: 'Overview', content: [{type: 'prose', text: `Do ${name}.`}]},
|
|
45
|
-
],
|
|
46
|
-
...fields,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** The docs of a small integration: a namespace, two guides, and a topic. */
|
|
51
|
-
function kit() {
|
|
52
|
-
return {
|
|
53
|
-
'acme.doc.mjs': NAMESPACE,
|
|
54
|
-
'setup.doc.mjs': guide('setup', {
|
|
55
|
-
placement: {parent: 'namespace:acme', slot: 'guides', order: 1},
|
|
56
|
-
sections: [
|
|
57
|
-
{
|
|
58
|
-
title: 'Install',
|
|
59
|
-
content: [
|
|
60
|
-
{
|
|
61
|
-
type: 'prose',
|
|
62
|
-
text: 'Frobnicate the kit, then check it with {@link @astryxdesign/cli:command:doctor}.',
|
|
63
|
-
},
|
|
64
|
-
{type: 'prose', text: 'Next: {@link generic:deploy}.'},
|
|
65
|
-
],
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
title: 'Configure',
|
|
69
|
-
content: [{type: 'prose', text: 'Add it to astryx.config.'}],
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
}),
|
|
73
|
-
'deploy.doc.mjs': guide('deploy', {
|
|
74
|
-
placement: {parent: 'namespace:acme', slot: 'guides', order: 2},
|
|
75
|
-
}),
|
|
76
|
-
'notes.doc.mjs': {
|
|
77
|
-
type: 'generic',
|
|
78
|
-
name: 'acme-notes',
|
|
79
|
-
title: 'Acme notes',
|
|
80
|
-
description: 'Notes about the kit.',
|
|
81
|
-
sections: [
|
|
82
|
-
{
|
|
83
|
-
title: 'Start',
|
|
84
|
-
content: [{type: 'prose', text: 'Start at {@link generic:setup}.'}],
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** A guide whose only link names no doc. */
|
|
92
|
-
const broken = () =>
|
|
93
|
-
guide('broken', {
|
|
94
|
-
sections: [
|
|
95
|
-
{
|
|
96
|
-
title: 'Overview',
|
|
97
|
-
content: [{type: 'prose', text: 'See {@link generic:nope}.'}],
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* A consumer project that configures `@acme/kit`, whose manifest names a
|
|
104
|
-
* provider id that differs from its package name.
|
|
105
|
-
* @param {Record<string, object>} files
|
|
106
|
-
*/
|
|
107
|
-
function scaffold(files) {
|
|
108
|
-
fs.writeFileSync(
|
|
109
|
-
path.join(tmpDir, 'package.json'),
|
|
110
|
-
JSON.stringify({name: 'consumer'}),
|
|
111
|
-
);
|
|
112
|
-
fs.writeFileSync(
|
|
113
|
-
path.join(tmpDir, 'astryx.config.mjs'),
|
|
114
|
-
"export default {integrations: ['@acme/kit']};\n",
|
|
115
|
-
);
|
|
116
|
-
const pkgDir = path.join(tmpDir, 'node_modules', '@acme', 'kit');
|
|
117
|
-
fs.mkdirSync(path.join(pkgDir, 'docs'), {recursive: true});
|
|
118
|
-
fs.writeFileSync(
|
|
119
|
-
path.join(pkgDir, 'package.json'),
|
|
120
|
-
JSON.stringify({name: '@acme/kit', version: '1.0.0'}),
|
|
121
|
-
);
|
|
122
|
-
fs.writeFileSync(
|
|
123
|
-
path.join(pkgDir, 'astryx.integration.mjs'),
|
|
124
|
-
"export default {docs: './docs', providerId: '@acme/tree-provider'};\n",
|
|
125
|
-
);
|
|
126
|
-
for (const [file, doc] of Object.entries(files)) {
|
|
127
|
-
fs.writeFileSync(
|
|
128
|
-
path.join(pkgDir, 'docs', file),
|
|
129
|
-
`export const docs = ${JSON.stringify(doc, null, 2)};\n`,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
beforeEach(() => {
|
|
135
|
-
tmpDir = fs.mkdtempSync(
|
|
136
|
-
path.join(process.cwd(), '.astryx-integration-tree-test-'),
|
|
137
|
-
);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
afterEach(() => {
|
|
141
|
-
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('integration docs in the docs tree', () => {
|
|
145
|
-
it('names a package whose docs did not load, instead of dropping them silently', async () => {
|
|
146
|
-
scaffold({
|
|
147
|
-
...kit(),
|
|
148
|
-
'broken.doc.mjs': {
|
|
149
|
-
type: 'generic',
|
|
150
|
-
name: 'broken',
|
|
151
|
-
title: 'Broken',
|
|
152
|
-
description: 'A topic whose block no topic may hold.',
|
|
153
|
-
sections: [
|
|
154
|
-
{
|
|
155
|
-
title: 'Only',
|
|
156
|
-
content: [
|
|
157
|
-
{
|
|
158
|
-
type: 'workflow',
|
|
159
|
-
steps: [{title: 'Set up', references: ['generic:setup']}],
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
},
|
|
165
|
-
});
|
|
166
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
167
|
-
expect(listed.meta?.notLoaded).toEqual([
|
|
168
|
-
expect.objectContaining({package: '@acme/kit', message: expect.any(String)}),
|
|
169
|
-
]);
|
|
170
|
-
}, 60_000);
|
|
171
|
-
|
|
172
|
-
it('lists an integration namespace beside the CLI, named by its provider id', async () => {
|
|
173
|
-
scaffold(kit());
|
|
174
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
175
|
-
expect(listed.meta.namespaces).toContainEqual({
|
|
176
|
-
topic: 'acme',
|
|
177
|
-
description: 'Everything about the Acme kit.',
|
|
178
|
-
package: '@acme/kit',
|
|
179
|
-
});
|
|
180
|
-
const top = await docs('acme', undefined, {cwd: tmpDir});
|
|
181
|
-
expect(top.type).toBe('docs.node');
|
|
182
|
-
expect(top.data).toMatchObject({
|
|
183
|
-
id: 'astryx:artifact:v1/%40acme%2Ftree-provider/namespace/acme',
|
|
184
|
-
package: '@acme/kit',
|
|
185
|
-
links: {up: 'astryx docs'},
|
|
186
|
-
});
|
|
187
|
-
expect(
|
|
188
|
-
top.data.slots[0].children.map((/** @type {any} */ c) => c.route),
|
|
189
|
-
).toEqual(['acme/setup', 'acme/deploy']);
|
|
190
|
-
}, SLOW);
|
|
191
|
-
|
|
192
|
-
it('reads a placed guide one level at a time, with its links resolved', async () => {
|
|
193
|
-
scaffold(kit());
|
|
194
|
-
const index = await docs('acme/setup', undefined, {cwd: tmpDir, index: true});
|
|
195
|
-
expect(index.type).toBe('docs.index');
|
|
196
|
-
expect(index.data.links.up).toBe('astryx docs acme');
|
|
197
|
-
const install = await docs('acme/setup', 'install', {cwd: tmpDir});
|
|
198
|
-
const [prose, next] = install.data.content;
|
|
199
|
-
expect(prose.text).toBe(
|
|
200
|
-
'Frobnicate the kit, then check it with `astryx docs cli/commands/doctor`.',
|
|
201
|
-
);
|
|
202
|
-
expect(next.text).toBe('Next: `astryx docs acme/deploy`.');
|
|
203
|
-
const notes = await docs('acme-notes', undefined, {cwd: tmpDir});
|
|
204
|
-
expect(notes.data.sections[0].content[0].text).toBe(
|
|
205
|
-
'Start at `astryx docs acme/setup`.',
|
|
206
|
-
);
|
|
207
|
-
}, SLOW);
|
|
208
|
-
|
|
209
|
-
it('finds a section of the guide by search, with its package and parent', async () => {
|
|
210
|
-
scaffold(kit());
|
|
211
|
-
const {data} = await search('frobnicate', {cwd: tmpDir, type: 'doc'});
|
|
212
|
-
expect(data.results[0]).toMatchObject({
|
|
213
|
-
name: 'acme/setup',
|
|
214
|
-
section: 'install',
|
|
215
|
-
command: 'astryx docs acme/setup install',
|
|
216
|
-
parent: 'astryx docs acme/setup --index',
|
|
217
|
-
package: '@acme/kit',
|
|
218
|
-
});
|
|
219
|
-
}, SLOW);
|
|
220
|
-
|
|
221
|
-
it('passes doctor, and warns on a link that names no doc', async () => {
|
|
222
|
-
scaffold(kit());
|
|
223
|
-
const ok = await checkDocsTree({
|
|
224
|
-
docsCatalog: await loadDocsCatalog(tmpDir),
|
|
225
|
-
});
|
|
226
|
-
expect(ok).toMatchObject({id: 'docs-tree', status: 'pass'});
|
|
227
|
-
scaffold({...kit(), 'broken.doc.mjs': broken()});
|
|
228
|
-
const bad = await checkDocsTree({
|
|
229
|
-
docsCatalog: await loadDocsCatalog(tmpDir),
|
|
230
|
-
});
|
|
231
|
-
expect(bad.status).toBe('warn');
|
|
232
|
-
expect(bad.message).toContain('acme/broken');
|
|
233
|
-
expect(bad.message).toContain('"generic:nope" names no doc');
|
|
234
|
-
}, SLOW);
|
|
235
|
-
|
|
236
|
-
it("keeps the CLI's routes: an integration namespace or topic that claims one is withdrawn, and both doctors say so", async () => {
|
|
237
|
-
const flat = (/** @type {string} */ name) => ({
|
|
238
|
-
type: 'generic',
|
|
239
|
-
name,
|
|
240
|
-
title: `Acme ${name}`,
|
|
241
|
-
description: `Acme's ${name} notes.`,
|
|
242
|
-
sections: [
|
|
243
|
-
{title: 'One', content: [{type: 'prose', text: 'One.'}]},
|
|
244
|
-
{title: 'Two', content: [{type: 'prose', text: 'Two.'}]},
|
|
245
|
-
],
|
|
246
|
-
});
|
|
247
|
-
scaffold({
|
|
248
|
-
...kit(),
|
|
249
|
-
'unorganized.doc.mjs': {...NAMESPACE, name: 'unorganized', title: 'Mine', summary: 'Mine.'},
|
|
250
|
-
'tokens.doc.mjs': {...NAMESPACE, name: 'tokens', title: 'Acme tokens', summary: 'Acme tokens.'},
|
|
251
|
-
'cli.doc.mjs': flat('cli'),
|
|
252
|
-
});
|
|
253
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
254
|
-
expect(listed.meta.namespaces).toEqual(
|
|
255
|
-
expect.arrayContaining([
|
|
256
|
-
expect.objectContaining({topic: 'cli', package: '@astryxdesign/cli'}),
|
|
257
|
-
expect.objectContaining({topic: 'unorganized', package: '@astryxdesign/cli'}),
|
|
258
|
-
]),
|
|
259
|
-
);
|
|
260
|
-
expect(listed.meta.namespaces.filter(n => ['tokens', 'unorganized'].includes(n.topic) && n.package === '@acme/kit')).toEqual([]);
|
|
261
|
-
expect(listed.data.map(entry => entry.topic)).not.toContain('cli');
|
|
262
|
-
// Each name opens the CLI's doc, and a CLI topic keeps its home.
|
|
263
|
-
expect((await docs('cli', undefined, {cwd: tmpDir})).data).toMatchObject({route: 'cli', package: '@astryxdesign/cli'});
|
|
264
|
-
expect((await docs('unorganized', undefined, {cwd: tmpDir})).data).toMatchObject({route: 'unorganized', package: '@astryxdesign/cli'});
|
|
265
|
-
const tokens = await docs('tokens', undefined, {cwd: tmpDir});
|
|
266
|
-
expect(tokens.type).toBe('docs.detail');
|
|
267
|
-
expect(tokens.data.links.up).toBe('astryx docs unorganized');
|
|
268
|
-
// The project doctor and the package doctor both name the claims.
|
|
269
|
-
const check = await checkDocsTree({docsCatalog: await loadDocsCatalog(tmpDir)});
|
|
270
|
-
expect(check.status).toBe('warn');
|
|
271
|
-
expect(check.message).toContain('takes the route "unorganized", which the CLI\'s own docs keep');
|
|
272
|
-
expect(check.message).toContain('takes the route "tokens"');
|
|
273
|
-
expect(check.message).toContain('both have the route "cli"');
|
|
274
|
-
const result = await integrationDocConflicts('@acme/kit', {cwd: tmpDir});
|
|
275
|
-
const graph = result.data.issues.filter(issue => issue.code === 'invalid_doc_graph').map(issue => issue.message).join('\n');
|
|
276
|
-
expect(graph).toContain('takes the route "unorganized"');
|
|
277
|
-
expect(graph).toContain('takes the route "tokens"');
|
|
278
|
-
expect(graph).toContain('route "cli"');
|
|
279
|
-
}, SLOW);
|
|
280
|
-
|
|
281
|
-
it("keeps the CLI's routes from a claim that differs only in case", async () => {
|
|
282
|
-
const flat = (/** @type {string} */ name) => ({
|
|
283
|
-
type: 'generic',
|
|
284
|
-
name,
|
|
285
|
-
title: `Acme ${name}`,
|
|
286
|
-
description: `Acme's ${name} notes.`,
|
|
287
|
-
sections: [
|
|
288
|
-
{title: 'One', content: [{type: 'prose', text: 'One.'}]},
|
|
289
|
-
{title: 'Two', content: [{type: 'prose', text: 'Two.'}]},
|
|
290
|
-
],
|
|
291
|
-
});
|
|
292
|
-
scaffold({...kit(), 'caps-cli.doc.mjs': flat('CLI')});
|
|
293
|
-
// Another spelling, in a nested folder of the package's docs.
|
|
294
|
-
const nested = path.join(tmpDir, 'node_modules', '@acme', 'kit', 'docs', 'nested');
|
|
295
|
-
fs.mkdirSync(nested, {recursive: true});
|
|
296
|
-
fs.writeFileSync(
|
|
297
|
-
path.join(nested, 'caps-unorganized.doc.mjs'),
|
|
298
|
-
`export const docs = ${JSON.stringify(flat('Unorganized'), null, 2)};\n`,
|
|
299
|
-
);
|
|
300
|
-
fs.writeFileSync(
|
|
301
|
-
path.join(nested, 'caps-tokens.doc.mjs'),
|
|
302
|
-
`export const docs = ${JSON.stringify(flat('TOKENS'), null, 2)};\n`,
|
|
303
|
-
);
|
|
304
|
-
expect((await docs('cli', undefined, {cwd: tmpDir})).data).toMatchObject({route: 'cli', package: '@astryxdesign/cli'});
|
|
305
|
-
expect((await docs('unorganized', undefined, {cwd: tmpDir})).data).toMatchObject({route: 'unorganized', package: '@astryxdesign/cli'});
|
|
306
|
-
expect((await docs('theme', undefined, {cwd: tmpDir, index: true})).data.links.up).toBe('astryx docs unorganized');
|
|
307
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
308
|
-
expect(listed.data.map(entry => entry.topic.toLowerCase())).not.toContain('cli');
|
|
309
|
-
// Search does not offer a topic whose route another doc owns.
|
|
310
|
-
const found = await search("Acme's CLI notes", {cwd: tmpDir, type: 'doc', limit: 20});
|
|
311
|
-
expect(
|
|
312
|
-
found.data.results.filter(hit => hit.package === '@acme/kit' && /^cli$/i.test(hit.name)),
|
|
313
|
-
).toEqual([]);
|
|
314
|
-
const check = await checkDocsTree({docsCatalog: await loadDocsCatalog(tmpDir)});
|
|
315
|
-
expect(check.status).toBe('warn');
|
|
316
|
-
expect(check.message).toContain('route "CLI"');
|
|
317
|
-
expect(check.message).toContain('takes the route "Unorganized"');
|
|
318
|
-
// `TOKENS` is the CLI's topic `tokens` in another spelling: the CLI's wins.
|
|
319
|
-
const tokens = await docs('TOKENS', undefined, {cwd: tmpDir, index: true});
|
|
320
|
-
expect(tokens.data).toMatchObject({name: 'tokens', links: {up: 'astryx docs unorganized'}});
|
|
321
|
-
expect(tokens.data.title).not.toBe('Acme TOKENS');
|
|
322
|
-
const result = await integrationDocConflicts('@acme/kit', {cwd: tmpDir});
|
|
323
|
-
const graph = result.data.issues
|
|
324
|
-
.filter(issue => issue.code === 'invalid_doc_graph')
|
|
325
|
-
.map(issue => issue.message)
|
|
326
|
-
.join('\n');
|
|
327
|
-
expect(graph).toContain('route "CLI"');
|
|
328
|
-
expect(graph).toContain('takes the route "Unorganized"');
|
|
329
|
-
}, SLOW);
|
|
330
|
-
|
|
331
|
-
it("keeps a replaced name for the topic that replaces it, over another integration's namespace", async () => {
|
|
332
|
-
scaffold({...kit(), 'tokens-ns.doc.mjs': {...NAMESPACE, name: 'tokens', title: 'Kit tokens', summary: 'Kit tokens.'}});
|
|
333
|
-
const two = path.join(tmpDir, 'node_modules', '@acme', 'two');
|
|
334
|
-
fs.mkdirSync(path.join(two, 'docs'), {recursive: true});
|
|
335
|
-
fs.writeFileSync(path.join(two, 'package.json'), JSON.stringify({name: '@acme/two', version: '1.0.0'}));
|
|
336
|
-
fs.writeFileSync(path.join(two, 'astryx.integration.mjs'), "export default {docs: './docs'};\n");
|
|
337
|
-
fs.writeFileSync(
|
|
338
|
-
path.join(two, 'docs', 'acme-tokens.doc.mjs'),
|
|
339
|
-
`export const docs = ${JSON.stringify({
|
|
340
|
-
type: 'generic',
|
|
341
|
-
name: 'acme-tokens',
|
|
342
|
-
title: 'Acme tokens',
|
|
343
|
-
description: 'Acme tokens.',
|
|
344
|
-
replaces: 'tokens',
|
|
345
|
-
sections: [{title: 'One', content: [{type: 'prose', text: 'One.'}]}],
|
|
346
|
-
}, null, 2)};\n`,
|
|
347
|
-
);
|
|
348
|
-
fs.writeFileSync(
|
|
349
|
-
path.join(tmpDir, 'astryx.config.mjs'),
|
|
350
|
-
"export default {integrations: ['@acme/kit', '@acme/two']};\n",
|
|
351
|
-
);
|
|
352
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
353
|
-
expect(listed.meta.namespaces.map(entry => entry.topic)).not.toContain('tokens');
|
|
354
|
-
const read = await docs('tokens', undefined, {cwd: tmpDir, index: true});
|
|
355
|
-
expect(read.data.name).toBe('acme-tokens');
|
|
356
|
-
const check = await checkDocsTree({docsCatalog: await loadDocsCatalog(tmpDir)});
|
|
357
|
-
expect(check.status).toBe('warn');
|
|
358
|
-
expect(check.message).toContain('which the topic "acme-tokens" also answers to');
|
|
359
|
-
}, SLOW);
|
|
360
|
-
|
|
361
|
-
it('keeps every name a topic replaced twice answers to, and the CLI\'s links to it still open', async () => {
|
|
362
|
-
scaffold({...kit(), 'tokens-ns.doc.mjs': {...NAMESPACE, name: 'tokens', title: 'Kit tokens', summary: 'Kit tokens.'}});
|
|
363
|
-
/** @param {string} pkg @param {string} name @param {string} replaces */
|
|
364
|
-
const replacement = (pkg, name, replaces) => {
|
|
365
|
-
const dir = path.join(tmpDir, 'node_modules', '@acme', pkg);
|
|
366
|
-
fs.mkdirSync(path.join(dir, 'docs'), {recursive: true});
|
|
367
|
-
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({name: `@acme/${pkg}`, version: '1.0.0'}));
|
|
368
|
-
fs.writeFileSync(path.join(dir, 'astryx.integration.mjs'), "export default {docs: './docs'};\n");
|
|
369
|
-
fs.writeFileSync(
|
|
370
|
-
path.join(dir, 'docs', `${name}.doc.mjs`),
|
|
371
|
-
`export const docs = ${JSON.stringify({
|
|
372
|
-
type: 'generic',
|
|
373
|
-
name,
|
|
374
|
-
title: `Tokens by ${pkg}`,
|
|
375
|
-
description: `Tokens by ${pkg}.`,
|
|
376
|
-
replaces,
|
|
377
|
-
sections: [{title: 'One', content: [{type: 'prose', text: 'One.'}]}],
|
|
378
|
-
}, null, 2)};\n`,
|
|
379
|
-
);
|
|
380
|
-
};
|
|
381
|
-
replacement('two', 'acme-tokens', 'tokens');
|
|
382
|
-
replacement('three', 'b-tokens', 'tokens');
|
|
383
|
-
replacement('four', 'super-tokens', 'b-tokens');
|
|
384
|
-
fs.writeFileSync(
|
|
385
|
-
path.join(tmpDir, 'astryx.config.mjs'),
|
|
386
|
-
"export default {integrations: ['@acme/kit', '@acme/two', '@acme/three', '@acme/four']};\n",
|
|
387
|
-
);
|
|
388
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
389
|
-
expect(listed.meta.namespaces.map(entry => entry.topic)).not.toContain('tokens');
|
|
390
|
-
for (const name of ['tokens', 'acme-tokens', 'b-tokens', 'super-tokens']) {
|
|
391
|
-
expect((await docs(name, undefined, {cwd: tmpDir, index: true})).data.name).toBe('super-tokens');
|
|
392
|
-
}
|
|
393
|
-
// A walk over every topic: the CLI's own links to `tokens` still open it.
|
|
394
|
-
/** @type {string[]} */
|
|
395
|
-
const raw = [];
|
|
396
|
-
for (const entry of listed.data) {
|
|
397
|
-
const read = await docs(entry.topic, undefined, {cwd: tmpDir});
|
|
398
|
-
if (/\{@link [^}]*tokens\}/.test(JSON.stringify(read.data))) raw.push(entry.topic);
|
|
399
|
-
}
|
|
400
|
-
expect(raw).toEqual([]);
|
|
401
|
-
const principles = await docs('principles', undefined, {cwd: tmpDir});
|
|
402
|
-
expect(JSON.stringify(principles.data)).toContain('astryx docs super-tokens');
|
|
403
|
-
const check = await checkDocsTree({docsCatalog: await loadDocsCatalog(tmpDir)});
|
|
404
|
-
expect(check.message).toContain('takes the route "tokens", which the topic "super-tokens" also answers to');
|
|
405
|
-
expect(check.message).not.toContain('names no doc');
|
|
406
|
-
}, SLOW);
|
|
407
|
-
|
|
408
|
-
it("keeps the CLI's routes from a replacement that answers to one, in one package or across a chain", async () => {
|
|
409
|
-
const flat = (/** @type {string} */ name, /** @type {object} */ extra = {}) => ({
|
|
410
|
-
type: 'generic',
|
|
411
|
-
name,
|
|
412
|
-
title: `Acme ${name}`,
|
|
413
|
-
description: `Acme's ${name} notes.`,
|
|
414
|
-
sections: [
|
|
415
|
-
{title: 'One', content: [{type: 'prose', text: 'One.'}]},
|
|
416
|
-
{title: 'Two', content: [{type: 'prose', text: 'Two.'}]},
|
|
417
|
-
],
|
|
418
|
-
...extra,
|
|
419
|
-
});
|
|
420
|
-
scaffold({
|
|
421
|
-
...kit(),
|
|
422
|
-
'a-cli.doc.mjs': flat('cli'),
|
|
423
|
-
'a-unorganized.doc.mjs': flat('Unorganized'),
|
|
424
|
-
'z-b2.doc.mjs': flat('b2', {replaces: 'cli'}),
|
|
425
|
-
'z-u2.doc.mjs': flat('u2', {replaces: 'Unorganized'}),
|
|
426
|
-
});
|
|
427
|
-
// Another package carries the chain on: c3 replaces b2, which replaced cli.
|
|
428
|
-
const three = path.join(tmpDir, 'node_modules', '@acme', 'three');
|
|
429
|
-
fs.mkdirSync(path.join(three, 'docs'), {recursive: true});
|
|
430
|
-
fs.writeFileSync(path.join(three, 'package.json'), JSON.stringify({name: '@acme/three', version: '1.0.0'}));
|
|
431
|
-
fs.writeFileSync(path.join(three, 'astryx.integration.mjs'), "export default {docs: './docs'};\n");
|
|
432
|
-
fs.writeFileSync(
|
|
433
|
-
path.join(three, 'docs', 'c3.doc.mjs'),
|
|
434
|
-
`export const docs = ${JSON.stringify(flat('c3', {replaces: 'b2'}), null, 2)};\n`,
|
|
435
|
-
);
|
|
436
|
-
fs.writeFileSync(
|
|
437
|
-
path.join(tmpDir, 'astryx.config.mjs'),
|
|
438
|
-
"export default {integrations: ['@acme/kit', '@acme/three']};\n",
|
|
439
|
-
);
|
|
440
|
-
for (const name of ['cli', 'CLI']) {
|
|
441
|
-
expect((await docs(name, undefined, {cwd: tmpDir})).data).toMatchObject({route: 'cli', package: '@astryxdesign/cli'});
|
|
442
|
-
}
|
|
443
|
-
for (const name of ['unorganized', 'UNORGANIZED']) {
|
|
444
|
-
expect((await docs(name, undefined, {cwd: tmpDir})).data).toMatchObject({route: 'unorganized', package: '@astryxdesign/cli'});
|
|
445
|
-
}
|
|
446
|
-
// The replacement still answers to its own names.
|
|
447
|
-
for (const name of ['b2', 'c3']) {
|
|
448
|
-
expect((await docs(name, undefined, {cwd: tmpDir, index: true})).data.name).toBe('c3');
|
|
449
|
-
}
|
|
450
|
-
const listed = await docs(undefined, undefined, {cwd: tmpDir});
|
|
451
|
-
for (const entry of listed.data) {
|
|
452
|
-
const read = await docs(entry.topic, undefined, {cwd: tmpDir});
|
|
453
|
-
expect(read.type).toBe('docs.detail');
|
|
454
|
-
expect(read.data.name).toBe(entry.topic);
|
|
455
|
-
}
|
|
456
|
-
const check = await checkDocsTree({docsCatalog: await loadDocsCatalog(tmpDir)});
|
|
457
|
-
expect(check.status).toBe('warn');
|
|
458
|
-
expect(check.message).toContain('The topic "c3" answers to "cli" through replaces');
|
|
459
|
-
expect(check.message).toContain('The topic "u2" answers to "unorganized" through replaces');
|
|
460
|
-
const inPackage = await integrationDocConflicts('@acme/kit', {cwd: tmpDir});
|
|
461
|
-
const graph = inPackage.data.issues
|
|
462
|
-
.filter(issue => issue.code === 'invalid_doc_graph')
|
|
463
|
-
.map(issue => issue.message)
|
|
464
|
-
.join('\n');
|
|
465
|
-
expect(graph).toContain('answers to "cli" through replaces');
|
|
466
|
-
}, SLOW);
|
|
467
|
-
|
|
468
|
-
it('runs the same checks inside the package: doctor integration docs', async () => {
|
|
469
|
-
scaffold({...kit(), 'broken.doc.mjs': broken()});
|
|
470
|
-
const result = await integrationDocConflicts('@acme/kit', {cwd: tmpDir});
|
|
471
|
-
expect(result.data.issues).toContainEqual(
|
|
472
|
-
expect.objectContaining({
|
|
473
|
-
code: 'invalid_doc_graph',
|
|
474
|
-
severity: 'warning',
|
|
475
|
-
message: expect.stringContaining('"generic:nope" names no doc'),
|
|
476
|
-
}),
|
|
477
|
-
);
|
|
478
|
-
}, SLOW);
|
|
479
|
-
|
|
480
|
-
it("resolves an extension's links against the extension's provider, not the base topic's", async () => {
|
|
481
|
-
scaffold({
|
|
482
|
-
...kit(),
|
|
483
|
-
'integrations.doc.mjs': guide('integrations'),
|
|
484
|
-
'theme-acme.doc.mjs': {
|
|
485
|
-
type: 'generic',
|
|
486
|
-
name: 'theme-acme',
|
|
487
|
-
title: 'Acme theming',
|
|
488
|
-
description: 'Acme notes on theming.',
|
|
489
|
-
extends: 'theme',
|
|
490
|
-
sections: [
|
|
491
|
-
{
|
|
492
|
-
title: 'Acme theming notes',
|
|
493
|
-
content: [
|
|
494
|
-
{
|
|
495
|
-
type: 'prose',
|
|
496
|
-
text: 'See {@link generic:integrations}, and {@link @astryxdesign/cli:generic:tokens} for the tokens.',
|
|
497
|
-
},
|
|
498
|
-
],
|
|
499
|
-
},
|
|
500
|
-
],
|
|
501
|
-
},
|
|
502
|
-
});
|
|
503
|
-
const {data} = await docs('theme', 'acme-theming-notes', {cwd: tmpDir});
|
|
504
|
-
// `generic:integrations` is the extension's own guide, never the CLI's
|
|
505
|
-
// `cli/integrations`; a provider-qualified link reaches the CLI's topic.
|
|
506
|
-
expect(data.content[0].text).toBe(
|
|
507
|
-
'See `astryx docs acme/integrations`, and `astryx docs tokens` for the tokens.',
|
|
508
|
-
);
|
|
509
|
-
// The CLI's own sections of the topic still resolve against the CLI.
|
|
510
|
-
const full = await docs('theme', undefined, {cwd: tmpDir});
|
|
511
|
-
expect(JSON.stringify(full.data)).not.toContain('{@link');
|
|
512
|
-
}, SLOW);
|
|
513
|
-
|
|
514
|
-
it("warns, in the project and in the package, on an extension link that names no doc of its provider", async () => {
|
|
515
|
-
scaffold({
|
|
516
|
-
...kit(),
|
|
517
|
-
'theme-acme.doc.mjs': {
|
|
518
|
-
type: 'generic',
|
|
519
|
-
name: 'theme-acme',
|
|
520
|
-
title: 'Acme theming',
|
|
521
|
-
description: 'Acme notes on theming.',
|
|
522
|
-
extends: 'theme',
|
|
523
|
-
sections: [
|
|
524
|
-
{
|
|
525
|
-
title: 'Acme theming notes',
|
|
526
|
-
content: [{type: 'prose', text: 'See {@link generic:tokens}.'}],
|
|
527
|
-
},
|
|
528
|
-
],
|
|
529
|
-
},
|
|
530
|
-
});
|
|
531
|
-
const check = await checkDocsTree({
|
|
532
|
-
docsCatalog: await loadDocsCatalog(tmpDir),
|
|
533
|
-
});
|
|
534
|
-
expect(check.status).toBe('warn');
|
|
535
|
-
expect(check.message).toContain('"generic:tokens" names no doc');
|
|
536
|
-
const result = await integrationDocConflicts('@acme/kit', {cwd: tmpDir});
|
|
537
|
-
expect(result.data.issues).toContainEqual(
|
|
538
|
-
expect.objectContaining({
|
|
539
|
-
code: 'invalid_doc_graph',
|
|
540
|
-
message: expect.stringContaining('"generic:tokens" names no doc'),
|
|
541
|
-
}),
|
|
542
|
-
);
|
|
543
|
-
}, SLOW);
|
|
544
|
-
|
|
545
|
-
it('keeps the CLI route when an integration claims it, and names the claim', async () => {
|
|
546
|
-
scaffold({'cli.doc.mjs': {...NAMESPACE, name: 'cli', title: 'Not the CLI'}});
|
|
547
|
-
const top = await docs('cli', undefined, {cwd: tmpDir});
|
|
548
|
-
expect(top.data.package).toBe('@astryxdesign/cli');
|
|
549
|
-
const check = await checkDocsTree({
|
|
550
|
-
docsCatalog: await loadDocsCatalog(tmpDir),
|
|
551
|
-
});
|
|
552
|
-
expect(check.status).toBe('warn');
|
|
553
|
-
expect(check.message).toContain('both have the route "cli"');
|
|
554
|
-
}, SLOW);
|
|
555
|
-
});
|