Repository: sveltejs/language-tools
Pull request #1359 (2022-01-31 09:56:04)

(fix) allow data attributes
Any attribute prefixed with data- is valid
#1352


Patch:
diff --git a/packages/svelte-check/README.md b/packages/svelte-check/README.md
index f9e1b266..6ca0d249 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,7 +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 |
+| `--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/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
index 7c4cd4e2..9e3d7950 100644
--- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
@@ -69,8 +69,18 @@ export function handleAttribute(
 
     const addAttribute =
         element instanceof Element
-            ? (name: TransformationArray, value?: TransformationArray) =>
-                  element.addAttribute(name, value)
+            ? (name: TransformationArray, value?: TransformationArray) => {
+                  if (attr.name.startsWith('data-')) {
+                      // any attribute prefixed with data- is valid, but we can't
+                      // type that statically, so we need this workaround
+                      name.unshift('...__sveltets_2_empty({');
+                      if (!value) {
+                          value = ['__sveltets_2_any()'];
+                      }
+                      value.push('})');
+                  }
+                  element.addAttribute(name, value);
+              }
             : (name: TransformationArray, value?: TransformationArray) => {
                   if (attr.name.startsWith('--') && attr.value !== true) {
                       // CSS custom properties are not part of the props
diff --git a/packages/svelte2tsx/svelte-shims.d.ts b/packages/svelte2tsx/svelte-shims.d.ts
index 58bd6aeb..e7320188 100644
--- a/packages/svelte2tsx/svelte-shims.d.ts
+++ b/packages/svelte2tsx/svelte-shims.d.ts
@@ -222,6 +222,7 @@ declare function __sveltets_2_createCreateSlot<Slots = Record<string, Record<str
 declare function __sveltets_2_createComponentAny(props: Record<string, any>): Svelte2TsxComponent<any, any, any>;
 
 declare function __sveltets_2_any(...dummy: any[]): any;
+declare function __sveltets_2_empty(...dummy: any[]): {};
 
 declare function __sveltets_2_cssProp(prop: Record<string, any>): {};
 


Test patch:
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expected.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expected.json
new file mode 100644
index 00000000..d9e98319
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expected.json
@@ -0,0 +1,10 @@
+[
+    {
+        "range": { "start": { "line": 10, "character": 4 }, "end": { "line": 10, "character": 4 } },
+        "severity": 1,
+        "source": "ts",
+        "message": "Type '{ bar: string; }' is not assignable to type 'HTMLProps<HTMLDivElement>'.\n  Property 'bar' does not exist on type 'HTMLProps<HTMLDivElement>'.",
+        "code": 2322,
+        "tags": []
+    }
+]
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expectedv2.json
new file mode 100644
index 00000000..c39d0a9e
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/expectedv2.json
@@ -0,0 +1,18 @@
+[
+    {
+        "range": { "start": { "line": 9, "character": 5 }, "end": { "line": 9, "character": 19 } },
+        "severity": 1,
+        "source": "ts",
+        "message": "Argument of type '{ \"this-is\": string; }' is not assignable to parameter of type 'HTMLProps<HTMLDivElement>'.\n  Object literal may only specify known properties, and '\"this-is\"' does not exist in type 'HTMLProps<HTMLDivElement>'.",
+        "code": 2345,
+        "tags": []
+    },
+    {
+        "range": { "start": { "line": 10, "character": 6 }, "end": { "line": 10, "character": 9 } },
+        "severity": 1,
+        "source": "ts",
+        "message": "Argument of type '{ bar: string; }' is not assignable to parameter of type 'HTMLProps<HTMLDivElement>'.\n  Object literal may only specify known properties, and 'bar' does not exist in type 'HTMLProps<HTMLDivElement>'.",
+        "code": 2345,
+        "tags": []
+    }
+]
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/input.svelte
new file mode 100644
index 00000000..a901da58
--- /dev/null
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/element-attributes.only/input.svelte
@@ -0,0 +1,11 @@
+<script lang="ts">
+    let bar = "bar";
+</script>
+
+<!-- valid -->
+<div data-foo data-bar={bar} />
+<div class={bar} />
+
+<!-- invalid -->
+<div this-is="wrong" />
+<div {bar} />
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expected.jsx b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expected.jsx
new file mode 100644
index 00000000..3eec850d
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expected.jsx
@@ -0,0 +1,1 @@
+<><div data-foo={true} data-bare data-bar="to" /></>
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expectedv2.js b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expectedv2.js
new file mode 100644
index 00000000..4586f377
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/expectedv2.js
@@ -0,0 +1,1 @@
+ { svelteHTML.createElement("div", {     ...__sveltets_2_empty({"data-foo":true}),...__sveltets_2_empty({"data-bare":true}),...__sveltets_2_empty({"data-bar":"to"}),});}
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/input.svelte b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/input.svelte
new file mode 100644
index 00000000..618a3c4a
--- /dev/null
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/attribute-data/input.svelte
@@ -0,0 +1,1 @@
+<div data-foo={true} data-bare data-bar="to" />