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 | 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 5x 5x 5x 5x 2x 1x 1x 6x 2x 2x 2x 2x 6x 1x 1x 1x 6x 1x 1x 1x 1x 1x | import {diffLines} from 'diff'
import {chartToChordsOverWords, parseChordPro} from './chordpro'
export type DiffRow = {kind: 'same' | 'added' | 'removed'; text: string}
/**
* Line diff between two chart versions, compared as chords-over-lyrics text
* (what musicians read) rather than raw ChordPro. Long unchanged stretches are
* folded to a few lines of context either side of each change.
*/
export function chartDiff(
before: string,
after: string,
context = 2,
): DiffRow[] {
const a = chartToChordsOverWords(parseChordPro(before))
const b = chartToChordsOverWords(parseChordPro(after))
const rows: DiffRow[] = []
for (const part of diffLines(a ? a + '\n' : '', b ? b + '\n' : '')) {
const kind = part.added ? 'added' : part.removed ? 'removed' : 'same'
for (const text of part.value.replace(/\n$/, '').split('\n'))
rows.push({kind, text})
}
if (!rows.some((r) => r.kind !== 'same')) return []
const keep = rows.map(() => false)
rows.forEach((r, i) => {
if (r.kind === 'same') return
for (
let j = Math.max(0, i - context);
j <= Math.min(rows.length - 1, i + context);
j++
)
keep[j] = true
})
const out: DiffRow[] = []
rows.forEach((r, i) => {
if (keep[i]) out.push(r)
else if (keep[i - 1] || (i === 0 && !keep[0]))
out.push({kind: 'same', text: '…'})
})
return out
}
|