var wrap = require('wordwrap'),align = {right: require('right-align'),center: require('center-align')},top = 0,right = 1,bottom = 2,left = 3function UI (opts) {this.width = opts.widththis.wrap = opts.wrapthis.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,rows = str.split('\n'),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 && columns[0].length > leftColumnWidth) {leftColumnWidth = Math.min(Math.floor(_this.width * 0.5),columns[0].length)}})// 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: [0, r.match(/\s*$/)[0].length, 0, r.match(/^\s*/)[0].length],width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined}}))})return this.rows[this.rows.length - 1]}UI.prototype._colFromString = function (str) {return {text: str}}UI.prototype.toString = function () {var _this = this,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,paddingLeft,rrows = this._rasterize(row),str = '',ts,width,wrapWidthrrows.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.for (var i = 0; i < Math.max(wrapWidth, col.length); i++) {ts += col.charAt(i) || ''}// align the string within its column.if (row[c].align && row[c].align !== 'left' && _this.wrap) {ts = align[row[c].align](ts.trim() + '\n' + new Array(wrapWidth + 1).join('')).split('\n')[0]if (ts.length < wrapWidth) ts += new Array(width - ts.length).join('')}// add left/right padding and print string.paddingLeft = (row[c].padding || [0, 0, 0, 0])[left]if (paddingLeft) str += new Array(row[c].padding[left] + 1).join('')str += tsif (row[c].padding && row[c].padding[right]) str += new Array(row[c].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], paddingLeft)}})// remove trailing whitespace.lines.push({text: str.replace(/ +$/, ''),span: row.span})})return lines}// if the full 'source' can render in// the target line, do so.UI.prototype._renderInline = function (source, previousLine, paddingLeft) {var target = previousLine.text,str = ''if (!previousLine.span) return source// if we're not applying wrapping logic,// just always append to the span.if (!this.wrap) {previousLine.hidden = truereturn target + source}for (var i = 0, tc, sc; i < Math.max(source.length, target.length); i++) {tc = target.charAt(i) || ''sc = source.charAt(i) || ''// we tried to overwrite a character in the other string.if (tc !== '' && sc !== '') return source// there is not enough whitespace to maintain padding.if (sc !== '' && i < paddingLeft + target.length) return source// :thumbsup:if (tc === '') str += scelse str += tc}previousLine.hidden = truereturn str}UI.prototype._rasterize = function (row) {var _this = this,i,rrow,rrows = [],widths = this._columnWidths(row),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.hard(_this._negatePadding(col))(col.text).split('\n')else wrapped = col.text.split('\n')// 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.widthif (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)return wrapWidth}UI.prototype._columnWidths = function (row) {var _this = this,widths = [],unset = row.length,unsetWidth,remainingWidth = this.width// column widths can be set in config.row.forEach(function (col, i) {if (col.width) {unset--widths[i] = col.widthremainingWidth -= 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 || row[i].text.lengthelse 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 || []return 1 + (padding[left] || 0) + (padding[right] || 0)}module.exports = function (opts) {opts = opts || {}return new UI({width: (opts || {}).width || 80,wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true})}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型