github.com/kata-containers/tests@v0.0.0-20240307153542-772105b56064/cmd/check-markdown/parse.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  	"fmt"
    11  	"os"
    12  	"strings"
    13  
    14  	bf "gopkg.in/russross/blackfriday.v2"
    15  )
    16  
    17  // List of errors found by visitor. Used as the visitor cannot return an error
    18  // directly.
    19  var errorList []error
    20  
    21  func (d *Doc) parse() error {
    22  	if !d.ShowTOC && !d.ListMode {
    23  		d.Logger.Info("Checking file")
    24  	}
    25  
    26  	err := d.parseMarkdown()
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	// mark document as having been handled
    32  	d.Parsed = true
    33  
    34  	return nil
    35  }
    36  
    37  // parseMarkdown parses the documents markdown.
    38  func (d *Doc) parseMarkdown() error {
    39  	bytes, err := os.ReadFile(d.Name)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	md := bf.New(bf.WithExtensions(bf.CommonExtensions))
    45  
    46  	root := md.Parse(bytes)
    47  
    48  	root.Walk(makeVisitor(d, d.ShowTOC))
    49  
    50  	errorCount := len(errorList)
    51  	if errorCount > 0 {
    52  		extra := ""
    53  		if errorCount != 1 {
    54  			extra = "s"
    55  		}
    56  
    57  		var msg []string
    58  
    59  		for _, err := range errorList {
    60  			msg = append(msg, err.Error())
    61  		}
    62  
    63  		return fmt.Errorf("found %d parse error%s:\n%s",
    64  			errorCount,
    65  			extra,
    66  			strings.Join(msg, "\n"))
    67  	}
    68  
    69  	return d.check()
    70  }
    71  
    72  // makeVisitor returns a function that is used to visit all document nodes.
    73  //
    74  // If createTOC is false, the visitor will check all nodes, but if true, the
    75  // visitor will only display a table of contents for the document.
    76  func makeVisitor(doc *Doc, createTOC bool) func(node *bf.Node, entering bool) bf.WalkStatus {
    77  	f := func(node *bf.Node, entering bool) bf.WalkStatus {
    78  		if !entering {
    79  			return bf.GoToNext
    80  		}
    81  
    82  		var err error
    83  
    84  		if createTOC {
    85  			err = doc.displayTOC(node)
    86  		} else {
    87  			err = doc.handleNode(node)
    88  		}
    89  
    90  		if err != nil {
    91  			// The visitor cannot return an error, so collect up all parser
    92  			// errors for dealing with later.
    93  			errorList = append(errorList, err)
    94  		}
    95  
    96  		return bf.GoToNext
    97  	}
    98  
    99  	return f
   100  }