Keeps undefined from showing in template

Removes attributes which have a value of undefined.

```html
<div id="undefined"></div>
<!-- is now -->
<div></div>
```

```html
<h1>Hello undefined!</h1>
<!-- is now -->
<h1>Hello !</h1>
```

This may be considered backwards incompatable and may need to wait until Svelte 3. If existing apps rely on e.g. querySelector('[id="undefined"]') then this could require changes.
pull/1803/head
Jacob Wright 7 years ago
parent 4890d4dc02
commit dd7bc6a988

@ -181,12 +181,13 @@ export default class Attribute extends Node {
let updater;
const init = shouldCache ? `${last} = ${value}` : value;
const updaterValue = shouldCache ? last : value;
if (isLegacyInputType) {
block.builders.hydrate.addLine(
`@setInputType(${node.var}, ${init});`
);
updater = `@setInputType(${node.var}, ${shouldCache ? last : value});`;
updater = `@setInputType(${node.var}, ${updaterValue});`;
} else if (isSelectValueAttribute) {
// annoying special case
const isMultipleSelect = node.getStaticAttributeValue('multiple');
@ -216,19 +217,19 @@ export default class Attribute extends Node {
`);
} else if (propertyName) {
block.builders.hydrate.addLine(
`${node.var}.${propertyName} = ${init};`
`@setProperty(${node.var}, "${propertyName}", "${name}", ${init});`
);
updater = `${node.var}.${propertyName} = ${shouldCache ? last : value};`;
updater = `@setProperty(${node.var}, "${propertyName}", "${name}", ${updaterValue});`;
} else if (isDataSet) {
block.builders.hydrate.addLine(
`${node.var}.dataset.${camelCaseName} = ${init};`
`@setDataSet(${node.var}, "${camelCaseName}", "${name}", ${init});`
);
updater = `${node.var}.dataset.${camelCaseName} = ${shouldCache ? last : value};`;
updater = `@setDataSet(${node.var}, "${camelCaseName}", "${name}", ${updaterValue});`;
} else {
block.builders.hydrate.addLine(
`${method}(${node.var}, "${name}", ${init});`
);
updater = `${method}(${node.var}, "${name}", ${shouldCache ? last : value});`;
updater = `${method}(${node.var}, "${name}", ${updaterValue});`;
}
if (this.dependencies.size || isSelectValueAttribute) {

@ -970,13 +970,15 @@ export default class Element extends Node {
textareaContents = attribute.stringifyForSsr();
} else if (attribute.isTrue) {
openingTag += ` ${attribute.name}`;
} else if (
booleanAttributes.has(attribute.name) &&
attribute.chunks.length === 1 &&
attribute.chunks[0].type !== 'Text'
) {
} else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
if (booleanAttributes.has(attribute.name)) {
// a boolean attribute with one non-Text chunk
openingTag += '${' + attribute.chunks[0].snippet + ' ? " ' + attribute.name + '" : "" }';
} else {
openingTag += '${ (' + attribute.chunks[0].snippet + ') !== undefined ? ` ' +
` ${attribute.name}="${attribute.stringifyForSsr()}"` +
'` : "" }';
}
} else {
openingTag += ` ${attribute.name}="${attribute.stringifyForSsr()}"`;
}

@ -66,7 +66,7 @@ export function createSvgElement(name) {
}
export function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
export function createComment() {
@ -82,7 +82,11 @@ export function removeListener(node, event, handler) {
}
export function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
export function setAttributes(node, attributes) {
@ -110,6 +114,22 @@ export function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
export function setProperty(node, prop, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node[prop] = value;
}
}
export function setDataSet(node, prop, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.dataset[prop] = value;
}
}
export function setXlinkAttribute(node, attribute, value) {
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
}
@ -166,7 +186,7 @@ export function claimText (nodes, data) {
}
export function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
export function setInputType(input, type) {

@ -32,7 +32,7 @@ export const escaped = {
};
export function escape(html) {
return String(html).replace(/["'&<>]/g, match => escaped[match]);
return html === undefined ? '' : String(html).replace(/["'&<>]/g, match => escaped[match]);
}
export function each(items, assign, fn) {

@ -64,7 +64,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function addLoc(element, file, line, column, char) {

@ -69,7 +69,7 @@ var Main = (function(answer) { "use strict";
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function insert(target, node, anchor) {
@ -81,7 +81,7 @@ var Main = (function(answer) { "use strict";
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function detachNode(node) {

@ -64,7 +64,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function insert(target, node, anchor) {
@ -76,7 +76,7 @@ function append(target, node) {
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function detachNode(node) {

@ -22,11 +22,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -28,11 +28,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -34,11 +34,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -34,11 +34,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -28,7 +28,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function createComment() {
@ -36,7 +36,7 @@ function createComment() {
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -28,11 +28,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -18,7 +18,19 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function setDataSet(node, prop, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.dataset[prop] = value;
}
}
function blankObject() {
@ -156,7 +168,7 @@ function create_main_fragment(component, ctx) {
text = createText("\n");
div_1 = createElement("div");
div.dataset.foo = "bar";
div_1.dataset.foo = ctx.bar;
setDataSet(div_1, "foo", "data-foo", ctx.bar);
},
m(target, anchor) {
@ -167,7 +179,7 @@ function create_main_fragment(component, ctx) {
p(changed, ctx) {
if (changed.bar) {
div_1.dataset.foo = ctx.bar;
setDataSet(div_1, "foo", "data-foo", ctx.bar);
}
},

@ -1,5 +1,5 @@
/* generated by Svelte vX.Y.Z */
import { assign, createElement, createText, detachNode, init, insert, proto } from "svelte/shared.js";
import { assign, createElement, createText, detachNode, init, insert, proto, setDataSet } from "svelte/shared.js";
function create_main_fragment(component, ctx) {
var div, text, div_1;
@ -10,7 +10,7 @@ function create_main_fragment(component, ctx) {
text = createText("\n");
div_1 = createElement("div");
div.dataset.foo = "bar";
div_1.dataset.foo = ctx.bar;
setDataSet(div_1, "foo", "data-foo", ctx.bar);
},
m(target, anchor) {
@ -21,7 +21,7 @@ function create_main_fragment(component, ctx) {
p(changed, ctx) {
if (changed.bar) {
div_1.dataset.foo = ctx.bar;
setDataSet(div_1, "foo", "data-foo", ctx.bar);
}
},

@ -18,11 +18,19 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function blankObject() {

@ -22,7 +22,15 @@ function createSvgElement(name) {
}
function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function blankObject() {

@ -34,11 +34,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -22,7 +22,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function createComment() {
@ -30,7 +30,7 @@ function createComment() {
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function linear(t) {

@ -22,7 +22,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function createComment() {
@ -30,7 +30,7 @@ function createComment() {
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function destroyBlock(block, lookup) {

@ -18,7 +18,19 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function setProperty(node, prop, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node[prop] = value;
}
}
function blankObject() {
@ -155,8 +167,8 @@ function create_main_fragment(component, ctx) {
div = createElement("div");
text = createText("\n");
div_1 = createElement("div");
div.style.cssText = ctx.style;
div_1.style.cssText = div_1_style_value = "" + ctx.key + ": " + ctx.value;
setProperty(div, "style.cssText", "style", ctx.style);
setProperty(div_1, "style.cssText", "style", div_1_style_value = "" + ctx.key + ": " + ctx.value);
},
m(target, anchor) {
@ -167,11 +179,11 @@ function create_main_fragment(component, ctx) {
p(changed, ctx) {
if (changed.style) {
div.style.cssText = ctx.style;
setProperty(div, "style.cssText", "style", ctx.style);
}
if ((changed.key || changed.value) && div_1_style_value !== (div_1_style_value = "" + ctx.key + ": " + ctx.value)) {
div_1.style.cssText = div_1_style_value;
setProperty(div_1, "style.cssText", "style", div_1_style_value);
}
},

@ -1,5 +1,5 @@
/* generated by Svelte vX.Y.Z */
import { assign, createElement, createText, detachNode, init, insert, proto } from "svelte/shared.js";
import { assign, createElement, createText, detachNode, init, insert, proto, setProperty } from "svelte/shared.js";
function create_main_fragment(component, ctx) {
var div, text, div_1, div_1_style_value;
@ -9,8 +9,8 @@ function create_main_fragment(component, ctx) {
div = createElement("div");
text = createText("\n");
div_1 = createElement("div");
div.style.cssText = ctx.style;
div_1.style.cssText = div_1_style_value = "" + ctx.key + ": " + ctx.value;
setProperty(div, "style.cssText", "style", ctx.style);
setProperty(div_1, "style.cssText", "style", div_1_style_value = "" + ctx.key + ": " + ctx.value);
},
m(target, anchor) {
@ -21,11 +21,11 @@ function create_main_fragment(component, ctx) {
p(changed, ctx) {
if (changed.style) {
div.style.cssText = ctx.style;
setProperty(div, "style.cssText", "style", ctx.style);
}
if ((changed.key || changed.value) && div_1_style_value !== (div_1_style_value = "" + ctx.key + ": " + ctx.value)) {
div_1.style.cssText = div_1_style_value;
setProperty(div_1, "style.cssText", "style", div_1_style_value);
}
},

@ -26,7 +26,15 @@ function removeListener(node, event, handler) {
}
function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function blankObject() {

@ -26,7 +26,15 @@ function removeListener(node, event, handler) {
}
function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function toNumber(value) {

@ -26,7 +26,15 @@ function removeListener(node, event, handler) {
}
function setAttribute(node, attribute, value) {
if (value === undefined) {
removeAttribute(node, attribute);
} else {
node.setAttribute(attribute, value);
}
}
function removeAttribute(node, attribute) {
node.removeAttribute(attribute);
}
function blankObject() {

@ -16,7 +16,7 @@ function detachNode(node) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function blankObject() {

@ -22,7 +22,7 @@ function createSvgElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function blankObject() {

@ -22,7 +22,7 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function createComment() {

@ -22,11 +22,11 @@ function createElement(name) {
}
function createText(data) {
return document.createTextNode(data);
return document.createTextNode(data === undefined ? '' : data);
}
function setData(text, data) {
text.data = '' + data;
text.data = data === undefined ? '' : '' + data;
}
function blankObject() {

@ -0,0 +1,7 @@
export default {
html: `<textarea></textarea>`,
test (assert, component, target) {
const textarea = target.querySelector('textarea');
assert.ok(textarea.hasAttribute('data-foo') === false);
},
};

@ -0,0 +1 @@
<textarea data-foo="{undefined}"></textarea>

@ -0,0 +1,7 @@
export default {
html: `<textarea></textarea>`,
test (assert, component, target) {
const textarea = target.querySelector('textarea');
assert.ok(textarea.hasAttribute('readonly') === false);
},
};

@ -0,0 +1 @@
<textarea readonly="{undefined}"></textarea>

@ -0,0 +1,7 @@
export default {
html: `<textarea></textarea>`,
test (assert, component, target) {
const textarea = target.querySelector('textarea');
assert.ok(textarea.hasAttribute('foo') === false);
},
};

@ -0,0 +1 @@
<textarea foo="{undefined}"></textarea>

@ -37,7 +37,7 @@ export default {
assert.equal( component.get().count, undefined );
assert.htmlEqual( target.innerHTML, `
<input type='number'>
<p>undefined undefined</p>
<p>undefined </p>
` );
}
};

@ -7,7 +7,7 @@ export default {
html: `
<p>woo!</p>
<p>undefined</p>
<p></p>
`,
test(assert, component, target) {

@ -0,0 +1,11 @@
export default {
html: 'foo is ',
test(assert, component, target) {
component.set({ foo: 42 });
assert.htmlEqual(target.innerHTML, 'foo is 42');
component.set({ foo: undefined });
assert.htmlEqual(target.innerHTML, 'foo is ');
}
};
Loading…
Cancel
Save