Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / mvdan.cc / xurls / v2@v2.2.0 / xurls.go
1 // Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
2 // See LICENSE for licensing information
3
4 // Package xurls extracts urls from plain text using regular expressions.
5 package xurls
6
7 import (
8         "bytes"
9         "regexp"
10 )
11
12 //go:generate go run generate/tldsgen/main.go
13 //go:generate go run generate/schemesgen/main.go
14
15 const (
16         letter    = `\p{L}`
17         mark      = `\p{M}`
18         number    = `\p{N}`
19         iriChar   = letter + mark + number
20         currency  = `\p{Sc}`
21         otherSymb = `\p{So}`
22         endChar   = iriChar + `/\-_+&~%=#` + currency + otherSymb
23         otherPunc = `\p{Po}`
24         midChar   = endChar + "_*" + otherPunc
25         wellParen = `\([` + midChar + `]*(\([` + midChar + `]*\)[` + midChar + `]*)*\)`
26         wellBrack = `\[[` + midChar + `]*(\[[` + midChar + `]*\][` + midChar + `]*)*\]`
27         wellBrace = `\{[` + midChar + `]*(\{[` + midChar + `]*\}[` + midChar + `]*)*\}`
28         wellAll   = wellParen + `|` + wellBrack + `|` + wellBrace
29         pathCont  = `([` + midChar + `]*(` + wellAll + `|[` + endChar + `])+)+`
30
31         iri      = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
32         domain   = `(` + iri + `\.)+`
33         octet    = `(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
34         ipv4Addr = `\b` + octet + `\.` + octet + `\.` + octet + `\.` + octet + `\b`
35         ipv6Addr = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
36         ipAddr   = `(` + ipv4Addr + `|` + ipv6Addr + `)`
37         port     = `(:[0-9]*)?`
38 )
39
40 // AnyScheme can be passed to StrictMatchingScheme to match any possibly valid
41 // scheme, and not just the known ones.
42 var AnyScheme = `([a-zA-Z][a-zA-Z.\-+]*://|` + anyOf(SchemesNoAuthority...) + `:)`
43
44 // SchemesNoAuthority is a sorted list of some well-known url schemes that are
45 // followed by ":" instead of "://".
46 var SchemesNoAuthority = []string{
47         `bitcoin`, // Bitcoin
48         `file`,    // Files
49         `magnet`,  // Torrent magnets
50         `mailto`,  // Mail
51         `sms`,     // SMS
52         `tel`,     // Telephone
53         `xmpp`,    // XMPP
54 }
55
56 func anyOf(strs ...string) string {
57         var b bytes.Buffer
58         b.WriteByte('(')
59         for i, s := range strs {
60                 if i != 0 {
61                         b.WriteByte('|')
62                 }
63                 b.WriteString(regexp.QuoteMeta(s))
64         }
65         b.WriteByte(')')
66         return b.String()
67 }
68
69 func strictExp() string {
70         schemes := `(` + anyOf(Schemes...) + `://|` + anyOf(SchemesNoAuthority...) + `:)`
71         return `(?i)` + schemes + `(?-i)` + pathCont
72 }
73
74 func relaxedExp() string {
75         punycode := `xn--[a-z0-9-]+`
76         knownTLDs := anyOf(append(TLDs, PseudoTLDs...)...)
77         site := domain + `(?i)(` + punycode + `|` + knownTLDs + `)(?-i)`
78         hostName := `(` + site + `|` + ipAddr + `)`
79         webURL := hostName + port + `(/|/` + pathCont + `)?`
80         return strictExp() + `|` + webURL
81 }
82
83 // Strict produces a regexp that matches any URL with a scheme in either the
84 // Schemes or SchemesNoAuthority lists.
85 func Strict() *regexp.Regexp {
86         re := regexp.MustCompile(strictExp())
87         re.Longest()
88         return re
89 }
90
91 // Relaxed produces a regexp that matches any URL matched by Strict, plus any
92 // URL with no scheme.
93 func Relaxed() *regexp.Regexp {
94         re := regexp.MustCompile(relaxedExp())
95         re.Longest()
96         return re
97 }
98
99 // StrictMatchingScheme produces a regexp similar to Strict, but requiring that
100 // the scheme match the given regular expression. See AnyScheme too.
101 func StrictMatchingScheme(exp string) (*regexp.Regexp, error) {
102         strictMatching := `(?i)(` + exp + `)(?-i)` + pathCont
103         re, err := regexp.Compile(strictMatching)
104         if err != nil {
105                 return nil, err
106         }
107         re.Longest()
108         return re, nil
109 }