@vobs/vite-plugin 1.2.1 → 1.3.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/dist/index.cjs CHANGED
@@ -1,1153 +1,47 @@
1
- 'use strict';
2
-
3
- var promises = require('fs/promises');
4
- var path = require('path');
5
- var ts = require('typescript');
6
- var error = require('@vobs/runtime/error');
7
- var parse5 = require('parse5');
8
-
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var path__default = /*#__PURE__*/_interopDefault(path);
12
- var ts__default = /*#__PURE__*/_interopDefault(ts);
13
-
1
+ var __VOBS_CJS_FILE_URL = require("url").pathToFileURL(__filename).href;
2
+ "use strict";
3
+ var __create = Object.create;
14
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
15
9
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
16
- function compileWithSourceMap(code, options = {}) {
17
- const filename = options.filename ?? "component.tsx";
18
- let sourceFile = ts__default.default.createSourceFile(
19
- filename,
20
- code,
21
- ts__default.default.ScriptTarget.Latest,
22
- true,
23
- ts__default.default.ScriptKind.TSX
24
- );
25
- const state = {
26
- generatedId: 0,
27
- filename,
28
- sourceFile,
29
- statementSources: /* @__PURE__ */ new WeakMap(),
30
- takenNames: collectDeclaredNames(sourceFile),
31
- helperAliases: /* @__PURE__ */ new Map(),
32
- templates: /* @__PURE__ */ new Map(),
33
- sourceLocation: options.sourceLocation ?? true,
34
- stateAliases: collectStateAliases(sourceFile),
35
- localBindings: collectLocallyDeclaredNames(sourceFile),
36
- diagnostics: []
37
- };
38
- const cleanFilename = filename.split(/[?#]/u, 1)[0] || filename;
39
- const diagnostics = ts__default.default.transpileModule(code, {
40
- // Vite appends query strings (for example `?direct`) to module IDs;
41
- // strip them so TypeScript still recognizes TSX syntax for diagnostics.
42
- fileName: cleanFilename,
43
- reportDiagnostics: true,
44
- compilerOptions: { jsx: ts__default.default.JsxEmit.Preserve, target: ts__default.default.ScriptTarget.Latest }
45
- }).diagnostics?.map((diagnostic) => toCompilerDiagnostic(diagnostic, sourceFile, cleanFilename)) ?? [];
46
- const plugins = options.plugins ?? [];
47
- validatePlugins(plugins);
48
- const context = {
49
- filename,
50
- factory: ts__default.default.factory,
51
- addRuntimeImport(name) {
52
- resolveHelperName(state, name);
53
- },
54
- helperRef: /* @__PURE__ */ __name((name) => helperRef(state, name), "helperRef")
55
- };
56
- for (const plugin of plugins) plugin.analyze?.(sourceFile, context);
57
- for (const plugin of plugins) {
58
- sourceFile = plugin.transform?.program?.(sourceFile, context) ?? sourceFile;
59
- }
60
- for (const plugin of plugins) sourceFile = transformPluginNodes(sourceFile, plugin, context);
61
- const statements = sourceFile.statements.map(
62
- (statement) => ts__default.default.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement)
63
- );
64
- const templateDeclarations = createTemplateDeclarations(state);
65
- const resultFile = ts__default.default.factory.updateSourceFile(sourceFile, [
66
- ...createRuntimeImports(state),
67
- ...templateDeclarations,
68
- ...statements
69
- ]);
70
- const generated = ts__default.default.createPrinter().printFile(resultFile);
71
- return {
72
- code: generated,
73
- map: buildSourceMap(state, filename, code, generated, resultFile),
74
- diagnostics: [...diagnostics, ...state.diagnostics]
75
- };
76
- }
77
- __name(compileWithSourceMap, "compileWithSourceMap");
78
- function toCompilerDiagnostic(diagnostic, sourceFile, filename) {
79
- const start = diagnostic.start ?? 0;
80
- const length = diagnostic.length ?? 1;
81
- const message = ts__default.default.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
82
- const { line, column, codeFrame } = buildCodeFrame(sourceFile, start, length);
83
- return {
84
- code: `VOBS_C${String(diagnostic.code).padStart(3, "0")}`,
85
- severity: diagnostic.category === ts__default.default.DiagnosticCategory.Warning ? "warning" : "error",
86
- message,
87
- location: { file: filename, line, column },
88
- codeFrame
89
- };
90
- }
91
- __name(toCompilerDiagnostic, "toCompilerDiagnostic");
92
- function buildCodeFrame(sourceFile, start, length) {
93
- const position = sourceFile.getLineAndCharacterOfPosition(start);
94
- const lineText = sourceFile.text.split(/\r?\n/u)[position.line] ?? "";
95
- const markerLength = Math.max(1, Math.min(length, Math.max(1, lineText.length - position.character)));
96
- return {
97
- line: position.line + 1,
98
- column: position.character + 1,
99
- codeFrame: `${position.line + 1} | ${lineText}
100
- ${" ".repeat(String(position.line + 1).length + 3 + position.character)}${"^".repeat(markerLength)}`
101
- };
102
- }
103
- __name(buildCodeFrame, "buildCodeFrame");
104
- function reportUnsupportedTag(state, tagName) {
105
- const sourceFile = tagName.getSourceFile() ?? state.sourceFile;
106
- if (!sourceFile) return;
107
- const label = tagName.getText();
108
- const kindNote = tagName.kind === ts__default.default.SyntaxKind.JsxNamespacedName ? "\uFF08JSX \u547D\u540D\u7A7A\u95F4\u6807\u7B7E\uFF09" : "";
109
- const { line, column, codeFrame } = buildCodeFrame(sourceFile, tagName.getStart(sourceFile), tagName.getWidth(sourceFile));
110
- state.diagnostics.push({
111
- code: "VOBS_C101",
112
- severity: "error",
113
- message: `\u4E0D\u652F\u6301\u7684 JSX \u6807\u7B7E\u5F62\u6001\uFF1A<${label}>${kindNote}\u3002\u7EC4\u4EF6\u5FC5\u987B\u662F\u5927\u5199\u5F00\u5934\u7684\u6807\u8BC6\u7B26\uFF0CDOM \u5143\u7D20\u5FC5\u987B\u662F\u5C0F\u5199\u6807\u7B7E\u540D\u3002`,
114
- location: { file: state.filename, line, column },
115
- codeFrame,
116
- fix: `\u628A <${label}> \u6539\u4E3A <Component /> \u5F62\u5F0F\u7684\u7EC4\u4EF6\u6216\u5C0F\u5199 DOM \u6807\u7B7E\uFF1BFragment \u8BF7\u4F7F\u7528 <Fragment> \u6216 <>...</>\u3002`
117
- });
118
- }
119
- __name(reportUnsupportedTag, "reportUnsupportedTag");
120
- function buildSourceMap(state, filename, source, generated, resultFile) {
121
- const reparsed = ts__default.default.createSourceFile(filename, generated, ts__default.default.ScriptTarget.Latest, true, ts__default.default.ScriptKind.TSX);
122
- const segments = [];
123
- walkPairedTrees(state, resultFile, reparsed, reparsed, segments);
124
- segments.sort((a, b) => a.genLine - b.genLine || a.genCol - b.genCol);
125
- return {
126
- version: 3,
127
- file: filename,
128
- sources: [filename],
129
- sourcesContent: [source],
130
- names: [],
131
- mappings: encodeMappings(segments, generated.split("\n").length)
132
- };
133
- }
134
- __name(buildSourceMap, "buildSourceMap");
135
- function statementLists(node) {
136
- if (ts__default.default.isSourceFile(node) || ts__default.default.isBlock(node) || ts__default.default.isModuleBlock(node)) return node.statements;
137
- if (ts__default.default.isCaseClause(node) || ts__default.default.isDefaultClause(node)) return node.statements;
138
- return null;
139
- }
140
- __name(statementLists, "statementLists");
141
- function walkPairedTrees(state, original, generated, reparsed, segments) {
142
- const originalStatements = statementLists(original);
143
- const generatedStatements = statementLists(generated);
144
- if (originalStatements && generatedStatements) {
145
- if (originalStatements.length !== generatedStatements.length) return;
146
- for (let index = 0; index < originalStatements.length; index++) {
147
- const originalStatement = originalStatements[index];
148
- const generatedStatement = generatedStatements[index];
149
- recordSegment(state, originalStatement, generatedStatement, reparsed, segments);
150
- walkPairedTrees(state, originalStatement, generatedStatement, reparsed, segments);
151
- }
152
- return;
153
- }
154
- const originalChildren = [];
155
- const generatedChildren = [];
156
- ts__default.default.forEachChild(original, (node) => {
157
- originalChildren.push(node);
158
- });
159
- ts__default.default.forEachChild(generated, (node) => {
160
- generatedChildren.push(node);
161
- });
162
- if (originalChildren.length !== generatedChildren.length) return;
163
- for (let index = 0; index < originalChildren.length; index++) {
164
- walkPairedTrees(state, originalChildren[index], generatedChildren[index], reparsed, segments);
165
- }
166
- }
167
- __name(walkPairedTrees, "walkPairedTrees");
168
- function recordSegment(state, originalStatement, generatedStatement, reparsed, segments) {
169
- const source = state.statementSources.get(originalStatement) ?? positionOfOriginalStatement(state, originalStatement);
170
- if (!source) return;
171
- const position = reparsed.getLineAndCharacterOfPosition(generatedStatement.getStart(reparsed));
172
- segments.push({
173
- genLine: position.line,
174
- genCol: position.character,
175
- srcLine: source.line,
176
- srcCol: source.column
177
- });
178
- }
179
- __name(recordSegment, "recordSegment");
180
- function positionOfOriginalStatement(state, statement) {
181
- if (statement.pos < 0 || !state.sourceFile) return null;
182
- const { line, character } = state.sourceFile.getLineAndCharacterOfPosition(
183
- statement.getStart(state.sourceFile)
184
- );
185
- return { line, column: character };
186
- }
187
- __name(positionOfOriginalStatement, "positionOfOriginalStatement");
188
- function encodeMappings(segments, lineCount) {
189
- const lines = Array.from({ length: lineCount }, () => []);
190
- let prevGenLine = -1;
191
- let prevGenCol = 0;
192
- let prevSrcLine = 0;
193
- let prevSrcCol = 0;
194
- for (const segment of segments) {
195
- if (segment.genLine !== prevGenLine) {
196
- prevGenCol = 0;
197
- prevGenLine = segment.genLine;
198
- }
199
- const values = [
200
- segment.genCol - prevGenCol,
201
- 0,
202
- segment.srcLine - prevSrcLine,
203
- segment.srcCol - prevSrcCol
204
- ];
205
- lines[segment.genLine].push(values.map(encodeVlq).join(""));
206
- prevGenCol = segment.genCol;
207
- prevSrcLine = segment.srcLine;
208
- prevSrcCol = segment.srcCol;
209
- }
210
- return lines.map((line) => line.join(",")).join(";");
211
- }
212
- __name(encodeMappings, "encodeMappings");
213
- var base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
214
- function encodeVlq(value) {
215
- let encoded = value < 0 ? -value << 1 | 1 : value << 1;
216
- let result = "";
217
- do {
218
- let digit = encoded & 31;
219
- encoded >>>= 5;
220
- if (encoded > 0) digit |= 32;
221
- result += base64Chars[digit];
222
- } while (encoded > 0);
223
- return result;
224
- }
225
- __name(encodeVlq, "encodeVlq");
226
- function validatePlugins(plugins) {
227
- const names = /* @__PURE__ */ new Set();
228
- for (const plugin of plugins) {
229
- if (!plugin.name) throw new error.VobsError({ code: "VOBS_C007", layer: "compiler", message: "\u7F16\u8BD1\u5668\u63D2\u4EF6\u5FC5\u987B\u63D0\u4F9B name", fix: "\u4E3A\u63D2\u4EF6\u6DFB\u52A0\u7A33\u5B9A\u4E14\u552F\u4E00\u7684 name\u3002" });
230
- if (names.has(plugin.name)) throw new error.VobsError({ code: "VOBS_C007", layer: "compiler", message: `\u68C0\u6D4B\u5230\u91CD\u590D\u63D2\u4EF6: ${plugin.name}`, fix: "\u4E3A\u6BCF\u4E2A\u7F16\u8BD1\u5668\u63D2\u4EF6\u4F7F\u7528\u552F\u4E00\u7684 name\u3002" });
231
- names.add(plugin.name);
232
- }
233
- }
234
- __name(validatePlugins, "validatePlugins");
235
- function transformPluginNodes(sourceFile, plugin, context) {
236
- const transformNode = plugin.transform?.node ?? plugin.transformNode;
237
- if (!transformNode) return sourceFile;
238
- const transformer = /* @__PURE__ */ __name((transformContext) => (root) => {
239
- const visit = /* @__PURE__ */ __name((node) => {
240
- const replacement = transformNode(node, context);
241
- if (replacement === null) return void 0;
242
- return ts__default.default.visitEachChild(replacement ?? node, visit, transformContext);
243
- }, "visit");
244
- return ts__default.default.visitNode(root, visit);
245
- }, "transformer");
246
- const result = ts__default.default.transform(sourceFile, [transformer]);
247
- try {
248
- return result.transformed[0];
249
- } finally {
250
- result.dispose();
251
- }
252
- }
253
- __name(transformPluginNodes, "transformPluginNodes");
254
- function collectDeclaredNames(sourceFile) {
255
- const names = /* @__PURE__ */ new Set();
256
- const visit = /* @__PURE__ */ __name((node) => {
257
- if (ts__default.default.isIdentifier(node) && isBindingName(node)) names.add(node.text);
258
- ts__default.default.forEachChild(node, visit);
259
- }, "visit");
260
- visit(sourceFile);
261
- return names;
262
- }
263
- __name(collectDeclaredNames, "collectDeclaredNames");
264
- function collectStateAliases(sourceFile) {
265
- const aliases = /* @__PURE__ */ new Set();
266
- for (const statement of sourceFile.statements) {
267
- if (!ts__default.default.isImportDeclaration(statement) || !ts__default.default.isStringLiteral(statement.moduleSpecifier)) continue;
268
- const module = statement.moduleSpecifier.text;
269
- if (module !== "@vobs/reactivity" && module !== "@vobs/vobs") continue;
270
- const clause = statement.importClause;
271
- if (!clause?.namedBindings || !ts__default.default.isNamedImports(clause.namedBindings)) continue;
272
- for (const element of clause.namedBindings.elements) {
273
- if (element.propertyName ? element.propertyName.text === "state" : element.name.text === "state") {
274
- aliases.add(element.name.text);
275
- }
276
- }
277
- }
278
- return aliases;
279
- }
280
- __name(collectStateAliases, "collectStateAliases");
281
- function collectLocallyDeclaredNames(sourceFile) {
282
- const names = /* @__PURE__ */ new Set();
283
- const visit = /* @__PURE__ */ __name((node) => {
284
- if (ts__default.default.isImportDeclaration(node)) return;
285
- if (ts__default.default.isIdentifier(node) && isBindingName(node)) names.add(node.text);
286
- ts__default.default.forEachChild(node, visit);
287
- }, "visit");
288
- visit(sourceFile);
289
- return names;
290
- }
291
- __name(collectLocallyDeclaredNames, "collectLocallyDeclaredNames");
292
- function isBindingName(node) {
293
- const parent = node.parent;
294
- if (!parent) return false;
295
- if (ts__default.default.isPropertyAccessExpression(parent) && parent.name === node) return false;
296
- if (ts__default.default.isQualifiedName(parent) && parent.right === node) return false;
297
- if (ts__default.default.isJsxAttribute(parent)) return false;
298
- return parent.name === node;
299
- }
300
- __name(isBindingName, "isBindingName");
301
- function resolveHelperName(state, name) {
302
- const existing = state.helperAliases.get(name);
303
- if (existing) return existing;
304
- let alias = name;
305
- if (state.takenNames.has(alias)) {
306
- alias = `_vobs_${name}`;
307
- let suffix = 1;
308
- while (state.takenNames.has(alias)) alias = `_vobs_${name}_${suffix++}`;
309
- }
310
- state.helperAliases.set(name, alias);
311
- return alias;
312
- }
313
- __name(resolveHelperName, "resolveHelperName");
314
- function helperRef(state, name) {
315
- return ts__default.default.factory.createIdentifier(resolveHelperName(state, name));
316
- }
317
- __name(helperRef, "helperRef");
318
- function createRuntimeImports(state) {
319
- const modules = /* @__PURE__ */ new Map();
320
- for (const [name, alias] of state.helperAliases) {
321
- const module = name === "insertResourceBoundary" ? "@vobs/resource" : "@vobs/vobs";
322
- const imported = modules.get(module) ?? [];
323
- imported.push(ts__default.default.factory.createImportSpecifier(
324
- false,
325
- alias === name ? void 0 : ts__default.default.factory.createIdentifier(name),
326
- ts__default.default.factory.createIdentifier(alias)
327
- ));
328
- modules.set(module, imported);
329
- }
330
- return [...modules.entries()].map(([module, imported]) => ts__default.default.factory.createImportDeclaration(
331
- void 0,
332
- ts__default.default.factory.createImportClause(
333
- false,
334
- void 0,
335
- ts__default.default.factory.createNamedImports(imported)
336
- ),
337
- ts__default.default.factory.createStringLiteral(module)
338
- ));
339
- }
340
- __name(createRuntimeImports, "createRuntimeImports");
341
- function rebuildImport(state, node) {
342
- if (!ts__default.default.isStringLiteral(node.moduleSpecifier)) return node;
343
- return tagStatement(state, ts__default.default.factory.createImportDeclaration(
344
- node.modifiers,
345
- node.importClause,
346
- ts__default.default.factory.createStringLiteral(node.moduleSpecifier.text),
347
- node.attributes
348
- ), node);
349
- }
350
- __name(rebuildImport, "rebuildImport");
351
- function transformStatement(state, node) {
352
- if (ts__default.default.isFunctionDeclaration(node) && node.body) {
353
- return tagStatement(state, ts__default.default.factory.updateFunctionDeclaration(
354
- node,
355
- node.modifiers,
356
- node.asteriskToken,
357
- node.name,
358
- node.typeParameters,
359
- node.parameters,
360
- node.type,
361
- transformBlock(state, node.body)
362
- ), node);
363
- }
364
- if (ts__default.default.isVariableStatement(node)) return transformVariableStatement(state, node);
365
- if (ts__default.default.isExportAssignment(node) && containsJsx(node.expression)) {
366
- return tagStatement(state, ts__default.default.factory.updateExportAssignment(node, node.modifiers, transformEmbeddedExpression(state, node.expression)), node);
367
- }
368
- if (ts__default.default.isExpressionStatement(node) && containsJsx(node.expression)) {
369
- return tagStatement(state, ts__default.default.factory.updateExpressionStatement(node, transformEmbeddedExpression(state, node.expression)), node);
370
- }
371
- if (ts__default.default.isReturnStatement(node) && node.expression && containsJsx(node.expression)) {
372
- return tagStatement(state, ts__default.default.factory.updateReturnStatement(node, transformEmbeddedExpression(state, node.expression)), node);
373
- }
374
- return node;
375
- }
376
- __name(transformStatement, "transformStatement");
377
- function transformVariableStatement(state, node) {
378
- let changed = false;
379
- const declarations = node.declarationList.declarations.map((declaration) => {
380
- const initializer = declaration.initializer;
381
- if (!initializer) return declaration;
382
- let nextInitializer = inferStateDebugName(state, declaration, initializer) ?? initializer;
383
- if (containsJsx(nextInitializer)) {
384
- nextInitializer = transformEmbeddedExpression(state, nextInitializer);
385
- }
386
- if (nextInitializer === initializer) return declaration;
387
- changed = true;
388
- return ts__default.default.factory.updateVariableDeclaration(
389
- declaration,
390
- declaration.name,
391
- declaration.exclamationToken,
392
- declaration.type,
393
- nextInitializer
394
- );
395
- });
396
- if (!changed) return node;
397
- return tagStatement(state, ts__default.default.factory.updateVariableStatement(
398
- node,
399
- node.modifiers,
400
- ts__default.default.factory.updateVariableDeclarationList(node.declarationList, declarations)
401
- ), node);
402
- }
403
- __name(transformVariableStatement, "transformVariableStatement");
404
- function inferStateDebugName(state, declaration, initializer) {
405
- if (state.stateAliases.size === 0) return void 0;
406
- if (!ts__default.default.isIdentifier(declaration.name)) return void 0;
407
- let call = initializer;
408
- while (ts__default.default.isParenthesizedExpression(call) || ts__default.default.isAsExpression(call) || ts__default.default.isTypeAssertionExpression(call) || ts__default.default.isSatisfiesExpression(call)) {
409
- call = call.expression;
410
- }
411
- if (!ts__default.default.isCallExpression(call)) return void 0;
412
- const callee = call.expression;
413
- if (!ts__default.default.isIdentifier(callee) || !state.stateAliases.has(callee.text)) return void 0;
414
- if (state.localBindings.has(callee.text)) return void 0;
415
- if (call.arguments.length !== 1) return void 0;
416
- return ts__default.default.factory.createCallExpression(callee, call.typeArguments, [
417
- ...call.arguments,
418
- ts__default.default.factory.createStringLiteral(declaration.name.text)
419
- ]);
420
- }
421
- __name(inferStateDebugName, "inferStateDebugName");
422
- function containsJsx(expression) {
423
- let found = false;
424
- const visit = /* @__PURE__ */ __name((node) => {
425
- if (isJsxExpression(node)) {
426
- found = true;
427
- return;
428
- }
429
- ts__default.default.forEachChild(node, visit);
430
- }, "visit");
431
- visit(expression);
432
- return found;
433
- }
434
- __name(containsJsx, "containsJsx");
435
- function transformBlock(state, block) {
436
- const statements = block.statements.map((statement) => {
437
- if (!ts__default.default.isReturnStatement(statement) || !statement.expression) return transformStatement(state, statement);
438
- const expression = ts__default.default.isParenthesizedExpression(statement.expression) ? statement.expression.expression : statement.expression;
439
- return isJsxExpression(expression) ? tagStatement(state, ts__default.default.factory.updateReturnStatement(statement, transformJsxExpression(state, expression)), statement) : statement;
440
- });
441
- return ts__default.default.factory.updateBlock(block, statements);
442
- }
443
- __name(transformBlock, "transformBlock");
444
- function isJsxExpression(node) {
445
- return ts__default.default.isJsxElement(node) || ts__default.default.isJsxSelfClosingElement(node) || ts__default.default.isJsxFragment(node);
446
- }
447
- __name(isJsxExpression, "isJsxExpression");
448
- function transformJsxExpression(state, node) {
449
- if (ts__default.default.isJsxFragment(node)) return transformFragment(state, node.children);
450
- if (ts__default.default.isJsxElement(node)) {
451
- return transformElement(state, node, node.openingElement.tagName, node.openingElement.attributes, node.children);
452
- }
453
- return transformElement(state, node, node.tagName, node.attributes, []);
454
- }
455
- __name(transformJsxExpression, "transformJsxExpression");
456
- function transformElement(state, node, tagName, attributes, children) {
457
- if (isFragmentTag(tagName)) return transformFragment(state, children);
458
- if (!ts__default.default.isIdentifier(tagName)) {
459
- reportUnsupportedTag(state, tagName);
460
- }
461
- if (ts__default.default.isIdentifier(tagName) && tagName.text === "ResourceBoundary") {
462
- return transformResourceBoundary(state, node, attributes, children);
463
- }
464
- if (ts__default.default.isIdentifier(tagName) && tagName.text === "AsyncBoundary") {
465
- return transformAsyncBoundary(state, node, attributes, children);
466
- }
467
- if (ts__default.default.isIdentifier(tagName) && tagName.text === "ErrorBoundary") {
468
- return transformErrorBoundary(state, node, attributes, children);
469
- }
470
- if (ts__default.default.isIdentifier(tagName) && tagName.text === "Profiler") {
471
- return transformProfiler(state, node, attributes, children);
472
- }
473
- if (ts__default.default.isIdentifier(tagName) && /^[A-Z]/.test(tagName.text)) {
474
- const args = [
475
- ts__default.default.factory.createCallExpression(helperRef(state, "resolveComponent"), void 0, [
476
- tagName,
477
- ts__default.default.factory.createStringLiteral(state.filename),
478
- ts__default.default.factory.createStringLiteral(tagName.text)
479
- ]),
480
- createComponentProps(state, attributes, children)
481
- ];
482
- if (state.sourceLocation) args.push(createSourceLocation(tagName));
483
- return ts__default.default.factory.createCallExpression(helperRef(state, "createComponent"), void 0, args);
484
- }
485
- if (isStaticElement(tagName, attributes, children)) {
486
- return ts__default.default.factory.createCallExpression(
487
- helperRef(state, "cloneTemplate"),
488
- void 0,
489
- [registerTemplate(state, serializeStaticHtml(node))]
490
- );
491
- }
492
- const elementName = tagName.getText();
493
- const elementId = nextIdentifier(state, "_el");
494
- const statements = [
495
- createConstStatement(
496
- state,
497
- elementId,
498
- ts__default.default.factory.createCallExpression(
499
- helperRef(state, "createElement"),
500
- void 0,
501
- [ts__default.default.factory.createStringLiteral(elementName)]
502
- ),
503
- node
504
- )
505
- ];
506
- appendAttributes(state, statements, elementId, attributes);
507
- appendChildren(state, statements, elementId, children);
508
- statements.push(tagStatement(state, ts__default.default.factory.createReturnStatement(elementId), node));
509
- return ts__default.default.factory.createCallExpression(
510
- ts__default.default.factory.createArrowFunction(
511
- void 0,
512
- void 0,
513
- [],
514
- void 0,
515
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
516
- ts__default.default.factory.createBlock(statements, true)
517
- ),
518
- void 0,
519
- []
520
- );
521
- }
522
- __name(transformElement, "transformElement");
523
- function isFragmentTag(tagName) {
524
- return tagName.getText() === "Fragment" || tagName.getText() === "Vobs.Fragment";
525
- }
526
- __name(isFragmentTag, "isFragmentTag");
527
- function transformFragment(state, children) {
528
- const parent = nextIdentifier(state, "_fragmentParent");
529
- const anchor = nextIdentifier(state, "_fragmentAnchor");
530
- const statements = [];
531
- appendChildren(state, statements, parent, children, anchor);
532
- return ts__default.default.factory.createCallExpression(
533
- helperRef(state, "createFragment"),
534
- void 0,
535
- [ts__default.default.factory.createArrowFunction(
536
- void 0,
537
- void 0,
538
- [
539
- ts__default.default.factory.createParameterDeclaration(void 0, void 0, parent),
540
- ts__default.default.factory.createParameterDeclaration(void 0, void 0, anchor)
541
- ],
542
- void 0,
543
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
544
- ts__default.default.factory.createBlock(statements, true)
545
- )]
546
- );
547
- }
548
- __name(transformFragment, "transformFragment");
549
- function transformResourceBoundary(state, node, attributes, children) {
550
- const resource = getAttributeExpression(attributes, "resource");
551
- if (!resource) throw new error.VobsError({ code: "VOBS_C002", layer: "compiler", message: "ResourceBoundary \u5FC5\u987B\u63D0\u4F9B resource \u5C5E\u6027", fix: "\u4E3A ResourceBoundary \u6DFB\u52A0 resource={resource}\u3002" });
552
- const options = [
553
- ts__default.default.factory.createPropertyAssignment("resource", transformEmbeddedExpression(state, resource)),
554
- ts__default.default.factory.createPropertyAssignment("children", createBoundaryFactory(state, children))
555
- ];
556
- appendBoundaryOptionalProperty(state, options, attributes, "loading");
557
- appendBoundaryOptionalProperty(state, options, attributes, "empty");
558
- appendBoundaryOptionalProperty(state, options, attributes, "fallback");
559
- return createBoundaryFragment(state, node, "insertResourceBoundary", options);
560
- }
561
- __name(transformResourceBoundary, "transformResourceBoundary");
562
- function transformErrorBoundary(state, node, attributes, children) {
563
- const fallback = getAttributeExpression(attributes, "fallback");
564
- if (!fallback) throw new error.VobsError({ code: "VOBS_C002", layer: "compiler", message: "ErrorBoundary \u5FC5\u987B\u63D0\u4F9B fallback \u5C5E\u6027", fix: "\u4E3A ErrorBoundary \u6DFB\u52A0 fallback={(error, retry) => ...}\u3002" });
565
- return createBoundaryFragment(state, node, "insertErrorBoundary", [
566
- ts__default.default.factory.createPropertyAssignment("children", createBoundaryFactory(state, children)),
567
- ts__default.default.factory.createPropertyAssignment("fallback", transformEmbeddedExpression(state, fallback))
568
- ]);
569
- }
570
- __name(transformErrorBoundary, "transformErrorBoundary");
571
- function transformAsyncBoundary(state, node, attributes, children) {
572
- const promise = getAttributeExpression(attributes, "promise");
573
- if (!promise) throw new error.VobsError({ code: "VOBS_C002", layer: "compiler", message: "AsyncBoundary \u5FC5\u987B\u63D0\u4F9B promise \u5C5E\u6027", fix: "\u4E3A AsyncBoundary \u6DFB\u52A0 promise={promise}\u3002" });
574
- const options = [
575
- ts__default.default.factory.createPropertyAssignment("promise", transformEmbeddedExpression(state, promise)),
576
- ts__default.default.factory.createPropertyAssignment("children", createAsyncFactory(state, children))
577
- ];
578
- appendBoundaryOptionalProperty(state, options, attributes, "loading");
579
- appendBoundaryOptionalProperty(state, options, attributes, "fallback");
580
- const resetKey = getAttributeExpression(attributes, "resetKey");
581
- if (resetKey) options.push(ts__default.default.factory.createPropertyAssignment("resetKey", createGetter(resetKey)));
582
- return createBoundaryFragment(state, node, "insertAsyncBoundary", options);
583
- }
584
- __name(transformAsyncBoundary, "transformAsyncBoundary");
585
- function transformProfiler(state, node, attributes, children) {
586
- const idAttribute = attributes.properties.find((attribute) => ts__default.default.isJsxAttribute(attribute) && attribute.name.getText() === "id");
587
- const id = idAttribute && ts__default.default.isJsxAttribute(idAttribute) && idAttribute.initializer && ts__default.default.isStringLiteral(idAttribute.initializer) ? ts__default.default.factory.createStringLiteral(idAttribute.initializer.text) : idAttribute && ts__default.default.isJsxAttribute(idAttribute) && idAttribute.initializer && ts__default.default.isJsxExpression(idAttribute.initializer) ? idAttribute.initializer.expression : null;
588
- if (!id) throw new error.VobsError({ code: "VOBS_C002", layer: "compiler", message: "Profiler \u5FC5\u987B\u63D0\u4F9B id \u5C5E\u6027", fix: '\u4E3A Profiler \u6DFB\u52A0 id="ComponentName"\u3002' });
589
- const options = [
590
- ts__default.default.factory.createPropertyAssignment("id", transformEmbeddedExpression(state, id)),
591
- ts__default.default.factory.createPropertyAssignment("children", createBoundaryFactory(state, children))
592
- ];
593
- appendBoundaryOptionalProperty(state, options, attributes, "onRender");
594
- return createBoundaryFragment(state, node, "insertProfiler", options);
595
- }
596
- __name(transformProfiler, "transformProfiler");
597
- function createBoundaryFragment(state, node, helper, options) {
598
- const parent = nextIdentifier(state, "_boundaryParent");
599
- const anchor = nextIdentifier(state, "_boundaryAnchor");
600
- return ts__default.default.factory.createCallExpression(
601
- helperRef(state, "createFragment"),
602
- void 0,
603
- [ts__default.default.factory.createArrowFunction(
604
- void 0,
605
- void 0,
606
- [
607
- ts__default.default.factory.createParameterDeclaration(void 0, void 0, parent),
608
- ts__default.default.factory.createParameterDeclaration(void 0, void 0, anchor)
609
- ],
610
- void 0,
611
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
612
- ts__default.default.factory.createBlock([callStatement(state, helper, [
613
- parent,
614
- anchor,
615
- ts__default.default.factory.createObjectLiteralExpression(options, true)
616
- ], node)], true)
617
- )]
618
- );
619
- }
620
- __name(createBoundaryFragment, "createBoundaryFragment");
621
- function createBoundaryFactory(state, children) {
622
- const content = transformFragment(state, children);
623
- return ts__default.default.factory.createArrowFunction(
624
- void 0,
625
- void 0,
626
- [],
627
- void 0,
628
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
629
- content
630
- );
631
- }
632
- __name(createBoundaryFactory, "createBoundaryFactory");
633
- function createAsyncFactory(state, children) {
634
- const value = ts__default.default.factory.createIdentifier("value");
635
- const expressionChild = children.length === 1 && children[0].kind === ts__default.default.SyntaxKind.JsxExpression ? children[0].expression : void 0;
636
- if (expressionChild && ts__default.default.isArrowFunction(expressionChild)) {
637
- const transformed = transformEmbeddedExpression(state, expressionChild);
638
- return transformed;
639
- }
640
- const content = transformFragment(state, children);
641
- return ts__default.default.factory.createArrowFunction(void 0, void 0, [
642
- ts__default.default.factory.createParameterDeclaration(void 0, void 0, value)
643
- ], void 0, ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken), content);
644
- }
645
- __name(createAsyncFactory, "createAsyncFactory");
646
- function appendBoundaryOptionalProperty(state, properties, attributes, name) {
647
- const expression = getAttributeExpression(attributes, name);
648
- if (expression) {
649
- const transformed = transformEmbeddedExpression(state, expression);
650
- const value = isJsxExpression(unwrapExpression(expression)) ? createGetter(transformed) : transformed;
651
- properties.push(ts__default.default.factory.createPropertyAssignment(name, value));
652
- }
653
- }
654
- __name(appendBoundaryOptionalProperty, "appendBoundaryOptionalProperty");
655
- function getAttributeExpression(attributes, name) {
656
- for (const attribute of attributes.properties) {
657
- if (!ts__default.default.isJsxAttribute(attribute) || attribute.name.getText() !== name) continue;
658
- if (attribute.initializer && ts__default.default.isJsxExpression(attribute.initializer)) {
659
- return attribute.initializer.expression ?? null;
660
- }
661
- }
662
- return null;
663
- }
664
- __name(getAttributeExpression, "getAttributeExpression");
665
- function transformEmbeddedExpression(state, expression) {
666
- const result = ts__default.default.transform(expression, [(context) => (root) => {
667
- const visit = /* @__PURE__ */ __name((node) => {
668
- if (ts__default.default.isJsxElement(node) || ts__default.default.isJsxSelfClosingElement(node) || ts__default.default.isJsxFragment(node)) {
669
- return transformJsxExpression(state, node);
670
- }
671
- return ts__default.default.visitEachChild(node, visit, context);
672
- }, "visit");
673
- return ts__default.default.visitNode(root, visit);
674
- }]);
675
- try {
676
- return result.transformed[0];
677
- } finally {
678
- result.dispose();
679
- }
680
- }
681
- __name(transformEmbeddedExpression, "transformEmbeddedExpression");
682
- function isStaticElement(tagName, attributes, children) {
683
- if (!ts__default.default.isIdentifier(tagName) || !/^[a-z]/.test(tagName.text)) return false;
684
- for (const attribute of attributes.properties) {
685
- if (ts__default.default.isJsxSpreadAttribute(attribute)) return false;
686
- if (!ts__default.default.isJsxAttribute(attribute)) return false;
687
- const name = attribute.name.getText();
688
- if (name === "key" || name === "ref" || name.startsWith("on")) return false;
689
- if (isPropertyAttribute(name)) return false;
690
- const initializer = attribute.initializer;
691
- if (initializer && !ts__default.default.isStringLiteral(initializer)) return false;
692
- }
693
- for (const child of children) {
694
- if (ts__default.default.isJsxText(child)) continue;
695
- if (ts__default.default.isJsxElement(child) || ts__default.default.isJsxSelfClosingElement(child)) {
696
- const nested = ts__default.default.isJsxElement(child) ? { tagName: child.openingElement.tagName, attributes: child.openingElement.attributes, children: child.children } : { tagName: child.tagName, attributes: child.attributes, children: [] };
697
- if (!isStaticElement(nested.tagName, nested.attributes, nested.children)) return false;
698
- continue;
699
- }
700
- return false;
701
- }
702
- return true;
703
- }
704
- __name(isStaticElement, "isStaticElement");
705
- function serializeStaticHtml(node) {
706
- const { tagName, attributes, children } = ts__default.default.isJsxElement(node) ? { tagName: node.openingElement.tagName, attributes: node.openingElement.attributes, children: node.children } : { tagName: node.tagName, attributes: node.attributes, children: [] };
707
- return serializeStaticElement(tagName, attributes, children);
708
- }
709
- __name(serializeStaticHtml, "serializeStaticHtml");
710
- function serializeStaticElement(tagName, attributes, children) {
711
- const name = tagName.getText();
712
- let html = `<${name}`;
713
- for (const attribute of attributes.properties) {
714
- if (!ts__default.default.isJsxAttribute(attribute)) continue;
715
- const attributeName = attribute.name.getText() === "className" ? "class" : attribute.name.getText();
716
- const initializer = attribute.initializer;
717
- if (!initializer) {
718
- html += ` ${attributeName}=""`;
719
- continue;
720
- }
721
- if (ts__default.default.isStringLiteral(initializer)) {
722
- html += ` ${attributeName}="${escapeHtmlAttribute(initializer.text)}"`;
723
- }
724
- }
725
- html += ">";
726
- for (const child of children) {
727
- if (ts__default.default.isJsxText(child)) {
728
- const text = child.text.replace(/\s+/g, " ").trimStart();
729
- if (text.trim()) html += escapeHtmlText(text);
730
- continue;
731
- }
732
- if (ts__default.default.isJsxElement(child)) {
733
- html += serializeStaticElement(
734
- child.openingElement.tagName,
735
- child.openingElement.attributes,
736
- child.children
737
- );
738
- continue;
739
- }
740
- if (ts__default.default.isJsxSelfClosingElement(child)) {
741
- html += serializeStaticElement(child.tagName, child.attributes, []);
742
- }
743
- }
744
- html += `</${name}>`;
745
- return html;
746
- }
747
- __name(serializeStaticElement, "serializeStaticElement");
748
- function escapeHtmlAttribute(value) {
749
- return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
750
- }
751
- __name(escapeHtmlAttribute, "escapeHtmlAttribute");
752
- function escapeHtmlText(value) {
753
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
754
- }
755
- __name(escapeHtmlText, "escapeHtmlText");
756
- function registerTemplate(state, html) {
757
- const existing = state.templates.get(html);
758
- if (existing) return existing;
759
- const identifier = nextIdentifier(state, "_tpl");
760
- state.templates.set(html, identifier);
761
- return identifier;
762
- }
763
- __name(registerTemplate, "registerTemplate");
764
- function createTemplateDeclarations(state) {
765
- return [...state.templates.entries()].map(
766
- ([html, identifier]) => ts__default.default.factory.createVariableStatement(void 0, ts__default.default.factory.createVariableDeclarationList([
767
- ts__default.default.factory.createVariableDeclaration(identifier, void 0, void 0, ts__default.default.factory.createCallExpression(
768
- helperRef(state, "createTemplate"),
769
- void 0,
770
- [ts__default.default.factory.createStringLiteral(html)]
771
- ))
772
- ], ts__default.default.NodeFlags.Const))
773
- );
774
- }
775
- __name(createTemplateDeclarations, "createTemplateDeclarations");
776
- function appendAttributes(state, statements, element, attributes) {
777
- const staticProps = [];
778
- const hasSpread = attributes.properties.some((attribute) => ts__default.default.isJsxSpreadAttribute(attribute));
779
- for (const attribute of attributes.properties) {
780
- if (ts__default.default.isJsxSpreadAttribute(attribute)) {
781
- statements.push(callStatement(state, "spreadProps", [element, transformEmbeddedExpression(state, attribute.expression)], attribute));
782
- continue;
783
- }
784
- if (!ts__default.default.isJsxAttribute(attribute)) continue;
785
- const name = attribute.name.getText();
786
- if (name === "key") continue;
787
- if (name === "ref") {
788
- const initializer2 = attribute.initializer;
789
- if (initializer2 && ts__default.default.isJsxExpression(initializer2) && initializer2.expression) {
790
- statements.push(callStatement(state, "setRef", [element, transformEmbeddedExpression(state, initializer2.expression)], attribute));
791
- }
792
- continue;
793
- }
794
- const initializer = attribute.initializer;
795
- if (name.startsWith("on") && initializer && ts__default.default.isJsxExpression(initializer) && initializer.expression) {
796
- statements.push(callStatement(state, "addEventListener", [
797
- element,
798
- ts__default.default.factory.createStringLiteral(name.slice(2).toLowerCase()),
799
- initializer.expression
800
- ], attribute));
801
- continue;
802
- }
803
- if (!initializer) {
804
- if (hasSpread) {
805
- statements.push(callStatement(state, isPropertyAttribute(name) ? "setProperty" : "setAttribute", [element, ts__default.default.factory.createStringLiteral(isPropertyAttribute(name) ? name : name === "className" ? "class" : name), isPropertyAttribute(name) ? ts__default.default.factory.createTrue() : ts__default.default.factory.createStringLiteral("")], attribute));
806
- continue;
807
- }
808
- if (isPropertyAttribute(name)) staticProps.push(createStaticProperty(name, ts__default.default.factory.createTrue()));
809
- else staticProps.push(createStaticProperty(name === "className" ? "class" : name, ts__default.default.factory.createStringLiteral("")));
810
- continue;
811
- }
812
- if (ts__default.default.isStringLiteral(initializer)) {
813
- if (hasSpread) {
814
- statements.push(callStatement(state, isPropertyAttribute(name) ? "setProperty" : "setAttribute", [element, ts__default.default.factory.createStringLiteral(isPropertyAttribute(name) ? name : name === "className" ? "class" : name), ts__default.default.factory.createStringLiteral(initializer.text)], attribute));
815
- continue;
816
- }
817
- staticProps.push(createStaticProperty(
818
- isPropertyAttribute(name) ? name : name === "className" ? "class" : name,
819
- ts__default.default.factory.createStringLiteral(initializer.text)
820
- ));
821
- continue;
822
- }
823
- const attributeName = name === "className" ? "class" : name;
824
- const propertyAttribute = isPropertyAttribute(name);
825
- if (ts__default.default.isJsxExpression(initializer) && initializer.expression) {
826
- statements.push(callStatement(state, propertyAttribute ? "bindProperty" : "bindAttribute", [
827
- element,
828
- ts__default.default.factory.createStringLiteral(propertyAttribute ? name : attributeName),
829
- createGetter(initializer.expression)
830
- ], attribute));
831
- }
832
- }
833
- if (staticProps.length) statements.splice(1, 0, callStatement(state, "setStaticProps", [
834
- element,
835
- ts__default.default.factory.createObjectLiteralExpression(staticProps, true)
836
- ], attributes));
837
- }
838
- __name(appendAttributes, "appendAttributes");
839
- function createStaticProperty(name, value) {
840
- return ts__default.default.factory.createPropertyAssignment(ts__default.default.factory.createStringLiteral(name), value);
841
- }
842
- __name(createStaticProperty, "createStaticProperty");
843
- function isPropertyAttribute(name) {
844
- return name === "value" || name === "checked" || name === "selected" || name === "disabled" || name === "multiple" || name === "readOnly" || name === "required" || name === "autofocus" || name === "hidden" || name === "tabIndex";
845
- }
846
- __name(isPropertyAttribute, "isPropertyAttribute");
847
- function appendChildren(state, statements, element, children, anchor = ts__default.default.factory.createNull()) {
848
- for (const child of children) {
849
- if (ts__default.default.isJsxText(child)) {
850
- const text = child.text.replace(/\s+/g, " ").trimStart();
851
- if (text.trim()) {
852
- statements.push(callStatement(state, "insertBefore", [
853
- element,
854
- ts__default.default.factory.createCallExpression(helperRef(state, "createText"), void 0, [
855
- ts__default.default.factory.createStringLiteral(text)
856
- ]),
857
- anchor
858
- ], child));
859
- }
860
- continue;
861
- }
862
- if (ts__default.default.isJsxElement(child) || ts__default.default.isJsxSelfClosingElement(child) || ts__default.default.isJsxFragment(child)) {
863
- statements.push(callStatement(state, "insertBefore", [
864
- element,
865
- transformJsxExpression(state, child),
866
- anchor
867
- ], child));
868
- continue;
869
- }
870
- if (child.kind === ts__default.default.SyntaxKind.JsxExpression) {
871
- const expression = child.expression;
872
- if (!expression) continue;
873
- const list = transformListExpression(state, element, expression, anchor);
874
- if (list) {
875
- statements.push(callStatement(state, "insertList", list, child));
876
- continue;
877
- }
878
- const dynamic = transformDynamicExpression(state, expression);
879
- if (dynamic) {
880
- statements.push(callStatement(state, "insertDynamic", [element, anchor, dynamic], child));
881
- continue;
882
- }
883
- if (!containsJsx(expression) && !ts__default.default.isIdentifier(expression)) {
884
- const textId = nextIdentifier(state, "_text");
885
- statements.push(createConstStatement(state, textId, ts__default.default.factory.createCallExpression(helperRef(state, "createText"), void 0, [ts__default.default.factory.createStringLiteral("")]), child));
886
- statements.push(callStatement(state, "insertBefore", [element, textId, anchor], child));
887
- statements.push(callStatement(state, "bindText", [textId, createGetter(expression)], child));
888
- continue;
889
- }
890
- const value = transformEmbeddedExpression(state, expression);
891
- statements.push(callStatement(state, "insertDynamicValue", [element, anchor, createGetter(value)], child));
892
- }
893
- }
894
- }
895
- __name(appendChildren, "appendChildren");
896
- function createComponentProps(state, attributes, children) {
897
- const properties = [];
898
- for (const attribute of attributes.properties) {
899
- if (ts__default.default.isJsxSpreadAttribute(attribute)) {
900
- properties.push(ts__default.default.factory.createSpreadAssignment(attribute.expression));
901
- continue;
902
- }
903
- const name = propertyName(attribute.name.getText());
904
- if (attribute.name.getText() === "key") continue;
905
- const initializer = attribute.initializer;
906
- if (!initializer) {
907
- properties.push(ts__default.default.factory.createPropertyAssignment(name, ts__default.default.factory.createTrue()));
908
- } else if (ts__default.default.isStringLiteral(initializer)) {
909
- properties.push(ts__default.default.factory.createPropertyAssignment(name, ts__default.default.factory.createStringLiteral(initializer.text)));
910
- } else if (ts__default.default.isJsxExpression(initializer) && initializer.expression) {
911
- properties.push(createGetterProperty(name, transformEmbeddedExpression(state, initializer.expression)));
912
- }
913
- }
914
- const childExpressions = children.flatMap((child) => childToComponentExpression(state, child));
915
- if (childExpressions.length === 1) {
916
- properties.push(createGetterProperty("children", childExpressions[0]));
917
- } else if (childExpressions.length > 1) {
918
- properties.push(createGetterProperty("children", ts__default.default.factory.createArrayLiteralExpression(childExpressions)));
919
- }
920
- return ts__default.default.factory.createObjectLiteralExpression(properties, true);
921
- }
922
- __name(createComponentProps, "createComponentProps");
923
- function createSourceLocation(node) {
924
- const sourceFile = node.getSourceFile();
925
- const position = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
926
- return ts__default.default.factory.createObjectLiteralExpression([
927
- ts__default.default.factory.createPropertyAssignment("file", ts__default.default.factory.createStringLiteral(sourceFile.fileName)),
928
- ts__default.default.factory.createPropertyAssignment("line", ts__default.default.factory.createNumericLiteral(position.line + 1)),
929
- ts__default.default.factory.createPropertyAssignment("column", ts__default.default.factory.createNumericLiteral(position.character + 1))
930
- ], true);
931
- }
932
- __name(createSourceLocation, "createSourceLocation");
933
- function transformDynamicExpression(state, expression) {
934
- if (ts__default.default.isBinaryExpression(expression) && expression.operatorToken.kind === ts__default.default.SyntaxKind.AmpersandAmpersandToken) {
935
- const right = unwrapExpression(expression.right);
936
- if (!isJsxExpression(right)) return null;
937
- return createGetter(ts__default.default.factory.createConditionalExpression(
938
- expression.left,
939
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.QuestionToken),
940
- transformJsxExpression(state, right),
941
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.ColonToken),
942
- ts__default.default.factory.createNull()
943
- ));
944
- }
945
- if (ts__default.default.isConditionalExpression(expression)) {
946
- const whenTrue = transformDynamicBranch(state, expression.whenTrue);
947
- const whenFalse = transformDynamicBranch(state, expression.whenFalse);
948
- if (!whenTrue && !whenFalse) return null;
949
- return createGetter(ts__default.default.factory.createConditionalExpression(
950
- expression.condition,
951
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.QuestionToken),
952
- whenTrue ?? ts__default.default.factory.createNull(),
953
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.ColonToken),
954
- whenFalse ?? ts__default.default.factory.createNull()
955
- ));
956
- }
957
- return null;
958
- }
959
- __name(transformDynamicExpression, "transformDynamicExpression");
960
- function transformDynamicBranch(state, expression) {
961
- const branch = unwrapExpression(expression);
962
- if (isJsxExpression(branch)) return transformJsxExpression(state, branch);
963
- if (branch.kind === ts__default.default.SyntaxKind.NullKeyword || branch.kind === ts__default.default.SyntaxKind.FalseKeyword) return branch;
964
- return null;
965
- }
966
- __name(transformDynamicBranch, "transformDynamicBranch");
967
- function transformListExpression(state, parent, expression, anchor) {
968
- if (!ts__default.default.isCallExpression(expression) || expression.arguments.length !== 1) return null;
969
- if (!ts__default.default.isPropertyAccessExpression(expression.expression) || expression.expression.name.text !== "map") return null;
970
- const callback = expression.arguments[0];
971
- if (!ts__default.default.isArrowFunction(callback) && !ts__default.default.isFunctionExpression(callback)) return null;
972
- const body = unwrapExpression(callback.body);
973
- if (!isJsxExpression(body) || ts__default.default.isJsxFragment(body)) return null;
974
- const key = findKeyExpression(body);
975
- const renderItem = transformListCallback(callback, transformJsxExpression(state, body));
976
- const args = [
977
- parent,
978
- anchor,
979
- createGetter(expression.expression.expression),
980
- renderItem
981
- ];
982
- if (key) args.push(createKeyCallback(callback, key));
983
- return args;
984
- }
985
- __name(transformListExpression, "transformListExpression");
986
- function transformListCallback(callback, body) {
987
- if (ts__default.default.isArrowFunction(callback)) {
988
- return ts__default.default.factory.updateArrowFunction(
989
- callback,
990
- callback.modifiers,
991
- callback.typeParameters,
992
- callback.parameters,
993
- callback.type,
994
- callback.equalsGreaterThanToken,
995
- body
996
- );
997
- }
998
- return ts__default.default.factory.updateFunctionExpression(
999
- callback,
1000
- callback.modifiers,
1001
- callback.asteriskToken,
1002
- callback.name,
1003
- callback.typeParameters,
1004
- callback.parameters,
1005
- callback.type,
1006
- ts__default.default.factory.createBlock([ts__default.default.factory.createReturnStatement(body)], true)
1007
- );
1008
- }
1009
- __name(transformListCallback, "transformListCallback");
1010
- function createKeyCallback(callback, key) {
1011
- return ts__default.default.factory.createArrowFunction(
1012
- void 0,
1013
- void 0,
1014
- callback.parameters,
1015
- void 0,
1016
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
1017
- key
1018
- );
1019
- }
1020
- __name(createKeyCallback, "createKeyCallback");
1021
- function findKeyExpression(node) {
1022
- const attributes = ts__default.default.isJsxElement(node) ? node.openingElement.attributes : node.attributes;
1023
- for (const attribute of attributes.properties) {
1024
- if (!ts__default.default.isJsxAttribute(attribute) || attribute.name.getText() !== "key") continue;
1025
- if (attribute.initializer && ts__default.default.isJsxExpression(attribute.initializer)) {
1026
- return attribute.initializer.expression ?? null;
1027
- }
1028
- }
1029
- return null;
1030
- }
1031
- __name(findKeyExpression, "findKeyExpression");
1032
- function unwrapExpression(node) {
1033
- return ts__default.default.isParenthesizedExpression(node) ? node.expression : node;
1034
- }
1035
- __name(unwrapExpression, "unwrapExpression");
1036
- function childToComponentExpression(state, child) {
1037
- if (ts__default.default.isJsxText(child)) {
1038
- const text = child.text.replace(/\s+/g, " ").trim();
1039
- return text ? [ts__default.default.factory.createStringLiteral(text)] : [];
1040
- }
1041
- if (ts__default.default.isJsxElement(child) || ts__default.default.isJsxSelfClosingElement(child) || ts__default.default.isJsxFragment(child)) {
1042
- return [transformJsxExpression(state, child)];
1043
- }
1044
- if (child.kind === ts__default.default.SyntaxKind.JsxExpression) {
1045
- const expression = child.expression;
1046
- return expression ? [transformEmbeddedExpression(state, expression)] : [];
1047
- }
1048
- return [];
1049
- }
1050
- __name(childToComponentExpression, "childToComponentExpression");
1051
- function propertyName(name) {
1052
- return /^[$A-Z_a-z][$\w]*$/u.test(name) ? ts__default.default.factory.createIdentifier(name) : ts__default.default.factory.createStringLiteral(name);
1053
- }
1054
- __name(propertyName, "propertyName");
1055
- function createGetter(expression) {
1056
- return ts__default.default.factory.createArrowFunction(
1057
- void 0,
1058
- void 0,
1059
- [],
1060
- void 0,
1061
- ts__default.default.factory.createToken(ts__default.default.SyntaxKind.EqualsGreaterThanToken),
1062
- expression
1063
- );
1064
- }
1065
- __name(createGetter, "createGetter");
1066
- function createGetterProperty(name, expression) {
1067
- return ts__default.default.factory.createGetAccessorDeclaration(
1068
- void 0,
1069
- typeof name === "string" ? propertyName(name) : name,
1070
- [],
1071
- void 0,
1072
- ts__default.default.factory.createBlock([ts__default.default.factory.createReturnStatement(expression)], true)
1073
- );
1074
- }
1075
- __name(createGetterProperty, "createGetterProperty");
1076
- function callStatement(state, name, args, source) {
1077
- const statement = ts__default.default.factory.createExpressionStatement(
1078
- ts__default.default.factory.createCallExpression(helperRef(state, name), void 0, args)
1079
- );
1080
- return source ? tagStatement(state, statement, source) : statement;
1081
- }
1082
- __name(callStatement, "callStatement");
1083
- function createConstStatement(state, name, initializer, source) {
1084
- const statement = ts__default.default.factory.createVariableStatement(
1085
- void 0,
1086
- ts__default.default.factory.createVariableDeclarationList([
1087
- ts__default.default.factory.createVariableDeclaration(name, void 0, void 0, initializer)
1088
- ], ts__default.default.NodeFlags.Const)
1089
- );
1090
- return source ? tagStatement(state, statement, source) : statement;
1091
- }
1092
- __name(createConstStatement, "createConstStatement");
1093
- function tagStatement(state, statement, source) {
1094
- const position = positionOfNode(state, source);
1095
- if (position) state.statementSources.set(statement, position);
1096
- return statement;
1097
- }
1098
- __name(tagStatement, "tagStatement");
1099
- function positionOfNode(state, node) {
1100
- const sourceFile = node.getSourceFile() ?? state.sourceFile;
1101
- if (!sourceFile || node.pos < 0) return null;
1102
- const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
1103
- return { line, column: character };
1104
- }
1105
- __name(positionOfNode, "positionOfNode");
1106
- function nextIdentifier(state, prefix) {
1107
- let name;
1108
- do {
1109
- name = `${prefix}${state.generatedId++}`;
1110
- } while (state.takenNames.has(name));
1111
- return ts__default.default.factory.createIdentifier(name);
1112
- }
1113
- __name(nextIdentifier, "nextIdentifier");
1114
- function createI18nExtractor(options = {}) {
1115
- const names = new Set(options.functions ?? ["t"]);
1116
- const keys = /* @__PURE__ */ new Set();
1117
- const plugin = {
1118
- name: "i18n-extractor",
1119
- analyze(program, context) {
1120
- const visit = /* @__PURE__ */ __name((node) => {
1121
- if (ts__default.default.isCallExpression(node) && isTranslationCall(node.expression, names)) {
1122
- const key = readStaticKey(node.arguments[0]);
1123
- if (key) {
1124
- keys.add(key);
1125
- options.onKey?.(key, context.filename);
1126
- }
1127
- }
1128
- ts__default.default.forEachChild(node, visit);
1129
- }, "visit");
1130
- visit(program);
1131
- }
1132
- };
1133
- return {
1134
- plugin,
1135
- getKeys: /* @__PURE__ */ __name(() => [...keys].sort(), "getKeys"),
1136
- reset: /* @__PURE__ */ __name(() => keys.clear(), "reset")
1137
- };
1138
- }
1139
- __name(createI18nExtractor, "createI18nExtractor");
1140
- function isTranslationCall(expression, names) {
1141
- if (ts__default.default.isIdentifier(expression)) return names.has(expression.text);
1142
- return ts__default.default.isPropertyAccessExpression(expression) && names.has(expression.name.text);
1143
- }
1144
- __name(isTranslationCall, "isTranslationCall");
1145
- function readStaticKey(argument) {
1146
- if (!argument) return void 0;
1147
- if (ts__default.default.isStringLiteral(argument) || ts__default.default.isNoSubstitutionTemplateLiteral(argument)) return argument.text;
1148
- return void 0;
1149
- }
1150
- __name(readStaticKey, "readStaticKey");
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // packages/vite-plugin/src/index.ts
33
+ var src_exports = {};
34
+ __export(src_exports, {
35
+ vobsPlugin: () => vobsPlugin
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+ var import_promises = require("fs/promises");
39
+ var import_node_path = __toESM(require("path"), 1);
40
+ var import_compiler = require("@vobs/compiler");
41
+ var import_error = require("@vobs/runtime/error");
42
+
43
+ // packages/vite-plugin/src/html-component.ts
44
+ var import_parse5 = require("parse5");
1151
45
  var blockedTags = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "base", "meta", "link", "style"]);
1152
46
  var blockedAttributes = /^(?:on[a-z]+|srcdoc|style)$/iu;
1153
47
  var urlAttributes = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "poster", "xlink:href"]);
@@ -1166,7 +60,7 @@ var safePropertyNames = /* @__PURE__ */ new Set([
1166
60
  "tabindex"
1167
61
  ]);
1168
62
  function compileHtmlComponent(source, options = {}) {
1169
- const fragment = parse5.parseFragment(source);
63
+ const fragment = (0, import_parse5.parseFragment)(source);
1170
64
  const body = compileChildren(fragment, options.filename ?? "component.html");
1171
65
  const result = body.length === 1 ? body[0] : `createFragment((parent, anchor) => {${body.map((code) => `insertBefore(parent, ${code}, anchor);`).join("")}})`;
1172
66
  return `import { addEventListener, bindAttribute, bindProperty, bindText, createElement, createFragment, createText, insertBefore, insertDynamic, setAttribute } from '@vobs/vobs';
@@ -1282,33 +176,45 @@ function vobsPlugin(options = {}) {
1282
176
  const include = options.include ?? /\.tsx(?:$|\?)/;
1283
177
  const htmlModules = /* @__PURE__ */ new Set();
1284
178
  let productionBuild = false;
179
+ let hmrStateEnabled = (options.hmr ?? true) && (options.hmrState ?? true);
1285
180
  return {
1286
181
  name: "vobs",
1287
182
  enforce: "pre",
1288
183
  configResolved(config) {
1289
184
  productionBuild = config.command === "build";
185
+ hmrStateEnabled = (options.hmr ?? true) && !productionBuild && (options.hmrState ?? true);
1290
186
  },
1291
187
  resolveId(source, importer) {
1292
188
  if (!importer || !isHtmlComponent(source, options.html) || !isRelativeModule(source)) return null;
1293
189
  const cleanImporter = importer.split(/[?#]/u, 1)[0];
1294
190
  const cleanSource = source.split(/[?#]/u, 1)[0];
1295
- const resolved = path__default.default.resolve(path__default.default.dirname(cleanImporter), cleanSource);
191
+ const resolved = import_node_path.default.resolve(import_node_path.default.dirname(cleanImporter), cleanSource);
1296
192
  htmlModules.add(resolved);
1297
193
  return resolved;
1298
194
  },
1299
195
  async load(id) {
1300
196
  if (!htmlModules.has(id)) return null;
1301
- return compileHtmlComponent(await promises.readFile(id, "utf8"), { filename: id });
197
+ return compileHtmlComponent(await (0, import_promises.readFile)(id, "utf8"), { filename: id });
1302
198
  },
1303
199
  transform(code, id) {
1304
- include.lastIndex = 0;
1305
- if (!include.test(id)) return null;
1306
- const extractor = options.extractI18n ? createI18nExtractor({ onKey: options.extractI18n }) : void 0;
1307
- const result = compileWithSourceMap(code, {
200
+ const cleanId = id.split(/[?#]/u, 1)[0];
201
+ const isTsx = cleanId.endsWith(".tsx");
202
+ const isStateTs = isStateModulePath(cleanId);
203
+ if (!isTsx && !isStateTs) return null;
204
+ if (options.include) {
205
+ include.lastIndex = 0;
206
+ if (!include.test(id)) return null;
207
+ }
208
+ if (!isTsx && (!hmrStateEnabled || !isStatefulModule(code))) return null;
209
+ const extractor = options.extractI18n ? (0, import_compiler.createI18nExtractor)({ onKey: options.extractI18n }) : void 0;
210
+ const hmr = options.hmr ?? !productionBuild;
211
+ const result = (0, import_compiler.compileWithSourceMap)(code, {
1308
212
  ...options.compiler,
1309
213
  // 生产构建默认剔除组件源码位置(错误定位走 source map);显式配置优先。
1310
214
  sourceLocation: options.compiler?.sourceLocation ?? !productionBuild,
1311
215
  filename: id,
216
+ // HMR 模块标识必须跨 ?t= 查询稳定(registry 复用语义依赖它),用干净路径。
217
+ hmrModuleId: hmr ? cleanId : options.compiler?.hmrModuleId,
1312
218
  plugins: [
1313
219
  ...options.compiler?.plugins ?? [],
1314
220
  ...extractor ? [extractor.plugin] : []
@@ -1316,7 +222,7 @@ function vobsPlugin(options = {}) {
1316
222
  });
1317
223
  const diagnostic = result.diagnostics.find((item) => item.severity === "error");
1318
224
  if (diagnostic) {
1319
- throw new error.VobsError({
225
+ throw new import_error.VobsError({
1320
226
  code: diagnostic.code,
1321
227
  layer: "compiler",
1322
228
  message: diagnostic.message,
@@ -1325,8 +231,7 @@ function vobsPlugin(options = {}) {
1325
231
  fix: diagnostic.fix
1326
232
  });
1327
233
  }
1328
- const hmr = options.hmr ?? !productionBuild;
1329
- const hmrCode = hmr ? createHmrCode(id) : "";
234
+ const hmrCode = hmr ? createHmrCode(cleanId) : "";
1330
235
  return {
1331
236
  code: `${result.code}${hmrCode}`,
1332
237
  map: result.map
@@ -1335,6 +240,17 @@ function vobsPlugin(options = {}) {
1335
240
  };
1336
241
  }
1337
242
  __name(vobsPlugin, "vobsPlugin");
243
+ function isStatefulModule(code) {
244
+ return /\bimport\s+(?:type\s+)?\{[^}]*\bstate\b[^}]*\}\s*from\s*['"]@vobs\/(?:reactivity|vobs)['"]/u.test(code) && /(?<![\w$.])state\s*\(/u.test(code);
245
+ }
246
+ __name(isStatefulModule, "isStatefulModule");
247
+ function isStateModulePath(cleanId) {
248
+ if (!cleanId.endsWith(".ts")) return false;
249
+ if (cleanId.endsWith(".d.ts")) return false;
250
+ if (cleanId.includes("node_modules")) return false;
251
+ return true;
252
+ }
253
+ __name(isStateModulePath, "isStateModulePath");
1338
254
  function isRelativeModule(source) {
1339
255
  return source.startsWith("./") || source.startsWith("../");
1340
256
  }
@@ -1360,7 +276,8 @@ if (import.meta.hot) {
1360
276
  `;
1361
277
  }
1362
278
  __name(createHmrCode, "createHmrCode");
1363
-
1364
- exports.vobsPlugin = vobsPlugin;
1365
- //# sourceMappingURL=index.cjs.map
279
+ // Annotate the CommonJS export names for ESM import in node:
280
+ 0 && (module.exports = {
281
+ vobsPlugin
282
+ });
1366
283
  //# sourceMappingURL=index.cjs.map