From eaf3bd3bf476ae852247be9edd35f9ab1622aba1 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:16:14 +0800 Subject: [PATCH 01/12] Update Node test matrix --- .github/workflows/main.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 18531b3..d50ada6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,13 +10,12 @@ jobs: fail-fast: false matrix: node-version: + - 18 + - 16 - 14 - - 12 - - 10 - - 8 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm install From 90edf9c09bf09030ede0ffca61ceafa55a78a420 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:19:48 +0800 Subject: [PATCH 02/12] Update through2@4.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 869dcc1..e2ae4d7 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "rev-hash": "^3.0.0", "rev-path": "^2.0.0", "sort-keys": "^4.0.0", - "through2": "^3.0.1", + "through2": "^4.0.2", "vinyl": "^2.1.0", "vinyl-file": "^3.0.0" }, From e23c31b209eee01894d121ad5b1dc2264b48b62e Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:21:35 +0800 Subject: [PATCH 03/12] Update plugin-error@2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2ae4d7..d809304 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ ], "dependencies": { "modify-filename": "^1.1.0", - "plugin-error": "^1.0.1", + "plugin-error": "^2.0.1", "rev-hash": "^3.0.0", "rev-path": "^2.0.0", "sort-keys": "^4.0.0", From 06781d2d0ee22ea2b50d00e470a6ca967ab0b2d2 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:23:15 +0800 Subject: [PATCH 04/12] Update vinyl@3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d809304..aa8644e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "rev-path": "^2.0.0", "sort-keys": "^4.0.0", "through2": "^4.0.2", - "vinyl": "^2.1.0", + "vinyl": "^3.0.0", "vinyl-file": "^3.0.0" }, "devDependencies": { From 9ba4fc925c1804d28dffdf0dad6f7b3096437969 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:23:48 +0800 Subject: [PATCH 05/12] Require node>=14 in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aa8644e..f86805e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "url": "sindresorhus.com" }, "engines": { - "node": ">=8" + "node": ">=14" }, "scripts": { "test": "xo && ava" From 53269bb2d5c616ce24a74d7e3e95af7817401961 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 00:47:53 +0800 Subject: [PATCH 06/12] Update dependencies and move to ESM --- index.js | 36 +++++++++++------------ package.json | 19 +++++++------ test/_helper.js | 5 ++-- test/manifest.js | 50 +++++++++++++++++--------------- test/rev.js | 74 ++++++++++++++++++++++++++---------------------- 5 files changed, 99 insertions(+), 85 deletions(-) diff --git a/index.js b/index.js index 6aaa8ea..52a4e49 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,13 @@ -'use strict'; -const path = require('path'); -const through = require('through2'); -const vinylFile = require('vinyl-file'); -const revHash = require('rev-hash'); -const revPath = require('rev-path'); -const sortKeys = require('sort-keys'); -const modifyFilename = require('modify-filename'); -const Vinyl = require('vinyl'); -const PluginError = require('plugin-error'); +import {Buffer} from 'node:buffer'; +import path from 'node:path'; +import through from 'through2'; +import {vinylFile} from 'vinyl-file'; +import revHash from 'rev-hash'; +import {revPath} from 'rev-path'; +import sortKeys from 'sort-keys'; +import modifyFilename from 'modify-filename'; +import Vinyl from 'vinyl'; +import PluginError from 'plugin-error'; function relativePath(base, filePath) { filePath = filePath.replace(/\\/g, '/'); @@ -35,9 +35,9 @@ function transformFilename(file) { file.path = modifyFilename(file.path, (filename, extension) => { const extIndex = filename.lastIndexOf('.'); - filename = extIndex === -1 ? - revPath(filename, file.revHash) : - revPath(filename.slice(0, extIndex), file.revHash) + filename.slice(extIndex); + filename = extIndex === -1 + ? revPath(filename, file.revHash) + : revPath(filename.slice(0, extIndex), file.revHash) + filename.slice(extIndex); return filename + extension; }); @@ -45,7 +45,7 @@ function transformFilename(file) { const getManifestFile = async options => { try { - return await vinylFile.read(options.path, options); + return await vinylFile(options.path, options); } catch (error) { if (error.code === 'ENOENT') { return new Vinyl(options); @@ -89,7 +89,7 @@ const plugin = () => { // Attempt to parse the sourcemap's JSON to get the reverse filename try { reverseFilename = JSON.parse(file.contents.toString()).file; - } catch (_) {} + } catch {} if (!reverseFilename) { reverseFilename = path.relative(path.dirname(file.path), path.basename(file.path, '.map')); @@ -123,7 +123,7 @@ plugin.manifest = (path_, options) => { merge: false, transformer: JSON, ...options, - ...path_ + ...path_, }; let manifest = {}; @@ -157,7 +157,7 @@ plugin.manifest = (path_, options) => { try { oldManifest = options.transformer.parse(manifestFile.contents.toString()); - } catch (_) {} + } catch {} manifest = Object.assign(oldManifest, manifest); } @@ -172,4 +172,4 @@ plugin.manifest = (path_, options) => { }); }; -module.exports = plugin; +export default plugin; diff --git a/package.json b/package.json index f86805e..842d3f9 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,14 @@ "description": "Static asset revisioning by appending content hash to filenames: unicorn.css => unicorn-d41d8cd98f.css", "license": "MIT", "repository": "sindresorhus/gulp-rev", + "funding": "https://github.com/sponsors/sindresorhus", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", "url": "sindresorhus.com" }, + "type": "module", + "exports": "./index.js", "engines": { "node": ">=14" }, @@ -34,19 +37,19 @@ "assets" ], "dependencies": { - "modify-filename": "^1.1.0", + "modify-filename": "^2.0.0", "plugin-error": "^2.0.1", - "rev-hash": "^3.0.0", - "rev-path": "^2.0.0", - "sort-keys": "^4.0.0", + "rev-hash": "^4.0.0", + "rev-path": "^3.0.0", + "sort-keys": "^5.0.0", "through2": "^4.0.2", "vinyl": "^3.0.0", - "vinyl-file": "^3.0.0" + "vinyl-file": "^5.0.0" }, "devDependencies": { - "ava": "^2.3.0", - "p-event": "^4.1.0", - "xo": "^0.24.0" + "ava": "^5.1.0", + "p-event": "^5.0.1", + "xo": "^0.53.1" }, "peerDependencies": { "gulp": ">=4" diff --git a/test/_helper.js b/test/_helper.js index b5456d7..5df1eaf 100644 --- a/test/_helper.js +++ b/test/_helper.js @@ -1,3 +1,4 @@ +import {Buffer} from 'node:buffer'; import Vinyl from 'vinyl'; export default function createFile({ @@ -8,13 +9,13 @@ export default function createFile({ revName, cwd, base, - contents = '' + contents = '', }) { const file = new Vinyl({ path, cwd, base, - contents: Buffer.from(contents) + contents: Buffer.from(contents), }); file.revOrigPath = revOrigPath; file.revOrigBase = revOrigBase; diff --git a/test/manifest.js b/test/manifest.js index a7289bd..101a5b5 100644 --- a/test/manifest.js +++ b/test/manifest.js @@ -1,8 +1,12 @@ -import path from 'path'; +import {Buffer} from 'node:buffer'; +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; import test from 'ava'; -import pEvent from 'p-event'; -import rev from '..'; -import createFile from './_helper'; +import {pEvent} from 'p-event'; +import rev from '../index.js'; +import createFile from './_helper.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const manifestFixture = './test.manifest-fixture.json'; const manifestFixturePath = path.join(__dirname, manifestFixture); @@ -14,14 +18,14 @@ test('builds a rev manifest file', async t => { stream.end(createFile({ path: 'unicorn-d41d8cd98f.css', - revOrigPath: 'unicorn.css' + revOrigPath: 'unicorn.css', })); const file = await data; t.is(file.relative, 'rev-manifest.json'); t.deepEqual( JSON.parse(file.contents.toString()), - {'unicorn.css': 'unicorn-d41d8cd98f.css'} + {'unicorn.css': 'unicorn-d41d8cd98f.css'}, ); }); @@ -32,7 +36,7 @@ test('allows naming the manifest file', async t => { stream.end(createFile({ path: 'unicorn-d41d8cd98f.css', - revOrigPath: 'unicorn.css' + revOrigPath: 'unicorn.css', })); const file = await data; @@ -42,13 +46,13 @@ test('allows naming the manifest file', async t => { test('appends to an existing rev manifest file', async t => { const stream = rev.manifest({ path: manifestFixturePath, - merge: true + merge: true, }); const data = pEvent(stream, 'data'); stream.end(createFile({ path: 'unicorn-d41d8cd98f.css', - revOrigPath: 'unicorn.css' + revOrigPath: 'unicorn.css', })); const file = await data; @@ -57,8 +61,8 @@ test('appends to an existing rev manifest file', async t => { JSON.parse(file.contents.toString()), { 'app.js': 'app-a41d8cd1.js', - 'unicorn.css': 'unicorn-d41d8cd98f.css' - } + 'unicorn.css': 'unicorn-d41d8cd98f.css', + }, ); }); @@ -68,37 +72,37 @@ test('does not append to an existing rev manifest by default', async t => { stream.end(createFile({ path: 'unicorn-d41d8cd98f.css', - revOrigPath: 'unicorn.css' + revOrigPath: 'unicorn.css', })); const file = await data; t.is(file.relative, manifestFixtureRelative); t.deepEqual( JSON.parse(file.contents.toString()), - {'unicorn.css': 'unicorn-d41d8cd98f.css'} + {'unicorn.css': 'unicorn-d41d8cd98f.css'}, ); }); test('sorts the rev manifest keys', async t => { const stream = rev.manifest({ path: manifestFixturePath, - merge: true + merge: true, }); const data = pEvent(stream, 'data'); stream.write(createFile({ path: 'unicorn-d41d8cd98f.css', - revOrigPath: 'unicorn.css' + revOrigPath: 'unicorn.css', })); stream.end(createFile({ path: 'pony-d41d8cd98f.css', - revOrigPath: 'pony.css' + revOrigPath: 'pony.css', })); const file = await data; t.deepEqual( Object.keys(JSON.parse(file.contents.toString())), - ['app.js', 'pony.css', 'unicorn.css'] + ['app.js', 'pony.css', 'unicorn.css'], ); }); @@ -113,7 +117,7 @@ test('respects directories', async t => { revOrigPath: path.join(__dirname, 'foo', 'unicorn.css'), revOrigBase: __dirname, origName: 'unicorn.css', - revName: 'unicorn-d41d8cd98f.css' + revName: 'unicorn-d41d8cd98f.css', })); stream.end(createFile({ cwd: __dirname, @@ -122,7 +126,7 @@ test('respects directories', async t => { revOrigBase: __dirname, revOrigPath: path.join(__dirname, 'bar', 'pony.css'), origName: 'pony.css', - revName: 'pony-d41d8cd98f.css' + revName: 'pony-d41d8cd98f.css', })); const MANIFEST = {}; @@ -146,7 +150,7 @@ test('respects files coming from directories with different bases', async t => { revOrigBase: path.join(__dirname, 'vendor1'), revOrigPath: path.join(__dirname, 'vendor1', 'foo', 'scriptfoo.js'), origName: 'scriptfoo.js', - revName: 'scriptfoo-d41d8cd98f.js' + revName: 'scriptfoo-d41d8cd98f.js', })); stream.end(createFile({ cwd: __dirname, @@ -155,7 +159,7 @@ test('respects files coming from directories with different bases', async t => { revOrigBase: path.join(__dirname, 'vendor2'), revOrigPath: path.join(__dirname, 'vendor2', 'bar', 'scriptbar.js'), origName: 'scriptfoo.js', - revName: 'scriptfoo-d41d8cd98f.js' + revName: 'scriptfoo-d41d8cd98f.js', })); const MANIFEST = {}; @@ -175,13 +179,13 @@ test('uses correct base path for each file', async t => { cwd: 'app/', base: 'app/', path: path.join('app', 'foo', 'scriptfoo-d41d8cd98f.js'), - revOrigPath: 'scriptfoo.js' + revOrigPath: 'scriptfoo.js', })); stream.end(createFile({ cwd: '/', base: 'assets/', path: path.join('/assets', 'bar', 'scriptbar-d41d8cd98f.js'), - revOrigPath: 'scriptbar.js' + revOrigPath: 'scriptbar.js', })); const MANIFEST = {}; diff --git a/test/rev.js b/test/rev.js index a47ba87..c406d20 100644 --- a/test/rev.js +++ b/test/rev.js @@ -1,15 +1,15 @@ -import path from 'path'; +import path from 'node:path'; import test from 'ava'; -import pEvent from 'p-event'; -import rev from '..'; -import createFile from './_helper'; +import {pEvent, pEventIterator} from 'p-event'; +import rev from '../index.js'; +import createFile from './_helper.js'; test('revs files', async t => { const stream = rev(); const data = pEvent(stream, 'data'); stream.end(createFile({ - path: 'unicorn.css' + path: 'unicorn.css', })); const file = await data; @@ -22,7 +22,7 @@ test('adds the revision hash before the first `.` in the filename', async t => { const data = pEvent(stream, 'data'); stream.end(createFile({ - path: 'unicorn.css.map' + path: 'unicorn.css.map', })); const file = await data; @@ -35,7 +35,7 @@ test('stores the hashes for later', async t => { const data = pEvent(stream, 'data'); stream.end(createFile({ - path: 'unicorn.css' + path: 'unicorn.css', })); const file = await data; @@ -44,64 +44,70 @@ test('stores the hashes for later', async t => { t.is(file.revHash, 'd41d8cd98f'); }); -test.cb('handles sourcemaps transparently', t => { +test('handles sourcemaps transparently', async t => { const stream = rev(); - - stream.on('data', file => { - if (path.extname(file.path) === '.map') { - t.is(file.path, path.normalize('maps/pastissada-d41d8cd98f.css.map')); - t.end(); - } + const data = pEventIterator(stream, 'data', { + resolutionEvents: ['finish'], }); stream.write(createFile({ - path: 'pastissada.css' + path: 'pastissada.css', })); stream.end(createFile({ path: 'maps/pastissada.css.map', - contents: JSON.stringify({file: 'pastissada.css'}) + contents: JSON.stringify({file: 'pastissada.css'}), })); -}); -test.cb('handles unparseable sourcemaps correctly', t => { - const stream = rev(); - - stream.on('data', file => { + for await (const file of data) { if (path.extname(file.path) === '.map') { - t.is(file.path, 'pastissada-d41d8cd98f.css.map'); - t.end(); + t.is(file.path, path.normalize('maps/pastissada-d41d8cd98f.css.map')); } + } +}); + +test('handles unparseable sourcemaps correctly', async t => { + const stream = rev(); + const data = pEventIterator(stream, 'data', { + resolutionEvents: ['finish'], }); stream.write(createFile({ - path: 'pastissada.css' + path: 'pastissada.css', })); stream.end(createFile({ path: 'pastissada.css.map', - contents: 'Wait a minute, this is invalid JSON!' + contents: 'Wait a minute, this is invalid JSON!', })); -}); - -test.cb('okay when the optional sourcemap.file is not defined', t => { - const stream = rev(); - stream.on('data', file => { + for await (const file of data) { if (path.extname(file.path) === '.map') { t.is(file.path, 'pastissada-d41d8cd98f.css.map'); - t.end(); } + } +}); + +test('okay when the optional sourcemap.file is not defined', async t => { + const stream = rev(); + const data = pEventIterator(stream, 'data', { + resolutionEvents: ['finish'], }); stream.write(createFile({ - path: 'pastissada.css' + path: 'pastissada.css', })); stream.end(createFile({ path: 'pastissada.css.map', - contents: JSON.stringify({}) + contents: JSON.stringify({}), })); + + for await (const file of data) { + if (path.extname(file.path) === '.map') { + t.is(file.path, 'pastissada-d41d8cd98f.css.map'); + } + } }); test('handles a `.` in the folder name', async t => { @@ -109,7 +115,7 @@ test('handles a `.` in the folder name', async t => { const data = pEvent(stream, 'data'); stream.end(createFile({ - path: 'mysite.io/unicorn.css' + path: 'mysite.io/unicorn.css', })); const file = await data; From b77b437b89c2d9aa386c5a3239aba2a6acba6096 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 01:02:06 +0800 Subject: [PATCH 07/12] Update examples in README.md --- readme.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/readme.md b/readme.md index d87fe35..49b83f3 100644 --- a/readme.md +++ b/readme.md @@ -16,13 +16,13 @@ $ npm install --save-dev gulp-rev ## Usage ```js -const gulp = require('gulp'); -const rev = require('gulp-rev'); +import {src, dest} from 'gulp'; +import rev from 'gulp-rev'; -exports.default = () => ( - gulp.src('src/*.css') +export default () => ( + src('src/*.css') .pipe(rev()) - .pipe(gulp.dest('dist')) + .pipe(dest('dist')) ); ``` @@ -83,18 +83,18 @@ The hash of each rev'd file is stored at `file.revHash`. You can use this for cu ### Asset manifest ```js -const gulp = require('gulp'); -const rev = require('gulp-rev'); +import {src, dest} from 'gulp'; +import rev from 'gulp-rev'; -exports.default = () => ( +export default = () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: - gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) - .pipe(gulp.dest('build/assets')) // Copy original assets to build dir + src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) + .pipe(dest('build/assets')) // Copy original assets to build dir .pipe(rev()) - .pipe(gulp.dest('build/assets')) // Write rev'd assets to build dir + .pipe(dest('build/assets')) // Write rev'd assets to build dir .pipe(rev.manifest()) - .pipe(gulp.dest('build/assets')) // Write manifest to build dir + .pipe(dest('build/assets')) // Write manifest to build dir ); ``` @@ -110,21 +110,21 @@ An asset manifest, mapping the original paths to the revisioned paths, will be w By default, `rev-manifest.json` will be replaced as a whole. To merge with an existing manifest, pass `merge: true` and the output destination (as `base`) to `rev.manifest()`: ```js -const gulp = require('gulp'); -const rev = require('gulp-rev'); +import {src, dest} from 'gulp'; +import rev from 'gulp-rev'; -exports.default = () => ( +export default = () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: - gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) - .pipe(gulp.dest('build/assets')) + src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) + .pipe(dest('build/assets')) .pipe(rev()) - .pipe(gulp.dest('build/assets')) + .pipe(dest('build/assets')) .pipe(rev.manifest({ base: 'build/assets', merge: true // Merge with the existing manifest if one exists })) - .pipe(gulp.dest('build/assets')) + .pipe(dest('build/assets')) ); ``` @@ -136,18 +136,18 @@ Because of the way `gulp-concat` handles file paths, you may need to set `cwd` a ```js const gulp = require('gulp'); -const rev = require('gulp-rev'); const sourcemaps = require('gulp-sourcemaps'); const concat = require('gulp-concat'); -exports.default = () => ( - gulp.src('src/*.js') +exports.default = async () => { + const {default: rev} = await import('gulp-rev'); + return gulp.src('src/*.js') .pipe(sourcemaps.init()) .pipe(concat({path: 'bundle.js', cwd: ''})) .pipe(rev()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('dist')) -); +}; ``` ## Different hash for unchanged files @@ -167,16 +167,16 @@ const gulp = require('gulp'); const browserify = require('browserify'); const source = require('vinyl-source-stream'); const buffer = require('gulp-buffer'); -const rev = require('gulp-rev'); -exports.default = () => ( - browserify('src/index.js') +exports.default = async () => { + const {default: rev} = await import('gulp-rev'); + return browserify('src/index.js') .bundle({debug: true}) .pipe(source('index.min.js')) .pipe(buffer()) .pipe(rev()) .pipe(gulp.dest('dist')) -); +}; ``` ## Integration From 59c5e4ed1624500ead82d3dbb6f67fadb96ff797 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Fri, 9 Dec 2022 23:04:31 +0800 Subject: [PATCH 08/12] Replace through2 with easy-transform-stream --- index.js | 57 +++++++++++++++++++++------------------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index 52a4e49..37231a5 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ import {Buffer} from 'node:buffer'; import path from 'node:path'; -import through from 'through2'; +import transformStream from 'easy-transform-stream'; import {vinylFile} from 'vinyl-file'; import revHash from 'rev-hash'; import {revPath} from 'rev-path'; @@ -59,21 +59,18 @@ const plugin = () => { const sourcemaps = []; const pathMap = {}; - return through.obj((file, encoding, callback) => { + return transformStream({objectMode: true}, file => { if (file.isNull()) { - callback(null, file); - return; + return file; } if (file.isStream()) { - callback(new PluginError('gulp-rev', 'Streaming not supported')); - return; + throw new PluginError('gulp-rev', 'Streaming not supported'); } // This is a sourcemap, hold until the end if (path.extname(file.path) === '.map') { sourcemaps.push(file); - callback(); return; } @@ -81,8 +78,10 @@ const plugin = () => { transformFilename(file); pathMap[oldPath] = file.revHash; - callback(null, file); - }, function (callback) { + return file; + }, () => { + const files = []; + for (const file of sourcemaps) { let reverseFilename; @@ -106,10 +105,10 @@ const plugin = () => { transformFilename(file); } - this.push(file); + files.push(file); } - callback(); + return files; }); }; @@ -128,10 +127,9 @@ plugin.manifest = (path_, options) => { let manifest = {}; - return through.obj((file, encoding, callback) => { + return transformStream({objectMode: true}, file => { // Ignore all non-rev'd files if (!file.path || !file.revOrigPath) { - callback(); return; } @@ -139,36 +137,27 @@ plugin.manifest = (path_, options) => { const originalFile = path.join(path.dirname(revisionedFile), path.basename(file.revOrigPath)).replace(/\\/g, '/'); manifest[originalFile] = revisionedFile; - - callback(); - }, function (callback) { + }, async function * () { // No need to write a manifest file if there's nothing to manifest if (Object.keys(manifest).length === 0) { - callback(); return; } - (async () => { - try { - const manifestFile = await getManifestFile(options); + const manifestFile = await getManifestFile(options); - if (options.merge && !manifestFile.isNull()) { - let oldManifest = {}; + if (options.merge && !manifestFile.isNull()) { + let oldManifest = {}; - try { - oldManifest = options.transformer.parse(manifestFile.contents.toString()); - } catch {} + try { + oldManifest = options.transformer.parse(manifestFile.contents.toString()); + } catch {} - manifest = Object.assign(oldManifest, manifest); - } + manifest = Object.assign(oldManifest, manifest); + } - manifestFile.contents = Buffer.from(options.transformer.stringify(sortKeys(manifest), undefined, ' ')); - this.push(manifestFile); - callback(); - } catch (error) { - callback(error); - } - })(); + manifestFile.contents = Buffer.from(options.transformer.stringify(sortKeys(manifest), undefined, ' ')); + + yield manifestFile; }); }; diff --git a/package.json b/package.json index 842d3f9..51e97d0 100644 --- a/package.json +++ b/package.json @@ -37,12 +37,12 @@ "assets" ], "dependencies": { + "easy-transform-stream": "^1.0.0", "modify-filename": "^2.0.0", "plugin-error": "^2.0.1", "rev-hash": "^4.0.0", "rev-path": "^3.0.0", "sort-keys": "^5.0.0", - "through2": "^4.0.2", "vinyl": "^3.0.0", "vinyl-file": "^5.0.0" }, From 33571027b5aeb7bc28891fc5639c6f54dd6e2a16 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Sun, 11 Dec 2022 17:53:33 +0800 Subject: [PATCH 09/12] Require node>=16 --- .github/workflows/main.yml | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d50ada6..6a82b18 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,6 @@ jobs: node-version: - 18 - 16 - - 14 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 diff --git a/package.json b/package.json index 51e97d0..afbd04c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "type": "module", "exports": "./index.js", "engines": { - "node": ">=14" + "node": ">=16" }, "scripts": { "test": "xo && ava" From 39e09fa8de35869791c9942f33c444927079a1c7 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Sun, 11 Dec 2022 17:54:56 +0800 Subject: [PATCH 10/12] Import default 'gulp' in examples --- readme.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/readme.md b/readme.md index 49b83f3..89a8cd7 100644 --- a/readme.md +++ b/readme.md @@ -16,13 +16,13 @@ $ npm install --save-dev gulp-rev ## Usage ```js -import {src, dest} from 'gulp'; +import gulp from 'gulp'; import rev from 'gulp-rev'; export default () => ( - src('src/*.css') + gulp.src('src/*.css') .pipe(rev()) - .pipe(dest('dist')) + .pipe(gulp.dest('dist')) ); ``` @@ -83,18 +83,18 @@ The hash of each rev'd file is stored at `file.revHash`. You can use this for cu ### Asset manifest ```js -import {src, dest} from 'gulp'; +import gulp from 'gulp'; import rev from 'gulp-rev'; export default = () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: - src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) - .pipe(dest('build/assets')) // Copy original assets to build dir + gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) + .pipe(gulp.dest('build/assets')) // Copy original assets to build dir .pipe(rev()) - .pipe(dest('build/assets')) // Write rev'd assets to build dir + .pipe(gulp.dest('build/assets')) // Write rev'd assets to build dir .pipe(rev.manifest()) - .pipe(dest('build/assets')) // Write manifest to build dir + .pipe(gulp.dest('build/assets')) // Write manifest to build dir ); ``` @@ -110,21 +110,21 @@ An asset manifest, mapping the original paths to the revisioned paths, will be w By default, `rev-manifest.json` will be replaced as a whole. To merge with an existing manifest, pass `merge: true` and the output destination (as `base`) to `rev.manifest()`: ```js -import {src, dest} from 'gulp'; +import gulp from 'gulp'; import rev from 'gulp-rev'; export default = () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: - src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) - .pipe(dest('build/assets')) + gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) + .pipe(gulp.dest('build/assets')) .pipe(rev()) - .pipe(dest('build/assets')) + .pipe(gulp.dest('build/assets')) .pipe(rev.manifest({ base: 'build/assets', merge: true // Merge with the existing manifest if one exists })) - .pipe(dest('build/assets')) + .pipe(gulp.dest('build/assets')) ); ``` From 553466b0f75371af33a199c1f835e4ec6122124c Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Sun, 11 Dec 2022 18:04:01 +0800 Subject: [PATCH 11/12] Ensure correct file count during tests --- test/rev.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/rev.js b/test/rev.js index c406d20..7cc967d 100644 --- a/test/rev.js +++ b/test/rev.js @@ -59,11 +59,15 @@ test('handles sourcemaps transparently', async t => { contents: JSON.stringify({file: 'pastissada.css'}), })); + let sourcemapCount = 0; for await (const file of data) { if (path.extname(file.path) === '.map') { t.is(file.path, path.normalize('maps/pastissada-d41d8cd98f.css.map')); + sourcemapCount++; } } + + t.is(sourcemapCount, 1); }); test('handles unparseable sourcemaps correctly', async t => { @@ -81,11 +85,15 @@ test('handles unparseable sourcemaps correctly', async t => { contents: 'Wait a minute, this is invalid JSON!', })); + let sourcemapCount = 0; for await (const file of data) { if (path.extname(file.path) === '.map') { t.is(file.path, 'pastissada-d41d8cd98f.css.map'); + sourcemapCount++; } } + + t.is(sourcemapCount, 1); }); test('okay when the optional sourcemap.file is not defined', async t => { @@ -103,11 +111,15 @@ test('okay when the optional sourcemap.file is not defined', async t => { contents: JSON.stringify({}), })); + let sourcemapCount = 0; for await (const file of data) { if (path.extname(file.path) === '.map') { t.is(file.path, 'pastissada-d41d8cd98f.css.map'); + sourcemapCount++; } } + + t.is(sourcemapCount, 1); }); test('handles a `.` in the folder name', async t => { From 1d6480d2f95fd54a3dae53ea0c05665935962b85 Mon Sep 17 00:00:00 2001 From: Gilles Piou Date: Sun, 11 Dec 2022 18:12:09 +0800 Subject: [PATCH 12/12] Update examples in readme --- readme.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/readme.md b/readme.md index 89a8cd7..9d24566 100644 --- a/readme.md +++ b/readme.md @@ -86,7 +86,7 @@ The hash of each rev'd file is stored at `file.revHash`. You can use this for cu import gulp from 'gulp'; import rev from 'gulp-rev'; -export default = () => ( +export default () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) @@ -113,7 +113,7 @@ By default, `rev-manifest.json` will be replaced as a whole. To merge with an ex import gulp from 'gulp'; import rev from 'gulp-rev'; -export default = () => ( +export default () => ( // By default, Gulp would pick `assets/css` as the base, // so we need to set it explicitly: gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'}) @@ -135,19 +135,19 @@ You can optionally call `rev.manifest('manifest.json')` to give it a different p Because of the way `gulp-concat` handles file paths, you may need to set `cwd` and `path` manually on your `gulp-concat` instance to get everything to work correctly: ```js -const gulp = require('gulp'); -const sourcemaps = require('gulp-sourcemaps'); -const concat = require('gulp-concat'); +import gulp from 'gulp'; +import rev from 'gulp-rev'; +import sourcemaps from 'gulp-sourcemaps'; +import concat from 'gulp-concat'; -exports.default = async () => { - const {default: rev} = await import('gulp-rev'); - return gulp.src('src/*.js') +export default () => ( + gulp.src('src/*.js') .pipe(sourcemaps.init()) .pipe(concat({path: 'bundle.js', cwd: ''})) .pipe(rev()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('dist')) -}; +); ``` ## Different hash for unchanged files @@ -163,20 +163,20 @@ Since the order of streams are not guaranteed, some plugins such as `gulp-concat This plugin does not support streaming. If you have files from a streaming source, such as Browserify, you should use [`gulp-buffer`](https://github.com/jeromew/gulp-buffer) before `gulp-rev` in your pipeline: ```js -const gulp = require('gulp'); -const browserify = require('browserify'); -const source = require('vinyl-source-stream'); -const buffer = require('gulp-buffer'); - -exports.default = async () => { - const {default: rev} = await import('gulp-rev'); - return browserify('src/index.js') +import gulp from 'gulp'; +import browserify from 'browserify'; +import source from 'vinyl-source-stream'; +import buffer from 'gulp-buffer'; +import rev from 'gulp-rev'; + +export default () => ( + browserify('src/index.js') .bundle({debug: true}) .pipe(source('index.min.js')) .pipe(buffer()) .pipe(rev()) .pipe(gulp.dest('dist')) -}; +); ``` ## Integration