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/html.js CHANGED
@@ -1,51 +1,33 @@
1
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
- */
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 btoa_1 = __importDefault(require('btoa'));
9
+ const ejs_1 = __importDefault(require('ejs'));
10
+ const fs_1 = __importDefault(require('fs'));
11
+ const path_1 = __importDefault(require('path'));
12
+ const escape_html_1 = __importDefault(require('escape-html'));
13
+ const helpers_1 = require('./helpers');
14
+ const coverage_1 = require('./coverage');
30
15
  function generateHtml(exploreResults, options) {
31
16
  const assets = {
32
- webtreemapJs: (0, _btoa.default)(
33
- _fs.default.readFileSync(require.resolve('./vendor/webtreemap.js'))
17
+ webtreemapJs: btoa_1.default(
18
+ fs_1.default.readFileSync(require.resolve('./vendor/webtreemap.js'))
34
19
  ),
35
- webtreemapCss: (0, _btoa.default)(
36
- _fs.default.readFileSync(require.resolve('./vendor/webtreemap.css'))
20
+ webtreemapCss: btoa_1.default(
21
+ fs_1.default.readFileSync(require.resolve('./vendor/webtreemap.css'))
37
22
  ),
38
- }; // Create a combined bundle if applicable
39
-
23
+ };
40
24
  if (exploreResults.length > 1) {
41
25
  exploreResults = [makeMergedBundle(exploreResults)].concat(exploreResults);
42
- } // Get bundles info to generate select element
43
-
44
- const bundles = exploreResults.map(data => ({
26
+ }
27
+ const bundles = exploreResults.map((data) => ({
45
28
  name: data.bundleName,
46
- size: (0, _helpers.formatBytes)(data.totalBytes),
47
- })); // Get webtreemap data to update map on bundle select
48
-
29
+ size: helpers_1.formatBytes(data.totalBytes),
30
+ }));
49
31
  const treeDataMap = exploreResults.reduce((result, data, index) => {
50
32
  result[index] = {
51
33
  name: data.bundleName,
@@ -53,8 +35,8 @@ function generateHtml(exploreResults, options) {
53
35
  };
54
36
  return result;
55
37
  }, {});
56
- const template = (0, _helpers.getFileContent)(_path.default.join(__dirname, 'tree-viz.ejs'));
57
- return _ejs.default.render(template, {
38
+ const template = helpers_1.getFileContent(path_1.default.join(__dirname, 'tree-viz.ejs'));
39
+ return ejs_1.default.render(template, {
58
40
  options,
59
41
  bundles,
60
42
  treeDataMap,
@@ -62,16 +44,11 @@ function generateHtml(exploreResults, options) {
62
44
  webtreemapCss: assets.webtreemapCss,
63
45
  });
64
46
  }
65
- /**
66
- * Create a combined result where each of the inputs is a separate node under the root
67
- */
68
-
47
+ exports.generateHtml = generateHtml;
69
48
  function makeMergedBundle(exploreResults) {
70
49
  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
-
50
+ const files = {};
51
+ const commonPrefix = helpers_1.getCommonPathPrefix(exploreResults.map((r) => r.bundleName));
75
52
  for (const result of exploreResults) {
76
53
  totalBytes += result.totalBytes;
77
54
  const prefix = result.bundleName.slice(commonPrefix.length);
@@ -79,7 +56,6 @@ function makeMergedBundle(exploreResults) {
79
56
  files[`${prefix}/${fileName}`] = size;
80
57
  });
81
58
  }
82
-
83
59
  return {
84
60
  bundleName: '[combined]',
85
61
  totalBytes,
@@ -89,114 +65,111 @@ function makeMergedBundle(exploreResults) {
89
65
  files,
90
66
  };
91
67
  }
92
-
68
+ function getNodePath(parts, depthIndex) {
69
+ return parts.slice(0, depthIndex + 1).join('/');
70
+ }
71
+ const WEBPACK_FILENAME_PREFIX = 'webpack:///';
72
+ const WEBPACK_FILENAME_PREFIX_LENGTH = WEBPACK_FILENAME_PREFIX.length;
73
+ function splitFilename(file) {
74
+ const webpackPrefixIndex = file.indexOf(WEBPACK_FILENAME_PREFIX);
75
+ if (webpackPrefixIndex !== -1) {
76
+ return [
77
+ ...file.substring(0, webpackPrefixIndex).split('/'),
78
+ WEBPACK_FILENAME_PREFIX,
79
+ ...file.substring(webpackPrefixIndex + WEBPACK_FILENAME_PREFIX_LENGTH).split('/'),
80
+ ].filter(Boolean);
81
+ }
82
+ return file.split('/');
83
+ }
93
84
  function getTreeNodesMap(fileDataMap) {
94
- let partsSourceTuples = Object.keys(fileDataMap).map(file => [file.split('/'), file]);
85
+ let partsSourceTuples = Object.keys(fileDataMap).map((file) => [splitFilename(file), file]);
95
86
  const maxDepth = Math.max(...partsSourceTuples.map(([parts]) => parts.length));
96
-
97
87
  for (let depthIndex = 0; depthIndex < maxDepth; depthIndex += 1) {
98
- partsSourceTuples = partsSourceTuples.map(([parts, file]) => {
99
- const rootPart = parts[depthIndex];
100
-
101
- if (rootPart) {
102
- const sameRootParts = partsSourceTuples.filter(
103
- ([pathParts]) => pathParts[depthIndex] === rootPart
104
- );
105
-
106
- if (sameRootParts.length === 1) {
107
- // Collapse non-contributing path parts
88
+ partsSourceTuples = partsSourceTuples.map(([parts, file], currentNodeIndex) => {
89
+ if (parts[depthIndex]) {
90
+ const nodePath = getNodePath(parts, depthIndex);
91
+ const hasSameRootPaths = partsSourceTuples.some(([pathParts], index) => {
92
+ if (index === currentNodeIndex) {
93
+ return false;
94
+ }
95
+ if (!pathParts[depthIndex]) {
96
+ return false;
97
+ }
98
+ return getNodePath(pathParts, depthIndex) === nodePath;
99
+ });
100
+ if (!hasSameRootPaths) {
108
101
  return [[...parts.slice(0, depthIndex), parts.slice(depthIndex).join('/')], file];
109
102
  }
110
103
  }
111
-
112
104
  return [parts, file];
113
105
  });
114
106
  }
115
-
116
107
  return partsSourceTuples.reduce((result, [parts, file]) => {
117
108
  result[file] = parts;
118
109
  return result;
119
110
  }, {});
120
111
  }
121
-
122
- /**
123
- * Convert file size map to webtreemap data
124
- */
125
112
  function getWebTreeMapData(files) {
126
113
  const treeNodesMap = getTreeNodesMap(files);
127
114
  const treeData = newNode('/');
128
-
129
115
  for (const source in files) {
130
116
  addNode(treeNodesMap[source], files[source], treeData);
131
117
  }
132
-
133
118
  addSizeToTitle(treeData, treeData.data['$area']);
134
119
  return treeData;
135
120
  }
136
-
121
+ exports.getWebTreeMapData = getWebTreeMapData;
137
122
  function newNode(name) {
138
123
  return {
139
- name: (0, _escapeHtml.default)(name),
124
+ name: escape_html_1.default(name),
140
125
  data: {
141
126
  $area: 0,
142
127
  },
143
128
  };
144
129
  }
145
-
146
130
  function setNodeData(node, fileData) {
147
131
  const size = node.data['$area'] + fileData.size;
148
-
149
132
  if (fileData.coveredSize !== undefined) {
150
133
  const coveredSize = (node.data.coveredSize || 0) + fileData.coveredSize;
151
134
  node.data.coveredSize = coveredSize;
152
- node.data.backgroundColor = (0, _coverage.getColorByPercent)(coveredSize / size);
135
+ node.data.backgroundColor = coverage_1.getColorByPercent(coveredSize / size);
153
136
  }
154
-
155
137
  node.data['$area'] = size;
156
138
  }
157
-
158
139
  function addNode(parts, fileData, treeData) {
159
- // No need to create nodes with zero size (e.g. '[unmapped]')
160
140
  if (fileData.size === 0) {
161
141
  return;
162
142
  }
163
-
164
143
  let node = treeData;
165
144
  setNodeData(node, fileData);
166
- parts.forEach(part => {
145
+ parts.forEach((part) => {
167
146
  if (!node.children) {
168
147
  node.children = [];
169
148
  }
170
-
171
- let child = node.children.find(child => child.name === part);
172
-
149
+ let child = node.children.find((child) => child.name === part);
173
150
  if (!child) {
174
151
  child = newNode(part);
175
152
  node.children.push(child);
176
153
  }
177
-
178
154
  node = child;
179
155
  setNodeData(child, fileData);
180
156
  });
181
157
  }
182
-
183
158
  function addSizeToTitle(node, total) {
184
159
  const { $area: size, coveredSize } = node.data;
185
160
  const titleParts = [
186
161
  node.name,
187
- (0, _helpers.formatBytes)(size),
188
- `${(0, _helpers.formatPercent)(size, total, 1)}%`,
189
- ]; // Add coverage label to leaf nodes only
190
-
162
+ helpers_1.formatBytes(size),
163
+ `${helpers_1.formatPercent(size, total, 1)}%`,
164
+ ];
191
165
  if (coveredSize !== undefined && node.children === undefined) {
192
- titleParts.push(`Coverage: ${(0, _helpers.formatPercent)(coveredSize, size, 1)}%`);
166
+ titleParts.push(`Coverage: ${helpers_1.formatPercent(coveredSize, size, 1)}%`);
193
167
  }
194
-
195
168
  node.name = titleParts.join(' • ');
196
-
197
169
  if (node.children) {
198
- node.children.forEach(child => {
170
+ node.children.forEach((child) => {
199
171
  addSizeToTitle(child, total);
200
172
  });
201
173
  }
202
174
  }
175
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/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';\n\nimport { formatBytes, getCommonPathPrefix, getFileContent, formatPercent } from './helpers';\nimport { getColorByPercent } from './coverage';\n\nimport type { ExploreOptions, ExploreBundleResult, FileData, FileDataMap } from './types';\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 // Create a combined bundle if applicable\n if (exploreResults.length > 1) {\n exploreResults = [makeMergedBundle(exploreResults)].concat(exploreResults);\n }\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 // Get webtreemap data to update map on bundle select\n const treeDataMap = exploreResults.reduce<Record<string, { name: string; data: WebTreeMapNode }>>(\n (result, data, index) => {\n result[index] = {\n name: data.bundleName,\n data: getWebTreeMapData(data.files),\n };\n\n return result;\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 result where each of the inputs is a separate node under the root\n */\nfunction makeMergedBundle(exploreResults: ExploreBundleResult[]): ExploreBundleResult {\n let totalBytes = 0;\n const files: FileDataMap = {};\n\n // Remove any common prefix to keep the visualization as simple as possible.\n const commonPrefix = getCommonPathPrefix(exploreResults.map((r) => r.bundleName));\n\n for (const result of exploreResults) {\n totalBytes += result.totalBytes;\n\n const prefix = result.bundleName.slice(commonPrefix.length);\n\n Object.entries(result.files).forEach(([fileName, size]) => {\n files[`${prefix}/${fileName}`] = size;\n });\n }\n\n return {\n bundleName: '[combined]',\n totalBytes,\n mappedBytes: 0,\n eolBytes: 0,\n sourceMapCommentBytes: 0,\n files,\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\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 addSizeToTitle(treeData, treeData.data['$area']);\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/dist/index.d.ts CHANGED
@@ -1,92 +1,4 @@
1
- /// <reference types="node" />
2
1
  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 };
2
+ export { UNMAPPED_KEY, SOURCE_MAP_COMMENT_KEY, NO_SOURCE_KEY } from './explore';
3
+ export { explore };
5
4
  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 CHANGED
@@ -1,38 +1,10 @@
1
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;
2
+ Object.defineProperty(exports, '__esModule', { value: true });
3
+ const api_1 = require('./api');
4
+ exports.explore = api_1.explore;
5
+ var explore_1 = require('./explore');
6
+ exports.UNMAPPED_KEY = explore_1.UNMAPPED_KEY;
7
+ exports.SOURCE_MAP_COMMENT_KEY = explore_1.SOURCE_MAP_COMMENT_KEY;
8
+ exports.NO_SOURCE_KEY = explore_1.NO_SOURCE_KEY;
9
+ exports.default = api_1.explore;
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,+BAAgC;AAIvB,kBAJA,aAAO,CAIA;AAHhB,qCAAgF;AAAvE,iCAAA,YAAY,CAAA;AAAE,2CAAA,sBAAsB,CAAA;AAAE,kCAAA,aAAa,CAAA;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/output.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { ExploreBundleResult, ExploreOptions, ExploreResult } from './index';
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/output.js CHANGED
@@ -1,56 +1,35 @@
1
1
  'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true,
5
- });
6
- exports.formatOutput = formatOutput;
7
- exports.saveOutputToFile = saveOutputToFile;
8
-
9
- var _os = _interopRequireDefault(require('os'));
10
-
11
- var _path = _interopRequireDefault(require('path'));
12
-
13
- var _fs = _interopRequireDefault(require('fs'));
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
+ const os_1 = __importDefault(require('os'));
9
+ const path_1 = __importDefault(require('path'));
10
+ const fs_1 = __importDefault(require('fs'));
11
+ const html_1 = require('./html');
12
+ const app_error_1 = require('./app-error');
23
13
  function formatOutput(results, options) {
24
14
  if (!options.output) {
25
15
  return;
26
16
  }
27
-
28
17
  switch (options.output.format) {
29
18
  case 'json':
30
- return JSON.stringify(
31
- {
32
- results,
33
- },
34
- null,
35
- ' '
36
- );
37
-
19
+ return JSON.stringify({ results }, null, ' ');
38
20
  case 'tsv':
39
21
  return outputAsTsv(results);
40
-
41
22
  case 'html':
42
- return (0, _html.generateHtml)(results, options);
23
+ return html_1.generateHtml(results, options);
43
24
  }
44
25
  }
45
-
26
+ exports.formatOutput = formatOutput;
46
27
  function outputAsTsv(results) {
47
28
  const lines = ['Source\tSize'];
48
29
  results.forEach((bundle, index) => {
49
30
  if (index > 0) {
50
- // Separate bundles by empty line
51
31
  lines.push('');
52
32
  }
53
-
54
33
  Object.entries(bundle.files)
55
34
  .map(([source, data]) => [source, data.size])
56
35
  .sort(sortFilesBySize)
@@ -58,37 +37,26 @@ function outputAsTsv(results) {
58
37
  lines.push(`${source}\t${size}`);
59
38
  });
60
39
  });
61
- return lines.join(_os.default.EOL);
40
+ return lines.join(os_1.default.EOL);
62
41
  }
63
-
64
42
  function sortFilesBySize([, aSize], [, bSize]) {
65
43
  return bSize - aSize;
66
44
  }
67
-
68
45
  function saveOutputToFile(result, options) {
69
46
  if (!options.output) {
70
47
  return;
71
48
  }
72
-
73
49
  const output = result.output;
74
50
  const filename = options.output.filename;
75
-
76
51
  if (output && filename) {
77
52
  try {
78
- const dir = _path.default.dirname(filename);
79
-
80
- _fs.default.mkdirSync(dir, {
81
- recursive: true,
82
- });
83
-
84
- _fs.default.writeFileSync(filename, output);
53
+ const dir = path_1.default.dirname(filename);
54
+ fs_1.default.mkdirSync(dir, { recursive: true });
55
+ fs_1.default.writeFileSync(filename, output);
85
56
  } catch (error) {
86
- throw new _appError.AppError(
87
- {
88
- code: 'CannotSaveFile',
89
- },
90
- error
91
- );
57
+ throw new app_error_1.AppError({ code: 'CannotSaveFile' }, error);
92
58
  }
93
59
  }
94
60
  }
61
+ exports.saveOutputToFile = saveOutputToFile;
62
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAEpB,iCAAsC;AACtC,2CAAuC;AAIvC,SAAgB,YAAY,CAC1B,OAA8B,EAC9B,OAAuB;IAEvB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO;KACR;IAED,QAAQ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;QAC7B,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAEjD,KAAK,KAAK;YACR,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;QAE9B,KAAK,MAAM;YACT,OAAO,mBAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;KACzC;AACH,CAAC;AAlBD,oCAkBC;AAED,SAAS,WAAW,CAAC,OAA8B;IACjD,MAAM,KAAK,GAAG,CAAC,cAAc,CAAC,CAAC;IAE/B,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChC,IAAI,KAAK,GAAG,CAAC,EAAE;YAEb,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SAChB;QAED,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;aACzB,GAAG,CAAmB,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;aAC9D,IAAI,CAAC,eAAe,CAAC;aACrB,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE;YAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC,IAAI,CAAC,YAAE,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,eAAe,CAAC,CAAC,EAAE,KAAK,CAAmB,EAAE,CAAC,EAAE,KAAK,CAAmB;IAC/E,OAAO,KAAK,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,SAAgB,gBAAgB,CAAC,MAAqB,EAAE,OAAuB;IAC7E,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO;KACR;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IAEzC,IAAI,MAAM,IAAI,QAAQ,EAAE;QACtB,IAAI;YACF,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAEnC,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;SACpC;QAAC,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,oBAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,KAAK,CAAC,CAAC;SACvD;KACF;AACH,CAAC;AAlBD,4CAkBC","sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\n\nimport { generateHtml } from './html';\nimport { AppError } from './app-error';\n\nimport type { ExploreBundleResult, ExploreOptions, ExploreResult } from './types';\n\nexport function formatOutput(\n results: ExploreBundleResult[],\n options: ExploreOptions\n): string | undefined {\n if (!options.output) {\n return;\n }\n\n switch (options.output.format) {\n case 'json':\n return JSON.stringify({ results }, null, ' ');\n\n case 'tsv':\n return outputAsTsv(results);\n\n case 'html':\n return generateHtml(results, options);\n }\n}\n\nfunction outputAsTsv(results: ExploreBundleResult[]): string {\n const lines = ['Source\\tSize'];\n\n results.forEach((bundle, index) => {\n if (index > 0) {\n // Separate bundles by empty line\n lines.push('');\n }\n\n Object.entries(bundle.files)\n .map<[string, number]>(([source, data]) => [source, data.size])\n .sort(sortFilesBySize)\n .forEach(([source, size]) => {\n lines.push(`${source}\\t${size}`);\n });\n });\n\n return lines.join(os.EOL);\n}\n\nfunction sortFilesBySize([, aSize]: [string, number], [, bSize]: [string, number]): number {\n return bSize - aSize;\n}\n\nexport function saveOutputToFile(result: ExploreResult, options: ExploreOptions): void {\n if (!options.output) {\n return;\n }\n\n const output = result.output;\n const filename = options.output.filename;\n\n if (output && filename) {\n try {\n const dir = path.dirname(filename);\n\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(filename, output);\n } catch (error) {\n throw new AppError({ code: 'CannotSaveFile' }, error);\n }\n }\n}\n"]}