1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
package test_helpers
import (
"os"
"path/filepath"
"regexp"
"strings"
)
var punctuationRE = regexp.MustCompile(`[^\w\-\s]`)
var linkRE = regexp.MustCompile(`\]\(([\w:/#\-\.]*)\)`)
type Doc struct {
Name string
URLs []string
path string
}
func (doc Doc) Path(root string) string {
return filepath.Join(root, doc.path)
}
type Docs []Doc
func (d Docs) DocWithName(name string) Doc {
for _, doc := range d {
if doc.Name == name {
return doc
}
}
return Doc{}
}
func (d Docs) DocWithURL(url string) Doc {
for _, doc := range d {
for _, u := range doc.URLs {
if u == url {
return doc
}
}
}
return Doc{}
}
var DOCS = Docs{
{"index.md", []string{"https://onsi.github.io/ginkgo/"}, "docs/index.md"},
{"MIGRATING_TO_V2.md", []string{"https://onsi.github.io/ginkgo/MIGRATING_TO_V2"}, "docs/MIGRATING_TO_V2.md"},
{"README.md", []string{"https://github.com/onsi/ginkgo", "https://github.com/onsi/ginkgo/blob/master/README.md"}, "README.md"},
}
type Anchors struct {
Docs Docs
DocAnchors map[string][]string
}
func (a Anchors) IsResolvable(docName string, link string) bool {
var anchorSet []string
var expectedAnchor string
if strings.HasPrefix(link, "#") {
anchorSet = a.DocAnchors[docName]
expectedAnchor = strings.TrimPrefix(link, "#")
} else {
components := strings.Split(link, "#")
doc := a.Docs.DocWithURL(components[0])
if doc.Name == "" {
//allow external links
return true
}
if len(components) == 1 {
//allow links to the doc with no anchor
return true
}
expectedAnchor = components[1]
anchorSet = a.DocAnchors[doc.Name]
}
for _, anchor := range anchorSet {
if anchor == expectedAnchor {
return true
}
}
return false
}
func LoadAnchors(docs Docs, rootPath string) (Anchors, error) {
out := Anchors{
Docs: docs,
DocAnchors: map[string][]string{},
}
for _, doc := range docs {
anchors, err := loadMarkdownHeadingAnchors(doc.Path(rootPath))
if err != nil {
return Anchors{}, err
}
out.DocAnchors[doc.Name] = anchors
}
return out, nil
}
func loadMarkdownHeadingAnchors(filename string) ([]string, error) {
headings, err := LoadMarkdownHeadings(filename)
if err != nil {
return nil, err
}
var anchors []string
for _, heading := range headings {
heading = punctuationRE.ReplaceAllString(heading, "")
heading = strings.ToLower(heading)
heading = strings.ReplaceAll(heading, " ", "-")
anchors = append(anchors, heading)
}
return anchors, nil
}
func LoadMarkdownHeadings(filename string) ([]string, error) {
b, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
headings := []string{}
lines := strings.Split(string(b), "\n")
for _, line := range lines {
line = strings.TrimLeft(line, " ")
line = strings.TrimRight(line, " ")
if !strings.HasPrefix(line, "#") {
continue
}
line = strings.TrimLeft(line, "# ")
headings = append(headings, line)
}
return headings, nil
}
func LoadMarkdownLinks(filename string) ([]string, error) {
b, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
links := []string{}
lines := strings.Split(string(b), "\n")
for _, line := range lines {
matches := linkRE.FindAllStringSubmatch(line, -1)
for _, match := range matches {
if match[1] != "" {
links = append(links, match[1])
}
}
}
return links, nil
}
|