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/README.md +19 -7
- package/{dist → bin}/cli.d.ts +1 -1
- package/{dist → bin}/cli.js +59 -93
- package/bin/cli.js.map +1 -0
- package/{dist → lib}/api.d.ts +1 -7
- package/lib/api.js +134 -0
- package/lib/api.js.map +1 -0
- package/{dist → lib}/app-error.d.ts +1 -1
- package/{dist → lib}/app-error.js +14 -34
- package/lib/app-error.js.map +1 -0
- package/{dist → lib}/coverage.d.ts +1 -10
- package/{dist → lib}/coverage.js +28 -125
- package/lib/coverage.js.map +1 -0
- package/{dist → lib}/explore.d.ts +1 -4
- package/lib/explore.js +227 -0
- package/lib/explore.js.map +1 -0
- package/{dist → lib}/helpers.d.ts +2 -16
- package/{dist → lib}/helpers.js +36 -68
- package/lib/helpers.js.map +1 -0
- package/{dist → lib}/html.d.ts +6 -7
- package/lib/html.js +191 -0
- package/lib/html.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +31 -0
- package/lib/index.js.map +1 -0
- package/{dist → lib}/output.d.ts +1 -1
- package/{dist → lib}/output.js +22 -53
- package/lib/output.js.map +1 -0
- package/{dist → lib}/tree-viz.ejs +0 -0
- package/lib/types.d.ts +121 -0
- package/{dist → lib}/vendor/webtreemap.css +0 -0
- package/{dist → lib}/vendor/webtreemap.js +0 -0
- package/package.json +72 -72
- package/dist/api.js +0 -168
- package/dist/explore.js +0 -258
- package/dist/html.js +0 -213
- package/dist/index.d.ts +0 -92
- package/dist/index.js +0 -38
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explore.js","sourceRoot":"","sources":["../src/lib/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"]}
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { MappingRange } from './
|
|
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 → lib}/helpers.js
RENAMED
|
@@ -1,55 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
exports
|
|
8
|
-
exports.formatPercent =
|
|
9
|
-
|
|
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
|
+
exports.mergeRanges = exports.isEOLAtPosition = exports.getOccurrencesCount = exports.detectEOL = exports.getFirstRegexMatch = exports.getCommonPathPrefix = exports.formatPercent = exports.formatBytes = exports.getFileContent = void 0;
|
|
9
|
+
const fs_1 = __importDefault(require('fs'));
|
|
21
10
|
function getFileContent(file) {
|
|
22
|
-
const buffer = Buffer.isBuffer(file) ? file :
|
|
11
|
+
const buffer = Buffer.isBuffer(file) ? file : fs_1.default.readFileSync(file);
|
|
23
12
|
return buffer.toString();
|
|
24
13
|
}
|
|
25
|
-
|
|
26
|
-
const BYTE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
27
|
-
|
|
14
|
+
exports.getFileContent = getFileContent;
|
|
15
|
+
const BYTE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
28
16
|
const SIZE_BASE = 1024;
|
|
29
|
-
/**
|
|
30
|
-
* Format number of bytes as string
|
|
31
|
-
* Source @see https://stackoverflow.com/a/18650828/388951
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
17
|
function formatBytes(bytes, decimals = 2) {
|
|
35
18
|
if (bytes === 0) return `0 ${BYTE_SIZES[0]}`;
|
|
36
19
|
const exponent = Math.floor(Math.log(bytes) / Math.log(SIZE_BASE));
|
|
37
|
-
const value = bytes / Math.pow(SIZE_BASE, exponent);
|
|
38
|
-
|
|
20
|
+
const value = bytes / Math.pow(SIZE_BASE, exponent);
|
|
39
21
|
return `${parseFloat(value.toFixed(decimals))} ${BYTE_SIZES[exponent]}`;
|
|
40
22
|
}
|
|
41
|
-
|
|
23
|
+
exports.formatBytes = formatBytes;
|
|
42
24
|
function formatPercent(value, total, fractionDigits) {
|
|
43
25
|
return ((100.0 * value) / total).toFixed(fractionDigits);
|
|
44
26
|
}
|
|
45
|
-
|
|
27
|
+
exports.formatPercent = formatPercent;
|
|
46
28
|
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
29
|
function getCommonPathPrefix(paths) {
|
|
54
30
|
if (paths.length < 2) return '';
|
|
55
31
|
const A = paths.concat().sort();
|
|
@@ -57,73 +33,65 @@ function getCommonPathPrefix(paths) {
|
|
|
57
33
|
const a2 = A[A.length - 1].split(PATH_SEPARATOR_REGEX);
|
|
58
34
|
const L = a1.length;
|
|
59
35
|
let i = 0;
|
|
60
|
-
|
|
61
36
|
while (i < L && a1[i] === a2[i]) i++;
|
|
62
|
-
|
|
63
37
|
return a1.slice(0, i).join('');
|
|
64
38
|
}
|
|
65
|
-
|
|
39
|
+
exports.getCommonPathPrefix = getCommonPathPrefix;
|
|
66
40
|
function getFirstRegexMatch(regex, string) {
|
|
67
41
|
const match = string.match(regex);
|
|
68
42
|
return match ? match[0] : null;
|
|
69
43
|
}
|
|
70
|
-
|
|
44
|
+
exports.getFirstRegexMatch = getFirstRegexMatch;
|
|
71
45
|
const LF = '\n';
|
|
72
46
|
const CR_LF = '\r\n';
|
|
73
|
-
|
|
74
47
|
function detectEOL(content) {
|
|
75
48
|
return content.includes(CR_LF) ? CR_LF : LF;
|
|
76
49
|
}
|
|
77
|
-
|
|
78
|
-
* Get `subString` occurrences count in `string`
|
|
79
|
-
*/
|
|
80
|
-
|
|
50
|
+
exports.detectEOL = detectEOL;
|
|
81
51
|
function getOccurrencesCount(subString, string) {
|
|
82
52
|
let count = 0;
|
|
83
53
|
let position = string.indexOf(subString);
|
|
84
54
|
const subStringLength = subString.length;
|
|
85
|
-
|
|
86
55
|
while (position !== -1) {
|
|
87
56
|
count += 1;
|
|
88
57
|
position = string.indexOf(subString, position + subStringLength);
|
|
89
58
|
}
|
|
90
|
-
|
|
91
59
|
return count;
|
|
92
60
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
61
|
+
exports.getOccurrencesCount = getOccurrencesCount;
|
|
62
|
+
function isEOLAtPosition(string, [line, column]) {
|
|
63
|
+
const eol = detectEOL(string);
|
|
64
|
+
const eolLength = eol.length;
|
|
65
|
+
let lineOffset = 0;
|
|
66
|
+
for (let lineIndex = 1; lineIndex < line; lineIndex += 1) {
|
|
67
|
+
lineOffset = string.indexOf(eol, lineOffset);
|
|
68
|
+
if (lineOffset === -1) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
lineOffset += eolLength;
|
|
72
|
+
}
|
|
73
|
+
return string.substr(lineOffset + column, eolLength) === eol;
|
|
74
|
+
}
|
|
75
|
+
exports.isEOLAtPosition = isEOLAtPosition;
|
|
97
76
|
function mergeRanges(ranges) {
|
|
98
77
|
const mergedRanges = [];
|
|
99
78
|
const rangesCount = ranges.length;
|
|
100
|
-
|
|
101
79
|
if (rangesCount === 1) {
|
|
102
80
|
return ranges;
|
|
103
81
|
}
|
|
104
|
-
|
|
105
82
|
let { start, end, source } = ranges[0];
|
|
106
|
-
|
|
107
83
|
for (let i = 1; i < rangesCount; i += 1) {
|
|
108
84
|
const isSourceMatch = ranges[i].source === ranges[i - 1].source;
|
|
109
85
|
const isConsecutive = ranges[i].start - ranges[i - 1].end === 1;
|
|
110
|
-
|
|
111
86
|
if (isSourceMatch && isConsecutive) {
|
|
112
87
|
end = ranges[i].end;
|
|
113
88
|
} else {
|
|
114
|
-
mergedRanges.push({
|
|
115
|
-
start,
|
|
116
|
-
end,
|
|
117
|
-
source,
|
|
118
|
-
});
|
|
89
|
+
mergedRanges.push({ start, end, source });
|
|
119
90
|
({ start, end, source } = ranges[i]);
|
|
120
91
|
}
|
|
121
92
|
}
|
|
122
|
-
|
|
123
|
-
mergedRanges.push({
|
|
124
|
-
start,
|
|
125
|
-
end,
|
|
126
|
-
source,
|
|
127
|
-
});
|
|
93
|
+
mergedRanges.push({ start, end, source });
|
|
128
94
|
return mergedRanges;
|
|
129
95
|
}
|
|
96
|
+
exports.mergeRanges = mergeRanges;
|
|
97
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/lib/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 → lib}/html.d.ts
RENAMED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { ExploreOptions, ExploreBundleResult, FileDataMap } from './
|
|
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;
|
|
3
|
+
export declare function makeMergedTreeDataMap(treeData: WebTreeData[]): WebTreeData;
|
|
6
4
|
interface WebTreeMapNode {
|
|
7
5
|
name: string;
|
|
8
6
|
data: {
|
|
@@ -12,8 +10,9 @@ interface WebTreeMapNode {
|
|
|
12
10
|
};
|
|
13
11
|
children?: WebTreeMapNode[];
|
|
14
12
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
export interface WebTreeData {
|
|
14
|
+
name: string;
|
|
15
|
+
data: WebTreeMapNode;
|
|
16
|
+
}
|
|
18
17
|
export declare function getWebTreeMapData(files: FileDataMap): WebTreeMapNode;
|
|
19
18
|
export {};
|
package/lib/html.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
'use strict';
|
|
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
|
+
exports.getWebTreeMapData = exports.makeMergedTreeDataMap = exports.generateHtml = void 0;
|
|
9
|
+
const btoa_1 = __importDefault(require('btoa'));
|
|
10
|
+
const ejs_1 = __importDefault(require('ejs'));
|
|
11
|
+
const fs_1 = __importDefault(require('fs'));
|
|
12
|
+
const path_1 = __importDefault(require('path'));
|
|
13
|
+
const escape_html_1 = __importDefault(require('escape-html'));
|
|
14
|
+
const lodash_1 = require('lodash');
|
|
15
|
+
const helpers_1 = require('./helpers');
|
|
16
|
+
const coverage_1 = require('./coverage');
|
|
17
|
+
const COMBINED_BUNDLE_NAME = '[combined]';
|
|
18
|
+
function getTreeDataMap(exploreResults) {
|
|
19
|
+
let treeData = exploreResults.map((data) => ({
|
|
20
|
+
name: data.bundleName,
|
|
21
|
+
data: getWebTreeMapData(data.files),
|
|
22
|
+
}));
|
|
23
|
+
if (treeData.length > 1) {
|
|
24
|
+
treeData = [makeMergedTreeDataMap(lodash_1.cloneDeep(treeData)), ...treeData];
|
|
25
|
+
}
|
|
26
|
+
for (const webTreeData of treeData) {
|
|
27
|
+
addSizeToTitle(webTreeData.data, webTreeData.data.data['$area']);
|
|
28
|
+
}
|
|
29
|
+
return { ...treeData };
|
|
30
|
+
}
|
|
31
|
+
function generateHtml(exploreResults, options) {
|
|
32
|
+
const assets = {
|
|
33
|
+
webtreemapJs: btoa_1.default(
|
|
34
|
+
fs_1.default.readFileSync(require.resolve('./vendor/webtreemap.js'))
|
|
35
|
+
),
|
|
36
|
+
webtreemapCss: btoa_1.default(
|
|
37
|
+
fs_1.default.readFileSync(require.resolve('./vendor/webtreemap.css'))
|
|
38
|
+
),
|
|
39
|
+
};
|
|
40
|
+
const treeDataMap = getTreeDataMap(exploreResults);
|
|
41
|
+
const bundles = exploreResults.map((data) => ({
|
|
42
|
+
name: data.bundleName,
|
|
43
|
+
size: helpers_1.formatBytes(data.totalBytes),
|
|
44
|
+
}));
|
|
45
|
+
if (exploreResults.length > 1) {
|
|
46
|
+
bundles.unshift({
|
|
47
|
+
name: COMBINED_BUNDLE_NAME,
|
|
48
|
+
size: helpers_1.formatBytes(
|
|
49
|
+
exploreResults.reduce((total, result) => total + result.totalBytes, 0)
|
|
50
|
+
),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const template = helpers_1.getFileContent(path_1.default.join(__dirname, 'tree-viz.ejs'));
|
|
54
|
+
return ejs_1.default.render(template, {
|
|
55
|
+
options,
|
|
56
|
+
bundles,
|
|
57
|
+
treeDataMap,
|
|
58
|
+
webtreemapJs: assets.webtreemapJs,
|
|
59
|
+
webtreemapCss: assets.webtreemapCss,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
exports.generateHtml = generateHtml;
|
|
63
|
+
function makeMergedTreeDataMap(treeData) {
|
|
64
|
+
const data = newNode('/');
|
|
65
|
+
data.children = [];
|
|
66
|
+
for (const result of treeData) {
|
|
67
|
+
const childTree = result.data;
|
|
68
|
+
childTree.name = result.name;
|
|
69
|
+
data.data['$area'] += childTree.data['$area'];
|
|
70
|
+
data.children.push(childTree);
|
|
71
|
+
}
|
|
72
|
+
const commonPrefix = helpers_1.getCommonPathPrefix(data.children.map((node) => node.name));
|
|
73
|
+
const commonPrefixLength = commonPrefix.length;
|
|
74
|
+
if (commonPrefixLength > 0) {
|
|
75
|
+
for (const node of data.children) {
|
|
76
|
+
node.name = node.name.slice(commonPrefixLength);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
name: COMBINED_BUNDLE_NAME,
|
|
81
|
+
data,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
exports.makeMergedTreeDataMap = makeMergedTreeDataMap;
|
|
85
|
+
function getNodePath(parts, depthIndex) {
|
|
86
|
+
return parts.slice(0, depthIndex + 1).join('/');
|
|
87
|
+
}
|
|
88
|
+
const WEBPACK_FILENAME_PREFIX = 'webpack:///';
|
|
89
|
+
const WEBPACK_FILENAME_PREFIX_LENGTH = WEBPACK_FILENAME_PREFIX.length;
|
|
90
|
+
function splitFilename(file) {
|
|
91
|
+
const webpackPrefixIndex = file.indexOf(WEBPACK_FILENAME_PREFIX);
|
|
92
|
+
if (webpackPrefixIndex !== -1) {
|
|
93
|
+
return [
|
|
94
|
+
...file.substring(0, webpackPrefixIndex).split('/'),
|
|
95
|
+
WEBPACK_FILENAME_PREFIX,
|
|
96
|
+
...file.substring(webpackPrefixIndex + WEBPACK_FILENAME_PREFIX_LENGTH).split('/'),
|
|
97
|
+
].filter(Boolean);
|
|
98
|
+
}
|
|
99
|
+
return file.split('/');
|
|
100
|
+
}
|
|
101
|
+
function getTreeNodesMap(fileDataMap) {
|
|
102
|
+
let partsSourceTuples = Object.keys(fileDataMap).map((file) => [splitFilename(file), file]);
|
|
103
|
+
const maxDepth = Math.max(...partsSourceTuples.map(([parts]) => parts.length));
|
|
104
|
+
for (let depthIndex = 0; depthIndex < maxDepth; depthIndex += 1) {
|
|
105
|
+
partsSourceTuples = partsSourceTuples.map(([parts, file], currentNodeIndex) => {
|
|
106
|
+
if (parts[depthIndex]) {
|
|
107
|
+
const nodePath = getNodePath(parts, depthIndex);
|
|
108
|
+
const hasSameRootPaths = partsSourceTuples.some(([pathParts], index) => {
|
|
109
|
+
if (index === currentNodeIndex) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (!pathParts[depthIndex]) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return getNodePath(pathParts, depthIndex) === nodePath;
|
|
116
|
+
});
|
|
117
|
+
if (!hasSameRootPaths) {
|
|
118
|
+
return [[...parts.slice(0, depthIndex), parts.slice(depthIndex).join('/')], file];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return [parts, file];
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return partsSourceTuples.reduce((result, [parts, file]) => {
|
|
125
|
+
result[file] = parts;
|
|
126
|
+
return result;
|
|
127
|
+
}, {});
|
|
128
|
+
}
|
|
129
|
+
function getWebTreeMapData(files) {
|
|
130
|
+
const treeNodesMap = getTreeNodesMap(files);
|
|
131
|
+
const treeData = newNode('/');
|
|
132
|
+
for (const source in files) {
|
|
133
|
+
addNode(treeNodesMap[source], files[source], treeData);
|
|
134
|
+
}
|
|
135
|
+
return treeData;
|
|
136
|
+
}
|
|
137
|
+
exports.getWebTreeMapData = getWebTreeMapData;
|
|
138
|
+
function newNode(name) {
|
|
139
|
+
return {
|
|
140
|
+
name: escape_html_1.default(name),
|
|
141
|
+
data: {
|
|
142
|
+
$area: 0,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function setNodeData(node, fileData) {
|
|
147
|
+
const size = node.data['$area'] + fileData.size;
|
|
148
|
+
if (fileData.coveredSize !== undefined) {
|
|
149
|
+
const coveredSize = (node.data.coveredSize || 0) + fileData.coveredSize;
|
|
150
|
+
node.data.coveredSize = coveredSize;
|
|
151
|
+
node.data.backgroundColor = coverage_1.getColorByPercent(coveredSize / size);
|
|
152
|
+
}
|
|
153
|
+
node.data['$area'] = size;
|
|
154
|
+
}
|
|
155
|
+
function addNode(parts, fileData, treeData) {
|
|
156
|
+
if (fileData.size === 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
let node = treeData;
|
|
160
|
+
setNodeData(node, fileData);
|
|
161
|
+
parts.forEach((part) => {
|
|
162
|
+
if (!node.children) {
|
|
163
|
+
node.children = [];
|
|
164
|
+
}
|
|
165
|
+
let child = node.children.find((child) => child.name === part);
|
|
166
|
+
if (!child) {
|
|
167
|
+
child = newNode(part);
|
|
168
|
+
node.children.push(child);
|
|
169
|
+
}
|
|
170
|
+
node = child;
|
|
171
|
+
setNodeData(child, fileData);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
function addSizeToTitle(node, total) {
|
|
175
|
+
const { $area: size, coveredSize } = node.data;
|
|
176
|
+
const titleParts = [
|
|
177
|
+
node.name,
|
|
178
|
+
helpers_1.formatBytes(size),
|
|
179
|
+
`${helpers_1.formatPercent(size, total, 1)}%`,
|
|
180
|
+
];
|
|
181
|
+
if (coveredSize !== undefined && node.children === undefined) {
|
|
182
|
+
titleParts.push(`Coverage: ${helpers_1.formatPercent(coveredSize, size, 1)}%`);
|
|
183
|
+
}
|
|
184
|
+
node.name = titleParts.join(' • ');
|
|
185
|
+
if (node.children) {
|
|
186
|
+
node.children.forEach((child) => {
|
|
187
|
+
addSizeToTitle(child, total);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=html.js.map
|
package/lib/html.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../src/lib/html.ts"],"names":[],"mappings":"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","sourcesContent":["import btoa from 'btoa';\nimport ejs from 'ejs';\nimport fs from 'fs';\nimport path from 'path';\nimport escapeHtml from 'escape-html';\nimport { cloneDeep } from 'lodash';\n\nimport { formatBytes, getCommonPathPrefix, getFileContent, formatPercent } from './helpers';\nimport { getColorByPercent } from './coverage';\n\nimport type { ExploreOptions, ExploreBundleResult, FileData, FileDataMap } from './types';\n\nconst COMBINED_BUNDLE_NAME = '[combined]';\n\n/**\n * Get webtreemap data to update map on bundle select\n */\nfunction getTreeDataMap(exploreResults: ExploreBundleResult[]): { [id: number]: WebTreeData } {\n let treeData = exploreResults.map<WebTreeData>((data) => ({\n name: data.bundleName,\n data: getWebTreeMapData(data.files),\n }));\n\n if (treeData.length > 1) {\n treeData = [makeMergedTreeDataMap(cloneDeep(treeData)), ...treeData];\n }\n\n for (const webTreeData of treeData) {\n addSizeToTitle(webTreeData.data, webTreeData.data.data['$area']);\n }\n\n return { ...treeData };\n}\n\n/**\n * Generate HTML file content for specified files\n */\nexport function generateHtml(\n exploreResults: ExploreBundleResult[],\n options: ExploreOptions\n): string {\n const assets = {\n webtreemapJs: btoa(fs.readFileSync(require.resolve('./vendor/webtreemap.js'))),\n webtreemapCss: btoa(fs.readFileSync(require.resolve('./vendor/webtreemap.css'))),\n };\n\n const treeDataMap = getTreeDataMap(exploreResults);\n\n // Get bundles info to generate select element\n const bundles = exploreResults.map((data) => ({\n name: data.bundleName,\n size: formatBytes(data.totalBytes),\n }));\n\n // Create a combined bundle if applicable\n if (exploreResults.length > 1) {\n bundles.unshift({\n name: COMBINED_BUNDLE_NAME,\n size: formatBytes(exploreResults.reduce((total, result) => total + result.totalBytes, 0)),\n });\n }\n\n const template = getFileContent(path.join(__dirname, 'tree-viz.ejs'));\n\n return ejs.render(template, {\n options,\n bundles,\n treeDataMap,\n webtreemapJs: assets.webtreemapJs,\n webtreemapCss: assets.webtreemapCss,\n });\n}\n\n/**\n * Create a combined tree data where each of the inputs is a separate node under the root\n */\nexport function makeMergedTreeDataMap(treeData: WebTreeData[]): WebTreeData {\n const data: WebTreeMapNode = newNode('/');\n\n data.children = [];\n\n for (const result of treeData) {\n const childTree = result.data;\n\n childTree.name = result.name;\n\n data.data['$area'] += childTree.data['$area'];\n data.children.push(childTree);\n }\n\n const commonPrefix = getCommonPathPrefix(data.children.map((node) => node.name));\n const commonPrefixLength = commonPrefix.length;\n\n if (commonPrefixLength > 0) {\n for (const node of data.children) {\n node.name = node.name.slice(commonPrefixLength);\n }\n }\n\n return {\n name: COMBINED_BUNDLE_NAME,\n data,\n };\n}\n\ntype TreeNodesMap = { [source: string]: string[] };\n\nfunction getNodePath(parts: string[], depthIndex: number): string {\n return parts.slice(0, depthIndex + 1).join('/');\n}\n\nconst WEBPACK_FILENAME_PREFIX = 'webpack:///';\nconst WEBPACK_FILENAME_PREFIX_LENGTH = WEBPACK_FILENAME_PREFIX.length;\n\nfunction splitFilename(file: string): string[] {\n const webpackPrefixIndex = file.indexOf(WEBPACK_FILENAME_PREFIX);\n\n // Treat webpack file prefix as a filename part\n if (webpackPrefixIndex !== -1) {\n return [\n ...file.substring(0, webpackPrefixIndex).split('/'),\n WEBPACK_FILENAME_PREFIX,\n ...file.substring(webpackPrefixIndex + WEBPACK_FILENAME_PREFIX_LENGTH).split('/'),\n ].filter(Boolean);\n }\n\n return file.split('/');\n}\n\nfunction getTreeNodesMap(fileDataMap: FileDataMap): TreeNodesMap {\n let partsSourceTuples = Object.keys(fileDataMap).map<[string[], string]>((file) => [\n splitFilename(file),\n file,\n ]);\n\n const maxDepth = Math.max(...partsSourceTuples.map(([parts]) => parts.length));\n\n for (let depthIndex = 0; depthIndex < maxDepth; depthIndex += 1) {\n partsSourceTuples = partsSourceTuples.map(([parts, file], currentNodeIndex) => {\n if (parts[depthIndex]) {\n const nodePath = getNodePath(parts, depthIndex);\n\n const hasSameRootPaths = partsSourceTuples.some(([pathParts], index) => {\n if (index === currentNodeIndex) {\n return false;\n }\n if (!pathParts[depthIndex]) {\n return false;\n }\n\n return getNodePath(pathParts, depthIndex) === nodePath;\n });\n\n if (!hasSameRootPaths) {\n // Collapse non-contributing path parts\n return [[...parts.slice(0, depthIndex), parts.slice(depthIndex).join('/')], file];\n }\n }\n\n return [parts, file];\n });\n }\n\n return partsSourceTuples.reduce((result, [parts, file]) => {\n result[file] = parts;\n\n return result;\n }, {});\n}\n\ninterface WebTreeMapNode {\n name: string;\n data: {\n $area: number;\n coveredSize?: number;\n backgroundColor?: string;\n };\n children?: WebTreeMapNode[];\n}\n\nexport interface WebTreeData {\n name: string;\n data: WebTreeMapNode;\n}\n\n/**\n * Convert file size map to webtreemap data\n */\nexport function getWebTreeMapData(files: FileDataMap): WebTreeMapNode {\n const treeNodesMap = getTreeNodesMap(files);\n const treeData = newNode('/');\n\n for (const source in files) {\n addNode(treeNodesMap[source], files[source], treeData);\n }\n\n return treeData;\n}\n\nfunction newNode(name: string): WebTreeMapNode {\n return {\n name: escapeHtml(name),\n data: {\n $area: 0,\n },\n };\n}\n\nfunction setNodeData(node: WebTreeMapNode, fileData: FileData): void {\n const size = node.data['$area'] + fileData.size;\n\n if (fileData.coveredSize !== undefined) {\n const coveredSize = (node.data.coveredSize || 0) + fileData.coveredSize;\n\n node.data.coveredSize = coveredSize;\n node.data.backgroundColor = getColorByPercent(coveredSize / size);\n }\n\n node.data['$area'] = size;\n}\n\nfunction addNode(parts: string[], fileData: FileData, treeData: WebTreeMapNode): void {\n // No need to create nodes with zero size (e.g. '[unmapped]')\n if (fileData.size === 0) {\n return;\n }\n\n let node = treeData;\n\n setNodeData(node, fileData);\n\n parts.forEach((part) => {\n if (!node.children) {\n node.children = [];\n }\n\n let child = node.children.find((child) => child.name === part);\n\n if (!child) {\n child = newNode(part);\n node.children.push(child);\n }\n\n node = child;\n\n setNodeData(child, fileData);\n });\n}\n\nfunction addSizeToTitle(node: WebTreeMapNode, total: number): void {\n const { $area: size, coveredSize } = node.data;\n\n const titleParts = [node.name, formatBytes(size), `${formatPercent(size, total, 1)}%`];\n\n // Add coverage label to leaf nodes only\n if (coveredSize !== undefined && node.children === undefined) {\n titleParts.push(`Coverage: ${formatPercent(coveredSize, size, 1)}%`);\n }\n\n node.name = titleParts.join(' • ');\n\n if (node.children) {\n node.children.forEach((child) => {\n addSizeToTitle(child, total);\n });\n }\n}\n"]}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.explore = void 0;
|
|
4
|
+
const api_1 = require('./api');
|
|
5
|
+
Object.defineProperty(exports, 'explore', {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function () {
|
|
8
|
+
return api_1.explore;
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
var explore_1 = require('./explore');
|
|
12
|
+
Object.defineProperty(exports, 'UNMAPPED_KEY', {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return explore_1.UNMAPPED_KEY;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, 'SOURCE_MAP_COMMENT_KEY', {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return explore_1.SOURCE_MAP_COMMENT_KEY;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, 'NO_SOURCE_KEY', {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return explore_1.NO_SOURCE_KEY;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
exports.default = api_1.explore;
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":";;;AAAA,+BAAgC;AAIvB,wFAJA,aAAO,OAIA;AAHhB,qCAAgF;AAAvE,uGAAA,YAAY,OAAA;AAAE,iHAAA,sBAAsB,OAAA;AAAE,wGAAA,aAAa,OAAA;AAI5D,kBAAe,aAAO,CAAC","sourcesContent":["import { explore } from './api';\nexport { UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY } from './explore';\n\n// Provide both default and named export for convenience\nexport { explore };\nexport default explore;\n"]}
|
package/{dist → lib}/output.d.ts
RENAMED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ExploreBundleResult, ExploreOptions, ExploreResult } from './
|
|
1
|
+
import type { ExploreBundleResult, ExploreOptions, ExploreResult } from './types';
|
|
2
2
|
export declare function formatOutput(results: ExploreBundleResult[], options: ExploreOptions): string | undefined;
|
|
3
3
|
export declare function saveOutputToFile(result: ExploreResult, options: ExploreOptions): void;
|
package/{dist → lib}/output.js
RENAMED
|
@@ -1,56 +1,36 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
exports
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
var _html = require('./html');
|
|
16
|
-
|
|
17
|
-
var _appError = require('./app-error');
|
|
18
|
-
|
|
19
|
-
function _interopRequireDefault(obj) {
|
|
20
|
-
return obj && obj.__esModule ? obj : { default: obj };
|
|
21
|
-
}
|
|
22
|
-
|
|
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
|
+
exports.saveOutputToFile = exports.formatOutput = void 0;
|
|
9
|
+
const os_1 = __importDefault(require('os'));
|
|
10
|
+
const path_1 = __importDefault(require('path'));
|
|
11
|
+
const fs_1 = __importDefault(require('fs'));
|
|
12
|
+
const html_1 = require('./html');
|
|
13
|
+
const app_error_1 = require('./app-error');
|
|
23
14
|
function formatOutput(results, options) {
|
|
24
15
|
if (!options.output) {
|
|
25
16
|
return;
|
|
26
17
|
}
|
|
27
|
-
|
|
28
18
|
switch (options.output.format) {
|
|
29
19
|
case 'json':
|
|
30
|
-
return JSON.stringify(
|
|
31
|
-
{
|
|
32
|
-
results,
|
|
33
|
-
},
|
|
34
|
-
null,
|
|
35
|
-
' '
|
|
36
|
-
);
|
|
37
|
-
|
|
20
|
+
return JSON.stringify({ results }, null, ' ');
|
|
38
21
|
case 'tsv':
|
|
39
22
|
return outputAsTsv(results);
|
|
40
|
-
|
|
41
23
|
case 'html':
|
|
42
|
-
return
|
|
24
|
+
return html_1.generateHtml(results, options);
|
|
43
25
|
}
|
|
44
26
|
}
|
|
45
|
-
|
|
27
|
+
exports.formatOutput = formatOutput;
|
|
46
28
|
function outputAsTsv(results) {
|
|
47
29
|
const lines = ['Source\tSize'];
|
|
48
30
|
results.forEach((bundle, index) => {
|
|
49
31
|
if (index > 0) {
|
|
50
|
-
// Separate bundles by empty line
|
|
51
32
|
lines.push('');
|
|
52
33
|
}
|
|
53
|
-
|
|
54
34
|
Object.entries(bundle.files)
|
|
55
35
|
.map(([source, data]) => [source, data.size])
|
|
56
36
|
.sort(sortFilesBySize)
|
|
@@ -58,37 +38,26 @@ function outputAsTsv(results) {
|
|
|
58
38
|
lines.push(`${source}\t${size}`);
|
|
59
39
|
});
|
|
60
40
|
});
|
|
61
|
-
return lines.join(
|
|
41
|
+
return lines.join(os_1.default.EOL);
|
|
62
42
|
}
|
|
63
|
-
|
|
64
43
|
function sortFilesBySize([, aSize], [, bSize]) {
|
|
65
44
|
return bSize - aSize;
|
|
66
45
|
}
|
|
67
|
-
|
|
68
46
|
function saveOutputToFile(result, options) {
|
|
69
47
|
if (!options.output) {
|
|
70
48
|
return;
|
|
71
49
|
}
|
|
72
|
-
|
|
73
50
|
const output = result.output;
|
|
74
51
|
const filename = options.output.filename;
|
|
75
|
-
|
|
76
52
|
if (output && filename) {
|
|
77
53
|
try {
|
|
78
|
-
const dir =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
recursive: true,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
_fs.default.writeFileSync(filename, output);
|
|
54
|
+
const dir = path_1.default.dirname(filename);
|
|
55
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
56
|
+
fs_1.default.writeFileSync(filename, output);
|
|
85
57
|
} catch (error) {
|
|
86
|
-
throw new
|
|
87
|
-
{
|
|
88
|
-
code: 'CannotSaveFile',
|
|
89
|
-
},
|
|
90
|
-
error
|
|
91
|
-
);
|
|
58
|
+
throw new app_error_1.AppError({ code: 'CannotSaveFile' }, error);
|
|
92
59
|
}
|
|
93
60
|
}
|
|
94
61
|
}
|
|
62
|
+
exports.saveOutputToFile = saveOutputToFile;
|
|
63
|
+
//# sourceMappingURL=output.js.map
|