@vobs/compiler 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.js CHANGED
@@ -1,8 +1,9 @@
1
- import ts from 'typescript';
2
- import { VobsError } from '@vobs/runtime/error';
3
-
4
1
  var __defProp = Object.defineProperty;
5
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // packages/compiler/src/compile.ts
5
+ import ts from "typescript";
6
+ import { VobsError } from "@vobs/runtime/error";
6
7
  function createCompiler(options = {}) {
7
8
  const basePlugins = options.plugins ?? [];
8
9
  return {
@@ -57,7 +58,8 @@ function compileWithSourceMap(code, options = {}) {
57
58
  sourceLocation: options.sourceLocation ?? true,
58
59
  stateAliases: collectStateAliases(sourceFile),
59
60
  localBindings: collectLocallyDeclaredNames(sourceFile),
60
- diagnostics: []
61
+ diagnostics: [],
62
+ hmrModuleId: options.hmrModuleId ?? null
61
63
  };
62
64
  const cleanFilename = filename.split(/[?#]/u, 1)[0] || filename;
63
65
  const diagnostics = ts.transpileModule(code, {
@@ -83,14 +85,15 @@ function compileWithSourceMap(code, options = {}) {
83
85
  }
84
86
  for (const plugin of plugins) sourceFile = transformPluginNodes(sourceFile, plugin, context);
85
87
  const statements = sourceFile.statements.map(
86
- (statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement)
88
+ (statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement, true)
87
89
  );
88
90
  const templateDeclarations = createTemplateDeclarations(state);
89
- const resultFile = ts.factory.updateSourceFile(sourceFile, [
91
+ let resultFile = ts.factory.updateSourceFile(sourceFile, [
90
92
  ...createRuntimeImports(state),
91
93
  ...templateDeclarations,
92
94
  ...statements
93
95
  ]);
96
+ resultFile = transformResidualJsx(state, resultFile);
94
97
  const generated = ts.createPrinter().printFile(resultFile);
95
98
  return {
96
99
  code: generated,
@@ -372,7 +375,7 @@ function rebuildImport(state, node) {
372
375
  ), node);
373
376
  }
374
377
  __name(rebuildImport, "rebuildImport");
375
- function transformStatement(state, node) {
378
+ function transformStatement(state, node, moduleScope = false) {
376
379
  if (ts.isFunctionDeclaration(node) && node.body) {
377
380
  return tagStatement(state, ts.factory.updateFunctionDeclaration(
378
381
  node,
@@ -385,7 +388,7 @@ function transformStatement(state, node) {
385
388
  transformBlock(state, node.body)
386
389
  ), node);
387
390
  }
388
- if (ts.isVariableStatement(node)) return transformVariableStatement(state, node);
391
+ if (ts.isVariableStatement(node)) return transformVariableStatement(state, node, moduleScope);
389
392
  if (ts.isExportAssignment(node) && containsJsx(node.expression)) {
390
393
  return tagStatement(state, ts.factory.updateExportAssignment(node, node.modifiers, transformEmbeddedExpression(state, node.expression)), node);
391
394
  }
@@ -398,7 +401,7 @@ function transformStatement(state, node) {
398
401
  return node;
399
402
  }
400
403
  __name(transformStatement, "transformStatement");
401
- function transformVariableStatement(state, node) {
404
+ function transformVariableStatement(state, node, moduleScope = false) {
402
405
  let changed = false;
403
406
  const declarations = node.declarationList.declarations.map((declaration) => {
404
407
  const initializer = declaration.initializer;
@@ -406,6 +409,8 @@ function transformVariableStatement(state, node) {
406
409
  let nextInitializer = inferStateDebugName(state, declaration, initializer) ?? initializer;
407
410
  if (containsJsx(nextInitializer)) {
408
411
  nextInitializer = transformEmbeddedExpression(state, nextInitializer);
412
+ } else if (moduleScope && state.hmrModuleId !== null) {
413
+ nextInitializer = wrapStateWithHmrRef(state, declaration, nextInitializer) ?? nextInitializer;
409
414
  }
410
415
  if (nextInitializer === initializer) return declaration;
411
416
  changed = true;
@@ -443,6 +448,29 @@ function inferStateDebugName(state, declaration, initializer) {
443
448
  ]);
444
449
  }
445
450
  __name(inferStateDebugName, "inferStateDebugName");
451
+ function wrapStateWithHmrRef(state, declaration, initializer) {
452
+ let call = initializer;
453
+ while (ts.isParenthesizedExpression(call) || ts.isAsExpression(call) || ts.isTypeAssertionExpression(call) || ts.isSatisfiesExpression(call)) {
454
+ call = call.expression;
455
+ }
456
+ if (!ts.isCallExpression(call)) return void 0;
457
+ const callee = call.expression;
458
+ if (!ts.isIdentifier(callee) || !state.stateAliases.has(callee.text)) return void 0;
459
+ if (state.localBindings.has(callee.text)) return void 0;
460
+ if (!ts.isIdentifier(declaration.name)) return void 0;
461
+ return ts.factory.createCallExpression(helperRef(state, "hmrStateRef"), void 0, [
462
+ ts.factory.createStringLiteral(`${state.hmrModuleId}#${declaration.name.text}`),
463
+ ts.factory.createArrowFunction(
464
+ void 0,
465
+ void 0,
466
+ [],
467
+ void 0,
468
+ ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
469
+ initializer
470
+ )
471
+ ]);
472
+ }
473
+ __name(wrapStateWithHmrRef, "wrapStateWithHmrRef");
446
474
  function containsJsx(expression) {
447
475
  let found = false;
448
476
  const visit = /* @__PURE__ */ __name((node) => {
@@ -703,6 +731,27 @@ function transformEmbeddedExpression(state, expression) {
703
731
  }
704
732
  }
705
733
  __name(transformEmbeddedExpression, "transformEmbeddedExpression");
734
+ function transformResidualJsx(state, sourceFile) {
735
+ if (!containsJsx(sourceFile)) return sourceFile;
736
+ const result = ts.transform(sourceFile, [(context) => (root) => {
737
+ const visit = /* @__PURE__ */ __name((node) => {
738
+ if (ts.isReturnStatement(node) && node.expression && containsJsx(node.expression)) {
739
+ return ts.factory.updateReturnStatement(node, transformEmbeddedExpression(state, node.expression));
740
+ }
741
+ if (isJsxExpression(node)) {
742
+ return transformJsxExpression(state, node);
743
+ }
744
+ return ts.visitEachChild(node, visit, context);
745
+ }, "visit");
746
+ return ts.visitNode(root, visit);
747
+ }]);
748
+ try {
749
+ return result.transformed[0];
750
+ } finally {
751
+ result.dispose();
752
+ }
753
+ }
754
+ __name(transformResidualJsx, "transformResidualJsx");
706
755
  function isStaticElement(tagName, attributes, children) {
707
756
  if (!ts.isIdentifier(tagName) || !/^[a-z]/.test(tagName.text)) return false;
708
757
  for (const attribute of attributes.properties) {
@@ -955,36 +1004,52 @@ function createSourceLocation(node) {
955
1004
  }
956
1005
  __name(createSourceLocation, "createSourceLocation");
957
1006
  function transformDynamicExpression(state, expression) {
1007
+ const converted = convertDynamicNodeExpression(state, expression);
1008
+ return converted ? createGetter(converted) : null;
1009
+ }
1010
+ __name(transformDynamicExpression, "transformDynamicExpression");
1011
+ function convertDynamicNodeExpression(state, expression) {
958
1012
  if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
959
1013
  const right = unwrapExpression(expression.right);
960
- if (!isJsxExpression(right)) return null;
961
- return createGetter(ts.factory.createConditionalExpression(
962
- expression.left,
963
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
964
- transformJsxExpression(state, right),
965
- ts.factory.createToken(ts.SyntaxKind.ColonToken),
966
- ts.factory.createNull()
967
- ));
1014
+ if (isJsxExpression(right)) {
1015
+ return createNodeConditional(expression.left, transformJsxExpression(state, right), null);
1016
+ }
1017
+ const convertedRight = convertDynamicNodeExpression(state, right);
1018
+ if (convertedRight) return createNodeConditional(expression.left, convertedRight, null);
1019
+ return null;
968
1020
  }
969
1021
  if (ts.isConditionalExpression(expression)) {
970
1022
  const whenTrue = transformDynamicBranch(state, expression.whenTrue);
971
1023
  const whenFalse = transformDynamicBranch(state, expression.whenFalse);
972
1024
  if (!whenTrue && !whenFalse) return null;
973
- return createGetter(ts.factory.createConditionalExpression(
1025
+ return ts.factory.createConditionalExpression(
974
1026
  expression.condition,
975
1027
  ts.factory.createToken(ts.SyntaxKind.QuestionToken),
976
1028
  whenTrue ?? ts.factory.createNull(),
977
1029
  ts.factory.createToken(ts.SyntaxKind.ColonToken),
978
1030
  whenFalse ?? ts.factory.createNull()
979
- ));
1031
+ );
980
1032
  }
981
1033
  return null;
982
1034
  }
983
- __name(transformDynamicExpression, "transformDynamicExpression");
1035
+ __name(convertDynamicNodeExpression, "convertDynamicNodeExpression");
1036
+ function createNodeConditional(condition, whenTrue, whenFalse) {
1037
+ return ts.factory.createConditionalExpression(
1038
+ condition,
1039
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1040
+ whenTrue,
1041
+ ts.factory.createToken(ts.SyntaxKind.ColonToken),
1042
+ whenFalse ?? ts.factory.createNull()
1043
+ );
1044
+ }
1045
+ __name(createNodeConditional, "createNodeConditional");
984
1046
  function transformDynamicBranch(state, expression) {
985
1047
  const branch = unwrapExpression(expression);
986
1048
  if (isJsxExpression(branch)) return transformJsxExpression(state, branch);
987
1049
  if (branch.kind === ts.SyntaxKind.NullKeyword || branch.kind === ts.SyntaxKind.FalseKeyword) return branch;
1050
+ if (ts.isConditionalExpression(branch) || ts.isBinaryExpression(branch) && branch.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
1051
+ return convertDynamicNodeExpression(state, branch);
1052
+ }
988
1053
  return null;
989
1054
  }
990
1055
  __name(transformDynamicBranch, "transformDynamicBranch");
@@ -1135,6 +1200,9 @@ function nextIdentifier(state, prefix) {
1135
1200
  return ts.factory.createIdentifier(name);
1136
1201
  }
1137
1202
  __name(nextIdentifier, "nextIdentifier");
1203
+
1204
+ // packages/compiler/src/i18n-extractor.ts
1205
+ import ts2 from "typescript";
1138
1206
  function createI18nExtractor(options = {}) {
1139
1207
  const names = new Set(options.functions ?? ["t"]);
1140
1208
  const keys = /* @__PURE__ */ new Set();
@@ -1142,14 +1210,14 @@ function createI18nExtractor(options = {}) {
1142
1210
  name: "i18n-extractor",
1143
1211
  analyze(program, context) {
1144
1212
  const visit = /* @__PURE__ */ __name((node) => {
1145
- if (ts.isCallExpression(node) && isTranslationCall(node.expression, names)) {
1213
+ if (ts2.isCallExpression(node) && isTranslationCall(node.expression, names)) {
1146
1214
  const key = readStaticKey(node.arguments[0]);
1147
1215
  if (key) {
1148
1216
  keys.add(key);
1149
1217
  options.onKey?.(key, context.filename);
1150
1218
  }
1151
1219
  }
1152
- ts.forEachChild(node, visit);
1220
+ ts2.forEachChild(node, visit);
1153
1221
  }, "visit");
1154
1222
  visit(program);
1155
1223
  }
@@ -1162,17 +1230,20 @@ function createI18nExtractor(options = {}) {
1162
1230
  }
1163
1231
  __name(createI18nExtractor, "createI18nExtractor");
1164
1232
  function isTranslationCall(expression, names) {
1165
- if (ts.isIdentifier(expression)) return names.has(expression.text);
1166
- return ts.isPropertyAccessExpression(expression) && names.has(expression.name.text);
1233
+ if (ts2.isIdentifier(expression)) return names.has(expression.text);
1234
+ return ts2.isPropertyAccessExpression(expression) && names.has(expression.name.text);
1167
1235
  }
1168
1236
  __name(isTranslationCall, "isTranslationCall");
1169
1237
  function readStaticKey(argument) {
1170
1238
  if (!argument) return void 0;
1171
- if (ts.isStringLiteral(argument) || ts.isNoSubstitutionTemplateLiteral(argument)) return argument.text;
1239
+ if (ts2.isStringLiteral(argument) || ts2.isNoSubstitutionTemplateLiteral(argument)) return argument.text;
1172
1240
  return void 0;
1173
1241
  }
1174
1242
  __name(readStaticKey, "readStaticKey");
1175
-
1176
- export { compile, compileWithSourceMap, createCompiler, createI18nExtractor };
1177
- //# sourceMappingURL=index.js.map
1243
+ export {
1244
+ compile,
1245
+ compileWithSourceMap,
1246
+ createCompiler,
1247
+ createI18nExtractor
1248
+ };
1178
1249
  //# sourceMappingURL=index.js.map