Skip to content

Commit 5b9a4ac

Browse files
authored
fix: prevent error with escape sequence in attribute (#2968)
Fixes #2964
1 parent 7cef47d commit 5b9a4ac

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

.changeset/ready-parents-brake.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'svelte2tsx': patch
3+
'svelte-language-server': patch
4+
'svelte-check': patch
5+
---
6+
7+
fix: prevent error with escape sequence in attribute

packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,12 @@ export function handleAttribute(
203203
if (!needsNumberConversion) {
204204
attributeValue.push(quote);
205205
}
206-
if (includesTemplateLiteralQuote && attrVal.data.split('\n').length > 1) {
207-
// Multiline attribute value text which can't be wrapped in a template literal
208-
// -> ensure it's still a valid transformation by transforming the actual line break
209-
str.overwrite(attrVal.start, attrVal.end, attrVal.data.split('\n').join('\\n'), {
210-
contentOnly: true
211-
});
206+
const escapedValue = tryEscapeAttributeValue(
207+
attrVal.data,
208+
!includesTemplateLiteralQuote
209+
);
210+
if (escapedValue !== null) {
211+
str.overwrite(attrVal.start, attrVal.end, escapedValue, { contentOnly: true });
212212
}
213213
attributeValue.push([attrVal.start, attrVal.end]);
214214
if (!needsNumberConversion) {
@@ -248,3 +248,14 @@ export function handleAttribute(
248248
function attributeValueIsOfType(value: true | BaseNode[], type: string): value is [BaseNode] {
249249
return value !== true && value.length == 1 && value[0].type == type;
250250
}
251+
252+
function tryEscapeAttributeValue(str: string, useTemplateLiteral: boolean): string | null {
253+
// Multiline attribute value text which can't be wrapped in a template literal
254+
// -> ensure it's still a valid transformation by transforming the actual line break
255+
// \ is not a valid escape in HTML, but it could be part of the attribute value and would break the generated code
256+
if (!str.includes('\\') && (useTemplateLiteral || !str.includes('\n'))) {
257+
return null;
258+
}
259+
260+
return JSON.stringify(str).slice(1, -1);
261+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{ svelteHTML.createElement("div", { "class":`a\\00a0`,}); }
2+
{ svelteHTML.createElement("div", { "class":`a\\xz`,}); }
3+
{ svelteHTML.createElement("div", { "class":`a\\uz`,}); }
4+
{ svelteHTML.createElement("div", { "class":`a\\`,}); }
5+
6+
{ svelteHTML.createElement("div", { "class":`\\x0000`,}); }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div class="a\00a0"></div>
2+
<div class="a\xz"></div>
3+
<div class="a\uz"></div>
4+
<div class="a\"></div>
5+
6+
<div class="\x0000"></div>

0 commit comments

Comments
 (0)