Merge pull request #1165 from sveltejs/sigil-component-attribute-ssr

SSR: more sigil and template string escaping fixes
pull/1167/head
Rich Harris 7 years ago committed by GitHub
commit 41a2592708
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,7 +6,7 @@ import { AppendTarget } from '../interfaces';
import { Node } from '../../../interfaces'; import { Node } from '../../../interfaces';
import getObject from '../../../utils/getObject'; import getObject from '../../../utils/getObject';
import getTailSnippet from '../../../utils/getTailSnippet'; import getTailSnippet from '../../../utils/getTailSnippet';
import { stringify } from '../../../utils/stringify'; import { escape, escapeTemplate, stringify } from '../../../utils/stringify';
export default function visitComponent( export default function visitComponent(
generator: SsrGenerator, generator: SsrGenerator,
@ -14,7 +14,9 @@ export default function visitComponent(
node: Node node: Node
) { ) {
function stringifyAttribute(chunk: Node) { function stringifyAttribute(chunk: Node) {
if (chunk.type === 'Text') return chunk.data; if (chunk.type === 'Text') {
return escapeTemplate(escape(chunk.data));
}
if (chunk.type === 'MustacheTag') { if (chunk.type === 'MustacheTag') {
block.contextualise(chunk.expression); block.contextualise(chunk.expression);
const { snippet } = chunk.metadata; const { snippet } = chunk.metadata;

@ -1,6 +1,6 @@
import { SsrGenerator } from '../index'; import { SsrGenerator } from '../index';
import Block from '../Block'; import Block from '../Block';
import { escape, escapeHTML } from '../../../utils/stringify'; import { escape, escapeHTML, escapeTemplate } from '../../../utils/stringify';
import { Node } from '../../../interfaces'; import { Node } from '../../../interfaces';
export default function visitText( export default function visitText(
@ -8,7 +8,7 @@ export default function visitText(
block: Block, block: Block,
node: Node node: Node
) { ) {
let text = escape(node.data).replace(/(\${|`|\\)/g, '\\$1'); let text = node.data;
if ( if (
!node.parent || !node.parent ||
node.parent.type !== 'Element' || node.parent.type !== 'Element' ||
@ -17,5 +17,5 @@ export default function visitText(
// unless this Text node is inside a <script> or <style> element, escape &,<,> // unless this Text node is inside a <script> or <style> element, escape &,<,>
text = escapeHTML(text); text = escapeHTML(text);
} }
generator.append(text); generator.append(escape(escapeTemplate(text)));
} }

@ -1,12 +1,12 @@
import Block from '../../Block'; import Block from '../../Block';
import { escape } from '../../../../utils/stringify'; import { escape, escapeTemplate } from '../../../../utils/stringify';
import { Node } from '../../../../interfaces'; import { Node } from '../../../../interfaces';
export default function stringifyAttributeValue(block: Block, chunks: Node[]) { export default function stringifyAttributeValue(block: Block, chunks: Node[]) {
return chunks return chunks
.map((chunk: Node) => { .map((chunk: Node) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return escape(chunk.data).replace(/"/g, '&quot;'); return escapeTemplate(escape(chunk.data).replace(/"/g, '&quot;'));
} }
block.contextualise(chunk.expression); block.contextualise(chunk.expression);

@ -17,3 +17,7 @@ const escaped = {
export function escapeHTML(html) { export function escapeHTML(html) {
return String(html).replace(/[&<>]/g, match => escaped[match]); return String(html).replace(/[&<>]/g, match => escaped[match]);
} }
export function escapeTemplate(str) {
return str.replace(/(\${|`|\\)/g, '\\$1');
}

@ -1,3 +1,3 @@
export default { export default {
html: '<code>`${foo}\\n`</code>' html: '<code>`${foo}\\n`</code>\n<div title="`${foo}\\n`">foo</div>\n<div>`${foo}\\n`</div>',
}; };

@ -1 +1,8 @@
<code>`${foo}\n`</code> <code>`${foo}\n`</code>
<div title="`${foo}\n`">foo</div>
<Widget value="`${foo}\n`"/>
<script>
import Widget from './Widget.html';
export default { components: { Widget } };
</script>

@ -0,0 +1,4 @@
export default {
data: { foo: 'foo' },
html: `<div>foo @ foo # foo</div>`,
};

@ -0,0 +1,6 @@
<Widget value='foo @ {{foo}} # foo'/>
<script>
import Widget from './Widget.html';
export default { components: { Widget } };
</script>
Loading…
Cancel
Save