design-embed 0.1.0 → 0.2.0
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 +1 -1
- package/README.md +98 -2
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +273 -0
- package/dist/core-BLV62TaX.mjs +907 -0
- package/dist/index.d.mts +273 -0
- package/dist/index.mjs +2 -0
- package/package.json +6 -19
- package/src/cli.ts +8 -16
- package/src/commands/compile.ts +25 -110
- package/src/commands/generateTests.ts +14 -96
- package/src/commands/init.ts +52 -55
- package/src/commands/plugin.ts +6 -21
- package/src/config/index.ts +302 -0
- package/{node_modules/@design-embed/core/src → src/core}/index.ts +151 -163
- package/src/core/nodes.ts +74 -0
- package/src/core/plugins/pluginApi.ts +44 -0
- package/src/core/types.ts +120 -0
- package/src/index.ts +48 -2
- package/src/targets/html.ts +621 -0
- package/dist/args.js +0 -36
- package/dist/cli.js +0 -35
- package/dist/commands/check.js +0 -4
- package/dist/commands/compile.js +0 -157
- package/dist/commands/generateTests.js +0 -113
- package/dist/commands/init.js +0 -102
- package/dist/commands/plugin.js +0 -68
- package/dist/index.js +0 -2
- package/node_modules/@design-embed/config/README.md +0 -5
- package/node_modules/@design-embed/config/dist/index.js +0 -283
- package/node_modules/@design-embed/config/package.json +0 -19
- package/node_modules/@design-embed/config/src/index.ts +0 -518
- package/node_modules/@design-embed/core/README.md +0 -5
- package/node_modules/@design-embed/core/dist/diagnostics/diagnostic.js +0 -3
- package/node_modules/@design-embed/core/dist/diagnostics/jsonDiagnostic.js +0 -35
- package/node_modules/@design-embed/core/dist/index.js +0 -351
- package/node_modules/@design-embed/core/dist/pipeline/checkMode.js +0 -29
- package/node_modules/@design-embed/core/dist/plugins/pluginApi.js +0 -1
- package/node_modules/@design-embed/core/dist/plugins/pluginRegistry.js +0 -25
- package/node_modules/@design-embed/core/package.json +0 -19
- package/node_modules/@design-embed/core/src/plugins/pluginApi.ts +0 -78
- package/node_modules/@design-embed/core/src/plugins/pluginRegistry.ts +0 -37
- /package/{node_modules/@design-embed/core/src → src/core}/diagnostics/diagnostic.ts +0 -0
- /package/{node_modules/@design-embed/core/src → src/core}/diagnostics/jsonDiagnostic.ts +0 -0
- /package/{node_modules/@design-embed/core/src → src/core}/pipeline/checkMode.ts +0 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
//#region packages/design-embed/src/core/nodes.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Location in the source HTML file.
|
|
4
|
+
*/
|
|
5
|
+
interface SourceLocation {
|
|
6
|
+
/** Absolute offset in characters. */
|
|
7
|
+
offset: number;
|
|
8
|
+
/** 1-based line number. */
|
|
9
|
+
line: number;
|
|
10
|
+
/** 1-based column number. */
|
|
11
|
+
column: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A normalized node in the design AST.
|
|
15
|
+
*/
|
|
16
|
+
interface DesignNode {
|
|
17
|
+
/** The type of node. */
|
|
18
|
+
kind: "element" | "text" | "component";
|
|
19
|
+
/** HTML tag name (for element kind). */
|
|
20
|
+
tagName?: string;
|
|
21
|
+
/** HTML attributes (for element kind). */
|
|
22
|
+
attributes?: Record<string, string>;
|
|
23
|
+
/** Parsed inline styles (for element kind). */
|
|
24
|
+
styles?: Record<string, string>;
|
|
25
|
+
/** Utility classes to apply. */
|
|
26
|
+
generatedClassNames?: string[];
|
|
27
|
+
/** Child nodes. */
|
|
28
|
+
children?: DesignNode[];
|
|
29
|
+
/** Inner text content (for text kind). */
|
|
30
|
+
text?: string;
|
|
31
|
+
/** Original location in the source HTML. */
|
|
32
|
+
source?: SourceLocation;
|
|
33
|
+
/** Component name (for component kind). */
|
|
34
|
+
component?: string;
|
|
35
|
+
/** Named export of the component. */
|
|
36
|
+
importName?: string;
|
|
37
|
+
/** Mapped prop values for the component. */
|
|
38
|
+
props?: Record<string, PropValue>;
|
|
39
|
+
/** Import path of the component. */
|
|
40
|
+
importPath?: string;
|
|
41
|
+
/**
|
|
42
|
+
* The original element node a component was mapped from. Retained so
|
|
43
|
+
* targets can reconstruct the element's structure when emitting the
|
|
44
|
+
* component implementation.
|
|
45
|
+
*/
|
|
46
|
+
sourceElement?: DesignNode;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A value passed to a component prop.
|
|
50
|
+
*/
|
|
51
|
+
type PropValue = {
|
|
52
|
+
kind: "literal";
|
|
53
|
+
value: string | number | boolean; /** Source attribute name when the prop is bound to `$attr.*`. */
|
|
54
|
+
attribute?: string;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "text";
|
|
57
|
+
value: string;
|
|
58
|
+
} | {
|
|
59
|
+
kind: "children";
|
|
60
|
+
value: DesignNode[];
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region packages/design-embed/src/core/plugins/pluginApi.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* Represents a file generated by the compiler.
|
|
66
|
+
*/
|
|
67
|
+
interface GeneratedFile {
|
|
68
|
+
/** Relative path from the output directory. */
|
|
69
|
+
path: string;
|
|
70
|
+
/** File content. */
|
|
71
|
+
contents: string;
|
|
72
|
+
}
|
|
73
|
+
interface GeneratedAsset {
|
|
74
|
+
path: string;
|
|
75
|
+
contents?: string | Uint8Array;
|
|
76
|
+
sourceUrl?: string;
|
|
77
|
+
}
|
|
78
|
+
interface SourcePlugin {
|
|
79
|
+
name: string;
|
|
80
|
+
run(input: SourcePluginInput): Promise<SourcePluginResult>;
|
|
81
|
+
}
|
|
82
|
+
interface SourcePluginInput {
|
|
83
|
+
cwd: string;
|
|
84
|
+
config?: unknown;
|
|
85
|
+
}
|
|
86
|
+
interface SourcePluginResult {
|
|
87
|
+
html?: string;
|
|
88
|
+
css?: string;
|
|
89
|
+
assets?: GeneratedAsset[];
|
|
90
|
+
files?: GeneratedFile[];
|
|
91
|
+
diagnostics: Diagnostic[];
|
|
92
|
+
}
|
|
93
|
+
interface TargetEmitResult {
|
|
94
|
+
files: GeneratedFile[];
|
|
95
|
+
}
|
|
96
|
+
interface TargetTestGenerateResult {
|
|
97
|
+
files: GeneratedFile[];
|
|
98
|
+
diagnostics: Diagnostic[];
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region packages/design-embed/src/core/types.d.ts
|
|
102
|
+
interface TargetEmitInput {
|
|
103
|
+
nodes: DesignNode[];
|
|
104
|
+
css?: string;
|
|
105
|
+
config?: DesignEmbedConfig;
|
|
106
|
+
diagnostics: Diagnostic[];
|
|
107
|
+
}
|
|
108
|
+
interface TargetEmitter {
|
|
109
|
+
emit(input: TargetEmitInput): TargetEmitResult;
|
|
110
|
+
}
|
|
111
|
+
interface TargetTestGenerateInput {
|
|
112
|
+
html: string;
|
|
113
|
+
css?: string;
|
|
114
|
+
config: DesignEmbedConfig;
|
|
115
|
+
}
|
|
116
|
+
interface TargetTestGenerator {
|
|
117
|
+
generateTests(input: TargetTestGenerateInput): TargetTestGenerateResult;
|
|
118
|
+
}
|
|
119
|
+
type StyleMode = "inline" | "css-modules" | "tailwind";
|
|
120
|
+
interface ComponentMapping {
|
|
121
|
+
selector: string;
|
|
122
|
+
component: string;
|
|
123
|
+
props?: Record<string, string>;
|
|
124
|
+
}
|
|
125
|
+
interface TokenConfig {
|
|
126
|
+
spacing?: {
|
|
127
|
+
unit?: "px" | "rem";
|
|
128
|
+
threshold?: number;
|
|
129
|
+
values?: Record<string, number>;
|
|
130
|
+
};
|
|
131
|
+
sizing?: NumericTokenGroup;
|
|
132
|
+
typography?: NumericTokenGroup;
|
|
133
|
+
radius?: Record<string, number>;
|
|
134
|
+
borderWidth?: Record<string, number>;
|
|
135
|
+
shadow?: Record<string, string>;
|
|
136
|
+
colors?: Record<string, string>;
|
|
137
|
+
colorThreshold?: number;
|
|
138
|
+
}
|
|
139
|
+
interface NumericTokenGroup {
|
|
140
|
+
unit?: "px" | "rem";
|
|
141
|
+
threshold?: number;
|
|
142
|
+
values?: Record<string, number>;
|
|
143
|
+
}
|
|
144
|
+
type StyleMappings = Record<string, Record<string, string>>;
|
|
145
|
+
interface TestGenerationConfig {
|
|
146
|
+
outputDir?: string;
|
|
147
|
+
runner?: "playwright";
|
|
148
|
+
viewports?: TestViewport[];
|
|
149
|
+
states?: TestState[];
|
|
150
|
+
assertions?: TestAssertions;
|
|
151
|
+
}
|
|
152
|
+
interface TestViewport {
|
|
153
|
+
name?: string;
|
|
154
|
+
width: number;
|
|
155
|
+
height: number;
|
|
156
|
+
}
|
|
157
|
+
interface TestState {
|
|
158
|
+
name: string;
|
|
159
|
+
hover?: string;
|
|
160
|
+
focus?: string;
|
|
161
|
+
click?: string;
|
|
162
|
+
waitFor?: string;
|
|
163
|
+
}
|
|
164
|
+
interface TestAssertions {
|
|
165
|
+
screenshot?: boolean;
|
|
166
|
+
layout?: boolean;
|
|
167
|
+
layoutTolerance?: number;
|
|
168
|
+
selectors?: string[];
|
|
169
|
+
/**
|
|
170
|
+
* Per-pixel color sensitivity (0-1) for the screenshot comparison. Smaller
|
|
171
|
+
* is stricter. Defaults to 0.2.
|
|
172
|
+
*/
|
|
173
|
+
screenshotThreshold?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Maximum number of differing pixels tolerated in the screenshot
|
|
176
|
+
* comparison. Defaults to 0 (byte-exact).
|
|
177
|
+
*/
|
|
178
|
+
screenshotMaxDiffPixels?: number;
|
|
179
|
+
}
|
|
180
|
+
interface DesignEmbedConfig {
|
|
181
|
+
output?: {
|
|
182
|
+
viewsDir?: string | URL;
|
|
183
|
+
target?: "html" | TargetEmitter;
|
|
184
|
+
viewName?: string;
|
|
185
|
+
styleMode?: StyleMode;
|
|
186
|
+
};
|
|
187
|
+
components?: ComponentMapping[];
|
|
188
|
+
tokens?: TokenConfig;
|
|
189
|
+
styleMappings?: StyleMappings;
|
|
190
|
+
source?: SourcePlugin;
|
|
191
|
+
tests?: TestGenerationConfig;
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region packages/design-embed/src/core/index.d.ts
|
|
195
|
+
/**
|
|
196
|
+
* Input for the core embed function.
|
|
197
|
+
*/
|
|
198
|
+
interface DesignEmbedInput {
|
|
199
|
+
/** The compiler configuration. */
|
|
200
|
+
config?: DesignEmbedConfig;
|
|
201
|
+
/** Working directory. */
|
|
202
|
+
cwd?: string;
|
|
203
|
+
/** When true, skips writing output files to disk. Defaults to false. */
|
|
204
|
+
dryRun?: boolean;
|
|
205
|
+
/** When true, generates test files alongside output files. Defaults to false. */
|
|
206
|
+
generateTests?: boolean;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Result of the embedding process.
|
|
210
|
+
*/
|
|
211
|
+
interface DesignEmbedResult {
|
|
212
|
+
/** Source HTML resolved from the config's source plugin. */
|
|
213
|
+
html: string;
|
|
214
|
+
/** Source CSS resolved from the config's source plugin. */
|
|
215
|
+
css?: string;
|
|
216
|
+
/** Generated files. */
|
|
217
|
+
files: GeneratedFile[];
|
|
218
|
+
/** Diagnostics reported during compilation. */
|
|
219
|
+
diagnostics: Diagnostic[];
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The main compiler entry point.
|
|
223
|
+
* Parses HTML, applies component mappings, and emits files.
|
|
224
|
+
*
|
|
225
|
+
* @param input - The compilation input.
|
|
226
|
+
* @returns A promise resolving to the compilation result.
|
|
227
|
+
*
|
|
228
|
+
*/
|
|
229
|
+
declare function embed(input: DesignEmbedInput): Promise<DesignEmbedResult>;
|
|
230
|
+
declare function applyComponentMappings(nodes: DesignNode[], mappings: ComponentMapping[], diagnostics?: Diagnostic[]): DesignNode[];
|
|
231
|
+
declare function parseHtml(html: string): DesignNode[];
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region packages/design-embed/src/core/diagnostics/diagnostic.d.ts
|
|
234
|
+
type DiagnosticSeverity = "error" | "warning" | "info";
|
|
235
|
+
interface Diagnostic {
|
|
236
|
+
code: string;
|
|
237
|
+
message: string;
|
|
238
|
+
severity: DiagnosticSeverity;
|
|
239
|
+
file?: string;
|
|
240
|
+
source?: SourceLocation;
|
|
241
|
+
selector?: string;
|
|
242
|
+
property?: string;
|
|
243
|
+
details?: Record<string, unknown>;
|
|
244
|
+
}
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region packages/design-embed/src/config/index.d.ts
|
|
247
|
+
interface LoadConfigResult {
|
|
248
|
+
config?: DesignEmbedConfig;
|
|
249
|
+
configPath?: string;
|
|
250
|
+
diagnostics: Diagnostic[];
|
|
251
|
+
}
|
|
252
|
+
declare function defineConfig(config: DesignEmbedConfig): DesignEmbedConfig;
|
|
253
|
+
declare function fromFile(htmlPath: string | URL, cssPath?: string | URL): SourcePlugin;
|
|
254
|
+
declare function loadConfig(configPath: string, cwd?: string): Promise<LoadConfigResult>;
|
|
255
|
+
declare function validateConfig(config: DesignEmbedConfig): Diagnostic[];
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region packages/design-embed/src/targets/html.d.ts
|
|
258
|
+
interface HtmlTargetOptions {
|
|
259
|
+
domModel?: "light" | "shadow";
|
|
260
|
+
}
|
|
261
|
+
declare class HtmlTarget implements TargetEmitter, TargetTestGenerator {
|
|
262
|
+
private readonly domModel;
|
|
263
|
+
constructor(options?: HtmlTargetOptions);
|
|
264
|
+
emit({
|
|
265
|
+
nodes,
|
|
266
|
+
css,
|
|
267
|
+
config
|
|
268
|
+
}: TargetEmitInput): TargetEmitResult;
|
|
269
|
+
generateTests(input: TargetTestGenerateInput): TargetTestGenerateResult;
|
|
270
|
+
}
|
|
271
|
+
declare const htmlTarget: TargetEmitter & TargetTestGenerator;
|
|
272
|
+
//#endregion
|
|
273
|
+
export { type ComponentMapping, type DesignEmbedConfig, type DesignEmbedInput, type DesignEmbedResult, type DesignNode, type Diagnostic, type DiagnosticSeverity, type GeneratedAsset, type GeneratedFile, HtmlTarget, type HtmlTargetOptions, type LoadConfigResult, type NumericTokenGroup, type PropValue, type SourceLocation, type SourcePlugin, type SourcePluginInput, type SourcePluginResult, type StyleMappings, type StyleMode, type TargetEmitInput, type TargetEmitResult, type TargetEmitter, type TargetTestGenerateInput, type TargetTestGenerateResult, type TargetTestGenerator, type TestAssertions, type TestGenerationConfig, type TestState, type TestViewport, type TokenConfig, applyComponentMappings, defineConfig, embed, fromFile, htmlTarget, loadConfig, parseHtml, validateConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { c as htmlTarget, d as loadConfig, f as validateConfig, l as defineConfig, n as embed, r as parseHtml, s as HtmlTarget, t as applyComponentMappings, u as fromFile } from "./core-BLV62TaX.mjs";
|
|
2
|
+
export { HtmlTarget, applyComponentMappings, defineConfig, embed, fromFile, htmlTarget, loadConfig, parseHtml, validateConfig };
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "design-embed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
|
-
"access": "public"
|
|
7
|
+
"access": "public",
|
|
8
|
+
"provenance": true
|
|
8
9
|
},
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
12
|
"types": "./src/index.ts",
|
|
12
13
|
"development": "./src/index.ts",
|
|
13
|
-
"default": "./dist/index.
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
@@ -20,23 +21,9 @@
|
|
|
20
21
|
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"bin": {
|
|
23
|
-
"design-embed": "./dist/cli.
|
|
24
|
+
"design-embed": "./dist/cli.mjs"
|
|
24
25
|
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@design-embed/config": "0.1.0",
|
|
27
|
-
"@design-embed/core": "0.1.0",
|
|
28
|
-
"@design-embed/target-html": "0.1.0",
|
|
29
|
-
"@design-embed/target-react": "0.1.0"
|
|
30
|
-
},
|
|
31
|
-
"bundledDependencies": [
|
|
32
|
-
"@design-embed/config",
|
|
33
|
-
"@design-embed/core"
|
|
34
|
-
],
|
|
35
26
|
"scripts": {
|
|
36
|
-
"
|
|
37
|
-
"compile:react": "node src/cli.ts react",
|
|
38
|
-
"compile:html": "node src/cli.ts html",
|
|
39
|
-
"compile:vanjs": "node src/cli.ts vanjs",
|
|
40
|
-
"get-raw": "node src/cli.ts raw"
|
|
27
|
+
"test": "node --conditions=development --test src/**/*.test.ts"
|
|
41
28
|
}
|
|
42
29
|
}
|
package/src/cli.ts
CHANGED
|
@@ -4,29 +4,21 @@ import { runCheckCommand } from "./commands/check.ts";
|
|
|
4
4
|
import { runCompileCommand } from "./commands/compile.ts";
|
|
5
5
|
import { runGenerateTestsCommand } from "./commands/generateTests.ts";
|
|
6
6
|
import { runInitCommand } from "./commands/init.ts";
|
|
7
|
-
import { runPluginCommand } from "./commands/plugin.ts";
|
|
8
7
|
|
|
9
8
|
async function main(): Promise<number> {
|
|
10
|
-
const
|
|
11
|
-
const parsed = parseArgs(args);
|
|
9
|
+
const { command, flags } = parseArgs(process.argv.slice(2));
|
|
12
10
|
|
|
13
|
-
if (
|
|
14
|
-
return runCheckCommand(
|
|
11
|
+
if (command === "check") {
|
|
12
|
+
return runCheckCommand(flags);
|
|
15
13
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return runPluginCommand(parsed.positionals[0], parsed.flags);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (args[0] === "generate-tests") {
|
|
22
|
-
return runGenerateTestsCommand(parsed.flags);
|
|
14
|
+
if (command === "generate-tests") {
|
|
15
|
+
return runGenerateTestsCommand(flags);
|
|
23
16
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return runInitCommand(parsed.flags);
|
|
17
|
+
if (command === "init") {
|
|
18
|
+
return runInitCommand(flags);
|
|
27
19
|
}
|
|
28
20
|
|
|
29
|
-
return runCompileCommand(
|
|
21
|
+
return runCompileCommand(flags);
|
|
30
22
|
}
|
|
31
23
|
|
|
32
24
|
main()
|
package/src/commands/compile.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { getBooleanFlag, getFormat, getStringFlag } from "../args.ts";
|
|
4
|
+
import { loadConfig } from "../config/index.ts";
|
|
4
5
|
import {
|
|
5
6
|
checkGeneratedFiles,
|
|
6
7
|
type Diagnostic,
|
|
7
8
|
embed,
|
|
8
9
|
formatDiagnosticText,
|
|
9
|
-
type TransformerPlugin,
|
|
10
10
|
toJsonDiagnostics,
|
|
11
|
-
} from "
|
|
12
|
-
import { htmlEmitter } from "@design-embed/target-html";
|
|
13
|
-
import { reactEmitter } from "@design-embed/target-react";
|
|
14
|
-
import { getBooleanFlag, getFormat, getStringFlag } from "../args.ts";
|
|
11
|
+
} from "../core/index.ts";
|
|
15
12
|
|
|
16
13
|
export interface CompileCommandOptions {
|
|
17
14
|
check?: boolean;
|
|
@@ -22,65 +19,43 @@ export async function runCompileCommand(
|
|
|
22
19
|
options: CompileCommandOptions = {},
|
|
23
20
|
): Promise<number> {
|
|
24
21
|
const cwd = resolve(process.cwd(), getStringFlag(flags, "--cwd") ?? ".");
|
|
25
|
-
const
|
|
26
|
-
const
|
|
22
|
+
const explicitConfigPath = getStringFlag(flags, "--config");
|
|
23
|
+
const defaultConfigPath = resolve(cwd, "design-embed.config.ts");
|
|
24
|
+
const configPath =
|
|
25
|
+
explicitConfigPath ??
|
|
26
|
+
(existsSync(defaultConfigPath) ? "design-embed.config.ts" : undefined);
|
|
27
27
|
const quiet = getBooleanFlag(flags, "--quiet");
|
|
28
28
|
const format = getFormat(flags);
|
|
29
29
|
const diagnostics: Diagnostic[] = [];
|
|
30
30
|
|
|
31
|
-
if (!
|
|
31
|
+
if (!configPath) {
|
|
32
32
|
diagnostics.push({
|
|
33
|
-
code: "
|
|
34
|
-
message:
|
|
33
|
+
code: "CONFIG_REQUIRED",
|
|
34
|
+
message:
|
|
35
|
+
"No config file found. Create design-embed.config.ts or use --config.",
|
|
35
36
|
severity: "error",
|
|
36
37
|
});
|
|
37
38
|
printDiagnostics(diagnostics, format, quiet);
|
|
38
39
|
return 2;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
severity: "error",
|
|
47
|
-
file: inputPath,
|
|
48
|
-
});
|
|
42
|
+
const configResult = await loadConfig(configPath, cwd);
|
|
43
|
+
diagnostics.push(...configResult.diagnostics);
|
|
44
|
+
const config = configResult.config;
|
|
45
|
+
|
|
46
|
+
if (hasErrors(diagnostics)) {
|
|
49
47
|
printDiagnostics(diagnostics, format, quiet);
|
|
50
48
|
return 2;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (configPath) {
|
|
56
|
-
const configResult = await loadConfig(configPath, cwd);
|
|
57
|
-
diagnostics.push(...configResult.diagnostics);
|
|
58
|
-
config = configResult.config;
|
|
59
|
-
|
|
60
|
-
if (hasErrors(diagnostics)) {
|
|
61
|
-
printDiagnostics(diagnostics, format, quiet);
|
|
62
|
-
return 2;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
transformers = await loadTransformers(config, configPath, cwd, diagnostics);
|
|
66
|
-
if (hasErrors(diagnostics)) {
|
|
67
|
-
printDiagnostics(diagnostics, format, quiet);
|
|
68
|
-
return 2;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const target = config?.output?.target ?? "html";
|
|
73
|
-
const targetEmitter = target === "react" ? reactEmitter : htmlEmitter;
|
|
51
|
+
const isCheckMode = options.check && !getBooleanFlag(flags, "--write");
|
|
52
|
+
const generateTests = !getBooleanFlag(flags, "--no-test");
|
|
74
53
|
|
|
75
|
-
const cssPath = getStringFlag(flags, "--css");
|
|
76
54
|
const result = await embed({
|
|
77
|
-
html: readFileSync(resolvedInputPath, "utf-8"),
|
|
78
|
-
css: cssPath ? readFileSync(resolve(cwd, cssPath), "utf-8") : undefined,
|
|
79
|
-
configPath,
|
|
80
55
|
config,
|
|
81
56
|
cwd,
|
|
82
|
-
|
|
83
|
-
|
|
57
|
+
dryRun: isCheckMode,
|
|
58
|
+
generateTests,
|
|
84
59
|
});
|
|
85
60
|
diagnostics.push(...result.diagnostics);
|
|
86
61
|
|
|
@@ -89,7 +64,7 @@ export async function runCompileCommand(
|
|
|
89
64
|
return 2;
|
|
90
65
|
}
|
|
91
66
|
|
|
92
|
-
if (
|
|
67
|
+
if (isCheckMode) {
|
|
93
68
|
const checkResult = checkGeneratedFiles({
|
|
94
69
|
cwd,
|
|
95
70
|
files: result.files,
|
|
@@ -97,21 +72,11 @@ export async function runCompileCommand(
|
|
|
97
72
|
return existsSync(path) ? readFileSync(path, "utf-8") : undefined;
|
|
98
73
|
},
|
|
99
74
|
});
|
|
100
|
-
|
|
101
|
-
diagnostics.push(...checkDiagnostics);
|
|
75
|
+
diagnostics.push(...checkResult.diagnostics);
|
|
102
76
|
printDiagnostics(diagnostics, format, quiet);
|
|
103
77
|
return checkResult.ok ? 0 : 3;
|
|
104
78
|
}
|
|
105
79
|
|
|
106
|
-
for (const file of result.files) {
|
|
107
|
-
const outPath = resolve(cwd, file.path);
|
|
108
|
-
mkdirSync(dirname(outPath), { recursive: true });
|
|
109
|
-
writeFileSync(outPath, file.contents, "utf-8");
|
|
110
|
-
if (!quiet && format === "text") {
|
|
111
|
-
console.log(`Wrote ${file.path}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
80
|
printDiagnostics(diagnostics, format, quiet);
|
|
116
81
|
if (!quiet && format === "text") {
|
|
117
82
|
console.log(`Success. Generated ${result.files.length} file(s).`);
|
|
@@ -143,56 +108,6 @@ export function printDiagnostics(
|
|
|
143
108
|
}
|
|
144
109
|
}
|
|
145
110
|
|
|
146
|
-
function isPackageName(path: string): boolean {
|
|
147
|
-
return !path.startsWith(".") && !isAbsolute(path);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function loadTransformers(
|
|
151
|
-
config: DesignEmbedConfig | undefined,
|
|
152
|
-
configPath: string,
|
|
153
|
-
cwd: string,
|
|
154
|
-
diagnostics: Diagnostic[],
|
|
155
|
-
): Promise<TransformerPlugin[]> {
|
|
156
|
-
const configDir = dirname(resolve(cwd, configPath));
|
|
157
|
-
const loaded: TransformerPlugin[] = [];
|
|
158
|
-
|
|
159
|
-
for (const transformer of config?.transformers ?? []) {
|
|
160
|
-
const specifier = isPackageName(transformer.path)
|
|
161
|
-
? transformer.path
|
|
162
|
-
: isAbsolute(transformer.path)
|
|
163
|
-
? transformer.path
|
|
164
|
-
: resolve(configDir, transformer.path);
|
|
165
|
-
try {
|
|
166
|
-
const module = await import(specifier);
|
|
167
|
-
const plugin = module.default ?? module.transformer;
|
|
168
|
-
if (!plugin?.transform) {
|
|
169
|
-
diagnostics.push({
|
|
170
|
-
code: "TRANSFORMER_INVALID",
|
|
171
|
-
message: `Transformer ${transformer.path} must export a plugin object with transform().`,
|
|
172
|
-
severity: "error",
|
|
173
|
-
file: transformer.path,
|
|
174
|
-
});
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
loaded.push({
|
|
178
|
-
name: plugin.name ?? transformer.path,
|
|
179
|
-
order: transformer.order ?? plugin.order,
|
|
180
|
-
transform: plugin.transform,
|
|
181
|
-
});
|
|
182
|
-
} catch (error) {
|
|
183
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
184
|
-
diagnostics.push({
|
|
185
|
-
code: "TRANSFORMER_LOAD_FAILED",
|
|
186
|
-
message: `Failed to load transformer ${transformer.path}: ${message}`,
|
|
187
|
-
severity: "error",
|
|
188
|
-
file: transformer.path,
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return loaded;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
111
|
function hasErrors(diagnostics: Diagnostic[]): boolean {
|
|
197
112
|
return diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
198
113
|
}
|