@fragments-sdk/cli 0.2.2
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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +4783 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-4FDQSGKX.js +786 -0
- package/dist/chunk-4FDQSGKX.js.map +1 -0
- package/dist/chunk-7H2MMGYG.js +369 -0
- package/dist/chunk-7H2MMGYG.js.map +1 -0
- package/dist/chunk-BSCG3IP7.js +619 -0
- package/dist/chunk-BSCG3IP7.js.map +1 -0
- package/dist/chunk-LY2CFFPY.js +898 -0
- package/dist/chunk-LY2CFFPY.js.map +1 -0
- package/dist/chunk-MUZ6CM66.js +6636 -0
- package/dist/chunk-MUZ6CM66.js.map +1 -0
- package/dist/chunk-OAENNG3G.js +1489 -0
- package/dist/chunk-OAENNG3G.js.map +1 -0
- package/dist/chunk-XHNKNI6J.js +235 -0
- package/dist/chunk-XHNKNI6J.js.map +1 -0
- package/dist/core-DWKLGY4N.js +68 -0
- package/dist/core-DWKLGY4N.js.map +1 -0
- package/dist/generate-4LQNJ7SX.js +249 -0
- package/dist/generate-4LQNJ7SX.js.map +1 -0
- package/dist/index.d.ts +775 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/init-EMVI47QG.js +416 -0
- package/dist/init-EMVI47QG.js.map +1 -0
- package/dist/mcp-bin.d.ts +1 -0
- package/dist/mcp-bin.js +1117 -0
- package/dist/mcp-bin.js.map +1 -0
- package/dist/scan-4YPRF7FV.js +12 -0
- package/dist/scan-4YPRF7FV.js.map +1 -0
- package/dist/service-QSZMZJBJ.js +208 -0
- package/dist/service-QSZMZJBJ.js.map +1 -0
- package/dist/static-viewer-MIPGZ4Z7.js +12 -0
- package/dist/static-viewer-MIPGZ4Z7.js.map +1 -0
- package/dist/test-SQ5ZHXWU.js +1067 -0
- package/dist/test-SQ5ZHXWU.js.map +1 -0
- package/dist/tokens-HSGMYK64.js +173 -0
- package/dist/tokens-HSGMYK64.js.map +1 -0
- package/dist/viewer-YRF4SQE4.js +11101 -0
- package/dist/viewer-YRF4SQE4.js.map +1 -0
- package/package.json +107 -0
- package/src/ai.ts +266 -0
- package/src/analyze.ts +265 -0
- package/src/bin.ts +916 -0
- package/src/build.ts +248 -0
- package/src/commands/a11y.ts +302 -0
- package/src/commands/add.ts +313 -0
- package/src/commands/audit.ts +195 -0
- package/src/commands/baseline.ts +221 -0
- package/src/commands/build.ts +144 -0
- package/src/commands/compare.ts +337 -0
- package/src/commands/context.ts +107 -0
- package/src/commands/dev.ts +107 -0
- package/src/commands/enhance.ts +858 -0
- package/src/commands/generate.ts +391 -0
- package/src/commands/init.ts +531 -0
- package/src/commands/link/figma.ts +645 -0
- package/src/commands/link/index.ts +10 -0
- package/src/commands/link/storybook.ts +267 -0
- package/src/commands/list.ts +49 -0
- package/src/commands/metrics.ts +114 -0
- package/src/commands/reset.ts +242 -0
- package/src/commands/scan.ts +537 -0
- package/src/commands/storygen.ts +207 -0
- package/src/commands/tokens.ts +251 -0
- package/src/commands/validate.ts +93 -0
- package/src/commands/verify.ts +215 -0
- package/src/core/composition.test.ts +262 -0
- package/src/core/composition.ts +255 -0
- package/src/core/config.ts +84 -0
- package/src/core/constants.ts +111 -0
- package/src/core/context.ts +380 -0
- package/src/core/defineSegment.ts +137 -0
- package/src/core/discovery.ts +337 -0
- package/src/core/figma.ts +263 -0
- package/src/core/fragment-types.ts +214 -0
- package/src/core/generators/context.ts +389 -0
- package/src/core/generators/index.ts +23 -0
- package/src/core/generators/registry.ts +364 -0
- package/src/core/generators/typescript-extractor.ts +374 -0
- package/src/core/importAnalyzer.ts +217 -0
- package/src/core/index.ts +149 -0
- package/src/core/loader.ts +155 -0
- package/src/core/node.ts +63 -0
- package/src/core/parser.ts +551 -0
- package/src/core/previewLoader.ts +172 -0
- package/src/core/schema/fragment.schema.json +189 -0
- package/src/core/schema/registry.schema.json +137 -0
- package/src/core/schema.ts +182 -0
- package/src/core/storyAdapter.test.ts +571 -0
- package/src/core/storyAdapter.ts +761 -0
- package/src/core/token-types.ts +287 -0
- package/src/core/types.ts +754 -0
- package/src/diff.ts +323 -0
- package/src/index.ts +43 -0
- package/src/mcp/__tests__/projectFields.test.ts +130 -0
- package/src/mcp/bin.ts +36 -0
- package/src/mcp/index.ts +8 -0
- package/src/mcp/server.ts +1310 -0
- package/src/mcp/utils.ts +54 -0
- package/src/mcp-bin.ts +36 -0
- package/src/migrate/__tests__/argTypes/argTypes.test.ts +189 -0
- package/src/migrate/__tests__/args/args.test.ts +452 -0
- package/src/migrate/__tests__/meta/meta.test.ts +198 -0
- package/src/migrate/__tests__/stories/stories.test.ts +278 -0
- package/src/migrate/__tests__/utils/utils.test.ts +371 -0
- package/src/migrate/__tests__/values/values.test.ts +303 -0
- package/src/migrate/bin.ts +108 -0
- package/src/migrate/converter.ts +658 -0
- package/src/migrate/detect.ts +196 -0
- package/src/migrate/index.ts +45 -0
- package/src/migrate/migrate.ts +163 -0
- package/src/migrate/parser.ts +1136 -0
- package/src/migrate/report.ts +624 -0
- package/src/migrate/types.ts +169 -0
- package/src/screenshot.ts +249 -0
- package/src/service/__tests__/ast-utils.test.ts +426 -0
- package/src/service/__tests__/enhance-scanner.test.ts +200 -0
- package/src/service/__tests__/figma/figma.test.ts +652 -0
- package/src/service/__tests__/metrics-store.test.ts +409 -0
- package/src/service/__tests__/patch-generator.test.ts +186 -0
- package/src/service/__tests__/props-extractor.test.ts +365 -0
- package/src/service/__tests__/token-registry.test.ts +267 -0
- package/src/service/analytics.ts +659 -0
- package/src/service/ast-utils.ts +444 -0
- package/src/service/browser-pool.ts +339 -0
- package/src/service/capture.ts +267 -0
- package/src/service/diff.ts +279 -0
- package/src/service/enhance/aggregator.ts +489 -0
- package/src/service/enhance/cache.ts +275 -0
- package/src/service/enhance/codebase-scanner.ts +357 -0
- package/src/service/enhance/context-generator.ts +529 -0
- package/src/service/enhance/doc-extractor.ts +523 -0
- package/src/service/enhance/index.ts +131 -0
- package/src/service/enhance/props-extractor.ts +665 -0
- package/src/service/enhance/scanner.ts +445 -0
- package/src/service/enhance/storybook-parser.ts +552 -0
- package/src/service/enhance/types.ts +346 -0
- package/src/service/enhance/variant-renderer.ts +479 -0
- package/src/service/figma.ts +1008 -0
- package/src/service/index.ts +249 -0
- package/src/service/metrics-store.ts +333 -0
- package/src/service/patch-generator.ts +349 -0
- package/src/service/report.ts +854 -0
- package/src/service/storage.ts +401 -0
- package/src/service/token-fixes.ts +281 -0
- package/src/service/token-parser.ts +504 -0
- package/src/service/token-registry.ts +721 -0
- package/src/service/utils.ts +172 -0
- package/src/setup.ts +241 -0
- package/src/shared/command-wrapper.ts +81 -0
- package/src/shared/dev-server-client.ts +199 -0
- package/src/shared/index.ts +8 -0
- package/src/shared/segment-loader.ts +59 -0
- package/src/shared/types.ts +147 -0
- package/src/static-viewer.ts +715 -0
- package/src/test/discovery.ts +172 -0
- package/src/test/index.ts +281 -0
- package/src/test/reporters/console.ts +194 -0
- package/src/test/reporters/json.ts +190 -0
- package/src/test/reporters/junit.ts +186 -0
- package/src/test/runner.ts +598 -0
- package/src/test/types.ts +245 -0
- package/src/test/watch.ts +200 -0
- package/src/validators.ts +152 -0
- package/src/viewer/__tests__/jsx-parser.test.ts +502 -0
- package/src/viewer/__tests__/render-utils.test.ts +232 -0
- package/src/viewer/__tests__/style-utils.test.ts +404 -0
- package/src/viewer/bin.ts +86 -0
- package/src/viewer/cli/health.ts +256 -0
- package/src/viewer/cli/index.ts +33 -0
- package/src/viewer/cli/scan.ts +124 -0
- package/src/viewer/cli/utils.ts +174 -0
- package/src/viewer/components/AccessibilityPanel.tsx +1404 -0
- package/src/viewer/components/ActionCapture.tsx +172 -0
- package/src/viewer/components/ActionsPanel.tsx +371 -0
- package/src/viewer/components/App.tsx +638 -0
- package/src/viewer/components/BottomPanel.tsx +224 -0
- package/src/viewer/components/CodePanel.tsx +589 -0
- package/src/viewer/components/CommandPalette.tsx +336 -0
- package/src/viewer/components/ComponentGraph.tsx +394 -0
- package/src/viewer/components/ComponentHeader.tsx +85 -0
- package/src/viewer/components/ContractPanel.tsx +234 -0
- package/src/viewer/components/ErrorBoundary.tsx +85 -0
- package/src/viewer/components/FigmaEmbed.tsx +231 -0
- package/src/viewer/components/FragmentEditor.tsx +485 -0
- package/src/viewer/components/HealthDashboard.tsx +452 -0
- package/src/viewer/components/HmrStatusIndicator.tsx +71 -0
- package/src/viewer/components/Icons.tsx +417 -0
- package/src/viewer/components/InteractionsPanel.tsx +720 -0
- package/src/viewer/components/IsolatedPreviewFrame.tsx +321 -0
- package/src/viewer/components/IsolatedRender.tsx +111 -0
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +89 -0
- package/src/viewer/components/LandingPage.tsx +441 -0
- package/src/viewer/components/Layout.tsx +22 -0
- package/src/viewer/components/LeftSidebar.tsx +391 -0
- package/src/viewer/components/MultiViewportPreview.tsx +429 -0
- package/src/viewer/components/PreviewArea.tsx +404 -0
- package/src/viewer/components/PreviewFrameHost.tsx +310 -0
- package/src/viewer/components/PreviewPane.tsx +150 -0
- package/src/viewer/components/PreviewToolbar.tsx +176 -0
- package/src/viewer/components/PropsEditor.tsx +512 -0
- package/src/viewer/components/PropsTable.tsx +98 -0
- package/src/viewer/components/RelationsSection.tsx +57 -0
- package/src/viewer/components/ResizablePanel.tsx +328 -0
- package/src/viewer/components/RightSidebar.tsx +118 -0
- package/src/viewer/components/ScreenshotButton.tsx +90 -0
- package/src/viewer/components/Sidebar.tsx +169 -0
- package/src/viewer/components/SkeletonLoader.tsx +156 -0
- package/src/viewer/components/StoryRenderer.tsx +128 -0
- package/src/viewer/components/ThemeProvider.tsx +96 -0
- package/src/viewer/components/Toast.tsx +67 -0
- package/src/viewer/components/TokenStylePanel.tsx +708 -0
- package/src/viewer/components/UsageSection.tsx +95 -0
- package/src/viewer/components/VariantMatrix.tsx +350 -0
- package/src/viewer/components/VariantRenderer.tsx +131 -0
- package/src/viewer/components/VariantTabs.tsx +84 -0
- package/src/viewer/components/ViewportSelector.tsx +165 -0
- package/src/viewer/components/_future/CreatePage.tsx +836 -0
- package/src/viewer/composition-renderer.ts +381 -0
- package/src/viewer/constants/index.ts +1 -0
- package/src/viewer/constants/ui.ts +185 -0
- package/src/viewer/entry.tsx +299 -0
- package/src/viewer/hooks/index.ts +2 -0
- package/src/viewer/hooks/useA11yCache.ts +383 -0
- package/src/viewer/hooks/useA11yService.ts +498 -0
- package/src/viewer/hooks/useActions.ts +138 -0
- package/src/viewer/hooks/useAppState.ts +124 -0
- package/src/viewer/hooks/useFigmaIntegration.ts +132 -0
- package/src/viewer/hooks/useHmrStatus.ts +109 -0
- package/src/viewer/hooks/useKeyboardShortcuts.ts +222 -0
- package/src/viewer/hooks/usePreviewBridge.ts +347 -0
- package/src/viewer/hooks/useScrollSpy.ts +78 -0
- package/src/viewer/hooks/useUrlState.ts +330 -0
- package/src/viewer/hooks/useViewSettings.ts +125 -0
- package/src/viewer/index.html +28 -0
- package/src/viewer/index.ts +14 -0
- package/src/viewer/intelligence/healthReport.ts +505 -0
- package/src/viewer/intelligence/styleDrift.ts +340 -0
- package/src/viewer/intelligence/usageScanner.ts +309 -0
- package/src/viewer/jsx-parser.ts +485 -0
- package/src/viewer/postcss.config.js +6 -0
- package/src/viewer/preview-frame-entry.tsx +25 -0
- package/src/viewer/preview-frame.html +109 -0
- package/src/viewer/render-template.html +68 -0
- package/src/viewer/render-utils.ts +170 -0
- package/src/viewer/server.ts +276 -0
- package/src/viewer/style-utils.ts +414 -0
- package/src/viewer/styles/globals.css +355 -0
- package/src/viewer/tailwind.config.js +37 -0
- package/src/viewer/types/a11y.ts +197 -0
- package/src/viewer/utils/a11y-fixes.ts +471 -0
- package/src/viewer/utils/actionExport.ts +372 -0
- package/src/viewer/utils/colorSchemes.ts +201 -0
- package/src/viewer/utils/detectRelationships.ts +256 -0
- package/src/viewer/vite-plugin.ts +2143 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { __testing } from "../../parser.js";
|
|
3
|
+
|
|
4
|
+
const { parseArgValue, resolveEscapeSequences, tryParseStringConcatenation } = __testing;
|
|
5
|
+
|
|
6
|
+
describe("parseArgValue", () => {
|
|
7
|
+
describe("string values", () => {
|
|
8
|
+
it("parses single-quoted strings", () => {
|
|
9
|
+
expect(parseArgValue("'hello'")).toBe("hello");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("parses double-quoted strings", () => {
|
|
13
|
+
expect(parseArgValue('"world"')).toBe("world");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("parses template literals", () => {
|
|
17
|
+
expect(parseArgValue("`template`")).toBe("template");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("handles empty strings", () => {
|
|
21
|
+
expect(parseArgValue("''")).toBe("");
|
|
22
|
+
expect(parseArgValue('""')).toBe("");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("handles strings with spaces", () => {
|
|
26
|
+
expect(parseArgValue("'hello world'")).toBe("hello world");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("handles strings with escape sequences", () => {
|
|
30
|
+
expect(parseArgValue("'hello\\nworld'")).toBe("hello\nworld");
|
|
31
|
+
expect(parseArgValue("'tab\\there'")).toBe("tab\there");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe("numeric values", () => {
|
|
36
|
+
it("parses integers", () => {
|
|
37
|
+
expect(parseArgValue("42")).toBe(42);
|
|
38
|
+
expect(parseArgValue("0")).toBe(0);
|
|
39
|
+
expect(parseArgValue("-10")).toBe(-10);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("parses floats", () => {
|
|
43
|
+
expect(parseArgValue("3.14")).toBe(3.14);
|
|
44
|
+
expect(parseArgValue("-0.5")).toBe(-0.5);
|
|
45
|
+
expect(parseArgValue("100.0")).toBe(100.0);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("boolean values", () => {
|
|
50
|
+
it("parses true", () => {
|
|
51
|
+
expect(parseArgValue("true")).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("parses false", () => {
|
|
55
|
+
expect(parseArgValue("false")).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("null and undefined", () => {
|
|
60
|
+
it("parses null", () => {
|
|
61
|
+
expect(parseArgValue("null")).toBeNull();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("parses undefined", () => {
|
|
65
|
+
expect(parseArgValue("undefined")).toBeUndefined();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("nested objects", () => {
|
|
70
|
+
it("parses simple object", () => {
|
|
71
|
+
expect(parseArgValue("{ key: 'value' }")).toEqual({ key: "value" });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("parses nested object", () => {
|
|
75
|
+
expect(parseArgValue("{ a: { b: 'c' } }")).toEqual({ a: { b: "c" } });
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("parses empty object", () => {
|
|
79
|
+
expect(parseArgValue("{}")).toEqual({});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("parses object with multiple properties", () => {
|
|
83
|
+
expect(parseArgValue("{ name: 'test', count: 5 }")).toEqual({
|
|
84
|
+
name: "test",
|
|
85
|
+
count: 5,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("arrays", () => {
|
|
91
|
+
it("parses string array", () => {
|
|
92
|
+
expect(parseArgValue("['a', 'b', 'c']")).toEqual(["a", "b", "c"]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("parses numeric array", () => {
|
|
96
|
+
expect(parseArgValue("[1, 2, 3]")).toEqual([1, 2, 3]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("parses empty array", () => {
|
|
100
|
+
expect(parseArgValue("[]")).toEqual([]);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("parses mixed array", () => {
|
|
104
|
+
expect(parseArgValue("['text', 42, true]")).toEqual(["text", 42, true]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("parses array of objects", () => {
|
|
108
|
+
expect(parseArgValue("[{ id: 1 }, { id: 2 }]")).toEqual([
|
|
109
|
+
{ id: 1 },
|
|
110
|
+
{ id: 2 },
|
|
111
|
+
]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("JSX values", () => {
|
|
116
|
+
it("marks self-closing JSX as special", () => {
|
|
117
|
+
expect(parseArgValue("<Icon />")).toBe("__JSX__");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("marks JSX with content as special", () => {
|
|
121
|
+
expect(parseArgValue("<span>text</span>")).toBe("__JSX__");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("marks JSX with props as special", () => {
|
|
125
|
+
expect(parseArgValue("<Button variant='primary' />")).toBe("__JSX__");
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("function expressions", () => {
|
|
130
|
+
it("marks arrow functions as expressions", () => {
|
|
131
|
+
expect(parseArgValue("() => {}")).toBe("__EXPR__");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("marks arrow functions with body as expressions", () => {
|
|
135
|
+
expect(parseArgValue("(e) => console.log(e)")).toBe("__EXPR__");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("marks function calls as expressions", () => {
|
|
139
|
+
expect(parseArgValue("getValue()")).toBe("__EXPR__");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("marks function calls with args as expressions", () => {
|
|
143
|
+
expect(parseArgValue("format(date, 'YYYY')")).toBe("__EXPR__");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("variable references", () => {
|
|
148
|
+
it("marks simple identifiers as references", () => {
|
|
149
|
+
expect(parseArgValue("myVariable")).toBe("__REF__myVariable");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("marks property access as references", () => {
|
|
153
|
+
expect(parseArgValue("obj.prop")).toBe("__REF__obj.prop");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("marks deep property access as references", () => {
|
|
157
|
+
expect(parseArgValue("a.b.c.d")).toBe("__REF__a.b.c.d");
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("marks optional chaining as references", () => {
|
|
161
|
+
expect(parseArgValue("obj?.prop")).toBe("__REF__obj?.prop");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("marks array index access as references", () => {
|
|
165
|
+
expect(parseArgValue("arr[0]")).toBe("__REF__arr[0]");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("marks complex array access as references", () => {
|
|
169
|
+
expect(parseArgValue("items[0].name")).toBe("__REF__items[0].name");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("marks non-null assertion as reference", () => {
|
|
173
|
+
expect(parseArgValue("value!")).toBe("__REF__value!");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe("TypeScript as const", () => {
|
|
178
|
+
it("handles 'as const' assertion with single quotes", () => {
|
|
179
|
+
expect(parseArgValue("'left' as const")).toBe("left");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("handles 'as const' assertion with double quotes", () => {
|
|
183
|
+
expect(parseArgValue('"right" as const')).toBe("right");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("TypeScript type assertions", () => {
|
|
188
|
+
it("marks type assertions as expressions", () => {
|
|
189
|
+
expect(parseArgValue("value as SomeType")).toBe("__EXPR__");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("marks complex type assertions as expressions", () => {
|
|
193
|
+
expect(parseArgValue("obj as Type<T>")).toBe("__EXPR__");
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe("string concatenation", () => {
|
|
198
|
+
it("resolves simple string concatenation", () => {
|
|
199
|
+
expect(parseArgValue("'hello' + ' world'")).toBe("hello world");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("resolves multi-part concatenation", () => {
|
|
203
|
+
expect(parseArgValue("'a' + 'b' + 'c'")).toBe("abc");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("resolves mixed quote concatenation", () => {
|
|
207
|
+
expect(parseArgValue(`"hello" + ' ' + "world"`)).toBe("hello world");
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe("trailing comma handling", () => {
|
|
212
|
+
it("removes trailing comma from values", () => {
|
|
213
|
+
expect(parseArgValue("'test',")).toBe("test");
|
|
214
|
+
expect(parseArgValue("42,")).toBe(42);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe("whitespace handling", () => {
|
|
219
|
+
it("trims whitespace from values", () => {
|
|
220
|
+
expect(parseArgValue(" 'test' ")).toBe("test");
|
|
221
|
+
expect(parseArgValue(" 42 ")).toBe(42);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe("resolveEscapeSequences", () => {
|
|
227
|
+
it("resolves newline escape", () => {
|
|
228
|
+
expect(resolveEscapeSequences("hello\\nworld")).toBe("hello\nworld");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("resolves tab escape", () => {
|
|
232
|
+
expect(resolveEscapeSequences("col1\\tcol2")).toBe("col1\tcol2");
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it("resolves carriage return escape", () => {
|
|
236
|
+
expect(resolveEscapeSequences("line1\\rline2")).toBe("line1\rline2");
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("resolves backslash escape", () => {
|
|
240
|
+
expect(resolveEscapeSequences("path\\\\to\\\\file")).toBe("path\\to\\file");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("resolves quote escapes", () => {
|
|
244
|
+
expect(resolveEscapeSequences('say \\"hello\\"')).toBe('say "hello"');
|
|
245
|
+
expect(resolveEscapeSequences("it\\'s")).toBe("it's");
|
|
246
|
+
expect(resolveEscapeSequences("template\\`string")).toBe("template`string");
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("handles multiple escapes in sequence", () => {
|
|
250
|
+
expect(resolveEscapeSequences("line1\\nline2\\n\\tindented")).toBe(
|
|
251
|
+
"line1\nline2\n\tindented"
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("preserves unrecognized escape sequences", () => {
|
|
256
|
+
expect(resolveEscapeSequences("hello\\xworld")).toBe("hello\\xworld");
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it("handles strings without escapes", () => {
|
|
260
|
+
expect(resolveEscapeSequences("no escapes here")).toBe("no escapes here");
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
describe("tryParseStringConcatenation", () => {
|
|
265
|
+
it("returns null for non-concatenation strings", () => {
|
|
266
|
+
expect(tryParseStringConcatenation("'simple'")).toBeNull();
|
|
267
|
+
expect(tryParseStringConcatenation("42")).toBeNull();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it("parses two-part concatenation", () => {
|
|
271
|
+
expect(tryParseStringConcatenation("'hello' + ' world'")).toBe("hello world");
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("parses multi-part concatenation", () => {
|
|
275
|
+
expect(tryParseStringConcatenation("'a' + 'b' + 'c' + 'd'")).toBe("abcd");
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("handles different quote styles", () => {
|
|
279
|
+
expect(tryParseStringConcatenation(`'single' + "double"`)).toBe("singledouble");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("returns null for mixed concatenation (string + variable)", () => {
|
|
283
|
+
expect(tryParseStringConcatenation("'hello' + name")).toBeNull();
|
|
284
|
+
expect(tryParseStringConcatenation("prefix + 'suffix'")).toBeNull();
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it("handles whitespace around operators", () => {
|
|
288
|
+
expect(tryParseStringConcatenation("'a' + 'b'")).toBe("ab");
|
|
289
|
+
expect(tryParseStringConcatenation("'a'+ 'b'")).toBe("ab");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("preserves spaces within strings", () => {
|
|
293
|
+
expect(tryParseStringConcatenation("'hello ' + 'world'")).toBe("hello world");
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it("returns null for template literals with interpolation", () => {
|
|
297
|
+
expect(tryParseStringConcatenation("`hello ${name}` + 'suffix'")).toBeNull();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("handles template literals without interpolation", () => {
|
|
301
|
+
expect(tryParseStringConcatenation("`hello` + ` world`")).toBe("hello world");
|
|
302
|
+
});
|
|
303
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for migration tool.
|
|
4
|
+
*
|
|
5
|
+
* Can be run standalone or integrated with the main segments CLI.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
import { BRAND } from "../core/index.js";
|
|
11
|
+
import { migrate } from "./migrate.js";
|
|
12
|
+
|
|
13
|
+
const program = new Command();
|
|
14
|
+
|
|
15
|
+
program
|
|
16
|
+
.name("segments-migrate")
|
|
17
|
+
.description(`${BRAND.name} Storybook Migration Tool`)
|
|
18
|
+
.version("0.0.1");
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.command("migrate")
|
|
22
|
+
.description("Migrate Storybook stories to Segments")
|
|
23
|
+
.argument("<source>", "Source directory or file containing .stories.tsx files")
|
|
24
|
+
.option("-o, --output <dir>", "Output directory (default: same as source)")
|
|
25
|
+
.option("--dry-run", "Show what would be generated without writing files")
|
|
26
|
+
.option("--overwrite", "Overwrite existing segment files")
|
|
27
|
+
.option("--report", "Generate HTML migration report")
|
|
28
|
+
.option("--report-path <path>", "Path for the migration report")
|
|
29
|
+
.option("-v, --verbose", "Verbose output")
|
|
30
|
+
.action(async (source, options) => {
|
|
31
|
+
try {
|
|
32
|
+
console.log(pc.cyan(`\n${BRAND.name} Migration Tool\n`));
|
|
33
|
+
console.log(pc.dim("Discovering Storybook files...\n"));
|
|
34
|
+
|
|
35
|
+
const report = await migrate({
|
|
36
|
+
from: source,
|
|
37
|
+
to: options.output,
|
|
38
|
+
dryRun: options.dryRun,
|
|
39
|
+
overwrite: options.overwrite,
|
|
40
|
+
report: options.report,
|
|
41
|
+
reportPath: options.reportPath,
|
|
42
|
+
verbose: options.verbose,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Print results
|
|
46
|
+
if (report.totalStoryFiles === 0) {
|
|
47
|
+
console.log(pc.yellow("No story files found.\n"));
|
|
48
|
+
console.log(pc.dim("Looking for: *.stories.tsx, *.stories.ts, *.stories.jsx, *.stories.js"));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(pc.dim(`Found ${report.totalStoryFiles} story file(s)\n`));
|
|
53
|
+
|
|
54
|
+
// Print each conversion
|
|
55
|
+
for (const result of report.results) {
|
|
56
|
+
if (result.success) {
|
|
57
|
+
console.log(`${pc.green("✓")} ${pc.bold(result.componentName)} → ${result.outputFile}`);
|
|
58
|
+
console.log(pc.dim(` ${result.variantCount} variant(s), ${result.todos.length} TODO(s)`));
|
|
59
|
+
} else {
|
|
60
|
+
console.log(`${pc.red("✗")} ${result.sourceFile}`);
|
|
61
|
+
for (const warning of result.warnings) {
|
|
62
|
+
console.log(pc.dim(` ${warning}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log();
|
|
68
|
+
|
|
69
|
+
// Summary
|
|
70
|
+
if (report.successfulConversions > 0) {
|
|
71
|
+
console.log(pc.green(`✓ Converted ${report.successfulConversions} component(s)`));
|
|
72
|
+
}
|
|
73
|
+
if (report.failedConversions > 0) {
|
|
74
|
+
console.log(pc.red(`✗ Failed ${report.failedConversions} conversion(s)`));
|
|
75
|
+
}
|
|
76
|
+
console.log(pc.dim(` ${report.totalVariants} variant(s) total`));
|
|
77
|
+
console.log(pc.dim(` ${report.totalTodos} TODO(s) need attention`));
|
|
78
|
+
|
|
79
|
+
if (options.dryRun) {
|
|
80
|
+
console.log(pc.yellow("\n[Dry run - no files were written]"));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (options.report) {
|
|
84
|
+
const reportPath = options.reportPath ?? `${source}/migration-report.html`;
|
|
85
|
+
console.log(pc.cyan(`\n📊 Report generated: ${reportPath}`));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Next steps
|
|
89
|
+
console.log(pc.dim("\n───────────────────────────────────────"));
|
|
90
|
+
console.log(pc.bold("\nNext steps:"));
|
|
91
|
+
console.log(` 1. Review generated ${BRAND.fileExtension} files`);
|
|
92
|
+
console.log(` 2. Fill in TODO comments (usage.when, usage.whenNot, etc.)`);
|
|
93
|
+
console.log(` 3. Run ${pc.cyan(`${BRAND.cliCommand} build`)} to compile`);
|
|
94
|
+
console.log(` 4. Run ${pc.cyan(`${BRAND.cliCommand} dev`)} to view your design system`);
|
|
95
|
+
console.log();
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(pc.red("Error:"), error instanceof Error ? error.message : error);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Also support direct execution without subcommand
|
|
103
|
+
if (process.argv.length > 2 && !process.argv[2].startsWith("-") && process.argv[2] !== "migrate") {
|
|
104
|
+
// Insert "migrate" as the command
|
|
105
|
+
process.argv.splice(2, 0, "migrate");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
program.parse();
|