| 120 | |
| 121 | // Pure comparison: returns null when in sync, otherwise a drift descriptor. |
| 122 | function diffTexts(name, expected, actual) { |
| 123 | if (expected === actual) return null; |
| 124 | const expectedLines = expected.split(/\r?\n/); |
| 125 | const actualLines = actual.split(/\r?\n/); |
| 126 | const max = Math.max(expectedLines.length, actualLines.length); |
| 127 | for (let index = 0; index < max; index++) { |
| 128 | if (expectedLines[index] !== actualLines[index]) { |
| 129 | return { |
| 130 | name, |
| 131 | reason: `first difference at line ${index + 1}`, |
| 132 | expectedLine: expectedLines[index], |
| 133 | actualLine: actualLines[index], |
| 134 | }; |
| 135 | } |
| 136 | } |
| 137 | return { name, reason: 'line-ending difference' }; |
| 138 | } |
| 139 | |
| 140 | function checkProject(projectRoot) { |
| 141 | const { surfaces } = expectedSurfaces(projectRoot); |