Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/ready-parents-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'svelte2tsx': patch
'svelte-language-server': patch
'svelte-check': patch
---

fix: prevent error with escape sequence in attribute
23 changes: 17 additions & 6 deletions packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,12 @@ export function handleAttribute(
if (!needsNumberConversion) {
attributeValue.push(quote);
}
if (includesTemplateLiteralQuote && attrVal.data.split('\n').length > 1) {
// Multiline attribute value text which can't be wrapped in a template literal
// -> ensure it's still a valid transformation by transforming the actual line break
str.overwrite(attrVal.start, attrVal.end, attrVal.data.split('\n').join('\\n'), {
contentOnly: true
});
const escapedValue = tryEscapeAttributeValue(
attrVal.data,
!includesTemplateLiteralQuote
);
if (escapedValue !== null) {
str.overwrite(attrVal.start, attrVal.end, escapedValue, { contentOnly: true });
}
attributeValue.push([attrVal.start, attrVal.end]);
if (!needsNumberConversion) {
Expand Down Expand Up @@ -248,3 +248,14 @@ export function handleAttribute(
function attributeValueIsOfType(value: true | BaseNode[], type: string): value is [BaseNode] {
return value !== true && value.length == 1 && value[0].type == type;
}

function tryEscapeAttributeValue(str: string, useTemplateLiteral: boolean): string | null {
// Multiline attribute value text which can't be wrapped in a template literal
// -> ensure it's still a valid transformation by transforming the actual line break
// \ is not a valid escape in HTML, but it could be part of the attribute value and would break the generated code
if (!str.includes('\\') && (useTemplateLiteral || !str.includes('\n'))) {
return null;
}

return JSON.stringify(str).slice(1, -1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ svelteHTML.createElement("div", { "class":`a\\00a0`,}); }
{ svelteHTML.createElement("div", { "class":`a\\xz`,}); }
{ svelteHTML.createElement("div", { "class":`a\\uz`,}); }
{ svelteHTML.createElement("div", { "class":`a\\`,}); }

{ svelteHTML.createElement("div", { "class":`\\x0000`,}); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="a\00a0"></div>
<div class="a\xz"></div>
<div class="a\uz"></div>
<div class="a\"></div>

<div class="\x0000"></div>