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/dist/cli.js CHANGED
@@ -1,41 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
-
4
- Object.defineProperty(exports, '__esModule', {
5
- value: true,
6
- });
7
- exports.logError = logError;
8
- exports.logWarn = logWarn;
9
- exports.logInfo = logInfo;
10
-
11
- var _yargs = _interopRequireDefault(require('yargs'));
12
-
13
- var _fs = _interopRequireDefault(require('fs'));
14
-
15
- var _temp = _interopRequireDefault(require('temp'));
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 = _yargs.default
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) // Do not limit line length
104
+ .wrap(null)
111
105
  .parserConfiguration({
112
- 'boolean-negation': false, // Allow --no-root
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(); // Trim extra quotes
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 (!(0, _lodash.isString)(message)) {
130
- message = (0, _appError.getErrorMessage)(message);
120
+ if (!lodash_1.isString(message)) {
121
+ message = app_error_1.getErrorMessage(message);
131
122
  }
132
-
133
123
  if (error) {
134
- console.error(_chalk.default.red(message), error);
124
+ console.error(chalk_1.default.red(message), error);
135
125
  } else {
136
- console.error(_chalk.default.red(message));
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(_chalk.default.yellow(message));
131
+ console.warn(chalk_1.default.yellow(message));
142
132
  }
143
-
133
+ exports.logWarn = logWarn;
144
134
  function logInfo(message) {
145
- console.log(_chalk.default.green(message));
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
- // By default CLI needs result in HTML in order to create a temporary file
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 = _temp.default.path({
198
- prefix: 'sme-result-',
199
- suffix: '.html',
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
- // Catch error output from child process
208
- childProcess.stderr.once('data', error => {
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 _appError.AppError(
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
- } // Group errors by bundle name
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(_lodash.isString);
213
+ const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(lodash_1.isString);
251
214
  const options = getExploreOptions(argv);
252
- (0, _api.explore)(argv._, options)
253
- .then(result => {
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
@@ -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"]}
@@ -1,13 +1,4 @@
1
- import { Bundle, ColumnsRange, MappingRange, FileDataMap } from './index';
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
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
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 = (0, _helpers.detectEOL)(text);
8
+ const eol = helpers_1.detectEOL(text);
20
9
  const eolLength = eol.length;
21
- const lines = text.split(eol); // Current line offset
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
- } // Exclusive line start/end
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
- // Range includes line range
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
- // Line range includes range
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
- // Range starts within line range
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
- // Range ends within line range
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
- }, []); // Move to next line jumping over EOL character
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((0, _helpers.getFileContent)(coverageFilename));
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 // pathname contains filename
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]; // Start from filename and go up to path root
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
- ); // Stop when exact (among bundles) match found or no matches found
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 _appError.AppError(
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 _appError.AppError({
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
- percent: 0.0,
203
- color: {
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, ExploreOptions, ExploreBundleResult, FileDataMap } from './index';
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;