diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index cd7c7222..df309789 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -92,14 +92,23 @@ var Parser = function Parser(context, imports, fileInfo) { // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply // parse: function (str, callback, additionalData) { - var root, error = null, globalVars, modifyVars, preText = ""; + var root, error = null, globalVars, modifyVars, ignored, preText = ""; globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : ''; modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : ''; + if (context.pluginManager) { + var preProcessors = context.pluginManager.getPreProcessors(); + for (var i = 0; i < preProcessors.length; i++) { + str = preProcessors[i].process(str, { context: context, imports: imports, fileInfo: fileInfo }); + } + } + if (globalVars || (additionalData && additionalData.banner)) { preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars; - imports.contentsIgnoredChars[fileInfo.filename] = preText.length; + ignored = imports.contentsIgnoredChars; + ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0; + ignored[fileInfo.filename] += preText.length; } str = str.replace(/\r\n?/g, '\n'); diff --git a/lib/less/plugin-manager.js b/lib/less/plugin-manager.js index abae2f1c..8f6df7c7 100644 --- a/lib/less/plugin-manager.js +++ b/lib/less/plugin-manager.js @@ -4,6 +4,7 @@ var PluginManager = function(less) { this.less = less; this.visitors = []; + this.preProcessors = []; this.postProcessors = []; this.installedPlugins = []; this.fileManagers = []; @@ -35,6 +36,20 @@ PluginManager.prototype.addPlugin = function(plugin) { PluginManager.prototype.addVisitor = function(visitor) { this.visitors.push(visitor); }; +/** + * Adds a pre processor object + * @param {object} preProcessor + * @param {number} priority - guidelines 1 = before import, 1000 = import, 2000 = after import + */ +PluginManager.prototype.addPreProcessor = function(preProcessor, priority) { + var indexToInsertAt; + for (indexToInsertAt = 0; indexToInsertAt < this.preProcessors.length; indexToInsertAt++) { + if (this.preProcessors[indexToInsertAt].priority >= priority) { + break; + } + } + this.preProcessors.splice(indexToInsertAt, 0, {preProcessor: preProcessor, priority: priority}); +}; /** * Adds a post processor object * @param {object} postProcessor @@ -56,6 +71,18 @@ PluginManager.prototype.addPostProcessor = function(postProcessor, priority) { PluginManager.prototype.addFileManager = function(manager) { this.fileManagers.push(manager); }; +/** + * + * @returns {Array} + * @private + */ +PluginManager.prototype.getPreProcessors = function() { + var preProcessors = []; + for (var i = 0; i < this.preProcessors.length; i++) { + preProcessors.push(this.preProcessors[i].preProcessor); + } + return preProcessors; +}; /** * * @returns {Array} diff --git a/lib/less/source-map-builder.js b/lib/less/source-map-builder.js index 5163a88d..ee28041e 100644 --- a/lib/less/source-map-builder.js +++ b/lib/less/source-map-builder.js @@ -30,8 +30,12 @@ module.exports = function (SourceMapOutput, environment) { }; SourceMapBuilder.prototype.getCSSAppendage = function() { + var sourceMapURL = this.sourceMapURL; if (this.options.sourceMapFileInline) { + if (this.sourceMap === undefined) { + return ""; + } sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap); } diff --git a/test/index.js b/test/index.js index c58e1e19..7a858d67 100644 --- a/test/index.js +++ b/test/index.js @@ -40,6 +40,7 @@ lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: true, glo } return path.join('test/sourcemaps', filename) + '.json'; }); +lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: {sourceMapFileInline: true}}, "sourcemaps-empty/", lessTester.testEmptySourcemap); lessTester.runTestSet({globalVars: true, banner: "/**\n * Test\n */\n"}, "globalVars/", null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; }); lessTester.runTestSet({modifyVars: true}, "modifyVars/", @@ -49,4 +50,4 @@ lessTester.runTestSet({paths: ['test/data/', 'test/less/import/']}, "include-pat lessTester.testSyncronous({syncImport: true}, "import"); lessTester.testSyncronous({syncImport: true}, "css"); lessTester.testNoOptions(); -lessTester.finished(); \ No newline at end of file +lessTester.finished(); diff --git a/test/less-test.js b/test/less-test.js index ba142418..b90d58de 100644 --- a/test/less-test.js +++ b/test/less-test.js @@ -89,6 +89,23 @@ module.exports = function() { }); } + function testEmptySourcemap(name, err, compiledLess, doReplacements, sourcemap, baseFolder) { + process.stdout.write("- " + path.join(baseFolder, name) + ": "); + if (err) { + fail("ERROR: " + (err && err.message)); + } else { + var expectedSourcemap = undefined; + if ( compiledLess !== "" ) { + difference("\nCompiledLess must be empty", "", compiledLess); + + } else if (sourcemap !== expectedSourcemap) { + fail("Sourcemap must be undefined"); + } else { + ok('OK'); + } + } + } + function testErrors(name, err, compiledLess, doReplacements, sourcemap, baseFolder) { fs.readFile(path.join(baseFolder, name) + '.txt', 'utf8', function (e, expectedErr) { process.stdout.write("- " + path.join(baseFolder, name) + ": "); @@ -189,7 +206,7 @@ module.exports = function() { totalTests++; - if (options.sourceMap) { + if (options.sourceMap && !options.sourceMap.sourceMapFileInline) { options.sourceMapOutputFilename = name + ".css"; options.sourceMapBasepath = path.join(process.cwd(), baseFolder); options.sourceMapRootpath = "testweb/"; @@ -247,10 +264,10 @@ module.exports = function() { function diff(left, right) { require('diff').diffLines(left, right).forEach(function(item) { if (item.added || item.removed) { - var text = item.value.replace("\n", String.fromCharCode(182) + "\n").replace('\ufeff', '[[BOM]]'); + var text = item.value && item.value.replace("\n", String.fromCharCode(182) + "\n").replace('\ufeff', '[[BOM]]'); process.stdout.write(stylize(text, item.added ? 'green' : 'red')); } else { - process.stdout.write(item.value.replace('\ufeff', '[[BOM]]')); + process.stdout.write(item.value && item.value.replace('\ufeff', '[[BOM]]')); } }); process.stdout.write("\n"); @@ -352,6 +369,7 @@ module.exports = function() { testSyncronous: testSyncronous, testErrors: testErrors, testSourcemap: testSourcemap, + testEmptySourcemap: testEmptySourcemap, testNoOptions: testNoOptions, prepBomTest: prepBomTest, finished: finished diff --git a/test/less/sourcemaps-empty/empty.less b/test/less/sourcemaps-empty/empty.less new file mode 100644 index 00000000..e69de29b diff --git a/test/less/sourcemaps-empty/var-defs.less b/test/less/sourcemaps-empty/var-defs.less new file mode 100644 index 00000000..19465415 --- /dev/null +++ b/test/less/sourcemaps-empty/var-defs.less @@ -0,0 +1 @@ +@test-var: 'something'; \ No newline at end of file