debug.js
2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
* MIT License http://opensource.org/licenses/MIT
* Author: Ben Holloway @bholloway
*/
'use strict';
const path = require('path');
const PACKAGE_NAME = require('../../package.json').name;
/**
* Paths are formatted to have posix style path separators and those within the CWD are made relative to CWD.
*
* @param {string} absolutePath An absolute path to format
* @returns {string} the formatted path
*/
const pathToString = (absolutePath) => {
if (absolutePath === '') {
return '-empty-';
} else {
const relative = path.relative(process.cwd(), absolutePath).split(path.sep);
const segments =
(relative[0] !== '..') ? ['.'].concat(relative).filter(Boolean) :
(relative.lastIndexOf('..') < 2) ? relative :
absolutePath.split(path.sep);
return segments.join('/');
}
};
exports.pathToString = pathToString;
/**
* Format a debug message.
*
* @param {string} filename The file being processed by webpack
* @param {string} uri A uri path, relative or absolute
* @param {Array<{base:string,joined:string,isSuccess:boolean}>} attempts An array of attempts, possibly empty
* @return {string} Formatted message
*/
const formatJoinMessage = (filename, uri, attempts) => {
const attemptToCells = (_, i, array) => {
const { base: prev } = (i === 0) ? {} : array[i-1];
const { base: curr, joined } = array[i];
return [(curr === prev) ? '' : pathToString(curr), pathToString(joined)];
};
const formatCells = (lines) => {
const maxWidth = lines.reduce((max, [cellA]) => Math.max(max, cellA.length), 0);
return lines.map(([cellA, cellB]) => [cellA.padEnd(maxWidth), cellB]).map((cells) => cells.join(' --> '));
};
return [PACKAGE_NAME + ': ' + pathToString(filename) + ': ' + uri]
.concat(attempts.length === 0 ? '-empty-' : formatCells(attempts.map(attemptToCells)))
.concat(attempts.some(({ isSuccess }) => isSuccess) ? 'FOUND' : 'NOT FOUND')
.join('\n ');
};
exports.formatJoinMessage = formatJoinMessage;
/**
* A factory for a log function predicated on the given debug parameter.
*
* The logging function created accepts a function that formats a message and parameters that the function utilises.
* Presuming the message function may be expensive we only call it if logging is enabled.
*
* The log messages are de-duplicated based on the parameters, so it is assumed they are simple types that stringify
* well.
*
* @param {function|boolean} debug A boolean or debug function
* @return {function(function, array):void} A logging function possibly degenerate
*/
const createDebugLogger = (debug) => {
const log = !!debug && ((typeof debug === 'function') ? debug : console.log);
const cache = {};
return log ?
((msgFn, params) => {
const key = Function.prototype.toString.call(msgFn) + JSON.stringify(params);
if (!cache[key]) {
cache[key] = true;
log(msgFn.apply(null, params));
}
}) :
(() => undefined);
};
exports.createDebugLogger = createDebugLogger;