@vadenai/mcp-server 0.3.0 → 0.3.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.
@@ -1,5 +1,6 @@
1
1
  import { componentMetadata } from "../guides/component-metadata.js";
2
2
  import { generateComponentGuide } from "../guides/generate-guide.js";
3
+ import { resolveVisualProperties, } from "../utils/tailwind-resolver.js";
3
4
  let cache = new WeakMap();
4
5
  const CACHE_TTL_MS = 5 * 60 * 1000; // 5分
5
6
  function getClientCache(client) {
@@ -307,8 +308,156 @@ function formatStyleSection(data) {
307
308
  }
308
309
  lines.push("");
309
310
  }
311
+ // --- Resolved Styles ---
312
+ const resolvedStyleEntries = [];
313
+ if (type === "single") {
314
+ const baseStylesValue = data.baseStyles;
315
+ if (typeof baseStylesValue === "string" && baseStylesValue.trim()) {
316
+ resolvedStyleEntries.push({
317
+ label: "baseStyles",
318
+ props: resolveVisualProperties(baseStylesValue, resolvedColors ?? {}),
319
+ });
320
+ }
321
+ }
322
+ else if (type === "multipart") {
323
+ const slotsObj = data.slots;
324
+ if (slotsObj && typeof slotsObj === "object") {
325
+ for (const [slotName, classes] of Object.entries(slotsObj)) {
326
+ if (typeof classes !== "string" || !classes.trim())
327
+ continue;
328
+ resolvedStyleEntries.push({
329
+ label: slotName,
330
+ props: resolveVisualProperties(classes, resolvedColors ?? {}),
331
+ });
332
+ }
333
+ }
334
+ }
335
+ // --- Variant Resolved Styles ---
336
+ const resolvedVariantEntries = [];
337
+ const variants = data.variants;
338
+ if (variants && typeof variants === "object") {
339
+ for (const [groupName, groupVariants] of Object.entries(variants)) {
340
+ if (!groupVariants || typeof groupVariants !== "object")
341
+ continue;
342
+ for (const [variantName, classes] of Object.entries(groupVariants)) {
343
+ if (typeof classes !== "string" || !classes.trim())
344
+ continue;
345
+ resolvedVariantEntries.push({
346
+ group: groupName,
347
+ name: variantName,
348
+ props: resolveVisualProperties(classes, resolvedColors ?? {}),
349
+ });
350
+ }
351
+ }
352
+ }
353
+ if (resolvedStyleEntries.length > 0 || resolvedVariantEntries.length > 0) {
354
+ lines.push("## Resolved Styles");
355
+ lines.push("");
356
+ lines.push("Visual properties resolved from Style Config classes and design tokens.");
357
+ lines.push("Use these values for accurate rendering in design tools (Figma, Framer, etc.).");
358
+ lines.push("");
359
+ for (const { label, props } of resolvedStyleEntries) {
360
+ const propLines = formatResolvedProps(props);
361
+ if (propLines.length > 0) {
362
+ lines.push(`**${label}**:`);
363
+ for (const line of propLines) {
364
+ lines.push(`- ${line}`);
365
+ }
366
+ lines.push("");
367
+ }
368
+ }
369
+ if (resolvedVariantEntries.length > 0) {
370
+ lines.push("### Variants");
371
+ lines.push("");
372
+ let currentGroup = "";
373
+ for (const { group, name, props } of resolvedVariantEntries) {
374
+ const propLines = formatResolvedProps(props);
375
+ if (propLines.length === 0)
376
+ continue;
377
+ if (group !== currentGroup) {
378
+ lines.push(`**${group}**:`);
379
+ currentGroup = group;
380
+ }
381
+ lines.push(` *${name}*:`);
382
+ for (const line of propLines) {
383
+ lines.push(` - ${line}`);
384
+ }
385
+ }
386
+ lines.push("");
387
+ }
388
+ }
310
389
  return lines.join("\n");
311
390
  }
391
+ function formatResolvedProps(props) {
392
+ const result = [];
393
+ if (props.display)
394
+ result.push(`display: ${props.display}`);
395
+ if (props.width)
396
+ result.push(`width: ${props.width}`);
397
+ if (props.height)
398
+ result.push(`height: ${props.height}`);
399
+ if (props.aspectRatio)
400
+ result.push(`aspect-ratio: ${props.aspectRatio}`);
401
+ if (props.overflow)
402
+ result.push(`overflow: ${props.overflow}`);
403
+ if (props.borderRadius)
404
+ result.push(`border-radius: ${props.borderRadius}`);
405
+ if (props.border) {
406
+ const style = props.borderStyle ?? (props.border.color ? "solid" : undefined);
407
+ const parts = [
408
+ props.border.width,
409
+ style,
410
+ props.border.color || undefined,
411
+ ].filter(Boolean);
412
+ result.push(`border: ${parts.join(" ")}`);
413
+ }
414
+ if (props.backgroundColor)
415
+ result.push(`background-color: ${props.backgroundColor}`);
416
+ if (props.color)
417
+ result.push(`color: ${props.color}`);
418
+ if (props.fontWeight)
419
+ result.push(`font-weight: ${props.fontWeight}`);
420
+ if (props.fontSize)
421
+ result.push(`font-size: ${props.fontSize}`);
422
+ if (props.objectFit)
423
+ result.push(`object-fit: ${props.objectFit}`);
424
+ if (props.alignItems)
425
+ result.push(`align-items: ${props.alignItems}`);
426
+ if (props.justifyContent)
427
+ result.push(`justify-content: ${props.justifyContent}`);
428
+ if (props.opacity)
429
+ result.push(`opacity: ${props.opacity}`);
430
+ if (props.boxShadow)
431
+ result.push(`box-shadow: ${props.boxShadow}`);
432
+ if (props.padding)
433
+ result.push(`padding: ${props.padding}`);
434
+ if (props.paddingX)
435
+ result.push(`padding-inline: ${props.paddingX}`);
436
+ if (props.paddingY)
437
+ result.push(`padding-block: ${props.paddingY}`);
438
+ if (props.paddingTop)
439
+ result.push(`padding-top: ${props.paddingTop}`);
440
+ if (props.paddingBottom)
441
+ result.push(`padding-bottom: ${props.paddingBottom}`);
442
+ if (props.paddingLeft)
443
+ result.push(`padding-left: ${props.paddingLeft}`);
444
+ if (props.paddingRight)
445
+ result.push(`padding-right: ${props.paddingRight}`);
446
+ if (props.gap)
447
+ result.push(`gap: ${props.gap}`);
448
+ if (props.letterSpacing)
449
+ result.push(`letter-spacing: ${props.letterSpacing}`);
450
+ if (props.flexShrink)
451
+ result.push(`flex-shrink: ${props.flexShrink}`);
452
+ if (props.borderStyle && !props.border)
453
+ result.push(`border-style: ${props.borderStyle}`);
454
+ if (props.fontFamily)
455
+ result.push(`font-family: ${props.fontFamily}`);
456
+ if (props.gradient) {
457
+ result.push(`background: ${props.gradient}`);
458
+ }
459
+ return result;
460
+ }
312
461
  /** テスト用にキャッシュをクリアする */
313
462
  export function clearRegistryCache() {
314
463
  cache = new WeakMap();
@@ -0,0 +1,35 @@
1
+ export interface ResolvedVisualProperties {
2
+ width?: string;
3
+ height?: string;
4
+ borderRadius?: string;
5
+ border?: {
6
+ width: string;
7
+ color: string;
8
+ };
9
+ backgroundColor?: string;
10
+ color?: string;
11
+ fontWeight?: string;
12
+ fontSize?: string;
13
+ overflow?: string;
14
+ objectFit?: string;
15
+ aspectRatio?: string;
16
+ display?: string;
17
+ alignItems?: string;
18
+ justifyContent?: string;
19
+ opacity?: string;
20
+ boxShadow?: string;
21
+ padding?: string;
22
+ paddingX?: string;
23
+ paddingY?: string;
24
+ paddingTop?: string;
25
+ paddingBottom?: string;
26
+ paddingLeft?: string;
27
+ paddingRight?: string;
28
+ gap?: string;
29
+ letterSpacing?: string;
30
+ flexShrink?: string;
31
+ borderStyle?: string;
32
+ fontFamily?: string;
33
+ gradient?: string;
34
+ }
35
+ export declare function resolveVisualProperties(classes: string, resolvedColors: Record<string, unknown>): ResolvedVisualProperties;
@@ -0,0 +1,632 @@
1
+ const SIZE_MAP = {
2
+ "0": "0px",
3
+ "0.5": "2px",
4
+ "1": "4px",
5
+ "1.5": "6px",
6
+ "2": "8px",
7
+ "2.5": "10px",
8
+ "3": "12px",
9
+ "3.5": "14px",
10
+ "4": "16px",
11
+ "5": "20px",
12
+ "6": "24px",
13
+ "7": "28px",
14
+ "8": "32px",
15
+ "9": "36px",
16
+ "10": "40px",
17
+ "11": "44px",
18
+ "12": "48px",
19
+ "14": "56px",
20
+ "16": "64px",
21
+ "20": "80px",
22
+ "24": "96px",
23
+ full: "100%",
24
+ };
25
+ const RADIUS_MAP = {
26
+ none: "0px",
27
+ sm: "0.125rem",
28
+ "": "0.25rem",
29
+ md: "0.375rem",
30
+ lg: "0.5rem",
31
+ xl: "0.75rem",
32
+ "2xl": "1rem",
33
+ "3xl": "1.5rem",
34
+ full: "9999px",
35
+ };
36
+ const FONT_WEIGHT_MAP = {
37
+ thin: "100",
38
+ extralight: "200",
39
+ light: "300",
40
+ normal: "400",
41
+ medium: "500",
42
+ semibold: "600",
43
+ bold: "700",
44
+ extrabold: "800",
45
+ black: "900",
46
+ };
47
+ const FONT_SIZE_MAP = {
48
+ xs: "0.75rem",
49
+ sm: "0.875rem",
50
+ base: "1rem",
51
+ lg: "1.125rem",
52
+ xl: "1.25rem",
53
+ "2xl": "1.5rem",
54
+ "3xl": "1.875rem",
55
+ };
56
+ const STATIC_COLORS = {
57
+ white: "#ffffff",
58
+ black: "#000000",
59
+ transparent: "transparent",
60
+ };
61
+ const TAILWIND_PALETTE = {
62
+ // Gray
63
+ "gray-50": "#f9fafb",
64
+ "gray-100": "#f3f4f6",
65
+ "gray-200": "#e5e7eb",
66
+ "gray-300": "#d1d5db",
67
+ "gray-400": "#9ca3af",
68
+ "gray-500": "#6b7280",
69
+ "gray-600": "#4b5563",
70
+ "gray-700": "#374151",
71
+ "gray-800": "#1f2937",
72
+ "gray-900": "#111827",
73
+ // Pink
74
+ "pink-50": "#fdf2f8",
75
+ "pink-100": "#fce7f3",
76
+ "pink-200": "#fbcfe8",
77
+ "pink-300": "#f9a8d4",
78
+ "pink-400": "#f472b6",
79
+ "pink-500": "#ec4899",
80
+ "pink-600": "#db2777",
81
+ "pink-700": "#be185d",
82
+ "pink-800": "#9d174d",
83
+ "pink-900": "#831843",
84
+ // Purple
85
+ "purple-400": "#a78bfa",
86
+ "purple-500": "#8b5cf6",
87
+ "purple-600": "#7c3aed",
88
+ "purple-900": "#4c1d95",
89
+ // Cyan
90
+ "cyan-400": "#22d3ee",
91
+ "cyan-500": "#06b6d4",
92
+ // Yellow
93
+ "yellow-200": "#fef08a",
94
+ "yellow-400": "#facc15",
95
+ // Red
96
+ "red-500": "#ef4444",
97
+ "red-600": "#dc2626",
98
+ // Green
99
+ "green-500": "#22c55e",
100
+ // Blue
101
+ "blue-500": "#3b82f6",
102
+ "blue-600": "#2563eb",
103
+ };
104
+ const SHADOW_MAP = {
105
+ sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
106
+ "": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
107
+ md: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
108
+ lg: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
109
+ xl: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 10px 10px -5px rgb(0 0 0 / 0.1)",
110
+ "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
111
+ none: "none",
112
+ };
113
+ const TRACKING_MAP = {
114
+ tighter: "-0.05em",
115
+ tight: "-0.025em",
116
+ normal: "0em",
117
+ wide: "0.025em",
118
+ wider: "0.05em",
119
+ widest: "0.1em",
120
+ };
121
+ const FONT_FAMILY_MAP = {
122
+ sans: "sans-serif",
123
+ serif: "serif",
124
+ mono: "monospace",
125
+ body: "var(--font-body)",
126
+ heading: "var(--font-heading)",
127
+ };
128
+ const GRADIENT_DIR_MAP = {
129
+ r: "right",
130
+ l: "left",
131
+ t: "top",
132
+ b: "bottom",
133
+ tr: "top right",
134
+ tl: "top left",
135
+ br: "bottom right",
136
+ bl: "bottom left",
137
+ };
138
+ const FONT_SIZE_KEYS = new Set(Object.keys(FONT_SIZE_MAP));
139
+ function normalizeHex(hex) {
140
+ const h = hex.replace("#", "");
141
+ if (h.length === 3) {
142
+ return `#${h[0]}${h[0]}${h[1]}${h[1]}${h[2]}${h[2]}`;
143
+ }
144
+ if (h.length === 4) {
145
+ const r = parseInt(`${h[0]}${h[0]}`, 16);
146
+ const g = parseInt(`${h[1]}${h[1]}`, 16);
147
+ const b = parseInt(`${h[2]}${h[2]}`, 16);
148
+ const a = parseInt(`${h[3]}${h[3]}`, 16) / 255;
149
+ return `rgba(${r},${g},${b},${Number(a.toFixed(3))})`;
150
+ }
151
+ if (h.length === 8) {
152
+ const r = parseInt(h.slice(0, 2), 16);
153
+ const g = parseInt(h.slice(2, 4), 16);
154
+ const b = parseInt(h.slice(4, 6), 16);
155
+ const a = parseInt(h.slice(6, 8), 16) / 255;
156
+ return `rgba(${r},${g},${b},${Number(a.toFixed(3))})`;
157
+ }
158
+ return `#${h.slice(0, 6)}`;
159
+ }
160
+ function parseArbitraryValue(val) {
161
+ const m = val.match(/^\[(.+)\]$/);
162
+ // Tailwind の arbitrary value では _ はスペースとして扱われる
163
+ // e.g. w-[calc(100%_-_1rem)] → calc(100% - 1rem)
164
+ return m ? m[1].replace(/_/g, " ") : null;
165
+ }
166
+ function resolveColorValue(value, resolvedColors) {
167
+ // 0. Arbitrary bracket color: [#hex], [rgba(...)], [hsl(...)], [oklch(...)]
168
+ const arbitrary = parseArbitraryValue(value);
169
+ if (arbitrary) {
170
+ // raw hex
171
+ if (/^#([0-9a-fA-F]{3,8})$/.test(arbitrary)) {
172
+ return normalizeHex(arbitrary);
173
+ }
174
+ // css function: rgba(...), hsl(...), oklch(...)
175
+ if (/^(rgba?|hsla?|oklch)\(.+\)$/i.test(arbitrary)) {
176
+ return arbitrary;
177
+ }
178
+ return null;
179
+ }
180
+ // 0.5. Raw hex without brackets (used in gradient stops like from-#hex)
181
+ if (/^#([0-9a-fA-F]{3,8})$/.test(value)) {
182
+ return normalizeHex(value);
183
+ }
184
+ // 1a. Bracket opacity: {name}/[0.05]
185
+ const bracketOpacityMatch = value.match(/^(.+)\/\[([0-9.]+)\]$/);
186
+ if (bracketOpacityMatch) {
187
+ const [, colorName, opacityStr] = bracketOpacityMatch;
188
+ const opacity = Number(opacityStr);
189
+ if (colorName === "white")
190
+ return `rgba(255,255,255,${opacity})`;
191
+ if (colorName === "black")
192
+ return `rgba(0,0,0,${opacity})`;
193
+ const baseColor = resolveColorValue(colorName, resolvedColors);
194
+ if (baseColor?.startsWith("#")) {
195
+ const r = parseInt(baseColor.slice(1, 3), 16);
196
+ const g = parseInt(baseColor.slice(3, 5), 16);
197
+ const b = parseInt(baseColor.slice(5, 7), 16);
198
+ return `rgba(${r},${g},${b},${opacity})`;
199
+ }
200
+ }
201
+ // 1b. Opacity-suffixed colors: white/10, black/50, primary/10
202
+ const opacityMatch = value.match(/^(.+)\/(\d+)$/);
203
+ if (opacityMatch) {
204
+ const [, colorName, opacityStr] = opacityMatch;
205
+ const opacity = Number(opacityStr) / 100;
206
+ if (colorName === "white")
207
+ return `rgba(255,255,255,${opacity})`;
208
+ if (colorName === "black")
209
+ return `rgba(0,0,0,${opacity})`;
210
+ // Try resolving semantic color
211
+ const baseColor = resolveColorValue(colorName, resolvedColors);
212
+ if (baseColor?.startsWith("#")) {
213
+ const r = parseInt(baseColor.slice(1, 3), 16);
214
+ const g = parseInt(baseColor.slice(3, 5), 16);
215
+ const b = parseInt(baseColor.slice(5, 7), 16);
216
+ return `rgba(${r},${g},${b},${opacity})`;
217
+ }
218
+ }
219
+ // 2. Static colors
220
+ if (value in STATIC_COLORS) {
221
+ return STATIC_COLORS[value];
222
+ }
223
+ // 2.5 Tailwind palette colors (e.g. gray-300, pink-400)
224
+ if (value in TAILWIND_PALETTE) {
225
+ return TAILWIND_PALETTE[value];
226
+ }
227
+ // 3. Semantic tokens from resolvedColors
228
+ // muted-foreground → resolvedColors.muted.foreground
229
+ // foreground → resolvedColors.base.foreground
230
+ // muted → resolvedColors.muted.background
231
+ // primary → resolvedColors.primary.background
232
+ // destructive → resolvedColors.destructive (if string)
233
+ // Handle compound tokens like "muted-foreground", "primary-foreground"
234
+ const dashIndex = value.indexOf("-");
235
+ if (dashIndex !== -1) {
236
+ const prefix = value.substring(0, dashIndex);
237
+ const suffix = value.substring(dashIndex + 1);
238
+ const group = resolvedColors[prefix];
239
+ if (group && typeof group === "object" && group !== null) {
240
+ const resolved = group[suffix];
241
+ if (typeof resolved === "string") {
242
+ return resolved;
243
+ }
244
+ }
245
+ return null;
246
+ }
247
+ // Handle simple tokens
248
+ if (value === "foreground") {
249
+ const base = resolvedColors.base;
250
+ if (base && typeof base === "object" && base !== null) {
251
+ const fg = base.foreground;
252
+ if (typeof fg === "string")
253
+ return fg;
254
+ }
255
+ return null;
256
+ }
257
+ if (value === "background") {
258
+ const base = resolvedColors.base;
259
+ if (base && typeof base === "object" && base !== null) {
260
+ const bg = base.background;
261
+ if (typeof bg === "string")
262
+ return bg;
263
+ }
264
+ return null;
265
+ }
266
+ // For tokens like "muted", "primary" → look up .background
267
+ const group = resolvedColors[value];
268
+ if (typeof group === "string") {
269
+ return group;
270
+ }
271
+ if (group && typeof group === "object" && group !== null) {
272
+ const bg = group.background;
273
+ if (typeof bg === "string")
274
+ return bg;
275
+ }
276
+ return null;
277
+ }
278
+ export function resolveVisualProperties(classes, resolvedColors) {
279
+ const result = {};
280
+ const tokens = classes.split(/\s+/).filter(Boolean);
281
+ for (const token of tokens) {
282
+ // Height
283
+ if (token.startsWith("h-")) {
284
+ const val = token.slice(2);
285
+ if (val === "screen") {
286
+ result.height = "100vh";
287
+ }
288
+ else if (val in SIZE_MAP) {
289
+ result.height = SIZE_MAP[val];
290
+ }
291
+ else {
292
+ const arb = parseArbitraryValue(val);
293
+ if (arb)
294
+ result.height = arb;
295
+ }
296
+ continue;
297
+ }
298
+ // Width
299
+ if (token.startsWith("w-")) {
300
+ const val = token.slice(2);
301
+ if (val === "screen") {
302
+ result.width = "100vw";
303
+ }
304
+ else if (val in SIZE_MAP) {
305
+ result.width = SIZE_MAP[val];
306
+ }
307
+ else {
308
+ const arb = parseArbitraryValue(val);
309
+ if (arb)
310
+ result.width = arb;
311
+ }
312
+ continue;
313
+ }
314
+ // Padding (check px-/py-/pt-/pb-/pl-/pr- before p- to avoid false match)
315
+ if (token.startsWith("px-")) {
316
+ const val = token.slice(3);
317
+ if (val in SIZE_MAP)
318
+ result.paddingX = SIZE_MAP[val];
319
+ else {
320
+ const arb = parseArbitraryValue(val);
321
+ if (arb)
322
+ result.paddingX = arb;
323
+ }
324
+ continue;
325
+ }
326
+ if (token.startsWith("py-")) {
327
+ const val = token.slice(3);
328
+ if (val in SIZE_MAP)
329
+ result.paddingY = SIZE_MAP[val];
330
+ else {
331
+ const arb = parseArbitraryValue(val);
332
+ if (arb)
333
+ result.paddingY = arb;
334
+ }
335
+ continue;
336
+ }
337
+ if (token.startsWith("pt-")) {
338
+ const val = token.slice(3);
339
+ if (val in SIZE_MAP)
340
+ result.paddingTop = SIZE_MAP[val];
341
+ else {
342
+ const arb = parseArbitraryValue(val);
343
+ if (arb)
344
+ result.paddingTop = arb;
345
+ }
346
+ continue;
347
+ }
348
+ if (token.startsWith("pb-")) {
349
+ const val = token.slice(3);
350
+ if (val in SIZE_MAP)
351
+ result.paddingBottom = SIZE_MAP[val];
352
+ else {
353
+ const arb = parseArbitraryValue(val);
354
+ if (arb)
355
+ result.paddingBottom = arb;
356
+ }
357
+ continue;
358
+ }
359
+ if (token.startsWith("pl-")) {
360
+ const val = token.slice(3);
361
+ if (val in SIZE_MAP)
362
+ result.paddingLeft = SIZE_MAP[val];
363
+ else {
364
+ const arb = parseArbitraryValue(val);
365
+ if (arb)
366
+ result.paddingLeft = arb;
367
+ }
368
+ continue;
369
+ }
370
+ if (token.startsWith("pr-")) {
371
+ const val = token.slice(3);
372
+ if (val in SIZE_MAP)
373
+ result.paddingRight = SIZE_MAP[val];
374
+ else {
375
+ const arb = parseArbitraryValue(val);
376
+ if (arb)
377
+ result.paddingRight = arb;
378
+ }
379
+ continue;
380
+ }
381
+ if (token.startsWith("p-")) {
382
+ const val = token.slice(2);
383
+ if (val in SIZE_MAP)
384
+ result.padding = SIZE_MAP[val];
385
+ else {
386
+ const arb = parseArbitraryValue(val);
387
+ if (arb)
388
+ result.padding = arb;
389
+ }
390
+ continue;
391
+ }
392
+ // Gap
393
+ if (token.startsWith("gap-")) {
394
+ const val = token.slice(4);
395
+ if (val in SIZE_MAP)
396
+ result.gap = SIZE_MAP[val];
397
+ else {
398
+ const arb = parseArbitraryValue(val);
399
+ if (arb)
400
+ result.gap = arb;
401
+ }
402
+ continue;
403
+ }
404
+ // Letter-spacing (tracking)
405
+ if (token.startsWith("tracking-")) {
406
+ const val = token.slice(9);
407
+ if (val in TRACKING_MAP)
408
+ result.letterSpacing = TRACKING_MAP[val];
409
+ continue;
410
+ }
411
+ // Flex-shrink
412
+ if (token === "shrink-0") {
413
+ result.flexShrink = "0";
414
+ continue;
415
+ }
416
+ if (token === "shrink") {
417
+ result.flexShrink = "1";
418
+ continue;
419
+ }
420
+ // Border radius
421
+ if (token === "rounded") {
422
+ result.borderRadius = "0.25rem";
423
+ continue;
424
+ }
425
+ if (token.startsWith("rounded-")) {
426
+ const val = token.slice(8);
427
+ if (val in RADIUS_MAP) {
428
+ result.borderRadius = RADIUS_MAP[val];
429
+ }
430
+ continue;
431
+ }
432
+ // Display
433
+ if (token === "flex") {
434
+ result.display = "flex";
435
+ continue;
436
+ }
437
+ if (token === "inline-flex") {
438
+ result.display = "inline-flex";
439
+ continue;
440
+ }
441
+ if (token === "grid") {
442
+ result.display = "grid";
443
+ continue;
444
+ }
445
+ // Align items
446
+ if (token === "items-center") {
447
+ result.alignItems = "center";
448
+ continue;
449
+ }
450
+ if (token === "items-start") {
451
+ result.alignItems = "flex-start";
452
+ continue;
453
+ }
454
+ if (token === "items-end") {
455
+ result.alignItems = "flex-end";
456
+ continue;
457
+ }
458
+ // Justify content
459
+ if (token === "justify-center") {
460
+ result.justifyContent = "center";
461
+ continue;
462
+ }
463
+ if (token === "justify-between") {
464
+ result.justifyContent = "space-between";
465
+ continue;
466
+ }
467
+ // Overflow
468
+ if (token === "overflow-hidden") {
469
+ result.overflow = "hidden";
470
+ continue;
471
+ }
472
+ // Aspect ratio
473
+ if (token === "aspect-square") {
474
+ result.aspectRatio = "1/1";
475
+ continue;
476
+ }
477
+ if (token === "aspect-video") {
478
+ result.aspectRatio = "16/9";
479
+ continue;
480
+ }
481
+ // Object fit
482
+ if (token === "object-cover") {
483
+ result.objectFit = "cover";
484
+ continue;
485
+ }
486
+ if (token === "object-contain") {
487
+ result.objectFit = "contain";
488
+ continue;
489
+ }
490
+ // Font family / weight
491
+ if (token.startsWith("font-")) {
492
+ const val = token.slice(5);
493
+ if (val in FONT_FAMILY_MAP) {
494
+ result.fontFamily = FONT_FAMILY_MAP[val];
495
+ continue;
496
+ }
497
+ if (val in FONT_WEIGHT_MAP) {
498
+ result.fontWeight = FONT_WEIGHT_MAP[val];
499
+ }
500
+ continue;
501
+ }
502
+ // Opacity
503
+ if (token.startsWith("opacity-")) {
504
+ const val = token.slice(8);
505
+ const num = Number(val);
506
+ if (!Number.isNaN(num)) {
507
+ result.opacity = String(num / 100);
508
+ }
509
+ continue;
510
+ }
511
+ // Shadow: semantic values first, then arbitrary
512
+ if (token === "shadow") {
513
+ result.boxShadow = SHADOW_MAP[""];
514
+ continue;
515
+ }
516
+ if (token.startsWith("shadow-[")) {
517
+ const inner = token.slice(8, -1);
518
+ result.boxShadow = inner.replace(/_/g, " ");
519
+ continue;
520
+ }
521
+ if (token.startsWith("shadow-")) {
522
+ const val = token.slice(7);
523
+ if (val in SHADOW_MAP) {
524
+ result.boxShadow = SHADOW_MAP[val];
525
+ }
526
+ continue;
527
+ }
528
+ // Border: must check before bg-/text- color resolution
529
+ if (token === "border") {
530
+ result.border = {
531
+ width: "1px",
532
+ color: result.border?.color ?? "",
533
+ };
534
+ continue;
535
+ }
536
+ // border-{n} where n is a single digit
537
+ if (token.startsWith("border-")) {
538
+ const val = token.slice(7);
539
+ // border-style: dashed, dotted, solid (must check before color resolution)
540
+ if (val === "dashed" || val === "dotted" || val === "solid") {
541
+ result.borderStyle = val;
542
+ continue;
543
+ }
544
+ // border-[{n}px] arbitrary value
545
+ const arbitraryMatch = val.match(/^\[(\d+)px\]$/);
546
+ if (arbitraryMatch) {
547
+ result.border = {
548
+ width: `${arbitraryMatch[1]}px`,
549
+ color: result.border?.color ?? "",
550
+ };
551
+ continue;
552
+ }
553
+ // border-{n} numeric
554
+ if (/^\d+$/.test(val)) {
555
+ result.border = {
556
+ width: `${val}px`,
557
+ color: result.border?.color ?? "",
558
+ };
559
+ continue;
560
+ }
561
+ // border-{colorValue}
562
+ const color = resolveColorValue(val, resolvedColors);
563
+ if (color) {
564
+ result.border = {
565
+ width: result.border?.width ?? "1px",
566
+ color,
567
+ };
568
+ }
569
+ continue;
570
+ }
571
+ // text-{size} MUST come before text-{color}
572
+ if (token.startsWith("text-")) {
573
+ const val = token.slice(5);
574
+ if (FONT_SIZE_KEYS.has(val)) {
575
+ result.fontSize = FONT_SIZE_MAP[val];
576
+ continue;
577
+ }
578
+ // text-{color}
579
+ const color = resolveColorValue(val, resolvedColors);
580
+ if (color) {
581
+ result.color = color;
582
+ }
583
+ continue;
584
+ }
585
+ // bg-gradient-to-{direction} (must check before bg-{color})
586
+ if (token.startsWith("bg-gradient-to-")) {
587
+ const dir = token.slice(15);
588
+ result.gradient = `linear-gradient(to ${GRADIENT_DIR_MAP[dir] ?? dir}`;
589
+ continue;
590
+ }
591
+ // bg-{color}
592
+ if (token.startsWith("bg-")) {
593
+ const val = token.slice(3);
594
+ const color = resolveColorValue(val, resolvedColors);
595
+ if (color) {
596
+ result.backgroundColor = color;
597
+ }
598
+ continue;
599
+ }
600
+ // from-{color} (gradient)
601
+ if (token.startsWith("from-")) {
602
+ const val = token.slice(5);
603
+ const color = resolveColorValue(val, resolvedColors);
604
+ if (color) {
605
+ result.gradient = `${result.gradient ?? "linear-gradient("}, ${color}`;
606
+ }
607
+ continue;
608
+ }
609
+ // via-{color} (gradient middle stop)
610
+ if (token.startsWith("via-")) {
611
+ const val = token.slice(4);
612
+ const color = resolveColorValue(val, resolvedColors);
613
+ if (color) {
614
+ result.gradient = `${result.gradient ?? "linear-gradient("}, ${color}`;
615
+ }
616
+ continue;
617
+ }
618
+ // to-{color} (gradient stop)
619
+ if (token.startsWith("to-")) {
620
+ const val = token.slice(3);
621
+ const color = resolveColorValue(val, resolvedColors);
622
+ if (color) {
623
+ result.gradient = `${result.gradient ?? "linear-gradient("}, ${color})`;
624
+ }
625
+ }
626
+ }
627
+ // グラデーションが閉じ括弧なしで終わっている場合は追加
628
+ if (result.gradient && !result.gradient.endsWith(")")) {
629
+ result.gradient = `${result.gradient})`;
630
+ }
631
+ return result;
632
+ }
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  ],
11
11
  "homepage": "https://vaden.ai",
12
12
  "license": "MIT",
13
- "version": "0.3.0",
13
+ "version": "0.3.1",
14
14
  "type": "module",
15
15
  "publishConfig": {
16
16
  "access": "public"