diff --git a/packages/language-server/package.json b/packages/language-server/package.json
index 02e6876f1..fef2200dd 100644
--- a/packages/language-server/package.json
+++ b/packages/language-server/package.json
@@ -53,9 +53,9 @@
"fast-glob": "^3.2.7",
"lodash": "^4.17.21",
"prettier": "2.5.1",
- "prettier-plugin-svelte": "~2.6.0",
+ "prettier-plugin-svelte": "~2.7.0",
"source-map": "^0.7.3",
- "svelte": "^3.46.1",
+ "svelte": "^3.47.0",
"svelte-preprocess": "~4.10.1",
"svelte2tsx": "~0.5.0",
"typescript": "*",
diff --git a/packages/language-server/src/plugins/html/dataProvider.ts b/packages/language-server/src/plugins/html/dataProvider.ts
index e515b1e3f..86323ffb2 100644
--- a/packages/language-server/src/plugins/html/dataProvider.ts
+++ b/packages/language-server/src/plugins/html/dataProvider.ts
@@ -85,6 +85,18 @@ const svelteTags: ITagData[] = [
}
]
},
+ {
+ name: 'svelte:element',
+ description:
+ 'Renders a DOM element dynamically, using the string as the this property. When the property changes, the element is destroyed and recreated.\n\nIf this is falsy, no element is rendered.',
+ attributes: [
+ {
+ name: 'this',
+ description:
+ 'DOM element to render.\n\nWhen this property changes, the element is destroyed and recreated.\nIf this is falsy, no element is rendered.'
+ }
+ ]
+ },
{
name: 'svelte:window',
description:
diff --git a/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts b/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts
index ceb6902fe..8ce588264 100644
--- a/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts
+++ b/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts
@@ -471,12 +471,11 @@ describe('SveltePlugin#getDiagnostics', () => {
assert.deepStrictEqual(diagnostics, [
{
- range: { start: { line: 1, character: 15 }, end: { line: 1, character: 27 } },
- message:
- "Component has unused export property 'name'. If it is for external reference only, please consider using `export const name`",
+ range: { start: { line: 1, character: 4 }, end: { line: 1, character: 26 } },
+ message: '$: has no effect in a module script',
severity: 2,
source: 'svelte',
- code: 'unused-export-let'
+ code: 'module-script-reactive-declaration'
}
]);
});
diff --git a/packages/language-server/test/plugins/svelte/testfiles/diagnostics-module.svelte b/packages/language-server/test/plugins/svelte/testfiles/diagnostics-module.svelte
index e85090964..3abb81402 100644
--- a/packages/language-server/test/plugins/svelte/testfiles/diagnostics-module.svelte
+++ b/packages/language-server/test/plugins/svelte/testfiles/diagnostics-module.svelte
@@ -1,3 +1,3 @@
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expected.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expected.json
new file mode 100644
index 000000000..57e3758f8
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expected.json
@@ -0,0 +1,9 @@
+[
+ {
+ "range": { "start": { "line": 10, "character": 0 }, "end": { "line": 10, "character": 0 } },
+ "severity": 1,
+ "source": "js",
+ "message": " must have a 'this' attribute",
+ "code": -1
+ }
+]
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expectedv2.json
new file mode 100644
index 000000000..57e3758f8
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/expectedv2.json
@@ -0,0 +1,9 @@
+[
+ {
+ "range": { "start": { "line": 10, "character": 0 }, "end": { "line": 10, "character": 0 } },
+ "severity": 1,
+ "source": "js",
+ "message": " must have a 'this' attribute",
+ "code": -1
+ }
+]
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/input.svelte
new file mode 100644
index 000000000..ec1324d02
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/svelte-element/input.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+{tag}
+ tag} />
+
+
+
diff --git a/packages/svelte2tsx/package.json b/packages/svelte2tsx/package.json
index 384740f37..b539b8e8d 100644
--- a/packages/svelte2tsx/package.json
+++ b/packages/svelte2tsx/package.json
@@ -34,7 +34,7 @@
"source-map": "^0.6.1",
"source-map-support": "^0.5.16",
"sourcemap-codec": "^1.4.8",
- "svelte": "~3.46.1",
+ "svelte": "~3.47.0",
"tiny-glob": "^0.2.6",
"tslib": "^1.10.0",
"typescript": "^4.6.2"
diff --git a/packages/svelte2tsx/src/htmlxtojsx/index.ts b/packages/svelte2tsx/src/htmlxtojsx/index.ts
index 2947d35cc..f4b4eccb7 100644
--- a/packages/svelte2tsx/src/htmlxtojsx/index.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx/index.ts
@@ -111,6 +111,9 @@ export function convertHtmlxToJsx(
);
break;
case 'Element':
+ if (node.name === 'svelte:element') {
+ handleSvelteTag(htmlx, str, node);
+ }
templateScopeManager.componentOrSlotTemplateOrElementEnter(node);
handleElement(
htmlx,
diff --git a/packages/svelte2tsx/src/htmlxtojsx/nodes/svelte-tag.ts b/packages/svelte2tsx/src/htmlxtojsx/nodes/svelte-tag.ts
index 44a64db07..143e2e183 100644
--- a/packages/svelte2tsx/src/htmlxtojsx/nodes/svelte-tag.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx/nodes/svelte-tag.ts
@@ -3,7 +3,7 @@ import { BaseNode } from '../../interfaces';
/**
* `...` ----> `...`
- * (same for :head, :body, :options, :fragment)
+ * (same for :head, :body, :options, :fragment, :element)
*/
export function handleSvelteTag(htmlx: string, str: MagicString, node: BaseNode): void {
const colon = htmlx.indexOf(':', node.start);
diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Element.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Element.ts
index 6403dbf74..19f432dc2 100644
--- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Element.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Element.ts
@@ -11,7 +11,7 @@ import {
const voidTags = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'.split(',');
/**
- * Handles HTML elements as well as svelte:options, svelte:head, svelte:window, svelte:body
+ * Handles HTML elements as well as svelte:options, svelte:head, svelte:window, svelte:body, svelte:element
*
* Children of this element should call the methods on this class to add themselves to the correct
* position within the transformation.
@@ -94,6 +94,7 @@ export class Element {
case 'svelte:head':
case 'svelte:window':
case 'svelte:body':
+ case 'svelte:element':
case 'svelte:fragment': {
// remove the colon: svelte:xxx -> sveltexxx
const nodeName = `svelte${this.node.name.substring(7)}`;
diff --git a/packages/svelte2tsx/svelte-jsx.d.ts b/packages/svelte2tsx/svelte-jsx.d.ts
index 92655d158..ed36e15e6 100644
--- a/packages/svelte2tsx/svelte-jsx.d.ts
+++ b/packages/svelte2tsx/svelte-jsx.d.ts
@@ -298,6 +298,7 @@ declare namespace svelteHTML {
sveltefragment: { slot?: string; };
svelteoptions: { [name: string]: any };
sveltehead: { [name: string]: any };
+ svelteelement: { 'this': string | undefined | null; } & HTMLProps & SVGProps;
[name: string]: { [name: string]: any };
}
@@ -1453,6 +1454,7 @@ declare namespace svelte.JSX {
sveltefragment: { slot?: string; };
svelteoptions: { [name: string]: any };
sveltehead: { [name: string]: any };
+ svelteelement: { 'this': string | undefined | null; } & HTMLProps & SVGProps;
[name: string]: { [name: string]: any };
}
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx
new file mode 100644
index 000000000..134e60738
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx
@@ -0,0 +1,14 @@
+///
+<>>;function render() {
+
+ let tag = 'div';
+;
+() => (<>
+
+
+{tag}
+ tag} />>);
+return { props: {}, slots: {}, getters: {}, events: {} }}
+
+export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
+}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts
new file mode 100644
index 000000000..312059a87
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts
@@ -0,0 +1,14 @@
+///
+;function render() {
+
+ let tag = 'div';
+;
+async () => {
+
+ { svelteHTML.createElement("svelteelement", { });}
+ { svelteHTML.createElement("svelteelement", { });tag; }
+ { svelteHTML.createElement("svelteelement", { "onclick":() => tag,});}};
+return { props: {}, slots: {}, getters: {}, events: {} }}
+
+export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
+}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte
new file mode 100644
index 000000000..e0c57b76b
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte
@@ -0,0 +1,7 @@
+
+
+
+{tag}
+ tag} />
diff --git a/yarn.lock b/yarn.lock
index 5d3752b76..ba1ba014d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2093,10 +2093,10 @@ prelude-ls@^1.2.1:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-prettier-plugin-svelte@~2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.6.0.tgz#0e845b560b55cd1d951d6c50431b4949f8591746"
- integrity sha512-NPSRf6Y5rufRlBleok/pqg4+1FyGsL0zYhkYP6hnueeL1J/uCm3OfOZPsLX4zqD9VAdcXfyEL2PYqGv8ZoOSfA==
+prettier-plugin-svelte@~2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.7.0.tgz#ecfa4fe824238a4466a3497df1a96d15cf43cabb"
+ integrity sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==
prettier@2.3.2:
version "2.3.2"
@@ -2533,10 +2533,10 @@ svelte-preprocess@~4.10.1:
sorcery "^0.10.0"
strip-indent "^3.0.0"
-svelte@^3.46.1, svelte@~3.46.1:
- version "3.46.1"
- resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.46.1.tgz#8ea23595824a39d47d04c16c217000fbc4c52c49"
- integrity sha512-Ue8ivq+G45AfZZL4Z93xNFiC352wPkyGiY9QSuWjxXh6jiaZMrpthinjc1rz0OSTceuST7Pxr1HDBj2KioliZg==
+svelte@^3.47.0, svelte@~3.47.0:
+ version "3.47.0"
+ resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.47.0.tgz#ba46fe4aea99fc650d6939c215cd4694f5325a19"
+ integrity sha512-4JaJp3HEoTCGARRWZQIZDUanhYv0iyoHikklVHVLH9xFE9db22g4TDv7CPeNA8HD1JgjXI1vlhR1JZvvhaTu2Q==
table@^5.2.3:
version "5.4.6"