UNPKG

assetgraph

Version:

An auto discovery dependency graph based optimization framework for web pages and applications

172 lines (160 loc) 5.59 kB
const chalk = require('chalk'); const _ = require('lodash'); const Path = require('path'); const urlTools = require('urltools'); const AssetGraph = require('../AssetGraph'); function indentSubsequentLines(str, level) { return str.replace(/\n/g, `\n${new Array(level + 1).join(' ')}`); } function escapeRegExpMetaChars(str) { return str.replace(/[$.^()[\]{}]/g, '\\$&'); } module.exports = ({ afterTransform, repl, stopOnWarning } = {}) => { let startReplRegExp; if (repl) { startReplRegExp = new RegExp( _.flatten( _.flatten([repl]).map(transformName => transformName.split(',')) ) .map(transformName => transformName.replace(/[.+{}[]()?^$]/g, '\\$&')) .join('|') ); } return function logEvents(assetGraph) { const assetGraphRootRelativeToCwd = Path.relative( process.cwd(), urlTools.fileUrlToFsPath(assetGraph.root) ); const assetGraphRootRelativeToCwdRegExp = new RegExp( `\\b${escapeRegExpMetaChars(assetGraphRootRelativeToCwd)}/`, 'g' ); const cwdRegExp = new RegExp( `(?:file://)?${escapeRegExpMetaChars(`${process.cwd()}/`)}`, 'g' ); const colorBySeverity = { info: 'cyan', warn: 'yellow', error: 'red' }; const symbolBySeverity = { info: 'ℹ', warn: '⚠', error: '✘' }; function outputMessage(messageOrError, severity) { severity = severity || 'info'; let message; if (Object.prototype.toString.call(messageOrError) === '[object Error]') { if (severity === 'error') { message = messageOrError.stack; } else { message = messageOrError.message || messageOrError.name || messageOrError.code; } if (messageOrError.asset) { const fileLineCol = [messageOrError.asset.urlOrDescription]; if (messageOrError.line) { fileLineCol.push(messageOrError.line); if (messageOrError.column) { fileLineCol.push(messageOrError.col); } } message = `${fileLineCol.join(':')} - ${message}`; const incomingRelations = messageOrError.asset.incomingRelations; if (incomingRelations.length > 0) { message += `\nIncluding assets:\n ${incomingRelations .map(incomingRelation => { return incomingRelation.from.urlOrDescription; }) .join('\n ')}\n`; } } } else { if (typeof messageOrError === 'string') { message = messageOrError; } else if (typeof messageOrError.message === 'string') { message = messageOrError.message; } else { // Give up guessing. This is probably an error on the next lines... message = messageOrError; } } const caption = ` ${ symbolBySeverity[severity] } ${severity.toUpperCase()}: `; message = message .replace(cwdRegExp, '') .replace( assetGraphRootRelativeToCwdRegExp, chalk.gray(`${assetGraphRootRelativeToCwd}/`) ); console[severity]( chalk[colorBySeverity[severity]](caption) + indentSubsequentLines(message, caption.length) ); } let firstWarningSeenDuringTransform = null; const transformStack = [logEvents]; assetGraph .on('beforeTransform', transform => { firstWarningSeenDuringTransform = null; transformStack.push(transform); }) .on('afterTransform', function(transform, elapsedTime) { if (firstWarningSeenDuringTransform && stopOnWarning) { console.error( `${chalk.red(' ✘ ERROR: ') + (transform.name ? `${transform.name}: ` : '')}A warning was encountered while stopOnWarning is on, exiting with a non-zero exit code` ); process.exit(1); } if (transform !== transformStack.pop()) { throw new Error( 'logEvents: Internal error in the transformStack housekeeping' ); } if (afterTransform !== false) { console.log( `${chalk.green(' ✔ ') + (elapsedTime / 1000).toFixed(3)} secs: ${ transform.name }` ); } if (startReplRegExp && startReplRegExp.test(transform.name)) { this.transformQueue.transforms.unshift( AssetGraph.transforms.startRepl() ); } }) .on('info', info => { outputMessage(info, 'info'); }) .on('warn', function(err) { outputMessage(err, 'warn'); if (startReplRegExp && startReplRegExp.test('warn')) { this.transformQueue.transforms.unshift( AssetGraph.transforms.startRepl() ); } if (transformStack.length > 0) { firstWarningSeenDuringTransform = firstWarningSeenDuringTransform || err; } else if (stopOnWarning) { console.error( `${chalk.red( ' ✘ ERROR: ' )}A warning was encountered while stopOnWarning is on, exiting with a non-zero exit code` ); process.exit(1); } }) .on('error', function(err) { outputMessage(err, 'error'); if (startReplRegExp && startReplRegExp.test('error')) { this.transformQueue.transforms.unshift( AssetGraph.transforms.startRepl() ); } else { process.exit(1); } }); }; };