svelte2tsx 0.5.10 → 0.5.13

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/index.js CHANGED
@@ -2096,7 +2096,7 @@ const oneWayBindingAttributes$1 = new Map(['clientWidth', 'clientHeight', 'offse
2096
2096
  * List of all binding names that are transformed to sth like `binding = variable`.
2097
2097
  * This applies to readonly bindings and the this binding.
2098
2098
  */
2099
- const assignmentBindings = new Set([...oneWayBindingAttributes$1.keys(), 'this']);
2099
+ new Set([...oneWayBindingAttributes$1.keys(), 'this']);
2100
2100
  /**
2101
2101
  * Transform bind:xxx into something that conforms to JSX
2102
2102
  */
@@ -3495,8 +3495,8 @@ class Element {
3495
3495
  // remove the colon: svelte:xxx -> sveltexxx
3496
3496
  const nodeName = `svelte${this.node.name.substring(7)}`;
3497
3497
  this._name = '$$_' + nodeName + this.computeDepth();
3498
- this.startTransformation.push(`{ ${createElement}("${nodeName}", {`);
3499
- this.addNameConstDeclaration = () => (this.startTransformation[0] = `{ const ${this._name} = ${createElement}("${nodeName}", {`);
3498
+ this.startTransformation.push(`{ ${createElement}("${this.node.name}", {`);
3499
+ this.addNameConstDeclaration = () => (this.startTransformation[0] = `{ const ${this._name} = ${createElement}("${this.node.name}", {`);
3500
3500
  break;
3501
3501
  }
3502
3502
  case 'svelte:element': {
@@ -4858,22 +4858,6 @@ function getNamesFromLabeledStatement(node) {
4858
4858
  // svelte won't let you create a variable with $ prefix (reserved for stores)
4859
4859
  .filter((name) => !name.startsWith('$')));
4860
4860
  }
4861
- function isSafeToPrefixWithSemicolon(node) {
4862
- let parent = node.parent;
4863
- while (parent && !ts__default['default'].isExpressionStatement(parent)) {
4864
- parent = parent.parent;
4865
- }
4866
- if (!parent) {
4867
- return false;
4868
- }
4869
- return (parent.getStart() === node.getStart() &&
4870
- !(parent.parent &&
4871
- (ts__default['default'].isIfStatement(parent.parent) ||
4872
- ts__default['default'].isForStatement(parent.parent) ||
4873
- ts__default['default'].isForInStatement(parent.parent) ||
4874
- ts__default['default'].isForOfStatement(parent.parent) ||
4875
- ts__default['default'].isWhileStatement(parent.parent))));
4876
- }
4877
4861
 
4878
4862
  function is$$EventsDeclaration(node) {
4879
4863
  return isInterfaceOrTypeDeclaration(node) && node.name.text === '$$Events';
@@ -5978,72 +5962,12 @@ function getSingleSlotDef(componentNode, slotName) {
5978
5962
  return `__sveltets_1_instanceOf(${componentType}).$$slot_def['${slotName}']`;
5979
5963
  }
5980
5964
 
5981
- function handleStore(node, parent, str) {
5982
- const storename = node.name.slice(1);
5983
- //handle assign to
5984
- if (parent.type == 'AssignmentExpression' && parent.left == node && parent.operator == '=') {
5985
- const dollar = str.original.indexOf('$', node.start);
5986
- str.remove(dollar, dollar + 1);
5987
- str.overwrite(node.end, str.original.indexOf('=', node.end) + 1, '.set(');
5988
- str.appendLeft(parent.end, ')');
5989
- return;
5990
- }
5991
- // handle Assignment operators ($store +=, -=, *=, /=, %=, **=, etc.)
5992
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment
5993
- const operators = ['+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
5994
- if (parent.type == 'AssignmentExpression' &&
5995
- parent.left == node &&
5996
- operators.includes(parent.operator)) {
5997
- const storename = node.name.slice(1); // drop the $
5998
- const operator = parent.operator.substring(0, parent.operator.length - 1); // drop the = sign
5999
- str.overwrite(parent.start, str.original.indexOf('=', node.end) + 1, `${storename}.set( $${storename} ${operator}`);
6000
- str.appendLeft(parent.end, ')');
6001
- return;
6002
- }
6003
- // handle $store++, $store--, ++$store, --$store
6004
- if (parent.type == 'UpdateExpression') {
6005
- let simpleOperator;
6006
- if (parent.operator === '++') {
6007
- simpleOperator = '+';
6008
- }
6009
- if (parent.operator === '--') {
6010
- simpleOperator = '-';
6011
- }
6012
- if (simpleOperator) {
6013
- const storename = node.name.slice(1); // drop the $
6014
- str.overwrite(parent.start, parent.end, `(${storename}.set( $${storename} ${simpleOperator} 1), $${storename})`);
6015
- }
6016
- else {
6017
- console.warn(`Warning - unrecognized UpdateExpression operator ${parent.operator}!
6018
- This is an edge case unaccounted for in svelte2tsx, please file an issue:
6019
- https://github.com/sveltejs/language-tools/issues/new/choose
6020
- `, str.original.slice(parent.start, parent.end));
6021
- }
6022
- return;
6023
- }
6024
- const dollar = str.original.indexOf('$', node.start);
6025
- // handle bindings which are transformed to assignments. These need special treatment because
6026
- // `(__sveltets_1_store_get(foo), foo$) = something` is syntactically invalid
6027
- // Therefore remove the outer commas. Note: This relies on the binding expression wrapping
6028
- // this statement with __sveltets_1_empty
6029
- if (parent.type === 'Binding' && assignmentBindings.has(parent.name)) {
6030
- str.overwrite(dollar, dollar + 1, '__sveltets_1_store_get(', { contentOnly: true });
6031
- str.prependLeft(node.end, `), $${storename}`);
6032
- return;
6033
- }
6034
- // we change "$store" references into "(__sveltets_1_store_get(store), $store)"
6035
- // - in order to get ts errors if store is not assignable to SvelteStore
6036
- // - use $store variable defined above to get ts flow control
6037
- str.overwrite(dollar, dollar + 1, '(__sveltets_1_store_get(', { contentOnly: true });
6038
- str.prependLeft(node.end, `), $${storename})`);
6039
- }
6040
5965
  const reservedNames = new Set(['$$props', '$$restProps', '$$slots']);
6041
5966
  class Stores {
6042
- constructor(scope, str, isDeclaration) {
5967
+ constructor(scope, isDeclaration) {
6043
5968
  this.scope = scope;
6044
- this.str = str;
6045
5969
  this.isDeclaration = isDeclaration;
6046
- this.pendingStoreResolutions = [];
5970
+ this.possibleStores = [];
6047
5971
  }
6048
5972
  handleDirective(node, str) {
6049
5973
  if (this.notAStore(node.name) || this.isDeclaration.value) {
@@ -6051,7 +5975,7 @@ class Stores {
6051
5975
  }
6052
5976
  const start = str.original.indexOf('$', node.start);
6053
5977
  const end = start + node.name.length;
6054
- this.pendingStoreResolutions.push({
5978
+ this.possibleStores.push({
6055
5979
  node: { type: 'Identifier', start, end, name: node.name },
6056
5980
  parent: { start: 0, end: 0, type: '' },
6057
5981
  scope: this.scope.current
@@ -6075,18 +5999,17 @@ class Stores {
6075
5999
  if (isObjectKey(parent, prop)) {
6076
6000
  return;
6077
6001
  }
6078
- this.pendingStoreResolutions.push({ node, parent, scope: this.scope.current });
6002
+ this.possibleStores.push({ node, parent, scope: this.scope.current });
6079
6003
  }
6080
6004
  }
6081
- resolveStores() {
6082
- const unresolvedStores = this.pendingStoreResolutions.filter(({ node, scope }) => {
6005
+ getStoreNames() {
6006
+ const stores = this.possibleStores.filter(({ node, scope }) => {
6083
6007
  const name = node.name;
6084
6008
  // if variable starting with '$' was manually declared by the user,
6085
6009
  // this isn't a store access.
6086
6010
  return !scope.hasDefined(name);
6087
6011
  });
6088
- unresolvedStores.forEach(({ node, parent }) => handleStore(node, parent, this.str));
6089
- return unresolvedStores.map(({ node }) => node.name.slice(1));
6012
+ return stores.map(({ node }) => node.name.slice(1));
6090
6013
  }
6091
6014
  notAStore(name) {
6092
6015
  return name[0] !== '$' || reservedNames.has(name);
@@ -6377,9 +6300,15 @@ class Generics {
6377
6300
  /**
6378
6301
  * move imports to top of script so they appear outside our render function
6379
6302
  */
6380
- function handleImportDeclaration(node, str, astOffset, scriptStart) {
6303
+ function handleImportDeclaration(node, str, astOffset, scriptStart, sourceFile) {
6381
6304
  var _a;
6305
+ const scanner = ts__default['default'].createScanner(sourceFile.languageVersion,
6306
+ /*skipTrivia*/ false, sourceFile.languageVariant);
6382
6307
  const comments = (_a = ts__default['default'].getLeadingCommentRanges(node.getFullText(), 0)) !== null && _a !== void 0 ? _a : [];
6308
+ if (!comments.some((comment) => comment.hasTrailingNewLine) &&
6309
+ isNewGroup(sourceFile, node, scanner)) {
6310
+ str.appendRight(node.getStart() + astOffset, '\n');
6311
+ }
6383
6312
  for (const comment of comments) {
6384
6313
  const commentEnd = node.pos + comment.end + astOffset;
6385
6314
  str.move(node.pos + comment.pos + astOffset, commentEnd, scriptStart + 1);
@@ -6392,8 +6321,27 @@ function handleImportDeclaration(node, str, astOffset, scriptStart) {
6392
6321
  const originalEndChar = str.original[node.end + astOffset - 1];
6393
6322
  str.overwrite(node.end + astOffset - 1, node.end + astOffset, originalEndChar + '\n');
6394
6323
  }
6324
+ /**
6325
+ * adopted from https://github.com/microsoft/TypeScript/blob/6e0447fdf165b1cec9fc80802abcc15bd23a268f/src/services/organizeImports.ts#L111
6326
+ */
6327
+ function isNewGroup(sourceFile, topLevelImportDecl, scanner) {
6328
+ const startPos = topLevelImportDecl.getFullStart();
6329
+ const endPos = topLevelImportDecl.getStart();
6330
+ scanner.setText(sourceFile.text, startPos, endPos - startPos);
6331
+ let numberOfNewLines = 0;
6332
+ while (scanner.getTokenPos() < endPos) {
6333
+ const tokenKind = scanner.scan();
6334
+ if (tokenKind === ts__default['default'].SyntaxKind.NewLineTrivia) {
6335
+ numberOfNewLines++;
6336
+ if (numberOfNewLines >= 2) {
6337
+ return true;
6338
+ }
6339
+ }
6340
+ }
6341
+ return false;
6342
+ }
6395
6343
 
6396
- function processInstanceScriptContent(str, script, events, implicitStoreValues, mode) {
6344
+ function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript) {
6397
6345
  const htmlx = str.original;
6398
6346
  const scriptContent = htmlx.substring(script.content.start, script.content.end);
6399
6347
  const tsAst = ts__namespace.createSourceFile('component.ts.svelte', scriptContent, ts__namespace.ScriptTarget.Latest, true, ts__namespace.ScriptKind.TS);
@@ -6414,95 +6362,8 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6414
6362
  const rootScope = scope;
6415
6363
  const pushScope = () => (scope = new Scope(scope));
6416
6364
  const popScope = () => (scope = scope.parent);
6417
- const handleStore = (ident, parent) => {
6418
- // ignore "typeof $store"
6419
- if (parent && parent.kind === ts__namespace.SyntaxKind.TypeQuery) {
6420
- return;
6421
- }
6422
- // ignore break
6423
- if (parent && parent.kind === ts__namespace.SyntaxKind.BreakStatement) {
6424
- return;
6425
- }
6426
- const storename = ident.getText().slice(1); // drop the $
6427
- // handle assign to
6428
- if (parent &&
6429
- ts__namespace.isBinaryExpression(parent) &&
6430
- parent.operatorToken.kind == ts__namespace.SyntaxKind.EqualsToken &&
6431
- parent.left == ident) {
6432
- //remove $
6433
- const dollar = str.original.indexOf('$', ident.getStart() + astOffset);
6434
- str.remove(dollar, dollar + 1);
6435
- // replace = with .set(
6436
- str.overwrite(ident.end + astOffset, parent.operatorToken.end + astOffset, '.set(');
6437
- // append )
6438
- str.appendLeft(parent.end + astOffset, ')');
6439
- return;
6440
- }
6441
- // handle Assignment operators ($store +=, -=, *=, /=, %=, **=, etc.)
6442
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment
6443
- const operators = {
6444
- [ts__namespace.SyntaxKind.PlusEqualsToken]: '+',
6445
- [ts__namespace.SyntaxKind.MinusEqualsToken]: '-',
6446
- [ts__namespace.SyntaxKind.AsteriskEqualsToken]: '*',
6447
- [ts__namespace.SyntaxKind.SlashEqualsToken]: '/',
6448
- [ts__namespace.SyntaxKind.PercentEqualsToken]: '%',
6449
- [ts__namespace.SyntaxKind.AsteriskAsteriskEqualsToken]: '**',
6450
- [ts__namespace.SyntaxKind.LessThanLessThanEqualsToken]: '<<',
6451
- [ts__namespace.SyntaxKind.GreaterThanGreaterThanEqualsToken]: '>>',
6452
- [ts__namespace.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken]: '>>>',
6453
- [ts__namespace.SyntaxKind.AmpersandEqualsToken]: '&',
6454
- [ts__namespace.SyntaxKind.CaretEqualsToken]: '^',
6455
- [ts__namespace.SyntaxKind.BarEqualsToken]: '|'
6456
- };
6457
- if (ts__namespace.isBinaryExpression(parent) &&
6458
- parent.left == ident &&
6459
- Object.keys(operators).find((x) => x === String(parent.operatorToken.kind))) {
6460
- const operator = operators[parent.operatorToken.kind];
6461
- str.overwrite(parent.getStart() + astOffset, str.original.indexOf('=', ident.end + astOffset) + 1, `${storename}.set( $${storename} ${operator}`);
6462
- str.appendLeft(parent.end + astOffset, ')');
6463
- return;
6464
- }
6465
- // handle $store++, $store--, ++$store, --$store
6466
- if ((ts__namespace.isPrefixUnaryExpression(parent) || ts__namespace.isPostfixUnaryExpression(parent)) &&
6467
- ![
6468
- ts__namespace.SyntaxKind.ExclamationToken,
6469
- ts__namespace.SyntaxKind.PlusToken,
6470
- ts__namespace.SyntaxKind.MinusToken,
6471
- ts__namespace.SyntaxKind.TildeToken // ~$store
6472
- ].includes(parent.operator) /* `!$store` etc does not need processing */) {
6473
- let simpleOperator;
6474
- if (parent.operator === ts__namespace.SyntaxKind.PlusPlusToken) {
6475
- simpleOperator = '+';
6476
- }
6477
- if (parent.operator === ts__namespace.SyntaxKind.MinusMinusToken) {
6478
- simpleOperator = '-';
6479
- }
6480
- if (simpleOperator) {
6481
- str.overwrite(parent.getStart() + astOffset, parent.end + astOffset, `(${storename}.set( $${storename} ${simpleOperator} 1), $${storename})`);
6482
- return;
6483
- }
6484
- else {
6485
- console.warn(`Warning - unrecognized UnaryExpression operator ${parent.operator}!
6486
- This is an edge case unaccounted for in svelte2tsx, please file an issue:
6487
- https://github.com/sveltejs/language-tools/issues/new/choose
6488
- `, parent.getText());
6489
- }
6490
- }
6491
- // we change "$store" references into "(__sveltets_1_store_get(store), $store)"
6492
- // - in order to get ts errors if store is not assignable to SvelteStore
6493
- // - use $store variable defined above to get ts flow control
6494
- const dollar = str.original.indexOf('$', ident.getStart() + astOffset);
6495
- const getPrefix = isSafeToPrefixWithSemicolon(ident)
6496
- ? ';'
6497
- : ts__namespace.isShorthandPropertyAssignment(parent)
6498
- ? // { $store } --> { $store: __sveltets_1_store_get(..)}
6499
- ident.text + ': '
6500
- : '';
6501
- str.overwrite(dollar, dollar + 1, getPrefix + '(__sveltets_1_store_get(');
6502
- str.prependLeft(ident.end + astOffset, `), $${storename})`);
6503
- };
6504
6365
  const resolveStore = (pending) => {
6505
- let { node, parent, scope } = pending;
6366
+ let { node, scope } = pending;
6506
6367
  const name = node.text;
6507
6368
  while (scope) {
6508
6369
  if (scope.declared.has(name)) {
@@ -6511,8 +6372,6 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6511
6372
  }
6512
6373
  scope = scope.parent;
6513
6374
  }
6514
- //We haven't been resolved, we must be a store read/write, handle it.
6515
- handleStore(node, parent);
6516
6375
  const storename = node.getText().slice(1);
6517
6376
  implicitStoreValues.addStoreAcess(storename);
6518
6377
  };
@@ -6589,7 +6448,7 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6589
6448
  exportedNames.handleExportDeclaration(node);
6590
6449
  }
6591
6450
  if (ts__namespace.isImportDeclaration(node)) {
6592
- handleImportDeclaration(node, str, astOffset, script.start);
6451
+ handleImportDeclaration(node, str, astOffset, script.start, tsAst);
6593
6452
  // Check if import is the event dispatcher
6594
6453
  events.checkIfImportIsEventDispatcher(node);
6595
6454
  }
@@ -6662,7 +6521,9 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6662
6521
  .filter(ts__namespace.isImportDeclaration)
6663
6522
  .sort((a, b) => a.end - b.end)[0];
6664
6523
  if (firstImport) {
6665
- str.appendRight(firstImport.getStart() + astOffset, '\n');
6524
+ // ensure it's in a newline.
6525
+ // if file has module script ensure an empty line to separate imports
6526
+ str.appendRight(firstImport.getStart() + astOffset, '\n' + (hasModuleScript ? '\n' : ''));
6666
6527
  }
6667
6528
  if (mode === 'dts') {
6668
6529
  // Transform interface declarations to type declarations because indirectly
@@ -6986,7 +6847,7 @@ function processSvelteTemplate(str, options) {
6986
6847
  //track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes
6987
6848
  //which prevents us just changing all instances of Identity that start with $
6988
6849
  const scopeStack = new ScopeStack();
6989
- const stores = new Stores(scopeStack, str, isDeclaration);
6850
+ const stores = new Stores(scopeStack, isDeclaration);
6990
6851
  const scripts = new Scripts(htmlxAst);
6991
6852
  const handleSvelteOptions = (node) => {
6992
6853
  for (let i = 0; i < node.attributes.length; i++) {
@@ -7173,7 +7034,7 @@ function processSvelteTemplate(str, options) {
7173
7034
  const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags();
7174
7035
  scripts.blankOtherScriptTags(str);
7175
7036
  //resolve stores
7176
- const resolvedStores = stores.resolveStores();
7037
+ const resolvedStores = stores.getStoreNames();
7177
7038
  return {
7178
7039
  htmlAst: htmlxAst,
7179
7040
  moduleScriptTag,
@@ -7223,7 +7084,8 @@ function svelte2tsx(svelte, options = {}) {
7223
7084
  if (scriptTag.start != instanceScriptTarget) {
7224
7085
  str.move(scriptTag.start, scriptTag.end, instanceScriptTarget);
7225
7086
  }
7226
- const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode);
7087
+ const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode,
7088
+ /**hasModuleScripts */ !!moduleScriptTag);
7227
7089
  uses$$props = uses$$props || res.uses$$props;
7228
7090
  uses$$restProps = uses$$restProps || res.uses$$restProps;
7229
7091
  uses$$slots = uses$$slots || res.uses$$slots;
package/index.mjs CHANGED
@@ -2066,7 +2066,7 @@ const oneWayBindingAttributes$1 = new Map(['clientWidth', 'clientHeight', 'offse
2066
2066
  * List of all binding names that are transformed to sth like `binding = variable`.
2067
2067
  * This applies to readonly bindings and the this binding.
2068
2068
  */
2069
- const assignmentBindings = new Set([...oneWayBindingAttributes$1.keys(), 'this']);
2069
+ new Set([...oneWayBindingAttributes$1.keys(), 'this']);
2070
2070
  /**
2071
2071
  * Transform bind:xxx into something that conforms to JSX
2072
2072
  */
@@ -3465,8 +3465,8 @@ class Element {
3465
3465
  // remove the colon: svelte:xxx -> sveltexxx
3466
3466
  const nodeName = `svelte${this.node.name.substring(7)}`;
3467
3467
  this._name = '$$_' + nodeName + this.computeDepth();
3468
- this.startTransformation.push(`{ ${createElement}("${nodeName}", {`);
3469
- this.addNameConstDeclaration = () => (this.startTransformation[0] = `{ const ${this._name} = ${createElement}("${nodeName}", {`);
3468
+ this.startTransformation.push(`{ ${createElement}("${this.node.name}", {`);
3469
+ this.addNameConstDeclaration = () => (this.startTransformation[0] = `{ const ${this._name} = ${createElement}("${this.node.name}", {`);
3470
3470
  break;
3471
3471
  }
3472
3472
  case 'svelte:element': {
@@ -4828,22 +4828,6 @@ function getNamesFromLabeledStatement(node) {
4828
4828
  // svelte won't let you create a variable with $ prefix (reserved for stores)
4829
4829
  .filter((name) => !name.startsWith('$')));
4830
4830
  }
4831
- function isSafeToPrefixWithSemicolon(node) {
4832
- let parent = node.parent;
4833
- while (parent && !ts__default.isExpressionStatement(parent)) {
4834
- parent = parent.parent;
4835
- }
4836
- if (!parent) {
4837
- return false;
4838
- }
4839
- return (parent.getStart() === node.getStart() &&
4840
- !(parent.parent &&
4841
- (ts__default.isIfStatement(parent.parent) ||
4842
- ts__default.isForStatement(parent.parent) ||
4843
- ts__default.isForInStatement(parent.parent) ||
4844
- ts__default.isForOfStatement(parent.parent) ||
4845
- ts__default.isWhileStatement(parent.parent))));
4846
- }
4847
4831
 
4848
4832
  function is$$EventsDeclaration(node) {
4849
4833
  return isInterfaceOrTypeDeclaration(node) && node.name.text === '$$Events';
@@ -5948,72 +5932,12 @@ function getSingleSlotDef(componentNode, slotName) {
5948
5932
  return `__sveltets_1_instanceOf(${componentType}).$$slot_def['${slotName}']`;
5949
5933
  }
5950
5934
 
5951
- function handleStore(node, parent, str) {
5952
- const storename = node.name.slice(1);
5953
- //handle assign to
5954
- if (parent.type == 'AssignmentExpression' && parent.left == node && parent.operator == '=') {
5955
- const dollar = str.original.indexOf('$', node.start);
5956
- str.remove(dollar, dollar + 1);
5957
- str.overwrite(node.end, str.original.indexOf('=', node.end) + 1, '.set(');
5958
- str.appendLeft(parent.end, ')');
5959
- return;
5960
- }
5961
- // handle Assignment operators ($store +=, -=, *=, /=, %=, **=, etc.)
5962
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment
5963
- const operators = ['+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
5964
- if (parent.type == 'AssignmentExpression' &&
5965
- parent.left == node &&
5966
- operators.includes(parent.operator)) {
5967
- const storename = node.name.slice(1); // drop the $
5968
- const operator = parent.operator.substring(0, parent.operator.length - 1); // drop the = sign
5969
- str.overwrite(parent.start, str.original.indexOf('=', node.end) + 1, `${storename}.set( $${storename} ${operator}`);
5970
- str.appendLeft(parent.end, ')');
5971
- return;
5972
- }
5973
- // handle $store++, $store--, ++$store, --$store
5974
- if (parent.type == 'UpdateExpression') {
5975
- let simpleOperator;
5976
- if (parent.operator === '++') {
5977
- simpleOperator = '+';
5978
- }
5979
- if (parent.operator === '--') {
5980
- simpleOperator = '-';
5981
- }
5982
- if (simpleOperator) {
5983
- const storename = node.name.slice(1); // drop the $
5984
- str.overwrite(parent.start, parent.end, `(${storename}.set( $${storename} ${simpleOperator} 1), $${storename})`);
5985
- }
5986
- else {
5987
- console.warn(`Warning - unrecognized UpdateExpression operator ${parent.operator}!
5988
- This is an edge case unaccounted for in svelte2tsx, please file an issue:
5989
- https://github.com/sveltejs/language-tools/issues/new/choose
5990
- `, str.original.slice(parent.start, parent.end));
5991
- }
5992
- return;
5993
- }
5994
- const dollar = str.original.indexOf('$', node.start);
5995
- // handle bindings which are transformed to assignments. These need special treatment because
5996
- // `(__sveltets_1_store_get(foo), foo$) = something` is syntactically invalid
5997
- // Therefore remove the outer commas. Note: This relies on the binding expression wrapping
5998
- // this statement with __sveltets_1_empty
5999
- if (parent.type === 'Binding' && assignmentBindings.has(parent.name)) {
6000
- str.overwrite(dollar, dollar + 1, '__sveltets_1_store_get(', { contentOnly: true });
6001
- str.prependLeft(node.end, `), $${storename}`);
6002
- return;
6003
- }
6004
- // we change "$store" references into "(__sveltets_1_store_get(store), $store)"
6005
- // - in order to get ts errors if store is not assignable to SvelteStore
6006
- // - use $store variable defined above to get ts flow control
6007
- str.overwrite(dollar, dollar + 1, '(__sveltets_1_store_get(', { contentOnly: true });
6008
- str.prependLeft(node.end, `), $${storename})`);
6009
- }
6010
5935
  const reservedNames = new Set(['$$props', '$$restProps', '$$slots']);
6011
5936
  class Stores {
6012
- constructor(scope, str, isDeclaration) {
5937
+ constructor(scope, isDeclaration) {
6013
5938
  this.scope = scope;
6014
- this.str = str;
6015
5939
  this.isDeclaration = isDeclaration;
6016
- this.pendingStoreResolutions = [];
5940
+ this.possibleStores = [];
6017
5941
  }
6018
5942
  handleDirective(node, str) {
6019
5943
  if (this.notAStore(node.name) || this.isDeclaration.value) {
@@ -6021,7 +5945,7 @@ class Stores {
6021
5945
  }
6022
5946
  const start = str.original.indexOf('$', node.start);
6023
5947
  const end = start + node.name.length;
6024
- this.pendingStoreResolutions.push({
5948
+ this.possibleStores.push({
6025
5949
  node: { type: 'Identifier', start, end, name: node.name },
6026
5950
  parent: { start: 0, end: 0, type: '' },
6027
5951
  scope: this.scope.current
@@ -6045,18 +5969,17 @@ class Stores {
6045
5969
  if (isObjectKey(parent, prop)) {
6046
5970
  return;
6047
5971
  }
6048
- this.pendingStoreResolutions.push({ node, parent, scope: this.scope.current });
5972
+ this.possibleStores.push({ node, parent, scope: this.scope.current });
6049
5973
  }
6050
5974
  }
6051
- resolveStores() {
6052
- const unresolvedStores = this.pendingStoreResolutions.filter(({ node, scope }) => {
5975
+ getStoreNames() {
5976
+ const stores = this.possibleStores.filter(({ node, scope }) => {
6053
5977
  const name = node.name;
6054
5978
  // if variable starting with '$' was manually declared by the user,
6055
5979
  // this isn't a store access.
6056
5980
  return !scope.hasDefined(name);
6057
5981
  });
6058
- unresolvedStores.forEach(({ node, parent }) => handleStore(node, parent, this.str));
6059
- return unresolvedStores.map(({ node }) => node.name.slice(1));
5982
+ return stores.map(({ node }) => node.name.slice(1));
6060
5983
  }
6061
5984
  notAStore(name) {
6062
5985
  return name[0] !== '$' || reservedNames.has(name);
@@ -6347,9 +6270,15 @@ class Generics {
6347
6270
  /**
6348
6271
  * move imports to top of script so they appear outside our render function
6349
6272
  */
6350
- function handleImportDeclaration(node, str, astOffset, scriptStart) {
6273
+ function handleImportDeclaration(node, str, astOffset, scriptStart, sourceFile) {
6351
6274
  var _a;
6275
+ const scanner = ts__default.createScanner(sourceFile.languageVersion,
6276
+ /*skipTrivia*/ false, sourceFile.languageVariant);
6352
6277
  const comments = (_a = ts__default.getLeadingCommentRanges(node.getFullText(), 0)) !== null && _a !== void 0 ? _a : [];
6278
+ if (!comments.some((comment) => comment.hasTrailingNewLine) &&
6279
+ isNewGroup(sourceFile, node, scanner)) {
6280
+ str.appendRight(node.getStart() + astOffset, '\n');
6281
+ }
6353
6282
  for (const comment of comments) {
6354
6283
  const commentEnd = node.pos + comment.end + astOffset;
6355
6284
  str.move(node.pos + comment.pos + astOffset, commentEnd, scriptStart + 1);
@@ -6362,8 +6291,27 @@ function handleImportDeclaration(node, str, astOffset, scriptStart) {
6362
6291
  const originalEndChar = str.original[node.end + astOffset - 1];
6363
6292
  str.overwrite(node.end + astOffset - 1, node.end + astOffset, originalEndChar + '\n');
6364
6293
  }
6294
+ /**
6295
+ * adopted from https://github.com/microsoft/TypeScript/blob/6e0447fdf165b1cec9fc80802abcc15bd23a268f/src/services/organizeImports.ts#L111
6296
+ */
6297
+ function isNewGroup(sourceFile, topLevelImportDecl, scanner) {
6298
+ const startPos = topLevelImportDecl.getFullStart();
6299
+ const endPos = topLevelImportDecl.getStart();
6300
+ scanner.setText(sourceFile.text, startPos, endPos - startPos);
6301
+ let numberOfNewLines = 0;
6302
+ while (scanner.getTokenPos() < endPos) {
6303
+ const tokenKind = scanner.scan();
6304
+ if (tokenKind === ts__default.SyntaxKind.NewLineTrivia) {
6305
+ numberOfNewLines++;
6306
+ if (numberOfNewLines >= 2) {
6307
+ return true;
6308
+ }
6309
+ }
6310
+ }
6311
+ return false;
6312
+ }
6365
6313
 
6366
- function processInstanceScriptContent(str, script, events, implicitStoreValues, mode) {
6314
+ function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript) {
6367
6315
  const htmlx = str.original;
6368
6316
  const scriptContent = htmlx.substring(script.content.start, script.content.end);
6369
6317
  const tsAst = ts.createSourceFile('component.ts.svelte', scriptContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
@@ -6384,95 +6332,8 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6384
6332
  const rootScope = scope;
6385
6333
  const pushScope = () => (scope = new Scope(scope));
6386
6334
  const popScope = () => (scope = scope.parent);
6387
- const handleStore = (ident, parent) => {
6388
- // ignore "typeof $store"
6389
- if (parent && parent.kind === ts.SyntaxKind.TypeQuery) {
6390
- return;
6391
- }
6392
- // ignore break
6393
- if (parent && parent.kind === ts.SyntaxKind.BreakStatement) {
6394
- return;
6395
- }
6396
- const storename = ident.getText().slice(1); // drop the $
6397
- // handle assign to
6398
- if (parent &&
6399
- ts.isBinaryExpression(parent) &&
6400
- parent.operatorToken.kind == ts.SyntaxKind.EqualsToken &&
6401
- parent.left == ident) {
6402
- //remove $
6403
- const dollar = str.original.indexOf('$', ident.getStart() + astOffset);
6404
- str.remove(dollar, dollar + 1);
6405
- // replace = with .set(
6406
- str.overwrite(ident.end + astOffset, parent.operatorToken.end + astOffset, '.set(');
6407
- // append )
6408
- str.appendLeft(parent.end + astOffset, ')');
6409
- return;
6410
- }
6411
- // handle Assignment operators ($store +=, -=, *=, /=, %=, **=, etc.)
6412
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment
6413
- const operators = {
6414
- [ts.SyntaxKind.PlusEqualsToken]: '+',
6415
- [ts.SyntaxKind.MinusEqualsToken]: '-',
6416
- [ts.SyntaxKind.AsteriskEqualsToken]: '*',
6417
- [ts.SyntaxKind.SlashEqualsToken]: '/',
6418
- [ts.SyntaxKind.PercentEqualsToken]: '%',
6419
- [ts.SyntaxKind.AsteriskAsteriskEqualsToken]: '**',
6420
- [ts.SyntaxKind.LessThanLessThanEqualsToken]: '<<',
6421
- [ts.SyntaxKind.GreaterThanGreaterThanEqualsToken]: '>>',
6422
- [ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken]: '>>>',
6423
- [ts.SyntaxKind.AmpersandEqualsToken]: '&',
6424
- [ts.SyntaxKind.CaretEqualsToken]: '^',
6425
- [ts.SyntaxKind.BarEqualsToken]: '|'
6426
- };
6427
- if (ts.isBinaryExpression(parent) &&
6428
- parent.left == ident &&
6429
- Object.keys(operators).find((x) => x === String(parent.operatorToken.kind))) {
6430
- const operator = operators[parent.operatorToken.kind];
6431
- str.overwrite(parent.getStart() + astOffset, str.original.indexOf('=', ident.end + astOffset) + 1, `${storename}.set( $${storename} ${operator}`);
6432
- str.appendLeft(parent.end + astOffset, ')');
6433
- return;
6434
- }
6435
- // handle $store++, $store--, ++$store, --$store
6436
- if ((ts.isPrefixUnaryExpression(parent) || ts.isPostfixUnaryExpression(parent)) &&
6437
- ![
6438
- ts.SyntaxKind.ExclamationToken,
6439
- ts.SyntaxKind.PlusToken,
6440
- ts.SyntaxKind.MinusToken,
6441
- ts.SyntaxKind.TildeToken // ~$store
6442
- ].includes(parent.operator) /* `!$store` etc does not need processing */) {
6443
- let simpleOperator;
6444
- if (parent.operator === ts.SyntaxKind.PlusPlusToken) {
6445
- simpleOperator = '+';
6446
- }
6447
- if (parent.operator === ts.SyntaxKind.MinusMinusToken) {
6448
- simpleOperator = '-';
6449
- }
6450
- if (simpleOperator) {
6451
- str.overwrite(parent.getStart() + astOffset, parent.end + astOffset, `(${storename}.set( $${storename} ${simpleOperator} 1), $${storename})`);
6452
- return;
6453
- }
6454
- else {
6455
- console.warn(`Warning - unrecognized UnaryExpression operator ${parent.operator}!
6456
- This is an edge case unaccounted for in svelte2tsx, please file an issue:
6457
- https://github.com/sveltejs/language-tools/issues/new/choose
6458
- `, parent.getText());
6459
- }
6460
- }
6461
- // we change "$store" references into "(__sveltets_1_store_get(store), $store)"
6462
- // - in order to get ts errors if store is not assignable to SvelteStore
6463
- // - use $store variable defined above to get ts flow control
6464
- const dollar = str.original.indexOf('$', ident.getStart() + astOffset);
6465
- const getPrefix = isSafeToPrefixWithSemicolon(ident)
6466
- ? ';'
6467
- : ts.isShorthandPropertyAssignment(parent)
6468
- ? // { $store } --> { $store: __sveltets_1_store_get(..)}
6469
- ident.text + ': '
6470
- : '';
6471
- str.overwrite(dollar, dollar + 1, getPrefix + '(__sveltets_1_store_get(');
6472
- str.prependLeft(ident.end + astOffset, `), $${storename})`);
6473
- };
6474
6335
  const resolveStore = (pending) => {
6475
- let { node, parent, scope } = pending;
6336
+ let { node, scope } = pending;
6476
6337
  const name = node.text;
6477
6338
  while (scope) {
6478
6339
  if (scope.declared.has(name)) {
@@ -6481,8 +6342,6 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6481
6342
  }
6482
6343
  scope = scope.parent;
6483
6344
  }
6484
- //We haven't been resolved, we must be a store read/write, handle it.
6485
- handleStore(node, parent);
6486
6345
  const storename = node.getText().slice(1);
6487
6346
  implicitStoreValues.addStoreAcess(storename);
6488
6347
  };
@@ -6559,7 +6418,7 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6559
6418
  exportedNames.handleExportDeclaration(node);
6560
6419
  }
6561
6420
  if (ts.isImportDeclaration(node)) {
6562
- handleImportDeclaration(node, str, astOffset, script.start);
6421
+ handleImportDeclaration(node, str, astOffset, script.start, tsAst);
6563
6422
  // Check if import is the event dispatcher
6564
6423
  events.checkIfImportIsEventDispatcher(node);
6565
6424
  }
@@ -6632,7 +6491,9 @@ function processInstanceScriptContent(str, script, events, implicitStoreValues,
6632
6491
  .filter(ts.isImportDeclaration)
6633
6492
  .sort((a, b) => a.end - b.end)[0];
6634
6493
  if (firstImport) {
6635
- str.appendRight(firstImport.getStart() + astOffset, '\n');
6494
+ // ensure it's in a newline.
6495
+ // if file has module script ensure an empty line to separate imports
6496
+ str.appendRight(firstImport.getStart() + astOffset, '\n' + (hasModuleScript ? '\n' : ''));
6636
6497
  }
6637
6498
  if (mode === 'dts') {
6638
6499
  // Transform interface declarations to type declarations because indirectly
@@ -6956,7 +6817,7 @@ function processSvelteTemplate(str, options) {
6956
6817
  //track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes
6957
6818
  //which prevents us just changing all instances of Identity that start with $
6958
6819
  const scopeStack = new ScopeStack();
6959
- const stores = new Stores(scopeStack, str, isDeclaration);
6820
+ const stores = new Stores(scopeStack, isDeclaration);
6960
6821
  const scripts = new Scripts(htmlxAst);
6961
6822
  const handleSvelteOptions = (node) => {
6962
6823
  for (let i = 0; i < node.attributes.length; i++) {
@@ -7143,7 +7004,7 @@ function processSvelteTemplate(str, options) {
7143
7004
  const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags();
7144
7005
  scripts.blankOtherScriptTags(str);
7145
7006
  //resolve stores
7146
- const resolvedStores = stores.resolveStores();
7007
+ const resolvedStores = stores.getStoreNames();
7147
7008
  return {
7148
7009
  htmlAst: htmlxAst,
7149
7010
  moduleScriptTag,
@@ -7193,7 +7054,8 @@ function svelte2tsx(svelte, options = {}) {
7193
7054
  if (scriptTag.start != instanceScriptTarget) {
7194
7055
  str.move(scriptTag.start, scriptTag.end, instanceScriptTarget);
7195
7056
  }
7196
- const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode);
7057
+ const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode,
7058
+ /**hasModuleScripts */ !!moduleScriptTag);
7197
7059
  uses$$props = uses$$props || res.uses$$props;
7198
7060
  uses$$restProps = uses$$restProps || res.uses$$restProps;
7199
7061
  uses$$slots = uses$$slots || res.uses$$slots;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte2tsx",
3
- "version": "0.5.10",
3
+ "version": "0.5.13",
4
4
  "description": "Convert Svelte components to TSX for type checking",
5
5
  "author": "David Pershouse",
6
6
  "license": "MIT",
@@ -34,10 +34,10 @@
34
34
  "rollup-plugin-delete": "^2.0.0",
35
35
  "source-map-support": "^0.5.16",
36
36
  "sourcemap-codec": "^1.4.8",
37
- "svelte": "~3.48.0",
37
+ "svelte": "~3.49.0",
38
38
  "tiny-glob": "^0.2.6",
39
39
  "tslib": "^1.10.0",
40
- "typescript": "^4.6.2"
40
+ "typescript": "^4.7.3"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "svelte": "^3.24",
package/svelte-jsx.d.ts CHANGED
@@ -294,11 +294,11 @@ declare namespace svelteHTML {
294
294
  view: SVGProps<SVGViewElement>;
295
295
 
296
296
  // Svelte specific
297
- sveltewindow: HTMLProps<Window> & SvelteWindowProps;
298
- sveltebody: HTMLProps<HTMLElement>;
299
- sveltefragment: { slot?: string; };
300
- svelteoptions: { [name: string]: any };
301
- sveltehead: { [name: string]: any };
297
+ 'svelte:window': HTMLProps<Window> & SvelteWindowProps;
298
+ 'svelte:body': HTMLProps<HTMLElement>;
299
+ 'svelte:fragment': { slot?: string; };
300
+ 'svelte:options': { [name: string]: any };
301
+ 'svelte:head': { [name: string]: any };
302
302
 
303
303
  [name: string]: { [name: string]: any };
304
304
  }
@@ -888,6 +888,7 @@ declare namespace svelte.JSX {
888
888
  autosave?: string | undefined | null;
889
889
  color?: string | undefined | null;
890
890
  controlslist?: 'nodownload' | 'nofullscreen' | 'noplaybackrate' | 'noremoteplayback';
891
+ inert?: boolean | undefined | null;
891
892
  itemprop?: string | undefined | null;
892
893
  itemscope?: boolean | undefined | null;
893
894
  itemtype?: string | undefined | null;
package/svelte-shims.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  // -- start svelte-ls-remove --
7
7
  declare module '*.svelte' {
8
- export default Svelte2TsxComponent
8
+ export default _SvelteComponent
9
9
  }
10
10
  // -- end svelte-ls-remove --
11
11
 
@@ -53,6 +53,8 @@ declare class Svelte2TsxComponent<
53
53
  $inject_state(): void;
54
54
  }
55
55
 
56
+ type _SvelteComponent<Props=any,Events=any,Slots=any> = typeof import("svelte") extends {SvelteComponentTyped: any} ? import("svelte").SvelteComponentTyped<Props,Events,Slots> : Svelte2TsxComponent<Props,Events,Slots>;
57
+
56
58
  interface Svelte2TsxComponentConstructorParameters<Props extends {}> {
57
59
  /**
58
60
  * An HTMLElement to render to. This option is required.
@@ -167,7 +169,7 @@ declare function __sveltets_1_store_get<T = any>(store: SvelteStore<T>): T
167
169
  declare function __sveltets_1_store_get<Store extends SvelteStore<any> | undefined | null>(store: Store): Store extends SvelteStore<infer T> ? T : Store;
168
170
  declare function __sveltets_1_any(dummy: any): any;
169
171
  declare function __sveltets_1_empty(...dummy: any[]): {};
170
- declare function __sveltets_1_componentType(): AConstructorTypeOf<Svelte2TsxComponent<any, any, any>>
172
+ declare function __sveltets_1_componentType(): AConstructorTypeOf<_SvelteComponent<any, any, any>>
171
173
  declare function __sveltets_1_invalidate<T>(getValue: () => T): T
172
174
 
173
175
  declare function __sveltets_1_mapWindowEvent<K extends keyof HTMLBodyElementEventMap>(
@@ -217,17 +219,18 @@ declare function __sveltets_1_each<T extends ArrayLike<unknown>>(
217
219
 
218
220
  declare function __sveltets_1_createSvelte2TsxComponent<Props, Events, Slots>(
219
221
  render: {props: Props, events: Events, slots: Slots }
220
- ): SvelteComponentConstructor<Svelte2TsxComponent<Props, Events, Slots>,Svelte2TsxComponentConstructorParameters<Props>>;
222
+ ): SvelteComponentConstructor<_SvelteComponent<Props, Events, Slots>,Svelte2TsxComponentConstructorParameters<Props>>;
221
223
 
222
224
  declare function __sveltets_1_unwrapArr<T>(arr: ArrayLike<T>): T
223
225
  declare function __sveltets_1_unwrapPromiseLike<T>(promise: PromiseLike<T> | T): T
224
226
 
225
227
  // v2
226
228
  declare function __sveltets_2_createCreateSlot<Slots = Record<string, Record<string, any>>>(): <SlotName extends keyof Slots>(slotName: SlotName, attrs: Slots[SlotName]) => Record<string, any>;
227
- declare function __sveltets_2_createComponentAny(props: Record<string, any>): Svelte2TsxComponent<any, any, any>;
229
+ declare function __sveltets_2_createComponentAny(props: Record<string, any>): _SvelteComponent<any, any, any>;
228
230
 
229
231
  declare function __sveltets_2_any(...dummy: any[]): any;
230
232
  declare function __sveltets_2_empty(...dummy: any[]): {};
233
+ declare function __sveltets_2_union<T1,T2,T3,T4,T5>(t1:T1,t2?:T2,t3?:T3,t4?:T4,t5?:T5): T1 & T2 & T3 & T4 & T5;
231
234
 
232
235
  declare function __sveltets_2_cssProp(prop: Record<string, any>): {};
233
236
 
@@ -263,7 +266,7 @@ declare function __sveltets_2_ensureType<T1, T2>(type1: AConstructorTypeOf<T1>,
263
266
 
264
267
  // The following is necessary because there are two clashing errors that can't be solved at the same time
265
268
  // when using Svelte2TsxComponent, more precisely the event typings in
266
- // __sveltets_2_ensureComponent<T extends new (..) => Svelte2TsxComponent<any,||any||<-this,any>>(type: T): T;
269
+ // __sveltets_2_ensureComponent<T extends new (..) => _SvelteComponent<any,||any||<-this,any>>(type: T): T;
267
270
  // If we type it as "any", we have an error when using sth like {a: CustomEvent<any>}
268
271
  // If we type it as "{}", we have an error when using sth like {[evt: string]: CustomEvent<any>}
269
272
  // If we type it as "unknown", we get all kinds of follow up errors which we want to avoid