11const { Minipass } = require ( 'minipass' )
22const columnify = require ( 'columnify' )
3- const ansiTrim = require ( '../utils/ansi-trim.js' )
43
54// This module consumes package data in the following format:
65//
@@ -16,8 +15,8 @@ const ansiTrim = require('../utils/ansi-trim.js')
1615// The returned stream will format this package data
1716// into a byte stream of formatted, displayable output.
1817
19- module . exports = ( opts ) => {
20- return opts . json ? new JSONOutputStream ( ) : new TextOutputStream ( opts )
18+ module . exports = async ( opts , clean ) => {
19+ return opts . json ? new JSONOutputStream ( ) : new TextOutputStream ( opts , clean )
2120}
2221
2322class JSONOutputStream extends Minipass {
@@ -41,121 +40,96 @@ class JSONOutputStream extends Minipass {
4140}
4241
4342class TextOutputStream extends Minipass {
44- constructor ( opts ) {
43+ #clean
44+ #opts
45+ #line = 0
46+
47+ constructor ( opts , clean ) {
4548 super ( )
46- this . _opts = opts
47- this . _line = 0
49+ this . #clean = clean
50+ this . #opts = opts
4851 }
4952
5053 write ( pkg ) {
51- return super . write ( prettify ( pkg , ++ this . _line , this . _opts ) )
52- }
53- }
54-
55- function prettify ( data , num , opts ) {
56- var truncate = ! opts . long
57-
58- var pkg = normalizePackage ( data , opts )
59-
60- var columns = [ 'name' , 'description' , 'author' , 'date' , 'version' , 'keywords' ]
61-
62- if ( opts . parseable ) {
63- return columns . map ( function ( col ) {
64- return pkg [ col ] && ( '' + pkg [ col ] ) . replace ( / \t / g, ' ' )
65- } ) . join ( '\t' )
54+ return super . write ( this . #prettify( pkg ) )
6655 }
6756
68- // stdout in tap is never a tty
69- /* istanbul ignore next */
70- const maxWidth = process . stdout . isTTY ? process . stdout . getWindowSize ( ) [ 0 ] : Infinity
71- let output = columnify (
72- [ pkg ] ,
73- {
74- include : columns ,
75- showHeaders : num <= 1 ,
76- columnSplitter : ' | ' ,
77- truncate : truncate ,
78- config : {
79- name : { minWidth : 25 , maxWidth : 25 , truncate : false , truncateMarker : '' } ,
80- description : { minWidth : 20 , maxWidth : 20 } ,
81- author : { minWidth : 15 , maxWidth : 15 } ,
82- date : { maxWidth : 11 } ,
83- version : { minWidth : 8 , maxWidth : 8 } ,
84- keywords : { maxWidth : Infinity } ,
85- } ,
57+ #prettify ( data ) {
58+ const pkg = {
59+ author : data . maintainers . map ( ( m ) => `=${ this . #clean( m . username ) } ` ) . join ( ' ' ) ,
60+ date : 'prehistoric' ,
61+ description : this . #clean( data . description ?? '' ) ,
62+ keywords : '' ,
63+ name : this . #clean( data . name ) ,
64+ version : data . version ,
65+ }
66+ if ( Array . isArray ( data . keywords ) ) {
67+ pkg . keywords = data . keywords . map ( ( k ) => this . #clean( k ) ) . join ( ' ' )
68+ } else if ( typeof data . keywords === 'string' ) {
69+ pkg . keywords = this . #clean( data . keywords . replace ( / [ , \s ] + / , ' ' ) )
70+ }
71+ if ( data . date ) {
72+ pkg . date = data . date . toISOString ( ) . split ( 'T' ) [ 0 ] // remove time
8673 }
87- ) . split ( '\n' ) . map ( line => line . slice ( 0 , maxWidth ) ) . join ( '\n' )
88-
89- if ( opts . color ) {
90- output = highlightSearchTerms ( output , opts . args )
91- }
92-
93- return output
94- }
95-
96- var colors = [ 31 , 33 , 32 , 36 , 34 , 35 ]
97- var cl = colors . length
98-
99- function addColorMarker ( str , arg , i ) {
100- var m = i % cl + 1
101- var markStart = String . fromCharCode ( m )
102- var markEnd = String . fromCharCode ( 0 )
103-
104- if ( arg . charAt ( 0 ) === '/' ) {
105- return str . replace (
106- new RegExp ( arg . slice ( 1 , - 1 ) , 'gi' ) ,
107- bit => markStart + bit + markEnd
108- )
109- }
110-
111- // just a normal string, do the split/map thing
112- var pieces = str . toLowerCase ( ) . split ( arg . toLowerCase ( ) )
113- var p = 0
114-
115- return pieces . map ( function ( piece ) {
116- piece = str . slice ( p , p + piece . length )
117- var mark = markStart +
118- str . slice ( p + piece . length , p + piece . length + arg . length ) +
119- markEnd
120- p += piece . length + arg . length
121- return piece + mark
122- } ) . join ( '' )
123- }
124-
125- function colorize ( line ) {
126- for ( var i = 0 ; i < cl ; i ++ ) {
127- var m = i + 1
128- var color = '\u001B[' + colors [ i ] + 'm'
129- line = line . split ( String . fromCharCode ( m ) ) . join ( color )
130- }
131- var uncolor = '\u001B[0m'
132- return line . split ( '\u0000' ) . join ( uncolor )
133- }
13474
135- function highlightSearchTerms ( str , terms ) {
136- terms . forEach ( function ( arg , i ) {
137- str = addColorMarker ( str , arg , i )
138- } )
75+ const columns = [ 'name' , 'description' , 'author' , 'date' , 'version' , 'keywords' ]
76+ if ( this . #opts . parseable ) {
77+ return columns . map ( ( col ) => pkg [ col ] && ( '' + pkg [ col ] ) . replace ( / \t / g , ' ' ) ) . join ( '\t' )
78+ }
13979
140- return colorize ( str ) . trim ( )
141- }
80+ // stdout in tap is never a tty
81+ /* istanbul ignore next */
82+ const maxWidth = process . stdout . isTTY ? process . stdout . getWindowSize ( ) [ 0 ] : Infinity
83+ let output = columnify (
84+ [ pkg ] ,
85+ {
86+ include : columns ,
87+ showHeaders : ++ this . #line <= 1 ,
88+ columnSplitter : ' | ' ,
89+ truncate : ! this . #opts. long ,
90+ config : {
91+ name : { minWidth : 25 , maxWidth : 25 , truncate : false , truncateMarker : '' } ,
92+ description : { minWidth : 20 , maxWidth : 20 } ,
93+ author : { minWidth : 15 , maxWidth : 15 } ,
94+ date : { maxWidth : 11 } ,
95+ version : { minWidth : 8 , maxWidth : 8 } ,
96+ keywords : { maxWidth : Infinity } ,
97+ } ,
98+ }
99+ ) . split ( '\n' ) . map ( line => line . slice ( 0 , maxWidth ) ) . join ( '\n' )
100+
101+ if ( ! this . #opts. color ) {
102+ return output
103+ }
142104
143- function normalizePackage ( data , opts ) {
144- return {
145- name : ansiTrim ( data . name ) ,
146- description : ansiTrim ( data . description ?? '' ) ,
147- author : data . maintainers . map ( ( m ) => `=${ ansiTrim ( m . username ) } ` ) . join ( ' ' ) ,
148- keywords : Array . isArray ( data . keywords )
149- ? data . keywords . map ( ansiTrim ) . join ( ' ' )
150- : typeof data . keywords === 'string'
151- ? ansiTrim ( data . keywords . replace ( / [ , \s ] + / , ' ' ) )
152- : '' ,
153- version : data . version ,
154- date : ( data . date &&
155- ( data . date . toISOString ( ) // remove time
156- . split ( 'T' ) . join ( ' ' )
157- . replace ( / : [ 0 - 9 ] { 2 } \. [ 0 - 9 ] { 3 } Z $ / , '' ) )
158- . slice ( 0 , - 5 ) ) ||
159- 'prehistoric' ,
105+ const colors = [ '31m' , '33m' , '32m' , '36m' , '34m' , '35m' ]
106+
107+ this . #opts. args . forEach ( ( arg , i ) => {
108+ const markStart = String . fromCharCode ( i % colors . length + 1 )
109+ const markEnd = String . fromCharCode ( 0 )
110+
111+ if ( arg . charAt ( 0 ) === '/' ) {
112+ output = output . replace (
113+ new RegExp ( arg . slice ( 1 , - 1 ) , 'gi' ) ,
114+ bit => `${ markStart } ${ bit } ${ markEnd } `
115+ )
116+ } else {
117+ // just a normal string, do the split/map thing
118+ let p = 0
119+
120+ output = output . toLowerCase ( ) . split ( arg . toLowerCase ( ) ) . map ( piece => {
121+ piece = output . slice ( p , p + piece . length )
122+ p += piece . length
123+ const mark = `${ markStart } ${ output . slice ( p , p + arg . length ) } ${ markEnd } `
124+ p += arg . length
125+ return `${ piece } ${ mark } `
126+ } ) . join ( '' )
127+ }
128+ } )
129+
130+ for ( let i = 1 ; i <= colors . length ; i ++ ) {
131+ output = output . split ( String . fromCharCode ( i ) ) . join ( `\u001B[${ colors [ i - 1 ] } ` )
132+ }
133+ return output . split ( '\u0000' ) . join ( '\u001B[0m' ) . trim ( )
160134 }
161135}
0 commit comments