Skip to content

Commit ea074c7

Browse files
committed
fix placeholder corruption
1 parent d3fb8cc commit ea074c7

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

src/vite/observable.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,49 @@ function stripExpressions(template: TemplateLiteral, input: string): string {
163163
const source = new Sourcemap(input);
164164
let index = template.start;
165165
for (const q of template.quasis) {
166-
if (q.start > index) source.delete(index, q.start);
166+
if (q.start > index) {
167+
// In a case such as <img src=${…} style=…>, we must replace the
168+
// placeholder with a non-empty value or it will change the interpre-
169+
// tation of the subsequent attribute to be part of the src attribute!
170+
// But we also don’t want to use a non-empty src attribute because that
171+
// would cause the browser to load an asset that does not exist (before
172+
// it is replaced by the client-generated content).
173+
if (hasPrecedingEquals(input, index)) {
174+
source.replaceLeft(index, q.start, '""');
175+
} else {
176+
source.delete(index, q.start);
177+
}
178+
}
167179
index = q.end;
168180
}
169181
return String(source);
170182
}
171183

184+
/** Returns true if the specified character is preceded by an equals sign, ignoring whitespace. */
185+
function hasPrecedingEquals(input: string, index: number): boolean {
186+
let i = index - 1;
187+
while (isSpaceCode(input.charCodeAt(i))) --i;
188+
return input.charCodeAt(i) === CODE_EQ;
189+
}
190+
191+
const CODE_TAB = 9,
192+
CODE_LF = 10,
193+
CODE_FF = 12,
194+
CODE_CR = 13,
195+
CODE_SPACE = 32,
196+
CODE_EQ = 61;
197+
198+
/** Returns true if the specified character code is considered whitespace by HTML. */
199+
function isSpaceCode(code: number): boolean {
200+
return (
201+
code === CODE_TAB ||
202+
code === CODE_LF ||
203+
code === CODE_FF ||
204+
code === CODE_SPACE ||
205+
code === CODE_CR
206+
);
207+
}
208+
172209
/** Note: only suitable for use in a script element. */
173210
function escapeScript(script: string): string {
174211
return script.replace(/<\/script>/g, "<\\/script>"); // TODO handle other contexts

0 commit comments

Comments
 (0)