From b87019a90f40d3bd95563e5850fec8da5fdabd02 Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 17 Feb 2016 10:02:43 -0700 Subject: [PATCH] Fixes #230 - Marko v3: Special case class attribute to allow object or array expression --- compiler/ast/HtmlAttribute.js | 21 +++--- runtime/helpers.js | 70 ++++++++++++++----- .../autotest/class-attr-array/expected.html | 1 + .../autotest/class-attr-array/template.marko | 1 + .../render/autotest/class-attr-array/test.js | 1 + .../autotest/class-attr-object/expected.html | 1 + .../autotest/class-attr-object/template.marko | 1 + .../render/autotest/class-attr-object/test.js | 1 + .../autotest/class-attr-string/expected.html | 1 + .../autotest/class-attr-string/template.marko | 1 + .../render/autotest/class-attr-string/test.js | 1 + .../style-attr-object-escape/expected.html | 1 - .../style-attr-object-escape/template.marko | 1 - .../autotest/style-attr-object-escape/test.js | 5 -- .../style-attr-object-no-escape/expected.html | 1 - .../template.marko | 1 - .../style-attr-object-no-escape/test.js | 5 -- 17 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 test/fixtures/render/autotest/class-attr-array/expected.html create mode 100644 test/fixtures/render/autotest/class-attr-array/template.marko create mode 100644 test/fixtures/render/autotest/class-attr-array/test.js create mode 100644 test/fixtures/render/autotest/class-attr-object/expected.html create mode 100644 test/fixtures/render/autotest/class-attr-object/template.marko create mode 100644 test/fixtures/render/autotest/class-attr-object/test.js create mode 100644 test/fixtures/render/autotest/class-attr-string/expected.html create mode 100644 test/fixtures/render/autotest/class-attr-string/template.marko create mode 100644 test/fixtures/render/autotest/class-attr-string/test.js delete mode 100644 test/fixtures/render/autotest/style-attr-object-escape/expected.html delete mode 100644 test/fixtures/render/autotest/style-attr-object-escape/template.marko delete mode 100644 test/fixtures/render/autotest/style-attr-object-escape/test.js delete mode 100644 test/fixtures/render/autotest/style-attr-object-no-escape/expected.html delete mode 100644 test/fixtures/render/autotest/style-attr-object-no-escape/template.marko delete mode 100644 test/fixtures/render/autotest/style-attr-object-no-escape/test.js diff --git a/compiler/ast/HtmlAttribute.js b/compiler/ast/HtmlAttribute.js index 4851199fe..67a8593f3 100644 --- a/compiler/ast/HtmlAttribute.js +++ b/compiler/ast/HtmlAttribute.js @@ -79,21 +79,16 @@ function generateCodeForExpressionAttr(name, value, escape, codegen) { } codegen.addWriteLiteral('"'); } else { - if (name === 'style') { + if (name === 'class') { // let builder = codegen.builder; // let valueWithEscaping = handleEscaping(value); - let styleAttr = codegen.addStaticVar('styleAttr', '__helpers.sa'); - - if (escape === false || isNoEscapeXml(value)) { - escape = false; - } - - let styleAttrArgs = [value]; - - if (escape === false) { - styleAttrArgs.push(codegen.builder.literal(false)); - } - codegen.addWrite(codegen.builder.functionCall(styleAttr, styleAttrArgs)); + let classAttrVar = codegen.addStaticVar('classAttr', '__helpers.ca'); + codegen.addWrite(codegen.builder.functionCall(classAttrVar, [value])); + } else if (name === 'style') { + // let builder = codegen.builder; + // let valueWithEscaping = handleEscaping(value); + let styleAttrVar = codegen.addStaticVar('styleAttr', '__helpers.sa'); + codegen.addWrite(codegen.builder.functionCall(styleAttrVar, [value])); } else { // let builder = codegen.builder; // let valueWithEscaping = handleEscaping(value); diff --git a/runtime/helpers.js b/runtime/helpers.js index ce9141e3c..672000c12 100644 --- a/runtime/helpers.js +++ b/runtime/helpers.js @@ -21,7 +21,8 @@ var runtime = require('./'); // Circular dependency, but that is okay var attr = require('raptor-util/attr'); var attrs = require('raptor-util/attrs'); var isArray = Array.isArray; -var STYLE = 'style'; +var STYLE_ATTR = 'style'; +var CLASS_ATTR = 'class'; function notEmpty(o) { if (o == null) { @@ -35,6 +36,17 @@ function notEmpty(o) { return true; } +function classListArray(classList) { + var classNames = []; + for (var i=0, len=classList.length; i ' style="color: red; font-weight: bold"' * sa({color: 'red', 'font-weight': 'bold'}) ==> ' style="color: red; font-weight: bold"' */ - sa: function(style, escape) { + sa: function(style) { if (!style) { - return; + return ''; } - escape = escape !== false; - if (typeof style === 'string') { - return attr(STYLE, style, escape); + return attr(STYLE_ATTR, style, false); } else if (typeof style === 'object') { var parts = []; for (var name in style) { if (style.hasOwnProperty(name)) { var value = style[name]; if (value) { - parts.push(name + ':' + (escape ? escapeXmlAttr(value) : value)); + parts.push(name + ':' + value); } } } - return parts ? attr(STYLE, parts.join(';'), false) : ''; + return parts ? attr(STYLE_ATTR, parts.join(';'), false) : ''; } else { return ''; } }, + + /** + * Internal helper method to handle the "class" attribute. The value can either + * be a string, an array or an object. For example: + * + * ca('foo bar') ==> ' class="foo bar"' + * ca({foo: true, bar: false, baz: true}) ==> ' class="foo baz"' + * ca(['foo', 'bar']) ==> ' class="foo bar"' + */ + ca: function(classNames) { + if (!classNames) { + return ''; + } + + if (typeof classNames === 'string') { + return attr(CLASS_ATTR, classNames, false); + } else if (isArray(classNames)) { + return attr(CLASS_ATTR, classListArray(classNames), false); + } else if (typeof classNames === 'object') { + var classList = []; + for (var name in classNames) { + if (classNames.hasOwnProperty(name)) { + var value = classNames[name]; + if (value) { + classList.push(name); + } + } + } + return attr(CLASS_ATTR, classListArray(classList), false); + } else { + return ''; + } + }, + /** * Loads a template */ @@ -307,14 +351,6 @@ module.exports = { * */ cl: function() { - var args = arguments; - var classNames = []; - for (var i=0, len=args.length; i \ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-array/template.marko b/test/fixtures/render/autotest/class-attr-array/template.marko new file mode 100644 index 000000000..03fbe984d --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-array/template.marko @@ -0,0 +1 @@ +div class=['a', null, 'c'] \ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-array/test.js b/test/fixtures/render/autotest/class-attr-array/test.js new file mode 100644 index 000000000..c4013b344 --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-array/test.js @@ -0,0 +1 @@ +exports.templateData = {}; diff --git a/test/fixtures/render/autotest/class-attr-object/expected.html b/test/fixtures/render/autotest/class-attr-object/expected.html new file mode 100644 index 000000000..09486ef26 --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-object/expected.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-object/template.marko b/test/fixtures/render/autotest/class-attr-object/template.marko new file mode 100644 index 000000000..b8fe2ffff --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-object/template.marko @@ -0,0 +1 @@ +div class={a: true, b: false, c: true} \ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-object/test.js b/test/fixtures/render/autotest/class-attr-object/test.js new file mode 100644 index 000000000..c4013b344 --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-object/test.js @@ -0,0 +1 @@ +exports.templateData = {}; diff --git a/test/fixtures/render/autotest/class-attr-string/expected.html b/test/fixtures/render/autotest/class-attr-string/expected.html new file mode 100644 index 000000000..09486ef26 --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-string/expected.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-string/template.marko b/test/fixtures/render/autotest/class-attr-string/template.marko new file mode 100644 index 000000000..f9e15d77d --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-string/template.marko @@ -0,0 +1 @@ +div class='a c' \ No newline at end of file diff --git a/test/fixtures/render/autotest/class-attr-string/test.js b/test/fixtures/render/autotest/class-attr-string/test.js new file mode 100644 index 000000000..c4013b344 --- /dev/null +++ b/test/fixtures/render/autotest/class-attr-string/test.js @@ -0,0 +1 @@ +exports.templateData = {}; diff --git a/test/fixtures/render/autotest/style-attr-object-escape/expected.html b/test/fixtures/render/autotest/style-attr-object-escape/expected.html deleted file mode 100644 index 8d866cf4f..000000000 --- a/test/fixtures/render/autotest/style-attr-object-escape/expected.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/test/fixtures/render/autotest/style-attr-object-escape/template.marko b/test/fixtures/render/autotest/style-attr-object-escape/template.marko deleted file mode 100644 index 2191218ce..000000000 --- a/test/fixtures/render/autotest/style-attr-object-escape/template.marko +++ /dev/null @@ -1 +0,0 @@ -div style=data.style \ No newline at end of file diff --git a/test/fixtures/render/autotest/style-attr-object-escape/test.js b/test/fixtures/render/autotest/style-attr-object-escape/test.js deleted file mode 100644 index 5a2f4c28f..000000000 --- a/test/fixtures/render/autotest/style-attr-object-escape/test.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.templateData = { - style: { - color: '' - } -}; diff --git a/test/fixtures/render/autotest/style-attr-object-no-escape/expected.html b/test/fixtures/render/autotest/style-attr-object-no-escape/expected.html deleted file mode 100644 index 4f2e9396c..000000000 --- a/test/fixtures/render/autotest/style-attr-object-no-escape/expected.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/test/fixtures/render/autotest/style-attr-object-no-escape/template.marko b/test/fixtures/render/autotest/style-attr-object-no-escape/template.marko deleted file mode 100644 index 6a27503c6..000000000 --- a/test/fixtures/render/autotest/style-attr-object-no-escape/template.marko +++ /dev/null @@ -1 +0,0 @@ -div style="$!{data.style}" \ No newline at end of file diff --git a/test/fixtures/render/autotest/style-attr-object-no-escape/test.js b/test/fixtures/render/autotest/style-attr-object-no-escape/test.js deleted file mode 100644 index 5a2f4c28f..000000000 --- a/test/fixtures/render/autotest/style-attr-object-no-escape/test.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.templateData = { - style: { - color: '' - } -};