Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 15x 15x 15x 15x 108x 108x 108x 108x 108x 15x 5x 5x 5x 5x 23x 23x 108x 108x 108x 108x 23x 3x 3x 23x 15x 11x 5x 5x 5x 19x 12x 11x 15x 5x 5x 5x 5x 5x 5x 5x 5x 5x 19x 19x 19x 6x 6x 6x 13x 5x 5x 5x 8x 8x 8x 8x 19x 4x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x | import { diffLines, Change } from 'diff'
import chalk from 'chalk'
import { isNil } from 'ramda'
const createLineNumberFormater = (maxOldLineNumberLength: number, maxNewLineNumberLength: number) => (oldNumber: number | null, newNumber: number | null) => {
const oldNumberStr = isNil(oldNumber) ? ' ' : String(oldNumber)
const newNumberStr = isNil(newNumber) ? ' ' : String(newNumber)
const oldN = oldNumberStr.padEnd(maxOldLineNumberLength, ' ')
const newN = newNumberStr.padEnd(maxNewLineNumberLength, ' ')
return `${oldN}|${newN} `
}
type LineFormater = (oldNumber: number | null, newNumber: number | null, tag: string, str: string, fold?: boolean) => string
const createLineFormater = (maxOldLineNumber: number, maxNewLineNumber: number): LineFormater => {
const maxOldLineNumberLength = String(maxOldLineNumber).length
const maxNewLineNumberLength = String(maxNewLineNumber).length
const formatLineNumber = createLineNumberFormater(maxOldLineNumberLength, maxNewLineNumberLength)
return (oldNumber, newNumber, tag, str, fold) => {
let lines = str.match(/((.*\n)|(.+$))/g) || []
lines = lines
.map((line, i) => {
const oldNumberWithOffset = oldNumber && oldNumber + i
const newNumberWithOffset = newNumber && newNumber + i
const lineNumber = formatLineNumber(oldNumberWithOffset, newNumberWithOffset)
return `${lineNumber} ${tag} ${line.replace(/(\n$)/, '')}\n`
})
if (fold && lines.length > 2) {
const dot = '...\n'.padStart(maxOldLineNumberLength + 3, ' ')
lines.splice(1, lines.length - 2, dot)
}
return lines.join('')
}
}
type EndLineValidater = (i: number) => boolean
const createEndLineValider = (diffPairs: Change[]): EndLineValidater => {
const index = [...diffPairs].reverse().findIndex(item => !item.added && !item.removed)
const count = diffPairs.length - 1
const lastSamePairIndex = index >= 0 ? count - index : index
return i => {
if (lastSamePairIndex < i) return true
else if (lastSamePairIndex === diffPairs.length - 1 && lastSamePairIndex === i) return true
return false
}
}
interface ShowDiffOptions {
fold?: boolean
}
export default function showDiff(
filename: string,
oldContent: string,
newContent: string,
options: ShowDiffOptions = {}
): string {
let str = ''
let oldLineNumber = 1
let newLineNumber = 1
const maxOldLineNumber = oldContent.split('\n').length
const maxNewLineNumber = oldContent.split('\n').length
const formatLine = createLineFormater(maxOldLineNumber, maxNewLineNumber)
const diffPairs = diffLines(oldContent, newContent)
const isEndLine = createEndLineValider(diffPairs)
diffPairs.forEach(({ added, removed, value }, i) => {
const needFillEndLine = isEndLine(i)
const inc = value.split('\n').length - 1
if (added) {
const strWithoutColor = formatLine(null, newLineNumber, '+', value)
str += chalk.green(strWithoutColor)
newLineNumber += inc
} else if (removed) {
const strWithoutColor = formatLine(oldLineNumber, null, '-', value)
str += chalk.red(strWithoutColor)
oldLineNumber += inc
} else {
const strWithoutColor = formatLine(oldLineNumber, newLineNumber, ' ', value, options.fold)
str += chalk.grey(strWithoutColor)
newLineNumber += inc
oldLineNumber += inc
}
/**
* Add an empty line,
* if '\n' at the end of file.
* So, It's easy to tell if the last line end with '\n'
*/
if (needFillEndLine && /\n$/.test(value)) {
if (added) {
const strWithoutColor = formatLine(null, newLineNumber, '+', '\n')
str += chalk.green(strWithoutColor)
newLineNumber += 1
} else if (removed) {
const strWithoutColor = formatLine(oldLineNumber, null, '-', '\n')
str += chalk.red(strWithoutColor)
oldLineNumber += 1
} else {
const strWithoutColor = formatLine(oldLineNumber, newLineNumber, ' ', '\n')
str += chalk.grey(strWithoutColor)
newLineNumber += 1
oldLineNumber += 1
}
}
})
const headerLength = filename.length + 4
const header = chalk.yellow([
Array(headerLength).fill('=').join(''),
` ${filename} `,
Array(headerLength).fill('-').join(''),
].join('\n'))
const footer = chalk.yellow(Array(headerLength).fill('=').join(''))
return ['\n', header, str, footer].join('\n')
}
|