github.com/dmaizel/tests@v0.0.0-20210728163746-cae6a2d9cee8/cmd/check-markdown/link.go (about) 1 // 2 // Copyright (c) 2019 Intel Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 package main 8 9 import ( 10 "errors" 11 "os" 12 "path/filepath" 13 "regexp" 14 "strings" 15 ) 16 17 // newLink creates a new Link. 18 func newLink(doc *Doc, address, description string) (Link, error) { 19 l := Link{ 20 Doc: doc, 21 Address: address, 22 Description: description, 23 } 24 25 err := l.categorise() 26 if err != nil { 27 return Link{}, err 28 } 29 30 return l, nil 31 } 32 33 // categorise determines the type of Link. 34 func (l *Link) categorise() error { 35 address := l.Address 36 37 // markdown file extension with optional link name ("#...") 38 const re = `\.md#*.*$` 39 40 pattern := regexp.MustCompile(re) 41 42 matched := pattern.MatchString(address) 43 44 if strings.HasPrefix(address, "http:") { 45 l.Type = urlLink 46 } else if strings.HasPrefix(address, "https:") { 47 l.Type = urlLink 48 } else if strings.HasPrefix(address, "mailto:") { 49 l.Type = mailLink 50 } else if strings.HasPrefix(address, anchorPrefix) { 51 l.Type = internalLink 52 53 // Remove the prefix to make a valid link address 54 address = strings.TrimPrefix(address, anchorPrefix) 55 l.Address = address 56 } else if matched { 57 l.Type = externalLink 58 59 file, _, err := splitLink(address) 60 if err != nil { 61 return err 62 } 63 64 file, err = l.Doc.linkAddrToPath(file) 65 if err != nil { 66 return err 67 } 68 69 l.ResolvedPath = file 70 } else { 71 isREADME, err := l.handleImplicitREADME() 72 if err != nil { 73 return err 74 } 75 76 if !isREADME { 77 // Link must be an external file, but not a markdown file. 78 l.Type = externalFile 79 } 80 } 81 82 return nil 83 } 84 85 // handleImplicitREADME determines if the specified link is an implicit link 86 // to a README document. 87 func (l *Link) handleImplicitREADME() (isREADME bool, err error) { 88 const readme = "README.md" 89 90 address := l.Address 91 if address == "" { 92 return false, errors.New("need link address") 93 } 94 95 file, err := l.Doc.linkAddrToPath(address) 96 if err != nil { 97 return false, err 98 } 99 100 // The resolved path should exist as this is a local file. 101 st, err := os.Stat(file) 102 if err != nil { 103 return false, err 104 } 105 106 if !st.IsDir() { 107 return false, nil 108 } 109 110 // The file is a directory so try appending the implicit README file 111 // and see if that exists. 112 resolvedPath := filepath.Join(file, readme) 113 114 success := fileExists(resolvedPath) 115 116 if success { 117 l.Type = externalLink 118 l.ResolvedPath = resolvedPath 119 } 120 121 return success, nil 122 }