sparkle-design-cli 1.3.8 → 1.3.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sparkle Design CLI
2
2
 
3
- デザインシステム CSS を設定ファイルから生成する CLI ツールです。
3
+ Sparkle Design の CSS 生成、導入先プロジェクト向けのアンチパターン検査、AI エージェント向け guard 設定を行う CLI ツールです。
4
4
 
5
5
  ## インストール
6
6
 
@@ -10,7 +10,28 @@ npm install -g sparkle-design-cli
10
10
 
11
11
  ## 使用方法
12
12
 
13
- ### 基本的な使用方法
13
+ ### サブコマンド
14
+
15
+ ```bash
16
+ # CSS を生成
17
+ npx sparkle-design-cli generate
18
+
19
+ # アンチパターンを検査
20
+ npx sparkle-design-cli check src --strict
21
+
22
+ # AI 向けに JSON で検査結果と手動確認項目を取得
23
+ npx sparkle-design-cli check src --format json
24
+
25
+ # Claude / Codex / Cursor 向けの guard 設定を差し込む
26
+ npx sparkle-design-cli setup --assistant claude
27
+ ```
28
+
29
+ ### 後方互換モード
30
+
31
+ 既存の `npx sparkle-design-cli` も引き続き動作し、内部的には `generate` として扱われます。
32
+ ただし後方互換のための動作なので、新規利用やドキュメント上の案内では `sparkle-design-cli generate` を使用してください。
33
+
34
+ ### generate: 基本的な使用方法
14
35
 
15
36
  1. プロジェクトのルートディレクトリに `sparkle.config.json` ファイルを作成または配置します:
16
37
 
@@ -26,39 +47,124 @@ npm install -g sparkle-design-cli
26
47
  2. CLI ツールを実行します:
27
48
 
28
49
  ```bash
29
- npx sparkle-design-cli
50
+ npx sparkle-design-cli generate
30
51
  ```
31
52
 
32
- または、グローバルにインストールした場合:
53
+ 既存プロジェクトでサブコマンドなしの呼び出しを使っている場合も、後方互換として次の実行方法を継続利用できます:
33
54
 
34
55
  ```bash
35
- sparkle-design-cli
56
+ npx sparkle-design-cli
36
57
  ```
37
58
 
38
59
  3. `src/app/sparkle-design.css` に CSS ファイルが生成されます。
39
60
 
40
- ### コマンドオプション
61
+ ### generate: コマンドオプション
41
62
 
42
63
  ```bash
43
64
  # ヘルプを表示
44
- sparkle-design-cli --help
65
+ sparkle-design-cli generate --help
45
66
 
46
67
  # カスタム設定ファイルを指定
47
- sparkle-design-cli --config ./config/design.json
68
+ sparkle-design-cli generate --config ./config/design.json
48
69
 
49
70
  # カスタム出力先を指定
50
- sparkle-design-cli --output ./styles/design.css
71
+ sparkle-design-cli generate --output ./styles/design.css
51
72
 
52
73
  # 設定ファイルと出力先を両方指定
53
- sparkle-design-cli -c ./config/custom.json -o ./dist/styles.css
74
+ sparkle-design-cli generate -c ./config/custom.json -o ./dist/styles.css
54
75
  ```
55
76
 
56
- #### オプション一覧
77
+ #### generate オプション一覧
57
78
 
58
79
  - `-h, --help`: ヘルプメッセージを表示
59
80
  - `-c, --config <パス>`: 設定ファイルのパス(デフォルト: `./sparkle.config.json`)
60
81
  - `-o, --output <パス>`: 出力ファイルのパス(デフォルト: `./src/app/sparkle-design.css`)
61
82
 
83
+ ### check: アンチパターン検査
84
+
85
+ `sparkle-design-cli check` は、導入先プロジェクトで発生しやすい Sparkle Design のアンチパターンを検出します。
86
+
87
+ ```bash
88
+ # src を検査
89
+ sparkle-design-cli check
90
+
91
+ # 特定ディレクトリを strict モードで検査
92
+ sparkle-design-cli check src/components src/features --strict
93
+
94
+ # AI 向けに JSON 出力
95
+ sparkle-design-cli check src --format json
96
+
97
+ # check のヘルプを表示
98
+ sparkle-design-cli check --help
99
+ ```
100
+
101
+ #### check オプション一覧
102
+
103
+ - `-h, --help`: ヘルプメッセージを表示
104
+ - `--strict`: 違反が見つかった場合に exit code 1 で終了
105
+ - `--format <text|json>`: 出力形式。AI 連携では `json` を推奨
106
+
107
+ #### 現在検出するルール
108
+
109
+ - フォーム入力に Dialog を使わない
110
+ - DialogCancel/DialogAction を Button で二重ラップしない
111
+ - children なしの Button に prefixIcon / suffixIcon を使わない
112
+ - Material Symbols を className 直書きで使わない
113
+ - shadcn/ui 既定 token を Sparkle Design 内へ持ち込まない
114
+
115
+ #### Manual Review Reminders
116
+
117
+ `--format json` では、機械検出できない観点も `manualReviewReminders` として返します。現在は次を含みます。
118
+
119
+ - Badge と Tag の意味的な使い分け
120
+ - CardDescription の typography / color token 明示
121
+ - Dialog と Modal の UX 上の使い分け
122
+
123
+ #### 導入先での推奨設定
124
+
125
+ ```json
126
+ {
127
+ "scripts": {
128
+ "lint:sparkle": "sparkle-design-cli check src --strict"
129
+ }
130
+ }
131
+ ```
132
+
133
+ AI エージェントや CI からこの `lint:sparkle` を呼ぶ運用にすると、ガイドラインの注意書きだけに頼らず機械的に検査できます。
134
+
135
+ ### setup: AI ガード設定の差し込み
136
+
137
+ `sparkle-design-cli setup` は、導入先プロジェクトの `package.json` と AI 向け指示ファイルに Sparkle Design guard を追加します。
138
+
139
+ ```bash
140
+ # Claude Code 向け
141
+ sparkle-design-cli setup --assistant claude
142
+
143
+ # Codex / AGENTS.md 向け
144
+ sparkle-design-cli setup --assistant codex
145
+
146
+ # Cursor rules 向け
147
+ sparkle-design-cli setup --assistant cursor
148
+
149
+ # generic な Markdown を生成
150
+ sparkle-design-cli setup --assistant generic
151
+ ```
152
+
153
+ 追加されるもの:
154
+ - `package.json` の `lint:sparkle`
155
+ - `package.json` の `lint:sparkle:json`
156
+ - assistant ごとの指示ファイルへの managed block
157
+
158
+ `--target` を省略した場合は `src`, `src/components`, `src/features`, `app`, `components` の順で自動検出します。既存の `lint:sparkle*` がすでに Sparkle Design 向け script なら再実行時に更新されます。独自 script は保持され、上書きしたい場合だけ `--force-script-update` を付けます。
159
+
160
+ 利用できる assistant:
161
+ - `claude`: `CLAUDE.md`
162
+ - `codex`: `AGENTS.md`
163
+ - `cursor`: `.cursor/rules/sparkle-design-guard.mdc`
164
+ - `generic`: `SPARKLE-DESIGN-AI.md`
165
+
166
+ `setup` は通常実行時も JSON サマリーを stdout に表示します。`--dry-run` を付けると、その JSON を表示したままファイル変更だけを抑止します。
167
+
62
168
  ## 設定ファイル (sparkle.config.json)
63
169
 
64
170
  ### 設定ファイルの作成
@@ -105,12 +211,12 @@ sparkle-design-cli -c ./config/custom.json -o ./dist/styles.css
105
211
  生成される `globals.css`:
106
212
 
107
213
  ```css
108
- @import "tailwindcss";
214
+ @import 'tailwindcss';
109
215
  /* npm パッケージのコンテンツスキャン(Tailwind がクラスを検出するために必要) */
110
216
  @source "../node_modules/@goodpatch/sparkle-design/dist";
111
217
  @source "../node_modules/@scope/my-extension-design/dist";
112
218
  /* Sparkle Design のカスタム定義(Tailwindの後にインポート) */
113
- @import "./sparkle-design.css";
219
+ @import './sparkle-design.css';
114
220
  ```
115
221
 
116
222
  > **注意**: `source-packages` を指定しない場合、`@source` ディレクティブは生成されません。
@@ -192,14 +298,17 @@ npm run format:check
192
298
  ### CLI実行テスト
193
299
 
194
300
  ```bash
195
- # デフォルト設定でテスト
301
+ # CSS生成
302
+ sparkle-design-cli generate
303
+
304
+ # 既存呼び出しの後方互換モード
196
305
  sparkle-design-cli
197
306
 
198
307
  # ヘルプ表示
199
- sparkle-design-cli --help
308
+ sparkle-design-cli generate --help
200
309
 
201
- # カスタムパスでテスト
202
- sparkle-design-cli -c test-config.json -o test-output.css
310
+ # 検査
311
+ sparkle-design-cli check src --strict
203
312
  ```
204
313
 
205
314
  ## ライセンス
@@ -1,93 +1,252 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { generateCSS } from '../lib/generate-css.js';
4
+ import { checkProject } from '../lib/check.js';
5
+ import { setupAssistant } from '../lib/setup.js';
4
6
 
5
- // コマンドライン引数を解析
6
- function parseArguments() {
7
- const args = process.argv.slice(2);
7
+ const SUBCOMMANDS = new Set(['generate', 'check', 'setup']);
8
+
9
+ function requireOptionValue(args, index, flags) {
10
+ const value = args[index + 1];
11
+ if (!value || value.startsWith('-')) {
12
+ throw new Error(`Missing value for ${flags}`);
13
+ }
14
+ return value;
15
+ }
16
+
17
+ function parseGenerateOptions(args) {
8
18
  const options = {
9
19
  configPath: null,
10
20
  outputPath: null,
11
21
  help: false,
12
22
  };
13
23
 
14
- for (let i = 0; i < args.length; i++) {
24
+ for (let i = 0; i < args.length; i += 1) {
15
25
  const arg = args[i];
16
26
 
17
27
  if (arg === '-h' || arg === '--help') {
18
28
  options.help = true;
19
29
  } else if (arg === '-c' || arg === '--config') {
20
- options.configPath = args[i + 1];
21
- i++; // 次の引数をスキップ
30
+ options.configPath = requireOptionValue(args, i, '-c/--config');
31
+ i += 1;
22
32
  } else if (arg === '-o' || arg === '--output') {
23
- options.outputPath = args[i + 1];
24
- i++; // 次の引数をスキップ
33
+ options.outputPath = requireOptionValue(args, i, '-o/--output');
34
+ i += 1;
35
+ } else {
36
+ throw new Error(`Unknown option for generate: ${arg}`);
37
+ }
38
+ }
39
+
40
+ return options;
41
+ }
42
+
43
+ function parseCheckOptions(args) {
44
+ const options = {
45
+ targets: [],
46
+ strict: false,
47
+ format: 'text',
48
+ help: false,
49
+ };
50
+
51
+ for (let i = 0; i < args.length; i += 1) {
52
+ const arg = args[i];
53
+
54
+ if (arg === '-h' || arg === '--help') {
55
+ options.help = true;
56
+ } else if (arg === '--strict') {
57
+ options.strict = true;
58
+ } else if (arg === '--format') {
59
+ const value = requireOptionValue(args, i, '--format');
60
+ if (value !== 'text' && value !== 'json') {
61
+ throw new Error(`Unsupported format for check: ${value}`);
62
+ }
63
+ options.format = value;
64
+ i += 1;
65
+ } else if (arg.startsWith('-')) {
66
+ throw new Error(`Unknown option for check: ${arg}`);
67
+ } else {
68
+ options.targets.push(arg);
69
+ }
70
+ }
71
+
72
+ return options;
73
+ }
74
+
75
+ function parseSetupOptions(args) {
76
+ const options = {
77
+ assistant: 'generic',
78
+ target: null,
79
+ dryRun: false,
80
+ forceScriptUpdate: false,
81
+ help: false,
82
+ };
83
+
84
+ for (let i = 0; i < args.length; i += 1) {
85
+ const arg = args[i];
86
+
87
+ if (arg === '-h' || arg === '--help') {
88
+ options.help = true;
89
+ } else if (arg === '--assistant') {
90
+ options.assistant = requireOptionValue(args, i, '--assistant');
91
+ i += 1;
92
+ } else if (arg === '--target') {
93
+ options.target = requireOptionValue(args, i, '--target');
94
+ i += 1;
95
+ } else if (arg === '--dry-run') {
96
+ options.dryRun = true;
97
+ } else if (arg === '--force-script-update') {
98
+ options.forceScriptUpdate = true;
99
+ } else {
100
+ throw new Error(`Unknown option for setup: ${arg}`);
25
101
  }
26
102
  }
27
103
 
28
104
  return options;
29
105
  }
30
106
 
31
- // ヘルプメッセージを表示
32
107
  function showHelp() {
33
108
  console.log(`
34
- Sparkle Design CLI - デザインシステム CSS 生成ツール
109
+ Sparkle Design CLI
35
110
 
36
111
  使用方法:
37
- sparkle-design-cli [オプション]
112
+ sparkle-design-cli <command> [options]
113
+
114
+ Commands:
115
+ generate sparkle.config.json から CSS を生成
116
+ check Sparkle Design のアンチパターンを検査
117
+ setup AI エージェント向けの guard 設定を導入
38
118
 
39
- 基本的な使用方法:
40
- 1. プロジェクトのルートディレクトリに sparkle.config.json ファイルを作成または配置
41
- 2. CLI ツールを実行: sparkle-design-cli
42
- 3. src/app/sparkle-design.css に CSS ファイルが生成されます
119
+ 後方互換:
120
+ sparkle-design-cli [generate options]
121
+ サブコマンドなしの実行は現在も generate として動作しますが、
122
+ 正式リリース時に削除予定です。今後は sparkle-design-cli generate を使ってください。
43
123
 
44
- オプション:
124
+ Generate:
125
+ sparkle-design-cli generate
126
+ sparkle-design-cli generate --config ./config/design.json
127
+ sparkle-design-cli generate --output ./styles/design.css
128
+ sparkle-design-cli generate -c ./config/custom.json -o ./dist/styles.css
129
+
130
+ Check:
131
+ sparkle-design-cli check
132
+ sparkle-design-cli check src --strict
133
+ sparkle-design-cli check src --format json
134
+ sparkle-design-cli check src/components src/features
135
+
136
+ Setup:
137
+ sparkle-design-cli setup --assistant claude
138
+ sparkle-design-cli setup --assistant codex --target src
139
+ sparkle-design-cli setup --assistant cursor --dry-run
140
+ sparkle-design-cli setup --assistant claude --force-script-update
141
+
142
+ Generate options:
45
143
  -h, --help このヘルプメッセージを表示
46
- -c, --config <パス> 設定ファイルのパス (デフォルト: ./sparkle.config.json)
47
- -o, --output <パス> 出力ファイルのパス (デフォルト: ./src/app/sparkle-design.css)
48
-
49
- 使用例:
50
- sparkle-design-cli
51
- sparkle-design-cli --config ./config/design.json
52
- sparkle-design-cli --output ./styles/design.css
53
- sparkle-design-cli -c ./config/custom.json -o ./dist/styles.css
54
-
55
- 設定ファイル (sparkle.config.json):
56
- 設定ファイルは専用のプラグインから自動生成することを推奨します。
57
- プロジェクトのルートディレクトリに配置してください。
58
-
59
- 設定例:
60
- {
61
- "primary": "blue",
62
- "font-pro": "BIZ UDPGothic",
63
- "font-mono": "BIZ UDGothic",
64
- "radius": "md"
65
- }
144
+ -c, --config <path> 設定ファイルのパス (default: ./sparkle.config.json)
145
+ -o, --output <path> 出力ファイルのパス (default: ./src/app/sparkle-design.css)
66
146
 
67
- 設定オプション:
68
- - primary: プライマリカラー (blue, red, orange など)
69
- - font-pro: プロポーショナルフォント (Google Fonts の名前)
70
- - font-mono: モノスペースフォント (Google Fonts の名前)
71
- - radius: 角丸設定 (sm, md, lg など)
147
+ Check options:
148
+ -h, --help このヘルプメッセージを表示
149
+ --strict 違反があれば exit code 1 で終了
150
+ --format <text|json> 出力形式 (default: text)
72
151
 
73
- 出力:
74
- - デフォルト出力先: src/app/sparkle-design.css
75
- - カスタム出力先: -o オプションで指定可能
76
- - 実行場所を基準として相対パスで処理されます
152
+ Setup options:
153
+ -h, --help このヘルプメッセージを表示
154
+ --assistant <name> claude / codex / cursor / generic (default: generic)
155
+ --target <path> lint 対象パス (default: auto-detect)
156
+ --dry-run ファイルを変更せず結果だけ表示
157
+ --force-script-update 既存の lint:sparkle 系 script も上書きする
158
+
159
+ Check で検出する主なパターン:
160
+ - フォーム入力に Dialog を使っている
161
+ - DialogCancel / DialogAction を <Button> で二重ラップしている
162
+ - children なしの Button に prefixIcon / suffixIcon を使っている
163
+ - Material Symbols を className 直書きしている
164
+ - text-muted-foreground / bg-background / border-border を持ち込んでいる
165
+
166
+ JSON 出力では manualReviewReminders も返すため、AI から実行する場合は --format json を推奨
77
167
  `);
78
168
  }
79
169
 
80
- // メイン処理
81
- function main() {
82
- const options = parseArguments();
170
+ function showGenerateDeprecationNotice() {
171
+ console.warn(
172
+ '[sparkle-design-cli] Running without a subcommand defaults to `generate`. ' +
173
+ 'Use `sparkle-design-cli generate` instead. This compatibility mode will be removed at the formal release.'
174
+ );
175
+ }
83
176
 
84
- if (options.help) {
85
- showHelp();
86
- process.exit(0);
87
- }
177
+ function main() {
178
+ const args = process.argv.slice(2);
179
+ const command = args[0];
88
180
 
89
181
  try {
90
- generateCSS(options.configPath, options.outputPath);
182
+ if (args.length === 0) {
183
+ showGenerateDeprecationNotice();
184
+ generateCSS();
185
+ return;
186
+ }
187
+
188
+ if (command === '-h' || command === '--help') {
189
+ showHelp();
190
+ process.exit(0);
191
+ }
192
+ if (command === 'generate') {
193
+ const options = parseGenerateOptions(args.slice(1));
194
+
195
+ if (options.help) {
196
+ showHelp();
197
+ process.exit(0);
198
+ }
199
+
200
+ generateCSS(options.configPath, options.outputPath);
201
+ return;
202
+ }
203
+
204
+ if (command === 'check') {
205
+ const options = parseCheckOptions(args.slice(1));
206
+
207
+ if (options.help) {
208
+ showHelp();
209
+ process.exit(0);
210
+ }
211
+
212
+ const hasFindings = checkProject(options.targets, {
213
+ strict: options.strict,
214
+ format: options.format,
215
+ });
216
+ if (hasFindings && options.strict) {
217
+ process.exit(1);
218
+ }
219
+ return;
220
+ }
221
+
222
+ if (command === 'setup') {
223
+ const options = parseSetupOptions(args.slice(1));
224
+
225
+ if (options.help) {
226
+ showHelp();
227
+ process.exit(0);
228
+ }
229
+
230
+ setupAssistant(options);
231
+ return;
232
+ }
233
+
234
+ if (!SUBCOMMANDS.has(command) && command.startsWith('-')) {
235
+ showGenerateDeprecationNotice();
236
+ const options = parseGenerateOptions(args);
237
+
238
+ if (options.help) {
239
+ showHelp();
240
+ process.exit(0);
241
+ }
242
+
243
+ generateCSS(options.configPath, options.outputPath);
244
+ return;
245
+ }
246
+
247
+ if (!SUBCOMMANDS.has(command)) {
248
+ throw new Error(`Unknown command: ${command}`);
249
+ }
91
250
  } catch (error) {
92
251
  console.error('❌ エラーが発生しました:', error.message);
93
252
  process.exit(1);