Repository: sveltejs/language-tools
Pull request #1351 (2022-01-29 22:50:37)

[fix] useNewTransformation cleanup
- fix title transformation
- add useNewTransformation option to svelte-check
- update docs


Patch:
diff --git a/docs/internal/overview.md b/docs/internal/overview.md
index 7013de53..33e378f8 100644
--- a/docs/internal/overview.md
+++ b/docs/internal/overview.md
@@ -56,6 +56,8 @@ The code generated by `svelte2tsx` is not runnable in any way and does not actua
 
 The code also returns source mappings so we know which position in the original code corresponds to which generated position.
 
+There's a new transformation now which does the same but transforms the code to TS or JS, which makes it possible to write transformations in an easier way, preserving control flow for if, each etc more easily. It's hidden behind a flag for now but will be the new default soon.
+
 ### Integration of svelte2tsx into the language-server
 
 This example shows how our `language-server` uses `svelte2tsx`:
diff --git a/packages/language-server/README.md b/packages/language-server/README.md
index 6e98ca72..e5e35058 100644
--- a/packages/language-server/README.md
+++ b/packages/language-server/README.md
@@ -229,6 +229,10 @@ Enable rename tags for the opening/closing tag pairs in HTML. _Default_: `true`
 
 Enable the Svelte plugin. _Default_: `true`
 
+##### `svelte.plugin.svelte.useNewTransformation`
+
+Svelte files need to be transformed to something that TypeScript understands for intellisense. Version 2.0 of this transformation can be enabled with this setting. It will be the default, soon.
+
 ##### `svelte.plugin.svelte.diagnostics.enable`
 
 Enable diagnostic messages for Svelte. _Default_: `true`
diff --git a/packages/language-server/src/svelte-check.ts b/packages/language-server/src/svelte-check.ts
index 0671ed72..e1677c81 100644
--- a/packages/language-server/src/svelte-check.ts
+++ b/packages/language-server/src/svelte-check.ts
@@ -23,6 +23,10 @@ export interface SvelteCheckOptions {
      * Path has to be absolute
      */
     tsconfig?: string;
+    /**
+     * Whether or not to use the new transformation of svelte2tsx
+     */
+    useNewTransformation?: boolean;
 }
 
 /**
@@ -49,7 +53,8 @@ export class SvelteCheck {
 
         this.configManager.update({
             svelte: {
-                compilerWarnings: options.compilerWarnings
+                compilerWarnings: options.compilerWarnings,
+                useNewTransformation: options.useNewTransformation ?? false
             }
         });
         // No HTMLPlugin, it does not provide diagnostics
diff --git a/packages/svelte-check/README.md b/packages/svelte-check/README.md
index 7fb51853..f9e1b266 100644
--- a/packages/svelte-check/README.md
+++ b/packages/svelte-check/README.md
@@ -51,7 +51,7 @@ Usage:
 ### Args:
 
 | Flag                                                            | Description                                                                                                                                                                                                                                                                                                      |
-| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `--workspace <path>`                                            | Path to your workspace. All subdirectories except node_modules and those listed in `--ignore` are checked                                                                                                                                                                                                        |
 | `--output <human\|human-verbose\|machine>`                      |
 | `--watch`                                                       | Will not exit after one pass but keep watching files for changes and rerun diagnostics                                                                                                                                                                                                                           |
@@ -62,6 +62,7 @@ Usage:
 | `--compiler-warnings <code1:error\|ignore,code2:error\|ignore>` | A list of Svelte compiler warning codes. Each entry defines whether that warning should be ignored or treated as an error. Warnings are comma-separated, between warning code and error level is a colon; all inside quotes. Example: `--compiler-warnings "css-unused-selector:ignore,unused-export-let:error"` |
 | `--diagnostic-sources <js,svelte,css>`                          | A list of diagnostic sources which should run diagnostics on your code. Possible values are `js` (includes TS), `svelte`, `css`. Comma-separated, inside quotes. By default all are active. Example: `--diagnostic-sources "js,svelte"`                                                                          |
 | `--threshold <error\|warning>`                                  | Filters the diagnostics to display. `error` will output only errors while `warning` will output warnings and errors.                                                                                                                                                                                             |
+| `--use-new-transformation <true                                 | false>`                                                                                                                                                                                                                                                                                                          | Svelte files need to be transformed to something that TypeScript understands for intellisense. Version 2.0 of this transformation can be enabled with this setting. It will be the default, soon. Please try it out and provide feedback |
 
 ### FAQ
 
diff --git a/packages/svelte-check/src/index.ts b/packages/svelte-check/src/index.ts
index d9ab4fe1..c7cb8e51 100644
--- a/packages/svelte-check/src/index.ts
+++ b/packages/svelte-check/src/index.ts
@@ -177,7 +177,8 @@ parseOptions(async (opts) => {
         const svelteCheck = new SvelteCheck(opts.workspaceUri.fsPath, {
             compilerWarnings: opts.compilerWarnings,
             diagnosticSources: opts.diagnosticSources,
-            tsconfig: opts.tsconfig
+            tsconfig: opts.tsconfig,
+            useNewTransformation: opts.useNewTransformation
         });
 
         if (opts.watch) {
diff --git a/packages/svelte-check/src/options.ts b/packages/svelte-check/src/options.ts
index 23c09df3..b4e08261 100644
--- a/packages/svelte-check/src/options.ts
+++ b/packages/svelte-check/src/options.ts
@@ -13,6 +13,7 @@ export interface SvelteCheckCliOptions {
     compilerWarnings: Record<string, 'error' | 'ignore'>;
     diagnosticSources: DiagnosticSource[];
     threshold: Threshold;
+    useNewTransformation: boolean;
 }
 
 // eslint-disable max-len
@@ -60,6 +61,11 @@ export function parseOptions(cb: (opts: SvelteCheckCliOptions) => any) {
             'Filters the diagnostics to display. `error` will output only errors while `warning` will output warnings and errors.',
             'hint'
         )
+        .option(
+            '--use-new-transformation',
+            'Svelte files need to be transformed to something that TypeScript understands for intellisense. Version 2.0 of this transformation can be enabled with this setting. It will be the default, soon.',
+            false
+        )
         .action((opts) => {
             const workspaceUri = getWorkspaceUri(opts);
             cb({
@@ -72,7 +78,9 @@ export function parseOptions(cb: (opts: SvelteCheckCliOptions) => any) {
                 failOnHints: !!opts['fail-on-hints'],
                 compilerWarnings: getCompilerWarnings(opts),
                 diagnosticSources: getDiagnosticSources(opts),
-                threshold: getThreshold(opts)
+                threshold: getThreshold(opts),
+                useNewTransformation:
+                    opts['use-new-transformation'] && opts['use-new-transformation'] !== 'false'
             });
         });
 
diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts
index 9d82686d..e543d77f 100644
--- a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts
@@ -95,6 +95,7 @@ export function convertHtmlxToJsx(
                     case 'Options':
                     case 'Window':
                     case 'Head':
+                    case 'Title':
                     case 'Body':
                     case 'Slot':
                     case 'SlotTemplate':
@@ -179,6 +180,7 @@ export function convertHtmlxToJsx(
                     case 'Options':
                     case 'Window':
                     case 'Head':
+                    case 'Title':
                     case 'Body':
                     case 'Slot':
                     case 'SlotTemplate':
diff --git a/packages/typescript-plugin/internal.md b/packages/typescript-plugin/internal.md
index 1df2d17c..06e8c61a 100644
--- a/packages/typescript-plugin/internal.md
+++ b/packages/typescript-plugin/internal.md
@@ -8,9 +8,9 @@ However, for getting Svelte support inside TS/JS files, we need to do more than
 -   present Svelte files to TypeScript in a way TypeScript understands
 -   enhance the language service (the part that's shown in the how-to)
 
-To make TypeScript aware of Svelte files, we need to patch its module resolution algorithm. `.svelte` is not a valid file ending for TypeScript, so it searches for files like `.svelte.ts`. This logic is decorated in `src/module-loader` to also resolve Svelte files. They are resolved to file-type TSX/JSX, which leads us to the next obstacle: to present Svelte files to TypeScript in a way it understands.
+To make TypeScript aware of Svelte files, we need to patch its module resolution algorithm. `.svelte` is not a valid file ending for TypeScript, so it searches for files like `.svelte.ts`. This logic is decorated in `src/module-loader` to also resolve Svelte files. They are resolved to file-type TS/JS, which leads us to the next obstacle: to present Svelte files to TypeScript in a way it understands.
 
-We achieve that by utilizing `svelte2tsx`, which transforms Svelte code into TSX/JSX code. We do that transformation by patching `readFile` of TypeScript's project service in `src/svelte-snapshots`: If a Svelte file is read, transform the code before returning it. During that we also patch the ScriptInfo that TypeScript uses to interact with files. We patch the methods that transform positions to offsets and vice versa and either do transforms on the generated or original code, depending on the situation.
+We achieve that by utilizing `svelte2tsx`, which transforms Svelte code into TS/JS code. We do that transformation by patching `readFile` of TypeScript's project service in `src/svelte-snapshots`: If a Svelte file is read, transform the code before returning it. During that we also patch the ScriptInfo that TypeScript uses to interact with files. We patch the methods that transform positions to offsets and vice versa and either do transforms on the generated or original code, depending on the situation.
 
 The last step is to enhance the language service. For that, we patch the desired methods and apply custom logic. Most of that is transforming the generated code positions to the original code positions.
 


Test patch:
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expected.jsx b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expected.jsx
new file mode 100644
index 00000000..f4e378e3
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expected.jsx
@@ -0,0 +1,3 @@
+<><sveltehead>
+	<title>Home</title>
+</sveltehead></>
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expectedv2.js b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expectedv2.js
new file mode 100644
index 00000000..99b023e7
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/expectedv2.js
@@ -0,0 +1,3 @@
+ { svelteHTML.createElement("sveltehead", {});
+	 { svelteHTML.createElement("title", {});  }
+ }
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/input.svelte b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/input.svelte
new file mode 100644
index 00000000..8a28dc7c
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltehead-title/input.svelte
@@ -0,0 +1,3 @@
+<svelte:head>
+	<title>Home</title>
+</svelte:head>