github.com/argots/stencil@v0.0.2/pkg/stencil/markdown.go (about) 1 package stencil 2 3 import ( 4 "bufio" 5 "regexp" 6 "strings" 7 ) 8 9 // Markdown implements the markdown functionality. 10 type Markdown struct { 11 *Stencil 12 } 13 14 // CopyMarkdownSnippets first treats the url as a markdown stripping out 15 // everything but code fences with names matching the provided regex. 16 // The name of the code fence is the first word after the triple backquote. 17 // 18 // Note that standard go templates are still executed on top of this 19 // so the embedded code can use any stencil function. 20 func (m *Markdown) CopyMarkdownSnippets(key, localPath, url, regex string) error { 21 m.Printf("copying %s (snippets %s) to %s, key (%s)\n", url, regex, localPath, key) 22 23 key = key + "(regex: " + regex + ")" 24 m.Objects.addFile(key, localPath, url) 25 26 data, err := m.executeFilter(url, func(md string) (string, error) { 27 return m.FilterMarkdown(md, regex) 28 }) 29 if err != nil { 30 return m.Errorf("Error reading %s %v\n", url, err) 31 } 32 33 return m.Write(localPath, []byte(data), 0666) 34 } 35 36 func (m *Markdown) FilterMarkdown(data, regex string) (string, error) { 37 result := "" 38 if regex == "" { 39 regex = ".*" 40 } 41 42 re, err := regexp.Compile(regex) 43 if err != nil { 44 return "", err 45 } 46 47 m.forEachCodeFence(data, func(name, code string) { 48 if re.MatchString(name) { 49 result += code 50 } 51 }) 52 53 return result, nil 54 } 55 56 func (m *Markdown) forEachCodeFence(md string, visit func(name, code string)) { 57 re := regexp.MustCompile("(?msU)^```(.*)^```$") 58 for _, fence := range re.FindAllString(md, -1) { 59 fence = strings.Trim(fence, "`") 60 scanner := bufio.NewScanner(strings.NewReader(fence)) 61 scanner.Scan() 62 name := scanner.Text() 63 visit(strings.TrimSpace(name), fence[len(name)+1:]) 64 } 65 }