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/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":";;;;;;AAAA,4EAAyC;AACzC,gDAAwB;AACxB,2CAAiG;AACjG,0DAAiC;AACjC,mCAAiC;AAEjC,+BAAsC;AACtC,uCAQmB;AACnB,2CAAuC;AACvC,yCAA6C;AAahC,QAAA,YAAY,GAAG,YAAY,CAAC;AAC5B,QAAA,sBAAsB,GAAG,oBAAoB,CAAC;AAC9C,QAAA,aAAa,GAAG,aAAa,CAAC;AAC9B,QAAA,OAAO,GAAG,QAAQ,CAAC;AAEnB,QAAA,iBAAiB,GAAG,CAAC,oBAAY,EAAE,8BAAsB,EAAE,qBAAa,EAAE,eAAO,CAAC,CAAC;AAKzF,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,OAAuB;IAEvB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IAE7C,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAErD,MAAM,KAAK,GAAG,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAEvE,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAGtD,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAEjC,OAAO;QACL,UAAU,EAAE,mBAAa,CAAC,MAAM,CAAC;QACjC,GAAG,KAAK;QACR,KAAK;KACN,CAAC;AACJ,CAAC;AApBD,sCAoBC;AAYD,KAAK,UAAU,aAAa,CAAC,QAAc,EAAE,aAAoB;IAC/D,MAAM,eAAe,GAAG,wBAAc,CAAC,QAAQ,CAAC,CAAC;IAEjD,IAAI,QAAkB,CAAC;IAEvB,IAAI,aAAa,EAAE;QACjB,MAAM,oBAAoB,GAAG,wBAAc,CAAC,aAAa,CAAC,CAAC;QAE3D,QAAQ,GAAG,MAAM,IAAI,8BAAiB,CAAC,oBAAoB,CAAC,CAAC;KAC9D;SAAM;QAEL,IAAI,SAAS,GAAG,4BAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QAEpD,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAC5C,SAAS,GAAG,4BAAO,CAAC,iBAAiB,CAAC,eAAe,EAAE,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;SAChF;QAED,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,IAAI,oBAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;SAC7C;QAED,QAAQ,GAAG,MAAM,IAAI,8BAAiB,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;KAC5D;IAED,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,oBAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;KAC7C;IAED,OAAO;QACL,QAAQ;QACR,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,4BAAO,CAAC,YAAY,CAAC;AAC3C,MAAM,sBAAsB,GAAG,4BAAO,CAAC,mBAAmB,CAAC;AAK3D,SAAS,mBAAmB,CAAC,WAAmB;IAC9C,MAAM,gBAAgB,GACpB,4BAAkB,CAAC,aAAa,EAAE,WAAW,CAAC;QAC9C,4BAAkB,CAAC,sBAAsB,EAAE,WAAW,CAAC;QACvD,EAAE,CAAC;IAGL,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC;AACjC,CAAC;AAcD,SAAS,gBAAgB,CAAC,OAAgC,EAAE,cAAsB;IAChF,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAGrE,IAAI,cAAc,GAAG,eAAe,GAAG,CAAC,EAAE;QACxC,OAAO,KAAK,CAAC;KACd;IAGD,IAAI,CAAC,MAAM,EAAE;QACX,OAAO,KAAK,CAAC;KACd;IAGD,IAAI,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;QAC9C,OAAO,IAAI,CAAC;KACb;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAGxD,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,KAAK,CAAC;KACd;IAED,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,mBAAmB,CAAC;QACpD,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,eAAe;KACxB,CAAC,CAAC;IAEH,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,EAAE;QACpC,OAAO,KAAK,CAAC;KACd;IAED,IAAI,yBAAe,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE;QAC5C,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE3C,OAAO,IAAI,CAAC;KACb;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,yBAAyB,CAAC,OAAgC;IACjE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IACzD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAEvC,IAAI,eAAe,GAAG,cAAc,EAAE;QACpC,IAAI,gBAAgB,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE;YAC7C,OAAO;SACR;QAED,MAAM,IAAI,oBAAQ,CAAC;YACjB,IAAI,EAAE,sBAAsB;YAC5B,aAAa;YACb,eAAe;YACf,SAAS,EAAE,IAAI,CAAC,MAAM;SACvB,CAAC,CAAC;KACJ;AACH,CAAC;AAKD,SAAS,gBAAgB,CACvB,aAA4B,EAC5B,OAAuB,EACvB,cAAkC;IAElC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC;IAEjE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAE1D,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvE,MAAM,GAAG,GAAG,mBAAS,CAAC,WAAW,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEvC,MAAM,aAAa,GAAqB,EAAE,CAAC;IAE3C,MAAM,OAAO,GAA4B;QACvC,aAAa,EAAE,CAAC,CAAC;QACjB,eAAe,EAAE,CAAC,CAAC;QACnB,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,IAAI;QACZ,QAAQ;QACR,sBAAsB,EAAE,IAAI,GAAG,EAAE;KAClC,CAAC;IAEF,QAAQ,CAAC,kBAAkB,EAAE,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,EAAE,EAAE;QAGvF,MAAM,SAAS,GAAG,aAAa,GAAG,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QAE9B,IAAI,IAAI,KAAK,SAAS,EAAE;YACtB,IAAI,OAAO,CAAC,cAAc,EAAE;gBAC1B,OAAO;aACR;YAED,MAAM,IAAI,oBAAQ,CAAC;gBACjB,IAAI,EAAE,oBAAoB;gBAC1B,aAAa;gBACb,OAAO,EAAE,KAAK,CAAC,MAAM;aACtB,CAAC,CAAC;SACJ;QAED,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;QACtC,OAAO,CAAC,eAAe,GAAG,mBAAmB,IAAI,eAAe,CAAC;QACjE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QACpB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;QAExB,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YAC3B,yBAAyB,CAAC,OAAO,CAAC,CAAC;SACpC;QAED,MAAM,KAAK,GAAG,eAAe,CAAC;QAC9B,MAAM,GAAG,GAAG,mBAAmB,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;QAEjF,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAElD,UAAU,CAAC,IAAI,CAAC;YACd,KAAK;YACL,GAAG;YACH,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,qBAAa,CAAC,CAAC,CAAC,MAAM;SACjD,CAAC,CAAC;QAEH,aAAa,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAI,KAAK,GAAgB,EAAE,CAAC;IAC5B,IAAI,WAAW,GAAG,CAAC,CAAC;IAGpB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;IAEjE,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9B,MAAM,YAAY,GAAG,qBAAW,CAAC,UAAU,CAAC,CAAC;QAE7C,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;YAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YACnD,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;YAE7C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;gBAClB,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;aAC7B;YAED,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC;YAEtC,WAAW,IAAI,eAAe,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,IAAI,cAAc,EAAE;YAClB,KAAK,GAAG,0BAAe,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;SAC/E;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,6BAAmB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,IAAI,aAAiC,CAAC;IAEtC,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE;QACpC,KAAK,CAAC,8BAAsB,CAAC,GAAG,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC;KACjE;IAED,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;QACvB,aAAa,GAAG,UAAU,GAAG,WAAW,GAAG,qBAAqB,GAAG,QAAQ,CAAC;QAC5E,KAAK,CAAC,oBAAY,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;KAC/C;IAED,IAAI,QAAQ,GAAG,CAAC,EAAE;QAChB,KAAK,CAAC,eAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;KACrC;IAED,OAAO;QACL,GAAG,CAAC,OAAO,CAAC,uBAAuB;YACjC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,GAAG,qBAAqB,EAAE;YACpD,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACnB,WAAW;QACX,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,aAAa,EAAE,CAAC;QAC7C,QAAQ;QACR,qBAAqB;QACrB,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,WAAwB,EAAE,OAAuB;IACjF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,MAAM,MAAM,GAAG,6BAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE7B,IAAI,MAAM,EAAE;YACV,WAAW,GAAG,gBAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;SAC5E;KACF;IAED,IAAI,OAAO,CAAC,UAAU,EAAE;QACtB,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE;YAClF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAEvC,OAAO,gBAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1E,CAAC,EAAE,WAAW,CAAC,CAAC;KACjB;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAnBD,8CAmBC","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
|