all repos — grayfriday @ e35b4b66cc57e2551f52df155cf3d3f4e2c67280

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	"flag"
 20	"fmt"
 21	"io/ioutil"
 22	"github.com/russross/blackfriday"
 23	"os"
 24	"runtime/pprof"
 25	"strings"
 26)
 27
 28const DEFAULT_TITLE = ""
 29
 30func main() {
 31	// parse command-line options
 32	var page, toc, toconly, xhtml, latex, smartypants, latexdashes, fractions bool
 33	var css, cpuprofile string
 34	var repeat int
 35	flag.BoolVar(&page, "page", false,
 36		"Generate a standalone HTML page (implies -latex=false)")
 37	flag.BoolVar(&toc, "toc", false,
 38		"Generate a table of contents (implies -latex=false)")
 39	flag.BoolVar(&toconly, "toconly", false,
 40		"Generate a table of contents only (implies -toc)")
 41	flag.BoolVar(&xhtml, "xhtml", true,
 42		"Use XHTML-style tags in HTML output")
 43	flag.BoolVar(&latex, "latex", false,
 44		"Generate LaTeX output instead of HTML")
 45	flag.BoolVar(&smartypants, "smartypants", true,
 46		"Apply smartypants-style substitutions")
 47	flag.BoolVar(&latexdashes, "latexdashes", true,
 48		"Use LaTeX-style dash rules for smartypants")
 49	flag.BoolVar(&fractions, "fractions", true,
 50		"Use improved fraction rules for smartypants")
 51	flag.StringVar(&css, "css", "",
 52		"Link to a CSS stylesheet (implies -page)")
 53	flag.StringVar(&cpuprofile, "cpuprofile", "",
 54		"Write cpu profile to a file")
 55	flag.IntVar(&repeat, "repeat", 1,
 56		"Process the input multiple times (for benchmarking)")
 57	flag.Usage = func() {
 58		fmt.Fprintf(os.Stderr, "Blackfriday Markdown Processor v"+blackfriday.VERSION+
 59			"\nAvailable at http://github.com/russross/blackfriday\n\n"+
 60			"Copyright © 2011 Russ Ross <russ@russross.com>\n"+
 61			"Distributed under the Simplified BSD License\n"+
 62			"See website for details\n\n"+
 63			"Usage:\n"+
 64			"  %s [options] [inputfile [outputfile]]\n\n"+
 65			"Options:\n",
 66			os.Args[0])
 67		flag.PrintDefaults()
 68	}
 69	flag.Parse()
 70
 71	// enforce implied options
 72	if css != "" {
 73		page = true
 74	}
 75	if page {
 76		latex = false
 77	}
 78	if toconly {
 79		toc = true
 80	}
 81	if toc {
 82		latex = false
 83	}
 84
 85	// turn on profiling?
 86	if cpuprofile != "" {
 87		f, err := os.Create(cpuprofile)
 88		if err != nil {
 89			fmt.Fprintln(os.Stderr, err)
 90		}
 91		pprof.StartCPUProfile(f)
 92		defer pprof.StopCPUProfile()
 93	}
 94
 95	// read the input
 96	var input []byte
 97	var err os.Error
 98	args := flag.Args()
 99	switch len(args) {
100	case 0:
101		if input, err = ioutil.ReadAll(os.Stdin); err != nil {
102			fmt.Fprintln(os.Stderr, "Error reading from Stdin:", err)
103			os.Exit(-1)
104		}
105	case 1, 2:
106		if input, err = ioutil.ReadFile(args[0]); err != nil {
107			fmt.Fprintln(os.Stderr, "Error reading from", args[0], ":", err)
108			os.Exit(-1)
109		}
110	default:
111		flag.Usage()
112		os.Exit(-1)
113	}
114
115	// set up options
116	extensions := 0
117	extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
118	extensions |= blackfriday.EXTENSION_TABLES
119	extensions |= blackfriday.EXTENSION_FENCED_CODE
120	extensions |= blackfriday.EXTENSION_AUTOLINK
121	extensions |= blackfriday.EXTENSION_STRIKETHROUGH
122	extensions |= blackfriday.EXTENSION_SPACE_HEADERS
123
124	var renderer blackfriday.Renderer
125	if latex {
126		// render the data into LaTeX
127		renderer = blackfriday.LatexRenderer(0)
128	} else {
129		// render the data into HTML
130		htmlFlags := 0
131		if xhtml {
132			htmlFlags |= blackfriday.HTML_USE_XHTML
133		}
134		if smartypants {
135			htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
136		}
137		if fractions {
138			htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
139		}
140		if latexdashes {
141			htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
142		}
143		title := ""
144		if page {
145			htmlFlags |= blackfriday.HTML_COMPLETE_PAGE
146			title = getTitle(input)
147		}
148		if toconly {
149			htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
150		}
151		if toc {
152			htmlFlags |= blackfriday.HTML_TOC
153		}
154		renderer = blackfriday.HtmlRenderer(htmlFlags, title, css)
155	}
156
157	// parse and render
158	var output []byte
159	for i := 0; i < repeat; i++ {
160		output = blackfriday.Markdown(input, renderer, extensions)
161	}
162
163	// output the result
164	var out *os.File
165	if len(args) == 2 {
166		if out, err = os.Create(args[1]); err != nil {
167			fmt.Fprintf(os.Stderr, "Error creating %s: %v", args[1], err)
168			os.Exit(-1)
169		}
170		defer out.Close()
171	} else {
172		out = os.Stdout
173	}
174
175	if _, err = out.Write(output); err != nil {
176		fmt.Fprintln(os.Stderr, "Error writing output:", err)
177		os.Exit(-1)
178	}
179}
180
181// try to guess the title from the input buffer
182// just check if it starts with an <h1> element and use that
183func getTitle(input []byte) string {
184	i := 0
185
186	// skip blank lines
187	for i < len(input) && (input[i] == '\n' || input[i] == '\r') {
188		i++
189	}
190	if i >= len(input) {
191		return DEFAULT_TITLE
192	}
193	if input[i] == '\r' && i+1 < len(input) && input[i+1] == '\n' {
194		i++
195	}
196
197	// find the first line
198	start := i
199	for i < len(input) && input[i] != '\n' && input[i] != '\r' {
200		i++
201	}
202	line1 := input[start:i]
203	if input[i] == '\r' && i+1 < len(input) && input[i+1] == '\n' {
204		i++
205	}
206	i++
207
208	// check for a prefix header
209	if len(line1) >= 3 && line1[0] == '#' && (line1[1] == ' ' || line1[1] == '\t') {
210		return strings.TrimSpace(string(line1[2:]))
211	}
212
213	// check for an underlined header
214	if i >= len(input) || input[i] != '=' {
215		return DEFAULT_TITLE
216	}
217	for i < len(input) && input[i] == '=' {
218		i++
219	}
220	for i < len(input) && (input[i] == ' ' || input[i] == '\t') {
221		i++
222	}
223	if i >= len(input) || (input[i] != '\n' && input[i] != '\r') {
224		return DEFAULT_TITLE
225	}
226
227	return strings.TrimSpace(string(line1))
228}