github.com/dmaizel/tests@v0.0.0-20210728163746-cae6a2d9cee8/cmd/check-markdown/check.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 "fmt" 12 ) 13 14 // checkLink checks the validity of the specified link. If checkOtherDoc is 15 // true and the link is an external one, validate the link by considering the 16 // external document too. 17 func (d *Doc) checkLink(address string, link Link, checkOtherDoc bool) error { 18 if address == "" { 19 return errors.New("link address not set") 20 } 21 22 switch link.Type { 23 case externalFile: 24 fallthrough 25 case externalLink: 26 // Check to ensure that referenced file actually exists 27 28 var file string 29 30 if link.ResolvedPath != "" { 31 file = link.ResolvedPath 32 } else { 33 file, _, err := splitLink(address) 34 if err != nil { 35 return err 36 } 37 38 file, err = d.linkAddrToPath(file) 39 if err != nil { 40 return err 41 } 42 43 if !fileExists(file) { 44 return d.Errorf("link type %v invalid: %q does not exist", 45 link.Type, 46 file) 47 } 48 } 49 50 if link.Type == externalFile { 51 break 52 } 53 54 // Check the other document 55 other, err := getDoc(file, d.Logger) 56 if err != nil { 57 return err 58 } 59 60 if !checkOtherDoc { 61 break 62 } 63 64 _, section, err := splitLink(address) 65 if err != nil { 66 return err 67 } 68 69 if section == "" { 70 break 71 } 72 73 if !other.hasHeading(section) { 74 return other.Errorf("invalid link %v", address) 75 } 76 77 case internalLink: 78 // must be a link to an existing heading 79 80 // search for a heading whose LinkName == name 81 found := d.headingByLinkName(address) 82 if found == nil { 83 msg := fmt.Sprintf("failed to find heading for link %q (%+v)", address, link) 84 85 // There is a chance the link description matches the 86 // correct heading the link address refers to. In 87 // which case, we can derive the correct link address! 88 suggestion, err2 := createHeadingID(link.Description) 89 90 if err2 == nil && suggestion != link.Address { 91 found = d.headingByLinkName(suggestion) 92 if found != nil { 93 msg = fmt.Sprintf("%s - correct link name is %q", msg, suggestion) 94 } 95 } 96 97 return d.Errorf("%s", msg) 98 } 99 case urlLink: 100 // NOP - handled by xurls 101 } 102 103 return nil 104 } 105 106 // check performs all checks on the document. 107 func (d *Doc) check() error { 108 for name, linkList := range d.Links { 109 for _, link := range linkList { 110 err := d.checkLink(name, link, false) 111 if err != nil { 112 return err 113 } 114 } 115 } 116 117 return nil 118 }