diff --git a/.changeset/lazy-eyes-wait.md b/.changeset/lazy-eyes-wait.md
new file mode 100644
index 000000000..74f2c8611
--- /dev/null
+++ b/.changeset/lazy-eyes-wait.md
@@ -0,0 +1,5 @@
+---
+'eslint-plugin-svelte': minor
+---
+
+Added new `no-deprecated-raw-special-elements` rule
diff --git a/README.md b/README.md
index 9682cbf66..7c569527b 100644
--- a/README.md
+++ b/README.md
@@ -380,6 +380,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
| Rule ID | Description | |
|:--------|:------------|:---|
| [svelte/infinite-reactive-loop](https://sveltejs.github.io/eslint-plugin-svelte/rules/infinite-reactive-loop/) | Svelte runtime prevents calling the same reactive statement twice in a microtask. But between different microtask, it doesn't prevent. | |
+| [svelte/no-deprecated-raw-special-elements](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-deprecated-raw-special-elements/) | Recommends not using raw special elements in Svelte versions previous to 5. | :wrench: |
| [svelte/no-dom-manipulating](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-dom-manipulating/) | disallow DOM manipulating | |
| [svelte/no-dupe-else-if-blocks](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-dupe-else-if-blocks/) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: |
| [svelte/no-dupe-on-directives](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-dupe-on-directives/) | disallow duplicate `on:` directives | |
diff --git a/docs/rules.md b/docs/rules.md
index fb067e57c..29701ff7e 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -17,6 +17,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
| Rule ID | Description | |
| :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- | :------------- |
| [svelte/infinite-reactive-loop](./rules/infinite-reactive-loop.md) | Svelte runtime prevents calling the same reactive statement twice in a microtask. But between different microtask, it doesn't prevent. | |
+| [svelte/no-deprecated-raw-special-elements](./rules/no-deprecated-raw-special-elements.md) | Recommends not using raw special elements in Svelte versions previous to 5. | :wrench: |
| [svelte/no-dom-manipulating](./rules/no-dom-manipulating.md) | disallow DOM manipulating | |
| [svelte/no-dupe-else-if-blocks](./rules/no-dupe-else-if-blocks.md) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: |
| [svelte/no-dupe-on-directives](./rules/no-dupe-on-directives.md) | disallow duplicate `on:` directives | |
diff --git a/docs/rules/no-deprecated-raw-special-elements.md b/docs/rules/no-deprecated-raw-special-elements.md
new file mode 100644
index 000000000..4bf863ae6
--- /dev/null
+++ b/docs/rules/no-deprecated-raw-special-elements.md
@@ -0,0 +1,52 @@
+---
+pageClass: 'rule-details'
+sidebarDepth: 0
+title: 'svelte/no-deprecated-raw-special-elements'
+description: 'Recommends not using raw special elements in Svelte versions previous to 5.'
+---
+
+# svelte/no-deprecated-raw-special-elements
+
+> Recommends not using raw special elements in Svelte versions previous to 5.
+
+- :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 reports the usage of `head`, `body`, `window`, `document`, `element` and `options` HTML elements. These elements were valid in in versions proior to 5, but since Svelte 5 they must be used with `svelte:`.
+
+
+
+
+
+```svelte
+
+
+
+
+ Valid
+
+
+
+
+ Invalid
+
+```
+
+
+
+## :wrench: Options
+
+Nothing.
+
+## :books: Further Reading
+
+- See special elements section in [Svelte docs](https://svelte.dev/docs/svelte/svelte-window)
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-deprecated-raw-special-elements.ts)
+- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-deprecated-raw-special-elements.ts)
diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts
index 8e747b6e4..8b7cbe80c 100644
--- a/packages/eslint-plugin-svelte/src/rule-types.ts
+++ b/packages/eslint-plugin-svelte/src/rule-types.ts
@@ -104,6 +104,11 @@ export interface RuleOptions {
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-at-html-tags/
*/
'svelte/no-at-html-tags'?: Linter.RuleEntry<[]>
+ /**
+ * Recommends not using raw special elements in Svelte versions previous to 5.
+ * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-deprecated-raw-special-elements/
+ */
+ 'svelte/no-deprecated-raw-special-elements'?: Linter.RuleEntry<[]>
/**
* disallow DOM manipulating
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-dom-manipulating/
diff --git a/packages/eslint-plugin-svelte/src/rules/no-deprecated-raw-special-elements.ts b/packages/eslint-plugin-svelte/src/rules/no-deprecated-raw-special-elements.ts
new file mode 100644
index 000000000..d47ef72e1
--- /dev/null
+++ b/packages/eslint-plugin-svelte/src/rules/no-deprecated-raw-special-elements.ts
@@ -0,0 +1,47 @@
+import type { AST } from 'svelte-eslint-parser';
+import { createRule } from '../utils';
+
+const INVALID_HTML_ELEMENTS = ['head', 'body', 'window', 'document', 'element', 'options'];
+const VALID_PREFIX = 'svelte:';
+
+export default createRule('no-deprecated-raw-special-elements', {
+ meta: {
+ docs: {
+ description: 'Recommends not using raw special elements in Svelte versions previous to 5.',
+ category: 'Possible Errors',
+ // TODO: Switch to recommended in the major version
+ recommended: false
+ },
+ schema: [],
+ messages: {
+ deprecatedElement:
+ 'Special {{name}} element is deprecated in v5, use svelte:{{name}} instead.'
+ },
+ type: 'problem', // 'problem', or 'layout',
+ fixable: 'code'
+ },
+ create(context) {
+ return {
+ 'SvelteElement[kind="html"]'(node: AST.SvelteHTMLElement) {
+ const { name } = node.name;
+ if (INVALID_HTML_ELEMENTS.includes(name)) {
+ context.report({
+ node,
+ messageId: 'deprecatedElement',
+ data: { name },
+ *fix(fixer) {
+ const { endTag } = node;
+ yield fixer.insertTextBeforeRange([node.range[0] + 1, node.range[1]], VALID_PREFIX);
+ if (endTag) {
+ yield fixer.insertTextBeforeRange(
+ [endTag.range[0] + 2, endTag.range[1]],
+ VALID_PREFIX
+ );
+ }
+ }
+ });
+ }
+ }
+ };
+ }
+});
diff --git a/packages/eslint-plugin-svelte/src/utils/rules.ts b/packages/eslint-plugin-svelte/src/utils/rules.ts
index 5bb5a080c..862db8b99 100644
--- a/packages/eslint-plugin-svelte/src/utils/rules.ts
+++ b/packages/eslint-plugin-svelte/src/utils/rules.ts
@@ -20,6 +20,7 @@ import maxAttributesPerLine from '../rules/max-attributes-per-line';
import mustacheSpacing from '../rules/mustache-spacing';
import noAtDebugTags from '../rules/no-at-debug-tags';
import noAtHtmlTags from '../rules/no-at-html-tags';
+import noDeprecatedRawSpecialElements from '../rules/no-deprecated-raw-special-elements';
import noDomManipulating from '../rules/no-dom-manipulating';
import noDupeElseIfBlocks from '../rules/no-dupe-else-if-blocks';
import noDupeOnDirectives from '../rules/no-dupe-on-directives';
@@ -87,6 +88,7 @@ export const rules = [
mustacheSpacing,
noAtDebugTags,
noAtHtmlTags,
+ noDeprecatedRawSpecialElements,
noDomManipulating,
noDupeElseIfBlocks,
noDupeOnDirectives,
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-errors.yaml
new file mode 100644
index 000000000..2acb009df
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-errors.yaml
@@ -0,0 +1,24 @@
+- message: Special head element is deprecated in v5, use svelte:head instead.
+ line: 1
+ column: 1
+ suggestions: null
+- message: Special body element is deprecated in v5, use svelte:body instead.
+ line: 2
+ column: 1
+ suggestions: null
+- message: Special window element is deprecated in v5, use svelte:window instead.
+ line: 3
+ column: 1
+ suggestions: null
+- message: Special document element is deprecated in v5, use svelte:document instead.
+ line: 4
+ column: 1
+ suggestions: null
+- message: Special element element is deprecated in v5, use svelte:element instead.
+ line: 5
+ column: 1
+ suggestions: null
+- message: Special options element is deprecated in v5, use svelte:options instead.
+ line: 6
+ column: 1
+ suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-input.svelte
new file mode 100644
index 000000000..0856e15ef
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-input.svelte
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-output.svelte
new file mode 100644
index 000000000..507eea7d8
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/invalid/test01-output.svelte
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/valid/test01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/valid/test01-input.svelte
new file mode 100644
index 000000000..ea0dfc2a0
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-deprecated-raw-special-elements/valid/test01-input.svelte
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/packages/eslint-plugin-svelte/tests/src/rules/no-deprecated-raw-special-elements.ts b/packages/eslint-plugin-svelte/tests/src/rules/no-deprecated-raw-special-elements.ts
new file mode 100644
index 000000000..dbe2fe152
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/src/rules/no-deprecated-raw-special-elements.ts
@@ -0,0 +1,12 @@
+import { RuleTester } from '../../utils/eslint-compat';
+import rule from '../../../src/rules/no-deprecated-raw-special-elements';
+import { loadTestCases } from '../../utils/utils';
+
+const tester = new RuleTester({
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module'
+ }
+});
+
+tester.run('no-deprecated-raw-special-elements', rule as any, loadTestCases('no-deprecated-raw-special-elements'));