| 1 | const { escape } = require('./render'); |
| 2 | const config = require('./config'); |
| 3 | |
| 4 | function render(rawDiff) { |
| 5 | const maxLines = config.get('repos.maxRenderDiffLines') || 5000; |
| 6 | const lines = rawDiff.split('\n'); |
| 7 | if (lines.length > maxLines) { |
| 8 | return `<p class="diff-truncated">Diff too large (${lines.length} lines). Showing raw only.</p>`; |
| 9 | } |
| 10 | |
| 11 | const out = []; |
| 12 | let inFile = false; |
| 13 | |
| 14 | for (const line of lines) { |
| 15 | if (line.startsWith('diff --git ')) { |
| 16 | if (inFile) out.push('</tbody></table></div>'); |
| 17 | const m = line.match(/diff --git a\/.+ b\/(.+)$/); |
| 18 | const fname = m ? m[1] : line.slice(11); |
| 19 | out.push(`<div class="diff-file">`); |
| 20 | out.push(`<div class="diff-filename">${escape(fname)}</div>`); |
| 21 | out.push(`<table class="diff-table"><tbody>`); |
| 22 | inFile = true; |
| 23 | continue; |
| 24 | } |
| 25 | |
| 26 | if (!inFile) continue; |
| 27 | |
| 28 | if (line.startsWith('index ') || |
| 29 | line.startsWith('--- ') || |
| 30 | line.startsWith('+++ ') || |
| 31 | line.startsWith('old mode') || |
| 32 | line.startsWith('new mode') || |
| 33 | line.startsWith('new file') || |
| 34 | line.startsWith('deleted file') || |
| 35 | line.startsWith('rename ') || |
| 36 | line.startsWith('similarity ')) { |
| 37 | if (line.startsWith('Binary files')) { |
| 38 | out.push(`<tr><td colspan="2" class="diff-binary">${escape(line)}</td></tr>`); |
| 39 | } |
| 40 | continue; |
| 41 | } |
| 42 | |
| 43 | if (line.startsWith('@@ ')) { |
| 44 | out.push(`<tr><td colspan="2" class="diff-hunk">${escape(line)}</td></tr>`); |
| 45 | continue; |
| 46 | } |
| 47 | |
| 48 | if (line.startsWith('+')) { |
| 49 | out.push(`<tr class="diff-add"><td class="diff-sign">+</td><td class="diff-code"><code>${escape(line.slice(1))}</code></td></tr>`); |
| 50 | } else if (line.startsWith('-')) { |
| 51 | out.push(`<tr class="diff-del"><td class="diff-sign">-</td><td class="diff-code"><code>${escape(line.slice(1))}</code></td></tr>`); |
| 52 | } else { |
| 53 | const content = line.startsWith(' ') ? line.slice(1) : line; |
| 54 | out.push(`<tr class="diff-ctx"><td class="diff-sign"></td><td class="diff-code"><code>${escape(content)}</code></td></tr>`); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | if (inFile) out.push('</tbody></table></div>'); |
| 59 | return out.join('\n'); |
| 60 | } |
| 61 | |
| 62 | module.exports = { render }; |
| 63 | |