example/main.go (view raw)
1//
2// Blackfriday Markdown Processor
3// Available at http://github.com/russross/blackfriday
4//
5// Copyright © 2011 Russ Ross <russ@russross.com>.
6// Distributed under the Simplified BSD License.
7// See README.md for details.
8//
9
10//
11//
12// Example front-end for command-line use
13//
14//
15
16package main
17
18import (
19 "bytes"
20 "flag"
21 "fmt"
22 "io/ioutil"
23 "github.com/russross/blackfriday"
24 "os"
25 "runtime/pprof"
26)
27
28func main() {
29 // parse command-line options
30 var page, xhtml, latex, smartypants, latexdashes, fractions bool
31 var css, cpuprofile string
32 var repeat int
33 flag.BoolVar(&page, "page", false,
34 "Generate a standalone HTML page (implies -latex=false)")
35 flag.BoolVar(&xhtml, "xhtml", true,
36 "Use XHTML-style tags in HTML output")
37 flag.BoolVar(&latex, "latex", false,
38 "Generate LaTeX output instead of HTML")
39 flag.BoolVar(&smartypants, "smartypants", true,
40 "Apply smartypants-style substitutions")
41 flag.BoolVar(&latexdashes, "latexdashes", true,
42 "Use LaTeX-style dash rules for smartypants")
43 flag.BoolVar(&fractions, "fractions", true,
44 "Use improved fraction rules for smartypants")
45 flag.StringVar(&css, "css", "",
46 "Link to a CSS stylesheet (implies -page)")
47 flag.StringVar(&cpuprofile, "cpuprofile", "",
48 "Write cpu profile to a file")
49 flag.IntVar(&repeat, "repeat", 1,
50 "Process the input multiple times (for benchmarking)")
51 flag.Usage = func() {
52 fmt.Fprintf(os.Stderr, "Blackfriday Markdown Processor v"+blackfriday.VERSION+
53 "\nAvailable at http://github.com/russross/blackfriday\n\n"+
54 "Copyright © 2011 Russ Ross <russ@russross.com>\n"+
55 "Distributed under the Simplified BSD License\n"+
56 "See website for details\n\n"+
57 "Usage:\n"+
58 " %s [options] [inputfile [outputfile]]\n\n"+
59 "Options:\n",
60 os.Args[0])
61 flag.PrintDefaults()
62 }
63 flag.Parse()
64
65 // enforce implied options
66 if css != "" {
67 page = true
68 }
69 if page {
70 latex = false
71 }
72
73 // turn on profiling?
74 if cpuprofile != "" {
75 f, err := os.Create(cpuprofile)
76 if err != nil {
77 fmt.Fprintln(os.Stderr, err)
78 }
79 pprof.StartCPUProfile(f)
80 defer pprof.StopCPUProfile()
81 }
82
83 // read the input
84 var input []byte
85 var err os.Error
86 args := flag.Args()
87 switch len(args) {
88 case 0:
89 if input, err = ioutil.ReadAll(os.Stdin); err != nil {
90 fmt.Fprintln(os.Stderr, "Error reading from Stdin:", err)
91 os.Exit(-1)
92 }
93 case 1, 2:
94 if input, err = ioutil.ReadFile(args[0]); err != nil {
95 fmt.Fprintln(os.Stderr, "Error reading from", args[0], ":", err)
96 os.Exit(-1)
97 }
98 default:
99 flag.Usage()
100 os.Exit(-1)
101 }
102
103 // set up options
104 extensions := 0
105 extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
106 extensions |= blackfriday.EXTENSION_TABLES
107 extensions |= blackfriday.EXTENSION_FENCED_CODE
108 extensions |= blackfriday.EXTENSION_AUTOLINK
109 extensions |= blackfriday.EXTENSION_STRIKETHROUGH
110 extensions |= blackfriday.EXTENSION_SPACE_HEADERS
111
112 var renderer *blackfriday.Renderer
113 if latex {
114 // render the data into LaTeX
115 renderer = blackfriday.LatexRenderer(0)
116 } else {
117 // render the data into HTML
118 htmlFlags := 0
119 if xhtml {
120 htmlFlags |= blackfriday.HTML_USE_XHTML
121 }
122 if smartypants {
123 htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
124 }
125 if fractions {
126 htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
127 }
128 if latexdashes {
129 htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
130 }
131 renderer = blackfriday.HtmlRenderer(htmlFlags)
132 }
133
134 // parse and render
135 var output []byte
136 for i := 0; i < repeat; i++ {
137 output = blackfriday.Markdown(input, renderer, extensions)
138 }
139
140 // output the result
141 var out *os.File
142 if len(args) == 2 {
143 if out, err = os.Create(args[1]); err != nil {
144 fmt.Fprintf(os.Stderr, "Error creating %s: %v", args[1], err)
145 os.Exit(-1)
146 }
147 defer out.Close()
148 } else {
149 out = os.Stdout
150 }
151
152 if page {
153 // if it starts with an <h1>, make that the title
154 title := ""
155 if bytes.HasPrefix(output, []byte("<h1>")) {
156 end := 0
157 // we know the buffer ends with a newline, so no need to check bounds
158 for output[end] != '\n' {
159 end++
160 }
161 if bytes.HasSuffix(output[:end], []byte("</h1>")) {
162 title = string(output[len("<h1>") : end-len("</h1>")])
163 }
164 }
165
166 ending := ""
167 if xhtml {
168 fmt.Fprint(out, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ")
169 fmt.Fprintln(out, "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
170 fmt.Fprintln(out, "<html xmlns=\"http://www.w3.org/1999/xhtml\">")
171 ending = " /"
172 } else {
173 fmt.Fprint(out, "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" ")
174 fmt.Fprintln(out, "\"http://www.w3.org/TR/html4/strict.dtd\">")
175 fmt.Fprintln(out, "<html>")
176 }
177 fmt.Fprintln(out, "<head>")
178 fmt.Fprintf(out, " <title>%s</title>\n", title)
179 fmt.Fprintf(out, " <meta name=\"GENERATOR\" content=\"Blackfriday Markdown Processor v%s\"%s>\n",
180 blackfriday.VERSION, ending)
181 fmt.Fprintf(out, " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"%s>\n",
182 ending)
183 if css != "" {
184 fmt.Fprintf(out, " <link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />\n", css)
185 }
186 fmt.Fprintln(out, "</head>")
187 fmt.Fprintln(out, "<body>")
188 }
189 if _, err = out.Write(output); err != nil {
190 fmt.Fprintln(os.Stderr, "Error writing output:", err)
191 os.Exit(-1)
192 }
193 if page {
194 fmt.Fprintln(out, "</body>")
195 fmt.Fprintln(out, "</html>")
196 }
197}