├── package.json ├── README.md └── index.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-revm-collector", 3 | "version": "1.0.1", 4 | "description": "Static asset revision data collector from manifests, generated from different streams, and replace their links in html template.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/WeideMo/gulp-revm-collector.git" 8 | }, 9 | "author": "", 10 | "main": "index.js", 11 | "scripts": { 12 | "test": "mocha" 13 | }, 14 | "keywords": [ 15 | "gulpplugin", 16 | "gulp", 17 | "rev", 18 | "revision", 19 | "version", 20 | "versioning", 21 | "static", 22 | "asset", 23 | "assets", 24 | "collect", 25 | "collector" 26 | ], 27 | "dependencies": { 28 | "gulp-util": "^3.0.0", 29 | "through2": ">=0.5.1", 30 | "underscore": "^1.6.0" 31 | }, 32 | "devDependencies": { 33 | "mocha": "*" 34 | }, 35 | "bugs": { 36 | "url": "https://github.com/WeideMo/gulp-revm-collector/issues" 37 | }, 38 | "homepage": "https://github.com/WeideMo/gulp-revm-collector", 39 | "readme": "ERROR: No README data found!" 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # [gulp](https://github.com/WeideMo/gulp-revm-collector)-revm-collector 3 | 4 | ## About 5 | 6 | > gulp-revm-collector is a modified version of gulp-rev-collector based on the main processing for appending the hash to filename with gulp-revm, in the plugin you can use all API as in gulp-rev-collector.gulp-revm through the gulp-revm can easily solve the page loading process cache with file-generated md5. 7 | 8 | ## Install 9 | 10 | ```sh 11 | $ npm install --save gulp-revm-collector 12 | ``` 13 | 14 | ## Usage 15 | 16 | We can use [gulp-revm](https://github.com/WeideMo/gulp-revm) to cache-bust several assets and generate manifest files for them. Then using gulp-revm-collector we can collect data from several manifest files and replace lincks to assets in html templates. 17 | 18 | ```js 19 | var gulp = require('gulp'); 20 | var rev = require('gulp-revm'); 21 | 22 | gulp.task('css', function () { 23 | return gulp.src('src/css/*.css') 24 | .pipe(rev()) 25 | .pipe(gulp.dest('dist/css')) 26 | .pipe( rev.manifest() ) 27 | .pipe( gulp.dest( 'rev/css' ) ); 28 | }); 29 | 30 | gulp.task('scripts', function () { 31 | return gulp.src('src/js/*.js') 32 | .pipe(rev()) 33 | .pipe(gulp.dest('dist/js')) 34 | .pipe( rev.manifest() ) 35 | .pipe( gulp.dest( 'rev/js' ) ); 36 | }); 37 | 38 | ... 39 | 40 | var revCollector = require('gulp-revm-collector'); 41 | var minifyHTML = require('gulp-minify-html'); 42 | 43 | gulp.task('rev', function () { 44 | return gulp.src(['rev/**/*.json', 'templates/**/*.html']) 45 | .pipe( revCollector({ 46 | replaceReved: true, 47 | dirReplacements: { 48 | 'css': '/dist/css', 49 | '/js/': '/dist/js/', 50 | 'cdn/': function(manifest_value) { 51 | return '//cdn' + (Math.floor(Math.random() * 9) + 1) + '.' + 'exsample.dot' + '/img/' + manifest_value; 52 | } 53 | } 54 | }) ) 55 | .pipe( minifyHTML({ 56 | empty:true, 57 | spare:true 58 | }) ) 59 | .pipe( gulp.dest('dist') ); 60 | }); 61 | ``` 62 | 63 | ### Options 64 | 65 | #### replaceReved 66 | 67 | Type : `Boolean` 68 | 69 | You set a flag, replaceReved, which will replace alredy replaced links in template's files. Default value is `false`. 70 | 71 | #### dirReplacements 72 | 73 | Specifies a directories replacement set. [gulp-revm](https://github.com/WeideMo/gulp-revm) creates manifest files without any info about directories. E.c. if you use dirReplacements param from [Usage](#usage) example, you get next replacement: 74 | 75 | ``` 76 | "/css/style.css" => "/dist/css/style.css?1d87bebe" 77 | "/js/script1.js" => "/dist/script1.js?61e0be79" 78 | "cdn/image.gif" => "//cdn8.example.dot/img/image.gif?35c3af8134" 79 | ``` 80 | 81 | #### revSuffix 82 | 83 | Type : `String` 84 | 85 | It is pattern for define reved files suffixes. Default value is '-[0-9a-f]{8,10}-?'. This is necessary in case of e.c. [gulp-rename](https://github.com/hparra/gulp-rename) usage. If reved filenames had different from default mask. 86 | 87 | 88 | ### Works with gulp-revm-collector 89 | 90 | - [gulp-revm](https://github.com/WeideMo/gulp-revm) -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var _ = require('underscore'); 3 | var gutil = require('gulp-util'); 4 | var PluginError = gutil.PluginError; 5 | var through = require('through2'); 6 | var path = require('path'); 7 | 8 | var PLUGIN_NAME = 'gulp-revm-collector'; 9 | 10 | var defaults = { 11 | revSuffix: '-[0-9a-f]{8,10}-?' 12 | }; 13 | 14 | function _getManifestData(file, opts) { 15 | var data; 16 | var ext = path.extname(file.path); 17 | if (ext === '.json') { 18 | var json = {}; 19 | try { 20 | var content = file.contents.toString('utf8'); 21 | if (content) { 22 | json = JSON.parse(content); 23 | } 24 | } catch (x) { 25 | this.emit('error', new PluginError(PLUGIN_NAME, x)); 26 | return; 27 | } 28 | if (_.isObject(json)) { 29 | var isRev = 1; 30 | Object.keys(json).forEach(function (key) { 31 | if ( path.basename(json[key]).split('?')[0] !== path.basename(key) ) { 32 | isRev = 0; 33 | } 34 | }); 35 | 36 | if (isRev) { 37 | data = json; 38 | } 39 | } 40 | 41 | } 42 | return data; 43 | } 44 | 45 | function escPathPattern(pattern) { 46 | return pattern.replace(/[\-\[\]\{\}\(\)\*\+\?\.\^\$\|\/\\]/g, "\\$&"); 47 | } 48 | 49 | function closeDirBySep(dirname) { 50 | return dirname + (!dirname || new RegExp( escPathPattern('/') + '$' ).test(dirname) ? '' : '/'); 51 | } 52 | 53 | function revCollector(opts) { 54 | opts = _.defaults((opts || {}), defaults); 55 | 56 | var manifest = {}; 57 | var mutables = []; 58 | return through.obj(function (file, enc, cb) { 59 | if (!file.isNull()) { 60 | var mData = _getManifestData.call(this, file, opts); 61 | if (mData) { 62 | _.extend( manifest, mData ); 63 | } else { 64 | mutables.push(file); 65 | } 66 | } 67 | cb(); 68 | }, function (cb) { 69 | var changes = []; 70 | var dirReplacements = []; 71 | if ( _.isObject(opts.dirReplacements) ) { 72 | Object.keys(opts.dirReplacements).forEach(function (srcDirname) { 73 | dirReplacements.push({ 74 | dirRX: escPathPattern( closeDirBySep(srcDirname) ), 75 | dirRpl: opts.dirReplacements[srcDirname] 76 | }); 77 | }); 78 | } 79 | 80 | for (var key in manifest) { 81 | var patterns = [ escPathPattern(key) ]; 82 | if (opts.replaceReved) { 83 | patterns.push( escPathPattern( (path.dirname(key) === '.' ? '' : closeDirBySep(path.dirname(key)) ) + path.basename(key, path.extname(key)) ) 84 | + opts.revSuffix 85 | + escPathPattern( path.extname(key) ) 86 | ); 87 | } 88 | 89 | if ( dirReplacements.length ) { 90 | dirReplacements.forEach(function (dirRule) { 91 | patterns.forEach(function (pattern) { 92 | changes.push({ 93 | regexp: new RegExp( dirRule.dirRX + pattern, 'g' ), 94 | patternLength: (dirRule.dirRX + pattern).length, 95 | replacement: _.isFunction(dirRule.dirRpl) 96 | ? dirRule.dirRpl(manifest[key]) 97 | : closeDirBySep(dirRule.dirRpl) + manifest[key] 98 | }); 99 | }); 100 | }); 101 | } else { 102 | patterns.forEach(function (pattern) { 103 | changes.push({ 104 | regexp: new RegExp( pattern, 'g' ), 105 | patternLength: pattern.length, 106 | replacement: manifest[key] 107 | }); 108 | }); 109 | } 110 | } 111 | 112 | // Replace longer patterns first 113 | // e.g. match `script.js.map` before `script.js` 114 | changes.sort( 115 | function(a, b) { 116 | return b.patternLength - a.patternLength; 117 | } 118 | ); 119 | mutables.forEach(function (file){ 120 | if (!file.isNull()) { 121 | var src = file.contents.toString('utf8'); 122 | changes.forEach(function (r) { 123 | src = src.replace(r.regexp, r.replacement); 124 | }); 125 | file.contents = new Buffer(src); 126 | } 127 | this.push(file); 128 | }, this); 129 | 130 | cb(); 131 | }); 132 | } 133 | 134 | module.exports = revCollector; 135 | --------------------------------------------------------------------------------