Add bundle size information to the build output (#169)
This commit is contained in:
parent
75b05b393a
commit
0054f78e42
6 changed files with 163 additions and 14 deletions
|
@ -54,6 +54,7 @@
|
||||||
"find-up": "^5.0.0",
|
"find-up": "^5.0.0",
|
||||||
"github-slugger": "^1.3.0",
|
"github-slugger": "^1.3.0",
|
||||||
"gray-matter": "^4.0.2",
|
"gray-matter": "^4.0.2",
|
||||||
|
"gzip-size": "^6.0.0",
|
||||||
"hast-to-hyperscript": "~9.0.0",
|
"hast-to-hyperscript": "~9.0.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"locate-character": "^2.0.5",
|
"locate-character": "^2.0.5",
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
"sass": "^1.32.8",
|
"sass": "^1.32.8",
|
||||||
"snowpack": "^3.3.7",
|
"snowpack": "^3.3.7",
|
||||||
|
"string-width": "^5.0.0",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"svelte": "^3.35.0",
|
"svelte": "^3.35.0",
|
||||||
"unified": "^9.2.1",
|
"unified": "^9.2.1",
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type { LogOptions } from './logger';
|
||||||
import type { AstroRuntime, LoadResult } from './runtime';
|
import type { AstroRuntime, LoadResult } from './runtime';
|
||||||
|
|
||||||
import { existsSync, promises as fsPromises } from 'fs';
|
import { existsSync, promises as fsPromises } from 'fs';
|
||||||
import { bold, green, yellow, underline } from 'kleur/colors';
|
import { bold, green, yellow } from 'kleur/colors';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import cheerio from 'cheerio';
|
import cheerio from 'cheerio';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
@ -16,6 +16,7 @@ import { generateRSS } from './build/rss.js';
|
||||||
import { generateSitemap } from './build/sitemap.js';
|
import { generateSitemap } from './build/sitemap.js';
|
||||||
import { collectStatics } from './build/static.js';
|
import { collectStatics } from './build/static.js';
|
||||||
import { canonicalURL } from './build/util.js';
|
import { canonicalURL } from './build/util.js';
|
||||||
|
import { createURLStats, mapBundleStatsToURLStats, logURLStats } from './build/stats.js';
|
||||||
|
|
||||||
const { mkdir, readFile, writeFile } = fsPromises;
|
const { mkdir, readFile, writeFile } = fsPromises;
|
||||||
|
|
||||||
|
@ -205,8 +206,11 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
||||||
const statics = new Set<string>();
|
const statics = new Set<string>();
|
||||||
const collectImportsOptions = { astroConfig, logging, resolvePackageUrl, mode };
|
const collectImportsOptions = { astroConfig, logging, resolvePackageUrl, mode };
|
||||||
|
|
||||||
const pages = await allPages(pageRoot);
|
|
||||||
let builtURLs: string[] = [];
|
let builtURLs: string[] = [];
|
||||||
|
let urlStats = createURLStats();
|
||||||
|
let importsToUrl = new Map<string, Set<string>>();
|
||||||
|
|
||||||
|
const pages = await allPages(pageRoot);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
info(logging, 'build', yellow('! building pages...'));
|
info(logging, 'build', yellow('! building pages...'));
|
||||||
|
@ -218,8 +222,10 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
||||||
|
|
||||||
const pageType = getPageType(filepath);
|
const pageType = getPageType(filepath);
|
||||||
const pageOptions: PageBuildOptions = { astroRoot, dist, filepath, runtime, site: astroConfig.buildOptions.site, sitemap: astroConfig.buildOptions.sitemap, statics };
|
const pageOptions: PageBuildOptions = { astroRoot, dist, filepath, runtime, site: astroConfig.buildOptions.site, sitemap: astroConfig.buildOptions.sitemap, statics };
|
||||||
|
let urls: string[];
|
||||||
if (pageType === 'collection') {
|
if (pageType === 'collection') {
|
||||||
const { canonicalURLs, rss } = await buildCollectionPage(pageOptions);
|
const { canonicalURLs, rss } = await buildCollectionPage(pageOptions);
|
||||||
|
urls = canonicalURLs;
|
||||||
builtURLs.push(...canonicalURLs);
|
builtURLs.push(...canonicalURLs);
|
||||||
if (rss) {
|
if (rss) {
|
||||||
const basename = path
|
const basename = path
|
||||||
|
@ -230,10 +236,27 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { canonicalURLs } = await buildStaticPage(pageOptions);
|
const { canonicalURLs } = await buildStaticPage(pageOptions);
|
||||||
|
urls = canonicalURLs;
|
||||||
builtURLs.push(...canonicalURLs);
|
builtURLs.push(...canonicalURLs);
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeSet(imports, await collectDynamicImports(filepath, collectImportsOptions));
|
const dynamicImports = await collectDynamicImports(filepath, collectImportsOptions);
|
||||||
|
mergeSet(imports, dynamicImports);
|
||||||
|
|
||||||
|
// Keep track of urls and dynamic imports for stats.
|
||||||
|
for(const url of urls) {
|
||||||
|
urlStats.set(url, {
|
||||||
|
dynamicImports,
|
||||||
|
stats: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let imp of dynamicImports) {
|
||||||
|
if(!importsToUrl.has(imp)) {
|
||||||
|
importsToUrl.set(imp, new Set<string>());
|
||||||
|
}
|
||||||
|
mergeSet(importsToUrl.get(imp)!, new Set(urls));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
info(logging, 'build', green('✔'), 'pages built.');
|
info(logging, 'build', green('✔'), 'pages built.');
|
||||||
|
@ -253,7 +276,8 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
||||||
if (imports.size > 0) {
|
if (imports.size > 0) {
|
||||||
try {
|
try {
|
||||||
info(logging, 'build', yellow('! bundling client-side code.'));
|
info(logging, 'build', yellow('! bundling client-side code.'));
|
||||||
await bundle(imports, { dist, runtime, astroConfig });
|
const bundleStats = await bundle(imports, { dist, runtime, astroConfig });
|
||||||
|
mapBundleStatsToURLStats(urlStats, importsToUrl, bundleStats);
|
||||||
info(logging, 'build', green('✔'), 'bundling complete.');
|
info(logging, 'build', green('✔'), 'bundling complete.');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error(logging, 'build', err);
|
error(logging, 'build', err);
|
||||||
|
@ -297,13 +321,8 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
||||||
info(logging, 'tip', `Set "buildOptions.site" in astro.config.mjs to generate a sitemap.xml`);
|
info(logging, 'tip', `Set "buildOptions.site" in astro.config.mjs to generate a sitemap.xml`);
|
||||||
}
|
}
|
||||||
|
|
||||||
builtURLs.sort((a, b) => a.localeCompare(b, 'en', { numeric: true }));
|
// Log in a table-like view.
|
||||||
info(logging, 'build', underline('Pages'));
|
logURLStats(logging, urlStats, builtURLs);
|
||||||
const lastIndex = builtURLs.length - 1;
|
|
||||||
builtURLs.forEach((url, index) => {
|
|
||||||
const sep = index === 0 ? '┌' : index === lastIndex ? '└' : '├';
|
|
||||||
info(logging, null, ' ' + sep, url === '/' ? url : url + '/');
|
|
||||||
});
|
|
||||||
|
|
||||||
await runtime.shutdown();
|
await runtime.shutdown();
|
||||||
info(logging, 'build', bold(green('▶ Build Complete!')));
|
info(logging, 'build', bold(green('▶ Build Complete!')));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { AstroConfig, RuntimeMode, ValidExtensionPlugins } from '../@types/astro';
|
import type { AstroConfig, RuntimeMode, ValidExtensionPlugins } from '../@types/astro';
|
||||||
import type { ImportDeclaration } from '@babel/types';
|
import type { ImportDeclaration } from '@babel/types';
|
||||||
import type { InputOptions, OutputOptions } from 'rollup';
|
import type { InputOptions, OutputOptions, OutputChunk } from 'rollup';
|
||||||
import type { AstroRuntime } from '../runtime';
|
import type { AstroRuntime } from '../runtime';
|
||||||
import type { LogOptions } from '../logger';
|
import type { LogOptions } from '../logger';
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import babelParser from '@babel/parser';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { rollup } from 'rollup';
|
import { rollup } from 'rollup';
|
||||||
import { terser } from 'rollup-plugin-terser';
|
import { terser } from 'rollup-plugin-terser';
|
||||||
|
import { createBundleStats, addBundleStats } from './stats.js';
|
||||||
|
|
||||||
const { transformSync } = esbuild;
|
const { transformSync } = esbuild;
|
||||||
const { readFile } = fsPromises;
|
const { readFile } = fsPromises;
|
||||||
|
@ -309,5 +310,12 @@ export async function bundle(imports: Set<string>, { runtime, dist }: BundleOpti
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
await build.write(outputOptions);
|
const stats = createBundleStats();
|
||||||
|
const {output} = await build.write(outputOptions);
|
||||||
|
await Promise.all(output.map(async chunk => {
|
||||||
|
const code = (chunk as OutputChunk).code || '';
|
||||||
|
await addBundleStats(stats, code, chunk.fileName);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
61
packages/astro/src/build/stats.ts
Normal file
61
packages/astro/src/build/stats.ts
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import type { LogOptions } from '../logger';
|
||||||
|
|
||||||
|
import { info, table } from '../logger.js';
|
||||||
|
import { underline } from 'kleur/colors';
|
||||||
|
import gzipSize from 'gzip-size';
|
||||||
|
|
||||||
|
interface BundleStats {
|
||||||
|
size: number;
|
||||||
|
gzipSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface URLStats {
|
||||||
|
dynamicImports: Set<string>;
|
||||||
|
stats: BundleStats[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BundleStatsMap = Map<string, BundleStats>;
|
||||||
|
export type URLStatsMap = Map<string, URLStats>;
|
||||||
|
|
||||||
|
export function createURLStats(): URLStatsMap {
|
||||||
|
return new Map<string, URLStats>();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createBundleStats(): BundleStatsMap {
|
||||||
|
return new Map<string, BundleStats>();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function addBundleStats(bundleStatsMap: BundleStatsMap, code: string, filename: string) {
|
||||||
|
const gzsize = await gzipSize(code);
|
||||||
|
|
||||||
|
bundleStatsMap.set(filename, {
|
||||||
|
size: Buffer.byteLength(code),
|
||||||
|
gzipSize: gzsize
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapBundleStatsToURLStats(urlStats: URLStatsMap, importsToUrl: Map<string, Set<string>>, bundleStats: BundleStatsMap) {
|
||||||
|
for(let [imp, stats] of bundleStats) {
|
||||||
|
for(let url of importsToUrl.get('/' + imp) || []) {
|
||||||
|
urlStats.get(url)?.stats.push(stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logURLStats(logging: LogOptions, urlStats: URLStatsMap, builtURLs: string[]) {
|
||||||
|
builtURLs.sort((a, b) => a.localeCompare(b, 'en', { numeric: true }));
|
||||||
|
info(logging, null, '');
|
||||||
|
const log = table(logging, [60, 20]);
|
||||||
|
log(info, ' ' + underline('Pages'), underline('GZip Size'));
|
||||||
|
|
||||||
|
const lastIndex = builtURLs.length - 1;
|
||||||
|
builtURLs.forEach((url, index) => {
|
||||||
|
const sep = index === 0 ? '┌' : index === lastIndex ? '└' : '├';
|
||||||
|
const urlPart = (' ' + sep + ' ') + (url === '/' ? url : url + '/');
|
||||||
|
|
||||||
|
const bytes = urlStats.get(url)?.stats.map(s => s.gzipSize).reduce((a, b) => a + b, 0) || 0;
|
||||||
|
const kb = (bytes * 0.001).toFixed(2);
|
||||||
|
const sizePart = kb + ' kB';
|
||||||
|
log(info, urlPart, sizePart);
|
||||||
|
});
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import type { CompileError } from 'astro-parser';
|
||||||
import { bold, blue, red, grey, underline } from 'kleur/colors';
|
import { bold, blue, red, grey, underline } from 'kleur/colors';
|
||||||
import { Writable } from 'stream';
|
import { Writable } from 'stream';
|
||||||
import { format as utilFormat } from 'util';
|
import { format as utilFormat } from 'util';
|
||||||
|
import stringWidth from 'string-width';
|
||||||
|
|
||||||
type ConsoleStream = Writable & {
|
type ConsoleStream = Writable & {
|
||||||
fd: 1 | 2;
|
fd: 1 | 2;
|
||||||
|
@ -102,6 +103,15 @@ export function error(opts: LogOptions, type: string | null, ...messages: Array<
|
||||||
return log(opts, 'error', type, ...messages);
|
return log(opts, 'error', type, ...messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LogFn = typeof debug | typeof info | typeof warn | typeof error;
|
||||||
|
|
||||||
|
export function table(opts: LogOptions, columns: number[]) {
|
||||||
|
return function logTable(logFn: LogFn, ...input: Array<any>) {
|
||||||
|
const messages = columns.map((len, i) => padStr(input[i].toString(), len));
|
||||||
|
logFn(opts, null, ...messages);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Pretty format error for display */
|
/** Pretty format error for display */
|
||||||
export function parseError(opts: LogOptions, err: CompileError) {
|
export function parseError(opts: LogOptions, err: CompileError) {
|
||||||
let frame = err.frame
|
let frame = err.frame
|
||||||
|
@ -142,3 +152,14 @@ export function trapWarn(cb: (...args: any[]) => void = () => {}) {
|
||||||
};
|
};
|
||||||
return () => (console.warn = warn);
|
return () => (console.warn = warn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function padStr(str: string, len: number) {
|
||||||
|
const strLen = stringWidth(str);
|
||||||
|
if(strLen > len) {
|
||||||
|
return str.substring(0, len - 3) + '...';
|
||||||
|
}
|
||||||
|
const spaces = Array.from({ length: len - strLen }, () => ' ').join('');
|
||||||
|
return str + spaces;
|
||||||
|
}
|
40
yarn.lock
40
yarn.lock
|
@ -2019,6 +2019,11 @@ ansi-regex@^5.0.0:
|
||||||
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz"
|
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz"
|
||||||
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
||||||
|
|
||||||
|
ansi-regex@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.0.tgz#ecc7f5933cbe5ac7b33e209a5ff409ab1669c6b2"
|
||||||
|
integrity sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==
|
||||||
|
|
||||||
ansi-styles@^2.2.1:
|
ansi-styles@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
|
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
|
||||||
|
@ -3972,7 +3977,7 @@ duplexer3@^0.1.4:
|
||||||
resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz"
|
resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz"
|
||||||
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
|
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
|
||||||
|
|
||||||
duplexer@^0.1.1:
|
duplexer@^0.1.1, duplexer@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
|
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
|
||||||
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
|
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
|
||||||
|
@ -4059,6 +4064,11 @@ emoji-regex@^8.0.0:
|
||||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
|
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
|
||||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||||
|
|
||||||
|
emoji-regex@^9.2.2:
|
||||||
|
version "9.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||||
|
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||||
|
|
||||||
emojis-list@^3.0.0:
|
emojis-list@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz"
|
||||||
|
@ -5263,6 +5273,13 @@ gray-matter@^4.0.2:
|
||||||
section-matter "^1.0.0"
|
section-matter "^1.0.0"
|
||||||
strip-bom-string "^1.0.0"
|
strip-bom-string "^1.0.0"
|
||||||
|
|
||||||
|
gzip-size@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
|
||||||
|
integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
|
||||||
|
dependencies:
|
||||||
|
duplexer "^0.1.2"
|
||||||
|
|
||||||
hamljs@^0.6.2:
|
hamljs@^0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.npmjs.org/hamljs/-/hamljs-0.6.2.tgz"
|
resolved "https://registry.npmjs.org/hamljs/-/hamljs-0.6.2.tgz"
|
||||||
|
@ -6054,6 +6071,11 @@ is-fullwidth-code-point@^3.0.0:
|
||||||
resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz"
|
||||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||||
|
|
||||||
|
is-fullwidth-code-point@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
|
||||||
|
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
|
||||||
|
|
||||||
is-glob@^2.0.0:
|
is-glob@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz"
|
||||||
|
@ -10453,6 +10475,15 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
string-width@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.0.0.tgz#19191f152f937b96f4ec54ba0986a5656660c5a2"
|
||||||
|
integrity sha512-zwXcRmLUdiWhMPrHz6EXITuyTgcEnUqDzspTkCLhQovxywWz6NP9VHgqfVg20V/1mUg0B95AKbXxNT+ALRmqCw==
|
||||||
|
dependencies:
|
||||||
|
emoji-regex "^9.2.2"
|
||||||
|
is-fullwidth-code-point "^4.0.0"
|
||||||
|
strip-ansi "^7.0.0"
|
||||||
|
|
||||||
string.prototype.trimend@^1.0.4:
|
string.prototype.trimend@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz"
|
resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz"
|
||||||
|
@ -10521,6 +10552,13 @@ strip-ansi@^6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^5.0.0"
|
ansi-regex "^5.0.0"
|
||||||
|
|
||||||
|
strip-ansi@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.0.tgz#1dc49b980c3a4100366617adac59327eefdefcb0"
|
||||||
|
integrity sha512-UhDTSnGF1dc0DRbUqr1aXwNoY3RgVkSWG8BrpnuFIxhP57IqbS7IRta2Gfiavds4yCxc5+fEAVVOgBZWnYkvzg==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^6.0.0"
|
||||||
|
|
||||||
strip-ansi@~0.1.0:
|
strip-ansi@~0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz"
|
||||||
|
|
Loading…
Reference in a new issue