diff --git a/.changeset/soft-bears-hear.md b/.changeset/soft-bears-hear.md new file mode 100644 index 000000000..d54cb5bb7 --- /dev/null +++ b/.changeset/soft-bears-hear.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': major +--- + +feat!: Updated the `html-self-closing` rule to follow Svelte5 diff --git a/docs/rules/html-self-closing.md b/docs/rules/html-self-closing.md index 18c131b68..0cb623119 100644 --- a/docs/rules/html-self-closing.md +++ b/docs/rules/html-self-closing.md @@ -14,10 +14,10 @@ since: 'v2.5.0' ## :book: Rule Details -You can choose either two styles for elements without content +You can choose either two styles for elements without content. -- always: `
` -- never: `
` +- always: `` +- never: `` @@ -28,18 +28,21 @@ You can choose either two styles for elements without content -

Hello

-
+
+ + + -
-

-
- +
+
+ + + ``` @@ -52,7 +55,7 @@ presets: { "svelte/html-self-closing": [ "error", - "all" // or "html" or "none" + "default" // or "all" or "html" or "none" ] } ``` @@ -65,8 +68,9 @@ config object: "error", { "void": "always", // or "never" or "ignore" - "normal": "always", // or "never" or "ignore" - "foreign": "always", // or "never" or "ignore" + "normal": "never", // or "always" or "ignore" + "svg": "always", // or "never" or "ignore" + "never": "never", // or "always" or "ignore" "component": "always", // or "never" or "ignore" "svelte": "always" // or "never" or "ignore" } @@ -76,23 +80,33 @@ config object: presets: -- `all` - all elements should be self closing (unless they have children) -- `html` - html-compliant - only void elements and svelte special elements should be self closing -- `none` - no elements should be self closing +- `default` - MathML and non-void HTML elements should have a closing tag; otherwise, they should be self-closing. +- `all` - all elements should be self-closing (unless they have children) +- `html` - html-compliant - only void elements and svelte special elements should be self-closing +- `none` - no elements should be self-closing + +::: warning Note +We recommend selecting `default` as the preset. Choosing any other option may result in settings that are inconsistent with the compiler when using Svelte5. +::: config object: - `void` (`"always"` in default preset)... Style of HTML void elements -- `foreign` (`"always"` in default preset)... Style of foreign elements (SVG and MathML) +- `normal` (`"never"` in default preset)... Style of other elements +- `svg` (`"always"` in default preset)... Style of SVG +- `math` (`never` in default preset)... Style of MathML - `component` (`"always"` in default preset)... Style of svelte components - `svelte` (`"always"` in default preset)... Style of svelte special elements (``, ``) -- `normal` (`"always"` in default preset)... Style of other elements -Every config oject option can be set to +::: warning +`foreign` is removed in `eslint-plugin-svelte` v3. +::: + +Every config object option can be set to -- "always" (`
`) -- "never" (`
`) -- "ignore" (either `
` or `
`) +- "always" (``) +- "never" (``) +- "ignore" (either `` or ``) ## :rocket: Version diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 438ec0ff7..3bc21b67f 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -419,7 +419,8 @@ type SvelteHtmlQuotes = []|[{ type SvelteHtmlSelfClosing = []|[({ void?: ("never" | "always" | "ignore") normal?: ("never" | "always" | "ignore") - foreign?: ("never" | "always" | "ignore") + svg?: ("never" | "always" | "ignore") + math?: ("never" | "always" | "ignore") component?: ("never" | "always" | "ignore") svelte?: ("never" | "always" | "ignore") } | ("all" | "html" | "none"))] diff --git a/packages/eslint-plugin-svelte/src/rules/html-self-closing.ts b/packages/eslint-plugin-svelte/src/rules/html-self-closing.ts index 7e3d3ff98..13c8e324f 100644 --- a/packages/eslint-plugin-svelte/src/rules/html-self-closing.ts +++ b/packages/eslint-plugin-svelte/src/rules/html-self-closing.ts @@ -1,17 +1,23 @@ import type { AST } from 'svelte-eslint-parser'; import { createRule } from '../utils/index.js'; -import { getNodeName, isVoidHtmlElement, isForeignElement } from '../utils/ast-utils.js'; +import { + getNodeName, + isVoidHtmlElement, + isSvgElement, + isMathMLElement +} from '../utils/ast-utils.js'; import { getSourceCode } from '../utils/compat.js'; const TYPE_MESSAGES = { normal: 'HTML elements', void: 'HTML void elements', - foreign: 'foreign (SVG or MathML) elements', + svg: 'SVG elements', + math: 'MathML elements', component: 'Svelte custom components', svelte: 'Svelte special elements' }; -type ElementTypes = 'normal' | 'void' | 'foreign' | 'component' | 'svelte'; +type ElementTypes = 'normal' | 'void' | 'svg' | 'math' | 'component' | 'svelte'; export default createRule('html-self-closing', { meta: { @@ -38,7 +44,10 @@ export default createRule('html-self-closing', { normal: { enum: ['never', 'always', 'ignore'] }, - foreign: { + svg: { + enum: ['never', 'always', 'ignore'] + }, + math: { enum: ['never', 'always', 'ignore'] }, component: { @@ -58,34 +67,49 @@ export default createRule('html-self-closing', { ] }, create(context) { + // default let options = { void: 'always', - normal: 'always', - foreign: 'always', + normal: 'never', + svg: 'always', + math: 'never', component: 'always', svelte: 'always' }; const option = context.options?.[0]; switch (option) { - case 'none': + case 'all': options = { - void: 'never', - normal: 'never', - foreign: 'never', - component: 'never', - svelte: 'never' + void: 'always', + normal: 'always', + svg: 'always', + math: 'always', + component: 'always', + svelte: 'always' }; break; case 'html': options = { void: 'always', normal: 'never', - foreign: 'always', + svg: 'always', + math: 'never', component: 'never', svelte: 'always' }; break; + case 'none': + options = { + void: 'never', + normal: 'never', + svg: 'never', + math: 'never', + component: 'never', + svelte: 'never' + }; + break; + default: if (typeof option !== 'object' || option === null) break; @@ -108,7 +132,8 @@ export default createRule('html-self-closing', { if (node.kind === 'component') return 'component'; if (node.kind === 'special') return 'svelte'; if (isVoidHtmlElement(node)) return 'void'; - if (isForeignElement(node)) return 'foreign'; + if (isSvgElement(node)) return 'svg'; + if (isMathMLElement(node)) return 'math'; return 'normal'; } diff --git a/packages/eslint-plugin-svelte/src/utils/ast-utils.ts b/packages/eslint-plugin-svelte/src/utils/ast-utils.ts index d12e56e88..e844ab842 100644 --- a/packages/eslint-plugin-svelte/src/utils/ast-utils.ts +++ b/packages/eslint-plugin-svelte/src/utils/ast-utils.ts @@ -567,6 +567,14 @@ export function isForeignElement(node: SvAST.SvelteElement): boolean { return svgElements.includes(getNodeName(node)) || mathmlElements.includes(getNodeName(node)); } +export function isSvgElement(node: SvAST.SvelteElement): boolean { + return svgElements.includes(getNodeName(node)); +} + +export function isMathMLElement(node: SvAST.SvelteElement): boolean { + return mathmlElements.includes(getNodeName(node)); +} + /** Checks whether the given identifier node is used as an expression. */ export function isExpressionIdentifier(node: TSESTree.Identifier): boolean { const parent = node.parent; diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-errors.yaml deleted file mode 100644 index a2e0ece09..000000000 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-errors.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- message: Disallow self-closing on foreign (SVG or MathML) elements. - line: 2 - column: 12 - suggestions: null -- message: Disallow self-closing on foreign (SVG or MathML) elements. - line: 3 - column: 13 - suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/_config.json similarity index 56% rename from packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/_config.json rename to packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/_config.json index 6081aab9f..f40ed66a5 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/_config.json +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/_config.json @@ -1,7 +1,7 @@ { "options": [ { - "foreign": "never" + "math": "never" } ] } diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-errors.yaml new file mode 100644 index 000000000..382d8779d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-errors.yaml @@ -0,0 +1,4 @@ +- message: Disallow self-closing on MathML elements. + line: 3 + column: 13 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-input.svelte similarity index 100% rename from packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-input.svelte rename to packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-input.svelte diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-output.svelte similarity index 67% rename from packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-output.svelte rename to packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-output.svelte index 76223b771..3e19b1ce6 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/foreign-never/svelte-never-output.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/math-never/svelte-never-output.svelte @@ -1,3 +1,3 @@ - + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/_config.json new file mode 100644 index 000000000..211f2f072 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/_config.json @@ -0,0 +1,7 @@ +{ + "options": [ + { + "normal": "always" + } + ] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-errors.yaml new file mode 100644 index 000000000..d25b212b4 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-errors.yaml @@ -0,0 +1,4 @@ +- message: Require self-closing on HTML elements. + line: 3 + column: 7 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-input.svelte new file mode 100644 index 000000000..d594af233 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-input.svelte @@ -0,0 +1,4 @@ + +
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-output.svelte new file mode 100644 index 000000000..a1b0b4598 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/normal-always/component-never-output.svelte @@ -0,0 +1,4 @@ + +
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml index ed068bc5f..7620e93bb 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml @@ -10,11 +10,11 @@ line: 5 column: 18 suggestions: null -- message: Require self-closing on foreign (SVG or MathML) elements. +- message: Require self-closing on SVG elements. line: 6 column: 13 suggestions: null -- message: Require self-closing on foreign (SVG or MathML) elements. +- message: Disallow self-closing on MathML elements. line: 7 column: 14 suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-input.svelte index e9b5f1794..a71eee651 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-input.svelte @@ -4,7 +4,7 @@ - +
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-output.svelte index d11d92be5..7091289d3 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-output.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-output.svelte @@ -4,7 +4,7 @@ - +
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml index f12f4c329..99c396801 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml @@ -10,11 +10,11 @@ line: 5 column: 8 suggestions: null -- message: Disallow self-closing on foreign (SVG or MathML) elements. +- message: Disallow self-closing on SVG elements. line: 6 column: 14 suggestions: null -- message: Disallow self-closing on foreign (SVG or MathML) elements. +- message: Disallow self-closing on MathML elements. line: 7 column: 15 suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/_config.json new file mode 100644 index 000000000..271eb820b --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/_config.json @@ -0,0 +1,7 @@ +{ + "options": [ + { + "svg": "never" + } + ] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-errors.yaml new file mode 100644 index 000000000..1ed481969 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-errors.yaml @@ -0,0 +1,4 @@ +- message: Disallow self-closing on SVG elements. + line: 2 + column: 12 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-input.svelte new file mode 100644 index 000000000..ae9136472 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-input.svelte @@ -0,0 +1,3 @@ + + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-output.svelte new file mode 100644 index 000000000..19cfc1982 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/svg-never/svelte-never-output.svelte @@ -0,0 +1,3 @@ + + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-errors.yaml index 3b98d6dae..81f26b618 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-errors.yaml @@ -1,4 +1,4 @@ -- message: Require self-closing on HTML elements. +- message: Disallow self-closing on HTML elements. line: 3 column: 7 suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-input.svelte index b8d7b8051..a9529442c 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-input.svelte @@ -1,6 +1,6 @@
-
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-output.svelte index d8a1286c5..ca2cc6754 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-output.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/invalid/test01-output.svelte @@ -1,6 +1,6 @@
-
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/valid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/valid/test01-input.svelte index 082bc477c..ca8a085e3 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/valid/test01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-self-closing/valid/test01-input.svelte @@ -1,9 +1,9 @@
-
+
hello
- + {#if true} {/if}