From 2c1e578ac3d2710ea93ee5050f48a348f6f33a96 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Mon, 1 Oct 2012 09:23:22 -0700 Subject: [PATCH] re-introduce basic generator --- .gitignore | 1 + style/book.css | 121 +++++++++++++++++++++++++++++++++++++++++ style/lit.css | 136 ---------------------------------------------- tool/generate.go | 137 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 259 insertions(+), 136 deletions(-) delete mode 100644 style/lit.css create mode 100644 tool/generate.go diff --git a/.gitignore b/.gitignore index 378eac2..d858ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +tool/generate diff --git a/style/book.css b/style/book.css index 4c54fc4..6029bf6 100644 --- a/style/book.css +++ b/style/book.css @@ -1 +1,122 @@ +/* PDF Formatting */ @page { margin: 10pt 0pt 10pt 0pt } + +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 14px; + line-height: 20px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} +a:visited { + color: #261a3b; +} +p { + margin: 0 0 15px 0; +} +h1, h2, h3, h4, h5, h6 { + margin: 0px 0 15px 0; +} +hr { + border: 0 none; + border-top: 1px solid #e5e5ee; + height: 1px; + margin: 20px 0; +} +#container { + position: relative; +} +table td { + border: 0; + outline: 0; +} +td.docs { + max-width: 400px; + min-width: 400px; + min-height: 5px; + padding: 10px 15px 1px 30px; + overflow-x: hidden; + vertical-align: top; + text-align: left; +} +td.code { + padding: 14px 30px 16px 15px; + width: 100%; + vertical-align: top; + border-left: 1px solid #e5e5ee; +} +pre, code { + font-size: 11px; line-height: 16px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; +} + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .err { border: 1px solid #FF0000 } /* Error */ +body .c { color: #408080; font-style: italic } /* Comment */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/style/lit.css b/style/lit.css deleted file mode 100644 index 9ec89a2..0000000 --- a/style/lit.css +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------- Layout and Typography ----------------------------*/ -body { - font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; - font-size: 14px; - line-height: 20px; - color: #252519; - margin: 0; padding: 0; -} -a { - color: #261a3b; -} - a:visited { - color: #261a3b; - } -p { - margin: 0 0 15px 0; -} -h1, h2, h3, h4, h5, h6 { - margin: 0px 0 15px 0; -} - h1 { - margin-top: 40px; - } -hr { - border: 0 none; - border-top: 1px solid #e5e5ee; - height: 1px; - margin: 20px 0; -} -#container { - position: relative; -} -#background { - position: fixed; - top: 0; left: 400px; right: 0; bottom: 0; - /* background: #f5f5ff; */ - border-left: 1px solid #e5e5ee; - z-index: -1; -} -table td { - border: 0; - outline: 0; -} - td.docs, th.docs { - max-width: 400px; - min-width: 400px; - min-height: 5px; - padding: 10px 15px 1px 30px; - overflow-x: hidden; - vertical-align: top; - text-align: left; - } - .docs p tt, .docs p code { - background: #f8f8ff; - border: 1px solid #dedede; - font-size: 11px; - padding: 0 0.2em; - } - td.code, th.code { - padding: 14px 30px 16px 15px; - width: 100%; - vertical-align: top; - /* background: #f5f5ff; */ - border-left: 1px solid #e5e5ee; - } - pre, tt, code { - font-size: 11px; line-height: 16px; - font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; - margin: 0; padding: 0; - } - - -/*---------------------- Syntax Highlighting -----------------------------*/ -td.linenos { background-color: #f0f0f0; padding-right: 10px; } -span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } -body .hll { background-color: #ffffcc } -body .err { border: 1px solid #FF0000 } /* Error */ -body .c { color: #408080; font-style: italic } /* Comment */ -body .k { color: #954121 } /* Keyword */ -body .o { color: #666666 } /* Operator */ -body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -body .cp { color: #BC7A00 } /* Comment.Preproc */ -body .c1 { color: #408080; font-style: italic } /* Comment.Single */ -body .cs { color: #408080; font-style: italic } /* Comment.Special */ -body .gd { color: #A00000 } /* Generic.Deleted */ -body .ge { font-style: italic } /* Generic.Emph */ -body .gr { color: #FF0000 } /* Generic.Error */ -body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -body .gi { color: #00A000 } /* Generic.Inserted */ -body .go { color: #808080 } /* Generic.Output */ -body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -body .gs { font-weight: bold } /* Generic.Strong */ -body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -body .gt { color: #0040D0 } /* Generic.Traceback */ -body .kc { color: #954121 } /* Keyword.Constant */ -body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ -body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ -body .kp { color: #954121 } /* Keyword.Pseudo */ -body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ -body .kt { color: #B00040 } /* Keyword.Type */ -body .m { color: #666666 } /* Literal.Number */ -body .s { color: #219161 } /* Literal.String */ -body .na { color: #7D9029 } /* Name.Attribute */ -body .nb { color: #954121 } /* Name.Builtin */ -body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -body .no { color: #880000 } /* Name.Constant */ -body .nd { color: #AA22FF } /* Name.Decorator */ -body .ni { color: #999999; font-weight: bold } /* Name.Entity */ -body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -body .nf { color: #0000FF } /* Name.Function */ -body .nl { color: #A0A000 } /* Name.Label */ -body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -body .nt { color: #954121; font-weight: bold } /* Name.Tag */ -body .nv { color: #19469D } /* Name.Variable */ -body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -body .w { color: #bbbbbb } /* Text.Whitespace */ -body .mf { color: #666666 } /* Literal.Number.Float */ -body .mh { color: #666666 } /* Literal.Number.Hex */ -body .mi { color: #666666 } /* Literal.Number.Integer */ -body .mo { color: #666666 } /* Literal.Number.Oct */ -body .sb { color: #219161 } /* Literal.String.Backtick */ -body .sc { color: #219161 } /* Literal.String.Char */ -body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ -body .s2 { color: #219161 } /* Literal.String.Double */ -body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -body .sh { color: #219161 } /* Literal.String.Heredoc */ -body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -body .sx { color: #954121 } /* Literal.String.Other */ -body .sr { color: #BB6688 } /* Literal.String.Regex */ -body .s1 { color: #219161 } /* Literal.String.Single */ -body .ss { color: #19469D } /* Literal.String.Symbol */ -body .bp { color: #954121 } /* Name.Builtin.Pseudo */ -body .vc { color: #19469D } /* Name.Variable.Class */ -body .vg { color: #19469D } /* Name.Variable.Global */ -body .vi { color: #19469D } /* Name.Variable.Instance */ -body .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/tool/generate.go b/tool/generate.go new file mode 100644 index 0000000..7997078 --- /dev/null +++ b/tool/generate.go @@ -0,0 +1,137 @@ +// Generate an HTML file from the book source. Derived from golit. + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "regexp" + "strings" +) + +func check(err error) { + if err != nil { + panic(err) + } +} + +func pipe(bin string, arg []string, src string) string { + cmd := exec.Command(bin, arg...) + in, _ := cmd.StdinPipe() + out, _ := cmd.StdoutPipe() + cmd.Start() + in.Write([]byte(src)) + in.Close() + bytes, _ := ioutil.ReadAll(out) + err := cmd.Wait() + check(err) + return string(bytes) +} + +var docsPat = regexp.MustCompile("^\\s*\\/\\/\\s") + +var headerPat = regexp.MustCompile("^\\s*\\/\\/\\s#+\\s") + +type seg struct { + docs, code, docsRendered, codeRendered string +} + +func main() { + if len(os.Args) != 3 { + fmt.Fprintln(os.Stderr, "usage: tool/generate input.go title > output.html") + os.Exit(1) + } + sourcePath := os.Args[1] + title := os.Args[2] + + markdownPath, err := exec.LookPath("markdown") + check(err) + pygmentizePath, err := exec.LookPath("pygmentize") + check(err) + + srcBytes, err := ioutil.ReadFile(sourcePath) + check(err) + lines := strings.Split(string(srcBytes), "\n") + + segs := []*seg{} + segs = append(segs, &seg{code: "", docs: ""}) + lastSeen := "" + for _, line := range lines { + headerMatch := headerPat.MatchString(line) + docsMatch := docsPat.MatchString(line) + emptyMatch := line == "" + lastSeg := segs[len(segs)-1] + lastHeader := lastSeen == "header" + lastDocs := lastSeen == "docs" + newHeader := (lastSeen != "header") + newDocs := (lastSeen != "docs") && lastSeg.docs != "" + newCode := (lastSeen != "code") && lastSeg.code != "" + if headerMatch || (emptyMatch && lastHeader) { + trimmed := docsPat.ReplaceAllString(line, "") + if newHeader { + newSeg := seg{docs: trimmed, code: ""} + segs = append(segs, &newSeg) + } else { + lastSeg.docs = lastSeg.docs + "\n" + trimmed + } + } else if docsMatch || (emptyMatch && lastDocs) { + trimmed := docsPat.ReplaceAllString(line, "") + if newDocs { + newSeg := seg{docs: trimmed, code: ""} + segs = append(segs, &newSeg) + } else { + lastSeg.docs = lastSeg.docs + "\n" + trimmed + } + lastSeen = "docs" + } else { + if newCode { + newSeg := seg{docs: "", code: line} + segs = append(segs, &newSeg) + } else { + lastSeg.code = lastSeg.code + "\n" + line + } + lastSeen = "code" + } + } + + for _, seg := range segs { + seg.docsRendered = pipe(markdownPath, []string{}, seg.docs) + seg.codeRendered = pipe(pygmentizePath, []string{"-l", "go", "-f", "html"}, seg.code+" ") + } + + fmt.Printf(` + + + + + %s + + + +
+
+ + + + + + + + `, title) + + for _, seg := range segs { + fmt.Printf( + ` + + + `, seg.docsRendered, seg.codeRendered) + } + + fmt.Print(` +
%s%s
+
+ + `) +}