diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index 320e11ac..b8e84ec9 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -197,7 +197,7 @@ tree.Ruleset.prototype = { } css.push(rulesets); - return css.join('') + (env.compress ? '' : '\n'); + return css.join(''); }, joinSelectors: function (paths, context, selectors) { diff --git a/test/css/debug/comments.css b/test/css/debug/comments.css new file mode 100644 index 00000000..06e33ede --- /dev/null +++ b/test/css/debug/comments.css @@ -0,0 +1,32 @@ +/* line 21, {pathimport}test.less */ +.tst3 { + color: grey; +} +/* line 12, {path}comments.less */ +.test1 { + color: black; +} +/* line 3, {path}comments.less */ +.test2 { + color: red; +} +@media all { + /* line 3, {pathimport}test.less */ + .tst { + color: black; + } +} +@media all and screen { + /* line 3, {pathimport}test.less */ + .tst { + color: red; + } + /* line 7, {pathimport}test.less */ + .tst .tst3 { + color: white; + } +} +/* line 16, {pathimport}test.less */ +.tst2 { + color: white; +} diff --git a/test/less-test.js b/test/less-test.js index 0b3309ce..96daa97b 100644 --- a/test/less-test.js +++ b/test/less-test.js @@ -7,100 +7,146 @@ var stylize = require('../lib/less/lessc_helper').stylize; var oneTestOnly = process.argv[2]; +var totalTests = 0, + failedTests = 0, + passedTests = 0; + less.tree.functions.add = function (a, b) { return new(less.tree.Dimension)(a.value + b.value); -} +}; less.tree.functions.increment = function (a) { return new(less.tree.Dimension)(a.value + 1); -} +}; less.tree.functions._color = function (str) { if (str.value === "evil red") { return new(less.tree.Color)("600") } -} +}; sys.puts("\n" + stylize("LESS", 'underline') + "\n"); -fs.readdirSync('test/less').forEach(function (file) { - if (! /\.less/.test(file)) { return } - - var name = path.basename(file, '.less'); - - if (oneTestOnly && name !== oneTestOnly) { return; } +runTestSet(); - toCSS('test/less/' + file, function (err, less) { - - fs.readFile(path.join('test/css', name) + '.css', 'utf-8', function (e, css) { - sys.print("- " + name + ": ") - css = css && css.replace(/\r\n/g, '\n'); - if (less === css) { sys.print(stylize('OK', 'green')) } - else if (err) { - sys.print(stylize("ERROR: " + (err && err.message), 'red')); +runTestSet(null, "errors/", function(name, err, compiledLess) { + fs.readFile(path.join('test/less/', name) + '.txt', 'utf-8', function (e, expectedErr) { + sys.print("- " + name + ": "); + expectedErr = doReplacements(expectedErr, 'test/less/errors/'); + if (!err) { + if (compiledLess) { + fail("No Error", 'red'); } else { - sys.print(stylize("FAIL", 'yellow') + '\n'); - - require('diff').diffLines(css, less).forEach(function(item) { - if(item.added || item.removed) { - sys.print(stylize(item.value, item.added ? 'green' : 'red')); - } else { - sys.print(item.value); - } - }) + fail("No Error, No Output"); } - sys.puts(""); + } else { + var errMessage = less.formatError(err); + if (errMessage === expectedErr) { + ok('OK'); + } else { + difference("FAIL", expectedErr, errMessage); + } + } + sys.puts(""); + });}); + +runTestSet({dumpLineNumbers: true}, "debug/"); + +function runTestSet(options, foldername, verifyFunction) { + foldername = foldername || ""; + + fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) { + if (! /\.less/.test(file)) { return } + + var name = foldername + path.basename(file, '.less'); + + if (oneTestOnly && name !== oneTestOnly) { return; } + + totalTests++; + + toCSS(options, path.join('test/less/', foldername + file), function (err, less) { + + if (verifyFunction) { + return verifyFunction(name, err, less); + } + + fs.readFile(path.join('test/css', name) + '.css', 'utf-8', function (e, css) { + sys.print("- " + name + ": ") + + css = css && doReplacements(css, 'test/less/' + foldername); + if (less === css) { ok('OK'); } + else if (err) { + fail("ERROR: " + (err && err.message)); + } else { + difference("FAIL", css, less); + } + sys.puts(""); + }); }); }); -}); +} -fs.readdirSync('test/less/errors').forEach(function (file) { - if (! /\.less/.test(file)) { return } - - var name = path.basename(file, '.less'); - - if (oneTestOnly && ("error/" + name) !== oneTestOnly) { return; } +function doReplacements(input, directory) { + return input.replace(/\{path\}/g, path.join(process.cwd(), directory)) + .replace(/\{pathimport\}/g, path.join(process.cwd(), directory + "import/")) + .replace("{path}", path.join(process.cwd(), "/test/less/errors/")) + .replace("{pathrel}", path.join("test", "less", "errors/")) + .replace(/\r\n/g, '\n'); +} - toCSS('test/less/errors/' + file, function (err, compiledLess) { - fs.readFile(path.join('test/less/errors', name) + '.txt', 'utf-8', function (e, expectedErr) { - sys.print("- error/" + name + ": "); - expectedErr = expectedErr.replace("{path}", path.join(process.cwd(), "/test/less/errors/")) - .replace("{pathrel}", path.join("test", "less", "errors/")) - .replace(/\r\n/g, '\n'); - if (!err) { - if (compiledLess) { - sys.print(stylize("No Error", 'red')); - } else { - sys.print(stylize("No Error, No Output", 'red')); - } - - } else { - var errMessage = less.formatError(err); - if (errMessage === expectedErr) { - sys.print(stylize('OK', 'green')); - } else { - sys.print(stylize("FAIL", 'yellow') + '\n'); - - require('diff').diffLines(expectedErr, errMessage).forEach(function(item) { - if(item.added || item.removed) { - sys.print(stylize(item.value, item.added ? 'green' : 'red')); - } else { - sys.print(item.value); - } - }) - } - } - sys.puts(""); - }); +function diff(left, right) { + sys.puts(""); + require('diff').diffLines(left, right).forEach(function(item) { + if(item.added || item.removed) { + sys.print(stylize(item.value, item.added ? 'green' : 'red')); + } else { + sys.print(item.value); + } }); -}); +} -function toCSS(path, callback) { +function fail(msg) { + sys.print(stylize(msg, 'red')); + failedTests++; + endTest(); +} + +function difference(msg, left, right) { + sys.print(stylize(msg, 'yellow')); + failedTests++; + + diff(left, right); + endTest(); +} + +function ok(msg) { + sys.print(stylize(msg, 'green')); + passedTests++; + endTest(); +} + +function endTest() { + if (failedTests + passedTests === totalTests) { + sys.puts(""); + sys.puts(""); + if (failedTests > 0) { + sys.print(failedTests); + sys.print(stylize(" Failed", "red")); + sys.print(", " + passedTests + " passed"); + } else { + sys.print(stylize("All Passed ", "green")); + sys.print(passedTests + " run"); + } + } +} + +function toCSS(options, path, callback) { var tree, css; + options = options || {}; fs.readFile(path, 'utf-8', function (e, str) { if (e) { return callback(e) } + + options.paths = [require('path').dirname(path)]; + options.filename = require('path').resolve(process.cwd(), path); + options.optimization = options.optimization || 0; - new(less.Parser)({ - paths: [require('path').dirname(path)], - optimization: 0, - filename: require('path').resolve(process.cwd(), path) - }).parse(str, function (err, tree) { + new(less.Parser)(options).parse(str, function (err, tree) { if (err) { callback(err); } else { diff --git a/test/less/debug/comments.less b/test/less/debug/comments.less new file mode 100644 index 00000000..dbf9770e --- /dev/null +++ b/test/less/debug/comments.less @@ -0,0 +1,21 @@ +@import "import/test.less"; + +.start() { + .test2 { + color: red; + } +} + +.mix() { + color: black; +} + +.test1 { + .mix(); +} + +.start(); + +.mixin_import1(); + +.mixin_import2(); \ No newline at end of file diff --git a/test/less/debug/import/test.less b/test/less/debug/import/test.less new file mode 100644 index 00000000..83e60636 --- /dev/null +++ b/test/less/debug/import/test.less @@ -0,0 +1,23 @@ +.mixin_import1() { + @media all { + .tst { + color: black; + @media screen { + color: red; + .tst3 { + color: white; + } + } + } + } +} + +.mixin_import2() { + .tst2 { + color: white; + } +} + +.tst3 { + color: grey; +} \ No newline at end of file