diff --git a/lib/haml.js b/lib/haml.js index a497912..d5fa3fd 100755 --- a/lib/haml.js +++ b/lib/haml.js @@ -4,6 +4,15 @@ var Haml; var matchers, self_close_tags, embedder, forceXML, escaperName, escapeHtmlByDefault; + if (process && process.platform) { + var NEW_LINE_STR = process.platform.match(/^win/i) ? "\\r\\n" : "\\n"; + var NEW_LINE = process.platform.match(/^win/i) ? "\r\n" : "\n"; + } + else { + var NEW_LINE_STR = "\\n"; + var NEW_LINE = "\n"; + } + function html_escape(text) { return (text + ""). replace(/&/g, "&"). @@ -299,8 +308,8 @@ var Haml; 'var ' + rvar + ' = [], ' + ivar + ', ' + vvar + '; ' + 'for (' + ivar + ' in ' + avar + ') { ' + 'if (' + avar + '.hasOwnProperty(' + ivar + ')) { ' + - vvar + ' = ' + avar + '[' + ivar + ']; ' + - rvar + '.push(\n' + (this.render_contents() || "''") + '\n); ' + + vvar + ' = ' + avar + '[' + ivar + ']; _$output = ' + (this.render_contents() || "''") + ";" + + rvar + '.push(_$output); ' + '} } return ' + rvar + '.join(""); }).call(this)'; } }, @@ -334,7 +343,7 @@ var Haml; process: function () { this.contents.unshift(this.matches[2]); - return '""'; + return '""'; } }, @@ -343,7 +352,54 @@ var Haml; name: "rawjs", regexp: /^(\s*)-\s*(.*)\s*$/i, process: function () { + function removeComments(js) { + var inString = null, + chars = js.length, + i, chr, chrNext, + result = []; + + COMMENT_SEARCH: + for (i = 0; i < chars; i++) { + chr = js.charAt(i); + if (inString) { + // Check if it is the end of a string + if (chr === inString) { + inString = null; + } + } + else { + switch (chr) { + // Check if it is a beginning of a string + case "'": + case '"': + inString = chr; + break; + + // Check a comment + case "/": + if (i < chars - 1) { + chrNext = js.charAt(i + 1); + if (chrNext == "/") { + break COMMENT_SEARCH; + } + } + + break; + } + } + + result.push(chr); + } + + js = result.join(""); + return js; + } + this.contents.unshift(this.matches[2]); + for (var i in this.contents) { + this.contents[i] = removeComments(this.contents[i]); + } + return '"";' + this.contents.join("\n")+"; _$output = _$output "; } }, @@ -403,7 +459,7 @@ var Haml; line = ""; break; } - return JSON.stringify(line + "\n"); + return JSON.stringify(line + NEW_LINE); } }, @@ -421,10 +477,10 @@ var Haml; name: "script", regexp: /^(\s*):(?:java)?script\s*$/, process: function () { - return parse_interpol('\n\n"); + return parse_interpol(NEW_LINE + '" + NEW_LINE); } }, @@ -433,9 +489,9 @@ var Haml; name: "css", regexp: /^(\s*):css\s*$/, process: function () { - return JSON.stringify('"); + return JSON.stringify('"); } } @@ -447,7 +503,7 @@ var Haml; // If lines is a string, turn it into an array if (typeof lines === 'string') { - lines = lines.trim().replace(/\n\r|\r/g, '\n').split('\n'); + lines = lines.trim().replace(/\r\n|\r/g, '\n').split('\n'); } lines.forEach(function(line) { @@ -557,7 +613,7 @@ var Haml; buffer = []; } } - js.replace(/\n\r|\r/g, '\n').split('\n').forEach(function (line) { + js.replace(/\r\n|\r/g, '\n').split('\n').forEach(function (line) { part = line.match(/^(\".*\")(\s*\+\s*)?$/); if (!part) { flush(); @@ -579,6 +635,8 @@ var Haml; function render(text, options) { options = options || {}; + escaperName = options.customEscape || "html_escape" + text = text || ""; var js = compile(text, options); if (options.optimize) { diff --git a/test/js_after_each.haml b/test/js_after_each.haml new file mode 100644 index 0000000..2c1d59a --- /dev/null +++ b/test/js_after_each.haml @@ -0,0 +1,4 @@ +:each question in questions + - var temp = 'hello' + %div&= question + %div&= temp \ No newline at end of file diff --git a/test/js_after_each.html b/test/js_after_each.html new file mode 100644 index 0000000..ee9846a --- /dev/null +++ b/test/js_after_each.html @@ -0,0 +1 @@ +
question 1
hello
question 2
hello
question 3
hello
\ No newline at end of file diff --git a/test/js_after_each.js b/test/js_after_each.js new file mode 100644 index 0000000..6de834a --- /dev/null +++ b/test/js_after_each.js @@ -0,0 +1,5 @@ +{ + locals: { + questions: ["question 1", "question 2", "question 3"] + } +} \ No newline at end of file diff --git a/test/js_eol_comment.haml b/test/js_eol_comment.haml new file mode 100644 index 0000000..e71762b --- /dev/null +++ b/test/js_eol_comment.haml @@ -0,0 +1,31 @@ +:each user in users + - var testComment = "hello " + user // sample eol-comment + %div&= testComment + +:each user in users + - var testComment = 'hello ' + user // sample eol-comment + %div&= testComment + +:each user in users + - var testComment = "hello // ok " + user + %div&= testComment + +:each user in users + - var testComment = "hello // ok " + user // sample eol-comment + %div&= testComment + +:each user in users + - var testComment = 'hello // ok ' + user + %div&= testComment + +:each user in users + - var testComment = 'hello // ok ' + user // sample eol-comment + %div&= testComment + +:each user in users + - var testComment = "hel'lo " + user // sample eol-comment + %div&= testComment + +:each user in users + - var testComment = 'hel"lo ' + user // sample eol-comment + %div&= testComment \ No newline at end of file diff --git a/test/js_eol_comment.html b/test/js_eol_comment.html new file mode 100644 index 0000000..79f9ad2 --- /dev/null +++ b/test/js_eol_comment.html @@ -0,0 +1 @@ +
hello Alex
hello Alex
hello // ok Alex
hello // ok Alex
hello // ok Alex
hello // ok Alex
hel'lo Alex
hel"lo Alex
\ No newline at end of file diff --git a/test/js_eol_comment.js b/test/js_eol_comment.js new file mode 100644 index 0000000..2d3068f --- /dev/null +++ b/test/js_eol_comment.js @@ -0,0 +1,5 @@ +{ + locals: { + users: ["Alex"] + } +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index adcc36f..55f39ab 100644 --- a/test/test.js +++ b/test/test.js @@ -1,49 +1,59 @@ var fs = require('fs'); var assert = require('assert'); -var sys = require('sys'); +var util = require('util'); var Haml = require("../lib/haml"); - - function compare(haml_file, haml, expected, scope, options){ options || (options = {}); try { - sys.puts(haml_file + " Begun") + util.puts(haml_file + " Begun") var js = Haml.compile(haml); var js_opt = Haml.optimize(js); var jsFn = Haml(haml, options); var actual = jsFn.call(scope.context, scope.locals); assert.equal(actual, expected); - sys.puts(haml_file + " Passed") + util.puts(haml_file + " Passed") actual = Haml.render(haml, {context:scope.context, locals:scope.locals}) assert.equal(actual, expected); - sys.puts(haml_file + " Haml.render Passed") + util.puts(haml_file + " Haml.render Passed") } catch (e) { var message = e.name; if (e.message) { message += ": " + e.message; } - sys.error(haml_file + " FAILED") - sys.error(message); - sys.error("\nJS:\n\n" + js); - sys.error("\nOptimized JS:\n\n" + js_opt); - sys.error("\nJS fn:\n\n"+jsFn.toString()); - sys.error("\nStack:\n\n"+e.stack); + util.error(haml_file + " FAILED") + util.error(message); + util.error("\nJS:\n\n" + js); + util.error("\nOptimized JS:\n\n" + js_opt); + util.error("\nJS fn:\n\n"+jsFn.toString()); + util.error("\nStack:\n\n"+e.stack); try{ - sys.error("\nActual["+actual.length+"]:\n\n" + actual); - sys.error("\nExpected["+expected.length+"]:\n\n" + expected); + util.error("\nActual["+actual.length+"]:\n\n" + actual); + util.error("\nExpected["+expected.length+"]:\n\n" + expected); }catch(e2){} process.exit(); } } +// Load command line arguments to run a specific test +var test_param = []; + +if (process.argv.length > 2) { + for (var i = 2; i < process.argv.length; ++i) { + test_param.push(process.argv[i].toLowerCase()); + } +} fs.readdir('.', function (err, files) { files.forEach(function (haml_file) { + if (test_param.length != 0 && test_param.indexOf(haml_file.toLowerCase()) === -1) { + return; + } + var m = haml_file.match(/^(.*)\.haml/), base; if (!m) { @@ -71,25 +81,35 @@ fs.readdir('.', function (err, files) { }); (function(){ - var hamlSrc = fs.readFileSync("alt_attribs.haml", "utf8"); + var haml_file = "alt_attribs.haml"; + + if (test_param.length != 0 && test_param.indexOf(haml_file) === -1) { + return; + } + + var hamlSrc = fs.readFileSync(haml_file, "utf8"); var includeEscape = Haml(hamlSrc).toString(); var customEscape = Haml(hamlSrc, {customEscape:"$esc"}).toString(); try{ assert.ok(customEscape.length < includeEscape.length); }catch(e){ - sys.error(e.stack); - sys.error(customEscape); + util.error(e.stack); + util.error(customEscape); process.exit(); } })(); (function(){ + if (test_param.length != 0 && test_param.indexOf("custom_escape.haml") === -1) { + return; + } + var hamlSrc = fs.readFileSync("./other/custom_escape.haml", "utf8"); var expected = fs.readFileSync("./other/custom_escape.html", "utf8"); var scope = eval("(" + fs.readFileSync("escaping.js") + ")"); - sys.puts("custom_escape" + " Begun") + util.puts("custom_escape" + " Begun") var jsFn = Haml(hamlSrc, {customEscape:"$esc"}); this.$esc = function(){ @@ -100,21 +120,25 @@ fs.readdir('.', function (err, files) { try{ assert.equal(actual, expected); }catch(e){ - sys.error("\nActual["+actual.length+"]:\n\n" + actual); - sys.error("\nExpected["+expected.length+"]:\n\n" + expected); + util.error("\nActual["+actual.length+"]:\n\n" + actual); + util.error("\nExpected["+expected.length+"]:\n\n" + expected); process.exit(); } - sys.puts("custom_escape" + " Passed") + util.puts("custom_escape" + " Passed") })(); (function(){ + if (test_param.length != 0 && test_param.indexOf("escape_by_default.haml") === -1) { + return; + } + var hamlSrc = fs.readFileSync("./other/escape_by_default.haml", "utf8"); var expected = fs.readFileSync("./other/escape_by_default.html", "utf8"); var scope = {}; - sys.puts("escape_by_default" + " Begun") + util.puts("escape_by_default" + " Begun") var js = Haml.compile(hamlSrc); var jsFn = Haml(hamlSrc, {escapeHtmlByDefault:true}); @@ -127,11 +151,11 @@ fs.readdir('.', function (err, files) { try{ assert.equal(actual, expected); }catch(e){ - sys.error("\nActual["+actual.length+"]:\n\n" + actual); - sys.error("\nExpected["+expected.length+"]:\n\n" + expected); + util.error("\nActual["+actual.length+"]:\n\n" + actual); + util.error("\nExpected["+expected.length+"]:\n\n" + expected); process.exit(); } - sys.puts("escape_by_default" + " Passed") + util.puts("escape_by_default" + " Passed") })();