github.com/elves/elvish@v0.15.0/website/cmd/macros/macros.go (about) 1 // The macros program implements an ad-hoc preprocessor for Markdown files, used 2 // in Elvish's website. 3 package main 4 5 import ( 6 "bufio" 7 "bytes" 8 "fmt" 9 "io/ioutil" 10 "log" 11 "os" 12 "path" 13 "strings" 14 ) 15 16 const ( 17 ttyshot = "@ttyshot " 18 cf = "@cf " 19 dl = "@dl " 20 ) 21 22 func main() { 23 scanner := bufio.NewScanner(os.Stdin) 24 for scanner.Scan() { 25 line := scanner.Text() 26 line = expandTtyshot(line) 27 line = expandCf(line) 28 line = expandDl(line) 29 fmt.Println(line) 30 } 31 } 32 33 func expandTtyshot(line string) string { 34 i := strings.Index(line, ttyshot) 35 if i < 0 { 36 return line 37 } 38 name := line[i+len(ttyshot):] 39 content, err := ioutil.ReadFile(path.Join("ttyshot", name+".html")) 40 if err != nil { 41 log.Fatal(err) 42 } 43 var buf bytes.Buffer 44 buf.WriteString(line[:i]) 45 buf.WriteString(`<pre class="ttyshot"><code>`) 46 buf.Write(bytes.Replace( 47 content, []byte("\n"), []byte("<br>"), -1)) 48 buf.WriteString("</code></pre>") 49 return buf.String() 50 } 51 52 func expandCf(line string) string { 53 i := strings.Index(line, cf) 54 if i < 0 { 55 return line 56 } 57 targets := strings.Split(line[i+len(cf):], " ") 58 var buf strings.Builder 59 buf.WriteString("See also") 60 for i, target := range targets { 61 if i == 0 { 62 buf.WriteString(" ") 63 } else if i == len(targets)-1 { 64 buf.WriteString(" and ") 65 } else { 66 buf.WriteString(", ") 67 } 68 fmt.Fprintf(&buf, "[`%s`](%s)", target, cfHref(target)) 69 } 70 buf.WriteString(".") 71 return buf.String() 72 } 73 74 // Returns the href for a `@cf` reference. 75 func cfHref(target string) string { 76 i := strings.IndexRune(target, ':') 77 if i == -1 { 78 // A link within the builtin page. Use unqualified name (e.g. #put). 79 return "#" + target 80 } 81 82 module, symbol := target[:i], target[i+1:] 83 if module == "builtin" { 84 // A link from outside the builtin page to the builtin page. Use 85 // unqualified name (e.g. #put). 86 return "builtin.html#" + symbol 87 } 88 // A link to a non-builtin page. The section names are always qualified 89 // names (e.g str:join), but pandoc strips the colons from the anchor (e.g. 90 // #strjoin). 91 return module + ".html#" + strings.ReplaceAll(target, ":", "") 92 } 93 94 func expandDl(line string) string { 95 i := strings.Index(line, dl) 96 if i < 0 { 97 return line 98 } 99 fields := strings.SplitN(line[i+len(dl):], " ", 2) 100 name := fields[0] 101 url := name 102 if len(fields) == 2 { 103 url = fields[1] 104 } 105 return line[:i] + fmt.Sprintf( 106 `<a href="https://dl.elv.sh/%s">%s</a>`, url, name) 107 }