1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// The PDF package of PrintDraftFast creates a PDF out of the Lex markdown parsetree.
package pdf
import (
"git.kiefte.eu/lapingvino/printdraftfast/lex"
"git.kiefte.eu/lapingvino/printdraftfast/rules"
"git.kiefte.eu/lapingvino/printdraftfast/font"
"strconv"
"strings"
"regexp"
"github.com/phpdave11/gofpdf"
)
type Tree struct {
PDF *gofpdf.Fpdf
Rules rules.Set
F lex.Document
HTML gofpdf.HTMLBasicType
}
func (t Tree) pr(a string, text string) {
line(t.PDF, t.Rules.Get(a), t.HTML, t.Rules.Get(a).Prefix+text+t.Rules.Get(a).Postfix)
}
func (t Tree) Render() {
var block string
var lastsection int
for _, row := range t.F {
switch row.Type {
case "newpage":
block = ""
t.PDF.AddPage()
t.PDF.SetHeaderFuncMode(func() {
t.PDF.SetFont("CourierPrime", "", 12)
t.PDF.SetXY(-1, 0.5)
t.PDF.Cell(0, 0, strconv.Itoa(t.PDF.PageNo())+".")
}, true)
continue
case "titlepage":
block = "title"
t.PDF.SetY(4)
case "title", "Title":
t.PDF.SetTitle(row.Contents, true)
case "metasection":
block = "meta"
t.PDF.SetY(-2)
}
var contents string
var level int
if row.Type == "section" {
contents = strings.TrimLeft(row.Contents, "#")
level = len(row.Contents) - len(contents)
contents = strings.TrimLeft(contents, " ")
lastsection = level
} else if row.Type == "scene" {
level = lastsection + 1
contents = row.Contents
}
if contents != "" {
t.PDF.Bookmark(contents, level, -1)
}
if t.Rules.Get(row.Type).Hide && block == "" {
continue
}
if block != "" {
row.Type = block
}
t.pr(row.Type, row.Contents)
}
}
var (
bolditalic = regexp.MustCompile("\\*{3}([^\\*\n]+)\\*{3}")
bold = regexp.MustCompile("\\*{2}([^\\*\n]+)\\*{2}")
italic = regexp.MustCompile("\\*{1}([^\\*\n]+)\\*{1}")
underline = regexp.MustCompile("_{1}([^\\*\n]+)_{1}")
)
func line(pdf *gofpdf.Fpdf, format rules.Format, html gofpdf.HTMLBasicType, text string) {
pdf.SetFont(format.Font, format.Style, format.Size)
pdf.SetX(0)
pdf.SetLeftMargin(format.Left)
pdf.SetRightMargin(format.Right)
text = strings.TrimRight(text, "\r\n")
if strings.ContainsAny(text, "*_") {
text = bolditalic.ReplaceAllString(text, "<b><i>$1</i></b>")
text = bold.ReplaceAllString(text, "<b>$1</b>")
text = italic.ReplaceAllString(text, "<i>$1</i>")
text = underline.ReplaceAllString(text, "<u>$1</u>")
if format.Align == "C" {
text = "<center>"+text+"</center>"
}
html.Write(0.165, text)
pdf.SetY(pdf.GetY()+0.165)
return
}
pdf.MultiCell(0, 0.165, text, "", format.Align, false)
}
func Create(file string, format rules.Set, contents lex.Document) {
pdf := gofpdf.New("P", "in", "Letter", "")
pdf.AddUTF8FontFromBytes("CourierPrime", "", font.MustAsset("Courier-Prime.ttf"))
pdf.AddUTF8FontFromBytes("CourierPrime", "B", font.MustAsset("Courier-Prime-Bold.ttf"))
pdf.AddUTF8FontFromBytes("CourierPrime", "I", font.MustAsset("Courier-Prime-Italic.ttf"))
pdf.AddUTF8FontFromBytes("CourierPrime", "BI", font.MustAsset("Courier-Prime-Bold-Italic.ttf"))
pdf.AddPage()
pdf.SetMargins(1, 1, 1)
pdf.SetXY(1, 1)
f := Tree{
PDF: pdf,
Rules: format,
F: contents,
HTML: pdf.HTMLBasicNew(),
}
f.Render()
err := pdf.OutputFileAndClose(file)
if err != nil {
panic(err)
}
}
|