diff --git a/.changeset/eight-comics-tell.md b/.changeset/eight-comics-tell.md
new file mode 100644
index 0000000000..fa506aba46
--- /dev/null
+++ b/.changeset/eight-comics-tell.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+feat: add support for ``
diff --git a/packages/svelte/messages/compile-errors/template.md b/packages/svelte/messages/compile-errors/template.md
index 4e24714647..7920329c8b 100644
--- a/packages/svelte/messages/compile-errors/template.md
+++ b/packages/svelte/messages/compile-errors/template.md
@@ -324,7 +324,7 @@ HTML restricts where certain elements can appear. In case of a violation the bro
## svelte_options_invalid_attribute_value
-> Valid values are %list%
+> Value must be %list%, if specified
## svelte_options_invalid_customelement
diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js
index 0b91336ee0..958c86a817 100644
--- a/packages/svelte/src/compiler/errors.js
+++ b/packages/svelte/src/compiler/errors.js
@@ -1275,13 +1275,13 @@ export function svelte_options_invalid_attribute(node) {
}
/**
- * Valid values are %list%
+ * Value must be %list%, if specified
* @param {null | number | NodeLike} node
* @param {string} list
* @returns {never}
*/
export function svelte_options_invalid_attribute_value(node, list) {
- e(node, "svelte_options_invalid_attribute_value", `Valid values are ${list}`);
+ e(node, "svelte_options_invalid_attribute_value", `Value must be ${list}, if specified`);
}
/**
diff --git a/packages/svelte/src/compiler/phases/1-parse/read/options.js b/packages/svelte/src/compiler/phases/1-parse/read/options.js
index 751fe5f672..7c83946336 100644
--- a/packages/svelte/src/compiler/phases/1-parse/read/options.js
+++ b/packages/svelte/src/compiler/phases/1-parse/read/options.js
@@ -175,6 +175,17 @@ export default function read_options(node) {
break;
}
+ case 'css': {
+ const value = get_static_value(attribute);
+
+ if (value === 'injected') {
+ component_options.css = value;
+ } else {
+ e.svelte_options_invalid_attribute_value(attribute, `"injected"`);
+ }
+
+ break;
+ }
case 'immutable': {
component_options.immutable = get_boolean_value(attribute);
break;
diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts
index ee6315a98c..373822a873 100644
--- a/packages/svelte/src/compiler/types/template.d.ts
+++ b/packages/svelte/src/compiler/types/template.d.ts
@@ -75,6 +75,7 @@ export interface SvelteOptions {
accessors?: boolean;
preserveWhitespace?: boolean;
namespace?: Namespace;
+ css?: 'injected';
customElement?: {
tag: string;
shadow?: 'open' | 'none';
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/Nested.svelte b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/Nested.svelte
new file mode 100644
index 0000000000..81243bf114
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/Nested.svelte
@@ -0,0 +1,9 @@
+
+
+
bar
+
+
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_config.js b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_config.js
new file mode 100644
index 0000000000..286454e931
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_config.js
@@ -0,0 +1,7 @@
+import { test } from '../../test';
+
+export default test({
+ compileOptions: {
+ css: 'external'
+ }
+});
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.css b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.css
new file mode 100644
index 0000000000..bddefdd00c
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.css
@@ -0,0 +1,4 @@
+
+.foo.svelte-sg04hs {
+ color: red;
+}
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.html
new file mode 100644
index 0000000000..1f0b2b95fe
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected.html
@@ -0,0 +1 @@
+bar
foo
\ No newline at end of file
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected_head.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected_head.html
new file mode 100644
index 0000000000..806f6c2db2
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/_expected_head.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/main.svelte b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/main.svelte
new file mode 100644
index 0000000000..a2b9f38de3
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options-nested/main.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+foo
+
+
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_config.js b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_config.js
new file mode 100644
index 0000000000..286454e931
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_config.js
@@ -0,0 +1,7 @@
+import { test } from '../../test';
+
+export default test({
+ compileOptions: {
+ css: 'external'
+ }
+});
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.css b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.css
new file mode 100644
index 0000000000..8882c6ec7e
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.css
@@ -0,0 +1,4 @@
+
+ .foo.svelte-sg04hs {
+ color: red;
+ }
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.html
new file mode 100644
index 0000000000..8ebe1ad73e
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected.html
@@ -0,0 +1 @@
+foo
\ No newline at end of file
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected_head.html b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected_head.html
new file mode 100644
index 0000000000..7281935646
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/_expected_head.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/packages/svelte/tests/server-side-rendering/samples/css-injected-options/main.svelte b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/main.svelte
new file mode 100644
index 0000000000..7387067b9b
--- /dev/null
+++ b/packages/svelte/tests/server-side-rendering/samples/css-injected-options/main.svelte
@@ -0,0 +1,9 @@
+
+
+foo
+
+
diff --git a/packages/svelte/tests/validator/samples/namespace-invalid/errors.json b/packages/svelte/tests/validator/samples/namespace-invalid/errors.json
index ae98ee7e25..bcd2dc1d9c 100644
--- a/packages/svelte/tests/validator/samples/namespace-invalid/errors.json
+++ b/packages/svelte/tests/validator/samples/namespace-invalid/errors.json
@@ -1,7 +1,7 @@
[
{
"code": "svelte_options_invalid_attribute_value",
- "message": "Valid values are \"html\", \"mathml\", \"svg\" or \"foreign\"",
+ "message": "Value must be \"html\", \"mathml\", \"svg\" or \"foreign\", if specified",
"start": {
"line": 1,
"column": 16
diff --git a/packages/svelte/tests/validator/samples/namespace-non-literal/errors.json b/packages/svelte/tests/validator/samples/namespace-non-literal/errors.json
index 439dbd032b..d7d637fbb1 100644
--- a/packages/svelte/tests/validator/samples/namespace-non-literal/errors.json
+++ b/packages/svelte/tests/validator/samples/namespace-non-literal/errors.json
@@ -1,7 +1,7 @@
[
{
"code": "svelte_options_invalid_attribute_value",
- "message": "Valid values are \"html\", \"mathml\", \"svg\" or \"foreign\"",
+ "message": "Value must be \"html\", \"mathml\", \"svg\" or \"foreign\", if specified",
"start": {
"line": 1,
"column": 16
diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts
index 8ba68e1d2d..8212c52cc0 100644
--- a/packages/svelte/types/index.d.ts
+++ b/packages/svelte/types/index.d.ts
@@ -1533,6 +1533,7 @@ declare module 'svelte/compiler' {
accessors?: boolean;
preserveWhitespace?: boolean;
namespace?: Namespace;
+ css?: 'injected';
customElement?: {
tag: string;
shadow?: 'open' | 'none';