all repos — grayfriday @ f0cd9a420e028f3c0d19866fa8c873d6a70e5ae2

blackfriday fork with a few changes

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}