|
54 | 54 | shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
|
55 | 55 |
|
56 | 56 | // anyHashPattern splits url containing SHA into parts
|
57 |
| - anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`) |
| 57 | + anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~%./\w]+)?(\?[-+~%.\w&=]+)?(#[-+~%.\w]+)?`) |
58 | 58 |
|
59 | 59 | // comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
|
60 | 60 | comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
|
@@ -963,57 +963,62 @@ func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
|
963 | 963 | }
|
964 | 964 | }
|
965 | 965 |
|
966 |
| -// fullHashPatternProcessor renders SHA containing URLs |
967 |
| -func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) { |
968 |
| - if ctx.Metas == nil { |
969 |
| - return |
970 |
| - } |
971 |
| - |
972 |
| - next := node.NextSibling |
973 |
| - for node != nil && node != next { |
974 |
| - m := anyHashPattern.FindStringSubmatchIndex(node.Data) |
975 |
| - if m == nil { |
976 |
| - return |
977 |
| - } |
| 966 | +type anyHashPatternResult struct { |
| 967 | + PosStart int |
| 968 | + PosEnd int |
| 969 | + FullURL string |
| 970 | + CommitID string |
| 971 | + SubPath string |
| 972 | + QueryHash string |
| 973 | +} |
978 | 974 |
|
979 |
| - urlFull := node.Data[m[0]:m[1]] |
980 |
| - text := base.ShortSha(node.Data[m[2]:m[3]]) |
| 975 | +func anyHashPatternExtract(s string) (ret anyHashPatternResult, ok bool) { |
| 976 | + m := anyHashPattern.FindStringSubmatchIndex(s) |
| 977 | + if m == nil { |
| 978 | + return ret, false |
| 979 | + } |
981 | 980 |
|
982 |
| - // 3rd capture group matches a optional path |
983 |
| - subpath := "" |
984 |
| - if m[5] > 0 { |
985 |
| - subpath = node.Data[m[4]:m[5]] |
| 981 | + ret.PosStart, ret.PosEnd = m[0], m[1] |
| 982 | + ret.FullURL = s[ret.PosStart:ret.PosEnd] |
| 983 | + if strings.HasSuffix(ret.FullURL, ".") { |
| 984 | + ret.PosEnd-- |
| 985 | + ret.FullURL = ret.FullURL[:len(ret.FullURL)-1] |
| 986 | + for i := 0; i < len(m); i++ { |
| 987 | + m[i] = min(m[i], ret.PosEnd) |
986 | 988 | }
|
| 989 | + } |
987 | 990 |
|
988 |
| - // 4th capture group matches a optional url hash |
989 |
| - hash := "" |
990 |
| - if m[7] > 0 { |
991 |
| - hash = node.Data[m[6]:m[7]][1:] |
992 |
| - } |
| 991 | + ret.CommitID = s[m[2]:m[3]] |
| 992 | + if m[5] > 0 { |
| 993 | + ret.SubPath = s[m[4]:m[5]] |
| 994 | + } |
993 | 995 |
|
994 |
| - start := m[0] |
995 |
| - end := m[1] |
| 996 | + lastStart, lastEnd := m[len(m)-2], m[len(m)-1] |
| 997 | + if lastEnd > 0 { |
| 998 | + ret.QueryHash = s[lastStart:lastEnd][1:] |
| 999 | + } |
| 1000 | + return ret, true |
| 1001 | +} |
996 | 1002 |
|
997 |
| - // If url ends in '.', it's very likely that it is not part of the |
998 |
| - // actual url but used to finish a sentence. |
999 |
| - if strings.HasSuffix(urlFull, ".") { |
1000 |
| - end-- |
1001 |
| - urlFull = urlFull[:len(urlFull)-1] |
1002 |
| - if hash != "" { |
1003 |
| - hash = hash[:len(hash)-1] |
1004 |
| - } else if subpath != "" { |
1005 |
| - subpath = subpath[:len(subpath)-1] |
1006 |
| - } |
| 1003 | +// fullHashPatternProcessor renders SHA containing URLs |
| 1004 | +func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) { |
| 1005 | + if ctx.Metas == nil { |
| 1006 | + return |
| 1007 | + } |
| 1008 | + for node != nil { |
| 1009 | + ret, ok := anyHashPatternExtract(node.Data) |
| 1010 | + if !ok { |
| 1011 | + node = node.NextSibling |
| 1012 | + continue |
1007 | 1013 | }
|
1008 |
| - |
1009 |
| - if subpath != "" { |
1010 |
| - text += subpath |
| 1014 | + text := base.ShortSha(ret.CommitID) |
| 1015 | + if ret.SubPath != "" { |
| 1016 | + text += ret.SubPath |
1011 | 1017 | }
|
1012 |
| - |
1013 |
| - if hash != "" { |
1014 |
| - text += " (" + hash + ")" |
| 1018 | + if ret.QueryHash != "" { |
| 1019 | + text += " (" + ret.QueryHash + ")" |
1015 | 1020 | }
|
1016 |
| - replaceContent(node, start, end, createCodeLink(urlFull, text, "commit")) |
| 1021 | + replaceContent(node, ret.PosStart, ret.PosEnd, createCodeLink(ret.FullURL, text, "commit")) |
1017 | 1022 | node = node.NextSibling.NextSibling
|
1018 | 1023 | }
|
1019 | 1024 | }
|
|
0 commit comments