@astryxdesign/cli 0.6.3-canary.7ada42e → 0.6.3-canary.7ec7be0
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 +21 -19
- package/api/build/_adapter.d.mts +50 -0
- package/api/build/_adapter.mjs +60 -0
- package/api/build/build.doc.mjs +13 -7
- package/api/build/build.test.mjs +184 -6
- package/api/build/build.type.d.mts +57 -2
- package/api/build/build.type.mjs +30 -7
- package/api/build/help/help.d.mts +4 -0
- package/api/build/help/help.mjs +24 -11
- package/api/build/kit/kit.d.mts +4 -1
- package/api/build/kit/kit.mjs +165 -49
- package/api/build/kit/rank.d.mts +44 -0
- package/api/build/kit/rank.mjs +432 -0
- package/api/build/kit/rank.test.mjs +196 -0
- package/api/component/_adapter.d.mts +6 -12
- package/api/component/_adapter.mjs +20 -10
- package/api/component/component.mjs +60 -12
- package/api/component/list/list.mjs +3 -2
- package/api/docs/_adapter.d.mts +251 -28
- package/api/docs/_adapter.mjs +918 -35
- package/api/docs/detail/detail.mjs +11 -3
- package/api/docs/detail/section/section.mjs +24 -13
- package/api/docs/detail/section/section.test.mjs +15 -6
- package/api/docs/docs.d.mts +5 -3
- package/api/docs/docs.doc.mjs +38 -17
- package/api/docs/docs.mjs +44 -8
- package/api/docs/docs.test.mjs +158 -4
- package/api/docs/docs.type.d.mts +181 -2
- package/api/docs/docs.type.mjs +117 -3
- package/api/docs/index/index.mjs +11 -3
- package/api/docs/index/index.test.mjs +1 -1
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +14 -14
- package/api/docs/list/list.mjs +25 -5
- package/api/docs/node/node.d.mts +43 -0
- package/api/docs/node/node.mjs +192 -0
- package/api/docs/reference-blocks.test.mjs +406 -0
- package/api/doctor/doctor.d.mts +30 -2
- package/api/doctor/doctor.mjs +151 -8
- package/api/doctor/doctor.test.mjs +95 -7
- package/api/index.d.mts +1 -1
- package/api/index.mjs +1 -0
- package/api/init/init.doc.mjs +1 -1
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +107 -5
- package/api/integration/add-contribution.test.mjs +137 -0
- package/api/integration/authoring-checks.mjs +138 -28
- package/api/integration/authoring-checks.test.mjs +171 -3
- package/api/integration/authoring-checks.type.mjs +6 -1
- package/api/integration/integration-authoring.type.d.mts +2 -0
- package/api/integration/integration-authoring.type.mjs +2 -0
- package/api/integration/integrationAdd.doc.mjs +6 -0
- package/api/integration/integrationAddDoc.doc.mjs +7 -1
- package/api/integration/integrationDocConflicts.doc.mjs +1 -1
- package/api/integration/integrationPackCheck.doc.mjs +1 -1
- package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +3 -0
- package/api/integration/pack-check.mjs +34 -0
- package/api/integration/pack-check.test.mjs +121 -0
- package/api/integration/pack-check.type.d.mts +26 -2
- package/api/integration/pack-check.type.mjs +14 -1
- package/api/integration/template-conflict-compatibility.test.mjs +73 -0
- package/api/integration/validate-integration.test.mjs +3 -3
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/json/index.ts +2 -0
- package/api/layout/_adapter.mjs +20 -5
- package/api/search/search.d.mts +59 -1
- package/api/search/search.doc.mjs +4 -3
- package/api/search/search.mjs +442 -71
- package/api/search/search.test.mjs +91 -2
- package/api/search/search.type.d.mts +13 -1
- package/api/search/search.type.mjs +4 -1
- package/api/template/list/list.mjs +1 -0
- package/api/template/table-floating-bulk-actions.test.mjs +66 -0
- package/api/template/template-integration.test.mjs +1072 -3
- package/api/template/template.doc.mjs +27 -7
- package/api/template/template.mjs +45 -8
- package/api/template/template.type.d.mts +6 -8
- package/api/template/template.type.mjs +3 -2
- package/api/theme/template/template.test.mjs +5 -0
- package/api/theme/themeTemplate.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/layout.doc.dense.mjs +2 -2
- package/assets/docs/layout.doc.mjs +1 -1
- package/assets/docs/principles.doc.mjs +6 -6
- package/assets/docs/styling-libraries.doc.mjs +3 -3
- package/assets/docs/styling.doc.mjs +4 -4
- package/assets/docs/theme.doc.mjs +4 -4
- package/assets/docs/tokens.doc.mjs +1 -1
- package/assets/docs/tree/api.doc.mjs +30 -0
- package/assets/docs/tree/cli.doc.mjs +23 -0
- package/assets/docs/tree/commands.doc.mjs +25 -0
- package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +37 -9
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/working-with-ai.doc.mjs +3 -3
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
- package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
- package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
- package/authoring/debug/parse.d.mts +3 -3
- package/authoring/doctypes/_schema.d.mts +119 -117
- package/authoring/doctypes/_schema.mjs +54 -3
- package/authoring/doctypes/base/graph-fields.doc.mjs +7 -5
- package/authoring/doctypes/base/type.ts +6 -5
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +2 -2
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -1
- package/authoring/doctypes/function/function.doc.mjs +3 -2
- package/authoring/doctypes/function/type.ts +3 -2
- package/authoring/doctypes/load-contract.test.mjs +26 -1
- package/authoring/doctypes/namespace/namespace.doc.mjs +6 -10
- package/authoring/doctypes/namespace/parse.test.mjs +23 -25
- package/authoring/doctypes/namespace/type.ts +5 -2
- package/authoring/doctypes/parse.mjs +3 -2
- package/authoring/doctypes/reference/reference.doc.mjs +34 -5
- package/authoring/doctypes/reference/type.ts +28 -11
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +1 -1
- package/authoring/doctypes/template/parse.d.mts +2 -0
- package/authoring/doctypes/template/parse.mjs +4 -0
- package/authoring/doctypes/template/parse.test.mjs +18 -0
- package/authoring/doctypes/template/template.doc.mjs +6 -0
- package/authoring/doctypes/template/type.ts +8 -0
- package/authoring/identity/identity.doc.mjs +2 -2
- package/authoring/index.d.ts +1 -0
- package/authoring/integration/type.ts +1 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.mjs +1 -1
- package/clients/cli/commands/build.doc.mjs +11 -6
- package/clients/cli/commands/build.mjs +105 -67
- package/clients/cli/commands/build.text-fields.test.mjs +41 -0
- package/clients/cli/commands/component/index.mjs +1 -1
- package/clients/cli/commands/component-ownership.test.mjs +3 -3
- package/clients/cli/commands/discover.broken-integration.test.mjs +7 -8
- package/clients/cli/commands/discover.mjs +1 -1
- package/clients/cli/commands/docs.doc.mjs +20 -8
- package/clients/cli/commands/docs.mjs +183 -69
- package/clients/cli/commands/docs.test.mjs +120 -16
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +2 -2
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +14 -7
- package/clients/cli/commands/doctor-integration.test.mjs +75 -1
- package/clients/cli/commands/doctor.mjs +53 -16
- package/clients/cli/commands/integration-add.doc.mjs +10 -0
- package/clients/cli/commands/integration.mjs +1 -0
- package/clients/cli/commands/search.mjs +11 -2
- package/clients/cli/commands/setup-nudge.test.mjs +6 -0
- package/clients/cli/commands/template.doc.mjs +23 -6
- package/clients/cli/commands/template.mjs +4 -91
- package/clients/cli/index.mjs +8 -0
- package/clients/cli/lib/manifest.mjs +9 -2
- package/foundation/agent-docs/agent-docs.d.mts +3 -2
- package/foundation/agent-docs/agent-docs.mjs +13 -9
- package/foundation/agent-docs/agent-docs.test.mjs +19 -1
- package/foundation/config/project.d.mts +12 -11
- package/foundation/config/project.mjs +73 -59
- package/foundation/config/project.test.mjs +141 -5
- package/foundation/discovery/authoring-self-docs.d.mts +12 -0
- package/foundation/discovery/authoring-self-docs.mjs +20 -8
- package/foundation/discovery/authoring-self-docs.test.mjs +25 -9
- package/foundation/discovery/cli-self-docs.d.mts +40 -34
- package/foundation/discovery/cli-self-docs.mjs +91 -115
- package/foundation/discovery/cli-self-docs.test.mjs +104 -166
- package/foundation/discovery/component-discovery.d.mts +38 -0
- package/foundation/discovery/component-discovery.mjs +48 -0
- package/foundation/discovery/docs-discovery.d.mts +109 -9
- package/foundation/discovery/docs-discovery.mjs +223 -24
- package/foundation/discovery/docs-discovery.test.mjs +103 -27
- package/foundation/discovery/docs-output-budget.d.mts +2 -2
- package/foundation/discovery/docs-output-budget.mjs +1 -1
- package/foundation/discovery/docs-section-key.d.mts +28 -10
- package/foundation/discovery/docs-section-key.mjs +134 -33
- package/foundation/discovery/docs-section-key.test.mjs +41 -19
- package/foundation/discovery/template-adapter.d.mts +92 -6
- package/foundation/discovery/template-adapter.mjs +453 -17
- package/foundation/discovery/template-adapter.test.mjs +42 -0
- package/foundation/discovery/template-conflict-release.d.mts +13 -0
- package/foundation/discovery/template-conflict-release.mjs +40 -0
- package/foundation/discovery/template-conflict-release.test.mjs +40 -0
- package/foundation/doc-compiler/bundle.mjs +61 -1
- package/foundation/doc-compiler/bundle.test.mjs +21 -10
- package/foundation/doc-compiler/compile.d.mts +113 -132
- package/foundation/doc-compiler/compile.mjs +57 -10
- package/foundation/doc-compiler/diagnostics.mjs +28 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +2 -2
- package/foundation/doc-compiler/inputs.d.mts +2 -2
- package/foundation/doc-compiler/inputs.mjs +6 -1
- package/foundation/doc-compiler/ir.mjs +7 -0
- package/foundation/doc-compiler/lenses.d.mts +8 -5
- package/foundation/doc-compiler/lenses.mjs +50 -4
- package/foundation/doc-compiler/links.d.mts +162 -0
- package/foundation/doc-compiler/links.mjs +294 -0
- package/foundation/doc-compiler/links.test.mjs +192 -0
- package/foundation/doc-compiler/lower-doc.test.mjs +5 -2
- package/foundation/doc-compiler/read.d.mts +3 -2
- package/foundation/doc-compiler/read.mjs +6 -1
- package/foundation/doc-compiler/tree.d.mts +288 -0
- package/foundation/doc-compiler/tree.mjs +876 -0
- package/foundation/doc-compiler/tree.test.mjs +598 -0
- package/foundation/integrations/autolink.test.mjs +1 -1
- package/foundation/integrations/cli-requirement.d.mts +45 -0
- package/foundation/integrations/cli-requirement.mjs +154 -0
- package/foundation/integrations/cli-requirement.test.mjs +84 -0
- package/foundation/integrations/contribution-inventory.d.mts +2 -1
- package/foundation/integrations/contribution-inventory.mjs +10 -4
- package/foundation/integrations/contribution-inventory.test.mjs +19 -0
- package/foundation/integrations/integration-warnings.d.mts +9 -2
- package/foundation/integrations/integration-warnings.mjs +51 -26
- package/foundation/integrations/integration-warnings.test.mjs +74 -1
- package/foundation/integrations/validate-contributions.mjs +25 -27
- package/foundation/response/response-types.doc.d.mts +5 -1
- package/foundation/response/response-types.doc.mjs +19 -10
- package/foundation/text/string-utils.d.mts +8 -0
- package/foundation/text/string-utils.mjs +18 -0
- package/foundation/xle/expand.mjs +1 -1
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +9 -9
- package/assets/docs/cli.doc.mjs +0 -15
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Links between docs (spec:AST-047 FR9): the target grammar, and how a
|
|
5
|
+
* list of blocks comes back with every link resolved or named as a problem.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {describe, expect, it} from 'vitest';
|
|
9
|
+
import {
|
|
10
|
+
linkBlocks,
|
|
11
|
+
linkSections,
|
|
12
|
+
parseLinkTarget,
|
|
13
|
+
unlinkText,
|
|
14
|
+
} from './links.mjs';
|
|
15
|
+
|
|
16
|
+
/** A resolver over two docs, the second from another provider. */
|
|
17
|
+
const resolve = async (/** @type {string} */ target) => {
|
|
18
|
+
const docs = {
|
|
19
|
+
'command:doctor': {route: 'cli/commands/doctor', title: 'astryx doctor'},
|
|
20
|
+
'@acme/kit:generic:setup': {route: 'acme/setup', title: 'Set up Acme'},
|
|
21
|
+
};
|
|
22
|
+
const doc = /** @type {any} */ (docs)[target];
|
|
23
|
+
return doc
|
|
24
|
+
? {
|
|
25
|
+
target,
|
|
26
|
+
id: `id:${target}`,
|
|
27
|
+
route: doc.route,
|
|
28
|
+
title: doc.title,
|
|
29
|
+
summary: `About ${doc.title}.`,
|
|
30
|
+
command: `astryx docs ${doc.route}`,
|
|
31
|
+
}
|
|
32
|
+
: {problem: `"${target}" names no doc`};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
describe('parseLinkTarget', () => {
|
|
36
|
+
it('reads a doc of the same provider, or of a named one', () => {
|
|
37
|
+
expect(parseLinkTarget('command:theme build')).toEqual({
|
|
38
|
+
provider: null,
|
|
39
|
+
kind: 'command',
|
|
40
|
+
name: 'theme build',
|
|
41
|
+
});
|
|
42
|
+
expect(parseLinkTarget('@astryxdesign/cli:function:search')).toEqual({
|
|
43
|
+
provider: '@astryxdesign/cli',
|
|
44
|
+
kind: 'function',
|
|
45
|
+
name: 'search',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('refuses a target that is not `[<provider>:]<kind>:<name>`', () => {
|
|
50
|
+
for (const bad of ['', 'search', 'a:b:c:d', 'command:', 'widget:x']) {
|
|
51
|
+
expect(parseLinkTarget(bad)).toHaveProperty('error');
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('linkBlocks', () => {
|
|
57
|
+
it('reads an inline link as the command that opens its doc', async () => {
|
|
58
|
+
const {content, problems} = await linkBlocks(
|
|
59
|
+
[
|
|
60
|
+
{type: 'prose', text: 'Check it with {@link command:doctor}.'},
|
|
61
|
+
{type: 'list', style: 'unordered', items: ['See {@link @acme/kit:generic:setup}']},
|
|
62
|
+
{type: 'table', headers: ['Doc'], rows: [['{@link command:doctor}']]},
|
|
63
|
+
{type: 'code', lang: 'js', code: '{@link command:doctor}'},
|
|
64
|
+
],
|
|
65
|
+
resolve,
|
|
66
|
+
);
|
|
67
|
+
expect(problems).toEqual([]);
|
|
68
|
+
expect(content[0].text).toBe('Check it with `astryx docs cli/commands/doctor`.');
|
|
69
|
+
expect(content[1].items).toEqual(['See `astryx docs acme/setup`']);
|
|
70
|
+
expect(content[2].rows).toEqual([['`astryx docs cli/commands/doctor`']]);
|
|
71
|
+
// Code is an example: it is shown as written.
|
|
72
|
+
expect(content[3].code).toBe('{@link command:doctor}');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('shows a link written in code ticks as written', async () => {
|
|
76
|
+
const {content, problems} = await linkBlocks(
|
|
77
|
+
[{type: 'prose', text: 'Write `{@link <target>}` to link; {@link command:doctor} checks it.'}],
|
|
78
|
+
resolve,
|
|
79
|
+
);
|
|
80
|
+
expect(problems).toEqual([]);
|
|
81
|
+
expect(content[0].text).toBe(
|
|
82
|
+
'Write `{@link <target>}` to link; `astryx docs cli/commands/doctor` checks it.',
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('gives a reference block and each workflow step the doc they name', async () => {
|
|
87
|
+
const {content, problems} = await linkBlocks(
|
|
88
|
+
[
|
|
89
|
+
{type: 'reference', target: 'command:doctor'},
|
|
90
|
+
{
|
|
91
|
+
type: 'workflow',
|
|
92
|
+
steps: [{title: 'Check', references: ['command:doctor']}],
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
resolve,
|
|
96
|
+
);
|
|
97
|
+
expect(problems).toEqual([]);
|
|
98
|
+
expect(content[0].link).toMatchObject({
|
|
99
|
+
route: 'cli/commands/doctor',
|
|
100
|
+
command: 'astryx docs cli/commands/doctor',
|
|
101
|
+
title: 'astryx doctor',
|
|
102
|
+
});
|
|
103
|
+
expect(content[1].steps[0].links[0].command).toBe(
|
|
104
|
+
'astryx docs cli/commands/doctor',
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('includes what a reference block names, and marks what it cannot include', async () => {
|
|
109
|
+
/** @type {any[]} */
|
|
110
|
+
const asked = [];
|
|
111
|
+
const include = async (/** @type {any} */ block) => {
|
|
112
|
+
asked.push(block.target);
|
|
113
|
+
return {
|
|
114
|
+
content: [{type: 'prose', text: 'The doctor command.'}],
|
|
115
|
+
problems: block.projection ? ['projection.fields: no such field'] : [],
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
const {content, problems} = await linkBlocks(
|
|
119
|
+
[
|
|
120
|
+
{type: 'reference', target: 'command:doctor'},
|
|
121
|
+
{
|
|
122
|
+
type: 'reference',
|
|
123
|
+
target: 'command:doctor',
|
|
124
|
+
projection: {fields: ['--nope']},
|
|
125
|
+
},
|
|
126
|
+
{type: 'reference', target: 'command:gone'},
|
|
127
|
+
],
|
|
128
|
+
resolve,
|
|
129
|
+
{section: 'check'},
|
|
130
|
+
include,
|
|
131
|
+
);
|
|
132
|
+
// A target that names no doc is never handed to the includer.
|
|
133
|
+
expect(asked).toEqual(['command:doctor', 'command:doctor']);
|
|
134
|
+
expect(content[0]).toMatchObject({
|
|
135
|
+
link: {command: 'astryx docs cli/commands/doctor'},
|
|
136
|
+
content: [{type: 'prose', text: 'The doctor command.'}],
|
|
137
|
+
});
|
|
138
|
+
expect(content[2]).toEqual({
|
|
139
|
+
type: 'reference',
|
|
140
|
+
target: 'command:gone',
|
|
141
|
+
link: null,
|
|
142
|
+
});
|
|
143
|
+
// Both are the authoring check's: the block includes content, where a
|
|
144
|
+
// link only points at it.
|
|
145
|
+
expect(problems).toEqual([
|
|
146
|
+
{
|
|
147
|
+
target: 'command:doctor',
|
|
148
|
+
message: 'projection.fields: no such field',
|
|
149
|
+
include: true,
|
|
150
|
+
section: 'check',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
target: 'command:gone',
|
|
154
|
+
message: '"command:gone" names no doc',
|
|
155
|
+
include: true,
|
|
156
|
+
section: 'check',
|
|
157
|
+
},
|
|
158
|
+
]);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('names every link that finds no doc, and never guesses', async () => {
|
|
162
|
+
const {content, problems} = await linkSections(
|
|
163
|
+
[
|
|
164
|
+
{
|
|
165
|
+
id: 'one',
|
|
166
|
+
title: 'One',
|
|
167
|
+
content: [
|
|
168
|
+
{type: 'prose', text: 'See {@link command:nope}.'},
|
|
169
|
+
{type: 'reference', target: 'generic:gone'},
|
|
170
|
+
{type: 'collection', source: {slot: 'guides'}},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
resolve,
|
|
175
|
+
).then(({sections, problems}) => ({content: sections[0].content, problems}));
|
|
176
|
+
expect(content[0].text).toBe('See {@link command:nope}.');
|
|
177
|
+
expect(content[1].link).toBeNull();
|
|
178
|
+
expect(problems.map(p => [p.section, p.target])).toEqual([
|
|
179
|
+
['one', 'command:nope'],
|
|
180
|
+
['one', 'generic:gone'],
|
|
181
|
+
['one', 'collection:guides'],
|
|
182
|
+
]);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('unlinkText', () => {
|
|
187
|
+
it('keeps the name of each link, for an index', () => {
|
|
188
|
+
expect(unlinkText('Run {@link command:theme build} or {@link x}.')).toBe(
|
|
189
|
+
'Run theme build or x.',
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -386,7 +386,10 @@ describe('parseCompiledDocNode and parseCompiledDocsBundle', () => {
|
|
|
386
386
|
it('accepts a node of every kind and a bundle, as given', () => {
|
|
387
387
|
const value = bundle();
|
|
388
388
|
expect(parseCompiledDocsBundle(value)).toBe(value);
|
|
389
|
-
expect(COMPILED_DOC_KINDS).toHaveLength(
|
|
389
|
+
expect(COMPILED_DOC_KINDS).toHaveLength(10);
|
|
390
|
+
// A namespace doc, which the docs tree reads, lowers to a node too.
|
|
391
|
+
const namespace = {...node(), kind: 'namespace'};
|
|
392
|
+
expect(parseCompiledDocNode(namespace)).toBe(namespace);
|
|
390
393
|
});
|
|
391
394
|
|
|
392
395
|
it('names schema skew with its own diagnostic, before anything else', () => {
|
|
@@ -413,7 +416,7 @@ describe('parseCompiledDocNode and parseCompiledDocsBundle', () => {
|
|
|
413
416
|
],
|
|
414
417
|
[
|
|
415
418
|
'an unknown kind',
|
|
416
|
-
(/** @type {any} */ n) => (n.kind = '
|
|
419
|
+
(/** @type {any} */ n) => (n.kind = 'workflow'),
|
|
417
420
|
/not a compiled doc kind/,
|
|
418
421
|
],
|
|
419
422
|
[
|
|
@@ -73,11 +73,12 @@ export const DOC_EXPORTS: Readonly<{
|
|
|
73
73
|
hooks: string[];
|
|
74
74
|
templates: string[];
|
|
75
75
|
'self-docs': string[];
|
|
76
|
+
tree: string[];
|
|
76
77
|
}>;
|
|
77
78
|
/** The localized overlays a docs read can apply. */
|
|
78
79
|
export const OVERLAY_LANGUAGES: string[];
|
|
79
80
|
export type ReadOptions = {
|
|
80
|
-
root: "components" | "hooks" | "templates" | "themes" | "self-docs";
|
|
81
|
+
root: "components" | "hooks" | "templates" | "themes" | "self-docs" | "tree";
|
|
81
82
|
/**
|
|
82
83
|
* overlay language; null reads the authored
|
|
83
84
|
* text
|
|
@@ -101,7 +102,7 @@ export type ReadOptions = {
|
|
|
101
102
|
* how to import the module (default
|
|
102
103
|
* `user`)
|
|
103
104
|
*/
|
|
104
|
-
loader?: "template" | "
|
|
105
|
+
loader?: "template" | "native" | "user" | undefined;
|
|
105
106
|
/**
|
|
106
107
|
* which exports name the doc, in
|
|
107
108
|
* precedence order, for a reader that has always read a narrower set than its
|
|
@@ -45,6 +45,8 @@ export const DOC_EXPORTS = Object.freeze({
|
|
|
45
45
|
hooks: ['default', 'docs'],
|
|
46
46
|
templates: ['default', 'doc'],
|
|
47
47
|
'self-docs': ['doc', 'docs', 'default'],
|
|
48
|
+
// The docs tree's own files: namespace docs and the guides it places.
|
|
49
|
+
tree: ['docs', 'default'],
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
/** How a reader imports a doc module. */
|
|
@@ -59,7 +61,7 @@ const LOADERS = Object.freeze({
|
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* @typedef {object} ReadOptions
|
|
62
|
-
* @property {'components' | 'hooks' | 'templates' | 'themes' | 'self-docs'} root
|
|
64
|
+
* @property {'components' | 'hooks' | 'templates' | 'themes' | 'self-docs' | 'tree'} root
|
|
63
65
|
* @property {string | null} [lang] overlay language; null reads the authored
|
|
64
66
|
* text
|
|
65
67
|
* @property {string} [label] how a parse error names the file (default: its
|
|
@@ -307,14 +309,17 @@ export async function loadTopicInput(entry, lang) {
|
|
|
307
309
|
extensions.push({
|
|
308
310
|
...(await loadTopicFile(extension.path, lang)),
|
|
309
311
|
provider: extension.package,
|
|
312
|
+
providerId: extension.providerId ?? extension.package,
|
|
310
313
|
});
|
|
311
314
|
}
|
|
312
315
|
return {
|
|
313
316
|
id: entry.name,
|
|
314
317
|
provider: entry.package,
|
|
318
|
+
providerId: entry.providerId ?? entry.package,
|
|
315
319
|
replaces: entry.replaces ?? null,
|
|
316
320
|
lang,
|
|
317
321
|
base: await loadTopicFile(entry.path, lang),
|
|
318
322
|
extensions,
|
|
323
|
+
...(entry.tree === true ? {tree: true} : {}),
|
|
319
324
|
};
|
|
320
325
|
}
|
|
@@ -0,0 +1,288 @@
|
|
|
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
|
+
* Build the tree. Pure: the same inputs give the same tree, whatever order
|
|
6
|
+
* they arrive in.
|
|
7
|
+
*
|
|
8
|
+
* A doc's home is decided once, in this order: its explicit `placement`, then
|
|
9
|
+
* the one adoption rule in its package that matches its group and kind. A
|
|
10
|
+
* placement that fails withdraws the doc; it never falls back to adoption. A
|
|
11
|
+
* doc with neither is a flat topic: it keeps its flat name as its route, and its
|
|
12
|
+
* home is the generated Unorganized level. The CLI keeps its own routes: an
|
|
13
|
+
* integration's node that would take one is withdrawn with a diagnostic.
|
|
14
|
+
*
|
|
15
|
+
* @param {{namespaces: TreeNamespaceInput[], docs: TreeDocInput[], topics?: TreeTopicInput[]}} inputs
|
|
16
|
+
* @returns {DocsTree}
|
|
17
|
+
*/
|
|
18
|
+
export function buildDocsTree({ namespaces, docs, topics }: {
|
|
19
|
+
namespaces: TreeNamespaceInput[];
|
|
20
|
+
docs: TreeDocInput[];
|
|
21
|
+
topics?: TreeTopicInput[];
|
|
22
|
+
}): DocsTree;
|
|
23
|
+
/**
|
|
24
|
+
* The files under {@link TREE_DOCS_DIR}, sorted.
|
|
25
|
+
* @param {string} [dir]
|
|
26
|
+
* @returns {string[]}
|
|
27
|
+
*/
|
|
28
|
+
export function treeDocFiles(dir?: string): string[];
|
|
29
|
+
/**
|
|
30
|
+
* The CLI's own tree inputs: the namespace docs and guides under
|
|
31
|
+
* assets/docs/tree, and, unless left out, every typed self-doc with its
|
|
32
|
+
* `namespace` group. A file that fails to load or parse is a diagnostic, never
|
|
33
|
+
* a thrown error.
|
|
34
|
+
* @param {{selfDocs?: boolean, dir?: string}} [options]
|
|
35
|
+
* @returns {Promise<{namespaces: TreeNamespaceInput[], docs: TreeDocInput[], diagnostics: CompilerDiagnostic[]}>}
|
|
36
|
+
*/
|
|
37
|
+
export function loadTreeInputs({ selfDocs, dir, }?: {
|
|
38
|
+
selfDocs?: boolean;
|
|
39
|
+
dir?: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
namespaces: TreeNamespaceInput[];
|
|
42
|
+
docs: TreeDocInput[];
|
|
43
|
+
diagnostics: CompilerDiagnostic[];
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* The CLI's own docs tree, built once per process. With `selfDocs: false` it
|
|
47
|
+
* holds only the namespaces and guides, which is all a topic list needs.
|
|
48
|
+
* @param {{selfDocs?: boolean, fresh?: boolean}} [options]
|
|
49
|
+
* @returns {Promise<DocsTree>}
|
|
50
|
+
*/
|
|
51
|
+
export function loadDocsTree({ selfDocs, fresh }?: {
|
|
52
|
+
selfDocs?: boolean;
|
|
53
|
+
fresh?: boolean;
|
|
54
|
+
}): Promise<DocsTree>;
|
|
55
|
+
export { routeSegment };
|
|
56
|
+
/** Where the CLI keeps the docs that only the tree reads. */
|
|
57
|
+
export const TREE_DOCS_DIR: string;
|
|
58
|
+
/** One route segment: lowercase letters and digits joined by single hyphens. */
|
|
59
|
+
export const ROUTE_SEGMENT_RE: RegExp;
|
|
60
|
+
/**
|
|
61
|
+
* The generated level that `groupBy: 'kind'` makes for each kind: its route
|
|
62
|
+
* segment, title, and summary.
|
|
63
|
+
* @type {Readonly<Record<string, {segment: string, title: string, summary: string}>>}
|
|
64
|
+
*/
|
|
65
|
+
export const KIND_GROUPS: Readonly<Record<string, {
|
|
66
|
+
segment: string;
|
|
67
|
+
title: string;
|
|
68
|
+
summary: string;
|
|
69
|
+
}>>;
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {import('../../authoring/doctypes/namespace/type').NamespaceDoc} NamespaceDoc
|
|
72
|
+
* @typedef {import('../../authoring/doctypes/base/type').DocPlacement} DocPlacement
|
|
73
|
+
* @typedef {import('./diagnostics.mjs').CompilerDiagnostic} CompilerDiagnostic
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* @typedef {object} TreeNamespaceInput
|
|
77
|
+
* @property {string} provider the package that owns the namespace
|
|
78
|
+
* @property {string} providerId the provider's ProviderId (its manifest
|
|
79
|
+
* `providerId`, else its package name); node ids are built from it
|
|
80
|
+
* @property {number} [rank] which provider wins a contested route: the CLI's
|
|
81
|
+
* own docs are 0, then each integration in configured order
|
|
82
|
+
* @property {string} source `<package>/<path>` of its file
|
|
83
|
+
* @property {NamespaceDoc} doc
|
|
84
|
+
*/
|
|
85
|
+
/**
|
|
86
|
+
* @typedef {object} TreeDocInput
|
|
87
|
+
* @property {string} provider the package that authored the doc
|
|
88
|
+
* @property {string} providerId the provider's ProviderId (its manifest
|
|
89
|
+
* `providerId`, else its package name); node ids are built from it
|
|
90
|
+
* @property {number} [rank] which provider wins a contested route: the CLI's
|
|
91
|
+
* own docs are 0, then each integration in configured order
|
|
92
|
+
* @property {string} source
|
|
93
|
+
* @property {import('../../authoring/doctypes/base/type').AuthoredDocKind} kind
|
|
94
|
+
* the authored kind: `generic`, `command`, `function`, `schema`, or `enum`
|
|
95
|
+
* @property {string} name the doc's stable name
|
|
96
|
+
* @property {string} title
|
|
97
|
+
* @property {string} summary
|
|
98
|
+
* @property {string | null} group the discovery group adoption reads, or null
|
|
99
|
+
* @property {DocPlacement | undefined} placement
|
|
100
|
+
* @property {any} [ref] what a reader needs to open the doc, carried as given
|
|
101
|
+
*/
|
|
102
|
+
/**
|
|
103
|
+
* @typedef {object} TreeSlot
|
|
104
|
+
* @property {string} name
|
|
105
|
+
* @property {string} title
|
|
106
|
+
* @property {string[]} children child routes, in reading order
|
|
107
|
+
*/
|
|
108
|
+
/**
|
|
109
|
+
* A flat topic: a reference topic that no namespace places. The tree gives it
|
|
110
|
+
* a home in the generated Unorganized level, under its own name.
|
|
111
|
+
* @typedef {object} TreeTopicInput
|
|
112
|
+
* @property {string} provider the package that owns the topic
|
|
113
|
+
* @property {string} providerId the provider's ProviderId
|
|
114
|
+
* @property {string} name the topic's name, which stays its route
|
|
115
|
+
* @property {string} title
|
|
116
|
+
* @property {string} summary
|
|
117
|
+
* @property {string} source where the topic comes from, for diagnostics
|
|
118
|
+
* @property {string[]} [aliases] every other name the topic answers to: the
|
|
119
|
+
* topics it replaced, directly or through a chain
|
|
120
|
+
*/
|
|
121
|
+
/** The route of the generated level that holds every flat topic. */
|
|
122
|
+
export const UNORGANIZED: "unorganized";
|
|
123
|
+
export type NamespaceDoc = import("../../authoring/doctypes/namespace/type").NamespaceDoc;
|
|
124
|
+
export type DocPlacement = import("../../authoring/doctypes/base/type").DocPlacement;
|
|
125
|
+
export type CompilerDiagnostic = import("./diagnostics.mjs").CompilerDiagnostic;
|
|
126
|
+
export type TreeNamespaceInput = {
|
|
127
|
+
/**
|
|
128
|
+
* the package that owns the namespace
|
|
129
|
+
*/
|
|
130
|
+
provider: string;
|
|
131
|
+
/**
|
|
132
|
+
* the provider's ProviderId (its manifest
|
|
133
|
+
* `providerId`, else its package name); node ids are built from it
|
|
134
|
+
*/
|
|
135
|
+
providerId: string;
|
|
136
|
+
/**
|
|
137
|
+
* which provider wins a contested route: the CLI's
|
|
138
|
+
* own docs are 0, then each integration in configured order
|
|
139
|
+
*/
|
|
140
|
+
rank?: number | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* `<package>/<path>` of its file
|
|
143
|
+
*/
|
|
144
|
+
source: string;
|
|
145
|
+
doc: NamespaceDoc;
|
|
146
|
+
};
|
|
147
|
+
export type TreeDocInput = {
|
|
148
|
+
/**
|
|
149
|
+
* the package that authored the doc
|
|
150
|
+
*/
|
|
151
|
+
provider: string;
|
|
152
|
+
/**
|
|
153
|
+
* the provider's ProviderId (its manifest
|
|
154
|
+
* `providerId`, else its package name); node ids are built from it
|
|
155
|
+
*/
|
|
156
|
+
providerId: string;
|
|
157
|
+
/**
|
|
158
|
+
* which provider wins a contested route: the CLI's
|
|
159
|
+
* own docs are 0, then each integration in configured order
|
|
160
|
+
*/
|
|
161
|
+
rank?: number | undefined;
|
|
162
|
+
source: string;
|
|
163
|
+
/**
|
|
164
|
+
* the authored kind: `generic`, `command`, `function`, `schema`, or `enum`
|
|
165
|
+
*/
|
|
166
|
+
kind: import("../../authoring/doctypes/base/type").AuthoredDocKind;
|
|
167
|
+
/**
|
|
168
|
+
* the doc's stable name
|
|
169
|
+
*/
|
|
170
|
+
name: string;
|
|
171
|
+
title: string;
|
|
172
|
+
summary: string;
|
|
173
|
+
/**
|
|
174
|
+
* the discovery group adoption reads, or null
|
|
175
|
+
*/
|
|
176
|
+
group: string | null;
|
|
177
|
+
placement: DocPlacement | undefined;
|
|
178
|
+
/**
|
|
179
|
+
* what a reader needs to open the doc, carried as given
|
|
180
|
+
*/
|
|
181
|
+
ref?: any;
|
|
182
|
+
};
|
|
183
|
+
export type TreeSlot = {
|
|
184
|
+
name: string;
|
|
185
|
+
title: string;
|
|
186
|
+
/**
|
|
187
|
+
* child routes, in reading order
|
|
188
|
+
*/
|
|
189
|
+
children: string[];
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* A flat topic: a reference topic that no namespace places. The tree gives it
|
|
193
|
+
* a home in the generated Unorganized level, under its own name.
|
|
194
|
+
*/
|
|
195
|
+
export type TreeTopicInput = {
|
|
196
|
+
/**
|
|
197
|
+
* the package that owns the topic
|
|
198
|
+
*/
|
|
199
|
+
provider: string;
|
|
200
|
+
/**
|
|
201
|
+
* the provider's ProviderId
|
|
202
|
+
*/
|
|
203
|
+
providerId: string;
|
|
204
|
+
/**
|
|
205
|
+
* the topic's name, which stays its route
|
|
206
|
+
*/
|
|
207
|
+
name: string;
|
|
208
|
+
title: string;
|
|
209
|
+
summary: string;
|
|
210
|
+
/**
|
|
211
|
+
* where the topic comes from, for diagnostics
|
|
212
|
+
*/
|
|
213
|
+
source: string;
|
|
214
|
+
/**
|
|
215
|
+
* every other name the topic answers to: the
|
|
216
|
+
* topics it replaced, directly or through a chain
|
|
217
|
+
*/
|
|
218
|
+
aliases?: string[] | undefined;
|
|
219
|
+
};
|
|
220
|
+
export type TreeNode = {
|
|
221
|
+
/**
|
|
222
|
+
* the doc's DocId, built from its provider's
|
|
223
|
+
* ProviderId, kind, and name: stable when the route moves; null on a
|
|
224
|
+
* generated level, which has no authored doc
|
|
225
|
+
*/
|
|
226
|
+
id: string | null;
|
|
227
|
+
route: string;
|
|
228
|
+
/**
|
|
229
|
+
* `namespace` or the doc's authored kind
|
|
230
|
+
*/
|
|
231
|
+
kind: string;
|
|
232
|
+
/**
|
|
233
|
+
* the package that owns it
|
|
234
|
+
*/
|
|
235
|
+
provider: string;
|
|
236
|
+
/**
|
|
237
|
+
* its provider's ProviderId
|
|
238
|
+
*/
|
|
239
|
+
providerId: string;
|
|
240
|
+
name: string;
|
|
241
|
+
title: string;
|
|
242
|
+
summary: string;
|
|
243
|
+
/**
|
|
244
|
+
* the parent's route; null at the top
|
|
245
|
+
*/
|
|
246
|
+
parent: string | null;
|
|
247
|
+
/**
|
|
248
|
+
* the parent slot this node sits in
|
|
249
|
+
*/
|
|
250
|
+
slot: string | null;
|
|
251
|
+
order: number | null;
|
|
252
|
+
/**
|
|
253
|
+
* made by the compiler (a `groupBy: 'kind'`
|
|
254
|
+
* level, or the Unorganized level), not authored
|
|
255
|
+
*/
|
|
256
|
+
generated: boolean;
|
|
257
|
+
/**
|
|
258
|
+
* a namespace's slots; empty for a leaf
|
|
259
|
+
*/
|
|
260
|
+
slots: TreeSlot[];
|
|
261
|
+
source: string;
|
|
262
|
+
ref?: any;
|
|
263
|
+
};
|
|
264
|
+
export type DocsTree = {
|
|
265
|
+
/**
|
|
266
|
+
* by route, in route order
|
|
267
|
+
*/
|
|
268
|
+
nodes: Map<string, TreeNode>;
|
|
269
|
+
/**
|
|
270
|
+
* sorted
|
|
271
|
+
*/
|
|
272
|
+
diagnostics: CompilerDiagnostic[];
|
|
273
|
+
get: (route: string) => TreeNode | undefined;
|
|
274
|
+
/**
|
|
275
|
+
* the node at a
|
|
276
|
+
* route compared without case, as topic names are
|
|
277
|
+
*/
|
|
278
|
+
getFolded: (route: string) => TreeNode | undefined;
|
|
279
|
+
/**
|
|
280
|
+
* the namespaces with no parent
|
|
281
|
+
*/
|
|
282
|
+
roots: () => TreeNode[];
|
|
283
|
+
/**
|
|
284
|
+
* top first, not the node
|
|
285
|
+
*/
|
|
286
|
+
ancestors: (node: TreeNode) => TreeNode[];
|
|
287
|
+
};
|
|
288
|
+
import { routeSegment } from '../discovery/docs-section-key.mjs';
|