diff --git a/compiler/ast/HtmlAttribute/html/generateCode.js b/compiler/ast/HtmlAttribute/html/generateCode.js index e65ea7a44..66a018bd5 100644 --- a/compiler/ast/HtmlAttribute/html/generateCode.js +++ b/compiler/ast/HtmlAttribute/html/generateCode.js @@ -1,7 +1,8 @@ 'use strict'; -var attr = require('../../../../runtime/html/attr'); -var escapeXmlAttr = require('../../../../runtime/html/escapeXml').attr; +var runtimeHtmlHelpers = require('../../../../runtime/html/helpers'); +var attr = runtimeHtmlHelpers.a; +var escapeXmlAttr = runtimeHtmlHelpers.xa; function isStringLiteral(node) { return node.type === 'Literal' && typeof node.value === 'string'; @@ -76,12 +77,11 @@ function generateCodeForExpressionAttr(name, value, escape, codegen) { if (isStringLiteral(part)) { part.value = escapeXmlAttr(part.value); } else if (part.type === 'Literal') { - } else if (isNoEscapeXml(part)) { part = codegen.builder.functionCall(context.helper('str'), [part]); } else { if (escape !== false) { - part = codegen.builder.functionCall(context.helper('escapeXmlAttr'), [part]); + part = builder.functionCall(context.helper('escapeXmlAttr'), [part]); } } addHtml(part); diff --git a/compiler/ast/Text/html/generateCode.js b/compiler/ast/Text/html/generateCode.js index c179f70e3..9feb57a5e 100644 --- a/compiler/ast/Text/html/generateCode.js +++ b/compiler/ast/Text/html/generateCode.js @@ -1,6 +1,6 @@ 'use strict'; -var escapeXml = require('../../../../runtime/html/escapeXml'); +var escapeXml = require('../../../../runtime/html/helpers').x; var Literal = require('../..//Literal'); module.exports = function(node, codegen) { diff --git a/compiler/ast/Text/vdom/TextVDOM.js b/compiler/ast/Text/vdom/TextVDOM.js index 9d63715f0..781fa2945 100644 --- a/compiler/ast/Text/vdom/TextVDOM.js +++ b/compiler/ast/Text/vdom/TextVDOM.js @@ -21,16 +21,6 @@ class TextVDOM extends Node { vdomUtil.registerOptimizer(context); - var args = this.arguments; - - for (var i=0, len=args.length; i 'a b' - * - */ - cl: function() { - return classList(arguments); - }, - - /** - * Loads a template (__helpers.l --> marko_loadTemplate(path)) - */ - l: load, - - i: require('./include') + }; + } else { + return renderer; + } }; + +/** + * Merges object properties + * @param {[type]} object [description] + * @param {[type]} source [description] + * @return {[type]} [description] + */ +exports.m = function mergeHelper(into, source) { + for (var k in source) { + if (source.hasOwnProperty(k) && !into.hasOwnProperty(k)) { + into[k] = source[k]; + } + } + return into; +}; + +/** + * classList(a, b, c, ...) + * Joines a list of class names with spaces. Empty class names are omitted. + * + * classList('a', undefined, 'b') --> 'a b' + * + */ +exports.cl = function classListHelper() { + return classList(arguments); +}; + +/** + * Loads a template (__helpers.l --> marko_loadTemplate(path)) + */ +exports.l = require('./loader'); +exports.i = require('./include'); \ No newline at end of file diff --git a/runtime/html/AsyncStream.js b/runtime/html/AsyncStream.js index 0c89296d4..7a3f58d67 100644 --- a/runtime/html/AsyncStream.js +++ b/runtime/html/AsyncStream.js @@ -2,11 +2,9 @@ var EventEmitter = require('events').EventEmitter; var StringWriter = require('./StringWriter'); var BufferedWriter = require('./BufferedWriter'); -var attr = require('./attr'); -var escapeXml = require('./escapeXml'); var extend = require('raptor-util/extend'); - -var defaultDocument = typeof document != 'undefined' && document; +var documentProvider = require('../document-provider'); +var helpers; var voidWriter = { write:function(){} }; @@ -412,12 +410,10 @@ var proto = AsyncStream.prototype = { return new AsyncStream(this.global); }, - beginElement: function(name, attrs) { + beginElement: function(name, elementAttrs) { var str = '<' + name; - for (var attrName in attrs) { - str += attr(attrName, attrs[attrName]); - } + helpers.as(elementAttrs); str += '>'; @@ -436,7 +432,7 @@ var proto = AsyncStream.prototype = { }, text: function(str) { - this.write(escapeXml(str)); + this.write(helpers.x(str)); }, getNode: function(doc) { @@ -446,7 +442,7 @@ var proto = AsyncStream.prototype = { var html = this.getOutput(); if (!doc) { - doc = this.document || defaultDocument; + doc = documentProvider.document; } if (!node) { @@ -504,4 +500,6 @@ proto.w = proto.write; extend(proto, require('../OutMixins')); -module.exports = AsyncStream; \ No newline at end of file +module.exports = AsyncStream; + +helpers = require('./helpers'); \ No newline at end of file diff --git a/runtime/html/attr.js b/runtime/html/attr.js deleted file mode 100644 index d038d1ce9..000000000 --- a/runtime/html/attr.js +++ /dev/null @@ -1,13 +0,0 @@ -var escapeXmlAttr = require('./escapeXml').attr; - -module.exports = function(name, value, shouldEscape) { - if (typeof value === 'string') { - return ' ' + name + '="' + (shouldEscape !== false ? escapeXmlAttr(value) : value) + '"'; - } else if (value === true) { - return ' ' + name; - } else if (value == null || value === false) { - return ''; - } else { - return ' ' + name + '="' + value.toString() + '"'; - } -}; diff --git a/runtime/html/escapeXml.js b/runtime/html/escapeXml.js deleted file mode 100644 index 8a43dec41..000000000 --- a/runtime/html/escapeXml.js +++ /dev/null @@ -1,35 +0,0 @@ -var elTest = /[&<]/; -var elTestReplace = /[&<]/g; -var attrTest = /[&<\"\n]/; -var attrReplace = /[&<\"\n]/g; -var replacements = { - '<': '<', - '&': '&', - '"': '"', - '\n': ' ' //Preserve new lines so that they don't get normalized as space -}; - -function replaceChar(match) { - return replacements[match]; -} - -function escapeXml(str) { - // check for most common case first - if (typeof str === 'string') { - return elTest.test(str) ? str.replace(elTestReplace, replaceChar) : str; - } - - return (str == null) ? '' : str.toString(); -} - -function escapeXmlAttr(str) { - if (typeof str === 'string') { - return attrTest.test(str) ? str.replace(attrReplace, replaceChar) : str; - } - - return (str == null) ? '' : str.toString(); -} - - -module.exports = escapeXml; -escapeXml.attr = escapeXmlAttr; \ No newline at end of file diff --git a/runtime/html/helpers.js b/runtime/html/helpers.js index 6a920a618..4443bc139 100644 --- a/runtime/html/helpers.js +++ b/runtime/html/helpers.js @@ -1,120 +1,193 @@ 'use strict'; -var escapeXml = require('./escapeXml'); -var escapeXmlAttr = escapeXml.attr; -var attr = require('./attr'); +require('raptor-polyfill/string/startsWith'); + +var warp10 = require('warp10'); var extend = require('raptor-util/extend'); var STYLE_ATTR = 'style'; var CLASS_ATTR = 'class'; var escapeEndingScriptTagRegExp = /<\//g; -var commonHelpers = require('../helpers'); +var elTest = /[&<]/; +var elTestReplace = /[&<]/g; +var attrTest = /[&<\"\n]/; +var attrReplace = /[&<\"\n]/g; +var stringifiedAttrTest = /[&\'\n]/; +var stringifiedAttrReplace = /[&\'\n]/g; -var classList = commonHelpers.cl; +var classList; -module.exports = extend({ - /** - * Internal method to escape special XML characters - * @private - */ - x: escapeXml, - /** - * Internal method to escape special XML characters within an attribute - * @private - */ - xa: escapeXmlAttr, +var replacements = { + '<': '<', + '&': '&', + '"': '"', + '\'': ''', + '\n': ' ' //Preserve new lines so that they don't get normalized as space +}; - /** - * Escapes the ' body to avoid the `' - * }; - * - * - * - * Without escaping the ending '' sequence the opening ' + * }; + * + * + * + * Without escaping the ending '' sequence the opening