github.com/kata-containers/tests@v0.0.0-20240307153542-772105b56064/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  }