Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

less-middleware

Package Overview
Dependencies
Maintainers
2
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

less-middleware - npm Package Compare versions

Comparing version 1.0.4 to 2.0.0

changelog.md

146

lib/middleware.js

@@ -10,3 +10,2 @@ "use strict";

var determine_imports = require('./determine-imports');
var extend = require('node.extend');

@@ -22,3 +21,2 @@ var fs = require('fs');

var lessFiles = {};
var cachedLessFiles = {};
var cacheFileInitialized = false;

@@ -51,3 +49,3 @@ // Allow tests to force flushing of cacheFile

var loadCacheFile = function(cacheFile, log) {
var initCacheFile = function(cacheFile, log) {
cacheFileInitialized = true;

@@ -82,3 +80,3 @@ var cacheFileSaved = false;

try {
extend(cachedLessFiles, JSON.parse(data));
lessFiles = extend(JSON.parse(data), lessFiles);
} catch (err) {

@@ -96,8 +94,3 @@ log('error parsing cached imports in file ' + cacheFile, err);

*/
module.exports = less.middleware = function(source, options, parserOptions, compilerOptions){
// Check for 0.1.x usage.
if (typeof source == 'object') {
throw new Error('Please update your less-middleware usage: http://goo.gl/aXuck7');
}
module.exports = less.middleware = function(source, options){
// Source dir is required.

@@ -110,7 +103,3 @@ if (!source) {

options = extend(true, {
compiler: extend(true, {
compress: 'auto',
sourceMap: false,
yuicompress: false
}, compilerOptions || {}),
cacheFile: null,
debug: false,

@@ -120,12 +109,6 @@ dest: source,

once: false,
parser: extend(true, {
dumpLineNumbers: 0,
paths: [source],
optimization: 0,
relativeUrls: false
}, parserOptions || {}),
pathRoot: null,
cacheFile: null,
postprocess: {
css: function(css, req) { return css; }
css: function(css, req) { return css; },
sourcemap: function(sourcemap, req) { return sourcemap; }
},

@@ -136,3 +119,7 @@ preprocess: {

},
storeCss: function(pathname, css, next) {
render: {
compress: 'auto',
yuicompress: false
},
storeCss: function(pathname, css, req, next) {
mkdirp(path.dirname(pathname), 511 /* 0777 */, function(err){

@@ -143,2 +130,12 @@ if (err) return next(err);

});
},
storeSourcemap: function(pathname, sourcemap, req) {
mkdirp(path.dirname(pathname), 511 /* 0777 */, function(err){
if (err) {
utilities.lessError(err);
return;
}
fs.writeFile(pathname, sourcemap, 'utf8');
});
}

@@ -150,61 +147,9 @@ }, options || {});

// Deprecate the usage of separate options.
if(typeof parserOptions != 'undefined' || typeof compilerOptions != 'undefined') {
log('deprecated', 'Use of the separate arguments for parser and compiler options is deprecated');
if (options.cacheFile && !cacheFileInitialized) {
initCacheFile(options.cacheFile, log);
}
if (options.cacheFile && !cacheFileInitialized) {
loadCacheFile(options.cacheFile, log);
}
// Expose for testing.
less.middleware._saveCacheToFile = _saveCacheToFile;
// Parse and compile the CSS from the source string.
var render = function(str, lessPath, cssPath, callback) {
var parser = new less.Parser(extend({}, options.parser, {
filename: lessPath
}));
parser.parse(str, function(err, tree) {
if(err) {
return callback(err);
}
try {
// If sourceMap is enabled, set sourceMapbasepath to the directory of the less file
// Set sourceMapURL to enable separate source-map file.
if( options.compiler.sourceMap ){
options.compiler.sourceMapBasepath = path.dirname( lessPath );
options.compiler.sourceMapURL = path.basename( lessPath, '.less' ) + '.css.map';
// To generate the exact source-map file.
options.compiler.writeSourceMap = function( sourceMap ){
var sourceMapFilePath = path.join( path.dirname( cssPath ), path.basename( cssPath, '.css' ) + '.css.map' );
fs.writeFile( sourceMapFilePath, sourceMap, function( err ){
if( err ){
log( 'source-map', 'write source map to ' + sourceMapFilePath + ' fail, error: ', err );
}
else {
log( 'source-map', 'Write source map to ' + sourceMapFilePath + ' success.' );
}
});
};
}
var css = tree.toCSS(extend({}, options.compiler, {
compress: (options.compress == 'auto' ? utilities.isCompressedPath(cssPath) : options.compress)
}));
// Store the less import paths for cache invalidation.
lessFiles[lessPath] = {
mtime: Date.now(),
imports: determine_imports(tree, lessPath, options.parser.paths)
};
callback(err, css);
} catch(parseError) {
callback(parseError, null);
}
});
};
// Actual middleware.

@@ -233,2 +178,4 @@ return function(req, res, next) {

var sourcemapPath = cssPath + '.map';
// Allow for preprocessing the source filename.

@@ -256,3 +203,4 @@ lessPath = options.preprocess.path(lessPath, req);

lessSrc = options.preprocess.less(lessSrc, req);
render(lessSrc, lessPath, cssPath, function(err, css){
options.render.filename = lessPath;
less.render(lessSrc, options.render, function(err, output){
if (err) {

@@ -263,7 +211,21 @@ utilities.lessError(err);

// Allow postprocessing on the css.
css = options.postprocess.css(css, req);
// Store the less paths for simple cache invalidation.
lessFiles[lessPath] = {
mtime: Date.now(),
imports: output.imports
};
// Allow postprocessing for custom storage.
options.storeCss(cssPath, css, next);
if(output.map) {
// Postprocessing on the sourcemap.
var map = options.postprocess.sourcemap(output.map, req);
// Custom sourcemap storage.
options.storeSourcemap(sourcemapPath, map, req);
}
// Postprocessing on the css.
var css = options.postprocess.css(output.css, req);
// Custom css storage.
options.storeCss(cssPath, css, req, next);
});

@@ -289,7 +251,3 @@ } catch (err) {

if (!lessFiles[lessPath]) {
if (cachedLessFiles[lessPath]) {
lessFiles[lessPath] = cachedLessFiles[lessPath];
} else {
return compile();
}
return compile();
}

@@ -311,6 +269,8 @@

return compile();
} else {
return next(err);
}
} else if (lessStats.mtime > cssStats.mtime) {
return next(err);
}
if (lessStats.mtime > cssStats.mtime) {
// Source has changed, compile it

@@ -322,3 +282,3 @@ log('modified', cssPath);

// This can happen if lessFiles[lessPath] was copied from
// cachedLessFiles above, but the cache file was out of date (which
// cacheFile above, but the cache file was out of date (which
// can happen e.g. if node is killed and we were unable to write out

@@ -325,0 +285,0 @@ // lessFiles on exit). Since imports might have changed, we need to

@@ -5,3 +5,3 @@ {

"description": "LESS.js middleware for connect.",
"version": "1.0.4",
"version": "2.0.0",
"repository": {

@@ -13,11 +13,11 @@ "type": "git",

"dependencies": {
"less": "1.7.x",
"mkdirp": "~0.3.5",
"node.extend": "~1.0.8"
"less": "2.4.x",
"mkdirp": "~0.5",
"node.extend": "~1.1"
},
"devDependencies": {
"mocha": "~1.17.1",
"supertest": "~0.9.0",
"express": "~3.4.7",
"fs-extra": "~0.11.0"
"mocha": "~2.1",
"supertest": "~0.15",
"express": "~4.11",
"fs-extra": "~0.16"
},

@@ -24,0 +24,0 @@ "engines": {

{
"{$}/import.less":{
"imports":[
{
"path":"{$}/import-header.less"
},
{
"path":"{$}/import-color.less"
},
{
"path":"{$}/import-widget.less"
}
"{$}/import.less": {
"imports": [
"{$}/import-header.less",
"{$}/import-widget.less",
"{$}/import-color.less"
]
}
}
{
"{$}/import.less":{
"imports":[
{
"path":"{$}/import-color.less"
}
"{$}/import.less": {
"imports": [
"{$}/import-color.less"
]
}
}
}

@@ -50,4 +50,6 @@ "use strict";

force: true, // Need to force since using the same file as the simple test.
compiler: {
sourceMap: true
render: {
sourceMap: {
sourceMapBasepath: __dirname + '/fixtures'
}
}

@@ -115,4 +117,4 @@ });

less: function(src, req) {
if (req.param("namespace")) {
src = req.param("namespace") + " { " + src + " }";
if (req.query.namespace) {
src = req.query.namespace + " { " + src + " }";
}

@@ -185,72 +187,79 @@ return src;

});
});
describe('cacheFile', function() {
var middlewareSrc = tmpDest + '/fixturesCopy';
var dest = tmpDest + '/cacheFileTest';
var cacheFile = dest + '/cacheFile.json';
try {
mkdirp.sync(middlewareSrc);
} catch(e) {
if (e && e.code != 'EEXIST') throw e;
}
copySync(__dirname + '/fixtures', middlewareSrc);
var app;
var expandExpected = function(file) {
return file.replace(/\{\$\}/g, middlewareSrc);
}
describe('cacheFile', function() {
var middlewareSrc = tmpDest + '/fixturesCopy';
var dest = tmpDest + '/cacheFileTest';
var cacheFile = dest + '/cacheFile.json';
try {
mkdirp.sync(middlewareSrc);
} catch(e) {
if (e && e.code != 'EEXIST') throw e;
}
copySync(__dirname + '/fixtures', middlewareSrc);
var app;
var checkCacheFile = function(cacheFile, expectedFile){
return function(){
middleware._saveCacheToFile();
var cacheFileExpected = JSON.parse(expandExpected(fs.readFileSync(expectedFile, 'utf8')));
var cacheFileOutput = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
for (var file in cacheFileExpected) {
assert(cacheFileOutput[file] != undefined);
var expectedImports = cacheFileExpected[file].imports;
var outputImports = cacheFileOutput[file].imports;
for (var i = 0; i < expectedImports.length; i++) {
assert.equal(expectedImports[i].path, outputImports[i].path);
}
assert.equal(outputImports.length, expectedImports.length);
var expandExpected = function(file) {
return file.replace(/\{\$\}/g, middlewareSrc);
}
var checkCacheFile = function(cacheFile, expectedFile){
return function(){
// Force cacheFile write.
middleware._saveCacheToFile();
var cacheFileExpected = JSON.parse(expandExpected(fs.readFileSync(expectedFile, 'utf8')));
var cacheFileOutput = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
for (var file in cacheFileExpected) {
assert(cacheFileOutput[file] != undefined);
var expectedImports = cacheFileExpected[file].imports.sort();
var outputImports = cacheFileOutput[file].imports.sort();
assert.equal(outputImports.length, expectedImports.length);
for (var i = 0; i < expectedImports.length; i++) {
assert.equal(expectedImports[i], outputImports[i]);
}
}
}
}
beforeEach(function() {
// Unfortunately because cache-related items are stored in globals
// (which they need to be so that they are shared across different
// middleware invocations), to properly test the cacheFile option we
// need to re-require the middleware for each of these tests.
var mpath = path.resolve(__dirname, '../lib/middleware.js');
delete require.cache[mpath];
middleware = require('../lib/middleware');
app = setupExpress(middlewareSrc, {
dest: dest,
cacheFile: cacheFile
});
beforeEach(function() {
// Unfortunately because cache-related items are stored in globals
// (which they need to be so that they are shared across different
// middleware invocations), to properly test the cacheFile option we
// need to re-require the middleware for each of these tests.
var mpath = path.resolve(__dirname, '../lib/middleware.js');
delete require.cache[mpath];
middleware = require('../lib/middleware');
app = setupExpress(middlewareSrc, {
dest: dest,
cacheFile: cacheFile
});
});
it('should process files correctly and store the right cached imports', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/import-exp.css', 'utf8');
request(app)
.get('/import.css')
.expect(200)
.expect(expected)
.expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp.json'))
.end(done);
});
it('should process files correctly and store the right cached imports', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/import-exp.css', 'utf8');
request(app)
.get('/import.css')
.expect(200)
.expect(expected)
.expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp.json'))
.end(done);
});
it('should ignore cached imports if the file has changed and update cached imports', function(done){
copySync(middlewareSrc + '/importSimple.less', middlewareSrc + '/import.less');
var expected = fs.readFileSync(__dirname + '/fixtures/importSimple-exp.css', 'utf8');
request(app)
.get('/import.css')
.expect(200)
.expect(expected)
.expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp2.json'))
.end(done);
});
it('should ignore cached imports if the file has changed and update cached imports', function(done){
copySync(middlewareSrc + '/importSimple.less', middlewareSrc + '/import.less');
var expected = fs.readFileSync(__dirname + '/fixtures/importSimple-exp.css', 'utf8');
request(app)
.get('/import.css')
.expect(200)
.expect(expected)
.expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp2.json'))
.end(done);
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc