@@ -16,6 +16,7 @@ import (
16
16
"net/url"
17
17
"os"
18
18
"os/exec"
19
+ "regexp"
19
20
"sort"
20
21
"strconv"
21
22
"strings"
@@ -180,55 +181,61 @@ var (
180
181
removedCodePrefix = []byte (`<span class="removed-code">` )
181
182
codeTagSuffix = []byte (`</span>` )
182
183
)
184
+ var addSpanRegex = regexp .MustCompile (`<span class="[a-z]*$` )
183
185
184
186
func diffToHTML (fileName string , diffs []diffmatchpatch.Diff , lineType DiffLineType ) template.HTML {
185
187
buf := bytes .NewBuffer (nil )
186
- var addSpan bool
188
+ var addSpan string
187
189
for i := range diffs {
188
190
switch {
189
191
case diffs [i ].Type == diffmatchpatch .DiffEqual :
190
192
// Looking for the case where our 3rd party diff library previously detected a string difference
191
193
// in the middle of a span class because we highlight them first. This happens when added/deleted code
192
- // also changes the chroma class name. If found, just move the openining span code forward into the next section
193
- if addSpan {
194
- diffs [i ].Text = "<span class=\" " + diffs [i ].Text
194
+ // also changes the chroma class name, either partially or fully. If found, just move the openining span code forward into the next section
195
+ // see TestDiffToHTML for examples
196
+ if len (addSpan ) > 0 {
197
+ diffs [i ].Text = addSpan + diffs [i ].Text
198
+ addSpan = ""
195
199
}
196
- if strings .HasSuffix (diffs [i ].Text , "<span class=\" " ) {
197
- addSpan = true
198
- buf .WriteString (strings .TrimSuffix (diffs [i ].Text , "<span class=\" " ))
200
+ m := addSpanRegex .FindStringSubmatchIndex (diffs [i ].Text )
201
+ if m != nil {
202
+ addSpan = diffs [i ].Text [m [0 ]:m [1 ]]
203
+ buf .WriteString (strings .TrimSuffix (diffs [i ].Text , addSpan ))
199
204
} else {
200
- addSpan = false
205
+ addSpan = ""
201
206
buf .WriteString (getLineContent (diffs [i ].Text ))
202
207
}
203
208
case diffs [i ].Type == diffmatchpatch .DiffInsert && lineType == DiffLineAdd :
204
- if addSpan {
205
- addSpan = false
206
- diffs [ i ]. Text = "<span class= \" " + diffs [ i ]. Text
209
+ if len ( addSpan ) > 0 {
210
+ diffs [ i ]. Text = addSpan + diffs [ i ]. Text
211
+ addSpan = ""
207
212
}
208
213
// Print existing closing span first before opening added-code span so it doesn't unintentionally close it
209
214
if strings .HasPrefix (diffs [i ].Text , "</span>" ) {
210
215
buf .WriteString ("</span>" )
211
216
diffs [i ].Text = strings .TrimPrefix (diffs [i ].Text , "</span>" )
212
217
}
213
- if strings .HasSuffix (diffs [i ].Text , "<span class=\" " ) {
214
- addSpan = true
215
- diffs [i ].Text = strings .TrimSuffix (diffs [i ].Text , "<span class=\" " )
218
+ m := addSpanRegex .FindStringSubmatchIndex (diffs [i ].Text )
219
+ if m != nil {
220
+ addSpan = diffs [i ].Text [m [0 ]:m [1 ]]
221
+ diffs [i ].Text = strings .TrimSuffix (diffs [i ].Text , addSpan )
216
222
}
217
223
buf .Write (addedCodePrefix )
218
224
buf .WriteString (getLineContent (diffs [i ].Text ))
219
225
buf .Write (codeTagSuffix )
220
226
case diffs [i ].Type == diffmatchpatch .DiffDelete && lineType == DiffLineDel :
221
- if addSpan {
222
- addSpan = false
223
- diffs [ i ]. Text = "<span class= \" " + diffs [ i ]. Text
227
+ if len ( addSpan ) > 0 {
228
+ diffs [ i ]. Text = addSpan + diffs [ i ]. Text
229
+ addSpan = ""
224
230
}
225
231
if strings .HasPrefix (diffs [i ].Text , "</span>" ) {
226
232
buf .WriteString ("</span>" )
227
233
diffs [i ].Text = strings .TrimPrefix (diffs [i ].Text , "</span>" )
228
234
}
229
- if strings .HasSuffix (diffs [i ].Text , "<span class=\" " ) {
230
- addSpan = true
231
- diffs [i ].Text = strings .TrimSuffix (diffs [i ].Text , "<span class=\" " )
235
+ m := addSpanRegex .FindStringSubmatchIndex (diffs [i ].Text )
236
+ if m != nil {
237
+ addSpan = diffs [i ].Text [m [0 ]:m [1 ]]
238
+ diffs [i ].Text = strings .TrimSuffix (diffs [i ].Text , addSpan )
232
239
}
233
240
buf .Write (removedCodePrefix )
234
241
buf .WriteString (getLineContent (diffs [i ].Text ))
0 commit comments