123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- 'use strict'
- var ms = require('mississippi')
- var jsonstream = require('JSONStream')
- var columnify = require('columnify')
- // This module consumes package data in the following format:
- //
- // {
- // name: String,
- // description: String,
- // maintainers: [{ username: String, email: String }],
- // keywords: String | [String],
- // version: String,
- // date: Date // can be null,
- // }
- //
- // The returned stream will format this package data
- // into a byte stream of formatted, displayable output.
- module.exports = formatPackageStream
- function formatPackageStream (opts) {
- opts = opts || {}
- if (opts.json) {
- return jsonOutputStream()
- } else {
- return textOutputStream(opts)
- }
- }
- function jsonOutputStream () {
- return ms.pipeline.obj(
- ms.through.obj(),
- jsonstream.stringify('[', ',', ']'),
- ms.through()
- )
- }
- function textOutputStream (opts) {
- var line = 0
- return ms.through.obj(function (pkg, enc, cb) {
- cb(null, prettify(pkg, ++line, opts))
- })
- }
- function prettify (data, num, opts) {
- opts = opts || {}
- var truncate = !opts.long
- var pkg = normalizePackage(data, opts)
- var columns = opts.description
- ? ['name', 'description', 'author', 'date', 'version', 'keywords']
- : ['name', 'author', 'date', 'version', 'keywords']
- if (opts.parseable) {
- return columns.map(function (col) {
- return pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')
- }).join('\t')
- }
- var output = columnify(
- [pkg],
- {
- include: columns,
- showHeaders: num <= 1,
- columnSplitter: ' | ',
- truncate: truncate,
- config: {
- name: { minWidth: 25, maxWidth: 25, truncate: false, truncateMarker: '' },
- description: { minWidth: 20, maxWidth: 20 },
- author: { minWidth: 15, maxWidth: 15 },
- date: { maxWidth: 11 },
- version: { minWidth: 8, maxWidth: 8 },
- keywords: { maxWidth: Infinity }
- }
- }
- )
- output = trimToMaxWidth(output)
- if (opts.color) {
- output = highlightSearchTerms(output, opts.args)
- }
- return output
- }
- var colors = [31, 33, 32, 36, 34, 35]
- var cl = colors.length
- function addColorMarker (str, arg, i) {
- var m = i % cl + 1
- var markStart = String.fromCharCode(m)
- var markEnd = String.fromCharCode(0)
- if (arg.charAt(0) === '/') {
- return str.replace(
- new RegExp(arg.substr(1, arg.length - 2), 'gi'),
- function (bit) { return markStart + bit + markEnd }
- )
- }
- // just a normal string, do the split/map thing
- var pieces = str.toLowerCase().split(arg.toLowerCase())
- var p = 0
- return pieces.map(function (piece) {
- piece = str.substr(p, piece.length)
- var mark = markStart +
- str.substr(p + piece.length, arg.length) +
- markEnd
- p += piece.length + arg.length
- return piece + mark
- }).join('')
- }
- function colorize (line) {
- for (var i = 0; i < cl; i++) {
- var m = i + 1
- var color = '\u001B[' + colors[i] + 'm'
- line = line.split(String.fromCharCode(m)).join(color)
- }
- var uncolor = '\u001B[0m'
- return line.split('\u0000').join(uncolor)
- }
- function getMaxWidth () {
- var cols
- try {
- var tty = require('tty')
- var stdout = process.stdout
- cols = !tty.isatty(stdout.fd) ? Infinity : process.stdout.getWindowSize()[0]
- cols = (cols === 0) ? Infinity : cols
- } catch (ex) { cols = Infinity }
- return cols
- }
- function trimToMaxWidth (str) {
- var maxWidth = getMaxWidth()
- return str.split('\n').map(function (line) {
- return line.slice(0, maxWidth)
- }).join('\n')
- }
- function highlightSearchTerms (str, terms) {
- terms.forEach(function (arg, i) {
- str = addColorMarker(str, arg, i)
- })
- return colorize(str).trim()
- }
- function normalizePackage (data, opts) {
- opts = opts || {}
- return {
- name: data.name,
- description: opts.description ? data.description : '',
- author: (data.maintainers || []).map(function (m) {
- return '=' + m.username
- }).join(' '),
- keywords: Array.isArray(data.keywords)
- ? data.keywords.join(' ')
- : typeof data.keywords === 'string'
- ? data.keywords.replace(/[,\s]+/, ' ')
- : '',
- version: data.version,
- date: (data.date &&
- (data.date.toISOString() // remove time
- .split('T').join(' ')
- .replace(/:[0-9]{2}\.[0-9]{3}Z$/, ''))
- .slice(0, -5)) ||
- 'prehistoric'
- }
- }
|