Skip to content

Commit 7a37884

Browse files
committed
fix: handle strings the same in cjs, esm, and deno
This also ports some of the `// istanbul ignore` comments to their associated `/* c8 ignore start/stop */` equivalents, and coverage-ignores some value fallbacks that are there for safety but can never be hit in normal usage. Fix: yargs#138
1 parent 3ed58ce commit 7a37884

8 files changed

+74
-48
lines changed

deno.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
// Bootstrap cliui with CommonJS dependencies:
1+
// Bootstrap cliui with ESM dependencies in Deno's style:
22
import { cliui, UI } from './build/lib/index.js'
33
import type { UIOptions } from './build/lib/index.d.ts'
4-
import { wrap, stripAnsi } from './build/lib/string-utils.js'
4+
5+
import stringWidth from 'npm:string-width'
6+
import stripAnsi from 'npm:strip-ansi'
7+
import wrap from 'npm:wrap-ansi'
58

69
export default function ui (opts: UIOptions): UI {
710
return cliui(opts, {
8-
stringWidth: (str: string) => {
9-
return [...str].length
10-
},
11+
stringWidth,
1112
stripAnsi,
1213
wrap
1314
})

index.mjs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
// Bootstrap cliui with CommonJS dependencies:
1+
// Bootstrap cliui with ESM dependencies:
22
import { cliui } from './build/lib/index.js'
3-
import { wrap, stripAnsi } from './build/lib/string-utils.js'
3+
4+
import stringWidth from 'string-width'
5+
import stripAnsi from 'strip-ansi'
6+
import wrap from 'wrap-ansi'
47

58
export default function ui (opts) {
69
return cliui(opts, {
7-
stringWidth: (str) => {
8-
return [...str].length
9-
},
10+
stringWidth,
1011
stripAnsi,
1112
wrap
1213
})

lib/cjs.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Bootstrap cliui with CommonJS dependencies:
22
import { cliui, UIOptions } from './index.js'
3-
const stringWidth = require('string-width')
4-
const stripAnsi = require('strip-ansi')
5-
const wrap = require('wrap-ansi')
3+
const stringWidth = require('string-width-cjs')
4+
const stripAnsi = require('strip-ansi-cjs')
5+
const wrap = require('wrap-ansi-cjs')
66
export default function ui (opts: UIOptions) {
77
return cliui(opts, {
88
stringWidth,

lib/index.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ export class UI {
4747

4848
constructor (opts: UIOptions) {
4949
this.width = opts.width
50+
/* c8 ignore start */
5051
this.wrap = opts.wrap ?? true
52+
/* c8 ignore stop */
5153
this.rows = []
5254
}
5355

@@ -164,7 +166,10 @@ export class UI {
164166
const fn = align[(row[c].align as 'right'|'center')]
165167
ts = fn(ts, wrapWidth)
166168
if (mixin.stringWidth(ts) < wrapWidth) {
167-
ts += ' '.repeat((width || 0) - mixin.stringWidth(ts) - 1)
169+
/* c8 ignore start */
170+
const w = width || 0
171+
/* c8 ignore stop */
172+
ts += ' '.repeat(w - mixin.stringWidth(ts) - 1)
168173
}
169174
}
170175

@@ -202,7 +207,9 @@ export class UI {
202207
// the target line, do so.
203208
private renderInline (source: string, previousLine: Line) {
204209
const match = source.match(/^ */)
210+
/* c8 ignore start */
205211
const leadingWhitespace = match ? match[0].length : 0
212+
/* c8 ignore stop */
206213
const target = previousLine.text
207214
const targetTextWidth = mixin.stringWidth(target.trimEnd())
208215

@@ -274,7 +281,9 @@ export class UI {
274281
}
275282

276283
private negatePadding (col: Column) {
284+
/* c8 ignore start */
277285
let wrapWidth = col.width || 0
286+
/* c8 ignore stop */
278287
if (col.padding) {
279288
wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
280289
}
@@ -308,7 +317,9 @@ export class UI {
308317
})
309318

310319
// any unset widths should be calculated.
320+
/* c8 ignore start */
311321
const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0
322+
/* c8 ignore stop */
312323

313324
return widths.map((w, i) => {
314325
if (w === undefined) {
@@ -349,12 +360,14 @@ function _minWidth (col: Column) {
349360
}
350361

351362
function getWindowWidth (): number {
363+
/* c8 ignore start */
352364
/* istanbul ignore next: depends on terminal */
353365
if (typeof process === 'object' && process.stdout && process.stdout.columns) {
354366
return process.stdout.columns
355367
}
356368
return 80
357369
}
370+
/* c8 ignore stop */
358371

359372
function alignRight (str: string, width: number): string {
360373
str = str.trim()
@@ -371,10 +384,12 @@ function alignCenter (str: string, width: number): string {
371384
str = str.trim()
372385
const strWidth = mixin.stringWidth(str)
373386

387+
/* c8 ignore start */
374388
/* istanbul ignore next */
375389
if (strWidth >= width) {
376390
return str
377391
}
392+
/* c8 ignore stop */
378393

379394
return ' '.repeat((width - strWidth) >> 1) + str
380395
}
@@ -383,7 +398,9 @@ let mixin: Mixin
383398
export function cliui (opts: Partial<UIOptions>, _mixin: Mixin) {
384399
mixin = _mixin
385400
return new UI({
401+
/* c8 ignore start */
386402
width: opts?.width || getWindowWidth(),
387403
wrap: opts?.wrap
404+
/* c8 ignore stop */
388405
})
389406
}

lib/string-utils.ts

-30
This file was deleted.

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@
4949
"author": "Ben Coe <[email protected]>",
5050
"license": "ISC",
5151
"dependencies": {
52-
"string-width": "^4.2.0",
53-
"strip-ansi": "^6.0.1",
54-
"wrap-ansi": "^7.0.0"
52+
"string-width": "^5.1.2",
53+
"string-width-cjs": "npm:string-width@^4.2.0",
54+
"strip-ansi": "^7.0.1",
55+
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
56+
"wrap-ansi": "^8.1.0",
57+
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
5558
},
5659
"devDependencies": {
5760
"@types/node": "^14.0.27",

test/cjs-esm-compare.cjs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict'
2+
3+
/* global describe, it */
4+
5+
require('chai').should()
6+
7+
const text = `usage: git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]
8+
<tagname> [<commit> | <object>]
9+
or: git tag -d <tagname>...
10+
or: git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
11+
[--points-at <object>] [--column[=<options>] | --no-column]
12+
[--create-reflog] [--sort=<key>] [--format=<format>]
13+
[--merged <commit>] [--no-merged <commit>] [<pattern>...]
14+
or: git tag -v [--format=<format>] <tagname>...`
15+
16+
17+
const cliuiCJS = require('../build/index.cjs')
18+
import('../index.mjs').then(({ default: cliuiESM }) => {
19+
describe('consistent wrapping', () => {
20+
it('should produce matching output in cjs and esm', () => {
21+
const uiCJS = cliuiCJS({})
22+
const uiESM = cliuiESM({})
23+
uiCJS.div({
24+
padding: [0, 0, 0, 0],
25+
text,
26+
})
27+
uiESM.div({
28+
padding: [0, 0, 0, 0],
29+
text,
30+
})
31+
uiCJS.toString().should.equal(uiESM.toString())
32+
})
33+
})
34+
})

test/cliui.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ process.env.FORCE_COLOR = 1
99

1010
const chalk = require('chalk')
1111
const cliui = require('../build/index.cjs')
12-
const stripAnsi = require('strip-ansi')
12+
const stripAnsi = require('strip-ansi-cjs')
1313

1414
describe('cliui', () => {
1515
describe('resetOutput', () => {

0 commit comments

Comments
 (0)