gulp-cdnizer
Advanced tools
Comparing version 0.1.3 to 0.2.1
171
index.js
var through = require("through2"), | ||
gutil = require("gulp-util"), | ||
minimatch = require('minimatch'), | ||
merge = require('deepmerge'), | ||
fs = require('fs'), | ||
path = require('path'), | ||
_ = require('lodash'); | ||
cdnizer = require('cdnizer'); | ||
var error = function(msg) { | ||
return new gutil.PluginError("gulp-cdnizer", msg); | ||
}, | ||
parseOptions = function(opts) { | ||
if(!opts || (typeof opts !== 'object' && !Array.isArray(opts))) { | ||
throw error("No options or invalid options supplied"); | ||
} | ||
if(Array.isArray(opts)) { | ||
opts = {files: opts}; | ||
} | ||
if(!Array.isArray(opts.files) || opts.files.length === 0) { | ||
throw error("Invalid or empty files list supplied"); | ||
} | ||
opts = merge({ | ||
defaultCDNBase: '', | ||
defaultCDN: '<%= defaultCDNBase %>/<%= filepathRel %>', | ||
allowRev: true, | ||
allowMin: true, | ||
bowerComponents: null, | ||
// escaped to prevent IntelliJ from being too smart | ||
fallbackScript: '<scr'+'ipt>function cdnizerLoad(u) {document.write(\'<scr\'+\'ipt src="\'+encodeURIComponent(u)+\'"></scr\'+\'ipt>\');}</script>', | ||
fallbackTest: '<scr'+'ipt>if(!(${ test })) cdnizerLoad("${ filepath }");</script>', | ||
shouldAddFallback: false | ||
}, opts); | ||
opts.files = opts.files.map(function(fileInfo) { | ||
if(typeof fileInfo === 'string' && fileInfo.length > 0) { | ||
fileInfo = { file: fileInfo }; | ||
} | ||
if(!fileInfo.file || typeof fileInfo.file !== 'string') { | ||
throw error('File declaration is invalid'); | ||
} | ||
if(fileInfo.test) { | ||
opts.shouldAddFallback = true; | ||
} | ||
if(opts.allowMin && fileInfo.file.indexOf('.min') === -1) { | ||
fileInfo.file = fileInfo.file.replace(/\.(.*)$/, '.?(min.)$1'); | ||
} | ||
if(opts.allowRev) { | ||
fileInfo.file = fileInfo.file.replace(/(\..*)$/, '?(-????????)$1'); | ||
} | ||
return fileInfo; | ||
}); | ||
opts.defaultCDNBase = opts.defaultCDNBase.replace(/\/$/, ''); | ||
return opts; | ||
}, | ||
matchers = [ | ||
{ pattern: /(<script\s.*?src=["'])(.+?)(["'].*?>\s*<\/script>)/gi, fallback: true }, | ||
{ pattern: /(<link\s.*?href=["'])(.+?)(["'].*?>\s*<\/link>)/gi, fallback: true }, | ||
{ pattern: /(<link\s.*?href=["'])(.+?)(["'].*?\/?>)/gi, fallback: true }, | ||
{ pattern: /(<img\s.*?src=["'])(.+?)(["'])/gi, fallback: false }, | ||
{ pattern: /(url\()(.+?)(\))/gi, fallback: false } | ||
]; | ||
function pluginError(msg) { | ||
return new gutil.PluginError("gulp-cdnizer", msg); | ||
} | ||
module.exports = function(opts) { | ||
"use strict"; | ||
opts = parseOptions(opts); | ||
function findFileInfo(url) { | ||
url = decodeURIComponent(url); | ||
return _.find(opts.files, function(fileInfo) { | ||
return minimatch(url, fileInfo.file); | ||
}); | ||
} | ||
var bowerRoot = './bower_components', | ||
bowerrc; | ||
if(opts.bowerComponents) { | ||
bowerRoot = opts.bowerComponents; | ||
} else if(fs.existsSync('./.bowerrc')) { | ||
bowerrc = JSON.parse(require('fs').readFileSync('./.bowerrc', {encoding: 'utf8'})); | ||
if(bowerrc && bowerrc.directory) { | ||
bowerRoot = path.join('.', bowerrc.directory); | ||
} | ||
} | ||
var versionInfoCache = {}; | ||
function getVersionInfo(pkg) { | ||
if(!pkg) return {}; | ||
if(!versionInfoCache[pkg]) { | ||
var packageInfo, version, packageRoot = path.join(process.cwd(), bowerRoot, pkg); | ||
if(fs.existsSync(path.join(packageRoot, 'bower.json'))) { | ||
packageInfo = require(path.join(packageRoot, 'bower.json')); | ||
} else if(fs.existsSync(path.join(packageRoot, '.bower.json'))) { | ||
packageInfo = require(path.join(packageRoot, '.bower.json')); | ||
} else { | ||
throw error('Unable to load bower.json for package "'+pkg+'". Looked under "'+packageRoot+'"'); | ||
} | ||
version = (packageInfo.version || '0.0.0').match(/(\d+)?\.(\d+)?\.(\d+)?/); | ||
versionInfoCache[pkg] = { | ||
version: packageInfo.version || '0.0.0', | ||
major: version[1] || 0, | ||
minor: version[2] || 0, | ||
patch: version[3] || 0 | ||
} | ||
} | ||
return versionInfoCache[pkg]; | ||
} | ||
function getFilenameMin(url) { | ||
url = path.basename(url); | ||
if(opts.allowRev) { | ||
url = url.replace(/-\w{8}(\..+)$/, '$1'); | ||
} | ||
url = url.replace(/\.(min\.)?(\..+)$/, '.min.$2'); | ||
return url; | ||
} | ||
var cdnizerHandler = cdnizer(opts); | ||
function cdnizer(file, enc, callback) { | ||
//noinspection JSUnusedLocalSymbols | ||
function cdnizerStream(file, enc, callback) { | ||
@@ -131,3 +25,3 @@ // Do nothing if no contents | ||
if(file.isStream()) { | ||
this.emit("error", error("Stream content is not supported")); | ||
this.emit("error", pluginError("Stream content is not supported")); | ||
return callback(); | ||
@@ -138,45 +32,8 @@ } | ||
if(file.isBuffer()) { | ||
var contents = String(file.contents), | ||
canAddFallback = opts.shouldAddFallback && contents.indexOf('<head') !== -1, | ||
didAddFallback = false; | ||
matchers.forEach(function(m) { | ||
contents = contents.replace(m.pattern, function(match, pre, url, post) { | ||
var fileInfo = findFileInfo(url), result, params; | ||
if(fileInfo) { | ||
result = pre; | ||
params = merge(getVersionInfo(fileInfo.package), { | ||
defaultCDNBase: opts.defaultCDNBase, | ||
filepath: url, | ||
filepathRel: url.replace(/^\//, ''), | ||
filename: path.basename(url), | ||
filenameMin: getFilenameMin(url), | ||
package: fileInfo.package, | ||
test: fileInfo.test | ||
}); | ||
result += _.template(fileInfo.cdn || opts.defaultCDN, params); | ||
result += post; | ||
if(canAddFallback && m.fallback && fileInfo.test) { | ||
result += _.template(opts.fallbackTest, params); | ||
didAddFallback = true; | ||
} | ||
return result; | ||
} else { | ||
// do nothing | ||
return match; | ||
} | ||
}); | ||
}); | ||
if(didAddFallback) { | ||
contents = contents.replace(/<link|<script|<\/head/i, function(m) { | ||
return opts.fallbackScript + m; | ||
}); | ||
try { | ||
file.contents = new Buffer(cdnizerHandler(String(file.contents))); | ||
this.push(file); | ||
} catch(error) { | ||
this.emit("error", error(error.toString())) | ||
} | ||
file.contents = new Buffer(contents); | ||
this.push(file); | ||
} | ||
@@ -186,3 +43,3 @@ return callback(); | ||
return through.obj(cdnizer); | ||
return through.obj(cdnizerStream); | ||
}; |
{ | ||
"name": "gulp-cdnizer", | ||
"version": "0.1.3", | ||
"version": "0.2.1", | ||
"description": "A plugin for Gulp", | ||
@@ -28,5 +28,3 @@ "keywords": [ | ||
"gulp-util": "~2.2.0", | ||
"minimatch": "~0.2.14", | ||
"deepmerge": "~0.2.7", | ||
"lodash": "~2.4.1" | ||
"cdnizer": "*" | ||
}, | ||
@@ -33,0 +31,0 @@ "devDependencies": { |
@@ -82,2 +82,14 @@ # gulp-cdnizer | ||
Works great on `url()`s in CSS files, too: | ||
```js | ||
gulp.src("./src/css/style.css") | ||
.pipe(cdnizer({ | ||
defaultCDNBase: '//my.cdn.url/', | ||
relativeRoot: 'css', | ||
files: ['**/*.{gif,png,jpg,jpeg}'] | ||
}) | ||
.pipe(gulp.dest("./dist/css/")); | ||
``` | ||
## API | ||
@@ -103,2 +115,11 @@ | ||
#### options.relativeRoot | ||
Type: `String` | ||
Default: `''` | ||
If you are processing a file that references relative files, or is not rooted to the CDN, you can set `relativeRoot` to get correct results. | ||
For example, if you have a CSS file under `style/`, and you reference images as `../img/foo.png`, you should set `relativeRoot` to `style/`. Now if your `defaultCDNBase` is `//example/`, the image will be resolved to `//example/img/foo.png`. | ||
#### options.allowRev | ||
@@ -105,0 +126,0 @@ Type: `Boolean` |
Sorry, the diff of this file is not supported yet
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
3
232
0
13063
5
33
3
+ Addedcdnizer@*
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedcdnizer@3.3.0(transitive)
+ Addedcdnjs-cdn-data@0.1.2(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedgoogle-cdn-data@0.1.25(transitive)
+ Addedjsdelivr-cdn-data@1.0.4(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedsemver@5.0.3(transitive)
- Removeddeepmerge@~0.2.7
- Removedlodash@~2.4.1
- Removedminimatch@~0.2.14
- Removeddeepmerge@0.2.10(transitive)
- Removedlodash@2.4.2(transitive)
- Removedlru-cache@2.7.3(transitive)
- Removedminimatch@0.2.14(transitive)
- Removedsigmund@1.0.1(transitive)