summaryrefslogtreecommitdiffstats
path: root/vendor/gitlab.com/golang-commonmark/mdurl/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gitlab.com/golang-commonmark/mdurl/parse.go')
-rw-r--r--vendor/gitlab.com/golang-commonmark/mdurl/parse.go146
1 files changed, 146 insertions, 0 deletions
diff --git a/vendor/gitlab.com/golang-commonmark/mdurl/parse.go b/vendor/gitlab.com/golang-commonmark/mdurl/parse.go
new file mode 100644
index 00000000..595fcdea
--- /dev/null
+++ b/vendor/gitlab.com/golang-commonmark/mdurl/parse.go
@@ -0,0 +1,146 @@
+// Copyright 2015 The Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mdurl
+
+import (
+ "errors"
+ "strings"
+)
+
+// ErrMissingScheme error is returned by Parse if the passed URL starts with a colon.
+var ErrMissingScheme = errors.New("missing protocol scheme")
+
+var slashedProtocol = map[string]bool{
+ "http": true,
+ "https": true,
+ "ftp": true,
+ "gopher": true,
+ "file": true,
+}
+
+func split(s string, c byte) (string, string, bool) {
+ i := strings.IndexByte(s, c)
+ if i < 0 {
+ return s, "", false
+ }
+ return s[:i], s[i+1:], true
+}
+
+func findScheme(s string) (int, error) {
+ if s == "" {
+ return 0, nil
+ }
+
+ b := s[0]
+ if b == ':' {
+ return 0, ErrMissingScheme
+ }
+ if !letter(b) {
+ return 0, nil
+ }
+
+ for i := 1; i < len(s); i++ {
+ b := s[i]
+ switch {
+ case b == ':':
+ return i, nil
+ case strings.IndexByte("+-.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", b) != -1:
+ // do nothing
+ default:
+ return 0, nil
+ }
+ }
+
+ return 0, nil
+}
+
+// Parse parses rawurl into a URL structure.
+func Parse(rawurl string) (*URL, error) {
+ n, err := findScheme(rawurl)
+ if err != nil {
+ return nil, err
+ }
+
+ var url URL
+ rest := rawurl
+ hostless := false
+ if n > 0 {
+ url.RawScheme = rest[:n]
+ url.Scheme, rest = strings.ToLower(rest[:n]), rest[n+1:]
+ if url.Scheme == "javascript" {
+ hostless = true
+ }
+ }
+
+ if !hostless && strings.HasPrefix(rest, "//") {
+ url.Slashes, rest = true, rest[2:]
+ }
+
+ if !hostless && (url.Slashes || (url.Scheme != "" && !slashedProtocol[url.Scheme])) {
+ hostEnd := strings.IndexAny(rest, "#/?")
+ atSign := -1
+ i := hostEnd
+ if i == -1 {
+ i = len(rest) - 1
+ }
+ for i >= 0 {
+ if rest[i] == '@' {
+ atSign = i
+ break
+ }
+ i--
+ }
+
+ if atSign != -1 {
+ url.Auth, rest = rest[:atSign], rest[atSign+1:]
+ }
+
+ hostEnd = strings.IndexAny(rest, "\t\r\n \"#%'/;<>?\\^`{|}")
+ if hostEnd == -1 {
+ hostEnd = len(rest)
+ }
+ if hostEnd > 0 && hostEnd < len(rest) && rest[hostEnd-1] == ':' {
+ hostEnd--
+ }
+ host := rest[:hostEnd]
+
+ if len(host) > 1 {
+ b := host[hostEnd-1]
+ if digit(b) {
+ for i := len(host) - 2; i >= 0; i-- {
+ b := host[i]
+ if b == ':' {
+ url.Host, url.Port = host[:i], host[i+1:]
+ break
+ }
+ if !digit(b) {
+ break
+ }
+ }
+ } else if b == ':' {
+ host = host[:hostEnd-1]
+ hostEnd--
+ }
+ }
+ if url.Port == "" {
+ url.Host = host
+ }
+ rest = rest[hostEnd:]
+
+ if ipv6 := len(url.Host) > 2 &&
+ url.Host[0] == '[' &&
+ url.Host[len(url.Host)-1] == ']'; ipv6 {
+ url.Host = url.Host[1 : len(url.Host)-1]
+ url.IPv6 = true
+ } else if i := strings.IndexByte(url.Host, ':'); i >= 0 {
+ url.Host, rest = url.Host[:i], url.Host[i:]+rest
+ }
+ }
+
+ rest, url.Fragment, url.HasFragment = split(rest, '#')
+ url.Path, url.RawQuery, url.HasQuery = split(rest, '?')
+
+ return &url, nil
+}