Skip to content

Commit

Permalink
fix: make all color output use an npm instance of chalk (#6284)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys committed Mar 29, 2023
1 parent a57a97b commit 09b58e4
Show file tree
Hide file tree
Showing 25 changed files with 381 additions and 413 deletions.
2 changes: 1 addition & 1 deletion lib/commands/explain.js
Expand Up @@ -78,7 +78,7 @@ class Explain extends ArboristWorkspaceCmd {
this.npm.output(JSON.stringify(expls, null, 2))
} else {
this.npm.output(expls.map(expl => {
return explainNode(expl, Infinity, this.npm.color)
return explainNode(expl, Infinity, this.npm.chalk)
}).join('\n\n'))
}
}
Expand Down
6 changes: 2 additions & 4 deletions lib/commands/fund.js
@@ -1,6 +1,5 @@
const archy = require('archy')
const Arborist = require('@npmcli/arborist')
const chalk = require('chalk')
const pacote = require('pacote')
const semver = require('semver')
const npa = require('npm-package-arg')
Expand Down Expand Up @@ -96,7 +95,6 @@ class Fund extends ArboristWorkspaceCmd {
}

printHuman (fundingInfo) {
const color = this.npm.color
const unicode = this.npm.config.get('unicode')
const seenUrls = new Map()

Expand All @@ -117,7 +115,7 @@ class Fund extends ArboristWorkspaceCmd {

if (url) {
item.label = tree({
label: color ? chalk.bgBlack.white(url) : url,
label: this.npm.chalk.bgBlack.white(url),
nodes: [pkgRef],
}).trim()

Expand Down Expand Up @@ -154,7 +152,7 @@ class Fund extends ArboristWorkspaceCmd {
})

const res = tree(result)
return color ? chalk.reset(res) : res
return this.npm.chalk.reset(res)
}

async openFundingUrl ({ path, tree, spec, fundingSourceNumber }) {
Expand Down
7 changes: 1 addition & 6 deletions lib/commands/help-search.js
@@ -1,6 +1,5 @@
const { readFile } = require('fs/promises')
const path = require('path')
const chalk = require('chalk')
const glob = require('glob')
const BaseCommand = require('../base-command.js')

Expand Down Expand Up @@ -163,18 +162,14 @@ class HelpSearch extends BaseCommand {
return
}

if (!this.npm.color) {
out.push(line + '\n')
return
}
const hilitLine = []
for (const arg of args) {
const finder = line.toLowerCase().split(arg.toLowerCase())
let p = 0
for (const f of finder) {
hilitLine.push(line.slice(p, p + f.length))
const word = line.slice(p + f.length, p + f.length + arg.length)
const hilit = chalk.bgBlack.red(word)
const hilit = this.npm.chalk.bgBlack.red(word)
hilitLine.push(hilit)
p += f.length + arg.length
}
Expand Down
28 changes: 13 additions & 15 deletions lib/commands/ls.js
Expand Up @@ -3,7 +3,6 @@ const relativePrefix = `.${sep}`
const { EOL } = require('os')

const archy = require('archy')
const chalk = require('chalk')
const Arborist = require('@npmcli/arborist')
const { breadth } = require('treeverse')
const npa = require('npm-package-arg')
Expand Down Expand Up @@ -50,7 +49,7 @@ class LS extends ArboristWorkspaceCmd {

async exec (args) {
const all = this.npm.config.get('all')
const color = this.npm.color
const chalk = this.npm.chalk
const depth = this.npm.config.get('depth')
const global = this.npm.global
const json = this.npm.config.get('json')
Expand Down Expand Up @@ -157,7 +156,7 @@ class LS extends ArboristWorkspaceCmd {
? getJsonOutputItem(node, { global, long })
: parseable
? null
: getHumanOutputItem(node, { args, color, global, long })
: getHumanOutputItem(node, { args, chalk, global, long })

// loop through list of node problems to add them to global list
if (node[_include]) {
Expand All @@ -180,7 +179,7 @@ class LS extends ArboristWorkspaceCmd {
this.npm.outputBuffer(
json ? jsonOutput({ path, problems, result, rootError, seenItems }) :
parseable ? parseableOutput({ seenNodes, global, long }) :
humanOutput({ color, result, seenItems, unicode })
humanOutput({ chalk, result, seenItems, unicode })
)

// if filtering items, should exit with error code on no results
Expand Down Expand Up @@ -278,9 +277,9 @@ const augmentItemWithIncludeMetadata = (node, item) => {
return item
}

const getHumanOutputItem = (node, { args, color, global, long }) => {
const getHumanOutputItem = (node, { args, chalk, global, long }) => {
const { pkgid, path } = node
const workspacePkgId = color ? chalk.green(pkgid) : pkgid
const workspacePkgId = chalk.green(pkgid)
let printable = node.isWorkspace ? workspacePkgId : pkgid

// special formatting for top-level package name
Expand All @@ -293,8 +292,7 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
}
}

const highlightDepName =
color && args.length && node[_filteredBy]
const highlightDepName = args.length && node[_filteredBy]
const missingColor = isOptional(node)
? chalk.yellow.bgBlack
: chalk.red.bgBlack
Expand All @@ -308,28 +306,28 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
const label =
(
node[_missing]
? (color ? missingColor(missingMsg) : missingMsg) + ' '
? missingColor(missingMsg) + ' '
: ''
) +
`${highlightDepName ? chalk.yellow.bgBlack(printable) : printable}` +
(
node[_dedupe]
? ' ' + (color ? chalk.gray('deduped') : 'deduped')
? ' ' + chalk.gray('deduped')
: ''
) +
(
invalid
? ' ' + (color ? chalk.red.bgBlack(invalid) : invalid)
? ' ' + chalk.red.bgBlack(invalid)
: ''
) +
(
isExtraneous(node, { global })
? ' ' + (color ? chalk.green.bgBlack('extraneous') : 'extraneous')
? ' ' + chalk.green.bgBlack('extraneous')
: ''
) +
(
node.overridden
? ' ' + (color ? chalk.gray('overridden') : 'overridden')
? ' ' + chalk.gray('overridden')
: ''
) +
(isGitNode(node) ? ` (${node.resolved})` : '') +
Expand Down Expand Up @@ -504,7 +502,7 @@ const augmentNodesWithMetadata = ({

const sortAlphabetically = ({ pkgid: a }, { pkgid: b }) => localeCompare(a, b)

const humanOutput = ({ color, result, seenItems, unicode }) => {
const humanOutput = ({ chalk, result, seenItems, unicode }) => {
// we need to traverse the entire tree in order to determine which items
// should be included (since a nested transitive included dep will make it
// so that all its ancestors should be displayed)
Expand All @@ -520,7 +518,7 @@ const humanOutput = ({ color, result, seenItems, unicode }) => {
}

const archyOutput = archy(result, '', { unicode })
return color ? chalk.reset(archyOutput) : archyOutput
return chalk.reset(archyOutput)
}

const jsonOutput = ({ path, problems, result, rootError, seenItems }) => {
Expand Down
17 changes: 6 additions & 11 deletions lib/commands/outdated.js
Expand Up @@ -2,7 +2,6 @@ const os = require('os')
const { resolve } = require('path')
const pacote = require('pacote')
const table = require('text-table')
const chalk = require('chalk')
const npa = require('npm-package-arg')
const pickManifest = require('npm-pick-manifest')
const localeCompare = require('@isaacs/string-locale-compare')('en')
Expand Down Expand Up @@ -104,9 +103,7 @@ class Outdated extends ArboristWorkspaceCmd {
}
const outTable = [outHead].concat(outList)

if (this.npm.color) {
outTable[0] = outTable[0].map(heading => chalk.underline(heading))
}
outTable[0] = outTable[0].map(heading => this.npm.chalk.underline(heading))

const tableOpts = {
align: ['l', 'r', 'r', 'r', 'l'],
Expand Down Expand Up @@ -281,8 +278,8 @@ class Outdated extends ArboristWorkspaceCmd {
? node.pkgid
: node.name

return this.npm.color && humanOutput
? chalk.green(workspaceName)
return humanOutput
? this.npm.chalk.green(workspaceName)
: workspaceName
}

Expand All @@ -306,11 +303,9 @@ class Outdated extends ArboristWorkspaceCmd {
columns[7] = homepage
}

if (this.npm.color) {
columns[0] = chalk[current === wanted ? 'yellow' : 'red'](columns[0]) // current
columns[2] = chalk.green(columns[2]) // wanted
columns[3] = chalk.magenta(columns[3]) // latest
}
columns[0] = this.npm.chalk[current === wanted ? 'yellow' : 'red'](columns[0]) // current
columns[2] = this.npm.chalk.green(columns[2]) // wanted
columns[3] = this.npm.chalk.magenta(columns[3]) // latest

return columns
}
Expand Down
3 changes: 1 addition & 2 deletions lib/commands/profile.js
@@ -1,6 +1,5 @@
const inspect = require('util').inspect
const { URL } = require('url')
const chalk = require('chalk')
const log = require('../utils/log-shim.js')
const npmProfile = require('npm-profile')
const qrcodeTerminal = require('qrcode-terminal')
Expand Down Expand Up @@ -161,7 +160,7 @@ class Profile extends BaseCommand {
} else {
const table = new Table()
for (const key of Object.keys(cleaned)) {
table.push({ [chalk.bold(key)]: cleaned[key] })
table.push({ [this.npm.chalk.bold(key)]: cleaned[key] })
}

this.npm.output(table.toString())
Expand Down
12 changes: 1 addition & 11 deletions lib/commands/run-script.js
@@ -1,5 +1,4 @@
const { resolve } = require('path')
const chalk = require('chalk')
const runScript = require('@npmcli/run-script')
const { isServerPackage } = runScript
const rpj = require('read-package-json-fast')
Expand All @@ -18,14 +17,6 @@ const cmdList = [
'version',
].reduce((l, p) => l.concat(['pre' + p, p, 'post' + p]), [])

const nocolor = {
reset: s => s,
bold: s => s,
dim: s => s,
blue: s => s,
green: s => s,
}

const BaseCommand = require('../base-command.js')
class RunScript extends BaseCommand {
static description = 'Run arbitrary package scripts'
Expand Down Expand Up @@ -138,7 +129,6 @@ class RunScript extends BaseCommand {
path = path || this.npm.localPrefix
const { scripts, name, _id } = await rpj(`${path}/package.json`)
const pkgid = _id || name
const color = this.npm.color

if (!scripts) {
return []
Expand Down Expand Up @@ -170,7 +160,7 @@ class RunScript extends BaseCommand {
const list = cmdList.includes(script) ? cmds : runScripts
list.push(script)
}
const colorize = color ? chalk : nocolor
const colorize = this.npm.chalk

if (cmds.length) {
this.npm.output(
Expand Down
3 changes: 1 addition & 2 deletions lib/commands/token.js
@@ -1,5 +1,4 @@
const Table = require('cli-table3')
const chalk = require('chalk')
const { v4: isCidrV4, v6: isCidrV6 } = require('is-cidr')
const log = require('../utils/log-shim.js')
const profile = require('npm-profile')
Expand Down Expand Up @@ -152,7 +151,7 @@ class Token extends BaseCommand {
} else {
const table = new Table()
for (const k of Object.keys(result)) {
table.push({ [chalk.bold(k)]: String(result[k]) })
table.push({ [this.npm.chalk.bold(k)]: String(result[k]) })
}
this.npm.output(table.toString())
}
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/view.js
@@ -1,4 +1,3 @@
const chalk = require('chalk')
const columns = require('cli-columns')
const fs = require('fs')
const jsonParse = require('json-parse-even-better-errors')
Expand Down Expand Up @@ -315,6 +314,7 @@ class View extends BaseCommand {
prettyView (packu, manifest) {
// More modern, pretty printing of default view
const unicode = this.npm.config.get('unicode')
const chalk = this.npm.chalk
const tags = []

Object.keys(packu['dist-tags']).forEach((t) => {
Expand Down
24 changes: 19 additions & 5 deletions lib/npm.js
Expand Up @@ -37,6 +37,8 @@ class Npm extends EventEmitter {
#title = 'npm'
#argvClean = []
#chalk = null
#logChalk = null
#noColorChalk = new chalk.Instance({ level: 0 })
#npmRoot = null
#warnedNonDashArg = false

Expand Down Expand Up @@ -261,6 +263,7 @@ class Npm extends EventEmitter {
this.#display.load({
// Use logColor since that is based on stderr
color: this.logColor,
chalk: this.logChalk,
progress: this.flatOptions.progress,
silent: this.silent,
timing: this.config.get('timing'),
Expand Down Expand Up @@ -330,17 +333,28 @@ class Npm extends EventEmitter {
return this.flatOptions.logColor
}

get noColorChalk () {
return this.#noColorChalk
}

get chalk () {
if (!this.#chalk) {
let level = chalk.level
if (!this.color) {
level = 0
}
this.#chalk = new chalk.Instance({ level })
this.#chalk = new chalk.Instance({
level: this.color ? chalk.level : 0,
})
}
return this.#chalk
}

get logChalk () {
if (!this.#logChalk) {
this.#logChalk = new chalk.Instance({
level: this.logColor ? chalk.stderr.level : 0,
})
}
return this.#logChalk
}

get global () {
return this.config.get('global') || this.config.get('location') === 'global'
}
Expand Down
7 changes: 6 additions & 1 deletion lib/utils/display.js
Expand Up @@ -4,6 +4,8 @@ const log = require('./log-shim.js')
const { explain } = require('./explain-eresolve.js')

class Display {
#chalk = null

constructor () {
// pause by default until config is loaded
this.on()
Expand All @@ -26,6 +28,7 @@ class Display {
load (config) {
const {
color,
chalk,
timing,
loglevel,
unicode,
Expand All @@ -34,6 +37,8 @@ class Display {
heading = 'npm',
} = config

this.#chalk = chalk

// npmlog is still going away someday, so this is a hack to dynamically
// set the loglevel of timing based on the timing flag, instead of making
// a breaking change to npmlog. The result is that timing logs are never
Expand Down Expand Up @@ -111,7 +116,7 @@ class Display {
expl && typeof expl === 'object'
) {
this.#npmlog(level, heading, message)
this.#npmlog(level, '', explain(expl, log.useColor(), 2))
this.#npmlog(level, '', explain(expl, this.#chalk, 2))
// Return true to short circuit other log in chain
return true
}
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/error-message.js
Expand Up @@ -38,7 +38,7 @@ const errorMessage = (er, npm) => {
// XXX(display): error messages are logged so we use the logColor since that is based
// on stderr. This should be handled solely by the display layer so it could also be
// printed to stdout if necessary.
const { explanation, file } = report(er, !!npm.logColor)
const { explanation, file } = report(er, npm.logChalk, npm.noColorChalk)
detail.push(['', explanation])
files.push(['eresolve-report.txt', file])
break
Expand Down

0 comments on commit 09b58e4

Please sign in to comment.