github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/present/link.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package present 6 7 import ( 8 "fmt" 9 "log" 10 "net/url" 11 "strings" 12 ) 13 14 func init() { 15 Register("link", parseLink) 16 } 17 18 type Link struct { 19 URL *url.URL 20 Label string 21 } 22 23 func (l Link) TemplateName() string { return "link" } 24 25 func parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, error) { 26 args := strings.Fields(text) 27 url, err := url.Parse(args[1]) 28 if err != nil { 29 return nil, err 30 } 31 label := "" 32 if len(args) > 2 { 33 label = strings.Join(args[2:], " ") 34 } else { 35 scheme := url.Scheme + "://" 36 if url.Scheme == "mailto" { 37 scheme = "mailto:" 38 } 39 label = strings.Replace(url.String(), scheme, "", 1) 40 } 41 return Link{url, label}, nil 42 } 43 44 func renderLink(href, text string) string { 45 text = font(text) 46 if text == "" { 47 text = href 48 } 49 // Open links in new window only when their url is absolute. 50 target := "_blank" 51 if u, err := url.Parse(href); err != nil { 52 log.Println("rendernLink parsing url:", err) 53 } else if !u.IsAbs() || u.Scheme == "javascript" { 54 target = "_self" 55 } 56 57 return fmt.Sprintf(`<a href="%s" target="%s">%s</a>`, href, target, text) 58 } 59 60 // parseInlineLink parses an inline link at the start of s, and returns 61 // a rendered HTML link and the total length of the raw inline link. 62 // If no inline link is present, it returns all zeroes. 63 func parseInlineLink(s string) (link string, length int) { 64 if !strings.HasPrefix(s, "[[") { 65 return 66 } 67 end := strings.Index(s, "]]") 68 if end == -1 { 69 return 70 } 71 urlEnd := strings.Index(s, "]") 72 rawURL := s[2:urlEnd] 73 const badURLChars = `<>"{}|\^[] ` + "`" // per RFC2396 section 2.4.3 74 if strings.ContainsAny(rawURL, badURLChars) { 75 return 76 } 77 if urlEnd == end { 78 simpleUrl := "" 79 url, err := url.Parse(rawURL) 80 if err == nil { 81 // If the URL is http://foo.com, drop the http:// 82 // In other words, render [[http://golang.org]] as: 83 // <a href="http://golang.org">golang.org</a> 84 if strings.HasPrefix(rawURL, url.Scheme+"://") { 85 simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+"://") 86 } else if strings.HasPrefix(rawURL, url.Scheme+":") { 87 simpleUrl = strings.TrimPrefix(rawURL, url.Scheme+":") 88 } 89 } 90 return renderLink(rawURL, simpleUrl), end + 2 91 } 92 if s[urlEnd:urlEnd+2] != "][" { 93 return 94 } 95 text := s[urlEnd+2 : end] 96 return renderLink(rawURL, text), end + 2 97 }