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 @@
+
\ 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")
})();