diff --git a/lib/haml.js b/lib/haml.js index 38a8ca2..a3f179b 100755 --- a/lib/haml.js +++ b/lib/haml.js @@ -15,7 +15,7 @@ var Haml; function render_attribs(attribs) { var key, value, result = []; for (key in attribs) { - if (key !== '_content' && attribs.hasOwnProperty(key)) { + if (key !== '_content' && key != '_splats' && attribs.hasOwnProperty(key)) { switch (attribs[key]) { case 'undefined': case 'false': @@ -44,12 +44,13 @@ var Haml; // Parse the attribute block using a state machine function parse_attribs(line) { - var attributes = {}, + var attributes = { _splats: [] }, l = line.length, i, c, count = 1, quote = false, skip = false, + splat = false, open, close, joiner, seperator, pair = { start: 1, @@ -104,18 +105,26 @@ var Haml; if (c === '"' || c === "'") { quote = c; } + if (c === '*') { + splat = true; + } if (count === 1) { if (c === joiner) { pair.middle = i; } - if (c === seperator || c === close) { + if (!splat && (c === seperator || c === close)) { pair.end = i; process_pair(); if (c === seperator) { pair.start = i + 1; } } + if (splat && (c === seperator || c === close || c === ' ')) { + attributes._splats.push(line.substr(pair.start, i - pair.start).trim().substr(1)); + splat = false; + pair.start = i+1; + } } if (c === open || c === "(") { @@ -178,7 +187,7 @@ var Haml; name: "html tags", regexp: /^(\s*)((?:[.#%][a-z_\-][a-z0-9_:\-]*)+)(.*)$/i, process: function () { - var line_beginning, tag, classes, ids, attribs, content, whitespaceSpecifier, whitespace={}, output; + var line_beginning, tag, classes, ids, attribs, splat_code, content, whitespaceSpecifier, whitespace={}, output; line_beginning = this.matches[2]; classes = line_beginning.match(/\.([a-z_\-][a-z0-9_\-]*)/gi); ids = line_beginning.match(/\#([a-z_\-][a-z0-9_\-]*)/gi); @@ -245,6 +254,17 @@ var Haml; } } + if (attribs._splats && attribs._splats.length) { + var tmp = [], + splats = attribs._splats; + for(i=0;i 0 : self_close_tags.indexOf(tag) == -1) { - output = '"<' + tag + attribs + '>"' + + output = '"<' + tag + attribs + splat_code + '>"' + (content.length > 0 ? ' + \n' + content : "") + ' + \n""'; } else { - output = '"<' + tag + attribs + ' />"'; + output = '"<' + tag + attribs + splat_code + ' />"'; } if(whitespace.around){ @@ -639,11 +659,41 @@ var Haml; return execute(js, options.context || Haml, options.locals); }; + function make_render_splat(escaperName) { + return new Function('attribs', [ + " var key, value, result = [];", + " for (key in attribs) {", + " if (attribs.hasOwnProperty(key)) {", + " switch (attribs[key]) {", + " case undefined:", + " case false:", + " case null:", + " case \"\":", + " break;", + " default:", + " try {", + " value = JSON.parse(\"[\" + attribs[key] +\"]\")[0];", + " if (value === true) {", + " value = key;", + " } else {", + " value = html_escape(value);", + " }", + " result.push(\" \" + key + '=\"' + value + '\"');", + " } catch (e) {", + " result.push(\" \" + key + '=\"' + " + escaperName +"(attribs[key]) + '\"');", + " }", + " }", + " }", + " }", + " return result.join(\"\");"].join('\n')); + } + function execute(js, self, locals) { return (function () { with(locals || {}) { try { var _$output; + var render_splat = make_render_splat((Haml.config && Haml.config.customEscape) ? Haml.config.customEscape : html_escape); eval("_$output =" + js ); return _$output; //set in eval } catch (e) { @@ -682,7 +732,7 @@ var Haml; "}" try{ - var f = new Function("locals", escaper + str ); + var f = new Function("locals", escaper + 'var render_splat = ' + make_render_splat(escaperName).toString() + ";" + str ); return f; }catch(e){ if ( typeof(console) !== 'undefined' ) { console.error(str); } diff --git a/test/splats.haml b/test/splats.haml new file mode 100644 index 0000000..246c2be --- /dev/null +++ b/test/splats.haml @@ -0,0 +1,4 @@ +%div.splat{attrib: true, *splat} + content +%div.multi-splat{ *splat1, attrib: true, durr: 'false', derp: null, *splat2,*splat3 } + content \ No newline at end of file diff --git a/test/splats.html b/test/splats.html new file mode 100644 index 0000000..41dc6ac --- /dev/null +++ b/test/splats.html @@ -0,0 +1 @@ +
content
content
\ No newline at end of file diff --git a/test/splats.js b/test/splats.js new file mode 100644 index 0000000..9a927d0 --- /dev/null +++ b/test/splats.js @@ -0,0 +1,19 @@ +{ + locals: { + splat: { + splata: 'value' + }, + splat1: { + 'some-value': 'value', + 'some-code': '', + }, + splat2: { + 'bad-code': '">', + number: 123, + 'a-null': null, + }, + splat3: { + splata: 'another value' + } + } +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index adcc36f..d3b7d0d 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,6 @@ var fs = require('fs'); var assert = require('assert'); -var sys = require('sys'); +var sys = require('util'); var Haml = require("../lib/haml");