diff --git a/packages/marko/src/runtime/html/helpers/_dynamic-attr.js b/packages/marko/src/runtime/html/helpers/_dynamic-attr.js new file mode 100644 index 000000000..87ecbcd74 --- /dev/null +++ b/packages/marko/src/runtime/html/helpers/_dynamic-attr.js @@ -0,0 +1,35 @@ +"use strict"; +var attrHelper = require("./attr"); +var notEmptyAttr = attrHelper.___notEmptyAttr; +var isEmptyAttrValue = attrHelper.___isEmptyAttrValue; +var classHelper = require("./class-attr"); +var styleHelper = require("./style-attr"); + +module.exports = function dynamicAttr(name, value) { + switch (name) { + case "class": + return classHelper(value); + case "style": + return styleHelper(value); + case "renderBody": + return ""; + default: + return isEmptyAttrValue(value) || isInvalidAttrName(name) + ? "" + : notEmptyAttr(name, value); + } +}; + +// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 +// Technically the above includes more invalid characters for attributes. +// In practice however the only character that does not become an attribute name +// is when there is a >. +function isInvalidAttrName(name) { + for (let i = name.length; i--; ) { + if (name[i] === ">") { + return true; + } + } + + return false; +} diff --git a/packages/marko/src/runtime/html/helpers/attr.js b/packages/marko/src/runtime/html/helpers/attr.js index a8c41f49f..47de9cc9e 100644 --- a/packages/marko/src/runtime/html/helpers/attr.js +++ b/packages/marko/src/runtime/html/helpers/attr.js @@ -4,28 +4,39 @@ var escapeQuoteHelpers = require("./escape-quotes"); var escapeDoubleQuotes = escapeQuoteHelpers.___escapeDoubleQuotes; var escapeSingleQuotes = escapeQuoteHelpers.___escapeSingleQuotes; -module.exports = function attr(name, value) { +module.exports = maybeEmptyAttr; + +maybeEmptyAttr.___notEmptyAttr = notEmptyAttr; +maybeEmptyAttr.___isEmptyAttrValue = isEmpty; + +function maybeEmptyAttr(name, value) { + if (isEmpty(value)) { + return ""; + } + + return notEmptyAttr(name, value); +} + +function notEmptyAttr(name, value) { switch (typeof value) { case "string": return " " + name + guessQuotes(value); case "boolean": - return value ? " " + name : ""; + return " " + name; case "number": return " " + name + "=" + value; - case "undefined": - return ""; case "object": - if (value === null) { - return ""; - } - if (value instanceof RegExp) { return " " + name + doubleQuote(value.source); } } return " " + name + guessQuotes(value + ""); -}; +} + +function isEmpty(value) { + return value == null || value === false; +} function doubleQuote(value) { return '="' + escapeDoubleQuotes(value) + '"'; diff --git a/packages/marko/src/runtime/html/helpers/attrs.js b/packages/marko/src/runtime/html/helpers/attrs.js index 654715489..e0a9e8e77 100644 --- a/packages/marko/src/runtime/html/helpers/attrs.js +++ b/packages/marko/src/runtime/html/helpers/attrs.js @@ -1,51 +1,18 @@ "use strict"; -var attrHelper = require("./attr"); -var classAttrHelper = require("./class-attr"); -var styleAttrHelper = require("./style-attr"); +var dynamicAttrHelper = require("./_dynamic-attr"); -// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 -var invalidAttrNameCharacters = /[\s'" a.name.localeCompare(b.name)) + .forEach(attr => { + node.removeAttributeNode(attr); + node.setAttributeNode(attr); + }); } }