Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/build/browserify.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var fs = require('fs');
var path = require('path');
var through = require('through2');
var merge = require('lodash.merge');
var trackFilenames = require('gulp-track-filenames');
var transformTools = require('browserify-transform-tools');
var browserify = require('browserify');
Expand Down Expand Up @@ -230,10 +231,11 @@ function compile(bannerWidth, transforms) {
// transforms
transforms
.concat(requireTransform(false))
.filter(function (candidate) {
return (typeof candidate === 'function');
}).forEach(function (item) {
bundler.transform(item, { global: true });
.forEach(function (item, i, list) {
if (typeof item === 'function') {
var opts = (typeof list[i+1] === 'object') ? merge({ global: true }, list[i+1]) : { global: true };
bundler.transform(item, opts);
}
});

// require statements
Expand Down
148 changes: 87 additions & 61 deletions lib/build/node-sass.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var path = require('path');
var fs = require('fs');
var through = require('through2');
var minimatch = require('minimatch');
var sass = require('node-sass');
var gutil = require('gulp-util');
var slash = require('gulp-slash');
Expand All @@ -12,52 +11,76 @@ var SourceMapConsumer = require('source-map').SourceMapConsumer;
var mime = require('mime');

/**
* Search for the relative file reference from the <code>startPath</code> up to, but not including, the process
* working directory.
* @param {string} startPath The path to which the <code>relative</code> path might be specified
* @param {string} relative A possibly relative file path
* @param {string} [callerPath] The full path of the invoking function instance where recursion has occured
* Search for the relative file reference from the <code>startPath</code> up to the process
* working directory, avoiding any other directories with a <code>package.json</code> or <code>bower.json</code>.
* @param {string} startPath The location of the uri declaration and the place to start the search from
* @param {string} uri The content of the url() statement, expected to be a relative file path
* @returns {string} dataURI of the file where found or <code>undefined</code> otherwise
*/
function encodeRelativeURL(startPath, relative, callerPath) {

// ensure we are at a valid start path that is not process working directory
var absStart = path.resolve(startPath);
var parentDir = path.resolve(path.join(absStart, '..'));
if (fs.existsSync(absStart)) {
var fullPath = path.resolve(path.join(startPath, relative));
if (fs.existsSync(fullPath)) {

// file exists so get the dataURI
var type = mime.lookup(fullPath);
var contents = fs.readFileSync(fullPath);
var base64 = new Buffer(contents).toString('base64');
return 'url(data:' + type + ';base64,' + base64 + ')';

} else if (parentDir !== process.cwd()) { // will not jump across bower or npm packages

// find parent and child directories
var childDirs = fs.readdirSync(absStart)
.map(function toAbsolute(filename) {
return path.join(absStart, filename);
}).filter(function directoriesOnly(absolute) {
return fs.statSync(absolute).isDirectory();
});
function encodeRelativeURL(startPath, uri) {
'use strict';

// recurse paths down and up except the caller path
// return the first success
var result;
childDirs.concat(parentDir)
.filter(function excludeCallerDir(absoluteDir) {
return (absoluteDir !== callerPath);
})
.some(function encode(absoluteDir) {
result = encodeRelativeURL(absoluteDir, relative, absStart);
return result;
});
/**
* Test whether the given directory is the root of its own package
* @param {string} absolutePath An absolute path
* @returns {boolean} True where a package.json or bower.json exists, else False
*/
function notPackage(absolutePath) {
return ['package.json', 'bower.json'].every(function fileNotFound(file) {
return !(fs.existsSync(path.resolve(absolutePath, file)));
});
}

// ignore data uris and ensure we are at a valid start path
var absoluteStart = !(/^data\:/.test(uri)) && path.resolve(startPath);
if (absoluteStart) {

// find path to the root, stopping at cwd, package.json or bower.json
var pathToRoot = [ ];
do {
pathToRoot.push(absoluteStart);
var isWorking = (absoluteStart !== process.cwd()) && notPackage(absoluteStart);
absoluteStart = path.resolve(absoluteStart, '..');
} while (isWorking);

// may be undefined
return result;
// start a queue with the path to the root
var queue = pathToRoot.concat();

// process the queue until empty
// the queue pattern ensures that we favour paths closest the the start path
while (queue.length) {

// shift the first item off the queue, consider it the base for our relative uri
var basePath = queue.shift();
var fullPath = path.resolve(basePath, uri);

// file exists so convert to a dataURI and end
if (fs.existsSync(fullPath)) {
var type = mime.lookup(fullPath);
var contents = fs.readFileSync(fullPath);
var base64 = new Buffer(contents).toString('base64');
return 'url(data:' + type + ';base64,' + base64 + ')';
}
// enqueue subdirectories that are not packages and are not in the root path
else {
fs.readdirSync(basePath)
.filter(function notHidden(filename) {
return (filename.charAt(0) !== '.');
})
.map(function toAbsolute(filename) {
return path.join(basePath, filename);
})
.filter(function directoriesOnly(absolutePath) {
return fs.statSync(absolutePath).isDirectory();
})
.filter(function notInRootPath(absolutePath) {
return (pathToRoot.indexOf(absolutePath) < 0);
})
.filter(notPackage)
.forEach(function enqueue(absolutePath) {
queue.push(absolutePath);
});
}
}
}
}
Expand Down Expand Up @@ -124,10 +147,13 @@ module.exports = function (bannerWidth, libraryPaths) {
line: cssStart.line,
column: cssStart.column
});
if (!sassStart.source) {
throw new Error('failed to decode node-sass source map'); // this can occur with regressions in libsass
}
var sassDir = path.dirname(sassStart.source);

// allow multiple url() values in the declaration
// the url will be every second value (i % 2)
// the uri will be every second value (i % 2)
declaration.value = declaration.value
.split(/url\s*\(\s*['"]?([^'"?#]*)[^)]*\)/g) // split by url statements
.map(function (token, i) {
Expand All @@ -139,21 +165,20 @@ module.exports = function (bannerWidth, libraryPaths) {

/**
* Handler for successful transpilation using node-sass.
* This functions gets called with an object containing a CSS file and its source-map,
* which is modified and passed through CSS rework, before being pushed to the results.
* @param {string} css Compiled css
* @param {string} map The source-map for the compiled css
*/
function successHandler(css, map) {

// adjust sourcemap
var source = minimatch.makeRe(file.cwd).source
.replace(/^\^|\$$/g, '') // match text anywhere on the line by removing line start/end
.replace(/\\\//g, '[\\\\\\/]') + // detect any platform path format
'|\\.\\.\\/'; // relative paths are an artifact and must be removed
var parsable = slash(map.replace(new RegExp(source, 'g'), ''));
var sourceMap = JSON.parse(parsable);
// adjust source-map
var sourceMap = convert.fromJSON(map).toObject();
sourceMap.sources.forEach(function (value, i, array) {
array[i] = path.resolve(value.replace(/^\//, '').replace(/\b\/+\b/g, '/')); // ensure single slash absolute
});

// prepare the adjusted sass source-map for later look-ups
sourceMapConsumer = new SourceMapConsumer(sourceMap);

// embed sourcemap in css
Expand All @@ -179,7 +204,7 @@ module.exports = function (bannerWidth, libraryPaths) {

// write stream output
pushResult('.css', reworked.code + '\n/*# sourceMappingURL=' + mapName + ' */');
pushResult('.css.map', JSON.stringify(reworked.map, null, ' '));
pushResult('.css.map', JSON.stringify(reworked.map, null, 2));
done();
}

Expand Down Expand Up @@ -208,19 +233,20 @@ module.exports = function (bannerWidth, libraryPaths) {
}

// perform the sass render
sass.render({
file: file.path,
data: file.contents.toString(),
success: successHandler,
error: errorHandler,
sass.render({
file : file.path,
data : file.contents.toString(),
success : successHandler,
error : errorHandler,
includePaths: libList,
outputStyle: 'compressed',
stats: { },
sourceMap: mapName
outputStyle : 'compressed',
stats : { },
sourceMap : mapName
});

// display the output buffer with padding before and after and between each item
}, function (done) {

// display the output buffer with padding before and after and between each item
if (output.length) {
var width = Number(bannerWidth) || 0;
var hr = new Array(width + 1); // this is a good trick to repeat a character N times
Expand Down
43 changes: 21 additions & 22 deletions lib/test/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ var karmaReporterMatchNameRegex = /^karma-(.+)-reporter$/ ;
*/
function getKarmaReporterPluginPath(reporterName) {
if (typeof reporterName !== 'string') {
throw 'Get Karma Reporter Plugin Path: Reporter name is unspecified';
throw 'Reporter name is unspecified';
}

//Default reporter is a dependency of angularity
Expand All @@ -61,8 +61,7 @@ function getKarmaReporterPluginPath(reporterName) {
require(reporterPath);
}
catch (ex) {
throw 'Get Karma Reporter Plugin Path: Attempt to require reporter from path ' +
reporterPath + ' with no success.';
throw 'Attempt to require reporter from path ' + reporterPath + ' with no success.';
}
reporterPath = path.normalize(reporterPath);

Expand Down Expand Up @@ -128,8 +127,8 @@ function karmaCreateConfig(reporters, configFileName) {
else {
//non-javascript files, such as source maps, should be included but not tested
files.push({
pattern: file.path,
included: false,
pattern : file.path,
included: false
});
}
transformDone();
Expand Down Expand Up @@ -164,8 +163,8 @@ function karmaCreateConfig(reporters, configFileName) {

function specTransformFn(file, encoding, specFileDone) {
files.push({
pattern: file.path,
included: false,
pattern : file.path,
included: false
});
specFileDone();
}
Expand Down Expand Up @@ -219,8 +218,8 @@ function karmaRun(reporters, bannerWidth) {
//NOTE this workaround is necessary, see issue:
//https://github.com/sindresorhus/supports-color/issues/13
//TODO @bguiz remove workaround when issue has been resolved
SUPPORTS_COLOR: true,
}),
SUPPORTS_COLOR: true
})
});
karmaBackground.on('close', function(exitCode) {
done();
Expand All @@ -229,37 +228,37 @@ function karmaRun(reporters, bannerWidth) {
});
};

var yargsOptionDefiniton = {
key: 'karmareporter',
var yargsOptionDefinition = {
key: 'karma-reporter',
value: {
describe: 'Specify a custom Karma reporter to use. ' +
'Either a locally npm installed module, or an asolute path to one.',
alias: ['k'],
default: defaultReporterName,
string:true,
describe: 'Specify a custom Karma reporter to use. Either a locally npm installed module, or an asolute path to ' +
'one.',
alias : ['k'],
default : defaultReporterName,
string : true
}
};
var checkKarmaReporter = yargs.createCheck()
.withGate(function (argv) {
return !argv.help;
})
.withTest({
karmareporter: function(value) {
'karma-reporter': function(value) {
if (typeof value !== 'undefined') {
try {
getKarmaReporterPluginPath(value);
}
catch (ex) {
return 'Illegal value for "reporter"\n' + ex;
return 'Illegal value for "karma-reporter": ' + ex;
}
}
},
}
})
.commit();

module.exports = {
createConfig: karmaCreateConfig,
run: karmaRun,
yargsCheck: checkKarmaReporter,
yargsOption: yargsOptionDefiniton,
run : karmaRun,
yargsCheck : checkKarmaReporter,
yargsOption : yargsOptionDefinition
};
18 changes: 9 additions & 9 deletions lib/util/jshint-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function getJsHintReporter(reporterName) {
// establish a cached copy
if (!resolvedReporter) {
if (typeof reporterName !== 'string') {
throw 'Get JsHint Reporter: Reporter name is unspecified';
throw 'Reporter name is unspecified';
}
else {
var reporterPath;
Expand All @@ -58,7 +58,7 @@ function getJsHintReporter(reporterName) {
}
});
if (!resolvedReporter) {
throw 'Get JsHint Reporter: Attempt to require specified reporter with no success.';
throw 'Attempt to require specified reporter with no success.';
}
}
}
Expand All @@ -73,34 +73,34 @@ function getJsHintReporter(reporterName) {
return gulpJshint.reporter(resolvedReporter);
}
else {
throw 'Get JsHint Reporter: Given reporter is badly formed';
throw 'Given reporter is badly formed';
}
}

var yargsOptionDefiniton = {
key: 'reporter',
key: 'jshint-reporter',
value: {
describe: 'Specify a custom JsHint reporter to use. Either a locally npm installed module, or the absolute path ' +
'to one.',
alias: ['r'],
default: defaultReporterName,
string: true
alias : ['j'],
default : defaultReporterName,
string : true
}
};
var checkJsHintReporter = yargs.createCheck()
.withGate(function (argv) {
return !argv.help;
})
.withTest({
reporter: function(value) {
'jshint-reporter': function(value) {
if (typeof value === 'undefined') {
return;
}
try {
getJsHintReporter(value);
}
catch (ex) {
return 'Illegal value for "reporter"\n' + ex;
return 'Illegal value for "jshint-reporter": ' + ex;
}
}
})
Expand Down
Loading