1
1
const fs = require ( 'fs' )
2
+ const { EOL } = require ( 'os' )
2
3
const { promisify } = require ( 'util' )
4
+ const ansi = require ( 'ansi-styles' )
3
5
const Arborist = require ( '@npmcli/arborist' )
4
6
const jsDiff = require ( 'diff' )
5
7
const pacote = require ( 'pacote' )
@@ -50,6 +52,8 @@ const getMime = () => {
50
52
'patents' ,
51
53
'readme' ,
52
54
'ts' ,
55
+ 'yml' ,
56
+ 'yaml' ,
53
57
'flow'
54
58
] , 'text/plain' )
55
59
@@ -112,7 +116,34 @@ const untar = ({ files, item, prefix, opts, refs }) =>
112
116
. end ( item )
113
117
} )
114
118
115
- const printDiff = ( { files, refs, versions } ) => {
119
+ const colorizeDiff = ( { res, headerLength } ) => {
120
+ const colors = {
121
+ charsRemoved : ansi . bgRed ,
122
+ charsAdded : ansi . bgGreen ,
123
+ removed : ansi . red ,
124
+ added : ansi . green ,
125
+ header : ansi . yellow ,
126
+ section : ansi . magenta
127
+ }
128
+ const colorize = ( str , colorId ) => {
129
+ var { open, close } = colors [ colorId ]
130
+ // avoid highlighting the "\n" (would highlight till the end of the line)
131
+ return str . replace ( / [ ^ \n \r ] + / g, open + '$&' + close )
132
+ }
133
+
134
+ // this RegExp will include all the `\n` chars into the lines, easier to join
135
+ const lines = res . split ( / ^ / m)
136
+
137
+ const start = colorize ( lines . slice ( 0 , headerLength || 2 ) . join ( '' ) , 'header' )
138
+ const end = lines . slice ( headerLength || 2 ) . join ( '' )
139
+ . replace ( / ^ - .* / gm, colorize ( '$&' , 'removed' ) )
140
+ . replace ( / ^ \+ .* / gm, colorize ( '$&' , 'added' ) )
141
+ . replace ( / ^ @ @ .+ @ @ / gm, colorize ( '$&' , 'section' ) )
142
+
143
+ return start + end
144
+ }
145
+
146
+ const printDiff = ( { files, opts, refs, versions } ) => {
116
147
for ( const filename of files . values ( ) ) {
117
148
const names = {
118
149
a : `a/${ filename } ` ,
@@ -135,9 +166,31 @@ const printDiff = ({ files, refs, versions }) => {
135
166
136
167
if ( contents . a === contents . b ) continue
137
168
138
- let res
169
+ let res = ''
170
+ let headerLength = 0
171
+ const header = str => {
172
+ headerLength ++
173
+ res += `${ str } ${ EOL } `
174
+ }
175
+
176
+ // manually build a git diff-compatible header
177
+ header ( `diff --git ${ names . a } ${ names . b } ` )
178
+ if ( modes . a === modes . b ) {
179
+ fileMode = filenames . a . mode
180
+ } else {
181
+ if ( modes . a && modes . b ) {
182
+ header ( `old mode ${ modes . a } ` )
183
+ header ( `new mode ${ modes . b } ` )
184
+ } else if ( modes . a && ! modes . b ) {
185
+ header ( `deleted file mode ${ modes . a } ` )
186
+ } else if ( ! modes . a && modes . b ) {
187
+ header ( `new file mode ${ modes . b } ` )
188
+ }
189
+ }
190
+ header ( `index ${ versions . a } ..${ versions . b } ${ fileMode } ` )
191
+
139
192
if ( diffFileType ( filename ) ) {
140
- res = jsDiff . createTwoFilesPatch (
193
+ res + = jsDiff . createTwoFilesPatch (
141
194
names . a ,
142
195
names . b ,
143
196
contents . a || '' ,
@@ -149,27 +202,17 @@ const printDiff = ({ files, refs, versions }) => {
149
202
'===================================================================\n' ,
150
203
''
151
204
)
205
+ headerLength += 2
152
206
} else {
153
- res = `--- ${ names . a } \n+++ ${ names . b } `
207
+ header ( `--- ${ names . a } ` )
208
+ header ( `+++ ${ names . b } ` )
154
209
}
155
210
156
- output ( `diff --git ${ names . a } ${ names . b } ` )
157
-
158
- if ( modes . a === modes . b ) {
159
- fileMode = filenames . a . mode
160
- } else {
161
- if ( modes . a && modes . b ) {
162
- output ( `old mode ${ modes . a } ` )
163
- output ( `new mode ${ modes . b } ` )
164
- } else if ( modes . a && ! modes . b ) {
165
- output ( `deleted file mode ${ modes . a } ` )
166
- } else if ( ! modes . a && modes . b ) {
167
- output ( `new file mode ${ modes . b } ` )
168
- }
169
- }
170
-
171
- output ( `index ${ versions . a } ..${ versions . b } ${ fileMode } ` )
172
- output ( res )
211
+ output (
212
+ opts . color
213
+ ? colorizeDiff ( { res, headerLength } )
214
+ : res
215
+ )
173
216
}
174
217
}
175
218
@@ -224,6 +267,7 @@ const diffSelf = async () => {
224
267
225
268
printDiff ( {
226
269
files,
270
+ opts,
227
271
refs,
228
272
versions
229
273
} )
@@ -293,6 +337,7 @@ const diffComparison = async (specs) => {
293
337
294
338
printDiff ( {
295
339
files,
340
+ opts,
296
341
refs,
297
342
versions
298
343
} )
0 commit comments