dont render undefined/null attributes in SSR

pull/1815/head
Rich Harris 6 years ago
parent 8642ef17a4
commit b5945e13ea

@ -1,4 +1,4 @@
import { escape, escapeTemplate, stringify } from '../../utils/stringify';
import { stringify } from '../../utils/stringify';
import addToSet from '../../utils/addToSet';
import Component from '../Component';
import Node from './shared/Node';
@ -16,6 +16,7 @@ export default class Attribute extends Node {
name: string;
isSpread: boolean;
isTrue: boolean;
isConcatenated: boolean;
isDynamic: boolean;
isSynthetic: boolean;
shouldCache: boolean;
@ -38,6 +39,7 @@ export default class Attribute extends Node {
this.isDynamic = true; // TODO not necessarily
this.shouldCache = false; // TODO does this mean anything here?
this.isConcatenated = false;
}
else {
@ -65,6 +67,8 @@ export default class Attribute extends Node {
? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name)
: true
: false;
this.isConcatenated = this.chunks.length > 1;
}
}
@ -99,16 +103,4 @@ export default class Attribute extends Node {
? this.chunks[0].data
: '';
}
stringifyForSsr() {
return this.chunks
.map((chunk: Node) => {
if (chunk.type === 'Text') {
return escapeTemplate(escape(chunk.data).replace(/"/g, '"'));
}
return '${@escape(' + chunk.snippet + ')}';
})
.join('');
}
}

@ -1,5 +1,8 @@
import { quotePropIfNecessary, quoteNameIfNecessary } from '../../../utils/quoteIfNecessary';
import isVoidElementName from '../../../utils/isVoidElementName';
import Attribute from '../../nodes/Attribute';
import Node from '../../nodes/shared/Node';
import { escapeTemplate } from '../../../utils/stringify';
// source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7
const boolean_attributes = new Set([
@ -71,7 +74,7 @@ export default function(node, renderer, options) {
args.push(attribute.expression.snippet);
} else {
if (attribute.name === 'value' && node.name === 'textarea') {
textareaContents = attribute.stringifyForSsr();
textareaContents = stringifyAttribute(attribute);
} else if (attribute.isTrue) {
args.push(`{ ${quoteNameIfNecessary(attribute.name)}: true }`);
} else if (
@ -82,18 +85,18 @@ export default function(node, renderer, options) {
// a boolean attribute with one non-Text chunk
args.push(`{ ${quoteNameIfNecessary(attribute.name)}: ${attribute.chunks[0].snippet} }`);
} else {
args.push(`{ ${quoteNameIfNecessary(attribute.name)}: \`${attribute.stringifyForSsr()}\` }`);
args.push(`{ ${quoteNameIfNecessary(attribute.name)}: \`${stringifyAttribute(attribute)}\` }`);
}
}
});
openingTag += "${@spread([" + args.join(', ') + "])}";
} else {
node.attributes.forEach((attribute: Node) => {
node.attributes.forEach((attribute: Attribute) => {
if (attribute.type !== 'Attribute') return;
if (attribute.name === 'value' && node.name === 'textarea') {
textareaContents = attribute.stringifyForSsr();
textareaContents = stringifyAttribute(attribute);
} else if (attribute.isTrue) {
openingTag += ` ${attribute.name}`;
} else if (
@ -105,9 +108,14 @@ export default function(node, renderer, options) {
openingTag += '${' + attribute.chunks[0].snippet + ' ? " ' + attribute.name + '" : "" }';
} else if (attribute.name === 'class' && classExpr) {
addClassAttribute = false;
openingTag += ` class="\${[\`${attribute.stringifyForSsr()}\`, ${classExpr}].join(' ').trim() }"`;
openingTag += ` class="\${[\`${stringifyAttribute(attribute)}\`, ${classExpr}].join(' ').trim() }"`;
} else if (attribute.isConcatenated || !attribute.isDynamic) {
openingTag += ` ${attribute.name}="${stringifyAttribute(attribute)}"`;
} else {
openingTag += ` ${attribute.name}="${attribute.stringifyForSsr()}"`;
const { name } = attribute;
const { snippet } = attribute.chunks[0];
openingTag += '${(v => v == null ? "" : ` ' + name + '=${' + snippet + '}`)(' + snippet + ')}';
}
});
}
@ -129,4 +137,16 @@ export default function(node, renderer, options) {
if (!isVoidElementName(node.name)) {
renderer.append(`</${node.name}>`);
}
}
function stringifyAttribute(attribute: Attribute) {
return attribute.chunks
.map((chunk: Node) => {
if (chunk.type === 'Text') {
return escapeTemplate(escape(chunk.data).replace(/"/g, '&quot;'));
}
return '${@escape(' + chunk.snippet + ')}';
})
.join('');
}

@ -82,7 +82,7 @@ export function removeListener(node, event, handler) {
}
export function setAttribute(node, attribute, value) {
if (value == null) removeAttribute(node, attribute);
if (value == null) node.removeAttribute(attribute);
else node.setAttribute(attribute, value);
}
@ -104,14 +104,10 @@ export function setCustomElementData(node, prop, value) {
} else if (value) {
setAttribute(node, prop, value);
} else {
removeAttribute(node, prop);
node.removeAttribute(prop);
}
}
export function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
export function setXlinkAttribute(node, attribute, value) {
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
}

@ -1,5 +1,5 @@
export default {
'skip-ssr': true,
html: '<div></div>',
html: '<div></div>'
ssrHtml: '<div foo=1></div>'
};

Loading…
Cancel
Save