[Pkg-javascript-commits] [node-cliui] 01/03: Import Upstream version 3.2.0

Paolo Greppi paolog-guest at moszumanska.debian.org
Sat Nov 26 00:35:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

paolog-guest pushed a commit to branch master
in repository node-cliui.

commit d69c9cedee7652d67954b44137535eb71b144696
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date:   Sat Nov 26 00:25:41 2016 +0000

    Import Upstream version 3.2.0
---
 .coveralls.yml |   1 +
 .gitignore     |   3 +
 .travis.yml    |   7 +
 CHANGELOG.md   |  15 ++
 LICENSE.txt    |  14 ++
 README.md      | 110 ++++++++++++++
 index.js       | 316 +++++++++++++++++++++++++++++++++++++++
 package.json   |  64 ++++++++
 screenshot.png | Bin 0 -> 18253 bytes
 test/cliui.js  | 457 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 987 insertions(+)

diff --git a/.coveralls.yml b/.coveralls.yml
new file mode 100644
index 0000000..73367db
--- /dev/null
+++ b/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: NiRhyj91Z2vtgob6XdEAqs83rzNnbMZUu
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..62adae5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+node_modules
+.nyc_output
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..ea02669
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+node_js:
+  - "0.10"
+  - "0.12"
+  - "4"
+  - "5"
+after_script: npm run coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ef6a35e
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+<a name="3.2.0"></a>
+# [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11)
+
+
+### Bug Fixes
+
+* reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33))
+
+### Features
+
+* adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32))
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..c7e2747
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,14 @@
+Copyright (c) 2015, Contributors
+
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..028392c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,110 @@
+# cliui
+
+[![Build Status](https://travis-ci.org/yargs/cliui.svg)](https://travis-ci.org/yargs/cliui)
+[![Coverage Status](https://coveralls.io/repos/yargs/cliui/badge.svg?branch=)](https://coveralls.io/r/yargs/cliui?branch=)
+[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui)
+[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
+
+easily create complex multi-column command-line-interfaces.
+
+## Example
+
+```js
+var ui = require('cliui')({
+  width: 80
+})
+
+ui.div('Usage: $0 [command] [options]')
+
+ui.div({
+  text: 'Options:',
+  padding: [2, 0, 2, 0]
+})
+
+ui.div(
+  {
+    text: "-f, --file",
+    width: 20,
+    padding: [0, 4, 0, 4]
+  },
+  {
+    text: "the file to load." +
+      chalk.green("(if this description is long it wraps).")
+    ,
+    width: 20
+  },
+  {
+    text: chalk.red("[required]"),
+    align: 'right'
+  }
+)
+
+console.log(ui.toString())
+```
+
+<img width="500" src="screenshot.png">
+
+## Layout DSL
+
+cliui exposes a simple layout DSL:
+
+If you create a single `ui.row`, passing a string rather than an
+object:
+
+* `\n`: characters will be interpreted as new rows.
+* `\t`: characters will be interpreted as new columns.
+* `\s`: characters will be interpreted as padding.
+
+**as an example...**
+
+```js
+var ui = require('./')({
+  width: 60
+})
+
+ui.div(
+  'Usage: node ./bin/foo.js\n' +
+  '  <regex>\t  provide a regex\n' +
+  '  <glob>\t  provide a glob\t [required]'
+)
+
+console.log(ui.toString())
+```
+
+**will output:**
+
+```shell
+Usage: node ./bin/foo.js
+  <regex>  provide a regex
+  <glob>   provide a glob          [required]
+```
+
+## Methods
+
+```js
+cliui = require('cliui')
+```
+
+### cliui({width: integer})
+
+Specify the maximum width of the UI being generated.
+
+### cliui({wrap: boolean})
+
+Enable or disable the wrapping of text in a column.
+
+### cliui.div(column, column, column)
+
+Create a row with any number of columns, a column
+can either be a string, or an object with the following
+options:
+
+* **width:** the width of a column.
+* **align:** alignment, `right` or `center`.
+* **padding:** `[top, right, bottom, left]`.
+* **border:** should a border be placed around the div?
+
+### cliui.span(column, column, column)
+
+Similar to `div`, except the next row will be appended without
+a new line being created.
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..e501e78
--- /dev/null
+++ b/index.js
@@ -0,0 +1,316 @@
+var stringWidth = require('string-width')
+var stripAnsi = require('strip-ansi')
+var wrap = require('wrap-ansi')
+var align = {
+  right: alignRight,
+  center: alignCenter
+}
+var top = 0
+var right = 1
+var bottom = 2
+var left = 3
+
+function UI (opts) {
+  this.width = opts.width
+  this.wrap = opts.wrap
+  this.rows = []
+}
+
+UI.prototype.span = function () {
+  var cols = this.div.apply(this, arguments)
+  cols.span = true
+}
+
+UI.prototype.div = function () {
+  if (arguments.length === 0) this.div('')
+  if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) {
+    return this._applyLayoutDSL(arguments[0])
+  }
+
+  var cols = []
+
+  for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) {
+    if (typeof arg === 'string') cols.push(this._colFromString(arg))
+    else cols.push(arg)
+  }
+
+  this.rows.push(cols)
+  return cols
+}
+
+UI.prototype._shouldApplyLayoutDSL = function () {
+  return arguments.length === 1 && typeof arguments[0] === 'string' &&
+    /[\t\n]/.test(arguments[0])
+}
+
+UI.prototype._applyLayoutDSL = function (str) {
+  var _this = this
+  var rows = str.split('\n')
+  var leftColumnWidth = 0
+
+  // simple heuristic for layout, make sure the
+  // second column lines up along the left-hand.
+  // don't allow the first column to take up more
+  // than 50% of the screen.
+  rows.forEach(function (row) {
+    var columns = row.split('\t')
+    if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
+      leftColumnWidth = Math.min(
+        Math.floor(_this.width * 0.5),
+        stringWidth(columns[0])
+      )
+    }
+  })
+
+  // generate a table:
+  //  replacing ' ' with padding calculations.
+  //  using the algorithmically generated width.
+  rows.forEach(function (row) {
+    var columns = row.split('\t')
+    _this.div.apply(_this, columns.map(function (r, i) {
+      return {
+        text: r.trim(),
+        padding: _this._measurePadding(r),
+        width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
+      }
+    }))
+  })
+
+  return this.rows[this.rows.length - 1]
+}
+
+UI.prototype._colFromString = function (str) {
+  return {
+    text: str,
+    padding: this._measurePadding(str)
+  }
+}
+
+UI.prototype._measurePadding = function (str) {
+  // measure padding without ansi escape codes
+  var noAnsi = stripAnsi(str)
+  return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
+}
+
+UI.prototype.toString = function () {
+  var _this = this
+  var lines = []
+
+  _this.rows.forEach(function (row, i) {
+    _this.rowToString(row, lines)
+  })
+
+  // don't display any lines with the
+  // hidden flag set.
+  lines = lines.filter(function (line) {
+    return !line.hidden
+  })
+
+  return lines.map(function (line) {
+    return line.text
+  }).join('\n')
+}
+
+UI.prototype.rowToString = function (row, lines) {
+  var _this = this
+  var padding
+  var rrows = this._rasterize(row)
+  var str = ''
+  var ts
+  var width
+  var wrapWidth
+
+  rrows.forEach(function (rrow, r) {
+    str = ''
+    rrow.forEach(function (col, c) {
+      ts = '' // temporary string used during alignment/padding.
+      width = row[c].width // the width with padding.
+      wrapWidth = _this._negatePadding(row[c]) // the width without padding.
+
+      ts += col
+
+      for (var i = 0; i < wrapWidth - stringWidth(col); i++) {
+        ts += ' '
+      }
+
+      // align the string within its column.
+      if (row[c].align && row[c].align !== 'left' && _this.wrap) {
+        ts = align[row[c].align](ts, wrapWidth)
+        if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ')
+      }
+
+      // apply border and padding to string.
+      padding = row[c].padding || [0, 0, 0, 0]
+      if (padding[left]) str += new Array(padding[left] + 1).join(' ')
+      str += addBorder(row[c], ts, '| ')
+      str += ts
+      str += addBorder(row[c], ts, ' |')
+      if (padding[right]) str += new Array(padding[right] + 1).join(' ')
+
+      // if prior row is span, try to render the
+      // current row on the prior line.
+      if (r === 0 && lines.length > 0) {
+        str = _this._renderInline(str, lines[lines.length - 1])
+      }
+    })
+
+    // remove trailing whitespace.
+    lines.push({
+      text: str.replace(/ +$/, ''),
+      span: row.span
+    })
+  })
+
+  return lines
+}
+
+function addBorder (col, ts, style) {
+  if (col.border) {
+    if (/[.']-+[.']/.test(ts)) return ''
+    else if (ts.trim().length) return style
+    else return '  '
+  }
+  return ''
+}
+
+// if the full 'source' can render in
+// the target line, do so.
+UI.prototype._renderInline = function (source, previousLine) {
+  var leadingWhitespace = source.match(/^ */)[0].length
+  var target = previousLine.text
+  var targetTextWidth = stringWidth(target.trimRight())
+
+  if (!previousLine.span) return source
+
+  // if we're not applying wrapping logic,
+  // just always append to the span.
+  if (!this.wrap) {
+    previousLine.hidden = true
+    return target + source
+  }
+
+  if (leadingWhitespace < targetTextWidth) return source
+
+  previousLine.hidden = true
+
+  return target.trimRight() + new Array(leadingWhitespace - targetTextWidth + 1).join(' ') + source.trimLeft()
+}
+
+UI.prototype._rasterize = function (row) {
+  var _this = this
+  var i
+  var rrow
+  var rrows = []
+  var widths = this._columnWidths(row)
+  var wrapped
+
+  // word wrap all columns, and create
+  // a data-structure that is easy to rasterize.
+  row.forEach(function (col, c) {
+    // leave room for left and right padding.
+    col.width = widths[c]
+    if (_this.wrap) wrapped = wrap(col.text, _this._negatePadding(col), {hard: true}).split('\n')
+    else wrapped = col.text.split('\n')
+
+    if (col.border) {
+      wrapped.unshift('.' + new Array(_this._negatePadding(col) + 3).join('-') + '.')
+      wrapped.push("'" + new Array(_this._negatePadding(col) + 3).join('-') + "'")
+    }
+
+    // add top and bottom padding.
+    if (col.padding) {
+      for (i = 0; i < (col.padding[top] || 0); i++) wrapped.unshift('')
+      for (i = 0; i < (col.padding[bottom] || 0); i++) wrapped.push('')
+    }
+
+    wrapped.forEach(function (str, r) {
+      if (!rrows[r]) rrows.push([])
+
+      rrow = rrows[r]
+
+      for (var i = 0; i < c; i++) {
+        if (rrow[i] === undefined) rrow.push('')
+      }
+      rrow.push(str)
+    })
+  })
+
+  return rrows
+}
+
+UI.prototype._negatePadding = function (col) {
+  var wrapWidth = col.width
+  if (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
+  if (col.border) wrapWidth -= 4
+  return wrapWidth
+}
+
+UI.prototype._columnWidths = function (row) {
+  var _this = this
+  var widths = []
+  var unset = row.length
+  var unsetWidth
+  var remainingWidth = this.width
+
+  // column widths can be set in config.
+  row.forEach(function (col, i) {
+    if (col.width) {
+      unset--
+      widths[i] = col.width
+      remainingWidth -= col.width
+    } else {
+      widths[i] = undefined
+    }
+  })
+
+  // any unset widths should be calculated.
+  if (unset) unsetWidth = Math.floor(remainingWidth / unset)
+  widths.forEach(function (w, i) {
+    if (!_this.wrap) widths[i] = row[i].width || stringWidth(row[i].text)
+    else if (w === undefined) widths[i] = Math.max(unsetWidth, _minWidth(row[i]))
+  })
+
+  return widths
+}
+
+// calculates the minimum width of
+// a column, based on padding preferences.
+function _minWidth (col) {
+  var padding = col.padding || []
+  var minWidth = 1 + (padding[left] || 0) + (padding[right] || 0)
+  if (col.border) minWidth += 4
+  return minWidth
+}
+
+function alignRight (str, width) {
+  str = str.trim()
+  var padding = ''
+  var strWidth = stringWidth(str)
+
+  if (strWidth < width) {
+    padding = new Array(width - strWidth + 1).join(' ')
+  }
+
+  return padding + str
+}
+
+function alignCenter (str, width) {
+  str = str.trim()
+  var padding = ''
+  var strWidth = stringWidth(str.trim())
+
+  if (strWidth < width) {
+    padding = new Array(parseInt((width - strWidth) / 2, 10) + 1).join(' ')
+  }
+
+  return padding + str
+}
+
+module.exports = function (opts) {
+  opts = opts || {}
+
+  return new UI({
+    width: (opts || {}).width || 80,
+    wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true
+  })
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..31c654c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,64 @@
+{
+  "name": "cliui",
+  "version": "3.2.0",
+  "description": "easily create complex multi-column command-line-interfaces",
+  "main": "index.js",
+  "scripts": {
+    "pretest": "standard",
+    "test": "nyc mocha",
+    "coverage": "nyc --reporter=text-lcov mocha | coveralls",
+    "version": "standard-version"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/yargs/cliui.git"
+  },
+  "config": {
+    "blanket": {
+      "pattern": [
+        "index.js"
+      ],
+      "data-cover-never": [
+        "node_modules",
+        "test"
+      ],
+      "output-reporter": "spec"
+    }
+  },
+  "standard": {
+    "ignore": [
+      "**/example/**"
+    ],
+    "globals": [
+      "it"
+    ]
+  },
+  "keywords": [
+    "cli",
+    "command-line",
+    "layout",
+    "design",
+    "console",
+    "wrap",
+    "table"
+  ],
+  "author": "Ben Coe <ben at npmjs.com>",
+  "license": "ISC",
+  "dependencies": {
+    "string-width": "^1.0.1",
+    "strip-ansi": "^3.0.1",
+    "wrap-ansi": "^2.0.0"
+  },
+  "devDependencies": {
+    "chai": "^3.5.0",
+    "chalk": "^1.1.2",
+    "coveralls": "^2.11.8",
+    "mocha": "^2.4.5",
+    "nyc": "^6.4.0",
+    "standard": "^6.0.8",
+    "standard-version": "^2.1.2"
+  },
+  "files": [
+    "index.js"
+  ]
+}
\ No newline at end of file
diff --git a/screenshot.png b/screenshot.png
new file mode 100644
index 0000000..d969fa0
Binary files /dev/null and b/screenshot.png differ
diff --git a/test/cliui.js b/test/cliui.js
new file mode 100644
index 0000000..fd27f5a
--- /dev/null
+++ b/test/cliui.js
@@ -0,0 +1,457 @@
+/* global describe, it */
+
+require('chai').should()
+
+var chalk = require('chalk')
+var cliui = require('../')
+var stripAnsi = require('strip-ansi')
+
+describe('cliui', function () {
+  describe('div', function () {
+    it("wraps text at 'width' if a single column is given", function () {
+      var ui = cliui({
+        width: 10
+      })
+
+      ui.div('i am a string that should be wrapped')
+
+      ui.toString().split('\n').forEach(function (row) {
+        row.length.should.be.lte(10)
+      })
+    })
+
+    it('evenly divides text across columns if multiple columns are given', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        {text: 'i am a string that should be wrapped', width: 15},
+        'i am a second string that should be wrapped',
+        'i am a third string that should be wrapped'
+      )
+
+      // total width of all columns is <=
+      // the width cliui is initialized with.
+      ui.toString().split('\n').forEach(function (row) {
+        row.length.should.be.lte(40)
+      })
+
+      // it should wrap each column appropriately.
+      var expected = [
+        'i am a string  i am a      i am a third',
+        'that should be second      string that',
+        'wrapped        string that should be',
+        '               should be   wrapped',
+        '               wrapped'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('allows for a blank row to be appended', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div()
+
+      // it should wrap each column appropriately.
+      var expected = ['']
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+  })
+
+  describe('_columnWidths', function () {
+    it('uses same width for each column by default', function () {
+      var ui = cliui({
+        width: 40
+      })
+      var widths = ui._columnWidths([{}, {}, {}])
+
+      widths[0].should.equal(13)
+      widths[1].should.equal(13)
+      widths[2].should.equal(13)
+    })
+
+    it('divides width over remaining columns if first column has width specified', function () {
+      var ui = cliui({
+        width: 40
+      })
+      var widths = ui._columnWidths([{width: 20}, {}, {}])
+
+      widths[0].should.equal(20)
+      widths[1].should.equal(10)
+      widths[2].should.equal(10)
+    })
+
+    it('divides width over remaining columns if middle column has width specified', function () {
+      var ui = cliui({
+        width: 40
+      })
+      var widths = ui._columnWidths([{}, {width: 10}, {}])
+
+      widths[0].should.equal(15)
+      widths[1].should.equal(10)
+      widths[2].should.equal(15)
+    })
+
+    it('keeps track of remaining width if multiple columns have width specified', function () {
+      var ui = cliui({
+        width: 40
+      })
+      var widths = ui._columnWidths([{width: 20}, {width: 12}, {}])
+
+      widths[0].should.equal(20)
+      widths[1].should.equal(12)
+      widths[2].should.equal(8)
+    })
+
+    it('uses a sane default if impossible widths are specified', function () {
+      var ui = cliui({
+        width: 40
+      })
+      var widths = ui._columnWidths([{width: 30}, {width: 30}, {padding: [0, 2, 0, 1]}])
+
+      widths[0].should.equal(30)
+      widths[1].should.equal(30)
+      widths[2].should.equal(4)
+    })
+  })
+
+  describe('alignment', function () {
+    it('allows a column to be right aligned', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        'i am a string',
+        {text: 'i am a second string', align: 'right'},
+        'i am a third string that should be wrapped'
+      )
+
+      // it should right-align the second column.
+      var expected = [
+        'i am a stringi am a secondi am a third',
+        '                    stringstring that',
+        '                          should be',
+        '                          wrapped'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('allows a column to be center aligned', function () {
+      var ui = cliui({
+        width: 60
+      })
+
+      ui.div(
+        'i am a string',
+        {text: 'i am a second string', align: 'center', padding: [0, 2, 0, 2]},
+        'i am a third string that should be wrapped'
+      )
+
+      // it should right-align the second column.
+      var expected = [
+        'i am a string          i am a second       i am a third string',
+        '                           string          that should be',
+        '                                           wrapped'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+  })
+
+  describe('padding', function () {
+    it('handles left/right padding', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        {text: 'i have padding on my left', padding: [0, 0, 0, 4]},
+        {text: 'i have padding on my right', padding: [0, 2, 0, 0], align: 'center'},
+        {text: 'i have no padding', padding: [0, 0, 0, 0]}
+      )
+
+      // it should add left/right padding to columns.
+      var expected = [
+        '    i have     i have      i have no',
+        '    padding  padding on    padding',
+        '    on my     my right',
+        '    left'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('handles top/bottom padding', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        'i am a string',
+        {text: 'i am a second string', padding: [2, 0, 0, 0]},
+        {text: 'i am a third string that should be wrapped', padding: [0, 0, 1, 0]}
+      )
+
+      // it should add top/bottom padding to second
+      // and third columns.
+      var expected = [
+        'i am a string             i am a third',
+        '                          string that',
+        '             i am a secondshould be',
+        '             string       wrapped',
+        ''
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('preserves leading whitespace as padding', function () {
+      var ui = cliui()
+
+      ui.div('     LEADING WHITESPACE')
+      ui.div('\u001b[34m     with ansi\u001b[39m')
+
+      var expected = [
+        '     LEADING WHITESPACE',
+        '     with ansi'
+      ]
+
+      ui.toString().split('\n').map(function (l) {
+        return stripAnsi(l)
+      }).should.eql(expected)
+    })
+  })
+
+  describe('border', function () {
+    it('allows a border to be placed around a div', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        {text: 'i am a first string', padding: [0, 0, 0, 0], border: true},
+        {text: 'i am a second string', padding: [1, 0, 0, 0], border: true}
+      )
+
+      var expected = [
+        '.------------------.',
+        '| i am a first     |.------------------.',
+        '| string           || i am a second    |',
+        "'------------------'| string           |",
+        "                    '------------------'"
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+  })
+
+  describe('wrap', function () {
+    it('allows wordwrap to be disabled', function () {
+      var ui = cliui({
+        wrap: false
+      })
+
+      ui.div(
+        {text: 'i am a string', padding: [0, 1, 0, 0]},
+        {text: 'i am a second string', padding: [0, 2, 0, 0]},
+        {text: 'i am a third string that should not be wrapped', padding: [0, 0, 0, 2]}
+      )
+
+      ui.toString().should.equal('i am a string i am a second string    i am a third string that should not be wrapped')
+    })
+  })
+
+  describe('span', function () {
+    it('appends the next row to the end of the prior row if it fits', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.span(
+        {text: 'i am a string that will be wrapped', width: 30}
+      )
+
+      ui.div(
+        {text: ' [required] [default: 99]', align: 'right'}
+      )
+
+      var expected = [
+        'i am a string that will be',
+        'wrapped         [required] [default: 99]'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('does not append the string if it does not fit on the prior row', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.span(
+        {text: 'i am a string that will be wrapped', width: 30}
+      )
+
+      ui.div(
+        {text: 'i am a second row', align: 'left'}
+      )
+
+      var expected = [
+        'i am a string that will be',
+        'wrapped',
+        'i am a second row'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('always appends text to prior span if wrap is disabled', function () {
+      var ui = cliui({
+        wrap: false,
+        width: 40
+      })
+
+      ui.span(
+        {text: 'i am a string that will be wrapped', width: 30}
+      )
+
+      ui.div(
+        {text: 'i am a second row', align: 'left', padding: [0, 0, 0, 3]}
+      )
+
+      ui.div('a third line')
+
+      var expected = [
+        'i am a string that will be wrapped   i am a second row',
+        'a third line'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('appends to prior line appropriately when strings contain ansi escape codes', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.span(
+        {text: chalk.green('i am a string that will be wrapped'), width: 30}
+      )
+
+      ui.div(
+        {text: chalk.blue(' [required] [default: 99]'), align: 'right'}
+      )
+
+      var expected = [
+        'i am a string that will be',
+        'wrapped         [required] [default: 99]'
+      ]
+
+      ui.toString().split('\n').map(function (l) {
+        return stripAnsi(l)
+      }).should.eql(expected)
+    })
+  })
+
+  describe('layoutDSL', function () {
+    it('turns tab into multiple columns', function () {
+      var ui = cliui({
+        width: 60
+      })
+
+      ui.div(
+        '  <regex>  \tmy awesome regex\n  <my second thing>  \tanother row\t  a third column'
+      )
+
+      var expected = [
+        '  <regex>            my awesome regex',
+        '  <my second thing>  another row          a third column'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('turns newline into multiple rows', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        'Usage: $0\n  <regex>\t  my awesome regex\n  <glob>\t  my awesome glob\t  [required]'
+      )
+      var expected = [
+        'Usage: $0',
+        '  <regex>  my awesome regex',
+        '  <glob>   my awesome     [required]',
+        '           glob'
+      ]
+
+      ui.toString().split('\n').should.eql(expected)
+    })
+
+    it('aligns rows appropriately when they contain ansi escape codes', function () {
+      var ui = cliui({
+        width: 40
+      })
+
+      ui.div(
+        '  <regex>\t  ' + chalk.red('my awesome regex') + '\t  [regex]\n  ' + chalk.blue('<glob>') + '\t  my awesome glob\t  [required]'
+      )
+
+      var expected = [
+        '  <regex>  my awesome     [regex]',
+        '           regex',
+        '  <glob>   my awesome     [required]',
+        '           glob'
+      ]
+
+      ui.toString().split('\n').map(function (l) {
+        return stripAnsi(l)
+      }).should.eql(expected)
+    })
+
+    it('ignores ansi escape codes when measuring padding', function () {
+      var ui = cliui({
+        width: 25
+      })
+
+      // using figlet font 'Shadow' rendering of text 'true' here
+      ui.div(
+        chalk.blue('  |                      \n  __|   __|  |   |   _ \\ \n  |    |     |   |   __/ \n \\__| _|    \\__,_| \\___| \n                         ')
+      )
+
+      // relevant part is first line - leading whitespace should be preserved as left padding
+      var expected = [
+        '  |',
+        '  __|   __|  |   |   _ \\',
+        '  |    |     |   |   __/',
+        ' \\__| _|    \\__,_| \\___|',
+        '                         '
+      ]
+
+      ui.toString().split('\n').map(function (l) {
+        return stripAnsi(l)
+      }).should.eql(expected)
+    })
+
+    it('does not apply DSL if wrap is false', function () {
+      var ui = cliui({
+        width: 40,
+        wrap: false
+      })
+
+      ui.div(
+        'Usage: $0\ttwo\tthree'
+      )
+
+      ui.toString().should.eql('Usage: $0\ttwo\tthree')
+    })
+  })
+})

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-cliui.git



More information about the Pkg-javascript-commits mailing list