source-map-explorer 2.3.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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;
|