From 57a555e00c1b700c2ff86f519ce4d5ed93eb6cbd Mon Sep 17 00:00:00 2001
From: dpiercey
Date: Thu, 16 Apr 2026 18:05:35 -0700
Subject: [PATCH] fix: html script, style, and comment escaping
---
.changeset/blue-dragons-see.md | 14 ++++++
.changeset/frank-memes-knock.md | 13 ++++++
.../helpers/escape-comment-placeholder.js | 17 +++++++
.../html/helpers/escape-script-placeholder.js | 2 +-
.../html/helpers/escape-style-placeholder.js | 2 +-
.../taglib/core/translate-html-comment.js | 30 ++++++++++---
.../fixtures/escape-comment/expected.html | 1 +
.../fixtures/escape-comment/template.marko | 1 +
.../render/fixtures/escape-comment/test.js | 3 ++
.../escape-comment/vdom-expected.html | 1 +
.../fixtures/escape-script-case/expected.html | 3 ++
.../escape-script-case/template.marko | 4 ++
.../fixtures/escape-script-case/test.js | 5 +++
.../escape-script-case/vdom-expected.html | 4 ++
.../fixtures/escape-style-case/expected.html | 5 +++
.../fixtures/escape-style-case/template.marko | 5 +++
.../render/fixtures/escape-style-case/test.js | 3 ++
.../escape-style-case/vdom-expected.html | 2 +
.../__snapshots__/html.expected/template.js | 2 +-
.../__snapshots__/.name-cache.json | 5 +++
.../__snapshots__/csr-sanitized.expected.md | 1 +
.../__snapshots__/csr.expected.md | 9 ++++
.../dom.expected/template.hydrate.js | 1 +
.../__snapshots__/dom.expected/template.js | 7 +++
.../__snapshots__/html.expected/template.js | 6 +++
.../resume-sanitized.expected.md | 1 +
.../__snapshots__/resume.expected.md | 8 ++++
.../__snapshots__/ssr-sanitized.expected.md | 1 +
.../__snapshots__/ssr.expected.md | 21 +++++++++
.../html-comment-placeholder/template.marko | 1 +
.../fixtures/html-comment-placeholder/test.ts | 5 +++
.../__snapshots__/.name-cache.json | 5 +++
.../__snapshots__/csr-sanitized.expected.md | 1 +
.../__snapshots__/csr.expected.md | 11 +++++
.../dom.expected/template.hydrate.js | 1 +
.../__snapshots__/dom.expected/template.js | 9 ++++
.../__snapshots__/html.expected/template.js | 8 ++++
.../resume-sanitized.expected.md | 1 +
.../__snapshots__/resume.expected.md | 11 +++++
.../__snapshots__/ssr-sanitized.expected.md | 1 +
.../__snapshots__/ssr.expected.md | 25 +++++++++++
.../html-script-injection/template.marko | 2 +
.../fixtures/html-script-injection/test.ts | 5 +++
.../__snapshots__/.name-cache.json | 5 +++
.../__snapshots__/csr-sanitized.expected.md | 1 +
.../__snapshots__/csr.expected.md | 11 +++++
.../dom.expected/template.hydrate.js | 1 +
.../__snapshots__/dom.expected/template.js | 9 ++++
.../__snapshots__/html.expected/template.js | 8 ++++
.../resume-sanitized.expected.md | 1 +
.../__snapshots__/resume.expected.md | 11 +++++
.../__snapshots__/ssr-sanitized.expected.md | 1 +
.../__snapshots__/ssr.expected.md | 25 +++++++++++
.../html-style-injection/template.marko | 2 +
.../fixtures/html-style-injection/test.ts | 5 +++
.../src/__tests__/html-content.test.ts | 45 +++++++++++++++++++
packages/runtime-tags/src/html.ts | 1 +
packages/runtime-tags/src/html/content.ts | 12 ++++-
.../src/translator/core/html-comment.ts | 2 +-
.../src/translator/util/runtime.ts | 2 +
60 files changed, 394 insertions(+), 11 deletions(-)
create mode 100644 .changeset/blue-dragons-see.md
create mode 100644 .changeset/frank-memes-knock.md
create mode 100644 packages/runtime-class/src/runtime/html/helpers/escape-comment-placeholder.js
create mode 100644 packages/runtime-class/test/render/fixtures/escape-comment/expected.html
create mode 100644 packages/runtime-class/test/render/fixtures/escape-comment/template.marko
create mode 100644 packages/runtime-class/test/render/fixtures/escape-comment/test.js
create mode 100644 packages/runtime-class/test/render/fixtures/escape-comment/vdom-expected.html
create mode 100644 packages/runtime-class/test/render/fixtures/escape-script-case/expected.html
create mode 100644 packages/runtime-class/test/render/fixtures/escape-script-case/template.marko
create mode 100644 packages/runtime-class/test/render/fixtures/escape-script-case/test.js
create mode 100644 packages/runtime-class/test/render/fixtures/escape-script-case/vdom-expected.html
create mode 100644 packages/runtime-class/test/render/fixtures/escape-style-case/expected.html
create mode 100644 packages/runtime-class/test/render/fixtures/escape-style-case/template.marko
create mode 100644 packages/runtime-class/test/render/fixtures/escape-style-case/test.js
create mode 100644 packages/runtime-class/test/render/fixtures/escape-style-case/vdom-expected.html
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/.name-cache.json
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.hydrate.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/html.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/template.marko
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/test.ts
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/.name-cache.json
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.hydrate.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/html.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/template.marko
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-script-injection/test.ts
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/.name-cache.json
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/csr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/csr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/dom.expected/template.hydrate.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/dom.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/html.expected/template.js
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/resume-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/resume.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/ssr-sanitized.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/__snapshots__/ssr.expected.md
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/template.marko
create mode 100644 packages/runtime-tags/src/__tests__/fixtures/html-style-injection/test.ts
diff --git a/.changeset/blue-dragons-see.md b/.changeset/blue-dragons-see.md
new file mode 100644
index 0000000000..fb412ce4ed
--- /dev/null
+++ b/.changeset/blue-dragons-see.md
@@ -0,0 +1,14 @@
+---
+"marko": patch
+"@marko/runtime-tags": patch
+---
+
+Fix escaping issue for dynamic text interpolation inside ` "}
+```
+
+Note that `script` and `style` there should _never_ render unsanitized user defined values, regardless of wether or not the closing tag is escaped, since these are conceptually just "eval".
diff --git a/.changeset/frank-memes-knock.md b/.changeset/frank-memes-knock.md
new file mode 100644
index 0000000000..25e56dc10d
--- /dev/null
+++ b/.changeset/frank-memes-knock.md
@@ -0,0 +1,13 @@
+---
+"marko": patch
+"@marko/runtime-tags": patch
+---
+
+Fix escaping for `` tag.
+Previously this tag relied on normal xml escaping which looks for `<`.
+This PR updates to have a special escape for `` tags that replaces `>` instead.
+
+```marko
+// Previously incorrectly escaped.
+${">Uh oh"}
+```
diff --git a/packages/runtime-class/src/runtime/html/helpers/escape-comment-placeholder.js b/packages/runtime-class/src/runtime/html/helpers/escape-comment-placeholder.js
new file mode 100644
index 0000000000..350a007a0a
--- /dev/null
+++ b/packages/runtime-class/src/runtime/html/helpers/escape-comment-placeholder.js
@@ -0,0 +1,17 @@
+"use strict";
+const unsafeCharsReg = />/g;
+const replaceMatch = () => ">";
+const escape = (str) =>
+ unsafeCharsReg.test(str) ? str.replace(unsafeCharsReg, replaceMatch) : str;
+
+/**
+ * Escapes content placed inside an tag.
+ *
+ * For example:
+ * ${userInput}
+ *
+ * Without escaping, a value of `>`,
- ]);
+ const { file } = path.hub;
+ const nodes = [writeHTML``);
+ path.replaceWithMultiple(nodes.filter(Boolean));
} else {
const templateQuasis = [];
const templateExpressions = [];
diff --git a/packages/runtime-class/test/render/fixtures/escape-comment/expected.html b/packages/runtime-class/test/render/fixtures/escape-comment/expected.html
new file mode 100644
index 0000000000..90eb036ed8
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-comment/expected.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/runtime-class/test/render/fixtures/escape-comment/template.marko b/packages/runtime-class/test/render/fixtures/escape-comment/template.marko
new file mode 100644
index 0000000000..019e855e8a
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-comment/template.marko
@@ -0,0 +1 @@
+${input.text}
diff --git a/packages/runtime-class/test/render/fixtures/escape-comment/test.js b/packages/runtime-class/test/render/fixtures/escape-comment/test.js
new file mode 100644
index 0000000000..eb04215fef
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-comment/test.js
@@ -0,0 +1,3 @@
+exports.templateData = {
+ text: "-->",
+};
diff --git a/packages/runtime-class/test/render/fixtures/escape-comment/vdom-expected.html b/packages/runtime-class/test/render/fixtures/escape-comment/vdom-expected.html
new file mode 100644
index 0000000000..b2c6a1f288
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-comment/vdom-expected.html
@@ -0,0 +1 @@
+"-->
diff --git a/packages/runtime-class/test/render/fixtures/escape-script-case/expected.html b/packages/runtime-class/test/render/fixtures/escape-script-case/expected.html
new file mode 100644
index 0000000000..50ec8d57c7
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-script-case/expected.html
@@ -0,0 +1,3 @@
+{"name":"Evil </SCRIPT>"}
\ No newline at end of file
diff --git a/packages/runtime-class/test/render/fixtures/escape-script-case/template.marko b/packages/runtime-class/test/render/fixtures/escape-script-case/template.marko
new file mode 100644
index 0000000000..4ff4986f79
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-script-case/template.marko
@@ -0,0 +1,4 @@
+
+${JSON.stringify(input.foo)}
\ No newline at end of file
diff --git a/packages/runtime-class/test/render/fixtures/escape-script-case/test.js b/packages/runtime-class/test/render/fixtures/escape-script-case/test.js
new file mode 100644
index 0000000000..c0a15e5cc7
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-script-case/test.js
@@ -0,0 +1,5 @@
+exports.templateData = {
+ foo: {
+ name: "Evil ",
+ },
+};
diff --git a/packages/runtime-class/test/render/fixtures/escape-script-case/vdom-expected.html b/packages/runtime-class/test/render/fixtures/escape-script-case/vdom-expected.html
new file mode 100644
index 0000000000..591eb6cbd5
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-script-case/vdom-expected.html
@@ -0,0 +1,4 @@
+\"};\n"
+
+ "{\"name\":\"Evil \"}"
diff --git a/packages/runtime-class/test/render/fixtures/escape-style-case/expected.html b/packages/runtime-class/test/render/fixtures/escape-style-case/expected.html
new file mode 100644
index 0000000000..067d80802e
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-style-case/expected.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/packages/runtime-class/test/render/fixtures/escape-style-case/template.marko b/packages/runtime-class/test/render/fixtures/escape-style-case/template.marko
new file mode 100644
index 0000000000..37c1ff9d51
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-style-case/template.marko
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/packages/runtime-class/test/render/fixtures/escape-style-case/test.js b/packages/runtime-class/test/render/fixtures/escape-style-case/test.js
new file mode 100644
index 0000000000..49ffcd626c
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-style-case/test.js
@@ -0,0 +1,3 @@
+exports.templateData = {
+ color: '',
+};
diff --git a/packages/runtime-class/test/render/fixtures/escape-style-case/vdom-expected.html b/packages/runtime-class/test/render/fixtures/escape-style-case/vdom-expected.html
new file mode 100644
index 0000000000..e44cc7224b
--- /dev/null
+++ b/packages/runtime-class/test/render/fixtures/escape-style-case/vdom-expected.html
@@ -0,0 +1,2 @@
+;\n }\n"
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-counter/__snapshots__/html.expected/template.js b/packages/runtime-tags/src/__tests__/fixtures/html-comment-counter/__snapshots__/html.expected/template.js
index 37d8b6e5c1..2c14854fa5 100644
--- a/packages/runtime-tags/src/__tests__/fixtures/html-comment-counter/__snapshots__/html.expected/template.js
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-counter/__snapshots__/html.expected/template.js
@@ -3,7 +3,7 @@ export default _._template("__tests__/template.marko", input => {
_._scope_reason();
const $scope0_id = _._scope_id();
let count = 0;
- _._html(`${_._escape(count)}${_._el_resume($scope0_id, "#text/1")} ${_._el_resume($scope0_id, "#button/0")}${_._el_resume($scope0_id, "#comment/2")}
`);
+ _._html(`${_._escape(count)}${_._el_resume($scope0_id, "#text/1")} ${_._el_resume($scope0_id, "#button/0")}${_._el_resume($scope0_id, "#comment/2")}
`);
_._script($scope0_id, "__tests__/template.marko_0_count");
_._scope($scope0_id, {
count
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/.name-cache.json b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/.name-cache.json
new file mode 100644
index 0000000000..db413faf9a
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/.name-cache.json
@@ -0,0 +1,5 @@
+{
+ "vars": {
+ "props": {}
+ }
+}
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr-sanitized.expected.md
new file mode 100644
index 0000000000..ba2aa26adb
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr-sanitized.expected.md
@@ -0,0 +1 @@
+# Render
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr.expected.md
new file mode 100644
index 0000000000..586d7abdd9
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/csr.expected.md
@@ -0,0 +1,9 @@
+# Render
+```html
+
+```
+
+# Mutations
+```
+INSERT #comment
+```
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.hydrate.js b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.hydrate.js
new file mode 100644
index 0000000000..3eb9cd79d3
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.hydrate.js
@@ -0,0 +1 @@
+// size: 0
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.js b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.js
new file mode 100644
index 0000000000..f3f0c0e75b
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/dom.expected/template.js
@@ -0,0 +1,7 @@
+export const $template = "";
+export const $walks = /* get, over(1) */" b";
+import * as _ from "@marko/runtime-tags/debug/dom";
+export function $setup($scope) {
+ _._text($scope["#comment/0"], `${_._to_text("-->")}`);
+}
+export default /* @__PURE__ */_._template("__tests__/template.marko", $template, $walks, $setup);
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/html.expected/template.js b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/html.expected/template.js
new file mode 100644
index 0000000000..bfbbc4d336
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/html.expected/template.js
@@ -0,0 +1,6 @@
+import * as _ from "@marko/runtime-tags/debug/html";
+export default _._template("__tests__/template.marko", input => {
+ _._scope_reason();
+ const $scope0_id = _._scope_id();
+ _._html(`")}-->`);
+}, 1);
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume-sanitized.expected.md
new file mode 100644
index 0000000000..ba2aa26adb
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume-sanitized.expected.md
@@ -0,0 +1 @@
+# Render
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume.expected.md
new file mode 100644
index 0000000000..365737353e
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/resume.expected.md
@@ -0,0 +1,8 @@
+# Render
+```html
+
+
+
+
+
+```
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr-sanitized.expected.md
new file mode 100644
index 0000000000..ef85d03440
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr-sanitized.expected.md
@@ -0,0 +1 @@
+# Render End
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr.expected.md
new file mode 100644
index 0000000000..448176687d
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/__snapshots__/ssr.expected.md
@@ -0,0 +1,21 @@
+# Write
+```html
+
+```
+
+# Render End
+```html
+
+
+
+
+
+```
+
+# Mutations
+```
+INSERT #comment
+INSERT html
+INSERT html/head
+INSERT html/body
+```
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/template.marko b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/template.marko
new file mode 100644
index 0000000000..aba548c30c
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/template.marko
@@ -0,0 +1 @@
+${"-->"}
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/test.ts b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/test.ts
new file mode 100644
index 0000000000..53375135d8
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-comment-placeholder/test.ts
@@ -0,0 +1,5 @@
+import type { TestConfig } from "../../main.test";
+
+export const config: TestConfig = {
+ steps: [{}],
+};
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/.name-cache.json b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/.name-cache.json
new file mode 100644
index 0000000000..db413faf9a
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/.name-cache.json
@@ -0,0 +1,5 @@
+{
+ "vars": {
+ "props": {}
+ }
+}
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr-sanitized.expected.md
new file mode 100644
index 0000000000..ba2aa26adb
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr-sanitized.expected.md
@@ -0,0 +1 @@
+# Render
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr.expected.md
new file mode 100644
index 0000000000..71efbf4060
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/csr.expected.md
@@ -0,0 +1,11 @@
+# Render
+```html
+
+```
+
+# Mutations
+```
+INSERT script
+```
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.hydrate.js b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.hydrate.js
new file mode 100644
index 0000000000..3eb9cd79d3
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.hydrate.js
@@ -0,0 +1 @@
+// size: 0
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.js b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.js
new file mode 100644
index 0000000000..90a9a02e3d
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/dom.expected/template.js
@@ -0,0 +1,9 @@
+export const $template = "";
+export const $walks = /* get, over(1) */" b";
+import * as _ from "@marko/runtime-tags/debug/dom";
+const $injection = /* @__PURE__ */_._let("injection/1", $scope => _._text_content($scope["#script/0"], `var x = '${_._to_text($scope.injection)}'`));
+export function $setup($scope) {
+ _._attr_nonce($scope, "#script/0");
+ $injection($scope, "");
+}
+export default /* @__PURE__ */_._template("__tests__/template.marko", $template, $walks, $setup);
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/html.expected/template.js b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/html.expected/template.js
new file mode 100644
index 0000000000..b29927ad38
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/html.expected/template.js
@@ -0,0 +1,8 @@
+import * as _ from "@marko/runtime-tags/debug/html";
+export default _._template("__tests__/template.marko", input => {
+ _._scope_reason();
+ const $scope0_id = _._scope_id();
+ let injection = "";
+ _._html(``);
+ _._resume_branch($scope0_id);
+}, 1);
\ No newline at end of file
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume-sanitized.expected.md
new file mode 100644
index 0000000000..ba2aa26adb
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume-sanitized.expected.md
@@ -0,0 +1 @@
+# Render
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume.expected.md
new file mode 100644
index 0000000000..02ab76f066
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/resume.expected.md
@@ -0,0 +1,11 @@
+# Render
+```html
+
+
+
+
+
+
+```
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr-sanitized.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr-sanitized.expected.md
new file mode 100644
index 0000000000..ef85d03440
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr-sanitized.expected.md
@@ -0,0 +1 @@
+# Render End
diff --git a/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr.expected.md
new file mode 100644
index 0000000000..1e305281e0
--- /dev/null
+++ b/packages/runtime-tags/src/__tests__/fixtures/html-script-injection/__snapshots__/ssr.expected.md
@@ -0,0 +1,25 @@
+# Write
+```html
+
+```
+
+# Render End
+```html
+
+
+
+
+