sparkle-design-cli 1.1.1 → 1.1.3

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.
@@ -4,33 +4,33 @@ import { generateCSS } from '../lib/generate-css.js';
4
4
 
5
5
  // コマンドライン引数を解析
6
6
  function parseArguments() {
7
- const args = process.argv.slice(2);
8
- const options = {
9
- configPath: null,
10
- outputPath: null,
11
- help: false,
12
- };
13
-
14
- for (let i = 0; i < args.length; i++) {
15
- const arg = args[i];
16
-
17
- if (arg === '-h' || arg === '--help') {
18
- options.help = true;
19
- } else if (arg === '-c' || arg === '--config') {
20
- options.configPath = args[i + 1];
21
- i++; // 次の引数をスキップ
22
- } else if (arg === '-o' || arg === '--output') {
23
- options.outputPath = args[i + 1];
24
- i++; // 次の引数をスキップ
25
- }
26
- }
27
-
28
- return options;
7
+ const args = process.argv.slice(2);
8
+ const options = {
9
+ configPath: null,
10
+ outputPath: null,
11
+ help: false,
12
+ };
13
+
14
+ for (let i = 0; i < args.length; i++) {
15
+ const arg = args[i];
16
+
17
+ if (arg === '-h' || arg === '--help') {
18
+ options.help = true;
19
+ } else if (arg === '-c' || arg === '--config') {
20
+ options.configPath = args[i + 1];
21
+ i++; // 次の引数をスキップ
22
+ } else if (arg === '-o' || arg === '--output') {
23
+ options.outputPath = args[i + 1];
24
+ i++; // 次の引数をスキップ
25
+ }
26
+ }
27
+
28
+ return options;
29
29
  }
30
30
 
31
31
  // ヘルプメッセージを表示
32
32
  function showHelp() {
33
- console.log(`
33
+ console.log(`
34
34
  Sparkle Design CLI - デザインシステム CSS 生成ツール
35
35
 
36
36
  使用方法:
@@ -79,19 +79,19 @@ Sparkle Design CLI - デザインシステム CSS 生成ツール
79
79
 
80
80
  // メイン処理
81
81
  function main() {
82
- const options = parseArguments();
83
-
84
- if (options.help) {
85
- showHelp();
86
- process.exit(0);
87
- }
88
-
89
- try {
90
- generateCSS(options.configPath, options.outputPath);
91
- } catch (error) {
92
- console.error('❌ エラーが発生しました:', error.message);
93
- process.exit(1);
94
- }
82
+ const options = parseArguments();
83
+
84
+ if (options.help) {
85
+ showHelp();
86
+ process.exit(0);
87
+ }
88
+
89
+ try {
90
+ generateCSS(options.configPath, options.outputPath);
91
+ } catch (error) {
92
+ console.error('❌ エラーが発生しました:', error.message);
93
+ process.exit(1);
94
+ }
95
95
  }
96
96
 
97
97
  main();
@@ -3,6 +3,7 @@
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import { fileURLToPath } from 'url';
6
+ import { oklch } from 'culori';
6
7
 
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = path.dirname(__filename);
@@ -11,174 +12,180 @@ const __dirname = path.dirname(__filename);
11
12
  * sparkle.config.jsonを読み込む
12
13
  */
13
14
  function loadConfig(configPath = null) {
14
- // カスタムパスが指定されていない場合は実行場所のsparkle.config.jsonを探す
15
- const defaultConfigPath = path.resolve(process.cwd(), 'sparkle.config.json');
16
- const resolvedConfigPath = configPath ? path.resolve(configPath) : defaultConfigPath;
17
-
18
- try {
19
- const configContent = fs.readFileSync(resolvedConfigPath, 'utf8');
20
- const config = JSON.parse(configContent);
21
- console.log('✅ sparkle.config.json を読み込みました:', resolvedConfigPath);
22
- console.log(' 設定内容:', config);
23
- return config;
24
- } catch (error) {
25
- console.error('❌ sparkle.config.json の読み込みに失敗しました:', error.message);
26
- console.error('設定ファイルパス:', resolvedConfigPath);
27
- console.error('設定ファイルは専用プラグインから生成するか、手動で作成してください');
28
- process.exit(1);
29
- }
15
+ // カスタムパスが指定されていない場合は実行場所のsparkle.config.jsonを探す
16
+ const defaultConfigPath = path.resolve(process.cwd(), 'sparkle.config.json');
17
+ const resolvedConfigPath = configPath ? path.resolve(configPath) : defaultConfigPath;
18
+
19
+ try {
20
+ const configContent = fs.readFileSync(resolvedConfigPath, 'utf8');
21
+ const config = JSON.parse(configContent);
22
+ console.log('✅ sparkle.config.json を読み込みました:', resolvedConfigPath);
23
+ console.log(' 設定内容:', config);
24
+ return config;
25
+ } catch (error) {
26
+ console.error('❌ sparkle.config.json の読み込みに失敗しました:', error.message);
27
+ console.error('設定ファイルパス:', resolvedConfigPath);
28
+ console.error('設定ファイルは専用プラグインから生成するか、手動で作成してください');
29
+ process.exit(1);
30
+ }
30
31
  }
31
32
 
32
33
  /**
33
34
  * CSSテンプレートを読み込む
34
35
  */
35
36
  function loadTemplate() {
36
- const templatePath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'sparkle-design.template.css');
37
-
38
- try {
39
- const templateContent = fs.readFileSync(templatePath, 'utf8');
40
- console.log('✅ CSSテンプレートを読み込みました');
41
- return templateContent;
42
- } catch (error) {
43
- console.error('❌ CSSテンプレートの読み込みに失敗しました:', error.message);
44
- console.error('テンプレートファイルが存在することを確認してください:', templatePath);
45
- process.exit(1);
46
- }
37
+ const templatePath = path.join(
38
+ __dirname,
39
+ '..',
40
+ 'templates',
41
+ 'sparkle-variables',
42
+ 'sparkle-design.template.css'
43
+ );
44
+
45
+ try {
46
+ const templateContent = fs.readFileSync(templatePath, 'utf8');
47
+ console.log('✅ CSSテンプレートを読み込みました');
48
+ return templateContent;
49
+ } catch (error) {
50
+ console.error('❌ CSSテンプレートの読み込みに失敗しました:', error.message);
51
+ console.error('テンプレートファイルが存在することを確認してください:', templatePath);
52
+ process.exit(1);
53
+ }
47
54
  }
48
55
 
49
56
  /**
50
57
  * 色定義(colors.json)を読み込む
51
58
  */
52
59
  function loadColors() {
53
- const colorsPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'colors.json');
54
-
55
- try {
56
- const colorsContent = fs.readFileSync(colorsPath, 'utf8');
57
- const colors = JSON.parse(colorsContent);
58
- console.log('✅ colors.json を読み込みました');
59
- return colors;
60
- } catch (error) {
61
- console.error('❌ colors.json の読み込みに失敗しました:', error.message);
62
- process.exit(1);
63
- }
60
+ const colorsPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'colors.json');
61
+
62
+ try {
63
+ const colorsContent = fs.readFileSync(colorsPath, 'utf8');
64
+ const colors = JSON.parse(colorsContent);
65
+ console.log('✅ colors.json を読み込みました');
66
+ return colors;
67
+ } catch (error) {
68
+ console.error('❌ colors.json の読み込みに失敗しました:', error.message);
69
+ process.exit(1);
70
+ }
64
71
  }
65
72
 
66
73
  /**
67
74
  * gray.jsonを読み込む
68
75
  */
69
76
  function loadGrayMapping() {
70
- const grayJsonPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'gray.json');
71
-
72
- try {
73
- const grayContent = fs.readFileSync(grayJsonPath, 'utf8');
74
- const grayMapping = JSON.parse(grayContent);
75
- console.log('✅ gray.json を読み込みました');
76
- return grayMapping;
77
- } catch (error) {
78
- console.error('❌ gray.json の読み込みに失敗しました:', error.message);
79
- process.exit(1);
80
- }
77
+ const grayJsonPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'gray.json');
78
+
79
+ try {
80
+ const grayContent = fs.readFileSync(grayJsonPath, 'utf8');
81
+ const grayMapping = JSON.parse(grayContent);
82
+ console.log('✅ gray.json を読み込みました');
83
+ return grayMapping;
84
+ } catch (error) {
85
+ console.error('❌ gray.json の読み込みに失敗しました:', error.message);
86
+ process.exit(1);
87
+ }
81
88
  }
82
89
 
83
90
  /**
84
91
  * radius.csvを読み込む
85
92
  */
86
93
  function loadRadiusMapping() {
87
- const radiusCsvPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'radius.csv');
88
-
89
- try {
90
- const csvContent = fs.readFileSync(radiusCsvPath, 'utf8');
91
- const lines = csvContent.trim().split('\n');
92
- const headers = lines[0].split(',');
93
- const radiusMapping = {};
94
-
95
- for (let i = 1; i < lines.length; i++) {
96
- const values = lines[i].split(',');
97
- const name = values[0];
98
- radiusMapping[name] = {};
99
-
100
- for (let j = 1; j < headers.length; j++) {
101
- radiusMapping[name][headers[j]] = values[j];
102
- }
103
- }
104
-
105
- console.log('✅ radius.csv を読み込みました');
106
- return radiusMapping;
107
- } catch (error) {
108
- console.error('❌ radius.csv の読み込みに失敗しました:', error.message);
109
- process.exit(1);
110
- }
94
+ const radiusCsvPath = path.join(__dirname, '..', 'templates', 'sparkle-variables', 'radius.csv');
95
+
96
+ try {
97
+ const csvContent = fs.readFileSync(radiusCsvPath, 'utf8');
98
+ const lines = csvContent.trim().split('\n');
99
+ const headers = lines[0].split(',');
100
+ const radiusMapping = {};
101
+
102
+ for (let i = 1; i < lines.length; i++) {
103
+ const values = lines[i].split(',');
104
+ const name = values[0];
105
+ radiusMapping[name] = {};
106
+
107
+ for (let j = 1; j < headers.length; j++) {
108
+ radiusMapping[name][headers[j]] = values[j];
109
+ }
110
+ }
111
+
112
+ console.log('✅ radius.csv を読み込みました');
113
+ return radiusMapping;
114
+ } catch (error) {
115
+ console.error('❌ radius.csv の読み込みに失敗しました:', error.message);
116
+ process.exit(1);
117
+ }
111
118
  }
112
119
 
113
120
  /**
114
121
  * テンプレート変数を設定値で置換する
115
122
  */
116
123
  function processTemplate(template, config, grayMapping, radiusMapping, colors) {
117
- let processedCSS = template;
118
-
119
- // 1. 色のトークンを生成して置換
120
- const colorTokens = generateColorTokens(colors, grayMapping, config.primary);
121
- // プレースホルダーを色のトークンで置換(改行を含む)
122
- processedCSS = processedCSS.replace(/\s*\/\* \{\{COLOR_TOKENS\}\} \*\/\s*/, `\n${colorTokens}\n`);
123
-
124
- // 2. 基本的な設定値による置換
125
- Object.entries(config).forEach(([key, value]) => {
126
- // 通常のプレースホルダー(CSS用 - スペースはそのまま)
127
- const placeholder = `{{${key.toUpperCase().replace('-', '_')}}}`;
128
- processedCSS = processedCSS.replace(new RegExp(placeholder, 'g'), value);
129
-
130
- // フォントファミリーの場合はURL用のプレースホルダーも生成(スペースを+に置き換え)
131
- if (key.toLowerCase().includes('font')) {
132
- const urlPlaceholder = `{{${key.toUpperCase().replace('-', '_')}_URL}}`;
133
- const urlValue = value.replace(/\s+/g, '+');
134
- processedCSS = processedCSS.replace(new RegExp(urlPlaceholder, 'g'), urlValue);
135
- }
136
- });
137
-
138
- // 3. Radiusの一括置換
139
- if (config.radius && radiusMapping[config.radius]) {
140
- const radiusValues = radiusMapping[config.radius];
141
-
142
- Object.entries(radiusValues).forEach(([semanticName, radiusValue]) => {
143
- if (semanticName === 'round') return; // roundは特別扱い
144
-
145
- const semanticPattern = new RegExp(
146
- `--radius-${semanticName}:\\s*var\\(--radius-[^)]+\\)`,
147
- 'g'
148
- );
149
- processedCSS = processedCSS.replace(
150
- semanticPattern,
151
- `--radius-${semanticName}: var(--radius-${radiusValue})`
152
- );
153
- });
154
-
155
- console.log(`✅ ${config.radius}に対応するradius設定を適用しました`);
156
- }
157
-
158
- console.log('✅ テンプレートを設定値で処理しました');
159
- return processedCSS;
124
+ let processedCSS = template;
125
+
126
+ // 1. 色のトークンを生成して置換
127
+ const colorTokens = generateColorTokens(colors, grayMapping, config.primary);
128
+ // プレースホルダーを色のトークンで置換(改行を含む)
129
+ processedCSS = processedCSS.replace(/\s*\/\* \{\{COLOR_TOKENS\}\} \*\/\s*/, `\n${colorTokens}\n`);
130
+
131
+ // 2. 基本的な設定値による置換
132
+ Object.entries(config).forEach(([key, value]) => {
133
+ // 通常のプレースホルダー(CSS用 - スペースはそのまま)
134
+ const placeholder = `{{${key.toUpperCase().replace('-', '_')}}}`;
135
+ processedCSS = processedCSS.replace(new RegExp(placeholder, 'g'), value);
136
+
137
+ // フォントファミリーの場合はURL用のプレースホルダーも生成(スペースを+に置き換え)
138
+ if (key.toLowerCase().includes('font')) {
139
+ const urlPlaceholder = `{{${key.toUpperCase().replace('-', '_')}_URL}}`;
140
+ const urlValue = value.replace(/\s+/g, '+');
141
+ processedCSS = processedCSS.replace(new RegExp(urlPlaceholder, 'g'), urlValue);
142
+ }
143
+ });
144
+
145
+ // 3. Radiusの一括置換
146
+ if (config.radius && radiusMapping[config.radius]) {
147
+ const radiusValues = radiusMapping[config.radius];
148
+
149
+ Object.entries(radiusValues).forEach(([semanticName, radiusValue]) => {
150
+ if (semanticName === 'round') return; // roundは特別扱い
151
+
152
+ const semanticPattern = new RegExp(
153
+ `--radius-${semanticName}:\\s*var\\(--radius-[^)]+\\)`,
154
+ 'g'
155
+ );
156
+ processedCSS = processedCSS.replace(
157
+ semanticPattern,
158
+ `--radius-${semanticName}: var(--radius-${radiusValue})`
159
+ );
160
+ });
161
+
162
+ console.log(`✅ ${config.radius}に対応するradius設定を適用しました`);
163
+ }
164
+
165
+ console.log('✅ テンプレートを設定値で処理しました');
166
+ return processedCSS;
160
167
  }
161
168
 
162
169
  /**
163
170
  * 16進数カラーをrgba形式に変換
164
171
  */
165
172
  function hexToRgba(hex) {
166
- // #を削除
167
- hex = hex.replace('#', '');
168
-
169
- // 3桁の場合は6桁に拡張
170
- if (hex.length === 3) {
171
- hex = hex
172
- .split('')
173
- .map((char) => char + char)
174
- .join('');
175
- }
176
-
177
- const r = parseInt(hex.substring(0, 2), 16);
178
- const g = parseInt(hex.substring(2, 4), 16);
179
- const b = parseInt(hex.substring(4, 6), 16);
180
-
181
- return `rgba(${r}, ${g}, ${b}, 1)`;
173
+ // #を削除
174
+ hex = hex.replace('#', '');
175
+
176
+ // 3桁の場合は6桁に拡張
177
+ if (hex.length === 3) {
178
+ hex = hex
179
+ .split('')
180
+ .map((char) => char + char)
181
+ .join('');
182
+ }
183
+
184
+ const r = parseInt(hex.substring(0, 2), 16);
185
+ const g = parseInt(hex.substring(2, 4), 16);
186
+ const b = parseInt(hex.substring(4, 6), 16);
187
+
188
+ return `rgba(${r}, ${g}, ${b}, 1)`;
182
189
  }
183
190
 
184
191
  /**
@@ -187,68 +194,32 @@ function hexToRgba(hex) {
187
194
  * @returns {string} OKLCH形式の文字列
188
195
  */
189
196
  function hexToOklch(hex) {
190
- // #を削除
191
- hex = hex.replace('#', '');
192
-
193
- // 3桁の場合は6桁に拡張
194
- if (hex.length === 3) {
195
- hex = hex
196
- .split('')
197
- .map((char) => char + char)
198
- .join('');
199
- }
200
-
201
- const r = parseInt(hex.substring(0, 2), 16) / 255;
202
- const g = parseInt(hex.substring(2, 4), 16) / 255;
203
- const b = parseInt(hex.substring(4, 6), 16) / 255;
204
-
205
- // sRGBからLinear RGBに変換
206
- function srgbToLinear(c) {
207
- return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
208
- }
209
-
210
- const linearR = srgbToLinear(r);
211
- const linearG = srgbToLinear(g);
212
- const linearB = srgbToLinear(b);
213
-
214
- // Linear RGBからXYZ(D65)への変換
215
- const x = linearR * 0.4124564 + linearG * 0.3575761 + linearB * 0.1804375;
216
- const y = linearR * 0.2126729 + linearG * 0.7151522 + linearB * 0.0721750;
217
- const z = linearR * 0.0193339 + linearG * 0.1191920 + linearB * 0.9503041;
218
-
219
- // XYZからOKLabへの変換
220
- function f(t) {
221
- const c1 = 0.8359375; // 3^3/29^3
222
- const c2 = 0.2109375; // 1/3^3
223
- const c3 = 29 / (6 ** 3); // 29/6^3
224
-
225
- return t > c1 ? Math.cbrt(t) : c2 * t + c3;
226
- }
227
-
228
- const l = 0.8189330101 * x + 0.3618667424 * y - 0.1288597137 * z;
229
- const m = 0.0329845436 * x + 0.9293118715 * y + 0.0361456387 * z;
230
- const s = 0.0482003018 * x + 0.2643662691 * y + 0.6338517070 * z;
231
-
232
- const fL = f(l);
233
- const fM = f(m);
234
- const fS = f(s);
235
-
236
- const L = 0.2104542553 * fL + 0.7936177850 * fM - 0.0040720468 * fS;
237
- const a = 1.9779984951 * fL - 2.4285922050 * fM + 0.4505937099 * fS;
238
- const b_lab = 0.0259040371 * fL + 0.7827717662 * fM - 0.8086757660 * fS;
239
-
240
- // OKLabからOKLCHへの変換
241
- const lightness = L;
242
- const chroma = Math.sqrt(a * a + b_lab * b_lab);
243
- let hue = Math.atan2(b_lab, a) * 180 / Math.PI;
244
- if (hue < 0) hue += 360;
245
-
246
- // 精度を調整して出力(少数点以下4桁で丸める)
247
- const l_rounded = Math.round(lightness * 10000) / 10000;
248
- const c_rounded = Math.round(chroma * 10000) / 10000;
249
- const h_rounded = chroma < 0.0001 ? 0 : Math.round(hue * 10) / 10;
250
-
251
- return `oklch(${l_rounded} ${c_rounded} ${h_rounded})`;
197
+ // #を削除
198
+ const cleanHex = hex.replace('#', '');
199
+
200
+ // 3桁の場合は6桁に拡張
201
+ const fullHex =
202
+ cleanHex.length === 3
203
+ ? cleanHex
204
+ .split('')
205
+ .map((char) => char + char)
206
+ .join('')
207
+ : cleanHex;
208
+
209
+ // culoriを使用してHEXからOKLCHに変換
210
+ const oklchColor = oklch(`#${fullHex}`);
211
+
212
+ if (!oklchColor) {
213
+ console.warn(`⚠️ 色の変換に失敗しました: ${hex}`);
214
+ return `oklch(0 0 0)`;
215
+ }
216
+
217
+ // 精度を調整して出力
218
+ const l = Math.round((oklchColor.l || 0) * 10000) / 10000;
219
+ const c = Math.round((oklchColor.c || 0) * 10000) / 10000;
220
+ const h = oklchColor.h ? Math.round(oklchColor.h * 10) / 10 : 0;
221
+
222
+ return `oklch(${l} ${c} ${h})`;
252
223
  }
253
224
 
254
225
  /**
@@ -259,109 +230,120 @@ function hexToOklch(hex) {
259
230
  * @returns {string} 色のトークンのCSS文字列
260
231
  */
261
232
  function generateColorTokens(colors, grayMapping, primaryColor) {
262
- const colorTokens = [];
263
-
264
- // 通常の色トークンを生成
265
- Object.entries(colors).forEach(([colorName, colorValues]) => {
266
- if (typeof colorValues === 'object' && colorValues !== null) {
267
- Object.entries(colorValues).forEach(([level, hexValue]) => {
268
- const oklchValue = hexToOklch(hexValue);
269
- colorTokens.push(` --color-${colorName}-${level}: ${oklchValue};`);
270
- });
271
- } else if (typeof colorValues === 'string') {
272
- // black, white, web-focusなどの単色
273
- const oklchValue = hexToOklch(colorValues);
274
- colorTokens.push(` --color-${colorName}: ${oklchValue};`);
275
- }
276
- });
277
-
278
- // グレーの色トークンを生成(プライマリカラーに基づく)
279
- if (primaryColor && grayMapping[primaryColor]) {
280
- const grayColors = grayMapping[primaryColor];
281
- Object.entries(grayColors).forEach(([key, hexValue]) => {
282
- const grayLevel = key === '0' ? '50'
283
- : key === '1' ? '100'
284
- : key === '2' ? '200'
285
- : key === '3' ? '300'
286
- : key === '4' ? '400'
287
- : key === '5' ? '500'
288
- : key === '6' ? '600'
289
- : key === '7' ? '700'
290
- : key === '8' ? '800'
291
- : key === '9' ? '900'
292
- : key;
293
-
294
- const oklchValue = hexToOklch(hexValue);
295
- colorTokens.push(` --color-gray-${grayLevel}: ${oklchValue};`);
296
- });
297
- }
298
-
299
- return colorTokens.join('\n');
233
+ const colorTokens = [];
234
+
235
+ // 通常の色トークンを生成
236
+ Object.entries(colors).forEach(([colorName, colorValues]) => {
237
+ if (typeof colorValues === 'object' && colorValues !== null) {
238
+ Object.entries(colorValues).forEach(([level, hexValue]) => {
239
+ const oklchValue = hexToOklch(hexValue);
240
+ colorTokens.push(` --color-${colorName}-${level}: ${oklchValue};`);
241
+ });
242
+ } else if (typeof colorValues === 'string') {
243
+ // black, white, web-focusなどの単色
244
+ const oklchValue = hexToOklch(colorValues);
245
+ colorTokens.push(` --color-${colorName}: ${oklchValue};`);
246
+ }
247
+ });
248
+
249
+ // グレーの色トークンを生成(プライマリカラーに基づく)
250
+ if (primaryColor && grayMapping[primaryColor]) {
251
+ const grayColors = grayMapping[primaryColor];
252
+ Object.entries(grayColors).forEach(([key, hexValue]) => {
253
+ const grayLevel =
254
+ key === '0'
255
+ ? '50'
256
+ : key === '1'
257
+ ? '100'
258
+ : key === '2'
259
+ ? '200'
260
+ : key === '3'
261
+ ? '300'
262
+ : key === '4'
263
+ ? '400'
264
+ : key === '5'
265
+ ? '500'
266
+ : key === '6'
267
+ ? '600'
268
+ : key === '7'
269
+ ? '700'
270
+ : key === '8'
271
+ ? '800'
272
+ : key === '9'
273
+ ? '900'
274
+ : key;
275
+
276
+ const oklchValue = hexToOklch(hexValue);
277
+ colorTokens.push(` --color-gray-${grayLevel}: ${oklchValue};`);
278
+ });
279
+ }
280
+
281
+ return colorTokens.join('\n');
300
282
  }
301
283
 
302
284
  /**
303
285
  * 生成されたCSSをファイルに書き出す
304
286
  */
305
287
  function writeCSS(cssContent, outputPath = null) {
306
- // カスタムパスが指定されていない場合は実行場所からsrc/appディレクトリに出力
307
- const defaultOutputPath = path.resolve(process.cwd(), 'src', 'app', 'sparkle-design.css');
308
- const resolvedOutputPath = outputPath ? path.resolve(outputPath) : defaultOutputPath;
309
-
310
- try {
311
- // 出力ディレクトリが存在しない場合は作成
312
- const outputDir = path.dirname(resolvedOutputPath);
313
- if (!fs.existsSync(outputDir)) {
314
- fs.mkdirSync(outputDir, { recursive: true });
315
- }
316
-
317
- fs.writeFileSync(resolvedOutputPath, cssContent, 'utf8');
318
- console.log('✅ sparkle-design.css を生成しました:', resolvedOutputPath);
319
- } catch (error) {
320
- console.error('❌ CSSファイルの書き出しに失敗しました:', error.message);
321
- process.exit(1);
322
- }
288
+ // カスタムパスが指定されていない場合は実行場所からsrc/appディレクトリに出力
289
+ const defaultOutputPath = path.resolve(process.cwd(), 'src', 'app', 'sparkle-design.css');
290
+ const resolvedOutputPath = outputPath ? path.resolve(outputPath) : defaultOutputPath;
291
+
292
+ try {
293
+ // 出力ディレクトリが存在しない場合は作成
294
+ const outputDir = path.dirname(resolvedOutputPath);
295
+ if (!fs.existsSync(outputDir)) {
296
+ fs.mkdirSync(outputDir, { recursive: true });
297
+ }
298
+
299
+ fs.writeFileSync(resolvedOutputPath, cssContent, 'utf8');
300
+ console.log('✅ sparkle-design.css を生成しました:', resolvedOutputPath);
301
+ } catch (error) {
302
+ console.error('❌ CSSファイルの書き出しに失敗しました:', error.message);
303
+ process.exit(1);
304
+ }
323
305
  }
324
306
 
325
307
  /**
326
308
  * メイン処理
327
309
  */
328
310
  export function generateCSS(configPath = null, outputPath = null) {
329
- console.log('🚀 Sparkle Design CSS Generator を開始します...\n');
311
+ console.log('🚀 Sparkle Design CSS Generator を開始します...\n');
330
312
 
331
- // 1. 設定ファイルを読み込み
332
- const config = loadConfig(configPath);
313
+ // 1. 設定ファイルを読み込み
314
+ const config = loadConfig(configPath);
333
315
 
334
- // 2. テンプレートを読み込み
335
- const template = loadTemplate();
316
+ // 2. テンプレートを読み込み
317
+ const template = loadTemplate();
336
318
 
337
- // 3. colors.json、gray.json、radius.csvを読み込み
338
- const colors = loadColors();
339
- const grayMapping = loadGrayMapping();
340
- const radiusMapping = loadRadiusMapping();
319
+ // 3. colors.json、gray.json、radius.csvを読み込み
320
+ const colors = loadColors();
321
+ const grayMapping = loadGrayMapping();
322
+ const radiusMapping = loadRadiusMapping();
341
323
 
342
- // 4. テンプレートを設定値で処理
343
- const processedCSS = processTemplate(template, config, grayMapping, radiusMapping, colors);
324
+ // 4. テンプレートを設定値で処理
325
+ const processedCSS = processTemplate(template, config, grayMapping, radiusMapping, colors);
344
326
 
345
- // 5. CSSファイルを書き出し
346
- writeCSS(processedCSS, outputPath);
327
+ // 5. CSSファイルを書き出し
328
+ writeCSS(processedCSS, outputPath);
347
329
 
348
- console.log('\n🎉 CSS生成が完了しました!');
330
+ console.log('\n🎉 CSS生成が完了しました!');
349
331
  }
350
332
 
351
333
  // スクリプトが直接実行された場合のみメイン処理を実行
352
334
  if (import.meta.url === `file://${process.argv[1]}`) {
353
- generateCSS();
335
+ generateCSS();
354
336
  }
355
337
 
356
338
  export {
357
- loadConfig,
358
- loadTemplate,
359
- loadColors,
360
- loadGrayMapping,
361
- loadRadiusMapping,
362
- processTemplate,
363
- writeCSS,
364
- hexToRgba,
365
- hexToOklch,
366
- generateColorTokens,
339
+ loadConfig,
340
+ loadTemplate,
341
+ loadColors,
342
+ loadGrayMapping,
343
+ loadRadiusMapping,
344
+ processTemplate,
345
+ writeCSS,
346
+ hexToRgba,
347
+ hexToOklch,
348
+ generateColorTokens,
367
349
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sparkle-design-cli",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Sparkle Design CSS Generator - デザインシステムCSSを設定ファイルから生成するツール",
5
5
  "main": "lib/generate-css.js",
6
6
  "type": "module",
@@ -24,10 +24,10 @@
24
24
  "author": "Goodpatch Inc. <sparkle-design@goodpatch.com>",
25
25
  "license": "MIT",
26
26
  "devDependencies": {
27
- "power-assert": "^1.6.1",
27
+ "@eslint/js": "^8.57.0",
28
28
  "eslint": "^8.57.0",
29
- "prettier": "^3.2.5",
30
- "@eslint/js": "^8.57.0"
29
+ "power-assert": "^1.6.1",
30
+ "prettier": "^3.2.5"
31
31
  },
32
32
  "files": [
33
33
  "bin/",
@@ -35,5 +35,8 @@
35
35
  "templates/",
36
36
  "README.md",
37
37
  "LICENSE"
38
- ]
38
+ ],
39
+ "dependencies": {
40
+ "culori": "^4.0.2"
41
+ }
39
42
  }
@@ -9,14 +9,14 @@
9
9
  /* {{COLOR_TOKENS}} */
10
10
 
11
11
  /* 角丸変数 */
12
- --radius-none: 0;
13
- --radius-xs: 0.125rem;
14
- --radius-sm: 0.25rem;
15
- --radius-md: 0.5rem;
16
- --radius-lg: 0.75rem;
17
- --radius-xl: 1rem;
18
- --radius-2xl: 1.5rem;
19
- --radius-3xl: 2rem;
12
+ --radius-none: 0; /* 0px */
13
+ --radius-xs: 0.125rem; /* 2px */
14
+ --radius-sm: 0.25rem; /* 4px */
15
+ --radius-md: 0.375rem; /* 6px */
16
+ --radius-lg: 0.5rem; /* 8px */
17
+ --radius-xl: 0.75rem; /* 12px */
18
+ --radius-2xl: 1rem; /* 16px */
19
+ --radius-3xl: 1.5rem; /* 24px */
20
20
  --radius-full: 9999px;
21
21
 
22
22
  /* タイポグラフィ変数 */