diff --git a/README.md b/README.md
index 610a270d6..cef48dc14 100644
--- a/README.md
+++ b/README.md
@@ -440,6 +440,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
|:--------|:------------|:---|
| [svelte/derived-has-same-inputs-outputs](https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/) | derived store should use same variable names between values and callback | |
| [svelte/first-attribute-linebreak](https://sveltejs.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak/) | enforce the location of first attribute | :wrench: |
+| [svelte/html-closing-bracket-new-line](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-new-line/) | Require or disallow a line break before tag's closing brackets | :wrench: |
| [svelte/html-closing-bracket-spacing](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-spacing/) | require or disallow a space before tag's closing brackets | :wrench: |
| [svelte/html-quotes](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-quotes/) | enforce quotes style of HTML attributes | :wrench: |
| [svelte/html-self-closing](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-self-closing/) | enforce self-closing style | :wrench: |
diff --git a/docs/rules.md b/docs/rules.md
index 7f115da5c..57d224ff6 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -77,6 +77,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
| :------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :------- |
| [svelte/derived-has-same-inputs-outputs](./rules/derived-has-same-inputs-outputs.md) | derived store should use same variable names between values and callback | |
| [svelte/first-attribute-linebreak](./rules/first-attribute-linebreak.md) | enforce the location of first attribute | :wrench: |
+| [svelte/html-closing-bracket-new-line](./rules/html-closing-bracket-new-line.md) | Require or disallow a line break before tag's closing brackets | :wrench: |
| [svelte/html-closing-bracket-spacing](./rules/html-closing-bracket-spacing.md) | require or disallow a space before tag's closing brackets | :wrench: |
| [svelte/html-quotes](./rules/html-quotes.md) | enforce quotes style of HTML attributes | :wrench: |
| [svelte/html-self-closing](./rules/html-self-closing.md) | enforce self-closing style | :wrench: |
diff --git a/docs/rules/html-closing-bracket-new-line.md b/docs/rules/html-closing-bracket-new-line.md
new file mode 100644
index 000000000..39ed84ed4
--- /dev/null
+++ b/docs/rules/html-closing-bracket-new-line.md
@@ -0,0 +1,89 @@
+---
+pageClass: 'rule-details'
+sidebarDepth: 0
+title: 'svelte/html-closing-bracket-new-line'
+description: "Require or disallow a line break before tag's closing brackets"
+---
+
+# svelte/html-closing-bracket-new-line
+
+> Require or disallow a line break before tag's closing brackets
+
+- :exclamation: **_This rule has not been released yet._**
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+## :book: Rule Details
+
+This rule enforces a line break (or no line break) before tag's closing brackets, which can also be configured to be enforced on self-closing tags.
+
+
+
+
+
+
+```svelte
+
+
+
+
+
+ Children
+
+
+
+
+
+
+
+
+
+ Children
+
+
+
+
+```
+
+
+
+
+
+## :wrench: Options
+
+```jsonc
+{
+ "svelte/brackets-same-line": [
+ "error",
+ {
+ "singleline": "never", // ["never", "always"]
+ "multiline": "always", // ["never", "always"]
+ "selfClosingTag": {
+ "singleline": "never", // ["never", "always"]
+ "multiline": "always" // ["never", "always"]
+ }
+ }
+ ]
+}
+```
+
+- `singleline`: (`"never"` by default) Configuration for single-line elements. It's a single-line element if the element does not have attributes or the last attribute is on the same line as the opening bracket.
+- `multiline`: (`"always"` by default) Configuration for multi-line elements. It's a multi-line element if the last attribute is not on the same line of the opening bracket.
+- `selfClosingTag.singleline`: Configuration for single-line self closing elements.
+- `selfClosingTag.multiline`: Configuration for multi-line self closing elements.
+
+The `selfClosing` is optional, and by default it will use the same configuration as `singleline` and `multiline`, respectively.
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/html-closing-bracket-new-line.ts)
+- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/html-closing-bracket-new-line.ts)
diff --git a/packages/eslint-plugin-svelte/src/configs/flat/prettier.ts b/packages/eslint-plugin-svelte/src/configs/flat/prettier.ts
index f383837db..a97e410c5 100644
--- a/packages/eslint-plugin-svelte/src/configs/flat/prettier.ts
+++ b/packages/eslint-plugin-svelte/src/configs/flat/prettier.ts
@@ -10,6 +10,7 @@ const config: Linter.Config[] = [
rules: {
// eslint-plugin-svelte rules
'svelte/first-attribute-linebreak': 'off',
+ 'svelte/html-closing-bracket-new-line': 'off',
'svelte/html-closing-bracket-spacing': 'off',
'svelte/html-quotes': 'off',
'svelte/html-self-closing': 'off',
diff --git a/packages/eslint-plugin-svelte/src/configs/prettier.ts b/packages/eslint-plugin-svelte/src/configs/prettier.ts
index eb76a588c..6b4faf299 100644
--- a/packages/eslint-plugin-svelte/src/configs/prettier.ts
+++ b/packages/eslint-plugin-svelte/src/configs/prettier.ts
@@ -10,6 +10,7 @@ const config: Linter.LegacyConfig = {
rules: {
// eslint-plugin-svelte rules
'svelte/first-attribute-linebreak': 'off',
+ 'svelte/html-closing-bracket-new-line': 'off',
'svelte/html-closing-bracket-spacing': 'off',
'svelte/html-quotes': 'off',
'svelte/html-self-closing': 'off',
diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts
index c6b683f45..01901d52b 100644
--- a/packages/eslint-plugin-svelte/src/rule-types.ts
+++ b/packages/eslint-plugin-svelte/src/rule-types.ts
@@ -54,6 +54,11 @@ export interface RuleOptions {
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak/
*/
'svelte/first-attribute-linebreak'?: Linter.RuleEntry
+ /**
+ * Require or disallow a line break before tag's closing brackets
+ * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-new-line/
+ */
+ 'svelte/html-closing-bracket-new-line'?: Linter.RuleEntry
/**
* require or disallow a space before tag's closing brackets
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-spacing/
@@ -361,6 +366,15 @@ type SvelteFirstAttributeLinebreak = []|[{
multiline?: ("below" | "beside")
singleline?: ("below" | "beside")
}]
+// ----- svelte/html-closing-bracket-new-line -----
+type SvelteHtmlClosingBracketNewLine = []|[{
+ singleline?: ("always" | "never")
+ multiline?: ("always" | "never")
+ selfClosingTag?: {
+ singleline?: ("always" | "never")
+ multiline?: ("always" | "never")
+ }
+}]
// ----- svelte/html-closing-bracket-spacing -----
type SvelteHtmlClosingBracketSpacing = []|[{
startTag?: ("always" | "never" | "ignore")
diff --git a/packages/eslint-plugin-svelte/src/rules/html-closing-bracket-new-line.ts b/packages/eslint-plugin-svelte/src/rules/html-closing-bracket-new-line.ts
new file mode 100644
index 000000000..20902d7ed
--- /dev/null
+++ b/packages/eslint-plugin-svelte/src/rules/html-closing-bracket-new-line.ts
@@ -0,0 +1,163 @@
+import type { AST } from 'svelte-eslint-parser';
+import { createRule } from '../utils';
+import { getSourceCode } from '../utils/compat';
+import type { SourceCode } from '../types';
+
+type ExpectedNode = AST.SvelteStartTag | AST.SvelteEndTag;
+type OptionValue = 'always' | 'never';
+type RuleOptions = {
+ singleline: OptionValue;
+ multiline: OptionValue;
+ selfClosingTag?: Omit;
+};
+
+function getPhrase(lineBreaks: number) {
+ switch (lineBreaks) {
+ case 0: {
+ return 'no line breaks';
+ }
+ case 1: {
+ return '1 line break';
+ }
+ default: {
+ return `${lineBreaks} line breaks`;
+ }
+ }
+}
+
+function getExpectedLineBreaks(
+ node: ExpectedNode,
+ options: RuleOptions,
+ type: keyof Omit
+) {
+ const isSelfClosingTag = node.type === 'SvelteStartTag' && node.selfClosing;
+ if (isSelfClosingTag && options.selfClosingTag && options.selfClosingTag[type]) {
+ return options.selfClosingTag[type] === 'always' ? 1 : 0;
+ }
+
+ return options[type] === 'always' ? 1 : 0;
+}
+
+type NodeData = {
+ actualLineBreaks: number;
+ expectedLineBreaks: number;
+ startToken: AST.Token;
+ endToken: AST.Token;
+};
+
+function getSelfClosingData(
+ sourceCode: SourceCode,
+ node: AST.SvelteStartTag,
+ options: RuleOptions
+): NodeData | null {
+ const tokens = sourceCode.getTokens(node);
+ const closingToken = tokens[tokens.length - 2];
+ if (closingToken.value !== '/') {
+ return null;
+ }
+
+ const prevToken = sourceCode.getTokenBefore(closingToken)!;
+ const type = node.loc.start.line === prevToken.loc.end.line ? 'singleline' : 'multiline';
+
+ const expectedLineBreaks = getExpectedLineBreaks(node, options, type);
+ const actualLineBreaks = closingToken.loc.start.line - prevToken.loc.end.line;
+
+ return { actualLineBreaks, expectedLineBreaks, startToken: prevToken, endToken: closingToken };
+}
+
+function getNodeData(
+ sourceCode: SourceCode,
+ node: ExpectedNode,
+ options: RuleOptions
+): NodeData | null {
+ const closingToken = sourceCode.getLastToken(node);
+ if (closingToken.value !== '>') {
+ return null;
+ }
+
+ const prevToken = sourceCode.getTokenBefore(closingToken)!;
+ const type = node.loc.start.line === prevToken.loc.end.line ? 'singleline' : 'multiline';
+
+ const expectedLineBreaks = getExpectedLineBreaks(node, options, type);
+ const actualLineBreaks = closingToken.loc.start.line - prevToken.loc.end.line;
+
+ return { actualLineBreaks, expectedLineBreaks, startToken: prevToken, endToken: closingToken };
+}
+
+export default createRule('html-closing-bracket-new-line', {
+ meta: {
+ docs: {
+ description: "Require or disallow a line break before tag's closing brackets",
+ category: 'Stylistic Issues',
+ recommended: false,
+ conflictWithPrettier: true
+ },
+ schema: [
+ {
+ type: 'object',
+ properties: {
+ singleline: { enum: ['always', 'never'] },
+ multiline: { enum: ['always', 'never'] },
+ selfClosingTag: {
+ type: 'object',
+ properties: {
+ singleline: { enum: ['always', 'never'] },
+ multiline: { enum: ['always', 'never'] }
+ },
+ additionalProperties: false,
+ minProperties: 1
+ }
+ },
+ additionalProperties: false
+ }
+ ],
+ messages: {
+ expectedBeforeClosingBracket:
+ 'Expected {{expected}} before closing bracket, but {{actual}} found.'
+ },
+ fixable: 'code',
+ type: 'suggestion'
+ },
+ create(context) {
+ const options: RuleOptions = context.options[0] ?? {};
+ options.singleline ??= 'never';
+ options.multiline ??= 'always';
+
+ const sourceCode = getSourceCode(context);
+
+ return {
+ 'SvelteStartTag, SvelteEndTag'(node: ExpectedNode) {
+ const data =
+ node.type === 'SvelteStartTag' && node.selfClosing
+ ? getSelfClosingData(sourceCode, node, options)
+ : getNodeData(sourceCode, node, options);
+ if (!data) {
+ return;
+ }
+
+ const { actualLineBreaks, expectedLineBreaks, startToken, endToken } = data;
+ if (actualLineBreaks !== expectedLineBreaks) {
+ // For SvelteEndTag, does not make sense to add a line break, so we only fix if there are extra line breaks
+ if (node.type === 'SvelteEndTag' && expectedLineBreaks !== 0) {
+ return;
+ }
+
+ context.report({
+ node,
+ loc: { start: startToken.loc.end, end: endToken.loc.start },
+ messageId: 'expectedBeforeClosingBracket',
+ data: {
+ expected: getPhrase(expectedLineBreaks),
+ actual: getPhrase(actualLineBreaks)
+ },
+ fix(fixer) {
+ const range: AST.Range = [startToken.range[1], endToken.range[0]];
+ const text = '\n'.repeat(expectedLineBreaks);
+ return fixer.replaceTextRange(range, text);
+ }
+ });
+ }
+ }
+ };
+ }
+});
diff --git a/packages/eslint-plugin-svelte/src/utils/rules.ts b/packages/eslint-plugin-svelte/src/utils/rules.ts
index af0dd20e6..614c3ef6a 100644
--- a/packages/eslint-plugin-svelte/src/utils/rules.ts
+++ b/packages/eslint-plugin-svelte/src/utils/rules.ts
@@ -10,6 +10,7 @@ import derivedHasSameInputsOutputs from '../rules/derived-has-same-inputs-output
import experimentalRequireSlotTypes from '../rules/experimental-require-slot-types';
import experimentalRequireStrictEvents from '../rules/experimental-require-strict-events';
import firstAttributeLinebreak from '../rules/first-attribute-linebreak';
+import htmlClosingBracketNewLine from '../rules/html-closing-bracket-new-line';
import htmlClosingBracketSpacing from '../rules/html-closing-bracket-spacing';
import htmlQuotes from '../rules/html-quotes';
import htmlSelfClosing from '../rules/html-self-closing';
@@ -75,6 +76,7 @@ export const rules = [
experimentalRequireSlotTypes,
experimentalRequireStrictEvents,
firstAttributeLinebreak,
+ htmlClosingBracketNewLine,
htmlClosingBracketSpacing,
htmlQuotes,
htmlSelfClosing,
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/_config.json
new file mode 100644
index 000000000..1c8db1860
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/_config.json
@@ -0,0 +1,3 @@
+{
+ "options": [{ "multiline": "never" }]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-errors.yaml
new file mode 100644
index 000000000..fc094d043
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-errors.yaml
@@ -0,0 +1,8 @@
+- message: Expected no line breaks before closing bracket, but 1 line break found.
+ line: 2
+ column: 12
+ suggestions: null
+- message: Expected no line breaks before closing bracket, but 1 line break found.
+ line: 7
+ column: 12
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-input.svelte
new file mode 100644
index 000000000..e3e5b5e1f
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-input.svelte
@@ -0,0 +1,10 @@
+
+
+
+Children
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-output.svelte
new file mode 100644
index 000000000..40b9c843e
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/multiline-never/test01-output.svelte
@@ -0,0 +1,8 @@
+
+
+
+Children
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/_config.json
new file mode 100644
index 000000000..0d0e60c52
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/_config.json
@@ -0,0 +1,3 @@
+{
+ "options": [{ "selfClosingTag": { "singleline": "always", "multiline": "always" } }]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-errors.yaml
new file mode 100644
index 000000000..1a10165e6
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-errors.yaml
@@ -0,0 +1,8 @@
+- message: Expected 1 line break before closing bracket, but no line breaks found.
+ line: 1
+ column: 18
+ suggestions: null
+- message: Expected 1 line break before closing bracket, but 2 line breaks found.
+ line: 6
+ column: 12
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-input.svelte
new file mode 100644
index 000000000..b150ca599
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-input.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-output.svelte
new file mode 100644
index 000000000..f39f85537
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/always/test-output.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/_config.json
new file mode 100644
index 000000000..127cc8b7c
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/_config.json
@@ -0,0 +1,3 @@
+{
+ "options": [{ "selfClosingTag": { "singleline": "never", "multiline": "never" } }]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-errors.yaml
new file mode 100644
index 000000000..a124b0cf2
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-errors.yaml
@@ -0,0 +1,8 @@
+- message: Expected no line breaks before closing bracket, but 1 line break found.
+ line: 3
+ column: 12
+ suggestions: null
+- message: Expected no line breaks before closing bracket, but 2 line breaks found.
+ line: 6
+ column: 12
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-input.svelte
new file mode 100644
index 000000000..b150ca599
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-input.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-output.svelte
new file mode 100644
index 000000000..580b4158f
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/self-closing/never/test-output.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/_config.json
new file mode 100644
index 000000000..74ea9fd71
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/_config.json
@@ -0,0 +1,3 @@
+{
+ "options": [{ "singleline": "always" }]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-errors.yaml
new file mode 100644
index 000000000..e7b7863fc
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-errors.yaml
@@ -0,0 +1,8 @@
+- message: Expected 1 line break before closing bracket, but no line breaks found.
+ line: 1
+ column: 5
+ suggestions: null
+- message: Expected 1 line break before closing bracket, but no line breaks found.
+ line: 2
+ column: 5
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-input.svelte
new file mode 100644
index 000000000..2cf49756b
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-input.svelte
@@ -0,0 +1,3 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-output.svelte
new file mode 100644
index 000000000..da7c82492
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/singleline-always/test01-output.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-errors.yaml
new file mode 100644
index 000000000..548d3143f
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-errors.yaml
@@ -0,0 +1,12 @@
+- message: Expected no line breaks before closing bracket, but 3 line breaks found.
+ line: 3
+ column: 8
+ suggestions: null
+- message: Expected no line breaks before closing bracket, but 1 line break found.
+ line: 8
+ column: 5
+ suggestions: null
+- message: Expected 1 line break before closing bracket, but no line breaks found.
+ line: 11
+ column: 14
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-input.svelte
new file mode 100644
index 000000000..fb10f848f
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-input.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-output.svelte
new file mode 100644
index 000000000..45cdbc87d
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test01-output.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-errors.yaml
new file mode 100644
index 000000000..354b3d192
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-errors.yaml
@@ -0,0 +1,8 @@
+- message: Expected 1 line break before closing bracket, but 2 line breaks found.
+ line: 3
+ column: 14
+ suggestions: null
+- message: Expected no line breaks before closing bracket, but 2 line breaks found.
+ line: 7
+ column: 5
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-input.svelte
new file mode 100644
index 000000000..ab050693c
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-input.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-output.svelte
new file mode 100644
index 000000000..f145cb7e2
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/invalid/test02-output.svelte
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/valid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/valid/test01-input.svelte
new file mode 100644
index 000000000..aa2be93c0
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/html-closing-bracket-new-line/valid/test01-input.svelte
@@ -0,0 +1,4 @@
+
+
diff --git a/packages/eslint-plugin-svelte/tests/src/rules/html-closing-bracket-new-line.ts b/packages/eslint-plugin-svelte/tests/src/rules/html-closing-bracket-new-line.ts
new file mode 100644
index 000000000..dfeba140c
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/src/rules/html-closing-bracket-new-line.ts
@@ -0,0 +1,12 @@
+import { RuleTester } from '../../utils/eslint-compat';
+import rule from '../../../src/rules/html-closing-bracket-new-line';
+import { loadTestCases } from '../../utils/utils';
+
+const tester = new RuleTester({
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module'
+ }
+});
+
+tester.run('html-closing-bracket-new-line', rule as any, loadTestCases('html-closing-bracket-new-line'));