@astryxdesign/cli 0.1.0-canary.a95a267 → 0.1.0-canary.cfbdec3
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/docs/getting-started.doc.mjs +11 -11
- package/docs/styling.doc.mjs +1 -2
- package/package.json +7 -7
- package/src/api/doctor.mjs +3 -3
- package/src/commands/agent-docs.mjs +27 -10
- package/src/commands/agent-docs.test.mjs +21 -21
- package/src/commands/init.mjs +1 -1
- package/src/utils/package-manager.mjs +1 -1
- package/templates/pages/documentation/page.tsx +39 -52
- package/templates/pages/documentation-design/page.tsx +80 -55
- package/templates/pages/documentation-technical/page.tsx +101 -59
- package/templates/pages/ide/page.tsx +167 -236
|
@@ -88,7 +88,7 @@ import {VStack} from '@astryxdesign/core/Layout';
|
|
|
88
88
|
export default function Page() {
|
|
89
89
|
return (
|
|
90
90
|
<VStack gap={2}>
|
|
91
|
-
<Button label="Hello
|
|
91
|
+
<Button label="Hello Astryx" onClick={() => alert('Hi!')} />
|
|
92
92
|
</VStack>
|
|
93
93
|
);
|
|
94
94
|
}`,
|
|
@@ -96,11 +96,11 @@ export default function Page() {
|
|
|
96
96
|
],
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
|
-
title: 'Customize with
|
|
99
|
+
title: 'Customize with StyleX',
|
|
100
100
|
content: [
|
|
101
101
|
{
|
|
102
102
|
type: 'prose',
|
|
103
|
-
text: '
|
|
103
|
+
text: 'Astryx components support various styling solutions, from plain CSS and `className` to Tailwind and CSS-in-JS. See the [styling docs](/docs/styling) for the full guide. Astryx also has a deep integration with [StyleX](https://stylexjs.com/), an atomic CSS-in-JS library: create styles with `stylex.create()` and pass them to components with the `xstyle` prop.',
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
type: 'code',
|
|
@@ -127,19 +127,19 @@ const overrides = stylex.create({
|
|
|
127
127
|
type: 'table',
|
|
128
128
|
headers: ['Example', 'Stack', 'Path'],
|
|
129
129
|
rows: [
|
|
130
|
-
['Next.js', 'Next.js + theme CSS', 'apps/example-nextjs'],
|
|
131
|
-
['Next.js + StyleX', 'Next.js + StyleX for custom styles', 'apps/example-nextjs-stylex'],
|
|
132
|
-
['Next.js + Tailwind', 'Next.js + Tailwind bridge', 'apps/example-nextjs-tailwind'],
|
|
133
|
-
['Next.js Source', 'Next.js importing from source', 'apps/example-nextjs-source'],
|
|
134
|
-
['Vite', 'Vite', 'apps/example-vite'],
|
|
130
|
+
['Next.js', 'Next.js + theme CSS', '[apps/example-nextjs](https://github.com/facebook/astryx/tree/main/apps/example-nextjs)'],
|
|
131
|
+
['Next.js + StyleX', 'Next.js + StyleX for custom styles', '[apps/example-nextjs-stylex](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-stylex)'],
|
|
132
|
+
['Next.js + Tailwind', 'Next.js + Tailwind bridge', '[apps/example-nextjs-tailwind](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-tailwind)'],
|
|
133
|
+
['Next.js Source', 'Next.js importing from source', '[apps/example-nextjs-source](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-source)'],
|
|
134
|
+
['Vite', 'Vite', '[apps/example-vite](https://github.com/facebook/astryx/tree/main/apps/example-vite)'],
|
|
135
135
|
],
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
type: 'code',
|
|
139
139
|
lang: 'bash',
|
|
140
140
|
label: 'Clone and run an example',
|
|
141
|
-
code: `git clone https://github.com/
|
|
142
|
-
cd
|
|
141
|
+
code: `git clone https://github.com/facebook/astryx.git
|
|
142
|
+
cd astryx/apps/example-nextjs
|
|
143
143
|
pnpm install
|
|
144
144
|
pnpm dev`,
|
|
145
145
|
},
|
|
@@ -157,7 +157,7 @@ pnpm dev`,
|
|
|
157
157
|
lang: 'json',
|
|
158
158
|
label: 'package.json',
|
|
159
159
|
code: `"scripts": {
|
|
160
|
-
"
|
|
160
|
+
"astryx": "node node_modules/@astryxdesign/cli/bin/astryx.mjs"
|
|
161
161
|
}`,
|
|
162
162
|
},
|
|
163
163
|
{
|
package/docs/styling.doc.mjs
CHANGED
|
@@ -22,9 +22,8 @@ export const docs = {
|
|
|
22
22
|
type: 'table',
|
|
23
23
|
headers: ['Approach', 'Use for', 'Example'],
|
|
24
24
|
rows: [
|
|
25
|
-
['
|
|
25
|
+
['StyleX', 'Component-specific overrides, reusable styles, pseudo-classes, and typed tokens', 'const styles = stylex.create(...); <Button xstyle={styles.save} />'],
|
|
26
26
|
['Tailwind utilities', 'Layout, wrappers, and utility styling', 'className="flex gap-3 p-4"'],
|
|
27
|
-
['stylex.create', 'Reusable styles, pseudo-classes, typed tokens', 'stylex.create({ card: { ... } })'],
|
|
28
27
|
['className', 'Integrating with external CSS or Tailwind on components', 'className="my-card shadow-lg"'],
|
|
29
28
|
['Styling-library token aliases', 'Keeping Panda, Chakra, MUI, Emotion, styled-components, UnoCSS, CSS Modules, or Sass in sync with the system', "colors.surface = 'var(--color-background-surface)'"],
|
|
30
29
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.cfbdec3",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"jscodeshift": "^17.3.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
58
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
59
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
57
|
+
"@astryxdesign/core": "0.1.0-canary.cfbdec3",
|
|
58
|
+
"@astryxdesign/lab": "0.1.0-canary.cfbdec3",
|
|
59
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.cfbdec3"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@astryxdesign/core": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
74
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
75
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
73
|
+
"@astryxdesign/core": "0.1.0-canary.cfbdec3",
|
|
74
|
+
"@astryxdesign/lab": "0.1.0-canary.cfbdec3",
|
|
75
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.cfbdec3"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"astryx": "node bin/astryx.mjs",
|
package/src/api/doctor.mjs
CHANGED
|
@@ -355,8 +355,8 @@ export function checkAgentDocs(ctx) {
|
|
|
355
355
|
try {
|
|
356
356
|
const content = fs.readFileSync(path.join(ctx.cwd, rel), 'utf-8');
|
|
357
357
|
return (
|
|
358
|
-
content.includes('<!-- XDS:START -->') &&
|
|
359
|
-
content.includes('<!-- XDS:END -->')
|
|
358
|
+
(content.includes('<!-- ASTRYX:START -->') || content.includes('<!-- XDS:START -->')) &&
|
|
359
|
+
(content.includes('<!-- ASTRYX:END -->') || content.includes('<!-- XDS:END -->'))
|
|
360
360
|
);
|
|
361
361
|
} catch {
|
|
362
362
|
return false;
|
|
@@ -368,7 +368,7 @@ export function checkAgentDocs(ctx) {
|
|
|
368
368
|
id: 'agent-docs',
|
|
369
369
|
label: 'AI agent docs',
|
|
370
370
|
status: 'warn',
|
|
371
|
-
message: `Agent docs present (${present.join(', ')}) but no
|
|
371
|
+
message: `Agent docs present (${present.join(', ')}) but no Astryx section markers found.`,
|
|
372
372
|
fix: 'Add the XDS section to your agent docs with `astryx init --features agents`.',
|
|
373
373
|
};
|
|
374
374
|
}
|
|
@@ -31,8 +31,11 @@ const AGENTS_MD = 'AGENTS.md';
|
|
|
31
31
|
const CLAUDE_MD = 'CLAUDE.md';
|
|
32
32
|
const CLAUDE_DIR_MD = path.join('.claude', 'CLAUDE.md');
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const MARKER_START = '<!-- ASTRYX:START -->';
|
|
35
|
+
const MARKER_END = '<!-- ASTRYX:END -->';
|
|
36
|
+
// Legacy markers — read during migration so the script finds existing XDS blocks
|
|
37
|
+
const LEGACY_MARKER_START = '<!-- XDS:START -->';
|
|
38
|
+
const LEGACY_MARKER_END = '<!-- XDS:END -->';
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Agent tool presets — maps tool names to their file search paths.
|
|
@@ -99,7 +102,7 @@ export function resolveAgentPaths(targetDir, agent) {
|
|
|
99
102
|
*/
|
|
100
103
|
export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPrefix()} = {}) {
|
|
101
104
|
const run = `${runPrefix} astryx`;
|
|
102
|
-
const lines = [
|
|
105
|
+
const lines = [MARKER_START];
|
|
103
106
|
|
|
104
107
|
// Component count from live discovery
|
|
105
108
|
let componentCount = '90+';
|
|
@@ -177,7 +180,7 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
|
|
|
177
180
|
lines.push(`${run} swizzle <Name> eject source (--gap to report why)`);
|
|
178
181
|
lines.push(`${run} upgrade --apply codemods after version bump`);
|
|
179
182
|
lines.push(`after @astryxdesign/core bump, always run ${run} upgrade --apply`);
|
|
180
|
-
lines.push(
|
|
183
|
+
lines.push(MARKER_END);
|
|
181
184
|
|
|
182
185
|
return lines.join('\n');
|
|
183
186
|
}
|
|
@@ -218,14 +221,21 @@ export function injectXdsBlock(filePath, compressedIndex, {createIfMissing = fal
|
|
|
218
221
|
if (fs.existsSync(filePath)) {
|
|
219
222
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
220
223
|
|
|
221
|
-
|
|
222
|
-
|
|
224
|
+
// Find existing section — try new markers first, fall back to legacy XDS markers
|
|
225
|
+
let startIdx = content.indexOf(MARKER_START);
|
|
226
|
+
let endIdx = content.indexOf(MARKER_END);
|
|
227
|
+
let markerEndLength = MARKER_END.length;
|
|
228
|
+
if (startIdx === -1) {
|
|
229
|
+
startIdx = content.indexOf(LEGACY_MARKER_START);
|
|
230
|
+
endIdx = content.indexOf(LEGACY_MARKER_END);
|
|
231
|
+
markerEndLength = LEGACY_MARKER_END.length;
|
|
232
|
+
}
|
|
223
233
|
|
|
224
234
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
225
235
|
content =
|
|
226
236
|
content.slice(0, startIdx) +
|
|
227
237
|
compressedIndex +
|
|
228
|
-
content.slice(endIdx +
|
|
238
|
+
content.slice(endIdx + markerEndLength);
|
|
229
239
|
} else if (onlyReplace) {
|
|
230
240
|
// File exists but has no Astryx markers — skip it
|
|
231
241
|
return false;
|
|
@@ -277,13 +287,20 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
|
277
287
|
if (!fs.existsSync(filePath)) return false;
|
|
278
288
|
|
|
279
289
|
let content = fs.readFileSync(filePath, 'utf-8');
|
|
280
|
-
|
|
281
|
-
|
|
290
|
+
// Find existing section — try new markers first, fall back to legacy
|
|
291
|
+
let startIdx = content.indexOf(MARKER_START);
|
|
292
|
+
let endIdx = content.indexOf(MARKER_END);
|
|
293
|
+
let markerEndLen = MARKER_END.length;
|
|
294
|
+
if (startIdx === -1) {
|
|
295
|
+
startIdx = content.indexOf(LEGACY_MARKER_START);
|
|
296
|
+
endIdx = content.indexOf(LEGACY_MARKER_END);
|
|
297
|
+
markerEndLen = LEGACY_MARKER_END.length;
|
|
298
|
+
}
|
|
282
299
|
|
|
283
300
|
if (startIdx === -1 || endIdx === -1) return false;
|
|
284
301
|
|
|
285
302
|
const before = content.slice(0, startIdx).trimEnd();
|
|
286
|
-
const after = content.slice(endIdx +
|
|
303
|
+
const after = content.slice(endIdx + markerEndLen).trimStart();
|
|
287
304
|
content = before + (after ? '\n\n' + after : '') + '\n';
|
|
288
305
|
|
|
289
306
|
if (deleteIfEmpty) {
|
|
@@ -32,8 +32,8 @@ describe('generateCompressedIndex', () => {
|
|
|
32
32
|
it('includes the version number', () => {
|
|
33
33
|
const result = generateCompressedIndex('1.2.3');
|
|
34
34
|
expect(result).toContain('Astryx v1.2.3');
|
|
35
|
-
expect(result).toContain('<!--
|
|
36
|
-
expect(result).toContain('<!--
|
|
35
|
+
expect(result).toContain('<!-- ASTRYX:START -->');
|
|
36
|
+
expect(result).toContain('<!-- ASTRYX:END -->');
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('includes theme nudge rule', () => {
|
|
@@ -82,19 +82,19 @@ describe('injectXdsBlock', () => {
|
|
|
82
82
|
const filePath = path.join(tmpDir, 'test.md');
|
|
83
83
|
fs.writeFileSync(filePath, '# Existing content\n');
|
|
84
84
|
|
|
85
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
85
|
+
const result = injectXdsBlock(filePath, '<!-- ASTRYX:START -->\nnew\n<!-- ASTRYX:END -->');
|
|
86
86
|
|
|
87
87
|
expect(result).toBe(true);
|
|
88
88
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
89
89
|
expect(content).toContain('# Existing content');
|
|
90
|
-
expect(content).toContain('<!--
|
|
90
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('replaces existing markers', () => {
|
|
94
94
|
const filePath = path.join(tmpDir, 'test.md');
|
|
95
95
|
fs.writeFileSync(filePath, 'before\n<!-- XDS:START -->\nold\n<!-- XDS:END -->\nafter\n');
|
|
96
96
|
|
|
97
|
-
injectXdsBlock(filePath, '<!--
|
|
97
|
+
injectXdsBlock(filePath, '<!-- ASTRYX:START -->\nnew\n<!-- ASTRYX:END -->');
|
|
98
98
|
|
|
99
99
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
100
100
|
expect(content).toContain('new');
|
|
@@ -106,7 +106,7 @@ describe('injectXdsBlock', () => {
|
|
|
106
106
|
it('returns false and does not create file when createIfMissing is false', () => {
|
|
107
107
|
const filePath = path.join(tmpDir, 'nonexistent.md');
|
|
108
108
|
|
|
109
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
109
|
+
const result = injectXdsBlock(filePath, '<!-- ASTRYX:START -->\ncontent\n<!-- ASTRYX:END -->');
|
|
110
110
|
|
|
111
111
|
expect(result).toBe(false);
|
|
112
112
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
@@ -116,11 +116,11 @@ describe('injectXdsBlock', () => {
|
|
|
116
116
|
const filePath = path.join(tmpDir, 'test.md');
|
|
117
117
|
fs.writeFileSync(filePath, '# Existing content\n\nNo XDS markers here.\n');
|
|
118
118
|
|
|
119
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
119
|
+
const result = injectXdsBlock(filePath, '<!-- ASTRYX:START -->\nnew\n<!-- ASTRYX:END -->', {onlyReplace: true});
|
|
120
120
|
|
|
121
121
|
expect(result).toBe(false);
|
|
122
122
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
123
|
-
expect(content).not.toContain('<!--
|
|
123
|
+
expect(content).not.toContain('<!-- ASTRYX:START -->');
|
|
124
124
|
expect(content).toBe('# Existing content\n\nNo XDS markers here.\n');
|
|
125
125
|
});
|
|
126
126
|
|
|
@@ -128,7 +128,7 @@ describe('injectXdsBlock', () => {
|
|
|
128
128
|
const filePath = path.join(tmpDir, 'test.md');
|
|
129
129
|
fs.writeFileSync(filePath, 'before\n<!-- XDS:START -->\nold\n<!-- XDS:END -->\nafter\n');
|
|
130
130
|
|
|
131
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
131
|
+
const result = injectXdsBlock(filePath, '<!-- ASTRYX:START -->\nnew\n<!-- ASTRYX:END -->', {onlyReplace: true});
|
|
132
132
|
|
|
133
133
|
expect(result).toBe(true);
|
|
134
134
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
@@ -139,7 +139,7 @@ describe('injectXdsBlock', () => {
|
|
|
139
139
|
it('creates file when createIfMissing is true', () => {
|
|
140
140
|
const filePath = path.join(tmpDir, 'new.md');
|
|
141
141
|
|
|
142
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
142
|
+
const result = injectXdsBlock(filePath, '<!-- ASTRYX:START -->\ncontent\n<!-- ASTRYX:END -->', {
|
|
143
143
|
createIfMissing: true,
|
|
144
144
|
header: '# Header',
|
|
145
145
|
});
|
|
@@ -147,7 +147,7 @@ describe('injectXdsBlock', () => {
|
|
|
147
147
|
expect(result).toBe(true);
|
|
148
148
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
149
149
|
expect(content).toContain('# Header');
|
|
150
|
-
expect(content).toContain('<!--
|
|
150
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
151
151
|
});
|
|
152
152
|
});
|
|
153
153
|
|
|
@@ -157,9 +157,9 @@ describe('injectAgentsMd', () => {
|
|
|
157
157
|
|
|
158
158
|
const content = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
159
159
|
expect(content).toContain('# AGENTS.md');
|
|
160
|
-
expect(content).toContain('<!--
|
|
160
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
161
161
|
expect(content).toContain('Astryx v1.0.0');
|
|
162
|
-
expect(content).toContain('<!--
|
|
162
|
+
expect(content).toContain('<!-- ASTRYX:END -->');
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
it('updates existing AGENTS.md by replacing XDS markers', () => {
|
|
@@ -195,7 +195,7 @@ Existing agent docs.
|
|
|
195
195
|
|
|
196
196
|
const content = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
197
197
|
expect(content).toContain('Existing agent docs.');
|
|
198
|
-
expect(content).toContain('<!--
|
|
198
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
199
199
|
expect(content).toContain('Astryx v1.0.0');
|
|
200
200
|
});
|
|
201
201
|
});
|
|
@@ -210,7 +210,7 @@ describe('injectClaudeMd', () => {
|
|
|
210
210
|
const content = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
211
211
|
expect(content).toContain('# Claude Config');
|
|
212
212
|
expect(content).toContain('Existing rules.');
|
|
213
|
-
expect(content).toContain('<!--
|
|
213
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
214
214
|
expect(content).toContain('Astryx v1.0.0');
|
|
215
215
|
});
|
|
216
216
|
|
|
@@ -322,7 +322,7 @@ describe('installAgentDocs', () => {
|
|
|
322
322
|
expect(fs.existsSync(path.join(tmpDir, '.claude', 'CLAUDE.md'))).toBe(true);
|
|
323
323
|
expect(fs.existsSync(path.join(tmpDir, 'AGENTS.md'))).toBe(false);
|
|
324
324
|
const content = fs.readFileSync(path.join(tmpDir, '.claude', 'CLAUDE.md'), 'utf-8');
|
|
325
|
-
expect(content).toContain('<!--
|
|
325
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
326
326
|
});
|
|
327
327
|
|
|
328
328
|
it('injects into CLAUDE.md at root when it exists', () => {
|
|
@@ -334,7 +334,7 @@ describe('installAgentDocs', () => {
|
|
|
334
334
|
expect(written).toEqual(['CLAUDE.md']);
|
|
335
335
|
expect(fs.existsSync(path.join(tmpDir, 'AGENTS.md'))).toBe(false);
|
|
336
336
|
const claudeContent = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
337
|
-
expect(claudeContent).toContain('<!--
|
|
337
|
+
expect(claudeContent).toContain('<!-- ASTRYX:START -->');
|
|
338
338
|
expect(claudeContent).toContain('Project rules.');
|
|
339
339
|
});
|
|
340
340
|
|
|
@@ -349,8 +349,8 @@ describe('installAgentDocs', () => {
|
|
|
349
349
|
expect(written).toContain('CLAUDE.md');
|
|
350
350
|
const agentsContent = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
351
351
|
const claudeContent = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
352
|
-
expect(agentsContent).toContain('<!--
|
|
353
|
-
expect(claudeContent).toContain('<!--
|
|
352
|
+
expect(agentsContent).toContain('<!-- ASTRYX:START -->');
|
|
353
|
+
expect(claudeContent).toContain('<!-- ASTRYX:START -->');
|
|
354
354
|
});
|
|
355
355
|
|
|
356
356
|
it('updates existing .claude/CLAUDE.md', () => {
|
|
@@ -363,7 +363,7 @@ describe('installAgentDocs', () => {
|
|
|
363
363
|
expect(written).toEqual(['.claude/CLAUDE.md']);
|
|
364
364
|
const content = fs.readFileSync(path.join(tmpDir, '.claude', 'CLAUDE.md'), 'utf-8');
|
|
365
365
|
expect(content).toContain('Existing content.');
|
|
366
|
-
expect(content).toContain('<!--
|
|
366
|
+
expect(content).toContain('<!-- ASTRYX:START -->');
|
|
367
367
|
});
|
|
368
368
|
|
|
369
369
|
it('respects --agent claude preset: finds existing CLAUDE.md', () => {
|
|
@@ -410,7 +410,7 @@ describe('installAgentDocs', () => {
|
|
|
410
410
|
|
|
411
411
|
expect(written).toEqual([]);
|
|
412
412
|
const content = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
413
|
-
expect(content).not.toContain('<!--
|
|
413
|
+
expect(content).not.toContain('<!-- ASTRYX:START -->');
|
|
414
414
|
expect(content).toBe('# Claude\n\nProject rules only.\n');
|
|
415
415
|
});
|
|
416
416
|
|
package/src/commands/init.mjs
CHANGED
|
@@ -248,7 +248,7 @@ export function registerInit(program) {
|
|
|
248
248
|
humanLog(' 2. Optionally add a theme:');
|
|
249
249
|
humanLog(" import { neutralTheme } from '@astryxdesign/theme-neutral'");
|
|
250
250
|
humanLog(' <Theme theme={neutralTheme}>...</Theme>');
|
|
251
|
-
humanLog(` 3. ${run}
|
|
251
|
+
humanLog(` 3. ${run} astryx --help for all commands`);
|
|
252
252
|
humanLog('');
|
|
253
253
|
});
|
|
254
254
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file Detect the project's package manager from lockfiles.
|
|
5
5
|
*
|
|
6
6
|
* Returns the correct command prefix for running package binaries
|
|
7
|
-
* (e.g. 'npx
|
|
7
|
+
* (e.g. 'npx astryx', 'yarn astryx', 'pnpm exec astryx').
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import * as fs from 'node:fs';
|
|
@@ -3,24 +3,23 @@
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
5
|
import * as stylex from '@stylexjs/stylex';
|
|
6
|
-
import {
|
|
7
|
-
SideNav,
|
|
8
|
-
SideNavHeading,
|
|
9
|
-
SideNavItem,
|
|
10
|
-
SideNavSection,
|
|
11
|
-
} from '@astryxdesign/core/SideNav';
|
|
12
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
6
|
+
import {Heading, Text} from '@astryxdesign/core/Text';
|
|
13
7
|
import {Button} from '@astryxdesign/core/Button';
|
|
14
8
|
import {Card} from '@astryxdesign/core/Card';
|
|
9
|
+
import {ClickableCard} from '@astryxdesign/core/ClickableCard';
|
|
15
10
|
import {HStack, VStack, StackItem} from '@astryxdesign/core/Stack';
|
|
16
|
-
import {Layout, LayoutContent
|
|
11
|
+
import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
|
|
17
12
|
import {Grid} from '@astryxdesign/core/Grid';
|
|
18
13
|
import {radiusVars} from '@astryxdesign/core/theme/tokens.stylex';
|
|
19
14
|
|
|
20
15
|
const styles = stylex.create({
|
|
21
16
|
previewCard: {
|
|
22
|
-
borderRadius: radiusVars['--radius-
|
|
23
|
-
|
|
17
|
+
borderRadius: radiusVars['--radius-element'],
|
|
18
|
+
},
|
|
19
|
+
// Negative margin offsets each card's 8px padding so the grid content stays
|
|
20
|
+
// visually aligned while giving every card a padded hover/click target.
|
|
21
|
+
cardGrid: {
|
|
22
|
+
margin: -8,
|
|
24
23
|
},
|
|
25
24
|
});
|
|
26
25
|
|
|
@@ -213,30 +212,12 @@ const COMPONENT_CATEGORIES = [
|
|
|
213
212
|
export default function DocumentationOverviewPage() {
|
|
214
213
|
return (
|
|
215
214
|
<Layout
|
|
216
|
-
height="
|
|
215
|
+
height="auto"
|
|
217
216
|
contentWidth={1200}
|
|
218
|
-
start={
|
|
219
|
-
<LayoutPanel hasDivider padding={0}>
|
|
220
|
-
<SideNav header={<SideNavHeading heading="Product Name" />}>
|
|
221
|
-
<SideNavSection title="Navigation" isHeaderHidden>
|
|
222
|
-
<SideNavItem label="Home" isSelected />
|
|
223
|
-
<SideNavItem label="Getting started" />
|
|
224
|
-
</SideNavSection>
|
|
225
|
-
|
|
226
|
-
{COMPONENT_CATEGORIES.map(category => (
|
|
227
|
-
<SideNavSection key={category.label} title={category.label}>
|
|
228
|
-
{category.items.map(item => (
|
|
229
|
-
<SideNavItem key={item.key} label={item.name} />
|
|
230
|
-
))}
|
|
231
|
-
</SideNavSection>
|
|
232
|
-
))}
|
|
233
|
-
</SideNav>
|
|
234
|
-
</LayoutPanel>
|
|
235
|
-
}
|
|
236
217
|
content={
|
|
237
218
|
<LayoutContent padding={8}>
|
|
238
219
|
<VStack gap={10}>
|
|
239
|
-
<Card variant="
|
|
220
|
+
<Card variant="gray" padding={10}>
|
|
240
221
|
<HStack gap={8} vAlign="center">
|
|
241
222
|
<StackItem size="fill">
|
|
242
223
|
<VStack gap={4}>
|
|
@@ -246,11 +227,7 @@ export default function DocumentationOverviewPage() {
|
|
|
246
227
|
beautiful, accessible products.
|
|
247
228
|
</Text>
|
|
248
229
|
<HStack>
|
|
249
|
-
<Button
|
|
250
|
-
label="Get started"
|
|
251
|
-
variant="primary"
|
|
252
|
-
size="lg"
|
|
253
|
-
/>
|
|
230
|
+
<Button label="Get started" variant="primary" size="lg" />
|
|
254
231
|
</HStack>
|
|
255
232
|
</VStack>
|
|
256
233
|
</StackItem>
|
|
@@ -260,25 +237,35 @@ export default function DocumentationOverviewPage() {
|
|
|
260
237
|
|
|
261
238
|
{COMPONENT_CATEGORIES.map(category => (
|
|
262
239
|
<VStack key={category.label} gap={4}>
|
|
263
|
-
<
|
|
264
|
-
<Grid
|
|
240
|
+
<Heading level={2}>{category.label}</Heading>
|
|
241
|
+
<Grid
|
|
242
|
+
columns={{minWidth: 260}}
|
|
243
|
+
gap={2}
|
|
244
|
+
xstyle={styles.cardGrid}>
|
|
265
245
|
{category.items.map(item => (
|
|
266
|
-
<
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
{
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
246
|
+
<ClickableCard
|
|
247
|
+
key={item.key}
|
|
248
|
+
label={`Open ${item.name}`}
|
|
249
|
+
onClick={() => {}}
|
|
250
|
+
variant="transparent"
|
|
251
|
+
padding={2}>
|
|
252
|
+
<VStack gap={3}>
|
|
253
|
+
<Card
|
|
254
|
+
variant="muted"
|
|
255
|
+
padding={0}
|
|
256
|
+
minHeight={160}
|
|
257
|
+
xstyle={styles.previewCard}
|
|
258
|
+
/>
|
|
259
|
+
<VStack gap={0.5}>
|
|
260
|
+
<Text type="body" weight="bold">
|
|
261
|
+
{item.name}
|
|
262
|
+
</Text>
|
|
263
|
+
<Text type="body" color="secondary" maxLines={3}>
|
|
264
|
+
{item.desc}
|
|
265
|
+
</Text>
|
|
266
|
+
</VStack>
|
|
280
267
|
</VStack>
|
|
281
|
-
</
|
|
268
|
+
</ClickableCard>
|
|
282
269
|
))}
|
|
283
270
|
</Grid>
|
|
284
271
|
</VStack>
|