source-map-explorer 2.3.0 → 2.4.2
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +19 -7
- package/dist/api.d.ts +1 -7
- package/dist/api.js +49 -84
- package/dist/api.js.map +1 -0
- package/dist/app-error.d.ts +1 -1
- package/dist/app-error.js +13 -34
- package/dist/app-error.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +58 -93
- package/dist/cli.js.map +1 -0
- package/dist/coverage.d.ts +1 -10
- package/dist/coverage.js +27 -125
- package/dist/coverage.js.map +1 -0
- package/dist/explore.d.ts +1 -4
- package/dist/explore.js +118 -150
- package/dist/explore.js.map +1 -0
- package/dist/helpers.d.ts +2 -16
- package/dist/helpers.js +35 -68
- package/dist/helpers.js.map +1 -0
- package/dist/html.d.ts +1 -7
- package/dist/html.js +68 -95
- package/dist/html.js.map +1 -0
- package/dist/index.d.ts +2 -90
- package/dist/index.js +9 -37
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +1 -1
- package/dist/output.js +21 -53
- package/dist/output.js.map +1 -0
- package/dist/types.d.ts +121 -0
- package/package.json +49 -50
package/dist/cli.js
CHANGED
@@ -1,41 +1,27 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
'use strict';
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
}
|
7
|
-
|
8
|
-
exports
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
var _open = _interopRequireDefault(require('open'));
|
18
|
-
|
19
|
-
var _chalk = _interopRequireDefault(require('chalk'));
|
20
|
-
|
21
|
-
var _lodash = require('lodash');
|
22
|
-
|
23
|
-
var _api = require('./api');
|
24
|
-
|
25
|
-
var _appError = require('./app-error');
|
26
|
-
|
27
|
-
function _interopRequireDefault(obj) {
|
28
|
-
return obj && obj.__esModule ? obj : { default: obj };
|
29
|
-
}
|
30
|
-
|
3
|
+
var __importDefault =
|
4
|
+
(this && this.__importDefault) ||
|
5
|
+
function (mod) {
|
6
|
+
return mod && mod.__esModule ? mod : { default: mod };
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
9
|
+
const yargs_1 = __importDefault(require('yargs'));
|
10
|
+
const fs_1 = __importDefault(require('fs'));
|
11
|
+
const temp_1 = __importDefault(require('temp'));
|
12
|
+
const open_1 = __importDefault(require('open'));
|
13
|
+
const chalk_1 = __importDefault(require('chalk'));
|
14
|
+
const lodash_1 = require('lodash');
|
15
|
+
const api_1 = require('./api');
|
16
|
+
const app_error_1 = require('./app-error');
|
31
17
|
function parseArguments() {
|
32
|
-
const argv =
|
18
|
+
const argv = yargs_1.default
|
33
19
|
.strict()
|
34
20
|
.scriptName('source-map-explorer')
|
35
21
|
.usage('Analyze and debug space usage through source maps.')
|
36
22
|
.usage('Usage:')
|
37
23
|
.usage(
|
38
|
-
'$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--gzip] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'
|
24
|
+
'$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--no-border-checks] [--gzip] [--sort] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'
|
39
25
|
)
|
40
26
|
.example('$0 script.js script.js.map', 'Explore bundle')
|
41
27
|
.example('$0 script.js', 'Explore bundle with inline source map')
|
@@ -90,6 +76,10 @@ function parseArguments() {
|
|
90
76
|
description: 'See --replace.',
|
91
77
|
implies: 'replace',
|
92
78
|
},
|
79
|
+
'no-border-checks': {
|
80
|
+
type: 'boolean',
|
81
|
+
description: 'Disable invalid mapping column/line checks.',
|
82
|
+
},
|
93
83
|
coverage: {
|
94
84
|
type: 'string',
|
95
85
|
normalize: true,
|
@@ -101,53 +91,50 @@ function parseArguments() {
|
|
101
91
|
description: 'Calculate gzip size. It also sets onlyMapped flag',
|
102
92
|
conflicts: ['only-mapped'],
|
103
93
|
},
|
94
|
+
sort: {
|
95
|
+
type: 'boolean',
|
96
|
+
description: 'Sort filenames',
|
97
|
+
},
|
104
98
|
})
|
105
99
|
.group(['json', 'tsv', 'html'], 'Output:')
|
106
100
|
.group(['replace', 'with'], 'Replace:')
|
107
101
|
.help('h')
|
108
102
|
.alias('h', 'help')
|
109
103
|
.showHelpOnFail(false, 'Specify --help for available options')
|
110
|
-
.wrap(null)
|
104
|
+
.wrap(null)
|
111
105
|
.parserConfiguration({
|
112
|
-
'boolean-negation': false,
|
106
|
+
'boolean-negation': false,
|
113
107
|
})
|
114
|
-
.check(argv => {
|
108
|
+
.check((argv) => {
|
115
109
|
if (argv.replace && argv.with && argv.replace.length !== argv.with.length) {
|
116
110
|
throw new Error('--replace flags must be paired with --with flags');
|
117
111
|
}
|
118
|
-
|
119
112
|
return true;
|
120
113
|
})
|
121
|
-
.parse();
|
122
|
-
|
114
|
+
.parse();
|
123
115
|
const quoteRegex = /'/g;
|
124
|
-
argv._ = argv._.map(path => path.replace(quoteRegex, ''));
|
116
|
+
argv._ = argv._.map((path) => path.replace(quoteRegex, ''));
|
125
117
|
return argv;
|
126
118
|
}
|
127
|
-
|
128
119
|
function logError(message, error) {
|
129
|
-
if (!
|
130
|
-
message =
|
120
|
+
if (!lodash_1.isString(message)) {
|
121
|
+
message = app_error_1.getErrorMessage(message);
|
131
122
|
}
|
132
|
-
|
133
123
|
if (error) {
|
134
|
-
console.error(
|
124
|
+
console.error(chalk_1.default.red(message), error);
|
135
125
|
} else {
|
136
|
-
console.error(
|
126
|
+
console.error(chalk_1.default.red(message));
|
137
127
|
}
|
138
128
|
}
|
139
|
-
|
129
|
+
exports.logError = logError;
|
140
130
|
function logWarn(message) {
|
141
|
-
console.warn(
|
131
|
+
console.warn(chalk_1.default.yellow(message));
|
142
132
|
}
|
143
|
-
|
133
|
+
exports.logWarn = logWarn;
|
144
134
|
function logInfo(message) {
|
145
|
-
console.log(
|
135
|
+
console.log(chalk_1.default.green(message));
|
146
136
|
}
|
147
|
-
|
148
|
-
* Create options object for `explore` method
|
149
|
-
*/
|
150
|
-
|
137
|
+
exports.logInfo = logInfo;
|
151
138
|
function getExploreOptions(argv) {
|
152
139
|
const {
|
153
140
|
json,
|
@@ -158,83 +145,60 @@ function getExploreOptions(argv) {
|
|
158
145
|
onlyMapped,
|
159
146
|
excludeSourceMap: excludeSourceMapComment,
|
160
147
|
noRoot,
|
148
|
+
noBorderChecks,
|
161
149
|
coverage,
|
162
150
|
gzip,
|
151
|
+
sort,
|
163
152
|
} = argv;
|
164
153
|
let replaceMap;
|
165
|
-
|
166
154
|
if (replaceItems && withItems) {
|
167
155
|
replaceMap = replaceItems.reduce((result, item, index) => {
|
168
156
|
result[item] = withItems[index];
|
169
157
|
return result;
|
170
158
|
}, {});
|
171
159
|
}
|
172
|
-
|
173
160
|
return {
|
174
161
|
output: {
|
175
|
-
|
176
|
-
format: (0, _lodash.isString)(json) ? 'json' : (0, _lodash.isString)(tsv) ? 'tsv' : 'html',
|
162
|
+
format: lodash_1.isString(json) ? 'json' : lodash_1.isString(tsv) ? 'tsv' : 'html',
|
177
163
|
filename: json || tsv || html,
|
178
164
|
},
|
179
165
|
replaceMap,
|
180
166
|
onlyMapped,
|
181
167
|
excludeSourceMapComment,
|
182
168
|
noRoot,
|
169
|
+
noBorderChecks,
|
183
170
|
coverage,
|
184
171
|
gzip,
|
172
|
+
sort,
|
185
173
|
};
|
186
174
|
}
|
187
|
-
/**
|
188
|
-
* Write HTML content to a temporary file and open the file in a browser
|
189
|
-
*/
|
190
|
-
|
191
175
|
async function writeHtmlToTempFile(html) {
|
192
176
|
if (!html) {
|
193
177
|
return;
|
194
178
|
}
|
195
|
-
|
196
179
|
try {
|
197
|
-
const tempFile =
|
198
|
-
|
199
|
-
|
200
|
-
});
|
201
|
-
|
202
|
-
_fs.default.writeFileSync(tempFile, html);
|
203
|
-
|
204
|
-
const childProcess = await (0, _open.default)(tempFile);
|
205
|
-
|
180
|
+
const tempFile = temp_1.default.path({ prefix: 'sme-result-', suffix: '.html' });
|
181
|
+
fs_1.default.writeFileSync(tempFile, html);
|
182
|
+
const childProcess = await open_1.default(tempFile);
|
206
183
|
if (childProcess.stderr) {
|
207
|
-
|
208
|
-
|
209
|
-
logError({
|
210
|
-
code: 'CannotOpenTempFile',
|
211
|
-
tempFile,
|
212
|
-
error,
|
213
|
-
});
|
184
|
+
childProcess.stderr.once('data', (error) => {
|
185
|
+
logError({ code: 'CannotOpenTempFile', tempFile, error });
|
214
186
|
});
|
215
187
|
}
|
216
188
|
} catch (error) {
|
217
|
-
throw new
|
218
|
-
{
|
219
|
-
code: 'CannotCreateTempFile',
|
220
|
-
},
|
221
|
-
error
|
222
|
-
);
|
189
|
+
throw new app_error_1.AppError({ code: 'CannotCreateTempFile' }, error);
|
223
190
|
}
|
224
191
|
}
|
225
|
-
|
226
192
|
function outputErrors({ errors }) {
|
227
193
|
if (errors.length === 0) {
|
228
194
|
return;
|
229
|
-
}
|
230
|
-
|
231
|
-
const groupedErrors = (0, _lodash.groupBy)(errors, 'bundleName');
|
195
|
+
}
|
196
|
+
const groupedErrors = lodash_1.groupBy(errors, 'bundleName');
|
232
197
|
Object.entries(groupedErrors).forEach(([bundleName, errors]) => {
|
233
198
|
console.group(bundleName);
|
234
199
|
const hasManyErrors = errors.length > 1;
|
235
200
|
errors.forEach((error, index) => {
|
236
201
|
const message = `${hasManyErrors ? `${index + 1}. ` : ''}${error.message}`;
|
237
|
-
|
238
202
|
if (error.isWarning) {
|
239
203
|
logWarn(message);
|
240
204
|
} else {
|
@@ -244,16 +208,15 @@ function outputErrors({ errors }) {
|
|
244
208
|
console.groupEnd();
|
245
209
|
});
|
246
210
|
}
|
247
|
-
|
248
211
|
if (require.main === module) {
|
249
212
|
const argv = parseArguments();
|
250
|
-
const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(
|
213
|
+
const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(lodash_1.isString);
|
251
214
|
const options = getExploreOptions(argv);
|
252
|
-
|
253
|
-
.
|
215
|
+
api_1
|
216
|
+
.explore(argv._, options)
|
217
|
+
.then((result) => {
|
254
218
|
if (isOutputFormatSpecified && options.output) {
|
255
219
|
const filename = options.output.filename;
|
256
|
-
|
257
220
|
if (filename) {
|
258
221
|
logInfo(`Output saved to ${filename}`);
|
259
222
|
outputErrors(result);
|
@@ -266,11 +229,13 @@ if (require.main === module) {
|
|
266
229
|
});
|
267
230
|
}
|
268
231
|
})
|
269
|
-
.catch(error => {
|
232
|
+
.catch((error) => {
|
270
233
|
if (error.errors) {
|
271
234
|
outputErrors(error);
|
272
235
|
} else {
|
273
236
|
logError('Failed to explore', error);
|
274
237
|
}
|
238
|
+
process.exitCode = 1;
|
275
239
|
});
|
276
240
|
}
|
241
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport fs from 'fs';\nimport temp from 'temp';\nimport open from 'open';\nimport chalk from 'chalk';\nimport { groupBy, isString } from 'lodash';\n\nimport { explore } from './api';\nimport { AppError, getErrorMessage } from './app-error';\n\nimport type { ErrorContext } from './app-error';\nimport type { ExploreOptions, ReplaceMap, ExploreResult } from './types';\n\n/** Parsed CLI arguments */\ninterface Arguments {\n _: string[];\n json?: string;\n tsv?: string;\n html?: string;\n onlyMapped?: boolean;\n excludeSourceMap?: boolean;\n noRoot?: boolean;\n replace?: string[];\n with?: string[];\n noBorderChecks?: boolean;\n coverage?: string;\n gzip?: boolean;\n sort?: boolean;\n}\n\nfunction parseArguments(): Arguments {\n const argv = yargs\n .strict()\n .scriptName('source-map-explorer')\n .usage('Analyze and debug space usage through source maps.')\n .usage('Usage:')\n .usage(\n '$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--no-border-checks] [--gzip] [--sort] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'\n )\n .example('$0 script.js script.js.map', 'Explore bundle')\n .example('$0 script.js', 'Explore bundle with inline source map')\n .example('$0 dist/js/*.*', 'Explore all bundles inside dist/js folder')\n .example('$0 script.js --tsv', 'Explore and output result as TSV to stdout')\n .example('$0 script.js --json result.json', 'Explore and save result as JSON to the file')\n .demandCommand(1, 'At least one js file must be specified')\n .options({\n json: {\n type: 'string',\n description:\n 'If filename specified save output as JSON to specified file otherwise output to stdout.',\n conflicts: ['tsv', 'html'],\n },\n tsv: {\n type: 'string',\n description:\n 'If filename specified save output as TSV to specified file otherwise output to stdout.',\n conflicts: ['json', 'html'],\n },\n html: {\n type: 'string',\n description:\n 'If filename specified save output as HTML to specified file otherwise output to stdout rather than opening a browser.',\n conflicts: ['json', 'tsv'],\n },\n\n 'only-mapped': {\n alias: 'm',\n type: 'boolean',\n description:\n 'Exclude \"unmapped\" bytes from the output. This will result in total counts less than the file size',\n },\n\n 'exclude-source-map': {\n type: 'boolean',\n description: 'Exclude source map comment size from output',\n },\n\n 'no-root': {\n type: 'boolean',\n description:\n 'To simplify the visualization, source-map-explorer will remove any prefix shared by all sources. If you wish to disable this behavior, set --no-root.',\n },\n\n replace: {\n type: 'string',\n array: true,\n description:\n 'Apply a simple find/replace on source file names. This can be used to fix some oddities with paths that appear in the source map generation process. Accepts regular expressions.',\n implies: 'with',\n },\n with: {\n type: 'string',\n array: true,\n description: 'See --replace.',\n implies: 'replace',\n },\n\n 'no-border-checks': {\n type: 'boolean',\n description: 'Disable invalid mapping column/line checks.',\n },\n\n coverage: {\n type: 'string',\n normalize: true,\n description:\n 'If the path to a valid a chrome code coverage JSON export is supplied, the tree map will be colorized according to which percentage of the modules code was executed',\n },\n\n gzip: {\n type: 'boolean',\n description: 'Calculate gzip size. It also sets onlyMapped flag',\n conflicts: ['only-mapped'],\n },\n\n sort: {\n type: 'boolean',\n description: 'Sort filenames',\n },\n })\n .group(['json', 'tsv', 'html'], 'Output:')\n .group(['replace', 'with'], 'Replace:')\n .help('h')\n .alias('h', 'help')\n .showHelpOnFail(false, 'Specify --help for available options')\n .wrap(null) // Do not limit line length\n .parserConfiguration({\n 'boolean-negation': false, // Allow --no-root\n })\n .check((argv) => {\n if (argv.replace && argv.with && argv.replace.length !== argv.with.length) {\n throw new Error('--replace flags must be paired with --with flags');\n }\n\n return true;\n })\n .parse();\n\n // Trim extra quotes\n const quoteRegex = /'/g;\n\n argv._ = argv._.map((path) => path.replace(quoteRegex, ''));\n\n return argv;\n}\n\nexport function logError(message: string | ErrorContext, error?: Error): void {\n if (!isString(message)) {\n message = getErrorMessage(message);\n }\n\n if (error) {\n console.error(chalk.red(message), error);\n } else {\n console.error(chalk.red(message));\n }\n}\n\nexport function logWarn(message: string): void {\n console.warn(chalk.yellow(message));\n}\n\nexport function logInfo(message: string): void {\n console.log(chalk.green(message));\n}\n\n/**\n * Create options object for `explore` method\n */\nfunction getExploreOptions(argv: Arguments): ExploreOptions {\n const {\n json,\n tsv,\n html,\n replace: replaceItems,\n with: withItems,\n onlyMapped,\n excludeSourceMap: excludeSourceMapComment,\n noRoot,\n noBorderChecks,\n coverage,\n gzip,\n sort,\n } = argv;\n\n let replaceMap: ReplaceMap | undefined;\n\n if (replaceItems && withItems) {\n replaceMap = replaceItems.reduce<ReplaceMap>((result, item, index) => {\n result[item] = withItems[index];\n\n return result;\n }, {});\n }\n\n return {\n output: {\n // By default CLI needs result in HTML in order to create a temporary file\n format: isString(json) ? 'json' : isString(tsv) ? 'tsv' : 'html',\n filename: json || tsv || html,\n },\n replaceMap,\n onlyMapped,\n excludeSourceMapComment,\n noRoot,\n noBorderChecks,\n coverage,\n gzip,\n sort,\n };\n}\n\n/**\n * Write HTML content to a temporary file and open the file in a browser\n */\nasync function writeHtmlToTempFile(html?: string): Promise<void> {\n if (!html) {\n return;\n }\n\n try {\n const tempFile = temp.path({ prefix: 'sme-result-', suffix: '.html' });\n\n fs.writeFileSync(tempFile, html);\n\n const childProcess = await open(tempFile);\n\n if (childProcess.stderr) {\n // Catch error output from child process\n childProcess.stderr.once('data', (error: Buffer) => {\n logError({ code: 'CannotOpenTempFile', tempFile, error });\n });\n }\n } catch (error) {\n throw new AppError({ code: 'CannotCreateTempFile' }, error);\n }\n}\n\nfunction outputErrors({ errors }: ExploreResult): void {\n if (errors.length === 0) {\n return;\n }\n\n // Group errors by bundle name\n const groupedErrors = groupBy(errors, 'bundleName');\n\n Object.entries(groupedErrors).forEach(([bundleName, errors]) => {\n console.group(bundleName);\n\n const hasManyErrors = errors.length > 1;\n\n errors.forEach((error, index) => {\n const message = `${hasManyErrors ? `${index + 1}. ` : ''}${error.message}`;\n\n if (error.isWarning) {\n logWarn(message);\n } else {\n logError(message);\n }\n });\n\n console.groupEnd();\n });\n}\n\nif (require.main === module) {\n const argv = parseArguments();\n\n const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(isString);\n\n const options = getExploreOptions(argv);\n\n explore(argv._, options)\n .then((result) => {\n if (isOutputFormatSpecified && options.output) {\n const filename = options.output.filename;\n\n if (filename) {\n logInfo(`Output saved to ${filename}`);\n outputErrors(result);\n } else {\n console.log(result.output);\n }\n } else {\n writeHtmlToTempFile(result.output).then(() => {\n outputErrors(result);\n });\n }\n })\n .catch((error) => {\n if (error.errors) {\n outputErrors(error);\n } else {\n logError('Failed to explore', error);\n }\n\n process.exitCode = 1;\n });\n}\n"]}
|
package/dist/coverage.d.ts
CHANGED
@@ -1,13 +1,4 @@
|
|
1
|
-
import { Bundle, ColumnsRange, MappingRange, FileDataMap } from './
|
2
|
-
/**
|
3
|
-
* Match coverages' ranges to bundles by comparing coverage URL and bundle filename
|
4
|
-
*/
|
1
|
+
import type { Bundle, ColumnsRange, MappingRange, FileDataMap } from './types';
|
5
2
|
export declare function addCoverageRanges(bundles: Bundle[], coverageFilename?: string): Bundle[];
|
6
|
-
/**
|
7
|
-
* Set covered size for files
|
8
|
-
*/
|
9
3
|
export declare function setCoveredSizes(line: string, files: FileDataMap, mappingRanges: MappingRange[], coveredRanges: ColumnsRange[]): FileDataMap;
|
10
|
-
/**
|
11
|
-
* Get heat map color by coverage percent
|
12
|
-
*/
|
13
4
|
export declare function getColorByPercent(percent: number): string;
|
package/dist/coverage.js
CHANGED
@@ -1,116 +1,70 @@
|
|
1
1
|
'use strict';
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
exports.addCoverageRanges = addCoverageRanges;
|
7
|
-
exports.setCoveredSizes = setCoveredSizes;
|
8
|
-
exports.getColorByPercent = getColorByPercent;
|
9
|
-
|
10
|
-
var _helpers = require('./helpers');
|
11
|
-
|
12
|
-
var _appError = require('./app-error');
|
13
|
-
|
14
|
-
/**
|
15
|
-
* Convert one-line coverage ranges (exclusive) into per line ranges (inclusive)
|
16
|
-
*/
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
3
|
+
const url_1 = require('url');
|
4
|
+
const helpers_1 = require('./helpers');
|
5
|
+
const app_error_1 = require('./app-error');
|
17
6
|
function convertRangesToLinesRanges(coverage) {
|
18
7
|
const { ranges, text } = coverage;
|
19
|
-
const eol =
|
8
|
+
const eol = helpers_1.detectEOL(text);
|
20
9
|
const eolLength = eol.length;
|
21
|
-
const lines = text.split(eol);
|
22
|
-
|
10
|
+
const lines = text.split(eol);
|
23
11
|
let offset = 0;
|
24
|
-
const lineRanges = lines.map(line => {
|
12
|
+
const lineRanges = lines.map((line) => {
|
25
13
|
const lineLength = line.length;
|
26
|
-
|
27
14
|
if (lineLength === 0) {
|
28
15
|
return [];
|
29
|
-
}
|
30
|
-
|
16
|
+
}
|
31
17
|
const lineStart = offset;
|
32
18
|
const lineEnd = offset + lineLength;
|
33
19
|
const lineRanges = ranges.reduce((result, { start, end }) => {
|
34
|
-
// Inclusive range start/end within the line
|
35
20
|
const startIndex = start - lineStart;
|
36
21
|
const endIndex = end - lineStart - 1;
|
37
22
|
const lineEndIndex = lineLength - 1;
|
38
|
-
|
39
23
|
if (start <= lineStart && lineEnd <= end) {
|
40
|
-
|
41
|
-
result.push({
|
42
|
-
start: 0,
|
43
|
-
end: lineEndIndex,
|
44
|
-
});
|
24
|
+
result.push({ start: 0, end: lineEndIndex });
|
45
25
|
} else if (lineStart <= start && end <= lineEnd) {
|
46
|
-
|
47
|
-
result.push({
|
48
|
-
start: startIndex,
|
49
|
-
end: endIndex,
|
50
|
-
});
|
26
|
+
result.push({ start: startIndex, end: endIndex });
|
51
27
|
} else if (lineStart <= start && start <= lineEnd) {
|
52
|
-
|
53
|
-
result.push({
|
54
|
-
start: startIndex,
|
55
|
-
end: lineEndIndex,
|
56
|
-
});
|
28
|
+
result.push({ start: startIndex, end: lineEndIndex });
|
57
29
|
} else if (lineStart <= end && end <= lineEnd) {
|
58
|
-
|
59
|
-
result.push({
|
60
|
-
start: 0,
|
61
|
-
end: endIndex,
|
62
|
-
});
|
30
|
+
result.push({ start: 0, end: endIndex });
|
63
31
|
}
|
64
|
-
|
65
32
|
return result;
|
66
|
-
}, []);
|
67
|
-
|
33
|
+
}, []);
|
68
34
|
offset = lineEnd + eolLength;
|
69
35
|
return lineRanges;
|
70
36
|
});
|
71
37
|
return lineRanges;
|
72
38
|
}
|
73
|
-
|
74
39
|
const PATH_SEPARATOR_REGEX = /[/\\]/;
|
75
|
-
|
76
40
|
function getPathParts(path) {
|
77
41
|
return path.split(PATH_SEPARATOR_REGEX).filter(Boolean);
|
78
42
|
}
|
79
|
-
/**
|
80
|
-
* Match coverages' ranges to bundles by comparing coverage URL and bundle filename
|
81
|
-
*/
|
82
|
-
|
83
43
|
function addCoverageRanges(bundles, coverageFilename) {
|
84
44
|
if (!coverageFilename) {
|
85
45
|
return bundles;
|
86
46
|
}
|
87
|
-
|
88
47
|
try {
|
89
|
-
const coverages = JSON.parse(
|
48
|
+
const coverages = JSON.parse(helpers_1.getFileContent(coverageFilename));
|
90
49
|
const bundlesPaths = bundles.reduce((result, { code }, index) => {
|
91
50
|
if (!Buffer.isBuffer(code)) {
|
92
51
|
result.push([getPathParts(code).reverse(), index]);
|
93
52
|
}
|
94
|
-
|
95
53
|
return result;
|
96
54
|
}, []);
|
97
|
-
coverages
|
98
|
-
.map(({ url }) => getPathParts(new URL(url).pathname).reverse())
|
55
|
+
coverages
|
56
|
+
.map(({ url }) => getPathParts(new url_1.URL(url).pathname).reverse())
|
99
57
|
.forEach((partsA, coverageIndex) => {
|
100
|
-
// Exclude coverages for inlined code (URL doesn't contain a filename)
|
101
58
|
if (!partsA.length) return;
|
102
|
-
let matchingBundles = [...bundlesPaths];
|
103
|
-
|
59
|
+
let matchingBundles = [...bundlesPaths];
|
104
60
|
for (let i = 0; i < partsA.length; i++) {
|
105
61
|
matchingBundles = matchingBundles.filter(
|
106
62
|
([partsB]) => i < partsB.length && partsB[i] === partsA[i]
|
107
|
-
);
|
108
|
-
|
63
|
+
);
|
109
64
|
if (matchingBundles.length <= 1) {
|
110
65
|
break;
|
111
66
|
}
|
112
67
|
}
|
113
|
-
|
114
68
|
if (matchingBundles.length === 1) {
|
115
69
|
const [[, bundleIndex]] = matchingBundles;
|
116
70
|
bundles[bundleIndex].coverageRanges = convertRangesToLinesRanges(
|
@@ -119,38 +73,22 @@ function addCoverageRanges(bundles, coverageFilename) {
|
|
119
73
|
}
|
120
74
|
});
|
121
75
|
} catch (error) {
|
122
|
-
throw new
|
123
|
-
{
|
124
|
-
code: 'CannotOpenCoverageFile',
|
125
|
-
},
|
126
|
-
error
|
127
|
-
);
|
76
|
+
throw new app_error_1.AppError({ code: 'CannotOpenCoverageFile' }, error);
|
128
77
|
}
|
129
|
-
|
130
78
|
if (bundles.every(({ coverageRanges }) => coverageRanges === undefined)) {
|
131
|
-
throw new
|
132
|
-
code: 'NoCoverageMatches',
|
133
|
-
});
|
79
|
+
throw new app_error_1.AppError({ code: 'NoCoverageMatches' });
|
134
80
|
}
|
135
|
-
|
136
81
|
return bundles;
|
137
82
|
}
|
138
|
-
|
139
|
-
* Find overlaps in arrays of column ranges, using ratcheting pointers instead of nested loops for
|
140
|
-
* O(n) runtime instead of O(n^2)
|
141
|
-
*/
|
142
|
-
|
83
|
+
exports.addCoverageRanges = addCoverageRanges;
|
143
84
|
function findCoveredMappingRanges(mappingRanges, coveredRanges) {
|
144
85
|
let i = 0;
|
145
86
|
let j = 0;
|
146
87
|
const result = [];
|
147
|
-
|
148
88
|
while (i < mappingRanges.length && j < coveredRanges.length) {
|
149
89
|
const mappingRange = mappingRanges[i];
|
150
90
|
const coveredRange = coveredRanges[j];
|
151
|
-
|
152
91
|
if (mappingRange.start <= coveredRange.end && coveredRange.start <= mappingRange.end) {
|
153
|
-
// Overlaps, calculate amount, move to next coverage range
|
154
92
|
const end = Math.min(coveredRange.end, mappingRange.end);
|
155
93
|
const start = Math.max(mappingRange.start, coveredRange.start);
|
156
94
|
result.push({
|
@@ -158,35 +96,24 @@ function findCoveredMappingRanges(mappingRanges, coveredRanges) {
|
|
158
96
|
end,
|
159
97
|
source: mappingRange.source,
|
160
98
|
});
|
161
|
-
|
162
99
|
if (
|
163
100
|
mappingRanges[i + 1] !== undefined &&
|
164
101
|
mappingRanges[i + 1].start <= coveredRange.end &&
|
165
102
|
mappingRanges[i + 1].end >= coveredRange.start
|
166
103
|
) {
|
167
|
-
// Next module also overlaps current coverage range, advance to next module instead of advancing coverage
|
168
104
|
i++;
|
169
105
|
} else {
|
170
|
-
// Check next coverage range, it may also overlap this module range
|
171
106
|
j++;
|
172
107
|
}
|
173
108
|
} else if (mappingRange.end < coveredRange.start) {
|
174
|
-
// Module comes entirely before coverageRange, check next module range
|
175
109
|
i++;
|
176
110
|
}
|
177
|
-
|
178
111
|
if (coveredRange.end < mappingRange.start) {
|
179
|
-
// Module range comes entirely after coverage range, check next coverage range
|
180
112
|
j++;
|
181
113
|
}
|
182
114
|
}
|
183
|
-
|
184
115
|
return result;
|
185
116
|
}
|
186
|
-
/**
|
187
|
-
* Set covered size for files
|
188
|
-
*/
|
189
|
-
|
190
117
|
function setCoveredSizes(line, files, mappingRanges, coveredRanges) {
|
191
118
|
findCoveredMappingRanges(mappingRanges, coveredRanges).forEach(({ start, end, source }) => {
|
192
119
|
const rangeByteLength = Buffer.byteLength(line.substring(start, end + 1));
|
@@ -196,46 +123,19 @@ function setCoveredSizes(line, files, mappingRanges, coveredRanges) {
|
|
196
123
|
});
|
197
124
|
return files;
|
198
125
|
}
|
199
|
-
|
126
|
+
exports.setCoveredSizes = setCoveredSizes;
|
200
127
|
const percentColors = [
|
201
|
-
{
|
202
|
-
|
203
|
-
|
204
|
-
r: 0xff,
|
205
|
-
g: 0x00,
|
206
|
-
b: 0,
|
207
|
-
},
|
208
|
-
},
|
209
|
-
{
|
210
|
-
percent: 0.5,
|
211
|
-
color: {
|
212
|
-
r: 0xff,
|
213
|
-
g: 0xff,
|
214
|
-
b: 0,
|
215
|
-
},
|
216
|
-
},
|
217
|
-
{
|
218
|
-
percent: 1.0,
|
219
|
-
color: {
|
220
|
-
r: 0x00,
|
221
|
-
g: 0xff,
|
222
|
-
b: 0,
|
223
|
-
},
|
224
|
-
},
|
128
|
+
{ percent: 0.0, color: { r: 0xff, g: 0x00, b: 0 } },
|
129
|
+
{ percent: 0.5, color: { r: 0xff, g: 0xff, b: 0 } },
|
130
|
+
{ percent: 1.0, color: { r: 0x00, g: 0xff, b: 0 } },
|
225
131
|
];
|
226
|
-
/**
|
227
|
-
* Get heat map color by coverage percent
|
228
|
-
*/
|
229
|
-
|
230
132
|
function getColorByPercent(percent) {
|
231
133
|
let i = 1;
|
232
|
-
|
233
134
|
for (; i < percentColors.length - 1; i++) {
|
234
135
|
if (percent < percentColors[i].percent) {
|
235
136
|
break;
|
236
137
|
}
|
237
138
|
}
|
238
|
-
|
239
139
|
const lowerColor = percentColors[i - 1];
|
240
140
|
const upperColor = percentColors[i];
|
241
141
|
const rangeWithinColors = upperColor.percent - lowerColor.percent;
|
@@ -247,3 +147,5 @@ function getColorByPercent(percent) {
|
|
247
147
|
const b = Math.floor(lowerColor.color.b * percentLower + upperColor.color.b * percentUpper);
|
248
148
|
return `rgb(${r}, ${g}, ${b})`;
|
249
149
|
}
|
150
|
+
exports.getColorByPercent = getColorByPercent;
|
151
|
+
//# sourceMappingURL=coverage.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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","sourcesContent":["import { URL } from 'url';\n\nimport { getFileContent, detectEOL } from './helpers';\nimport { AppError } from './app-error';\n\nimport type { Bundle, Coverage, ColumnsRange, MappingRange, FileDataMap } from './types';\n\n/**\n * Convert one-line coverage ranges (exclusive) into per line ranges (inclusive)\n */\nfunction convertRangesToLinesRanges(coverage: Coverage): ColumnsRange[][] {\n const { ranges, text } = coverage;\n\n const eol = detectEOL(text);\n const eolLength = eol.length;\n const lines = text.split(eol);\n\n // Current line offset\n let offset = 0;\n\n const lineRanges = lines.map((line) => {\n const lineLength = line.length;\n\n if (lineLength === 0) {\n return [];\n }\n\n // Exclusive line start/end\n const lineStart = offset;\n const lineEnd = offset + lineLength;\n\n const lineRanges = ranges.reduce<ColumnsRange[]>((result, { start, end }) => {\n // Inclusive range start/end within the line\n const startIndex = start - lineStart;\n const endIndex = end - lineStart - 1;\n const lineEndIndex = lineLength - 1;\n\n if (start <= lineStart && lineEnd <= end) {\n // Range includes line range\n result.push({ start: 0, end: lineEndIndex });\n } else if (lineStart <= start && end <= lineEnd) {\n // Line range includes range\n result.push({ start: startIndex, end: endIndex });\n } else if (lineStart <= start && start <= lineEnd) {\n // Range starts within line range\n result.push({ start: startIndex, end: lineEndIndex });\n } else if (lineStart <= end && end <= lineEnd) {\n // Range ends within line range\n result.push({ start: 0, end: endIndex });\n }\n\n return result;\n }, []);\n\n // Move to next line jumping over EOL character\n offset = lineEnd + eolLength;\n\n return lineRanges;\n });\n\n return lineRanges;\n}\n\nconst PATH_SEPARATOR_REGEX = /[/\\\\]/;\n\nfunction getPathParts(path: string): string[] {\n return path.split(PATH_SEPARATOR_REGEX).filter(Boolean);\n}\n\n/**\n * Match coverages' ranges to bundles by comparing coverage URL and bundle filename\n */\nexport function addCoverageRanges(bundles: Bundle[], coverageFilename?: string): Bundle[] {\n if (!coverageFilename) {\n return bundles;\n }\n\n try {\n const coverages: Coverage[] = JSON.parse(getFileContent(coverageFilename));\n\n const bundlesPaths = bundles.reduce<[string[], number][]>((result, { code }, index) => {\n if (!Buffer.isBuffer(code)) {\n result.push([getPathParts(code).reverse(), index]);\n }\n\n return result;\n }, []);\n\n coverages\n // pathname contains filename\n .map(({ url }) => getPathParts(new URL(url).pathname).reverse())\n .forEach((partsA, coverageIndex) => {\n // Exclude coverages for inlined code (URL doesn't contain a filename)\n if (!partsA.length) return;\n let matchingBundles = [...bundlesPaths];\n\n // Start from filename and go up to path root\n for (let i = 0; i < partsA.length; i++) {\n matchingBundles = matchingBundles.filter(\n ([partsB]) => i < partsB.length && partsB[i] === partsA[i]\n );\n\n // Stop when exact (among bundles) match found or no matches found\n if (matchingBundles.length <= 1) {\n break;\n }\n }\n\n if (matchingBundles.length === 1) {\n const [[, bundleIndex]] = matchingBundles;\n\n bundles[bundleIndex].coverageRanges = convertRangesToLinesRanges(\n coverages[coverageIndex]\n );\n }\n });\n } catch (error) {\n throw new AppError({ code: 'CannotOpenCoverageFile' }, error);\n }\n\n if (bundles.every(({ coverageRanges }) => coverageRanges === undefined)) {\n throw new AppError({ code: 'NoCoverageMatches' });\n }\n\n return bundles;\n}\n\n/**\n * Find overlaps in arrays of column ranges, using ratcheting pointers instead of nested loops for\n * O(n) runtime instead of O(n^2)\n */\nfunction findCoveredMappingRanges(\n mappingRanges: MappingRange[],\n coveredRanges: ColumnsRange[]\n): MappingRange[] {\n let i = 0;\n let j = 0;\n\n const result: MappingRange[] = [];\n\n while (i < mappingRanges.length && j < coveredRanges.length) {\n const mappingRange = mappingRanges[i];\n const coveredRange = coveredRanges[j];\n\n if (mappingRange.start <= coveredRange.end && coveredRange.start <= mappingRange.end) {\n // Overlaps, calculate amount, move to next coverage range\n const end = Math.min(coveredRange.end, mappingRange.end);\n const start = Math.max(mappingRange.start, coveredRange.start);\n\n result.push({\n start,\n end,\n source: mappingRange.source,\n });\n\n if (\n mappingRanges[i + 1] !== undefined &&\n mappingRanges[i + 1].start <= coveredRange.end &&\n mappingRanges[i + 1].end >= coveredRange.start\n ) {\n // Next module also overlaps current coverage range, advance to next module instead of advancing coverage\n i++;\n } else {\n // Check next coverage range, it may also overlap this module range\n j++;\n }\n } else if (mappingRange.end < coveredRange.start) {\n // Module comes entirely before coverageRange, check next module range\n i++;\n }\n if (coveredRange.end < mappingRange.start) {\n // Module range comes entirely after coverage range, check next coverage range\n j++;\n }\n }\n\n return result;\n}\n\n/**\n * Set covered size for files\n */\nexport function setCoveredSizes(\n line: string,\n files: FileDataMap,\n mappingRanges: MappingRange[],\n coveredRanges: ColumnsRange[]\n): FileDataMap {\n findCoveredMappingRanges(mappingRanges, coveredRanges).forEach(({ start, end, source }) => {\n const rangeByteLength = Buffer.byteLength(line.substring(start, end + 1));\n\n let coveredSize = files[source].coveredSize || 0;\n\n coveredSize += rangeByteLength;\n\n files[source].coveredSize = coveredSize;\n });\n\n return files;\n}\n\nconst percentColors = [\n { percent: 0.0, color: { r: 0xff, g: 0x00, b: 0 } },\n { percent: 0.5, color: { r: 0xff, g: 0xff, b: 0 } },\n { percent: 1.0, color: { r: 0x00, g: 0xff, b: 0 } },\n];\n\n/**\n * Get heat map color by coverage percent\n */\nexport function getColorByPercent(percent: number): string {\n let i = 1;\n\n for (; i < percentColors.length - 1; i++) {\n if (percent < percentColors[i].percent) {\n break;\n }\n }\n\n const lowerColor = percentColors[i - 1];\n const upperColor = percentColors[i];\n const rangeWithinColors = upperColor.percent - lowerColor.percent;\n const rangePercent = (percent - lowerColor.percent) / rangeWithinColors;\n const percentLower = 1 - rangePercent;\n const percentUpper = rangePercent;\n\n const r = Math.floor(lowerColor.color.r * percentLower + upperColor.color.r * percentUpper);\n const g = Math.floor(lowerColor.color.g * percentLower + upperColor.color.g * percentUpper);\n const b = Math.floor(lowerColor.color.b * percentLower + upperColor.color.b * percentUpper);\n\n return `rgb(${r}, ${g}, ${b})`;\n}\n"]}
|
package/dist/explore.d.ts
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
import { Bundle,
|
1
|
+
import type { Bundle, ExploreBundleResult, ExploreOptions, FileDataMap } from './types';
|
2
2
|
export declare const UNMAPPED_KEY = "[unmapped]";
|
3
3
|
export declare const SOURCE_MAP_COMMENT_KEY = "[sourceMappingURL]";
|
4
4
|
export declare const NO_SOURCE_KEY = "[no source]";
|
5
5
|
export declare const EOL_KEY = "[EOLs]";
|
6
6
|
export declare const SPECIAL_FILENAMES: string[];
|
7
|
-
/**
|
8
|
-
* Analyze a bundle
|
9
|
-
*/
|
10
7
|
export declare function exploreBundle(bundle: Bundle, options: ExploreOptions): Promise<ExploreBundleResult>;
|
11
8
|
export declare function adjustSourcePaths(fileSizeMap: FileDataMap, options: ExploreOptions): FileDataMap;
|