mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
Merge pull request #2391 from DotNetSparky/fix-bom-imports
Remove BOM in imports.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,6 +16,7 @@ test/browser/less.js
|
||||
test/sourcemaps/**/*.map
|
||||
test/sourcemaps/*.map
|
||||
test/sourcemaps/*.css
|
||||
test/less-bom
|
||||
|
||||
# grunt
|
||||
.grunt
|
||||
|
||||
@@ -355,6 +355,8 @@ var parseLessFile = function (e, data) {
|
||||
return;
|
||||
}
|
||||
|
||||
data = data.replace(/^\uFEFF/, '');
|
||||
|
||||
options.paths = [path.dirname(input)].concat(options.paths);
|
||||
options.filename = input;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ module.exports = function(environment) {
|
||||
|
||||
var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
|
||||
if (!fileSync.contents) {
|
||||
logger.warn("Skipped data-uri embedding because file not found");
|
||||
logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
|
||||
return fallback(this, filePathNode || mimetypeNode);
|
||||
}
|
||||
var buf = fileSync.contents;
|
||||
|
||||
@@ -68,7 +68,7 @@ module.exports = function(environment) {
|
||||
|
||||
var loadFileCallback = function(loadedFile) {
|
||||
var resolvedFilename = loadedFile.filename,
|
||||
contents = loadedFile.contents;
|
||||
contents = loadedFile.contents.replace(/^\uFEFF/, '');
|
||||
|
||||
// Pass on an updated rootpath if path of imported file is relative and file
|
||||
// is in a (sub|sup) directory
|
||||
|
||||
66
test/copy-bom.js
Normal file
66
test/copy-bom.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/*jshint latedef: nofunc */
|
||||
|
||||
// This is used to copy a folder (the test/less/* files & sub-folders), adding a BOM to the start of each LESS and CSS file.
|
||||
// This is a based on the copySync method from fs-extra (https://github.com/jprichardson/node-fs-extra/).
|
||||
|
||||
module.exports = function() {
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
var BUF_LENGTH = 64 * 1024;
|
||||
var _buff = new Buffer(BUF_LENGTH);
|
||||
|
||||
function copyFolderWithBom(src, dest) {
|
||||
var stats = fs.lstatSync(src);
|
||||
var destFolder = path.dirname(dest);
|
||||
var destFolderExists = fs.existsSync(destFolder);
|
||||
var performCopy = false;
|
||||
|
||||
if (stats.isFile()) {
|
||||
if (!destFolderExists)
|
||||
fs.mkdirSync(destFolder);
|
||||
if (src.match(/\.(css|less)$/))
|
||||
copyFileAddingBomSync(src, dest);
|
||||
else
|
||||
copyFileSync(src, dest)
|
||||
}
|
||||
else if (stats.isDirectory()) {
|
||||
if (!fs.existsSync(destFolder))
|
||||
fs.mkdirSync(destFolder);
|
||||
if (!fs.existsSync(dest))
|
||||
fs.mkdirSync(dest);
|
||||
fs.readdirSync(src).forEach(function(d) {
|
||||
if (d !== 'bom')
|
||||
copyFolderWithBom(path.join(src, d), path.join(dest, d));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function copyFileAddingBomSync(srcFile, destFile) {
|
||||
var contents = fs.readFileSync(srcFile, { encoding: 'utf8' });
|
||||
if (!contents.length || contents.charCodeAt(0) !== 0xFEFF)
|
||||
contents = '\ufeff' + contents;
|
||||
fs.writeFileSync(destFile, contents, { encoding: 'utf8' });
|
||||
}
|
||||
|
||||
function copyFileSync(srcFile, destFile) {
|
||||
var fdr = fs.openSync(srcFile, 'r')
|
||||
var stat = fs.fstatSync(fdr)
|
||||
var fdw = fs.openSync(destFile, 'w', stat.mode)
|
||||
var bytesRead = 1
|
||||
var pos = 0
|
||||
|
||||
while (bytesRead > 0) {
|
||||
bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
|
||||
fs.writeSync(fdw, _buff, 0, bytesRead)
|
||||
pos += bytesRead
|
||||
}
|
||||
|
||||
fs.closeSync(fdr)
|
||||
fs.closeSync(fdw)
|
||||
}
|
||||
|
||||
return {
|
||||
copyFolderWithBom: copyFolderWithBom
|
||||
};
|
||||
};
|
||||
@@ -4,12 +4,11 @@ var lessTest = require("./less-test"),
|
||||
stylize = require('../lib/less-node/lessc-helper').stylize;
|
||||
|
||||
function getErrorPathReplacementFunction(dir) {
|
||||
return function(input) {
|
||||
return input.replace(
|
||||
/\{path\}/g, path.join(process.cwd(), "/test/less/" + dir + "/"))
|
||||
.replace(/\{node\}/g, "")
|
||||
.replace(/\{\/node\}/g, "")
|
||||
.replace(/\{pathrel\}/g, path.join("test", "less", dir + "/"))
|
||||
return function(input, baseDir) {
|
||||
return input.replace(/\{path\}/g, path.join(process.cwd(), baseDir, dir + "/"))
|
||||
.replace(/\{node\}/g, "")
|
||||
.replace(/\{\/node\}/g, "")
|
||||
.replace(/\{pathrel\}/g, path.join(baseDir, dir + "/"))
|
||||
.replace(/\{pathhref\}/g, "")
|
||||
.replace(/\{404status\}/g, "")
|
||||
.replace(/\r\n/g, '\n');
|
||||
@@ -17,6 +16,7 @@ function getErrorPathReplacementFunction(dir) {
|
||||
}
|
||||
|
||||
console.log("\n" + stylize("Less", 'underline') + "\n");
|
||||
lessTester.prepBomTest();
|
||||
lessTester.runTestSet({strictMath: true, relativeUrls: true, silent: true});
|
||||
lessTester.runTestSet({strictMath: true, strictUnits: true}, "errors/",
|
||||
lessTester.testErrors, null, getErrorPathReplacementFunction("errors"));
|
||||
@@ -34,16 +34,16 @@ lessTester.runTestSet({strictMath: true, strictUnits: true}, "strict-units/");
|
||||
lessTester.runTestSet({}, "legacy/");
|
||||
lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: true, globalVars: true }, "sourcemaps/",
|
||||
lessTester.testSourcemap, null, null,
|
||||
function(filename, type) {
|
||||
function(filename, type, baseFolder) {
|
||||
if (type === "vars") {
|
||||
return path.join('test/less/', filename) + '.json';
|
||||
return path.join(baseFolder, filename) + '.json';
|
||||
}
|
||||
return path.join('test/sourcemaps', filename) + '.json';
|
||||
});
|
||||
lessTester.runTestSet({globalVars: true, banner: "/**\n * Test\n */\n"}, "globalVars/",
|
||||
null, null, null, function(name) { return path.join('test/less/', name) + '.json'; });
|
||||
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; });
|
||||
lessTester.runTestSet({modifyVars: true}, "modifyVars/",
|
||||
null, null, null, function(name) { return path.join('test/less/', name) + '.json'; });
|
||||
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; });
|
||||
lessTester.runTestSet({urlArgs: '424242'}, "url-args/");
|
||||
lessTester.runTestSet({paths: ['test/data/','test/less/import/']}, "include-path/");
|
||||
lessTester.testSyncronous({syncImport: true}, "import");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
module.exports = function() {
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
copyBom = require('./copy-bom')();
|
||||
|
||||
var less = require('../lib/less-node');
|
||||
var stylize = require('../lib/less-node/lessc-helper').stylize;
|
||||
@@ -14,6 +15,9 @@ module.exports = function() {
|
||||
|
||||
var isVerbose = process.env.npm_config_loglevel === 'verbose';
|
||||
|
||||
var normalFolder = 'test/less';
|
||||
var bomFolder = 'test/less-bom';
|
||||
|
||||
less.logger.addListener({
|
||||
info: function(msg) {
|
||||
if (isVerbose) {
|
||||
@@ -67,9 +71,9 @@ module.exports = function() {
|
||||
}
|
||||
});
|
||||
|
||||
function testSourcemap(name, err, compiledLess, doReplacements, sourcemap) {
|
||||
function testSourcemap(name, err, compiledLess, doReplacements, sourcemap, baseFolder) {
|
||||
fs.readFile(path.join('test/', name) + '.json', 'utf8', function (e, expectedSourcemap) {
|
||||
process.stdout.write("- " + name + ": ");
|
||||
process.stdout.write("- " + path.join(baseFolder, name) + ": ");
|
||||
if (sourcemap === expectedSourcemap) {
|
||||
ok('OK');
|
||||
} else if (err) {
|
||||
@@ -84,10 +88,10 @@ module.exports = function() {
|
||||
});
|
||||
}
|
||||
|
||||
function testErrors(name, err, compiledLess, doReplacements) {
|
||||
fs.readFile(path.join('test/less/', name) + '.txt', 'utf8', function (e, expectedErr) {
|
||||
process.stdout.write("- " + name + ": ");
|
||||
expectedErr = doReplacements(expectedErr, 'test/less/errors/');
|
||||
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) + ": ");
|
||||
expectedErr = doReplacements(expectedErr, baseFolder);
|
||||
if (!err) {
|
||||
if (compiledLess) {
|
||||
fail("No Error", 'red');
|
||||
@@ -131,7 +135,7 @@ module.exports = function() {
|
||||
totalTests++;
|
||||
queue(function() {
|
||||
var isSync = true;
|
||||
toCSS(options, path.join('test/less/', filenameNoExtension + ".less"), function (err, result) {
|
||||
toCSS(options, path.join(normalFolder, filenameNoExtension + ".less"), function (err, result) {
|
||||
process.stdout.write("- Test Sync " + filenameNoExtension + ": ");
|
||||
|
||||
if (isSync) {
|
||||
@@ -145,7 +149,21 @@ module.exports = function() {
|
||||
});
|
||||
}
|
||||
|
||||
function prepBomTest() {
|
||||
copyBom.copyFolderWithBom(normalFolder, bomFolder);
|
||||
}
|
||||
|
||||
function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements, getFilename) {
|
||||
var options2 = options ? JSON.parse(JSON.stringify(options)) : {};
|
||||
runTestSetInternal(normalFolder, options, foldername, verifyFunction, nameModifier, doReplacements, getFilename);
|
||||
runTestSetInternal(bomFolder, options2, foldername, verifyFunction, nameModifier, doReplacements, getFilename);
|
||||
}
|
||||
|
||||
function runTestSetNormalOnly(options, foldername, verifyFunction, nameModifier, doReplacements, getFilename) {
|
||||
runTestSetInternal(normalFolder, options, foldername, verifyFunction, nameModifier, doReplacements, getFilename);
|
||||
}
|
||||
|
||||
function runTestSetInternal(baseFolder, options, foldername, verifyFunction, nameModifier, doReplacements, getFilename) {
|
||||
foldername = foldername || "";
|
||||
|
||||
if(!doReplacements) {
|
||||
@@ -156,7 +174,7 @@ module.exports = function() {
|
||||
return foldername + path.basename(file, '.less');
|
||||
}
|
||||
|
||||
fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) {
|
||||
fs.readdirSync(path.join(baseFolder, foldername)).forEach(function (file) {
|
||||
if (! /\.less/.test(file)) { return; }
|
||||
|
||||
var name = getBasename(file);
|
||||
@@ -169,19 +187,19 @@ module.exports = function() {
|
||||
|
||||
if (options.sourceMap) {
|
||||
options.sourceMapOutputFilename = name + ".css";
|
||||
options.sourceMapBasepath = path.join(process.cwd(), "test/less");
|
||||
options.sourceMapBasepath = path.join(process.cwd(), baseFolder);
|
||||
options.sourceMapRootpath = "testweb/";
|
||||
// TODO separate options?
|
||||
options.sourceMap = options;
|
||||
}
|
||||
|
||||
options.getVars = function(file) {
|
||||
return JSON.parse(fs.readFileSync(getFilename(getBasename(file), 'vars'), 'utf8'));
|
||||
return JSON.parse(fs.readFileSync(getFilename(getBasename(file), 'vars', baseFolder), 'utf8'));
|
||||
};
|
||||
|
||||
var doubleCallCheck = false;
|
||||
var doubleCallCheck = false;
|
||||
queue(function() {
|
||||
toCSS(options, path.join('test/less/', foldername + file), function (err, result) {
|
||||
toCSS(options, path.join(baseFolder, foldername + file), function (err, result) {
|
||||
if (doubleCallCheck) {
|
||||
totalTests++;
|
||||
fail("less is calling back twice");
|
||||
@@ -192,7 +210,7 @@ module.exports = function() {
|
||||
doubleCallCheck = (new Error()).stack;
|
||||
|
||||
if (verifyFunction) {
|
||||
var verificationResult = verifyFunction(name, err, result && result.css, doReplacements, result && result.map);
|
||||
var verificationResult = verifyFunction(name, err, result && result.css, doReplacements, result && result.map, baseFolder);
|
||||
release();
|
||||
return verificationResult;
|
||||
}
|
||||
@@ -208,9 +226,9 @@ module.exports = function() {
|
||||
var css_name = name;
|
||||
if(nameModifier) { css_name = nameModifier(name); }
|
||||
fs.readFile(path.join('test/css', css_name) + '.css', 'utf8', function (e, css) {
|
||||
process.stdout.write("- " + css_name + ": ");
|
||||
process.stdout.write("- " + path.join(baseFolder, css_name) + ": ");
|
||||
|
||||
css = css && doReplacements(css, 'test/less/' + foldername);
|
||||
css = css && doReplacements(css, path.join(baseFolder, foldername));
|
||||
if (result.css === css) { ok('OK'); }
|
||||
else {
|
||||
difference("FAIL", css, result.css);
|
||||
@@ -225,10 +243,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");
|
||||
var text = 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);
|
||||
process.stdout.write(item.value.replace('\ufeff', '[[BOM]]'));
|
||||
}
|
||||
});
|
||||
process.stdout.write("\n");
|
||||
@@ -327,10 +345,12 @@ module.exports = function() {
|
||||
|
||||
return {
|
||||
runTestSet: runTestSet,
|
||||
runTestSetNormalOnly: runTestSetNormalOnly,
|
||||
testSyncronous: testSyncronous,
|
||||
testErrors: testErrors,
|
||||
testSourcemap: testSourcemap,
|
||||
testNoOptions: testNoOptions,
|
||||
prepBomTest: prepBomTest,
|
||||
finished: finished
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user