diff --git a/lib/preprocessor.js b/lib/preprocessor.js index db59bd4bf..0728ecac1 100644 --- a/lib/preprocessor.js +++ b/lib/preprocessor.js @@ -1,16 +1,12 @@ -var fs = require('graceful-fs') -var crypto = require('crypto') -var mm = require('minimatch') -var isBinaryFile = require('isbinaryfile') -var combineLists = require('combine-lists') - -var log = require('./logger').create('preprocess') - -function sha1 (data) { - var hash = crypto.createHash('sha1') - hash.update(data) - return hash.digest('hex') -} +'use strict' + +const fs = require('graceful-fs') +const mm = require('minimatch') +const isBinaryFile = require('isbinaryfile') +const combineLists = require('combine-lists') +const CryptoUtils = require('./utils/crypto-utils') + +const log = require('./logger').create('preprocess') function createNextProcessor (preprocessors, file, done) { return function nextPreprocessor (error, content) { @@ -29,7 +25,7 @@ function createNextProcessor (preprocessors, file, done) { if (!preprocessors.length) { file.contentPath = null file.content = content - file.sha = sha1(content) + file.sha = CryptoUtils.sha1(content) return done() } @@ -38,27 +34,25 @@ function createNextProcessor (preprocessors, file, done) { } function createPreprocessor (config, basePath, injector) { - var alreadyDisplayedErrors = {} - var instances = {} - var patterns = Object.keys(config) - - var emitter = injector.get('emitter') + const emitter = injector.get('emitter') + const alreadyDisplayedErrors = {} + const instances = {} + let patterns = Object.keys(config) function instantiatePreprocessor (name) { if (alreadyDisplayedErrors[name]) { return } - var p + let p try { p = injector.get('preprocessor:' + name) } catch (e) { - if (e.message.indexOf('No provider for "preprocessor:' + name + '"') !== -1) { - log.error('Can not load "%s", it is not registered!\n ' + - 'Perhaps you are missing some plugin?', name) + if (e.message.indexOf(`No provider for "preprocessor:${name}"`) !== -1) { + log.error(`Can not load "${name}", it is not registered!\n Perhaps you are missing some plugin?`) } else { - log.error('Can not load "%s"!\n ' + e.stack, name) + log.error(`Can not load "${name}"!\n ` + e.stack) } alreadyDisplayedErrors[name] = true emitter.emit('load_error', 'preprocessor', name) @@ -67,16 +61,16 @@ function createPreprocessor (config, basePath, injector) { return p } - var allPreprocessors = [] - patterns.forEach(function (pattern) { + let allPreprocessors = [] + patterns.forEach((pattern) => { allPreprocessors = combineLists(allPreprocessors, config[pattern]) }) allPreprocessors.forEach(instantiatePreprocessor) return function preprocess (file, done) { patterns = Object.keys(config) - var retryCount = 0 - var maxRetries = 3 + let retryCount = 0 + let maxRetries = 3 function readFileCallback (err, buffer) { if (err) { log.warn(err) @@ -90,25 +84,22 @@ function createPreprocessor (config, basePath, injector) { } } - isBinaryFile(buffer, buffer.length, function (err, thisFileIsBinary) { + isBinaryFile(buffer, buffer.length, function (err, isBinary) { if (err) { throw err } var preprocessorNames = [] - for (var i = 0; i < patterns.length; i++) { - if (mm(file.originalPath, patterns[i], {dot: true})) { - preprocessorNames = combineLists(preprocessorNames, config[patterns[i]]) + patterns.forEach((pattern) => { + if (mm(file.originalPath, pattern, {dot: true})) { + preprocessorNames = combineLists(preprocessorNames, config[pattern]) } - } + }) - var preprocessors = [] - var nextPreprocessor = createNextProcessor(preprocessors, file, done) - preprocessorNames.forEach(function (name) { - var p = instances[name] - if (p == null) { - p = instantiatePreprocessor(name) - } + let preprocessors = [] + const nextPreprocessor = createNextProcessor(preprocessors, file, done) + preprocessorNames.forEach((name) => { + const p = instances[name] || instantiatePreprocessor(name) if (p == null) { if (!alreadyDisplayedErrors[name]) { @@ -120,7 +111,7 @@ function createPreprocessor (config, basePath, injector) { } instances[name] = p - if (!thisFileIsBinary || p.handleBinaryFiles) { + if (!isBinary || p.handleBinaryFiles) { preprocessors.push(p) } else { log.warn('Ignored preprocessing %s because %s has handleBinaryFiles=false.', @@ -128,12 +119,13 @@ function createPreprocessor (config, basePath, injector) { } }) - nextPreprocessor(null, thisFileIsBinary ? buffer : buffer.toString()) + nextPreprocessor(null, isBinary ? buffer : buffer.toString()) }) } return fs.readFile(file.originalPath, readFileCallback) } } + createPreprocessor.$inject = ['config.preprocessors', 'config.basePath', 'injector'] exports.createPreprocessor = createPreprocessor diff --git a/lib/utils/crypto-utils.js b/lib/utils/crypto-utils.js new file mode 100644 index 000000000..9dc9a073d --- /dev/null +++ b/lib/utils/crypto-utils.js @@ -0,0 +1,14 @@ +'use strict' + +const crypto = require('crypto') + +const CryptoUtils = { + sha1 (data) { + return crypto + .createHash('sha1') + .update(data) + .digest('hex') + } +} + +module.exports = CryptoUtils diff --git a/test/unit/preprocessor.spec.js b/test/unit/preprocessor.spec.js index 2bf6f9a62..1e4439a6c 100644 --- a/test/unit/preprocessor.spec.js +++ b/test/unit/preprocessor.spec.js @@ -1,16 +1,18 @@ -var mocks = require('mocks') -var di = require('di') -var path = require('path') +'use strict' -var events = require('../../lib/events') +const mocks = require('mocks') +const di = require('di') +const path = require('path') + +const events = require('../../lib/events') describe('preprocessor', () => { - var pp - var m - var mockFs - var emitterSetting + let pp + let m + let mockFs + let emitterSetting // mimic first few bytes of a pdf file - var binarydata = new Buffer([0x25, 0x50, 0x44, 0x66, 0x46, 0x00]) // eslint-disable-line node/no-deprecated-api + const binarydata = new Buffer([0x25, 0x50, 0x44, 0x66, 0x46, 0x00]) // eslint-disable-line node/no-deprecated-api beforeEach(() => { mockFs = mocks.fs.create({ @@ -26,7 +28,7 @@ describe('preprocessor', () => { } }) - var mocks_ = { + const mocks_ = { 'graceful-fs': mockFs, minimatch: require('minimatch') } @@ -35,19 +37,19 @@ describe('preprocessor', () => { }) it('should preprocess matching file', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { file.path = file.path + '-preprocessed' done(null, 'new-content') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': [ 'factory', function () { return fakePreprocessor } ] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['fake']}, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, () => { expect(fakePreprocessor).to.have.been.called @@ -58,17 +60,17 @@ describe('preprocessor', () => { }) it('should match directories starting with a dot', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { file.path = file.path + '-preprocessed' done(null, 'new-content') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['fake']}, null, injector) - var file = {originalPath: '/some/.dir/a.js', path: 'path'} + const file = {originalPath: '/some/.dir/a.js', path: 'path'} pp(file, () => { expect(fakePreprocessor).to.have.been.called @@ -79,18 +81,18 @@ describe('preprocessor', () => { }) it('should check patterns after creation when invoked', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { file.path = file.path + '-preprocessed' done(null, 'new-content') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) - var config = {'**/*.txt': ['fake']} + const config = {'**/*.txt': ['fake']} pp = m.createPreprocessor(config, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} config['**/*.js'] = ['fake'] @@ -103,16 +105,16 @@ describe('preprocessor', () => { }) it('should ignore not matching file', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, '') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['fake']}, null, injector) - var file = {originalPath: '/some/a.txt', path: 'path'} + const file = {originalPath: '/some/a.txt', path: 'path'} pp(file, () => { expect(fakePreprocessor).to.not.have.been.called @@ -121,24 +123,24 @@ describe('preprocessor', () => { }) it('should apply all preprocessors', (done) => { - var fakePreprocessor1 = sinon.spy((content, file, done) => { + const fakePreprocessor1 = sinon.spy((content, file, done) => { file.path = file.path + '-p1' done(null, content + '-c1') }) - var fakePreprocessor2 = sinon.spy((content, file, done) => { + const fakePreprocessor2 = sinon.spy((content, file, done) => { file.path = file.path + '-p2' done(content + '-c2') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake1': ['factory', function () { return fakePreprocessor1 }], 'preprocessor:fake2': ['factory', function () { return fakePreprocessor2 }] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['fake1', 'fake2']}, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, () => { expect(fakePreprocessor1).to.have.been.calledOnce @@ -151,12 +153,12 @@ describe('preprocessor', () => { it('should compute SHA', (done) => { pp = m.createPreprocessor({}, null, new di.Injector([emitterSetting])) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, () => { expect(file.sha).to.exist expect(file.sha.length).to.equal(40) - var previousSHA = file.sha + const previousSHA = file.sha pp(file, () => { expect(file.sha).to.equal(previousSHA) @@ -172,18 +174,18 @@ describe('preprocessor', () => { }) it('should compute SHA from content returned by a processor', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, content + '-processed') }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/a.js': ['fake']}, null, injector) - var fileProcess = {originalPath: '/some/a.js', path: 'path'} - var fileSkip = {originalPath: '/some/b.js', path: 'path'} + const fileProcess = {originalPath: '/some/a.js', path: 'path'} + const fileSkip = {originalPath: '/some/b.js', path: 'path'} pp(fileProcess, () => { pp(fileSkip, () => { @@ -198,17 +200,17 @@ describe('preprocessor', () => { }) it('should return error if any preprocessor fails', (done) => { - var failingPreprocessor = sinon.spy((content, file, done) => { + const failingPreprocessor = sinon.spy((content, file, done) => { done(new Error('Some error'), null) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:failing': ['factory', function () { return failingPreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['failing']}, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, (err) => { expect(err).to.exist @@ -217,22 +219,22 @@ describe('preprocessor', () => { }) it('should stop preprocessing after an error', (done) => { - var failingPreprocessor = sinon.spy((content, file, done) => { + const failingPreprocessor = sinon.spy((content, file, done) => { done(new Error('Some error'), null) }) - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, content) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:failing': ['factory', function () { return failingPreprocessor }], 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*.js': ['failing', 'fake']}, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, () => { expect(fakePreprocessor).not.to.have.been.called @@ -241,8 +243,8 @@ describe('preprocessor', () => { }) describe('when fs.readFile fails', () => { - var file = {originalPath: '/some/a.js', path: 'path'} - var getReadFileCallback = (nthCall) => { + const file = {originalPath: '/some/a.js', path: 'path'} + const getReadFileCallback = (nthCall) => { return mockFs.readFile.args[nthCall][1] } @@ -251,15 +253,15 @@ describe('preprocessor', () => { }) it('should retry up to 3 times', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, content) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) - var pp = m.createPreprocessor({'**/*.js': ['fake']}, null, injector) + const pp = m.createPreprocessor({'**/*.js': ['fake']}, null, injector) pp(file, () => { expect(fakePreprocessor).to.have.been.called @@ -267,15 +269,15 @@ describe('preprocessor', () => { }) getReadFileCallback(0)('error') getReadFileCallback(1)('error') - var thirdCallback = getReadFileCallback(2) + const thirdCallback = getReadFileCallback(2) mockFs.readFile.restore() thirdCallback('error') }) it('should throw after 3 retries', (done) => { - var injector = new di.Injector([{}, emitterSetting]) + const injector = new di.Injector([{}, emitterSetting]) - var pp = m.createPreprocessor({'**/*.js': []}, null, injector) + const pp = m.createPreprocessor({'**/*.js': []}, null, injector) pp(file, () => { }) @@ -289,17 +291,17 @@ describe('preprocessor', () => { }) it('should not preprocess binary files by default', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, content) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { return fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*': ['fake']}, null, injector) - var file = {originalPath: '/some/photo.png', path: 'path'} + const file = {originalPath: '/some/photo.png', path: 'path'} pp(file, (err) => { if (err) throw err @@ -334,17 +336,17 @@ describe('preprocessor', () => { }) it('should not preprocess binary files with capital letters in extension', (done) => { - var fakePreprocessor = sinon.spy((content, file, done) => { + const fakePreprocessor = sinon.spy((content, file, done) => { done(null, content) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fake': ['factory', function () { fakePreprocessor }] }, emitterSetting]) pp = m.createPreprocessor({'**/*': ['fake']}, null, injector) - var file = {originalPath: '/some/CAM_PHOTO.JPG', path: 'path'} + const file = {originalPath: '/some/CAM_PHOTO.JPG', path: 'path'} pp(file, (err) => { if (err) throw err @@ -356,25 +358,25 @@ describe('preprocessor', () => { }) it('should merge lists of preprocessors', (done) => { - var callOrder = [] - var fakePreprocessorA = sinon.spy((content, file, done) => { + const callOrder = [] + const fakePreprocessorA = sinon.spy((content, file, done) => { callOrder.push('a') done(null, content) }) - var fakePreprocessorB = sinon.spy((content, file, done) => { + const fakePreprocessorB = sinon.spy((content, file, done) => { callOrder.push('b') done(null, content) }) - var fakePreprocessorC = sinon.spy((content, file, done) => { + const fakePreprocessorC = sinon.spy((content, file, done) => { callOrder.push('c') done(null, content) }) - var fakePreprocessorD = sinon.spy((content, file, done) => { + const fakePreprocessorD = sinon.spy((content, file, done) => { callOrder.push('d') done(null, content) }) - var injector = new di.Injector([{ + const injector = new di.Injector([{ 'preprocessor:fakeA': ['factory', function () { return fakePreprocessorA }], 'preprocessor:fakeB': ['factory', function () { return fakePreprocessorB }], 'preprocessor:fakeC': ['factory', function () { return fakePreprocessorC }], @@ -387,7 +389,7 @@ describe('preprocessor', () => { '/some/a.js': ['fakeD'] }, null, injector) - var file = {originalPath: '/some/a.js', path: 'path'} + const file = {originalPath: '/some/a.js', path: 'path'} pp(file, (err) => { if (err) throw err diff --git a/test/unit/utils/crypto-utils.spec.js b/test/unit/utils/crypto-utils.spec.js new file mode 100644 index 000000000..671712ecf --- /dev/null +++ b/test/unit/utils/crypto-utils.spec.js @@ -0,0 +1,9 @@ +'use strict' + +const CryptoUtils = require('../../../lib/utils/crypto-utils') + +describe('CryptoUtils.sha1', () => { + it('create sha1 digest from string', () => { + expect(CryptoUtils.sha1('Example text')).to.equal('cf3df620b86f0c9f586359136950217cb3b8c035') + }) +})