Skip to content

Commit d15939c

Browse files
authored
Toggle JSX namespace based on svelte vs svelte-native (#351)
* Toggle JSX namespace based on svelte vs svelte-native * add svelte-native-jsx.d.ts to the package * lint fixes
1 parent 7f89480 commit d15939c

File tree

9 files changed

+76
-8
lines changed

9 files changed

+76
-8
lines changed

packages/language-server/src/plugins/typescript/features/RenameProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class RenameProviderImpl implements RenameProvider {
127127
if (
128128
!renameInfo.canRename ||
129129
renameInfo.kind === ts.ScriptElementKind.jsxAttribute ||
130-
renameInfo.fullDisplayName?.startsWith('JSX.')
130+
renameInfo.fullDisplayName?.includes("JSX.IntrinsicElements")
131131
) {
132132
return null;
133133
}

packages/language-server/src/plugins/typescript/service.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export function createLanguageService(
6666
const svelteModuleLoader = createSvelteModuleLoader(getSnapshot, compilerOptions);
6767

6868
const svelteTsPath = dirname(require.resolve('svelte2tsx'));
69-
const svelteTsxFiles = ['./svelte-shims.d.ts', './svelte-jsx.d.ts'].map((f) =>
69+
const svelteTsxFiles = ['./svelte-shims.d.ts', './svelte-jsx.d.ts', './svelte-native-jsx.d.ts'].map((f) =>
7070
ts.sys.resolvePath(resolve(svelteTsPath, f)),
7171
);
7272

@@ -162,8 +162,7 @@ export function createLanguageService(
162162
declaration: false,
163163
skipLibCheck: true,
164164
// these are needed to handle the results of svelte2tsx preprocessing:
165-
jsx: ts.JsxEmit.Preserve,
166-
jsxFactory: 'h',
165+
jsx: ts.JsxEmit.Preserve
167166
};
168167

169168
// always let ts parse config to get default compilerOption
@@ -203,6 +202,24 @@ export function createLanguageService(
203202
...forcedCompilerOptions,
204203
};
205204

205+
// detect which JSX namespace to use (svelte | svelteNative) if not specified or not compatible
206+
if (!compilerOptions.jsxFactory || !compilerOptions.jsxFactory.startsWith("svelte")) {
207+
//default to regular svelte, this causes the usage of the "svelte.JSX" namespace
208+
compilerOptions.jsxFactory = "svelte.createElement";
209+
210+
//override if we detect svelte-native
211+
if (workspacePath) {
212+
try {
213+
const svelteNativePkgInfo = getPackageInfo('svelte-native', workspacePath);
214+
if (svelteNativePkgInfo.path) {
215+
compilerOptions.jsxFactory = "svelteNative.createElement";
216+
}
217+
} catch (e) {
218+
//we stay regular svelte
219+
}
220+
}
221+
}
222+
206223
return { compilerOptions, files };
207224
}
208225

packages/language-server/test/plugins/typescript/features/CompletionProvider.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from 'vscode-languageserver';
1515
import { CompletionsProviderImpl, CompletionEntryWithIdentifer } from '../../../../src/plugins/typescript/features/CompletionProvider';
1616
import { LSAndTSDocResolver } from '../../../../src/plugins/typescript/LSAndTSDocResolver';
17+
import { sortBy } from 'lodash';
1718

1819
const testDir = join(__dirname, '..');
1920
const testFilesDir = join(testDir, 'testfiles');
@@ -182,8 +183,11 @@ describe('CompletionProviderImpl', () => {
182183
];
183184
const ignores = ['tsconfig.json', sourceFile];
184185

185-
const testfiles = readdirSync(testFilesDir)
186-
.filter((f) => supportedExtensions.includes(extname(f)) && !ignores.includes(f));
186+
const testfiles = readdirSync(testFilesDir, { withFileTypes: true })
187+
.filter((f) => f.isDirectory()
188+
|| (supportedExtensions.includes(extname(f.name))
189+
&& !ignores.includes(f.name)))
190+
.map(f => f.name);
187191

188192
const completions = await completionProvider.getCompletions(
189193
document,
@@ -194,7 +198,10 @@ describe('CompletionProviderImpl', () => {
194198
},
195199
);
196200

197-
assert.deepStrictEqual(completions?.items.map(item => item.label), testfiles);
201+
assert.deepStrictEqual(
202+
sortBy(completions?.items.map(item => item.label), x => x),
203+
sortBy(testfiles, x => x)
204+
);
198205
});
199206

200207
it('resolve auto import completion (is first import in file)', async () => {

packages/language-server/test/plugins/typescript/features/DiagnosticsProvider.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,10 @@ describe('TypescriptPlugin', () => {
103103

104104
assert.deepStrictEqual(diagnostics, []);
105105
});
106+
107+
it('handles svelte native syntax', async () => {
108+
const { plugin, document } = setup('svelte-native/svelte-native.svelte');
109+
const diagnostics = await plugin.getDiagnostics(document);
110+
assert.deepStrictEqual(diagnostics, []);
111+
});
106112
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<page>
2+
<label class="info" horizontalAlignment="center" verticalAlignment="center" textWrap="true">
3+
<formattedString>
4+
<span class="fas" text="&#xf135;" />
5+
<span text=" {message}" />
6+
</formattedString>
7+
</label>
8+
</page>
9+
10+
<script lang="typescript">
11+
let message: string = "Blank Svelte Native App"
12+
</script>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"jsxFactory": "svelteNative"
4+
}
5+
}

packages/svelte2tsx/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"README.md",
5757
"LICENSE",
5858
"svelte-jsx.d.ts",
59+
"svelte-native-jsx.d.ts",
5960
"svelte-shims.d.ts"
6061
],
6162
"dependencies": {

packages/svelte2tsx/svelte-jsx.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010

1111

12-
declare namespace JSX {
12+
declare namespace svelte.JSX {
1313

1414
/* svelte specific */
1515
interface ElementClass {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
declare namespace svelteNative.JSX {
2+
3+
/* svelte specific */
4+
interface ElementClass {
5+
$$prop_def: any;
6+
}
7+
8+
interface ElementAttributesProperty {
9+
$$prop_def: any; // specify the property name to use
10+
}
11+
12+
// Add empty IntrinsicAttributes to prevent fallback to the one in the JSX namespace
13+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
14+
interface IntrinsicAttributes {
15+
}
16+
17+
interface IntrinsicElements {
18+
[name: string]: { [name: string]: any };
19+
}
20+
}

0 commit comments

Comments
 (0)