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/dist/explore.js CHANGED
@@ -1,125 +1,114 @@
1
1
  'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
5
- });
6
- exports.exploreBundle = exploreBundle;
7
- exports.adjustSourcePaths = adjustSourcePaths;
8
- exports.SPECIAL_FILENAMES = exports.EOL_KEY = exports.NO_SOURCE_KEY = exports.SOURCE_MAP_COMMENT_KEY = exports.UNMAPPED_KEY = void 0;
9
-
10
- var _convertSourceMap = _interopRequireDefault(require('convert-source-map'));
11
-
12
- var _path = _interopRequireDefault(require('path'));
13
-
14
- var _sourceMap = require('source-map');
15
-
16
- var _gzipSize = _interopRequireDefault(require('gzip-size'));
17
-
18
- var _lodash = require('lodash');
19
-
20
- var _api = require('./api');
21
-
22
- var _helpers = require('./helpers');
23
-
24
- var _appError = require('./app-error');
25
-
26
- var _coverage = require('./coverage');
27
-
28
- function _interopRequireDefault(obj) {
29
- return obj && obj.__esModule ? obj : { default: obj };
30
- }
31
-
32
- const UNMAPPED_KEY = '[unmapped]';
33
- exports.UNMAPPED_KEY = UNMAPPED_KEY;
34
- const SOURCE_MAP_COMMENT_KEY = '[sourceMappingURL]';
35
- exports.SOURCE_MAP_COMMENT_KEY = SOURCE_MAP_COMMENT_KEY;
36
- const NO_SOURCE_KEY = '[no source]';
37
- exports.NO_SOURCE_KEY = NO_SOURCE_KEY;
38
- const EOL_KEY = '[EOLs]';
39
- exports.EOL_KEY = EOL_KEY;
40
- const SPECIAL_FILENAMES = [UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY, EOL_KEY];
41
- /**
42
- * Analyze a bundle
43
- */
44
-
45
- exports.SPECIAL_FILENAMES = SPECIAL_FILENAMES;
46
-
2
+ var __importDefault =
3
+ (this && this.__importDefault) ||
4
+ function (mod) {
5
+ return mod && mod.__esModule ? mod : { default: mod };
6
+ };
7
+ Object.defineProperty(exports, '__esModule', { value: true });
8
+ const convert_source_map_1 = __importDefault(require('convert-source-map'));
9
+ const path_1 = __importDefault(require('path'));
10
+ const source_map_1 = require('source-map');
11
+ const gzip_size_1 = __importDefault(require('gzip-size'));
12
+ const lodash_1 = require('lodash');
13
+ const api_1 = require('./api');
14
+ const helpers_1 = require('./helpers');
15
+ const app_error_1 = require('./app-error');
16
+ const coverage_1 = require('./coverage');
17
+ exports.UNMAPPED_KEY = '[unmapped]';
18
+ exports.SOURCE_MAP_COMMENT_KEY = '[sourceMappingURL]';
19
+ exports.NO_SOURCE_KEY = '[no source]';
20
+ exports.EOL_KEY = '[EOLs]';
21
+ exports.SPECIAL_FILENAMES = [
22
+ exports.UNMAPPED_KEY,
23
+ exports.SOURCE_MAP_COMMENT_KEY,
24
+ exports.NO_SOURCE_KEY,
25
+ exports.EOL_KEY,
26
+ ];
47
27
  async function exploreBundle(bundle, options) {
48
28
  const { code, map, coverageRanges } = bundle;
49
29
  const sourceMapData = await loadSourceMap(code, map);
50
30
  const sizes = computeFileSizes(sourceMapData, options, coverageRanges);
51
- const files = adjustSourcePaths(sizes.files, options); // Free Wasm data
52
-
31
+ const files = adjustSourcePaths(sizes.files, options);
53
32
  sourceMapData.consumer.destroy();
54
33
  return {
55
- bundleName: (0, _api.getBundleName)(bundle),
34
+ bundleName: api_1.getBundleName(bundle),
56
35
  ...sizes,
57
36
  files,
58
37
  };
59
38
  }
60
-
61
- /**
62
- * Get source map
63
- */
39
+ exports.exploreBundle = exploreBundle;
64
40
  async function loadSourceMap(codeFile, sourceMapFile) {
65
- const codeFileContent = (0, _helpers.getFileContent)(codeFile);
41
+ const codeFileContent = helpers_1.getFileContent(codeFile);
66
42
  let consumer;
67
-
68
43
  if (sourceMapFile) {
69
- const sourceMapFileContent = (0, _helpers.getFileContent)(sourceMapFile);
70
- consumer = await new _sourceMap.SourceMapConsumer(sourceMapFileContent);
44
+ const sourceMapFileContent = helpers_1.getFileContent(sourceMapFile);
45
+ consumer = await new source_map_1.SourceMapConsumer(sourceMapFileContent);
71
46
  } else {
72
- // Try to read a source map from a 'sourceMappingURL' comment.
73
- let converter = _convertSourceMap.default.fromSource(codeFileContent);
74
-
47
+ let converter = convert_source_map_1.default.fromSource(codeFileContent);
75
48
  if (!converter && !Buffer.isBuffer(codeFile)) {
76
- converter = _convertSourceMap.default.fromMapFileSource(
49
+ converter = convert_source_map_1.default.fromMapFileSource(
77
50
  codeFileContent,
78
- _path.default.dirname(codeFile)
51
+ path_1.default.dirname(codeFile)
79
52
  );
80
53
  }
81
-
82
54
  if (!converter) {
83
- throw new _appError.AppError({
84
- code: 'NoSourceMap',
85
- });
55
+ throw new app_error_1.AppError({ code: 'NoSourceMap' });
86
56
  }
87
-
88
- consumer = await new _sourceMap.SourceMapConsumer(converter.toJSON());
57
+ consumer = await new source_map_1.SourceMapConsumer(converter.toJSON());
89
58
  }
90
-
91
59
  if (!consumer) {
92
- throw new _appError.AppError({
93
- code: 'NoSourceMap',
94
- });
60
+ throw new app_error_1.AppError({ code: 'NoSourceMap' });
95
61
  }
96
-
97
62
  return {
98
63
  consumer,
99
64
  codeFileContent,
100
65
  };
101
66
  }
102
-
103
- const COMMENT_REGEX = _convertSourceMap.default.commentRegex;
104
- const MAP_FILE_COMMENT_REGEX = _convertSourceMap.default.mapFileCommentRegex;
105
- /**
106
- * Extract either source map comment/file
107
- */
108
-
67
+ const COMMENT_REGEX = convert_source_map_1.default.commentRegex;
68
+ const MAP_FILE_COMMENT_REGEX = convert_source_map_1.default.mapFileCommentRegex;
109
69
  function getSourceMapComment(fileContent) {
110
70
  const sourceMapComment =
111
- (0, _helpers.getFirstRegexMatch)(COMMENT_REGEX, fileContent) ||
112
- (0, _helpers.getFirstRegexMatch)(MAP_FILE_COMMENT_REGEX, fileContent) ||
113
- ''; // Remove trailing EOLs
114
-
71
+ helpers_1.getFirstRegexMatch(COMMENT_REGEX, fileContent) ||
72
+ helpers_1.getFirstRegexMatch(MAP_FILE_COMMENT_REGEX, fileContent) ||
73
+ '';
115
74
  return sourceMapComment.trim();
116
75
  }
117
-
118
- function checkInvalidMappingColumn({ generatedLine, generatedColumn, line }) {
76
+ function isReferencingEOL(context, maxColumnIndex) {
77
+ const { generatedLine, generatedColumn, source, consumer } = context;
78
+ if (maxColumnIndex - generatedColumn > 2) {
79
+ return false;
80
+ }
81
+ if (!source) {
82
+ return false;
83
+ }
84
+ if (context.mapReferenceEOLSources.has(source)) {
85
+ return true;
86
+ }
87
+ const content = consumer.sourceContentFor(source, true);
88
+ if (!content) {
89
+ return false;
90
+ }
91
+ const { line, column } = consumer.originalPositionFor({
92
+ line: generatedLine,
93
+ column: generatedColumn,
94
+ });
95
+ if (line === null || column === null) {
96
+ return false;
97
+ }
98
+ if (helpers_1.isEOLAtPosition(content, [line, column])) {
99
+ context.mapReferenceEOLSources.add(source);
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ function checkInvalidMappingColumn(context) {
105
+ const { line, generatedLine, generatedColumn } = context;
119
106
  const maxColumnIndex = line.length - 1;
120
-
121
107
  if (generatedColumn > maxColumnIndex) {
122
- throw new _appError.AppError({
108
+ if (isReferencingEOL(context, maxColumnIndex)) {
109
+ return;
110
+ }
111
+ throw new app_error_1.AppError({
123
112
  code: 'InvalidMappingColumn',
124
113
  generatedLine,
125
114
  generatedColumn,
@@ -127,132 +116,111 @@ function checkInvalidMappingColumn({ generatedLine, generatedColumn, line }) {
127
116
  });
128
117
  }
129
118
  }
130
- /**
131
- * Calculate the number of bytes contributed by each source file
132
- */
133
-
134
119
  function computeFileSizes(sourceMapData, options, coverageRanges) {
135
120
  const { consumer, codeFileContent: fileContent } = sourceMapData;
136
- const sourceMapComment = getSourceMapComment(fileContent); // Remove inline source map comment, source map file comment and trailing EOLs
137
-
138
- const source = fileContent.replace(sourceMapComment, '').trim();
139
- const eol = (0, _helpers.detectEOL)(fileContent); // Assume only one type of EOL is used
140
-
141
- const lines = source.split(eol);
121
+ const sourceMapComment = getSourceMapComment(fileContent);
122
+ const sourceContent = fileContent.replace(sourceMapComment, '').trim();
123
+ const eol = helpers_1.detectEOL(fileContent);
124
+ const lines = sourceContent.split(eol);
142
125
  const mappingRanges = [];
126
+ const context = {
127
+ generatedLine: -1,
128
+ generatedColumn: -1,
129
+ line: '',
130
+ source: null,
131
+ consumer,
132
+ mapReferenceEOLSources: new Set(),
133
+ };
143
134
  consumer.computeColumnSpans();
144
135
  consumer.eachMapping(({ source, generatedLine, generatedColumn, lastGeneratedColumn }) => {
145
- // Columns are 0-based, Lines are 1-based
146
136
  const lineIndex = generatedLine - 1;
147
137
  const line = lines[lineIndex];
148
-
149
138
  if (line === undefined) {
150
- throw new _appError.AppError({
139
+ if (options.noBorderChecks) {
140
+ return;
141
+ }
142
+ throw new app_error_1.AppError({
151
143
  code: 'InvalidMappingLine',
152
144
  generatedLine,
153
145
  maxLine: lines.length,
154
146
  });
155
- } // TODO: uncomment when https://github.com/danvk/source-map-explorer/issues/136 is fixed
156
-
157
- /* checkInvalidMappingColumn({
158
- generatedLine,
159
- generatedColumn: lastGeneratedColumn || generatedColumn,
160
- line,
161
- }); */
162
-
147
+ }
148
+ context.generatedLine = generatedLine;
149
+ context.generatedColumn = lastGeneratedColumn || generatedColumn;
150
+ context.line = line;
151
+ context.source = source;
152
+ if (!options.noBorderChecks) {
153
+ checkInvalidMappingColumn(context);
154
+ }
163
155
  const start = generatedColumn;
164
156
  const end = lastGeneratedColumn === null ? line.length - 1 : lastGeneratedColumn;
165
157
  const lineRanges = mappingRanges[lineIndex] || [];
166
158
  lineRanges.push({
167
159
  start,
168
160
  end,
169
- source: source === null ? NO_SOURCE_KEY : source,
161
+ source: source === null ? exports.NO_SOURCE_KEY : source,
170
162
  });
171
163
  mappingRanges[lineIndex] = lineRanges;
172
164
  });
173
165
  let files = {};
174
166
  let mappedBytes = 0;
175
- const getSize = options.gzip ? _gzipSize.default.sync : Buffer.byteLength;
167
+ const getSize = options.gzip ? gzip_size_1.default.sync : Buffer.byteLength;
176
168
  mappingRanges.forEach((lineRanges, lineIndex) => {
177
169
  const line = lines[lineIndex];
178
- const mergedRanges = (0, _helpers.mergeRanges)(lineRanges);
170
+ const mergedRanges = helpers_1.mergeRanges(lineRanges);
179
171
  mergedRanges.forEach(({ start, end, source }) => {
180
- const rangeString = line.substring(start, end + 1); // To account unicode measure byte length rather than symbols count
181
-
172
+ const rangeString = line.substring(start, end + 1);
182
173
  const rangeByteLength = getSize(rangeString);
183
-
184
174
  if (!files[source]) {
185
- files[source] = {
186
- size: 0,
187
- };
175
+ files[source] = { size: 0 };
188
176
  }
189
-
190
177
  files[source].size += rangeByteLength;
191
178
  mappedBytes += rangeByteLength;
192
179
  });
193
-
194
180
  if (coverageRanges) {
195
- files = (0, _coverage.setCoveredSizes)(line, files, mergedRanges, coverageRanges[lineIndex]);
181
+ files = coverage_1.setCoveredSizes(line, files, mergedRanges, coverageRanges[lineIndex]);
196
182
  }
197
183
  });
198
184
  const sourceMapCommentBytes = getSize(sourceMapComment);
199
- const eolBytes = (0, _helpers.getOccurrencesCount)(eol, fileContent) * Buffer.byteLength(eol);
185
+ const eolBytes = helpers_1.getOccurrencesCount(eol, fileContent) * Buffer.byteLength(eol);
200
186
  const totalBytes = getSize(fileContent);
201
187
  let unmappedBytes;
202
-
203
188
  if (!options.excludeSourceMapComment) {
204
- files[SOURCE_MAP_COMMENT_KEY] = {
205
- size: sourceMapCommentBytes,
206
- };
189
+ files[exports.SOURCE_MAP_COMMENT_KEY] = { size: sourceMapCommentBytes };
207
190
  }
208
-
209
191
  if (!options.onlyMapped) {
210
192
  unmappedBytes = totalBytes - mappedBytes - sourceMapCommentBytes - eolBytes;
211
- files[UNMAPPED_KEY] = {
212
- size: unmappedBytes,
213
- };
193
+ files[exports.UNMAPPED_KEY] = { size: unmappedBytes };
214
194
  }
215
-
216
195
  if (eolBytes > 0) {
217
- files[EOL_KEY] = {
218
- size: eolBytes,
219
- };
196
+ files[exports.EOL_KEY] = { size: eolBytes };
220
197
  }
221
-
222
198
  return {
223
199
  ...(options.excludeSourceMapComment
224
- ? {
225
- totalBytes: totalBytes - sourceMapCommentBytes,
226
- }
227
- : {
228
- totalBytes,
229
- }),
200
+ ? { totalBytes: totalBytes - sourceMapCommentBytes }
201
+ : { totalBytes }),
230
202
  mappedBytes,
231
- ...(!options.onlyMapped && {
232
- unmappedBytes,
233
- }),
203
+ ...(!options.onlyMapped && { unmappedBytes }),
234
204
  eolBytes,
235
205
  sourceMapCommentBytes,
236
206
  files,
237
207
  };
238
208
  }
239
-
240
209
  function adjustSourcePaths(fileSizeMap, options) {
241
210
  if (!options.noRoot) {
242
- const prefix = (0, _helpers.getCommonPathPrefix)(Object.keys(fileSizeMap));
211
+ const prefix = helpers_1.getCommonPathPrefix(Object.keys(fileSizeMap));
243
212
  const length = prefix.length;
244
-
245
213
  if (length) {
246
- fileSizeMap = (0, _lodash.mapKeys)(fileSizeMap, (size, source) => source.slice(length));
214
+ fileSizeMap = lodash_1.mapKeys(fileSizeMap, (size, source) => source.slice(length));
247
215
  }
248
216
  }
249
-
250
217
  if (options.replaceMap) {
251
218
  fileSizeMap = Object.entries(options.replaceMap).reduce((result, [before, after]) => {
252
219
  const regexp = new RegExp(before, 'g');
253
- return (0, _lodash.mapKeys)(result, (size, source) => source.replace(regexp, after));
220
+ return lodash_1.mapKeys(result, (size, source) => source.replace(regexp, after));
254
221
  }, fileSizeMap);
255
222
  }
256
-
257
223
  return fileSizeMap;
258
224
  }
225
+ exports.adjustSourcePaths = adjustSourcePaths;
226
+ //# sourceMappingURL=explore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.js","sourceRoot":"","sources":["../src/explore.ts"],"names":[],"mappings":"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","sourcesContent":["import convert from 'convert-source-map';\nimport path from 'path';\nimport { BasicSourceMapConsumer, IndexedSourceMapConsumer, SourceMapConsumer } from 'source-map';\nimport gzipSize from 'gzip-size';\nimport { mapKeys } from 'lodash';\n\nimport { getBundleName } from './api';\nimport {\n getFileContent,\n getCommonPathPrefix,\n getFirstRegexMatch,\n detectEOL,\n getOccurrencesCount,\n isEOLAtPosition,\n mergeRanges,\n} from './helpers';\nimport { AppError } from './app-error';\nimport { setCoveredSizes } from './coverage';\n\nimport type {\n Bundle,\n CoverageRange,\n ExploreBundleResult,\n ExploreOptions,\n File,\n FileDataMap,\n FileSizes,\n MappingRange,\n} from './types';\n\nexport const UNMAPPED_KEY = '[unmapped]';\nexport const SOURCE_MAP_COMMENT_KEY = '[sourceMappingURL]';\nexport const NO_SOURCE_KEY = '[no source]';\nexport const EOL_KEY = '[EOLs]';\n\nexport const SPECIAL_FILENAMES = [UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY, EOL_KEY];\n\n/**\n * Analyze a bundle\n */\nexport async function exploreBundle(\n bundle: Bundle,\n options: ExploreOptions\n): Promise<ExploreBundleResult> {\n const { code, map, coverageRanges } = bundle;\n\n const sourceMapData = await loadSourceMap(code, map);\n\n const sizes = computeFileSizes(sourceMapData, options, coverageRanges);\n\n const files = adjustSourcePaths(sizes.files, options);\n\n // Free Wasm data\n sourceMapData.consumer.destroy();\n\n return {\n bundleName: getBundleName(bundle),\n ...sizes,\n files,\n };\n}\n\ntype Consumer = BasicSourceMapConsumer | IndexedSourceMapConsumer;\n\ninterface SourceMapData {\n consumer: Consumer;\n codeFileContent: string;\n}\n\n/**\n * Get source map\n */\nasync function loadSourceMap(codeFile: File, sourceMapFile?: File): Promise<SourceMapData> {\n const codeFileContent = getFileContent(codeFile);\n\n let consumer: Consumer;\n\n if (sourceMapFile) {\n const sourceMapFileContent = getFileContent(sourceMapFile);\n\n consumer = await new SourceMapConsumer(sourceMapFileContent);\n } else {\n // Try to read a source map from a 'sourceMappingURL' comment.\n let converter = convert.fromSource(codeFileContent);\n\n if (!converter && !Buffer.isBuffer(codeFile)) {\n converter = convert.fromMapFileSource(codeFileContent, path.dirname(codeFile));\n }\n\n if (!converter) {\n throw new AppError({ code: 'NoSourceMap' });\n }\n\n consumer = await new SourceMapConsumer(converter.toJSON());\n }\n\n if (!consumer) {\n throw new AppError({ code: 'NoSourceMap' });\n }\n\n return {\n consumer,\n codeFileContent,\n };\n}\n\nconst COMMENT_REGEX = convert.commentRegex;\nconst MAP_FILE_COMMENT_REGEX = convert.mapFileCommentRegex;\n\n/**\n * Extract either source map comment/file\n */\nfunction getSourceMapComment(fileContent: string): string {\n const sourceMapComment =\n getFirstRegexMatch(COMMENT_REGEX, fileContent) ||\n getFirstRegexMatch(MAP_FILE_COMMENT_REGEX, fileContent) ||\n '';\n\n // Remove trailing EOLs\n return sourceMapComment.trim();\n}\n\ninterface ComputeFileSizesContext {\n generatedLine: number;\n generatedColumn: number;\n line: string;\n source: string | null;\n consumer: Consumer;\n mapReferenceEOLSources: Set<string>;\n}\n\n/**\n * Check if source map references EOL (see https://github.com/microsoft/TypeScript/issues/34695)\n */\nfunction isReferencingEOL(context: ComputeFileSizesContext, maxColumnIndex: number): boolean {\n const { generatedLine, generatedColumn, source, consumer } = context;\n\n // Ignore difference more than EOL max length (\\r\\n)\n if (maxColumnIndex - generatedColumn > 2) {\n return false;\n }\n\n // Ignore mapping w/o source\n if (!source) {\n return false;\n }\n\n // Don't check the same source twice. It covers most cases even though not 100% reliable\n if (context.mapReferenceEOLSources.has(source)) {\n return true;\n }\n\n const content = consumer.sourceContentFor(source, true);\n\n // Content is needed to detect EOL\n if (!content) {\n return false;\n }\n\n const { line, column } = consumer.originalPositionFor({\n line: generatedLine,\n column: generatedColumn,\n });\n\n if (line === null || column === null) {\n return false;\n }\n\n if (isEOLAtPosition(content, [line, column])) {\n context.mapReferenceEOLSources.add(source);\n\n return true;\n }\n\n return false;\n}\n\nfunction checkInvalidMappingColumn(context: ComputeFileSizesContext): void {\n const { line, generatedLine, generatedColumn } = context;\n const maxColumnIndex = line.length - 1;\n\n if (generatedColumn > maxColumnIndex) {\n if (isReferencingEOL(context, maxColumnIndex)) {\n return;\n }\n\n throw new AppError({\n code: 'InvalidMappingColumn',\n generatedLine,\n generatedColumn,\n maxColumn: line.length,\n });\n }\n}\n\n/**\n * Calculate the number of bytes contributed by each source file\n */\nfunction computeFileSizes(\n sourceMapData: SourceMapData,\n options: ExploreOptions,\n coverageRanges?: CoverageRange[][]\n): FileSizes {\n const { consumer, codeFileContent: fileContent } = sourceMapData;\n\n const sourceMapComment = getSourceMapComment(fileContent);\n // Remove inline source map comment, source map file comment and trailing EOLs\n const sourceContent = fileContent.replace(sourceMapComment, '').trim();\n\n const eol = detectEOL(fileContent);\n // Assume only one type of EOL is used\n const lines = sourceContent.split(eol);\n\n const mappingRanges: MappingRange[][] = [];\n\n const context: ComputeFileSizesContext = {\n generatedLine: -1,\n generatedColumn: -1,\n line: '',\n source: null,\n consumer,\n mapReferenceEOLSources: new Set(),\n };\n\n consumer.computeColumnSpans();\n consumer.eachMapping(({ source, generatedLine, generatedColumn, lastGeneratedColumn }) => {\n // Columns are 0-based, Lines are 1-based\n\n const lineIndex = generatedLine - 1;\n const line = lines[lineIndex];\n\n if (line === undefined) {\n if (options.noBorderChecks) {\n return;\n }\n\n throw new AppError({\n code: 'InvalidMappingLine',\n generatedLine,\n maxLine: lines.length,\n });\n }\n\n context.generatedLine = generatedLine;\n context.generatedColumn = lastGeneratedColumn || generatedColumn;\n context.line = line;\n context.source = source;\n\n if (!options.noBorderChecks) {\n checkInvalidMappingColumn(context);\n }\n\n const start = generatedColumn;\n const end = lastGeneratedColumn === null ? line.length - 1 : lastGeneratedColumn;\n\n const lineRanges = mappingRanges[lineIndex] || [];\n\n lineRanges.push({\n start,\n end,\n source: source === null ? NO_SOURCE_KEY : source,\n });\n\n mappingRanges[lineIndex] = lineRanges;\n });\n\n let files: FileDataMap = {};\n let mappedBytes = 0;\n\n // To account unicode measure byte length rather than symbols count\n const getSize = options.gzip ? gzipSize.sync : Buffer.byteLength;\n\n mappingRanges.forEach((lineRanges, lineIndex) => {\n const line = lines[lineIndex];\n const mergedRanges = mergeRanges(lineRanges);\n\n mergedRanges.forEach(({ start, end, source }) => {\n const rangeString = line.substring(start, end + 1);\n const rangeByteLength = getSize(rangeString);\n\n if (!files[source]) {\n files[source] = { size: 0 };\n }\n\n files[source].size += rangeByteLength;\n\n mappedBytes += rangeByteLength;\n });\n\n if (coverageRanges) {\n files = setCoveredSizes(line, files, mergedRanges, coverageRanges[lineIndex]);\n }\n });\n\n const sourceMapCommentBytes = getSize(sourceMapComment);\n const eolBytes = getOccurrencesCount(eol, fileContent) * Buffer.byteLength(eol);\n const totalBytes = getSize(fileContent);\n let unmappedBytes: number | undefined;\n\n if (!options.excludeSourceMapComment) {\n files[SOURCE_MAP_COMMENT_KEY] = { size: sourceMapCommentBytes };\n }\n\n if (!options.onlyMapped) {\n unmappedBytes = totalBytes - mappedBytes - sourceMapCommentBytes - eolBytes;\n files[UNMAPPED_KEY] = { size: unmappedBytes };\n }\n\n if (eolBytes > 0) {\n files[EOL_KEY] = { size: eolBytes };\n }\n\n return {\n ...(options.excludeSourceMapComment\n ? { totalBytes: totalBytes - sourceMapCommentBytes }\n : { totalBytes }),\n mappedBytes,\n ...(!options.onlyMapped && { unmappedBytes }),\n eolBytes,\n sourceMapCommentBytes,\n files,\n };\n}\n\nexport function adjustSourcePaths(fileSizeMap: FileDataMap, options: ExploreOptions): FileDataMap {\n if (!options.noRoot) {\n const prefix = getCommonPathPrefix(Object.keys(fileSizeMap));\n const length = prefix.length;\n\n if (length) {\n fileSizeMap = mapKeys(fileSizeMap, (size, source) => source.slice(length));\n }\n }\n\n if (options.replaceMap) {\n fileSizeMap = Object.entries(options.replaceMap).reduce((result, [before, after]) => {\n const regexp = new RegExp(before, 'g');\n\n return mapKeys(result, (size, source) => source.replace(regexp, after));\n }, fileSizeMap);\n }\n\n return fileSizeMap;\n}\n"]}
package/dist/helpers.d.ts CHANGED
@@ -1,25 +1,11 @@
1
1
  /// <reference types="node" />
2
- import { MappingRange } from './index';
2
+ import type { MappingRange } from './types';
3
3
  export declare function getFileContent(file: Buffer | string): string;
4
- /**
5
- * Format number of bytes as string
6
- * Source @see https://stackoverflow.com/a/18650828/388951
7
- */
8
4
  export declare function formatBytes(bytes: number, decimals?: number): string;
9
5
  export declare function formatPercent(value: number, total: number, fractionDigits?: number): string;
10
- /**
11
- * Find common path prefix
12
- * Source @see http://stackoverflow.com/a/1917041/388951
13
- * @param paths List of filenames
14
- */
15
6
  export declare function getCommonPathPrefix(paths: string[]): string;
16
7
  export declare function getFirstRegexMatch(regex: RegExp, string: string): string | null;
17
8
  export declare function detectEOL(content: string): string;
18
- /**
19
- * Get `subString` occurrences count in `string`
20
- */
21
9
  export declare function getOccurrencesCount(subString: string, string: string): number;
22
- /**
23
- * Merge consecutive ranges with the same source
24
- */
10
+ export declare function isEOLAtPosition(string: string, [line, column]: [number, number]): boolean;
25
11
  export declare function mergeRanges(ranges: MappingRange[]): MappingRange[];
package/dist/helpers.js CHANGED
@@ -1,55 +1,30 @@
1
1
  'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
5
- });
6
- exports.getFileContent = getFileContent;
7
- exports.formatBytes = formatBytes;
8
- exports.formatPercent = formatPercent;
9
- exports.getCommonPathPrefix = getCommonPathPrefix;
10
- exports.getFirstRegexMatch = getFirstRegexMatch;
11
- exports.detectEOL = detectEOL;
12
- exports.getOccurrencesCount = getOccurrencesCount;
13
- exports.mergeRanges = mergeRanges;
14
-
15
- var _fs = _interopRequireDefault(require('fs'));
16
-
17
- function _interopRequireDefault(obj) {
18
- return obj && obj.__esModule ? obj : { default: obj };
19
- }
20
-
2
+ var __importDefault =
3
+ (this && this.__importDefault) ||
4
+ function (mod) {
5
+ return mod && mod.__esModule ? mod : { default: mod };
6
+ };
7
+ Object.defineProperty(exports, '__esModule', { value: true });
8
+ const fs_1 = __importDefault(require('fs'));
21
9
  function getFileContent(file) {
22
- const buffer = Buffer.isBuffer(file) ? file : _fs.default.readFileSync(file);
10
+ const buffer = Buffer.isBuffer(file) ? file : fs_1.default.readFileSync(file);
23
11
  return buffer.toString();
24
12
  }
25
-
26
- const BYTE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; // Bytes
27
-
13
+ exports.getFileContent = getFileContent;
14
+ const BYTE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
28
15
  const SIZE_BASE = 1024;
29
- /**
30
- * Format number of bytes as string
31
- * Source @see https://stackoverflow.com/a/18650828/388951
32
- */
33
-
34
16
  function formatBytes(bytes, decimals = 2) {
35
17
  if (bytes === 0) return `0 ${BYTE_SIZES[0]}`;
36
18
  const exponent = Math.floor(Math.log(bytes) / Math.log(SIZE_BASE));
37
- const value = bytes / Math.pow(SIZE_BASE, exponent); // `parseFloat` removes trailing zero
38
-
19
+ const value = bytes / Math.pow(SIZE_BASE, exponent);
39
20
  return `${parseFloat(value.toFixed(decimals))} ${BYTE_SIZES[exponent]}`;
40
21
  }
41
-
22
+ exports.formatBytes = formatBytes;
42
23
  function formatPercent(value, total, fractionDigits) {
43
24
  return ((100.0 * value) / total).toFixed(fractionDigits);
44
25
  }
45
-
26
+ exports.formatPercent = formatPercent;
46
27
  const PATH_SEPARATOR_REGEX = /(\/)/;
47
- /**
48
- * Find common path prefix
49
- * Source @see http://stackoverflow.com/a/1917041/388951
50
- * @param paths List of filenames
51
- */
52
-
53
28
  function getCommonPathPrefix(paths) {
54
29
  if (paths.length < 2) return '';
55
30
  const A = paths.concat().sort();
@@ -57,73 +32,65 @@ function getCommonPathPrefix(paths) {
57
32
  const a2 = A[A.length - 1].split(PATH_SEPARATOR_REGEX);
58
33
  const L = a1.length;
59
34
  let i = 0;
60
-
61
35
  while (i < L && a1[i] === a2[i]) i++;
62
-
63
36
  return a1.slice(0, i).join('');
64
37
  }
65
-
38
+ exports.getCommonPathPrefix = getCommonPathPrefix;
66
39
  function getFirstRegexMatch(regex, string) {
67
40
  const match = string.match(regex);
68
41
  return match ? match[0] : null;
69
42
  }
70
-
43
+ exports.getFirstRegexMatch = getFirstRegexMatch;
71
44
  const LF = '\n';
72
45
  const CR_LF = '\r\n';
73
-
74
46
  function detectEOL(content) {
75
47
  return content.includes(CR_LF) ? CR_LF : LF;
76
48
  }
77
- /**
78
- * Get `subString` occurrences count in `string`
79
- */
80
-
49
+ exports.detectEOL = detectEOL;
81
50
  function getOccurrencesCount(subString, string) {
82
51
  let count = 0;
83
52
  let position = string.indexOf(subString);
84
53
  const subStringLength = subString.length;
85
-
86
54
  while (position !== -1) {
87
55
  count += 1;
88
56
  position = string.indexOf(subString, position + subStringLength);
89
57
  }
90
-
91
58
  return count;
92
59
  }
93
- /**
94
- * Merge consecutive ranges with the same source
95
- */
96
-
60
+ exports.getOccurrencesCount = getOccurrencesCount;
61
+ function isEOLAtPosition(string, [line, column]) {
62
+ const eol = detectEOL(string);
63
+ const eolLength = eol.length;
64
+ let lineOffset = 0;
65
+ for (let lineIndex = 1; lineIndex < line; lineIndex += 1) {
66
+ lineOffset = string.indexOf(eol, lineOffset);
67
+ if (lineOffset === -1) {
68
+ return false;
69
+ }
70
+ lineOffset += eolLength;
71
+ }
72
+ return string.substr(lineOffset + column, eolLength) === eol;
73
+ }
74
+ exports.isEOLAtPosition = isEOLAtPosition;
97
75
  function mergeRanges(ranges) {
98
76
  const mergedRanges = [];
99
77
  const rangesCount = ranges.length;
100
-
101
78
  if (rangesCount === 1) {
102
79
  return ranges;
103
80
  }
104
-
105
81
  let { start, end, source } = ranges[0];
106
-
107
82
  for (let i = 1; i < rangesCount; i += 1) {
108
83
  const isSourceMatch = ranges[i].source === ranges[i - 1].source;
109
84
  const isConsecutive = ranges[i].start - ranges[i - 1].end === 1;
110
-
111
85
  if (isSourceMatch && isConsecutive) {
112
86
  end = ranges[i].end;
113
87
  } else {
114
- mergedRanges.push({
115
- start,
116
- end,
117
- source,
118
- });
88
+ mergedRanges.push({ start, end, source });
119
89
  ({ start, end, source } = ranges[i]);
120
90
  }
121
91
  }
122
-
123
- mergedRanges.push({
124
- start,
125
- end,
126
- source,
127
- });
92
+ mergedRanges.push({ start, end, source });
128
93
  return mergedRanges;
129
94
  }
95
+ exports.mergeRanges = mergeRanges;
96
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport type { MappingRange } from './types';\n\nexport function getFileContent(file: Buffer | string): string {\n const buffer = Buffer.isBuffer(file) ? file : fs.readFileSync(file);\n\n return buffer.toString();\n}\n\nconst BYTE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n// Bytes\nconst SIZE_BASE = 1024;\n\n/**\n * Format number of bytes as string\n * Source @see https://stackoverflow.com/a/18650828/388951\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return `0 ${BYTE_SIZES[0]}`;\n\n const exponent = Math.floor(Math.log(bytes) / Math.log(SIZE_BASE));\n const value = bytes / Math.pow(SIZE_BASE, exponent);\n\n // `parseFloat` removes trailing zero\n return `${parseFloat(value.toFixed(decimals))} ${BYTE_SIZES[exponent]}`;\n}\n\nexport function formatPercent(value: number, total: number, fractionDigits?: number): string {\n return ((100.0 * value) / total).toFixed(fractionDigits);\n}\n\nconst PATH_SEPARATOR_REGEX = /(\\/)/;\n\n/**\n * Find common path prefix\n * Source @see http://stackoverflow.com/a/1917041/388951\n * @param paths List of filenames\n */\nexport function getCommonPathPrefix(paths: string[]): string {\n if (paths.length < 2) return '';\n\n const A = paths.concat().sort();\n const a1 = A[0].split(PATH_SEPARATOR_REGEX);\n const a2 = A[A.length - 1].split(PATH_SEPARATOR_REGEX);\n const L = a1.length;\n\n let i = 0;\n\n while (i < L && a1[i] === a2[i]) i++;\n\n return a1.slice(0, i).join('');\n}\n\nexport function getFirstRegexMatch(regex: RegExp, string: string): string | null {\n const match = string.match(regex);\n\n return match ? match[0] : null;\n}\n\nconst LF = '\\n';\nconst CR_LF = '\\r\\n';\n\nexport function detectEOL(content: string): string {\n return content.includes(CR_LF) ? CR_LF : LF;\n}\n\n/**\n * Get `subString` occurrences count in `string`\n */\nexport function getOccurrencesCount(subString: string, string: string): number {\n let count = 0;\n let position = string.indexOf(subString);\n const subStringLength = subString.length;\n\n while (position !== -1) {\n count += 1;\n position = string.indexOf(subString, position + subStringLength);\n }\n\n return count;\n}\n\nexport function isEOLAtPosition(string: string, [line, column]: [number, number]): boolean {\n const eol = detectEOL(string);\n const eolLength = eol.length;\n\n let lineOffset = 0;\n\n for (let lineIndex = 1; lineIndex < line; lineIndex += 1) {\n lineOffset = string.indexOf(eol, lineOffset);\n\n if (lineOffset === -1) {\n return false;\n }\n\n lineOffset += eolLength;\n }\n\n return string.substr(lineOffset + column, eolLength) === eol;\n}\n\n/**\n * Merge consecutive ranges with the same source\n */\nexport function mergeRanges(ranges: MappingRange[]): MappingRange[] {\n const mergedRanges: MappingRange[] = [];\n const rangesCount = ranges.length;\n\n if (rangesCount === 1) {\n return ranges;\n }\n\n let { start, end, source } = ranges[0];\n\n for (let i = 1; i < rangesCount; i += 1) {\n const isSourceMatch = ranges[i].source === ranges[i - 1].source;\n const isConsecutive = ranges[i].start - ranges[i - 1].end === 1;\n\n if (isSourceMatch && isConsecutive) {\n end = ranges[i].end;\n } else {\n mergedRanges.push({ start, end, source });\n\n ({ start, end, source } = ranges[i]);\n }\n }\n\n mergedRanges.push({ start, end, source });\n\n return mergedRanges;\n}\n"]}
package/dist/html.d.ts CHANGED
@@ -1,7 +1,4 @@
1
- import { ExploreOptions, ExploreBundleResult, FileDataMap } from './index';
2
- /**
3
- * Generate HTML file content for specified files
4
- */
1
+ import type { ExploreOptions, ExploreBundleResult, FileDataMap } from './types';
5
2
  export declare function generateHtml(exploreResults: ExploreBundleResult[], options: ExploreOptions): string;
6
3
  interface WebTreeMapNode {
7
4
  name: string;
@@ -12,8 +9,5 @@ interface WebTreeMapNode {
12
9
  };
13
10
  children?: WebTreeMapNode[];
14
11
  }
15
- /**
16
- * Convert file size map to webtreemap data
17
- */
18
12
  export declare function getWebTreeMapData(files: FileDataMap): WebTreeMapNode;
19
13
  export {};