Working Skelleton

This commit is contained in:
2019-03-11 17:03:55 +01:00
commit 8ed2de006d
6779 changed files with 514323 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
/node_modules/
/test/artifacts/
+19
View File
@@ -0,0 +1,19 @@
# 2.0.1
- 22 Feb 2015
* Fixed [#123](https://github.com/emberfeather/less.js-middleware/issues/123): imports are not objects for cache checking and did not have mtimes.
* Added a `preprocess.importPaths` for modifying the import paths per request.
# 2.0.0
21 Feb 2015
* Upgraded to the 2.4 version of Less.
* Updated dependencies to the latest versions.
* Removed `options.parser` since Less is simplifying to just a `render` function.
* Using `options.render` for passing through all rendering options directly to the less rendering.
* Changed `options.storeCss` arguments from `(pathname, css, next)` to `(pathname, css, req, next)`
* Added `postprocess.sourcemap` option for modifying the sourcemap.
* Added `storeSourcemap` option for manipulating the sourcemap storage.
* Removed pre `0.1.x` warning
+320
View File
@@ -0,0 +1,320 @@
"use strict";
/*!
* Less - middleware (adapted from the stylus middleware)
*
* Copyright(c) 2014 Randy Merrill <Zoramite+github@gmail.com>
* MIT Licensed
*/
var extend = require('node.extend');
var fs = require('fs');
var less = require('less');
var mkdirp = require('mkdirp');
var path = require('path');
var url = require('url');
var utilities = require('./utilities');
// Import mapping with mtimes
var lessFiles = {};
var cacheFileInitialized = false;
// Allow tests to force flushing of cacheFile
var _saveCacheToFile = function() {};
// Check imports for changes.
var checkImports = function(path, next) {
var nodes = lessFiles[path].imports;
if (!nodes || !nodes.length) {
return next();
}
var pending = nodes.length;
var changed = [];
nodes.forEach(function(imported){
fs.stat(imported.path, function(err, stat) {
// error or newer mtime
if (err || !imported.mtime || stat.mtime > imported.mtime) {
changed.push(imported.path);
}
--pending || next(changed);
});
});
};
var initCacheFile = function(cacheFile, log) {
cacheFileInitialized = true;
var cacheFileSaved = false;
_saveCacheToFile = function() {
if (cacheFileSaved) { // We expect to only save to the cache file once, just before exiting
log('cache file already appears to be saved, not saving again to', cacheFile);
return;
} else {
cacheFileSaved = true;
try {
fs.writeFileSync(cacheFile, JSON.stringify(lessFiles));
log('successfully cached imports to file', cacheFile);
} catch (err) {
log('error caching imports to file ' + cacheFile, err);
}
}
};
process.on('exit', _saveCacheToFile);
process.once('SIGUSR2', function() { // Handle nodemon restarts
_saveCacheToFile();
process.kill(process.pid, 'SIGUSR2');
});
process.once('SIGINT', function() {
_saveCacheToFile();
process.kill(process.pid, 'SIGINT'); // Let other SIGINT handlers run, if there are any
});
fs.readFile(cacheFile, 'utf8', function(err, data) {
if (!err) {
try {
lessFiles = extend(JSON.parse(data), lessFiles);
} catch (err) {
log('error parsing cached imports in file ' + cacheFile, err);
}
} else {
log('error loading cached imports file ' + cacheFile, err);
}
});
}
/**
* Return Connect middleware with the given `options`.
*/
module.exports = less.middleware = function(source, options){
// Source dir is required.
if (!source) {
throw new Error('less.middleware() requires `source` directory');
}
// Override the defaults for the middleware.
options = extend(true, {
cacheFile: null,
debug: false,
dest: source,
force: false,
once: false,
pathRoot: null,
postprocess: {
css: function(css, req) { return css; },
sourcemap: function(sourcemap, req) { return sourcemap; }
},
preprocess: {
less: function(src, req) { return src; },
path: function(pathname, req) { return pathname; },
importPaths: function(paths, req) { return paths; }
},
render: {
compress: 'auto',
yuicompress: false,
paths: []
},
storeCss: function(pathname, css, req, next) {
mkdirp(path.dirname(pathname), 511 /* 0777 */, function(err){
if (err) return next(err);
fs.writeFile(pathname, css, next);
});
},
storeSourcemap: function(pathname, sourcemap, req) {
mkdirp(path.dirname(pathname), 511 /* 0777 */, function(err){
if (err) {
utilities.lessError(err);
return;
}
fs.writeFile(pathname, sourcemap, function(err) {
if (err) throw err;
});
});
}
}, options || {});
// The log function is determined by the debug option.
var log = (options.debug ? utilities.logDebug : utilities.log);
if (options.cacheFile && !cacheFileInitialized) {
initCacheFile(options.cacheFile, log);
}
// Expose for testing.
less.middleware._saveCacheToFile = _saveCacheToFile;
// Actual middleware.
return function(req, res, next) {
if ('GET' != req.method.toUpperCase() && 'HEAD' != req.method.toUpperCase()) { return next(); }
var pathname = url.parse(req.url).pathname;
// Only handle the matching files in this middleware.
if (utilities.isValidPath(pathname)) {
var isSourceMap = utilities.isSourceMap(pathname);
// Translate source maps to a normal .css request which will update the associated source-map.
if( isSourceMap ){
pathname = pathname.replace( /\.map$/, '' );
}
var lessPath = path.join(source, utilities.maybeCompressedSource(pathname));
var cssPath = path.join(options.dest, pathname);
if (options.pathRoot) {
pathname = pathname.replace(options.dest, '');
cssPath = path.join(options.pathRoot, options.dest, pathname);
lessPath = path.join(options.pathRoot, source, utilities.maybeCompressedSource(pathname));
}
var sourcemapPath = cssPath + '.map';
// Allow for preprocessing the source filename.
lessPath = options.preprocess.path(lessPath, req);
log('pathname', pathname);
log('source', lessPath);
log('destination', cssPath);
// Ignore ENOENT to fall through as 404.
var error = function(err) {
return next('ENOENT' == err.code ? null : err);
};
var compile = function() {
fs.readFile(lessPath, 'utf8', function(err, lessSrc){
if (err) {
return error(err);
}
delete lessFiles[lessPath];
try {
var renderOptions = extend(true, {}, options.render, {
filename: lessPath,
paths: options.preprocess.importPaths(options.render.paths, req)
});
lessSrc = options.preprocess.less(lessSrc, req);
less.render(lessSrc, renderOptions, function(err, output){
if (err) {
utilities.lessError(err);
return next(err);
}
// Determine the imports used and check modified times.
var imports = [];
output.imports.forEach(function(imported) {
var currentImport = {
path: imported,
mtime: null
};
imports.push(currentImport);
// Update the mtime of the import async.
fs.stat(imported, function(err, lessStats){
if (err) {
return error(err);
}
currentImport.mtime = lessStats.mtime;
});
});
// Store the less paths for simple cache invalidation.
lessFiles[lessPath] = {
mtime: Date.now(),
imports: imports
};
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);
});
} catch (err) {
utilities.lessError(err);
return next(err);
}
});
};
// Force recompile of all files.
if (options.force) {
return compile();
}
// Only compile once, disregarding the file changes.
if (options.once && lessFiles[lessPath]) {
return next();
}
// Compile on (uncached) server restart and new files.
if (!lessFiles[lessPath]) {
return compile();
}
// Compare mtimes to determine if changed.
fs.stat(lessPath, function(err, lessStats){
if (err) {
return error(err);
}
fs.stat(cssPath, function(err, cssStats){
// CSS has not been compiled, compile it!
if (err) {
if ('ENOENT' == err.code) {
log('not found', cssPath);
// No CSS file found in dest
return compile();
}
return next(err);
}
if (lessStats.mtime > cssStats.mtime) {
// Source has changed, compile it
log('modified', cssPath);
return compile();
} else if (lessStats.mtime > lessFiles[lessPath].mtime) {
// This can happen if lessFiles[lessPath] was copied from
// 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
// lessFiles on exit). Since imports might have changed, we need to
// recompile.
log('cache file out of date for', lessPath);
return compile();
} else {
// Check if any of the less imports were changed
checkImports(lessPath, function(changed){
if(typeof changed != "undefined" && changed.length) {
log('modified import', changed);
return compile();
}
return next();
});
}
});
});
} else {
return next();
}
};
};
+58
View File
@@ -0,0 +1,58 @@
"use strict";
/*!
* Utiltiy methods for the less middleware.
*
* Copyright(c) 2014 Randy Merrill <Zoramite+github@gmail.com>
* MIT Licensed
*/
var regex = {
compress: /(\.|-)min\.css$/,
handle: /\.css(\.map)?$/,
sourceMap: /\.css\.map$/
};
module.exports = {
isCompressedPath: function(pathname) {
return regex.compress.test(pathname);
},
isSourceMap: function( pathname ){
return regex.sourceMap.test(pathname);
},
isValidPath: function(pathname) {
return regex.handle.test(pathname);
},
lessError: function(err) {
// An error while less is processing the file.
module.exports.log('LESS ' + err.type + ' error', err.message, 'error');
module.exports.log('LESS File', err.filename + ' ' + err.line + ':' + err.column, 'error');
},
log: function(key, value, type) {
// Only log for errors.
if(type !== 'error') {
return;
}
console[type](" \u001b[90m%s :\u001b[0m \u001b[36m%s\u001b[0m", key, value);
},
logDebug: function(key, value, type) {
switch(type) {
case 'log':
case 'info':
case 'error':
case 'warn':
break;
default:
type = 'log';
}
console[type](" \u001b[90m%s :\u001b[0m \u001b[36m%s\u001b[0m", key, value);
},
maybeCompressedSource: function(pathname) {
return (regex.compress.test(pathname)
? pathname.replace(regex.compress, '.less')
: pathname.replace('.css', '.less')
);
}
};
+22
View File
@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Randy Merrill <Zoramite+github@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+102
View File
@@ -0,0 +1,102 @@
{
"_args": [
[
{
"raw": "less-middleware@~2.2.1",
"scope": null,
"escapedName": "less-middleware",
"name": "less-middleware",
"rawSpec": "~2.2.1",
"spec": ">=2.2.1 <2.3.0",
"type": "range"
},
"/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp"
]
],
"_from": "less-middleware@>=2.2.1 <2.3.0",
"_id": "less-middleware@2.2.1",
"_inCache": true,
"_location": "/less-middleware",
"_nodeVersion": "8.2.1",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/less-middleware-2.2.1.tgz_1500918699559_0.3359121084213257"
},
"_npmUser": {
"name": "zoramite",
"email": "zoramite+npm@gmail.com"
},
"_npmVersion": "5.3.0",
"_phantomChildren": {},
"_requested": {
"raw": "less-middleware@~2.2.1",
"scope": null,
"escapedName": "less-middleware",
"name": "less-middleware",
"rawSpec": "~2.2.1",
"spec": ">=2.2.1 <2.3.0",
"type": "range"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/less-middleware/-/less-middleware-2.2.1.tgz",
"_shasum": "41bfc801b01acadb39bd380feda7fcc6a1da7b8c",
"_shrinkwrap": null,
"_spec": "less-middleware@~2.2.1",
"_where": "/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp",
"author": {
"name": "Randy Merrill",
"email": "Zoramite+github@gmail.com",
"url": "http://forthedeveloper.com"
},
"bugs": {
"url": "https://github.com/emberfeather/less.js-middleware/issues"
},
"dependencies": {
"less": "~2.7.1",
"mkdirp": "~0.5.1",
"node.extend": "~2.0.0"
},
"description": "LESS.js middleware for connect.",
"devDependencies": {
"express": "~4.15.3",
"fs-extra": "~4.0.0",
"mocha": "~3.4.2",
"supertest": "~3.0.0"
},
"directories": {},
"dist": {
"integrity": "sha512-1fDsyifwRGObMmqaZhkTDAmVnvgpZmdf6ZTSCbVv9vt+xhlzOz5TDNlLCbITsusEB3d0OKOEadwN9ic3PyOWCg==",
"shasum": "41bfc801b01acadb39bd380feda7fcc6a1da7b8c",
"tarball": "https://registry.npmjs.org/less-middleware/-/less-middleware-2.2.1.tgz"
},
"engines": {
"node": ">= 0.7.1"
},
"gitHead": "76f88860a2366ed9b9818f7087b2c45e4c03b633",
"homepage": "https://github.com/emberfeather/less.js-middleware#readme",
"license": "MIT",
"main": "lib/middleware.js",
"maintainers": [
{
"name": "zoramite",
"email": "Zoramite+node@gmail.com"
},
{
"name": "taxilian",
"email": "taxilian@gmail.com"
}
],
"name": "less-middleware",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git://github.com/emberfeather/less.js-middleware.git"
},
"scripts": {
"test": "mocha"
},
"version": "2.2.1"
}
+174
View File
@@ -0,0 +1,174 @@
This middleware was created to allow processing of [Less](http://lesscss.org) files for [Connect JS](http://www.senchalabs.org/connect/) framework and by extension the [Express JS](http://expressjs.com/) framework.
[![CircleCI](https://circleci.com/gh/emberfeather/less.js-middleware.svg?style=svg)](https://circleci.com/gh/emberfeather/less.js-middleware)
[![Dependency Status](https://david-dm.org/emberfeather/less.js-middleware.svg)](https://david-dm.org/emberfeather/less.js-middleware)
## Installation
```sh
npm install less-middleware --save
```
## Usage
```js
lessMiddleware(source, [{options}])
```
### Express
```js
var lessMiddleware = require('less-middleware');
var app = express();
app.use(lessMiddleware(__dirname + '/public'));
app.use(express.static(__dirname + '/public'));
```
### `options`
The following options can be used to control the behavior of the middleware:
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<th><code>debug</code></th>
<td>Show more verbose logging?</td>
<td><code>false</code></td>
</tr>
<tr>
<th><code>dest</code></th>
<td>Destination directory to output the compiled <code>.css</code> files.</td>
<td>Same directory as less source files.</td>
</tr>
<tr>
<th><code>force</code></th>
<td>Always re-compile less files on each request.</td>
<td><code>false</code></td>
</tr>
<tr>
<th><code>once</code></th>
<td>Only recompile once after each server restart. Useful for reducing disk i/o on production.</td>
<td><code>false</code></td>
</tr>
<tr>
<th><code>pathRoot</code></th>
<td>Common root of the source and destination. It is prepended to both the source and destination before being used.</td>
<td><code>null</code></td>
</tr>
<tr>
<th><code>postprocess</code></th>
<td>Object containing functions relevant to postprocessing data.</td>
<td></td>
</tr>
<tr>
<th><code>postprocess.css</code></th>
<td>Function that modifies the compiled css output before being stored.</td>
<td><code>function(css, req){...}</code></td>
</tr>
<tr>
<th><code>preprocess</code></th>
<td>Object containing functions relevant to preprocessing data.</td>
<td></td>
</tr>
<tr>
<th><code>preprocess.less</code></th>
<td>Function that modifies the raw less output before being parsed and compiled.</td>
<td><code>function(src, req){...}</code></td>
</tr>
<tr>
<th><code>preprocess.path</code></th>
<td>Function that modifies the less pathname before being loaded from the filesystem.</td>
<td><code>function(pathname, req){...}</code></td>
</tr>
<tr>
<th><code>preprocess.importPaths</code></th>
<td>Function that modifies the import paths used by the less parser per request.</td>
<td><code>function(paths, req){...}</code></td>
</tr>
<tr>
<th><code>render</code></th>
<td>Options for the less render. See the "<code>render</code> Options" section below.</td>
<td>&hellip;</td>
</tr>
<tr>
<th><code>storeCss</code></th>
<td>Function that is in charge of storing the css in the filesystem.</td>
<td><code>function(pathname, css, req, next){...}</code></td>
</tr>
<tr>
<th><code>cacheFile</code></th>
<td>Path to a JSON file that will be used to cache less data across server restarts. This can greatly speed up initial load time after a server restart - if the less files haven't changed and the css files still exist, specifying this option will mean that the less files don't need to be recompiled after a server restart.</td>
<td></td>
</tr>
</tbody>
</table>
## `render` Options
The `options.render` is passed directly into the `less.render` with minimal defaults or changes by the middleware.
The following are the defaults used by the middleware:
<table>
<thead>
<tr>
<th>Option</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<th><code>compress</code></th>
<td><code>auto</code></td>
</tr>
<tr>
<th><code>yuicompress</code></th>
<td><code>false</code></td>
</tr>
<tr>
<th><code>paths</code></th>
<td><code>[]</code></td>
</tr>
</tbody>
</table>
## Examples
Common examples of using the Less middleware are available in the [wiki](https://github.com/emberfeather/less.js-middleware/wiki/Examples).
## Troubleshooting
### My less never recompiles, even when I use `{force: true}`!
Make sure you're declaring less-middleware before your static middleware, if you're using the same directory, e.g. (with express):
```js
var lessMiddleware = require('less-middleware');
var app = express();
app.use(lessMiddleware(__dirname + '/public'));
app.use(express.static(__dirname + '/public'));
```
not
```js
var lessMiddleware = require('less-middleware');
var app = express();
app.use(express.static(__dirname + '/public'));
app.use(lessMiddleware(__dirname + '/public'));
```
### IIS
If you are hosting your app on IIS you will have to modify your `web.config` file in order to allow NodeJS to serve your CSS static files. IIS will cache your CSS files, bypassing NodeJS static file serving, which in turn does not allow the middleware to recompile your LESS files.
@@ -0,0 +1,18 @@
{
"{$}/import.less": {
"imports": [
{
"path": "{$}/import-header.less",
"mtime": null
},
{
"path": "{$}/import-widget.less",
"mtime": null
},
{
"path": "{$}/import-color.less",
"mtime": null
}
]
}
}
@@ -0,0 +1,10 @@
{
"{$}/import.less": {
"imports": [
{
"path": "{$}/import-color.less",
"mtime": null
}
]
}
}
@@ -0,0 +1 @@
@externalColor: #f03;
@@ -0,0 +1 @@
@paddingBox: 20px;
@@ -0,0 +1,2 @@
@titleColor: #f00;
@linkColor: #00f;
@@ -0,0 +1 @@
#header{color:#f00}.widget{color:#f00;background:#00f}
@@ -0,0 +1,3 @@
#header {
color: #ff0000;
}
@@ -0,0 +1,5 @@
@import "import-color";
#header {
color: @titleColor;
}
@@ -0,0 +1,4 @@
.widget {
color: #ff0000;
background: #0000ff;
}
@@ -0,0 +1,6 @@
@import "import-color";
.widget {
color: @titleColor;
background: @linkColor;
}
@@ -0,0 +1,7 @@
#header {
color: #ff0000;
}
.widget {
color: #ff0000;
background: #0000ff;
}
@@ -0,0 +1,2 @@
@import "import-header";
@import "import-widget";
@@ -0,0 +1 @@
a{color:#00f}
@@ -0,0 +1,3 @@
a {
color: #0000ff;
}
@@ -0,0 +1,5 @@
@import "import-color";
a {
color: @linkColor;
}
@@ -0,0 +1 @@
body{color:#d3d3d3}
@@ -0,0 +1,3 @@
body {
color: #d3d3d3;
}
@@ -0,0 +1,5 @@
@color1: #d3d3d3;
body {
color: @color1;
}
@@ -0,0 +1,2 @@
/* Prepended Comment */
.widget{color:#f00}
@@ -0,0 +1,3 @@
.widget {
color: #f00;
}
@@ -0,0 +1,3 @@
.widget {
color: #f00;
}
@@ -0,0 +1 @@
h1 .widget{color:#00f}
@@ -0,0 +1 @@
.widget{color:#00f}
@@ -0,0 +1,3 @@
.widget {
color: #00f;
}
@@ -0,0 +1,3 @@
.widget {
color: #00f;
}
@@ -0,0 +1 @@
.widget{color:#f03;padding:20px}
@@ -0,0 +1,6 @@
@import "externalvariables.less";
@import "ui.less";
.widget {
color: @externalColor;
padding: @paddingBox;
}
@@ -0,0 +1 @@
.widget{color:#0f0}
@@ -0,0 +1,3 @@
.widget {
color: #0f0;
}
@@ -0,0 +1,3 @@
.widget {
color: #0f0;
}
@@ -0,0 +1 @@
body{color:#d3d3d3}
@@ -0,0 +1 @@
{"version":3,"sources":["simple.less"],"names":[],"mappings":"AAEA,KACI"}
@@ -0,0 +1,3 @@
body {
color: #d3d3d3;
}
@@ -0,0 +1,5 @@
@color1: #d3d3d3;
body {
color: @color1;
}
+299
View File
@@ -0,0 +1,299 @@
"use strict";
var express = require('express');
var fs = require('fs');
var mkdirp = require('mkdirp');
var middleware = require('../lib/middleware');
var os = require('os');
var request = require('supertest');
var assert = require('assert');
var copySync = require('fs-extra').copySync;
var path = require('path');
var tmpDest = __dirname + '/artifacts';
var clearCache = function(filename) {
if(fs.existsSync(tmpDest + '/' + filename)) {
// Unlinking file since it is cached without reguard to params.
// TODO: Remove when the imports cache is aware of params.
fs.unlinkSync(tmpDest + '/' + filename);
}
};
var setupExpress = function(src, options, staticDest) {
staticDest = staticDest || options.dest;
options = options || {};
var app = express();
app.use(middleware(src, options));
app.use(express.static(staticDest));
return app;
}
describe('middleware', function(){
describe('simple', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest
});
it('should process simple less files', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/simple-exp.css', 'utf8');
request(app)
.get('/simple.css')
.expect(200)
.expect(expected, done);
});
});
describe('source map', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest,
force: true, // Need to force since using the same file as the simple test.
render: {
sourceMap: {
sourceMapBasepath: __dirname + '/fixtures'
}
}
});
it('should handle source map files', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/simple-exp.css.map', 'utf8');
request(app)
.get('/simple.css.map')
.expect(200)
.expect(expected, done);
});
});
describe('import', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest
});
it('should process less files with imports', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/importSimple-exp.css', 'utf8');
request(app)
.get('/importSimple.css')
.expect(200)
.expect(expected, done);
});
it('should process less files with nested imports', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/import-exp.css', 'utf8');
request(app)
.get('/import.css')
.expect(200)
.expect(expected, done);
});
});
describe('options', function(){
describe('postprocess', function(){
describe('css', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest,
postprocess: {
css: function(css, req) {
return '/* Prepended Comment */\n' + css;
}
}
});
it('should prepend the comment on all output css', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/postprocessCss-exp.css', 'utf8');
request(app)
.get('/postprocessCss.css')
.expect(200)
.expect(expected, done);
});
});
});
describe('preprocess', function(){
describe('less', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest,
preprocess: {
less: function(src, req) {
if (req.query.namespace) {
src = req.query.namespace + " { " + src + " }";
}
return src;
}
}
});
it('should add namespace when found', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/preprocessLess-exp-a.css', 'utf8');
clearCache('preprocessLess.css');
request(app)
.get('/preprocessLess.css?namespace=h1')
.expect(200)
.expect(expected, done);
});
it('should not add namespace when none provided', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/preprocessLess-exp-b.css', 'utf8');
clearCache('preprocessLess.css');
request(app)
.get('/preprocessLess.css')
.expect(200)
.expect(expected, done);
});
});
describe('path', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest,
preprocess: {
path: function(pathname, req) {
return pathname.replace('.ltr', '');
}
}
});
it('should remove .ltr from the less path when found', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/preprocessPath-exp.css', 'utf8');
request(app)
.get('/preprocessPath.ltr.css')
.expect(200)
.expect(expected, done);
});
it('should not change less path when no matching .ltr', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/preprocessPath-exp.css', 'utf8');
request(app)
.get('/preprocessPath.css')
.expect(200)
.expect(expected, done);
});
});
describe('importPaths', function(){
var app = setupExpress(__dirname + '/fixtures', {
dest: tmpDest,
preprocess: {
path: function(pathname, req) {
var returnPath = pathname.replace(/(\/[0-9\.0-9\.0-9].*\/)/, '/');
return returnPath;
},
importPaths: function(paths, req) {
var version = req.url.match(/\/([0-9\.0-9\.0-9]*)/);
var reqPath = path.join(__dirname, 'fixtures', 'external', version[1] , '/');
var paths = [
reqPath,
path.join(reqPath, 'ui')
];
return paths;
}
}
});
it('should respond with newly mapped paths', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/preprocessParserPaths-exp.css', 'utf8');
request(app)
.get('/2.43.3/preprocessParserPaths.css')
.expect(200)
.expect(expected, done);
});
});
describe('pathRoot', function(){
var app = setupExpress('/fixtures', {
dest: '/artifacts',
pathRoot: __dirname
}, tmpDest);
it('should process simple less files', function(done){
var expected = fs.readFileSync(__dirname + '/fixtures/pathRoot-exp.css', 'utf8');
request(app)
.get('/pathRoot.css')
.expect(200)
.expect(expected, done);
});
});
});
});
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);
}
var checkCacheFile = function(cacheFile, expectedFile){
var sortByPath = function(a, b) {
var keyA = a.path;
var keyB = b.path;
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
};
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(sortByPath);
var outputImports = cacheFileOutput[file].imports.sort(sortByPath);
assert.equal(outputImports.length, expectedImports.length);
for (var i = 0; i < expectedImports.length; i++) {
assert.equal(expectedImports[i].path, outputImports[i].path);
}
}
}
}
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 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);
});
});
});
+27
View File
@@ -0,0 +1,27 @@
"use strict";
var utilities = require('../lib/utilities');
var assert = require('assert');
describe('utilities', function(){
describe('#isCompressedPath()', function(){
it('should match path when valid path found', function(){
assert.equal(true, utilities.isCompressedPath('styles-min.css'));
assert.equal(true, utilities.isCompressedPath('styles.min.css'));
});
it('should not match path when invalid path found', function(){
assert.equal(false, utilities.isCompressedPath('styles.css'));
});
});
describe('#isValidPath()', function(){
it('should match path when valid path found', function(){
assert.equal(true, utilities.isValidPath('styles.css'));
});
it('should not match path when invalid path found', function(){
assert.equal(false, utilities.isValidPath('styles.less'));
});
});
});
+857
View File
@@ -0,0 +1,857 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
accepts@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
dependencies:
mime-types "~2.1.11"
negotiator "0.6.1"
ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
asn1@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
assert-plus@^1.0.0, assert-plus@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
aws-sign2@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
aws4@^1.2.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
balanced-match@^0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
bcrypt-pbkdf@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
dependencies:
tweetnacl "^0.14.3"
boom@2.x.x:
version "2.10.1"
resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
dependencies:
hoek "2.x.x"
brace-expansion@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
dependencies:
balanced-match "^0.4.1"
concat-map "0.0.1"
browser-stdout@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
buffer-shims@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
dependencies:
delayed-stream "~1.0.0"
commander@2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
graceful-readlink ">= 1.0.0"
component-emitter@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
content-disposition@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
content-type@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
cookiejar@^2.0.6:
version "2.1.1"
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a"
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
dependencies:
boom "2.x.x"
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
dependencies:
assert-plus "^1.0.0"
debug@^2.2.0:
version "2.6.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
dependencies:
ms "0.7.3"
debug@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b"
dependencies:
ms "0.7.2"
debug@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
dependencies:
ms "2.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
depd@~1.1.0, depd@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
diff@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
dependencies:
jsbn "~0.1.0"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
errno@^0.1.1:
version "0.1.4"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
dependencies:
prr "~0.0.0"
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
escape-string-regexp@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
etag@~1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
express@~4.15.3:
version "4.15.3"
resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
dependencies:
accepts "~1.3.3"
array-flatten "1.1.1"
content-disposition "0.5.2"
content-type "~1.0.2"
cookie "0.3.1"
cookie-signature "1.0.6"
debug "2.6.7"
depd "~1.1.0"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
finalhandler "~1.0.3"
fresh "0.5.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.1"
path-to-regexp "0.1.7"
proxy-addr "~1.1.4"
qs "6.4.0"
range-parser "~1.2.0"
send "0.15.3"
serve-static "1.12.3"
setprototypeof "1.0.3"
statuses "~1.3.1"
type-is "~1.6.15"
utils-merge "1.0.0"
vary "~1.1.1"
extend@^3.0.0, extend@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
extsprintf@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
finalhandler@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
dependencies:
debug "2.6.7"
encodeurl "~1.0.1"
escape-html "~1.0.3"
on-finished "~2.3.0"
parseurl "~1.3.1"
statuses "~1.3.1"
unpipe "~1.0.0"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
form-data@^2.1.1, form-data@~2.1.1:
version "2.1.4"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
mime-types "^2.1.12"
formidable@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9"
forwarded@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
fresh@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
fs-extra@~4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.0.tgz#414fb4ca2d2170ba0014159d3a8aec3303418d9e"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^3.0.0"
universalify "^0.1.0"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
dependencies:
assert-plus "^1.0.0"
glob@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.2"
once "^1.3.0"
path-is-absolute "^1.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
"graceful-readlink@>= 1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
growl@1.9.2:
version "1.9.2"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
dependencies:
ajv "^4.9.1"
har-schema "^1.0.5"
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
dependencies:
boom "2.x.x"
cryptiles "2.x.x"
hoek "2.x.x"
sntp "1.x.x"
hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
http-errors@~1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
dependencies:
depd "1.1.0"
inherits "2.0.3"
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
dependencies:
assert-plus "^0.2.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
image-size@~0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.1.tgz#28eea8548a4b1443480ddddc1e083ae54652439f"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
dependencies:
once "^1.3.0"
wrappy "1"
inherits@~2.0.1, inherits@2, inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
ipaddr.js@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
is@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5"
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
jodid25519@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
dependencies:
jsbn "~0.1.0"
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
json-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
dependencies:
jsonify "~0.0.0"
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
json3@3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
jsonfile@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.0.tgz#92e7c7444e5ffd5fa32e6a9ae8b85034df8347d0"
optionalDependencies:
graceful-fs "^4.1.6"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
jsprim@^1.2.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918"
dependencies:
assert-plus "1.0.0"
extsprintf "1.0.2"
json-schema "0.2.3"
verror "1.3.6"
less@~2.7.1:
version "2.7.2"
resolved "https://registry.yarnpkg.com/less/-/less-2.7.2.tgz#368d6cc73e1fb03981183280918743c5dcf9b3df"
optionalDependencies:
errno "^0.1.1"
graceful-fs "^4.1.2"
image-size "~0.5.0"
mime "^1.2.11"
mkdirp "^0.5.0"
promise "^7.1.1"
request "^2.72.0"
source-map "^0.5.3"
lodash._baseassign@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
dependencies:
lodash._basecopy "^3.0.0"
lodash.keys "^3.0.0"
lodash._basecopy@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
lodash._basecreate@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
lodash._isiterateecall@^3.0.0:
version "3.0.9"
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
lodash.create@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
dependencies:
lodash._baseassign "^3.0.0"
lodash._basecreate "^3.0.0"
lodash._isiterateecall "^3.0.0"
lodash.isarguments@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.keys@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
dependencies:
lodash._getnative "^3.0.0"
lodash.isarguments "^3.0.0"
lodash.isarray "^3.0.0"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
methods@^1.1.1, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
mime-db@~1.27.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
version "2.1.15"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
dependencies:
mime-db "~1.27.0"
mime@^1.2.11, mime@^1.3.4, mime@1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
minimatch@^3.0.2:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
mkdirp@^0.5.0, mkdirp@~0.5.1, mkdirp@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
mocha@~3.4.2:
version "3.4.2"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
dependencies:
browser-stdout "1.3.0"
commander "2.9.0"
debug "2.6.0"
diff "3.2.0"
escape-string-regexp "1.0.5"
glob "7.1.1"
growl "1.9.2"
json3 "3.3.2"
lodash.create "3.1.1"
mkdirp "0.5.1"
supports-color "3.1.2"
ms@0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
ms@0.7.3:
version "0.7.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
node.extend@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-2.0.0.tgz#7525a2875677ea534784a5e10ac78956139614df"
dependencies:
is "^3.2.1"
oauth-sign@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
dependencies:
ee-first "1.1.1"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
parseurl@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
promise@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
dependencies:
asap "~2.0.3"
proxy-addr@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
dependencies:
forwarded "~0.1.0"
ipaddr.js "1.3.0"
prr@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
qs@^6.1.0, qs@~6.4.0, qs@6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
range-parser@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
readable-stream@^2.0.5:
version "2.2.9"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
dependencies:
buffer-shims "~1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~1.0.0"
util-deprecate "~1.0.1"
request@^2.72.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
performance-now "^0.2.0"
qs "~6.4.0"
safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
tunnel-agent "^0.6.0"
uuid "^3.0.0"
safe-buffer@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
send@0.15.3:
version "0.15.3"
resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
dependencies:
debug "2.6.7"
depd "~1.1.0"
destroy "~1.0.4"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
fresh "0.5.0"
http-errors "~1.6.1"
mime "1.3.4"
ms "2.0.0"
on-finished "~2.3.0"
range-parser "~1.2.0"
statuses "~1.3.1"
serve-static@1.12.3:
version "1.12.3"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
dependencies:
encodeurl "~1.0.1"
escape-html "~1.0.3"
parseurl "~1.3.1"
send "0.15.3"
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
sntp@1.x.x:
version "1.0.9"
resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
dependencies:
hoek "2.x.x"
source-map@^0.5.3:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
sshpk@^1.7.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
dashdash "^1.12.0"
getpass "^0.1.1"
optionalDependencies:
bcrypt-pbkdf "^1.0.0"
ecc-jsbn "~0.1.1"
jodid25519 "^1.0.0"
jsbn "~0.1.0"
tweetnacl "~0.14.0"
"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
string_decoder@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
dependencies:
buffer-shims "~1.0.0"
stringstream@~0.0.4:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
superagent@^3.0.0:
version "3.5.2"
resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.5.2.tgz#3361a3971567504c351063abeaae0faa23dbf3f8"
dependencies:
component-emitter "^1.2.0"
cookiejar "^2.0.6"
debug "^2.2.0"
extend "^3.0.0"
form-data "^2.1.1"
formidable "^1.1.1"
methods "^1.1.1"
mime "^1.3.4"
qs "^6.1.0"
readable-stream "^2.0.5"
supertest@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/supertest/-/supertest-3.0.0.tgz#8d4bb68fd1830ee07033b1c5a5a9a4021c965296"
dependencies:
methods "~1.1.2"
superagent "^3.0.0"
supports-color@3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
dependencies:
has-flag "^1.0.0"
tough-cookie@~2.3.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
dependencies:
punycode "^1.4.1"
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
type-is@~1.6.15:
version "1.6.15"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
dependencies:
media-typer "0.3.0"
mime-types "~2.1.15"
universalify@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.0.tgz#9eb1c4651debcc670cc94f1a75762332bb967778"
unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
utils-merge@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
uuid@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
vary@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
verror@1.3.6:
version "1.3.6"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
dependencies:
extsprintf "1.0.2"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"