Remove last call to Truncate() from parser Autolink detection used to be triggered by a colon and preceding protocol name used to be rewound. Now instead of doing that, trigger autolink processing on [hmfHMF] and see if it looks like a link.
Vytautas Ĺ altenis vytas@rtfb.lt
Tue, 27 Oct 2015 21:56:16 +0200
3 files changed,
51 insertions(+),
14 deletions(-)
M
inline.go
→
inline.go
@@ -38,9 +38,23 @@ p.nesting++
i, end := 0, 0 for i < len(data) { - // copy inactive chars into the output - for end < len(data) && p.inlineCallback[data[end]] == nil { - end++ + // Copy inactive chars into the output, but first check for one quirk: + // 'h', 'm' and 'f' all might trigger a check for autolink processing + // and end this run of inactive characters. However, there's one nasty + // case where breaking this run would be bad: in smartypants fraction + // detection, we expect things like "1/2th" to be in a single run. So + // we check here if an 'h' is followed by 't' (from 'http') and if it's + // not, we short circuit the 'h' into the run of inactive characters. + for end < len(data) { + if p.inlineCallback[data[end]] != nil { + if end+1 < len(data) && data[end] == 'h' && data[end+1] != 't' { + end++ + } else { + break + } + } else { + end++ + } } p.r.NormalText(out, data[i:end])@@ -678,12 +692,32 @@ entityRanges := htmlEntity.FindAllIndex(data[:linkEnd], -1)
return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd } -func autoLink(p *parser, out *bytes.Buffer, data []byte, offset int) int { - // quick check to rule out most false hits on ':' - if p.insideLink || len(data) < offset+3 || data[offset+1] != '/' || data[offset+2] != '/' { +func maybeAutoLink(p *parser, out *bytes.Buffer, data []byte, offset int) int { + // quick check to rule out most false hits + if p.insideLink || len(data) < offset+6 { // 6 is the len() of the shortest prefix below return 0 } + prefixes := []string{ + "http://", + "https://", + "ftp://", + "file://", + "mailto:", + } + for _, prefix := range prefixes { + endOfHead := offset + 8 // 8 is the len() of the longest prefix + if endOfHead > len(data) { + endOfHead = len(data) + } + head := bytes.ToLower(data[offset:endOfHead]) + if bytes.HasPrefix(head, []byte(prefix)) { + return autoLink(p, out, data, offset) + } + } + return 0 +} +func autoLink(p *parser, out *bytes.Buffer, data []byte, offset int) int { // Now a more expensive check to see if we're not inside an anchor element anchorStart := offset offsetFromAnchor := 0@@ -694,7 +728,7 @@ }
anchorStr := anchorRe.Find(data[anchorStart:]) if anchorStr != nil { - out.Write(anchorStr[offsetFromAnchor:]) + out.Write(anchorStr[offsetFromAnchor:]) // XXX: write in parser? return len(anchorStr) - offsetFromAnchor }@@ -788,11 +822,6 @@ linkEnd--
} } - // we were triggered on the ':', so we need to rewind the output a bit - if out.Len() >= rewind { - out.Truncate(len(out.Bytes()) - rewind) - } - var uLink bytes.Buffer unescapeText(&uLink, data[:linkEnd])@@ -800,7 +829,7 @@ if uLink.Len() > 0 {
p.r.AutoLink(out, uLink.Bytes(), LinkTypeNormal) } - return linkEnd - rewind + return linkEnd } func isEndOfLink(char byte) bool {
M
inline_test.go
→
inline_test.go
@@ -808,6 +808,9 @@ "<p><a href=\"http://foo.com/viewtopic.php?param="18"zz\">http://foo.com/viewtopic.php?param="18"zz</a></p>\n",
"http://foo.com/viewtopic.php?param="18"", "<p><a href=\"http://foo.com/viewtopic.php?param="18"\">http://foo.com/viewtopic.php?param="18"</a></p>\n", + + "<a href=\"https://fancy.com\">https://fancy.com</a>\n", + "<p><a href=\"https://fancy.com\">https://fancy.com</a></p>\n", } doLinkTestsInline(t, tests) }
M
markdown.go
→
markdown.go
@@ -379,7 +379,12 @@ p.inlineCallback['^'] = maybeInlineFootnote
p.inlineCallback[' '] = maybeLineBreak if extensions&Autolink != 0 { - p.inlineCallback[':'] = autoLink + p.inlineCallback['h'] = maybeAutoLink + p.inlineCallback['m'] = maybeAutoLink + p.inlineCallback['f'] = maybeAutoLink + p.inlineCallback['H'] = maybeAutoLink + p.inlineCallback['M'] = maybeAutoLink + p.inlineCallback['F'] = maybeAutoLink } if extensions&Footnotes != 0 {