autorest/config.go (96 lines of code) (raw):
package autorest
import (
"fmt"
"os"
"path"
"regexp"
"strings"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
"github.com/gomarkdown/markdown/parser"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)
type Package struct {
Tag string
InputFiles []string
}
type YamlPackage struct {
InputFiles []string `yaml:"input-file"`
}
var r = regexp.MustCompile(`\$\(tag\)\s+==\s+'(.+)'`)
func ParseAutoRestConfig(filename string) []Package {
data, err := os.ReadFile(filename)
if err != nil {
return nil
}
md := markdown.Parse(data, parser.NewWithExtensions(parser.NoExtensions))
codeBlocks := allCodeBlocks(&md)
out := make([]Package, 0)
for _, codeBlock := range codeBlocks {
if string(codeBlock.Info) == "yaml" {
yamlPackage, err := ParseYamlConfig(string(codeBlock.Literal))
if err != nil {
logrus.Warnf("failed to parse yaml config: %+v", err)
} else {
for i, inputFile := range yamlPackage.InputFiles {
yamlPackage.InputFiles[i] = path.Clean(path.Join(path.Dir(filename), inputFile))
}
out = append(out, *yamlPackage)
}
}
}
return out
}
func allCodeBlocks(node *ast.Node) []ast.CodeBlock {
if node == nil {
return nil
}
switch v := (*node).(type) {
case *ast.Container:
out := make([]ast.CodeBlock, 0)
for _, child := range v.Children {
out = append(out, allCodeBlocks(&child)...)
}
return out
case *ast.Document:
out := make([]ast.CodeBlock, 0)
for _, child := range v.Children {
out = append(out, allCodeBlocks(&child)...)
}
return out
case *ast.Paragraph:
out := make([]ast.CodeBlock, 0)
for _, child := range v.Children {
out = append(out, allCodeBlocks(&child)...)
}
return out
case *ast.CodeBlock:
return []ast.CodeBlock{*v}
}
return nil
}
func ParseYamlConfig(content string) (*Package, error) {
matches := r.FindAllStringSubmatch(content, -1)
if len(matches) == 1 && len(matches[0]) == 2 {
tag := matches[0][1]
index := strings.Index(content, "\n")
if index == -1 {
return nil, fmt.Errorf("invalid yaml code block: no newline after tag, input: %v", content)
}
yamlContent := content[index+1:]
var yamlPackage YamlPackage
err := yaml.Unmarshal([]byte(yamlContent), &yamlPackage)
if err != nil {
return nil, err
}
if len(yamlPackage.InputFiles) == 0 {
return nil, fmt.Errorf("input-file is empty, input: %v", content)
}
return &Package{
Tag: tag,
InputFiles: yamlPackage.InputFiles,
}, nil
}
return nil, fmt.Errorf("tag not found in yaml config: %s", content)
}