source-map-explorer 2.3.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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;