gulp-fingerprint
Advanced tools
Comparing version 0.3.1 to 0.3.2
78
index.js
@@ -5,3 +5,3 @@ 'use strict'; | ||
var gutil = require('gulp-util'); | ||
// var path = require('path'); | ||
var path = require('path'); | ||
var split = require('split2'); | ||
@@ -23,5 +23,7 @@ var through = require('through2'); | ||
// var regex = new RegExp('url\\("(.*)"\\)|src="(.*)"|href="(.*)"|url\\(\'(.*)\'\\)|src=\'(.*)\'|href=\'(.*)\'', 'g'); | ||
var regex = /(?:url\(["']?(.*?)['"]?\)|src=["']{1}(.*?)['"]{1}|src=([^\s\>]+)(?:\>|\s)|href=["']{1}(.*?)['"]{1}|href=([^\s\>]+)(?:\>|\s))/g; | ||
var regex = /(?:url\(["']?(.*?)['"]?\)|src=["'](.*?)['"]|src=([^\s\>]+)(?:\>|\s)|href=["'](.*?)['"]|href=([^\s\>]+)(?:\>|\s))/g; | ||
var prefix = ''; | ||
var base; | ||
var base = ''; | ||
var strip = ''; | ||
var mode = 'regex'; | ||
var content = []; | ||
@@ -34,5 +36,23 @@ | ||
if (options.base) base = new RegExp('^\/' + options.base + '|^' + options.base); | ||
if (options.base) base = options.base.replace(/^\//, ''); | ||
function urlReplace(buf, enc, cb) { | ||
if (options.strip) strip = options.strip.replace(/^\//, ''); | ||
if (options.mode === 'replace') { | ||
mode = 'replace'; | ||
} | ||
if (strip) { | ||
var stripRegex = new RegExp('^\/' + strip + '|^' + strip); | ||
} | ||
if (base) { | ||
var baseRegex = new RegExp('^\/' + base + '|^' + base); | ||
} | ||
if (typeof(manifest) === 'string') { | ||
manifest = require(path.resolve(manifest)); | ||
} | ||
function regexMode(buf, enc, cb) { | ||
var line = buf.toString(); | ||
@@ -42,7 +62,12 @@ | ||
var url = Array.prototype.slice.call(arguments, 1).filter(function(a) {return a;})[0]; | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Found:', chalk.yellow(m.replace(/^\//, ''))); | ||
var replaced = manifest[url] || manifest[url.replace(/^\//, '')] || manifest[url.split('?')[0]]; | ||
if (!replaced && base) replaced = manifest[url.replace(base, '')]; | ||
if (replaced) str = str.replace(url, prefix + replaced); | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Replaced:', chalk.green(line)); | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Found:', chalk.yellow(url.replace(/^\//, ''))); | ||
var replaced = manifest[url] || manifest[url.replace(/^\//, '')] || manifest[url.split(/[#?]/)[0]]; | ||
if (!replaced && base) replaced = manifest[url.replace(baseRegex, '')]; | ||
if (replaced) { | ||
if (strip) { | ||
replaced = replaced.replace(stripRegex, ''); | ||
} | ||
str = str.replace(url, prefix + replaced); | ||
} | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Replaced:', chalk.green(prefix + replaced)); | ||
return str; | ||
@@ -55,2 +80,33 @@ }); | ||
function replaceMode(buf, enc, cb) { | ||
var line = buf.toString(); | ||
base = base.replace(/(^\/|\/$)/g, ''); | ||
for (var url in manifest) { | ||
var dest = manifest[url], replaced, bases; | ||
if (strip) { | ||
replaced = prefix + dest.replace(stripRegex, ''); | ||
} else { | ||
replaced = prefix + dest; | ||
} | ||
bases = ['/', '']; | ||
if (base) { | ||
bases.unshift('/' + base + '/', base + '/'); | ||
} | ||
for (var i = 0; i < bases.length; i++) { | ||
var newLine = line.split(bases[i] + url).join(replaced); | ||
if (line !== newLine) { | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Found:', chalk.yellow(url.replace(/^\//, ''))); | ||
if (options.verbose) gutil.log(PLUGIN_NAME, 'Replaced:', chalk.green(prefix + replaced)); | ||
line = newLine; | ||
break; | ||
} | ||
} | ||
} | ||
content.push(line); | ||
cb(); | ||
} | ||
var stream = through.obj(function(file, enc, cb) { | ||
@@ -75,3 +131,3 @@ var that = this; | ||
file.pipe(split()) | ||
.pipe(through(urlReplace, function(callback) { | ||
.pipe(through(mode === 'regex' ? regexMode : replaceMode, function(callback) { | ||
if (content.length) { | ||
@@ -78,0 +134,0 @@ file.contents = new Buffer(content.join('\n')); |
{ | ||
"name": "gulp-fingerprint", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"description": "Rename assets with fingerprinted assets", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -41,3 +41,3 @@ # [gulp](http://gulpjs.com)-fingerprint [![Build Status](https://travis-ci.org/vincentmac/gulp-fingerprint.svg?branch=master)](https://travis-ci.org/vincentmac/gulp-fingerprint) | ||
_Type_: `object` | ||
_Type_: `object, string` | ||
@@ -53,4 +53,13 @@ _Example_: `rev-manifest.json` produced from using [gulp-rev](https://www.npmjs.org/package/gulp-rev) | ||
If it's a string, it will be interpretered as path to json file. | ||
#### options | ||
##### mode | ||
_Type_: `string` | ||
_Default_: `regex` | ||
_Usage_: Setting a `prefix` will change the method of url replacing. There are two methods: `regex` and `replace`. Second method is less accurate but doesn't require to specify complicated regular expression. | ||
##### regex | ||
@@ -61,10 +70,13 @@ _Type_: [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) | ||
_ **Note** The default regex, `url\\("(.*)"\\)|src="(.*)"|href="(.*)"|url\\(\'(.*)\'\\)|src=\'(.*)\'|href=\'(.*)\'`, will match:_ | ||
_ **Note** The default regex, `/(?:url\(["']?(.*?)['"]?\)|src=["'](.*?)['"]|src=([^\s\>]+)(?:\>|\s)|href=["'](.*?)['"]|href=([^\s\>]+)(?:\>|\s))/g`, will match: | ||
- `url('path/to/resource')` | ||
- `url("path/to/resource")` | ||
- `url(path/to/resource)` | ||
- `href='path/to/resource'` | ||
- `href="path/to/resource"` | ||
- `href=path/to/resource` | ||
- `src='path/to/resource'` | ||
- `src="path/to/resource"` | ||
- `src=path/to/resource` | ||
@@ -96,2 +108,15 @@ ##### prefix | ||
##### strip | ||
_Type_: `string` | ||
_Usage_: Setting a `strip` will remove that string from the beginning of a result path | ||
```js | ||
... | ||
.pipe(fingerprint(manifest, {strip: 'images/'})) | ||
... | ||
// Original: `background-image: url("/images/some-logo2.png");` | ||
// Replaced: `background-image: url("some-logo2-abd84715.png");` in src file | ||
``` | ||
##### verbose | ||
@@ -98,0 +123,0 @@ _Type_: `boolean` |
{ | ||
"images/favicon.ico": "images/favicon.ico?v=99999", | ||
"images/favicon.ico": "images/favicon-99999.ico", | ||
"js/site.js": "js/site.js?v=10923", | ||
"js/other.js": "js/other.js?v=190283091" | ||
} |
@@ -11,3 +11,3 @@ /* globals it*/ | ||
+ '<title>Some Web Site</title>\n' | ||
+ '<link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico?v=74180833826528598c89f0d4949473a7">\n' | ||
+ '<link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico#v=74180833826528598c89f0d4949473a7">\n' | ||
+ ' <script src="js/site.js?v=c625c1e4b5dd80acb73126287946fd5b"></script>\n' | ||
@@ -20,26 +20,34 @@ + ' <script src="js/other.js"></script>\n' | ||
it('should replace query string based fingerprints', function (done) { | ||
var stream = fingerprint(manifest, {regex: /(?:href=|src=)"([^\"]*)"/}); | ||
['regex', 'replace'].forEach(function(mode) { | ||
stream.on('data', function (file) { | ||
var updatedHTML = file.contents.toString(); | ||
// console.log(updatedHTML); | ||
var regex1 = /images\/favicon\.ico\?v=99999/; | ||
var regex2 = /js\/site\.js\?v=10923/; | ||
var regex3 = /js\/other\.js\?v=190283091/; | ||
var match1 = regex1.exec(updatedHTML); | ||
var match2 = regex2.exec(updatedHTML); | ||
var match3 = regex3.exec(updatedHTML); | ||
describe('in `' + mode + '` mode', function () { | ||
assert.equal(match1[0], 'images/favicon.ico?v=99999'); | ||
assert.equal(match2[0], 'js/site.js?v=10923'); | ||
assert.equal(match3[0], 'js/other.js?v=190283091'); | ||
done(); | ||
it('should replace query string based fingerprints', function (done) { | ||
var stream = fingerprint(manifest, {regex: /(?:href=|src=)"([^\"]*)"/}); | ||
stream.on('data', function (file) { | ||
var updatedHTML = file.contents.toString(); | ||
// console.log(updatedHTML); | ||
var regex1 = /images\/favicon-99999\.ico/; | ||
var regex2 = /js\/site\.js\?v=10923/; | ||
var regex3 = /js\/other\.js\?v=190283091/; | ||
var match1 = regex1.exec(updatedHTML); | ||
var match2 = regex2.exec(updatedHTML); | ||
var match3 = regex3.exec(updatedHTML); | ||
assert.equal(match1[0], 'images/favicon-99999.ico'); | ||
assert.equal(match2[0], 'js/site.js?v=10923'); | ||
assert.equal(match3[0], 'js/other.js?v=190283091'); | ||
done(); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.html', | ||
contents: new Buffer(fakeFile) | ||
})); | ||
}); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.html', | ||
contents: new Buffer(fakeFile) | ||
})); | ||
}); |
243
test/test.js
@@ -33,138 +33,167 @@ /* globals it*/ | ||
it('should update multiple assets in one file', function (done) { | ||
var stream = fingerprint(manifest); | ||
['regex', 'replace'].forEach(function(mode) { | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/g; | ||
var regex2 = /images\/some-logo-abd84705.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
describe('in `' + mode + '` mode', function() { | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
done(); | ||
}); | ||
it('should update multiple assets in one file', function (done) { | ||
var stream = fingerprint(manifest, { mode: mode }); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/g; | ||
var regex2 = /images\/some-logo-abd84705.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
done(); | ||
}); | ||
it('should prepend assets in one file', function (done) { | ||
var stream = fingerprint(manifest, {prefix: 'https://cdn.example.com/'}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /https\:\/\/cdn.example.com\/images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /https\:\/\/cdn.example.com\/images\/some-logo-abd84705.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'https://cdn.example.com/images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'https://cdn.example.com/images/some-logo-abd84705.png'); | ||
done(); | ||
}); | ||
it('should prepend assets in one file', function (done) { | ||
var stream = fingerprint(manifest, {prefix: 'https://cdn.example.com/'}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /https\:\/\/cdn.example.com\/images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /https\:\/\/cdn.example.com\/images\/some-logo-abd84705.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'https://cdn.example.com/images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'https://cdn.example.com/images/some-logo-abd84705.png'); | ||
done(); | ||
}); | ||
it('should match assets with an optional base', function (done) { | ||
var stream = fingerprint(manifest, {base: 'assets/'}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /images\/some-logo-abd84705.png/; | ||
var regex3 = /images\/some-logo2-abd84715.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
var match3 = regex3.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
assert.equal(match3[0], 'images/some-logo2-abd84715.png'); | ||
done(); | ||
}); | ||
it('should match assets with an optional base', function (done) { | ||
var stream = fingerprint(manifest, {base: 'assets/'}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /images\/some-logo-abd84705.png/; | ||
var regex3 = /images\/some-logo2-abd84715.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
var match3 = regex3.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
assert.equal(match3[0], 'images/some-logo2-abd84715.png'); | ||
done(); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
it('should match assets with an optional base and prepend text', function (done) { | ||
var stream = fingerprint(manifest, { | ||
base: 'assets\\/', | ||
prefix: 'https://cdn.example.com/' | ||
}); | ||
}); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /https\:\/\/cdn.example.com\/images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /https\:\/\/cdn.example.com\/images\/some-logo-abd84705.png/; | ||
var regex3 = /https\:\/\/cdn.example.com\/images\/some-logo2-abd84715.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
var match3 = regex3.exec(updatedCSS); | ||
assert.equal(match1[0], 'https://cdn.example.com/images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'https://cdn.example.com/images/some-logo-abd84705.png'); | ||
assert.equal(match3[0], 'https://cdn.example.com/images/some-logo2-abd84715.png'); | ||
done(); | ||
}); | ||
it('should match assets with an optional base and prepend text', function (done) { | ||
var stream = fingerprint(manifest, { | ||
base: 'assets\\/', | ||
prefix: 'https://cdn.example.com/' | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /https\:\/\/cdn.example.com\/images\/body-bg-2d4a1176.jpg/; | ||
var regex2 = /https\:\/\/cdn.example.com\/images\/some-logo-abd84705.png/; | ||
var regex3 = /https\:\/\/cdn.example.com\/images\/some-logo2-abd84715.png/; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
var match3 = regex3.exec(updatedCSS); | ||
}); | ||
assert.equal(match1[0], 'https://cdn.example.com/images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'https://cdn.example.com/images/some-logo-abd84705.png'); | ||
assert.equal(match3[0], 'https://cdn.example.com/images/some-logo2-abd84715.png'); | ||
done(); | ||
}); | ||
it('should match several assets in one line', function(done) { | ||
var stream = fingerprint(manifest); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex = /images\/body-bg-2d4a1176.jpg/g; | ||
}); | ||
assert.equal(updatedCSS.match(regex).length, 2); | ||
done(); | ||
}); | ||
it('should match several assets in one line', function(done) { | ||
var stream = fingerprint(manifest, { mode: mode }); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
}); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex = /images\/body-bg-2d4a1176.jpg/g; | ||
it('should match assets in html', function(done) { | ||
var stream = fingerprint(manifest); | ||
assert.equal(updatedCSS.match(regex).length, 2); | ||
done(); | ||
}); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/g; | ||
var regex2 = /images\/some-logo-abd84705.png/g; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
}); | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
assert.equal(updatedCSS.match(regex1).length, 3); | ||
assert.equal(updatedCSS.match(regex2).length, 3); | ||
done(); | ||
it('should match assets in html', function(done) { | ||
var stream = fingerprint(manifest, { mode: mode }); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /images\/body-bg-2d4a1176.jpg/g; | ||
var regex2 = /images\/some-logo-abd84705.png/g; | ||
var match1 = regex1.exec(updatedCSS); | ||
var match2 = regex2.exec(updatedCSS); | ||
assert.equal(match1[0], 'images/body-bg-2d4a1176.jpg'); | ||
assert.equal(match2[0], 'images/some-logo-abd84705.png'); | ||
assert.equal(updatedCSS.match(regex1).length, 3); | ||
assert.equal(updatedCSS.match(regex2).length, 3); | ||
done(); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.html', | ||
contents: new Buffer(fakeHtmlFile) | ||
})); | ||
}); | ||
it('should strip asset path', function (done) { | ||
var stream = fingerprint(manifest, { | ||
strip: '/images/' | ||
}); | ||
stream.on('data', function (file) { | ||
var updatedCSS = file.contents.toString(); | ||
var regex1 = /"body-bg-2d4a1176.jpg"/g; | ||
var match1 = regex1.exec(updatedCSS); | ||
assert.equal(match1[0], '"body-bg-2d4a1176.jpg"'); | ||
done(); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.css', | ||
contents: new Buffer(fakeCssFile) | ||
})); | ||
}); | ||
}); | ||
stream.write(new gutil.File({ | ||
path: 'app.html', | ||
contents: new Buffer(fakeHtmlFile) | ||
})); | ||
}); |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
17510
328
132
1