annotate vendor/github.com/russross/blackfriday/v2/markdown.go @ 74:d8727551f403 draft

The Empress (III) * Change the way how versions are handled in version.go (to ease `go install`) * Upgrade yaml.v2 to yaml.v3 Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Mon, 04 Dec 2023 00:54:29 +0000
parents 787b5ee0289d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 // Blackfriday Markdown Processor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2 // Available at http://github.com/russross/blackfriday
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 // Copyright © 2011 Russ Ross <russ@russross.com>.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 // Distributed under the Simplified BSD License.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 // See README.md for details.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 package blackfriday
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 "bytes"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13 "io"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 "strings"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 "unicode/utf8"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 // Markdown parsing and processing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 // Version string of the package. Appears in the rendered document when
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 // CompletePage flag is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 const Version = "2.0"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 // Extensions is a bitwise or'ed collection of enabled Blackfriday's
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 // extensions.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 type Extensions int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 // These are the supported markdown parsing extensions.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 // OR these values together to select multiple extensions.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 NoExtensions Extensions = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 Tables // Render tables
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 FencedCode // Render fenced code blocks
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 Autolink // Detect embedded URLs that are not explicitly marked
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 Strikethrough // Strikethrough text using ~~test~~
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 LaxHTMLBlocks // Loosen up HTML block parsing rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 SpaceHeadings // Be strict about prefix heading rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 HardLineBreak // Translate newlines into line breaks
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 TabSizeEight // Expand tabs to eight spaces instead of four
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 Footnotes // Pandoc-style footnotes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 HeadingIDs // specify heading IDs with {#id}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 Titleblock // Titleblock ala pandoc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 AutoHeadingIDs // Create the heading ID from the text
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 BackslashLineBreak // Translate trailing backslashes into line breaks
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 DefinitionLists // Render definition lists
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 Autolink | Strikethrough | SpaceHeadings | HeadingIDs |
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 BackslashLineBreak | DefinitionLists
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 // ListType contains bitwise or'ed flags for list and list item objects.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 type ListType int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 // These are the possible flag values for the ListItem renderer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 // Multiple flag values may be ORed together.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 // These are mostly of interest if you are writing a new output format.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 ListTypeOrdered ListType = 1 << iota
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 ListTypeDefinition
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 ListTypeTerm
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 ListItemContainsBlock
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 ListItemBeginningOfList // TODO: figure out if this is of any use now
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 ListItemEndOfList
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 // CellAlignFlags holds a type of alignment in a table cell.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 type CellAlignFlags int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 // These are the possible flag values for the table cell renderer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 // Only a single one of these values will be used; they are not ORed together.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 // These are mostly of interest if you are writing a new output format.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 TableAlignmentLeft CellAlignFlags = 1 << iota
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 TableAlignmentRight
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 // The size of a tab stop.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 TabSizeDefault = 4
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 TabSizeDouble = 8
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 // blockTags is a set of tags that are recognized as HTML block tags.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 // Any of these can be included in markdown text without special escaping.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 var blockTags = map[string]struct{}{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 "blockquote": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 "del": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 "div": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 "dl": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 "fieldset": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 "form": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 "h1": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 "h2": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 "h3": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 "h4": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 "h5": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 "h6": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 "iframe": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 "ins": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 "math": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 "noscript": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 "ol": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 "pre": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 "p": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 "script": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 "style": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 "table": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 "ul": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 // HTML5
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 "address": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 "article": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 "aside": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 "canvas": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 "figcaption": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 "figure": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 "footer": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 "header": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 "hgroup": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 "main": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 "nav": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 "output": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 "progress": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 "section": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 "video": {},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 // Renderer is the rendering interface. This is mostly of interest if you are
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 // implementing a new rendering format.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 // Only an HTML implementation is provided in this repository, see the README
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 // for external implementations.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 type Renderer interface {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 // RenderNode is the main rendering method. It will be called once for
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 // every leaf node and twice for every non-leaf node (first with
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 // entering=true, then with entering=false). The method should write its
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 // rendition of the node to the supplied writer w.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 RenderNode(w io.Writer, node *Node, entering bool) WalkStatus
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 // RenderHeader is a method that allows the renderer to produce some
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 // content preceding the main body of the output document. The header is
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 // understood in the broad sense here. For example, the default HTML
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 // renderer will write not only the HTML document preamble, but also the
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 // table of contents if it was requested.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 // The method will be passed an entire document tree, in case a particular
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 // implementation needs to inspect it to produce output.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 // The output should be written to the supplied writer w. If your
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 // implementation has no header to write, supply an empty implementation.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 RenderHeader(w io.Writer, ast *Node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 // RenderFooter is a symmetric counterpart of RenderHeader.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 RenderFooter(w io.Writer, ast *Node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // Callback functions for inline parsing. One such function is defined
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 // for each character that triggers a response when parsing inline data.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 // Markdown is a type that holds extensions and the runtime state used by
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 // Parse, and the renderer. You can not use it directly, construct it with New.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 type Markdown struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 renderer Renderer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 referenceOverride ReferenceOverrideFunc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 refs map[string]*reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 inlineCallback [256]inlineParser
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 extensions Extensions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179 nesting int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 maxNesting int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 insideLink bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 // Footnotes need to be ordered as well as available to quickly check for
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 // presence. If a ref is also a footnote, it's stored both in refs and here
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 // in notes. Slice is nil if footnotes not enabled.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 notes []*reference
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 doc *Node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 tip *Node // = doc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 oldTip *Node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 lastMatchedContainer *Node // = doc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192 allClosed bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 func (p *Markdown) getRef(refid string) (ref *reference, found bool) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 if p.referenceOverride != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 r, overridden := p.referenceOverride(refid)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 if overridden {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 if r == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200 return nil, false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 return &reference{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 link: []byte(r.Link),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 title: []byte(r.Title),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 noteID: 0,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 hasBlock: false,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 text: []byte(r.Text)}, true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 // refs are case insensitive
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 ref, found = p.refs[strings.ToLower(refid)]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 return ref, found
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 func (p *Markdown) finalize(block *Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216 above := block.Parent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 block.open = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 p.tip = above
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 func (p *Markdown) addChild(node NodeType, offset uint32) *Node {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 return p.addExistingChild(NewNode(node), offset)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 for !p.tip.canContain(node.Type) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 p.finalize(p.tip)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 p.tip.AppendChild(node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 p.tip = node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 return node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 func (p *Markdown) closeUnmatchedBlocks() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 if !p.allClosed {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 for p.oldTip != p.lastMatchedContainer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 parent := p.oldTip.Parent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 p.finalize(p.oldTip)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 p.oldTip = parent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241 p.allClosed = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 // Public interface
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 // Reference represents the details of a link.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252 // See the documentation in Options for more details on use-case.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 type Reference struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 // Link is usually the URL the reference points to.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255 Link string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 // Title is the alternate text describing the link in more detail.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 Title string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 // Text is the optional text to override the ref with if the syntax used was
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 // [refid][]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 Text string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263 // ReferenceOverrideFunc is expected to be called with a reference string and
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264 // return either a valid Reference type that the reference string maps to or
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 // nil. If overridden is false, the default reference logic will be executed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266 // See the documentation in Options for more details on use-case.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 // New constructs a Markdown processor. You can use the same With* functions as
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270 // for Run() to customize parser's behavior and the renderer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 func New(opts ...Option) *Markdown {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272 var p Markdown
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 for _, opt := range opts {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274 opt(&p)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276 p.refs = make(map[string]*reference)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 p.maxNesting = 16
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 p.insideLink = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 docNode := NewNode(Document)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280 p.doc = docNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 p.tip = docNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282 p.oldTip = docNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 p.lastMatchedContainer = docNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 p.allClosed = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 // register inline parsers
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286 p.inlineCallback[' '] = maybeLineBreak
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 p.inlineCallback['*'] = emphasis
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288 p.inlineCallback['_'] = emphasis
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 if p.extensions&Strikethrough != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 p.inlineCallback['~'] = emphasis
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 p.inlineCallback['`'] = codeSpan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293 p.inlineCallback['\n'] = lineBreak
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294 p.inlineCallback['['] = link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 p.inlineCallback['<'] = leftAngle
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 p.inlineCallback['\\'] = escape
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 p.inlineCallback['&'] = entity
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298 p.inlineCallback['!'] = maybeImage
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 p.inlineCallback['^'] = maybeInlineFootnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 if p.extensions&Autolink != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 p.inlineCallback['h'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302 p.inlineCallback['m'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 p.inlineCallback['f'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 p.inlineCallback['H'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305 p.inlineCallback['M'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 p.inlineCallback['F'] = maybeAutoLink
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308 if p.extensions&Footnotes != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 p.notes = make([]*reference, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 return &p
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314 // Option customizes the Markdown processor's default behavior.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315 type Option func(*Markdown)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 // WithRenderer allows you to override the default renderer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318 func WithRenderer(r Renderer) Option {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 return func(p *Markdown) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320 p.renderer = r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 // WithExtensions allows you to pick some of the many extensions provided by
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 // Blackfriday. You can bitwise OR them.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 func WithExtensions(e Extensions) Option {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327 return func(p *Markdown) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 p.extensions = e
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 // WithNoExtensions turns off all extensions and custom behavior.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 func WithNoExtensions() Option {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 return func(p *Markdown) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335 p.extensions = NoExtensions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 p.renderer = NewHTMLRenderer(HTMLRendererParameters{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337 Flags: HTMLFlagsNone,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 // WithRefOverride sets an optional function callback that is called every
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 // time a reference is resolved.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 // In Markdown, the link reference syntax can be made to resolve a link to
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346 // a reference instead of an inline URL, in one of the following ways:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348 // * [link text][refid]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 // * [refid][]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 // Usually, the refid is defined at the bottom of the Markdown document. If
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352 // this override function is provided, the refid is passed to the override
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 // function first, before consulting the defined refids at the bottom. If
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 // the override function indicates an override did not occur, the refids at
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355 // the bottom will be used to fill in the link details.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 func WithRefOverride(o ReferenceOverrideFunc) Option {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 return func(p *Markdown) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358 p.referenceOverride = o
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 // Run is the main entry point to Blackfriday. It parses and renders a
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363 // block of markdown-encoded text.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365 // The simplest invocation of Run takes one argument, input:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 // output := Run(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 // This will parse the input with CommonExtensions enabled and render it with
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368 // the default HTMLRenderer (with CommonHTMLFlags).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370 // Variadic arguments opts can customize the default behavior. Since Markdown
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371 // type does not contain exported fields, you can not use it directly. Instead,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372 // use the With* functions. For example, this will call the most basic
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 // functionality, with no extensions:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374 // output := Run(input, WithNoExtensions())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 // You can use any number of With* arguments, even contradicting ones. They
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377 // will be applied in order of appearance and the latter will override the
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 // former:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379 // output := Run(input, WithNoExtensions(), WithExtensions(exts),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380 // WithRenderer(yourRenderer))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381 func Run(input []byte, opts ...Option) []byte {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382 r := NewHTMLRenderer(HTMLRendererParameters{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 Flags: CommonHTMLFlags,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 optList = append(optList, opts...)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 parser := New(optList...)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 ast := parser.Parse(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389 var buf bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390 parser.renderer.RenderHeader(&buf, ast)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 ast.Walk(func(node *Node, entering bool) WalkStatus {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 return parser.renderer.RenderNode(&buf, node, entering)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394 parser.renderer.RenderFooter(&buf, ast)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395 return buf.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398 // Parse is an entry point to the parsing part of Blackfriday. It takes an
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399 // input markdown document and produces a syntax tree for its contents. This
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400 // tree can then be rendered with a default or custom renderer, or
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401 // analyzed/transformed by the caller to whatever non-standard needs they have.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402 // The return value is the root node of the syntax tree.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 func (p *Markdown) Parse(input []byte) *Node {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404 p.block(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 // Walk the tree and finish up some of unfinished blocks
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406 for p.tip != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407 p.finalize(p.tip)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409 // Walk the tree again and process inline markdown in each block
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 p.doc.Walk(func(node *Node, entering bool) WalkStatus {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411 if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 p.inline(node, node.content)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413 node.content = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415 return GoToNext
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417 p.parseRefsToAST()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 return p.doc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421 func (p *Markdown) parseRefsToAST() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422 if p.extensions&Footnotes == 0 || len(p.notes) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425 p.tip = p.doc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 block := p.addBlock(List, nil)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427 block.IsFootnotesList = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 block.ListFlags = ListTypeOrdered
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429 flags := ListItemBeginningOfList
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 // Note: this loop is intentionally explicit, not range-form. This is
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431 // because the body of the loop will append nested footnotes to p.notes and
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 // we need to process those late additions. Range form would only walk over
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 // the fixed initial set.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 for i := 0; i < len(p.notes); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435 ref := p.notes[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 p.addExistingChild(ref.footnote, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437 block := ref.footnote
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438 block.ListFlags = flags | ListTypeOrdered
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 block.RefLink = ref.link
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440 if ref.hasBlock {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441 flags |= ListItemContainsBlock
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 p.block(ref.title)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 p.inline(block, ref.title)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446 flags &^= ListItemBeginningOfList | ListItemContainsBlock
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 above := block.Parent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 finalizeList(block)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450 p.tip = above
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451 block.Walk(func(node *Node, entering bool) WalkStatus {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452 if node.Type == Paragraph || node.Type == Heading {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 p.inline(node, node.content)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454 node.content = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456 return GoToNext
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461 // Link references
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 // This section implements support for references that (usually) appear
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 // as footnotes in a document, and can be referenced anywhere in the document.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465 // The basic format is:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 // [1]: http://www.google.com/ "Google"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 // [2]: http://www.github.com/ "Github"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 // Anywhere in the document, the reference can be linked by referring to its
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471 // label, i.e., 1 and 2 in this example, as in:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 // This library is hosted on [Github][2], a git hosting site.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 // Actual footnotes as specified in Pandoc and supported by some other Markdown
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476 // libraries such as php-markdown are also taken care of. They look like this:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 // This sentence needs a bit of further explanation.[^note]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480 // [^note]: This is the explanation.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
481 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
482 // Footnotes should be placed at the end of the document in an ordered list.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
483 // Finally, there are inline footnotes such as:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
484 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
485 // Inline footnotes^[Also supported.] provide a quick inline explanation,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
486 // but are rendered at the bottom of the document.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
487 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
488
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
489 // reference holds all information necessary for a reference-style links or
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
490 // footnotes.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
491 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
492 // Consider this markdown with reference-style links:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
493 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
494 // [link][ref]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
495 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
496 // [ref]: /url/ "tooltip title"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
497 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
498 // It will be ultimately converted to this HTML:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
499 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
500 // <p><a href=\"/url/\" title=\"title\">link</a></p>
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
501 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
502 // And a reference structure will be populated as follows:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
503 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
504 // p.refs["ref"] = &reference{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
505 // link: "/url/",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
506 // title: "tooltip title",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
507 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
508 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
509 // Alternatively, reference can contain information about a footnote. Consider
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
510 // this markdown:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
511 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
512 // Text needing a footnote.[^a]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
513 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
514 // [^a]: This is the note
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
515 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
516 // A reference structure will be populated as follows:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
517 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
518 // p.refs["a"] = &reference{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
519 // link: "a",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
520 // title: "This is the note",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
521 // noteID: <some positive int>,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
522 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
523 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
524 // TODO: As you can see, it begs for splitting into two dedicated structures
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
525 // for refs and for footnotes.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
526 type reference struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
527 link []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
528 title []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
529 noteID int // 0 if not a footnote ref
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
530 hasBlock bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
531 footnote *Node // a link to the Item node within a list of footnotes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
532
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
533 text []byte // only gets populated by refOverride feature with Reference.Text
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
534 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
535
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
536 func (r *reference) String() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
537 return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
538 r.link, r.title, r.text, r.noteID, r.hasBlock)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
539 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
540
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
541 // Check whether or not data starts with a reference link.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
542 // If so, it is parsed and stored in the list of references
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
543 // (in the render struct).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
544 // Returns the number of bytes to skip to move past it,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
545 // or zero if the first line is not a reference.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
546 func isReference(p *Markdown, data []byte, tabSize int) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
547 // up to 3 optional leading spaces
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
548 if len(data) < 4 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
549 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
550 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
551 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
552 for i < 3 && data[i] == ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
553 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
554 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
555
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
556 noteID := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
557
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
558 // id part: anything but a newline between brackets
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
559 if data[i] != '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
560 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
561 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
562 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
563 if p.extensions&Footnotes != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
564 if i < len(data) && data[i] == '^' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
565 // we can set it to anything here because the proper noteIds will
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
566 // be assigned later during the second pass. It just has to be != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
567 noteID = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
568 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
569 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
570 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
571 idOffset := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
572 for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
573 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
574 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
575 if i >= len(data) || data[i] != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
576 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
577 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
578 idEnd := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
579 // footnotes can have empty ID, like this: [^], but a reference can not be
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
580 // empty like this: []. Break early if it's not a footnote and there's no ID
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
581 if noteID == 0 && idOffset == idEnd {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
582 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
583 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
584 // spacer: colon (space | tab)* newline? (space | tab)*
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
585 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
586 if i >= len(data) || data[i] != ':' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
587 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
588 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
589 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
590 for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
591 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
592 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
593 if i < len(data) && (data[i] == '\n' || data[i] == '\r') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
594 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
595 if i < len(data) && data[i] == '\n' && data[i-1] == '\r' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
596 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
597 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
598 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
599 for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
600 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
601 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
602 if i >= len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
603 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
604 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
605
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
606 var (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
607 linkOffset, linkEnd int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
608 titleOffset, titleEnd int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
609 lineEnd int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
610 raw []byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
611 hasBlock bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
612 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
613
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
614 if p.extensions&Footnotes != 0 && noteID != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
615 linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
616 lineEnd = linkEnd
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
617 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
618 linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
619 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
620 if lineEnd == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
621 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
622 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
623
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
624 // a valid ref has been found
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
625
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
626 ref := &reference{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
627 noteID: noteID,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
628 hasBlock: hasBlock,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
629 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
630
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
631 if noteID > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
632 // reusing the link field for the id since footnotes don't have links
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
633 ref.link = data[idOffset:idEnd]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
634 // if footnote, it's not really a title, it's the contained text
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
635 ref.title = raw
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
636 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
637 ref.link = data[linkOffset:linkEnd]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
638 ref.title = data[titleOffset:titleEnd]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
639 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
640
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
641 // id matches are case-insensitive
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
642 id := string(bytes.ToLower(data[idOffset:idEnd]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
643
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
644 p.refs[id] = ref
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
645
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
646 return lineEnd
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
647 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
648
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
649 func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
650 // link: whitespace-free sequence, optionally between angle brackets
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
651 if data[i] == '<' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
652 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
653 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
654 linkOffset = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
655 for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
656 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
657 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
658 linkEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
659 if data[linkOffset] == '<' && data[linkEnd-1] == '>' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
660 linkOffset++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
661 linkEnd--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
662 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
663
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
664 // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
665 for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
666 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
667 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
668 if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
669 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
670 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
671
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
672 // compute end-of-line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
673 if i >= len(data) || data[i] == '\r' || data[i] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
674 lineEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
675 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
676 if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
677 lineEnd++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
678 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
679
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
680 // optional (space|tab)* spacer after a newline
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
681 if lineEnd > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
682 i = lineEnd + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
683 for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
684 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
685 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
686 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
687
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
688 // optional title: any non-newline sequence enclosed in '"() alone on its line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
689 if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
690 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
691 titleOffset = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
692
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
693 // look for EOL
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
694 for i < len(data) && data[i] != '\n' && data[i] != '\r' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
695 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
696 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
697 if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
698 titleEnd = i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
699 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
700 titleEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
701 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
702
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
703 // step back
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
704 i--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
705 for i > titleOffset && (data[i] == ' ' || data[i] == '\t') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
706 i--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
707 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
708 if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
709 lineEnd = titleEnd
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
710 titleEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
711 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
712 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
713
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
714 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
715 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
716
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
717 // The first bit of this logic is the same as Parser.listItem, but the rest
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
718 // is much simpler. This function simply finds the entire block and shifts it
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
719 // over by one tab if it is indeed a block (just returns the line if it's not).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
720 // blockEnd is the end of the section in the input buffer, and contents is the
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
721 // extracted text that was shifted over one tab. It will need to be rendered at
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
722 // the end of the document.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
723 func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
724 if i == 0 || len(data) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
725 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
726 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
727
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
728 // skip leading whitespace on first line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
729 for i < len(data) && data[i] == ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
730 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
731 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
732
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
733 blockStart = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
734
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
735 // find the end of the line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
736 blockEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
737 for i < len(data) && data[i-1] != '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
738 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
739 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
740
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
741 // get working buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
742 var raw bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
743
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
744 // put the first line into the working buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
745 raw.Write(data[blockEnd:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
746 blockEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
747
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
748 // process the following lines
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
749 containsBlankLine := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
750
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
751 gatherLines:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
752 for blockEnd < len(data) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
753 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
754
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
755 // find the end of this line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
756 for i < len(data) && data[i-1] != '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
757 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
758 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
759
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
760 // if it is an empty line, guess that it is part of this item
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
761 // and move on to the next line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
762 if p.isEmpty(data[blockEnd:i]) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
763 containsBlankLine = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
764 blockEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
765 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
766 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
767
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
768 n := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
769 if n = isIndented(data[blockEnd:i], indentSize); n == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
770 // this is the end of the block.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
771 // we don't want to include this last line in the index.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
772 break gatherLines
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
773 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
774
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
775 // if there were blank lines before this one, insert a new one now
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
776 if containsBlankLine {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
777 raw.WriteByte('\n')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
778 containsBlankLine = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
779 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
780
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
781 // get rid of that first tab, write to buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
782 raw.Write(data[blockEnd+n : i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
783 hasBlock = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
784
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
785 blockEnd = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
786 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
787
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
788 if data[blockEnd-1] != '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
789 raw.WriteByte('\n')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
790 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
791
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
792 contents = raw.Bytes()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
793
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
794 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
795 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
796
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
797 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
798 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
799 // Miscellaneous helper functions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
800 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
801 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
802
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
803 // Test if a character is a punctuation symbol.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
804 // Taken from a private function in regexp in the stdlib.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
805 func ispunct(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
806 for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
807 if c == r {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
808 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
809 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
810 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
811 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
812 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
813
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
814 // Test if a character is a whitespace character.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
815 func isspace(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
816 return ishorizontalspace(c) || isverticalspace(c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
817 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
818
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
819 // Test if a character is a horizontal whitespace character.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
820 func ishorizontalspace(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
821 return c == ' ' || c == '\t'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
822 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
823
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
824 // Test if a character is a vertical character.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
825 func isverticalspace(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
826 return c == '\n' || c == '\r' || c == '\f' || c == '\v'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
827 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
828
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
829 // Test if a character is letter.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
830 func isletter(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
831 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
832 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
833
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
834 // Test if a character is a letter or a digit.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
835 // TODO: check when this is looking for ASCII alnum and when it should use unicode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
836 func isalnum(c byte) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
837 return (c >= '0' && c <= '9') || isletter(c)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
838 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
839
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
840 // Replace tab characters with spaces, aligning to the next TAB_SIZE column.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
841 // always ends output with a newline
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
842 func expandTabs(out *bytes.Buffer, line []byte, tabSize int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
843 // first, check for common cases: no tabs, or only tabs at beginning of line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
844 i, prefix := 0, 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
845 slowcase := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
846 for i = 0; i < len(line); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
847 if line[i] == '\t' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
848 if prefix == i {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
849 prefix++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
850 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
851 slowcase = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
852 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
853 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
854 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
855 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
856
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
857 // no need to decode runes if all tabs are at the beginning of the line
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
858 if !slowcase {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
859 for i = 0; i < prefix*tabSize; i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
860 out.WriteByte(' ')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
861 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
862 out.Write(line[prefix:])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
863 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
864 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
865
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
866 // the slow case: we need to count runes to figure out how
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
867 // many spaces to insert for each tab
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
868 column := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
869 i = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
870 for i < len(line) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
871 start := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
872 for i < len(line) && line[i] != '\t' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
873 _, size := utf8.DecodeRune(line[i:])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
874 i += size
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
875 column++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
876 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
877
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
878 if i > start {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
879 out.Write(line[start:i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
880 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
881
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
882 if i >= len(line) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
883 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
884 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
885
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
886 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
887 out.WriteByte(' ')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
888 column++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
889 if column%tabSize == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
890 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
891 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
892 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
893
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
894 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
895 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
896 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
897
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
898 // Find if a line counts as indented or not.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
899 // Returns number of characters the indent is (0 = not indented).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
900 func isIndented(data []byte, indentSize int) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
901 if len(data) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
902 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
903 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
904 if data[0] == '\t' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
905 return 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
906 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
907 if len(data) < indentSize {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
908 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
909 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
910 for i := 0; i < indentSize; i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
911 if data[i] != ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
912 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
913 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
914 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
915 return indentSize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
916 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
917
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
918 // Create a url-safe slug for fragments
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
919 func slugify(in []byte) []byte {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
920 if len(in) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
921 return in
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
922 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
923 out := make([]byte, 0, len(in))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
924 sym := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
925
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
926 for _, ch := range in {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
927 if isalnum(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
928 sym = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
929 out = append(out, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
930 } else if sym {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
931 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
932 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
933 out = append(out, '-')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
934 sym = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
935 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
936 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
937 var a, b int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
938 var ch byte
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
939 for a, ch = range out {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
940 if ch != '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
941 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
942 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
943 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
944 for b = len(out) - 1; b > 0; b-- {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
945 if out[b] != '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
946 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
947 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
948 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
949 return out[a : b+1]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
950 }