source-map-explorer 2.3.1 → 2.5.0

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 DELETED
@@ -1,258 +0,0 @@
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
-
47
- async function exploreBundle(bundle, options) {
48
- const { code, map, coverageRanges } = bundle;
49
- const sourceMapData = await loadSourceMap(code, map);
50
- const sizes = computeFileSizes(sourceMapData, options, coverageRanges);
51
- const files = adjustSourcePaths(sizes.files, options); // Free Wasm data
52
-
53
- sourceMapData.consumer.destroy();
54
- return {
55
- bundleName: (0, _api.getBundleName)(bundle),
56
- ...sizes,
57
- files,
58
- };
59
- }
60
-
61
- /**
62
- * Get source map
63
- */
64
- async function loadSourceMap(codeFile, sourceMapFile) {
65
- const codeFileContent = (0, _helpers.getFileContent)(codeFile);
66
- let consumer;
67
-
68
- if (sourceMapFile) {
69
- const sourceMapFileContent = (0, _helpers.getFileContent)(sourceMapFile);
70
- consumer = await new _sourceMap.SourceMapConsumer(sourceMapFileContent);
71
- } else {
72
- // Try to read a source map from a 'sourceMappingURL' comment.
73
- let converter = _convertSourceMap.default.fromSource(codeFileContent);
74
-
75
- if (!converter && !Buffer.isBuffer(codeFile)) {
76
- converter = _convertSourceMap.default.fromMapFileSource(
77
- codeFileContent,
78
- _path.default.dirname(codeFile)
79
- );
80
- }
81
-
82
- if (!converter) {
83
- throw new _appError.AppError({
84
- code: 'NoSourceMap',
85
- });
86
- }
87
-
88
- consumer = await new _sourceMap.SourceMapConsumer(converter.toJSON());
89
- }
90
-
91
- if (!consumer) {
92
- throw new _appError.AppError({
93
- code: 'NoSourceMap',
94
- });
95
- }
96
-
97
- return {
98
- consumer,
99
- codeFileContent,
100
- };
101
- }
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
-
109
- function getSourceMapComment(fileContent) {
110
- const sourceMapComment =
111
- (0, _helpers.getFirstRegexMatch)(COMMENT_REGEX, fileContent) ||
112
- (0, _helpers.getFirstRegexMatch)(MAP_FILE_COMMENT_REGEX, fileContent) ||
113
- ''; // Remove trailing EOLs
114
-
115
- return sourceMapComment.trim();
116
- }
117
-
118
- function checkInvalidMappingColumn({ generatedLine, generatedColumn, line }) {
119
- const maxColumnIndex = line.length - 1;
120
-
121
- if (generatedColumn > maxColumnIndex) {
122
- throw new _appError.AppError({
123
- code: 'InvalidMappingColumn',
124
- generatedLine,
125
- generatedColumn,
126
- maxColumn: line.length,
127
- });
128
- }
129
- }
130
- /**
131
- * Calculate the number of bytes contributed by each source file
132
- */
133
-
134
- function computeFileSizes(sourceMapData, options, coverageRanges) {
135
- 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);
142
- const mappingRanges = [];
143
- consumer.computeColumnSpans();
144
- consumer.eachMapping(({ source, generatedLine, generatedColumn, lastGeneratedColumn }) => {
145
- // Columns are 0-based, Lines are 1-based
146
- const lineIndex = generatedLine - 1;
147
- const line = lines[lineIndex];
148
-
149
- if (line === undefined) {
150
- throw new _appError.AppError({
151
- code: 'InvalidMappingLine',
152
- generatedLine,
153
- maxLine: lines.length,
154
- });
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
-
163
- const start = generatedColumn;
164
- const end = lastGeneratedColumn === null ? line.length - 1 : lastGeneratedColumn;
165
- const lineRanges = mappingRanges[lineIndex] || [];
166
- lineRanges.push({
167
- start,
168
- end,
169
- source: source === null ? NO_SOURCE_KEY : source,
170
- });
171
- mappingRanges[lineIndex] = lineRanges;
172
- });
173
- let files = {};
174
- let mappedBytes = 0;
175
- const getSize = options.gzip ? _gzipSize.default.sync : Buffer.byteLength;
176
- mappingRanges.forEach((lineRanges, lineIndex) => {
177
- const line = lines[lineIndex];
178
- const mergedRanges = (0, _helpers.mergeRanges)(lineRanges);
179
- mergedRanges.forEach(({ start, end, source }) => {
180
- const rangeString = line.substring(start, end + 1); // To account unicode measure byte length rather than symbols count
181
-
182
- const rangeByteLength = getSize(rangeString);
183
-
184
- if (!files[source]) {
185
- files[source] = {
186
- size: 0,
187
- };
188
- }
189
-
190
- files[source].size += rangeByteLength;
191
- mappedBytes += rangeByteLength;
192
- });
193
-
194
- if (coverageRanges) {
195
- files = (0, _coverage.setCoveredSizes)(line, files, mergedRanges, coverageRanges[lineIndex]);
196
- }
197
- });
198
- const sourceMapCommentBytes = getSize(sourceMapComment);
199
- const eolBytes = (0, _helpers.getOccurrencesCount)(eol, fileContent) * Buffer.byteLength(eol);
200
- const totalBytes = getSize(fileContent);
201
- let unmappedBytes;
202
-
203
- if (!options.excludeSourceMapComment) {
204
- files[SOURCE_MAP_COMMENT_KEY] = {
205
- size: sourceMapCommentBytes,
206
- };
207
- }
208
-
209
- if (!options.onlyMapped) {
210
- unmappedBytes = totalBytes - mappedBytes - sourceMapCommentBytes - eolBytes;
211
- files[UNMAPPED_KEY] = {
212
- size: unmappedBytes,
213
- };
214
- }
215
-
216
- if (eolBytes > 0) {
217
- files[EOL_KEY] = {
218
- size: eolBytes,
219
- };
220
- }
221
-
222
- return {
223
- ...(options.excludeSourceMapComment
224
- ? {
225
- totalBytes: totalBytes - sourceMapCommentBytes,
226
- }
227
- : {
228
- totalBytes,
229
- }),
230
- mappedBytes,
231
- ...(!options.onlyMapped && {
232
- unmappedBytes,
233
- }),
234
- eolBytes,
235
- sourceMapCommentBytes,
236
- files,
237
- };
238
- }
239
-
240
- function adjustSourcePaths(fileSizeMap, options) {
241
- if (!options.noRoot) {
242
- const prefix = (0, _helpers.getCommonPathPrefix)(Object.keys(fileSizeMap));
243
- const length = prefix.length;
244
-
245
- if (length) {
246
- fileSizeMap = (0, _lodash.mapKeys)(fileSizeMap, (size, source) => source.slice(length));
247
- }
248
- }
249
-
250
- if (options.replaceMap) {
251
- fileSizeMap = Object.entries(options.replaceMap).reduce((result, [before, after]) => {
252
- const regexp = new RegExp(before, 'g');
253
- return (0, _lodash.mapKeys)(result, (size, source) => source.replace(regexp, after));
254
- }, fileSizeMap);
255
- }
256
-
257
- return fileSizeMap;
258
- }
package/dist/html.js DELETED
@@ -1,213 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
5
- });
6
- exports.generateHtml = generateHtml;
7
- exports.getWebTreeMapData = getWebTreeMapData;
8
-
9
- var _btoa = _interopRequireDefault(require('btoa'));
10
-
11
- var _ejs = _interopRequireDefault(require('ejs'));
12
-
13
- var _fs = _interopRequireDefault(require('fs'));
14
-
15
- var _path = _interopRequireDefault(require('path'));
16
-
17
- var _escapeHtml = _interopRequireDefault(require('escape-html'));
18
-
19
- var _helpers = require('./helpers');
20
-
21
- var _coverage = require('./coverage');
22
-
23
- function _interopRequireDefault(obj) {
24
- return obj && obj.__esModule ? obj : { default: obj };
25
- }
26
-
27
- /**
28
- * Generate HTML file content for specified files
29
- */
30
- function generateHtml(exploreResults, options) {
31
- const assets = {
32
- webtreemapJs: (0, _btoa.default)(
33
- _fs.default.readFileSync(require.resolve('./vendor/webtreemap.js'))
34
- ),
35
- webtreemapCss: (0, _btoa.default)(
36
- _fs.default.readFileSync(require.resolve('./vendor/webtreemap.css'))
37
- ),
38
- }; // Create a combined bundle if applicable
39
-
40
- if (exploreResults.length > 1) {
41
- exploreResults = [makeMergedBundle(exploreResults)].concat(exploreResults);
42
- } // Get bundles info to generate select element
43
-
44
- const bundles = exploreResults.map(data => ({
45
- name: data.bundleName,
46
- size: (0, _helpers.formatBytes)(data.totalBytes),
47
- })); // Get webtreemap data to update map on bundle select
48
-
49
- const treeDataMap = exploreResults.reduce((result, data, index) => {
50
- result[index] = {
51
- name: data.bundleName,
52
- data: getWebTreeMapData(data.files),
53
- };
54
- return result;
55
- }, {});
56
- const template = (0, _helpers.getFileContent)(_path.default.join(__dirname, 'tree-viz.ejs'));
57
- return _ejs.default.render(template, {
58
- options,
59
- bundles,
60
- treeDataMap,
61
- webtreemapJs: assets.webtreemapJs,
62
- webtreemapCss: assets.webtreemapCss,
63
- });
64
- }
65
- /**
66
- * Create a combined result where each of the inputs is a separate node under the root
67
- */
68
-
69
- function makeMergedBundle(exploreResults) {
70
- let totalBytes = 0;
71
- const files = {}; // Remove any common prefix to keep the visualization as simple as possible.
72
-
73
- const commonPrefix = (0, _helpers.getCommonPathPrefix)(exploreResults.map(r => r.bundleName));
74
-
75
- for (const result of exploreResults) {
76
- totalBytes += result.totalBytes;
77
- const prefix = result.bundleName.slice(commonPrefix.length);
78
- Object.entries(result.files).forEach(([fileName, size]) => {
79
- files[`${prefix}/${fileName}`] = size;
80
- });
81
- }
82
-
83
- return {
84
- bundleName: '[combined]',
85
- totalBytes,
86
- mappedBytes: 0,
87
- eolBytes: 0,
88
- sourceMapCommentBytes: 0,
89
- files,
90
- };
91
- }
92
-
93
- function getNodePath(parts, depthIndex) {
94
- return parts.slice(0, depthIndex + 1).join('/');
95
- }
96
-
97
- function getTreeNodesMap(fileDataMap) {
98
- let partsSourceTuples = Object.keys(fileDataMap).map(file => [file.split('/'), file]);
99
- const maxDepth = Math.max(...partsSourceTuples.map(([parts]) => parts.length));
100
-
101
- for (let depthIndex = 0; depthIndex < maxDepth; depthIndex += 1) {
102
- partsSourceTuples = partsSourceTuples.map(([parts, file], currentNodeIndex) => {
103
- if (parts[depthIndex]) {
104
- const nodePath = getNodePath(parts, depthIndex);
105
- const hasSameRootPaths = partsSourceTuples.some(([pathParts], index) => {
106
- if (index === currentNodeIndex) {
107
- return false;
108
- }
109
-
110
- if (!pathParts[depthIndex]) {
111
- return false;
112
- }
113
-
114
- return getNodePath(pathParts, depthIndex) === nodePath;
115
- });
116
-
117
- if (!hasSameRootPaths) {
118
- // Collapse non-contributing path parts
119
- return [[...parts.slice(0, depthIndex), parts.slice(depthIndex).join('/')], file];
120
- }
121
- }
122
-
123
- return [parts, file];
124
- });
125
- }
126
-
127
- return partsSourceTuples.reduce((result, [parts, file]) => {
128
- result[file] = parts;
129
- return result;
130
- }, {});
131
- }
132
-
133
- /**
134
- * Convert file size map to webtreemap data
135
- */
136
- function getWebTreeMapData(files) {
137
- const treeNodesMap = getTreeNodesMap(files);
138
- const treeData = newNode('/');
139
-
140
- for (const source in files) {
141
- addNode(treeNodesMap[source], files[source], treeData);
142
- }
143
-
144
- addSizeToTitle(treeData, treeData.data['$area']);
145
- return treeData;
146
- }
147
-
148
- function newNode(name) {
149
- return {
150
- name: (0, _escapeHtml.default)(name),
151
- data: {
152
- $area: 0,
153
- },
154
- };
155
- }
156
-
157
- function setNodeData(node, fileData) {
158
- const size = node.data['$area'] + fileData.size;
159
-
160
- if (fileData.coveredSize !== undefined) {
161
- const coveredSize = (node.data.coveredSize || 0) + fileData.coveredSize;
162
- node.data.coveredSize = coveredSize;
163
- node.data.backgroundColor = (0, _coverage.getColorByPercent)(coveredSize / size);
164
- }
165
-
166
- node.data['$area'] = size;
167
- }
168
-
169
- function addNode(parts, fileData, treeData) {
170
- // No need to create nodes with zero size (e.g. '[unmapped]')
171
- if (fileData.size === 0) {
172
- return;
173
- }
174
-
175
- let node = treeData;
176
- setNodeData(node, fileData);
177
- parts.forEach(part => {
178
- if (!node.children) {
179
- node.children = [];
180
- }
181
-
182
- let child = node.children.find(child => child.name === part);
183
-
184
- if (!child) {
185
- child = newNode(part);
186
- node.children.push(child);
187
- }
188
-
189
- node = child;
190
- setNodeData(child, fileData);
191
- });
192
- }
193
-
194
- function addSizeToTitle(node, total) {
195
- const { $area: size, coveredSize } = node.data;
196
- const titleParts = [
197
- node.name,
198
- (0, _helpers.formatBytes)(size),
199
- `${(0, _helpers.formatPercent)(size, total, 1)}%`,
200
- ]; // Add coverage label to leaf nodes only
201
-
202
- if (coveredSize !== undefined && node.children === undefined) {
203
- titleParts.push(`Coverage: ${(0, _helpers.formatPercent)(coveredSize, size, 1)}%`);
204
- }
205
-
206
- node.name = titleParts.join(' • ');
207
-
208
- if (node.children) {
209
- node.children.forEach(child => {
210
- addSizeToTitle(child, total);
211
- });
212
- }
213
- }
package/dist/index.d.ts DELETED
@@ -1,92 +0,0 @@
1
- /// <reference types="node" />
2
- import { explore } from './api';
3
- import { UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY } from './explore';
4
- export { explore, UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY };
5
- export default explore;
6
- export interface FileData {
7
- size: number;
8
- coveredSize?: number;
9
- }
10
- export declare type FileDataMap = Record<string, FileData>;
11
- export interface FileSizes {
12
- files: FileDataMap;
13
- mappedBytes: number;
14
- unmappedBytes?: number;
15
- eolBytes: number;
16
- sourceMapCommentBytes: number;
17
- totalBytes: number;
18
- }
19
- export declare type ErrorCode = 'Unknown' | 'NoBundles' | 'NoSourceMap' | 'OneSourceSourceMap' | 'UnmappedBytes' | 'InvalidMappingLine' | 'InvalidMappingColumn' | 'CannotSaveFile' | 'CannotCreateTempFile' | 'CannotOpenTempFile' | 'CannotOpenCoverageFile' | 'NoCoverageMatches';
20
- export declare type File = string | Buffer;
21
- export declare type ReplaceMap = Record<string, string>;
22
- export declare type OutputFormat = 'json' | 'tsv' | 'html';
23
- /** Represents single bundle */
24
- export interface Bundle {
25
- code: File;
26
- map?: File;
27
- coverageRanges?: ColumnsRange[][];
28
- }
29
- export interface ExploreOptions {
30
- /** Exclude "unmapped" bytes from the output */
31
- onlyMapped?: boolean;
32
- /** Exclude source map comment size from output */
33
- excludeSourceMapComment?: boolean;
34
- /** Output result as a string */
35
- output?: {
36
- format: OutputFormat;
37
- /** Filename to save output to */
38
- filename?: string;
39
- };
40
- /** Disable removing prefix shared by all sources */
41
- noRoot?: boolean;
42
- /** Replace "this" by "that" map */
43
- replaceMap?: ReplaceMap;
44
- coverage?: string;
45
- /** Calculate gzip size. Setting it to `true` will also set `onlyMapped` to `true` */
46
- gzip?: boolean;
47
- }
48
- export interface ExploreResult {
49
- bundles: ExploreBundleResult[];
50
- /** Result as a string - either JSON, TSV or HTML */
51
- output?: string;
52
- errors: ExploreErrorResult[];
53
- }
54
- export interface ExploreBundleResult extends FileSizes {
55
- bundleName: string;
56
- }
57
- export interface ExploreErrorResult {
58
- bundleName: string;
59
- code: string;
60
- message: string;
61
- error?: NodeJS.ErrnoException;
62
- isWarning?: boolean;
63
- }
64
- export declare type BundlesAndFileTokens = (Bundle | string)[] | Bundle | string;
65
- /** Represents inclusive range (e.g. [0,5] six columns) */
66
- export interface ColumnsRange {
67
- /** Fist column index */
68
- start: number;
69
- /** Last column index */
70
- end: number;
71
- }
72
- export interface MappingRange extends ColumnsRange {
73
- source: string;
74
- }
75
- /** Represents exclusive range (e.g. [0,5) - four columns) */
76
- export interface Coverage {
77
- url: string;
78
- ranges: CoverageRange[];
79
- /** File content as one line */
80
- text: string;
81
- }
82
- export interface CoverageRange {
83
- /** First column index */
84
- start: number;
85
- /** Column index next after last column index */
86
- end: number;
87
- }
88
- declare module 'source-map' {
89
- interface MappingItem {
90
- lastGeneratedColumn: number | null;
91
- }
92
- }
package/dist/index.js DELETED
@@ -1,38 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
5
- });
6
- Object.defineProperty(exports, 'explore', {
7
- enumerable: true,
8
- get: function() {
9
- return _api.explore;
10
- },
11
- });
12
- Object.defineProperty(exports, 'UNMAPPED_KEY', {
13
- enumerable: true,
14
- get: function() {
15
- return _explore.UNMAPPED_KEY;
16
- },
17
- });
18
- Object.defineProperty(exports, 'SOURCE_MAP_COMMENT_KEY', {
19
- enumerable: true,
20
- get: function() {
21
- return _explore.SOURCE_MAP_COMMENT_KEY;
22
- },
23
- });
24
- Object.defineProperty(exports, 'NO_SOURCE_KEY', {
25
- enumerable: true,
26
- get: function() {
27
- return _explore.NO_SOURCE_KEY;
28
- },
29
- });
30
- exports.default = void 0;
31
-
32
- var _api = require('./api');
33
-
34
- var _explore = require('./explore');
35
-
36
- var _default = _api.explore; // Export all interfaces from index.ts to avoid type exports in compiled js code. See https://github.com/babel/babel/issues/8361
37
-
38
- exports.default = _default;