|
147 | 147 | .replace(/\r\n?/g, '\n')
|
148 | 148 | .split('\n');
|
149 | 149 |
|
| 150 | + /* Diff Header */ |
| 151 | + var oldFileNameHeader = '--- '; |
| 152 | + var newFileNameHeader = '+++ '; |
| 153 | + var hunkHeaderPrefix = '@@'; |
| 154 | + |
150 | 155 | /* Diff */
|
151 | 156 | var oldMode = /^old mode (\d{6})/;
|
152 | 157 | var newMode = /^new mode (\d{6})/;
|
|
169 | 174 | var combinedNewFile = /^new file mode (\d{6})/;
|
170 | 175 | var combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/;
|
171 | 176 |
|
172 |
| - diffLines.forEach(function(line) { |
| 177 | + diffLines.forEach(function(line, lineIndex) { |
173 | 178 | // Unmerged paths, and possibly other non-diffable files
|
174 | 179 | // https://github.com/scottgonzalez/pretty-diff/issues/11
|
175 | 180 | // Also, remove some useless lines
|
176 | 181 | if (!line || utils.startsWith(line, '*')) {
|
177 | 182 | return;
|
178 | 183 | }
|
179 | 184 |
|
180 |
| - if ( |
181 |
| - utils.startsWith(line, 'diff') || // Git diffs always start with diff |
182 |
| - !currentFile || // If we do not have a file yet, we should crete one |
| 185 | + var prevLine = diffLines[lineIndex - 1]; |
| 186 | + var nxtLine = diffLines[lineIndex + 1]; |
| 187 | + var afterNxtLine = diffLines[lineIndex + 2]; |
| 188 | + |
| 189 | + if (utils.startsWith(line, 'diff')) { |
| 190 | + startFile(); |
| 191 | + currentFile.isGitDiff = true; |
| 192 | + return; |
| 193 | + } |
| 194 | + |
| 195 | + if (!currentFile || // If we do not have a file yet, we should crete one |
183 | 196 | (
|
184 |
| - currentFile && // If we already have some file in progress and |
| 197 | + !currentFile.isGitDiff && currentFile && // If we already have some file in progress and |
185 | 198 | (
|
186 |
| - currentFile.oldName && utils.startsWith(line, '--- ') || // Either we reached a old file identification line |
187 |
| - currentFile.newName && utils.startsWith(line, '+++ ') // Or we reached a new file identification line |
| 199 | + utils.startsWith(line, oldFileNameHeader) && // If we get to an old file path header line |
| 200 | + // And is followed by the new file path header line and the hunk header line |
| 201 | + utils.startsWith(nxtLine, newFileNameHeader) && utils.startsWith(afterNxtLine, hunkHeaderPrefix) |
188 | 202 | )
|
189 | 203 | )
|
190 | 204 | ) {
|
|
194 | 208 | var values;
|
195 | 209 |
|
196 | 210 | /*
|
197 |
| - * --- Date Timestamp[FractionalSeconds] TimeZone |
198 |
| - * --- 2002-02-21 23:30:39.942229878 -0800 |
| 211 | + * We need to make sure that we have the three lines of the header. |
| 212 | + * This avoids cases like the ones described in: |
| 213 | + * - https://github.com/rtfpessoa/diff2html/issues/87 |
199 | 214 | */
|
200 |
| - if (currentFile && !currentFile.oldName && |
201 |
| - utils.startsWith(line, '--- ') && (values = getSrcFilename(line, config))) { |
202 |
| - currentFile.oldName = values; |
203 |
| - currentFile.language = getExtension(currentFile.oldName, currentFile.language); |
204 |
| - return; |
205 |
| - } |
| 215 | + if ( |
| 216 | + (utils.startsWith(line, oldFileNameHeader) && |
| 217 | + utils.startsWith(nxtLine, newFileNameHeader) && utils.startsWith(afterNxtLine, hunkHeaderPrefix)) || |
| 218 | + |
| 219 | + (utils.startsWith(line, newFileNameHeader) && |
| 220 | + utils.startsWith(prevLine, oldFileNameHeader) && utils.startsWith(nxtLine, hunkHeaderPrefix)) |
| 221 | + ) { |
| 222 | + |
| 223 | + /* |
| 224 | + * --- Date Timestamp[FractionalSeconds] TimeZone |
| 225 | + * --- 2002-02-21 23:30:39.942229878 -0800 |
| 226 | + */ |
| 227 | + if (currentFile && !currentFile.oldName && |
| 228 | + utils.startsWith(line, '--- ') && (values = getSrcFilename(line, config))) { |
| 229 | + currentFile.oldName = values; |
| 230 | + currentFile.language = getExtension(currentFile.oldName, currentFile.language); |
| 231 | + return; |
| 232 | + } |
| 233 | + |
| 234 | + /* |
| 235 | + * +++ Date Timestamp[FractionalSeconds] TimeZone |
| 236 | + * +++ 2002-02-21 23:30:39.942229878 -0800 |
| 237 | + */ |
| 238 | + if (currentFile && !currentFile.newName && |
| 239 | + utils.startsWith(line, '+++ ') && (values = getDstFilename(line, config))) { |
| 240 | + currentFile.newName = values; |
| 241 | + currentFile.language = getExtension(currentFile.newName, currentFile.language); |
| 242 | + return; |
| 243 | + } |
206 | 244 |
|
207 |
| - /* |
208 |
| - * +++ Date Timestamp[FractionalSeconds] TimeZone |
209 |
| - * +++ 2002-02-21 23:30:39.942229878 -0800 |
210 |
| - */ |
211 |
| - if (currentFile && !currentFile.newName && |
212 |
| - utils.startsWith(line, '+++ ') && (values = getDstFilename(line, config))) { |
213 |
| - currentFile.newName = values; |
214 |
| - currentFile.language = getExtension(currentFile.newName, currentFile.language); |
215 |
| - return; |
216 | 245 | }
|
217 | 246 |
|
218 |
| - if (currentFile && utils.startsWith(line, '@')) { |
| 247 | + if (currentFile && utils.startsWith(line, hunkHeaderPrefix)) { |
219 | 248 | startBlock(line);
|
220 | 249 | return;
|
221 | 250 | }
|
|
231 | 260 | return;
|
232 | 261 | }
|
233 | 262 |
|
234 |
| - if ( |
235 |
| - (currentFile && currentFile.blocks.length) || |
236 |
| - (currentBlock && currentBlock.lines.length) |
237 |
| - ) { |
238 |
| - startFile(); |
239 |
| - } |
240 |
| - |
241 | 263 | /*
|
242 | 264 | * Git diffs provide more information regarding files modes, renames, copies,
|
243 | 265 | * commits between changes and similarity indexes
|
|
0 commit comments