From 864d7a0bfd3e17616b64efb832ffbbcfc42c5325 Mon Sep 17 00:00:00 2001 From: eupthere Date: Sun, 12 Apr 2026 04:59:37 +0900 Subject: [PATCH] chore: replace `picocolors` with builtins (#2210) Co-authored-by: Aaron --- packages/wxt/package.json | 1 - packages/wxt/src/core/clean.ts | 15 +++++-- packages/wxt/src/core/create-server.ts | 10 ++--- packages/wxt/src/core/initialize.ts | 42 +++++++++++-------- packages/wxt/src/core/keyboard-shortcuts.ts | 4 +- .../core/utils/building/build-entrypoints.ts | 8 ++-- .../core/utils/building/find-entrypoints.ts | 4 +- .../src/core/utils/building/internal-build.ts | 25 +++++++---- .../wxt/src/core/utils/log/printFileList.ts | 37 ++++++++-------- .../wxt/src/core/utils/log/printHeader.ts | 6 ++- packages/wxt/src/core/utils/syntax-errors.ts | 4 +- packages/wxt/src/utils/text-style.ts | 3 ++ pnpm-lock.yaml | 3 -- 13 files changed, 95 insertions(+), 67 deletions(-) create mode 100644 packages/wxt/src/utils/text-style.ts diff --git a/packages/wxt/package.json b/packages/wxt/package.json index c327ddc0..d5e8011e 100644 --- a/packages/wxt/package.json +++ b/packages/wxt/package.json @@ -49,7 +49,6 @@ "ohash": "^2.0.11", "open": "^11.0.0", "perfect-debounce": "^2.1.0", - "picocolors": "^1.1.1", "picomatch": "^4.0.3", "prompts": "^2.4.2", "publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.4", diff --git a/packages/wxt/src/core/clean.ts b/packages/wxt/src/core/clean.ts index 46cee527..a9c27a7d 100644 --- a/packages/wxt/src/core/clean.ts +++ b/packages/wxt/src/core/clean.ts @@ -1,9 +1,9 @@ import { rm } from 'node:fs/promises'; import path from 'node:path'; -import pc from 'picocolors'; import { glob } from 'tinyglobby'; import { InlineConfig } from '../types'; import { registerWxt, wxt } from './wxt'; +import { styleText } from 'node:util'; /** * Remove generated/temp files from the directory. @@ -42,7 +42,10 @@ export async function clean(config?: string | InlineConfig) { '**/.wxt', `${path.relative(root, wxt.config.outBaseDir)}/*`, ]; - wxt.logger.debug('Looking for:', tempDirs.map(pc.cyan).join(', ')); + wxt.logger.debug( + 'Looking for:', + tempDirs.map((dir) => styleText('cyan', dir)).join(', '), + ); const directories = await glob(tempDirs, { cwd: root, absolute: true, @@ -57,10 +60,14 @@ export async function clean(config?: string | InlineConfig) { wxt.logger.debug( 'Found:', - directories.map((dir) => pc.cyan(path.relative(root, dir))).join(', '), + directories + .map((dir) => styleText('cyan', path.relative(root, dir))) + .join(', '), ); for (const directory of directories) { await rm(directory, { force: true, recursive: true }); - wxt.logger.debug('Deleted ' + pc.cyan(path.relative(root, directory))); + wxt.logger.debug( + 'Deleted ' + styleText('cyan', path.relative(root, directory)), + ); } } diff --git a/packages/wxt/src/core/create-server.ts b/packages/wxt/src/core/create-server.ts index 44c17cb4..8cebff66 100644 --- a/packages/wxt/src/core/create-server.ts +++ b/packages/wxt/src/core/create-server.ts @@ -20,7 +20,6 @@ import { } from './utils/building'; import { createExtensionRunner } from './runners'; import { Mutex } from 'async-mutex'; -import pc from 'picocolors'; import { relative } from 'node:path'; import { deinitWxtModules, initWxtModules, registerWxt, wxt } from './wxt'; import { unnormalizePath } from './utils/paths'; @@ -30,6 +29,7 @@ import { } from './utils/content-scripts'; import { createKeyboardShortcuts } from './keyboard-shortcuts'; import { isBabelSyntaxError, logBabelSyntaxError } from './utils/syntax-errors'; +import { styleText } from 'node:util'; /** * Creates a dev server and pre-builds all the files that need to exist before @@ -238,7 +238,7 @@ function createFileReloader(server: WxtDevServer) { // Log the entrypoints that were effected wxt.logger.info( `Changed: ${Array.from(new Set(fileChanges)) - .map((file) => pc.dim(relative(wxt.config.root, file))) + .map((file) => styleText('dim', relative(wxt.config.root, file))) .join(', ')}`, ); @@ -344,10 +344,8 @@ function reloadHtmlPages( function getFilenameList(names: string[]): string { return names - .map((name) => { - return pc.cyan(name); - }) - .join(pc.dim(', ')); + .map((name) => styleText('cyan', name)) + .join(styleText('dim', ', ')); } /** diff --git a/packages/wxt/src/core/initialize.ts b/packages/wxt/src/core/initialize.ts index f9a64efb..f52829ec 100644 --- a/packages/wxt/src/core/initialize.ts +++ b/packages/wxt/src/core/initialize.ts @@ -4,8 +4,8 @@ import { downloadTemplate } from 'giget'; import { readdir, rename } from 'node:fs/promises'; import { pathExists } from './utils/fs'; import path from 'node:path'; -import pc from 'picocolors'; -import { Formatter } from 'picocolors/types'; +import { styleText } from 'node:util'; +import { TextStyle } from '../utils/text-style'; export async function initialize(options: { directory: string; @@ -32,8 +32,9 @@ export async function initialize(options: { type: () => (defaultTemplate == null ? 'select' : undefined), message: 'Choose a template', choices: templates.map((template) => ({ - title: - TEMPLATE_COLORS[template.name]?.(template.name) ?? template.name, + title: TEMPLATE_COLORS[template.name] + ? styleText(TEMPLATE_COLORS[template.name], template.name) + : template.name, value: template, })), }, @@ -42,10 +43,10 @@ export async function initialize(options: { type: () => (options.packageManager == null ? 'select' : undefined), message: 'Package Manager', choices: [ - { title: pc.red('npm'), value: 'npm' }, - { title: pc.yellow('pnpm'), value: 'pnpm' }, - { title: pc.cyan('yarn'), value: 'yarn' }, - { title: pc.magenta('bun'), value: 'bun' }, + { title: styleText('red', 'npm'), value: 'npm' }, + { title: styleText('yellow', 'pnpm'), value: 'pnpm' }, + { title: styleText('cyan', 'yarn'), value: 'yarn' }, + { title: styleText('magenta', 'bun'), value: 'bun' }, ], }, ], @@ -75,15 +76,20 @@ export async function initialize(options: { console.log(); consola.log( `✨ WXT project created with the ${ - TEMPLATE_COLORS[input.template.name]?.(input.template.name) ?? - input.template.name + TEMPLATE_COLORS[input.template.name] + ? styleText(TEMPLATE_COLORS[input.template.name], input.template.name) + : input.template.name } template.`, ); console.log(); consola.log('Next steps:'); let step = 0; - if (cdPath !== '') consola.log(` ${++step}.`, pc.cyan(`cd ${cdPath}`)); - consola.log(` ${++step}.`, pc.cyan(`${input.packageManager} install`)); + if (cdPath !== '') + consola.log(` ${++step}.`, styleText('cyan', `cd ${cdPath}`)); + consola.log( + ` ${++step}.`, + styleText('cyan', `${input.packageManager} install`), + ); console.log(); } @@ -182,12 +188,12 @@ async function cloneProject({ } } -const TEMPLATE_COLORS: Record = { - vanilla: pc.blue, - vue: pc.green, - react: pc.cyan, - svelte: pc.red, - solid: pc.blue, +const TEMPLATE_COLORS: Record = { + vanilla: 'blue', + vue: 'green', + react: 'cyan', + svelte: 'red', + solid: 'blue', }; const TEMPLATE_SORT_WEIGHT: Record = { diff --git a/packages/wxt/src/core/keyboard-shortcuts.ts b/packages/wxt/src/core/keyboard-shortcuts.ts index c3de02e3..19bf4719 100644 --- a/packages/wxt/src/core/keyboard-shortcuts.ts +++ b/packages/wxt/src/core/keyboard-shortcuts.ts @@ -1,7 +1,7 @@ import readline from 'node:readline'; import { WxtDevServer } from '../types'; import { wxt } from './wxt'; -import pc from 'picocolors'; +import { styleText } from 'node:util'; export interface KeyboardShortcutWatcher { start(): void; @@ -41,7 +41,7 @@ export function createKeyboardShortcuts( printHelp(flags) { if (flags.canReopenBrowser) { wxt.logger.info( - `${pc.dim('Press')} ${pc.bold('o + enter')} ${pc.dim('to reopen the browser')}`, + `${styleText('dim', 'Press')} ${styleText('bold', 'o + enter')} ${styleText('dim', 'to reopen the browser')}`, ); } }, diff --git a/packages/wxt/src/core/utils/building/build-entrypoints.ts b/packages/wxt/src/core/utils/building/build-entrypoints.ts index 5bc89840..9a589fe0 100644 --- a/packages/wxt/src/core/utils/building/build-entrypoints.ts +++ b/packages/wxt/src/core/utils/building/build-entrypoints.ts @@ -8,9 +8,9 @@ import { getPublicFiles } from '../fs'; import { copyFile, mkdir, writeFile } from 'node:fs/promises'; import { dirname, resolve } from 'path'; import type { Spinner } from 'nanospinner'; -import pc from 'picocolors'; import { wxt } from '../../wxt'; import { toArray } from '../arrays'; +import { styleText } from 'node:util'; export async function buildEntrypoints( groups: EntrypointGroup[], @@ -20,9 +20,11 @@ export async function buildEntrypoints( for (let i = 0; i < groups.length; i++) { const group = groups[i]; const groupNames = toArray(group).map((e) => e.name); - const groupNameColored = groupNames.join(pc.dim(', ')); + const groupNameColored = groupNames.join(styleText('dim', ', ')); spinner.update({ - text: pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`, + text: + styleText('dim', `[${i + 1}/${groups.length}]`) + + ` ${groupNameColored}`, }); try { steps.push(await wxt.builder.build(group)); diff --git a/packages/wxt/src/core/utils/building/find-entrypoints.ts b/packages/wxt/src/core/utils/building/find-entrypoints.ts index f27cc4dc..8900e8db 100644 --- a/packages/wxt/src/core/utils/building/find-entrypoints.ts +++ b/packages/wxt/src/core/utils/building/find-entrypoints.ts @@ -25,9 +25,9 @@ import { } from '../entrypoints'; import { VIRTUAL_NOOP_BACKGROUND_MODULE_ID } from '../constants'; import { CSS_EXTENSIONS_PATTERN } from '../paths'; -import pc from 'picocolors'; import { wxt } from '../../wxt'; import { camelCase } from 'scule'; +import { styleText } from 'node:util'; /** * Return entrypoints and their configuration by looking through the project's @@ -161,7 +161,7 @@ export async function findEntrypoints(): Promise { [ 'The following entrypoints have been skipped:', ...skippedEntrypointNames.map( - (item) => `${pc.dim('-')} ${pc.cyan(item)}`, + (item) => `${styleText('dim', '-')} ${styleText('cyan', item)}`, ), ].join('\n'), ); diff --git a/packages/wxt/src/core/utils/building/internal-build.ts b/packages/wxt/src/core/utils/building/internal-build.ts index 20bc6616..c0d889e1 100644 --- a/packages/wxt/src/core/utils/building/internal-build.ts +++ b/packages/wxt/src/core/utils/building/internal-build.ts @@ -1,6 +1,5 @@ import { findEntrypoints } from './find-entrypoints'; import { BuildOutput, Entrypoint } from '../../../types'; -import pc from 'picocolors'; import { mkdir, rm } from 'node:fs/promises'; import { groupEntrypoints } from './group-entrypoints'; import { formatDuration } from '../time'; @@ -18,6 +17,7 @@ import { import { wxt } from '../../wxt'; import { mergeJsonOutputs } from '@aklinker1/rollup-plugin-visualizer'; import { isCI } from 'ci-info'; +import { styleText } from 'node:util'; /** * Builds the extension based on an internal config. No more config discovery is @@ -36,7 +36,8 @@ export async function internalBuild(): Promise { const verb = wxt.config.command === 'serve' ? 'Pre-rendering' : 'Building'; const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`; wxt.logger.info( - `${verb} ${pc.cyan(target)} for ${pc.cyan(wxt.config.mode)} with ${pc.green( + `${verb} ${styleText('cyan', target)} for ${styleText('cyan', wxt.config.mode)} with ${styleText( + 'green', `${wxt.builder.name} ${wxt.builder.version}`, )}`, ); @@ -80,13 +81,17 @@ export async function internalBuild(): Promise { await combineAnalysisStats(); const statsPath = relative(wxt.config.root, wxt.config.analysis.outputFile); wxt.logger.info( - `Analysis complete:\n ${pc.gray('└─')} ${pc.yellow(statsPath)}`, + `Analysis complete:\n ${styleText('gray', '└─')} ${styleText('yellow', statsPath)}`, ); if (wxt.config.analysis.open) { if (isCI) { - wxt.logger.debug(`Skipped opening ${pc.yellow(statsPath)} in CI`); + wxt.logger.debug( + `Skipped opening ${styleText('yellow', statsPath)} in CI`, + ); } else { - wxt.logger.info(`Opening ${pc.yellow(statsPath)} in browser...`); + wxt.logger.info( + `Opening ${styleText('yellow', statsPath)} in browser...`, + ); const { default: open } = await import('open'); await open(wxt.config.analysis.outputFile); } @@ -140,8 +145,14 @@ function printValidationResults({ wxt.logger.log(relative(cwd, entrypoint.inputPath) + '\n'); errors.forEach((err) => { - const type = err.type === 'error' ? pc.red('ERROR') : pc.yellow('WARN'); - const received = pc.dim(`(received: ${JSON.stringify(err.value)})`); + const type = + err.type === 'error' + ? styleText('red', 'ERROR') + : styleText('yellow', 'WARN'); + const received = styleText( + 'dim', + `(received: ${JSON.stringify(err.value)})`, + ); wxt.logger.log(` - ${type} ${err.message} ${received}`); }); console.log(); diff --git a/packages/wxt/src/core/utils/log/printFileList.ts b/packages/wxt/src/core/utils/log/printFileList.ts index 8efa28f3..ab25d67a 100644 --- a/packages/wxt/src/core/utils/log/printFileList.ts +++ b/packages/wxt/src/core/utils/log/printFileList.ts @@ -1,8 +1,9 @@ import path from 'node:path'; -import pc from 'picocolors'; import { lstat } from 'node:fs/promises'; import { filesize } from 'filesize'; import { printTable } from './printTable'; +import { styleText } from 'node:util'; +import { TextStyle } from '../../../utils/text-style'; export async function printFileList( log: (message: string) => void, @@ -19,35 +20,37 @@ export async function printFileList( path.relative(baseDir, file), ]; const prefix = i === files.length - 1 ? ' └─' : ' ├─'; - const color = getChunkColor(file); + const chunkColor = getChunkColor(file); const stats = await lstat(file); totalSize += stats.size; const size = String(filesize(stats.size)); return [ - `${pc.gray(prefix)} ${pc.dim(parts[0])}${color(parts[1])}`, - pc.dim(size), + `${styleText('gray', prefix)} ${styleText('dim', parts[0])}${styleText(chunkColor, parts[1])}`, + styleText('dim', size), ]; }), ); - fileRows.push([`${pc.cyan('Σ Total size:')} ${String(filesize(totalSize))}`]); + fileRows.push([ + `${styleText('cyan', 'Σ Total size:')} ${String(filesize(totalSize))}`, + ]); printTable(log, header, fileRows); } -const DEFAULT_COLOR = pc.blue; -const CHUNK_COLORS: Record string> = { - '.js.map': pc.gray, - '.cjs.map': pc.gray, - '.mjs.map': pc.gray, - '.html': pc.green, - '.css': pc.magenta, - '.js': pc.cyan, - '.cjs': pc.cyan, - '.mjs': pc.cyan, - '.zip': pc.yellow, +const DEFAULT_COLOR: TextStyle = 'blue'; +const CHUNK_COLORS: Record = { + '.js.map': 'gray', + '.cjs.map': 'gray', + '.mjs.map': 'gray', + '.html': 'green', + '.css': 'magenta', + '.js': 'cyan', + '.cjs': 'cyan', + '.mjs': 'cyan', + '.zip': 'yellow', }; -function getChunkColor(filename: string) { +function getChunkColor(filename: string): TextStyle { return ( Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR diff --git a/packages/wxt/src/core/utils/log/printHeader.ts b/packages/wxt/src/core/utils/log/printHeader.ts index 09bbc76a..5a9f5352 100644 --- a/packages/wxt/src/core/utils/log/printHeader.ts +++ b/packages/wxt/src/core/utils/log/printHeader.ts @@ -1,7 +1,9 @@ -import pc from 'picocolors'; import { version } from '../../../version'; import { consola } from 'consola'; +import { styleText } from 'node:util'; export function printHeader() { - consola.log(`\n${pc.gray('WXT')} ${pc.gray(pc.bold(version))}`); + consola.log( + `\n${styleText('gray', 'WXT')} ${styleText(['bold', 'grey'], version)}`, + ); } diff --git a/packages/wxt/src/core/utils/syntax-errors.ts b/packages/wxt/src/core/utils/syntax-errors.ts index d0aef21a..683f00b4 100644 --- a/packages/wxt/src/core/utils/syntax-errors.ts +++ b/packages/wxt/src/core/utils/syntax-errors.ts @@ -1,6 +1,6 @@ import { relative } from 'node:path'; -import pc from 'picocolors'; import { wxt } from '../wxt'; +import { styleText } from 'node:util'; export interface BabelSyntaxError extends SyntaxError { code: 'BABEL_PARSER_SYNTAX_ERROR'; @@ -26,7 +26,7 @@ export function logBabelSyntaxError(error: BabelSyntaxError) { `(${filename}:${error.loc.line}:${error.loc.column + 1})`, ); if (error.frame) { - message += '\n\n' + pc.red(error.frame); + message += '\n\n' + styleText('red', error.frame); } wxt.logger.error(message); } diff --git a/packages/wxt/src/utils/text-style.ts b/packages/wxt/src/utils/text-style.ts new file mode 100644 index 00000000..7dbb9cc2 --- /dev/null +++ b/packages/wxt/src/utils/text-style.ts @@ -0,0 +1,3 @@ +import { styleText } from 'node:util'; + +export type TextStyle = Parameters[0]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8867ef66..001fadc4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -516,9 +516,6 @@ importers: perfect-debounce: specifier: ^2.1.0 version: 2.1.0 - picocolors: - specifier: ^1.1.1 - version: 1.1.1 picomatch: specifier: ^4.0.3 version: 4.0.3