sparkle-design-cli 1.5.0 → 1.5.1

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
@@ -111,6 +111,14 @@ sparkle-design-cli check --help
111
111
  - children なしの Button に prefixIcon / suffixIcon を使わない
112
112
  - Material Symbols を className 直書きで使わない
113
113
  - shadcn/ui 既定 token を Sparkle Design 内へ持ち込まない
114
+ - Tailwind デフォルト typography(text-sm, font-medium 等)を使わない
115
+ - CardTitle に typography を上書きしない
116
+ - CardControl に Button / IconButton 以外を入れない
117
+ - CardHeader / CardContent の padding を上書きしない
118
+ - asChild と prefixIcon / suffixIcon / isLoading を併用しない
119
+ - disabled を isDisabled の代わりに使わない
120
+ - Button の prefixIcon に JSX を渡さない
121
+ - Icon の children にテキストを渡さない
114
122
 
115
123
  #### Manual Review Reminders
116
124
 
@@ -119,6 +127,7 @@ sparkle-design-cli check --help
119
127
  - Badge と Tag の意味的な使い分け
120
128
  - CardDescription の typography / color token 明示
121
129
  - Dialog と Modal の UX 上の使い分け
130
+ - 手書き span が Tag で置き換え可能か
122
131
 
123
132
  #### 導入先での推奨設定
124
133
 
@@ -181,8 +190,8 @@ npx --yes sparkle-design-cli setup --assistant generic
181
190
  #### Core(プラグインが出力)
182
191
 
183
192
  - `primary`: プライマリカラー(blue, red, orange など)
184
- - `font-pro`: プロポーショナルフォント(文字列または配列。配列の場合はフォールバックチェーンになる)
185
- - `font-mono`: モノスペースフォント(文字列または配列)
193
+ - `font-pro`: プロポーショナルフォント([Google Fonts](https://fonts.google.com/) の名前)
194
+ - `font-mono`: モノスペースフォント([Google Fonts](https://fonts.google.com/) の名前)
186
195
  - `radius`: 角丸設定(sm, md, lg など)
187
196
 
188
197
  ### extend セクション(拡張設定)
@@ -186,7 +186,15 @@ Check で検出する主なパターン:
186
186
  - DialogCancel / DialogAction を <Button> で二重ラップしている
187
187
  - children なしの Button に prefixIcon / suffixIcon を使っている
188
188
  - Material Symbols を className 直書きしている
189
- - text-muted-foreground / bg-background / border-border を持ち込んでいる
189
+ - shadcn/ui 既定 token(text-muted-foreground 等)を持ち込んでいる
190
+ - Tailwind デフォルト typography(text-sm, font-medium 等)を使っている
191
+ - CardTitle に typography を上書きしている
192
+ - CardControl に Button / IconButton 以外を入れている
193
+ - CardHeader / CardContent の padding を上書きしている
194
+ - asChild と prefixIcon / suffixIcon / isLoading を併用している
195
+ - disabled を isDisabled の代わりに使っている
196
+ - Button の prefixIcon に JSX を渡している
197
+ - Icon の children にテキストを渡している
190
198
 
191
199
  JSON 出力では manualReviewReminders も返すため、AI から実行する場合は --format json を推奨
192
200
  `);
@@ -40,6 +40,11 @@ const MANUAL_REVIEW_REMINDERS = [
40
40
  message:
41
41
  'Dialog が確認用途、Modal が入力・詳細表示用途になっているか確認してください。文脈判断が必要なケースは機械検出されません。',
42
42
  },
43
+ {
44
+ id: 'tag-vs-handwritten-span',
45
+ message:
46
+ 'ステータスバッジ風の手書き span(bg-*-100 text-*-700 rounded-full 等)が Tag コンポーネントで置き換え可能か確認してください。',
47
+ },
43
48
  ];
44
49
 
45
50
  const ANTI_PATTERN_GROUPS = [
@@ -859,10 +864,220 @@ const ANTI_PATTERN_GROUPS = [
859
864
  },
860
865
  ],
861
866
  },
867
+ {
868
+ id: 'tailwind-typography',
869
+ check: {
870
+ description: 'Tailwind デフォルト typography を Sparkle Design コンポーネント内で使わない',
871
+ recommendation:
872
+ 'text-sm / text-xs / text-base / font-medium / font-semibold / font-bold は character-* utility に置き換えてください。',
873
+ pattern: /\b(text-(?:xs|sm|base|lg|xl|2xl)|font-(?:medium|semibold|bold|normal|light))\b/g,
874
+ },
875
+ featureSection: lines([
876
+ '### Tailwind デフォルト typography を使わない',
877
+ '',
878
+ '```tsx',
879
+ '// ✅ Correct — character-* utility を使う',
880
+ '<span className="character-3-regular-pro">テキスト</span>',
881
+ '',
882
+ '// ❌ Wrong — Tailwind デフォルトの typography を使わない',
883
+ '<span className="text-sm font-medium">テキスト</span>',
884
+ '```',
885
+ '',
886
+ 'Sparkle Design コンポーネント内では `character-*-pro` / `character-*-mono` を使用する。Tailwind の `text-sm` / `font-medium` 等は使わない。',
887
+ ]),
888
+ jsdocTargets: [],
889
+ },
890
+ {
891
+ id: 'card-title-typography',
892
+ check: {
893
+ description: 'CardTitle に typography 系クラスを付与しない',
894
+ recommendation:
895
+ 'CardTitle は character-4-bold-pro を内蔵しています。className で typography を上書きしないでください。',
896
+ pattern: /<CardTitle\b[^>]*\bclassName\s*=\s*(?:"[^"]*\bcharacter-[^"]*"|'[^']*\bcharacter-[^']*'|\{[^}]*\bcharacter-[^}]*\})[^>]*>/g,
897
+ },
898
+ featureSection: lines([
899
+ '### CardTitle に typography を上書きしない',
900
+ '',
901
+ '```tsx',
902
+ '// ✅ Correct — CardTitle はデフォルトで character-4-bold-pro が適用される',
903
+ '<CardTitle>タイトル</CardTitle>',
904
+ '',
905
+ '// ❌ Wrong — typography を上書きしない',
906
+ '<CardTitle className="character-2-bold-pro">タイトル</CardTitle>',
907
+ '```',
908
+ ]),
909
+ jsdocTargets: [],
910
+ },
911
+ {
912
+ id: 'card-control-non-button',
913
+ check: {
914
+ description: 'CardControl に Button / IconButton 以外を入れない',
915
+ recommendation:
916
+ 'CardControl はアクションボタン用です。ステータス表示には CardDescription を使ってください。',
917
+ pattern: /<CardControl\b[^>]*>[\s\S]*?<(?!Button\b|IconButton\b|\/CardControl)\w+/g,
918
+ },
919
+ featureSection: lines([
920
+ '### CardControl にはアクションボタンのみを入れる',
921
+ '',
922
+ '```tsx',
923
+ '// ✅ Correct — Button / IconButton を CardControl に入れる',
924
+ '<CardControl>',
925
+ ' <Button>保存</Button>',
926
+ '</CardControl>',
927
+ '',
928
+ '// ❌ Wrong — ステータス表示を CardControl に入れない(CardDescription を使う)',
929
+ '<CardControl>',
930
+ ' <Tag status="negative">警告</Tag>',
931
+ '</CardControl>',
932
+ '```',
933
+ ]),
934
+ jsdocTargets: [
935
+ {
936
+ file: 'src/components/ui/card/index.tsx',
937
+ targetName: 'CardControl',
938
+ section: {
939
+ bullets: [
940
+ {
941
+ ja: 'CardControl にはアクション用の Button / IconButton のみを入れてください。ステータス表示(Tag 等)は CardDescription に入れてください。',
942
+ en: 'CardControl is for action buttons (Button / IconButton) only. Place status displays (Tag, etc.) in CardDescription.',
943
+ },
944
+ ],
945
+ example: lines([
946
+ '// ✅ Correct',
947
+ '<CardControl>',
948
+ ' <Button theme="neutral" variant="outline">キャンセル</Button>',
949
+ ' <Button>保存</Button>',
950
+ '</CardControl>',
951
+ '',
952
+ '// ❌ Wrong - ステータス表示を CardControl に入れない',
953
+ '<CardControl>',
954
+ ' <Tag status="negative">警告</Tag>',
955
+ '</CardControl>',
956
+ ]),
957
+ },
958
+ },
959
+ ],
960
+ },
961
+ {
962
+ id: 'card-padding-override',
963
+ check: {
964
+ description: 'Card 系コンポーネントのデフォルト padding を安易に上書きしない',
965
+ recommendation:
966
+ 'CardHeader / CardContent のデフォルト padding(px-6 py-2)をそのまま使ってください。上書きは本当に必要な場合のみ。',
967
+ pattern: /<Card(?:Header|Content)\b[^>]*\bclassName\s*=\s*(?:"[^"]*\b(?:p-|px-|py-|pt-|pb-|pl-|pr-)[^"]*"|'[^']*\b(?:p-|px-|py-|pt-|pb-|pl-|pr-)[^']*'|\{[^}]*\b(?:p-|px-|py-|pt-|pb-|pl-|pr-)[^}]*\})[^>]*>/g,
968
+ },
969
+ featureSection: lines([
970
+ '### Card 系コンポーネントの padding を上書きしない',
971
+ '',
972
+ '```tsx',
973
+ '// ✅ Correct — デフォルトの padding をそのまま使う',
974
+ '<CardHeader>',
975
+ ' <CardTitle>タイトル</CardTitle>',
976
+ '</CardHeader>',
977
+ '',
978
+ '// ❌ Wrong — padding を安易に上書きしない',
979
+ '<CardHeader className="p-4 pb-2">',
980
+ ' <CardTitle>タイトル</CardTitle>',
981
+ '</CardHeader>',
982
+ '```',
983
+ ]),
984
+ jsdocTargets: [],
985
+ },
986
+ {
987
+ id: 'aschild-with-icon-props',
988
+ check: {
989
+ description: 'asChild 使用時に prefixIcon / suffixIcon / isLoading を使わない',
990
+ recommendation:
991
+ 'asChild モードでは prefixIcon / suffixIcon / isLoading は無視されます。アイコン付きの Link が必要なら asChild を外してください。',
992
+ pattern: /<Button\b(?=[^>]*\basChild\b)(?=[^>]*\b(?:prefixIcon|suffixIcon|isLoading)\b)[^>]*>/g,
993
+ },
994
+ featureSection: lines([
995
+ '### asChild と prefixIcon / suffixIcon / isLoading を併用しない',
996
+ '',
997
+ '```tsx',
998
+ '// ✅ Correct',
999
+ '<Button asChild>',
1000
+ ' <Link href="/items/new">新規作成</Link>',
1001
+ '</Button>',
1002
+ '',
1003
+ '// ❌ Wrong — asChild では prefixIcon は反映されない',
1004
+ '<Button asChild prefixIcon="add">',
1005
+ ' <Link href="/items/new">新規作成</Link>',
1006
+ '</Button>',
1007
+ '```',
1008
+ ]),
1009
+ jsdocTargets: [],
1010
+ },
1011
+ {
1012
+ id: 'disabled-vs-is-disabled',
1013
+ check: {
1014
+ description: 'Sparkle Design コンポーネントでは isDisabled を使う',
1015
+ recommendation:
1016
+ 'Button / Input / Checkbox / IconButton では disabled ではなく isDisabled を使ってください。',
1017
+ pattern: /<(Button|Input|Checkbox|IconButton)\b[^>]*\sdisabled(?!=\s*\{)\b/g,
1018
+ },
1019
+ featureSection: lines([
1020
+ '### disabled ではなく isDisabled を使う',
1021
+ '',
1022
+ '```tsx',
1023
+ '// ✅ Correct',
1024
+ '<Button isDisabled>確定</Button>',
1025
+ '<Input isDisabled placeholder="無効状態" />',
1026
+ '',
1027
+ '// ❌ Wrong — disabled 属性を直接使わない',
1028
+ '<Button disabled>確定</Button>',
1029
+ '```',
1030
+ '',
1031
+ 'HTML 標準の `disabled` も互換のため受け付けますが、Sparkle Design のコードでは `isDisabled` に統一します。',
1032
+ ]),
1033
+ jsdocTargets: [],
1034
+ },
1035
+ {
1036
+ id: 'button-prefixicon-jsx',
1037
+ check: {
1038
+ description: 'Button の prefixIcon / suffixIcon に JSX を渡さない',
1039
+ recommendation:
1040
+ 'prefixIcon / suffixIcon には Material Symbols のアイコン名(文字列)を渡してください。JSX(<Icon ... />)は渡さないでください。',
1041
+ pattern: /<Button\b[^>]*\b(?:prefixIcon|suffixIcon)\s*=\s*\{[^}]*</g,
1042
+ },
1043
+ featureSection: lines([
1044
+ '### Button の prefixIcon / suffixIcon に JSX を渡さない',
1045
+ '',
1046
+ '```tsx',
1047
+ '// ✅ Correct — 文字列でアイコン名を渡す',
1048
+ '<Button prefixIcon="bolt">アクション</Button>',
1049
+ '',
1050
+ '// ❌ Wrong — JSX を渡さない',
1051
+ '<Button prefixIcon={<Icon icon="bolt" size={4} />}>アクション</Button>',
1052
+ '```',
1053
+ ]),
1054
+ jsdocTargets: [],
1055
+ },
1056
+ {
1057
+ id: 'icon-children-text',
1058
+ check: {
1059
+ description: 'Icon の children にテキストを渡さない',
1060
+ recommendation:
1061
+ 'Icon には icon prop でアイコン名を渡してください。children にテキストを渡すのは旧 Material Icons の書き方です。',
1062
+ pattern: /<Icon\b(?:[^>]|\/(?!>))*>[^<]+<\/Icon>/g,
1063
+ },
1064
+ featureSection: lines([
1065
+ '### Icon の children にテキストを渡さない',
1066
+ '',
1067
+ '```tsx',
1068
+ '// ✅ Correct — icon prop を使う',
1069
+ '<Icon icon="chevron_left" size={4} />',
1070
+ '',
1071
+ '// ❌ Wrong — children にテキストを渡さない',
1072
+ '<Icon size={4}>chevron_left</Icon>',
1073
+ '```',
1074
+ ]),
1075
+ jsdocTargets: [],
1076
+ },
862
1077
  ];
863
1078
 
864
1079
  function getCheckRules() {
865
- const order = ['dialog-form', 'dialog-button-wrap', 'button-icon-only', 'material-symbols-direct', 'shadcn-token'];
1080
+ const order = ['dialog-form', 'dialog-button-wrap', 'button-icon-only', 'material-symbols-direct', 'shadcn-token', 'tailwind-typography', 'card-title-typography', 'card-control-non-button', 'card-padding-override', 'aschild-with-icon-props', 'disabled-vs-is-disabled', 'button-prefixicon-jsx', 'icon-children-text'];
866
1081
 
867
1082
  return ANTI_PATTERN_GROUPS.filter((group) => group.check)
868
1083
  .map((group) => ({
@@ -212,7 +212,7 @@ function processTemplate(template, config, grayMapping, radiusMapping, colors) {
212
212
  processedCSS = processedCSS.replace(/\{\{FONT_FAMILY_PRO\}\}/g, proFamilyValue);
213
213
  processedCSS = processedCSS.replace(/\{\{FONT_FAMILY_MONO\}\}/g, monoFamilyValue);
214
214
 
215
- // 5. 基本的な設定値による置換(font-pro / font-mono の配列以外)
215
+ // 5. 基本的な設定値による置換(オブジェクト・配列・拡張フィールドはスキップ)
216
216
  Object.entries(config).forEach(([key, value]) => {
217
217
  // 配列・オブジェクト・拡張フィールドはスキップ
218
218
  if (Array.isArray(value) || (typeof value === 'object' && value !== null) || key === 'custom-css' || key === 'fonts' || key === 'extend' || key === 'source-packages') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sparkle-design-cli",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Sparkle Design CSS Generator - デザインシステムCSSを設定ファイルから生成するツール",
5
5
  "main": "lib/generate-css.js",
6
6
  "type": "module",