From 331f6943116f98fb7033a20f52882db26fec5c00 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 19 Nov 2024 11:41:50 +0100 Subject: [PATCH 1/5] pretty print the error Instead of logging the full error when trying to resolve imports, just log the error message and where it's being imported. --- packages/@tailwindcss-upgrade/src/migrate.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/migrate.ts b/packages/@tailwindcss-upgrade/src/migrate.ts index a3f2e344adda..f34725d6cabe 100644 --- a/packages/@tailwindcss-upgrade/src/migrate.ts +++ b/packages/@tailwindcss-upgrade/src/migrate.ts @@ -120,8 +120,9 @@ export async function analyze(stylesheets: Stylesheet[]) { resolvedPath = resolveCssId(id, basePath) } } catch (err) { - console.warn(`Failed to resolve import: ${id}. Skipping.`) - console.error(err) + error( + `Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`, + ) return } @@ -334,10 +335,12 @@ export async function analyze(stylesheets: Stylesheet[]) { } } - let error = `You have one or more stylesheets that are imported into a utility layer and non-utility layer.\n` - error += `We cannot convert stylesheets under these conditions. Please look at the following stylesheets:\n` + { + let error = `You have one or more stylesheets that are imported into a utility layer and non-utility layer.\n` + error += `We cannot convert stylesheets under these conditions. Please look at the following stylesheets:\n` - throw new Error(error + lines.join('\n')) + throw new Error(error + lines.join('\n')) + } } export async function linkConfigs( From c2e5ed42a750017d3176ac91442375565cded515 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 19 Nov 2024 11:53:22 +0100 Subject: [PATCH 2/5] render headers conditionally --- packages/@tailwindcss-upgrade/src/index.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/index.ts b/packages/@tailwindcss-upgrade/src/index.ts index 3f57ef1987b1..e638b83870f2 100644 --- a/packages/@tailwindcss-upgrade/src/index.ts +++ b/packages/@tailwindcss-upgrade/src/index.ts @@ -110,7 +110,9 @@ async function run() { } // Migrate js config files, linked to stylesheets - info('Migrating JavaScript configuration files…') + if (stylesheets.some((sheet) => sheet.isTailwindRoot)) { + info('Migrating JavaScript configuration files…') + } let configBySheet = new Map>>() let jsConfigMigrationBySheet = new Map< Stylesheet, @@ -142,7 +144,9 @@ async function run() { } // Migrate source files, linked to config files - info('Migrating templates…') + if (configBySheet.size > 0) { + info('Migrating templates…') + } { // Template migrations for (let config of configBySheet.values()) { @@ -174,7 +178,9 @@ async function run() { } // Migrate each CSS file - info('Migrating stylesheets…') + if (stylesheets.length > 0) { + info('Migrating stylesheets…') + } let migrateResults = await Promise.allSettled( stylesheets.map((sheet) => { let config = configBySheet.get(sheet)! From 715fe76ab42d217a9d4142b6740d3a680499d644 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 19 Nov 2024 11:53:53 +0100 Subject: [PATCH 3/5] render errors during migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving the `error(…)` logic to where we are migrating the stylesheet allows us to use the `sheet` available in the current scope to improve the error messages. --- packages/@tailwindcss-upgrade/src/index.ts | 36 ++++++++++------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/index.ts b/packages/@tailwindcss-upgrade/src/index.ts index e638b83870f2..883d6997676b 100644 --- a/packages/@tailwindcss-upgrade/src/index.ts +++ b/packages/@tailwindcss-upgrade/src/index.ts @@ -181,31 +181,29 @@ async function run() { if (stylesheets.length > 0) { info('Migrating stylesheets…') } - let migrateResults = await Promise.allSettled( - stylesheets.map((sheet) => { - let config = configBySheet.get(sheet)! - let jsConfigMigration = jsConfigMigrationBySheet.get(sheet)! - - if (!config) { - for (let parent of sheet.ancestors()) { - if (parent.isTailwindRoot) { - config ??= configBySheet.get(parent)! - jsConfigMigration ??= jsConfigMigrationBySheet.get(parent)! - break + await Promise.all( + stylesheets.map(async (sheet) => { + try { + let config = configBySheet.get(sheet)! + let jsConfigMigration = jsConfigMigrationBySheet.get(sheet)! + + if (!config) { + for (let parent of sheet.ancestors()) { + if (parent.isTailwindRoot) { + config ??= configBySheet.get(parent)! + jsConfigMigration ??= jsConfigMigrationBySheet.get(parent)! + break + } } } - } - return migrateStylesheet(sheet, { ...config, jsConfigMigration }) + await migrateStylesheet(sheet, { ...config, jsConfigMigration }) + } catch (e: any) { + error(`${e} in ${highlight(relative(sheet.file!, base))}`) + } }), ) - for (let result of migrateResults) { - if (result.status === 'rejected') { - error(`${result.reason}`) - } - } - // Split up stylesheets (as needed) try { await splitStylesheets(stylesheets) From 86681f5275c2c267288f45fab59d5af7b3de2624 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 19 Nov 2024 11:55:07 +0100 Subject: [PATCH 4/5] improve error messages --- packages/@tailwindcss-upgrade/src/index.ts | 16 ++++++++-------- packages/@tailwindcss-upgrade/src/migrate.ts | 8 ++++---- .../src/template/prepare-config.ts | 2 +- .../src/utils/extract-static-plugins.ts | 4 ++-- packages/tailwindcss/src/at-import.ts | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/index.ts b/packages/@tailwindcss-upgrade/src/index.ts index 883d6997676b..c00976866d9d 100644 --- a/packages/@tailwindcss-upgrade/src/index.ts +++ b/packages/@tailwindcss-upgrade/src/index.ts @@ -84,7 +84,7 @@ async function run() { // Load and parse all stylesheets for (let result of loadResults) { if (result.status === 'rejected') { - error(`${result.reason}`) + error(`↳ ${result.reason?.message ?? result.reason}`) } } @@ -95,8 +95,8 @@ async function run() { // Analyze the stylesheets try { await analyzeStylesheets(stylesheets) - } catch (e: unknown) { - error(`${e}`) + } catch (e: any) { + error(`↳ ${e?.message ?? e}`) } // Ensure stylesheets are linked to configs @@ -105,8 +105,8 @@ async function run() { configPath: flags['--config'], base, }) - } catch (e: unknown) { - error(`${e}`) + } catch (e: any) { + error(`↳ ${e?.message ?? e}`) } // Migrate js config files, linked to stylesheets @@ -199,7 +199,7 @@ async function run() { await migrateStylesheet(sheet, { ...config, jsConfigMigration }) } catch (e: any) { - error(`${e} in ${highlight(relative(sheet.file!, base))}`) + error(`↳ ${e?.message ?? e} in ${highlight(relative(sheet.file!, base))}`) } }), ) @@ -207,8 +207,8 @@ async function run() { // Split up stylesheets (as needed) try { await splitStylesheets(stylesheets) - } catch (e: unknown) { - error(`${e}`) + } catch (e: any) { + error(`↳ ${e?.message ?? e}`) } // Cleanup `@import "…" layer(utilities)` diff --git a/packages/@tailwindcss-upgrade/src/migrate.ts b/packages/@tailwindcss-upgrade/src/migrate.ts index f34725d6cabe..20459d11e09b 100644 --- a/packages/@tailwindcss-upgrade/src/migrate.ts +++ b/packages/@tailwindcss-upgrade/src/migrate.ts @@ -121,7 +121,7 @@ export async function analyze(stylesheets: Stylesheet[]) { } } catch (err) { error( - `Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`, + `↳ Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`, ) return } @@ -350,7 +350,7 @@ export async function linkConfigs( let rootStylesheets = stylesheets.filter((sheet) => sheet.isTailwindRoot) if (rootStylesheets.length === 0) { throw new Error( - 'Cannot find any CSS files that reference Tailwind CSS.\nBefore your project can be upgraded you need to create a CSS file that imports Tailwind CSS or uses `@tailwind`.', + `Cannot find any CSS files that reference Tailwind CSS.\nBefore your project can be upgraded you need to create a CSS file that imports Tailwind CSS or uses ${highlight('@tailwind')}.`, ) } let withoutAtConfig = rootStylesheets.filter((sheet) => { @@ -398,7 +398,7 @@ export async function linkConfigs( if (problematicStylesheets.size > 1) { for (let sheet of problematicStylesheets) { error( - `Could not determine configuration file for: ${highlight(relative(sheet.file!, base))}\nUpdate your stylesheet to use ${highlight('@config')} to specify the correct configuration file explicitly and then run the upgrade tool again.`, + `↳ Could not determine configuration file for: ${highlight(relative(sheet.file!, base))}\n↳Update your stylesheet to use ${highlight('@config')} to specify the correct configuration file explicitly and then run the upgrade tool again.`, ) } @@ -450,7 +450,7 @@ export async function linkConfigs( } } } catch (e: any) { - error('Could not load the configuration file: ' + e.message) + error('↳ Could not load the configuration file: ' + e.message) process.exit(1) } } diff --git a/packages/@tailwindcss-upgrade/src/template/prepare-config.ts b/packages/@tailwindcss-upgrade/src/template/prepare-config.ts index a151b6ab46c5..8a0629588e73 100644 --- a/packages/@tailwindcss-upgrade/src/template/prepare-config.ts +++ b/packages/@tailwindcss-upgrade/src/template/prepare-config.ts @@ -65,7 +65,7 @@ export async function prepareConfig( configFilePath, } } catch (e: any) { - error('Could not load the configuration file: ' + e.message) + error('↳ Could not load the configuration file: ' + e.message) process.exit(1) } } diff --git a/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts b/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts index d0f6dbf8e2f4..93b496ea2889 100644 --- a/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts +++ b/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts @@ -272,8 +272,8 @@ export function findStaticPlugins(source: string): [string, null | StaticPluginO } } return plugins - } catch (error) { - console.error(error) + } catch (error: any) { + error(`↳ ${error?.message ?? error}`) return null } } diff --git a/packages/tailwindcss/src/at-import.ts b/packages/tailwindcss/src/at-import.ts index e5b937c71c3b..8066abd98ff9 100644 --- a/packages/tailwindcss/src/at-import.ts +++ b/packages/tailwindcss/src/at-import.ts @@ -85,7 +85,7 @@ export function parseImportParams(params: ValueParser.ValueAstNode[]) { } if (node.kind === 'function' && node.value.toLowerCase() === 'url') { - throw new Error('url functions are not supported') + throw new Error('`url(…)` functions are not supported') } if (!uri) throw new Error('Unable to find uri') @@ -95,7 +95,7 @@ export function parseImportParams(params: ValueParser.ValueAstNode[]) { node.value.toLowerCase() === 'layer' ) { if (layer) throw new Error('Multiple layers') - if (supports) throw new Error('layers must be defined before support conditions') + if (supports) throw new Error('`layer(…)` must be defined before `supports(…)` conditions') if ('nodes' in node) { layer = ValueParser.toCss(node.nodes) From e0cdfa9e1c1eb81d9ac44e148e45bd4c5ba10a49 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 19 Nov 2024 13:07:24 +0100 Subject: [PATCH 5/5] pretty print prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are printing a message with some prefix, then we do want to add the prefix to the first line, and indent the subsequent lines (in case we need to wrap) with the same width as the prefix. This means that if we had an error message that looked like this: ``` │ ↳ Cannot find any CSS files that reference Tailwind CSS. │ Before your project can be upgraded you need to create a CSS file that imports Tailwind CSS │ or uses `@tailwind`. ``` Now prints as: ``` │ ↳ Cannot find any CSS files that reference Tailwind CSS. │ Before your project can be upgraded you need to create a CSS file that imports Tailwind CSS │ or uses `@tailwind`. ``` --- packages/@tailwindcss-upgrade/src/index.ts | 20 +++++----- .../src/migrate-js-config.ts | 3 +- .../src/migrate-postcss.ts | 8 ++-- .../src/migrate-prettier.ts | 2 +- packages/@tailwindcss-upgrade/src/migrate.ts | 11 +++-- .../src/template/prepare-config.ts | 2 +- .../src/utils/extract-static-plugins.ts | 2 +- .../src/utils/renderer.ts | 40 ++++++++++--------- 8 files changed, 50 insertions(+), 38 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/index.ts b/packages/@tailwindcss-upgrade/src/index.ts index c00976866d9d..15d11b733d93 100644 --- a/packages/@tailwindcss-upgrade/src/index.ts +++ b/packages/@tailwindcss-upgrade/src/index.ts @@ -84,7 +84,7 @@ async function run() { // Load and parse all stylesheets for (let result of loadResults) { if (result.status === 'rejected') { - error(`↳ ${result.reason?.message ?? result.reason}`) + error(`${result.reason?.message ?? result.reason}`, { prefix: '↳ ' }) } } @@ -96,7 +96,7 @@ async function run() { try { await analyzeStylesheets(stylesheets) } catch (e: any) { - error(`↳ ${e?.message ?? e}`) + error(`${e?.message ?? e}`, { prefix: '↳ ' }) } // Ensure stylesheets are linked to configs @@ -106,7 +106,7 @@ async function run() { base, }) } catch (e: any) { - error(`↳ ${e?.message ?? e}`) + error(`${e?.message ?? e}`, { prefix: '↳ ' }) } // Migrate js config files, linked to stylesheets @@ -138,7 +138,8 @@ async function run() { if (jsConfigMigration !== null) { success( - `↳ Migrated configuration file: ${highlight(relative(config.configFilePath, base))}`, + `Migrated configuration file: ${highlight(relative(config.configFilePath, base))}`, + { prefix: '↳ ' }, ) } } @@ -172,7 +173,8 @@ async function run() { ) success( - `↳ Migrated templates for configuration file: ${highlight(relative(config.configFilePath, base))}`, + `Migrated templates for configuration file: ${highlight(relative(config.configFilePath, base))}`, + { prefix: '↳ ' }, ) } } @@ -199,7 +201,7 @@ async function run() { await migrateStylesheet(sheet, { ...config, jsConfigMigration }) } catch (e: any) { - error(`↳ ${e?.message ?? e} in ${highlight(relative(sheet.file!, base))}`) + error(`${e?.message ?? e} in ${highlight(relative(sheet.file!, base))}`, { prefix: '↳ ' }) } }), ) @@ -208,7 +210,7 @@ async function run() { try { await splitStylesheets(stylesheets) } catch (e: any) { - error(`↳ ${e?.message ?? e}`) + error(`${e?.message ?? e}`, { prefix: '↳ ' }) } // Cleanup `@import "…" layer(utilities)` @@ -245,7 +247,7 @@ async function run() { await fs.writeFile(sheet.file, sheet.root.toString()) if (sheet.isTailwindRoot) { - success(`↳ Migrated stylesheet: ${highlight(relative(sheet.file, base))}`) + success(`Migrated stylesheet: ${highlight(relative(sheet.file, base))}`, { prefix: '↳ ' }) } } } @@ -264,7 +266,7 @@ async function run() { try { // Upgrade Tailwind CSS await pkg(base).add(['tailwindcss@next']) - success(`↳ Updated package: ${highlight('tailwindcss')}`) + success(`Updated package: ${highlight('tailwindcss')}`, { prefix: '↳ ' }) } catch {} // Run all cleanup functions because we completed the migration diff --git a/packages/@tailwindcss-upgrade/src/migrate-js-config.ts b/packages/@tailwindcss-upgrade/src/migrate-js-config.ts index b69379df1f7d..e17bf9601c75 100644 --- a/packages/@tailwindcss-upgrade/src/migrate-js-config.ts +++ b/packages/@tailwindcss-upgrade/src/migrate-js-config.ts @@ -44,7 +44,8 @@ export async function migrateJsConfig( if (!canMigrateConfig(unresolvedConfig, source)) { info( - `↳ The configuration file at ${highlight(relative(fullConfigPath, base))} could not be automatically migrated to the new CSS configuration format, so your CSS has been updated to load your existing configuration file.`, + `The configuration file at ${highlight(relative(fullConfigPath, base))} could not be automatically migrated to the new CSS configuration format, so your CSS has been updated to load your existing configuration file.`, + { prefix: '↳ ' }, ) return null } diff --git a/packages/@tailwindcss-upgrade/src/migrate-postcss.ts b/packages/@tailwindcss-upgrade/src/migrate-postcss.ts index 1bfb2caa80f1..286884522bdd 100644 --- a/packages/@tailwindcss-upgrade/src/migrate-postcss.ts +++ b/packages/@tailwindcss-upgrade/src/migrate-postcss.ts @@ -92,7 +92,7 @@ export async function migratePostCSSConfig(base: string) { if (location !== null) { try { await pkg(base).add(['@tailwindcss/postcss@next'], location) - success(`↳ Installed package: ${highlight('@tailwindcss/postcss')}`) + success(`Installed package: ${highlight('@tailwindcss/postcss')}`, { prefix: '↳ ' }) } catch {} } } @@ -104,13 +104,15 @@ export async function migratePostCSSConfig(base: string) { ].filter(Boolean) as string[] await pkg(base).remove(packagesToRemove) for (let pkg of packagesToRemove) { - success(`↳ Removed package: ${highlight(pkg)}`) + success(`Removed package: ${highlight(pkg)}`, { prefix: '↳ ' }) } } catch {} } if (didMigrate && jsConfigPath) { - success(`↳ Migrated PostCSS configuration: ${highlight(relative(jsConfigPath, base))}`) + success(`Migrated PostCSS configuration: ${highlight(relative(jsConfigPath, base))}`, { + prefix: '↳ ', + }) } } diff --git a/packages/@tailwindcss-upgrade/src/migrate-prettier.ts b/packages/@tailwindcss-upgrade/src/migrate-prettier.ts index 7edf34f47a36..cd56cc6880e1 100644 --- a/packages/@tailwindcss-upgrade/src/migrate-prettier.ts +++ b/packages/@tailwindcss-upgrade/src/migrate-prettier.ts @@ -9,7 +9,7 @@ export async function migratePrettierPlugin(base: string) { let packageJson = await fs.readFile(packageJsonPath, 'utf-8') if (packageJson.includes('prettier-plugin-tailwindcss')) { await pkg(base).add(['prettier-plugin-tailwindcss@latest']) - success(`↳ Updated package: ${highlight('prettier-plugin-tailwindcss')}`) + success(`Updated package: ${highlight('prettier-plugin-tailwindcss')}`, { prefix: '↳ ' }) } } catch {} } diff --git a/packages/@tailwindcss-upgrade/src/migrate.ts b/packages/@tailwindcss-upgrade/src/migrate.ts index 20459d11e09b..932a0a726b22 100644 --- a/packages/@tailwindcss-upgrade/src/migrate.ts +++ b/packages/@tailwindcss-upgrade/src/migrate.ts @@ -121,7 +121,8 @@ export async function analyze(stylesheets: Stylesheet[]) { } } catch (err) { error( - `↳ Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`, + `Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`, + { prefix: '↳ ' }, ) return } @@ -398,7 +399,8 @@ export async function linkConfigs( if (problematicStylesheets.size > 1) { for (let sheet of problematicStylesheets) { error( - `↳ Could not determine configuration file for: ${highlight(relative(sheet.file!, base))}\n↳Update your stylesheet to use ${highlight('@config')} to specify the correct configuration file explicitly and then run the upgrade tool again.`, + `Could not determine configuration file for: ${highlight(relative(sheet.file!, base))}\nUpdate your stylesheet to use ${highlight('@config')} to specify the correct configuration file explicitly and then run the upgrade tool again.`, + { prefix: '↳ ' }, ) } @@ -410,7 +412,8 @@ export async function linkConfigs( try { if (!sheet || !sheet.file) return success( - `↳ Linked ${highlight(relativePath(configPath, base))} to ${highlight(relativePath(sheet.file, base))}`, + `Linked ${highlight(relativePath(configPath, base))} to ${highlight(relativePath(sheet.file, base))}`, + { prefix: '↳ ' }, ) // Link the `@config` directive to the root stylesheets @@ -450,7 +453,7 @@ export async function linkConfigs( } } } catch (e: any) { - error('↳ Could not load the configuration file: ' + e.message) + error('Could not load the configuration file: ' + e.message, { prefix: '↳ ' }) process.exit(1) } } diff --git a/packages/@tailwindcss-upgrade/src/template/prepare-config.ts b/packages/@tailwindcss-upgrade/src/template/prepare-config.ts index 8a0629588e73..f5a817d40ea3 100644 --- a/packages/@tailwindcss-upgrade/src/template/prepare-config.ts +++ b/packages/@tailwindcss-upgrade/src/template/prepare-config.ts @@ -65,7 +65,7 @@ export async function prepareConfig( configFilePath, } } catch (e: any) { - error('↳ Could not load the configuration file: ' + e.message) + error('Could not load the configuration file: ' + e.message, { prefix: '↳ ' }) process.exit(1) } } diff --git a/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts b/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts index 93b496ea2889..4318c14ef36e 100644 --- a/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts +++ b/packages/@tailwindcss-upgrade/src/utils/extract-static-plugins.ts @@ -273,7 +273,7 @@ export function findStaticPlugins(source: string): [string, null | StaticPluginO } return plugins } catch (error: any) { - error(`↳ ${error?.message ?? error}`) + error(`${error?.message ?? error}`, { prefix: '↳ ' }) return null } } diff --git a/packages/@tailwindcss-upgrade/src/utils/renderer.ts b/packages/@tailwindcss-upgrade/src/utils/renderer.ts index b902fe88d15d..38bd9826a0ab 100644 --- a/packages/@tailwindcss-upgrade/src/utils/renderer.ts +++ b/packages/@tailwindcss-upgrade/src/utils/renderer.ts @@ -89,32 +89,36 @@ export function indent(value: string, offset = 0) { return `${' '.repeat(offset + UI.indent)}${value}` } -export function success(message: string, print = eprintln) { - wordWrap(message, process.stderr.columns - 3).map((line) => { - return print(`${pc.green('\u2502')} ${line}`) +function log(message: string, { art = pc.gray('\u2502'), prefix = '', print = eprintln }) { + let prefixLength = prefix.length + let padding = ' ' + let paddingLength = padding.length + let artLength = stripVTControlCharacters(art).length + let availableWidth = process.stderr.columns + let totalWidth = availableWidth - prefixLength - paddingLength * 2 - artLength + + wordWrap(message, totalWidth).map((line, idx) => { + return print( + `${art}${padding}${idx === 0 ? prefix : ' '.repeat(prefixLength)}${line}${padding}`, + ) }) print() } -export function info(message: string, print = eprintln) { - wordWrap(message, process.stderr.columns - 3).map((line) => { - return print(`${pc.blue('\u2502')} ${line}`) - }) - print() +export function success(message: string, { prefix = '', print = eprintln } = {}) { + log(message, { art: pc.green('\u2502'), prefix, print }) } -export function error(message: string, print = eprintln) { - wordWrap(message, process.stderr.columns - 3).map((line) => { - return print(`${pc.red('\u2502')} ${line}`) - }) - print() +export function info(message: string, { prefix = '', print = eprintln } = {}) { + log(message, { art: pc.blue('\u2502'), prefix, print }) } -export function warn(message: string, print = eprintln) { - wordWrap(message, process.stderr.columns - 3).map((line) => { - return print(`${pc.yellow('\u2502')} ${line}`) - }) - print() +export function error(message: string, { prefix = '', print = eprintln } = {}) { + log(message, { art: pc.red('\u2502'), prefix, print }) +} + +export function warn(message: string, { prefix = '', print = eprintln } = {}) { + log(message, { art: pc.yellow('\u2502'), prefix, print }) } // Rust inspired functions to print to the console: