summaryrefslogtreecommitdiff
path: root/vendor/github.com/yuin/goldmark
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
commitc6cc0108ca7738023b45e0eeac0fa2390532dd93 (patch)
tree36890e6cd3091bbab8efbe686cc56f467f645bfd /vendor/github.com/yuin/goldmark
parent0130404a1dc663d4aa68d780c9bcb23a4243e68d (diff)
downloadjbmafp-c6cc0108ca7738023b45e0eeac0fa2390532dd93.tar.gz
Added vendor lock on depsHEADmaster
Diffstat (limited to 'vendor/github.com/yuin/goldmark')
-rw-r--r--vendor/github.com/yuin/goldmark/.gitignore19
-rw-r--r--vendor/github.com/yuin/goldmark/LICENSE21
-rw-r--r--vendor/github.com/yuin/goldmark/Makefile10
-rw-r--r--vendor/github.com/yuin/goldmark/README.md515
-rw-r--r--vendor/github.com/yuin/goldmark/ast/ast.go508
-rw-r--r--vendor/github.com/yuin/goldmark/ast/block.go508
-rw-r--r--vendor/github.com/yuin/goldmark/ast/inline.go548
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/definition_list.go83
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/footnote.go138
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/strikethrough.go29
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/table.go157
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/tasklist.go35
-rw-r--r--vendor/github.com/yuin/goldmark/extension/cjk.go51
-rw-r--r--vendor/github.com/yuin/goldmark/extension/definition_list.go270
-rw-r--r--vendor/github.com/yuin/goldmark/extension/footnote.go687
-rw-r--r--vendor/github.com/yuin/goldmark/extension/gfm.go18
-rw-r--r--vendor/github.com/yuin/goldmark/extension/linkify.go318
-rw-r--r--vendor/github.com/yuin/goldmark/extension/strikethrough.go116
-rw-r--r--vendor/github.com/yuin/goldmark/extension/table.go556
-rw-r--r--vendor/github.com/yuin/goldmark/extension/tasklist.go115
-rw-r--r--vendor/github.com/yuin/goldmark/extension/typographer.go339
-rw-r--r--vendor/github.com/yuin/goldmark/markdown.go140
-rw-r--r--vendor/github.com/yuin/goldmark/parser/attribute.go328
-rw-r--r--vendor/github.com/yuin/goldmark/parser/atx_heading.go246
-rw-r--r--vendor/github.com/yuin/goldmark/parser/auto_link.go42
-rw-r--r--vendor/github.com/yuin/goldmark/parser/blockquote.go69
-rw-r--r--vendor/github.com/yuin/goldmark/parser/code_block.go100
-rw-r--r--vendor/github.com/yuin/goldmark/parser/code_span.go84
-rw-r--r--vendor/github.com/yuin/goldmark/parser/delimiter.go238
-rw-r--r--vendor/github.com/yuin/goldmark/parser/emphasis.go50
-rw-r--r--vendor/github.com/yuin/goldmark/parser/fcode_block.go121
-rw-r--r--vendor/github.com/yuin/goldmark/parser/html_block.go228
-rw-r--r--vendor/github.com/yuin/goldmark/parser/link.go409
-rw-r--r--vendor/github.com/yuin/goldmark/parser/link_ref.go152
-rw-r--r--vendor/github.com/yuin/goldmark/parser/list.go287
-rw-r--r--vendor/github.com/yuin/goldmark/parser/list_item.go90
-rw-r--r--vendor/github.com/yuin/goldmark/parser/paragraph.go72
-rw-r--r--vendor/github.com/yuin/goldmark/parser/parser.go1253
-rw-r--r--vendor/github.com/yuin/goldmark/parser/raw_html.go163
-rw-r--r--vendor/github.com/yuin/goldmark/parser/setext_headings.go126
-rw-r--r--vendor/github.com/yuin/goldmark/parser/thematic_break.go75
-rw-r--r--vendor/github.com/yuin/goldmark/renderer/html/html.go932
-rw-r--r--vendor/github.com/yuin/goldmark/renderer/renderer.go174
-rw-r--r--vendor/github.com/yuin/goldmark/text/reader.go653
-rw-r--r--vendor/github.com/yuin/goldmark/text/segment.go209
-rw-r--r--vendor/github.com/yuin/goldmark/util/html5entities.go2142
-rw-r--r--vendor/github.com/yuin/goldmark/util/unicode_case_folding.go1534
-rw-r--r--vendor/github.com/yuin/goldmark/util/util.go989
-rw-r--r--vendor/github.com/yuin/goldmark/util/util_safe.go13
-rw-r--r--vendor/github.com/yuin/goldmark/util/util_unsafe.go23
50 files changed, 15983 insertions, 0 deletions
diff --git a/vendor/github.com/yuin/goldmark/.gitignore b/vendor/github.com/yuin/goldmark/.gitignore
new file mode 100644
index 0000000..06c135f
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/.gitignore
@@ -0,0 +1,19 @@
1# Binaries for programs and plugins
2*.exe
3*.exe~
4*.dll
5*.so
6*.dylib
7
8# Test binary, build with `go test -c`
9*.test
10*.pprof
11
12# Output of the go coverage tool, specifically when used with LiteIDE
13*.out
14
15.DS_Store
16fuzz/corpus
17fuzz/crashers
18fuzz/suppressions
19fuzz/fuzz-fuzz.zip
diff --git a/vendor/github.com/yuin/goldmark/LICENSE b/vendor/github.com/yuin/goldmark/LICENSE
new file mode 100644
index 0000000..dc5b2a6
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/LICENSE
@@ -0,0 +1,21 @@
1MIT License
2
3Copyright (c) 2019 Yusuke Inuzuka
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/vendor/github.com/yuin/goldmark/Makefile b/vendor/github.com/yuin/goldmark/Makefile
new file mode 100644
index 0000000..e34fe86
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/Makefile
@@ -0,0 +1,10 @@
1.PHONY: test fuzz
2
3test:
4 go test -coverprofile=profile.out -coverpkg=github.com/yuin/goldmark,github.com/yuin/goldmark/ast,github.com/yuin/goldmark/extension,github.com/yuin/goldmark/extension/ast,github.com/yuin/goldmark/parser,github.com/yuin/goldmark/renderer,github.com/yuin/goldmark/renderer/html,github.com/yuin/goldmark/text,github.com/yuin/goldmark/util ./...
5
6cov: test
7 go tool cover -html=profile.out
8
9fuzz:
10 cd ./fuzz && go test -fuzz=Fuzz
diff --git a/vendor/github.com/yuin/goldmark/README.md b/vendor/github.com/yuin/goldmark/README.md
new file mode 100644
index 0000000..6244b47
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/README.md
@@ -0,0 +1,515 @@
1goldmark
2==========================================
3
4[![https://pkg.go.dev/github.com/yuin/goldmark](https://pkg.go.dev/badge/github.com/yuin/goldmark.svg)](https://pkg.go.dev/github.com/yuin/goldmark)
5[![https://github.com/yuin/goldmark/actions?query=workflow:test](https://github.com/yuin/goldmark/workflows/test/badge.svg?branch=master&event=push)](https://github.com/yuin/goldmark/actions?query=workflow:test)
6[![https://coveralls.io/github/yuin/goldmark](https://coveralls.io/repos/github/yuin/goldmark/badge.svg?branch=master)](https://coveralls.io/github/yuin/goldmark)
7[![https://goreportcard.com/report/github.com/yuin/goldmark](https://goreportcard.com/badge/github.com/yuin/goldmark)](https://goreportcard.com/report/github.com/yuin/goldmark)
8
9> A Markdown parser written in Go. Easy to extend, standards-compliant, well-structured.
10
11goldmark is compliant with CommonMark 0.30.
12
13Motivation
14----------------------
15I needed a Markdown parser for Go that satisfies the following requirements:
16
17- Easy to extend.
18 - Markdown is poor in document expressions compared to other light markup languages such as reStructuredText.
19 - We have extensions to the Markdown syntax, e.g. PHP Markdown Extra, GitHub Flavored Markdown.
20- Standards-compliant.
21 - Markdown has many dialects.
22 - GitHub-Flavored Markdown is widely used and is based upon CommonMark, effectively mooting the question of whether or not CommonMark is an ideal specification.
23 - CommonMark is complicated and hard to implement.
24- Well-structured.
25 - AST-based; preserves source position of nodes.
26- Written in pure Go.
27
28[golang-commonmark](https://gitlab.com/golang-commonmark/markdown) may be a good choice, but it seems to be a copy of [markdown-it](https://github.com/markdown-it).
29
30[blackfriday.v2](https://github.com/russross/blackfriday/tree/v2) is a fast and widely-used implementation, but is not CommonMark-compliant and cannot be extended from outside of the package, since its AST uses structs instead of interfaces.
31
32Furthermore, its behavior differs from other implementations in some cases, especially regarding lists: [Deep nested lists don't output correctly #329](https://github.com/russross/blackfriday/issues/329), [List block cannot have a second line #244](https://github.com/russross/blackfriday/issues/244), etc.
33
34This behavior sometimes causes problems. If you migrate your Markdown text from GitHub to blackfriday-based wikis, many lists will immediately be broken.
35
36As mentioned above, CommonMark is complicated and hard to implement, so Markdown parsers based on CommonMark are few and far between.
37
38Features
39----------------------
40
41- **Standards-compliant.** goldmark is fully compliant with the latest [CommonMark](https://commonmark.org/) specification.
42- **Extensible.** Do you want to add a `@username` mention syntax to Markdown?
43 You can easily do so in goldmark. You can add your AST nodes,
44 parsers for block-level elements, parsers for inline-level elements,
45 transformers for paragraphs, transformers for the whole AST structure, and
46 renderers.
47- **Performance.** goldmark's performance is on par with that of cmark,
48 the CommonMark reference implementation written in C.
49- **Robust.** goldmark is tested with `go test --fuzz`.
50- **Built-in extensions.** goldmark ships with common extensions like tables, strikethrough,
51 task lists, and definition lists.
52- **Depends only on standard libraries.**
53
54Installation
55----------------------
56```bash
57$ go get github.com/yuin/goldmark
58```
59
60
61Usage
62----------------------
63Import packages:
64
65```go
66import (
67 "bytes"
68 "github.com/yuin/goldmark"
69)
70```
71
72
73Convert Markdown documents with the CommonMark-compliant mode:
74
75```go
76var buf bytes.Buffer
77if err := goldmark.Convert(source, &buf); err != nil {
78 panic(err)
79}
80```
81
82With options
83------------------------------
84
85```go
86var buf bytes.Buffer
87if err := goldmark.Convert(source, &buf, parser.WithContext(ctx)); err != nil {
88 panic(err)
89}
90```
91
92| Functional option | Type | Description |
93| ----------------- | ---- | ----------- |
94| `parser.WithContext` | A `parser.Context` | Context for the parsing phase. |
95
96Context options
97----------------------
98
99| Functional option | Type | Description |
100| ----------------- | ---- | ----------- |
101| `parser.WithIDs` | A `parser.IDs` | `IDs` allows you to change logics that are related to element id(ex: Auto heading id generation). |
102
103
104Custom parser and renderer
105--------------------------
106```go
107import (
108 "bytes"
109 "github.com/yuin/goldmark"
110 "github.com/yuin/goldmark/extension"
111 "github.com/yuin/goldmark/parser"
112 "github.com/yuin/goldmark/renderer/html"
113)
114
115md := goldmark.New(
116 goldmark.WithExtensions(extension.GFM),
117 goldmark.WithParserOptions(
118 parser.WithAutoHeadingID(),
119 ),
120 goldmark.WithRendererOptions(
121 html.WithHardWraps(),
122 html.WithXHTML(),
123 ),
124 )
125var buf bytes.Buffer
126if err := md.Convert(source, &buf); err != nil {
127 panic(err)
128}
129```
130
131| Functional option | Type | Description |
132| ----------------- | ---- | ----------- |
133| `goldmark.WithParser` | `parser.Parser` | This option must be passed before `goldmark.WithParserOptions` and `goldmark.WithExtensions` |
134| `goldmark.WithRenderer` | `renderer.Renderer` | This option must be passed before `goldmark.WithRendererOptions` and `goldmark.WithExtensions` |
135| `goldmark.WithParserOptions` | `...parser.Option` | |
136| `goldmark.WithRendererOptions` | `...renderer.Option` | |
137| `goldmark.WithExtensions` | `...goldmark.Extender` | |
138
139Parser and Renderer options
140------------------------------
141
142### Parser options
143
144| Functional option | Type | Description |
145| ----------------- | ---- | ----------- |
146| `parser.WithBlockParsers` | A `util.PrioritizedSlice` whose elements are `parser.BlockParser` | Parsers for parsing block level elements. |
147| `parser.WithInlineParsers` | A `util.PrioritizedSlice` whose elements are `parser.InlineParser` | Parsers for parsing inline level elements. |
148| `parser.WithParagraphTransformers` | A `util.PrioritizedSlice` whose elements are `parser.ParagraphTransformer` | Transformers for transforming paragraph nodes. |
149| `parser.WithASTTransformers` | A `util.PrioritizedSlice` whose elements are `parser.ASTTransformer` | Transformers for transforming an AST. |
150| `parser.WithAutoHeadingID` | `-` | Enables auto heading ids. |
151| `parser.WithAttribute` | `-` | Enables custom attributes. Currently only headings supports attributes. |
152
153### HTML Renderer options
154
155| Functional option | Type | Description |
156| ----------------- | ---- | ----------- |
157| `html.WithWriter` | `html.Writer` | `html.Writer` for writing contents to an `io.Writer`. |
158| `html.WithHardWraps` | `-` | Render newlines as `<br>`.|
159| `html.WithXHTML` | `-` | Render as XHTML. |
160| `html.WithUnsafe` | `-` | By default, goldmark does not render raw HTML or potentially dangerous links. With this option, goldmark renders such content as written. |
161
162### Built-in extensions
163
164- `extension.Table`
165 - [GitHub Flavored Markdown: Tables](https://github.github.com/gfm/#tables-extension-)
166- `extension.Strikethrough`
167 - [GitHub Flavored Markdown: Strikethrough](https://github.github.com/gfm/#strikethrough-extension-)
168- `extension.Linkify`
169 - [GitHub Flavored Markdown: Autolinks](https://github.github.com/gfm/#autolinks-extension-)
170- `extension.TaskList`
171 - [GitHub Flavored Markdown: Task list items](https://github.github.com/gfm/#task-list-items-extension-)
172- `extension.GFM`
173 - This extension enables Table, Strikethrough, Linkify and TaskList.
174 - This extension does not filter tags defined in [6.11: Disallowed Raw HTML (extension)](https://github.github.com/gfm/#disallowed-raw-html-extension-).
175 If you need to filter HTML tags, see [Security](#security).
176 - If you need to parse github emojis, you can use [goldmark-emoji](https://github.com/yuin/goldmark-emoji) extension.
177- `extension.DefinitionList`
178 - [PHP Markdown Extra: Definition lists](https://michelf.ca/projects/php-markdown/extra/#def-list)
179- `extension.Footnote`
180 - [PHP Markdown Extra: Footnotes](https://michelf.ca/projects/php-markdown/extra/#footnotes)
181- `extension.Typographer`
182 - This extension substitutes punctuations with typographic entities like [smartypants](https://daringfireball.net/projects/smartypants/).
183- `extension.CJK`
184 - This extension is a shortcut for CJK related functionalities.
185
186### Attributes
187The `parser.WithAttribute` option allows you to define attributes on some elements.
188
189Currently only headings support attributes.
190
191**Attributes are being discussed in the
192[CommonMark forum](https://talk.commonmark.org/t/consistent-attribute-syntax/272).
193This syntax may possibly change in the future.**
194
195
196#### Headings
197
198```
199## heading ## {#id .className attrName=attrValue class="class1 class2"}
200
201## heading {#id .className attrName=attrValue class="class1 class2"}
202```
203
204```
205heading {#id .className attrName=attrValue}
206============
207```
208
209### Table extension
210The Table extension implements [Table(extension)](https://github.github.com/gfm/#tables-extension-), as
211defined in [GitHub Flavored Markdown Spec](https://github.github.com/gfm/).
212
213Specs are defined for XHTML, so specs use some deprecated attributes for HTML5.
214
215You can override alignment rendering method via options.
216
217| Functional option | Type | Description |
218| ----------------- | ---- | ----------- |
219| `extension.WithTableCellAlignMethod` | `extension.TableCellAlignMethod` | Option indicates how are table cells aligned. |
220
221### Typographer extension
222
223The Typographer extension translates plain ASCII punctuation characters into typographic-punctuation HTML entities.
224
225Default substitutions are:
226
227| Punctuation | Default entity |
228| ------------ | ---------- |
229| `'` | `&lsquo;`, `&rsquo;` |
230| `"` | `&ldquo;`, `&rdquo;` |
231| `--` | `&ndash;` |
232| `---` | `&mdash;` |
233| `...` | `&hellip;` |
234| `<<` | `&laquo;` |
235| `>>` | `&raquo;` |
236
237You can override the default substitutions via `extensions.WithTypographicSubstitutions`:
238
239```go
240markdown := goldmark.New(
241 goldmark.WithExtensions(
242 extension.NewTypographer(
243 extension.WithTypographicSubstitutions(extension.TypographicSubstitutions{
244 extension.LeftSingleQuote: []byte("&sbquo;"),
245 extension.RightSingleQuote: nil, // nil disables a substitution
246 }),
247 ),
248 ),
249)
250```
251
252### Linkify extension
253
254The Linkify extension implements [Autolinks(extension)](https://github.github.com/gfm/#autolinks-extension-), as
255defined in [GitHub Flavored Markdown Spec](https://github.github.com/gfm/).
256
257Since the spec does not define details about URLs, there are numerous ambiguous cases.
258
259You can override autolinking patterns via options.
260
261| Functional option | Type | Description |
262| ----------------- | ---- | ----------- |
263| `extension.WithLinkifyAllowedProtocols` | `[][]byte` | List of allowed protocols such as `[][]byte{ []byte("http:") }` |
264| `extension.WithLinkifyURLRegexp` | `*regexp.Regexp` | Regexp that defines URLs, including protocols |
265| `extension.WithLinkifyWWWRegexp` | `*regexp.Regexp` | Regexp that defines URL starting with `www.`. This pattern corresponds to [the extended www autolink](https://github.github.com/gfm/#extended-www-autolink) |
266| `extension.WithLinkifyEmailRegexp` | `*regexp.Regexp` | Regexp that defines email addresses` |
267
268Example, using [xurls](https://github.com/mvdan/xurls):
269
270```go
271import "mvdan.cc/xurls/v2"
272
273markdown := goldmark.New(
274 goldmark.WithRendererOptions(
275 html.WithXHTML(),
276 html.WithUnsafe(),
277 ),
278 goldmark.WithExtensions(
279 extension.NewLinkify(
280 extension.WithLinkifyAllowedProtocols([][]byte{
281 []byte("http:"),
282 []byte("https:"),
283 }),
284 extension.WithLinkifyURLRegexp(
285 xurls.Strict,
286 ),
287 ),
288 ),
289)
290```
291
292### Footnotes extension
293
294The Footnote extension implements [PHP Markdown Extra: Footnotes](https://michelf.ca/projects/php-markdown/extra/#footnotes).
295
296This extension has some options:
297
298| Functional option | Type | Description |
299| ----------------- | ---- | ----------- |
300| `extension.WithFootnoteIDPrefix` | `[]byte` | a prefix for the id attributes.|
301| `extension.WithFootnoteIDPrefixFunction` | `func(gast.Node) []byte` | a function that determines the id attribute for given Node.|
302| `extension.WithFootnoteLinkTitle` | `[]byte` | an optional title attribute for footnote links.|
303| `extension.WithFootnoteBacklinkTitle` | `[]byte` | an optional title attribute for footnote backlinks. |
304| `extension.WithFootnoteLinkClass` | `[]byte` | a class for footnote links. This defaults to `footnote-ref`. |
305| `extension.WithFootnoteBacklinkClass` | `[]byte` | a class for footnote backlinks. This defaults to `footnote-backref`. |
306| `extension.WithFootnoteBacklinkHTML` | `[]byte` | a class for footnote backlinks. This defaults to `&#x21a9;&#xfe0e;`. |
307
308Some options can have special substitutions. Occurrences of “^^” in the string will be replaced by the corresponding footnote number in the HTML output. Occurrences of “%%” will be replaced by a number for the reference (footnotes can have multiple references).
309
310`extension.WithFootnoteIDPrefix` and `extension.WithFootnoteIDPrefixFunction` are useful if you have multiple Markdown documents displayed inside one HTML document to avoid footnote ids to clash each other.
311
312`extension.WithFootnoteIDPrefix` sets fixed id prefix, so you may write codes like the following:
313
314```go
315for _, path := range files {
316 source := readAll(path)
317 prefix := getPrefix(path)
318
319 markdown := goldmark.New(
320 goldmark.WithExtensions(
321 NewFootnote(
322 WithFootnoteIDPrefix([]byte(path)),
323 ),
324 ),
325 )
326 var b bytes.Buffer
327 err := markdown.Convert(source, &b)
328 if err != nil {
329 t.Error(err.Error())
330 }
331}
332```
333
334`extension.WithFootnoteIDPrefixFunction` determines an id prefix by calling given function, so you may write codes like the following:
335
336```go
337markdown := goldmark.New(
338 goldmark.WithExtensions(
339 NewFootnote(
340 WithFootnoteIDPrefixFunction(func(n gast.Node) []byte {
341 v, ok := n.OwnerDocument().Meta()["footnote-prefix"]
342 if ok {
343 return util.StringToReadOnlyBytes(v.(string))
344 }
345 return nil
346 }),
347 ),
348 ),
349)
350
351for _, path := range files {
352 source := readAll(path)
353 var b bytes.Buffer
354
355 doc := markdown.Parser().Parse(text.NewReader(source))
356 doc.Meta()["footnote-prefix"] = getPrefix(path)
357 err := markdown.Renderer().Render(&b, source, doc)
358}
359```
360
361You can use [goldmark-meta](https://github.com/yuin/goldmark-meta) to define a id prefix in the markdown document:
362
363
364```markdown
365---
366title: document title
367slug: article1
368footnote-prefix: article1
369---
370
371# My article
372
373```
374
375### CJK extension
376CommonMark gives compatibilities a high priority and original markdown was designed by westerners. So CommonMark lacks considerations for languages like CJK.
377
378This extension provides additional options for CJK users.
379
380| Functional option | Type | Description |
381| ----------------- | ---- | ----------- |
382| `extension.WithEastAsianLineBreaks` | `-` | Soft line breaks are rendered as a newline. Some asian users will see it as an unnecessary space. With this option, soft line breaks between east asian wide characters will be ignored. |
383| `extension.WithEscapedSpace` | `-` | Without spaces around an emphasis started with east asian punctuations, it is not interpreted as an emphasis(as defined in CommonMark spec). With this option, you can avoid this inconvenient behavior by putting 'not rendered' spaces around an emphasis like `太郎は\ **「こんにちわ」**\ といった`. |
384
385
386Security
387--------------------
388By default, goldmark does not render raw HTML or potentially-dangerous URLs.
389If you need to gain more control over untrusted contents, it is recommended that you
390use an HTML sanitizer such as [bluemonday](https://github.com/microcosm-cc/bluemonday).
391
392Benchmark
393--------------------
394You can run this benchmark in the `_benchmark` directory.
395
396### against other golang libraries
397
398blackfriday v2 seems to be the fastest, but as it is not CommonMark compliant, its performance cannot be directly compared to that of the CommonMark-compliant libraries.
399
400goldmark, meanwhile, builds a clean, extensible AST structure, achieves full compliance with
401CommonMark, and consumes less memory, all while being reasonably fast.
402
403- MBP 2019 13″(i5, 16GB), Go1.17
404
405```
406BenchmarkMarkdown/Blackfriday-v2-8 302 3743747 ns/op 3290445 B/op 20050 allocs/op
407BenchmarkMarkdown/GoldMark-8 280 4200974 ns/op 2559738 B/op 13435 allocs/op
408BenchmarkMarkdown/CommonMark-8 226 5283686 ns/op 2702490 B/op 20792 allocs/op
409BenchmarkMarkdown/Lute-8 12 92652857 ns/op 10602649 B/op 40555 allocs/op
410BenchmarkMarkdown/GoMarkdown-8 13 81380167 ns/op 2245002 B/op 22889 allocs/op
411```
412
413### against cmark (CommonMark reference implementation written in C)
414
415- MBP 2019 13″(i5, 16GB), Go1.17
416
417```
418----------- cmark -----------
419file: _data.md
420iteration: 50
421average: 0.0044073057 sec
422------- goldmark -------
423file: _data.md
424iteration: 50
425average: 0.0041611990 sec
426```
427
428As you can see, goldmark's performance is on par with cmark's.
429
430Extensions
431--------------------
432
433- [goldmark-meta](https://github.com/yuin/goldmark-meta): A YAML metadata
434 extension for the goldmark Markdown parser.
435- [goldmark-highlighting](https://github.com/yuin/goldmark-highlighting): A syntax-highlighting extension
436 for the goldmark markdown parser.
437- [goldmark-emoji](https://github.com/yuin/goldmark-emoji): An emoji
438 extension for the goldmark Markdown parser.
439- [goldmark-mathjax](https://github.com/litao91/goldmark-mathjax): Mathjax support for the goldmark markdown parser
440- [goldmark-pdf](https://github.com/stephenafamo/goldmark-pdf): A PDF renderer that can be passed to `goldmark.WithRenderer()`.
441- [goldmark-hashtag](https://github.com/abhinav/goldmark-hashtag): Adds support for `#hashtag`-based tagging to goldmark.
442- [goldmark-wikilink](https://github.com/abhinav/goldmark-wikilink): Adds support for `[[wiki]]`-style links to goldmark.
443- [goldmark-toc](https://github.com/abhinav/goldmark-toc): Adds support for generating tables-of-contents for goldmark documents.
444- [goldmark-mermaid](https://github.com/abhinav/goldmark-mermaid): Adds support for rendering [Mermaid](https://mermaid-js.github.io/mermaid/) diagrams in goldmark documents.
445- [goldmark-pikchr](https://github.com/jchenry/goldmark-pikchr): Adds support for rendering [Pikchr](https://pikchr.org/home/doc/trunk/homepage.md) diagrams in goldmark documents.
446- [goldmark-embed](https://github.com/13rac1/goldmark-embed): Adds support for rendering embeds from YouTube links.
447- [goldmark-latex](https://github.com/soypat/goldmark-latex): A $\LaTeX$ renderer that can be passed to `goldmark.WithRenderer()`.
448- [goldmark-fences](https://github.com/stefanfritsch/goldmark-fences): Support for pandoc-style [fenced divs](https://pandoc.org/MANUAL.html#divs-and-spans) in goldmark.
449- [goldmark-d2](https://github.com/FurqanSoftware/goldmark-d2): Adds support for [D2](https://d2lang.com/) diagrams.
450- [goldmark-katex](https://github.com/FurqanSoftware/goldmark-katex): Adds support for [KaTeX](https://katex.org/) math and equations.
451
452
453goldmark internal(for extension developers)
454----------------------------------------------
455### Overview
456goldmark's Markdown processing is outlined in the diagram below.
457
458```
459 <Markdown in []byte, parser.Context>
460 |
461 V
462 +-------- parser.Parser ---------------------------
463 | 1. Parse block elements into AST
464 | 1. If a parsed block is a paragraph, apply
465 | ast.ParagraphTransformer
466 | 2. Traverse AST and parse blocks.
467 | 1. Process delimiters(emphasis) at the end of
468 | block parsing
469 | 3. Apply parser.ASTTransformers to AST
470 |
471 V
472 <ast.Node>
473 |
474 V
475 +------- renderer.Renderer ------------------------
476 | 1. Traverse AST and apply renderer.NodeRenderer
477 | corespond to the node type
478
479 |
480 V
481 <Output>
482```
483
484### Parsing
485Markdown documents are read through `text.Reader` interface.
486
487AST nodes do not have concrete text. AST nodes have segment information of the documents, represented by `text.Segment` .
488
489`text.Segment` has 3 attributes: `Start`, `End`, `Padding` .
490
491(TBC)
492
493**TODO**
494
495See `extension` directory for examples of extensions.
496
497Summary:
498
4991. Define AST Node as a struct in which `ast.BaseBlock` or `ast.BaseInline` is embedded.
5002. Write a parser that implements `parser.BlockParser` or `parser.InlineParser`.
5013. Write a renderer that implements `renderer.NodeRenderer`.
5024. Define your goldmark extension that implements `goldmark.Extender`.
503
504
505Donation
506--------------------
507BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
508
509License
510--------------------
511MIT
512
513Author
514--------------------
515Yusuke Inuzuka
diff --git a/vendor/github.com/yuin/goldmark/ast/ast.go b/vendor/github.com/yuin/goldmark/ast/ast.go
new file mode 100644
index 0000000..3719ebb
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/ast.go
@@ -0,0 +1,508 @@
1// Package ast defines AST nodes that represent markdown elements.
2package ast
3
4import (
5 "bytes"
6 "fmt"
7 "strings"
8
9 textm "github.com/yuin/goldmark/text"
10 "github.com/yuin/goldmark/util"
11)
12
13// A NodeType indicates what type a node belongs to.
14type NodeType int
15
16const (
17 // TypeBlock indicates that a node is kind of block nodes.
18 TypeBlock NodeType = iota + 1
19 // TypeInline indicates that a node is kind of inline nodes.
20 TypeInline
21 // TypeDocument indicates that a node is kind of document nodes.
22 TypeDocument
23)
24
25// NodeKind indicates more specific type than NodeType.
26type NodeKind int
27
28func (k NodeKind) String() string {
29 return kindNames[k]
30}
31
32var kindMax NodeKind
33var kindNames = []string{""}
34
35// NewNodeKind returns a new Kind value.
36func NewNodeKind(name string) NodeKind {
37 kindMax++
38 kindNames = append(kindNames, name)
39 return kindMax
40}
41
42// An Attribute is an attribute of the Node
43type Attribute struct {
44 Name []byte
45 Value interface{}
46}
47
48// A Node interface defines basic AST node functionalities.
49type Node interface {
50 // Type returns a type of this node.
51 Type() NodeType
52
53 // Kind returns a kind of this node.
54 Kind() NodeKind
55
56 // NextSibling returns a next sibling node of this node.
57 NextSibling() Node
58
59 // PreviousSibling returns a previous sibling node of this node.
60 PreviousSibling() Node
61
62 // Parent returns a parent node of this node.
63 Parent() Node
64
65 // SetParent sets a parent node to this node.
66 SetParent(Node)
67
68 // SetPreviousSibling sets a previous sibling node to this node.
69 SetPreviousSibling(Node)
70
71 // SetNextSibling sets a next sibling node to this node.
72 SetNextSibling(Node)
73
74 // HasChildren returns true if this node has any children, otherwise false.
75 HasChildren() bool
76
77 // ChildCount returns a total number of children.
78 ChildCount() int
79
80 // FirstChild returns a first child of this node.
81 FirstChild() Node
82
83 // LastChild returns a last child of this node.
84 LastChild() Node
85
86 // AppendChild append a node child to the tail of the children.
87 AppendChild(self, child Node)
88
89 // RemoveChild removes a node child from this node.
90 // If a node child is not children of this node, RemoveChild nothing to do.
91 RemoveChild(self, child Node)
92
93 // RemoveChildren removes all children from this node.
94 RemoveChildren(self Node)
95
96 // SortChildren sorts childrens by comparator.
97 SortChildren(comparator func(n1, n2 Node) int)
98
99 // ReplaceChild replace a node v1 with a node insertee.
100 // If v1 is not children of this node, ReplaceChild append a insetee to the
101 // tail of the children.
102 ReplaceChild(self, v1, insertee Node)
103
104 // InsertBefore inserts a node insertee before a node v1.
105 // If v1 is not children of this node, InsertBefore append a insetee to the
106 // tail of the children.
107 InsertBefore(self, v1, insertee Node)
108
109 // InsertAfterinserts a node insertee after a node v1.
110 // If v1 is not children of this node, InsertBefore append a insetee to the
111 // tail of the children.
112 InsertAfter(self, v1, insertee Node)
113
114 // OwnerDocument returns this node's owner document.
115 // If this node is not a child of the Document node, OwnerDocument
116 // returns nil.
117 OwnerDocument() *Document
118
119 // Dump dumps an AST tree structure to stdout.
120 // This function completely aimed for debugging.
121 // level is a indent level. Implementer should indent informations with
122 // 2 * level spaces.
123 Dump(source []byte, level int)
124
125 // Text returns text values of this node.
126 Text(source []byte) []byte
127
128 // HasBlankPreviousLines returns true if the row before this node is blank,
129 // otherwise false.
130 // This method is valid only for block nodes.
131 HasBlankPreviousLines() bool
132
133 // SetBlankPreviousLines sets whether the row before this node is blank.
134 // This method is valid only for block nodes.
135 SetBlankPreviousLines(v bool)
136
137 // Lines returns text segments that hold positions in a source.
138 // This method is valid only for block nodes.
139 Lines() *textm.Segments
140
141 // SetLines sets text segments that hold positions in a source.
142 // This method is valid only for block nodes.
143 SetLines(*textm.Segments)
144
145 // IsRaw returns true if contents should be rendered as 'raw' contents.
146 IsRaw() bool
147
148 // SetAttribute sets the given value to the attributes.
149 SetAttribute(name []byte, value interface{})
150
151 // SetAttributeString sets the given value to the attributes.
152 SetAttributeString(name string, value interface{})
153
154 // Attribute returns a (attribute value, true) if an attribute
155 // associated with the given name is found, otherwise
156 // (nil, false)
157 Attribute(name []byte) (interface{}, bool)
158
159 // AttributeString returns a (attribute value, true) if an attribute
160 // associated with the given name is found, otherwise
161 // (nil, false)
162 AttributeString(name string) (interface{}, bool)
163
164 // Attributes returns a list of attributes.
165 // This may be a nil if there are no attributes.
166 Attributes() []Attribute
167
168 // RemoveAttributes removes all attributes from this node.
169 RemoveAttributes()
170}
171
172// A BaseNode struct implements the Node interface partialliy.
173type BaseNode struct {
174 firstChild Node
175 lastChild Node
176 parent Node
177 next Node
178 prev Node
179 childCount int
180 attributes []Attribute
181}
182
183func ensureIsolated(v Node) {
184 if p := v.Parent(); p != nil {
185 p.RemoveChild(p, v)
186 }
187}
188
189// HasChildren implements Node.HasChildren .
190func (n *BaseNode) HasChildren() bool {
191 return n.firstChild != nil
192}
193
194// SetPreviousSibling implements Node.SetPreviousSibling .
195func (n *BaseNode) SetPreviousSibling(v Node) {
196 n.prev = v
197}
198
199// SetNextSibling implements Node.SetNextSibling .
200func (n *BaseNode) SetNextSibling(v Node) {
201 n.next = v
202}
203
204// PreviousSibling implements Node.PreviousSibling .
205func (n *BaseNode) PreviousSibling() Node {
206 return n.prev
207}
208
209// NextSibling implements Node.NextSibling .
210func (n *BaseNode) NextSibling() Node {
211 return n.next
212}
213
214// RemoveChild implements Node.RemoveChild .
215func (n *BaseNode) RemoveChild(self, v Node) {
216 if v.Parent() != self {
217 return
218 }
219 n.childCount--
220 prev := v.PreviousSibling()
221 next := v.NextSibling()
222 if prev != nil {
223 prev.SetNextSibling(next)
224 } else {
225 n.firstChild = next
226 }
227 if next != nil {
228 next.SetPreviousSibling(prev)
229 } else {
230 n.lastChild = prev
231 }
232 v.SetParent(nil)
233 v.SetPreviousSibling(nil)
234 v.SetNextSibling(nil)
235}
236
237// RemoveChildren implements Node.RemoveChildren .
238func (n *BaseNode) RemoveChildren(self Node) {
239 for c := n.firstChild; c != nil; {
240 c.SetParent(nil)
241 c.SetPreviousSibling(nil)
242 next := c.NextSibling()
243 c.SetNextSibling(nil)
244 c = next
245 }
246 n.firstChild = nil
247 n.lastChild = nil
248 n.childCount = 0
249}
250
251// SortChildren implements Node.SortChildren
252func (n *BaseNode) SortChildren(comparator func(n1, n2 Node) int) {
253 var sorted Node
254 current := n.firstChild
255 for current != nil {
256 next := current.NextSibling()
257 if sorted == nil || comparator(sorted, current) >= 0 {
258 current.SetNextSibling(sorted)
259 if sorted != nil {
260 sorted.SetPreviousSibling(current)
261 }
262 sorted = current
263 sorted.SetPreviousSibling(nil)
264 } else {
265 c := sorted
266 for c.NextSibling() != nil && comparator(c.NextSibling(), current) < 0 {
267 c = c.NextSibling()
268 }
269 current.SetNextSibling(c.NextSibling())
270 current.SetPreviousSibling(c)
271 if c.NextSibling() != nil {
272 c.NextSibling().SetPreviousSibling(current)
273 }
274 c.SetNextSibling(current)
275 }
276 current = next
277 }
278 n.firstChild = sorted
279 for c := n.firstChild; c != nil; c = c.NextSibling() {
280 n.lastChild = c
281 }
282}
283
284// FirstChild implements Node.FirstChild .
285func (n *BaseNode) FirstChild() Node {
286 return n.firstChild
287}
288
289// LastChild implements Node.LastChild .
290func (n *BaseNode) LastChild() Node {
291 return n.lastChild
292}
293
294// ChildCount implements Node.ChildCount .
295func (n *BaseNode) ChildCount() int {
296 return n.childCount
297}
298
299// Parent implements Node.Parent .
300func (n *BaseNode) Parent() Node {
301 return n.parent
302}
303
304// SetParent implements Node.SetParent .
305func (n *BaseNode) SetParent(v Node) {
306 n.parent = v
307}
308
309// AppendChild implements Node.AppendChild .
310func (n *BaseNode) AppendChild(self, v Node) {
311 ensureIsolated(v)
312 if n.firstChild == nil {
313 n.firstChild = v
314 v.SetNextSibling(nil)
315 v.SetPreviousSibling(nil)
316 } else {
317 last := n.lastChild
318 last.SetNextSibling(v)
319 v.SetPreviousSibling(last)
320 }
321 v.SetParent(self)
322 n.lastChild = v
323 n.childCount++
324}
325
326// ReplaceChild implements Node.ReplaceChild .
327func (n *BaseNode) ReplaceChild(self, v1, insertee Node) {
328 n.InsertBefore(self, v1, insertee)
329 n.RemoveChild(self, v1)
330}
331
332// InsertAfter implements Node.InsertAfter .
333func (n *BaseNode) InsertAfter(self, v1, insertee Node) {
334 n.InsertBefore(self, v1.NextSibling(), insertee)
335}
336
337// InsertBefore implements Node.InsertBefore .
338func (n *BaseNode) InsertBefore(self, v1, insertee Node) {
339 n.childCount++
340 if v1 == nil {
341 n.AppendChild(self, insertee)
342 return
343 }
344 ensureIsolated(insertee)
345 if v1.Parent() == self {
346 c := v1
347 prev := c.PreviousSibling()
348 if prev != nil {
349 prev.SetNextSibling(insertee)
350 insertee.SetPreviousSibling(prev)
351 } else {
352 n.firstChild = insertee
353 insertee.SetPreviousSibling(nil)
354 }
355 insertee.SetNextSibling(c)
356 c.SetPreviousSibling(insertee)
357 insertee.SetParent(self)
358 }
359}
360
361// OwnerDocument implements Node.OwnerDocument
362func (n *BaseNode) OwnerDocument() *Document {
363 d := n.Parent()
364 for {
365 p := d.Parent()
366 if p == nil {
367 if v, ok := d.(*Document); ok {
368 return v
369 }
370 break
371 }
372 d = p
373 }
374 return nil
375}
376
377// Text implements Node.Text .
378func (n *BaseNode) Text(source []byte) []byte {
379 var buf bytes.Buffer
380 for c := n.firstChild; c != nil; c = c.NextSibling() {
381 buf.Write(c.Text(source))
382 }
383 return buf.Bytes()
384}
385
386// SetAttribute implements Node.SetAttribute.
387func (n *BaseNode) SetAttribute(name []byte, value interface{}) {
388 if n.attributes == nil {
389 n.attributes = make([]Attribute, 0, 10)
390 } else {
391 for i, a := range n.attributes {
392 if bytes.Equal(a.Name, name) {
393 n.attributes[i].Name = name
394 n.attributes[i].Value = value
395 return
396 }
397 }
398 }
399 n.attributes = append(n.attributes, Attribute{name, value})
400}
401
402// SetAttributeString implements Node.SetAttributeString
403func (n *BaseNode) SetAttributeString(name string, value interface{}) {
404 n.SetAttribute(util.StringToReadOnlyBytes(name), value)
405}
406
407// Attribute implements Node.Attribute.
408func (n *BaseNode) Attribute(name []byte) (interface{}, bool) {
409 if n.attributes == nil {
410 return nil, false
411 }
412 for i, a := range n.attributes {
413 if bytes.Equal(a.Name, name) {
414 return n.attributes[i].Value, true
415 }
416 }
417 return nil, false
418}
419
420// AttributeString implements Node.AttributeString.
421func (n *BaseNode) AttributeString(s string) (interface{}, bool) {
422 return n.Attribute(util.StringToReadOnlyBytes(s))
423}
424
425// Attributes implements Node.Attributes
426func (n *BaseNode) Attributes() []Attribute {
427 return n.attributes
428}
429
430// RemoveAttributes implements Node.RemoveAttributes
431func (n *BaseNode) RemoveAttributes() {
432 n.attributes = nil
433}
434
435// DumpHelper is a helper function to implement Node.Dump.
436// kv is pairs of an attribute name and an attribute value.
437// cb is a function called after wrote a name and attributes.
438func DumpHelper(v Node, source []byte, level int, kv map[string]string, cb func(int)) {
439 name := v.Kind().String()
440 indent := strings.Repeat(" ", level)
441 fmt.Printf("%s%s {\n", indent, name)
442 indent2 := strings.Repeat(" ", level+1)
443 if v.Type() == TypeBlock {
444 fmt.Printf("%sRawText: \"", indent2)
445 for i := 0; i < v.Lines().Len(); i++ {
446 line := v.Lines().At(i)
447 fmt.Printf("%s", line.Value(source))
448 }
449 fmt.Printf("\"\n")
450 fmt.Printf("%sHasBlankPreviousLines: %v\n", indent2, v.HasBlankPreviousLines())
451 }
452 for name, value := range kv {
453 fmt.Printf("%s%s: %s\n", indent2, name, value)
454 }
455 if cb != nil {
456 cb(level + 1)
457 }
458 for c := v.FirstChild(); c != nil; c = c.NextSibling() {
459 c.Dump(source, level+1)
460 }
461 fmt.Printf("%s}\n", indent)
462}
463
464// WalkStatus represents a current status of the Walk function.
465type WalkStatus int
466
467const (
468 // WalkStop indicates no more walking needed.
469 WalkStop WalkStatus = iota + 1
470
471 // WalkSkipChildren indicates that Walk wont walk on children of current
472 // node.
473 WalkSkipChildren
474
475 // WalkContinue indicates that Walk can continue to walk.
476 WalkContinue
477)
478
479// Walker is a function that will be called when Walk find a
480// new node.
481// entering is set true before walks children, false after walked children.
482// If Walker returns error, Walk function immediately stop walking.
483type Walker func(n Node, entering bool) (WalkStatus, error)
484
485// Walk walks a AST tree by the depth first search algorithm.
486func Walk(n Node, walker Walker) error {
487 _, err := walkHelper(n, walker)
488 return err
489}
490
491func walkHelper(n Node, walker Walker) (WalkStatus, error) {
492 status, err := walker(n, true)
493 if err != nil || status == WalkStop {
494 return status, err
495 }
496 if status != WalkSkipChildren {
497 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
498 if st, err := walkHelper(c, walker); err != nil || st == WalkStop {
499 return WalkStop, err
500 }
501 }
502 }
503 status, err = walker(n, false)
504 if err != nil || status == WalkStop {
505 return WalkStop, err
506 }
507 return WalkContinue, nil
508}
diff --git a/vendor/github.com/yuin/goldmark/ast/block.go b/vendor/github.com/yuin/goldmark/ast/block.go
new file mode 100644
index 0000000..02e9d51
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/block.go
@@ -0,0 +1,508 @@
1package ast
2
3import (
4 "fmt"
5 "strings"
6
7 textm "github.com/yuin/goldmark/text"
8)
9
10// A BaseBlock struct implements the Node interface partialliy.
11type BaseBlock struct {
12 BaseNode
13 blankPreviousLines bool
14 lines *textm.Segments
15}
16
17// Type implements Node.Type
18func (b *BaseBlock) Type() NodeType {
19 return TypeBlock
20}
21
22// IsRaw implements Node.IsRaw
23func (b *BaseBlock) IsRaw() bool {
24 return false
25}
26
27// HasBlankPreviousLines implements Node.HasBlankPreviousLines.
28func (b *BaseBlock) HasBlankPreviousLines() bool {
29 return b.blankPreviousLines
30}
31
32// SetBlankPreviousLines implements Node.SetBlankPreviousLines.
33func (b *BaseBlock) SetBlankPreviousLines(v bool) {
34 b.blankPreviousLines = v
35}
36
37// Lines implements Node.Lines
38func (b *BaseBlock) Lines() *textm.Segments {
39 if b.lines == nil {
40 b.lines = textm.NewSegments()
41 }
42 return b.lines
43}
44
45// SetLines implements Node.SetLines
46func (b *BaseBlock) SetLines(v *textm.Segments) {
47 b.lines = v
48}
49
50// A Document struct is a root node of Markdown text.
51type Document struct {
52 BaseBlock
53
54 meta map[string]interface{}
55}
56
57// KindDocument is a NodeKind of the Document node.
58var KindDocument = NewNodeKind("Document")
59
60// Dump implements Node.Dump .
61func (n *Document) Dump(source []byte, level int) {
62 DumpHelper(n, source, level, nil, nil)
63}
64
65// Type implements Node.Type .
66func (n *Document) Type() NodeType {
67 return TypeDocument
68}
69
70// Kind implements Node.Kind.
71func (n *Document) Kind() NodeKind {
72 return KindDocument
73}
74
75// OwnerDocument implements Node.OwnerDocument
76func (n *Document) OwnerDocument() *Document {
77 return n
78}
79
80// Meta returns metadata of this document.
81func (n *Document) Meta() map[string]interface{} {
82 if n.meta == nil {
83 n.meta = map[string]interface{}{}
84 }
85 return n.meta
86}
87
88// SetMeta sets given metadata to this document.
89func (n *Document) SetMeta(meta map[string]interface{}) {
90 if n.meta == nil {
91 n.meta = map[string]interface{}{}
92 }
93 for k, v := range meta {
94 n.meta[k] = v
95 }
96}
97
98// AddMeta adds given metadata to this document.
99func (n *Document) AddMeta(key string, value interface{}) {
100 if n.meta == nil {
101 n.meta = map[string]interface{}{}
102 }
103 n.meta[key] = value
104}
105
106// NewDocument returns a new Document node.
107func NewDocument() *Document {
108 return &Document{
109 BaseBlock: BaseBlock{},
110 meta: nil,
111 }
112}
113
114// A TextBlock struct is a node whose lines
115// should be rendered without any containers.
116type TextBlock struct {
117 BaseBlock
118}
119
120// Dump implements Node.Dump .
121func (n *TextBlock) Dump(source []byte, level int) {
122 DumpHelper(n, source, level, nil, nil)
123}
124
125// KindTextBlock is a NodeKind of the TextBlock node.
126var KindTextBlock = NewNodeKind("TextBlock")
127
128// Kind implements Node.Kind.
129func (n *TextBlock) Kind() NodeKind {
130 return KindTextBlock
131}
132
133// NewTextBlock returns a new TextBlock node.
134func NewTextBlock() *TextBlock {
135 return &TextBlock{
136 BaseBlock: BaseBlock{},
137 }
138}
139
140// A Paragraph struct represents a paragraph of Markdown text.
141type Paragraph struct {
142 BaseBlock
143}
144
145// Dump implements Node.Dump .
146func (n *Paragraph) Dump(source []byte, level int) {
147 DumpHelper(n, source, level, nil, nil)
148}
149
150// KindParagraph is a NodeKind of the Paragraph node.
151var KindParagraph = NewNodeKind("Paragraph")
152
153// Kind implements Node.Kind.
154func (n *Paragraph) Kind() NodeKind {
155 return KindParagraph
156}
157
158// NewParagraph returns a new Paragraph node.
159func NewParagraph() *Paragraph {
160 return &Paragraph{
161 BaseBlock: BaseBlock{},
162 }
163}
164
165// IsParagraph returns true if the given node implements the Paragraph interface,
166// otherwise false.
167func IsParagraph(node Node) bool {
168 _, ok := node.(*Paragraph)
169 return ok
170}
171
172// A Heading struct represents headings like SetextHeading and ATXHeading.
173type Heading struct {
174 BaseBlock
175 // Level returns a level of this heading.
176 // This value is between 1 and 6.
177 Level int
178}
179
180// Dump implements Node.Dump .
181func (n *Heading) Dump(source []byte, level int) {
182 m := map[string]string{
183 "Level": fmt.Sprintf("%d", n.Level),
184 }
185 DumpHelper(n, source, level, m, nil)
186}
187
188// KindHeading is a NodeKind of the Heading node.
189var KindHeading = NewNodeKind("Heading")
190
191// Kind implements Node.Kind.
192func (n *Heading) Kind() NodeKind {
193 return KindHeading
194}
195
196// NewHeading returns a new Heading node.
197func NewHeading(level int) *Heading {
198 return &Heading{
199 BaseBlock: BaseBlock{},
200 Level: level,
201 }
202}
203
204// A ThematicBreak struct represents a thematic break of Markdown text.
205type ThematicBreak struct {
206 BaseBlock
207}
208
209// Dump implements Node.Dump .
210func (n *ThematicBreak) Dump(source []byte, level int) {
211 DumpHelper(n, source, level, nil, nil)
212}
213
214// KindThematicBreak is a NodeKind of the ThematicBreak node.
215var KindThematicBreak = NewNodeKind("ThematicBreak")
216
217// Kind implements Node.Kind.
218func (n *ThematicBreak) Kind() NodeKind {
219 return KindThematicBreak
220}
221
222// NewThematicBreak returns a new ThematicBreak node.
223func NewThematicBreak() *ThematicBreak {
224 return &ThematicBreak{
225 BaseBlock: BaseBlock{},
226 }
227}
228
229// A CodeBlock interface represents an indented code block of Markdown text.
230type CodeBlock struct {
231 BaseBlock
232}
233
234// IsRaw implements Node.IsRaw.
235func (n *CodeBlock) IsRaw() bool {
236 return true
237}
238
239// Dump implements Node.Dump .
240func (n *CodeBlock) Dump(source []byte, level int) {
241 DumpHelper(n, source, level, nil, nil)
242}
243
244// KindCodeBlock is a NodeKind of the CodeBlock node.
245var KindCodeBlock = NewNodeKind("CodeBlock")
246
247// Kind implements Node.Kind.
248func (n *CodeBlock) Kind() NodeKind {
249 return KindCodeBlock
250}
251
252// NewCodeBlock returns a new CodeBlock node.
253func NewCodeBlock() *CodeBlock {
254 return &CodeBlock{
255 BaseBlock: BaseBlock{},
256 }
257}
258
259// A FencedCodeBlock struct represents a fenced code block of Markdown text.
260type FencedCodeBlock struct {
261 BaseBlock
262 // Info returns a info text of this fenced code block.
263 Info *Text
264
265 language []byte
266}
267
268// Language returns an language in an info string.
269// Language returns nil if this node does not have an info string.
270func (n *FencedCodeBlock) Language(source []byte) []byte {
271 if n.language == nil && n.Info != nil {
272 segment := n.Info.Segment
273 info := segment.Value(source)
274 i := 0
275 for ; i < len(info); i++ {
276 if info[i] == ' ' {
277 break
278 }
279 }
280 n.language = info[:i]
281 }
282 return n.language
283}
284
285// IsRaw implements Node.IsRaw.
286func (n *FencedCodeBlock) IsRaw() bool {
287 return true
288}
289
290// Dump implements Node.Dump .
291func (n *FencedCodeBlock) Dump(source []byte, level int) {
292 m := map[string]string{}
293 if n.Info != nil {
294 m["Info"] = fmt.Sprintf("\"%s\"", n.Info.Text(source))
295 }
296 DumpHelper(n, source, level, m, nil)
297}
298
299// KindFencedCodeBlock is a NodeKind of the FencedCodeBlock node.
300var KindFencedCodeBlock = NewNodeKind("FencedCodeBlock")
301
302// Kind implements Node.Kind.
303func (n *FencedCodeBlock) Kind() NodeKind {
304 return KindFencedCodeBlock
305}
306
307// NewFencedCodeBlock return a new FencedCodeBlock node.
308func NewFencedCodeBlock(info *Text) *FencedCodeBlock {
309 return &FencedCodeBlock{
310 BaseBlock: BaseBlock{},
311 Info: info,
312 }
313}
314
315// A Blockquote struct represents an blockquote block of Markdown text.
316type Blockquote struct {
317 BaseBlock
318}
319
320// Dump implements Node.Dump .
321func (n *Blockquote) Dump(source []byte, level int) {
322 DumpHelper(n, source, level, nil, nil)
323}
324
325// KindBlockquote is a NodeKind of the Blockquote node.
326var KindBlockquote = NewNodeKind("Blockquote")
327
328// Kind implements Node.Kind.
329func (n *Blockquote) Kind() NodeKind {
330 return KindBlockquote
331}
332
333// NewBlockquote returns a new Blockquote node.
334func NewBlockquote() *Blockquote {
335 return &Blockquote{
336 BaseBlock: BaseBlock{},
337 }
338}
339
340// A List struct represents a list of Markdown text.
341type List struct {
342 BaseBlock
343
344 // Marker is a marker character like '-', '+', ')' and '.'.
345 Marker byte
346
347 // IsTight is a true if this list is a 'tight' list.
348 // See https://spec.commonmark.org/0.30/#loose for details.
349 IsTight bool
350
351 // Start is an initial number of this ordered list.
352 // If this list is not an ordered list, Start is 0.
353 Start int
354}
355
356// IsOrdered returns true if this list is an ordered list, otherwise false.
357func (l *List) IsOrdered() bool {
358 return l.Marker == '.' || l.Marker == ')'
359}
360
361// CanContinue returns true if this list can continue with
362// the given mark and a list type, otherwise false.
363func (l *List) CanContinue(marker byte, isOrdered bool) bool {
364 return marker == l.Marker && isOrdered == l.IsOrdered()
365}
366
367// Dump implements Node.Dump.
368func (l *List) Dump(source []byte, level int) {
369 m := map[string]string{
370 "Ordered": fmt.Sprintf("%v", l.IsOrdered()),
371 "Marker": fmt.Sprintf("%c", l.Marker),
372 "Tight": fmt.Sprintf("%v", l.IsTight),
373 }
374 if l.IsOrdered() {
375 m["Start"] = fmt.Sprintf("%d", l.Start)
376 }
377 DumpHelper(l, source, level, m, nil)
378}
379
380// KindList is a NodeKind of the List node.
381var KindList = NewNodeKind("List")
382
383// Kind implements Node.Kind.
384func (l *List) Kind() NodeKind {
385 return KindList
386}
387
388// NewList returns a new List node.
389func NewList(marker byte) *List {
390 return &List{
391 BaseBlock: BaseBlock{},
392 Marker: marker,
393 IsTight: true,
394 }
395}
396
397// A ListItem struct represents a list item of Markdown text.
398type ListItem struct {
399 BaseBlock
400
401 // Offset is an offset position of this item.
402 Offset int
403}
404
405// Dump implements Node.Dump.
406func (n *ListItem) Dump(source []byte, level int) {
407 m := map[string]string{
408 "Offset": fmt.Sprintf("%d", n.Offset),
409 }
410 DumpHelper(n, source, level, m, nil)
411}
412
413// KindListItem is a NodeKind of the ListItem node.
414var KindListItem = NewNodeKind("ListItem")
415
416// Kind implements Node.Kind.
417func (n *ListItem) Kind() NodeKind {
418 return KindListItem
419}
420
421// NewListItem returns a new ListItem node.
422func NewListItem(offset int) *ListItem {
423 return &ListItem{
424 BaseBlock: BaseBlock{},
425 Offset: offset,
426 }
427}
428
429// HTMLBlockType represents kinds of an html blocks.
430// See https://spec.commonmark.org/0.30/#html-blocks
431type HTMLBlockType int
432
433const (
434 // HTMLBlockType1 represents type 1 html blocks
435 HTMLBlockType1 HTMLBlockType = iota + 1
436 // HTMLBlockType2 represents type 2 html blocks
437 HTMLBlockType2
438 // HTMLBlockType3 represents type 3 html blocks
439 HTMLBlockType3
440 // HTMLBlockType4 represents type 4 html blocks
441 HTMLBlockType4
442 // HTMLBlockType5 represents type 5 html blocks
443 HTMLBlockType5
444 // HTMLBlockType6 represents type 6 html blocks
445 HTMLBlockType6
446 // HTMLBlockType7 represents type 7 html blocks
447 HTMLBlockType7
448)
449
450// An HTMLBlock struct represents an html block of Markdown text.
451type HTMLBlock struct {
452 BaseBlock
453
454 // Type is a type of this html block.
455 HTMLBlockType HTMLBlockType
456
457 // ClosureLine is a line that closes this html block.
458 ClosureLine textm.Segment
459}
460
461// IsRaw implements Node.IsRaw.
462func (n *HTMLBlock) IsRaw() bool {
463 return true
464}
465
466// HasClosure returns true if this html block has a closure line,
467// otherwise false.
468func (n *HTMLBlock) HasClosure() bool {
469 return n.ClosureLine.Start >= 0
470}
471
472// Dump implements Node.Dump.
473func (n *HTMLBlock) Dump(source []byte, level int) {
474 indent := strings.Repeat(" ", level)
475 fmt.Printf("%s%s {\n", indent, "HTMLBlock")
476 indent2 := strings.Repeat(" ", level+1)
477 fmt.Printf("%sRawText: \"", indent2)
478 for i := 0; i < n.Lines().Len(); i++ {
479 s := n.Lines().At(i)
480 fmt.Print(string(source[s.Start:s.Stop]))
481 }
482 fmt.Printf("\"\n")
483 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
484 c.Dump(source, level+1)
485 }
486 if n.HasClosure() {
487 cl := n.ClosureLine
488 fmt.Printf("%sClosure: \"%s\"\n", indent2, string(cl.Value(source)))
489 }
490 fmt.Printf("%s}\n", indent)
491}
492
493// KindHTMLBlock is a NodeKind of the HTMLBlock node.
494var KindHTMLBlock = NewNodeKind("HTMLBlock")
495
496// Kind implements Node.Kind.
497func (n *HTMLBlock) Kind() NodeKind {
498 return KindHTMLBlock
499}
500
501// NewHTMLBlock returns a new HTMLBlock node.
502func NewHTMLBlock(typ HTMLBlockType) *HTMLBlock {
503 return &HTMLBlock{
504 BaseBlock: BaseBlock{},
505 HTMLBlockType: typ,
506 ClosureLine: textm.NewSegment(-1, -1),
507 }
508}
diff --git a/vendor/github.com/yuin/goldmark/ast/inline.go b/vendor/github.com/yuin/goldmark/ast/inline.go
new file mode 100644
index 0000000..7da098f
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/ast/inline.go
@@ -0,0 +1,548 @@
1package ast
2
3import (
4 "fmt"
5 "strings"
6
7 textm "github.com/yuin/goldmark/text"
8 "github.com/yuin/goldmark/util"
9)
10
11// A BaseInline struct implements the Node interface partialliy.
12type BaseInline struct {
13 BaseNode
14}
15
16// Type implements Node.Type
17func (b *BaseInline) Type() NodeType {
18 return TypeInline
19}
20
21// IsRaw implements Node.IsRaw
22func (b *BaseInline) IsRaw() bool {
23 return false
24}
25
26// HasBlankPreviousLines implements Node.HasBlankPreviousLines.
27func (b *BaseInline) HasBlankPreviousLines() bool {
28 panic("can not call with inline nodes.")
29}
30
31// SetBlankPreviousLines implements Node.SetBlankPreviousLines.
32func (b *BaseInline) SetBlankPreviousLines(v bool) {
33 panic("can not call with inline nodes.")
34}
35
36// Lines implements Node.Lines
37func (b *BaseInline) Lines() *textm.Segments {
38 panic("can not call with inline nodes.")
39}
40
41// SetLines implements Node.SetLines
42func (b *BaseInline) SetLines(v *textm.Segments) {
43 panic("can not call with inline nodes.")
44}
45
46// A Text struct represents a textual content of the Markdown text.
47type Text struct {
48 BaseInline
49 // Segment is a position in a source text.
50 Segment textm.Segment
51
52 flags uint8
53}
54
55const (
56 textSoftLineBreak = 1 << iota
57 textHardLineBreak
58 textRaw
59 textCode
60)
61
62func textFlagsString(flags uint8) string {
63 buf := []string{}
64 if flags&textSoftLineBreak != 0 {
65 buf = append(buf, "SoftLineBreak")
66 }
67 if flags&textHardLineBreak != 0 {
68 buf = append(buf, "HardLineBreak")
69 }
70 if flags&textRaw != 0 {
71 buf = append(buf, "Raw")
72 }
73 if flags&textCode != 0 {
74 buf = append(buf, "Code")
75 }
76 return strings.Join(buf, ", ")
77}
78
79// Inline implements Inline.Inline.
80func (n *Text) Inline() {
81}
82
83// SoftLineBreak returns true if this node ends with a new line,
84// otherwise false.
85func (n *Text) SoftLineBreak() bool {
86 return n.flags&textSoftLineBreak != 0
87}
88
89// SetSoftLineBreak sets whether this node ends with a new line.
90func (n *Text) SetSoftLineBreak(v bool) {
91 if v {
92 n.flags |= textSoftLineBreak
93 } else {
94 n.flags = n.flags &^ textSoftLineBreak
95 }
96}
97
98// IsRaw returns true if this text should be rendered without unescaping
99// back slash escapes and resolving references.
100func (n *Text) IsRaw() bool {
101 return n.flags&textRaw != 0
102}
103
104// SetRaw sets whether this text should be rendered as raw contents.
105func (n *Text) SetRaw(v bool) {
106 if v {
107 n.flags |= textRaw
108 } else {
109 n.flags = n.flags &^ textRaw
110 }
111}
112
113// HardLineBreak returns true if this node ends with a hard line break.
114// See https://spec.commonmark.org/0.30/#hard-line-breaks for details.
115func (n *Text) HardLineBreak() bool {
116 return n.flags&textHardLineBreak != 0
117}
118
119// SetHardLineBreak sets whether this node ends with a hard line break.
120func (n *Text) SetHardLineBreak(v bool) {
121 if v {
122 n.flags |= textHardLineBreak
123 } else {
124 n.flags = n.flags &^ textHardLineBreak
125 }
126}
127
128// Merge merges a Node n into this node.
129// Merge returns true if the given node has been merged, otherwise false.
130func (n *Text) Merge(node Node, source []byte) bool {
131 t, ok := node.(*Text)
132 if !ok {
133 return false
134 }
135 if n.Segment.Stop != t.Segment.Start || t.Segment.Padding != 0 || source[n.Segment.Stop-1] == '\n' || t.IsRaw() != n.IsRaw() {
136 return false
137 }
138 n.Segment.Stop = t.Segment.Stop
139 n.SetSoftLineBreak(t.SoftLineBreak())
140 n.SetHardLineBreak(t.HardLineBreak())
141 return true
142}
143
144// Text implements Node.Text.
145func (n *Text) Text(source []byte) []byte {
146 return n.Segment.Value(source)
147}
148
149// Dump implements Node.Dump.
150func (n *Text) Dump(source []byte, level int) {
151 fs := textFlagsString(n.flags)
152 if len(fs) != 0 {
153 fs = "(" + fs + ")"
154 }
155 fmt.Printf("%sText%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Text(source)), "\n"))
156}
157
158// KindText is a NodeKind of the Text node.
159var KindText = NewNodeKind("Text")
160
161// Kind implements Node.Kind.
162func (n *Text) Kind() NodeKind {
163 return KindText
164}
165
166// NewText returns a new Text node.
167func NewText() *Text {
168 return &Text{
169 BaseInline: BaseInline{},
170 }
171}
172
173// NewTextSegment returns a new Text node with the given source position.
174func NewTextSegment(v textm.Segment) *Text {
175 return &Text{
176 BaseInline: BaseInline{},
177 Segment: v,
178 }
179}
180
181// NewRawTextSegment returns a new Text node with the given source position.
182// The new node should be rendered as raw contents.
183func NewRawTextSegment(v textm.Segment) *Text {
184 t := &Text{
185 BaseInline: BaseInline{},
186 Segment: v,
187 }
188 t.SetRaw(true)
189 return t
190}
191
192// MergeOrAppendTextSegment merges a given s into the last child of the parent if
193// it can be merged, otherwise creates a new Text node and appends it to after current
194// last child.
195func MergeOrAppendTextSegment(parent Node, s textm.Segment) {
196 last := parent.LastChild()
197 t, ok := last.(*Text)
198 if ok && t.Segment.Stop == s.Start && !t.SoftLineBreak() {
199 t.Segment = t.Segment.WithStop(s.Stop)
200 } else {
201 parent.AppendChild(parent, NewTextSegment(s))
202 }
203}
204
205// MergeOrReplaceTextSegment merges a given s into a previous sibling of the node n
206// if a previous sibling of the node n is *Text, otherwise replaces Node n with s.
207func MergeOrReplaceTextSegment(parent Node, n Node, s textm.Segment) {
208 prev := n.PreviousSibling()
209 if t, ok := prev.(*Text); ok && t.Segment.Stop == s.Start && !t.SoftLineBreak() {
210 t.Segment = t.Segment.WithStop(s.Stop)
211 parent.RemoveChild(parent, n)
212 } else {
213 parent.ReplaceChild(parent, n, NewTextSegment(s))
214 }
215}
216
217// A String struct is a textual content that has a concrete value
218type String struct {
219 BaseInline
220
221 Value []byte
222 flags uint8
223}
224
225// Inline implements Inline.Inline.
226func (n *String) Inline() {
227}
228
229// IsRaw returns true if this text should be rendered without unescaping
230// back slash escapes and resolving references.
231func (n *String) IsRaw() bool {
232 return n.flags&textRaw != 0
233}
234
235// SetRaw sets whether this text should be rendered as raw contents.
236func (n *String) SetRaw(v bool) {
237 if v {
238 n.flags |= textRaw
239 } else {
240 n.flags = n.flags &^ textRaw
241 }
242}
243
244// IsCode returns true if this text should be rendered without any
245// modifications.
246func (n *String) IsCode() bool {
247 return n.flags&textCode != 0
248}
249
250// SetCode sets whether this text should be rendered without any modifications.
251func (n *String) SetCode(v bool) {
252 if v {
253 n.flags |= textCode
254 } else {
255 n.flags = n.flags &^ textCode
256 }
257}
258
259// Text implements Node.Text.
260func (n *String) Text(source []byte) []byte {
261 return n.Value
262}
263
264// Dump implements Node.Dump.
265func (n *String) Dump(source []byte, level int) {
266 fs := textFlagsString(n.flags)
267 if len(fs) != 0 {
268 fs = "(" + fs + ")"
269 }
270 fmt.Printf("%sString%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Value), "\n"))
271}
272
273// KindString is a NodeKind of the String node.
274var KindString = NewNodeKind("String")
275
276// Kind implements Node.Kind.
277func (n *String) Kind() NodeKind {
278 return KindString
279}
280
281// NewString returns a new String node.
282func NewString(v []byte) *String {
283 return &String{
284 Value: v,
285 }
286}
287
288// A CodeSpan struct represents a code span of Markdown text.
289type CodeSpan struct {
290 BaseInline
291}
292
293// Inline implements Inline.Inline .
294func (n *CodeSpan) Inline() {
295}
296
297// IsBlank returns true if this node consists of spaces, otherwise false.
298func (n *CodeSpan) IsBlank(source []byte) bool {
299 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
300 text := c.(*Text).Segment
301 if !util.IsBlank(text.Value(source)) {
302 return false
303 }
304 }
305 return true
306}
307
308// Dump implements Node.Dump
309func (n *CodeSpan) Dump(source []byte, level int) {
310 DumpHelper(n, source, level, nil, nil)
311}
312
313// KindCodeSpan is a NodeKind of the CodeSpan node.
314var KindCodeSpan = NewNodeKind("CodeSpan")
315
316// Kind implements Node.Kind.
317func (n *CodeSpan) Kind() NodeKind {
318 return KindCodeSpan
319}
320
321// NewCodeSpan returns a new CodeSpan node.
322func NewCodeSpan() *CodeSpan {
323 return &CodeSpan{
324 BaseInline: BaseInline{},
325 }
326}
327
328// An Emphasis struct represents an emphasis of Markdown text.
329type Emphasis struct {
330 BaseInline
331
332 // Level is a level of the emphasis.
333 Level int
334}
335
336// Dump implements Node.Dump.
337func (n *Emphasis) Dump(source []byte, level int) {
338 m := map[string]string{
339 "Level": fmt.Sprintf("%v", n.Level),
340 }
341 DumpHelper(n, source, level, m, nil)
342}
343
344// KindEmphasis is a NodeKind of the Emphasis node.
345var KindEmphasis = NewNodeKind("Emphasis")
346
347// Kind implements Node.Kind.
348func (n *Emphasis) Kind() NodeKind {
349 return KindEmphasis
350}
351
352// NewEmphasis returns a new Emphasis node with the given level.
353func NewEmphasis(level int) *Emphasis {
354 return &Emphasis{
355 BaseInline: BaseInline{},
356 Level: level,
357 }
358}
359
360type baseLink struct {
361 BaseInline
362
363 // Destination is a destination(URL) of this link.
364 Destination []byte
365
366 // Title is a title of this link.
367 Title []byte
368}
369
370// Inline implements Inline.Inline.
371func (n *baseLink) Inline() {
372}
373
374// A Link struct represents a link of the Markdown text.
375type Link struct {
376 baseLink
377}
378
379// Dump implements Node.Dump.
380func (n *Link) Dump(source []byte, level int) {
381 m := map[string]string{}
382 m["Destination"] = string(n.Destination)
383 m["Title"] = string(n.Title)
384 DumpHelper(n, source, level, m, nil)
385}
386
387// KindLink is a NodeKind of the Link node.
388var KindLink = NewNodeKind("Link")
389
390// Kind implements Node.Kind.
391func (n *Link) Kind() NodeKind {
392 return KindLink
393}
394
395// NewLink returns a new Link node.
396func NewLink() *Link {
397 c := &Link{
398 baseLink: baseLink{
399 BaseInline: BaseInline{},
400 },
401 }
402 return c
403}
404
405// An Image struct represents an image of the Markdown text.
406type Image struct {
407 baseLink
408}
409
410// Dump implements Node.Dump.
411func (n *Image) Dump(source []byte, level int) {
412 m := map[string]string{}
413 m["Destination"] = string(n.Destination)
414 m["Title"] = string(n.Title)
415 DumpHelper(n, source, level, m, nil)
416}
417
418// KindImage is a NodeKind of the Image node.
419var KindImage = NewNodeKind("Image")
420
421// Kind implements Node.Kind.
422func (n *Image) Kind() NodeKind {
423 return KindImage
424}
425
426// NewImage returns a new Image node.
427func NewImage(link *Link) *Image {
428 c := &Image{
429 baseLink: baseLink{
430 BaseInline: BaseInline{},
431 },
432 }
433 c.Destination = link.Destination
434 c.Title = link.Title
435 for n := link.FirstChild(); n != nil; {
436 next := n.NextSibling()
437 link.RemoveChild(link, n)
438 c.AppendChild(c, n)
439 n = next
440 }
441
442 return c
443}
444
445// AutoLinkType defines kind of auto links.
446type AutoLinkType int
447
448const (
449 // AutoLinkEmail indicates that an autolink is an email address.
450 AutoLinkEmail AutoLinkType = iota + 1
451 // AutoLinkURL indicates that an autolink is a generic URL.
452 AutoLinkURL
453)
454
455// An AutoLink struct represents an autolink of the Markdown text.
456type AutoLink struct {
457 BaseInline
458 // Type is a type of this autolink.
459 AutoLinkType AutoLinkType
460
461 // Protocol specified a protocol of the link.
462 Protocol []byte
463
464 value *Text
465}
466
467// Inline implements Inline.Inline.
468func (n *AutoLink) Inline() {}
469
470// Dump implements Node.Dump
471func (n *AutoLink) Dump(source []byte, level int) {
472 segment := n.value.Segment
473 m := map[string]string{
474 "Value": string(segment.Value(source)),
475 }
476 DumpHelper(n, source, level, m, nil)
477}
478
479// KindAutoLink is a NodeKind of the AutoLink node.
480var KindAutoLink = NewNodeKind("AutoLink")
481
482// Kind implements Node.Kind.
483func (n *AutoLink) Kind() NodeKind {
484 return KindAutoLink
485}
486
487// URL returns an url of this node.
488func (n *AutoLink) URL(source []byte) []byte {
489 if n.Protocol != nil {
490 s := n.value.Segment
491 ret := make([]byte, 0, len(n.Protocol)+s.Len()+3)
492 ret = append(ret, n.Protocol...)
493 ret = append(ret, ':', '/', '/')
494 ret = append(ret, n.value.Text(source)...)
495 return ret
496 }
497 return n.value.Text(source)
498}
499
500// Label returns a label of this node.
501func (n *AutoLink) Label(source []byte) []byte {
502 return n.value.Text(source)
503}
504
505// NewAutoLink returns a new AutoLink node.
506func NewAutoLink(typ AutoLinkType, value *Text) *AutoLink {
507 return &AutoLink{
508 BaseInline: BaseInline{},
509 value: value,
510 AutoLinkType: typ,
511 }
512}
513
514// A RawHTML struct represents an inline raw HTML of the Markdown text.
515type RawHTML struct {
516 BaseInline
517 Segments *textm.Segments
518}
519
520// Inline implements Inline.Inline.
521func (n *RawHTML) Inline() {}
522
523// Dump implements Node.Dump.
524func (n *RawHTML) Dump(source []byte, level int) {
525 m := map[string]string{}
526 t := []string{}
527 for i := 0; i < n.Segments.Len(); i++ {
528 segment := n.Segments.At(i)
529 t = append(t, string(segment.Value(source)))
530 }
531 m["RawText"] = strings.Join(t, "")
532 DumpHelper(n, source, level, m, nil)
533}
534
535// KindRawHTML is a NodeKind of the RawHTML node.
536var KindRawHTML = NewNodeKind("RawHTML")
537
538// Kind implements Node.Kind.
539func (n *RawHTML) Kind() NodeKind {
540 return KindRawHTML
541}
542
543// NewRawHTML returns a new RawHTML node.
544func NewRawHTML() *RawHTML {
545 return &RawHTML{
546 Segments: textm.NewSegments(),
547 }
548}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/definition_list.go b/vendor/github.com/yuin/goldmark/extension/ast/definition_list.go
new file mode 100644
index 0000000..1beffb3
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/ast/definition_list.go
@@ -0,0 +1,83 @@
1package ast
2
3import (
4 gast "github.com/yuin/goldmark/ast"
5)
6
7// A DefinitionList struct represents a definition list of Markdown
8// (PHPMarkdownExtra) text.
9type DefinitionList struct {
10 gast.BaseBlock
11 Offset int
12 TemporaryParagraph *gast.Paragraph
13}
14
15// Dump implements Node.Dump.
16func (n *DefinitionList) Dump(source []byte, level int) {
17 gast.DumpHelper(n, source, level, nil, nil)
18}
19
20// KindDefinitionList is a NodeKind of the DefinitionList node.
21var KindDefinitionList = gast.NewNodeKind("DefinitionList")
22
23// Kind implements Node.Kind.
24func (n *DefinitionList) Kind() gast.NodeKind {
25 return KindDefinitionList
26}
27
28// NewDefinitionList returns a new DefinitionList node.
29func NewDefinitionList(offset int, para *gast.Paragraph) *DefinitionList {
30 return &DefinitionList{
31 Offset: offset,
32 TemporaryParagraph: para,
33 }
34}
35
36// A DefinitionTerm struct represents a definition list term of Markdown
37// (PHPMarkdownExtra) text.
38type DefinitionTerm struct {
39 gast.BaseBlock
40}
41
42// Dump implements Node.Dump.
43func (n *DefinitionTerm) Dump(source []byte, level int) {
44 gast.DumpHelper(n, source, level, nil, nil)
45}
46
47// KindDefinitionTerm is a NodeKind of the DefinitionTerm node.
48var KindDefinitionTerm = gast.NewNodeKind("DefinitionTerm")
49
50// Kind implements Node.Kind.
51func (n *DefinitionTerm) Kind() gast.NodeKind {
52 return KindDefinitionTerm
53}
54
55// NewDefinitionTerm returns a new DefinitionTerm node.
56func NewDefinitionTerm() *DefinitionTerm {
57 return &DefinitionTerm{}
58}
59
60// A DefinitionDescription struct represents a definition list description of Markdown
61// (PHPMarkdownExtra) text.
62type DefinitionDescription struct {
63 gast.BaseBlock
64 IsTight bool
65}
66
67// Dump implements Node.Dump.
68func (n *DefinitionDescription) Dump(source []byte, level int) {
69 gast.DumpHelper(n, source, level, nil, nil)
70}
71
72// KindDefinitionDescription is a NodeKind of the DefinitionDescription node.
73var KindDefinitionDescription = gast.NewNodeKind("DefinitionDescription")
74
75// Kind implements Node.Kind.
76func (n *DefinitionDescription) Kind() gast.NodeKind {
77 return KindDefinitionDescription
78}
79
80// NewDefinitionDescription returns a new DefinitionDescription node.
81func NewDefinitionDescription() *DefinitionDescription {
82 return &DefinitionDescription{}
83}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/footnote.go b/vendor/github.com/yuin/goldmark/extension/ast/footnote.go
new file mode 100644
index 0000000..97fea44
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/ast/footnote.go
@@ -0,0 +1,138 @@
1package ast
2
3import (
4 "fmt"
5
6 gast "github.com/yuin/goldmark/ast"
7)
8
9// A FootnoteLink struct represents a link to a footnote of Markdown
10// (PHP Markdown Extra) text.
11type FootnoteLink struct {
12 gast.BaseInline
13 Index int
14 RefCount int
15 RefIndex int
16}
17
18// Dump implements Node.Dump.
19func (n *FootnoteLink) Dump(source []byte, level int) {
20 m := map[string]string{}
21 m["Index"] = fmt.Sprintf("%v", n.Index)
22 m["RefCount"] = fmt.Sprintf("%v", n.RefCount)
23 m["RefIndex"] = fmt.Sprintf("%v", n.RefIndex)
24 gast.DumpHelper(n, source, level, m, nil)
25}
26
27// KindFootnoteLink is a NodeKind of the FootnoteLink node.
28var KindFootnoteLink = gast.NewNodeKind("FootnoteLink")
29
30// Kind implements Node.Kind.
31func (n *FootnoteLink) Kind() gast.NodeKind {
32 return KindFootnoteLink
33}
34
35// NewFootnoteLink returns a new FootnoteLink node.
36func NewFootnoteLink(index int) *FootnoteLink {
37 return &FootnoteLink{
38 Index: index,
39 RefCount: 0,
40 RefIndex: 0,
41 }
42}
43
44// A FootnoteBacklink struct represents a link to a footnote of Markdown
45// (PHP Markdown Extra) text.
46type FootnoteBacklink struct {
47 gast.BaseInline
48 Index int
49 RefCount int
50 RefIndex int
51}
52
53// Dump implements Node.Dump.
54func (n *FootnoteBacklink) Dump(source []byte, level int) {
55 m := map[string]string{}
56 m["Index"] = fmt.Sprintf("%v", n.Index)
57 m["RefCount"] = fmt.Sprintf("%v", n.RefCount)
58 m["RefIndex"] = fmt.Sprintf("%v", n.RefIndex)
59 gast.DumpHelper(n, source, level, m, nil)
60}
61
62// KindFootnoteBacklink is a NodeKind of the FootnoteBacklink node.
63var KindFootnoteBacklink = gast.NewNodeKind("FootnoteBacklink")
64
65// Kind implements Node.Kind.
66func (n *FootnoteBacklink) Kind() gast.NodeKind {
67 return KindFootnoteBacklink
68}
69
70// NewFootnoteBacklink returns a new FootnoteBacklink node.
71func NewFootnoteBacklink(index int) *FootnoteBacklink {
72 return &FootnoteBacklink{
73 Index: index,
74 RefCount: 0,
75 RefIndex: 0,
76 }
77}
78
79// A Footnote struct represents a footnote of Markdown
80// (PHP Markdown Extra) text.
81type Footnote struct {
82 gast.BaseBlock
83 Ref []byte
84 Index int
85}
86
87// Dump implements Node.Dump.
88func (n *Footnote) Dump(source []byte, level int) {
89 m := map[string]string{}
90 m["Index"] = fmt.Sprintf("%v", n.Index)
91 m["Ref"] = fmt.Sprintf("%s", n.Ref)
92 gast.DumpHelper(n, source, level, m, nil)
93}
94
95// KindFootnote is a NodeKind of the Footnote node.
96var KindFootnote = gast.NewNodeKind("Footnote")
97
98// Kind implements Node.Kind.
99func (n *Footnote) Kind() gast.NodeKind {
100 return KindFootnote
101}
102
103// NewFootnote returns a new Footnote node.
104func NewFootnote(ref []byte) *Footnote {
105 return &Footnote{
106 Ref: ref,
107 Index: -1,
108 }
109}
110
111// A FootnoteList struct represents footnotes of Markdown
112// (PHP Markdown Extra) text.
113type FootnoteList struct {
114 gast.BaseBlock
115 Count int
116}
117
118// Dump implements Node.Dump.
119func (n *FootnoteList) Dump(source []byte, level int) {
120 m := map[string]string{}
121 m["Count"] = fmt.Sprintf("%v", n.Count)
122 gast.DumpHelper(n, source, level, m, nil)
123}
124
125// KindFootnoteList is a NodeKind of the FootnoteList node.
126var KindFootnoteList = gast.NewNodeKind("FootnoteList")
127
128// Kind implements Node.Kind.
129func (n *FootnoteList) Kind() gast.NodeKind {
130 return KindFootnoteList
131}
132
133// NewFootnoteList returns a new FootnoteList node.
134func NewFootnoteList() *FootnoteList {
135 return &FootnoteList{
136 Count: 0,
137 }
138}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/strikethrough.go b/vendor/github.com/yuin/goldmark/extension/ast/strikethrough.go
new file mode 100644
index 0000000..a9216b7
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/ast/strikethrough.go
@@ -0,0 +1,29 @@
1// Package ast defines AST nodes that represents extension's elements
2package ast
3
4import (
5 gast "github.com/yuin/goldmark/ast"
6)
7
8// A Strikethrough struct represents a strikethrough of GFM text.
9type Strikethrough struct {
10 gast.BaseInline
11}
12
13// Dump implements Node.Dump.
14func (n *Strikethrough) Dump(source []byte, level int) {
15 gast.DumpHelper(n, source, level, nil, nil)
16}
17
18// KindStrikethrough is a NodeKind of the Strikethrough node.
19var KindStrikethrough = gast.NewNodeKind("Strikethrough")
20
21// Kind implements Node.Kind.
22func (n *Strikethrough) Kind() gast.NodeKind {
23 return KindStrikethrough
24}
25
26// NewStrikethrough returns a new Strikethrough node.
27func NewStrikethrough() *Strikethrough {
28 return &Strikethrough{}
29}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/table.go b/vendor/github.com/yuin/goldmark/extension/ast/table.go
new file mode 100644
index 0000000..e9eff3c
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/ast/table.go
@@ -0,0 +1,157 @@
1package ast
2
3import (
4 "fmt"
5 gast "github.com/yuin/goldmark/ast"
6 "strings"
7)
8
9// Alignment is a text alignment of table cells.
10type Alignment int
11
12const (
13 // AlignLeft indicates text should be left justified.
14 AlignLeft Alignment = iota + 1
15
16 // AlignRight indicates text should be right justified.
17 AlignRight
18
19 // AlignCenter indicates text should be centered.
20 AlignCenter
21
22 // AlignNone indicates text should be aligned by default manner.
23 AlignNone
24)
25
26func (a Alignment) String() string {
27 switch a {
28 case AlignLeft:
29 return "left"
30 case AlignRight:
31 return "right"
32 case AlignCenter:
33 return "center"
34 case AlignNone:
35 return "none"
36 }
37 return ""
38}
39
40// A Table struct represents a table of Markdown(GFM) text.
41type Table struct {
42 gast.BaseBlock
43
44 // Alignments returns alignments of the columns.
45 Alignments []Alignment
46}
47
48// Dump implements Node.Dump
49func (n *Table) Dump(source []byte, level int) {
50 gast.DumpHelper(n, source, level, nil, func(level int) {
51 indent := strings.Repeat(" ", level)
52 fmt.Printf("%sAlignments {\n", indent)
53 for i, alignment := range n.Alignments {
54 indent2 := strings.Repeat(" ", level+1)
55 fmt.Printf("%s%s", indent2, alignment.String())
56 if i != len(n.Alignments)-1 {
57 fmt.Println("")
58 }
59 }
60 fmt.Printf("\n%s}\n", indent)
61 })
62}
63
64// KindTable is a NodeKind of the Table node.
65var KindTable = gast.NewNodeKind("Table")
66
67// Kind implements Node.Kind.
68func (n *Table) Kind() gast.NodeKind {
69 return KindTable
70}
71
72// NewTable returns a new Table node.
73func NewTable() *Table {
74 return &Table{
75 Alignments: []Alignment{},
76 }
77}
78
79// A TableRow struct represents a table row of Markdown(GFM) text.
80type TableRow struct {
81 gast.BaseBlock
82 Alignments []Alignment
83}
84
85// Dump implements Node.Dump.
86func (n *TableRow) Dump(source []byte, level int) {
87 gast.DumpHelper(n, source, level, nil, nil)
88}
89
90// KindTableRow is a NodeKind of the TableRow node.
91var KindTableRow = gast.NewNodeKind("TableRow")
92
93// Kind implements Node.Kind.
94func (n *TableRow) Kind() gast.NodeKind {
95 return KindTableRow
96}
97
98// NewTableRow returns a new TableRow node.
99func NewTableRow(alignments []Alignment) *TableRow {
100 return &TableRow{Alignments: alignments}
101}
102
103// A TableHeader struct represents a table header of Markdown(GFM) text.
104type TableHeader struct {
105 gast.BaseBlock
106 Alignments []Alignment
107}
108
109// KindTableHeader is a NodeKind of the TableHeader node.
110var KindTableHeader = gast.NewNodeKind("TableHeader")
111
112// Kind implements Node.Kind.
113func (n *TableHeader) Kind() gast.NodeKind {
114 return KindTableHeader
115}
116
117// Dump implements Node.Dump.
118func (n *TableHeader) Dump(source []byte, level int) {
119 gast.DumpHelper(n, source, level, nil, nil)
120}
121
122// NewTableHeader returns a new TableHeader node.
123func NewTableHeader(row *TableRow) *TableHeader {
124 n := &TableHeader{}
125 for c := row.FirstChild(); c != nil; {
126 next := c.NextSibling()
127 n.AppendChild(n, c)
128 c = next
129 }
130 return n
131}
132
133// A TableCell struct represents a table cell of a Markdown(GFM) text.
134type TableCell struct {
135 gast.BaseBlock
136 Alignment Alignment
137}
138
139// Dump implements Node.Dump.
140func (n *TableCell) Dump(source []byte, level int) {
141 gast.DumpHelper(n, source, level, nil, nil)
142}
143
144// KindTableCell is a NodeKind of the TableCell node.
145var KindTableCell = gast.NewNodeKind("TableCell")
146
147// Kind implements Node.Kind.
148func (n *TableCell) Kind() gast.NodeKind {
149 return KindTableCell
150}
151
152// NewTableCell returns a new TableCell node.
153func NewTableCell() *TableCell {
154 return &TableCell{
155 Alignment: AlignNone,
156 }
157}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/tasklist.go b/vendor/github.com/yuin/goldmark/extension/ast/tasklist.go
new file mode 100644
index 0000000..670cc14
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/ast/tasklist.go
@@ -0,0 +1,35 @@
1package ast
2
3import (
4 "fmt"
5 gast "github.com/yuin/goldmark/ast"
6)
7
8// A TaskCheckBox struct represents a checkbox of a task list.
9type TaskCheckBox struct {
10 gast.BaseInline
11 IsChecked bool
12}
13
14// Dump implements Node.Dump.
15func (n *TaskCheckBox) Dump(source []byte, level int) {
16 m := map[string]string{
17 "Checked": fmt.Sprintf("%v", n.IsChecked),
18 }
19 gast.DumpHelper(n, source, level, m, nil)
20}
21
22// KindTaskCheckBox is a NodeKind of the TaskCheckBox node.
23var KindTaskCheckBox = gast.NewNodeKind("TaskCheckBox")
24
25// Kind implements Node.Kind.
26func (n *TaskCheckBox) Kind() gast.NodeKind {
27 return KindTaskCheckBox
28}
29
30// NewTaskCheckBox returns a new TaskCheckBox node.
31func NewTaskCheckBox(checked bool) *TaskCheckBox {
32 return &TaskCheckBox{
33 IsChecked: checked,
34 }
35}
diff --git a/vendor/github.com/yuin/goldmark/extension/cjk.go b/vendor/github.com/yuin/goldmark/extension/cjk.go
new file mode 100644
index 0000000..cb6f955
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/cjk.go
@@ -0,0 +1,51 @@
1package extension
2
3import (
4 "github.com/yuin/goldmark"
5 "github.com/yuin/goldmark/parser"
6 "github.com/yuin/goldmark/renderer/html"
7)
8
9// A CJKOption sets options for CJK support mostly for HTML based renderers.
10type CJKOption func(*cjk)
11
12// WithEastAsianLineBreaks is a functional option that indicates whether softline breaks
13// between east asian wide characters should be ignored.
14func WithEastAsianLineBreaks() CJKOption {
15 return func(c *cjk) {
16 c.EastAsianLineBreaks = true
17 }
18}
19
20// WithEscapedSpace is a functional option that indicates that a '\' escaped half-space(0x20) should not be rendered.
21func WithEscapedSpace() CJKOption {
22 return func(c *cjk) {
23 c.EscapedSpace = true
24 }
25}
26
27type cjk struct {
28 EastAsianLineBreaks bool
29 EscapedSpace bool
30}
31
32var CJK = NewCJK(WithEastAsianLineBreaks(), WithEscapedSpace())
33
34// NewCJK returns a new extension with given options.
35func NewCJK(opts ...CJKOption) goldmark.Extender {
36 e := &cjk{}
37 for _, opt := range opts {
38 opt(e)
39 }
40 return e
41}
42
43func (e *cjk) Extend(m goldmark.Markdown) {
44 if e.EastAsianLineBreaks {
45 m.Renderer().AddOptions(html.WithEastAsianLineBreaks())
46 }
47 if e.EscapedSpace {
48 m.Renderer().AddOptions(html.WithWriter(html.NewWriter(html.WithEscapedSpace())))
49 m.Parser().AddOptions(parser.WithEscapedSpace())
50 }
51}
diff --git a/vendor/github.com/yuin/goldmark/extension/definition_list.go b/vendor/github.com/yuin/goldmark/extension/definition_list.go
new file mode 100644
index 0000000..d2f5fec
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/definition_list.go
@@ -0,0 +1,270 @@
1package extension
2
3import (
4 "github.com/yuin/goldmark"
5 gast "github.com/yuin/goldmark/ast"
6 "github.com/yuin/goldmark/extension/ast"
7 "github.com/yuin/goldmark/parser"
8 "github.com/yuin/goldmark/renderer"
9 "github.com/yuin/goldmark/renderer/html"
10 "github.com/yuin/goldmark/text"
11 "github.com/yuin/goldmark/util"
12)
13
14type definitionListParser struct {
15}
16
17var defaultDefinitionListParser = &definitionListParser{}
18
19// NewDefinitionListParser return a new parser.BlockParser that
20// can parse PHP Markdown Extra Definition lists.
21func NewDefinitionListParser() parser.BlockParser {
22 return defaultDefinitionListParser
23}
24
25func (b *definitionListParser) Trigger() []byte {
26 return []byte{':'}
27}
28
29func (b *definitionListParser) Open(parent gast.Node, reader text.Reader, pc parser.Context) (gast.Node, parser.State) {
30 if _, ok := parent.(*ast.DefinitionList); ok {
31 return nil, parser.NoChildren
32 }
33 line, _ := reader.PeekLine()
34 pos := pc.BlockOffset()
35 indent := pc.BlockIndent()
36 if pos < 0 || line[pos] != ':' || indent != 0 {
37 return nil, parser.NoChildren
38 }
39
40 last := parent.LastChild()
41 // need 1 or more spaces after ':'
42 w, _ := util.IndentWidth(line[pos+1:], pos+1)
43 if w < 1 {
44 return nil, parser.NoChildren
45 }
46 if w >= 8 { // starts with indented code
47 w = 5
48 }
49 w += pos + 1 /* 1 = ':' */
50
51 para, lastIsParagraph := last.(*gast.Paragraph)
52 var list *ast.DefinitionList
53 status := parser.HasChildren
54 var ok bool
55 if lastIsParagraph {
56 list, ok = last.PreviousSibling().(*ast.DefinitionList)
57 if ok { // is not first item
58 list.Offset = w
59 list.TemporaryParagraph = para
60 } else { // is first item
61 list = ast.NewDefinitionList(w, para)
62 status |= parser.RequireParagraph
63 }
64 } else if list, ok = last.(*ast.DefinitionList); ok { // multiple description
65 list.Offset = w
66 list.TemporaryParagraph = nil
67 } else {
68 return nil, parser.NoChildren
69 }
70
71 return list, status
72}
73
74func (b *definitionListParser) Continue(node gast.Node, reader text.Reader, pc parser.Context) parser.State {
75 line, _ := reader.PeekLine()
76 if util.IsBlank(line) {
77 return parser.Continue | parser.HasChildren
78 }
79 list, _ := node.(*ast.DefinitionList)
80 w, _ := util.IndentWidth(line, reader.LineOffset())
81 if w < list.Offset {
82 return parser.Close
83 }
84 pos, padding := util.IndentPosition(line, reader.LineOffset(), list.Offset)
85 reader.AdvanceAndSetPadding(pos, padding)
86 return parser.Continue | parser.HasChildren
87}
88
89func (b *definitionListParser) Close(node gast.Node, reader text.Reader, pc parser.Context) {
90 // nothing to do
91}
92
93func (b *definitionListParser) CanInterruptParagraph() bool {
94 return true
95}
96
97func (b *definitionListParser) CanAcceptIndentedLine() bool {
98 return false
99}
100
101type definitionDescriptionParser struct {
102}
103
104var defaultDefinitionDescriptionParser = &definitionDescriptionParser{}
105
106// NewDefinitionDescriptionParser return a new parser.BlockParser that
107// can parse definition description starts with ':'.
108func NewDefinitionDescriptionParser() parser.BlockParser {
109 return defaultDefinitionDescriptionParser
110}
111
112func (b *definitionDescriptionParser) Trigger() []byte {
113 return []byte{':'}
114}
115
116func (b *definitionDescriptionParser) Open(parent gast.Node, reader text.Reader, pc parser.Context) (gast.Node, parser.State) {
117 line, _ := reader.PeekLine()
118 pos := pc.BlockOffset()
119 indent := pc.BlockIndent()
120 if pos < 0 || line[pos] != ':' || indent != 0 {
121 return nil, parser.NoChildren
122 }
123 list, _ := parent.(*ast.DefinitionList)
124 if list == nil {
125 return nil, parser.NoChildren
126 }
127 para := list.TemporaryParagraph
128 list.TemporaryParagraph = nil
129 if para != nil {
130 lines := para.Lines()
131 l := lines.Len()
132 for i := 0; i < l; i++ {
133 term := ast.NewDefinitionTerm()
134 segment := lines.At(i)
135 term.Lines().Append(segment.TrimRightSpace(reader.Source()))
136 list.AppendChild(list, term)
137 }
138 para.Parent().RemoveChild(para.Parent(), para)
139 }
140 cpos, padding := util.IndentPosition(line[pos+1:], pos+1, list.Offset-pos-1)
141 reader.AdvanceAndSetPadding(cpos+1, padding)
142
143 return ast.NewDefinitionDescription(), parser.HasChildren
144}
145
146func (b *definitionDescriptionParser) Continue(node gast.Node, reader text.Reader, pc parser.Context) parser.State {
147 // definitionListParser detects end of the description.
148 // so this method will never be called.
149 return parser.Continue | parser.HasChildren
150}
151
152func (b *definitionDescriptionParser) Close(node gast.Node, reader text.Reader, pc parser.Context) {
153 desc := node.(*ast.DefinitionDescription)
154 desc.IsTight = !desc.HasBlankPreviousLines()
155 if desc.IsTight {
156 for gc := desc.FirstChild(); gc != nil; gc = gc.NextSibling() {
157 paragraph, ok := gc.(*gast.Paragraph)
158 if ok {
159 textBlock := gast.NewTextBlock()
160 textBlock.SetLines(paragraph.Lines())
161 desc.ReplaceChild(desc, paragraph, textBlock)
162 }
163 }
164 }
165}
166
167func (b *definitionDescriptionParser) CanInterruptParagraph() bool {
168 return true
169}
170
171func (b *definitionDescriptionParser) CanAcceptIndentedLine() bool {
172 return false
173}
174
175// DefinitionListHTMLRenderer is a renderer.NodeRenderer implementation that
176// renders DefinitionList nodes.
177type DefinitionListHTMLRenderer struct {
178 html.Config
179}
180
181// NewDefinitionListHTMLRenderer returns a new DefinitionListHTMLRenderer.
182func NewDefinitionListHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
183 r := &DefinitionListHTMLRenderer{
184 Config: html.NewConfig(),
185 }
186 for _, opt := range opts {
187 opt.SetHTMLOption(&r.Config)
188 }
189 return r
190}
191
192// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
193func (r *DefinitionListHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
194 reg.Register(ast.KindDefinitionList, r.renderDefinitionList)
195 reg.Register(ast.KindDefinitionTerm, r.renderDefinitionTerm)
196 reg.Register(ast.KindDefinitionDescription, r.renderDefinitionDescription)
197}
198
199// DefinitionListAttributeFilter defines attribute names which dl elements can have.
200var DefinitionListAttributeFilter = html.GlobalAttributeFilter
201
202func (r *DefinitionListHTMLRenderer) renderDefinitionList(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
203 if entering {
204 if n.Attributes() != nil {
205 _, _ = w.WriteString("<dl")
206 html.RenderAttributes(w, n, DefinitionListAttributeFilter)
207 _, _ = w.WriteString(">\n")
208 } else {
209 _, _ = w.WriteString("<dl>\n")
210 }
211 } else {
212 _, _ = w.WriteString("</dl>\n")
213 }
214 return gast.WalkContinue, nil
215}
216
217// DefinitionTermAttributeFilter defines attribute names which dd elements can have.
218var DefinitionTermAttributeFilter = html.GlobalAttributeFilter
219
220func (r *DefinitionListHTMLRenderer) renderDefinitionTerm(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
221 if entering {
222 if n.Attributes() != nil {
223 _, _ = w.WriteString("<dt")
224 html.RenderAttributes(w, n, DefinitionTermAttributeFilter)
225 _ = w.WriteByte('>')
226 } else {
227 _, _ = w.WriteString("<dt>")
228 }
229 } else {
230 _, _ = w.WriteString("</dt>\n")
231 }
232 return gast.WalkContinue, nil
233}
234
235// DefinitionDescriptionAttributeFilter defines attribute names which dd elements can have.
236var DefinitionDescriptionAttributeFilter = html.GlobalAttributeFilter
237
238func (r *DefinitionListHTMLRenderer) renderDefinitionDescription(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
239 if entering {
240 n := node.(*ast.DefinitionDescription)
241 _, _ = w.WriteString("<dd")
242 if n.Attributes() != nil {
243 html.RenderAttributes(w, n, DefinitionDescriptionAttributeFilter)
244 }
245 if n.IsTight {
246 _, _ = w.WriteString(">")
247 } else {
248 _, _ = w.WriteString(">\n")
249 }
250 } else {
251 _, _ = w.WriteString("</dd>\n")
252 }
253 return gast.WalkContinue, nil
254}
255
256type definitionList struct {
257}
258
259// DefinitionList is an extension that allow you to use PHP Markdown Extra Definition lists.
260var DefinitionList = &definitionList{}
261
262func (e *definitionList) Extend(m goldmark.Markdown) {
263 m.Parser().AddOptions(parser.WithBlockParsers(
264 util.Prioritized(NewDefinitionListParser(), 101),
265 util.Prioritized(NewDefinitionDescriptionParser(), 102),
266 ))
267 m.Renderer().AddOptions(renderer.WithNodeRenderers(
268 util.Prioritized(NewDefinitionListHTMLRenderer(), 500),
269 ))
270}
diff --git a/vendor/github.com/yuin/goldmark/extension/footnote.go b/vendor/github.com/yuin/goldmark/extension/footnote.go
new file mode 100644
index 0000000..09b6fa8
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/footnote.go
@@ -0,0 +1,687 @@
1package extension
2
3import (
4 "bytes"
5 "fmt"
6 "strconv"
7
8 "github.com/yuin/goldmark"
9 gast "github.com/yuin/goldmark/ast"
10 "github.com/yuin/goldmark/extension/ast"
11 "github.com/yuin/goldmark/parser"
12 "github.com/yuin/goldmark/renderer"
13 "github.com/yuin/goldmark/renderer/html"
14 "github.com/yuin/goldmark/text"
15 "github.com/yuin/goldmark/util"
16)
17
18var footnoteListKey = parser.NewContextKey()
19var footnoteLinkListKey = parser.NewContextKey()
20
21type footnoteBlockParser struct {
22}
23
24var defaultFootnoteBlockParser = &footnoteBlockParser{}
25
26// NewFootnoteBlockParser returns a new parser.BlockParser that can parse
27// footnotes of the Markdown(PHP Markdown Extra) text.
28func NewFootnoteBlockParser() parser.BlockParser {
29 return defaultFootnoteBlockParser
30}
31
32func (b *footnoteBlockParser) Trigger() []byte {
33 return []byte{'['}
34}
35
36func (b *footnoteBlockParser) Open(parent gast.Node, reader text.Reader, pc parser.Context) (gast.Node, parser.State) {
37 line, segment := reader.PeekLine()
38 pos := pc.BlockOffset()
39 if pos < 0 || line[pos] != '[' {
40 return nil, parser.NoChildren
41 }
42 pos++
43 if pos > len(line)-1 || line[pos] != '^' {
44 return nil, parser.NoChildren
45 }
46 open := pos + 1
47 closes := 0
48 closure := util.FindClosure(line[pos+1:], '[', ']', false, false)
49 closes = pos + 1 + closure
50 next := closes + 1
51 if closure > -1 {
52 if next >= len(line) || line[next] != ':' {
53 return nil, parser.NoChildren
54 }
55 } else {
56 return nil, parser.NoChildren
57 }
58 padding := segment.Padding
59 label := reader.Value(text.NewSegment(segment.Start+open-padding, segment.Start+closes-padding))
60 if util.IsBlank(label) {
61 return nil, parser.NoChildren
62 }
63 item := ast.NewFootnote(label)
64
65 pos = next + 1 - padding
66 if pos >= len(line) {
67 reader.Advance(pos)
68 return item, parser.NoChildren
69 }
70 reader.AdvanceAndSetPadding(pos, padding)
71 return item, parser.HasChildren
72}
73
74func (b *footnoteBlockParser) Continue(node gast.Node, reader text.Reader, pc parser.Context) parser.State {
75 line, _ := reader.PeekLine()
76 if util.IsBlank(line) {
77 return parser.Continue | parser.HasChildren
78 }
79 childpos, padding := util.IndentPosition(line, reader.LineOffset(), 4)
80 if childpos < 0 {
81 return parser.Close
82 }
83 reader.AdvanceAndSetPadding(childpos, padding)
84 return parser.Continue | parser.HasChildren
85}
86
87func (b *footnoteBlockParser) Close(node gast.Node, reader text.Reader, pc parser.Context) {
88 var list *ast.FootnoteList
89 if tlist := pc.Get(footnoteListKey); tlist != nil {
90 list = tlist.(*ast.FootnoteList)
91 } else {
92 list = ast.NewFootnoteList()
93 pc.Set(footnoteListKey, list)
94 node.Parent().InsertBefore(node.Parent(), node, list)
95 }
96 node.Parent().RemoveChild(node.Parent(), node)
97 list.AppendChild(list, node)
98}
99
100func (b *footnoteBlockParser) CanInterruptParagraph() bool {
101 return true
102}
103
104func (b *footnoteBlockParser) CanAcceptIndentedLine() bool {
105 return false
106}
107
108type footnoteParser struct {
109}
110
111var defaultFootnoteParser = &footnoteParser{}
112
113// NewFootnoteParser returns a new parser.InlineParser that can parse
114// footnote links of the Markdown(PHP Markdown Extra) text.
115func NewFootnoteParser() parser.InlineParser {
116 return defaultFootnoteParser
117}
118
119func (s *footnoteParser) Trigger() []byte {
120 // footnote syntax probably conflict with the image syntax.
121 // So we need trigger this parser with '!'.
122 return []byte{'!', '['}
123}
124
125func (s *footnoteParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
126 line, segment := block.PeekLine()
127 pos := 1
128 if len(line) > 0 && line[0] == '!' {
129 pos++
130 }
131 if pos >= len(line) || line[pos] != '^' {
132 return nil
133 }
134 pos++
135 if pos >= len(line) {
136 return nil
137 }
138 open := pos
139 closure := util.FindClosure(line[pos:], '[', ']', false, false)
140 if closure < 0 {
141 return nil
142 }
143 closes := pos + closure
144 value := block.Value(text.NewSegment(segment.Start+open, segment.Start+closes))
145 block.Advance(closes + 1)
146
147 var list *ast.FootnoteList
148 if tlist := pc.Get(footnoteListKey); tlist != nil {
149 list = tlist.(*ast.FootnoteList)
150 }
151 if list == nil {
152 return nil
153 }
154 index := 0
155 for def := list.FirstChild(); def != nil; def = def.NextSibling() {
156 d := def.(*ast.Footnote)
157 if bytes.Equal(d.Ref, value) {
158 if d.Index < 0 {
159 list.Count += 1
160 d.Index = list.Count
161 }
162 index = d.Index
163 break
164 }
165 }
166 if index == 0 {
167 return nil
168 }
169
170 fnlink := ast.NewFootnoteLink(index)
171 var fnlist []*ast.FootnoteLink
172 if tmp := pc.Get(footnoteLinkListKey); tmp != nil {
173 fnlist = tmp.([]*ast.FootnoteLink)
174 } else {
175 fnlist = []*ast.FootnoteLink{}
176 pc.Set(footnoteLinkListKey, fnlist)
177 }
178 pc.Set(footnoteLinkListKey, append(fnlist, fnlink))
179 if line[0] == '!' {
180 parent.AppendChild(parent, gast.NewTextSegment(text.NewSegment(segment.Start, segment.Start+1)))
181 }
182
183 return fnlink
184}
185
186type footnoteASTTransformer struct {
187}
188
189var defaultFootnoteASTTransformer = &footnoteASTTransformer{}
190
191// NewFootnoteASTTransformer returns a new parser.ASTTransformer that
192// insert a footnote list to the last of the document.
193func NewFootnoteASTTransformer() parser.ASTTransformer {
194 return defaultFootnoteASTTransformer
195}
196
197func (a *footnoteASTTransformer) Transform(node *gast.Document, reader text.Reader, pc parser.Context) {
198 var list *ast.FootnoteList
199 var fnlist []*ast.FootnoteLink
200 if tmp := pc.Get(footnoteListKey); tmp != nil {
201 list = tmp.(*ast.FootnoteList)
202 }
203 if tmp := pc.Get(footnoteLinkListKey); tmp != nil {
204 fnlist = tmp.([]*ast.FootnoteLink)
205 }
206
207 pc.Set(footnoteListKey, nil)
208 pc.Set(footnoteLinkListKey, nil)
209
210 if list == nil {
211 return
212 }
213
214 counter := map[int]int{}
215 if fnlist != nil {
216 for _, fnlink := range fnlist {
217 if fnlink.Index >= 0 {
218 counter[fnlink.Index]++
219 }
220 }
221 refCounter := map[int]int{}
222 for _, fnlink := range fnlist {
223 fnlink.RefCount = counter[fnlink.Index]
224 if _, ok := refCounter[fnlink.Index]; !ok {
225 refCounter[fnlink.Index] = 0
226 }
227 fnlink.RefIndex = refCounter[fnlink.Index]
228 refCounter[fnlink.Index]++
229 }
230 }
231 for footnote := list.FirstChild(); footnote != nil; {
232 var container gast.Node = footnote
233 next := footnote.NextSibling()
234 if fc := container.LastChild(); fc != nil && gast.IsParagraph(fc) {
235 container = fc
236 }
237 fn := footnote.(*ast.Footnote)
238 index := fn.Index
239 if index < 0 {
240 list.RemoveChild(list, footnote)
241 } else {
242 refCount := counter[index]
243 backLink := ast.NewFootnoteBacklink(index)
244 backLink.RefCount = refCount
245 backLink.RefIndex = 0
246 container.AppendChild(container, backLink)
247 if refCount > 1 {
248 for i := 1; i < refCount; i++ {
249 backLink := ast.NewFootnoteBacklink(index)
250 backLink.RefCount = refCount
251 backLink.RefIndex = i
252 container.AppendChild(container, backLink)
253 }
254 }
255 }
256 footnote = next
257 }
258 list.SortChildren(func(n1, n2 gast.Node) int {
259 if n1.(*ast.Footnote).Index < n2.(*ast.Footnote).Index {
260 return -1
261 }
262 return 1
263 })
264 if list.Count <= 0 {
265 list.Parent().RemoveChild(list.Parent(), list)
266 return
267 }
268
269 node.AppendChild(node, list)
270}
271
272// FootnoteConfig holds configuration values for the footnote extension.
273//
274// Link* and Backlink* configurations have some variables:
275// Occurrances of “^^” in the string will be replaced by the
276// corresponding footnote number in the HTML output.
277// Occurrances of “%%” will be replaced by a number for the
278// reference (footnotes can have multiple references).
279type FootnoteConfig struct {
280 html.Config
281
282 // IDPrefix is a prefix for the id attributes generated by footnotes.
283 IDPrefix []byte
284
285 // IDPrefix is a function that determines the id attribute for given Node.
286 IDPrefixFunction func(gast.Node) []byte
287
288 // LinkTitle is an optional title attribute for footnote links.
289 LinkTitle []byte
290
291 // BacklinkTitle is an optional title attribute for footnote backlinks.
292 BacklinkTitle []byte
293
294 // LinkClass is a class for footnote links.
295 LinkClass []byte
296
297 // BacklinkClass is a class for footnote backlinks.
298 BacklinkClass []byte
299
300 // BacklinkHTML is an HTML content for footnote backlinks.
301 BacklinkHTML []byte
302}
303
304// FootnoteOption interface is a functional option interface for the extension.
305type FootnoteOption interface {
306 renderer.Option
307 // SetFootnoteOption sets given option to the extension.
308 SetFootnoteOption(*FootnoteConfig)
309}
310
311// NewFootnoteConfig returns a new Config with defaults.
312func NewFootnoteConfig() FootnoteConfig {
313 return FootnoteConfig{
314 Config: html.NewConfig(),
315 LinkTitle: []byte(""),
316 BacklinkTitle: []byte(""),
317 LinkClass: []byte("footnote-ref"),
318 BacklinkClass: []byte("footnote-backref"),
319 BacklinkHTML: []byte("&#x21a9;&#xfe0e;"),
320 }
321}
322
323// SetOption implements renderer.SetOptioner.
324func (c *FootnoteConfig) SetOption(name renderer.OptionName, value interface{}) {
325 switch name {
326 case optFootnoteIDPrefixFunction:
327 c.IDPrefixFunction = value.(func(gast.Node) []byte)
328 case optFootnoteIDPrefix:
329 c.IDPrefix = value.([]byte)
330 case optFootnoteLinkTitle:
331 c.LinkTitle = value.([]byte)
332 case optFootnoteBacklinkTitle:
333 c.BacklinkTitle = value.([]byte)
334 case optFootnoteLinkClass:
335 c.LinkClass = value.([]byte)
336 case optFootnoteBacklinkClass:
337 c.BacklinkClass = value.([]byte)
338 case optFootnoteBacklinkHTML:
339 c.BacklinkHTML = value.([]byte)
340 default:
341 c.Config.SetOption(name, value)
342 }
343}
344
345type withFootnoteHTMLOptions struct {
346 value []html.Option
347}
348
349func (o *withFootnoteHTMLOptions) SetConfig(c *renderer.Config) {
350 if o.value != nil {
351 for _, v := range o.value {
352 v.(renderer.Option).SetConfig(c)
353 }
354 }
355}
356
357func (o *withFootnoteHTMLOptions) SetFootnoteOption(c *FootnoteConfig) {
358 if o.value != nil {
359 for _, v := range o.value {
360 v.SetHTMLOption(&c.Config)
361 }
362 }
363}
364
365// WithFootnoteHTMLOptions is functional option that wraps goldmark HTMLRenderer options.
366func WithFootnoteHTMLOptions(opts ...html.Option) FootnoteOption {
367 return &withFootnoteHTMLOptions{opts}
368}
369
370const optFootnoteIDPrefix renderer.OptionName = "FootnoteIDPrefix"
371
372type withFootnoteIDPrefix struct {
373 value []byte
374}
375
376func (o *withFootnoteIDPrefix) SetConfig(c *renderer.Config) {
377 c.Options[optFootnoteIDPrefix] = o.value
378}
379
380func (o *withFootnoteIDPrefix) SetFootnoteOption(c *FootnoteConfig) {
381 c.IDPrefix = o.value
382}
383
384// WithFootnoteIDPrefix is a functional option that is a prefix for the id attributes generated by footnotes.
385func WithFootnoteIDPrefix(a []byte) FootnoteOption {
386 return &withFootnoteIDPrefix{a}
387}
388
389const optFootnoteIDPrefixFunction renderer.OptionName = "FootnoteIDPrefixFunction"
390
391type withFootnoteIDPrefixFunction struct {
392 value func(gast.Node) []byte
393}
394
395func (o *withFootnoteIDPrefixFunction) SetConfig(c *renderer.Config) {
396 c.Options[optFootnoteIDPrefixFunction] = o.value
397}
398
399func (o *withFootnoteIDPrefixFunction) SetFootnoteOption(c *FootnoteConfig) {
400 c.IDPrefixFunction = o.value
401}
402
403// WithFootnoteIDPrefixFunction is a functional option that is a prefix for the id attributes generated by footnotes.
404func WithFootnoteIDPrefixFunction(a func(gast.Node) []byte) FootnoteOption {
405 return &withFootnoteIDPrefixFunction{a}
406}
407
408const optFootnoteLinkTitle renderer.OptionName = "FootnoteLinkTitle"
409
410type withFootnoteLinkTitle struct {
411 value []byte
412}
413
414func (o *withFootnoteLinkTitle) SetConfig(c *renderer.Config) {
415 c.Options[optFootnoteLinkTitle] = o.value
416}
417
418func (o *withFootnoteLinkTitle) SetFootnoteOption(c *FootnoteConfig) {
419 c.LinkTitle = o.value
420}
421
422// WithFootnoteLinkTitle is a functional option that is an optional title attribute for footnote links.
423func WithFootnoteLinkTitle(a []byte) FootnoteOption {
424 return &withFootnoteLinkTitle{a}
425}
426
427const optFootnoteBacklinkTitle renderer.OptionName = "FootnoteBacklinkTitle"
428
429type withFootnoteBacklinkTitle struct {
430 value []byte
431}
432
433func (o *withFootnoteBacklinkTitle) SetConfig(c *renderer.Config) {
434 c.Options[optFootnoteBacklinkTitle] = o.value
435}
436
437func (o *withFootnoteBacklinkTitle) SetFootnoteOption(c *FootnoteConfig) {
438 c.BacklinkTitle = o.value
439}
440
441// WithFootnoteBacklinkTitle is a functional option that is an optional title attribute for footnote backlinks.
442func WithFootnoteBacklinkTitle(a []byte) FootnoteOption {
443 return &withFootnoteBacklinkTitle{a}
444}
445
446const optFootnoteLinkClass renderer.OptionName = "FootnoteLinkClass"
447
448type withFootnoteLinkClass struct {
449 value []byte
450}
451
452func (o *withFootnoteLinkClass) SetConfig(c *renderer.Config) {
453 c.Options[optFootnoteLinkClass] = o.value
454}
455
456func (o *withFootnoteLinkClass) SetFootnoteOption(c *FootnoteConfig) {
457 c.LinkClass = o.value
458}
459
460// WithFootnoteLinkClass is a functional option that is a class for footnote links.
461func WithFootnoteLinkClass(a []byte) FootnoteOption {
462 return &withFootnoteLinkClass{a}
463}
464
465const optFootnoteBacklinkClass renderer.OptionName = "FootnoteBacklinkClass"
466
467type withFootnoteBacklinkClass struct {
468 value []byte
469}
470
471func (o *withFootnoteBacklinkClass) SetConfig(c *renderer.Config) {
472 c.Options[optFootnoteBacklinkClass] = o.value
473}
474
475func (o *withFootnoteBacklinkClass) SetFootnoteOption(c *FootnoteConfig) {
476 c.BacklinkClass = o.value
477}
478
479// WithFootnoteBacklinkClass is a functional option that is a class for footnote backlinks.
480func WithFootnoteBacklinkClass(a []byte) FootnoteOption {
481 return &withFootnoteBacklinkClass{a}
482}
483
484const optFootnoteBacklinkHTML renderer.OptionName = "FootnoteBacklinkHTML"
485
486type withFootnoteBacklinkHTML struct {
487 value []byte
488}
489
490func (o *withFootnoteBacklinkHTML) SetConfig(c *renderer.Config) {
491 c.Options[optFootnoteBacklinkHTML] = o.value
492}
493
494func (o *withFootnoteBacklinkHTML) SetFootnoteOption(c *FootnoteConfig) {
495 c.BacklinkHTML = o.value
496}
497
498// WithFootnoteBacklinkHTML is an HTML content for footnote backlinks.
499func WithFootnoteBacklinkHTML(a []byte) FootnoteOption {
500 return &withFootnoteBacklinkHTML{a}
501}
502
503// FootnoteHTMLRenderer is a renderer.NodeRenderer implementation that
504// renders FootnoteLink nodes.
505type FootnoteHTMLRenderer struct {
506 FootnoteConfig
507}
508
509// NewFootnoteHTMLRenderer returns a new FootnoteHTMLRenderer.
510func NewFootnoteHTMLRenderer(opts ...FootnoteOption) renderer.NodeRenderer {
511 r := &FootnoteHTMLRenderer{
512 FootnoteConfig: NewFootnoteConfig(),
513 }
514 for _, opt := range opts {
515 opt.SetFootnoteOption(&r.FootnoteConfig)
516 }
517 return r
518}
519
520// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
521func (r *FootnoteHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
522 reg.Register(ast.KindFootnoteLink, r.renderFootnoteLink)
523 reg.Register(ast.KindFootnoteBacklink, r.renderFootnoteBacklink)
524 reg.Register(ast.KindFootnote, r.renderFootnote)
525 reg.Register(ast.KindFootnoteList, r.renderFootnoteList)
526}
527
528func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
529 if entering {
530 n := node.(*ast.FootnoteLink)
531 is := strconv.Itoa(n.Index)
532 _, _ = w.WriteString(`<sup id="`)
533 _, _ = w.Write(r.idPrefix(node))
534 _, _ = w.WriteString(`fnref`)
535 if n.RefIndex > 0 {
536 _, _ = w.WriteString(fmt.Sprintf("%v", n.RefIndex))
537 }
538 _ = w.WriteByte(':')
539 _, _ = w.WriteString(is)
540 _, _ = w.WriteString(`"><a href="#`)
541 _, _ = w.Write(r.idPrefix(node))
542 _, _ = w.WriteString(`fn:`)
543 _, _ = w.WriteString(is)
544 _, _ = w.WriteString(`" class="`)
545 _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.LinkClass,
546 n.Index, n.RefCount))
547 if len(r.FootnoteConfig.LinkTitle) > 0 {
548 _, _ = w.WriteString(`" title="`)
549 _, _ = w.Write(util.EscapeHTML(applyFootnoteTemplate(r.FootnoteConfig.LinkTitle, n.Index, n.RefCount)))
550 }
551 _, _ = w.WriteString(`" role="doc-noteref">`)
552
553 _, _ = w.WriteString(is)
554 _, _ = w.WriteString(`</a></sup>`)
555 }
556 return gast.WalkContinue, nil
557}
558
559func (r *FootnoteHTMLRenderer) renderFootnoteBacklink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
560 if entering {
561 n := node.(*ast.FootnoteBacklink)
562 is := strconv.Itoa(n.Index)
563 _, _ = w.WriteString(`&#160;<a href="#`)
564 _, _ = w.Write(r.idPrefix(node))
565 _, _ = w.WriteString(`fnref`)
566 if n.RefIndex > 0 {
567 _, _ = w.WriteString(fmt.Sprintf("%v", n.RefIndex))
568 }
569 _ = w.WriteByte(':')
570 _, _ = w.WriteString(is)
571 _, _ = w.WriteString(`" class="`)
572 _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkClass, n.Index, n.RefCount))
573 if len(r.FootnoteConfig.BacklinkTitle) > 0 {
574 _, _ = w.WriteString(`" title="`)
575 _, _ = w.Write(util.EscapeHTML(applyFootnoteTemplate(r.FootnoteConfig.BacklinkTitle, n.Index, n.RefCount)))
576 }
577 _, _ = w.WriteString(`" role="doc-backlink">`)
578 _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkHTML, n.Index, n.RefCount))
579 _, _ = w.WriteString(`</a>`)
580 }
581 return gast.WalkContinue, nil
582}
583
584func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
585 n := node.(*ast.Footnote)
586 is := strconv.Itoa(n.Index)
587 if entering {
588 _, _ = w.WriteString(`<li id="`)
589 _, _ = w.Write(r.idPrefix(node))
590 _, _ = w.WriteString(`fn:`)
591 _, _ = w.WriteString(is)
592 _, _ = w.WriteString(`"`)
593 if node.Attributes() != nil {
594 html.RenderAttributes(w, node, html.ListItemAttributeFilter)
595 }
596 _, _ = w.WriteString(">\n")
597 } else {
598 _, _ = w.WriteString("</li>\n")
599 }
600 return gast.WalkContinue, nil
601}
602
603func (r *FootnoteHTMLRenderer) renderFootnoteList(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
604 if entering {
605 _, _ = w.WriteString(`<div class="footnotes" role="doc-endnotes"`)
606 if node.Attributes() != nil {
607 html.RenderAttributes(w, node, html.GlobalAttributeFilter)
608 }
609 _ = w.WriteByte('>')
610 if r.Config.XHTML {
611 _, _ = w.WriteString("\n<hr />\n")
612 } else {
613 _, _ = w.WriteString("\n<hr>\n")
614 }
615 _, _ = w.WriteString("<ol>\n")
616 } else {
617 _, _ = w.WriteString("</ol>\n")
618 _, _ = w.WriteString("</div>\n")
619 }
620 return gast.WalkContinue, nil
621}
622
623func (r *FootnoteHTMLRenderer) idPrefix(node gast.Node) []byte {
624 if r.FootnoteConfig.IDPrefix != nil {
625 return r.FootnoteConfig.IDPrefix
626 }
627 if r.FootnoteConfig.IDPrefixFunction != nil {
628 return r.FootnoteConfig.IDPrefixFunction(node)
629 }
630 return []byte("")
631}
632
633func applyFootnoteTemplate(b []byte, index, refCount int) []byte {
634 fast := true
635 for i, c := range b {
636 if i != 0 {
637 if b[i-1] == '^' && c == '^' {
638 fast = false
639 break
640 }
641 if b[i-1] == '%' && c == '%' {
642 fast = false
643 break
644 }
645 }
646 }
647 if fast {
648 return b
649 }
650 is := []byte(strconv.Itoa(index))
651 rs := []byte(strconv.Itoa(refCount))
652 ret := bytes.Replace(b, []byte("^^"), is, -1)
653 return bytes.Replace(ret, []byte("%%"), rs, -1)
654}
655
656type footnote struct {
657 options []FootnoteOption
658}
659
660// Footnote is an extension that allow you to use PHP Markdown Extra Footnotes.
661var Footnote = &footnote{
662 options: []FootnoteOption{},
663}
664
665// NewFootnote returns a new extension with given options.
666func NewFootnote(opts ...FootnoteOption) goldmark.Extender {
667 return &footnote{
668 options: opts,
669 }
670}
671
672func (e *footnote) Extend(m goldmark.Markdown) {
673 m.Parser().AddOptions(
674 parser.WithBlockParsers(
675 util.Prioritized(NewFootnoteBlockParser(), 999),
676 ),
677 parser.WithInlineParsers(
678 util.Prioritized(NewFootnoteParser(), 101),
679 ),
680 parser.WithASTTransformers(
681 util.Prioritized(NewFootnoteASTTransformer(), 999),
682 ),
683 )
684 m.Renderer().AddOptions(renderer.WithNodeRenderers(
685 util.Prioritized(NewFootnoteHTMLRenderer(e.options...), 500),
686 ))
687}
diff --git a/vendor/github.com/yuin/goldmark/extension/gfm.go b/vendor/github.com/yuin/goldmark/extension/gfm.go
new file mode 100644
index 0000000..a570fbd
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/gfm.go
@@ -0,0 +1,18 @@
1package extension
2
3import (
4 "github.com/yuin/goldmark"
5)
6
7type gfm struct {
8}
9
10// GFM is an extension that provides Github Flavored markdown functionalities.
11var GFM = &gfm{}
12
13func (e *gfm) Extend(m goldmark.Markdown) {
14 Linkify.Extend(m)
15 Table.Extend(m)
16 Strikethrough.Extend(m)
17 TaskList.Extend(m)
18}
diff --git a/vendor/github.com/yuin/goldmark/extension/linkify.go b/vendor/github.com/yuin/goldmark/extension/linkify.go
new file mode 100644
index 0000000..2f046eb
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/linkify.go
@@ -0,0 +1,318 @@
1package extension
2
3import (
4 "bytes"
5 "regexp"
6
7 "github.com/yuin/goldmark"
8 "github.com/yuin/goldmark/ast"
9 "github.com/yuin/goldmark/parser"
10 "github.com/yuin/goldmark/text"
11 "github.com/yuin/goldmark/util"
12)
13
14var wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-z]+(?:[/#?][-a-zA-Z0-9@:%_\+.~#!?&/=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
15
16var urlRegexp = regexp.MustCompile(`^(?:http|https|ftp)://[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-z]+(?::\d+)?(?:[/#?][-a-zA-Z0-9@:%_+.~#$!?&/=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
17
18// An LinkifyConfig struct is a data structure that holds configuration of the
19// Linkify extension.
20type LinkifyConfig struct {
21 AllowedProtocols [][]byte
22 URLRegexp *regexp.Regexp
23 WWWRegexp *regexp.Regexp
24 EmailRegexp *regexp.Regexp
25}
26
27const (
28 optLinkifyAllowedProtocols parser.OptionName = "LinkifyAllowedProtocols"
29 optLinkifyURLRegexp parser.OptionName = "LinkifyURLRegexp"
30 optLinkifyWWWRegexp parser.OptionName = "LinkifyWWWRegexp"
31 optLinkifyEmailRegexp parser.OptionName = "LinkifyEmailRegexp"
32)
33
34// SetOption implements SetOptioner.
35func (c *LinkifyConfig) SetOption(name parser.OptionName, value interface{}) {
36 switch name {
37 case optLinkifyAllowedProtocols:
38 c.AllowedProtocols = value.([][]byte)
39 case optLinkifyURLRegexp:
40 c.URLRegexp = value.(*regexp.Regexp)
41 case optLinkifyWWWRegexp:
42 c.WWWRegexp = value.(*regexp.Regexp)
43 case optLinkifyEmailRegexp:
44 c.EmailRegexp = value.(*regexp.Regexp)
45 }
46}
47
48// A LinkifyOption interface sets options for the LinkifyOption.
49type LinkifyOption interface {
50 parser.Option
51 SetLinkifyOption(*LinkifyConfig)
52}
53
54type withLinkifyAllowedProtocols struct {
55 value [][]byte
56}
57
58func (o *withLinkifyAllowedProtocols) SetParserOption(c *parser.Config) {
59 c.Options[optLinkifyAllowedProtocols] = o.value
60}
61
62func (o *withLinkifyAllowedProtocols) SetLinkifyOption(p *LinkifyConfig) {
63 p.AllowedProtocols = o.value
64}
65
66// WithLinkifyAllowedProtocols is a functional option that specify allowed
67// protocols in autolinks. Each protocol must end with ':' like
68// 'http:' .
69func WithLinkifyAllowedProtocols(value [][]byte) LinkifyOption {
70 return &withLinkifyAllowedProtocols{
71 value: value,
72 }
73}
74
75type withLinkifyURLRegexp struct {
76 value *regexp.Regexp
77}
78
79func (o *withLinkifyURLRegexp) SetParserOption(c *parser.Config) {
80 c.Options[optLinkifyURLRegexp] = o.value
81}
82
83func (o *withLinkifyURLRegexp) SetLinkifyOption(p *LinkifyConfig) {
84 p.URLRegexp = o.value
85}
86
87// WithLinkifyURLRegexp is a functional option that specify
88// a pattern of the URL including a protocol.
89func WithLinkifyURLRegexp(value *regexp.Regexp) LinkifyOption {
90 return &withLinkifyURLRegexp{
91 value: value,
92 }
93}
94
95// WithLinkifyWWWRegexp is a functional option that specify
96// a pattern of the URL without a protocol.
97// This pattern must start with 'www.' .
98type withLinkifyWWWRegexp struct {
99 value *regexp.Regexp
100}
101
102func (o *withLinkifyWWWRegexp) SetParserOption(c *parser.Config) {
103 c.Options[optLinkifyWWWRegexp] = o.value
104}
105
106func (o *withLinkifyWWWRegexp) SetLinkifyOption(p *LinkifyConfig) {
107 p.WWWRegexp = o.value
108}
109
110func WithLinkifyWWWRegexp(value *regexp.Regexp) LinkifyOption {
111 return &withLinkifyWWWRegexp{
112 value: value,
113 }
114}
115
116// WithLinkifyWWWRegexp is a functional otpion that specify
117// a pattern of the email address.
118type withLinkifyEmailRegexp struct {
119 value *regexp.Regexp
120}
121
122func (o *withLinkifyEmailRegexp) SetParserOption(c *parser.Config) {
123 c.Options[optLinkifyEmailRegexp] = o.value
124}
125
126func (o *withLinkifyEmailRegexp) SetLinkifyOption(p *LinkifyConfig) {
127 p.EmailRegexp = o.value
128}
129
130func WithLinkifyEmailRegexp(value *regexp.Regexp) LinkifyOption {
131 return &withLinkifyEmailRegexp{
132 value: value,
133 }
134}
135
136type linkifyParser struct {
137 LinkifyConfig
138}
139
140// NewLinkifyParser return a new InlineParser can parse
141// text that seems like a URL.
142func NewLinkifyParser(opts ...LinkifyOption) parser.InlineParser {
143 p := &linkifyParser{
144 LinkifyConfig: LinkifyConfig{
145 AllowedProtocols: nil,
146 URLRegexp: urlRegexp,
147 WWWRegexp: wwwURLRegxp,
148 },
149 }
150 for _, o := range opts {
151 o.SetLinkifyOption(&p.LinkifyConfig)
152 }
153 return p
154}
155
156func (s *linkifyParser) Trigger() []byte {
157 // ' ' indicates any white spaces and a line head
158 return []byte{' ', '*', '_', '~', '('}
159}
160
161var (
162 protoHTTP = []byte("http:")
163 protoHTTPS = []byte("https:")
164 protoFTP = []byte("ftp:")
165 domainWWW = []byte("www.")
166)
167
168func (s *linkifyParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node {
169 if pc.IsInLinkLabel() {
170 return nil
171 }
172 line, segment := block.PeekLine()
173 consumes := 0
174 start := segment.Start
175 c := line[0]
176 // advance if current position is not a line head.
177 if c == ' ' || c == '*' || c == '_' || c == '~' || c == '(' {
178 consumes++
179 start++
180 line = line[1:]
181 }
182
183 var m []int
184 var protocol []byte
185 var typ ast.AutoLinkType = ast.AutoLinkURL
186 if s.LinkifyConfig.AllowedProtocols == nil {
187 if bytes.HasPrefix(line, protoHTTP) || bytes.HasPrefix(line, protoHTTPS) || bytes.HasPrefix(line, protoFTP) {
188 m = s.LinkifyConfig.URLRegexp.FindSubmatchIndex(line)
189 }
190 } else {
191 for _, prefix := range s.LinkifyConfig.AllowedProtocols {
192 if bytes.HasPrefix(line, prefix) {
193 m = s.LinkifyConfig.URLRegexp.FindSubmatchIndex(line)
194 break
195 }
196 }
197 }
198 if m == nil && bytes.HasPrefix(line, domainWWW) {
199 m = s.LinkifyConfig.WWWRegexp.FindSubmatchIndex(line)
200 protocol = []byte("http")
201 }
202 if m != nil && m[0] != 0 {
203 m = nil
204 }
205 if m != nil && m[0] == 0 {
206 lastChar := line[m[1]-1]
207 if lastChar == '.' {
208 m[1]--
209 } else if lastChar == ')' {
210 closing := 0
211 for i := m[1] - 1; i >= m[0]; i-- {
212 if line[i] == ')' {
213 closing++
214 } else if line[i] == '(' {
215 closing--
216 }
217 }
218 if closing > 0 {
219 m[1] -= closing
220 }
221 } else if lastChar == ';' {
222 i := m[1] - 2
223 for ; i >= m[0]; i-- {
224 if util.IsAlphaNumeric(line[i]) {
225 continue
226 }
227 break
228 }
229 if i != m[1]-2 {
230 if line[i] == '&' {
231 m[1] -= m[1] - i
232 }
233 }
234 }
235 }
236 if m == nil {
237 if len(line) > 0 && util.IsPunct(line[0]) {
238 return nil
239 }
240 typ = ast.AutoLinkEmail
241 stop := -1
242 if s.LinkifyConfig.EmailRegexp == nil {
243 stop = util.FindEmailIndex(line)
244 } else {
245 m := s.LinkifyConfig.EmailRegexp.FindSubmatchIndex(line)
246 if m != nil && m[0] == 0 {
247 stop = m[1]
248 }
249 }
250 if stop < 0 {
251 return nil
252 }
253 at := bytes.IndexByte(line, '@')
254 m = []int{0, stop, at, stop - 1}
255 if m == nil || bytes.IndexByte(line[m[2]:m[3]], '.') < 0 {
256 return nil
257 }
258 lastChar := line[m[1]-1]
259 if lastChar == '.' {
260 m[1]--
261 }
262 if m[1] < len(line) {
263 nextChar := line[m[1]]
264 if nextChar == '-' || nextChar == '_' {
265 return nil
266 }
267 }
268 }
269 if m == nil {
270 return nil
271 }
272 if consumes != 0 {
273 s := segment.WithStop(segment.Start + 1)
274 ast.MergeOrAppendTextSegment(parent, s)
275 }
276 i := m[1] - 1
277 for ; i > 0; i-- {
278 c := line[i]
279 switch c {
280 case '?', '!', '.', ',', ':', '*', '_', '~':
281 default:
282 goto endfor
283 }
284 }
285endfor:
286 i++
287 consumes += i
288 block.Advance(consumes)
289 n := ast.NewTextSegment(text.NewSegment(start, start+i))
290 link := ast.NewAutoLink(typ, n)
291 link.Protocol = protocol
292 return link
293}
294
295func (s *linkifyParser) CloseBlock(parent ast.Node, pc parser.Context) {
296 // nothing to do
297}
298
299type linkify struct {
300 options []LinkifyOption
301}
302
303// Linkify is an extension that allow you to parse text that seems like a URL.
304var Linkify = &linkify{}
305
306func NewLinkify(opts ...LinkifyOption) goldmark.Extender {
307 return &linkify{
308 options: opts,
309 }
310}
311
312func (e *linkify) Extend(m goldmark.Markdown) {
313 m.Parser().AddOptions(
314 parser.WithInlineParsers(
315 util.Prioritized(NewLinkifyParser(e.options...), 999),
316 ),
317 )
318}
diff --git a/vendor/github.com/yuin/goldmark/extension/strikethrough.go b/vendor/github.com/yuin/goldmark/extension/strikethrough.go
new file mode 100644
index 0000000..1b629ad
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/strikethrough.go
@@ -0,0 +1,116 @@
1package extension
2
3import (
4 "github.com/yuin/goldmark"
5 gast "github.com/yuin/goldmark/ast"
6 "github.com/yuin/goldmark/extension/ast"
7 "github.com/yuin/goldmark/parser"
8 "github.com/yuin/goldmark/renderer"
9 "github.com/yuin/goldmark/renderer/html"
10 "github.com/yuin/goldmark/text"
11 "github.com/yuin/goldmark/util"
12)
13
14type strikethroughDelimiterProcessor struct {
15}
16
17func (p *strikethroughDelimiterProcessor) IsDelimiter(b byte) bool {
18 return b == '~'
19}
20
21func (p *strikethroughDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool {
22 return opener.Char == closer.Char
23}
24
25func (p *strikethroughDelimiterProcessor) OnMatch(consumes int) gast.Node {
26 return ast.NewStrikethrough()
27}
28
29var defaultStrikethroughDelimiterProcessor = &strikethroughDelimiterProcessor{}
30
31type strikethroughParser struct {
32}
33
34var defaultStrikethroughParser = &strikethroughParser{}
35
36// NewStrikethroughParser return a new InlineParser that parses
37// strikethrough expressions.
38func NewStrikethroughParser() parser.InlineParser {
39 return defaultStrikethroughParser
40}
41
42func (s *strikethroughParser) Trigger() []byte {
43 return []byte{'~'}
44}
45
46func (s *strikethroughParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
47 before := block.PrecendingCharacter()
48 line, segment := block.PeekLine()
49 node := parser.ScanDelimiter(line, before, 2, defaultStrikethroughDelimiterProcessor)
50 if node == nil {
51 return nil
52 }
53 node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
54 block.Advance(node.OriginalLength)
55 pc.PushDelimiter(node)
56 return node
57}
58
59func (s *strikethroughParser) CloseBlock(parent gast.Node, pc parser.Context) {
60 // nothing to do
61}
62
63// StrikethroughHTMLRenderer is a renderer.NodeRenderer implementation that
64// renders Strikethrough nodes.
65type StrikethroughHTMLRenderer struct {
66 html.Config
67}
68
69// NewStrikethroughHTMLRenderer returns a new StrikethroughHTMLRenderer.
70func NewStrikethroughHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
71 r := &StrikethroughHTMLRenderer{
72 Config: html.NewConfig(),
73 }
74 for _, opt := range opts {
75 opt.SetHTMLOption(&r.Config)
76 }
77 return r
78}
79
80// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
81func (r *StrikethroughHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
82 reg.Register(ast.KindStrikethrough, r.renderStrikethrough)
83}
84
85// StrikethroughAttributeFilter defines attribute names which dd elements can have.
86var StrikethroughAttributeFilter = html.GlobalAttributeFilter
87
88func (r *StrikethroughHTMLRenderer) renderStrikethrough(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
89 if entering {
90 if n.Attributes() != nil {
91 _, _ = w.WriteString("<del")
92 html.RenderAttributes(w, n, StrikethroughAttributeFilter)
93 _ = w.WriteByte('>')
94 } else {
95 _, _ = w.WriteString("<del>")
96 }
97 } else {
98 _, _ = w.WriteString("</del>")
99 }
100 return gast.WalkContinue, nil
101}
102
103type strikethrough struct {
104}
105
106// Strikethrough is an extension that allow you to use strikethrough expression like '~~text~~' .
107var Strikethrough = &strikethrough{}
108
109func (e *strikethrough) Extend(m goldmark.Markdown) {
110 m.Parser().AddOptions(parser.WithInlineParsers(
111 util.Prioritized(NewStrikethroughParser(), 500),
112 ))
113 m.Renderer().AddOptions(renderer.WithNodeRenderers(
114 util.Prioritized(NewStrikethroughHTMLRenderer(), 500),
115 ))
116}
diff --git a/vendor/github.com/yuin/goldmark/extension/table.go b/vendor/github.com/yuin/goldmark/extension/table.go
new file mode 100644
index 0000000..48d0d68
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/table.go
@@ -0,0 +1,556 @@
1package extension
2
3import (
4 "bytes"
5 "fmt"
6 "regexp"
7
8 "github.com/yuin/goldmark"
9 gast "github.com/yuin/goldmark/ast"
10 "github.com/yuin/goldmark/extension/ast"
11 "github.com/yuin/goldmark/parser"
12 "github.com/yuin/goldmark/renderer"
13 "github.com/yuin/goldmark/renderer/html"
14 "github.com/yuin/goldmark/text"
15 "github.com/yuin/goldmark/util"
16)
17
18var escapedPipeCellListKey = parser.NewContextKey()
19
20type escapedPipeCell struct {
21 Cell *ast.TableCell
22 Pos []int
23 Transformed bool
24}
25
26// TableCellAlignMethod indicates how are table cells aligned in HTML format.indicates how are table cells aligned in HTML format.
27type TableCellAlignMethod int
28
29const (
30 // TableCellAlignDefault renders alignments by default method.
31 // With XHTML, alignments are rendered as an align attribute.
32 // With HTML5, alignments are rendered as a style attribute.
33 TableCellAlignDefault TableCellAlignMethod = iota
34
35 // TableCellAlignAttribute renders alignments as an align attribute.
36 TableCellAlignAttribute
37
38 // TableCellAlignStyle renders alignments as a style attribute.
39 TableCellAlignStyle
40
41 // TableCellAlignNone does not care about alignments.
42 // If you using classes or other styles, you can add these attributes
43 // in an ASTTransformer.
44 TableCellAlignNone
45)
46
47// TableConfig struct holds options for the extension.
48type TableConfig struct {
49 html.Config
50
51 // TableCellAlignMethod indicates how are table celss aligned.
52 TableCellAlignMethod TableCellAlignMethod
53}
54
55// TableOption interface is a functional option interface for the extension.
56type TableOption interface {
57 renderer.Option
58 // SetTableOption sets given option to the extension.
59 SetTableOption(*TableConfig)
60}
61
62// NewTableConfig returns a new Config with defaults.
63func NewTableConfig() TableConfig {
64 return TableConfig{
65 Config: html.NewConfig(),
66 TableCellAlignMethod: TableCellAlignDefault,
67 }
68}
69
70// SetOption implements renderer.SetOptioner.
71func (c *TableConfig) SetOption(name renderer.OptionName, value interface{}) {
72 switch name {
73 case optTableCellAlignMethod:
74 c.TableCellAlignMethod = value.(TableCellAlignMethod)
75 default:
76 c.Config.SetOption(name, value)
77 }
78}
79
80type withTableHTMLOptions struct {
81 value []html.Option
82}
83
84func (o *withTableHTMLOptions) SetConfig(c *renderer.Config) {
85 if o.value != nil {
86 for _, v := range o.value {
87 v.(renderer.Option).SetConfig(c)
88 }
89 }
90}
91
92func (o *withTableHTMLOptions) SetTableOption(c *TableConfig) {
93 if o.value != nil {
94 for _, v := range o.value {
95 v.SetHTMLOption(&c.Config)
96 }
97 }
98}
99
100// WithTableHTMLOptions is functional option that wraps goldmark HTMLRenderer options.
101func WithTableHTMLOptions(opts ...html.Option) TableOption {
102 return &withTableHTMLOptions{opts}
103}
104
105const optTableCellAlignMethod renderer.OptionName = "TableTableCellAlignMethod"
106
107type withTableCellAlignMethod struct {
108 value TableCellAlignMethod
109}
110
111func (o *withTableCellAlignMethod) SetConfig(c *renderer.Config) {
112 c.Options[optTableCellAlignMethod] = o.value
113}
114
115func (o *withTableCellAlignMethod) SetTableOption(c *TableConfig) {
116 c.TableCellAlignMethod = o.value
117}
118
119// WithTableCellAlignMethod is a functional option that indicates how are table cells aligned in HTML format.
120func WithTableCellAlignMethod(a TableCellAlignMethod) TableOption {
121 return &withTableCellAlignMethod{a}
122}
123
124func isTableDelim(bs []byte) bool {
125 if w, _ := util.IndentWidth(bs, 0); w > 3 {
126 return false
127 }
128 for _, b := range bs {
129 if !(util.IsSpace(b) || b == '-' || b == '|' || b == ':') {
130 return false
131 }
132 }
133 return true
134}
135
136var tableDelimLeft = regexp.MustCompile(`^\s*\:\-+\s*$`)
137var tableDelimRight = regexp.MustCompile(`^\s*\-+\:\s*$`)
138var tableDelimCenter = regexp.MustCompile(`^\s*\:\-+\:\s*$`)
139var tableDelimNone = regexp.MustCompile(`^\s*\-+\s*$`)
140
141type tableParagraphTransformer struct {
142}
143
144var defaultTableParagraphTransformer = &tableParagraphTransformer{}
145
146// NewTableParagraphTransformer returns a new ParagraphTransformer
147// that can transform paragraphs into tables.
148func NewTableParagraphTransformer() parser.ParagraphTransformer {
149 return defaultTableParagraphTransformer
150}
151
152func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.Reader, pc parser.Context) {
153 lines := node.Lines()
154 if lines.Len() < 2 {
155 return
156 }
157 for i := 1; i < lines.Len(); i++ {
158 alignments := b.parseDelimiter(lines.At(i), reader)
159 if alignments == nil {
160 continue
161 }
162 header := b.parseRow(lines.At(i-1), alignments, true, reader, pc)
163 if header == nil || len(alignments) != header.ChildCount() {
164 return
165 }
166 table := ast.NewTable()
167 table.Alignments = alignments
168 table.AppendChild(table, ast.NewTableHeader(header))
169 for j := i + 1; j < lines.Len(); j++ {
170 table.AppendChild(table, b.parseRow(lines.At(j), alignments, false, reader, pc))
171 }
172 node.Lines().SetSliced(0, i-1)
173 node.Parent().InsertAfter(node.Parent(), node, table)
174 if node.Lines().Len() == 0 {
175 node.Parent().RemoveChild(node.Parent(), node)
176 } else {
177 last := node.Lines().At(i - 2)
178 last.Stop = last.Stop - 1 // trim last newline(\n)
179 node.Lines().Set(i-2, last)
180 }
181 }
182}
183
184func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []ast.Alignment, isHeader bool, reader text.Reader, pc parser.Context) *ast.TableRow {
185 source := reader.Source()
186 line := segment.Value(source)
187 pos := 0
188 pos += util.TrimLeftSpaceLength(line)
189 limit := len(line)
190 limit -= util.TrimRightSpaceLength(line)
191 row := ast.NewTableRow(alignments)
192 if len(line) > 0 && line[pos] == '|' {
193 pos++
194 }
195 if len(line) > 0 && line[limit-1] == '|' {
196 limit--
197 }
198 i := 0
199 for ; pos < limit; i++ {
200 alignment := ast.AlignNone
201 if i >= len(alignments) {
202 if !isHeader {
203 return row
204 }
205 } else {
206 alignment = alignments[i]
207 }
208
209 var escapedCell *escapedPipeCell
210 node := ast.NewTableCell()
211 node.Alignment = alignment
212 hasBacktick := false
213 closure := pos
214 for ; closure < limit; closure++ {
215 if line[closure] == '`' {
216 hasBacktick = true
217 }
218 if line[closure] == '|' {
219 if closure == 0 || line[closure-1] != '\\' {
220 break
221 } else if hasBacktick {
222 if escapedCell == nil {
223 escapedCell = &escapedPipeCell{node, []int{}, false}
224 escapedList := pc.ComputeIfAbsent(escapedPipeCellListKey,
225 func() interface{} {
226 return []*escapedPipeCell{}
227 }).([]*escapedPipeCell)
228 escapedList = append(escapedList, escapedCell)
229 pc.Set(escapedPipeCellListKey, escapedList)
230 }
231 escapedCell.Pos = append(escapedCell.Pos, segment.Start+closure-1)
232 }
233 }
234 }
235 seg := text.NewSegment(segment.Start+pos, segment.Start+closure)
236 seg = seg.TrimLeftSpace(source)
237 seg = seg.TrimRightSpace(source)
238 node.Lines().Append(seg)
239 row.AppendChild(row, node)
240 pos = closure + 1
241 }
242 for ; i < len(alignments); i++ {
243 row.AppendChild(row, ast.NewTableCell())
244 }
245 return row
246}
247
248func (b *tableParagraphTransformer) parseDelimiter(segment text.Segment, reader text.Reader) []ast.Alignment {
249
250 line := segment.Value(reader.Source())
251 if !isTableDelim(line) {
252 return nil
253 }
254 cols := bytes.Split(line, []byte{'|'})
255 if util.IsBlank(cols[0]) {
256 cols = cols[1:]
257 }
258 if len(cols) > 0 && util.IsBlank(cols[len(cols)-1]) {
259 cols = cols[:len(cols)-1]
260 }
261
262 var alignments []ast.Alignment
263 for _, col := range cols {
264 if tableDelimLeft.Match(col) {
265 alignments = append(alignments, ast.AlignLeft)
266 } else if tableDelimRight.Match(col) {
267 alignments = append(alignments, ast.AlignRight)
268 } else if tableDelimCenter.Match(col) {
269 alignments = append(alignments, ast.AlignCenter)
270 } else if tableDelimNone.Match(col) {
271 alignments = append(alignments, ast.AlignNone)
272 } else {
273 return nil
274 }
275 }
276 return alignments
277}
278
279type tableASTTransformer struct {
280}
281
282var defaultTableASTTransformer = &tableASTTransformer{}
283
284// NewTableASTTransformer returns a parser.ASTTransformer for tables.
285func NewTableASTTransformer() parser.ASTTransformer {
286 return defaultTableASTTransformer
287}
288
289func (a *tableASTTransformer) Transform(node *gast.Document, reader text.Reader, pc parser.Context) {
290 lst := pc.Get(escapedPipeCellListKey)
291 if lst == nil {
292 return
293 }
294 pc.Set(escapedPipeCellListKey, nil)
295 for _, v := range lst.([]*escapedPipeCell) {
296 if v.Transformed {
297 continue
298 }
299 _ = gast.Walk(v.Cell, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
300 if !entering || n.Kind() != gast.KindCodeSpan {
301 return gast.WalkContinue, nil
302 }
303
304 for c := n.FirstChild(); c != nil; {
305 next := c.NextSibling()
306 if c.Kind() != gast.KindText {
307 c = next
308 continue
309 }
310 parent := c.Parent()
311 ts := &c.(*gast.Text).Segment
312 n := c
313 for _, v := range lst.([]*escapedPipeCell) {
314 for _, pos := range v.Pos {
315 if ts.Start <= pos && pos < ts.Stop {
316 segment := n.(*gast.Text).Segment
317 n1 := gast.NewRawTextSegment(segment.WithStop(pos))
318 n2 := gast.NewRawTextSegment(segment.WithStart(pos + 1))
319 parent.InsertAfter(parent, n, n1)
320 parent.InsertAfter(parent, n1, n2)
321 parent.RemoveChild(parent, n)
322 n = n2
323 v.Transformed = true
324 }
325 }
326 }
327 c = next
328 }
329 return gast.WalkContinue, nil
330 })
331 }
332}
333
334// TableHTMLRenderer is a renderer.NodeRenderer implementation that
335// renders Table nodes.
336type TableHTMLRenderer struct {
337 TableConfig
338}
339
340// NewTableHTMLRenderer returns a new TableHTMLRenderer.
341func NewTableHTMLRenderer(opts ...TableOption) renderer.NodeRenderer {
342 r := &TableHTMLRenderer{
343 TableConfig: NewTableConfig(),
344 }
345 for _, opt := range opts {
346 opt.SetTableOption(&r.TableConfig)
347 }
348 return r
349}
350
351// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
352func (r *TableHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
353 reg.Register(ast.KindTable, r.renderTable)
354 reg.Register(ast.KindTableHeader, r.renderTableHeader)
355 reg.Register(ast.KindTableRow, r.renderTableRow)
356 reg.Register(ast.KindTableCell, r.renderTableCell)
357}
358
359// TableAttributeFilter defines attribute names which table elements can have.
360var TableAttributeFilter = html.GlobalAttributeFilter.Extend(
361 []byte("align"), // [Deprecated]
362 []byte("bgcolor"), // [Deprecated]
363 []byte("border"), // [Deprecated]
364 []byte("cellpadding"), // [Deprecated]
365 []byte("cellspacing"), // [Deprecated]
366 []byte("frame"), // [Deprecated]
367 []byte("rules"), // [Deprecated]
368 []byte("summary"), // [Deprecated]
369 []byte("width"), // [Deprecated]
370)
371
372func (r *TableHTMLRenderer) renderTable(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
373 if entering {
374 _, _ = w.WriteString("<table")
375 if n.Attributes() != nil {
376 html.RenderAttributes(w, n, TableAttributeFilter)
377 }
378 _, _ = w.WriteString(">\n")
379 } else {
380 _, _ = w.WriteString("</table>\n")
381 }
382 return gast.WalkContinue, nil
383}
384
385// TableHeaderAttributeFilter defines attribute names which <thead> elements can have.
386var TableHeaderAttributeFilter = html.GlobalAttributeFilter.Extend(
387 []byte("align"), // [Deprecated since HTML4] [Obsolete since HTML5]
388 []byte("bgcolor"), // [Not Standardized]
389 []byte("char"), // [Deprecated since HTML4] [Obsolete since HTML5]
390 []byte("charoff"), // [Deprecated since HTML4] [Obsolete since HTML5]
391 []byte("valign"), // [Deprecated since HTML4] [Obsolete since HTML5]
392)
393
394func (r *TableHTMLRenderer) renderTableHeader(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
395 if entering {
396 _, _ = w.WriteString("<thead")
397 if n.Attributes() != nil {
398 html.RenderAttributes(w, n, TableHeaderAttributeFilter)
399 }
400 _, _ = w.WriteString(">\n")
401 _, _ = w.WriteString("<tr>\n") // Header <tr> has no separate handle
402 } else {
403 _, _ = w.WriteString("</tr>\n")
404 _, _ = w.WriteString("</thead>\n")
405 if n.NextSibling() != nil {
406 _, _ = w.WriteString("<tbody>\n")
407 }
408 }
409 return gast.WalkContinue, nil
410}
411
412// TableRowAttributeFilter defines attribute names which <tr> elements can have.
413var TableRowAttributeFilter = html.GlobalAttributeFilter.Extend(
414 []byte("align"), // [Obsolete since HTML5]
415 []byte("bgcolor"), // [Obsolete since HTML5]
416 []byte("char"), // [Obsolete since HTML5]
417 []byte("charoff"), // [Obsolete since HTML5]
418 []byte("valign"), // [Obsolete since HTML5]
419)
420
421func (r *TableHTMLRenderer) renderTableRow(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
422 if entering {
423 _, _ = w.WriteString("<tr")
424 if n.Attributes() != nil {
425 html.RenderAttributes(w, n, TableRowAttributeFilter)
426 }
427 _, _ = w.WriteString(">\n")
428 } else {
429 _, _ = w.WriteString("</tr>\n")
430 if n.Parent().LastChild() == n {
431 _, _ = w.WriteString("</tbody>\n")
432 }
433 }
434 return gast.WalkContinue, nil
435}
436
437// TableThCellAttributeFilter defines attribute names which table <th> cells can have.
438var TableThCellAttributeFilter = html.GlobalAttributeFilter.Extend(
439 []byte("abbr"), // [OK] Contains a short abbreviated description of the cell's content [NOT OK in <td>]
440
441 []byte("align"), // [Obsolete since HTML5]
442 []byte("axis"), // [Obsolete since HTML5]
443 []byte("bgcolor"), // [Not Standardized]
444 []byte("char"), // [Obsolete since HTML5]
445 []byte("charoff"), // [Obsolete since HTML5]
446
447 []byte("colspan"), // [OK] Number of columns that the cell is to span
448 []byte("headers"), // [OK] This attribute contains a list of space-separated strings, each corresponding to the id attribute of the <th> elements that apply to this element
449
450 []byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
451
452 []byte("rowspan"), // [OK] Number of rows that the cell is to span
453 []byte("scope"), // [OK] This enumerated attribute defines the cells that the header (defined in the <th>) element relates to [NOT OK in <td>]
454
455 []byte("valign"), // [Obsolete since HTML5]
456 []byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
457)
458
459// TableTdCellAttributeFilter defines attribute names which table <td> cells can have.
460var TableTdCellAttributeFilter = html.GlobalAttributeFilter.Extend(
461 []byte("abbr"), // [Obsolete since HTML5] [OK in <th>]
462 []byte("align"), // [Obsolete since HTML5]
463 []byte("axis"), // [Obsolete since HTML5]
464 []byte("bgcolor"), // [Not Standardized]
465 []byte("char"), // [Obsolete since HTML5]
466 []byte("charoff"), // [Obsolete since HTML5]
467
468 []byte("colspan"), // [OK] Number of columns that the cell is to span
469 []byte("headers"), // [OK] This attribute contains a list of space-separated strings, each corresponding to the id attribute of the <th> elements that apply to this element
470
471 []byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
472
473 []byte("rowspan"), // [OK] Number of rows that the cell is to span
474
475 []byte("scope"), // [Obsolete since HTML5] [OK in <th>]
476 []byte("valign"), // [Obsolete since HTML5]
477 []byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
478)
479
480func (r *TableHTMLRenderer) renderTableCell(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
481 n := node.(*ast.TableCell)
482 tag := "td"
483 if n.Parent().Kind() == ast.KindTableHeader {
484 tag = "th"
485 }
486 if entering {
487 fmt.Fprintf(w, "<%s", tag)
488 if n.Alignment != ast.AlignNone {
489 amethod := r.TableConfig.TableCellAlignMethod
490 if amethod == TableCellAlignDefault {
491 if r.Config.XHTML {
492 amethod = TableCellAlignAttribute
493 } else {
494 amethod = TableCellAlignStyle
495 }
496 }
497 switch amethod {
498 case TableCellAlignAttribute:
499 if _, ok := n.AttributeString("align"); !ok { // Skip align render if overridden
500 fmt.Fprintf(w, ` align="%s"`, n.Alignment.String())
501 }
502 case TableCellAlignStyle:
503 v, ok := n.AttributeString("style")
504 var cob util.CopyOnWriteBuffer
505 if ok {
506 cob = util.NewCopyOnWriteBuffer(v.([]byte))
507 cob.AppendByte(';')
508 }
509 style := fmt.Sprintf("text-align:%s", n.Alignment.String())
510 cob.AppendString(style)
511 n.SetAttributeString("style", cob.Bytes())
512 }
513 }
514 if n.Attributes() != nil {
515 if tag == "td" {
516 html.RenderAttributes(w, n, TableTdCellAttributeFilter) // <td>
517 } else {
518 html.RenderAttributes(w, n, TableThCellAttributeFilter) // <th>
519 }
520 }
521 _ = w.WriteByte('>')
522 } else {
523 fmt.Fprintf(w, "</%s>\n", tag)
524 }
525 return gast.WalkContinue, nil
526}
527
528type table struct {
529 options []TableOption
530}
531
532// Table is an extension that allow you to use GFM tables .
533var Table = &table{
534 options: []TableOption{},
535}
536
537// NewTable returns a new extension with given options.
538func NewTable(opts ...TableOption) goldmark.Extender {
539 return &table{
540 options: opts,
541 }
542}
543
544func (e *table) Extend(m goldmark.Markdown) {
545 m.Parser().AddOptions(
546 parser.WithParagraphTransformers(
547 util.Prioritized(NewTableParagraphTransformer(), 200),
548 ),
549 parser.WithASTTransformers(
550 util.Prioritized(defaultTableASTTransformer, 0),
551 ),
552 )
553 m.Renderer().AddOptions(renderer.WithNodeRenderers(
554 util.Prioritized(NewTableHTMLRenderer(e.options...), 500),
555 ))
556}
diff --git a/vendor/github.com/yuin/goldmark/extension/tasklist.go b/vendor/github.com/yuin/goldmark/extension/tasklist.go
new file mode 100644
index 0000000..1f3e52c
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/tasklist.go
@@ -0,0 +1,115 @@
1package extension
2
3import (
4 "github.com/yuin/goldmark"
5 gast "github.com/yuin/goldmark/ast"
6 "github.com/yuin/goldmark/extension/ast"
7 "github.com/yuin/goldmark/parser"
8 "github.com/yuin/goldmark/renderer"
9 "github.com/yuin/goldmark/renderer/html"
10 "github.com/yuin/goldmark/text"
11 "github.com/yuin/goldmark/util"
12 "regexp"
13)
14
15var taskListRegexp = regexp.MustCompile(`^\[([\sxX])\]\s*`)
16
17type taskCheckBoxParser struct {
18}
19
20var defaultTaskCheckBoxParser = &taskCheckBoxParser{}
21
22// NewTaskCheckBoxParser returns a new InlineParser that can parse
23// checkboxes in list items.
24// This parser must take precedence over the parser.LinkParser.
25func NewTaskCheckBoxParser() parser.InlineParser {
26 return defaultTaskCheckBoxParser
27}
28
29func (s *taskCheckBoxParser) Trigger() []byte {
30 return []byte{'['}
31}
32
33func (s *taskCheckBoxParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
34 // Given AST structure must be like
35 // - List
36 // - ListItem : parent.Parent
37 // - TextBlock : parent
38 // (current line)
39 if parent.Parent() == nil || parent.Parent().FirstChild() != parent {
40 return nil
41 }
42
43 if _, ok := parent.Parent().(*gast.ListItem); !ok {
44 return nil
45 }
46 line, _ := block.PeekLine()
47 m := taskListRegexp.FindSubmatchIndex(line)
48 if m == nil {
49 return nil
50 }
51 value := line[m[2]:m[3]][0]
52 block.Advance(m[1])
53 checked := value == 'x' || value == 'X'
54 return ast.NewTaskCheckBox(checked)
55}
56
57func (s *taskCheckBoxParser) CloseBlock(parent gast.Node, pc parser.Context) {
58 // nothing to do
59}
60
61// TaskCheckBoxHTMLRenderer is a renderer.NodeRenderer implementation that
62// renders checkboxes in list items.
63type TaskCheckBoxHTMLRenderer struct {
64 html.Config
65}
66
67// NewTaskCheckBoxHTMLRenderer returns a new TaskCheckBoxHTMLRenderer.
68func NewTaskCheckBoxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
69 r := &TaskCheckBoxHTMLRenderer{
70 Config: html.NewConfig(),
71 }
72 for _, opt := range opts {
73 opt.SetHTMLOption(&r.Config)
74 }
75 return r
76}
77
78// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
79func (r *TaskCheckBoxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
80 reg.Register(ast.KindTaskCheckBox, r.renderTaskCheckBox)
81}
82
83func (r *TaskCheckBoxHTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
84 if !entering {
85 return gast.WalkContinue, nil
86 }
87 n := node.(*ast.TaskCheckBox)
88
89 if n.IsChecked {
90 w.WriteString(`<input checked="" disabled="" type="checkbox"`)
91 } else {
92 w.WriteString(`<input disabled="" type="checkbox"`)
93 }
94 if r.XHTML {
95 w.WriteString(" /> ")
96 } else {
97 w.WriteString("> ")
98 }
99 return gast.WalkContinue, nil
100}
101
102type taskList struct {
103}
104
105// TaskList is an extension that allow you to use GFM task lists.
106var TaskList = &taskList{}
107
108func (e *taskList) Extend(m goldmark.Markdown) {
109 m.Parser().AddOptions(parser.WithInlineParsers(
110 util.Prioritized(NewTaskCheckBoxParser(), 0),
111 ))
112 m.Renderer().AddOptions(renderer.WithNodeRenderers(
113 util.Prioritized(NewTaskCheckBoxHTMLRenderer(), 500),
114 ))
115}
diff --git a/vendor/github.com/yuin/goldmark/extension/typographer.go b/vendor/github.com/yuin/goldmark/extension/typographer.go
new file mode 100644
index 0000000..f56c06f
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/typographer.go
@@ -0,0 +1,339 @@
1package extension
2
3import (
4 "unicode"
5
6 "github.com/yuin/goldmark"
7 gast "github.com/yuin/goldmark/ast"
8 "github.com/yuin/goldmark/parser"
9 "github.com/yuin/goldmark/text"
10 "github.com/yuin/goldmark/util"
11)
12
13var uncloseCounterKey = parser.NewContextKey()
14
15type unclosedCounter struct {
16 Single int
17 Double int
18}
19
20func (u *unclosedCounter) Reset() {
21 u.Single = 0
22 u.Double = 0
23}
24
25func getUnclosedCounter(pc parser.Context) *unclosedCounter {
26 v := pc.Get(uncloseCounterKey)
27 if v == nil {
28 v = &unclosedCounter{}
29 pc.Set(uncloseCounterKey, v)
30 }
31 return v.(*unclosedCounter)
32}
33
34// TypographicPunctuation is a key of the punctuations that can be replaced with
35// typographic entities.
36type TypographicPunctuation int
37
38const (
39 // LeftSingleQuote is '
40 LeftSingleQuote TypographicPunctuation = iota + 1
41 // RightSingleQuote is '
42 RightSingleQuote
43 // LeftDoubleQuote is "
44 LeftDoubleQuote
45 // RightDoubleQuote is "
46 RightDoubleQuote
47 // EnDash is --
48 EnDash
49 // EmDash is ---
50 EmDash
51 // Ellipsis is ...
52 Ellipsis
53 // LeftAngleQuote is <<
54 LeftAngleQuote
55 // RightAngleQuote is >>
56 RightAngleQuote
57 // Apostrophe is '
58 Apostrophe
59
60 typographicPunctuationMax
61)
62
63// An TypographerConfig struct is a data structure that holds configuration of the
64// Typographer extension.
65type TypographerConfig struct {
66 Substitutions [][]byte
67}
68
69func newDefaultSubstitutions() [][]byte {
70 replacements := make([][]byte, typographicPunctuationMax)
71 replacements[LeftSingleQuote] = []byte("&lsquo;")
72 replacements[RightSingleQuote] = []byte("&rsquo;")
73 replacements[LeftDoubleQuote] = []byte("&ldquo;")
74 replacements[RightDoubleQuote] = []byte("&rdquo;")
75 replacements[EnDash] = []byte("&ndash;")
76 replacements[EmDash] = []byte("&mdash;")
77 replacements[Ellipsis] = []byte("&hellip;")
78 replacements[LeftAngleQuote] = []byte("&laquo;")
79 replacements[RightAngleQuote] = []byte("&raquo;")
80 replacements[Apostrophe] = []byte("&rsquo;")
81
82 return replacements
83}
84
85// SetOption implements SetOptioner.
86func (b *TypographerConfig) SetOption(name parser.OptionName, value interface{}) {
87 switch name {
88 case optTypographicSubstitutions:
89 b.Substitutions = value.([][]byte)
90 }
91}
92
93// A TypographerOption interface sets options for the TypographerParser.
94type TypographerOption interface {
95 parser.Option
96 SetTypographerOption(*TypographerConfig)
97}
98
99const optTypographicSubstitutions parser.OptionName = "TypographicSubstitutions"
100
101// TypographicSubstitutions is a list of the substitutions for the Typographer extension.
102type TypographicSubstitutions map[TypographicPunctuation][]byte
103
104type withTypographicSubstitutions struct {
105 value [][]byte
106}
107
108func (o *withTypographicSubstitutions) SetParserOption(c *parser.Config) {
109 c.Options[optTypographicSubstitutions] = o.value
110}
111
112func (o *withTypographicSubstitutions) SetTypographerOption(p *TypographerConfig) {
113 p.Substitutions = o.value
114}
115
116// WithTypographicSubstitutions is a functional otpion that specify replacement text
117// for punctuations.
118func WithTypographicSubstitutions(values map[TypographicPunctuation][]byte) TypographerOption {
119 replacements := newDefaultSubstitutions()
120 for k, v := range values {
121 replacements[k] = v
122 }
123
124 return &withTypographicSubstitutions{replacements}
125}
126
127type typographerDelimiterProcessor struct {
128}
129
130func (p *typographerDelimiterProcessor) IsDelimiter(b byte) bool {
131 return b == '\'' || b == '"'
132}
133
134func (p *typographerDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool {
135 return opener.Char == closer.Char
136}
137
138func (p *typographerDelimiterProcessor) OnMatch(consumes int) gast.Node {
139 return nil
140}
141
142var defaultTypographerDelimiterProcessor = &typographerDelimiterProcessor{}
143
144type typographerParser struct {
145 TypographerConfig
146}
147
148// NewTypographerParser return a new InlineParser that parses
149// typographer expressions.
150func NewTypographerParser(opts ...TypographerOption) parser.InlineParser {
151 p := &typographerParser{
152 TypographerConfig: TypographerConfig{
153 Substitutions: newDefaultSubstitutions(),
154 },
155 }
156 for _, o := range opts {
157 o.SetTypographerOption(&p.TypographerConfig)
158 }
159 return p
160}
161
162func (s *typographerParser) Trigger() []byte {
163 return []byte{'\'', '"', '-', '.', ',', '<', '>', '*', '['}
164}
165
166func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
167 line, _ := block.PeekLine()
168 c := line[0]
169 if len(line) > 2 {
170 if c == '-' {
171 if s.Substitutions[EmDash] != nil && line[1] == '-' && line[2] == '-' { // ---
172 node := gast.NewString(s.Substitutions[EmDash])
173 node.SetCode(true)
174 block.Advance(3)
175 return node
176 }
177 } else if c == '.' {
178 if s.Substitutions[Ellipsis] != nil && line[1] == '.' && line[2] == '.' { // ...
179 node := gast.NewString(s.Substitutions[Ellipsis])
180 node.SetCode(true)
181 block.Advance(3)
182 return node
183 }
184 return nil
185 }
186 }
187 if len(line) > 1 {
188 if c == '<' {
189 if s.Substitutions[LeftAngleQuote] != nil && line[1] == '<' { // <<
190 node := gast.NewString(s.Substitutions[LeftAngleQuote])
191 node.SetCode(true)
192 block.Advance(2)
193 return node
194 }
195 return nil
196 } else if c == '>' {
197 if s.Substitutions[RightAngleQuote] != nil && line[1] == '>' { // >>
198 node := gast.NewString(s.Substitutions[RightAngleQuote])
199 node.SetCode(true)
200 block.Advance(2)
201 return node
202 }
203 return nil
204 } else if s.Substitutions[EnDash] != nil && c == '-' && line[1] == '-' { // --
205 node := gast.NewString(s.Substitutions[EnDash])
206 node.SetCode(true)
207 block.Advance(2)
208 return node
209 }
210 }
211 if c == '\'' || c == '"' {
212 before := block.PrecendingCharacter()
213 d := parser.ScanDelimiter(line, before, 1, defaultTypographerDelimiterProcessor)
214 if d == nil {
215 return nil
216 }
217 counter := getUnclosedCounter(pc)
218 if c == '\'' {
219 if s.Substitutions[Apostrophe] != nil {
220 // Handle decade abbrevations such as '90s
221 if d.CanOpen && !d.CanClose && len(line) > 3 && util.IsNumeric(line[1]) && util.IsNumeric(line[2]) && line[3] == 's' {
222 after := rune(' ')
223 if len(line) > 4 {
224 after = util.ToRune(line, 4)
225 }
226 if len(line) == 3 || util.IsSpaceRune(after) || util.IsPunctRune(after) {
227 node := gast.NewString(s.Substitutions[Apostrophe])
228 node.SetCode(true)
229 block.Advance(1)
230 return node
231 }
232 }
233 // special cases: 'twas, 'em, 'net
234 if len(line) > 1 && (unicode.IsPunct(before) || unicode.IsSpace(before)) && (line[1] == 't' || line[1] == 'e' || line[1] == 'n' || line[1] == 'l') {
235 node := gast.NewString(s.Substitutions[Apostrophe])
236 node.SetCode(true)
237 block.Advance(1)
238 return node
239 }
240 // Convert normal apostrophes. This is probably more flexible than necessary but
241 // converts any apostrophe in between two alphanumerics.
242 if len(line) > 1 && (unicode.IsDigit(before) || unicode.IsLetter(before)) && (unicode.IsLetter(util.ToRune(line, 1))) {
243 node := gast.NewString(s.Substitutions[Apostrophe])
244 node.SetCode(true)
245 block.Advance(1)
246 return node
247 }
248 }
249 if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose {
250 nt := LeftSingleQuote
251 // special cases: Alice's, I'm, Don't, You'd
252 if len(line) > 1 && (line[1] == 's' || line[1] == 'm' || line[1] == 't' || line[1] == 'd') && (len(line) < 3 || util.IsPunct(line[2]) || util.IsSpace(line[2])) {
253 nt = RightSingleQuote
254 }
255 // special cases: I've, I'll, You're
256 if len(line) > 2 && ((line[1] == 'v' && line[2] == 'e') || (line[1] == 'l' && line[2] == 'l') || (line[1] == 'r' && line[2] == 'e')) && (len(line) < 4 || util.IsPunct(line[3]) || util.IsSpace(line[3])) {
257 nt = RightSingleQuote
258 }
259 if nt == LeftSingleQuote {
260 counter.Single++
261 }
262
263 node := gast.NewString(s.Substitutions[nt])
264 node.SetCode(true)
265 block.Advance(1)
266 return node
267 }
268 if s.Substitutions[RightSingleQuote] != nil {
269 // plural possesives and abbreviations: Smiths', doin'
270 if len(line) > 1 && unicode.IsSpace(util.ToRune(line, 0)) || unicode.IsPunct(util.ToRune(line, 0)) && (len(line) > 2 && !unicode.IsDigit(util.ToRune(line, 1))) {
271 node := gast.NewString(s.Substitutions[RightSingleQuote])
272 node.SetCode(true)
273 block.Advance(1)
274 return node
275 }
276 }
277 if s.Substitutions[RightSingleQuote] != nil && counter.Single > 0 {
278 isClose := d.CanClose && !d.CanOpen
279 maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && unicode.IsPunct(util.ToRune(line, 1)) && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
280 if isClose || maybeClose {
281 node := gast.NewString(s.Substitutions[RightSingleQuote])
282 node.SetCode(true)
283 block.Advance(1)
284 counter.Single--
285 return node
286 }
287 }
288 }
289 if c == '"' {
290 if s.Substitutions[LeftDoubleQuote] != nil && d.CanOpen && !d.CanClose {
291 node := gast.NewString(s.Substitutions[LeftDoubleQuote])
292 node.SetCode(true)
293 block.Advance(1)
294 counter.Double++
295 return node
296 }
297 if s.Substitutions[RightDoubleQuote] != nil && counter.Double > 0 {
298 isClose := d.CanClose && !d.CanOpen
299 maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (unicode.IsPunct(util.ToRune(line, 1))) && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
300 if isClose || maybeClose {
301 // special case: "Monitor 21""
302 if len(line) > 1 && line[1] == '"' && unicode.IsDigit(before) {
303 return nil
304 }
305 node := gast.NewString(s.Substitutions[RightDoubleQuote])
306 node.SetCode(true)
307 block.Advance(1)
308 counter.Double--
309 return node
310 }
311 }
312 }
313 }
314 return nil
315}
316
317func (s *typographerParser) CloseBlock(parent gast.Node, pc parser.Context) {
318 getUnclosedCounter(pc).Reset()
319}
320
321type typographer struct {
322 options []TypographerOption
323}
324
325// Typographer is an extension that replaces punctuations with typographic entities.
326var Typographer = &typographer{}
327
328// NewTypographer returns a new Extender that replaces punctuations with typographic entities.
329func NewTypographer(opts ...TypographerOption) goldmark.Extender {
330 return &typographer{
331 options: opts,
332 }
333}
334
335func (e *typographer) Extend(m goldmark.Markdown) {
336 m.Parser().AddOptions(parser.WithInlineParsers(
337 util.Prioritized(NewTypographerParser(e.options...), 9999),
338 ))
339}
diff --git a/vendor/github.com/yuin/goldmark/markdown.go b/vendor/github.com/yuin/goldmark/markdown.go
new file mode 100644
index 0000000..86d12e2
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/markdown.go
@@ -0,0 +1,140 @@
1// Package goldmark implements functions to convert markdown text to a desired format.
2package goldmark
3
4import (
5 "github.com/yuin/goldmark/parser"
6 "github.com/yuin/goldmark/renderer"
7 "github.com/yuin/goldmark/renderer/html"
8 "github.com/yuin/goldmark/text"
9 "github.com/yuin/goldmark/util"
10 "io"
11)
12
13// DefaultParser returns a new Parser that is configured by default values.
14func DefaultParser() parser.Parser {
15 return parser.NewParser(parser.WithBlockParsers(parser.DefaultBlockParsers()...),
16 parser.WithInlineParsers(parser.DefaultInlineParsers()...),
17 parser.WithParagraphTransformers(parser.DefaultParagraphTransformers()...),
18 )
19}
20
21// DefaultRenderer returns a new Renderer that is configured by default values.
22func DefaultRenderer() renderer.Renderer {
23 return renderer.NewRenderer(renderer.WithNodeRenderers(util.Prioritized(html.NewRenderer(), 1000)))
24}
25
26var defaultMarkdown = New()
27
28// Convert interprets a UTF-8 bytes source in Markdown and
29// write rendered contents to a writer w.
30func Convert(source []byte, w io.Writer, opts ...parser.ParseOption) error {
31 return defaultMarkdown.Convert(source, w, opts...)
32}
33
34// A Markdown interface offers functions to convert Markdown text to
35// a desired format.
36type Markdown interface {
37 // Convert interprets a UTF-8 bytes source in Markdown and write rendered
38 // contents to a writer w.
39 Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error
40
41 // Parser returns a Parser that will be used for conversion.
42 Parser() parser.Parser
43
44 // SetParser sets a Parser to this object.
45 SetParser(parser.Parser)
46
47 // Parser returns a Renderer that will be used for conversion.
48 Renderer() renderer.Renderer
49
50 // SetRenderer sets a Renderer to this object.
51 SetRenderer(renderer.Renderer)
52}
53
54// Option is a functional option type for Markdown objects.
55type Option func(*markdown)
56
57// WithExtensions adds extensions.
58func WithExtensions(ext ...Extender) Option {
59 return func(m *markdown) {
60 m.extensions = append(m.extensions, ext...)
61 }
62}
63
64// WithParser allows you to override the default parser.
65func WithParser(p parser.Parser) Option {
66 return func(m *markdown) {
67 m.parser = p
68 }
69}
70
71// WithParserOptions applies options for the parser.
72func WithParserOptions(opts ...parser.Option) Option {
73 return func(m *markdown) {
74 m.parser.AddOptions(opts...)
75 }
76}
77
78// WithRenderer allows you to override the default renderer.
79func WithRenderer(r renderer.Renderer) Option {
80 return func(m *markdown) {
81 m.renderer = r
82 }
83}
84
85// WithRendererOptions applies options for the renderer.
86func WithRendererOptions(opts ...renderer.Option) Option {
87 return func(m *markdown) {
88 m.renderer.AddOptions(opts...)
89 }
90}
91
92type markdown struct {
93 parser parser.Parser
94 renderer renderer.Renderer
95 extensions []Extender
96}
97
98// New returns a new Markdown with given options.
99func New(options ...Option) Markdown {
100 md := &markdown{
101 parser: DefaultParser(),
102 renderer: DefaultRenderer(),
103 extensions: []Extender{},
104 }
105 for _, opt := range options {
106 opt(md)
107 }
108 for _, e := range md.extensions {
109 e.Extend(md)
110 }
111 return md
112}
113
114func (m *markdown) Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error {
115 reader := text.NewReader(source)
116 doc := m.parser.Parse(reader, opts...)
117 return m.renderer.Render(writer, source, doc)
118}
119
120func (m *markdown) Parser() parser.Parser {
121 return m.parser
122}
123
124func (m *markdown) SetParser(v parser.Parser) {
125 m.parser = v
126}
127
128func (m *markdown) Renderer() renderer.Renderer {
129 return m.renderer
130}
131
132func (m *markdown) SetRenderer(v renderer.Renderer) {
133 m.renderer = v
134}
135
136// An Extender interface is used for extending Markdown.
137type Extender interface {
138 // Extend extends the Markdown.
139 Extend(Markdown)
140}
diff --git a/vendor/github.com/yuin/goldmark/parser/attribute.go b/vendor/github.com/yuin/goldmark/parser/attribute.go
new file mode 100644
index 0000000..f86c836
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/attribute.go
@@ -0,0 +1,328 @@
1package parser
2
3import (
4 "bytes"
5 "io"
6 "strconv"
7
8 "github.com/yuin/goldmark/text"
9 "github.com/yuin/goldmark/util"
10)
11
12var attrNameID = []byte("id")
13var attrNameClass = []byte("class")
14
15// An Attribute is an attribute of the markdown elements
16type Attribute struct {
17 Name []byte
18 Value interface{}
19}
20
21// An Attributes is a collection of attributes.
22type Attributes []Attribute
23
24// Find returns a (value, true) if an attribute correspond with given name is found, otherwise (nil, false).
25func (as Attributes) Find(name []byte) (interface{}, bool) {
26 for _, a := range as {
27 if bytes.Equal(a.Name, name) {
28 return a.Value, true
29 }
30 }
31 return nil, false
32}
33
34func (as Attributes) findUpdate(name []byte, cb func(v interface{}) interface{}) bool {
35 for i, a := range as {
36 if bytes.Equal(a.Name, name) {
37 as[i].Value = cb(a.Value)
38 return true
39 }
40 }
41 return false
42}
43
44// ParseAttributes parses attributes into a map.
45// ParseAttributes returns a parsed attributes and true if could parse
46// attributes, otherwise nil and false.
47func ParseAttributes(reader text.Reader) (Attributes, bool) {
48 savedLine, savedPosition := reader.Position()
49 reader.SkipSpaces()
50 if reader.Peek() != '{' {
51 reader.SetPosition(savedLine, savedPosition)
52 return nil, false
53 }
54 reader.Advance(1)
55 attrs := Attributes{}
56 for {
57 if reader.Peek() == '}' {
58 reader.Advance(1)
59 return attrs, true
60 }
61 attr, ok := parseAttribute(reader)
62 if !ok {
63 reader.SetPosition(savedLine, savedPosition)
64 return nil, false
65 }
66 if bytes.Equal(attr.Name, attrNameClass) {
67 if !attrs.findUpdate(attrNameClass, func(v interface{}) interface{} {
68 ret := make([]byte, 0, len(v.([]byte))+1+len(attr.Value.([]byte)))
69 ret = append(ret, v.([]byte)...)
70 return append(append(ret, ' '), attr.Value.([]byte)...)
71 }) {
72 attrs = append(attrs, attr)
73 }
74 } else {
75 attrs = append(attrs, attr)
76 }
77 reader.SkipSpaces()
78 if reader.Peek() == ',' {
79 reader.Advance(1)
80 reader.SkipSpaces()
81 }
82 }
83}
84
85func parseAttribute(reader text.Reader) (Attribute, bool) {
86 reader.SkipSpaces()
87 c := reader.Peek()
88 if c == '#' || c == '.' {
89 reader.Advance(1)
90 line, _ := reader.PeekLine()
91 i := 0
92 // HTML5 allows any kind of characters as id, but XHTML restricts characters for id.
93 // CommonMark is basically defined for XHTML(even though it is legacy).
94 // So we restrict id characters.
95 for ; i < len(line) && !util.IsSpace(line[i]) &&
96 (!util.IsPunct(line[i]) || line[i] == '_' || line[i] == '-' || line[i] == ':' || line[i] == '.'); i++ {
97 }
98 name := attrNameClass
99 if c == '#' {
100 name = attrNameID
101 }
102 reader.Advance(i)
103 return Attribute{Name: name, Value: line[0:i]}, true
104 }
105 line, _ := reader.PeekLine()
106 if len(line) == 0 {
107 return Attribute{}, false
108 }
109 c = line[0]
110 if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
111 c == '_' || c == ':') {
112 return Attribute{}, false
113 }
114 i := 0
115 for ; i < len(line); i++ {
116 c = line[i]
117 if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
118 (c >= '0' && c <= '9') ||
119 c == '_' || c == ':' || c == '.' || c == '-') {
120 break
121 }
122 }
123 name := line[:i]
124 reader.Advance(i)
125 reader.SkipSpaces()
126 c = reader.Peek()
127 if c != '=' {
128 return Attribute{}, false
129 }
130 reader.Advance(1)
131 reader.SkipSpaces()
132 value, ok := parseAttributeValue(reader)
133 if !ok {
134 return Attribute{}, false
135 }
136 if bytes.Equal(name, attrNameClass) {
137 if _, ok = value.([]byte); !ok {
138 return Attribute{}, false
139 }
140 }
141 return Attribute{Name: name, Value: value}, true
142}
143
144func parseAttributeValue(reader text.Reader) (interface{}, bool) {
145 reader.SkipSpaces()
146 c := reader.Peek()
147 var value interface{}
148 ok := false
149 switch c {
150 case text.EOF:
151 return Attribute{}, false
152 case '{':
153 value, ok = ParseAttributes(reader)
154 case '[':
155 value, ok = parseAttributeArray(reader)
156 case '"':
157 value, ok = parseAttributeString(reader)
158 default:
159 if c == '-' || c == '+' || util.IsNumeric(c) {
160 value, ok = parseAttributeNumber(reader)
161 } else {
162 value, ok = parseAttributeOthers(reader)
163 }
164 }
165 if !ok {
166 return nil, false
167 }
168 return value, true
169}
170
171func parseAttributeArray(reader text.Reader) ([]interface{}, bool) {
172 reader.Advance(1) // skip [
173 ret := []interface{}{}
174 for i := 0; ; i++ {
175 c := reader.Peek()
176 comma := false
177 if i != 0 && c == ',' {
178 reader.Advance(1)
179 comma = true
180 }
181 if c == ']' {
182 if !comma {
183 reader.Advance(1)
184 return ret, true
185 }
186 return nil, false
187 }
188 reader.SkipSpaces()
189 value, ok := parseAttributeValue(reader)
190 if !ok {
191 return nil, false
192 }
193 ret = append(ret, value)
194 reader.SkipSpaces()
195 }
196}
197
198func parseAttributeString(reader text.Reader) ([]byte, bool) {
199 reader.Advance(1) // skip "
200 line, _ := reader.PeekLine()
201 i := 0
202 l := len(line)
203 var buf bytes.Buffer
204 for i < l {
205 c := line[i]
206 if c == '\\' && i != l-1 {
207 n := line[i+1]
208 switch n {
209 case '"', '/', '\\':
210 buf.WriteByte(n)
211 i += 2
212 case 'b':
213 buf.WriteString("\b")
214 i += 2
215 case 'f':
216 buf.WriteString("\f")
217 i += 2
218 case 'n':
219 buf.WriteString("\n")
220 i += 2
221 case 'r':
222 buf.WriteString("\r")
223 i += 2
224 case 't':
225 buf.WriteString("\t")
226 i += 2
227 default:
228 buf.WriteByte('\\')
229 i++
230 }
231 continue
232 }
233 if c == '"' {
234 reader.Advance(i + 1)
235 return buf.Bytes(), true
236 }
237 buf.WriteByte(c)
238 i++
239 }
240 return nil, false
241}
242
243func scanAttributeDecimal(reader text.Reader, w io.ByteWriter) {
244 for {
245 c := reader.Peek()
246 if util.IsNumeric(c) {
247 w.WriteByte(c)
248 } else {
249 return
250 }
251 reader.Advance(1)
252 }
253}
254
255func parseAttributeNumber(reader text.Reader) (float64, bool) {
256 sign := 1
257 c := reader.Peek()
258 if c == '-' {
259 sign = -1
260 reader.Advance(1)
261 } else if c == '+' {
262 reader.Advance(1)
263 }
264 var buf bytes.Buffer
265 if !util.IsNumeric(reader.Peek()) {
266 return 0, false
267 }
268 scanAttributeDecimal(reader, &buf)
269 if buf.Len() == 0 {
270 return 0, false
271 }
272 c = reader.Peek()
273 if c == '.' {
274 buf.WriteByte(c)
275 reader.Advance(1)
276 scanAttributeDecimal(reader, &buf)
277 }
278 c = reader.Peek()
279 if c == 'e' || c == 'E' {
280 buf.WriteByte(c)
281 reader.Advance(1)
282 c = reader.Peek()
283 if c == '-' || c == '+' {
284 buf.WriteByte(c)
285 reader.Advance(1)
286 }
287 scanAttributeDecimal(reader, &buf)
288 }
289 f, err := strconv.ParseFloat(buf.String(), 10)
290 if err != nil {
291 return 0, false
292 }
293 return float64(sign) * f, true
294}
295
296var bytesTrue = []byte("true")
297var bytesFalse = []byte("false")
298var bytesNull = []byte("null")
299
300func parseAttributeOthers(reader text.Reader) (interface{}, bool) {
301 line, _ := reader.PeekLine()
302 c := line[0]
303 if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
304 c == '_' || c == ':') {
305 return nil, false
306 }
307 i := 0
308 for ; i < len(line); i++ {
309 c := line[i]
310 if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
311 (c >= '0' && c <= '9') ||
312 c == '_' || c == ':' || c == '.' || c == '-') {
313 break
314 }
315 }
316 value := line[:i]
317 reader.Advance(i)
318 if bytes.Equal(value, bytesTrue) {
319 return true, true
320 }
321 if bytes.Equal(value, bytesFalse) {
322 return false, true
323 }
324 if bytes.Equal(value, bytesNull) {
325 return nil, true
326 }
327 return value, true
328}
diff --git a/vendor/github.com/yuin/goldmark/parser/atx_heading.go b/vendor/github.com/yuin/goldmark/parser/atx_heading.go
new file mode 100644
index 0000000..13a198b
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/atx_heading.go
@@ -0,0 +1,246 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9// A HeadingConfig struct is a data structure that holds configuration of the renderers related to headings.
10type HeadingConfig struct {
11 AutoHeadingID bool
12 Attribute bool
13}
14
15// SetOption implements SetOptioner.
16func (b *HeadingConfig) SetOption(name OptionName, value interface{}) {
17 switch name {
18 case optAutoHeadingID:
19 b.AutoHeadingID = true
20 case optAttribute:
21 b.Attribute = true
22 }
23}
24
25// A HeadingOption interface sets options for heading parsers.
26type HeadingOption interface {
27 Option
28 SetHeadingOption(*HeadingConfig)
29}
30
31// AutoHeadingID is an option name that enables auto IDs for headings.
32const optAutoHeadingID OptionName = "AutoHeadingID"
33
34type withAutoHeadingID struct {
35}
36
37func (o *withAutoHeadingID) SetParserOption(c *Config) {
38 c.Options[optAutoHeadingID] = true
39}
40
41func (o *withAutoHeadingID) SetHeadingOption(p *HeadingConfig) {
42 p.AutoHeadingID = true
43}
44
45// WithAutoHeadingID is a functional option that enables custom heading ids and
46// auto generated heading ids.
47func WithAutoHeadingID() HeadingOption {
48 return &withAutoHeadingID{}
49}
50
51type withHeadingAttribute struct {
52 Option
53}
54
55func (o *withHeadingAttribute) SetHeadingOption(p *HeadingConfig) {
56 p.Attribute = true
57}
58
59// WithHeadingAttribute is a functional option that enables custom heading attributes.
60func WithHeadingAttribute() HeadingOption {
61 return &withHeadingAttribute{WithAttribute()}
62}
63
64type atxHeadingParser struct {
65 HeadingConfig
66}
67
68// NewATXHeadingParser return a new BlockParser that can parse ATX headings.
69func NewATXHeadingParser(opts ...HeadingOption) BlockParser {
70 p := &atxHeadingParser{}
71 for _, o := range opts {
72 o.SetHeadingOption(&p.HeadingConfig)
73 }
74 return p
75}
76
77func (b *atxHeadingParser) Trigger() []byte {
78 return []byte{'#'}
79}
80
81func (b *atxHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
82 line, segment := reader.PeekLine()
83 pos := pc.BlockOffset()
84 if pos < 0 {
85 return nil, NoChildren
86 }
87 i := pos
88 for ; i < len(line) && line[i] == '#'; i++ {
89 }
90 level := i - pos
91 if i == pos || level > 6 {
92 return nil, NoChildren
93 }
94 if i == len(line) { // alone '#' (without a new line character)
95 return ast.NewHeading(level), NoChildren
96 }
97 l := util.TrimLeftSpaceLength(line[i:])
98 if l == 0 {
99 return nil, NoChildren
100 }
101 start := i + l
102 if start >= len(line) {
103 start = len(line) - 1
104 }
105 origstart := start
106 stop := len(line) - util.TrimRightSpaceLength(line)
107
108 node := ast.NewHeading(level)
109 parsed := false
110 if b.Attribute { // handles special case like ### heading ### {#id}
111 start--
112 closureClose := -1
113 closureOpen := -1
114 for j := start; j < stop; {
115 c := line[j]
116 if util.IsEscapedPunctuation(line, j) {
117 j += 2
118 } else if util.IsSpace(c) && j < stop-1 && line[j+1] == '#' {
119 closureOpen = j + 1
120 k := j + 1
121 for ; k < stop && line[k] == '#'; k++ {
122 }
123 closureClose = k
124 break
125 } else {
126 j++
127 }
128 }
129 if closureClose > 0 {
130 reader.Advance(closureClose)
131 attrs, ok := ParseAttributes(reader)
132 rest, _ := reader.PeekLine()
133 parsed = ok && util.IsBlank(rest)
134 if parsed {
135 for _, attr := range attrs {
136 node.SetAttribute(attr.Name, attr.Value)
137 }
138 node.Lines().Append(text.NewSegment(segment.Start+start+1-segment.Padding, segment.Start+closureOpen-segment.Padding))
139 }
140 }
141 }
142 if !parsed {
143 start = origstart
144 stop := len(line) - util.TrimRightSpaceLength(line)
145 if stop <= start { // empty headings like '##[space]'
146 stop = start
147 } else {
148 i = stop - 1
149 for ; line[i] == '#' && i >= start; i-- {
150 }
151 if i != stop-1 && !util.IsSpace(line[i]) {
152 i = stop - 1
153 }
154 i++
155 stop = i
156 }
157
158 if len(util.TrimRight(line[start:stop], []byte{'#'})) != 0 { // empty heading like '### ###'
159 node.Lines().Append(text.NewSegment(segment.Start+start-segment.Padding, segment.Start+stop-segment.Padding))
160 }
161 }
162 return node, NoChildren
163}
164
165func (b *atxHeadingParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
166 return Close
167}
168
169func (b *atxHeadingParser) Close(node ast.Node, reader text.Reader, pc Context) {
170 if b.Attribute {
171 _, ok := node.AttributeString("id")
172 if !ok {
173 parseLastLineAttributes(node, reader, pc)
174 }
175 }
176
177 if b.AutoHeadingID {
178 id, ok := node.AttributeString("id")
179 if !ok {
180 generateAutoHeadingID(node.(*ast.Heading), reader, pc)
181 } else {
182 pc.IDs().Put(id.([]byte))
183 }
184 }
185}
186
187func (b *atxHeadingParser) CanInterruptParagraph() bool {
188 return true
189}
190
191func (b *atxHeadingParser) CanAcceptIndentedLine() bool {
192 return false
193}
194
195func generateAutoHeadingID(node *ast.Heading, reader text.Reader, pc Context) {
196 var line []byte
197 lastIndex := node.Lines().Len() - 1
198 if lastIndex > -1 {
199 lastLine := node.Lines().At(lastIndex)
200 line = lastLine.Value(reader.Source())
201 }
202 headingID := pc.IDs().Generate(line, ast.KindHeading)
203 node.SetAttribute(attrNameID, headingID)
204}
205
206func parseLastLineAttributes(node ast.Node, reader text.Reader, pc Context) {
207 lastIndex := node.Lines().Len() - 1
208 if lastIndex < 0 { // empty headings
209 return
210 }
211 lastLine := node.Lines().At(lastIndex)
212 line := lastLine.Value(reader.Source())
213 lr := text.NewReader(line)
214 var attrs Attributes
215 var ok bool
216 var start text.Segment
217 var sl int
218 var end text.Segment
219 for {
220 c := lr.Peek()
221 if c == text.EOF {
222 break
223 }
224 if c == '\\' {
225 lr.Advance(1)
226 if lr.Peek() == '{' {
227 lr.Advance(1)
228 }
229 continue
230 }
231 if c == '{' {
232 sl, start = lr.Position()
233 attrs, ok = ParseAttributes(lr)
234 _, end = lr.Position()
235 lr.SetPosition(sl, start)
236 }
237 lr.Advance(1)
238 }
239 if ok && util.IsBlank(line[end.Start:]) {
240 for _, attr := range attrs {
241 node.SetAttribute(attr.Name, attr.Value)
242 }
243 lastLine.Stop = lastLine.Start + start.Start
244 node.Lines().Set(lastIndex, lastLine)
245 }
246}
diff --git a/vendor/github.com/yuin/goldmark/parser/auto_link.go b/vendor/github.com/yuin/goldmark/parser/auto_link.go
new file mode 100644
index 0000000..726a505
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/auto_link.go
@@ -0,0 +1,42 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type autoLinkParser struct {
10}
11
12var defaultAutoLinkParser = &autoLinkParser{}
13
14// NewAutoLinkParser returns a new InlineParser that parses autolinks
15// surrounded by '<' and '>' .
16func NewAutoLinkParser() InlineParser {
17 return defaultAutoLinkParser
18}
19
20func (s *autoLinkParser) Trigger() []byte {
21 return []byte{'<'}
22}
23
24func (s *autoLinkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
25 line, segment := block.PeekLine()
26 stop := util.FindEmailIndex(line[1:])
27 typ := ast.AutoLinkType(ast.AutoLinkEmail)
28 if stop < 0 {
29 stop = util.FindURLIndex(line[1:])
30 typ = ast.AutoLinkURL
31 }
32 if stop < 0 {
33 return nil
34 }
35 stop++
36 if stop >= len(line) || line[stop] != '>' {
37 return nil
38 }
39 value := ast.NewTextSegment(text.NewSegment(segment.Start+1, segment.Start+stop))
40 block.Advance(stop + 1)
41 return ast.NewAutoLink(typ, value)
42}
diff --git a/vendor/github.com/yuin/goldmark/parser/blockquote.go b/vendor/github.com/yuin/goldmark/parser/blockquote.go
new file mode 100644
index 0000000..e7778dc
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/blockquote.go
@@ -0,0 +1,69 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type blockquoteParser struct {
10}
11
12var defaultBlockquoteParser = &blockquoteParser{}
13
14// NewBlockquoteParser returns a new BlockParser that
15// parses blockquotes.
16func NewBlockquoteParser() BlockParser {
17 return defaultBlockquoteParser
18}
19
20func (b *blockquoteParser) process(reader text.Reader) bool {
21 line, _ := reader.PeekLine()
22 w, pos := util.IndentWidth(line, reader.LineOffset())
23 if w > 3 || pos >= len(line) || line[pos] != '>' {
24 return false
25 }
26 pos++
27 if pos >= len(line) || line[pos] == '\n' {
28 reader.Advance(pos)
29 return true
30 }
31 if line[pos] == ' ' || line[pos] == '\t' {
32 pos++
33 }
34 reader.Advance(pos)
35 if line[pos-1] == '\t' {
36 reader.SetPadding(2)
37 }
38 return true
39}
40
41func (b *blockquoteParser) Trigger() []byte {
42 return []byte{'>'}
43}
44
45func (b *blockquoteParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
46 if b.process(reader) {
47 return ast.NewBlockquote(), HasChildren
48 }
49 return nil, NoChildren
50}
51
52func (b *blockquoteParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
53 if b.process(reader) {
54 return Continue | HasChildren
55 }
56 return Close
57}
58
59func (b *blockquoteParser) Close(node ast.Node, reader text.Reader, pc Context) {
60 // nothing to do
61}
62
63func (b *blockquoteParser) CanInterruptParagraph() bool {
64 return true
65}
66
67func (b *blockquoteParser) CanAcceptIndentedLine() bool {
68 return false
69}
diff --git a/vendor/github.com/yuin/goldmark/parser/code_block.go b/vendor/github.com/yuin/goldmark/parser/code_block.go
new file mode 100644
index 0000000..732f18c
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/code_block.go
@@ -0,0 +1,100 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type codeBlockParser struct {
10}
11
12// CodeBlockParser is a BlockParser implementation that parses indented code blocks.
13var defaultCodeBlockParser = &codeBlockParser{}
14
15// NewCodeBlockParser returns a new BlockParser that
16// parses code blocks.
17func NewCodeBlockParser() BlockParser {
18 return defaultCodeBlockParser
19}
20
21func (b *codeBlockParser) Trigger() []byte {
22 return nil
23}
24
25func (b *codeBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
26 line, segment := reader.PeekLine()
27 pos, padding := util.IndentPosition(line, reader.LineOffset(), 4)
28 if pos < 0 || util.IsBlank(line) {
29 return nil, NoChildren
30 }
31 node := ast.NewCodeBlock()
32 reader.AdvanceAndSetPadding(pos, padding)
33 _, segment = reader.PeekLine()
34 // if code block line starts with a tab, keep a tab as it is.
35 if segment.Padding != 0 {
36 preserveLeadingTabInCodeBlock(&segment, reader, 0)
37 }
38 node.Lines().Append(segment)
39 reader.Advance(segment.Len() - 1)
40 return node, NoChildren
41
42}
43
44func (b *codeBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
45 line, segment := reader.PeekLine()
46 if util.IsBlank(line) {
47 node.Lines().Append(segment.TrimLeftSpaceWidth(4, reader.Source()))
48 return Continue | NoChildren
49 }
50 pos, padding := util.IndentPosition(line, reader.LineOffset(), 4)
51 if pos < 0 {
52 return Close
53 }
54 reader.AdvanceAndSetPadding(pos, padding)
55 _, segment = reader.PeekLine()
56
57 // if code block line starts with a tab, keep a tab as it is.
58 if segment.Padding != 0 {
59 preserveLeadingTabInCodeBlock(&segment, reader, 0)
60 }
61
62 node.Lines().Append(segment)
63 reader.Advance(segment.Len() - 1)
64 return Continue | NoChildren
65}
66
67func (b *codeBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
68 // trim trailing blank lines
69 lines := node.Lines()
70 length := lines.Len() - 1
71 source := reader.Source()
72 for length >= 0 {
73 line := lines.At(length)
74 if util.IsBlank(line.Value(source)) {
75 length--
76 } else {
77 break
78 }
79 }
80 lines.SetSliced(0, length+1)
81}
82
83func (b *codeBlockParser) CanInterruptParagraph() bool {
84 return false
85}
86
87func (b *codeBlockParser) CanAcceptIndentedLine() bool {
88 return true
89}
90
91func preserveLeadingTabInCodeBlock(segment *text.Segment, reader text.Reader, indent int) {
92 offsetWithPadding := reader.LineOffset() + indent
93 sl, ss := reader.Position()
94 reader.SetPosition(sl, text.NewSegment(ss.Start-1, ss.Stop))
95 if offsetWithPadding == reader.LineOffset() {
96 segment.Padding = 0
97 segment.Start--
98 }
99 reader.SetPosition(sl, ss)
100}
diff --git a/vendor/github.com/yuin/goldmark/parser/code_span.go b/vendor/github.com/yuin/goldmark/parser/code_span.go
new file mode 100644
index 0000000..a74b09b
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/code_span.go
@@ -0,0 +1,84 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6)
7
8type codeSpanParser struct {
9}
10
11var defaultCodeSpanParser = &codeSpanParser{}
12
13// NewCodeSpanParser return a new InlineParser that parses inline codes
14// surrounded by '`' .
15func NewCodeSpanParser() InlineParser {
16 return defaultCodeSpanParser
17}
18
19func (s *codeSpanParser) Trigger() []byte {
20 return []byte{'`'}
21}
22
23func (s *codeSpanParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
24 line, startSegment := block.PeekLine()
25 opener := 0
26 for ; opener < len(line) && line[opener] == '`'; opener++ {
27 }
28 block.Advance(opener)
29 l, pos := block.Position()
30 node := ast.NewCodeSpan()
31 for {
32 line, segment := block.PeekLine()
33 if line == nil {
34 block.SetPosition(l, pos)
35 return ast.NewTextSegment(startSegment.WithStop(startSegment.Start + opener))
36 }
37 for i := 0; i < len(line); i++ {
38 c := line[i]
39 if c == '`' {
40 oldi := i
41 for ; i < len(line) && line[i] == '`'; i++ {
42 }
43 closure := i - oldi
44 if closure == opener && (i >= len(line) || line[i] != '`') {
45 segment = segment.WithStop(segment.Start + i - closure)
46 if !segment.IsEmpty() {
47 node.AppendChild(node, ast.NewRawTextSegment(segment))
48 }
49 block.Advance(i)
50 goto end
51 }
52 }
53 }
54 node.AppendChild(node, ast.NewRawTextSegment(segment))
55 block.AdvanceLine()
56 }
57end:
58 if !node.IsBlank(block.Source()) {
59 // trim first halfspace and last halfspace
60 segment := node.FirstChild().(*ast.Text).Segment
61 shouldTrimmed := true
62 if !(!segment.IsEmpty() && isSpaceOrNewline(block.Source()[segment.Start])) {
63 shouldTrimmed = false
64 }
65 segment = node.LastChild().(*ast.Text).Segment
66 if !(!segment.IsEmpty() && isSpaceOrNewline(block.Source()[segment.Stop-1])) {
67 shouldTrimmed = false
68 }
69 if shouldTrimmed {
70 t := node.FirstChild().(*ast.Text)
71 segment := t.Segment
72 t.Segment = segment.WithStart(segment.Start + 1)
73 t = node.LastChild().(*ast.Text)
74 segment = node.LastChild().(*ast.Text).Segment
75 t.Segment = segment.WithStop(segment.Stop - 1)
76 }
77
78 }
79 return node
80}
81
82func isSpaceOrNewline(c byte) bool {
83 return c == ' ' || c == '\n'
84}
diff --git a/vendor/github.com/yuin/goldmark/parser/delimiter.go b/vendor/github.com/yuin/goldmark/parser/delimiter.go
new file mode 100644
index 0000000..eb843af
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/delimiter.go
@@ -0,0 +1,238 @@
1package parser
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/yuin/goldmark/ast"
8 "github.com/yuin/goldmark/text"
9 "github.com/yuin/goldmark/util"
10)
11
12// A DelimiterProcessor interface provides a set of functions about
13// Delimiter nodes.
14type DelimiterProcessor interface {
15 // IsDelimiter returns true if given character is a delimiter, otherwise false.
16 IsDelimiter(byte) bool
17
18 // CanOpenCloser returns true if given opener can close given closer, otherwise false.
19 CanOpenCloser(opener, closer *Delimiter) bool
20
21 // OnMatch will be called when new matched delimiter found.
22 // OnMatch should return a new Node correspond to the matched delimiter.
23 OnMatch(consumes int) ast.Node
24}
25
26// A Delimiter struct represents a delimiter like '*' of the Markdown text.
27type Delimiter struct {
28 ast.BaseInline
29
30 Segment text.Segment
31
32 // CanOpen is set true if this delimiter can open a span for a new node.
33 // See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
34 CanOpen bool
35
36 // CanClose is set true if this delimiter can close a span for a new node.
37 // See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
38 CanClose bool
39
40 // Length is a remaining length of this delimiter.
41 Length int
42
43 // OriginalLength is a original length of this delimiter.
44 OriginalLength int
45
46 // Char is a character of this delimiter.
47 Char byte
48
49 // PreviousDelimiter is a previous sibling delimiter node of this delimiter.
50 PreviousDelimiter *Delimiter
51
52 // NextDelimiter is a next sibling delimiter node of this delimiter.
53 NextDelimiter *Delimiter
54
55 // Processor is a DelimiterProcessor associated with this delimiter.
56 Processor DelimiterProcessor
57}
58
59// Inline implements Inline.Inline.
60func (d *Delimiter) Inline() {}
61
62// Dump implements Node.Dump.
63func (d *Delimiter) Dump(source []byte, level int) {
64 fmt.Printf("%sDelimiter: \"%s\"\n", strings.Repeat(" ", level), string(d.Text(source)))
65}
66
67var kindDelimiter = ast.NewNodeKind("Delimiter")
68
69// Kind implements Node.Kind
70func (d *Delimiter) Kind() ast.NodeKind {
71 return kindDelimiter
72}
73
74// Text implements Node.Text
75func (d *Delimiter) Text(source []byte) []byte {
76 return d.Segment.Value(source)
77}
78
79// ConsumeCharacters consumes delimiters.
80func (d *Delimiter) ConsumeCharacters(n int) {
81 d.Length -= n
82 d.Segment = d.Segment.WithStop(d.Segment.Start + d.Length)
83}
84
85// CalcComsumption calculates how many characters should be used for opening
86// a new span correspond to given closer.
87func (d *Delimiter) CalcComsumption(closer *Delimiter) int {
88 if (d.CanClose || closer.CanOpen) && (d.OriginalLength+closer.OriginalLength)%3 == 0 && closer.OriginalLength%3 != 0 {
89 return 0
90 }
91 if d.Length >= 2 && closer.Length >= 2 {
92 return 2
93 }
94 return 1
95}
96
97// NewDelimiter returns a new Delimiter node.
98func NewDelimiter(canOpen, canClose bool, length int, char byte, processor DelimiterProcessor) *Delimiter {
99 c := &Delimiter{
100 BaseInline: ast.BaseInline{},
101 CanOpen: canOpen,
102 CanClose: canClose,
103 Length: length,
104 OriginalLength: length,
105 Char: char,
106 PreviousDelimiter: nil,
107 NextDelimiter: nil,
108 Processor: processor,
109 }
110 return c
111}
112
113// ScanDelimiter scans a delimiter by given DelimiterProcessor.
114func ScanDelimiter(line []byte, before rune, min int, processor DelimiterProcessor) *Delimiter {
115 i := 0
116 c := line[i]
117 j := i
118 if !processor.IsDelimiter(c) {
119 return nil
120 }
121 for ; j < len(line) && c == line[j]; j++ {
122 }
123 if (j - i) >= min {
124 after := rune(' ')
125 if j != len(line) {
126 after = util.ToRune(line, j)
127 }
128
129 canOpen, canClose := false, false
130 beforeIsPunctuation := util.IsPunctRune(before)
131 beforeIsWhitespace := util.IsSpaceRune(before)
132 afterIsPunctuation := util.IsPunctRune(after)
133 afterIsWhitespace := util.IsSpaceRune(after)
134
135 isLeft := !afterIsWhitespace &&
136 (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation)
137 isRight := !beforeIsWhitespace &&
138 (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation)
139
140 if line[i] == '_' {
141 canOpen = isLeft && (!isRight || beforeIsPunctuation)
142 canClose = isRight && (!isLeft || afterIsPunctuation)
143 } else {
144 canOpen = isLeft
145 canClose = isRight
146 }
147 return NewDelimiter(canOpen, canClose, j-i, c, processor)
148 }
149 return nil
150}
151
152// ProcessDelimiters processes the delimiter list in the context.
153// Processing will be stop when reaching the bottom.
154//
155// If you implement an inline parser that can have other inline nodes as
156// children, you should call this function when nesting span has closed.
157func ProcessDelimiters(bottom ast.Node, pc Context) {
158 lastDelimiter := pc.LastDelimiter()
159 if lastDelimiter == nil {
160 return
161 }
162 var closer *Delimiter
163 if bottom != nil {
164 if bottom != lastDelimiter {
165 for c := lastDelimiter.PreviousSibling(); c != nil && c != bottom; {
166 if d, ok := c.(*Delimiter); ok {
167 closer = d
168 }
169 c = c.PreviousSibling()
170 }
171 }
172 } else {
173 closer = pc.FirstDelimiter()
174 }
175 if closer == nil {
176 pc.ClearDelimiters(bottom)
177 return
178 }
179 for closer != nil {
180 if !closer.CanClose {
181 closer = closer.NextDelimiter
182 continue
183 }
184 consume := 0
185 found := false
186 maybeOpener := false
187 var opener *Delimiter
188 for opener = closer.PreviousDelimiter; opener != nil && opener != bottom; opener = opener.PreviousDelimiter {
189 if opener.CanOpen && opener.Processor.CanOpenCloser(opener, closer) {
190 maybeOpener = true
191 consume = opener.CalcComsumption(closer)
192 if consume > 0 {
193 found = true
194 break
195 }
196 }
197 }
198 if !found {
199 next := closer.NextDelimiter
200 if !maybeOpener && !closer.CanOpen {
201 pc.RemoveDelimiter(closer)
202 }
203 closer = next
204 continue
205 }
206 opener.ConsumeCharacters(consume)
207 closer.ConsumeCharacters(consume)
208
209 node := opener.Processor.OnMatch(consume)
210
211 parent := opener.Parent()
212 child := opener.NextSibling()
213
214 for child != nil && child != closer {
215 next := child.NextSibling()
216 node.AppendChild(node, child)
217 child = next
218 }
219 parent.InsertAfter(parent, opener, node)
220
221 for c := opener.NextDelimiter; c != nil && c != closer; {
222 next := c.NextDelimiter
223 pc.RemoveDelimiter(c)
224 c = next
225 }
226
227 if opener.Length == 0 {
228 pc.RemoveDelimiter(opener)
229 }
230
231 if closer.Length == 0 {
232 next := closer.NextDelimiter
233 pc.RemoveDelimiter(closer)
234 closer = next
235 }
236 }
237 pc.ClearDelimiters(bottom)
238}
diff --git a/vendor/github.com/yuin/goldmark/parser/emphasis.go b/vendor/github.com/yuin/goldmark/parser/emphasis.go
new file mode 100644
index 0000000..4886471
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/emphasis.go
@@ -0,0 +1,50 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6)
7
8type emphasisDelimiterProcessor struct {
9}
10
11func (p *emphasisDelimiterProcessor) IsDelimiter(b byte) bool {
12 return b == '*' || b == '_'
13}
14
15func (p *emphasisDelimiterProcessor) CanOpenCloser(opener, closer *Delimiter) bool {
16 return opener.Char == closer.Char
17}
18
19func (p *emphasisDelimiterProcessor) OnMatch(consumes int) ast.Node {
20 return ast.NewEmphasis(consumes)
21}
22
23var defaultEmphasisDelimiterProcessor = &emphasisDelimiterProcessor{}
24
25type emphasisParser struct {
26}
27
28var defaultEmphasisParser = &emphasisParser{}
29
30// NewEmphasisParser return a new InlineParser that parses emphasises.
31func NewEmphasisParser() InlineParser {
32 return defaultEmphasisParser
33}
34
35func (s *emphasisParser) Trigger() []byte {
36 return []byte{'*', '_'}
37}
38
39func (s *emphasisParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
40 before := block.PrecendingCharacter()
41 line, segment := block.PeekLine()
42 node := ScanDelimiter(line, before, 1, defaultEmphasisDelimiterProcessor)
43 if node == nil {
44 return nil
45 }
46 node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
47 block.Advance(node.OriginalLength)
48 pc.PushDelimiter(node)
49 return node
50}
diff --git a/vendor/github.com/yuin/goldmark/parser/fcode_block.go b/vendor/github.com/yuin/goldmark/parser/fcode_block.go
new file mode 100644
index 0000000..e51a35a
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/fcode_block.go
@@ -0,0 +1,121 @@
1package parser
2
3import (
4 "bytes"
5
6 "github.com/yuin/goldmark/ast"
7 "github.com/yuin/goldmark/text"
8 "github.com/yuin/goldmark/util"
9)
10
11type fencedCodeBlockParser struct {
12}
13
14var defaultFencedCodeBlockParser = &fencedCodeBlockParser{}
15
16// NewFencedCodeBlockParser returns a new BlockParser that
17// parses fenced code blocks.
18func NewFencedCodeBlockParser() BlockParser {
19 return defaultFencedCodeBlockParser
20}
21
22type fenceData struct {
23 char byte
24 indent int
25 length int
26 node ast.Node
27}
28
29var fencedCodeBlockInfoKey = NewContextKey()
30
31func (b *fencedCodeBlockParser) Trigger() []byte {
32 return []byte{'~', '`'}
33}
34
35func (b *fencedCodeBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
36 line, segment := reader.PeekLine()
37 pos := pc.BlockOffset()
38 if pos < 0 || (line[pos] != '`' && line[pos] != '~') {
39 return nil, NoChildren
40 }
41 findent := pos
42 fenceChar := line[pos]
43 i := pos
44 for ; i < len(line) && line[i] == fenceChar; i++ {
45 }
46 oFenceLength := i - pos
47 if oFenceLength < 3 {
48 return nil, NoChildren
49 }
50 var info *ast.Text
51 if i < len(line)-1 {
52 rest := line[i:]
53 left := util.TrimLeftSpaceLength(rest)
54 right := util.TrimRightSpaceLength(rest)
55 if left < len(rest)-right {
56 infoStart, infoStop := segment.Start-segment.Padding+i+left, segment.Stop-right
57 value := rest[left : len(rest)-right]
58 if fenceChar == '`' && bytes.IndexByte(value, '`') > -1 {
59 return nil, NoChildren
60 } else if infoStart != infoStop {
61 info = ast.NewTextSegment(text.NewSegment(infoStart, infoStop))
62 }
63 }
64 }
65 node := ast.NewFencedCodeBlock(info)
66 pc.Set(fencedCodeBlockInfoKey, &fenceData{fenceChar, findent, oFenceLength, node})
67 return node, NoChildren
68
69}
70
71func (b *fencedCodeBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
72 line, segment := reader.PeekLine()
73 fdata := pc.Get(fencedCodeBlockInfoKey).(*fenceData)
74
75 w, pos := util.IndentWidth(line, reader.LineOffset())
76 if w < 4 {
77 i := pos
78 for ; i < len(line) && line[i] == fdata.char; i++ {
79 }
80 length := i - pos
81 if length >= fdata.length && util.IsBlank(line[i:]) {
82 newline := 1
83 if line[len(line)-1] != '\n' {
84 newline = 0
85 }
86 reader.Advance(segment.Stop - segment.Start - newline + segment.Padding)
87 return Close
88 }
89 }
90 pos, padding := util.IndentPositionPadding(line, reader.LineOffset(), segment.Padding, fdata.indent)
91 if pos < 0 {
92 pos = util.FirstNonSpacePosition(line)
93 if pos < 0 {
94 pos = 0
95 }
96 padding = 0
97 }
98 seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding)
99 // if code block line starts with a tab, keep a tab as it is.
100 if padding != 0 {
101 preserveLeadingTabInCodeBlock(&seg, reader, fdata.indent)
102 }
103 node.Lines().Append(seg)
104 reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
105 return Continue | NoChildren
106}
107
108func (b *fencedCodeBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
109 fdata := pc.Get(fencedCodeBlockInfoKey).(*fenceData)
110 if fdata.node == node {
111 pc.Set(fencedCodeBlockInfoKey, nil)
112 }
113}
114
115func (b *fencedCodeBlockParser) CanInterruptParagraph() bool {
116 return true
117}
118
119func (b *fencedCodeBlockParser) CanAcceptIndentedLine() bool {
120 return false
121}
diff --git a/vendor/github.com/yuin/goldmark/parser/html_block.go b/vendor/github.com/yuin/goldmark/parser/html_block.go
new file mode 100644
index 0000000..6881e25
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/html_block.go
@@ -0,0 +1,228 @@
1package parser
2
3import (
4 "bytes"
5 "regexp"
6 "strings"
7
8 "github.com/yuin/goldmark/ast"
9 "github.com/yuin/goldmark/text"
10 "github.com/yuin/goldmark/util"
11)
12
13var allowedBlockTags = map[string]bool{
14 "address": true,
15 "article": true,
16 "aside": true,
17 "base": true,
18 "basefont": true,
19 "blockquote": true,
20 "body": true,
21 "caption": true,
22 "center": true,
23 "col": true,
24 "colgroup": true,
25 "dd": true,
26 "details": true,
27 "dialog": true,
28 "dir": true,
29 "div": true,
30 "dl": true,
31 "dt": true,
32 "fieldset": true,
33 "figcaption": true,
34 "figure": true,
35 "footer": true,
36 "form": true,
37 "frame": true,
38 "frameset": true,
39 "h1": true,
40 "h2": true,
41 "h3": true,
42 "h4": true,
43 "h5": true,
44 "h6": true,
45 "head": true,
46 "header": true,
47 "hr": true,
48 "html": true,
49 "iframe": true,
50 "legend": true,
51 "li": true,
52 "link": true,
53 "main": true,
54 "menu": true,
55 "menuitem": true,
56 "meta": true,
57 "nav": true,
58 "noframes": true,
59 "ol": true,
60 "optgroup": true,
61 "option": true,
62 "p": true,
63 "param": true,
64 "section": true,
65 "source": true,
66 "summary": true,
67 "table": true,
68 "tbody": true,
69 "td": true,
70 "tfoot": true,
71 "th": true,
72 "thead": true,
73 "title": true,
74 "tr": true,
75 "track": true,
76 "ul": true,
77}
78
79var htmlBlockType1OpenRegexp = regexp.MustCompile(`(?i)^[ ]{0,3}<(script|pre|style|textarea)(?:\s.*|>.*|/>.*|)(?:\r\n|\n)?$`)
80var htmlBlockType1CloseRegexp = regexp.MustCompile(`(?i)^.*</(?:script|pre|style|textarea)>.*`)
81
82var htmlBlockType2OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<!\-\-`)
83var htmlBlockType2Close = []byte{'-', '-', '>'}
84
85var htmlBlockType3OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<\?`)
86var htmlBlockType3Close = []byte{'?', '>'}
87
88var htmlBlockType4OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<![A-Z]+.*(?:\r\n|\n)?$`)
89var htmlBlockType4Close = []byte{'>'}
90
91var htmlBlockType5OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<\!\[CDATA\[`)
92var htmlBlockType5Close = []byte{']', ']', '>'}
93
94var htmlBlockType6Regexp = regexp.MustCompile(`^[ ]{0,3}<(?:/[ ]*)?([a-zA-Z]+[a-zA-Z0-9\-]*)(?:[ ].*|>.*|/>.*|)(?:\r\n|\n)?$`)
95
96var htmlBlockType7Regexp = regexp.MustCompile(`^[ ]{0,3}<(/[ ]*)?([a-zA-Z]+[a-zA-Z0-9\-]*)(` + attributePattern + `*)[ ]*(?:>|/>)[ ]*(?:\r\n|\n)?$`)
97
98type htmlBlockParser struct {
99}
100
101var defaultHTMLBlockParser = &htmlBlockParser{}
102
103// NewHTMLBlockParser return a new BlockParser that can parse html
104// blocks.
105func NewHTMLBlockParser() BlockParser {
106 return defaultHTMLBlockParser
107}
108
109func (b *htmlBlockParser) Trigger() []byte {
110 return []byte{'<'}
111}
112
113func (b *htmlBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
114 var node *ast.HTMLBlock
115 line, segment := reader.PeekLine()
116 last := pc.LastOpenedBlock().Node
117 if pos := pc.BlockOffset(); pos < 0 || line[pos] != '<' {
118 return nil, NoChildren
119 }
120
121 if m := htmlBlockType1OpenRegexp.FindSubmatchIndex(line); m != nil {
122 node = ast.NewHTMLBlock(ast.HTMLBlockType1)
123 } else if htmlBlockType2OpenRegexp.Match(line) {
124 node = ast.NewHTMLBlock(ast.HTMLBlockType2)
125 } else if htmlBlockType3OpenRegexp.Match(line) {
126 node = ast.NewHTMLBlock(ast.HTMLBlockType3)
127 } else if htmlBlockType4OpenRegexp.Match(line) {
128 node = ast.NewHTMLBlock(ast.HTMLBlockType4)
129 } else if htmlBlockType5OpenRegexp.Match(line) {
130 node = ast.NewHTMLBlock(ast.HTMLBlockType5)
131 } else if match := htmlBlockType7Regexp.FindSubmatchIndex(line); match != nil {
132 isCloseTag := match[2] > -1 && bytes.Equal(line[match[2]:match[3]], []byte("/"))
133 hasAttr := match[6] != match[7]
134 tagName := strings.ToLower(string(line[match[4]:match[5]]))
135 _, ok := allowedBlockTags[tagName]
136 if ok {
137 node = ast.NewHTMLBlock(ast.HTMLBlockType6)
138 } else if tagName != "script" && tagName != "style" && tagName != "pre" && !ast.IsParagraph(last) && !(isCloseTag && hasAttr) { // type 7 can not interrupt paragraph
139 node = ast.NewHTMLBlock(ast.HTMLBlockType7)
140 }
141 }
142 if node == nil {
143 if match := htmlBlockType6Regexp.FindSubmatchIndex(line); match != nil {
144 tagName := string(line[match[2]:match[3]])
145 _, ok := allowedBlockTags[strings.ToLower(tagName)]
146 if ok {
147 node = ast.NewHTMLBlock(ast.HTMLBlockType6)
148 }
149 }
150 }
151 if node != nil {
152 reader.Advance(segment.Len() - util.TrimRightSpaceLength(line))
153 node.Lines().Append(segment)
154 return node, NoChildren
155 }
156 return nil, NoChildren
157}
158
159func (b *htmlBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
160 htmlBlock := node.(*ast.HTMLBlock)
161 lines := htmlBlock.Lines()
162 line, segment := reader.PeekLine()
163 var closurePattern []byte
164
165 switch htmlBlock.HTMLBlockType {
166 case ast.HTMLBlockType1:
167 if lines.Len() == 1 {
168 firstLine := lines.At(0)
169 if htmlBlockType1CloseRegexp.Match(firstLine.Value(reader.Source())) {
170 return Close
171 }
172 }
173 if htmlBlockType1CloseRegexp.Match(line) {
174 htmlBlock.ClosureLine = segment
175 reader.Advance(segment.Len() - util.TrimRightSpaceLength(line))
176 return Close
177 }
178 case ast.HTMLBlockType2:
179 closurePattern = htmlBlockType2Close
180 fallthrough
181 case ast.HTMLBlockType3:
182 if closurePattern == nil {
183 closurePattern = htmlBlockType3Close
184 }
185 fallthrough
186 case ast.HTMLBlockType4:
187 if closurePattern == nil {
188 closurePattern = htmlBlockType4Close
189 }
190 fallthrough
191 case ast.HTMLBlockType5:
192 if closurePattern == nil {
193 closurePattern = htmlBlockType5Close
194 }
195
196 if lines.Len() == 1 {
197 firstLine := lines.At(0)
198 if bytes.Contains(firstLine.Value(reader.Source()), closurePattern) {
199 return Close
200 }
201 }
202 if bytes.Contains(line, closurePattern) {
203 htmlBlock.ClosureLine = segment
204 reader.Advance(segment.Len())
205 return Close
206 }
207
208 case ast.HTMLBlockType6, ast.HTMLBlockType7:
209 if util.IsBlank(line) {
210 return Close
211 }
212 }
213 node.Lines().Append(segment)
214 reader.Advance(segment.Len() - util.TrimRightSpaceLength(line))
215 return Continue | NoChildren
216}
217
218func (b *htmlBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
219 // nothing to do
220}
221
222func (b *htmlBlockParser) CanInterruptParagraph() bool {
223 return true
224}
225
226func (b *htmlBlockParser) CanAcceptIndentedLine() bool {
227 return false
228}
diff --git a/vendor/github.com/yuin/goldmark/parser/link.go b/vendor/github.com/yuin/goldmark/parser/link.go
new file mode 100644
index 0000000..99583ac
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/link.go
@@ -0,0 +1,409 @@
1package parser
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/yuin/goldmark/ast"
8 "github.com/yuin/goldmark/text"
9 "github.com/yuin/goldmark/util"
10)
11
12var linkLabelStateKey = NewContextKey()
13
14type linkLabelState struct {
15 ast.BaseInline
16
17 Segment text.Segment
18
19 IsImage bool
20
21 Prev *linkLabelState
22
23 Next *linkLabelState
24
25 First *linkLabelState
26
27 Last *linkLabelState
28}
29
30func newLinkLabelState(segment text.Segment, isImage bool) *linkLabelState {
31 return &linkLabelState{
32 Segment: segment,
33 IsImage: isImage,
34 }
35}
36
37func (s *linkLabelState) Text(source []byte) []byte {
38 return s.Segment.Value(source)
39}
40
41func (s *linkLabelState) Dump(source []byte, level int) {
42 fmt.Printf("%slinkLabelState: \"%s\"\n", strings.Repeat(" ", level), s.Text(source))
43}
44
45var kindLinkLabelState = ast.NewNodeKind("LinkLabelState")
46
47func (s *linkLabelState) Kind() ast.NodeKind {
48 return kindLinkLabelState
49}
50
51func linkLabelStateLength(v *linkLabelState) int {
52 if v == nil || v.Last == nil || v.First == nil {
53 return 0
54 }
55 return v.Last.Segment.Stop - v.First.Segment.Start
56}
57
58func pushLinkLabelState(pc Context, v *linkLabelState) {
59 tlist := pc.Get(linkLabelStateKey)
60 var list *linkLabelState
61 if tlist == nil {
62 list = v
63 v.First = v
64 v.Last = v
65 pc.Set(linkLabelStateKey, list)
66 } else {
67 list = tlist.(*linkLabelState)
68 l := list.Last
69 list.Last = v
70 l.Next = v
71 v.Prev = l
72 }
73}
74
75func removeLinkLabelState(pc Context, d *linkLabelState) {
76 tlist := pc.Get(linkLabelStateKey)
77 var list *linkLabelState
78 if tlist == nil {
79 return
80 }
81 list = tlist.(*linkLabelState)
82
83 if d.Prev == nil {
84 list = d.Next
85 if list != nil {
86 list.First = d
87 list.Last = d.Last
88 list.Prev = nil
89 pc.Set(linkLabelStateKey, list)
90 } else {
91 pc.Set(linkLabelStateKey, nil)
92 }
93 } else {
94 d.Prev.Next = d.Next
95 if d.Next != nil {
96 d.Next.Prev = d.Prev
97 }
98 }
99 if list != nil && d.Next == nil {
100 list.Last = d.Prev
101 }
102 d.Next = nil
103 d.Prev = nil
104 d.First = nil
105 d.Last = nil
106}
107
108type linkParser struct {
109}
110
111var defaultLinkParser = &linkParser{}
112
113// NewLinkParser return a new InlineParser that parses links.
114func NewLinkParser() InlineParser {
115 return defaultLinkParser
116}
117
118func (s *linkParser) Trigger() []byte {
119 return []byte{'!', '[', ']'}
120}
121
122var linkBottom = NewContextKey()
123
124func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
125 line, segment := block.PeekLine()
126 if line[0] == '!' {
127 if len(line) > 1 && line[1] == '[' {
128 block.Advance(1)
129 pc.Set(linkBottom, pc.LastDelimiter())
130 return processLinkLabelOpen(block, segment.Start+1, true, pc)
131 }
132 return nil
133 }
134 if line[0] == '[' {
135 pc.Set(linkBottom, pc.LastDelimiter())
136 return processLinkLabelOpen(block, segment.Start, false, pc)
137 }
138
139 // line[0] == ']'
140 tlist := pc.Get(linkLabelStateKey)
141 if tlist == nil {
142 return nil
143 }
144 last := tlist.(*linkLabelState).Last
145 if last == nil {
146 return nil
147 }
148 block.Advance(1)
149 removeLinkLabelState(pc, last)
150 // CommonMark spec says:
151 // > A link label can have at most 999 characters inside the square brackets.
152 if linkLabelStateLength(tlist.(*linkLabelState)) > 998 {
153 ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
154 return nil
155 }
156
157 if !last.IsImage && s.containsLink(last) { // a link in a link text is not allowed
158 ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
159 return nil
160 }
161
162 c := block.Peek()
163 l, pos := block.Position()
164 var link *ast.Link
165 var hasValue bool
166 if c == '(' { // normal link
167 link = s.parseLink(parent, last, block, pc)
168 } else if c == '[' { // reference link
169 link, hasValue = s.parseReferenceLink(parent, last, block, pc)
170 if link == nil && hasValue {
171 ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
172 return nil
173 }
174 }
175
176 if link == nil {
177 // maybe shortcut reference link
178 block.SetPosition(l, pos)
179 ssegment := text.NewSegment(last.Segment.Stop, segment.Start)
180 maybeReference := block.Value(ssegment)
181 // CommonMark spec says:
182 // > A link label can have at most 999 characters inside the square brackets.
183 if len(maybeReference) > 999 {
184 ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
185 return nil
186 }
187
188 ref, ok := pc.Reference(util.ToLinkReference(maybeReference))
189 if !ok {
190 ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
191 return nil
192 }
193 link = ast.NewLink()
194 s.processLinkLabel(parent, link, last, pc)
195 link.Title = ref.Title()
196 link.Destination = ref.Destination()
197 }
198 if last.IsImage {
199 last.Parent().RemoveChild(last.Parent(), last)
200 return ast.NewImage(link)
201 }
202 last.Parent().RemoveChild(last.Parent(), last)
203 return link
204}
205
206func (s *linkParser) containsLink(n ast.Node) bool {
207 if n == nil {
208 return false
209 }
210 for c := n; c != nil; c = c.NextSibling() {
211 if _, ok := c.(*ast.Link); ok {
212 return true
213 }
214 if s.containsLink(c.FirstChild()) {
215 return true
216 }
217 }
218 return false
219}
220
221func processLinkLabelOpen(block text.Reader, pos int, isImage bool, pc Context) *linkLabelState {
222 start := pos
223 if isImage {
224 start--
225 }
226 state := newLinkLabelState(text.NewSegment(start, pos+1), isImage)
227 pushLinkLabelState(pc, state)
228 block.Advance(1)
229 return state
230}
231
232func (s *linkParser) processLinkLabel(parent ast.Node, link *ast.Link, last *linkLabelState, pc Context) {
233 var bottom ast.Node
234 if v := pc.Get(linkBottom); v != nil {
235 bottom = v.(ast.Node)
236 }
237 pc.Set(linkBottom, nil)
238 ProcessDelimiters(bottom, pc)
239 for c := last.NextSibling(); c != nil; {
240 next := c.NextSibling()
241 parent.RemoveChild(parent, c)
242 link.AppendChild(link, c)
243 c = next
244 }
245}
246
247var linkFindClosureOptions text.FindClosureOptions = text.FindClosureOptions{
248 Nesting: false,
249 Newline: true,
250 Advance: true,
251}
252
253func (s *linkParser) parseReferenceLink(parent ast.Node, last *linkLabelState, block text.Reader, pc Context) (*ast.Link, bool) {
254 _, orgpos := block.Position()
255 block.Advance(1) // skip '['
256 segments, found := block.FindClosure('[', ']', linkFindClosureOptions)
257 if !found {
258 return nil, false
259 }
260
261 var maybeReference []byte
262 if segments.Len() == 1 { // avoid allocate a new byte slice
263 maybeReference = block.Value(segments.At(0))
264 } else {
265 maybeReference = []byte{}
266 for i := 0; i < segments.Len(); i++ {
267 s := segments.At(i)
268 maybeReference = append(maybeReference, block.Value(s)...)
269 }
270 }
271 if util.IsBlank(maybeReference) { // collapsed reference link
272 s := text.NewSegment(last.Segment.Stop, orgpos.Start-1)
273 maybeReference = block.Value(s)
274 }
275 // CommonMark spec says:
276 // > A link label can have at most 999 characters inside the square brackets.
277 if len(maybeReference) > 999 {
278 return nil, true
279 }
280
281 ref, ok := pc.Reference(util.ToLinkReference(maybeReference))
282 if !ok {
283 return nil, true
284 }
285
286 link := ast.NewLink()
287 s.processLinkLabel(parent, link, last, pc)
288 link.Title = ref.Title()
289 link.Destination = ref.Destination()
290 return link, true
291}
292
293func (s *linkParser) parseLink(parent ast.Node, last *linkLabelState, block text.Reader, pc Context) *ast.Link {
294 block.Advance(1) // skip '('
295 block.SkipSpaces()
296 var title []byte
297 var destination []byte
298 var ok bool
299 if block.Peek() == ')' { // empty link like '[link]()'
300 block.Advance(1)
301 } else {
302 destination, ok = parseLinkDestination(block)
303 if !ok {
304 return nil
305 }
306 block.SkipSpaces()
307 if block.Peek() == ')' {
308 block.Advance(1)
309 } else {
310 title, ok = parseLinkTitle(block)
311 if !ok {
312 return nil
313 }
314 block.SkipSpaces()
315 if block.Peek() == ')' {
316 block.Advance(1)
317 } else {
318 return nil
319 }
320 }
321 }
322
323 link := ast.NewLink()
324 s.processLinkLabel(parent, link, last, pc)
325 link.Destination = destination
326 link.Title = title
327 return link
328}
329
330func parseLinkDestination(block text.Reader) ([]byte, bool) {
331 block.SkipSpaces()
332 line, _ := block.PeekLine()
333 if block.Peek() == '<' {
334 i := 1
335 for i < len(line) {
336 c := line[i]
337 if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
338 i += 2
339 continue
340 } else if c == '>' {
341 block.Advance(i + 1)
342 return line[1:i], true
343 }
344 i++
345 }
346 return nil, false
347 }
348 opened := 0
349 i := 0
350 for i < len(line) {
351 c := line[i]
352 if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
353 i += 2
354 continue
355 } else if c == '(' {
356 opened++
357 } else if c == ')' {
358 opened--
359 if opened < 0 {
360 break
361 }
362 } else if util.IsSpace(c) {
363 break
364 }
365 i++
366 }
367 block.Advance(i)
368 return line[:i], len(line[:i]) != 0
369}
370
371func parseLinkTitle(block text.Reader) ([]byte, bool) {
372 block.SkipSpaces()
373 opener := block.Peek()
374 if opener != '"' && opener != '\'' && opener != '(' {
375 return nil, false
376 }
377 closer := opener
378 if opener == '(' {
379 closer = ')'
380 }
381 block.Advance(1)
382 segments, found := block.FindClosure(opener, closer, linkFindClosureOptions)
383 if found {
384 if segments.Len() == 1 {
385 return block.Value(segments.At(0)), true
386 }
387 var title []byte
388 for i := 0; i < segments.Len(); i++ {
389 s := segments.At(i)
390 title = append(title, block.Value(s)...)
391 }
392 return title, true
393 }
394 return nil, false
395}
396
397func (s *linkParser) CloseBlock(parent ast.Node, block text.Reader, pc Context) {
398 pc.Set(linkBottom, nil)
399 tlist := pc.Get(linkLabelStateKey)
400 if tlist == nil {
401 return
402 }
403 for s := tlist.(*linkLabelState); s != nil; {
404 next := s.Next
405 removeLinkLabelState(pc, s)
406 s.Parent().ReplaceChild(s.Parent(), s, ast.NewTextSegment(s.Segment))
407 s = next
408 }
409}
diff --git a/vendor/github.com/yuin/goldmark/parser/link_ref.go b/vendor/github.com/yuin/goldmark/parser/link_ref.go
new file mode 100644
index 0000000..ea3f654
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/link_ref.go
@@ -0,0 +1,152 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type linkReferenceParagraphTransformer struct {
10}
11
12// LinkReferenceParagraphTransformer is a ParagraphTransformer implementation
13// that parses and extracts link reference from paragraphs.
14var LinkReferenceParagraphTransformer = &linkReferenceParagraphTransformer{}
15
16func (p *linkReferenceParagraphTransformer) Transform(node *ast.Paragraph, reader text.Reader, pc Context) {
17 lines := node.Lines()
18 block := text.NewBlockReader(reader.Source(), lines)
19 removes := [][2]int{}
20 for {
21 start, end := parseLinkReferenceDefinition(block, pc)
22 if start > -1 {
23 if start == end {
24 end++
25 }
26 removes = append(removes, [2]int{start, end})
27 continue
28 }
29 break
30 }
31
32 offset := 0
33 for _, remove := range removes {
34 if lines.Len() == 0 {
35 break
36 }
37 s := lines.Sliced(remove[1]-offset, lines.Len())
38 lines.SetSliced(0, remove[0]-offset)
39 lines.AppendAll(s)
40 offset = remove[1]
41 }
42
43 if lines.Len() == 0 {
44 t := ast.NewTextBlock()
45 t.SetBlankPreviousLines(node.HasBlankPreviousLines())
46 node.Parent().ReplaceChild(node.Parent(), node, t)
47 return
48 }
49
50 node.SetLines(lines)
51}
52
53func parseLinkReferenceDefinition(block text.Reader, pc Context) (int, int) {
54 block.SkipSpaces()
55 line, _ := block.PeekLine()
56 if line == nil {
57 return -1, -1
58 }
59 startLine, _ := block.Position()
60 width, pos := util.IndentWidth(line, 0)
61 if width > 3 {
62 return -1, -1
63 }
64 if width != 0 {
65 pos++
66 }
67 if line[pos] != '[' {
68 return -1, -1
69 }
70 block.Advance(pos + 1)
71 segments, found := block.FindClosure('[', ']', linkFindClosureOptions)
72 if !found {
73 return -1, -1
74 }
75 var label []byte
76 if segments.Len() == 1 {
77 label = block.Value(segments.At(0))
78 } else {
79 for i := 0; i < segments.Len(); i++ {
80 s := segments.At(i)
81 label = append(label, block.Value(s)...)
82 }
83 }
84 if util.IsBlank(label) {
85 return -1, -1
86 }
87 if block.Peek() != ':' {
88 return -1, -1
89 }
90 block.Advance(1)
91 block.SkipSpaces()
92 destination, ok := parseLinkDestination(block)
93 if !ok {
94 return -1, -1
95 }
96 line, _ = block.PeekLine()
97 isNewLine := line == nil || util.IsBlank(line)
98
99 endLine, _ := block.Position()
100 _, spaces, _ := block.SkipSpaces()
101 opener := block.Peek()
102 if opener != '"' && opener != '\'' && opener != '(' {
103 if !isNewLine {
104 return -1, -1
105 }
106 ref := NewReference(label, destination, nil)
107 pc.AddReference(ref)
108 return startLine, endLine + 1
109 }
110 if spaces == 0 {
111 return -1, -1
112 }
113 block.Advance(1)
114 closer := opener
115 if opener == '(' {
116 closer = ')'
117 }
118 segments, found = block.FindClosure(opener, closer, linkFindClosureOptions)
119 if !found {
120 if !isNewLine {
121 return -1, -1
122 }
123 ref := NewReference(label, destination, nil)
124 pc.AddReference(ref)
125 block.AdvanceLine()
126 return startLine, endLine + 1
127 }
128 var title []byte
129 if segments.Len() == 1 {
130 title = block.Value(segments.At(0))
131 } else {
132 for i := 0; i < segments.Len(); i++ {
133 s := segments.At(i)
134 title = append(title, block.Value(s)...)
135 }
136 }
137
138 line, _ = block.PeekLine()
139 if line != nil && !util.IsBlank(line) {
140 if !isNewLine {
141 return -1, -1
142 }
143 ref := NewReference(label, destination, title)
144 pc.AddReference(ref)
145 return startLine, endLine
146 }
147
148 endLine, _ = block.Position()
149 ref := NewReference(label, destination, title)
150 pc.AddReference(ref)
151 return startLine, endLine + 1
152}
diff --git a/vendor/github.com/yuin/goldmark/parser/list.go b/vendor/github.com/yuin/goldmark/parser/list.go
new file mode 100644
index 0000000..e5cad11
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/list.go
@@ -0,0 +1,287 @@
1package parser
2
3import (
4 "strconv"
5
6 "github.com/yuin/goldmark/ast"
7 "github.com/yuin/goldmark/text"
8 "github.com/yuin/goldmark/util"
9)
10
11type listItemType int
12
13const (
14 notList listItemType = iota
15 bulletList
16 orderedList
17)
18
19var skipListParserKey = NewContextKey()
20var emptyListItemWithBlankLines = NewContextKey()
21var listItemFlagValue interface{} = true
22
23// Same as
24// `^(([ ]*)([\-\*\+]))(\s+.*)?\n?$`.FindSubmatchIndex or
25// `^(([ ]*)(\d{1,9}[\.\)]))(\s+.*)?\n?$`.FindSubmatchIndex
26func parseListItem(line []byte) ([6]int, listItemType) {
27 i := 0
28 l := len(line)
29 ret := [6]int{}
30 for ; i < l && line[i] == ' '; i++ {
31 c := line[i]
32 if c == '\t' {
33 return ret, notList
34 }
35 }
36 if i > 3 {
37 return ret, notList
38 }
39 ret[0] = 0
40 ret[1] = i
41 ret[2] = i
42 var typ listItemType
43 if i < l && (line[i] == '-' || line[i] == '*' || line[i] == '+') {
44 i++
45 ret[3] = i
46 typ = bulletList
47 } else if i < l {
48 for ; i < l && util.IsNumeric(line[i]); i++ {
49 }
50 ret[3] = i
51 if ret[3] == ret[2] || ret[3]-ret[2] > 9 {
52 return ret, notList
53 }
54 if i < l && (line[i] == '.' || line[i] == ')') {
55 i++
56 ret[3] = i
57 } else {
58 return ret, notList
59 }
60 typ = orderedList
61 } else {
62 return ret, notList
63 }
64 if i < l && line[i] != '\n' {
65 w, _ := util.IndentWidth(line[i:], 0)
66 if w == 0 {
67 return ret, notList
68 }
69 }
70 if i >= l {
71 ret[4] = -1
72 ret[5] = -1
73 return ret, typ
74 }
75 ret[4] = i
76 ret[5] = len(line)
77 if line[ret[5]-1] == '\n' && line[i] != '\n' {
78 ret[5]--
79 }
80 return ret, typ
81}
82
83func matchesListItem(source []byte, strict bool) ([6]int, listItemType) {
84 m, typ := parseListItem(source)
85 if typ != notList && (!strict || strict && m[1] < 4) {
86 return m, typ
87 }
88 return m, notList
89}
90
91func calcListOffset(source []byte, match [6]int) int {
92 offset := 0
93 if match[4] < 0 || util.IsBlank(source[match[4]:]) { // list item starts with a blank line
94 offset = 1
95 } else {
96 offset, _ = util.IndentWidth(source[match[4]:], match[4])
97 if offset > 4 { // offseted codeblock
98 offset = 1
99 }
100 }
101 return offset
102}
103
104func lastOffset(node ast.Node) int {
105 lastChild := node.LastChild()
106 if lastChild != nil {
107 return lastChild.(*ast.ListItem).Offset
108 }
109 return 0
110}
111
112type listParser struct {
113}
114
115var defaultListParser = &listParser{}
116
117// NewListParser returns a new BlockParser that
118// parses lists.
119// This parser must take precedence over the ListItemParser.
120func NewListParser() BlockParser {
121 return defaultListParser
122}
123
124func (b *listParser) Trigger() []byte {
125 return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
126}
127
128func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
129 last := pc.LastOpenedBlock().Node
130 if _, lok := last.(*ast.List); lok || pc.Get(skipListParserKey) != nil {
131 pc.Set(skipListParserKey, nil)
132 return nil, NoChildren
133 }
134 line, _ := reader.PeekLine()
135 match, typ := matchesListItem(line, true)
136 if typ == notList {
137 return nil, NoChildren
138 }
139 start := -1
140 if typ == orderedList {
141 number := line[match[2] : match[3]-1]
142 start, _ = strconv.Atoi(string(number))
143 }
144
145 if ast.IsParagraph(last) && last.Parent() == parent {
146 // we allow only lists starting with 1 to interrupt paragraphs.
147 if typ == orderedList && start != 1 {
148 return nil, NoChildren
149 }
150 //an empty list item cannot interrupt a paragraph:
151 if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
152 return nil, NoChildren
153 }
154 }
155
156 marker := line[match[3]-1]
157 node := ast.NewList(marker)
158 if start > -1 {
159 node.Start = start
160 }
161 pc.Set(emptyListItemWithBlankLines, nil)
162 return node, HasChildren
163}
164
165func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
166 list := node.(*ast.List)
167 line, _ := reader.PeekLine()
168 if util.IsBlank(line) {
169 if node.LastChild().ChildCount() == 0 {
170 pc.Set(emptyListItemWithBlankLines, listItemFlagValue)
171 }
172 return Continue | HasChildren
173 }
174
175 // "offset" means a width that bar indicates.
176 // - aaaaaaaa
177 // |----|
178 //
179 // If the indent is less than the last offset like
180 // - a
181 // - b <--- current line
182 // it maybe a new child of the list.
183 //
184 // Empty list items can have multiple blanklines
185 //
186 // - <--- 1st item is an empty thus "offset" is unknown
187 //
188 //
189 // - <--- current line
190 //
191 // -> 1 list with 2 blank items
192 //
193 // So if the last item is an empty, it maybe a new child of the list.
194 //
195 offset := lastOffset(node)
196 lastIsEmpty := node.LastChild().ChildCount() == 0
197 indent, _ := util.IndentWidth(line, reader.LineOffset())
198
199 if indent < offset || lastIsEmpty {
200 if indent < 4 {
201 match, typ := matchesListItem(line, false) // may have a leading spaces more than 3
202 if typ != notList && match[1]-offset < 4 {
203 marker := line[match[3]-1]
204 if !list.CanContinue(marker, typ == orderedList) {
205 return Close
206 }
207 // Thematic Breaks take precedence over lists
208 if isThematicBreak(line[match[3]-1:], 0) {
209 isHeading := false
210 last := pc.LastOpenedBlock().Node
211 if ast.IsParagraph(last) {
212 c, ok := matchesSetextHeadingBar(line[match[3]-1:])
213 if ok && c == '-' {
214 isHeading = true
215 }
216 }
217 if !isHeading {
218 return Close
219 }
220 }
221 return Continue | HasChildren
222 }
223 }
224 if !lastIsEmpty {
225 return Close
226 }
227 }
228
229 if lastIsEmpty && indent < offset {
230 return Close
231 }
232
233 // Non empty items can not exist next to an empty list item
234 // with blank lines. So we need to close the current list
235 //
236 // -
237 //
238 // foo
239 //
240 // -> 1 list with 1 blank items and 1 paragraph
241 if pc.Get(emptyListItemWithBlankLines) != nil {
242 return Close
243 }
244 return Continue | HasChildren
245}
246
247func (b *listParser) Close(node ast.Node, reader text.Reader, pc Context) {
248 list := node.(*ast.List)
249
250 for c := node.FirstChild(); c != nil && list.IsTight; c = c.NextSibling() {
251 if c.FirstChild() != nil && c.FirstChild() != c.LastChild() {
252 for c1 := c.FirstChild().NextSibling(); c1 != nil; c1 = c1.NextSibling() {
253 if bl, ok := c1.(ast.Node); ok && bl.HasBlankPreviousLines() {
254 list.IsTight = false
255 break
256 }
257 }
258 }
259 if c != node.FirstChild() {
260 if bl, ok := c.(ast.Node); ok && bl.HasBlankPreviousLines() {
261 list.IsTight = false
262 }
263 }
264 }
265
266 if list.IsTight {
267 for child := node.FirstChild(); child != nil; child = child.NextSibling() {
268 for gc := child.FirstChild(); gc != nil; {
269 paragraph, ok := gc.(*ast.Paragraph)
270 gc = gc.NextSibling()
271 if ok {
272 textBlock := ast.NewTextBlock()
273 textBlock.SetLines(paragraph.Lines())
274 child.ReplaceChild(child, paragraph, textBlock)
275 }
276 }
277 }
278 }
279}
280
281func (b *listParser) CanInterruptParagraph() bool {
282 return true
283}
284
285func (b *listParser) CanAcceptIndentedLine() bool {
286 return false
287}
diff --git a/vendor/github.com/yuin/goldmark/parser/list_item.go b/vendor/github.com/yuin/goldmark/parser/list_item.go
new file mode 100644
index 0000000..81357a9
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/list_item.go
@@ -0,0 +1,90 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type listItemParser struct {
10}
11
12var defaultListItemParser = &listItemParser{}
13
14// NewListItemParser returns a new BlockParser that
15// parses list items.
16func NewListItemParser() BlockParser {
17 return defaultListItemParser
18}
19
20func (b *listItemParser) Trigger() []byte {
21 return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
22}
23
24func (b *listItemParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
25 list, lok := parent.(*ast.List)
26 if !lok { // list item must be a child of a list
27 return nil, NoChildren
28 }
29 offset := lastOffset(list)
30 line, _ := reader.PeekLine()
31 match, typ := matchesListItem(line, false)
32 if typ == notList {
33 return nil, NoChildren
34 }
35 if match[1]-offset > 3 {
36 return nil, NoChildren
37 }
38
39 pc.Set(emptyListItemWithBlankLines, nil)
40
41 itemOffset := calcListOffset(line, match)
42 node := ast.NewListItem(match[3] + itemOffset)
43 if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
44 return node, NoChildren
45 }
46
47 pos, padding := util.IndentPosition(line[match[4]:], match[4], itemOffset)
48 child := match[3] + pos
49 reader.AdvanceAndSetPadding(child, padding)
50 return node, HasChildren
51}
52
53func (b *listItemParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
54 line, _ := reader.PeekLine()
55 if util.IsBlank(line) {
56 reader.Advance(len(line) - 1)
57 return Continue | HasChildren
58 }
59
60 offset := lastOffset(node.Parent())
61 isEmpty := node.ChildCount() == 0
62 indent, _ := util.IndentWidth(line, reader.LineOffset())
63 if (isEmpty || indent < offset) && indent < 4 {
64 _, typ := matchesListItem(line, true)
65 // new list item found
66 if typ != notList {
67 pc.Set(skipListParserKey, listItemFlagValue)
68 return Close
69 }
70 if !isEmpty {
71 return Close
72 }
73 }
74 pos, padding := util.IndentPosition(line, reader.LineOffset(), offset)
75 reader.AdvanceAndSetPadding(pos, padding)
76
77 return Continue | HasChildren
78}
79
80func (b *listItemParser) Close(node ast.Node, reader text.Reader, pc Context) {
81 // nothing to do
82}
83
84func (b *listItemParser) CanInterruptParagraph() bool {
85 return true
86}
87
88func (b *listItemParser) CanAcceptIndentedLine() bool {
89 return false
90}
diff --git a/vendor/github.com/yuin/goldmark/parser/paragraph.go b/vendor/github.com/yuin/goldmark/parser/paragraph.go
new file mode 100644
index 0000000..9d3fa38
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/paragraph.go
@@ -0,0 +1,72 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type paragraphParser struct {
10}
11
12var defaultParagraphParser = &paragraphParser{}
13
14// NewParagraphParser returns a new BlockParser that
15// parses paragraphs.
16func NewParagraphParser() BlockParser {
17 return defaultParagraphParser
18}
19
20func (b *paragraphParser) Trigger() []byte {
21 return nil
22}
23
24func (b *paragraphParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
25 _, segment := reader.PeekLine()
26 segment = segment.TrimLeftSpace(reader.Source())
27 if segment.IsEmpty() {
28 return nil, NoChildren
29 }
30 node := ast.NewParagraph()
31 node.Lines().Append(segment)
32 reader.Advance(segment.Len() - 1)
33 return node, NoChildren
34}
35
36func (b *paragraphParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
37 line, segment := reader.PeekLine()
38 if util.IsBlank(line) {
39 return Close
40 }
41 node.Lines().Append(segment)
42 reader.Advance(segment.Len() - 1)
43 return Continue | NoChildren
44}
45
46func (b *paragraphParser) Close(node ast.Node, reader text.Reader, pc Context) {
47 lines := node.Lines()
48 if lines.Len() != 0 {
49 // trim leading spaces
50 for i := 0; i < lines.Len(); i++ {
51 l := lines.At(i)
52 lines.Set(i, l.TrimLeftSpace(reader.Source()))
53 }
54
55 // trim trailing spaces
56 length := lines.Len()
57 lastLine := node.Lines().At(length - 1)
58 node.Lines().Set(length-1, lastLine.TrimRightSpace(reader.Source()))
59 }
60 if lines.Len() == 0 {
61 node.Parent().RemoveChild(node.Parent(), node)
62 return
63 }
64}
65
66func (b *paragraphParser) CanInterruptParagraph() bool {
67 return false
68}
69
70func (b *paragraphParser) CanAcceptIndentedLine() bool {
71 return false
72}
diff --git a/vendor/github.com/yuin/goldmark/parser/parser.go b/vendor/github.com/yuin/goldmark/parser/parser.go
new file mode 100644
index 0000000..a823692
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/parser.go
@@ -0,0 +1,1253 @@
1// Package parser contains stuff that are related to parsing a Markdown text.
2package parser
3
4import (
5 "fmt"
6 "strings"
7 "sync"
8
9 "github.com/yuin/goldmark/ast"
10 "github.com/yuin/goldmark/text"
11 "github.com/yuin/goldmark/util"
12)
13
14// A Reference interface represents a link reference in Markdown text.
15type Reference interface {
16 // String implements Stringer.
17 String() string
18
19 // Label returns a label of the reference.
20 Label() []byte
21
22 // Destination returns a destination(URL) of the reference.
23 Destination() []byte
24
25 // Title returns a title of the reference.
26 Title() []byte
27}
28
29type reference struct {
30 label []byte
31 destination []byte
32 title []byte
33}
34
35// NewReference returns a new Reference.
36func NewReference(label, destination, title []byte) Reference {
37 return &reference{label, destination, title}
38}
39
40func (r *reference) Label() []byte {
41 return r.label
42}
43
44func (r *reference) Destination() []byte {
45 return r.destination
46}
47
48func (r *reference) Title() []byte {
49 return r.title
50}
51
52func (r *reference) String() string {
53 return fmt.Sprintf("Reference{Label:%s, Destination:%s, Title:%s}", r.label, r.destination, r.title)
54}
55
56// An IDs interface is a collection of the element ids.
57type IDs interface {
58 // Generate generates a new element id.
59 Generate(value []byte, kind ast.NodeKind) []byte
60
61 // Put puts a given element id to the used ids table.
62 Put(value []byte)
63}
64
65type ids struct {
66 values map[string]bool
67}
68
69func newIDs() IDs {
70 return &ids{
71 values: map[string]bool{},
72 }
73}
74
75func (s *ids) Generate(value []byte, kind ast.NodeKind) []byte {
76 value = util.TrimLeftSpace(value)
77 value = util.TrimRightSpace(value)
78 result := []byte{}
79 for i := 0; i < len(value); {
80 v := value[i]
81 l := util.UTF8Len(v)
82 i += int(l)
83 if l != 1 {
84 continue
85 }
86 if util.IsAlphaNumeric(v) {
87 if 'A' <= v && v <= 'Z' {
88 v += 'a' - 'A'
89 }
90 result = append(result, v)
91 } else if util.IsSpace(v) || v == '-' || v == '_' {
92 result = append(result, '-')
93 }
94 }
95 if len(result) == 0 {
96 if kind == ast.KindHeading {
97 result = []byte("heading")
98 } else {
99 result = []byte("id")
100 }
101 }
102 if _, ok := s.values[util.BytesToReadOnlyString(result)]; !ok {
103 s.values[util.BytesToReadOnlyString(result)] = true
104 return result
105 }
106 for i := 1; ; i++ {
107 newResult := fmt.Sprintf("%s-%d", result, i)
108 if _, ok := s.values[newResult]; !ok {
109 s.values[newResult] = true
110 return []byte(newResult)
111 }
112
113 }
114}
115
116func (s *ids) Put(value []byte) {
117 s.values[util.BytesToReadOnlyString(value)] = true
118}
119
120// ContextKey is a key that is used to set arbitrary values to the context.
121type ContextKey int
122
123// ContextKeyMax is a maximum value of the ContextKey.
124var ContextKeyMax ContextKey
125
126// NewContextKey return a new ContextKey value.
127func NewContextKey() ContextKey {
128 ContextKeyMax++
129 return ContextKeyMax
130}
131
132// A Context interface holds a information that are necessary to parse
133// Markdown text.
134type Context interface {
135 // String implements Stringer.
136 String() string
137
138 // Get returns a value associated with the given key.
139 Get(ContextKey) interface{}
140
141 // ComputeIfAbsent computes a value if a value associated with the given key is absent and returns the value.
142 ComputeIfAbsent(ContextKey, func() interface{}) interface{}
143
144 // Set sets the given value to the context.
145 Set(ContextKey, interface{})
146
147 // AddReference adds the given reference to this context.
148 AddReference(Reference)
149
150 // Reference returns (a reference, true) if a reference associated with
151 // the given label exists, otherwise (nil, false).
152 Reference(label string) (Reference, bool)
153
154 // References returns a list of references.
155 References() []Reference
156
157 // IDs returns a collection of the element ids.
158 IDs() IDs
159
160 // BlockOffset returns a first non-space character position on current line.
161 // This value is valid only for BlockParser.Open.
162 // BlockOffset returns -1 if current line is blank.
163 BlockOffset() int
164
165 // BlockOffset sets a first non-space character position on current line.
166 // This value is valid only for BlockParser.Open.
167 SetBlockOffset(int)
168
169 // BlockIndent returns an indent width on current line.
170 // This value is valid only for BlockParser.Open.
171 // BlockIndent returns -1 if current line is blank.
172 BlockIndent() int
173
174 // BlockIndent sets an indent width on current line.
175 // This value is valid only for BlockParser.Open.
176 SetBlockIndent(int)
177
178 // FirstDelimiter returns a first delimiter of the current delimiter list.
179 FirstDelimiter() *Delimiter
180
181 // LastDelimiter returns a last delimiter of the current delimiter list.
182 LastDelimiter() *Delimiter
183
184 // PushDelimiter appends the given delimiter to the tail of the current
185 // delimiter list.
186 PushDelimiter(delimiter *Delimiter)
187
188 // RemoveDelimiter removes the given delimiter from the current delimiter list.
189 RemoveDelimiter(d *Delimiter)
190
191 // ClearDelimiters clears the current delimiter list.
192 ClearDelimiters(bottom ast.Node)
193
194 // OpenedBlocks returns a list of nodes that are currently in parsing.
195 OpenedBlocks() []Block
196
197 // SetOpenedBlocks sets a list of nodes that are currently in parsing.
198 SetOpenedBlocks([]Block)
199
200 // LastOpenedBlock returns a last node that is currently in parsing.
201 LastOpenedBlock() Block
202
203 // IsInLinkLabel returns true if current position seems to be in link label.
204 IsInLinkLabel() bool
205}
206
207// A ContextConfig struct is a data structure that holds configuration of the Context.
208type ContextConfig struct {
209 IDs IDs
210}
211
212// An ContextOption is a functional option type for the Context.
213type ContextOption func(*ContextConfig)
214
215// WithIDs is a functional option for the Context.
216func WithIDs(ids IDs) ContextOption {
217 return func(c *ContextConfig) {
218 c.IDs = ids
219 }
220}
221
222type parseContext struct {
223 store []interface{}
224 ids IDs
225 refs map[string]Reference
226 blockOffset int
227 blockIndent int
228 delimiters *Delimiter
229 lastDelimiter *Delimiter
230 openedBlocks []Block
231}
232
233// NewContext returns a new Context.
234func NewContext(options ...ContextOption) Context {
235 cfg := &ContextConfig{
236 IDs: newIDs(),
237 }
238 for _, option := range options {
239 option(cfg)
240 }
241
242 return &parseContext{
243 store: make([]interface{}, ContextKeyMax+1),
244 refs: map[string]Reference{},
245 ids: cfg.IDs,
246 blockOffset: -1,
247 blockIndent: -1,
248 delimiters: nil,
249 lastDelimiter: nil,
250 openedBlocks: []Block{},
251 }
252}
253
254func (p *parseContext) Get(key ContextKey) interface{} {
255 return p.store[key]
256}
257
258func (p *parseContext) ComputeIfAbsent(key ContextKey, f func() interface{}) interface{} {
259 v := p.store[key]
260 if v == nil {
261 v = f()
262 p.store[key] = v
263 }
264 return v
265}
266
267func (p *parseContext) Set(key ContextKey, value interface{}) {
268 p.store[key] = value
269}
270
271func (p *parseContext) IDs() IDs {
272 return p.ids
273}
274
275func (p *parseContext) BlockOffset() int {
276 return p.blockOffset
277}
278
279func (p *parseContext) SetBlockOffset(v int) {
280 p.blockOffset = v
281}
282
283func (p *parseContext) BlockIndent() int {
284 return p.blockIndent
285}
286
287func (p *parseContext) SetBlockIndent(v int) {
288 p.blockIndent = v
289}
290
291func (p *parseContext) LastDelimiter() *Delimiter {
292 return p.lastDelimiter
293}
294
295func (p *parseContext) FirstDelimiter() *Delimiter {
296 return p.delimiters
297}
298
299func (p *parseContext) PushDelimiter(d *Delimiter) {
300 if p.delimiters == nil {
301 p.delimiters = d
302 p.lastDelimiter = d
303 } else {
304 l := p.lastDelimiter
305 p.lastDelimiter = d
306 l.NextDelimiter = d
307 d.PreviousDelimiter = l
308 }
309}
310
311func (p *parseContext) RemoveDelimiter(d *Delimiter) {
312 if d.PreviousDelimiter == nil {
313 p.delimiters = d.NextDelimiter
314 } else {
315 d.PreviousDelimiter.NextDelimiter = d.NextDelimiter
316 if d.NextDelimiter != nil {
317 d.NextDelimiter.PreviousDelimiter = d.PreviousDelimiter
318 }
319 }
320 if d.NextDelimiter == nil {
321 p.lastDelimiter = d.PreviousDelimiter
322 }
323 if p.delimiters != nil {
324 p.delimiters.PreviousDelimiter = nil
325 }
326 if p.lastDelimiter != nil {
327 p.lastDelimiter.NextDelimiter = nil
328 }
329 d.NextDelimiter = nil
330 d.PreviousDelimiter = nil
331 if d.Length != 0 {
332 ast.MergeOrReplaceTextSegment(d.Parent(), d, d.Segment)
333 } else {
334 d.Parent().RemoveChild(d.Parent(), d)
335 }
336}
337
338func (p *parseContext) ClearDelimiters(bottom ast.Node) {
339 if p.lastDelimiter == nil {
340 return
341 }
342 var c ast.Node
343 for c = p.lastDelimiter; c != nil && c != bottom; {
344 prev := c.PreviousSibling()
345 if d, ok := c.(*Delimiter); ok {
346 p.RemoveDelimiter(d)
347 }
348 c = prev
349 }
350}
351
352func (p *parseContext) AddReference(ref Reference) {
353 key := util.ToLinkReference(ref.Label())
354 if _, ok := p.refs[key]; !ok {
355 p.refs[key] = ref
356 }
357}
358
359func (p *parseContext) Reference(label string) (Reference, bool) {
360 v, ok := p.refs[label]
361 return v, ok
362}
363
364func (p *parseContext) References() []Reference {
365 ret := make([]Reference, 0, len(p.refs))
366 for _, v := range p.refs {
367 ret = append(ret, v)
368 }
369 return ret
370}
371
372func (p *parseContext) String() string {
373 refs := []string{}
374 for _, r := range p.refs {
375 refs = append(refs, r.String())
376 }
377
378 return fmt.Sprintf("Context{Store:%#v, Refs:%s}", p.store, strings.Join(refs, ","))
379}
380
381func (p *parseContext) OpenedBlocks() []Block {
382 return p.openedBlocks
383}
384
385func (p *parseContext) SetOpenedBlocks(v []Block) {
386 p.openedBlocks = v
387}
388
389func (p *parseContext) LastOpenedBlock() Block {
390 if l := len(p.openedBlocks); l != 0 {
391 return p.openedBlocks[l-1]
392 }
393 return Block{}
394}
395
396func (p *parseContext) IsInLinkLabel() bool {
397 tlist := p.Get(linkLabelStateKey)
398 return tlist != nil
399}
400
401// State represents parser's state.
402// State is designed to use as a bit flag.
403type State int
404
405const (
406 none State = 1 << iota
407
408 // Continue indicates parser can continue parsing.
409 Continue
410
411 // Close indicates parser cannot parse anymore.
412 Close
413
414 // HasChildren indicates parser may have child blocks.
415 HasChildren
416
417 // NoChildren indicates parser does not have child blocks.
418 NoChildren
419
420 // RequireParagraph indicates parser requires that the last node
421 // must be a paragraph and is not converted to other nodes by
422 // ParagraphTransformers.
423 RequireParagraph
424)
425
426// A Config struct is a data structure that holds configuration of the Parser.
427type Config struct {
428 Options map[OptionName]interface{}
429 BlockParsers util.PrioritizedSlice /*<BlockParser>*/
430 InlineParsers util.PrioritizedSlice /*<InlineParser>*/
431 ParagraphTransformers util.PrioritizedSlice /*<ParagraphTransformer>*/
432 ASTTransformers util.PrioritizedSlice /*<ASTTransformer>*/
433 EscapedSpace bool
434}
435
436// NewConfig returns a new Config.
437func NewConfig() *Config {
438 return &Config{
439 Options: map[OptionName]interface{}{},
440 BlockParsers: util.PrioritizedSlice{},
441 InlineParsers: util.PrioritizedSlice{},
442 ParagraphTransformers: util.PrioritizedSlice{},
443 ASTTransformers: util.PrioritizedSlice{},
444 }
445}
446
447// An Option interface is a functional option type for the Parser.
448type Option interface {
449 SetParserOption(*Config)
450}
451
452// OptionName is a name of parser options.
453type OptionName string
454
455// Attribute is an option name that spacify attributes of elements.
456const optAttribute OptionName = "Attribute"
457
458type withAttribute struct {
459}
460
461func (o *withAttribute) SetParserOption(c *Config) {
462 c.Options[optAttribute] = true
463}
464
465// WithAttribute is a functional option that enables custom attributes.
466func WithAttribute() Option {
467 return &withAttribute{}
468}
469
470// A Parser interface parses Markdown text into AST nodes.
471type Parser interface {
472 // Parse parses the given Markdown text into AST nodes.
473 Parse(reader text.Reader, opts ...ParseOption) ast.Node
474
475 // AddOption adds the given option to this parser.
476 AddOptions(...Option)
477}
478
479// A SetOptioner interface sets the given option to the object.
480type SetOptioner interface {
481 // SetOption sets the given option to the object.
482 // Unacceptable options may be passed.
483 // Thus implementations must ignore unacceptable options.
484 SetOption(name OptionName, value interface{})
485}
486
487// A BlockParser interface parses a block level element like Paragraph, List,
488// Blockquote etc.
489type BlockParser interface {
490 // Trigger returns a list of characters that triggers Parse method of
491 // this parser.
492 // If Trigger returns a nil, Open will be called with any lines.
493 Trigger() []byte
494
495 // Open parses the current line and returns a result of parsing.
496 //
497 // Open must not parse beyond the current line.
498 // If Open has been able to parse the current line, Open must advance a reader
499 // position by consumed byte length.
500 //
501 // If Open has not been able to parse the current line, Open should returns
502 // (nil, NoChildren). If Open has been able to parse the current line, Open
503 // should returns a new Block node and returns HasChildren or NoChildren.
504 Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State)
505
506 // Continue parses the current line and returns a result of parsing.
507 //
508 // Continue must not parse beyond the current line.
509 // If Continue has been able to parse the current line, Continue must advance
510 // a reader position by consumed byte length.
511 //
512 // If Continue has not been able to parse the current line, Continue should
513 // returns Close. If Continue has been able to parse the current line,
514 // Continue should returns (Continue | NoChildren) or
515 // (Continue | HasChildren)
516 Continue(node ast.Node, reader text.Reader, pc Context) State
517
518 // Close will be called when the parser returns Close.
519 Close(node ast.Node, reader text.Reader, pc Context)
520
521 // CanInterruptParagraph returns true if the parser can interrupt paragraphs,
522 // otherwise false.
523 CanInterruptParagraph() bool
524
525 // CanAcceptIndentedLine returns true if the parser can open new node when
526 // the given line is being indented more than 3 spaces.
527 CanAcceptIndentedLine() bool
528}
529
530// An InlineParser interface parses an inline level element like CodeSpan, Link etc.
531type InlineParser interface {
532 // Trigger returns a list of characters that triggers Parse method of
533 // this parser.
534 // Trigger characters must be a punctuation or a halfspace.
535 // Halfspaces triggers this parser when character is any spaces characters or
536 // a head of line
537 Trigger() []byte
538
539 // Parse parse the given block into an inline node.
540 //
541 // Parse can parse beyond the current line.
542 // If Parse has been able to parse the current line, it must advance a reader
543 // position by consumed byte length.
544 Parse(parent ast.Node, block text.Reader, pc Context) ast.Node
545}
546
547// A CloseBlocker interface is a callback function that will be
548// called when block is closed in the inline parsing.
549type CloseBlocker interface {
550 // CloseBlock will be called when a block is closed.
551 CloseBlock(parent ast.Node, block text.Reader, pc Context)
552}
553
554// A ParagraphTransformer transforms parsed Paragraph nodes.
555// For example, link references are searched in parsed Paragraphs.
556type ParagraphTransformer interface {
557 // Transform transforms the given paragraph.
558 Transform(node *ast.Paragraph, reader text.Reader, pc Context)
559}
560
561// ASTTransformer transforms entire Markdown document AST tree.
562type ASTTransformer interface {
563 // Transform transforms the given AST tree.
564 Transform(node *ast.Document, reader text.Reader, pc Context)
565}
566
567// DefaultBlockParsers returns a new list of default BlockParsers.
568// Priorities of default BlockParsers are:
569//
570// SetextHeadingParser, 100
571// ThematicBreakParser, 200
572// ListParser, 300
573// ListItemParser, 400
574// CodeBlockParser, 500
575// ATXHeadingParser, 600
576// FencedCodeBlockParser, 700
577// BlockquoteParser, 800
578// HTMLBlockParser, 900
579// ParagraphParser, 1000
580func DefaultBlockParsers() []util.PrioritizedValue {
581 return []util.PrioritizedValue{
582 util.Prioritized(NewSetextHeadingParser(), 100),
583 util.Prioritized(NewThematicBreakParser(), 200),
584 util.Prioritized(NewListParser(), 300),
585 util.Prioritized(NewListItemParser(), 400),
586 util.Prioritized(NewCodeBlockParser(), 500),
587 util.Prioritized(NewATXHeadingParser(), 600),
588 util.Prioritized(NewFencedCodeBlockParser(), 700),
589 util.Prioritized(NewBlockquoteParser(), 800),
590 util.Prioritized(NewHTMLBlockParser(), 900),
591 util.Prioritized(NewParagraphParser(), 1000),
592 }
593}
594
595// DefaultInlineParsers returns a new list of default InlineParsers.
596// Priorities of default InlineParsers are:
597//
598// CodeSpanParser, 100
599// LinkParser, 200
600// AutoLinkParser, 300
601// RawHTMLParser, 400
602// EmphasisParser, 500
603func DefaultInlineParsers() []util.PrioritizedValue {
604 return []util.PrioritizedValue{
605 util.Prioritized(NewCodeSpanParser(), 100),
606 util.Prioritized(NewLinkParser(), 200),
607 util.Prioritized(NewAutoLinkParser(), 300),
608 util.Prioritized(NewRawHTMLParser(), 400),
609 util.Prioritized(NewEmphasisParser(), 500),
610 }
611}
612
613// DefaultParagraphTransformers returns a new list of default ParagraphTransformers.
614// Priorities of default ParagraphTransformers are:
615//
616// LinkReferenceParagraphTransformer, 100
617func DefaultParagraphTransformers() []util.PrioritizedValue {
618 return []util.PrioritizedValue{
619 util.Prioritized(LinkReferenceParagraphTransformer, 100),
620 }
621}
622
623// A Block struct holds a node and correspond parser pair.
624type Block struct {
625 // Node is a BlockNode.
626 Node ast.Node
627 // Parser is a BlockParser.
628 Parser BlockParser
629}
630
631type parser struct {
632 options map[OptionName]interface{}
633 blockParsers [256][]BlockParser
634 freeBlockParsers []BlockParser
635 inlineParsers [256][]InlineParser
636 closeBlockers []CloseBlocker
637 paragraphTransformers []ParagraphTransformer
638 astTransformers []ASTTransformer
639 escapedSpace bool
640 config *Config
641 initSync sync.Once
642}
643
644type withBlockParsers struct {
645 value []util.PrioritizedValue
646}
647
648func (o *withBlockParsers) SetParserOption(c *Config) {
649 c.BlockParsers = append(c.BlockParsers, o.value...)
650}
651
652// WithBlockParsers is a functional option that allow you to add
653// BlockParsers to the parser.
654func WithBlockParsers(bs ...util.PrioritizedValue) Option {
655 return &withBlockParsers{bs}
656}
657
658type withInlineParsers struct {
659 value []util.PrioritizedValue
660}
661
662func (o *withInlineParsers) SetParserOption(c *Config) {
663 c.InlineParsers = append(c.InlineParsers, o.value...)
664}
665
666// WithInlineParsers is a functional option that allow you to add
667// InlineParsers to the parser.
668func WithInlineParsers(bs ...util.PrioritizedValue) Option {
669 return &withInlineParsers{bs}
670}
671
672type withParagraphTransformers struct {
673 value []util.PrioritizedValue
674}
675
676func (o *withParagraphTransformers) SetParserOption(c *Config) {
677 c.ParagraphTransformers = append(c.ParagraphTransformers, o.value...)
678}
679
680// WithParagraphTransformers is a functional option that allow you to add
681// ParagraphTransformers to the parser.
682func WithParagraphTransformers(ps ...util.PrioritizedValue) Option {
683 return &withParagraphTransformers{ps}
684}
685
686type withASTTransformers struct {
687 value []util.PrioritizedValue
688}
689
690func (o *withASTTransformers) SetParserOption(c *Config) {
691 c.ASTTransformers = append(c.ASTTransformers, o.value...)
692}
693
694// WithASTTransformers is a functional option that allow you to add
695// ASTTransformers to the parser.
696func WithASTTransformers(ps ...util.PrioritizedValue) Option {
697 return &withASTTransformers{ps}
698}
699
700type withEscapedSpace struct {
701}
702
703func (o *withEscapedSpace) SetParserOption(c *Config) {
704 c.EscapedSpace = true
705}
706
707// WithEscapedSpace is a functional option indicates that a '\' escaped half-space(0x20) should not trigger parsers.
708func WithEscapedSpace() Option {
709 return &withEscapedSpace{}
710}
711
712type withOption struct {
713 name OptionName
714 value interface{}
715}
716
717func (o *withOption) SetParserOption(c *Config) {
718 c.Options[o.name] = o.value
719}
720
721// WithOption is a functional option that allow you to set
722// an arbitrary option to the parser.
723func WithOption(name OptionName, value interface{}) Option {
724 return &withOption{name, value}
725}
726
727// NewParser returns a new Parser with given options.
728func NewParser(options ...Option) Parser {
729 config := NewConfig()
730 for _, opt := range options {
731 opt.SetParserOption(config)
732 }
733
734 p := &parser{
735 options: map[OptionName]interface{}{},
736 config: config,
737 }
738
739 return p
740}
741
742func (p *parser) AddOptions(opts ...Option) {
743 for _, opt := range opts {
744 opt.SetParserOption(p.config)
745 }
746}
747
748func (p *parser) addBlockParser(v util.PrioritizedValue, options map[OptionName]interface{}) {
749 bp, ok := v.Value.(BlockParser)
750 if !ok {
751 panic(fmt.Sprintf("%v is not a BlockParser", v.Value))
752 }
753 tcs := bp.Trigger()
754 so, ok := v.Value.(SetOptioner)
755 if ok {
756 for oname, ovalue := range options {
757 so.SetOption(oname, ovalue)
758 }
759 }
760 if tcs == nil {
761 p.freeBlockParsers = append(p.freeBlockParsers, bp)
762 } else {
763 for _, tc := range tcs {
764 if p.blockParsers[tc] == nil {
765 p.blockParsers[tc] = []BlockParser{}
766 }
767 p.blockParsers[tc] = append(p.blockParsers[tc], bp)
768 }
769 }
770}
771
772func (p *parser) addInlineParser(v util.PrioritizedValue, options map[OptionName]interface{}) {
773 ip, ok := v.Value.(InlineParser)
774 if !ok {
775 panic(fmt.Sprintf("%v is not a InlineParser", v.Value))
776 }
777 tcs := ip.Trigger()
778 so, ok := v.Value.(SetOptioner)
779 if ok {
780 for oname, ovalue := range options {
781 so.SetOption(oname, ovalue)
782 }
783 }
784 if cb, ok := ip.(CloseBlocker); ok {
785 p.closeBlockers = append(p.closeBlockers, cb)
786 }
787 for _, tc := range tcs {
788 if p.inlineParsers[tc] == nil {
789 p.inlineParsers[tc] = []InlineParser{}
790 }
791 p.inlineParsers[tc] = append(p.inlineParsers[tc], ip)
792 }
793}
794
795func (p *parser) addParagraphTransformer(v util.PrioritizedValue, options map[OptionName]interface{}) {
796 pt, ok := v.Value.(ParagraphTransformer)
797 if !ok {
798 panic(fmt.Sprintf("%v is not a ParagraphTransformer", v.Value))
799 }
800 so, ok := v.Value.(SetOptioner)
801 if ok {
802 for oname, ovalue := range options {
803 so.SetOption(oname, ovalue)
804 }
805 }
806 p.paragraphTransformers = append(p.paragraphTransformers, pt)
807}
808
809func (p *parser) addASTTransformer(v util.PrioritizedValue, options map[OptionName]interface{}) {
810 at, ok := v.Value.(ASTTransformer)
811 if !ok {
812 panic(fmt.Sprintf("%v is not a ASTTransformer", v.Value))
813 }
814 so, ok := v.Value.(SetOptioner)
815 if ok {
816 for oname, ovalue := range options {
817 so.SetOption(oname, ovalue)
818 }
819 }
820 p.astTransformers = append(p.astTransformers, at)
821}
822
823// A ParseConfig struct is a data structure that holds configuration of the Parser.Parse.
824type ParseConfig struct {
825 Context Context
826}
827
828// A ParseOption is a functional option type for the Parser.Parse.
829type ParseOption func(c *ParseConfig)
830
831// WithContext is a functional option that allow you to override
832// a default context.
833func WithContext(context Context) ParseOption {
834 return func(c *ParseConfig) {
835 c.Context = context
836 }
837}
838
839func (p *parser) Parse(reader text.Reader, opts ...ParseOption) ast.Node {
840 p.initSync.Do(func() {
841 p.config.BlockParsers.Sort()
842 for _, v := range p.config.BlockParsers {
843 p.addBlockParser(v, p.config.Options)
844 }
845 for i := range p.blockParsers {
846 if p.blockParsers[i] != nil {
847 p.blockParsers[i] = append(p.blockParsers[i], p.freeBlockParsers...)
848 }
849 }
850
851 p.config.InlineParsers.Sort()
852 for _, v := range p.config.InlineParsers {
853 p.addInlineParser(v, p.config.Options)
854 }
855 p.config.ParagraphTransformers.Sort()
856 for _, v := range p.config.ParagraphTransformers {
857 p.addParagraphTransformer(v, p.config.Options)
858 }
859 p.config.ASTTransformers.Sort()
860 for _, v := range p.config.ASTTransformers {
861 p.addASTTransformer(v, p.config.Options)
862 }
863 p.escapedSpace = p.config.EscapedSpace
864 p.config = nil
865 })
866 c := &ParseConfig{}
867 for _, opt := range opts {
868 opt(c)
869 }
870 if c.Context == nil {
871 c.Context = NewContext()
872 }
873 pc := c.Context
874 root := ast.NewDocument()
875 p.parseBlocks(root, reader, pc)
876
877 blockReader := text.NewBlockReader(reader.Source(), nil)
878 p.walkBlock(root, func(node ast.Node) {
879 p.parseBlock(blockReader, node, pc)
880 })
881 for _, at := range p.astTransformers {
882 at.Transform(root, reader, pc)
883 }
884 // root.Dump(reader.Source(), 0)
885 return root
886}
887
888func (p *parser) transformParagraph(node *ast.Paragraph, reader text.Reader, pc Context) bool {
889 for _, pt := range p.paragraphTransformers {
890 pt.Transform(node, reader, pc)
891 if node.Parent() == nil {
892 return true
893 }
894 }
895 return false
896}
897
898func (p *parser) closeBlocks(from, to int, reader text.Reader, pc Context) {
899 blocks := pc.OpenedBlocks()
900 for i := from; i >= to; i-- {
901 node := blocks[i].Node
902 paragraph, ok := node.(*ast.Paragraph)
903 if ok && node.Parent() != nil {
904 p.transformParagraph(paragraph, reader, pc)
905 }
906 if node.Parent() != nil { // closes only if node has not been transformed
907 blocks[i].Parser.Close(blocks[i].Node, reader, pc)
908 }
909 }
910 if from == len(blocks)-1 {
911 blocks = blocks[0:to]
912 } else {
913 blocks = append(blocks[0:to], blocks[from+1:]...)
914 }
915 pc.SetOpenedBlocks(blocks)
916}
917
918type blockOpenResult int
919
920const (
921 paragraphContinuation blockOpenResult = iota + 1
922 newBlocksOpened
923 noBlocksOpened
924)
925
926func (p *parser) openBlocks(parent ast.Node, blankLine bool, reader text.Reader, pc Context) blockOpenResult {
927 result := blockOpenResult(noBlocksOpened)
928 continuable := false
929 lastBlock := pc.LastOpenedBlock()
930 if lastBlock.Node != nil {
931 continuable = ast.IsParagraph(lastBlock.Node)
932 }
933retry:
934 var bps []BlockParser
935 line, _ := reader.PeekLine()
936 w, pos := util.IndentWidth(line, reader.LineOffset())
937 if w >= len(line) {
938 pc.SetBlockOffset(-1)
939 pc.SetBlockIndent(-1)
940 } else {
941 pc.SetBlockOffset(pos)
942 pc.SetBlockIndent(w)
943 }
944 if line == nil || line[0] == '\n' {
945 goto continuable
946 }
947 bps = p.freeBlockParsers
948 if pos < len(line) {
949 bps = p.blockParsers[line[pos]]
950 if bps == nil {
951 bps = p.freeBlockParsers
952 }
953 }
954 if bps == nil {
955 goto continuable
956 }
957
958 for _, bp := range bps {
959 if continuable && result == noBlocksOpened && !bp.CanInterruptParagraph() {
960 continue
961 }
962 if w > 3 && !bp.CanAcceptIndentedLine() {
963 continue
964 }
965 lastBlock = pc.LastOpenedBlock()
966 last := lastBlock.Node
967 node, state := bp.Open(parent, reader, pc)
968 if node != nil {
969 // Parser requires last node to be a paragraph.
970 // With table extension:
971 //
972 // 0
973 // -:
974 // -
975 //
976 // '-' on 3rd line seems a Setext heading because 1st and 2nd lines
977 // are being paragraph when the Settext heading parser tries to parse the 3rd
978 // line.
979 // But 1st line and 2nd line are a table. Thus this paragraph will be transformed
980 // by a paragraph transformer. So this text should be converted to a table and
981 // an empty list.
982 if state&RequireParagraph != 0 {
983 if last == parent.LastChild() {
984 // Opened paragraph may be transformed by ParagraphTransformers in
985 // closeBlocks().
986 lastBlock.Parser.Close(last, reader, pc)
987 blocks := pc.OpenedBlocks()
988 pc.SetOpenedBlocks(blocks[0 : len(blocks)-1])
989 if p.transformParagraph(last.(*ast.Paragraph), reader, pc) {
990 // Paragraph has been transformed.
991 // So this parser is considered as failing.
992 continuable = false
993 goto retry
994 }
995 }
996 }
997 node.SetBlankPreviousLines(blankLine)
998 if last != nil && last.Parent() == nil {
999 lastPos := len(pc.OpenedBlocks()) - 1
1000 p.closeBlocks(lastPos, lastPos, reader, pc)
1001 }
1002 parent.AppendChild(parent, node)
1003 result = newBlocksOpened
1004 be := Block{node, bp}
1005 pc.SetOpenedBlocks(append(pc.OpenedBlocks(), be))
1006 if state&HasChildren != 0 {
1007 parent = node
1008 goto retry // try child block
1009 }
1010 break // no children, can not open more blocks on this line
1011 }
1012 }
1013
1014continuable:
1015 if result == noBlocksOpened && continuable {
1016 state := lastBlock.Parser.Continue(lastBlock.Node, reader, pc)
1017 if state&Continue != 0 {
1018 result = paragraphContinuation
1019 }
1020 }
1021 return result
1022}
1023
1024type lineStat struct {
1025 lineNum int
1026 level int
1027 isBlank bool
1028}
1029
1030func isBlankLine(lineNum, level int, stats []lineStat) bool {
1031 ret := true
1032 for i := len(stats) - 1 - level; i >= 0; i-- {
1033 ret = false
1034 s := stats[i]
1035 if s.lineNum == lineNum {
1036 if s.level < level && s.isBlank {
1037 return true
1038 } else if s.level == level {
1039 return s.isBlank
1040 }
1041 }
1042 if s.lineNum < lineNum {
1043 return ret
1044 }
1045 }
1046 return ret
1047}
1048
1049func (p *parser) parseBlocks(parent ast.Node, reader text.Reader, pc Context) {
1050 pc.SetOpenedBlocks([]Block{})
1051 blankLines := make([]lineStat, 0, 128)
1052 isBlank := false
1053 for { // process blocks separated by blank lines
1054 _, lines, ok := reader.SkipBlankLines()
1055 if !ok {
1056 return
1057 }
1058 lineNum, _ := reader.Position()
1059 if lines != 0 {
1060 blankLines = blankLines[0:0]
1061 l := len(pc.OpenedBlocks())
1062 for i := 0; i < l; i++ {
1063 blankLines = append(blankLines, lineStat{lineNum - 1, i, lines != 0})
1064 }
1065 }
1066 isBlank = isBlankLine(lineNum-1, 0, blankLines)
1067 // first, we try to open blocks
1068 if p.openBlocks(parent, isBlank, reader, pc) != newBlocksOpened {
1069 return
1070 }
1071 reader.AdvanceLine()
1072 for { // process opened blocks line by line
1073 openedBlocks := pc.OpenedBlocks()
1074 l := len(openedBlocks)
1075 if l == 0 {
1076 break
1077 }
1078 lastIndex := l - 1
1079 for i := 0; i < l; i++ {
1080 be := openedBlocks[i]
1081 line, _ := reader.PeekLine()
1082 if line == nil {
1083 p.closeBlocks(lastIndex, 0, reader, pc)
1084 reader.AdvanceLine()
1085 return
1086 }
1087 lineNum, _ := reader.Position()
1088 blankLines = append(blankLines, lineStat{lineNum, i, util.IsBlank(line)})
1089 // If node is a paragraph, p.openBlocks determines whether it is continuable.
1090 // So we do not process paragraphs here.
1091 if !ast.IsParagraph(be.Node) {
1092 state := be.Parser.Continue(be.Node, reader, pc)
1093 if state&Continue != 0 {
1094 // When current node is a container block and has no children,
1095 // we try to open new child nodes
1096 if state&HasChildren != 0 && i == lastIndex {
1097 isBlank = isBlankLine(lineNum-1, i, blankLines)
1098 p.openBlocks(be.Node, isBlank, reader, pc)
1099 break
1100 }
1101 continue
1102 }
1103 }
1104 // current node may be closed or lazy continuation
1105 isBlank = isBlankLine(lineNum-1, i, blankLines)
1106 thisParent := parent
1107 if i != 0 {
1108 thisParent = openedBlocks[i-1].Node
1109 }
1110 lastNode := openedBlocks[lastIndex].Node
1111 result := p.openBlocks(thisParent, isBlank, reader, pc)
1112 if result != paragraphContinuation {
1113 // lastNode is a paragraph and was transformed by the paragraph
1114 // transformers.
1115 if openedBlocks[lastIndex].Node != lastNode {
1116 lastIndex--
1117 }
1118 p.closeBlocks(lastIndex, i, reader, pc)
1119 }
1120 break
1121 }
1122
1123 reader.AdvanceLine()
1124 }
1125 }
1126}
1127
1128func (p *parser) walkBlock(block ast.Node, cb func(node ast.Node)) {
1129 for c := block.FirstChild(); c != nil; c = c.NextSibling() {
1130 p.walkBlock(c, cb)
1131 }
1132 cb(block)
1133}
1134
1135const (
1136 lineBreakHard uint8 = 1 << iota
1137 lineBreakSoft
1138 lineBreakVisible
1139)
1140
1141func (p *parser) parseBlock(block text.BlockReader, parent ast.Node, pc Context) {
1142 if parent.IsRaw() {
1143 return
1144 }
1145 escaped := false
1146 source := block.Source()
1147 block.Reset(parent.Lines())
1148 for {
1149 retry:
1150 line, _ := block.PeekLine()
1151 if line == nil {
1152 break
1153 }
1154 lineLength := len(line)
1155 var lineBreakFlags uint8 = 0
1156 hasNewLine := line[lineLength-1] == '\n'
1157 if ((lineLength >= 3 && line[lineLength-2] == '\\' && line[lineLength-3] != '\\') || (lineLength == 2 && line[lineLength-2] == '\\')) && hasNewLine { // ends with \\n
1158 lineLength -= 2
1159 lineBreakFlags |= lineBreakHard | lineBreakVisible
1160 } else if ((lineLength >= 4 && line[lineLength-3] == '\\' && line[lineLength-2] == '\r' && line[lineLength-4] != '\\') || (lineLength == 3 && line[lineLength-3] == '\\' && line[lineLength-2] == '\r')) && hasNewLine { // ends with \\r\n
1161 lineLength -= 3
1162 lineBreakFlags |= lineBreakHard | lineBreakVisible
1163 } else if lineLength >= 3 && line[lineLength-3] == ' ' && line[lineLength-2] == ' ' && hasNewLine { // ends with [space][space]\n
1164 lineLength -= 3
1165 lineBreakFlags |= lineBreakHard
1166 } else if lineLength >= 4 && line[lineLength-4] == ' ' && line[lineLength-3] == ' ' && line[lineLength-2] == '\r' && hasNewLine { // ends with [space][space]\r\n
1167 lineLength -= 4
1168 lineBreakFlags |= lineBreakHard
1169 } else if hasNewLine {
1170 // If the line ends with a newline character, but it is not a hardlineBreak, then it is a softLinebreak
1171 // If the line ends with a hardlineBreak, then it cannot end with a softLinebreak
1172 // See https://spec.commonmark.org/0.30/#soft-line-breaks
1173 lineBreakFlags |= lineBreakSoft
1174 }
1175
1176 l, startPosition := block.Position()
1177 n := 0
1178 for i := 0; i < lineLength; i++ {
1179 c := line[i]
1180 if c == '\n' {
1181 break
1182 }
1183 isSpace := util.IsSpace(c) && c != '\r' && c != '\n'
1184 isPunct := util.IsPunct(c)
1185 if (isPunct && !escaped) || isSpace && !(escaped && p.escapedSpace) || i == 0 {
1186 parserChar := c
1187 if isSpace || (i == 0 && !isPunct) {
1188 parserChar = ' '
1189 }
1190 ips := p.inlineParsers[parserChar]
1191 if ips != nil {
1192 block.Advance(n)
1193 n = 0
1194 savedLine, savedPosition := block.Position()
1195 if i != 0 {
1196 _, currentPosition := block.Position()
1197 ast.MergeOrAppendTextSegment(parent, startPosition.Between(currentPosition))
1198 _, startPosition = block.Position()
1199 }
1200 var inlineNode ast.Node
1201 for _, ip := range ips {
1202 inlineNode = ip.Parse(parent, block, pc)
1203 if inlineNode != nil {
1204 break
1205 }
1206 block.SetPosition(savedLine, savedPosition)
1207 }
1208 if inlineNode != nil {
1209 parent.AppendChild(parent, inlineNode)
1210 goto retry
1211 }
1212 }
1213 }
1214 if escaped {
1215 escaped = false
1216 n++
1217 continue
1218 }
1219
1220 if c == '\\' {
1221 escaped = true
1222 n++
1223 continue
1224 }
1225
1226 escaped = false
1227 n++
1228 }
1229 if n != 0 {
1230 block.Advance(n)
1231 }
1232 currentL, currentPosition := block.Position()
1233 if l != currentL {
1234 continue
1235 }
1236 diff := startPosition.Between(currentPosition)
1237 var text *ast.Text
1238 if lineBreakFlags&(lineBreakHard|lineBreakVisible) == lineBreakHard|lineBreakVisible {
1239 text = ast.NewTextSegment(diff)
1240 } else {
1241 text = ast.NewTextSegment(diff.TrimRightSpace(source))
1242 }
1243 text.SetSoftLineBreak(lineBreakFlags&lineBreakSoft != 0)
1244 text.SetHardLineBreak(lineBreakFlags&lineBreakHard != 0)
1245 parent.AppendChild(parent, text)
1246 block.AdvanceLine()
1247 }
1248
1249 ProcessDelimiters(nil, pc)
1250 for _, ip := range p.closeBlockers {
1251 ip.CloseBlock(parent, block, pc)
1252 }
1253}
diff --git a/vendor/github.com/yuin/goldmark/parser/raw_html.go b/vendor/github.com/yuin/goldmark/parser/raw_html.go
new file mode 100644
index 0000000..55b9a99
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/raw_html.go
@@ -0,0 +1,163 @@
1package parser
2
3import (
4 "bytes"
5 "regexp"
6
7 "github.com/yuin/goldmark/ast"
8 "github.com/yuin/goldmark/text"
9 "github.com/yuin/goldmark/util"
10)
11
12type rawHTMLParser struct {
13}
14
15var defaultRawHTMLParser = &rawHTMLParser{}
16
17// NewRawHTMLParser return a new InlineParser that can parse
18// inline htmls
19func NewRawHTMLParser() InlineParser {
20 return defaultRawHTMLParser
21}
22
23func (s *rawHTMLParser) Trigger() []byte {
24 return []byte{'<'}
25}
26
27func (s *rawHTMLParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
28 line, _ := block.PeekLine()
29 if len(line) > 1 && util.IsAlphaNumeric(line[1]) {
30 return s.parseMultiLineRegexp(openTagRegexp, block, pc)
31 }
32 if len(line) > 2 && line[1] == '/' && util.IsAlphaNumeric(line[2]) {
33 return s.parseMultiLineRegexp(closeTagRegexp, block, pc)
34 }
35 if bytes.HasPrefix(line, openComment) {
36 return s.parseComment(block, pc)
37 }
38 if bytes.HasPrefix(line, openProcessingInstruction) {
39 return s.parseUntil(block, closeProcessingInstruction, pc)
40 }
41 if len(line) > 2 && line[1] == '!' && line[2] >= 'A' && line[2] <= 'Z' {
42 return s.parseUntil(block, closeDecl, pc)
43 }
44 if bytes.HasPrefix(line, openCDATA) {
45 return s.parseUntil(block, closeCDATA, pc)
46 }
47 return nil
48}
49
50var tagnamePattern = `([A-Za-z][A-Za-z0-9-]*)`
51
52var attributePattern = `(?:[\r\n \t]+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:[\r\n \t]*=[\r\n \t]*(?:[^\"'=<>` + "`" + `\x00-\x20]+|'[^']*'|"[^"]*"))?)`
53var openTagRegexp = regexp.MustCompile("^<" + tagnamePattern + attributePattern + `*[ \t]*/?>`)
54var closeTagRegexp = regexp.MustCompile("^</" + tagnamePattern + `\s*>`)
55
56var openProcessingInstruction = []byte("<?")
57var closeProcessingInstruction = []byte("?>")
58var openCDATA = []byte("<![CDATA[")
59var closeCDATA = []byte("]]>")
60var closeDecl = []byte(">")
61var emptyComment = []byte("<!---->")
62var invalidComment1 = []byte("<!-->")
63var invalidComment2 = []byte("<!--->")
64var openComment = []byte("<!--")
65var closeComment = []byte("-->")
66var doubleHyphen = []byte("--")
67
68func (s *rawHTMLParser) parseComment(block text.Reader, pc Context) ast.Node {
69 savedLine, savedSegment := block.Position()
70 node := ast.NewRawHTML()
71 line, segment := block.PeekLine()
72 if bytes.HasPrefix(line, emptyComment) {
73 node.Segments.Append(segment.WithStop(segment.Start + len(emptyComment)))
74 block.Advance(len(emptyComment))
75 return node
76 }
77 if bytes.HasPrefix(line, invalidComment1) || bytes.HasPrefix(line, invalidComment2) {
78 return nil
79 }
80 offset := len(openComment)
81 line = line[offset:]
82 for {
83 hindex := bytes.Index(line, doubleHyphen)
84 if hindex > -1 {
85 hindex += offset
86 }
87 index := bytes.Index(line, closeComment) + offset
88 if index > -1 && hindex == index {
89 if index == 0 || len(line) < 2 || line[index-offset-1] != '-' {
90 node.Segments.Append(segment.WithStop(segment.Start + index + len(closeComment)))
91 block.Advance(index + len(closeComment))
92 return node
93 }
94 }
95 if hindex > 0 {
96 break
97 }
98 node.Segments.Append(segment)
99 block.AdvanceLine()
100 line, segment = block.PeekLine()
101 offset = 0
102 if line == nil {
103 break
104 }
105 }
106 block.SetPosition(savedLine, savedSegment)
107 return nil
108}
109
110func (s *rawHTMLParser) parseUntil(block text.Reader, closer []byte, pc Context) ast.Node {
111 savedLine, savedSegment := block.Position()
112 node := ast.NewRawHTML()
113 for {
114 line, segment := block.PeekLine()
115 if line == nil {
116 break
117 }
118 index := bytes.Index(line, closer)
119 if index > -1 {
120 node.Segments.Append(segment.WithStop(segment.Start + index + len(closer)))
121 block.Advance(index + len(closer))
122 return node
123 }
124 node.Segments.Append(segment)
125 block.AdvanceLine()
126 }
127 block.SetPosition(savedLine, savedSegment)
128 return nil
129}
130
131func (s *rawHTMLParser) parseMultiLineRegexp(reg *regexp.Regexp, block text.Reader, pc Context) ast.Node {
132 sline, ssegment := block.Position()
133 if block.Match(reg) {
134 node := ast.NewRawHTML()
135 eline, esegment := block.Position()
136 block.SetPosition(sline, ssegment)
137 for {
138 line, segment := block.PeekLine()
139 if line == nil {
140 break
141 }
142 l, _ := block.Position()
143 start := segment.Start
144 if l == sline {
145 start = ssegment.Start
146 }
147 end := segment.Stop
148 if l == eline {
149 end = esegment.Start
150 }
151
152 node.Segments.Append(text.NewSegment(start, end))
153 if l == eline {
154 block.Advance(end - start)
155 break
156 } else {
157 block.AdvanceLine()
158 }
159 }
160 return node
161 }
162 return nil
163}
diff --git a/vendor/github.com/yuin/goldmark/parser/setext_headings.go b/vendor/github.com/yuin/goldmark/parser/setext_headings.go
new file mode 100644
index 0000000..686efe1
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/setext_headings.go
@@ -0,0 +1,126 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9var temporaryParagraphKey = NewContextKey()
10
11type setextHeadingParser struct {
12 HeadingConfig
13}
14
15func matchesSetextHeadingBar(line []byte) (byte, bool) {
16 start := 0
17 end := len(line)
18 space := util.TrimLeftLength(line, []byte{' '})
19 if space > 3 {
20 return 0, false
21 }
22 start += space
23 level1 := util.TrimLeftLength(line[start:end], []byte{'='})
24 c := byte('=')
25 var level2 int
26 if level1 == 0 {
27 level2 = util.TrimLeftLength(line[start:end], []byte{'-'})
28 c = '-'
29 }
30 if util.IsSpace(line[end-1]) {
31 end -= util.TrimRightSpaceLength(line[start:end])
32 }
33 if !((level1 > 0 && start+level1 == end) || (level2 > 0 && start+level2 == end)) {
34 return 0, false
35 }
36 return c, true
37}
38
39// NewSetextHeadingParser return a new BlockParser that can parse Setext headings.
40func NewSetextHeadingParser(opts ...HeadingOption) BlockParser {
41 p := &setextHeadingParser{}
42 for _, o := range opts {
43 o.SetHeadingOption(&p.HeadingConfig)
44 }
45 return p
46}
47
48func (b *setextHeadingParser) Trigger() []byte {
49 return []byte{'-', '='}
50}
51
52func (b *setextHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
53 last := pc.LastOpenedBlock().Node
54 if last == nil {
55 return nil, NoChildren
56 }
57 paragraph, ok := last.(*ast.Paragraph)
58 if !ok || paragraph.Parent() != parent {
59 return nil, NoChildren
60 }
61 line, segment := reader.PeekLine()
62 c, ok := matchesSetextHeadingBar(line)
63 if !ok {
64 return nil, NoChildren
65 }
66 level := 1
67 if c == '-' {
68 level = 2
69 }
70 node := ast.NewHeading(level)
71 node.Lines().Append(segment)
72 pc.Set(temporaryParagraphKey, last)
73 return node, NoChildren | RequireParagraph
74}
75
76func (b *setextHeadingParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
77 return Close
78}
79
80func (b *setextHeadingParser) Close(node ast.Node, reader text.Reader, pc Context) {
81 heading := node.(*ast.Heading)
82 segment := node.Lines().At(0)
83 heading.Lines().Clear()
84 tmp := pc.Get(temporaryParagraphKey).(*ast.Paragraph)
85 pc.Set(temporaryParagraphKey, nil)
86 if tmp.Lines().Len() == 0 {
87 next := heading.NextSibling()
88 segment = segment.TrimLeftSpace(reader.Source())
89 if next == nil || !ast.IsParagraph(next) {
90 para := ast.NewParagraph()
91 para.Lines().Append(segment)
92 heading.Parent().InsertAfter(heading.Parent(), heading, para)
93 } else {
94 next.(ast.Node).Lines().Unshift(segment)
95 }
96 heading.Parent().RemoveChild(heading.Parent(), heading)
97 } else {
98 heading.SetLines(tmp.Lines())
99 heading.SetBlankPreviousLines(tmp.HasBlankPreviousLines())
100 tp := tmp.Parent()
101 if tp != nil {
102 tp.RemoveChild(tp, tmp)
103 }
104 }
105
106 if b.Attribute {
107 parseLastLineAttributes(node, reader, pc)
108 }
109
110 if b.AutoHeadingID {
111 id, ok := node.AttributeString("id")
112 if !ok {
113 generateAutoHeadingID(heading, reader, pc)
114 } else {
115 pc.IDs().Put(id.([]byte))
116 }
117 }
118}
119
120func (b *setextHeadingParser) CanInterruptParagraph() bool {
121 return true
122}
123
124func (b *setextHeadingParser) CanAcceptIndentedLine() bool {
125 return false
126}
diff --git a/vendor/github.com/yuin/goldmark/parser/thematic_break.go b/vendor/github.com/yuin/goldmark/parser/thematic_break.go
new file mode 100644
index 0000000..db20a1e
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/thematic_break.go
@@ -0,0 +1,75 @@
1package parser
2
3import (
4 "github.com/yuin/goldmark/ast"
5 "github.com/yuin/goldmark/text"
6 "github.com/yuin/goldmark/util"
7)
8
9type thematicBreakPraser struct {
10}
11
12var defaultThematicBreakPraser = &thematicBreakPraser{}
13
14// NewThematicBreakParser returns a new BlockParser that
15// parses thematic breaks.
16func NewThematicBreakParser() BlockParser {
17 return defaultThematicBreakPraser
18}
19
20func isThematicBreak(line []byte, offset int) bool {
21 w, pos := util.IndentWidth(line, offset)
22 if w > 3 {
23 return false
24 }
25 mark := byte(0)
26 count := 0
27 for i := pos; i < len(line); i++ {
28 c := line[i]
29 if util.IsSpace(c) {
30 continue
31 }
32 if mark == 0 {
33 mark = c
34 count = 1
35 if mark == '*' || mark == '-' || mark == '_' {
36 continue
37 }
38 return false
39 }
40 if c != mark {
41 return false
42 }
43 count++
44 }
45 return count > 2
46}
47
48func (b *thematicBreakPraser) Trigger() []byte {
49 return []byte{'-', '*', '_'}
50}
51
52func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
53 line, segment := reader.PeekLine()
54 if isThematicBreak(line, reader.LineOffset()) {
55 reader.Advance(segment.Len() - 1)
56 return ast.NewThematicBreak(), NoChildren
57 }
58 return nil, NoChildren
59}
60
61func (b *thematicBreakPraser) Continue(node ast.Node, reader text.Reader, pc Context) State {
62 return Close
63}
64
65func (b *thematicBreakPraser) Close(node ast.Node, reader text.Reader, pc Context) {
66 // nothing to do
67}
68
69func (b *thematicBreakPraser) CanInterruptParagraph() bool {
70 return true
71}
72
73func (b *thematicBreakPraser) CanAcceptIndentedLine() bool {
74 return false
75}
diff --git a/vendor/github.com/yuin/goldmark/renderer/html/html.go b/vendor/github.com/yuin/goldmark/renderer/html/html.go
new file mode 100644
index 0000000..7bf2ab8
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/renderer/html/html.go
@@ -0,0 +1,932 @@
1package html
2
3import (
4 "bytes"
5 "fmt"
6 "strconv"
7 "unicode/utf8"
8
9 "github.com/yuin/goldmark/ast"
10 "github.com/yuin/goldmark/renderer"
11 "github.com/yuin/goldmark/util"
12)
13
14// A Config struct has configurations for the HTML based renderers.
15type Config struct {
16 Writer Writer
17 HardWraps bool
18 EastAsianLineBreaks bool
19 XHTML bool
20 Unsafe bool
21}
22
23// NewConfig returns a new Config with defaults.
24func NewConfig() Config {
25 return Config{
26 Writer: DefaultWriter,
27 HardWraps: false,
28 EastAsianLineBreaks: false,
29 XHTML: false,
30 Unsafe: false,
31 }
32}
33
34// SetOption implements renderer.NodeRenderer.SetOption.
35func (c *Config) SetOption(name renderer.OptionName, value interface{}) {
36 switch name {
37 case optHardWraps:
38 c.HardWraps = value.(bool)
39 case optEastAsianLineBreaks:
40 c.EastAsianLineBreaks = value.(bool)
41 case optXHTML:
42 c.XHTML = value.(bool)
43 case optUnsafe:
44 c.Unsafe = value.(bool)
45 case optTextWriter:
46 c.Writer = value.(Writer)
47 }
48}
49
50// An Option interface sets options for HTML based renderers.
51type Option interface {
52 SetHTMLOption(*Config)
53}
54
55// TextWriter is an option name used in WithWriter.
56const optTextWriter renderer.OptionName = "Writer"
57
58type withWriter struct {
59 value Writer
60}
61
62func (o *withWriter) SetConfig(c *renderer.Config) {
63 c.Options[optTextWriter] = o.value
64}
65
66func (o *withWriter) SetHTMLOption(c *Config) {
67 c.Writer = o.value
68}
69
70// WithWriter is a functional option that allow you to set the given writer to
71// the renderer.
72func WithWriter(writer Writer) interface {
73 renderer.Option
74 Option
75} {
76 return &withWriter{writer}
77}
78
79// HardWraps is an option name used in WithHardWraps.
80const optHardWraps renderer.OptionName = "HardWraps"
81
82type withHardWraps struct {
83}
84
85func (o *withHardWraps) SetConfig(c *renderer.Config) {
86 c.Options[optHardWraps] = true
87}
88
89func (o *withHardWraps) SetHTMLOption(c *Config) {
90 c.HardWraps = true
91}
92
93// WithHardWraps is a functional option that indicates whether softline breaks
94// should be rendered as '<br>'.
95func WithHardWraps() interface {
96 renderer.Option
97 Option
98} {
99 return &withHardWraps{}
100}
101
102// EastAsianLineBreaks is an option name used in WithEastAsianLineBreaks.
103const optEastAsianLineBreaks renderer.OptionName = "EastAsianLineBreaks"
104
105type withEastAsianLineBreaks struct {
106}
107
108func (o *withEastAsianLineBreaks) SetConfig(c *renderer.Config) {
109 c.Options[optEastAsianLineBreaks] = true
110}
111
112func (o *withEastAsianLineBreaks) SetHTMLOption(c *Config) {
113 c.EastAsianLineBreaks = true
114}
115
116// WithEastAsianLineBreaks is a functional option that indicates whether softline breaks
117// between east asian wide characters should be ignored.
118func WithEastAsianLineBreaks() interface {
119 renderer.Option
120 Option
121} {
122 return &withEastAsianLineBreaks{}
123}
124
125// XHTML is an option name used in WithXHTML.
126const optXHTML renderer.OptionName = "XHTML"
127
128type withXHTML struct {
129}
130
131func (o *withXHTML) SetConfig(c *renderer.Config) {
132 c.Options[optXHTML] = true
133}
134
135func (o *withXHTML) SetHTMLOption(c *Config) {
136 c.XHTML = true
137}
138
139// WithXHTML is a functional option indicates that nodes should be rendered in
140// xhtml instead of HTML5.
141func WithXHTML() interface {
142 Option
143 renderer.Option
144} {
145 return &withXHTML{}
146}
147
148// Unsafe is an option name used in WithUnsafe.
149const optUnsafe renderer.OptionName = "Unsafe"
150
151type withUnsafe struct {
152}
153
154func (o *withUnsafe) SetConfig(c *renderer.Config) {
155 c.Options[optUnsafe] = true
156}
157
158func (o *withUnsafe) SetHTMLOption(c *Config) {
159 c.Unsafe = true
160}
161
162// WithUnsafe is a functional option that renders dangerous contents
163// (raw htmls and potentially dangerous links) as it is.
164func WithUnsafe() interface {
165 renderer.Option
166 Option
167} {
168 return &withUnsafe{}
169}
170
171// A Renderer struct is an implementation of renderer.NodeRenderer that renders
172// nodes as (X)HTML.
173type Renderer struct {
174 Config
175}
176
177// NewRenderer returns a new Renderer with given options.
178func NewRenderer(opts ...Option) renderer.NodeRenderer {
179 r := &Renderer{
180 Config: NewConfig(),
181 }
182
183 for _, opt := range opts {
184 opt.SetHTMLOption(&r.Config)
185 }
186 return r
187}
188
189// RegisterFuncs implements NodeRenderer.RegisterFuncs .
190func (r *Renderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
191 // blocks
192
193 reg.Register(ast.KindDocument, r.renderDocument)
194 reg.Register(ast.KindHeading, r.renderHeading)
195 reg.Register(ast.KindBlockquote, r.renderBlockquote)
196 reg.Register(ast.KindCodeBlock, r.renderCodeBlock)
197 reg.Register(ast.KindFencedCodeBlock, r.renderFencedCodeBlock)
198 reg.Register(ast.KindHTMLBlock, r.renderHTMLBlock)
199 reg.Register(ast.KindList, r.renderList)
200 reg.Register(ast.KindListItem, r.renderListItem)
201 reg.Register(ast.KindParagraph, r.renderParagraph)
202 reg.Register(ast.KindTextBlock, r.renderTextBlock)
203 reg.Register(ast.KindThematicBreak, r.renderThematicBreak)
204
205 // inlines
206
207 reg.Register(ast.KindAutoLink, r.renderAutoLink)
208 reg.Register(ast.KindCodeSpan, r.renderCodeSpan)
209 reg.Register(ast.KindEmphasis, r.renderEmphasis)
210 reg.Register(ast.KindImage, r.renderImage)
211 reg.Register(ast.KindLink, r.renderLink)
212 reg.Register(ast.KindRawHTML, r.renderRawHTML)
213 reg.Register(ast.KindText, r.renderText)
214 reg.Register(ast.KindString, r.renderString)
215}
216
217func (r *Renderer) writeLines(w util.BufWriter, source []byte, n ast.Node) {
218 l := n.Lines().Len()
219 for i := 0; i < l; i++ {
220 line := n.Lines().At(i)
221 r.Writer.RawWrite(w, line.Value(source))
222 }
223}
224
225// GlobalAttributeFilter defines attribute names which any elements can have.
226var GlobalAttributeFilter = util.NewBytesFilter(
227 []byte("accesskey"),
228 []byte("autocapitalize"),
229 []byte("autofocus"),
230 []byte("class"),
231 []byte("contenteditable"),
232 []byte("dir"),
233 []byte("draggable"),
234 []byte("enterkeyhint"),
235 []byte("hidden"),
236 []byte("id"),
237 []byte("inert"),
238 []byte("inputmode"),
239 []byte("is"),
240 []byte("itemid"),
241 []byte("itemprop"),
242 []byte("itemref"),
243 []byte("itemscope"),
244 []byte("itemtype"),
245 []byte("lang"),
246 []byte("part"),
247 []byte("role"),
248 []byte("slot"),
249 []byte("spellcheck"),
250 []byte("style"),
251 []byte("tabindex"),
252 []byte("title"),
253 []byte("translate"),
254)
255
256func (r *Renderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
257 // nothing to do
258 return ast.WalkContinue, nil
259}
260
261// HeadingAttributeFilter defines attribute names which heading elements can have
262var HeadingAttributeFilter = GlobalAttributeFilter
263
264func (r *Renderer) renderHeading(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
265 n := node.(*ast.Heading)
266 if entering {
267 _, _ = w.WriteString("<h")
268 _ = w.WriteByte("0123456"[n.Level])
269 if n.Attributes() != nil {
270 RenderAttributes(w, node, HeadingAttributeFilter)
271 }
272 _ = w.WriteByte('>')
273 } else {
274 _, _ = w.WriteString("</h")
275 _ = w.WriteByte("0123456"[n.Level])
276 _, _ = w.WriteString(">\n")
277 }
278 return ast.WalkContinue, nil
279}
280
281// BlockquoteAttributeFilter defines attribute names which blockquote elements can have
282var BlockquoteAttributeFilter = GlobalAttributeFilter.Extend(
283 []byte("cite"),
284)
285
286func (r *Renderer) renderBlockquote(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
287 if entering {
288 if n.Attributes() != nil {
289 _, _ = w.WriteString("<blockquote")
290 RenderAttributes(w, n, BlockquoteAttributeFilter)
291 _ = w.WriteByte('>')
292 } else {
293 _, _ = w.WriteString("<blockquote>\n")
294 }
295 } else {
296 _, _ = w.WriteString("</blockquote>\n")
297 }
298 return ast.WalkContinue, nil
299}
300
301func (r *Renderer) renderCodeBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
302 if entering {
303 _, _ = w.WriteString("<pre><code>")
304 r.writeLines(w, source, n)
305 } else {
306 _, _ = w.WriteString("</code></pre>\n")
307 }
308 return ast.WalkContinue, nil
309}
310
311func (r *Renderer) renderFencedCodeBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
312 n := node.(*ast.FencedCodeBlock)
313 if entering {
314 _, _ = w.WriteString("<pre><code")
315 language := n.Language(source)
316 if language != nil {
317 _, _ = w.WriteString(" class=\"language-")
318 r.Writer.Write(w, language)
319 _, _ = w.WriteString("\"")
320 }
321 _ = w.WriteByte('>')
322 r.writeLines(w, source, n)
323 } else {
324 _, _ = w.WriteString("</code></pre>\n")
325 }
326 return ast.WalkContinue, nil
327}
328
329func (r *Renderer) renderHTMLBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
330 n := node.(*ast.HTMLBlock)
331 if entering {
332 if r.Unsafe {
333 l := n.Lines().Len()
334 for i := 0; i < l; i++ {
335 line := n.Lines().At(i)
336 r.Writer.SecureWrite(w, line.Value(source))
337 }
338 } else {
339 _, _ = w.WriteString("<!-- raw HTML omitted -->\n")
340 }
341 } else {
342 if n.HasClosure() {
343 if r.Unsafe {
344 closure := n.ClosureLine
345 r.Writer.SecureWrite(w, closure.Value(source))
346 } else {
347 _, _ = w.WriteString("<!-- raw HTML omitted -->\n")
348 }
349 }
350 }
351 return ast.WalkContinue, nil
352}
353
354// ListAttributeFilter defines attribute names which list elements can have.
355var ListAttributeFilter = GlobalAttributeFilter.Extend(
356 []byte("start"),
357 []byte("reversed"),
358 []byte("type"),
359)
360
361func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
362 n := node.(*ast.List)
363 tag := "ul"
364 if n.IsOrdered() {
365 tag = "ol"
366 }
367 if entering {
368 _ = w.WriteByte('<')
369 _, _ = w.WriteString(tag)
370 if n.IsOrdered() && n.Start != 1 {
371 fmt.Fprintf(w, " start=\"%d\"", n.Start)
372 }
373 if n.Attributes() != nil {
374 RenderAttributes(w, n, ListAttributeFilter)
375 }
376 _, _ = w.WriteString(">\n")
377 } else {
378 _, _ = w.WriteString("</")
379 _, _ = w.WriteString(tag)
380 _, _ = w.WriteString(">\n")
381 }
382 return ast.WalkContinue, nil
383}
384
385// ListItemAttributeFilter defines attribute names which list item elements can have.
386var ListItemAttributeFilter = GlobalAttributeFilter.Extend(
387 []byte("value"),
388)
389
390func (r *Renderer) renderListItem(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
391 if entering {
392 if n.Attributes() != nil {
393 _, _ = w.WriteString("<li")
394 RenderAttributes(w, n, ListItemAttributeFilter)
395 _ = w.WriteByte('>')
396 } else {
397 _, _ = w.WriteString("<li>")
398 }
399 fc := n.FirstChild()
400 if fc != nil {
401 if _, ok := fc.(*ast.TextBlock); !ok {
402 _ = w.WriteByte('\n')
403 }
404 }
405 } else {
406 _, _ = w.WriteString("</li>\n")
407 }
408 return ast.WalkContinue, nil
409}
410
411// ParagraphAttributeFilter defines attribute names which paragraph elements can have.
412var ParagraphAttributeFilter = GlobalAttributeFilter
413
414func (r *Renderer) renderParagraph(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
415 if entering {
416 if n.Attributes() != nil {
417 _, _ = w.WriteString("<p")
418 RenderAttributes(w, n, ParagraphAttributeFilter)
419 _ = w.WriteByte('>')
420 } else {
421 _, _ = w.WriteString("<p>")
422 }
423 } else {
424 _, _ = w.WriteString("</p>\n")
425 }
426 return ast.WalkContinue, nil
427}
428
429func (r *Renderer) renderTextBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
430 if !entering {
431 if _, ok := n.NextSibling().(ast.Node); ok && n.FirstChild() != nil {
432 _ = w.WriteByte('\n')
433 }
434 }
435 return ast.WalkContinue, nil
436}
437
438// ThematicAttributeFilter defines attribute names which hr elements can have.
439var ThematicAttributeFilter = GlobalAttributeFilter.Extend(
440 []byte("align"), // [Deprecated]
441 []byte("color"), // [Not Standardized]
442 []byte("noshade"), // [Deprecated]
443 []byte("size"), // [Deprecated]
444 []byte("width"), // [Deprecated]
445)
446
447func (r *Renderer) renderThematicBreak(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
448 if !entering {
449 return ast.WalkContinue, nil
450 }
451 _, _ = w.WriteString("<hr")
452 if n.Attributes() != nil {
453 RenderAttributes(w, n, ThematicAttributeFilter)
454 }
455 if r.XHTML {
456 _, _ = w.WriteString(" />\n")
457 } else {
458 _, _ = w.WriteString(">\n")
459 }
460 return ast.WalkContinue, nil
461}
462
463// LinkAttributeFilter defines attribute names which link elements can have.
464var LinkAttributeFilter = GlobalAttributeFilter.Extend(
465 []byte("download"),
466 // []byte("href"),
467 []byte("hreflang"),
468 []byte("media"),
469 []byte("ping"),
470 []byte("referrerpolicy"),
471 []byte("rel"),
472 []byte("shape"),
473 []byte("target"),
474)
475
476func (r *Renderer) renderAutoLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
477 n := node.(*ast.AutoLink)
478 if !entering {
479 return ast.WalkContinue, nil
480 }
481 _, _ = w.WriteString(`<a href="`)
482 url := n.URL(source)
483 label := n.Label(source)
484 if n.AutoLinkType == ast.AutoLinkEmail && !bytes.HasPrefix(bytes.ToLower(url), []byte("mailto:")) {
485 _, _ = w.WriteString("mailto:")
486 }
487 _, _ = w.Write(util.EscapeHTML(util.URLEscape(url, false)))
488 if n.Attributes() != nil {
489 _ = w.WriteByte('"')
490 RenderAttributes(w, n, LinkAttributeFilter)
491 _ = w.WriteByte('>')
492 } else {
493 _, _ = w.WriteString(`">`)
494 }
495 _, _ = w.Write(util.EscapeHTML(label))
496 _, _ = w.WriteString(`</a>`)
497 return ast.WalkContinue, nil
498}
499
500// CodeAttributeFilter defines attribute names which code elements can have.
501var CodeAttributeFilter = GlobalAttributeFilter
502
503func (r *Renderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
504 if entering {
505 if n.Attributes() != nil {
506 _, _ = w.WriteString("<code")
507 RenderAttributes(w, n, CodeAttributeFilter)
508 _ = w.WriteByte('>')
509 } else {
510 _, _ = w.WriteString("<code>")
511 }
512 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
513 segment := c.(*ast.Text).Segment
514 value := segment.Value(source)
515 if bytes.HasSuffix(value, []byte("\n")) {
516 r.Writer.RawWrite(w, value[:len(value)-1])
517 r.Writer.RawWrite(w, []byte(" "))
518 } else {
519 r.Writer.RawWrite(w, value)
520 }
521 }
522 return ast.WalkSkipChildren, nil
523 }
524 _, _ = w.WriteString("</code>")
525 return ast.WalkContinue, nil
526}
527
528// EmphasisAttributeFilter defines attribute names which emphasis elements can have.
529var EmphasisAttributeFilter = GlobalAttributeFilter
530
531func (r *Renderer) renderEmphasis(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
532 n := node.(*ast.Emphasis)
533 tag := "em"
534 if n.Level == 2 {
535 tag = "strong"
536 }
537 if entering {
538 _ = w.WriteByte('<')
539 _, _ = w.WriteString(tag)
540 if n.Attributes() != nil {
541 RenderAttributes(w, n, EmphasisAttributeFilter)
542 }
543 _ = w.WriteByte('>')
544 } else {
545 _, _ = w.WriteString("</")
546 _, _ = w.WriteString(tag)
547 _ = w.WriteByte('>')
548 }
549 return ast.WalkContinue, nil
550}
551
552func (r *Renderer) renderLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
553 n := node.(*ast.Link)
554 if entering {
555 _, _ = w.WriteString("<a href=\"")
556 if r.Unsafe || !IsDangerousURL(n.Destination) {
557 _, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
558 }
559 _ = w.WriteByte('"')
560 if n.Title != nil {
561 _, _ = w.WriteString(` title="`)
562 r.Writer.Write(w, n.Title)
563 _ = w.WriteByte('"')
564 }
565 if n.Attributes() != nil {
566 RenderAttributes(w, n, LinkAttributeFilter)
567 }
568 _ = w.WriteByte('>')
569 } else {
570 _, _ = w.WriteString("</a>")
571 }
572 return ast.WalkContinue, nil
573}
574
575// ImageAttributeFilter defines attribute names which image elements can have.
576var ImageAttributeFilter = GlobalAttributeFilter.Extend(
577 []byte("align"),
578 []byte("border"),
579 []byte("crossorigin"),
580 []byte("decoding"),
581 []byte("height"),
582 []byte("importance"),
583 []byte("intrinsicsize"),
584 []byte("ismap"),
585 []byte("loading"),
586 []byte("referrerpolicy"),
587 []byte("sizes"),
588 []byte("srcset"),
589 []byte("usemap"),
590 []byte("width"),
591)
592
593func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
594 if !entering {
595 return ast.WalkContinue, nil
596 }
597 n := node.(*ast.Image)
598 _, _ = w.WriteString("<img src=\"")
599 if r.Unsafe || !IsDangerousURL(n.Destination) {
600 _, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
601 }
602 _, _ = w.WriteString(`" alt="`)
603 _, _ = w.Write(nodeToHTMLText(n, source))
604 _ = w.WriteByte('"')
605 if n.Title != nil {
606 _, _ = w.WriteString(` title="`)
607 r.Writer.Write(w, n.Title)
608 _ = w.WriteByte('"')
609 }
610 if n.Attributes() != nil {
611 RenderAttributes(w, n, ImageAttributeFilter)
612 }
613 if r.XHTML {
614 _, _ = w.WriteString(" />")
615 } else {
616 _, _ = w.WriteString(">")
617 }
618 return ast.WalkSkipChildren, nil
619}
620
621func (r *Renderer) renderRawHTML(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
622 if !entering {
623 return ast.WalkSkipChildren, nil
624 }
625 if r.Unsafe {
626 n := node.(*ast.RawHTML)
627 l := n.Segments.Len()
628 for i := 0; i < l; i++ {
629 segment := n.Segments.At(i)
630 _, _ = w.Write(segment.Value(source))
631 }
632 return ast.WalkSkipChildren, nil
633 }
634 _, _ = w.WriteString("<!-- raw HTML omitted -->")
635 return ast.WalkSkipChildren, nil
636}
637
638func (r *Renderer) renderText(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
639 if !entering {
640 return ast.WalkContinue, nil
641 }
642 n := node.(*ast.Text)
643 segment := n.Segment
644 if n.IsRaw() {
645 r.Writer.RawWrite(w, segment.Value(source))
646 } else {
647 value := segment.Value(source)
648 r.Writer.Write(w, value)
649 if n.HardLineBreak() || (n.SoftLineBreak() && r.HardWraps) {
650 if r.XHTML {
651 _, _ = w.WriteString("<br />\n")
652 } else {
653 _, _ = w.WriteString("<br>\n")
654 }
655 } else if n.SoftLineBreak() {
656 if r.EastAsianLineBreaks && len(value) != 0 {
657 sibling := node.NextSibling()
658 if sibling != nil && sibling.Kind() == ast.KindText {
659 if siblingText := sibling.(*ast.Text).Text(source); len(siblingText) != 0 {
660 thisLastRune := util.ToRune(value, len(value)-1)
661 siblingFirstRune, _ := utf8.DecodeRune(siblingText)
662 if !(util.IsEastAsianWideRune(thisLastRune) &&
663 util.IsEastAsianWideRune(siblingFirstRune)) {
664 _ = w.WriteByte('\n')
665 }
666 }
667 }
668 } else {
669 _ = w.WriteByte('\n')
670 }
671 }
672 }
673 return ast.WalkContinue, nil
674}
675
676func (r *Renderer) renderString(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
677 if !entering {
678 return ast.WalkContinue, nil
679 }
680 n := node.(*ast.String)
681 if n.IsCode() {
682 _, _ = w.Write(n.Value)
683 } else {
684 if n.IsRaw() {
685 r.Writer.RawWrite(w, n.Value)
686 } else {
687 r.Writer.Write(w, n.Value)
688 }
689 }
690 return ast.WalkContinue, nil
691}
692
693var dataPrefix = []byte("data-")
694
695// RenderAttributes renders given node's attributes.
696// You can specify attribute names to render by the filter.
697// If filter is nil, RenderAttributes renders all attributes.
698func RenderAttributes(w util.BufWriter, node ast.Node, filter util.BytesFilter) {
699 for _, attr := range node.Attributes() {
700 if filter != nil && !filter.Contains(attr.Name) {
701 if !bytes.HasPrefix(attr.Name, dataPrefix) {
702 continue
703 }
704 }
705 _, _ = w.WriteString(" ")
706 _, _ = w.Write(attr.Name)
707 _, _ = w.WriteString(`="`)
708 // TODO: convert numeric values to strings
709 _, _ = w.Write(util.EscapeHTML(attr.Value.([]byte)))
710 _ = w.WriteByte('"')
711 }
712}
713
714// A Writer interface writes textual contents to a writer.
715type Writer interface {
716 // Write writes the given source to writer with resolving references and unescaping
717 // backslash escaped characters.
718 Write(writer util.BufWriter, source []byte)
719
720 // RawWrite writes the given source to writer without resolving references and
721 // unescaping backslash escaped characters.
722 RawWrite(writer util.BufWriter, source []byte)
723
724 // SecureWrite writes the given source to writer with replacing insecure characters.
725 SecureWrite(writer util.BufWriter, source []byte)
726}
727
728var replacementCharacter = []byte("\ufffd")
729
730// A WriterConfig struct has configurations for the HTML based writers.
731type WriterConfig struct {
732 // EscapedSpace is an option that indicates that a '\' escaped half-space(0x20) should not be rendered.
733 EscapedSpace bool
734}
735
736// A WriterOption interface sets options for HTML based writers.
737type WriterOption func(*WriterConfig)
738
739// WithEscapedSpace is a WriterOption indicates that a '\' escaped half-space(0x20) should not be rendered.
740func WithEscapedSpace() WriterOption {
741 return func(c *WriterConfig) {
742 c.EscapedSpace = true
743 }
744}
745
746type defaultWriter struct {
747 WriterConfig
748}
749
750// NewWriter returns a new Writer.
751func NewWriter(opts ...WriterOption) Writer {
752 w := &defaultWriter{}
753 for _, opt := range opts {
754 opt(&w.WriterConfig)
755 }
756 return w
757}
758
759func escapeRune(writer util.BufWriter, r rune) {
760 if r < 256 {
761 v := util.EscapeHTMLByte(byte(r))
762 if v != nil {
763 _, _ = writer.Write(v)
764 return
765 }
766 }
767 _, _ = writer.WriteRune(util.ToValidRune(r))
768}
769
770func (d *defaultWriter) SecureWrite(writer util.BufWriter, source []byte) {
771 n := 0
772 l := len(source)
773 for i := 0; i < l; i++ {
774 if source[i] == '\u0000' {
775 _, _ = writer.Write(source[i-n : i])
776 n = 0
777 _, _ = writer.Write(replacementCharacter)
778 continue
779 }
780 n++
781 }
782 if n != 0 {
783 _, _ = writer.Write(source[l-n:])
784 }
785}
786
787func (d *defaultWriter) RawWrite(writer util.BufWriter, source []byte) {
788 n := 0
789 l := len(source)
790 for i := 0; i < l; i++ {
791 v := util.EscapeHTMLByte(source[i])
792 if v != nil {
793 _, _ = writer.Write(source[i-n : i])
794 n = 0
795 _, _ = writer.Write(v)
796 continue
797 }
798 n++
799 }
800 if n != 0 {
801 _, _ = writer.Write(source[l-n:])
802 }
803}
804
805func (d *defaultWriter) Write(writer util.BufWriter, source []byte) {
806 escaped := false
807 var ok bool
808 limit := len(source)
809 n := 0
810 for i := 0; i < limit; i++ {
811 c := source[i]
812 if escaped {
813 if util.IsPunct(c) {
814 d.RawWrite(writer, source[n:i-1])
815 n = i
816 escaped = false
817 continue
818 }
819 if d.EscapedSpace && c == ' ' {
820 d.RawWrite(writer, source[n:i-1])
821 n = i + 1
822 escaped = false
823 continue
824 }
825 }
826 if c == '\x00' {
827 d.RawWrite(writer, source[n:i])
828 d.RawWrite(writer, replacementCharacter)
829 n = i + 1
830 escaped = false
831 continue
832 }
833 if c == '&' {
834 pos := i
835 next := i + 1
836 if next < limit && source[next] == '#' {
837 nnext := next + 1
838 if nnext < limit {
839 nc := source[nnext]
840 // code point like #x22;
841 if nnext < limit && nc == 'x' || nc == 'X' {
842 start := nnext + 1
843 i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsHexDecimal)
844 if ok && i < limit && source[i] == ';' && i-start < 7 {
845 v, _ := strconv.ParseUint(util.BytesToReadOnlyString(source[start:i]), 16, 32)
846 d.RawWrite(writer, source[n:pos])
847 n = i + 1
848 escapeRune(writer, rune(v))
849 continue
850 }
851 // code point like #1234;
852 } else if nc >= '0' && nc <= '9' {
853 start := nnext
854 i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsNumeric)
855 if ok && i < limit && i-start < 8 && source[i] == ';' {
856 v, _ := strconv.ParseUint(util.BytesToReadOnlyString(source[start:i]), 10, 32)
857 d.RawWrite(writer, source[n:pos])
858 n = i + 1
859 escapeRune(writer, rune(v))
860 continue
861 }
862 }
863 }
864 } else {
865 start := next
866 i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsAlphaNumeric)
867 // entity reference
868 if ok && i < limit && source[i] == ';' {
869 name := util.BytesToReadOnlyString(source[start:i])
870 entity, ok := util.LookUpHTML5EntityByName(name)
871 if ok {
872 d.RawWrite(writer, source[n:pos])
873 n = i + 1
874 d.RawWrite(writer, entity.Characters)
875 continue
876 }
877 }
878 }
879 i = next - 1
880 }
881 if c == '\\' {
882 escaped = true
883 continue
884 }
885 escaped = false
886 }
887 d.RawWrite(writer, source[n:])
888}
889
890// DefaultWriter is a default instance of the Writer.
891var DefaultWriter = NewWriter()
892
893var bDataImage = []byte("data:image/")
894var bPng = []byte("png;")
895var bGif = []byte("gif;")
896var bJpeg = []byte("jpeg;")
897var bWebp = []byte("webp;")
898var bSvg = []byte("svg+xml;")
899var bJs = []byte("javascript:")
900var bVb = []byte("vbscript:")
901var bFile = []byte("file:")
902var bData = []byte("data:")
903
904// IsDangerousURL returns true if the given url seems a potentially dangerous url,
905// otherwise false.
906func IsDangerousURL(url []byte) bool {
907 if bytes.HasPrefix(url, bDataImage) && len(url) >= 11 {
908 v := url[11:]
909 if bytes.HasPrefix(v, bPng) || bytes.HasPrefix(v, bGif) ||
910 bytes.HasPrefix(v, bJpeg) || bytes.HasPrefix(v, bWebp) ||
911 bytes.HasPrefix(v, bSvg) {
912 return false
913 }
914 return true
915 }
916 return bytes.HasPrefix(url, bJs) || bytes.HasPrefix(url, bVb) ||
917 bytes.HasPrefix(url, bFile) || bytes.HasPrefix(url, bData)
918}
919
920func nodeToHTMLText(n ast.Node, source []byte) []byte {
921 var buf bytes.Buffer
922 for c := n.FirstChild(); c != nil; c = c.NextSibling() {
923 if s, ok := c.(*ast.String); ok && s.IsCode() {
924 buf.Write(s.Text(source))
925 } else if !c.HasChildren() {
926 buf.Write(util.EscapeHTML(c.Text(source)))
927 } else {
928 buf.Write(nodeToHTMLText(c, source))
929 }
930 }
931 return buf.Bytes()
932}
diff --git a/vendor/github.com/yuin/goldmark/renderer/renderer.go b/vendor/github.com/yuin/goldmark/renderer/renderer.go
new file mode 100644
index 0000000..10f6d40
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/renderer/renderer.go
@@ -0,0 +1,174 @@
1// Package renderer renders the given AST to certain formats.
2package renderer
3
4import (
5 "bufio"
6 "io"
7 "sync"
8
9 "github.com/yuin/goldmark/ast"
10 "github.com/yuin/goldmark/util"
11)
12
13// A Config struct is a data structure that holds configuration of the Renderer.
14type Config struct {
15 Options map[OptionName]interface{}
16 NodeRenderers util.PrioritizedSlice
17}
18
19// NewConfig returns a new Config
20func NewConfig() *Config {
21 return &Config{
22 Options: map[OptionName]interface{}{},
23 NodeRenderers: util.PrioritizedSlice{},
24 }
25}
26
27// An OptionName is a name of the option.
28type OptionName string
29
30// An Option interface is a functional option type for the Renderer.
31type Option interface {
32 SetConfig(*Config)
33}
34
35type withNodeRenderers struct {
36 value []util.PrioritizedValue
37}
38
39func (o *withNodeRenderers) SetConfig(c *Config) {
40 c.NodeRenderers = append(c.NodeRenderers, o.value...)
41}
42
43// WithNodeRenderers is a functional option that allow you to add
44// NodeRenderers to the renderer.
45func WithNodeRenderers(ps ...util.PrioritizedValue) Option {
46 return &withNodeRenderers{ps}
47}
48
49type withOption struct {
50 name OptionName
51 value interface{}
52}
53
54func (o *withOption) SetConfig(c *Config) {
55 c.Options[o.name] = o.value
56}
57
58// WithOption is a functional option that allow you to set
59// an arbitrary option to the parser.
60func WithOption(name OptionName, value interface{}) Option {
61 return &withOption{name, value}
62}
63
64// A SetOptioner interface sets given option to the object.
65type SetOptioner interface {
66 // SetOption sets given option to the object.
67 // Unacceptable options may be passed.
68 // Thus implementations must ignore unacceptable options.
69 SetOption(name OptionName, value interface{})
70}
71
72// NodeRendererFunc is a function that renders a given node.
73type NodeRendererFunc func(writer util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error)
74
75// A NodeRenderer interface offers NodeRendererFuncs.
76type NodeRenderer interface {
77 // RendererFuncs registers NodeRendererFuncs to given NodeRendererFuncRegisterer.
78 RegisterFuncs(NodeRendererFuncRegisterer)
79}
80
81// A NodeRendererFuncRegisterer registers
82type NodeRendererFuncRegisterer interface {
83 // Register registers given NodeRendererFunc to this object.
84 Register(ast.NodeKind, NodeRendererFunc)
85}
86
87// A Renderer interface renders given AST node to given
88// writer with given Renderer.
89type Renderer interface {
90 Render(w io.Writer, source []byte, n ast.Node) error
91
92 // AddOptions adds given option to this renderer.
93 AddOptions(...Option)
94}
95
96type renderer struct {
97 config *Config
98 options map[OptionName]interface{}
99 nodeRendererFuncsTmp map[ast.NodeKind]NodeRendererFunc
100 maxKind int
101 nodeRendererFuncs []NodeRendererFunc
102 initSync sync.Once
103}
104
105// NewRenderer returns a new Renderer with given options.
106func NewRenderer(options ...Option) Renderer {
107 config := NewConfig()
108 for _, opt := range options {
109 opt.SetConfig(config)
110 }
111
112 r := &renderer{
113 options: map[OptionName]interface{}{},
114 config: config,
115 nodeRendererFuncsTmp: map[ast.NodeKind]NodeRendererFunc{},
116 }
117
118 return r
119}
120
121func (r *renderer) AddOptions(opts ...Option) {
122 for _, opt := range opts {
123 opt.SetConfig(r.config)
124 }
125}
126
127func (r *renderer) Register(kind ast.NodeKind, v NodeRendererFunc) {
128 r.nodeRendererFuncsTmp[kind] = v
129 if int(kind) > r.maxKind {
130 r.maxKind = int(kind)
131 }
132}
133
134// Render renders the given AST node to the given writer with the given Renderer.
135func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
136 r.initSync.Do(func() {
137 r.options = r.config.Options
138 r.config.NodeRenderers.Sort()
139 l := len(r.config.NodeRenderers)
140 for i := l - 1; i >= 0; i-- {
141 v := r.config.NodeRenderers[i]
142 nr, _ := v.Value.(NodeRenderer)
143 if se, ok := v.Value.(SetOptioner); ok {
144 for oname, ovalue := range r.options {
145 se.SetOption(oname, ovalue)
146 }
147 }
148 nr.RegisterFuncs(r)
149 }
150 r.nodeRendererFuncs = make([]NodeRendererFunc, r.maxKind+1)
151 for kind, nr := range r.nodeRendererFuncsTmp {
152 r.nodeRendererFuncs[kind] = nr
153 }
154 r.config = nil
155 r.nodeRendererFuncsTmp = nil
156 })
157 writer, ok := w.(util.BufWriter)
158 if !ok {
159 writer = bufio.NewWriter(w)
160 }
161 err := ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
162 s := ast.WalkStatus(ast.WalkContinue)
163 var err error
164 f := r.nodeRendererFuncs[n.Kind()]
165 if f != nil {
166 s, err = f(writer, source, n, entering)
167 }
168 return s, err
169 })
170 if err != nil {
171 return err
172 }
173 return writer.Flush()
174}
diff --git a/vendor/github.com/yuin/goldmark/text/reader.go b/vendor/github.com/yuin/goldmark/text/reader.go
new file mode 100644
index 0000000..319f1c8
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/text/reader.go
@@ -0,0 +1,653 @@
1package text
2
3import (
4 "io"
5 "regexp"
6 "unicode/utf8"
7
8 "github.com/yuin/goldmark/util"
9)
10
11const invalidValue = -1
12
13// EOF indicates the end of file.
14const EOF = byte(0xff)
15
16// A Reader interface provides abstracted method for reading text.
17type Reader interface {
18 io.RuneReader
19
20 // Source returns a source of the reader.
21 Source() []byte
22
23 // ResetPosition resets positions.
24 ResetPosition()
25
26 // Peek returns a byte at current position without advancing the internal pointer.
27 Peek() byte
28
29 // PeekLine returns the current line without advancing the internal pointer.
30 PeekLine() ([]byte, Segment)
31
32 // PrecendingCharacter returns a character just before current internal pointer.
33 PrecendingCharacter() rune
34
35 // Value returns a value of the given segment.
36 Value(Segment) []byte
37
38 // LineOffset returns a distance from the line head to current position.
39 LineOffset() int
40
41 // Position returns current line number and position.
42 Position() (int, Segment)
43
44 // SetPosition sets current line number and position.
45 SetPosition(int, Segment)
46
47 // SetPadding sets padding to the reader.
48 SetPadding(int)
49
50 // Advance advances the internal pointer.
51 Advance(int)
52
53 // AdvanceAndSetPadding advances the internal pointer and add padding to the
54 // reader.
55 AdvanceAndSetPadding(int, int)
56
57 // AdvanceLine advances the internal pointer to the next line head.
58 AdvanceLine()
59
60 // SkipSpaces skips space characters and returns a non-blank line.
61 // If it reaches EOF, returns false.
62 SkipSpaces() (Segment, int, bool)
63
64 // SkipSpaces skips blank lines and returns a non-blank line.
65 // If it reaches EOF, returns false.
66 SkipBlankLines() (Segment, int, bool)
67
68 // Match performs regular expression matching to current line.
69 Match(reg *regexp.Regexp) bool
70
71 // Match performs regular expression searching to current line.
72 FindSubMatch(reg *regexp.Regexp) [][]byte
73
74 // FindClosure finds corresponding closure.
75 FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool)
76}
77
78// FindClosureOptions is options for Reader.FindClosure
79type FindClosureOptions struct {
80 // CodeSpan is a flag for the FindClosure. If this is set to true,
81 // FindClosure ignores closers in codespans.
82 CodeSpan bool
83
84 // Nesting is a flag for the FindClosure. If this is set to true,
85 // FindClosure allows nesting.
86 Nesting bool
87
88 // Newline is a flag for the FindClosure. If this is set to true,
89 // FindClosure searches for a closer over multiple lines.
90 Newline bool
91
92 // Advance is a flag for the FindClosure. If this is set to true,
93 // FindClosure advances pointers when closer is found.
94 Advance bool
95}
96
97type reader struct {
98 source []byte
99 sourceLength int
100 line int
101 peekedLine []byte
102 pos Segment
103 head int
104 lineOffset int
105}
106
107// NewReader return a new Reader that can read UTF-8 bytes .
108func NewReader(source []byte) Reader {
109 r := &reader{
110 source: source,
111 sourceLength: len(source),
112 }
113 r.ResetPosition()
114 return r
115}
116
117func (r *reader) FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool) {
118 return findClosureReader(r, opener, closer, options)
119}
120
121func (r *reader) ResetPosition() {
122 r.line = -1
123 r.head = 0
124 r.lineOffset = -1
125 r.AdvanceLine()
126}
127
128func (r *reader) Source() []byte {
129 return r.source
130}
131
132func (r *reader) Value(seg Segment) []byte {
133 return seg.Value(r.source)
134}
135
136func (r *reader) Peek() byte {
137 if r.pos.Start >= 0 && r.pos.Start < r.sourceLength {
138 if r.pos.Padding != 0 {
139 return space[0]
140 }
141 return r.source[r.pos.Start]
142 }
143 return EOF
144}
145
146func (r *reader) PeekLine() ([]byte, Segment) {
147 if r.pos.Start >= 0 && r.pos.Start < r.sourceLength {
148 if r.peekedLine == nil {
149 r.peekedLine = r.pos.Value(r.Source())
150 }
151 return r.peekedLine, r.pos
152 }
153 return nil, r.pos
154}
155
156// io.RuneReader interface
157func (r *reader) ReadRune() (rune, int, error) {
158 return readRuneReader(r)
159}
160
161func (r *reader) LineOffset() int {
162 if r.lineOffset < 0 {
163 v := 0
164 for i := r.head; i < r.pos.Start; i++ {
165 if r.source[i] == '\t' {
166 v += util.TabWidth(v)
167 } else {
168 v++
169 }
170 }
171 r.lineOffset = v - r.pos.Padding
172 }
173 return r.lineOffset
174}
175
176func (r *reader) PrecendingCharacter() rune {
177 if r.pos.Start <= 0 {
178 if r.pos.Padding != 0 {
179 return rune(' ')
180 }
181 return rune('\n')
182 }
183 i := r.pos.Start - 1
184 for ; i >= 0; i-- {
185 if utf8.RuneStart(r.source[i]) {
186 break
187 }
188 }
189 rn, _ := utf8.DecodeRune(r.source[i:])
190 return rn
191}
192
193func (r *reader) Advance(n int) {
194 r.lineOffset = -1
195 if n < len(r.peekedLine) && r.pos.Padding == 0 {
196 r.pos.Start += n
197 r.peekedLine = nil
198 return
199 }
200 r.peekedLine = nil
201 l := r.sourceLength
202 for ; n > 0 && r.pos.Start < l; n-- {
203 if r.pos.Padding != 0 {
204 r.pos.Padding--
205 continue
206 }
207 if r.source[r.pos.Start] == '\n' {
208 r.AdvanceLine()
209 continue
210 }
211 r.pos.Start++
212 }
213}
214
215func (r *reader) AdvanceAndSetPadding(n, padding int) {
216 r.Advance(n)
217 if padding > r.pos.Padding {
218 r.SetPadding(padding)
219 }
220}
221
222func (r *reader) AdvanceLine() {
223 r.lineOffset = -1
224 r.peekedLine = nil
225 r.pos.Start = r.pos.Stop
226 r.head = r.pos.Start
227 if r.pos.Start < 0 {
228 return
229 }
230 r.pos.Stop = r.sourceLength
231 for i := r.pos.Start; i < r.sourceLength; i++ {
232 c := r.source[i]
233 if c == '\n' {
234 r.pos.Stop = i + 1
235 break
236 }
237 }
238 r.line++
239 r.pos.Padding = 0
240}
241
242func (r *reader) Position() (int, Segment) {
243 return r.line, r.pos
244}
245
246func (r *reader) SetPosition(line int, pos Segment) {
247 r.lineOffset = -1
248 r.line = line
249 r.pos = pos
250}
251
252func (r *reader) SetPadding(v int) {
253 r.pos.Padding = v
254}
255
256func (r *reader) SkipSpaces() (Segment, int, bool) {
257 return skipSpacesReader(r)
258}
259
260func (r *reader) SkipBlankLines() (Segment, int, bool) {
261 return skipBlankLinesReader(r)
262}
263
264func (r *reader) Match(reg *regexp.Regexp) bool {
265 return matchReader(r, reg)
266}
267
268func (r *reader) FindSubMatch(reg *regexp.Regexp) [][]byte {
269 return findSubMatchReader(r, reg)
270}
271
272// A BlockReader interface is a reader that is optimized for Blocks.
273type BlockReader interface {
274 Reader
275 // Reset resets current state and sets new segments to the reader.
276 Reset(segment *Segments)
277}
278
279type blockReader struct {
280 source []byte
281 segments *Segments
282 segmentsLength int
283 line int
284 pos Segment
285 head int
286 last int
287 lineOffset int
288}
289
290// NewBlockReader returns a new BlockReader.
291func NewBlockReader(source []byte, segments *Segments) BlockReader {
292 r := &blockReader{
293 source: source,
294 }
295 if segments != nil {
296 r.Reset(segments)
297 }
298 return r
299}
300
301func (r *blockReader) FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool) {
302 return findClosureReader(r, opener, closer, options)
303}
304
305func (r *blockReader) ResetPosition() {
306 r.line = -1
307 r.head = 0
308 r.last = 0
309 r.lineOffset = -1
310 r.pos.Start = -1
311 r.pos.Stop = -1
312 r.pos.Padding = 0
313 if r.segmentsLength > 0 {
314 last := r.segments.At(r.segmentsLength - 1)
315 r.last = last.Stop
316 }
317 r.AdvanceLine()
318}
319
320func (r *blockReader) Reset(segments *Segments) {
321 r.segments = segments
322 r.segmentsLength = segments.Len()
323 r.ResetPosition()
324}
325
326func (r *blockReader) Source() []byte {
327 return r.source
328}
329
330func (r *blockReader) Value(seg Segment) []byte {
331 line := r.segmentsLength - 1
332 ret := make([]byte, 0, seg.Stop-seg.Start+1)
333 for ; line >= 0; line-- {
334 if seg.Start >= r.segments.At(line).Start {
335 break
336 }
337 }
338 i := seg.Start
339 for ; line < r.segmentsLength; line++ {
340 s := r.segments.At(line)
341 if i < 0 {
342 i = s.Start
343 }
344 ret = s.ConcatPadding(ret)
345 for ; i < seg.Stop && i < s.Stop; i++ {
346 ret = append(ret, r.source[i])
347 }
348 i = -1
349 if s.Stop > seg.Stop {
350 break
351 }
352 }
353 return ret
354}
355
356// io.RuneReader interface
357func (r *blockReader) ReadRune() (rune, int, error) {
358 return readRuneReader(r)
359}
360
361func (r *blockReader) PrecendingCharacter() rune {
362 if r.pos.Padding != 0 {
363 return rune(' ')
364 }
365 if r.segments.Len() < 1 {
366 return rune('\n')
367 }
368 firstSegment := r.segments.At(0)
369 if r.line == 0 && r.pos.Start <= firstSegment.Start {
370 return rune('\n')
371 }
372 l := len(r.source)
373 i := r.pos.Start - 1
374 for ; i < l && i >= 0; i-- {
375 if utf8.RuneStart(r.source[i]) {
376 break
377 }
378 }
379 if i < 0 || i >= l {
380 return rune('\n')
381 }
382 rn, _ := utf8.DecodeRune(r.source[i:])
383 return rn
384}
385
386func (r *blockReader) LineOffset() int {
387 if r.lineOffset < 0 {
388 v := 0
389 for i := r.head; i < r.pos.Start; i++ {
390 if r.source[i] == '\t' {
391 v += util.TabWidth(v)
392 } else {
393 v++
394 }
395 }
396 r.lineOffset = v - r.pos.Padding
397 }
398 return r.lineOffset
399}
400
401func (r *blockReader) Peek() byte {
402 if r.line < r.segmentsLength && r.pos.Start >= 0 && r.pos.Start < r.last {
403 if r.pos.Padding != 0 {
404 return space[0]
405 }
406 return r.source[r.pos.Start]
407 }
408 return EOF
409}
410
411func (r *blockReader) PeekLine() ([]byte, Segment) {
412 if r.line < r.segmentsLength && r.pos.Start >= 0 && r.pos.Start < r.last {
413 return r.pos.Value(r.source), r.pos
414 }
415 return nil, r.pos
416}
417
418func (r *blockReader) Advance(n int) {
419 r.lineOffset = -1
420
421 if n < r.pos.Stop-r.pos.Start && r.pos.Padding == 0 {
422 r.pos.Start += n
423 return
424 }
425
426 for ; n > 0; n-- {
427 if r.pos.Padding != 0 {
428 r.pos.Padding--
429 continue
430 }
431 if r.pos.Start >= r.pos.Stop-1 && r.pos.Stop < r.last {
432 r.AdvanceLine()
433 continue
434 }
435 r.pos.Start++
436 }
437}
438
439func (r *blockReader) AdvanceAndSetPadding(n, padding int) {
440 r.Advance(n)
441 if padding > r.pos.Padding {
442 r.SetPadding(padding)
443 }
444}
445
446func (r *blockReader) AdvanceLine() {
447 r.SetPosition(r.line+1, NewSegment(invalidValue, invalidValue))
448 r.head = r.pos.Start
449}
450
451func (r *blockReader) Position() (int, Segment) {
452 return r.line, r.pos
453}
454
455func (r *blockReader) SetPosition(line int, pos Segment) {
456 r.lineOffset = -1
457 r.line = line
458 if pos.Start == invalidValue {
459 if r.line < r.segmentsLength {
460 s := r.segments.At(line)
461 r.head = s.Start
462 r.pos = s
463 }
464 } else {
465 r.pos = pos
466 if r.line < r.segmentsLength {
467 s := r.segments.At(line)
468 r.head = s.Start
469 }
470 }
471}
472
473func (r *blockReader) SetPadding(v int) {
474 r.lineOffset = -1
475 r.pos.Padding = v
476}
477
478func (r *blockReader) SkipSpaces() (Segment, int, bool) {
479 return skipSpacesReader(r)
480}
481
482func (r *blockReader) SkipBlankLines() (Segment, int, bool) {
483 return skipBlankLinesReader(r)
484}
485
486func (r *blockReader) Match(reg *regexp.Regexp) bool {
487 return matchReader(r, reg)
488}
489
490func (r *blockReader) FindSubMatch(reg *regexp.Regexp) [][]byte {
491 return findSubMatchReader(r, reg)
492}
493
494func skipBlankLinesReader(r Reader) (Segment, int, bool) {
495 lines := 0
496 for {
497 line, seg := r.PeekLine()
498 if line == nil {
499 return seg, lines, false
500 }
501 if util.IsBlank(line) {
502 lines++
503 r.AdvanceLine()
504 } else {
505 return seg, lines, true
506 }
507 }
508}
509
510func skipSpacesReader(r Reader) (Segment, int, bool) {
511 chars := 0
512 for {
513 line, segment := r.PeekLine()
514 if line == nil {
515 return segment, chars, false
516 }
517 for i, c := range line {
518 if util.IsSpace(c) {
519 chars++
520 r.Advance(1)
521 continue
522 }
523 return segment.WithStart(segment.Start + i + 1), chars, true
524 }
525 }
526}
527
528func matchReader(r Reader, reg *regexp.Regexp) bool {
529 oldline, oldseg := r.Position()
530 match := reg.FindReaderSubmatchIndex(r)
531 r.SetPosition(oldline, oldseg)
532 if match == nil {
533 return false
534 }
535 r.Advance(match[1] - match[0])
536 return true
537}
538
539func findSubMatchReader(r Reader, reg *regexp.Regexp) [][]byte {
540 oldline, oldseg := r.Position()
541 match := reg.FindReaderSubmatchIndex(r)
542 r.SetPosition(oldline, oldseg)
543 if match == nil {
544 return nil
545 }
546 runes := make([]rune, 0, match[1]-match[0])
547 for i := 0; i < match[1]; {
548 r, size, _ := readRuneReader(r)
549 i += size
550 runes = append(runes, r)
551 }
552 result := [][]byte{}
553 for i := 0; i < len(match); i += 2 {
554 result = append(result, []byte(string(runes[match[i]:match[i+1]])))
555 }
556
557 r.SetPosition(oldline, oldseg)
558 r.Advance(match[1] - match[0])
559 return result
560}
561
562func readRuneReader(r Reader) (rune, int, error) {
563 line, _ := r.PeekLine()
564 if line == nil {
565 return 0, 0, io.EOF
566 }
567 rn, size := utf8.DecodeRune(line)
568 if rn == utf8.RuneError {
569 return 0, 0, io.EOF
570 }
571 r.Advance(size)
572 return rn, size, nil
573}
574
575func findClosureReader(r Reader, opener, closer byte, opts FindClosureOptions) (*Segments, bool) {
576 opened := 1
577 codeSpanOpener := 0
578 closed := false
579 orgline, orgpos := r.Position()
580 var ret *Segments
581
582 for {
583 bs, seg := r.PeekLine()
584 if bs == nil {
585 goto end
586 }
587 i := 0
588 for i < len(bs) {
589 c := bs[i]
590 if opts.CodeSpan && codeSpanOpener != 0 && c == '`' {
591 codeSpanCloser := 0
592 for ; i < len(bs); i++ {
593 if bs[i] == '`' {
594 codeSpanCloser++
595 } else {
596 i--
597 break
598 }
599 }
600 if codeSpanCloser == codeSpanOpener {
601 codeSpanOpener = 0
602 }
603 } else if codeSpanOpener == 0 && c == '\\' && i < len(bs)-1 && util.IsPunct(bs[i+1]) {
604 i += 2
605 continue
606 } else if opts.CodeSpan && codeSpanOpener == 0 && c == '`' {
607 for ; i < len(bs); i++ {
608 if bs[i] == '`' {
609 codeSpanOpener++
610 } else {
611 i--
612 break
613 }
614 }
615 } else if (opts.CodeSpan && codeSpanOpener == 0) || !opts.CodeSpan {
616 if c == closer {
617 opened--
618 if opened == 0 {
619 if ret == nil {
620 ret = NewSegments()
621 }
622 ret.Append(seg.WithStop(seg.Start + i))
623 r.Advance(i + 1)
624 closed = true
625 goto end
626 }
627 } else if c == opener {
628 if !opts.Nesting {
629 goto end
630 }
631 opened++
632 }
633 }
634 i++
635 }
636 if !opts.Newline {
637 goto end
638 }
639 r.AdvanceLine()
640 if ret == nil {
641 ret = NewSegments()
642 }
643 ret.Append(seg)
644 }
645end:
646 if !opts.Advance {
647 r.SetPosition(orgline, orgpos)
648 }
649 if closed {
650 return ret, true
651 }
652 return nil, false
653}
diff --git a/vendor/github.com/yuin/goldmark/text/segment.go b/vendor/github.com/yuin/goldmark/text/segment.go
new file mode 100644
index 0000000..badd4bc
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/text/segment.go
@@ -0,0 +1,209 @@
1package text
2
3import (
4 "bytes"
5 "github.com/yuin/goldmark/util"
6)
7
8var space = []byte(" ")
9
10// A Segment struct holds information about source positions.
11type Segment struct {
12 // Start is a start position of the segment.
13 Start int
14
15 // Stop is a stop position of the segment.
16 // This value should be excluded.
17 Stop int
18
19 // Padding is a padding length of the segment.
20 Padding int
21}
22
23// NewSegment return a new Segment.
24func NewSegment(start, stop int) Segment {
25 return Segment{
26 Start: start,
27 Stop: stop,
28 Padding: 0,
29 }
30}
31
32// NewSegmentPadding returns a new Segment with the given padding.
33func NewSegmentPadding(start, stop, n int) Segment {
34 return Segment{
35 Start: start,
36 Stop: stop,
37 Padding: n,
38 }
39}
40
41// Value returns a value of the segment.
42func (t *Segment) Value(buffer []byte) []byte {
43 if t.Padding == 0 {
44 return buffer[t.Start:t.Stop]
45 }
46 result := make([]byte, 0, t.Padding+t.Stop-t.Start+1)
47 result = append(result, bytes.Repeat(space, t.Padding)...)
48 return append(result, buffer[t.Start:t.Stop]...)
49}
50
51// Len returns a length of the segment.
52func (t *Segment) Len() int {
53 return t.Stop - t.Start + t.Padding
54}
55
56// Between returns a segment between this segment and the given segment.
57func (t *Segment) Between(other Segment) Segment {
58 if t.Stop != other.Stop {
59 panic("invalid state")
60 }
61 return NewSegmentPadding(
62 t.Start,
63 other.Start,
64 t.Padding-other.Padding,
65 )
66}
67
68// IsEmpty returns true if this segment is empty, otherwise false.
69func (t *Segment) IsEmpty() bool {
70 return t.Start >= t.Stop && t.Padding == 0
71}
72
73// TrimRightSpace returns a new segment by slicing off all trailing
74// space characters.
75func (t *Segment) TrimRightSpace(buffer []byte) Segment {
76 v := buffer[t.Start:t.Stop]
77 l := util.TrimRightSpaceLength(v)
78 if l == len(v) {
79 return NewSegment(t.Start, t.Start)
80 }
81 return NewSegmentPadding(t.Start, t.Stop-l, t.Padding)
82}
83
84// TrimLeftSpace returns a new segment by slicing off all leading
85// space characters including padding.
86func (t *Segment) TrimLeftSpace(buffer []byte) Segment {
87 v := buffer[t.Start:t.Stop]
88 l := util.TrimLeftSpaceLength(v)
89 return NewSegment(t.Start+l, t.Stop)
90}
91
92// TrimLeftSpaceWidth returns a new segment by slicing off leading space
93// characters until the given width.
94func (t *Segment) TrimLeftSpaceWidth(width int, buffer []byte) Segment {
95 padding := t.Padding
96 for ; width > 0; width-- {
97 if padding == 0 {
98 break
99 }
100 padding--
101 }
102 if width == 0 {
103 return NewSegmentPadding(t.Start, t.Stop, padding)
104 }
105 text := buffer[t.Start:t.Stop]
106 start := t.Start
107 for _, c := range text {
108 if start >= t.Stop-1 || width <= 0 {
109 break
110 }
111 if c == ' ' {
112 width--
113 } else if c == '\t' {
114 width -= 4
115 } else {
116 break
117 }
118 start++
119 }
120 if width < 0 {
121 padding = width * -1
122 }
123 return NewSegmentPadding(start, t.Stop, padding)
124}
125
126// WithStart returns a new Segment with same value except Start.
127func (t *Segment) WithStart(v int) Segment {
128 return NewSegmentPadding(v, t.Stop, t.Padding)
129}
130
131// WithStop returns a new Segment with same value except Stop.
132func (t *Segment) WithStop(v int) Segment {
133 return NewSegmentPadding(t.Start, v, t.Padding)
134}
135
136// ConcatPadding concats the padding to the given slice.
137func (t *Segment) ConcatPadding(v []byte) []byte {
138 if t.Padding > 0 {
139 return append(v, bytes.Repeat(space, t.Padding)...)
140 }
141 return v
142}
143
144// Segments is a collection of the Segment.
145type Segments struct {
146 values []Segment
147}
148
149// NewSegments return a new Segments.
150func NewSegments() *Segments {
151 return &Segments{
152 values: nil,
153 }
154}
155
156// Append appends the given segment after the tail of the collection.
157func (s *Segments) Append(t Segment) {
158 if s.values == nil {
159 s.values = make([]Segment, 0, 20)
160 }
161 s.values = append(s.values, t)
162}
163
164// AppendAll appends all elements of given segments after the tail of the collection.
165func (s *Segments) AppendAll(t []Segment) {
166 if s.values == nil {
167 s.values = make([]Segment, 0, 20)
168 }
169 s.values = append(s.values, t...)
170}
171
172// Len returns the length of the collection.
173func (s *Segments) Len() int {
174 if s.values == nil {
175 return 0
176 }
177 return len(s.values)
178}
179
180// At returns a segment at the given index.
181func (s *Segments) At(i int) Segment {
182 return s.values[i]
183}
184
185// Set sets the given Segment.
186func (s *Segments) Set(i int, v Segment) {
187 s.values[i] = v
188}
189
190// SetSliced replace the collection with a subsliced value.
191func (s *Segments) SetSliced(lo, hi int) {
192 s.values = s.values[lo:hi]
193}
194
195// Sliced returns a subslice of the collection.
196func (s *Segments) Sliced(lo, hi int) []Segment {
197 return s.values[lo:hi]
198}
199
200// Clear delete all element of the collection.
201func (s *Segments) Clear() {
202 s.values = nil
203}
204
205// Unshift insert the given Segment to head of the collection.
206func (s *Segments) Unshift(v Segment) {
207 s.values = append(s.values[0:1], s.values[0:]...)
208 s.values[0] = v
209}
diff --git a/vendor/github.com/yuin/goldmark/util/html5entities.go b/vendor/github.com/yuin/goldmark/util/html5entities.go
new file mode 100644
index 0000000..b8e00a9
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/html5entities.go
@@ -0,0 +1,2142 @@
1package util
2
3// An HTML5Entity struct represents HTML5 entitites.
4type HTML5Entity struct {
5 Name string
6 CodePoints []int
7 Characters []byte
8}
9
10// LookUpHTML5EntityByName returns (an HTML5Entity, true) if an entity named
11// given name is found, otherwise (nil, false)
12func LookUpHTML5EntityByName(name string) (*HTML5Entity, bool) {
13 v, ok := html5entities[name]
14 return v, ok
15}
16
17var html5entities = map[string]*HTML5Entity{
18 "AElig": {Name: "AElig", CodePoints: []int{198}, Characters: []byte{0xc3, 0x86}},
19 "AMP": {Name: "AMP", CodePoints: []int{38}, Characters: []byte{0x26}},
20 "Aacute": {Name: "Aacute", CodePoints: []int{193}, Characters: []byte{0xc3, 0x81}},
21 "Acirc": {Name: "Acirc", CodePoints: []int{194}, Characters: []byte{0xc3, 0x82}},
22 "Acy": {Name: "Acy", CodePoints: []int{1040}, Characters: []byte{0xd0, 0x90}},
23 "Afr": {Name: "Afr", CodePoints: []int{120068}, Characters: []byte{0xf0, 0x9d, 0x94, 0x84}},
24 "Agrave": {Name: "Agrave", CodePoints: []int{192}, Characters: []byte{0xc3, 0x80}},
25 "Alpha": {Name: "Alpha", CodePoints: []int{913}, Characters: []byte{0xce, 0x91}},
26 "Amacr": {Name: "Amacr", CodePoints: []int{256}, Characters: []byte{0xc4, 0x80}},
27 "And": {Name: "And", CodePoints: []int{10835}, Characters: []byte{0xe2, 0xa9, 0x93}},
28 "Aogon": {Name: "Aogon", CodePoints: []int{260}, Characters: []byte{0xc4, 0x84}},
29 "Aopf": {Name: "Aopf", CodePoints: []int{120120}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb8}},
30 "ApplyFunction": {Name: "ApplyFunction", CodePoints: []int{8289}, Characters: []byte{0xe2, 0x81, 0xa1}},
31 "Aring": {Name: "Aring", CodePoints: []int{197}, Characters: []byte{0xc3, 0x85}},
32 "Ascr": {Name: "Ascr", CodePoints: []int{119964}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9c}},
33 "Assign": {Name: "Assign", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
34 "Atilde": {Name: "Atilde", CodePoints: []int{195}, Characters: []byte{0xc3, 0x83}},
35 "Auml": {Name: "Auml", CodePoints: []int{196}, Characters: []byte{0xc3, 0x84}},
36 "Backslash": {Name: "Backslash", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
37 "Barv": {Name: "Barv", CodePoints: []int{10983}, Characters: []byte{0xe2, 0xab, 0xa7}},
38 "Barwed": {Name: "Barwed", CodePoints: []int{8966}, Characters: []byte{0xe2, 0x8c, 0x86}},
39 "Bcy": {Name: "Bcy", CodePoints: []int{1041}, Characters: []byte{0xd0, 0x91}},
40 "Because": {Name: "Because", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
41 "Bernoullis": {Name: "Bernoullis", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
42 "Beta": {Name: "Beta", CodePoints: []int{914}, Characters: []byte{0xce, 0x92}},
43 "Bfr": {Name: "Bfr", CodePoints: []int{120069}, Characters: []byte{0xf0, 0x9d, 0x94, 0x85}},
44 "Bopf": {Name: "Bopf", CodePoints: []int{120121}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb9}},
45 "Breve": {Name: "Breve", CodePoints: []int{728}, Characters: []byte{0xcb, 0x98}},
46 "Bscr": {Name: "Bscr", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
47 "Bumpeq": {Name: "Bumpeq", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
48 "CHcy": {Name: "CHcy", CodePoints: []int{1063}, Characters: []byte{0xd0, 0xa7}},
49 "COPY": {Name: "COPY", CodePoints: []int{169}, Characters: []byte{0xc2, 0xa9}},
50 "Cacute": {Name: "Cacute", CodePoints: []int{262}, Characters: []byte{0xc4, 0x86}},
51 "Cap": {Name: "Cap", CodePoints: []int{8914}, Characters: []byte{0xe2, 0x8b, 0x92}},
52 "CapitalDifferentialD": {Name: "CapitalDifferentialD", CodePoints: []int{8517}, Characters: []byte{0xe2, 0x85, 0x85}},
53 "Cayleys": {Name: "Cayleys", CodePoints: []int{8493}, Characters: []byte{0xe2, 0x84, 0xad}},
54 "Ccaron": {Name: "Ccaron", CodePoints: []int{268}, Characters: []byte{0xc4, 0x8c}},
55 "Ccedil": {Name: "Ccedil", CodePoints: []int{199}, Characters: []byte{0xc3, 0x87}},
56 "Ccirc": {Name: "Ccirc", CodePoints: []int{264}, Characters: []byte{0xc4, 0x88}},
57 "Cconint": {Name: "Cconint", CodePoints: []int{8752}, Characters: []byte{0xe2, 0x88, 0xb0}},
58 "Cdot": {Name: "Cdot", CodePoints: []int{266}, Characters: []byte{0xc4, 0x8a}},
59 "Cedilla": {Name: "Cedilla", CodePoints: []int{184}, Characters: []byte{0xc2, 0xb8}},
60 "CenterDot": {Name: "CenterDot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
61 "Cfr": {Name: "Cfr", CodePoints: []int{8493}, Characters: []byte{0xe2, 0x84, 0xad}},
62 "Chi": {Name: "Chi", CodePoints: []int{935}, Characters: []byte{0xce, 0xa7}},
63 "CircleDot": {Name: "CircleDot", CodePoints: []int{8857}, Characters: []byte{0xe2, 0x8a, 0x99}},
64 "CircleMinus": {Name: "CircleMinus", CodePoints: []int{8854}, Characters: []byte{0xe2, 0x8a, 0x96}},
65 "CirclePlus": {Name: "CirclePlus", CodePoints: []int{8853}, Characters: []byte{0xe2, 0x8a, 0x95}},
66 "CircleTimes": {Name: "CircleTimes", CodePoints: []int{8855}, Characters: []byte{0xe2, 0x8a, 0x97}},
67 "ClockwiseContourIntegral": {Name: "ClockwiseContourIntegral", CodePoints: []int{8754}, Characters: []byte{0xe2, 0x88, 0xb2}},
68 "CloseCurlyDoubleQuote": {Name: "CloseCurlyDoubleQuote", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
69 "CloseCurlyQuote": {Name: "CloseCurlyQuote", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
70 "Colon": {Name: "Colon", CodePoints: []int{8759}, Characters: []byte{0xe2, 0x88, 0xb7}},
71 "Colone": {Name: "Colone", CodePoints: []int{10868}, Characters: []byte{0xe2, 0xa9, 0xb4}},
72 "Congruent": {Name: "Congruent", CodePoints: []int{8801}, Characters: []byte{0xe2, 0x89, 0xa1}},
73 "Conint": {Name: "Conint", CodePoints: []int{8751}, Characters: []byte{0xe2, 0x88, 0xaf}},
74 "ContourIntegral": {Name: "ContourIntegral", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
75 "Copf": {Name: "Copf", CodePoints: []int{8450}, Characters: []byte{0xe2, 0x84, 0x82}},
76 "Coproduct": {Name: "Coproduct", CodePoints: []int{8720}, Characters: []byte{0xe2, 0x88, 0x90}},
77 "CounterClockwiseContourIntegral": {Name: "CounterClockwiseContourIntegral", CodePoints: []int{8755}, Characters: []byte{0xe2, 0x88, 0xb3}},
78 "Cross": {Name: "Cross", CodePoints: []int{10799}, Characters: []byte{0xe2, 0xa8, 0xaf}},
79 "Cscr": {Name: "Cscr", CodePoints: []int{119966}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9e}},
80 "Cup": {Name: "Cup", CodePoints: []int{8915}, Characters: []byte{0xe2, 0x8b, 0x93}},
81 "CupCap": {Name: "CupCap", CodePoints: []int{8781}, Characters: []byte{0xe2, 0x89, 0x8d}},
82 "DD": {Name: "DD", CodePoints: []int{8517}, Characters: []byte{0xe2, 0x85, 0x85}},
83 "DDotrahd": {Name: "DDotrahd", CodePoints: []int{10513}, Characters: []byte{0xe2, 0xa4, 0x91}},
84 "DJcy": {Name: "DJcy", CodePoints: []int{1026}, Characters: []byte{0xd0, 0x82}},
85 "DScy": {Name: "DScy", CodePoints: []int{1029}, Characters: []byte{0xd0, 0x85}},
86 "DZcy": {Name: "DZcy", CodePoints: []int{1039}, Characters: []byte{0xd0, 0x8f}},
87 "Dagger": {Name: "Dagger", CodePoints: []int{8225}, Characters: []byte{0xe2, 0x80, 0xa1}},
88 "Darr": {Name: "Darr", CodePoints: []int{8609}, Characters: []byte{0xe2, 0x86, 0xa1}},
89 "Dashv": {Name: "Dashv", CodePoints: []int{10980}, Characters: []byte{0xe2, 0xab, 0xa4}},
90 "Dcaron": {Name: "Dcaron", CodePoints: []int{270}, Characters: []byte{0xc4, 0x8e}},
91 "Dcy": {Name: "Dcy", CodePoints: []int{1044}, Characters: []byte{0xd0, 0x94}},
92 "Del": {Name: "Del", CodePoints: []int{8711}, Characters: []byte{0xe2, 0x88, 0x87}},
93 "Delta": {Name: "Delta", CodePoints: []int{916}, Characters: []byte{0xce, 0x94}},
94 "Dfr": {Name: "Dfr", CodePoints: []int{120071}, Characters: []byte{0xf0, 0x9d, 0x94, 0x87}},
95 "DiacriticalAcute": {Name: "DiacriticalAcute", CodePoints: []int{180}, Characters: []byte{0xc2, 0xb4}},
96 "DiacriticalDot": {Name: "DiacriticalDot", CodePoints: []int{729}, Characters: []byte{0xcb, 0x99}},
97 "DiacriticalDoubleAcute": {Name: "DiacriticalDoubleAcute", CodePoints: []int{733}, Characters: []byte{0xcb, 0x9d}},
98 "DiacriticalGrave": {Name: "DiacriticalGrave", CodePoints: []int{96}, Characters: []byte{0x60}},
99 "DiacriticalTilde": {Name: "DiacriticalTilde", CodePoints: []int{732}, Characters: []byte{0xcb, 0x9c}},
100 "Diamond": {Name: "Diamond", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
101 "DifferentialD": {Name: "DifferentialD", CodePoints: []int{8518}, Characters: []byte{0xe2, 0x85, 0x86}},
102 "Dopf": {Name: "Dopf", CodePoints: []int{120123}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbb}},
103 "Dot": {Name: "Dot", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
104 "DotDot": {Name: "DotDot", CodePoints: []int{8412}, Characters: []byte{0xe2, 0x83, 0x9c}},
105 "DotEqual": {Name: "DotEqual", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
106 "DoubleContourIntegral": {Name: "DoubleContourIntegral", CodePoints: []int{8751}, Characters: []byte{0xe2, 0x88, 0xaf}},
107 "DoubleDot": {Name: "DoubleDot", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
108 "DoubleDownArrow": {Name: "DoubleDownArrow", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
109 "DoubleLeftArrow": {Name: "DoubleLeftArrow", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
110 "DoubleLeftRightArrow": {Name: "DoubleLeftRightArrow", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
111 "DoubleLeftTee": {Name: "DoubleLeftTee", CodePoints: []int{10980}, Characters: []byte{0xe2, 0xab, 0xa4}},
112 "DoubleLongLeftArrow": {Name: "DoubleLongLeftArrow", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
113 "DoubleLongLeftRightArrow": {Name: "DoubleLongLeftRightArrow", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
114 "DoubleLongRightArrow": {Name: "DoubleLongRightArrow", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
115 "DoubleRightArrow": {Name: "DoubleRightArrow", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
116 "DoubleRightTee": {Name: "DoubleRightTee", CodePoints: []int{8872}, Characters: []byte{0xe2, 0x8a, 0xa8}},
117 "DoubleUpArrow": {Name: "DoubleUpArrow", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
118 "DoubleUpDownArrow": {Name: "DoubleUpDownArrow", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
119 "DoubleVerticalBar": {Name: "DoubleVerticalBar", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
120 "DownArrow": {Name: "DownArrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
121 "DownArrowBar": {Name: "DownArrowBar", CodePoints: []int{10515}, Characters: []byte{0xe2, 0xa4, 0x93}},
122 "DownArrowUpArrow": {Name: "DownArrowUpArrow", CodePoints: []int{8693}, Characters: []byte{0xe2, 0x87, 0xb5}},
123 "DownBreve": {Name: "DownBreve", CodePoints: []int{785}, Characters: []byte{0xcc, 0x91}},
124 "DownLeftRightVector": {Name: "DownLeftRightVector", CodePoints: []int{10576}, Characters: []byte{0xe2, 0xa5, 0x90}},
125 "DownLeftTeeVector": {Name: "DownLeftTeeVector", CodePoints: []int{10590}, Characters: []byte{0xe2, 0xa5, 0x9e}},
126 "DownLeftVector": {Name: "DownLeftVector", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
127 "DownLeftVectorBar": {Name: "DownLeftVectorBar", CodePoints: []int{10582}, Characters: []byte{0xe2, 0xa5, 0x96}},
128 "DownRightTeeVector": {Name: "DownRightTeeVector", CodePoints: []int{10591}, Characters: []byte{0xe2, 0xa5, 0x9f}},
129 "DownRightVector": {Name: "DownRightVector", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
130 "DownRightVectorBar": {Name: "DownRightVectorBar", CodePoints: []int{10583}, Characters: []byte{0xe2, 0xa5, 0x97}},
131 "DownTee": {Name: "DownTee", CodePoints: []int{8868}, Characters: []byte{0xe2, 0x8a, 0xa4}},
132 "DownTeeArrow": {Name: "DownTeeArrow", CodePoints: []int{8615}, Characters: []byte{0xe2, 0x86, 0xa7}},
133 "Downarrow": {Name: "Downarrow", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
134 "Dscr": {Name: "Dscr", CodePoints: []int{119967}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9f}},
135 "Dstrok": {Name: "Dstrok", CodePoints: []int{272}, Characters: []byte{0xc4, 0x90}},
136 "ENG": {Name: "ENG", CodePoints: []int{330}, Characters: []byte{0xc5, 0x8a}},
137 "ETH": {Name: "ETH", CodePoints: []int{208}, Characters: []byte{0xc3, 0x90}},
138 "Eacute": {Name: "Eacute", CodePoints: []int{201}, Characters: []byte{0xc3, 0x89}},
139 "Ecaron": {Name: "Ecaron", CodePoints: []int{282}, Characters: []byte{0xc4, 0x9a}},
140 "Ecirc": {Name: "Ecirc", CodePoints: []int{202}, Characters: []byte{0xc3, 0x8a}},
141 "Ecy": {Name: "Ecy", CodePoints: []int{1069}, Characters: []byte{0xd0, 0xad}},
142 "Edot": {Name: "Edot", CodePoints: []int{278}, Characters: []byte{0xc4, 0x96}},
143 "Efr": {Name: "Efr", CodePoints: []int{120072}, Characters: []byte{0xf0, 0x9d, 0x94, 0x88}},
144 "Egrave": {Name: "Egrave", CodePoints: []int{200}, Characters: []byte{0xc3, 0x88}},
145 "Element": {Name: "Element", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
146 "Emacr": {Name: "Emacr", CodePoints: []int{274}, Characters: []byte{0xc4, 0x92}},
147 "EmptySmallSquare": {Name: "EmptySmallSquare", CodePoints: []int{9723}, Characters: []byte{0xe2, 0x97, 0xbb}},
148 "EmptyVerySmallSquare": {Name: "EmptyVerySmallSquare", CodePoints: []int{9643}, Characters: []byte{0xe2, 0x96, 0xab}},
149 "Eogon": {Name: "Eogon", CodePoints: []int{280}, Characters: []byte{0xc4, 0x98}},
150 "Eopf": {Name: "Eopf", CodePoints: []int{120124}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbc}},
151 "Epsilon": {Name: "Epsilon", CodePoints: []int{917}, Characters: []byte{0xce, 0x95}},
152 "Equal": {Name: "Equal", CodePoints: []int{10869}, Characters: []byte{0xe2, 0xa9, 0xb5}},
153 "EqualTilde": {Name: "EqualTilde", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
154 "Equilibrium": {Name: "Equilibrium", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
155 "Escr": {Name: "Escr", CodePoints: []int{8496}, Characters: []byte{0xe2, 0x84, 0xb0}},
156 "Esim": {Name: "Esim", CodePoints: []int{10867}, Characters: []byte{0xe2, 0xa9, 0xb3}},
157 "Eta": {Name: "Eta", CodePoints: []int{919}, Characters: []byte{0xce, 0x97}},
158 "Euml": {Name: "Euml", CodePoints: []int{203}, Characters: []byte{0xc3, 0x8b}},
159 "Exists": {Name: "Exists", CodePoints: []int{8707}, Characters: []byte{0xe2, 0x88, 0x83}},
160 "ExponentialE": {Name: "ExponentialE", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
161 "Fcy": {Name: "Fcy", CodePoints: []int{1060}, Characters: []byte{0xd0, 0xa4}},
162 "Ffr": {Name: "Ffr", CodePoints: []int{120073}, Characters: []byte{0xf0, 0x9d, 0x94, 0x89}},
163 "FilledSmallSquare": {Name: "FilledSmallSquare", CodePoints: []int{9724}, Characters: []byte{0xe2, 0x97, 0xbc}},
164 "FilledVerySmallSquare": {Name: "FilledVerySmallSquare", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
165 "Fopf": {Name: "Fopf", CodePoints: []int{120125}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbd}},
166 "ForAll": {Name: "ForAll", CodePoints: []int{8704}, Characters: []byte{0xe2, 0x88, 0x80}},
167 "Fouriertrf": {Name: "Fouriertrf", CodePoints: []int{8497}, Characters: []byte{0xe2, 0x84, 0xb1}},
168 "Fscr": {Name: "Fscr", CodePoints: []int{8497}, Characters: []byte{0xe2, 0x84, 0xb1}},
169 "GJcy": {Name: "GJcy", CodePoints: []int{1027}, Characters: []byte{0xd0, 0x83}},
170 "GT": {Name: "GT", CodePoints: []int{62}, Characters: []byte{0x3e}},
171 "Gamma": {Name: "Gamma", CodePoints: []int{915}, Characters: []byte{0xce, 0x93}},
172 "Gammad": {Name: "Gammad", CodePoints: []int{988}, Characters: []byte{0xcf, 0x9c}},
173 "Gbreve": {Name: "Gbreve", CodePoints: []int{286}, Characters: []byte{0xc4, 0x9e}},
174 "Gcedil": {Name: "Gcedil", CodePoints: []int{290}, Characters: []byte{0xc4, 0xa2}},
175 "Gcirc": {Name: "Gcirc", CodePoints: []int{284}, Characters: []byte{0xc4, 0x9c}},
176 "Gcy": {Name: "Gcy", CodePoints: []int{1043}, Characters: []byte{0xd0, 0x93}},
177 "Gdot": {Name: "Gdot", CodePoints: []int{288}, Characters: []byte{0xc4, 0xa0}},
178 "Gfr": {Name: "Gfr", CodePoints: []int{120074}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8a}},
179 "Gg": {Name: "Gg", CodePoints: []int{8921}, Characters: []byte{0xe2, 0x8b, 0x99}},
180 "Gopf": {Name: "Gopf", CodePoints: []int{120126}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbe}},
181 "GreaterEqual": {Name: "GreaterEqual", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
182 "GreaterEqualLess": {Name: "GreaterEqualLess", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
183 "GreaterFullEqual": {Name: "GreaterFullEqual", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
184 "GreaterGreater": {Name: "GreaterGreater", CodePoints: []int{10914}, Characters: []byte{0xe2, 0xaa, 0xa2}},
185 "GreaterLess": {Name: "GreaterLess", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
186 "GreaterSlantEqual": {Name: "GreaterSlantEqual", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
187 "GreaterTilde": {Name: "GreaterTilde", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
188 "Gscr": {Name: "Gscr", CodePoints: []int{119970}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa2}},
189 "Gt": {Name: "Gt", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
190 "HARDcy": {Name: "HARDcy", CodePoints: []int{1066}, Characters: []byte{0xd0, 0xaa}},
191 "Hacek": {Name: "Hacek", CodePoints: []int{711}, Characters: []byte{0xcb, 0x87}},
192 "Hat": {Name: "Hat", CodePoints: []int{94}, Characters: []byte{0x5e}},
193 "Hcirc": {Name: "Hcirc", CodePoints: []int{292}, Characters: []byte{0xc4, 0xa4}},
194 "Hfr": {Name: "Hfr", CodePoints: []int{8460}, Characters: []byte{0xe2, 0x84, 0x8c}},
195 "HilbertSpace": {Name: "HilbertSpace", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
196 "Hopf": {Name: "Hopf", CodePoints: []int{8461}, Characters: []byte{0xe2, 0x84, 0x8d}},
197 "HorizontalLine": {Name: "HorizontalLine", CodePoints: []int{9472}, Characters: []byte{0xe2, 0x94, 0x80}},
198 "Hscr": {Name: "Hscr", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
199 "Hstrok": {Name: "Hstrok", CodePoints: []int{294}, Characters: []byte{0xc4, 0xa6}},
200 "HumpDownHump": {Name: "HumpDownHump", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
201 "HumpEqual": {Name: "HumpEqual", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
202 "IEcy": {Name: "IEcy", CodePoints: []int{1045}, Characters: []byte{0xd0, 0x95}},
203 "IJlig": {Name: "IJlig", CodePoints: []int{306}, Characters: []byte{0xc4, 0xb2}},
204 "IOcy": {Name: "IOcy", CodePoints: []int{1025}, Characters: []byte{0xd0, 0x81}},
205 "Iacute": {Name: "Iacute", CodePoints: []int{205}, Characters: []byte{0xc3, 0x8d}},
206 "Icirc": {Name: "Icirc", CodePoints: []int{206}, Characters: []byte{0xc3, 0x8e}},
207 "Icy": {Name: "Icy", CodePoints: []int{1048}, Characters: []byte{0xd0, 0x98}},
208 "Idot": {Name: "Idot", CodePoints: []int{304}, Characters: []byte{0xc4, 0xb0}},
209 "Ifr": {Name: "Ifr", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
210 "Igrave": {Name: "Igrave", CodePoints: []int{204}, Characters: []byte{0xc3, 0x8c}},
211 "Im": {Name: "Im", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
212 "Imacr": {Name: "Imacr", CodePoints: []int{298}, Characters: []byte{0xc4, 0xaa}},
213 "ImaginaryI": {Name: "ImaginaryI", CodePoints: []int{8520}, Characters: []byte{0xe2, 0x85, 0x88}},
214 "Implies": {Name: "Implies", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
215 "Int": {Name: "Int", CodePoints: []int{8748}, Characters: []byte{0xe2, 0x88, 0xac}},
216 "Integral": {Name: "Integral", CodePoints: []int{8747}, Characters: []byte{0xe2, 0x88, 0xab}},
217 "Intersection": {Name: "Intersection", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
218 "InvisibleComma": {Name: "InvisibleComma", CodePoints: []int{8291}, Characters: []byte{0xe2, 0x81, 0xa3}},
219 "InvisibleTimes": {Name: "InvisibleTimes", CodePoints: []int{8290}, Characters: []byte{0xe2, 0x81, 0xa2}},
220 "Iogon": {Name: "Iogon", CodePoints: []int{302}, Characters: []byte{0xc4, 0xae}},
221 "Iopf": {Name: "Iopf", CodePoints: []int{120128}, Characters: []byte{0xf0, 0x9d, 0x95, 0x80}},
222 "Iota": {Name: "Iota", CodePoints: []int{921}, Characters: []byte{0xce, 0x99}},
223 "Iscr": {Name: "Iscr", CodePoints: []int{8464}, Characters: []byte{0xe2, 0x84, 0x90}},
224 "Itilde": {Name: "Itilde", CodePoints: []int{296}, Characters: []byte{0xc4, 0xa8}},
225 "Iukcy": {Name: "Iukcy", CodePoints: []int{1030}, Characters: []byte{0xd0, 0x86}},
226 "Iuml": {Name: "Iuml", CodePoints: []int{207}, Characters: []byte{0xc3, 0x8f}},
227 "Jcirc": {Name: "Jcirc", CodePoints: []int{308}, Characters: []byte{0xc4, 0xb4}},
228 "Jcy": {Name: "Jcy", CodePoints: []int{1049}, Characters: []byte{0xd0, 0x99}},
229 "Jfr": {Name: "Jfr", CodePoints: []int{120077}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8d}},
230 "Jopf": {Name: "Jopf", CodePoints: []int{120129}, Characters: []byte{0xf0, 0x9d, 0x95, 0x81}},
231 "Jscr": {Name: "Jscr", CodePoints: []int{119973}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa5}},
232 "Jsercy": {Name: "Jsercy", CodePoints: []int{1032}, Characters: []byte{0xd0, 0x88}},
233 "Jukcy": {Name: "Jukcy", CodePoints: []int{1028}, Characters: []byte{0xd0, 0x84}},
234 "KHcy": {Name: "KHcy", CodePoints: []int{1061}, Characters: []byte{0xd0, 0xa5}},
235 "KJcy": {Name: "KJcy", CodePoints: []int{1036}, Characters: []byte{0xd0, 0x8c}},
236 "Kappa": {Name: "Kappa", CodePoints: []int{922}, Characters: []byte{0xce, 0x9a}},
237 "Kcedil": {Name: "Kcedil", CodePoints: []int{310}, Characters: []byte{0xc4, 0xb6}},
238 "Kcy": {Name: "Kcy", CodePoints: []int{1050}, Characters: []byte{0xd0, 0x9a}},
239 "Kfr": {Name: "Kfr", CodePoints: []int{120078}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8e}},
240 "Kopf": {Name: "Kopf", CodePoints: []int{120130}, Characters: []byte{0xf0, 0x9d, 0x95, 0x82}},
241 "Kscr": {Name: "Kscr", CodePoints: []int{119974}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa6}},
242 "LJcy": {Name: "LJcy", CodePoints: []int{1033}, Characters: []byte{0xd0, 0x89}},
243 "LT": {Name: "LT", CodePoints: []int{60}, Characters: []byte{0x3c}},
244 "Lacute": {Name: "Lacute", CodePoints: []int{313}, Characters: []byte{0xc4, 0xb9}},
245 "Lambda": {Name: "Lambda", CodePoints: []int{923}, Characters: []byte{0xce, 0x9b}},
246 "Lang": {Name: "Lang", CodePoints: []int{10218}, Characters: []byte{0xe2, 0x9f, 0xaa}},
247 "Laplacetrf": {Name: "Laplacetrf", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
248 "Larr": {Name: "Larr", CodePoints: []int{8606}, Characters: []byte{0xe2, 0x86, 0x9e}},
249 "Lcaron": {Name: "Lcaron", CodePoints: []int{317}, Characters: []byte{0xc4, 0xbd}},
250 "Lcedil": {Name: "Lcedil", CodePoints: []int{315}, Characters: []byte{0xc4, 0xbb}},
251 "Lcy": {Name: "Lcy", CodePoints: []int{1051}, Characters: []byte{0xd0, 0x9b}},
252 "LeftAngleBracket": {Name: "LeftAngleBracket", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
253 "LeftArrow": {Name: "LeftArrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
254 "LeftArrowBar": {Name: "LeftArrowBar", CodePoints: []int{8676}, Characters: []byte{0xe2, 0x87, 0xa4}},
255 "LeftArrowRightArrow": {Name: "LeftArrowRightArrow", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
256 "LeftCeiling": {Name: "LeftCeiling", CodePoints: []int{8968}, Characters: []byte{0xe2, 0x8c, 0x88}},
257 "LeftDoubleBracket": {Name: "LeftDoubleBracket", CodePoints: []int{10214}, Characters: []byte{0xe2, 0x9f, 0xa6}},
258 "LeftDownTeeVector": {Name: "LeftDownTeeVector", CodePoints: []int{10593}, Characters: []byte{0xe2, 0xa5, 0xa1}},
259 "LeftDownVector": {Name: "LeftDownVector", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
260 "LeftDownVectorBar": {Name: "LeftDownVectorBar", CodePoints: []int{10585}, Characters: []byte{0xe2, 0xa5, 0x99}},
261 "LeftFloor": {Name: "LeftFloor", CodePoints: []int{8970}, Characters: []byte{0xe2, 0x8c, 0x8a}},
262 "LeftRightArrow": {Name: "LeftRightArrow", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
263 "LeftRightVector": {Name: "LeftRightVector", CodePoints: []int{10574}, Characters: []byte{0xe2, 0xa5, 0x8e}},
264 "LeftTee": {Name: "LeftTee", CodePoints: []int{8867}, Characters: []byte{0xe2, 0x8a, 0xa3}},
265 "LeftTeeArrow": {Name: "LeftTeeArrow", CodePoints: []int{8612}, Characters: []byte{0xe2, 0x86, 0xa4}},
266 "LeftTeeVector": {Name: "LeftTeeVector", CodePoints: []int{10586}, Characters: []byte{0xe2, 0xa5, 0x9a}},
267 "LeftTriangle": {Name: "LeftTriangle", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
268 "LeftTriangleBar": {Name: "LeftTriangleBar", CodePoints: []int{10703}, Characters: []byte{0xe2, 0xa7, 0x8f}},
269 "LeftTriangleEqual": {Name: "LeftTriangleEqual", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
270 "LeftUpDownVector": {Name: "LeftUpDownVector", CodePoints: []int{10577}, Characters: []byte{0xe2, 0xa5, 0x91}},
271 "LeftUpTeeVector": {Name: "LeftUpTeeVector", CodePoints: []int{10592}, Characters: []byte{0xe2, 0xa5, 0xa0}},
272 "LeftUpVector": {Name: "LeftUpVector", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
273 "LeftUpVectorBar": {Name: "LeftUpVectorBar", CodePoints: []int{10584}, Characters: []byte{0xe2, 0xa5, 0x98}},
274 "LeftVector": {Name: "LeftVector", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
275 "LeftVectorBar": {Name: "LeftVectorBar", CodePoints: []int{10578}, Characters: []byte{0xe2, 0xa5, 0x92}},
276 "Leftarrow": {Name: "Leftarrow", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
277 "Leftrightarrow": {Name: "Leftrightarrow", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
278 "LessEqualGreater": {Name: "LessEqualGreater", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
279 "LessFullEqual": {Name: "LessFullEqual", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
280 "LessGreater": {Name: "LessGreater", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
281 "LessLess": {Name: "LessLess", CodePoints: []int{10913}, Characters: []byte{0xe2, 0xaa, 0xa1}},
282 "LessSlantEqual": {Name: "LessSlantEqual", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
283 "LessTilde": {Name: "LessTilde", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
284 "Lfr": {Name: "Lfr", CodePoints: []int{120079}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8f}},
285 "Ll": {Name: "Ll", CodePoints: []int{8920}, Characters: []byte{0xe2, 0x8b, 0x98}},
286 "Lleftarrow": {Name: "Lleftarrow", CodePoints: []int{8666}, Characters: []byte{0xe2, 0x87, 0x9a}},
287 "Lmidot": {Name: "Lmidot", CodePoints: []int{319}, Characters: []byte{0xc4, 0xbf}},
288 "LongLeftArrow": {Name: "LongLeftArrow", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
289 "LongLeftRightArrow": {Name: "LongLeftRightArrow", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
290 "LongRightArrow": {Name: "LongRightArrow", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
291 "Longleftarrow": {Name: "Longleftarrow", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
292 "Longleftrightarrow": {Name: "Longleftrightarrow", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
293 "Longrightarrow": {Name: "Longrightarrow", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
294 "Lopf": {Name: "Lopf", CodePoints: []int{120131}, Characters: []byte{0xf0, 0x9d, 0x95, 0x83}},
295 "LowerLeftArrow": {Name: "LowerLeftArrow", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
296 "LowerRightArrow": {Name: "LowerRightArrow", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
297 "Lscr": {Name: "Lscr", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
298 "Lsh": {Name: "Lsh", CodePoints: []int{8624}, Characters: []byte{0xe2, 0x86, 0xb0}},
299 "Lstrok": {Name: "Lstrok", CodePoints: []int{321}, Characters: []byte{0xc5, 0x81}},
300 "Lt": {Name: "Lt", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
301 "Map": {Name: "Map", CodePoints: []int{10501}, Characters: []byte{0xe2, 0xa4, 0x85}},
302 "Mcy": {Name: "Mcy", CodePoints: []int{1052}, Characters: []byte{0xd0, 0x9c}},
303 "MediumSpace": {Name: "MediumSpace", CodePoints: []int{8287}, Characters: []byte{0xe2, 0x81, 0x9f}},
304 "Mellintrf": {Name: "Mellintrf", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
305 "Mfr": {Name: "Mfr", CodePoints: []int{120080}, Characters: []byte{0xf0, 0x9d, 0x94, 0x90}},
306 "MinusPlus": {Name: "MinusPlus", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
307 "Mopf": {Name: "Mopf", CodePoints: []int{120132}, Characters: []byte{0xf0, 0x9d, 0x95, 0x84}},
308 "Mscr": {Name: "Mscr", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
309 "Mu": {Name: "Mu", CodePoints: []int{924}, Characters: []byte{0xce, 0x9c}},
310 "NJcy": {Name: "NJcy", CodePoints: []int{1034}, Characters: []byte{0xd0, 0x8a}},
311 "Nacute": {Name: "Nacute", CodePoints: []int{323}, Characters: []byte{0xc5, 0x83}},
312 "Ncaron": {Name: "Ncaron", CodePoints: []int{327}, Characters: []byte{0xc5, 0x87}},
313 "Ncedil": {Name: "Ncedil", CodePoints: []int{325}, Characters: []byte{0xc5, 0x85}},
314 "Ncy": {Name: "Ncy", CodePoints: []int{1053}, Characters: []byte{0xd0, 0x9d}},
315 "NegativeMediumSpace": {Name: "NegativeMediumSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
316 "NegativeThickSpace": {Name: "NegativeThickSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
317 "NegativeThinSpace": {Name: "NegativeThinSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
318 "NegativeVeryThinSpace": {Name: "NegativeVeryThinSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
319 "NestedGreaterGreater": {Name: "NestedGreaterGreater", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
320 "NestedLessLess": {Name: "NestedLessLess", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
321 "NewLine": {Name: "NewLine", CodePoints: []int{10}, Characters: []byte{0xa}},
322 "Nfr": {Name: "Nfr", CodePoints: []int{120081}, Characters: []byte{0xf0, 0x9d, 0x94, 0x91}},
323 "NoBreak": {Name: "NoBreak", CodePoints: []int{8288}, Characters: []byte{0xe2, 0x81, 0xa0}},
324 "NonBreakingSpace": {Name: "NonBreakingSpace", CodePoints: []int{160}, Characters: []byte{0xc2, 0xa0}},
325 "Nopf": {Name: "Nopf", CodePoints: []int{8469}, Characters: []byte{0xe2, 0x84, 0x95}},
326 "Not": {Name: "Not", CodePoints: []int{10988}, Characters: []byte{0xe2, 0xab, 0xac}},
327 "NotCongruent": {Name: "NotCongruent", CodePoints: []int{8802}, Characters: []byte{0xe2, 0x89, 0xa2}},
328 "NotCupCap": {Name: "NotCupCap", CodePoints: []int{8813}, Characters: []byte{0xe2, 0x89, 0xad}},
329 "NotDoubleVerticalBar": {Name: "NotDoubleVerticalBar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
330 "NotElement": {Name: "NotElement", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
331 "NotEqual": {Name: "NotEqual", CodePoints: []int{8800}, Characters: []byte{0xe2, 0x89, 0xa0}},
332 "NotEqualTilde": {Name: "NotEqualTilde", CodePoints: []int{8770, 824}, Characters: []byte{0xe2, 0x89, 0x82, 0xcc, 0xb8}},
333 "NotExists": {Name: "NotExists", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
334 "NotGreater": {Name: "NotGreater", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
335 "NotGreaterEqual": {Name: "NotGreaterEqual", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
336 "NotGreaterFullEqual": {Name: "NotGreaterFullEqual", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
337 "NotGreaterGreater": {Name: "NotGreaterGreater", CodePoints: []int{8811, 824}, Characters: []byte{0xe2, 0x89, 0xab, 0xcc, 0xb8}},
338 "NotGreaterLess": {Name: "NotGreaterLess", CodePoints: []int{8825}, Characters: []byte{0xe2, 0x89, 0xb9}},
339 "NotGreaterSlantEqual": {Name: "NotGreaterSlantEqual", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
340 "NotGreaterTilde": {Name: "NotGreaterTilde", CodePoints: []int{8821}, Characters: []byte{0xe2, 0x89, 0xb5}},
341 "NotHumpDownHump": {Name: "NotHumpDownHump", CodePoints: []int{8782, 824}, Characters: []byte{0xe2, 0x89, 0x8e, 0xcc, 0xb8}},
342 "NotHumpEqual": {Name: "NotHumpEqual", CodePoints: []int{8783, 824}, Characters: []byte{0xe2, 0x89, 0x8f, 0xcc, 0xb8}},
343 "NotLeftTriangle": {Name: "NotLeftTriangle", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
344 "NotLeftTriangleBar": {Name: "NotLeftTriangleBar", CodePoints: []int{10703, 824}, Characters: []byte{0xe2, 0xa7, 0x8f, 0xcc, 0xb8}},
345 "NotLeftTriangleEqual": {Name: "NotLeftTriangleEqual", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
346 "NotLess": {Name: "NotLess", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
347 "NotLessEqual": {Name: "NotLessEqual", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
348 "NotLessGreater": {Name: "NotLessGreater", CodePoints: []int{8824}, Characters: []byte{0xe2, 0x89, 0xb8}},
349 "NotLessLess": {Name: "NotLessLess", CodePoints: []int{8810, 824}, Characters: []byte{0xe2, 0x89, 0xaa, 0xcc, 0xb8}},
350 "NotLessSlantEqual": {Name: "NotLessSlantEqual", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
351 "NotLessTilde": {Name: "NotLessTilde", CodePoints: []int{8820}, Characters: []byte{0xe2, 0x89, 0xb4}},
352 "NotNestedGreaterGreater": {Name: "NotNestedGreaterGreater", CodePoints: []int{10914, 824}, Characters: []byte{0xe2, 0xaa, 0xa2, 0xcc, 0xb8}},
353 "NotNestedLessLess": {Name: "NotNestedLessLess", CodePoints: []int{10913, 824}, Characters: []byte{0xe2, 0xaa, 0xa1, 0xcc, 0xb8}},
354 "NotPrecedes": {Name: "NotPrecedes", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
355 "NotPrecedesEqual": {Name: "NotPrecedesEqual", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
356 "NotPrecedesSlantEqual": {Name: "NotPrecedesSlantEqual", CodePoints: []int{8928}, Characters: []byte{0xe2, 0x8b, 0xa0}},
357 "NotReverseElement": {Name: "NotReverseElement", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
358 "NotRightTriangle": {Name: "NotRightTriangle", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
359 "NotRightTriangleBar": {Name: "NotRightTriangleBar", CodePoints: []int{10704, 824}, Characters: []byte{0xe2, 0xa7, 0x90, 0xcc, 0xb8}},
360 "NotRightTriangleEqual": {Name: "NotRightTriangleEqual", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
361 "NotSquareSubset": {Name: "NotSquareSubset", CodePoints: []int{8847, 824}, Characters: []byte{0xe2, 0x8a, 0x8f, 0xcc, 0xb8}},
362 "NotSquareSubsetEqual": {Name: "NotSquareSubsetEqual", CodePoints: []int{8930}, Characters: []byte{0xe2, 0x8b, 0xa2}},
363 "NotSquareSuperset": {Name: "NotSquareSuperset", CodePoints: []int{8848, 824}, Characters: []byte{0xe2, 0x8a, 0x90, 0xcc, 0xb8}},
364 "NotSquareSupersetEqual": {Name: "NotSquareSupersetEqual", CodePoints: []int{8931}, Characters: []byte{0xe2, 0x8b, 0xa3}},
365 "NotSubset": {Name: "NotSubset", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
366 "NotSubsetEqual": {Name: "NotSubsetEqual", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
367 "NotSucceeds": {Name: "NotSucceeds", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
368 "NotSucceedsEqual": {Name: "NotSucceedsEqual", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
369 "NotSucceedsSlantEqual": {Name: "NotSucceedsSlantEqual", CodePoints: []int{8929}, Characters: []byte{0xe2, 0x8b, 0xa1}},
370 "NotSucceedsTilde": {Name: "NotSucceedsTilde", CodePoints: []int{8831, 824}, Characters: []byte{0xe2, 0x89, 0xbf, 0xcc, 0xb8}},
371 "NotSuperset": {Name: "NotSuperset", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
372 "NotSupersetEqual": {Name: "NotSupersetEqual", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
373 "NotTilde": {Name: "NotTilde", CodePoints: []int{8769}, Characters: []byte{0xe2, 0x89, 0x81}},
374 "NotTildeEqual": {Name: "NotTildeEqual", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
375 "NotTildeFullEqual": {Name: "NotTildeFullEqual", CodePoints: []int{8775}, Characters: []byte{0xe2, 0x89, 0x87}},
376 "NotTildeTilde": {Name: "NotTildeTilde", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
377 "NotVerticalBar": {Name: "NotVerticalBar", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
378 "Nscr": {Name: "Nscr", CodePoints: []int{119977}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa9}},
379 "Ntilde": {Name: "Ntilde", CodePoints: []int{209}, Characters: []byte{0xc3, 0x91}},
380 "Nu": {Name: "Nu", CodePoints: []int{925}, Characters: []byte{0xce, 0x9d}},
381 "OElig": {Name: "OElig", CodePoints: []int{338}, Characters: []byte{0xc5, 0x92}},
382 "Oacute": {Name: "Oacute", CodePoints: []int{211}, Characters: []byte{0xc3, 0x93}},
383 "Ocirc": {Name: "Ocirc", CodePoints: []int{212}, Characters: []byte{0xc3, 0x94}},
384 "Ocy": {Name: "Ocy", CodePoints: []int{1054}, Characters: []byte{0xd0, 0x9e}},
385 "Odblac": {Name: "Odblac", CodePoints: []int{336}, Characters: []byte{0xc5, 0x90}},
386 "Ofr": {Name: "Ofr", CodePoints: []int{120082}, Characters: []byte{0xf0, 0x9d, 0x94, 0x92}},
387 "Ograve": {Name: "Ograve", CodePoints: []int{210}, Characters: []byte{0xc3, 0x92}},
388 "Omacr": {Name: "Omacr", CodePoints: []int{332}, Characters: []byte{0xc5, 0x8c}},
389 "Omega": {Name: "Omega", CodePoints: []int{937}, Characters: []byte{0xce, 0xa9}},
390 "Omicron": {Name: "Omicron", CodePoints: []int{927}, Characters: []byte{0xce, 0x9f}},
391 "Oopf": {Name: "Oopf", CodePoints: []int{120134}, Characters: []byte{0xf0, 0x9d, 0x95, 0x86}},
392 "OpenCurlyDoubleQuote": {Name: "OpenCurlyDoubleQuote", CodePoints: []int{8220}, Characters: []byte{0xe2, 0x80, 0x9c}},
393 "OpenCurlyQuote": {Name: "OpenCurlyQuote", CodePoints: []int{8216}, Characters: []byte{0xe2, 0x80, 0x98}},
394 "Or": {Name: "Or", CodePoints: []int{10836}, Characters: []byte{0xe2, 0xa9, 0x94}},
395 "Oscr": {Name: "Oscr", CodePoints: []int{119978}, Characters: []byte{0xf0, 0x9d, 0x92, 0xaa}},
396 "Oslash": {Name: "Oslash", CodePoints: []int{216}, Characters: []byte{0xc3, 0x98}},
397 "Otilde": {Name: "Otilde", CodePoints: []int{213}, Characters: []byte{0xc3, 0x95}},
398 "Otimes": {Name: "Otimes", CodePoints: []int{10807}, Characters: []byte{0xe2, 0xa8, 0xb7}},
399 "Ouml": {Name: "Ouml", CodePoints: []int{214}, Characters: []byte{0xc3, 0x96}},
400 "OverBar": {Name: "OverBar", CodePoints: []int{8254}, Characters: []byte{0xe2, 0x80, 0xbe}},
401 "OverBrace": {Name: "OverBrace", CodePoints: []int{9182}, Characters: []byte{0xe2, 0x8f, 0x9e}},
402 "OverBracket": {Name: "OverBracket", CodePoints: []int{9140}, Characters: []byte{0xe2, 0x8e, 0xb4}},
403 "OverParenthesis": {Name: "OverParenthesis", CodePoints: []int{9180}, Characters: []byte{0xe2, 0x8f, 0x9c}},
404 "PartialD": {Name: "PartialD", CodePoints: []int{8706}, Characters: []byte{0xe2, 0x88, 0x82}},
405 "Pcy": {Name: "Pcy", CodePoints: []int{1055}, Characters: []byte{0xd0, 0x9f}},
406 "Pfr": {Name: "Pfr", CodePoints: []int{120083}, Characters: []byte{0xf0, 0x9d, 0x94, 0x93}},
407 "Phi": {Name: "Phi", CodePoints: []int{934}, Characters: []byte{0xce, 0xa6}},
408 "Pi": {Name: "Pi", CodePoints: []int{928}, Characters: []byte{0xce, 0xa0}},
409 "PlusMinus": {Name: "PlusMinus", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
410 "Poincareplane": {Name: "Poincareplane", CodePoints: []int{8460}, Characters: []byte{0xe2, 0x84, 0x8c}},
411 "Popf": {Name: "Popf", CodePoints: []int{8473}, Characters: []byte{0xe2, 0x84, 0x99}},
412 "Pr": {Name: "Pr", CodePoints: []int{10939}, Characters: []byte{0xe2, 0xaa, 0xbb}},
413 "Precedes": {Name: "Precedes", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
414 "PrecedesEqual": {Name: "PrecedesEqual", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
415 "PrecedesSlantEqual": {Name: "PrecedesSlantEqual", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
416 "PrecedesTilde": {Name: "PrecedesTilde", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
417 "Prime": {Name: "Prime", CodePoints: []int{8243}, Characters: []byte{0xe2, 0x80, 0xb3}},
418 "Product": {Name: "Product", CodePoints: []int{8719}, Characters: []byte{0xe2, 0x88, 0x8f}},
419 "Proportion": {Name: "Proportion", CodePoints: []int{8759}, Characters: []byte{0xe2, 0x88, 0xb7}},
420 "Proportional": {Name: "Proportional", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
421 "Pscr": {Name: "Pscr", CodePoints: []int{119979}, Characters: []byte{0xf0, 0x9d, 0x92, 0xab}},
422 "Psi": {Name: "Psi", CodePoints: []int{936}, Characters: []byte{0xce, 0xa8}},
423 "QUOT": {Name: "QUOT", CodePoints: []int{34}, Characters: []byte{0x22}},
424 "Qfr": {Name: "Qfr", CodePoints: []int{120084}, Characters: []byte{0xf0, 0x9d, 0x94, 0x94}},
425 "Qopf": {Name: "Qopf", CodePoints: []int{8474}, Characters: []byte{0xe2, 0x84, 0x9a}},
426 "Qscr": {Name: "Qscr", CodePoints: []int{119980}, Characters: []byte{0xf0, 0x9d, 0x92, 0xac}},
427 "RBarr": {Name: "RBarr", CodePoints: []int{10512}, Characters: []byte{0xe2, 0xa4, 0x90}},
428 "REG": {Name: "REG", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
429 "Racute": {Name: "Racute", CodePoints: []int{340}, Characters: []byte{0xc5, 0x94}},
430 "Rang": {Name: "Rang", CodePoints: []int{10219}, Characters: []byte{0xe2, 0x9f, 0xab}},
431 "Rarr": {Name: "Rarr", CodePoints: []int{8608}, Characters: []byte{0xe2, 0x86, 0xa0}},
432 "Rarrtl": {Name: "Rarrtl", CodePoints: []int{10518}, Characters: []byte{0xe2, 0xa4, 0x96}},
433 "Rcaron": {Name: "Rcaron", CodePoints: []int{344}, Characters: []byte{0xc5, 0x98}},
434 "Rcedil": {Name: "Rcedil", CodePoints: []int{342}, Characters: []byte{0xc5, 0x96}},
435 "Rcy": {Name: "Rcy", CodePoints: []int{1056}, Characters: []byte{0xd0, 0xa0}},
436 "Re": {Name: "Re", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
437 "ReverseElement": {Name: "ReverseElement", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
438 "ReverseEquilibrium": {Name: "ReverseEquilibrium", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
439 "ReverseUpEquilibrium": {Name: "ReverseUpEquilibrium", CodePoints: []int{10607}, Characters: []byte{0xe2, 0xa5, 0xaf}},
440 "Rfr": {Name: "Rfr", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
441 "Rho": {Name: "Rho", CodePoints: []int{929}, Characters: []byte{0xce, 0xa1}},
442 "RightAngleBracket": {Name: "RightAngleBracket", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
443 "RightArrow": {Name: "RightArrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
444 "RightArrowBar": {Name: "RightArrowBar", CodePoints: []int{8677}, Characters: []byte{0xe2, 0x87, 0xa5}},
445 "RightArrowLeftArrow": {Name: "RightArrowLeftArrow", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
446 "RightCeiling": {Name: "RightCeiling", CodePoints: []int{8969}, Characters: []byte{0xe2, 0x8c, 0x89}},
447 "RightDoubleBracket": {Name: "RightDoubleBracket", CodePoints: []int{10215}, Characters: []byte{0xe2, 0x9f, 0xa7}},
448 "RightDownTeeVector": {Name: "RightDownTeeVector", CodePoints: []int{10589}, Characters: []byte{0xe2, 0xa5, 0x9d}},
449 "RightDownVector": {Name: "RightDownVector", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
450 "RightDownVectorBar": {Name: "RightDownVectorBar", CodePoints: []int{10581}, Characters: []byte{0xe2, 0xa5, 0x95}},
451 "RightFloor": {Name: "RightFloor", CodePoints: []int{8971}, Characters: []byte{0xe2, 0x8c, 0x8b}},
452 "RightTee": {Name: "RightTee", CodePoints: []int{8866}, Characters: []byte{0xe2, 0x8a, 0xa2}},
453 "RightTeeArrow": {Name: "RightTeeArrow", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
454 "RightTeeVector": {Name: "RightTeeVector", CodePoints: []int{10587}, Characters: []byte{0xe2, 0xa5, 0x9b}},
455 "RightTriangle": {Name: "RightTriangle", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
456 "RightTriangleBar": {Name: "RightTriangleBar", CodePoints: []int{10704}, Characters: []byte{0xe2, 0xa7, 0x90}},
457 "RightTriangleEqual": {Name: "RightTriangleEqual", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
458 "RightUpDownVector": {Name: "RightUpDownVector", CodePoints: []int{10575}, Characters: []byte{0xe2, 0xa5, 0x8f}},
459 "RightUpTeeVector": {Name: "RightUpTeeVector", CodePoints: []int{10588}, Characters: []byte{0xe2, 0xa5, 0x9c}},
460 "RightUpVector": {Name: "RightUpVector", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
461 "RightUpVectorBar": {Name: "RightUpVectorBar", CodePoints: []int{10580}, Characters: []byte{0xe2, 0xa5, 0x94}},
462 "RightVector": {Name: "RightVector", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
463 "RightVectorBar": {Name: "RightVectorBar", CodePoints: []int{10579}, Characters: []byte{0xe2, 0xa5, 0x93}},
464 "Rightarrow": {Name: "Rightarrow", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
465 "Ropf": {Name: "Ropf", CodePoints: []int{8477}, Characters: []byte{0xe2, 0x84, 0x9d}},
466 "RoundImplies": {Name: "RoundImplies", CodePoints: []int{10608}, Characters: []byte{0xe2, 0xa5, 0xb0}},
467 "Rrightarrow": {Name: "Rrightarrow", CodePoints: []int{8667}, Characters: []byte{0xe2, 0x87, 0x9b}},
468 "Rscr": {Name: "Rscr", CodePoints: []int{8475}, Characters: []byte{0xe2, 0x84, 0x9b}},
469 "Rsh": {Name: "Rsh", CodePoints: []int{8625}, Characters: []byte{0xe2, 0x86, 0xb1}},
470 "RuleDelayed": {Name: "RuleDelayed", CodePoints: []int{10740}, Characters: []byte{0xe2, 0xa7, 0xb4}},
471 "SHCHcy": {Name: "SHCHcy", CodePoints: []int{1065}, Characters: []byte{0xd0, 0xa9}},
472 "SHcy": {Name: "SHcy", CodePoints: []int{1064}, Characters: []byte{0xd0, 0xa8}},
473 "SOFTcy": {Name: "SOFTcy", CodePoints: []int{1068}, Characters: []byte{0xd0, 0xac}},
474 "Sacute": {Name: "Sacute", CodePoints: []int{346}, Characters: []byte{0xc5, 0x9a}},
475 "Sc": {Name: "Sc", CodePoints: []int{10940}, Characters: []byte{0xe2, 0xaa, 0xbc}},
476 "Scaron": {Name: "Scaron", CodePoints: []int{352}, Characters: []byte{0xc5, 0xa0}},
477 "Scedil": {Name: "Scedil", CodePoints: []int{350}, Characters: []byte{0xc5, 0x9e}},
478 "Scirc": {Name: "Scirc", CodePoints: []int{348}, Characters: []byte{0xc5, 0x9c}},
479 "Scy": {Name: "Scy", CodePoints: []int{1057}, Characters: []byte{0xd0, 0xa1}},
480 "Sfr": {Name: "Sfr", CodePoints: []int{120086}, Characters: []byte{0xf0, 0x9d, 0x94, 0x96}},
481 "ShortDownArrow": {Name: "ShortDownArrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
482 "ShortLeftArrow": {Name: "ShortLeftArrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
483 "ShortRightArrow": {Name: "ShortRightArrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
484 "ShortUpArrow": {Name: "ShortUpArrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
485 "Sigma": {Name: "Sigma", CodePoints: []int{931}, Characters: []byte{0xce, 0xa3}},
486 "SmallCircle": {Name: "SmallCircle", CodePoints: []int{8728}, Characters: []byte{0xe2, 0x88, 0x98}},
487 "Sopf": {Name: "Sopf", CodePoints: []int{120138}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8a}},
488 "Sqrt": {Name: "Sqrt", CodePoints: []int{8730}, Characters: []byte{0xe2, 0x88, 0x9a}},
489 "Square": {Name: "Square", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
490 "SquareIntersection": {Name: "SquareIntersection", CodePoints: []int{8851}, Characters: []byte{0xe2, 0x8a, 0x93}},
491 "SquareSubset": {Name: "SquareSubset", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
492 "SquareSubsetEqual": {Name: "SquareSubsetEqual", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
493 "SquareSuperset": {Name: "SquareSuperset", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
494 "SquareSupersetEqual": {Name: "SquareSupersetEqual", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
495 "SquareUnion": {Name: "SquareUnion", CodePoints: []int{8852}, Characters: []byte{0xe2, 0x8a, 0x94}},
496 "Sscr": {Name: "Sscr", CodePoints: []int{119982}, Characters: []byte{0xf0, 0x9d, 0x92, 0xae}},
497 "Star": {Name: "Star", CodePoints: []int{8902}, Characters: []byte{0xe2, 0x8b, 0x86}},
498 "Sub": {Name: "Sub", CodePoints: []int{8912}, Characters: []byte{0xe2, 0x8b, 0x90}},
499 "Subset": {Name: "Subset", CodePoints: []int{8912}, Characters: []byte{0xe2, 0x8b, 0x90}},
500 "SubsetEqual": {Name: "SubsetEqual", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
501 "Succeeds": {Name: "Succeeds", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
502 "SucceedsEqual": {Name: "SucceedsEqual", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
503 "SucceedsSlantEqual": {Name: "SucceedsSlantEqual", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
504 "SucceedsTilde": {Name: "SucceedsTilde", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
505 "SuchThat": {Name: "SuchThat", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
506 "Sum": {Name: "Sum", CodePoints: []int{8721}, Characters: []byte{0xe2, 0x88, 0x91}},
507 "Sup": {Name: "Sup", CodePoints: []int{8913}, Characters: []byte{0xe2, 0x8b, 0x91}},
508 "Superset": {Name: "Superset", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
509 "SupersetEqual": {Name: "SupersetEqual", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
510 "Supset": {Name: "Supset", CodePoints: []int{8913}, Characters: []byte{0xe2, 0x8b, 0x91}},
511 "THORN": {Name: "THORN", CodePoints: []int{222}, Characters: []byte{0xc3, 0x9e}},
512 "TRADE": {Name: "TRADE", CodePoints: []int{8482}, Characters: []byte{0xe2, 0x84, 0xa2}},
513 "TSHcy": {Name: "TSHcy", CodePoints: []int{1035}, Characters: []byte{0xd0, 0x8b}},
514 "TScy": {Name: "TScy", CodePoints: []int{1062}, Characters: []byte{0xd0, 0xa6}},
515 "Tab": {Name: "Tab", CodePoints: []int{9}, Characters: []byte{0x9}},
516 "Tau": {Name: "Tau", CodePoints: []int{932}, Characters: []byte{0xce, 0xa4}},
517 "Tcaron": {Name: "Tcaron", CodePoints: []int{356}, Characters: []byte{0xc5, 0xa4}},
518 "Tcedil": {Name: "Tcedil", CodePoints: []int{354}, Characters: []byte{0xc5, 0xa2}},
519 "Tcy": {Name: "Tcy", CodePoints: []int{1058}, Characters: []byte{0xd0, 0xa2}},
520 "Tfr": {Name: "Tfr", CodePoints: []int{120087}, Characters: []byte{0xf0, 0x9d, 0x94, 0x97}},
521 "Therefore": {Name: "Therefore", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
522 "Theta": {Name: "Theta", CodePoints: []int{920}, Characters: []byte{0xce, 0x98}},
523 "ThickSpace": {Name: "ThickSpace", CodePoints: []int{8287, 8202}, Characters: []byte{0xe2, 0x81, 0x9f, 0xe2, 0x80, 0x8a}},
524 "ThinSpace": {Name: "ThinSpace", CodePoints: []int{8201}, Characters: []byte{0xe2, 0x80, 0x89}},
525 "Tilde": {Name: "Tilde", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
526 "TildeEqual": {Name: "TildeEqual", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
527 "TildeFullEqual": {Name: "TildeFullEqual", CodePoints: []int{8773}, Characters: []byte{0xe2, 0x89, 0x85}},
528 "TildeTilde": {Name: "TildeTilde", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
529 "Topf": {Name: "Topf", CodePoints: []int{120139}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8b}},
530 "TripleDot": {Name: "TripleDot", CodePoints: []int{8411}, Characters: []byte{0xe2, 0x83, 0x9b}},
531 "Tscr": {Name: "Tscr", CodePoints: []int{119983}, Characters: []byte{0xf0, 0x9d, 0x92, 0xaf}},
532 "Tstrok": {Name: "Tstrok", CodePoints: []int{358}, Characters: []byte{0xc5, 0xa6}},
533 "Uacute": {Name: "Uacute", CodePoints: []int{218}, Characters: []byte{0xc3, 0x9a}},
534 "Uarr": {Name: "Uarr", CodePoints: []int{8607}, Characters: []byte{0xe2, 0x86, 0x9f}},
535 "Uarrocir": {Name: "Uarrocir", CodePoints: []int{10569}, Characters: []byte{0xe2, 0xa5, 0x89}},
536 "Ubrcy": {Name: "Ubrcy", CodePoints: []int{1038}, Characters: []byte{0xd0, 0x8e}},
537 "Ubreve": {Name: "Ubreve", CodePoints: []int{364}, Characters: []byte{0xc5, 0xac}},
538 "Ucirc": {Name: "Ucirc", CodePoints: []int{219}, Characters: []byte{0xc3, 0x9b}},
539 "Ucy": {Name: "Ucy", CodePoints: []int{1059}, Characters: []byte{0xd0, 0xa3}},
540 "Udblac": {Name: "Udblac", CodePoints: []int{368}, Characters: []byte{0xc5, 0xb0}},
541 "Ufr": {Name: "Ufr", CodePoints: []int{120088}, Characters: []byte{0xf0, 0x9d, 0x94, 0x98}},
542 "Ugrave": {Name: "Ugrave", CodePoints: []int{217}, Characters: []byte{0xc3, 0x99}},
543 "Umacr": {Name: "Umacr", CodePoints: []int{362}, Characters: []byte{0xc5, 0xaa}},
544 "UnderBar": {Name: "UnderBar", CodePoints: []int{95}, Characters: []byte{0x5f}},
545 "UnderBrace": {Name: "UnderBrace", CodePoints: []int{9183}, Characters: []byte{0xe2, 0x8f, 0x9f}},
546 "UnderBracket": {Name: "UnderBracket", CodePoints: []int{9141}, Characters: []byte{0xe2, 0x8e, 0xb5}},
547 "UnderParenthesis": {Name: "UnderParenthesis", CodePoints: []int{9181}, Characters: []byte{0xe2, 0x8f, 0x9d}},
548 "Union": {Name: "Union", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
549 "UnionPlus": {Name: "UnionPlus", CodePoints: []int{8846}, Characters: []byte{0xe2, 0x8a, 0x8e}},
550 "Uogon": {Name: "Uogon", CodePoints: []int{370}, Characters: []byte{0xc5, 0xb2}},
551 "Uopf": {Name: "Uopf", CodePoints: []int{120140}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8c}},
552 "UpArrow": {Name: "UpArrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
553 "UpArrowBar": {Name: "UpArrowBar", CodePoints: []int{10514}, Characters: []byte{0xe2, 0xa4, 0x92}},
554 "UpArrowDownArrow": {Name: "UpArrowDownArrow", CodePoints: []int{8645}, Characters: []byte{0xe2, 0x87, 0x85}},
555 "UpDownArrow": {Name: "UpDownArrow", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
556 "UpEquilibrium": {Name: "UpEquilibrium", CodePoints: []int{10606}, Characters: []byte{0xe2, 0xa5, 0xae}},
557 "UpTee": {Name: "UpTee", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
558 "UpTeeArrow": {Name: "UpTeeArrow", CodePoints: []int{8613}, Characters: []byte{0xe2, 0x86, 0xa5}},
559 "Uparrow": {Name: "Uparrow", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
560 "Updownarrow": {Name: "Updownarrow", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
561 "UpperLeftArrow": {Name: "UpperLeftArrow", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
562 "UpperRightArrow": {Name: "UpperRightArrow", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
563 "Upsi": {Name: "Upsi", CodePoints: []int{978}, Characters: []byte{0xcf, 0x92}},
564 "Upsilon": {Name: "Upsilon", CodePoints: []int{933}, Characters: []byte{0xce, 0xa5}},
565 "Uring": {Name: "Uring", CodePoints: []int{366}, Characters: []byte{0xc5, 0xae}},
566 "Uscr": {Name: "Uscr", CodePoints: []int{119984}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb0}},
567 "Utilde": {Name: "Utilde", CodePoints: []int{360}, Characters: []byte{0xc5, 0xa8}},
568 "Uuml": {Name: "Uuml", CodePoints: []int{220}, Characters: []byte{0xc3, 0x9c}},
569 "VDash": {Name: "VDash", CodePoints: []int{8875}, Characters: []byte{0xe2, 0x8a, 0xab}},
570 "Vbar": {Name: "Vbar", CodePoints: []int{10987}, Characters: []byte{0xe2, 0xab, 0xab}},
571 "Vcy": {Name: "Vcy", CodePoints: []int{1042}, Characters: []byte{0xd0, 0x92}},
572 "Vdash": {Name: "Vdash", CodePoints: []int{8873}, Characters: []byte{0xe2, 0x8a, 0xa9}},
573 "Vdashl": {Name: "Vdashl", CodePoints: []int{10982}, Characters: []byte{0xe2, 0xab, 0xa6}},
574 "Vee": {Name: "Vee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
575 "Verbar": {Name: "Verbar", CodePoints: []int{8214}, Characters: []byte{0xe2, 0x80, 0x96}},
576 "Vert": {Name: "Vert", CodePoints: []int{8214}, Characters: []byte{0xe2, 0x80, 0x96}},
577 "VerticalBar": {Name: "VerticalBar", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
578 "VerticalLine": {Name: "VerticalLine", CodePoints: []int{124}, Characters: []byte{0x7c}},
579 "VerticalSeparator": {Name: "VerticalSeparator", CodePoints: []int{10072}, Characters: []byte{0xe2, 0x9d, 0x98}},
580 "VerticalTilde": {Name: "VerticalTilde", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
581 "VeryThinSpace": {Name: "VeryThinSpace", CodePoints: []int{8202}, Characters: []byte{0xe2, 0x80, 0x8a}},
582 "Vfr": {Name: "Vfr", CodePoints: []int{120089}, Characters: []byte{0xf0, 0x9d, 0x94, 0x99}},
583 "Vopf": {Name: "Vopf", CodePoints: []int{120141}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8d}},
584 "Vscr": {Name: "Vscr", CodePoints: []int{119985}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb1}},
585 "Vvdash": {Name: "Vvdash", CodePoints: []int{8874}, Characters: []byte{0xe2, 0x8a, 0xaa}},
586 "Wcirc": {Name: "Wcirc", CodePoints: []int{372}, Characters: []byte{0xc5, 0xb4}},
587 "Wedge": {Name: "Wedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
588 "Wfr": {Name: "Wfr", CodePoints: []int{120090}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9a}},
589 "Wopf": {Name: "Wopf", CodePoints: []int{120142}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8e}},
590 "Wscr": {Name: "Wscr", CodePoints: []int{119986}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb2}},
591 "Xfr": {Name: "Xfr", CodePoints: []int{120091}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9b}},
592 "Xi": {Name: "Xi", CodePoints: []int{926}, Characters: []byte{0xce, 0x9e}},
593 "Xopf": {Name: "Xopf", CodePoints: []int{120143}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8f}},
594 "Xscr": {Name: "Xscr", CodePoints: []int{119987}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb3}},
595 "YAcy": {Name: "YAcy", CodePoints: []int{1071}, Characters: []byte{0xd0, 0xaf}},
596 "YIcy": {Name: "YIcy", CodePoints: []int{1031}, Characters: []byte{0xd0, 0x87}},
597 "YUcy": {Name: "YUcy", CodePoints: []int{1070}, Characters: []byte{0xd0, 0xae}},
598 "Yacute": {Name: "Yacute", CodePoints: []int{221}, Characters: []byte{0xc3, 0x9d}},
599 "Ycirc": {Name: "Ycirc", CodePoints: []int{374}, Characters: []byte{0xc5, 0xb6}},
600 "Ycy": {Name: "Ycy", CodePoints: []int{1067}, Characters: []byte{0xd0, 0xab}},
601 "Yfr": {Name: "Yfr", CodePoints: []int{120092}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9c}},
602 "Yopf": {Name: "Yopf", CodePoints: []int{120144}, Characters: []byte{0xf0, 0x9d, 0x95, 0x90}},
603 "Yscr": {Name: "Yscr", CodePoints: []int{119988}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb4}},
604 "Yuml": {Name: "Yuml", CodePoints: []int{376}, Characters: []byte{0xc5, 0xb8}},
605 "ZHcy": {Name: "ZHcy", CodePoints: []int{1046}, Characters: []byte{0xd0, 0x96}},
606 "Zacute": {Name: "Zacute", CodePoints: []int{377}, Characters: []byte{0xc5, 0xb9}},
607 "Zcaron": {Name: "Zcaron", CodePoints: []int{381}, Characters: []byte{0xc5, 0xbd}},
608 "Zcy": {Name: "Zcy", CodePoints: []int{1047}, Characters: []byte{0xd0, 0x97}},
609 "Zdot": {Name: "Zdot", CodePoints: []int{379}, Characters: []byte{0xc5, 0xbb}},
610 "ZeroWidthSpace": {Name: "ZeroWidthSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
611 "Zeta": {Name: "Zeta", CodePoints: []int{918}, Characters: []byte{0xce, 0x96}},
612 "Zfr": {Name: "Zfr", CodePoints: []int{8488}, Characters: []byte{0xe2, 0x84, 0xa8}},
613 "Zopf": {Name: "Zopf", CodePoints: []int{8484}, Characters: []byte{0xe2, 0x84, 0xa4}},
614 "Zscr": {Name: "Zscr", CodePoints: []int{119989}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb5}},
615 "aacute": {Name: "aacute", CodePoints: []int{225}, Characters: []byte{0xc3, 0xa1}},
616 "abreve": {Name: "abreve", CodePoints: []int{259}, Characters: []byte{0xc4, 0x83}},
617 "ac": {Name: "ac", CodePoints: []int{8766}, Characters: []byte{0xe2, 0x88, 0xbe}},
618 "acE": {Name: "acE", CodePoints: []int{8766, 819}, Characters: []byte{0xe2, 0x88, 0xbe, 0xcc, 0xb3}},
619 "acd": {Name: "acd", CodePoints: []int{8767}, Characters: []byte{0xe2, 0x88, 0xbf}},
620 "acirc": {Name: "acirc", CodePoints: []int{226}, Characters: []byte{0xc3, 0xa2}},
621 "acute": {Name: "acute", CodePoints: []int{180}, Characters: []byte{0xc2, 0xb4}},
622 "acy": {Name: "acy", CodePoints: []int{1072}, Characters: []byte{0xd0, 0xb0}},
623 "aelig": {Name: "aelig", CodePoints: []int{230}, Characters: []byte{0xc3, 0xa6}},
624 "af": {Name: "af", CodePoints: []int{8289}, Characters: []byte{0xe2, 0x81, 0xa1}},
625 "afr": {Name: "afr", CodePoints: []int{120094}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9e}},
626 "agrave": {Name: "agrave", CodePoints: []int{224}, Characters: []byte{0xc3, 0xa0}},
627 "alefsym": {Name: "alefsym", CodePoints: []int{8501}, Characters: []byte{0xe2, 0x84, 0xb5}},
628 "aleph": {Name: "aleph", CodePoints: []int{8501}, Characters: []byte{0xe2, 0x84, 0xb5}},
629 "alpha": {Name: "alpha", CodePoints: []int{945}, Characters: []byte{0xce, 0xb1}},
630 "amacr": {Name: "amacr", CodePoints: []int{257}, Characters: []byte{0xc4, 0x81}},
631 "amalg": {Name: "amalg", CodePoints: []int{10815}, Characters: []byte{0xe2, 0xa8, 0xbf}},
632 "amp": {Name: "amp", CodePoints: []int{38}, Characters: []byte{0x26}},
633 "and": {Name: "and", CodePoints: []int{8743}, Characters: []byte{0xe2, 0x88, 0xa7}},
634 "andand": {Name: "andand", CodePoints: []int{10837}, Characters: []byte{0xe2, 0xa9, 0x95}},
635 "andd": {Name: "andd", CodePoints: []int{10844}, Characters: []byte{0xe2, 0xa9, 0x9c}},
636 "andslope": {Name: "andslope", CodePoints: []int{10840}, Characters: []byte{0xe2, 0xa9, 0x98}},
637 "andv": {Name: "andv", CodePoints: []int{10842}, Characters: []byte{0xe2, 0xa9, 0x9a}},
638 "ang": {Name: "ang", CodePoints: []int{8736}, Characters: []byte{0xe2, 0x88, 0xa0}},
639 "ange": {Name: "ange", CodePoints: []int{10660}, Characters: []byte{0xe2, 0xa6, 0xa4}},
640 "angle": {Name: "angle", CodePoints: []int{8736}, Characters: []byte{0xe2, 0x88, 0xa0}},
641 "angmsd": {Name: "angmsd", CodePoints: []int{8737}, Characters: []byte{0xe2, 0x88, 0xa1}},
642 "angmsdaa": {Name: "angmsdaa", CodePoints: []int{10664}, Characters: []byte{0xe2, 0xa6, 0xa8}},
643 "angmsdab": {Name: "angmsdab", CodePoints: []int{10665}, Characters: []byte{0xe2, 0xa6, 0xa9}},
644 "angmsdac": {Name: "angmsdac", CodePoints: []int{10666}, Characters: []byte{0xe2, 0xa6, 0xaa}},
645 "angmsdad": {Name: "angmsdad", CodePoints: []int{10667}, Characters: []byte{0xe2, 0xa6, 0xab}},
646 "angmsdae": {Name: "angmsdae", CodePoints: []int{10668}, Characters: []byte{0xe2, 0xa6, 0xac}},
647 "angmsdaf": {Name: "angmsdaf", CodePoints: []int{10669}, Characters: []byte{0xe2, 0xa6, 0xad}},
648 "angmsdag": {Name: "angmsdag", CodePoints: []int{10670}, Characters: []byte{0xe2, 0xa6, 0xae}},
649 "angmsdah": {Name: "angmsdah", CodePoints: []int{10671}, Characters: []byte{0xe2, 0xa6, 0xaf}},
650 "angrt": {Name: "angrt", CodePoints: []int{8735}, Characters: []byte{0xe2, 0x88, 0x9f}},
651 "angrtvb": {Name: "angrtvb", CodePoints: []int{8894}, Characters: []byte{0xe2, 0x8a, 0xbe}},
652 "angrtvbd": {Name: "angrtvbd", CodePoints: []int{10653}, Characters: []byte{0xe2, 0xa6, 0x9d}},
653 "angsph": {Name: "angsph", CodePoints: []int{8738}, Characters: []byte{0xe2, 0x88, 0xa2}},
654 "angst": {Name: "angst", CodePoints: []int{197}, Characters: []byte{0xc3, 0x85}},
655 "angzarr": {Name: "angzarr", CodePoints: []int{9084}, Characters: []byte{0xe2, 0x8d, 0xbc}},
656 "aogon": {Name: "aogon", CodePoints: []int{261}, Characters: []byte{0xc4, 0x85}},
657 "aopf": {Name: "aopf", CodePoints: []int{120146}, Characters: []byte{0xf0, 0x9d, 0x95, 0x92}},
658 "ap": {Name: "ap", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
659 "apE": {Name: "apE", CodePoints: []int{10864}, Characters: []byte{0xe2, 0xa9, 0xb0}},
660 "apacir": {Name: "apacir", CodePoints: []int{10863}, Characters: []byte{0xe2, 0xa9, 0xaf}},
661 "ape": {Name: "ape", CodePoints: []int{8778}, Characters: []byte{0xe2, 0x89, 0x8a}},
662 "apid": {Name: "apid", CodePoints: []int{8779}, Characters: []byte{0xe2, 0x89, 0x8b}},
663 "apos": {Name: "apos", CodePoints: []int{39}, Characters: []byte{0x27}},
664 "approx": {Name: "approx", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
665 "approxeq": {Name: "approxeq", CodePoints: []int{8778}, Characters: []byte{0xe2, 0x89, 0x8a}},
666 "aring": {Name: "aring", CodePoints: []int{229}, Characters: []byte{0xc3, 0xa5}},
667 "ascr": {Name: "ascr", CodePoints: []int{119990}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb6}},
668 "ast": {Name: "ast", CodePoints: []int{42}, Characters: []byte{0x2a}},
669 "asymp": {Name: "asymp", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
670 "asympeq": {Name: "asympeq", CodePoints: []int{8781}, Characters: []byte{0xe2, 0x89, 0x8d}},
671 "atilde": {Name: "atilde", CodePoints: []int{227}, Characters: []byte{0xc3, 0xa3}},
672 "auml": {Name: "auml", CodePoints: []int{228}, Characters: []byte{0xc3, 0xa4}},
673 "awconint": {Name: "awconint", CodePoints: []int{8755}, Characters: []byte{0xe2, 0x88, 0xb3}},
674 "awint": {Name: "awint", CodePoints: []int{10769}, Characters: []byte{0xe2, 0xa8, 0x91}},
675 "bNot": {Name: "bNot", CodePoints: []int{10989}, Characters: []byte{0xe2, 0xab, 0xad}},
676 "backcong": {Name: "backcong", CodePoints: []int{8780}, Characters: []byte{0xe2, 0x89, 0x8c}},
677 "backepsilon": {Name: "backepsilon", CodePoints: []int{1014}, Characters: []byte{0xcf, 0xb6}},
678 "backprime": {Name: "backprime", CodePoints: []int{8245}, Characters: []byte{0xe2, 0x80, 0xb5}},
679 "backsim": {Name: "backsim", CodePoints: []int{8765}, Characters: []byte{0xe2, 0x88, 0xbd}},
680 "backsimeq": {Name: "backsimeq", CodePoints: []int{8909}, Characters: []byte{0xe2, 0x8b, 0x8d}},
681 "barvee": {Name: "barvee", CodePoints: []int{8893}, Characters: []byte{0xe2, 0x8a, 0xbd}},
682 "barwed": {Name: "barwed", CodePoints: []int{8965}, Characters: []byte{0xe2, 0x8c, 0x85}},
683 "barwedge": {Name: "barwedge", CodePoints: []int{8965}, Characters: []byte{0xe2, 0x8c, 0x85}},
684 "bbrk": {Name: "bbrk", CodePoints: []int{9141}, Characters: []byte{0xe2, 0x8e, 0xb5}},
685 "bbrktbrk": {Name: "bbrktbrk", CodePoints: []int{9142}, Characters: []byte{0xe2, 0x8e, 0xb6}},
686 "bcong": {Name: "bcong", CodePoints: []int{8780}, Characters: []byte{0xe2, 0x89, 0x8c}},
687 "bcy": {Name: "bcy", CodePoints: []int{1073}, Characters: []byte{0xd0, 0xb1}},
688 "bdquo": {Name: "bdquo", CodePoints: []int{8222}, Characters: []byte{0xe2, 0x80, 0x9e}},
689 "becaus": {Name: "becaus", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
690 "because": {Name: "because", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
691 "bemptyv": {Name: "bemptyv", CodePoints: []int{10672}, Characters: []byte{0xe2, 0xa6, 0xb0}},
692 "bepsi": {Name: "bepsi", CodePoints: []int{1014}, Characters: []byte{0xcf, 0xb6}},
693 "bernou": {Name: "bernou", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
694 "beta": {Name: "beta", CodePoints: []int{946}, Characters: []byte{0xce, 0xb2}},
695 "beth": {Name: "beth", CodePoints: []int{8502}, Characters: []byte{0xe2, 0x84, 0xb6}},
696 "between": {Name: "between", CodePoints: []int{8812}, Characters: []byte{0xe2, 0x89, 0xac}},
697 "bfr": {Name: "bfr", CodePoints: []int{120095}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9f}},
698 "bigcap": {Name: "bigcap", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
699 "bigcirc": {Name: "bigcirc", CodePoints: []int{9711}, Characters: []byte{0xe2, 0x97, 0xaf}},
700 "bigcup": {Name: "bigcup", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
701 "bigodot": {Name: "bigodot", CodePoints: []int{10752}, Characters: []byte{0xe2, 0xa8, 0x80}},
702 "bigoplus": {Name: "bigoplus", CodePoints: []int{10753}, Characters: []byte{0xe2, 0xa8, 0x81}},
703 "bigotimes": {Name: "bigotimes", CodePoints: []int{10754}, Characters: []byte{0xe2, 0xa8, 0x82}},
704 "bigsqcup": {Name: "bigsqcup", CodePoints: []int{10758}, Characters: []byte{0xe2, 0xa8, 0x86}},
705 "bigstar": {Name: "bigstar", CodePoints: []int{9733}, Characters: []byte{0xe2, 0x98, 0x85}},
706 "bigtriangledown": {Name: "bigtriangledown", CodePoints: []int{9661}, Characters: []byte{0xe2, 0x96, 0xbd}},
707 "bigtriangleup": {Name: "bigtriangleup", CodePoints: []int{9651}, Characters: []byte{0xe2, 0x96, 0xb3}},
708 "biguplus": {Name: "biguplus", CodePoints: []int{10756}, Characters: []byte{0xe2, 0xa8, 0x84}},
709 "bigvee": {Name: "bigvee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
710 "bigwedge": {Name: "bigwedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
711 "bkarow": {Name: "bkarow", CodePoints: []int{10509}, Characters: []byte{0xe2, 0xa4, 0x8d}},
712 "blacklozenge": {Name: "blacklozenge", CodePoints: []int{10731}, Characters: []byte{0xe2, 0xa7, 0xab}},
713 "blacksquare": {Name: "blacksquare", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
714 "blacktriangle": {Name: "blacktriangle", CodePoints: []int{9652}, Characters: []byte{0xe2, 0x96, 0xb4}},
715 "blacktriangledown": {Name: "blacktriangledown", CodePoints: []int{9662}, Characters: []byte{0xe2, 0x96, 0xbe}},
716 "blacktriangleleft": {Name: "blacktriangleleft", CodePoints: []int{9666}, Characters: []byte{0xe2, 0x97, 0x82}},
717 "blacktriangleright": {Name: "blacktriangleright", CodePoints: []int{9656}, Characters: []byte{0xe2, 0x96, 0xb8}},
718 "blank": {Name: "blank", CodePoints: []int{9251}, Characters: []byte{0xe2, 0x90, 0xa3}},
719 "blk12": {Name: "blk12", CodePoints: []int{9618}, Characters: []byte{0xe2, 0x96, 0x92}},
720 "blk14": {Name: "blk14", CodePoints: []int{9617}, Characters: []byte{0xe2, 0x96, 0x91}},
721 "blk34": {Name: "blk34", CodePoints: []int{9619}, Characters: []byte{0xe2, 0x96, 0x93}},
722 "block": {Name: "block", CodePoints: []int{9608}, Characters: []byte{0xe2, 0x96, 0x88}},
723 "bne": {Name: "bne", CodePoints: []int{61, 8421}, Characters: []byte{0x3d, 0xe2, 0x83, 0xa5}},
724 "bnequiv": {Name: "bnequiv", CodePoints: []int{8801, 8421}, Characters: []byte{0xe2, 0x89, 0xa1, 0xe2, 0x83, 0xa5}},
725 "bnot": {Name: "bnot", CodePoints: []int{8976}, Characters: []byte{0xe2, 0x8c, 0x90}},
726 "bopf": {Name: "bopf", CodePoints: []int{120147}, Characters: []byte{0xf0, 0x9d, 0x95, 0x93}},
727 "bot": {Name: "bot", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
728 "bottom": {Name: "bottom", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
729 "bowtie": {Name: "bowtie", CodePoints: []int{8904}, Characters: []byte{0xe2, 0x8b, 0x88}},
730 "boxDL": {Name: "boxDL", CodePoints: []int{9559}, Characters: []byte{0xe2, 0x95, 0x97}},
731 "boxDR": {Name: "boxDR", CodePoints: []int{9556}, Characters: []byte{0xe2, 0x95, 0x94}},
732 "boxDl": {Name: "boxDl", CodePoints: []int{9558}, Characters: []byte{0xe2, 0x95, 0x96}},
733 "boxDr": {Name: "boxDr", CodePoints: []int{9555}, Characters: []byte{0xe2, 0x95, 0x93}},
734 "boxH": {Name: "boxH", CodePoints: []int{9552}, Characters: []byte{0xe2, 0x95, 0x90}},
735 "boxHD": {Name: "boxHD", CodePoints: []int{9574}, Characters: []byte{0xe2, 0x95, 0xa6}},
736 "boxHU": {Name: "boxHU", CodePoints: []int{9577}, Characters: []byte{0xe2, 0x95, 0xa9}},
737 "boxHd": {Name: "boxHd", CodePoints: []int{9572}, Characters: []byte{0xe2, 0x95, 0xa4}},
738 "boxHu": {Name: "boxHu", CodePoints: []int{9575}, Characters: []byte{0xe2, 0x95, 0xa7}},
739 "boxUL": {Name: "boxUL", CodePoints: []int{9565}, Characters: []byte{0xe2, 0x95, 0x9d}},
740 "boxUR": {Name: "boxUR", CodePoints: []int{9562}, Characters: []byte{0xe2, 0x95, 0x9a}},
741 "boxUl": {Name: "boxUl", CodePoints: []int{9564}, Characters: []byte{0xe2, 0x95, 0x9c}},
742 "boxUr": {Name: "boxUr", CodePoints: []int{9561}, Characters: []byte{0xe2, 0x95, 0x99}},
743 "boxV": {Name: "boxV", CodePoints: []int{9553}, Characters: []byte{0xe2, 0x95, 0x91}},
744 "boxVH": {Name: "boxVH", CodePoints: []int{9580}, Characters: []byte{0xe2, 0x95, 0xac}},
745 "boxVL": {Name: "boxVL", CodePoints: []int{9571}, Characters: []byte{0xe2, 0x95, 0xa3}},
746 "boxVR": {Name: "boxVR", CodePoints: []int{9568}, Characters: []byte{0xe2, 0x95, 0xa0}},
747 "boxVh": {Name: "boxVh", CodePoints: []int{9579}, Characters: []byte{0xe2, 0x95, 0xab}},
748 "boxVl": {Name: "boxVl", CodePoints: []int{9570}, Characters: []byte{0xe2, 0x95, 0xa2}},
749 "boxVr": {Name: "boxVr", CodePoints: []int{9567}, Characters: []byte{0xe2, 0x95, 0x9f}},
750 "boxbox": {Name: "boxbox", CodePoints: []int{10697}, Characters: []byte{0xe2, 0xa7, 0x89}},
751 "boxdL": {Name: "boxdL", CodePoints: []int{9557}, Characters: []byte{0xe2, 0x95, 0x95}},
752 "boxdR": {Name: "boxdR", CodePoints: []int{9554}, Characters: []byte{0xe2, 0x95, 0x92}},
753 "boxdl": {Name: "boxdl", CodePoints: []int{9488}, Characters: []byte{0xe2, 0x94, 0x90}},
754 "boxdr": {Name: "boxdr", CodePoints: []int{9484}, Characters: []byte{0xe2, 0x94, 0x8c}},
755 "boxh": {Name: "boxh", CodePoints: []int{9472}, Characters: []byte{0xe2, 0x94, 0x80}},
756 "boxhD": {Name: "boxhD", CodePoints: []int{9573}, Characters: []byte{0xe2, 0x95, 0xa5}},
757 "boxhU": {Name: "boxhU", CodePoints: []int{9576}, Characters: []byte{0xe2, 0x95, 0xa8}},
758 "boxhd": {Name: "boxhd", CodePoints: []int{9516}, Characters: []byte{0xe2, 0x94, 0xac}},
759 "boxhu": {Name: "boxhu", CodePoints: []int{9524}, Characters: []byte{0xe2, 0x94, 0xb4}},
760 "boxminus": {Name: "boxminus", CodePoints: []int{8863}, Characters: []byte{0xe2, 0x8a, 0x9f}},
761 "boxplus": {Name: "boxplus", CodePoints: []int{8862}, Characters: []byte{0xe2, 0x8a, 0x9e}},
762 "boxtimes": {Name: "boxtimes", CodePoints: []int{8864}, Characters: []byte{0xe2, 0x8a, 0xa0}},
763 "boxuL": {Name: "boxuL", CodePoints: []int{9563}, Characters: []byte{0xe2, 0x95, 0x9b}},
764 "boxuR": {Name: "boxuR", CodePoints: []int{9560}, Characters: []byte{0xe2, 0x95, 0x98}},
765 "boxul": {Name: "boxul", CodePoints: []int{9496}, Characters: []byte{0xe2, 0x94, 0x98}},
766 "boxur": {Name: "boxur", CodePoints: []int{9492}, Characters: []byte{0xe2, 0x94, 0x94}},
767 "boxv": {Name: "boxv", CodePoints: []int{9474}, Characters: []byte{0xe2, 0x94, 0x82}},
768 "boxvH": {Name: "boxvH", CodePoints: []int{9578}, Characters: []byte{0xe2, 0x95, 0xaa}},
769 "boxvL": {Name: "boxvL", CodePoints: []int{9569}, Characters: []byte{0xe2, 0x95, 0xa1}},
770 "boxvR": {Name: "boxvR", CodePoints: []int{9566}, Characters: []byte{0xe2, 0x95, 0x9e}},
771 "boxvh": {Name: "boxvh", CodePoints: []int{9532}, Characters: []byte{0xe2, 0x94, 0xbc}},
772 "boxvl": {Name: "boxvl", CodePoints: []int{9508}, Characters: []byte{0xe2, 0x94, 0xa4}},
773 "boxvr": {Name: "boxvr", CodePoints: []int{9500}, Characters: []byte{0xe2, 0x94, 0x9c}},
774 "bprime": {Name: "bprime", CodePoints: []int{8245}, Characters: []byte{0xe2, 0x80, 0xb5}},
775 "breve": {Name: "breve", CodePoints: []int{728}, Characters: []byte{0xcb, 0x98}},
776 "brvbar": {Name: "brvbar", CodePoints: []int{166}, Characters: []byte{0xc2, 0xa6}},
777 "bscr": {Name: "bscr", CodePoints: []int{119991}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb7}},
778 "bsemi": {Name: "bsemi", CodePoints: []int{8271}, Characters: []byte{0xe2, 0x81, 0x8f}},
779 "bsim": {Name: "bsim", CodePoints: []int{8765}, Characters: []byte{0xe2, 0x88, 0xbd}},
780 "bsime": {Name: "bsime", CodePoints: []int{8909}, Characters: []byte{0xe2, 0x8b, 0x8d}},
781 "bsol": {Name: "bsol", CodePoints: []int{92}, Characters: []byte{0x5c}},
782 "bsolb": {Name: "bsolb", CodePoints: []int{10693}, Characters: []byte{0xe2, 0xa7, 0x85}},
783 "bsolhsub": {Name: "bsolhsub", CodePoints: []int{10184}, Characters: []byte{0xe2, 0x9f, 0x88}},
784 "bull": {Name: "bull", CodePoints: []int{8226}, Characters: []byte{0xe2, 0x80, 0xa2}},
785 "bullet": {Name: "bullet", CodePoints: []int{8226}, Characters: []byte{0xe2, 0x80, 0xa2}},
786 "bump": {Name: "bump", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
787 "bumpE": {Name: "bumpE", CodePoints: []int{10926}, Characters: []byte{0xe2, 0xaa, 0xae}},
788 "bumpe": {Name: "bumpe", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
789 "bumpeq": {Name: "bumpeq", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
790 "cacute": {Name: "cacute", CodePoints: []int{263}, Characters: []byte{0xc4, 0x87}},
791 "cap": {Name: "cap", CodePoints: []int{8745}, Characters: []byte{0xe2, 0x88, 0xa9}},
792 "capand": {Name: "capand", CodePoints: []int{10820}, Characters: []byte{0xe2, 0xa9, 0x84}},
793 "capbrcup": {Name: "capbrcup", CodePoints: []int{10825}, Characters: []byte{0xe2, 0xa9, 0x89}},
794 "capcap": {Name: "capcap", CodePoints: []int{10827}, Characters: []byte{0xe2, 0xa9, 0x8b}},
795 "capcup": {Name: "capcup", CodePoints: []int{10823}, Characters: []byte{0xe2, 0xa9, 0x87}},
796 "capdot": {Name: "capdot", CodePoints: []int{10816}, Characters: []byte{0xe2, 0xa9, 0x80}},
797 "caps": {Name: "caps", CodePoints: []int{8745, 65024}, Characters: []byte{0xe2, 0x88, 0xa9, 0xef, 0xb8, 0x80}},
798 "caret": {Name: "caret", CodePoints: []int{8257}, Characters: []byte{0xe2, 0x81, 0x81}},
799 "caron": {Name: "caron", CodePoints: []int{711}, Characters: []byte{0xcb, 0x87}},
800 "ccaps": {Name: "ccaps", CodePoints: []int{10829}, Characters: []byte{0xe2, 0xa9, 0x8d}},
801 "ccaron": {Name: "ccaron", CodePoints: []int{269}, Characters: []byte{0xc4, 0x8d}},
802 "ccedil": {Name: "ccedil", CodePoints: []int{231}, Characters: []byte{0xc3, 0xa7}},
803 "ccirc": {Name: "ccirc", CodePoints: []int{265}, Characters: []byte{0xc4, 0x89}},
804 "ccups": {Name: "ccups", CodePoints: []int{10828}, Characters: []byte{0xe2, 0xa9, 0x8c}},
805 "ccupssm": {Name: "ccupssm", CodePoints: []int{10832}, Characters: []byte{0xe2, 0xa9, 0x90}},
806 "cdot": {Name: "cdot", CodePoints: []int{267}, Characters: []byte{0xc4, 0x8b}},
807 "cedil": {Name: "cedil", CodePoints: []int{184}, Characters: []byte{0xc2, 0xb8}},
808 "cemptyv": {Name: "cemptyv", CodePoints: []int{10674}, Characters: []byte{0xe2, 0xa6, 0xb2}},
809 "cent": {Name: "cent", CodePoints: []int{162}, Characters: []byte{0xc2, 0xa2}},
810 "centerdot": {Name: "centerdot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
811 "cfr": {Name: "cfr", CodePoints: []int{120096}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa0}},
812 "chcy": {Name: "chcy", CodePoints: []int{1095}, Characters: []byte{0xd1, 0x87}},
813 "check": {Name: "check", CodePoints: []int{10003}, Characters: []byte{0xe2, 0x9c, 0x93}},
814 "checkmark": {Name: "checkmark", CodePoints: []int{10003}, Characters: []byte{0xe2, 0x9c, 0x93}},
815 "chi": {Name: "chi", CodePoints: []int{967}, Characters: []byte{0xcf, 0x87}},
816 "cir": {Name: "cir", CodePoints: []int{9675}, Characters: []byte{0xe2, 0x97, 0x8b}},
817 "cirE": {Name: "cirE", CodePoints: []int{10691}, Characters: []byte{0xe2, 0xa7, 0x83}},
818 "circ": {Name: "circ", CodePoints: []int{710}, Characters: []byte{0xcb, 0x86}},
819 "circeq": {Name: "circeq", CodePoints: []int{8791}, Characters: []byte{0xe2, 0x89, 0x97}},
820 "circlearrowleft": {Name: "circlearrowleft", CodePoints: []int{8634}, Characters: []byte{0xe2, 0x86, 0xba}},
821 "circlearrowright": {Name: "circlearrowright", CodePoints: []int{8635}, Characters: []byte{0xe2, 0x86, 0xbb}},
822 "circledR": {Name: "circledR", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
823 "circledS": {Name: "circledS", CodePoints: []int{9416}, Characters: []byte{0xe2, 0x93, 0x88}},
824 "circledast": {Name: "circledast", CodePoints: []int{8859}, Characters: []byte{0xe2, 0x8a, 0x9b}},
825 "circledcirc": {Name: "circledcirc", CodePoints: []int{8858}, Characters: []byte{0xe2, 0x8a, 0x9a}},
826 "circleddash": {Name: "circleddash", CodePoints: []int{8861}, Characters: []byte{0xe2, 0x8a, 0x9d}},
827 "cire": {Name: "cire", CodePoints: []int{8791}, Characters: []byte{0xe2, 0x89, 0x97}},
828 "cirfnint": {Name: "cirfnint", CodePoints: []int{10768}, Characters: []byte{0xe2, 0xa8, 0x90}},
829 "cirmid": {Name: "cirmid", CodePoints: []int{10991}, Characters: []byte{0xe2, 0xab, 0xaf}},
830 "cirscir": {Name: "cirscir", CodePoints: []int{10690}, Characters: []byte{0xe2, 0xa7, 0x82}},
831 "clubs": {Name: "clubs", CodePoints: []int{9827}, Characters: []byte{0xe2, 0x99, 0xa3}},
832 "clubsuit": {Name: "clubsuit", CodePoints: []int{9827}, Characters: []byte{0xe2, 0x99, 0xa3}},
833 "colon": {Name: "colon", CodePoints: []int{58}, Characters: []byte{0x3a}},
834 "colone": {Name: "colone", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
835 "coloneq": {Name: "coloneq", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
836 "comma": {Name: "comma", CodePoints: []int{44}, Characters: []byte{0x2c}},
837 "commat": {Name: "commat", CodePoints: []int{64}, Characters: []byte{0x40}},
838 "comp": {Name: "comp", CodePoints: []int{8705}, Characters: []byte{0xe2, 0x88, 0x81}},
839 "compfn": {Name: "compfn", CodePoints: []int{8728}, Characters: []byte{0xe2, 0x88, 0x98}},
840 "complement": {Name: "complement", CodePoints: []int{8705}, Characters: []byte{0xe2, 0x88, 0x81}},
841 "complexes": {Name: "complexes", CodePoints: []int{8450}, Characters: []byte{0xe2, 0x84, 0x82}},
842 "cong": {Name: "cong", CodePoints: []int{8773}, Characters: []byte{0xe2, 0x89, 0x85}},
843 "congdot": {Name: "congdot", CodePoints: []int{10861}, Characters: []byte{0xe2, 0xa9, 0xad}},
844 "conint": {Name: "conint", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
845 "copf": {Name: "copf", CodePoints: []int{120148}, Characters: []byte{0xf0, 0x9d, 0x95, 0x94}},
846 "coprod": {Name: "coprod", CodePoints: []int{8720}, Characters: []byte{0xe2, 0x88, 0x90}},
847 "copy": {Name: "copy", CodePoints: []int{169}, Characters: []byte{0xc2, 0xa9}},
848 "copysr": {Name: "copysr", CodePoints: []int{8471}, Characters: []byte{0xe2, 0x84, 0x97}},
849 "crarr": {Name: "crarr", CodePoints: []int{8629}, Characters: []byte{0xe2, 0x86, 0xb5}},
850 "cross": {Name: "cross", CodePoints: []int{10007}, Characters: []byte{0xe2, 0x9c, 0x97}},
851 "cscr": {Name: "cscr", CodePoints: []int{119992}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb8}},
852 "csub": {Name: "csub", CodePoints: []int{10959}, Characters: []byte{0xe2, 0xab, 0x8f}},
853 "csube": {Name: "csube", CodePoints: []int{10961}, Characters: []byte{0xe2, 0xab, 0x91}},
854 "csup": {Name: "csup", CodePoints: []int{10960}, Characters: []byte{0xe2, 0xab, 0x90}},
855 "csupe": {Name: "csupe", CodePoints: []int{10962}, Characters: []byte{0xe2, 0xab, 0x92}},
856 "ctdot": {Name: "ctdot", CodePoints: []int{8943}, Characters: []byte{0xe2, 0x8b, 0xaf}},
857 "cudarrl": {Name: "cudarrl", CodePoints: []int{10552}, Characters: []byte{0xe2, 0xa4, 0xb8}},
858 "cudarrr": {Name: "cudarrr", CodePoints: []int{10549}, Characters: []byte{0xe2, 0xa4, 0xb5}},
859 "cuepr": {Name: "cuepr", CodePoints: []int{8926}, Characters: []byte{0xe2, 0x8b, 0x9e}},
860 "cuesc": {Name: "cuesc", CodePoints: []int{8927}, Characters: []byte{0xe2, 0x8b, 0x9f}},
861 "cularr": {Name: "cularr", CodePoints: []int{8630}, Characters: []byte{0xe2, 0x86, 0xb6}},
862 "cularrp": {Name: "cularrp", CodePoints: []int{10557}, Characters: []byte{0xe2, 0xa4, 0xbd}},
863 "cup": {Name: "cup", CodePoints: []int{8746}, Characters: []byte{0xe2, 0x88, 0xaa}},
864 "cupbrcap": {Name: "cupbrcap", CodePoints: []int{10824}, Characters: []byte{0xe2, 0xa9, 0x88}},
865 "cupcap": {Name: "cupcap", CodePoints: []int{10822}, Characters: []byte{0xe2, 0xa9, 0x86}},
866 "cupcup": {Name: "cupcup", CodePoints: []int{10826}, Characters: []byte{0xe2, 0xa9, 0x8a}},
867 "cupdot": {Name: "cupdot", CodePoints: []int{8845}, Characters: []byte{0xe2, 0x8a, 0x8d}},
868 "cupor": {Name: "cupor", CodePoints: []int{10821}, Characters: []byte{0xe2, 0xa9, 0x85}},
869 "cups": {Name: "cups", CodePoints: []int{8746, 65024}, Characters: []byte{0xe2, 0x88, 0xaa, 0xef, 0xb8, 0x80}},
870 "curarr": {Name: "curarr", CodePoints: []int{8631}, Characters: []byte{0xe2, 0x86, 0xb7}},
871 "curarrm": {Name: "curarrm", CodePoints: []int{10556}, Characters: []byte{0xe2, 0xa4, 0xbc}},
872 "curlyeqprec": {Name: "curlyeqprec", CodePoints: []int{8926}, Characters: []byte{0xe2, 0x8b, 0x9e}},
873 "curlyeqsucc": {Name: "curlyeqsucc", CodePoints: []int{8927}, Characters: []byte{0xe2, 0x8b, 0x9f}},
874 "curlyvee": {Name: "curlyvee", CodePoints: []int{8910}, Characters: []byte{0xe2, 0x8b, 0x8e}},
875 "curlywedge": {Name: "curlywedge", CodePoints: []int{8911}, Characters: []byte{0xe2, 0x8b, 0x8f}},
876 "curren": {Name: "curren", CodePoints: []int{164}, Characters: []byte{0xc2, 0xa4}},
877 "curvearrowleft": {Name: "curvearrowleft", CodePoints: []int{8630}, Characters: []byte{0xe2, 0x86, 0xb6}},
878 "curvearrowright": {Name: "curvearrowright", CodePoints: []int{8631}, Characters: []byte{0xe2, 0x86, 0xb7}},
879 "cuvee": {Name: "cuvee", CodePoints: []int{8910}, Characters: []byte{0xe2, 0x8b, 0x8e}},
880 "cuwed": {Name: "cuwed", CodePoints: []int{8911}, Characters: []byte{0xe2, 0x8b, 0x8f}},
881 "cwconint": {Name: "cwconint", CodePoints: []int{8754}, Characters: []byte{0xe2, 0x88, 0xb2}},
882 "cwint": {Name: "cwint", CodePoints: []int{8753}, Characters: []byte{0xe2, 0x88, 0xb1}},
883 "cylcty": {Name: "cylcty", CodePoints: []int{9005}, Characters: []byte{0xe2, 0x8c, 0xad}},
884 "dArr": {Name: "dArr", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
885 "dHar": {Name: "dHar", CodePoints: []int{10597}, Characters: []byte{0xe2, 0xa5, 0xa5}},
886 "dagger": {Name: "dagger", CodePoints: []int{8224}, Characters: []byte{0xe2, 0x80, 0xa0}},
887 "daleth": {Name: "daleth", CodePoints: []int{8504}, Characters: []byte{0xe2, 0x84, 0xb8}},
888 "darr": {Name: "darr", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
889 "dash": {Name: "dash", CodePoints: []int{8208}, Characters: []byte{0xe2, 0x80, 0x90}},
890 "dashv": {Name: "dashv", CodePoints: []int{8867}, Characters: []byte{0xe2, 0x8a, 0xa3}},
891 "dbkarow": {Name: "dbkarow", CodePoints: []int{10511}, Characters: []byte{0xe2, 0xa4, 0x8f}},
892 "dblac": {Name: "dblac", CodePoints: []int{733}, Characters: []byte{0xcb, 0x9d}},
893 "dcaron": {Name: "dcaron", CodePoints: []int{271}, Characters: []byte{0xc4, 0x8f}},
894 "dcy": {Name: "dcy", CodePoints: []int{1076}, Characters: []byte{0xd0, 0xb4}},
895 "dd": {Name: "dd", CodePoints: []int{8518}, Characters: []byte{0xe2, 0x85, 0x86}},
896 "ddagger": {Name: "ddagger", CodePoints: []int{8225}, Characters: []byte{0xe2, 0x80, 0xa1}},
897 "ddarr": {Name: "ddarr", CodePoints: []int{8650}, Characters: []byte{0xe2, 0x87, 0x8a}},
898 "ddotseq": {Name: "ddotseq", CodePoints: []int{10871}, Characters: []byte{0xe2, 0xa9, 0xb7}},
899 "deg": {Name: "deg", CodePoints: []int{176}, Characters: []byte{0xc2, 0xb0}},
900 "delta": {Name: "delta", CodePoints: []int{948}, Characters: []byte{0xce, 0xb4}},
901 "demptyv": {Name: "demptyv", CodePoints: []int{10673}, Characters: []byte{0xe2, 0xa6, 0xb1}},
902 "dfisht": {Name: "dfisht", CodePoints: []int{10623}, Characters: []byte{0xe2, 0xa5, 0xbf}},
903 "dfr": {Name: "dfr", CodePoints: []int{120097}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa1}},
904 "dharl": {Name: "dharl", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
905 "dharr": {Name: "dharr", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
906 "diam": {Name: "diam", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
907 "diamond": {Name: "diamond", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
908 "diamondsuit": {Name: "diamondsuit", CodePoints: []int{9830}, Characters: []byte{0xe2, 0x99, 0xa6}},
909 "diams": {Name: "diams", CodePoints: []int{9830}, Characters: []byte{0xe2, 0x99, 0xa6}},
910 "die": {Name: "die", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
911 "digamma": {Name: "digamma", CodePoints: []int{989}, Characters: []byte{0xcf, 0x9d}},
912 "disin": {Name: "disin", CodePoints: []int{8946}, Characters: []byte{0xe2, 0x8b, 0xb2}},
913 "div": {Name: "div", CodePoints: []int{247}, Characters: []byte{0xc3, 0xb7}},
914 "divide": {Name: "divide", CodePoints: []int{247}, Characters: []byte{0xc3, 0xb7}},
915 "divideontimes": {Name: "divideontimes", CodePoints: []int{8903}, Characters: []byte{0xe2, 0x8b, 0x87}},
916 "divonx": {Name: "divonx", CodePoints: []int{8903}, Characters: []byte{0xe2, 0x8b, 0x87}},
917 "djcy": {Name: "djcy", CodePoints: []int{1106}, Characters: []byte{0xd1, 0x92}},
918 "dlcorn": {Name: "dlcorn", CodePoints: []int{8990}, Characters: []byte{0xe2, 0x8c, 0x9e}},
919 "dlcrop": {Name: "dlcrop", CodePoints: []int{8973}, Characters: []byte{0xe2, 0x8c, 0x8d}},
920 "dollar": {Name: "dollar", CodePoints: []int{36}, Characters: []byte{0x24}},
921 "dopf": {Name: "dopf", CodePoints: []int{120149}, Characters: []byte{0xf0, 0x9d, 0x95, 0x95}},
922 "dot": {Name: "dot", CodePoints: []int{729}, Characters: []byte{0xcb, 0x99}},
923 "doteq": {Name: "doteq", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
924 "doteqdot": {Name: "doteqdot", CodePoints: []int{8785}, Characters: []byte{0xe2, 0x89, 0x91}},
925 "dotminus": {Name: "dotminus", CodePoints: []int{8760}, Characters: []byte{0xe2, 0x88, 0xb8}},
926 "dotplus": {Name: "dotplus", CodePoints: []int{8724}, Characters: []byte{0xe2, 0x88, 0x94}},
927 "dotsquare": {Name: "dotsquare", CodePoints: []int{8865}, Characters: []byte{0xe2, 0x8a, 0xa1}},
928 "doublebarwedge": {Name: "doublebarwedge", CodePoints: []int{8966}, Characters: []byte{0xe2, 0x8c, 0x86}},
929 "downarrow": {Name: "downarrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
930 "downdownarrows": {Name: "downdownarrows", CodePoints: []int{8650}, Characters: []byte{0xe2, 0x87, 0x8a}},
931 "downharpoonleft": {Name: "downharpoonleft", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
932 "downharpoonright": {Name: "downharpoonright", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
933 "drbkarow": {Name: "drbkarow", CodePoints: []int{10512}, Characters: []byte{0xe2, 0xa4, 0x90}},
934 "drcorn": {Name: "drcorn", CodePoints: []int{8991}, Characters: []byte{0xe2, 0x8c, 0x9f}},
935 "drcrop": {Name: "drcrop", CodePoints: []int{8972}, Characters: []byte{0xe2, 0x8c, 0x8c}},
936 "dscr": {Name: "dscr", CodePoints: []int{119993}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb9}},
937 "dscy": {Name: "dscy", CodePoints: []int{1109}, Characters: []byte{0xd1, 0x95}},
938 "dsol": {Name: "dsol", CodePoints: []int{10742}, Characters: []byte{0xe2, 0xa7, 0xb6}},
939 "dstrok": {Name: "dstrok", CodePoints: []int{273}, Characters: []byte{0xc4, 0x91}},
940 "dtdot": {Name: "dtdot", CodePoints: []int{8945}, Characters: []byte{0xe2, 0x8b, 0xb1}},
941 "dtri": {Name: "dtri", CodePoints: []int{9663}, Characters: []byte{0xe2, 0x96, 0xbf}},
942 "dtrif": {Name: "dtrif", CodePoints: []int{9662}, Characters: []byte{0xe2, 0x96, 0xbe}},
943 "duarr": {Name: "duarr", CodePoints: []int{8693}, Characters: []byte{0xe2, 0x87, 0xb5}},
944 "duhar": {Name: "duhar", CodePoints: []int{10607}, Characters: []byte{0xe2, 0xa5, 0xaf}},
945 "dwangle": {Name: "dwangle", CodePoints: []int{10662}, Characters: []byte{0xe2, 0xa6, 0xa6}},
946 "dzcy": {Name: "dzcy", CodePoints: []int{1119}, Characters: []byte{0xd1, 0x9f}},
947 "dzigrarr": {Name: "dzigrarr", CodePoints: []int{10239}, Characters: []byte{0xe2, 0x9f, 0xbf}},
948 "eDDot": {Name: "eDDot", CodePoints: []int{10871}, Characters: []byte{0xe2, 0xa9, 0xb7}},
949 "eDot": {Name: "eDot", CodePoints: []int{8785}, Characters: []byte{0xe2, 0x89, 0x91}},
950 "eacute": {Name: "eacute", CodePoints: []int{233}, Characters: []byte{0xc3, 0xa9}},
951 "easter": {Name: "easter", CodePoints: []int{10862}, Characters: []byte{0xe2, 0xa9, 0xae}},
952 "ecaron": {Name: "ecaron", CodePoints: []int{283}, Characters: []byte{0xc4, 0x9b}},
953 "ecir": {Name: "ecir", CodePoints: []int{8790}, Characters: []byte{0xe2, 0x89, 0x96}},
954 "ecirc": {Name: "ecirc", CodePoints: []int{234}, Characters: []byte{0xc3, 0xaa}},
955 "ecolon": {Name: "ecolon", CodePoints: []int{8789}, Characters: []byte{0xe2, 0x89, 0x95}},
956 "ecy": {Name: "ecy", CodePoints: []int{1101}, Characters: []byte{0xd1, 0x8d}},
957 "edot": {Name: "edot", CodePoints: []int{279}, Characters: []byte{0xc4, 0x97}},
958 "ee": {Name: "ee", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
959 "efDot": {Name: "efDot", CodePoints: []int{8786}, Characters: []byte{0xe2, 0x89, 0x92}},
960 "efr": {Name: "efr", CodePoints: []int{120098}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa2}},
961 "eg": {Name: "eg", CodePoints: []int{10906}, Characters: []byte{0xe2, 0xaa, 0x9a}},
962 "egrave": {Name: "egrave", CodePoints: []int{232}, Characters: []byte{0xc3, 0xa8}},
963 "egs": {Name: "egs", CodePoints: []int{10902}, Characters: []byte{0xe2, 0xaa, 0x96}},
964 "egsdot": {Name: "egsdot", CodePoints: []int{10904}, Characters: []byte{0xe2, 0xaa, 0x98}},
965 "el": {Name: "el", CodePoints: []int{10905}, Characters: []byte{0xe2, 0xaa, 0x99}},
966 "elinters": {Name: "elinters", CodePoints: []int{9191}, Characters: []byte{0xe2, 0x8f, 0xa7}},
967 "ell": {Name: "ell", CodePoints: []int{8467}, Characters: []byte{0xe2, 0x84, 0x93}},
968 "els": {Name: "els", CodePoints: []int{10901}, Characters: []byte{0xe2, 0xaa, 0x95}},
969 "elsdot": {Name: "elsdot", CodePoints: []int{10903}, Characters: []byte{0xe2, 0xaa, 0x97}},
970 "emacr": {Name: "emacr", CodePoints: []int{275}, Characters: []byte{0xc4, 0x93}},
971 "empty": {Name: "empty", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
972 "emptyset": {Name: "emptyset", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
973 "emptyv": {Name: "emptyv", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
974 "emsp": {Name: "emsp", CodePoints: []int{8195}, Characters: []byte{0xe2, 0x80, 0x83}},
975 "emsp13": {Name: "emsp13", CodePoints: []int{8196}, Characters: []byte{0xe2, 0x80, 0x84}},
976 "emsp14": {Name: "emsp14", CodePoints: []int{8197}, Characters: []byte{0xe2, 0x80, 0x85}},
977 "eng": {Name: "eng", CodePoints: []int{331}, Characters: []byte{0xc5, 0x8b}},
978 "ensp": {Name: "ensp", CodePoints: []int{8194}, Characters: []byte{0xe2, 0x80, 0x82}},
979 "eogon": {Name: "eogon", CodePoints: []int{281}, Characters: []byte{0xc4, 0x99}},
980 "eopf": {Name: "eopf", CodePoints: []int{120150}, Characters: []byte{0xf0, 0x9d, 0x95, 0x96}},
981 "epar": {Name: "epar", CodePoints: []int{8917}, Characters: []byte{0xe2, 0x8b, 0x95}},
982 "eparsl": {Name: "eparsl", CodePoints: []int{10723}, Characters: []byte{0xe2, 0xa7, 0xa3}},
983 "eplus": {Name: "eplus", CodePoints: []int{10865}, Characters: []byte{0xe2, 0xa9, 0xb1}},
984 "epsi": {Name: "epsi", CodePoints: []int{949}, Characters: []byte{0xce, 0xb5}},
985 "epsilon": {Name: "epsilon", CodePoints: []int{949}, Characters: []byte{0xce, 0xb5}},
986 "epsiv": {Name: "epsiv", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
987 "eqcirc": {Name: "eqcirc", CodePoints: []int{8790}, Characters: []byte{0xe2, 0x89, 0x96}},
988 "eqcolon": {Name: "eqcolon", CodePoints: []int{8789}, Characters: []byte{0xe2, 0x89, 0x95}},
989 "eqsim": {Name: "eqsim", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
990 "eqslantgtr": {Name: "eqslantgtr", CodePoints: []int{10902}, Characters: []byte{0xe2, 0xaa, 0x96}},
991 "eqslantless": {Name: "eqslantless", CodePoints: []int{10901}, Characters: []byte{0xe2, 0xaa, 0x95}},
992 "equals": {Name: "equals", CodePoints: []int{61}, Characters: []byte{0x3d}},
993 "equest": {Name: "equest", CodePoints: []int{8799}, Characters: []byte{0xe2, 0x89, 0x9f}},
994 "equiv": {Name: "equiv", CodePoints: []int{8801}, Characters: []byte{0xe2, 0x89, 0xa1}},
995 "equivDD": {Name: "equivDD", CodePoints: []int{10872}, Characters: []byte{0xe2, 0xa9, 0xb8}},
996 "eqvparsl": {Name: "eqvparsl", CodePoints: []int{10725}, Characters: []byte{0xe2, 0xa7, 0xa5}},
997 "erDot": {Name: "erDot", CodePoints: []int{8787}, Characters: []byte{0xe2, 0x89, 0x93}},
998 "erarr": {Name: "erarr", CodePoints: []int{10609}, Characters: []byte{0xe2, 0xa5, 0xb1}},
999 "escr": {Name: "escr", CodePoints: []int{8495}, Characters: []byte{0xe2, 0x84, 0xaf}},
1000 "esdot": {Name: "esdot", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
1001 "esim": {Name: "esim", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
1002 "eta": {Name: "eta", CodePoints: []int{951}, Characters: []byte{0xce, 0xb7}},
1003 "eth": {Name: "eth", CodePoints: []int{240}, Characters: []byte{0xc3, 0xb0}},
1004 "euml": {Name: "euml", CodePoints: []int{235}, Characters: []byte{0xc3, 0xab}},
1005 "euro": {Name: "euro", CodePoints: []int{8364}, Characters: []byte{0xe2, 0x82, 0xac}},
1006 "excl": {Name: "excl", CodePoints: []int{33}, Characters: []byte{0x21}},
1007 "exist": {Name: "exist", CodePoints: []int{8707}, Characters: []byte{0xe2, 0x88, 0x83}},
1008 "expectation": {Name: "expectation", CodePoints: []int{8496}, Characters: []byte{0xe2, 0x84, 0xb0}},
1009 "exponentiale": {Name: "exponentiale", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
1010 "fallingdotseq": {Name: "fallingdotseq", CodePoints: []int{8786}, Characters: []byte{0xe2, 0x89, 0x92}},
1011 "fcy": {Name: "fcy", CodePoints: []int{1092}, Characters: []byte{0xd1, 0x84}},
1012 "female": {Name: "female", CodePoints: []int{9792}, Characters: []byte{0xe2, 0x99, 0x80}},
1013 "ffilig": {Name: "ffilig", CodePoints: []int{64259}, Characters: []byte{0xef, 0xac, 0x83}},
1014 "fflig": {Name: "fflig", CodePoints: []int{64256}, Characters: []byte{0xef, 0xac, 0x80}},
1015 "ffllig": {Name: "ffllig", CodePoints: []int{64260}, Characters: []byte{0xef, 0xac, 0x84}},
1016 "ffr": {Name: "ffr", CodePoints: []int{120099}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa3}},
1017 "filig": {Name: "filig", CodePoints: []int{64257}, Characters: []byte{0xef, 0xac, 0x81}},
1018 "fjlig": {Name: "fjlig", CodePoints: []int{102, 106}, Characters: []byte{0x66, 0x6a}},
1019 "flat": {Name: "flat", CodePoints: []int{9837}, Characters: []byte{0xe2, 0x99, 0xad}},
1020 "fllig": {Name: "fllig", CodePoints: []int{64258}, Characters: []byte{0xef, 0xac, 0x82}},
1021 "fltns": {Name: "fltns", CodePoints: []int{9649}, Characters: []byte{0xe2, 0x96, 0xb1}},
1022 "fnof": {Name: "fnof", CodePoints: []int{402}, Characters: []byte{0xc6, 0x92}},
1023 "fopf": {Name: "fopf", CodePoints: []int{120151}, Characters: []byte{0xf0, 0x9d, 0x95, 0x97}},
1024 "forall": {Name: "forall", CodePoints: []int{8704}, Characters: []byte{0xe2, 0x88, 0x80}},
1025 "fork": {Name: "fork", CodePoints: []int{8916}, Characters: []byte{0xe2, 0x8b, 0x94}},
1026 "forkv": {Name: "forkv", CodePoints: []int{10969}, Characters: []byte{0xe2, 0xab, 0x99}},
1027 "fpartint": {Name: "fpartint", CodePoints: []int{10765}, Characters: []byte{0xe2, 0xa8, 0x8d}},
1028 "frac12": {Name: "frac12", CodePoints: []int{189}, Characters: []byte{0xc2, 0xbd}},
1029 "frac13": {Name: "frac13", CodePoints: []int{8531}, Characters: []byte{0xe2, 0x85, 0x93}},
1030 "frac14": {Name: "frac14", CodePoints: []int{188}, Characters: []byte{0xc2, 0xbc}},
1031 "frac15": {Name: "frac15", CodePoints: []int{8533}, Characters: []byte{0xe2, 0x85, 0x95}},
1032 "frac16": {Name: "frac16", CodePoints: []int{8537}, Characters: []byte{0xe2, 0x85, 0x99}},
1033 "frac18": {Name: "frac18", CodePoints: []int{8539}, Characters: []byte{0xe2, 0x85, 0x9b}},
1034 "frac23": {Name: "frac23", CodePoints: []int{8532}, Characters: []byte{0xe2, 0x85, 0x94}},
1035 "frac25": {Name: "frac25", CodePoints: []int{8534}, Characters: []byte{0xe2, 0x85, 0x96}},
1036 "frac34": {Name: "frac34", CodePoints: []int{190}, Characters: []byte{0xc2, 0xbe}},
1037 "frac35": {Name: "frac35", CodePoints: []int{8535}, Characters: []byte{0xe2, 0x85, 0x97}},
1038 "frac38": {Name: "frac38", CodePoints: []int{8540}, Characters: []byte{0xe2, 0x85, 0x9c}},
1039 "frac45": {Name: "frac45", CodePoints: []int{8536}, Characters: []byte{0xe2, 0x85, 0x98}},
1040 "frac56": {Name: "frac56", CodePoints: []int{8538}, Characters: []byte{0xe2, 0x85, 0x9a}},
1041 "frac58": {Name: "frac58", CodePoints: []int{8541}, Characters: []byte{0xe2, 0x85, 0x9d}},
1042 "frac78": {Name: "frac78", CodePoints: []int{8542}, Characters: []byte{0xe2, 0x85, 0x9e}},
1043 "frasl": {Name: "frasl", CodePoints: []int{8260}, Characters: []byte{0xe2, 0x81, 0x84}},
1044 "frown": {Name: "frown", CodePoints: []int{8994}, Characters: []byte{0xe2, 0x8c, 0xa2}},
1045 "fscr": {Name: "fscr", CodePoints: []int{119995}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbb}},
1046 "gE": {Name: "gE", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
1047 "gEl": {Name: "gEl", CodePoints: []int{10892}, Characters: []byte{0xe2, 0xaa, 0x8c}},
1048 "gacute": {Name: "gacute", CodePoints: []int{501}, Characters: []byte{0xc7, 0xb5}},
1049 "gamma": {Name: "gamma", CodePoints: []int{947}, Characters: []byte{0xce, 0xb3}},
1050 "gammad": {Name: "gammad", CodePoints: []int{989}, Characters: []byte{0xcf, 0x9d}},
1051 "gap": {Name: "gap", CodePoints: []int{10886}, Characters: []byte{0xe2, 0xaa, 0x86}},
1052 "gbreve": {Name: "gbreve", CodePoints: []int{287}, Characters: []byte{0xc4, 0x9f}},
1053 "gcirc": {Name: "gcirc", CodePoints: []int{285}, Characters: []byte{0xc4, 0x9d}},
1054 "gcy": {Name: "gcy", CodePoints: []int{1075}, Characters: []byte{0xd0, 0xb3}},
1055 "gdot": {Name: "gdot", CodePoints: []int{289}, Characters: []byte{0xc4, 0xa1}},
1056 "ge": {Name: "ge", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
1057 "gel": {Name: "gel", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
1058 "geq": {Name: "geq", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
1059 "geqq": {Name: "geqq", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
1060 "geqslant": {Name: "geqslant", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
1061 "ges": {Name: "ges", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
1062 "gescc": {Name: "gescc", CodePoints: []int{10921}, Characters: []byte{0xe2, 0xaa, 0xa9}},
1063 "gesdot": {Name: "gesdot", CodePoints: []int{10880}, Characters: []byte{0xe2, 0xaa, 0x80}},
1064 "gesdoto": {Name: "gesdoto", CodePoints: []int{10882}, Characters: []byte{0xe2, 0xaa, 0x82}},
1065 "gesdotol": {Name: "gesdotol", CodePoints: []int{10884}, Characters: []byte{0xe2, 0xaa, 0x84}},
1066 "gesl": {Name: "gesl", CodePoints: []int{8923, 65024}, Characters: []byte{0xe2, 0x8b, 0x9b, 0xef, 0xb8, 0x80}},
1067 "gesles": {Name: "gesles", CodePoints: []int{10900}, Characters: []byte{0xe2, 0xaa, 0x94}},
1068 "gfr": {Name: "gfr", CodePoints: []int{120100}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa4}},
1069 "gg": {Name: "gg", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
1070 "ggg": {Name: "ggg", CodePoints: []int{8921}, Characters: []byte{0xe2, 0x8b, 0x99}},
1071 "gimel": {Name: "gimel", CodePoints: []int{8503}, Characters: []byte{0xe2, 0x84, 0xb7}},
1072 "gjcy": {Name: "gjcy", CodePoints: []int{1107}, Characters: []byte{0xd1, 0x93}},
1073 "gl": {Name: "gl", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
1074 "glE": {Name: "glE", CodePoints: []int{10898}, Characters: []byte{0xe2, 0xaa, 0x92}},
1075 "gla": {Name: "gla", CodePoints: []int{10917}, Characters: []byte{0xe2, 0xaa, 0xa5}},
1076 "glj": {Name: "glj", CodePoints: []int{10916}, Characters: []byte{0xe2, 0xaa, 0xa4}},
1077 "gnE": {Name: "gnE", CodePoints: []int{8809}, Characters: []byte{0xe2, 0x89, 0xa9}},
1078 "gnap": {Name: "gnap", CodePoints: []int{10890}, Characters: []byte{0xe2, 0xaa, 0x8a}},
1079 "gnapprox": {Name: "gnapprox", CodePoints: []int{10890}, Characters: []byte{0xe2, 0xaa, 0x8a}},
1080 "gne": {Name: "gne", CodePoints: []int{10888}, Characters: []byte{0xe2, 0xaa, 0x88}},
1081 "gneq": {Name: "gneq", CodePoints: []int{10888}, Characters: []byte{0xe2, 0xaa, 0x88}},
1082 "gneqq": {Name: "gneqq", CodePoints: []int{8809}, Characters: []byte{0xe2, 0x89, 0xa9}},
1083 "gnsim": {Name: "gnsim", CodePoints: []int{8935}, Characters: []byte{0xe2, 0x8b, 0xa7}},
1084 "gopf": {Name: "gopf", CodePoints: []int{120152}, Characters: []byte{0xf0, 0x9d, 0x95, 0x98}},
1085 "grave": {Name: "grave", CodePoints: []int{96}, Characters: []byte{0x60}},
1086 "gscr": {Name: "gscr", CodePoints: []int{8458}, Characters: []byte{0xe2, 0x84, 0x8a}},
1087 "gsim": {Name: "gsim", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
1088 "gsime": {Name: "gsime", CodePoints: []int{10894}, Characters: []byte{0xe2, 0xaa, 0x8e}},
1089 "gsiml": {Name: "gsiml", CodePoints: []int{10896}, Characters: []byte{0xe2, 0xaa, 0x90}},
1090 "gt": {Name: "gt", CodePoints: []int{62}, Characters: []byte{0x3e}},
1091 "gtcc": {Name: "gtcc", CodePoints: []int{10919}, Characters: []byte{0xe2, 0xaa, 0xa7}},
1092 "gtcir": {Name: "gtcir", CodePoints: []int{10874}, Characters: []byte{0xe2, 0xa9, 0xba}},
1093 "gtdot": {Name: "gtdot", CodePoints: []int{8919}, Characters: []byte{0xe2, 0x8b, 0x97}},
1094 "gtlPar": {Name: "gtlPar", CodePoints: []int{10645}, Characters: []byte{0xe2, 0xa6, 0x95}},
1095 "gtquest": {Name: "gtquest", CodePoints: []int{10876}, Characters: []byte{0xe2, 0xa9, 0xbc}},
1096 "gtrapprox": {Name: "gtrapprox", CodePoints: []int{10886}, Characters: []byte{0xe2, 0xaa, 0x86}},
1097 "gtrarr": {Name: "gtrarr", CodePoints: []int{10616}, Characters: []byte{0xe2, 0xa5, 0xb8}},
1098 "gtrdot": {Name: "gtrdot", CodePoints: []int{8919}, Characters: []byte{0xe2, 0x8b, 0x97}},
1099 "gtreqless": {Name: "gtreqless", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
1100 "gtreqqless": {Name: "gtreqqless", CodePoints: []int{10892}, Characters: []byte{0xe2, 0xaa, 0x8c}},
1101 "gtrless": {Name: "gtrless", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
1102 "gtrsim": {Name: "gtrsim", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
1103 "gvertneqq": {Name: "gvertneqq", CodePoints: []int{8809, 65024}, Characters: []byte{0xe2, 0x89, 0xa9, 0xef, 0xb8, 0x80}},
1104 "gvnE": {Name: "gvnE", CodePoints: []int{8809, 65024}, Characters: []byte{0xe2, 0x89, 0xa9, 0xef, 0xb8, 0x80}},
1105 "hArr": {Name: "hArr", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
1106 "hairsp": {Name: "hairsp", CodePoints: []int{8202}, Characters: []byte{0xe2, 0x80, 0x8a}},
1107 "half": {Name: "half", CodePoints: []int{189}, Characters: []byte{0xc2, 0xbd}},
1108 "hamilt": {Name: "hamilt", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
1109 "hardcy": {Name: "hardcy", CodePoints: []int{1098}, Characters: []byte{0xd1, 0x8a}},
1110 "harr": {Name: "harr", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
1111 "harrcir": {Name: "harrcir", CodePoints: []int{10568}, Characters: []byte{0xe2, 0xa5, 0x88}},
1112 "harrw": {Name: "harrw", CodePoints: []int{8621}, Characters: []byte{0xe2, 0x86, 0xad}},
1113 "hbar": {Name: "hbar", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
1114 "hcirc": {Name: "hcirc", CodePoints: []int{293}, Characters: []byte{0xc4, 0xa5}},
1115 "hearts": {Name: "hearts", CodePoints: []int{9829}, Characters: []byte{0xe2, 0x99, 0xa5}},
1116 "heartsuit": {Name: "heartsuit", CodePoints: []int{9829}, Characters: []byte{0xe2, 0x99, 0xa5}},
1117 "hellip": {Name: "hellip", CodePoints: []int{8230}, Characters: []byte{0xe2, 0x80, 0xa6}},
1118 "hercon": {Name: "hercon", CodePoints: []int{8889}, Characters: []byte{0xe2, 0x8a, 0xb9}},
1119 "hfr": {Name: "hfr", CodePoints: []int{120101}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa5}},
1120 "hksearow": {Name: "hksearow", CodePoints: []int{10533}, Characters: []byte{0xe2, 0xa4, 0xa5}},
1121 "hkswarow": {Name: "hkswarow", CodePoints: []int{10534}, Characters: []byte{0xe2, 0xa4, 0xa6}},
1122 "hoarr": {Name: "hoarr", CodePoints: []int{8703}, Characters: []byte{0xe2, 0x87, 0xbf}},
1123 "homtht": {Name: "homtht", CodePoints: []int{8763}, Characters: []byte{0xe2, 0x88, 0xbb}},
1124 "hookleftarrow": {Name: "hookleftarrow", CodePoints: []int{8617}, Characters: []byte{0xe2, 0x86, 0xa9}},
1125 "hookrightarrow": {Name: "hookrightarrow", CodePoints: []int{8618}, Characters: []byte{0xe2, 0x86, 0xaa}},
1126 "hopf": {Name: "hopf", CodePoints: []int{120153}, Characters: []byte{0xf0, 0x9d, 0x95, 0x99}},
1127 "horbar": {Name: "horbar", CodePoints: []int{8213}, Characters: []byte{0xe2, 0x80, 0x95}},
1128 "hscr": {Name: "hscr", CodePoints: []int{119997}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbd}},
1129 "hslash": {Name: "hslash", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
1130 "hstrok": {Name: "hstrok", CodePoints: []int{295}, Characters: []byte{0xc4, 0xa7}},
1131 "hybull": {Name: "hybull", CodePoints: []int{8259}, Characters: []byte{0xe2, 0x81, 0x83}},
1132 "hyphen": {Name: "hyphen", CodePoints: []int{8208}, Characters: []byte{0xe2, 0x80, 0x90}},
1133 "iacute": {Name: "iacute", CodePoints: []int{237}, Characters: []byte{0xc3, 0xad}},
1134 "ic": {Name: "ic", CodePoints: []int{8291}, Characters: []byte{0xe2, 0x81, 0xa3}},
1135 "icirc": {Name: "icirc", CodePoints: []int{238}, Characters: []byte{0xc3, 0xae}},
1136 "icy": {Name: "icy", CodePoints: []int{1080}, Characters: []byte{0xd0, 0xb8}},
1137 "iecy": {Name: "iecy", CodePoints: []int{1077}, Characters: []byte{0xd0, 0xb5}},
1138 "iexcl": {Name: "iexcl", CodePoints: []int{161}, Characters: []byte{0xc2, 0xa1}},
1139 "iff": {Name: "iff", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
1140 "ifr": {Name: "ifr", CodePoints: []int{120102}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa6}},
1141 "igrave": {Name: "igrave", CodePoints: []int{236}, Characters: []byte{0xc3, 0xac}},
1142 "ii": {Name: "ii", CodePoints: []int{8520}, Characters: []byte{0xe2, 0x85, 0x88}},
1143 "iiiint": {Name: "iiiint", CodePoints: []int{10764}, Characters: []byte{0xe2, 0xa8, 0x8c}},
1144 "iiint": {Name: "iiint", CodePoints: []int{8749}, Characters: []byte{0xe2, 0x88, 0xad}},
1145 "iinfin": {Name: "iinfin", CodePoints: []int{10716}, Characters: []byte{0xe2, 0xa7, 0x9c}},
1146 "iiota": {Name: "iiota", CodePoints: []int{8489}, Characters: []byte{0xe2, 0x84, 0xa9}},
1147 "ijlig": {Name: "ijlig", CodePoints: []int{307}, Characters: []byte{0xc4, 0xb3}},
1148 "imacr": {Name: "imacr", CodePoints: []int{299}, Characters: []byte{0xc4, 0xab}},
1149 "image": {Name: "image", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
1150 "imagline": {Name: "imagline", CodePoints: []int{8464}, Characters: []byte{0xe2, 0x84, 0x90}},
1151 "imagpart": {Name: "imagpart", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
1152 "imath": {Name: "imath", CodePoints: []int{305}, Characters: []byte{0xc4, 0xb1}},
1153 "imof": {Name: "imof", CodePoints: []int{8887}, Characters: []byte{0xe2, 0x8a, 0xb7}},
1154 "imped": {Name: "imped", CodePoints: []int{437}, Characters: []byte{0xc6, 0xb5}},
1155 "in": {Name: "in", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
1156 "incare": {Name: "incare", CodePoints: []int{8453}, Characters: []byte{0xe2, 0x84, 0x85}},
1157 "infin": {Name: "infin", CodePoints: []int{8734}, Characters: []byte{0xe2, 0x88, 0x9e}},
1158 "infintie": {Name: "infintie", CodePoints: []int{10717}, Characters: []byte{0xe2, 0xa7, 0x9d}},
1159 "inodot": {Name: "inodot", CodePoints: []int{305}, Characters: []byte{0xc4, 0xb1}},
1160 "int": {Name: "int", CodePoints: []int{8747}, Characters: []byte{0xe2, 0x88, 0xab}},
1161 "intcal": {Name: "intcal", CodePoints: []int{8890}, Characters: []byte{0xe2, 0x8a, 0xba}},
1162 "integers": {Name: "integers", CodePoints: []int{8484}, Characters: []byte{0xe2, 0x84, 0xa4}},
1163 "intercal": {Name: "intercal", CodePoints: []int{8890}, Characters: []byte{0xe2, 0x8a, 0xba}},
1164 "intlarhk": {Name: "intlarhk", CodePoints: []int{10775}, Characters: []byte{0xe2, 0xa8, 0x97}},
1165 "intprod": {Name: "intprod", CodePoints: []int{10812}, Characters: []byte{0xe2, 0xa8, 0xbc}},
1166 "iocy": {Name: "iocy", CodePoints: []int{1105}, Characters: []byte{0xd1, 0x91}},
1167 "iogon": {Name: "iogon", CodePoints: []int{303}, Characters: []byte{0xc4, 0xaf}},
1168 "iopf": {Name: "iopf", CodePoints: []int{120154}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9a}},
1169 "iota": {Name: "iota", CodePoints: []int{953}, Characters: []byte{0xce, 0xb9}},
1170 "iprod": {Name: "iprod", CodePoints: []int{10812}, Characters: []byte{0xe2, 0xa8, 0xbc}},
1171 "iquest": {Name: "iquest", CodePoints: []int{191}, Characters: []byte{0xc2, 0xbf}},
1172 "iscr": {Name: "iscr", CodePoints: []int{119998}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbe}},
1173 "isin": {Name: "isin", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
1174 "isinE": {Name: "isinE", CodePoints: []int{8953}, Characters: []byte{0xe2, 0x8b, 0xb9}},
1175 "isindot": {Name: "isindot", CodePoints: []int{8949}, Characters: []byte{0xe2, 0x8b, 0xb5}},
1176 "isins": {Name: "isins", CodePoints: []int{8948}, Characters: []byte{0xe2, 0x8b, 0xb4}},
1177 "isinsv": {Name: "isinsv", CodePoints: []int{8947}, Characters: []byte{0xe2, 0x8b, 0xb3}},
1178 "isinv": {Name: "isinv", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
1179 "it": {Name: "it", CodePoints: []int{8290}, Characters: []byte{0xe2, 0x81, 0xa2}},
1180 "itilde": {Name: "itilde", CodePoints: []int{297}, Characters: []byte{0xc4, 0xa9}},
1181 "iukcy": {Name: "iukcy", CodePoints: []int{1110}, Characters: []byte{0xd1, 0x96}},
1182 "iuml": {Name: "iuml", CodePoints: []int{239}, Characters: []byte{0xc3, 0xaf}},
1183 "jcirc": {Name: "jcirc", CodePoints: []int{309}, Characters: []byte{0xc4, 0xb5}},
1184 "jcy": {Name: "jcy", CodePoints: []int{1081}, Characters: []byte{0xd0, 0xb9}},
1185 "jfr": {Name: "jfr", CodePoints: []int{120103}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa7}},
1186 "jmath": {Name: "jmath", CodePoints: []int{567}, Characters: []byte{0xc8, 0xb7}},
1187 "jopf": {Name: "jopf", CodePoints: []int{120155}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9b}},
1188 "jscr": {Name: "jscr", CodePoints: []int{119999}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbf}},
1189 "jsercy": {Name: "jsercy", CodePoints: []int{1112}, Characters: []byte{0xd1, 0x98}},
1190 "jukcy": {Name: "jukcy", CodePoints: []int{1108}, Characters: []byte{0xd1, 0x94}},
1191 "kappa": {Name: "kappa", CodePoints: []int{954}, Characters: []byte{0xce, 0xba}},
1192 "kappav": {Name: "kappav", CodePoints: []int{1008}, Characters: []byte{0xcf, 0xb0}},
1193 "kcedil": {Name: "kcedil", CodePoints: []int{311}, Characters: []byte{0xc4, 0xb7}},
1194 "kcy": {Name: "kcy", CodePoints: []int{1082}, Characters: []byte{0xd0, 0xba}},
1195 "kfr": {Name: "kfr", CodePoints: []int{120104}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa8}},
1196 "kgreen": {Name: "kgreen", CodePoints: []int{312}, Characters: []byte{0xc4, 0xb8}},
1197 "khcy": {Name: "khcy", CodePoints: []int{1093}, Characters: []byte{0xd1, 0x85}},
1198 "kjcy": {Name: "kjcy", CodePoints: []int{1116}, Characters: []byte{0xd1, 0x9c}},
1199 "kopf": {Name: "kopf", CodePoints: []int{120156}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9c}},
1200 "kscr": {Name: "kscr", CodePoints: []int{120000}, Characters: []byte{0xf0, 0x9d, 0x93, 0x80}},
1201 "lAarr": {Name: "lAarr", CodePoints: []int{8666}, Characters: []byte{0xe2, 0x87, 0x9a}},
1202 "lArr": {Name: "lArr", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
1203 "lAtail": {Name: "lAtail", CodePoints: []int{10523}, Characters: []byte{0xe2, 0xa4, 0x9b}},
1204 "lBarr": {Name: "lBarr", CodePoints: []int{10510}, Characters: []byte{0xe2, 0xa4, 0x8e}},
1205 "lE": {Name: "lE", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
1206 "lEg": {Name: "lEg", CodePoints: []int{10891}, Characters: []byte{0xe2, 0xaa, 0x8b}},
1207 "lHar": {Name: "lHar", CodePoints: []int{10594}, Characters: []byte{0xe2, 0xa5, 0xa2}},
1208 "lacute": {Name: "lacute", CodePoints: []int{314}, Characters: []byte{0xc4, 0xba}},
1209 "laemptyv": {Name: "laemptyv", CodePoints: []int{10676}, Characters: []byte{0xe2, 0xa6, 0xb4}},
1210 "lagran": {Name: "lagran", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
1211 "lambda": {Name: "lambda", CodePoints: []int{955}, Characters: []byte{0xce, 0xbb}},
1212 "lang": {Name: "lang", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
1213 "langd": {Name: "langd", CodePoints: []int{10641}, Characters: []byte{0xe2, 0xa6, 0x91}},
1214 "langle": {Name: "langle", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
1215 "lap": {Name: "lap", CodePoints: []int{10885}, Characters: []byte{0xe2, 0xaa, 0x85}},
1216 "laquo": {Name: "laquo", CodePoints: []int{171}, Characters: []byte{0xc2, 0xab}},
1217 "larr": {Name: "larr", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
1218 "larrb": {Name: "larrb", CodePoints: []int{8676}, Characters: []byte{0xe2, 0x87, 0xa4}},
1219 "larrbfs": {Name: "larrbfs", CodePoints: []int{10527}, Characters: []byte{0xe2, 0xa4, 0x9f}},
1220 "larrfs": {Name: "larrfs", CodePoints: []int{10525}, Characters: []byte{0xe2, 0xa4, 0x9d}},
1221 "larrhk": {Name: "larrhk", CodePoints: []int{8617}, Characters: []byte{0xe2, 0x86, 0xa9}},
1222 "larrlp": {Name: "larrlp", CodePoints: []int{8619}, Characters: []byte{0xe2, 0x86, 0xab}},
1223 "larrpl": {Name: "larrpl", CodePoints: []int{10553}, Characters: []byte{0xe2, 0xa4, 0xb9}},
1224 "larrsim": {Name: "larrsim", CodePoints: []int{10611}, Characters: []byte{0xe2, 0xa5, 0xb3}},
1225 "larrtl": {Name: "larrtl", CodePoints: []int{8610}, Characters: []byte{0xe2, 0x86, 0xa2}},
1226 "lat": {Name: "lat", CodePoints: []int{10923}, Characters: []byte{0xe2, 0xaa, 0xab}},
1227 "latail": {Name: "latail", CodePoints: []int{10521}, Characters: []byte{0xe2, 0xa4, 0x99}},
1228 "late": {Name: "late", CodePoints: []int{10925}, Characters: []byte{0xe2, 0xaa, 0xad}},
1229 "lates": {Name: "lates", CodePoints: []int{10925, 65024}, Characters: []byte{0xe2, 0xaa, 0xad, 0xef, 0xb8, 0x80}},
1230 "lbarr": {Name: "lbarr", CodePoints: []int{10508}, Characters: []byte{0xe2, 0xa4, 0x8c}},
1231 "lbbrk": {Name: "lbbrk", CodePoints: []int{10098}, Characters: []byte{0xe2, 0x9d, 0xb2}},
1232 "lbrace": {Name: "lbrace", CodePoints: []int{123}, Characters: []byte{0x7b}},
1233 "lbrack": {Name: "lbrack", CodePoints: []int{91}, Characters: []byte{0x5b}},
1234 "lbrke": {Name: "lbrke", CodePoints: []int{10635}, Characters: []byte{0xe2, 0xa6, 0x8b}},
1235 "lbrksld": {Name: "lbrksld", CodePoints: []int{10639}, Characters: []byte{0xe2, 0xa6, 0x8f}},
1236 "lbrkslu": {Name: "lbrkslu", CodePoints: []int{10637}, Characters: []byte{0xe2, 0xa6, 0x8d}},
1237 "lcaron": {Name: "lcaron", CodePoints: []int{318}, Characters: []byte{0xc4, 0xbe}},
1238 "lcedil": {Name: "lcedil", CodePoints: []int{316}, Characters: []byte{0xc4, 0xbc}},
1239 "lceil": {Name: "lceil", CodePoints: []int{8968}, Characters: []byte{0xe2, 0x8c, 0x88}},
1240 "lcub": {Name: "lcub", CodePoints: []int{123}, Characters: []byte{0x7b}},
1241 "lcy": {Name: "lcy", CodePoints: []int{1083}, Characters: []byte{0xd0, 0xbb}},
1242 "ldca": {Name: "ldca", CodePoints: []int{10550}, Characters: []byte{0xe2, 0xa4, 0xb6}},
1243 "ldquo": {Name: "ldquo", CodePoints: []int{8220}, Characters: []byte{0xe2, 0x80, 0x9c}},
1244 "ldquor": {Name: "ldquor", CodePoints: []int{8222}, Characters: []byte{0xe2, 0x80, 0x9e}},
1245 "ldrdhar": {Name: "ldrdhar", CodePoints: []int{10599}, Characters: []byte{0xe2, 0xa5, 0xa7}},
1246 "ldrushar": {Name: "ldrushar", CodePoints: []int{10571}, Characters: []byte{0xe2, 0xa5, 0x8b}},
1247 "ldsh": {Name: "ldsh", CodePoints: []int{8626}, Characters: []byte{0xe2, 0x86, 0xb2}},
1248 "le": {Name: "le", CodePoints: []int{8804}, Characters: []byte{0xe2, 0x89, 0xa4}},
1249 "leftarrow": {Name: "leftarrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
1250 "leftarrowtail": {Name: "leftarrowtail", CodePoints: []int{8610}, Characters: []byte{0xe2, 0x86, 0xa2}},
1251 "leftharpoondown": {Name: "leftharpoondown", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
1252 "leftharpoonup": {Name: "leftharpoonup", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
1253 "leftleftarrows": {Name: "leftleftarrows", CodePoints: []int{8647}, Characters: []byte{0xe2, 0x87, 0x87}},
1254 "leftrightarrow": {Name: "leftrightarrow", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
1255 "leftrightarrows": {Name: "leftrightarrows", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
1256 "leftrightharpoons": {Name: "leftrightharpoons", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
1257 "leftrightsquigarrow": {Name: "leftrightsquigarrow", CodePoints: []int{8621}, Characters: []byte{0xe2, 0x86, 0xad}},
1258 "leftthreetimes": {Name: "leftthreetimes", CodePoints: []int{8907}, Characters: []byte{0xe2, 0x8b, 0x8b}},
1259 "leg": {Name: "leg", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
1260 "leq": {Name: "leq", CodePoints: []int{8804}, Characters: []byte{0xe2, 0x89, 0xa4}},
1261 "leqq": {Name: "leqq", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
1262 "leqslant": {Name: "leqslant", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
1263 "les": {Name: "les", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
1264 "lescc": {Name: "lescc", CodePoints: []int{10920}, Characters: []byte{0xe2, 0xaa, 0xa8}},
1265 "lesdot": {Name: "lesdot", CodePoints: []int{10879}, Characters: []byte{0xe2, 0xa9, 0xbf}},
1266 "lesdoto": {Name: "lesdoto", CodePoints: []int{10881}, Characters: []byte{0xe2, 0xaa, 0x81}},
1267 "lesdotor": {Name: "lesdotor", CodePoints: []int{10883}, Characters: []byte{0xe2, 0xaa, 0x83}},
1268 "lesg": {Name: "lesg", CodePoints: []int{8922, 65024}, Characters: []byte{0xe2, 0x8b, 0x9a, 0xef, 0xb8, 0x80}},
1269 "lesges": {Name: "lesges", CodePoints: []int{10899}, Characters: []byte{0xe2, 0xaa, 0x93}},
1270 "lessapprox": {Name: "lessapprox", CodePoints: []int{10885}, Characters: []byte{0xe2, 0xaa, 0x85}},
1271 "lessdot": {Name: "lessdot", CodePoints: []int{8918}, Characters: []byte{0xe2, 0x8b, 0x96}},
1272 "lesseqgtr": {Name: "lesseqgtr", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
1273 "lesseqqgtr": {Name: "lesseqqgtr", CodePoints: []int{10891}, Characters: []byte{0xe2, 0xaa, 0x8b}},
1274 "lessgtr": {Name: "lessgtr", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
1275 "lesssim": {Name: "lesssim", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
1276 "lfisht": {Name: "lfisht", CodePoints: []int{10620}, Characters: []byte{0xe2, 0xa5, 0xbc}},
1277 "lfloor": {Name: "lfloor", CodePoints: []int{8970}, Characters: []byte{0xe2, 0x8c, 0x8a}},
1278 "lfr": {Name: "lfr", CodePoints: []int{120105}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa9}},
1279 "lg": {Name: "lg", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
1280 "lgE": {Name: "lgE", CodePoints: []int{10897}, Characters: []byte{0xe2, 0xaa, 0x91}},
1281 "lhard": {Name: "lhard", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
1282 "lharu": {Name: "lharu", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
1283 "lharul": {Name: "lharul", CodePoints: []int{10602}, Characters: []byte{0xe2, 0xa5, 0xaa}},
1284 "lhblk": {Name: "lhblk", CodePoints: []int{9604}, Characters: []byte{0xe2, 0x96, 0x84}},
1285 "ljcy": {Name: "ljcy", CodePoints: []int{1113}, Characters: []byte{0xd1, 0x99}},
1286 "ll": {Name: "ll", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
1287 "llarr": {Name: "llarr", CodePoints: []int{8647}, Characters: []byte{0xe2, 0x87, 0x87}},
1288 "llcorner": {Name: "llcorner", CodePoints: []int{8990}, Characters: []byte{0xe2, 0x8c, 0x9e}},
1289 "llhard": {Name: "llhard", CodePoints: []int{10603}, Characters: []byte{0xe2, 0xa5, 0xab}},
1290 "lltri": {Name: "lltri", CodePoints: []int{9722}, Characters: []byte{0xe2, 0x97, 0xba}},
1291 "lmidot": {Name: "lmidot", CodePoints: []int{320}, Characters: []byte{0xc5, 0x80}},
1292 "lmoust": {Name: "lmoust", CodePoints: []int{9136}, Characters: []byte{0xe2, 0x8e, 0xb0}},
1293 "lmoustache": {Name: "lmoustache", CodePoints: []int{9136}, Characters: []byte{0xe2, 0x8e, 0xb0}},
1294 "lnE": {Name: "lnE", CodePoints: []int{8808}, Characters: []byte{0xe2, 0x89, 0xa8}},
1295 "lnap": {Name: "lnap", CodePoints: []int{10889}, Characters: []byte{0xe2, 0xaa, 0x89}},
1296 "lnapprox": {Name: "lnapprox", CodePoints: []int{10889}, Characters: []byte{0xe2, 0xaa, 0x89}},
1297 "lne": {Name: "lne", CodePoints: []int{10887}, Characters: []byte{0xe2, 0xaa, 0x87}},
1298 "lneq": {Name: "lneq", CodePoints: []int{10887}, Characters: []byte{0xe2, 0xaa, 0x87}},
1299 "lneqq": {Name: "lneqq", CodePoints: []int{8808}, Characters: []byte{0xe2, 0x89, 0xa8}},
1300 "lnsim": {Name: "lnsim", CodePoints: []int{8934}, Characters: []byte{0xe2, 0x8b, 0xa6}},
1301 "loang": {Name: "loang", CodePoints: []int{10220}, Characters: []byte{0xe2, 0x9f, 0xac}},
1302 "loarr": {Name: "loarr", CodePoints: []int{8701}, Characters: []byte{0xe2, 0x87, 0xbd}},
1303 "lobrk": {Name: "lobrk", CodePoints: []int{10214}, Characters: []byte{0xe2, 0x9f, 0xa6}},
1304 "longleftarrow": {Name: "longleftarrow", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
1305 "longleftrightarrow": {Name: "longleftrightarrow", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
1306 "longmapsto": {Name: "longmapsto", CodePoints: []int{10236}, Characters: []byte{0xe2, 0x9f, 0xbc}},
1307 "longrightarrow": {Name: "longrightarrow", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
1308 "looparrowleft": {Name: "looparrowleft", CodePoints: []int{8619}, Characters: []byte{0xe2, 0x86, 0xab}},
1309 "looparrowright": {Name: "looparrowright", CodePoints: []int{8620}, Characters: []byte{0xe2, 0x86, 0xac}},
1310 "lopar": {Name: "lopar", CodePoints: []int{10629}, Characters: []byte{0xe2, 0xa6, 0x85}},
1311 "lopf": {Name: "lopf", CodePoints: []int{120157}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9d}},
1312 "loplus": {Name: "loplus", CodePoints: []int{10797}, Characters: []byte{0xe2, 0xa8, 0xad}},
1313 "lotimes": {Name: "lotimes", CodePoints: []int{10804}, Characters: []byte{0xe2, 0xa8, 0xb4}},
1314 "lowast": {Name: "lowast", CodePoints: []int{8727}, Characters: []byte{0xe2, 0x88, 0x97}},
1315 "lowbar": {Name: "lowbar", CodePoints: []int{95}, Characters: []byte{0x5f}},
1316 "loz": {Name: "loz", CodePoints: []int{9674}, Characters: []byte{0xe2, 0x97, 0x8a}},
1317 "lozenge": {Name: "lozenge", CodePoints: []int{9674}, Characters: []byte{0xe2, 0x97, 0x8a}},
1318 "lozf": {Name: "lozf", CodePoints: []int{10731}, Characters: []byte{0xe2, 0xa7, 0xab}},
1319 "lpar": {Name: "lpar", CodePoints: []int{40}, Characters: []byte{0x28}},
1320 "lparlt": {Name: "lparlt", CodePoints: []int{10643}, Characters: []byte{0xe2, 0xa6, 0x93}},
1321 "lrarr": {Name: "lrarr", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
1322 "lrcorner": {Name: "lrcorner", CodePoints: []int{8991}, Characters: []byte{0xe2, 0x8c, 0x9f}},
1323 "lrhar": {Name: "lrhar", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
1324 "lrhard": {Name: "lrhard", CodePoints: []int{10605}, Characters: []byte{0xe2, 0xa5, 0xad}},
1325 "lrm": {Name: "lrm", CodePoints: []int{8206}, Characters: []byte{0xe2, 0x80, 0x8e}},
1326 "lrtri": {Name: "lrtri", CodePoints: []int{8895}, Characters: []byte{0xe2, 0x8a, 0xbf}},
1327 "lsaquo": {Name: "lsaquo", CodePoints: []int{8249}, Characters: []byte{0xe2, 0x80, 0xb9}},
1328 "lscr": {Name: "lscr", CodePoints: []int{120001}, Characters: []byte{0xf0, 0x9d, 0x93, 0x81}},
1329 "lsh": {Name: "lsh", CodePoints: []int{8624}, Characters: []byte{0xe2, 0x86, 0xb0}},
1330 "lsim": {Name: "lsim", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
1331 "lsime": {Name: "lsime", CodePoints: []int{10893}, Characters: []byte{0xe2, 0xaa, 0x8d}},
1332 "lsimg": {Name: "lsimg", CodePoints: []int{10895}, Characters: []byte{0xe2, 0xaa, 0x8f}},
1333 "lsqb": {Name: "lsqb", CodePoints: []int{91}, Characters: []byte{0x5b}},
1334 "lsquo": {Name: "lsquo", CodePoints: []int{8216}, Characters: []byte{0xe2, 0x80, 0x98}},
1335 "lsquor": {Name: "lsquor", CodePoints: []int{8218}, Characters: []byte{0xe2, 0x80, 0x9a}},
1336 "lstrok": {Name: "lstrok", CodePoints: []int{322}, Characters: []byte{0xc5, 0x82}},
1337 "lt": {Name: "lt", CodePoints: []int{60}, Characters: []byte{0x3c}},
1338 "ltcc": {Name: "ltcc", CodePoints: []int{10918}, Characters: []byte{0xe2, 0xaa, 0xa6}},
1339 "ltcir": {Name: "ltcir", CodePoints: []int{10873}, Characters: []byte{0xe2, 0xa9, 0xb9}},
1340 "ltdot": {Name: "ltdot", CodePoints: []int{8918}, Characters: []byte{0xe2, 0x8b, 0x96}},
1341 "lthree": {Name: "lthree", CodePoints: []int{8907}, Characters: []byte{0xe2, 0x8b, 0x8b}},
1342 "ltimes": {Name: "ltimes", CodePoints: []int{8905}, Characters: []byte{0xe2, 0x8b, 0x89}},
1343 "ltlarr": {Name: "ltlarr", CodePoints: []int{10614}, Characters: []byte{0xe2, 0xa5, 0xb6}},
1344 "ltquest": {Name: "ltquest", CodePoints: []int{10875}, Characters: []byte{0xe2, 0xa9, 0xbb}},
1345 "ltrPar": {Name: "ltrPar", CodePoints: []int{10646}, Characters: []byte{0xe2, 0xa6, 0x96}},
1346 "ltri": {Name: "ltri", CodePoints: []int{9667}, Characters: []byte{0xe2, 0x97, 0x83}},
1347 "ltrie": {Name: "ltrie", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
1348 "ltrif": {Name: "ltrif", CodePoints: []int{9666}, Characters: []byte{0xe2, 0x97, 0x82}},
1349 "lurdshar": {Name: "lurdshar", CodePoints: []int{10570}, Characters: []byte{0xe2, 0xa5, 0x8a}},
1350 "luruhar": {Name: "luruhar", CodePoints: []int{10598}, Characters: []byte{0xe2, 0xa5, 0xa6}},
1351 "lvertneqq": {Name: "lvertneqq", CodePoints: []int{8808, 65024}, Characters: []byte{0xe2, 0x89, 0xa8, 0xef, 0xb8, 0x80}},
1352 "lvnE": {Name: "lvnE", CodePoints: []int{8808, 65024}, Characters: []byte{0xe2, 0x89, 0xa8, 0xef, 0xb8, 0x80}},
1353 "mDDot": {Name: "mDDot", CodePoints: []int{8762}, Characters: []byte{0xe2, 0x88, 0xba}},
1354 "macr": {Name: "macr", CodePoints: []int{175}, Characters: []byte{0xc2, 0xaf}},
1355 "male": {Name: "male", CodePoints: []int{9794}, Characters: []byte{0xe2, 0x99, 0x82}},
1356 "malt": {Name: "malt", CodePoints: []int{10016}, Characters: []byte{0xe2, 0x9c, 0xa0}},
1357 "maltese": {Name: "maltese", CodePoints: []int{10016}, Characters: []byte{0xe2, 0x9c, 0xa0}},
1358 "map": {Name: "map", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
1359 "mapsto": {Name: "mapsto", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
1360 "mapstodown": {Name: "mapstodown", CodePoints: []int{8615}, Characters: []byte{0xe2, 0x86, 0xa7}},
1361 "mapstoleft": {Name: "mapstoleft", CodePoints: []int{8612}, Characters: []byte{0xe2, 0x86, 0xa4}},
1362 "mapstoup": {Name: "mapstoup", CodePoints: []int{8613}, Characters: []byte{0xe2, 0x86, 0xa5}},
1363 "marker": {Name: "marker", CodePoints: []int{9646}, Characters: []byte{0xe2, 0x96, 0xae}},
1364 "mcomma": {Name: "mcomma", CodePoints: []int{10793}, Characters: []byte{0xe2, 0xa8, 0xa9}},
1365 "mcy": {Name: "mcy", CodePoints: []int{1084}, Characters: []byte{0xd0, 0xbc}},
1366 "mdash": {Name: "mdash", CodePoints: []int{8212}, Characters: []byte{0xe2, 0x80, 0x94}},
1367 "measuredangle": {Name: "measuredangle", CodePoints: []int{8737}, Characters: []byte{0xe2, 0x88, 0xa1}},
1368 "mfr": {Name: "mfr", CodePoints: []int{120106}, Characters: []byte{0xf0, 0x9d, 0x94, 0xaa}},
1369 "mho": {Name: "mho", CodePoints: []int{8487}, Characters: []byte{0xe2, 0x84, 0xa7}},
1370 "micro": {Name: "micro", CodePoints: []int{181}, Characters: []byte{0xc2, 0xb5}},
1371 "mid": {Name: "mid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
1372 "midast": {Name: "midast", CodePoints: []int{42}, Characters: []byte{0x2a}},
1373 "midcir": {Name: "midcir", CodePoints: []int{10992}, Characters: []byte{0xe2, 0xab, 0xb0}},
1374 "middot": {Name: "middot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
1375 "minus": {Name: "minus", CodePoints: []int{8722}, Characters: []byte{0xe2, 0x88, 0x92}},
1376 "minusb": {Name: "minusb", CodePoints: []int{8863}, Characters: []byte{0xe2, 0x8a, 0x9f}},
1377 "minusd": {Name: "minusd", CodePoints: []int{8760}, Characters: []byte{0xe2, 0x88, 0xb8}},
1378 "minusdu": {Name: "minusdu", CodePoints: []int{10794}, Characters: []byte{0xe2, 0xa8, 0xaa}},
1379 "mlcp": {Name: "mlcp", CodePoints: []int{10971}, Characters: []byte{0xe2, 0xab, 0x9b}},
1380 "mldr": {Name: "mldr", CodePoints: []int{8230}, Characters: []byte{0xe2, 0x80, 0xa6}},
1381 "mnplus": {Name: "mnplus", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
1382 "models": {Name: "models", CodePoints: []int{8871}, Characters: []byte{0xe2, 0x8a, 0xa7}},
1383 "mopf": {Name: "mopf", CodePoints: []int{120158}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9e}},
1384 "mp": {Name: "mp", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
1385 "mscr": {Name: "mscr", CodePoints: []int{120002}, Characters: []byte{0xf0, 0x9d, 0x93, 0x82}},
1386 "mstpos": {Name: "mstpos", CodePoints: []int{8766}, Characters: []byte{0xe2, 0x88, 0xbe}},
1387 "mu": {Name: "mu", CodePoints: []int{956}, Characters: []byte{0xce, 0xbc}},
1388 "multimap": {Name: "multimap", CodePoints: []int{8888}, Characters: []byte{0xe2, 0x8a, 0xb8}},
1389 "mumap": {Name: "mumap", CodePoints: []int{8888}, Characters: []byte{0xe2, 0x8a, 0xb8}},
1390 "nGg": {Name: "nGg", CodePoints: []int{8921, 824}, Characters: []byte{0xe2, 0x8b, 0x99, 0xcc, 0xb8}},
1391 "nGt": {Name: "nGt", CodePoints: []int{8811, 8402}, Characters: []byte{0xe2, 0x89, 0xab, 0xe2, 0x83, 0x92}},
1392 "nGtv": {Name: "nGtv", CodePoints: []int{8811, 824}, Characters: []byte{0xe2, 0x89, 0xab, 0xcc, 0xb8}},
1393 "nLeftarrow": {Name: "nLeftarrow", CodePoints: []int{8653}, Characters: []byte{0xe2, 0x87, 0x8d}},
1394 "nLeftrightarrow": {Name: "nLeftrightarrow", CodePoints: []int{8654}, Characters: []byte{0xe2, 0x87, 0x8e}},
1395 "nLl": {Name: "nLl", CodePoints: []int{8920, 824}, Characters: []byte{0xe2, 0x8b, 0x98, 0xcc, 0xb8}},
1396 "nLt": {Name: "nLt", CodePoints: []int{8810, 8402}, Characters: []byte{0xe2, 0x89, 0xaa, 0xe2, 0x83, 0x92}},
1397 "nLtv": {Name: "nLtv", CodePoints: []int{8810, 824}, Characters: []byte{0xe2, 0x89, 0xaa, 0xcc, 0xb8}},
1398 "nRightarrow": {Name: "nRightarrow", CodePoints: []int{8655}, Characters: []byte{0xe2, 0x87, 0x8f}},
1399 "nVDash": {Name: "nVDash", CodePoints: []int{8879}, Characters: []byte{0xe2, 0x8a, 0xaf}},
1400 "nVdash": {Name: "nVdash", CodePoints: []int{8878}, Characters: []byte{0xe2, 0x8a, 0xae}},
1401 "nabla": {Name: "nabla", CodePoints: []int{8711}, Characters: []byte{0xe2, 0x88, 0x87}},
1402 "nacute": {Name: "nacute", CodePoints: []int{324}, Characters: []byte{0xc5, 0x84}},
1403 "nang": {Name: "nang", CodePoints: []int{8736, 8402}, Characters: []byte{0xe2, 0x88, 0xa0, 0xe2, 0x83, 0x92}},
1404 "nap": {Name: "nap", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
1405 "napE": {Name: "napE", CodePoints: []int{10864, 824}, Characters: []byte{0xe2, 0xa9, 0xb0, 0xcc, 0xb8}},
1406 "napid": {Name: "napid", CodePoints: []int{8779, 824}, Characters: []byte{0xe2, 0x89, 0x8b, 0xcc, 0xb8}},
1407 "napos": {Name: "napos", CodePoints: []int{329}, Characters: []byte{0xc5, 0x89}},
1408 "napprox": {Name: "napprox", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
1409 "natur": {Name: "natur", CodePoints: []int{9838}, Characters: []byte{0xe2, 0x99, 0xae}},
1410 "natural": {Name: "natural", CodePoints: []int{9838}, Characters: []byte{0xe2, 0x99, 0xae}},
1411 "naturals": {Name: "naturals", CodePoints: []int{8469}, Characters: []byte{0xe2, 0x84, 0x95}},
1412 "nbsp": {Name: "nbsp", CodePoints: []int{160}, Characters: []byte{0xc2, 0xa0}},
1413 "nbump": {Name: "nbump", CodePoints: []int{8782, 824}, Characters: []byte{0xe2, 0x89, 0x8e, 0xcc, 0xb8}},
1414 "nbumpe": {Name: "nbumpe", CodePoints: []int{8783, 824}, Characters: []byte{0xe2, 0x89, 0x8f, 0xcc, 0xb8}},
1415 "ncap": {Name: "ncap", CodePoints: []int{10819}, Characters: []byte{0xe2, 0xa9, 0x83}},
1416 "ncaron": {Name: "ncaron", CodePoints: []int{328}, Characters: []byte{0xc5, 0x88}},
1417 "ncedil": {Name: "ncedil", CodePoints: []int{326}, Characters: []byte{0xc5, 0x86}},
1418 "ncong": {Name: "ncong", CodePoints: []int{8775}, Characters: []byte{0xe2, 0x89, 0x87}},
1419 "ncongdot": {Name: "ncongdot", CodePoints: []int{10861, 824}, Characters: []byte{0xe2, 0xa9, 0xad, 0xcc, 0xb8}},
1420 "ncup": {Name: "ncup", CodePoints: []int{10818}, Characters: []byte{0xe2, 0xa9, 0x82}},
1421 "ncy": {Name: "ncy", CodePoints: []int{1085}, Characters: []byte{0xd0, 0xbd}},
1422 "ndash": {Name: "ndash", CodePoints: []int{8211}, Characters: []byte{0xe2, 0x80, 0x93}},
1423 "ne": {Name: "ne", CodePoints: []int{8800}, Characters: []byte{0xe2, 0x89, 0xa0}},
1424 "neArr": {Name: "neArr", CodePoints: []int{8663}, Characters: []byte{0xe2, 0x87, 0x97}},
1425 "nearhk": {Name: "nearhk", CodePoints: []int{10532}, Characters: []byte{0xe2, 0xa4, 0xa4}},
1426 "nearr": {Name: "nearr", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
1427 "nearrow": {Name: "nearrow", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
1428 "nedot": {Name: "nedot", CodePoints: []int{8784, 824}, Characters: []byte{0xe2, 0x89, 0x90, 0xcc, 0xb8}},
1429 "nequiv": {Name: "nequiv", CodePoints: []int{8802}, Characters: []byte{0xe2, 0x89, 0xa2}},
1430 "nesear": {Name: "nesear", CodePoints: []int{10536}, Characters: []byte{0xe2, 0xa4, 0xa8}},
1431 "nesim": {Name: "nesim", CodePoints: []int{8770, 824}, Characters: []byte{0xe2, 0x89, 0x82, 0xcc, 0xb8}},
1432 "nexist": {Name: "nexist", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
1433 "nexists": {Name: "nexists", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
1434 "nfr": {Name: "nfr", CodePoints: []int{120107}, Characters: []byte{0xf0, 0x9d, 0x94, 0xab}},
1435 "ngE": {Name: "ngE", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
1436 "nge": {Name: "nge", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
1437 "ngeq": {Name: "ngeq", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
1438 "ngeqq": {Name: "ngeqq", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
1439 "ngeqslant": {Name: "ngeqslant", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
1440 "nges": {Name: "nges", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
1441 "ngsim": {Name: "ngsim", CodePoints: []int{8821}, Characters: []byte{0xe2, 0x89, 0xb5}},
1442 "ngt": {Name: "ngt", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
1443 "ngtr": {Name: "ngtr", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
1444 "nhArr": {Name: "nhArr", CodePoints: []int{8654}, Characters: []byte{0xe2, 0x87, 0x8e}},
1445 "nharr": {Name: "nharr", CodePoints: []int{8622}, Characters: []byte{0xe2, 0x86, 0xae}},
1446 "nhpar": {Name: "nhpar", CodePoints: []int{10994}, Characters: []byte{0xe2, 0xab, 0xb2}},
1447 "ni": {Name: "ni", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
1448 "nis": {Name: "nis", CodePoints: []int{8956}, Characters: []byte{0xe2, 0x8b, 0xbc}},
1449 "nisd": {Name: "nisd", CodePoints: []int{8954}, Characters: []byte{0xe2, 0x8b, 0xba}},
1450 "niv": {Name: "niv", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
1451 "njcy": {Name: "njcy", CodePoints: []int{1114}, Characters: []byte{0xd1, 0x9a}},
1452 "nlArr": {Name: "nlArr", CodePoints: []int{8653}, Characters: []byte{0xe2, 0x87, 0x8d}},
1453 "nlE": {Name: "nlE", CodePoints: []int{8806, 824}, Characters: []byte{0xe2, 0x89, 0xa6, 0xcc, 0xb8}},
1454 "nlarr": {Name: "nlarr", CodePoints: []int{8602}, Characters: []byte{0xe2, 0x86, 0x9a}},
1455 "nldr": {Name: "nldr", CodePoints: []int{8229}, Characters: []byte{0xe2, 0x80, 0xa5}},
1456 "nle": {Name: "nle", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
1457 "nleftarrow": {Name: "nleftarrow", CodePoints: []int{8602}, Characters: []byte{0xe2, 0x86, 0x9a}},
1458 "nleftrightarrow": {Name: "nleftrightarrow", CodePoints: []int{8622}, Characters: []byte{0xe2, 0x86, 0xae}},
1459 "nleq": {Name: "nleq", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
1460 "nleqq": {Name: "nleqq", CodePoints: []int{8806, 824}, Characters: []byte{0xe2, 0x89, 0xa6, 0xcc, 0xb8}},
1461 "nleqslant": {Name: "nleqslant", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
1462 "nles": {Name: "nles", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
1463 "nless": {Name: "nless", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
1464 "nlsim": {Name: "nlsim", CodePoints: []int{8820}, Characters: []byte{0xe2, 0x89, 0xb4}},
1465 "nlt": {Name: "nlt", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
1466 "nltri": {Name: "nltri", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
1467 "nltrie": {Name: "nltrie", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
1468 "nmid": {Name: "nmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
1469 "nopf": {Name: "nopf", CodePoints: []int{120159}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9f}},
1470 "not": {Name: "not", CodePoints: []int{172}, Characters: []byte{0xc2, 0xac}},
1471 "notin": {Name: "notin", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
1472 "notinE": {Name: "notinE", CodePoints: []int{8953, 824}, Characters: []byte{0xe2, 0x8b, 0xb9, 0xcc, 0xb8}},
1473 "notindot": {Name: "notindot", CodePoints: []int{8949, 824}, Characters: []byte{0xe2, 0x8b, 0xb5, 0xcc, 0xb8}},
1474 "notinva": {Name: "notinva", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
1475 "notinvb": {Name: "notinvb", CodePoints: []int{8951}, Characters: []byte{0xe2, 0x8b, 0xb7}},
1476 "notinvc": {Name: "notinvc", CodePoints: []int{8950}, Characters: []byte{0xe2, 0x8b, 0xb6}},
1477 "notni": {Name: "notni", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
1478 "notniva": {Name: "notniva", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
1479 "notnivb": {Name: "notnivb", CodePoints: []int{8958}, Characters: []byte{0xe2, 0x8b, 0xbe}},
1480 "notnivc": {Name: "notnivc", CodePoints: []int{8957}, Characters: []byte{0xe2, 0x8b, 0xbd}},
1481 "npar": {Name: "npar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
1482 "nparallel": {Name: "nparallel", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
1483 "nparsl": {Name: "nparsl", CodePoints: []int{11005, 8421}, Characters: []byte{0xe2, 0xab, 0xbd, 0xe2, 0x83, 0xa5}},
1484 "npart": {Name: "npart", CodePoints: []int{8706, 824}, Characters: []byte{0xe2, 0x88, 0x82, 0xcc, 0xb8}},
1485 "npolint": {Name: "npolint", CodePoints: []int{10772}, Characters: []byte{0xe2, 0xa8, 0x94}},
1486 "npr": {Name: "npr", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
1487 "nprcue": {Name: "nprcue", CodePoints: []int{8928}, Characters: []byte{0xe2, 0x8b, 0xa0}},
1488 "npre": {Name: "npre", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
1489 "nprec": {Name: "nprec", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
1490 "npreceq": {Name: "npreceq", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
1491 "nrArr": {Name: "nrArr", CodePoints: []int{8655}, Characters: []byte{0xe2, 0x87, 0x8f}},
1492 "nrarr": {Name: "nrarr", CodePoints: []int{8603}, Characters: []byte{0xe2, 0x86, 0x9b}},
1493 "nrarrc": {Name: "nrarrc", CodePoints: []int{10547, 824}, Characters: []byte{0xe2, 0xa4, 0xb3, 0xcc, 0xb8}},
1494 "nrarrw": {Name: "nrarrw", CodePoints: []int{8605, 824}, Characters: []byte{0xe2, 0x86, 0x9d, 0xcc, 0xb8}},
1495 "nrightarrow": {Name: "nrightarrow", CodePoints: []int{8603}, Characters: []byte{0xe2, 0x86, 0x9b}},
1496 "nrtri": {Name: "nrtri", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
1497 "nrtrie": {Name: "nrtrie", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
1498 "nsc": {Name: "nsc", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
1499 "nsccue": {Name: "nsccue", CodePoints: []int{8929}, Characters: []byte{0xe2, 0x8b, 0xa1}},
1500 "nsce": {Name: "nsce", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
1501 "nscr": {Name: "nscr", CodePoints: []int{120003}, Characters: []byte{0xf0, 0x9d, 0x93, 0x83}},
1502 "nshortmid": {Name: "nshortmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
1503 "nshortparallel": {Name: "nshortparallel", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
1504 "nsim": {Name: "nsim", CodePoints: []int{8769}, Characters: []byte{0xe2, 0x89, 0x81}},
1505 "nsime": {Name: "nsime", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
1506 "nsimeq": {Name: "nsimeq", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
1507 "nsmid": {Name: "nsmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
1508 "nspar": {Name: "nspar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
1509 "nsqsube": {Name: "nsqsube", CodePoints: []int{8930}, Characters: []byte{0xe2, 0x8b, 0xa2}},
1510 "nsqsupe": {Name: "nsqsupe", CodePoints: []int{8931}, Characters: []byte{0xe2, 0x8b, 0xa3}},
1511 "nsub": {Name: "nsub", CodePoints: []int{8836}, Characters: []byte{0xe2, 0x8a, 0x84}},
1512 "nsubE": {Name: "nsubE", CodePoints: []int{10949, 824}, Characters: []byte{0xe2, 0xab, 0x85, 0xcc, 0xb8}},
1513 "nsube": {Name: "nsube", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
1514 "nsubset": {Name: "nsubset", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
1515 "nsubseteq": {Name: "nsubseteq", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
1516 "nsubseteqq": {Name: "nsubseteqq", CodePoints: []int{10949, 824}, Characters: []byte{0xe2, 0xab, 0x85, 0xcc, 0xb8}},
1517 "nsucc": {Name: "nsucc", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
1518 "nsucceq": {Name: "nsucceq", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
1519 "nsup": {Name: "nsup", CodePoints: []int{8837}, Characters: []byte{0xe2, 0x8a, 0x85}},
1520 "nsupE": {Name: "nsupE", CodePoints: []int{10950, 824}, Characters: []byte{0xe2, 0xab, 0x86, 0xcc, 0xb8}},
1521 "nsupe": {Name: "nsupe", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
1522 "nsupset": {Name: "nsupset", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
1523 "nsupseteq": {Name: "nsupseteq", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
1524 "nsupseteqq": {Name: "nsupseteqq", CodePoints: []int{10950, 824}, Characters: []byte{0xe2, 0xab, 0x86, 0xcc, 0xb8}},
1525 "ntgl": {Name: "ntgl", CodePoints: []int{8825}, Characters: []byte{0xe2, 0x89, 0xb9}},
1526 "ntilde": {Name: "ntilde", CodePoints: []int{241}, Characters: []byte{0xc3, 0xb1}},
1527 "ntlg": {Name: "ntlg", CodePoints: []int{8824}, Characters: []byte{0xe2, 0x89, 0xb8}},
1528 "ntriangleleft": {Name: "ntriangleleft", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
1529 "ntrianglelefteq": {Name: "ntrianglelefteq", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
1530 "ntriangleright": {Name: "ntriangleright", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
1531 "ntrianglerighteq": {Name: "ntrianglerighteq", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
1532 "nu": {Name: "nu", CodePoints: []int{957}, Characters: []byte{0xce, 0xbd}},
1533 "num": {Name: "num", CodePoints: []int{35}, Characters: []byte{0x23}},
1534 "numero": {Name: "numero", CodePoints: []int{8470}, Characters: []byte{0xe2, 0x84, 0x96}},
1535 "numsp": {Name: "numsp", CodePoints: []int{8199}, Characters: []byte{0xe2, 0x80, 0x87}},
1536 "nvDash": {Name: "nvDash", CodePoints: []int{8877}, Characters: []byte{0xe2, 0x8a, 0xad}},
1537 "nvHarr": {Name: "nvHarr", CodePoints: []int{10500}, Characters: []byte{0xe2, 0xa4, 0x84}},
1538 "nvap": {Name: "nvap", CodePoints: []int{8781, 8402}, Characters: []byte{0xe2, 0x89, 0x8d, 0xe2, 0x83, 0x92}},
1539 "nvdash": {Name: "nvdash", CodePoints: []int{8876}, Characters: []byte{0xe2, 0x8a, 0xac}},
1540 "nvge": {Name: "nvge", CodePoints: []int{8805, 8402}, Characters: []byte{0xe2, 0x89, 0xa5, 0xe2, 0x83, 0x92}},
1541 "nvgt": {Name: "nvgt", CodePoints: []int{62, 8402}, Characters: []byte{0x3e, 0xe2, 0x83, 0x92}},
1542 "nvinfin": {Name: "nvinfin", CodePoints: []int{10718}, Characters: []byte{0xe2, 0xa7, 0x9e}},
1543 "nvlArr": {Name: "nvlArr", CodePoints: []int{10498}, Characters: []byte{0xe2, 0xa4, 0x82}},
1544 "nvle": {Name: "nvle", CodePoints: []int{8804, 8402}, Characters: []byte{0xe2, 0x89, 0xa4, 0xe2, 0x83, 0x92}},
1545 "nvlt": {Name: "nvlt", CodePoints: []int{60, 8402}, Characters: []byte{0x3c, 0xe2, 0x83, 0x92}},
1546 "nvltrie": {Name: "nvltrie", CodePoints: []int{8884, 8402}, Characters: []byte{0xe2, 0x8a, 0xb4, 0xe2, 0x83, 0x92}},
1547 "nvrArr": {Name: "nvrArr", CodePoints: []int{10499}, Characters: []byte{0xe2, 0xa4, 0x83}},
1548 "nvrtrie": {Name: "nvrtrie", CodePoints: []int{8885, 8402}, Characters: []byte{0xe2, 0x8a, 0xb5, 0xe2, 0x83, 0x92}},
1549 "nvsim": {Name: "nvsim", CodePoints: []int{8764, 8402}, Characters: []byte{0xe2, 0x88, 0xbc, 0xe2, 0x83, 0x92}},
1550 "nwArr": {Name: "nwArr", CodePoints: []int{8662}, Characters: []byte{0xe2, 0x87, 0x96}},
1551 "nwarhk": {Name: "nwarhk", CodePoints: []int{10531}, Characters: []byte{0xe2, 0xa4, 0xa3}},
1552 "nwarr": {Name: "nwarr", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
1553 "nwarrow": {Name: "nwarrow", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
1554 "nwnear": {Name: "nwnear", CodePoints: []int{10535}, Characters: []byte{0xe2, 0xa4, 0xa7}},
1555 "oS": {Name: "oS", CodePoints: []int{9416}, Characters: []byte{0xe2, 0x93, 0x88}},
1556 "oacute": {Name: "oacute", CodePoints: []int{243}, Characters: []byte{0xc3, 0xb3}},
1557 "oast": {Name: "oast", CodePoints: []int{8859}, Characters: []byte{0xe2, 0x8a, 0x9b}},
1558 "ocir": {Name: "ocir", CodePoints: []int{8858}, Characters: []byte{0xe2, 0x8a, 0x9a}},
1559 "ocirc": {Name: "ocirc", CodePoints: []int{244}, Characters: []byte{0xc3, 0xb4}},
1560 "ocy": {Name: "ocy", CodePoints: []int{1086}, Characters: []byte{0xd0, 0xbe}},
1561 "odash": {Name: "odash", CodePoints: []int{8861}, Characters: []byte{0xe2, 0x8a, 0x9d}},
1562 "odblac": {Name: "odblac", CodePoints: []int{337}, Characters: []byte{0xc5, 0x91}},
1563 "odiv": {Name: "odiv", CodePoints: []int{10808}, Characters: []byte{0xe2, 0xa8, 0xb8}},
1564 "odot": {Name: "odot", CodePoints: []int{8857}, Characters: []byte{0xe2, 0x8a, 0x99}},
1565 "odsold": {Name: "odsold", CodePoints: []int{10684}, Characters: []byte{0xe2, 0xa6, 0xbc}},
1566 "oelig": {Name: "oelig", CodePoints: []int{339}, Characters: []byte{0xc5, 0x93}},
1567 "ofcir": {Name: "ofcir", CodePoints: []int{10687}, Characters: []byte{0xe2, 0xa6, 0xbf}},
1568 "ofr": {Name: "ofr", CodePoints: []int{120108}, Characters: []byte{0xf0, 0x9d, 0x94, 0xac}},
1569 "ogon": {Name: "ogon", CodePoints: []int{731}, Characters: []byte{0xcb, 0x9b}},
1570 "ograve": {Name: "ograve", CodePoints: []int{242}, Characters: []byte{0xc3, 0xb2}},
1571 "ogt": {Name: "ogt", CodePoints: []int{10689}, Characters: []byte{0xe2, 0xa7, 0x81}},
1572 "ohbar": {Name: "ohbar", CodePoints: []int{10677}, Characters: []byte{0xe2, 0xa6, 0xb5}},
1573 "ohm": {Name: "ohm", CodePoints: []int{937}, Characters: []byte{0xce, 0xa9}},
1574 "oint": {Name: "oint", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
1575 "olarr": {Name: "olarr", CodePoints: []int{8634}, Characters: []byte{0xe2, 0x86, 0xba}},
1576 "olcir": {Name: "olcir", CodePoints: []int{10686}, Characters: []byte{0xe2, 0xa6, 0xbe}},
1577 "olcross": {Name: "olcross", CodePoints: []int{10683}, Characters: []byte{0xe2, 0xa6, 0xbb}},
1578 "oline": {Name: "oline", CodePoints: []int{8254}, Characters: []byte{0xe2, 0x80, 0xbe}},
1579 "olt": {Name: "olt", CodePoints: []int{10688}, Characters: []byte{0xe2, 0xa7, 0x80}},
1580 "omacr": {Name: "omacr", CodePoints: []int{333}, Characters: []byte{0xc5, 0x8d}},
1581 "omega": {Name: "omega", CodePoints: []int{969}, Characters: []byte{0xcf, 0x89}},
1582 "omicron": {Name: "omicron", CodePoints: []int{959}, Characters: []byte{0xce, 0xbf}},
1583 "omid": {Name: "omid", CodePoints: []int{10678}, Characters: []byte{0xe2, 0xa6, 0xb6}},
1584 "ominus": {Name: "ominus", CodePoints: []int{8854}, Characters: []byte{0xe2, 0x8a, 0x96}},
1585 "oopf": {Name: "oopf", CodePoints: []int{120160}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa0}},
1586 "opar": {Name: "opar", CodePoints: []int{10679}, Characters: []byte{0xe2, 0xa6, 0xb7}},
1587 "operp": {Name: "operp", CodePoints: []int{10681}, Characters: []byte{0xe2, 0xa6, 0xb9}},
1588 "oplus": {Name: "oplus", CodePoints: []int{8853}, Characters: []byte{0xe2, 0x8a, 0x95}},
1589 "or": {Name: "or", CodePoints: []int{8744}, Characters: []byte{0xe2, 0x88, 0xa8}},
1590 "orarr": {Name: "orarr", CodePoints: []int{8635}, Characters: []byte{0xe2, 0x86, 0xbb}},
1591 "ord": {Name: "ord", CodePoints: []int{10845}, Characters: []byte{0xe2, 0xa9, 0x9d}},
1592 "order": {Name: "order", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
1593 "orderof": {Name: "orderof", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
1594 "ordf": {Name: "ordf", CodePoints: []int{170}, Characters: []byte{0xc2, 0xaa}},
1595 "ordm": {Name: "ordm", CodePoints: []int{186}, Characters: []byte{0xc2, 0xba}},
1596 "origof": {Name: "origof", CodePoints: []int{8886}, Characters: []byte{0xe2, 0x8a, 0xb6}},
1597 "oror": {Name: "oror", CodePoints: []int{10838}, Characters: []byte{0xe2, 0xa9, 0x96}},
1598 "orslope": {Name: "orslope", CodePoints: []int{10839}, Characters: []byte{0xe2, 0xa9, 0x97}},
1599 "orv": {Name: "orv", CodePoints: []int{10843}, Characters: []byte{0xe2, 0xa9, 0x9b}},
1600 "oscr": {Name: "oscr", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
1601 "oslash": {Name: "oslash", CodePoints: []int{248}, Characters: []byte{0xc3, 0xb8}},
1602 "osol": {Name: "osol", CodePoints: []int{8856}, Characters: []byte{0xe2, 0x8a, 0x98}},
1603 "otilde": {Name: "otilde", CodePoints: []int{245}, Characters: []byte{0xc3, 0xb5}},
1604 "otimes": {Name: "otimes", CodePoints: []int{8855}, Characters: []byte{0xe2, 0x8a, 0x97}},
1605 "otimesas": {Name: "otimesas", CodePoints: []int{10806}, Characters: []byte{0xe2, 0xa8, 0xb6}},
1606 "ouml": {Name: "ouml", CodePoints: []int{246}, Characters: []byte{0xc3, 0xb6}},
1607 "ovbar": {Name: "ovbar", CodePoints: []int{9021}, Characters: []byte{0xe2, 0x8c, 0xbd}},
1608 "par": {Name: "par", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
1609 "para": {Name: "para", CodePoints: []int{182}, Characters: []byte{0xc2, 0xb6}},
1610 "parallel": {Name: "parallel", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
1611 "parsim": {Name: "parsim", CodePoints: []int{10995}, Characters: []byte{0xe2, 0xab, 0xb3}},
1612 "parsl": {Name: "parsl", CodePoints: []int{11005}, Characters: []byte{0xe2, 0xab, 0xbd}},
1613 "part": {Name: "part", CodePoints: []int{8706}, Characters: []byte{0xe2, 0x88, 0x82}},
1614 "pcy": {Name: "pcy", CodePoints: []int{1087}, Characters: []byte{0xd0, 0xbf}},
1615 "percnt": {Name: "percnt", CodePoints: []int{37}, Characters: []byte{0x25}},
1616 "period": {Name: "period", CodePoints: []int{46}, Characters: []byte{0x2e}},
1617 "permil": {Name: "permil", CodePoints: []int{8240}, Characters: []byte{0xe2, 0x80, 0xb0}},
1618 "perp": {Name: "perp", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
1619 "pertenk": {Name: "pertenk", CodePoints: []int{8241}, Characters: []byte{0xe2, 0x80, 0xb1}},
1620 "pfr": {Name: "pfr", CodePoints: []int{120109}, Characters: []byte{0xf0, 0x9d, 0x94, 0xad}},
1621 "phi": {Name: "phi", CodePoints: []int{966}, Characters: []byte{0xcf, 0x86}},
1622 "phiv": {Name: "phiv", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
1623 "phmmat": {Name: "phmmat", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
1624 "phone": {Name: "phone", CodePoints: []int{9742}, Characters: []byte{0xe2, 0x98, 0x8e}},
1625 "pi": {Name: "pi", CodePoints: []int{960}, Characters: []byte{0xcf, 0x80}},
1626 "pitchfork": {Name: "pitchfork", CodePoints: []int{8916}, Characters: []byte{0xe2, 0x8b, 0x94}},
1627 "piv": {Name: "piv", CodePoints: []int{982}, Characters: []byte{0xcf, 0x96}},
1628 "planck": {Name: "planck", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
1629 "planckh": {Name: "planckh", CodePoints: []int{8462}, Characters: []byte{0xe2, 0x84, 0x8e}},
1630 "plankv": {Name: "plankv", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
1631 "plus": {Name: "plus", CodePoints: []int{43}, Characters: []byte{0x2b}},
1632 "plusacir": {Name: "plusacir", CodePoints: []int{10787}, Characters: []byte{0xe2, 0xa8, 0xa3}},
1633 "plusb": {Name: "plusb", CodePoints: []int{8862}, Characters: []byte{0xe2, 0x8a, 0x9e}},
1634 "pluscir": {Name: "pluscir", CodePoints: []int{10786}, Characters: []byte{0xe2, 0xa8, 0xa2}},
1635 "plusdo": {Name: "plusdo", CodePoints: []int{8724}, Characters: []byte{0xe2, 0x88, 0x94}},
1636 "plusdu": {Name: "plusdu", CodePoints: []int{10789}, Characters: []byte{0xe2, 0xa8, 0xa5}},
1637 "pluse": {Name: "pluse", CodePoints: []int{10866}, Characters: []byte{0xe2, 0xa9, 0xb2}},
1638 "plusmn": {Name: "plusmn", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
1639 "plussim": {Name: "plussim", CodePoints: []int{10790}, Characters: []byte{0xe2, 0xa8, 0xa6}},
1640 "plustwo": {Name: "plustwo", CodePoints: []int{10791}, Characters: []byte{0xe2, 0xa8, 0xa7}},
1641 "pm": {Name: "pm", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
1642 "pointint": {Name: "pointint", CodePoints: []int{10773}, Characters: []byte{0xe2, 0xa8, 0x95}},
1643 "popf": {Name: "popf", CodePoints: []int{120161}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa1}},
1644 "pound": {Name: "pound", CodePoints: []int{163}, Characters: []byte{0xc2, 0xa3}},
1645 "pr": {Name: "pr", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
1646 "prE": {Name: "prE", CodePoints: []int{10931}, Characters: []byte{0xe2, 0xaa, 0xb3}},
1647 "prap": {Name: "prap", CodePoints: []int{10935}, Characters: []byte{0xe2, 0xaa, 0xb7}},
1648 "prcue": {Name: "prcue", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
1649 "pre": {Name: "pre", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
1650 "prec": {Name: "prec", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
1651 "precapprox": {Name: "precapprox", CodePoints: []int{10935}, Characters: []byte{0xe2, 0xaa, 0xb7}},
1652 "preccurlyeq": {Name: "preccurlyeq", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
1653 "preceq": {Name: "preceq", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
1654 "precnapprox": {Name: "precnapprox", CodePoints: []int{10937}, Characters: []byte{0xe2, 0xaa, 0xb9}},
1655 "precneqq": {Name: "precneqq", CodePoints: []int{10933}, Characters: []byte{0xe2, 0xaa, 0xb5}},
1656 "precnsim": {Name: "precnsim", CodePoints: []int{8936}, Characters: []byte{0xe2, 0x8b, 0xa8}},
1657 "precsim": {Name: "precsim", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
1658 "prime": {Name: "prime", CodePoints: []int{8242}, Characters: []byte{0xe2, 0x80, 0xb2}},
1659 "primes": {Name: "primes", CodePoints: []int{8473}, Characters: []byte{0xe2, 0x84, 0x99}},
1660 "prnE": {Name: "prnE", CodePoints: []int{10933}, Characters: []byte{0xe2, 0xaa, 0xb5}},
1661 "prnap": {Name: "prnap", CodePoints: []int{10937}, Characters: []byte{0xe2, 0xaa, 0xb9}},
1662 "prnsim": {Name: "prnsim", CodePoints: []int{8936}, Characters: []byte{0xe2, 0x8b, 0xa8}},
1663 "prod": {Name: "prod", CodePoints: []int{8719}, Characters: []byte{0xe2, 0x88, 0x8f}},
1664 "profalar": {Name: "profalar", CodePoints: []int{9006}, Characters: []byte{0xe2, 0x8c, 0xae}},
1665 "profline": {Name: "profline", CodePoints: []int{8978}, Characters: []byte{0xe2, 0x8c, 0x92}},
1666 "profsurf": {Name: "profsurf", CodePoints: []int{8979}, Characters: []byte{0xe2, 0x8c, 0x93}},
1667 "prop": {Name: "prop", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
1668 "propto": {Name: "propto", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
1669 "prsim": {Name: "prsim", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
1670 "prurel": {Name: "prurel", CodePoints: []int{8880}, Characters: []byte{0xe2, 0x8a, 0xb0}},
1671 "pscr": {Name: "pscr", CodePoints: []int{120005}, Characters: []byte{0xf0, 0x9d, 0x93, 0x85}},
1672 "psi": {Name: "psi", CodePoints: []int{968}, Characters: []byte{0xcf, 0x88}},
1673 "puncsp": {Name: "puncsp", CodePoints: []int{8200}, Characters: []byte{0xe2, 0x80, 0x88}},
1674 "qfr": {Name: "qfr", CodePoints: []int{120110}, Characters: []byte{0xf0, 0x9d, 0x94, 0xae}},
1675 "qint": {Name: "qint", CodePoints: []int{10764}, Characters: []byte{0xe2, 0xa8, 0x8c}},
1676 "qopf": {Name: "qopf", CodePoints: []int{120162}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa2}},
1677 "qprime": {Name: "qprime", CodePoints: []int{8279}, Characters: []byte{0xe2, 0x81, 0x97}},
1678 "qscr": {Name: "qscr", CodePoints: []int{120006}, Characters: []byte{0xf0, 0x9d, 0x93, 0x86}},
1679 "quaternions": {Name: "quaternions", CodePoints: []int{8461}, Characters: []byte{0xe2, 0x84, 0x8d}},
1680 "quatint": {Name: "quatint", CodePoints: []int{10774}, Characters: []byte{0xe2, 0xa8, 0x96}},
1681 "quest": {Name: "quest", CodePoints: []int{63}, Characters: []byte{0x3f}},
1682 "questeq": {Name: "questeq", CodePoints: []int{8799}, Characters: []byte{0xe2, 0x89, 0x9f}},
1683 "quot": {Name: "quot", CodePoints: []int{34}, Characters: []byte{0x22}},
1684 "rAarr": {Name: "rAarr", CodePoints: []int{8667}, Characters: []byte{0xe2, 0x87, 0x9b}},
1685 "rArr": {Name: "rArr", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
1686 "rAtail": {Name: "rAtail", CodePoints: []int{10524}, Characters: []byte{0xe2, 0xa4, 0x9c}},
1687 "rBarr": {Name: "rBarr", CodePoints: []int{10511}, Characters: []byte{0xe2, 0xa4, 0x8f}},
1688 "rHar": {Name: "rHar", CodePoints: []int{10596}, Characters: []byte{0xe2, 0xa5, 0xa4}},
1689 "race": {Name: "race", CodePoints: []int{8765, 817}, Characters: []byte{0xe2, 0x88, 0xbd, 0xcc, 0xb1}},
1690 "racute": {Name: "racute", CodePoints: []int{341}, Characters: []byte{0xc5, 0x95}},
1691 "radic": {Name: "radic", CodePoints: []int{8730}, Characters: []byte{0xe2, 0x88, 0x9a}},
1692 "raemptyv": {Name: "raemptyv", CodePoints: []int{10675}, Characters: []byte{0xe2, 0xa6, 0xb3}},
1693 "rang": {Name: "rang", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
1694 "rangd": {Name: "rangd", CodePoints: []int{10642}, Characters: []byte{0xe2, 0xa6, 0x92}},
1695 "range": {Name: "range", CodePoints: []int{10661}, Characters: []byte{0xe2, 0xa6, 0xa5}},
1696 "rangle": {Name: "rangle", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
1697 "raquo": {Name: "raquo", CodePoints: []int{187}, Characters: []byte{0xc2, 0xbb}},
1698 "rarr": {Name: "rarr", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
1699 "rarrap": {Name: "rarrap", CodePoints: []int{10613}, Characters: []byte{0xe2, 0xa5, 0xb5}},
1700 "rarrb": {Name: "rarrb", CodePoints: []int{8677}, Characters: []byte{0xe2, 0x87, 0xa5}},
1701 "rarrbfs": {Name: "rarrbfs", CodePoints: []int{10528}, Characters: []byte{0xe2, 0xa4, 0xa0}},
1702 "rarrc": {Name: "rarrc", CodePoints: []int{10547}, Characters: []byte{0xe2, 0xa4, 0xb3}},
1703 "rarrfs": {Name: "rarrfs", CodePoints: []int{10526}, Characters: []byte{0xe2, 0xa4, 0x9e}},
1704 "rarrhk": {Name: "rarrhk", CodePoints: []int{8618}, Characters: []byte{0xe2, 0x86, 0xaa}},
1705 "rarrlp": {Name: "rarrlp", CodePoints: []int{8620}, Characters: []byte{0xe2, 0x86, 0xac}},
1706 "rarrpl": {Name: "rarrpl", CodePoints: []int{10565}, Characters: []byte{0xe2, 0xa5, 0x85}},
1707 "rarrsim": {Name: "rarrsim", CodePoints: []int{10612}, Characters: []byte{0xe2, 0xa5, 0xb4}},
1708 "rarrtl": {Name: "rarrtl", CodePoints: []int{8611}, Characters: []byte{0xe2, 0x86, 0xa3}},
1709 "rarrw": {Name: "rarrw", CodePoints: []int{8605}, Characters: []byte{0xe2, 0x86, 0x9d}},
1710 "ratail": {Name: "ratail", CodePoints: []int{10522}, Characters: []byte{0xe2, 0xa4, 0x9a}},
1711 "ratio": {Name: "ratio", CodePoints: []int{8758}, Characters: []byte{0xe2, 0x88, 0xb6}},
1712 "rationals": {Name: "rationals", CodePoints: []int{8474}, Characters: []byte{0xe2, 0x84, 0x9a}},
1713 "rbarr": {Name: "rbarr", CodePoints: []int{10509}, Characters: []byte{0xe2, 0xa4, 0x8d}},
1714 "rbbrk": {Name: "rbbrk", CodePoints: []int{10099}, Characters: []byte{0xe2, 0x9d, 0xb3}},
1715 "rbrace": {Name: "rbrace", CodePoints: []int{125}, Characters: []byte{0x7d}},
1716 "rbrack": {Name: "rbrack", CodePoints: []int{93}, Characters: []byte{0x5d}},
1717 "rbrke": {Name: "rbrke", CodePoints: []int{10636}, Characters: []byte{0xe2, 0xa6, 0x8c}},
1718 "rbrksld": {Name: "rbrksld", CodePoints: []int{10638}, Characters: []byte{0xe2, 0xa6, 0x8e}},
1719 "rbrkslu": {Name: "rbrkslu", CodePoints: []int{10640}, Characters: []byte{0xe2, 0xa6, 0x90}},
1720 "rcaron": {Name: "rcaron", CodePoints: []int{345}, Characters: []byte{0xc5, 0x99}},
1721 "rcedil": {Name: "rcedil", CodePoints: []int{343}, Characters: []byte{0xc5, 0x97}},
1722 "rceil": {Name: "rceil", CodePoints: []int{8969}, Characters: []byte{0xe2, 0x8c, 0x89}},
1723 "rcub": {Name: "rcub", CodePoints: []int{125}, Characters: []byte{0x7d}},
1724 "rcy": {Name: "rcy", CodePoints: []int{1088}, Characters: []byte{0xd1, 0x80}},
1725 "rdca": {Name: "rdca", CodePoints: []int{10551}, Characters: []byte{0xe2, 0xa4, 0xb7}},
1726 "rdldhar": {Name: "rdldhar", CodePoints: []int{10601}, Characters: []byte{0xe2, 0xa5, 0xa9}},
1727 "rdquo": {Name: "rdquo", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
1728 "rdquor": {Name: "rdquor", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
1729 "rdsh": {Name: "rdsh", CodePoints: []int{8627}, Characters: []byte{0xe2, 0x86, 0xb3}},
1730 "real": {Name: "real", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
1731 "realine": {Name: "realine", CodePoints: []int{8475}, Characters: []byte{0xe2, 0x84, 0x9b}},
1732 "realpart": {Name: "realpart", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
1733 "reals": {Name: "reals", CodePoints: []int{8477}, Characters: []byte{0xe2, 0x84, 0x9d}},
1734 "rect": {Name: "rect", CodePoints: []int{9645}, Characters: []byte{0xe2, 0x96, 0xad}},
1735 "reg": {Name: "reg", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
1736 "rfisht": {Name: "rfisht", CodePoints: []int{10621}, Characters: []byte{0xe2, 0xa5, 0xbd}},
1737 "rfloor": {Name: "rfloor", CodePoints: []int{8971}, Characters: []byte{0xe2, 0x8c, 0x8b}},
1738 "rfr": {Name: "rfr", CodePoints: []int{120111}, Characters: []byte{0xf0, 0x9d, 0x94, 0xaf}},
1739 "rhard": {Name: "rhard", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
1740 "rharu": {Name: "rharu", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
1741 "rharul": {Name: "rharul", CodePoints: []int{10604}, Characters: []byte{0xe2, 0xa5, 0xac}},
1742 "rho": {Name: "rho", CodePoints: []int{961}, Characters: []byte{0xcf, 0x81}},
1743 "rhov": {Name: "rhov", CodePoints: []int{1009}, Characters: []byte{0xcf, 0xb1}},
1744 "rightarrow": {Name: "rightarrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
1745 "rightarrowtail": {Name: "rightarrowtail", CodePoints: []int{8611}, Characters: []byte{0xe2, 0x86, 0xa3}},
1746 "rightharpoondown": {Name: "rightharpoondown", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
1747 "rightharpoonup": {Name: "rightharpoonup", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
1748 "rightleftarrows": {Name: "rightleftarrows", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
1749 "rightleftharpoons": {Name: "rightleftharpoons", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
1750 "rightrightarrows": {Name: "rightrightarrows", CodePoints: []int{8649}, Characters: []byte{0xe2, 0x87, 0x89}},
1751 "rightsquigarrow": {Name: "rightsquigarrow", CodePoints: []int{8605}, Characters: []byte{0xe2, 0x86, 0x9d}},
1752 "rightthreetimes": {Name: "rightthreetimes", CodePoints: []int{8908}, Characters: []byte{0xe2, 0x8b, 0x8c}},
1753 "ring": {Name: "ring", CodePoints: []int{730}, Characters: []byte{0xcb, 0x9a}},
1754 "risingdotseq": {Name: "risingdotseq", CodePoints: []int{8787}, Characters: []byte{0xe2, 0x89, 0x93}},
1755 "rlarr": {Name: "rlarr", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
1756 "rlhar": {Name: "rlhar", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
1757 "rlm": {Name: "rlm", CodePoints: []int{8207}, Characters: []byte{0xe2, 0x80, 0x8f}},
1758 "rmoust": {Name: "rmoust", CodePoints: []int{9137}, Characters: []byte{0xe2, 0x8e, 0xb1}},
1759 "rmoustache": {Name: "rmoustache", CodePoints: []int{9137}, Characters: []byte{0xe2, 0x8e, 0xb1}},
1760 "rnmid": {Name: "rnmid", CodePoints: []int{10990}, Characters: []byte{0xe2, 0xab, 0xae}},
1761 "roang": {Name: "roang", CodePoints: []int{10221}, Characters: []byte{0xe2, 0x9f, 0xad}},
1762 "roarr": {Name: "roarr", CodePoints: []int{8702}, Characters: []byte{0xe2, 0x87, 0xbe}},
1763 "robrk": {Name: "robrk", CodePoints: []int{10215}, Characters: []byte{0xe2, 0x9f, 0xa7}},
1764 "ropar": {Name: "ropar", CodePoints: []int{10630}, Characters: []byte{0xe2, 0xa6, 0x86}},
1765 "ropf": {Name: "ropf", CodePoints: []int{120163}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa3}},
1766 "roplus": {Name: "roplus", CodePoints: []int{10798}, Characters: []byte{0xe2, 0xa8, 0xae}},
1767 "rotimes": {Name: "rotimes", CodePoints: []int{10805}, Characters: []byte{0xe2, 0xa8, 0xb5}},
1768 "rpar": {Name: "rpar", CodePoints: []int{41}, Characters: []byte{0x29}},
1769 "rpargt": {Name: "rpargt", CodePoints: []int{10644}, Characters: []byte{0xe2, 0xa6, 0x94}},
1770 "rppolint": {Name: "rppolint", CodePoints: []int{10770}, Characters: []byte{0xe2, 0xa8, 0x92}},
1771 "rrarr": {Name: "rrarr", CodePoints: []int{8649}, Characters: []byte{0xe2, 0x87, 0x89}},
1772 "rsaquo": {Name: "rsaquo", CodePoints: []int{8250}, Characters: []byte{0xe2, 0x80, 0xba}},
1773 "rscr": {Name: "rscr", CodePoints: []int{120007}, Characters: []byte{0xf0, 0x9d, 0x93, 0x87}},
1774 "rsh": {Name: "rsh", CodePoints: []int{8625}, Characters: []byte{0xe2, 0x86, 0xb1}},
1775 "rsqb": {Name: "rsqb", CodePoints: []int{93}, Characters: []byte{0x5d}},
1776 "rsquo": {Name: "rsquo", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
1777 "rsquor": {Name: "rsquor", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
1778 "rthree": {Name: "rthree", CodePoints: []int{8908}, Characters: []byte{0xe2, 0x8b, 0x8c}},
1779 "rtimes": {Name: "rtimes", CodePoints: []int{8906}, Characters: []byte{0xe2, 0x8b, 0x8a}},
1780 "rtri": {Name: "rtri", CodePoints: []int{9657}, Characters: []byte{0xe2, 0x96, 0xb9}},
1781 "rtrie": {Name: "rtrie", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
1782 "rtrif": {Name: "rtrif", CodePoints: []int{9656}, Characters: []byte{0xe2, 0x96, 0xb8}},
1783 "rtriltri": {Name: "rtriltri", CodePoints: []int{10702}, Characters: []byte{0xe2, 0xa7, 0x8e}},
1784 "ruluhar": {Name: "ruluhar", CodePoints: []int{10600}, Characters: []byte{0xe2, 0xa5, 0xa8}},
1785 "rx": {Name: "rx", CodePoints: []int{8478}, Characters: []byte{0xe2, 0x84, 0x9e}},
1786 "sacute": {Name: "sacute", CodePoints: []int{347}, Characters: []byte{0xc5, 0x9b}},
1787 "sbquo": {Name: "sbquo", CodePoints: []int{8218}, Characters: []byte{0xe2, 0x80, 0x9a}},
1788 "sc": {Name: "sc", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
1789 "scE": {Name: "scE", CodePoints: []int{10932}, Characters: []byte{0xe2, 0xaa, 0xb4}},
1790 "scap": {Name: "scap", CodePoints: []int{10936}, Characters: []byte{0xe2, 0xaa, 0xb8}},
1791 "scaron": {Name: "scaron", CodePoints: []int{353}, Characters: []byte{0xc5, 0xa1}},
1792 "sccue": {Name: "sccue", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
1793 "sce": {Name: "sce", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
1794 "scedil": {Name: "scedil", CodePoints: []int{351}, Characters: []byte{0xc5, 0x9f}},
1795 "scirc": {Name: "scirc", CodePoints: []int{349}, Characters: []byte{0xc5, 0x9d}},
1796 "scnE": {Name: "scnE", CodePoints: []int{10934}, Characters: []byte{0xe2, 0xaa, 0xb6}},
1797 "scnap": {Name: "scnap", CodePoints: []int{10938}, Characters: []byte{0xe2, 0xaa, 0xba}},
1798 "scnsim": {Name: "scnsim", CodePoints: []int{8937}, Characters: []byte{0xe2, 0x8b, 0xa9}},
1799 "scpolint": {Name: "scpolint", CodePoints: []int{10771}, Characters: []byte{0xe2, 0xa8, 0x93}},
1800 "scsim": {Name: "scsim", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
1801 "scy": {Name: "scy", CodePoints: []int{1089}, Characters: []byte{0xd1, 0x81}},
1802 "sdot": {Name: "sdot", CodePoints: []int{8901}, Characters: []byte{0xe2, 0x8b, 0x85}},
1803 "sdotb": {Name: "sdotb", CodePoints: []int{8865}, Characters: []byte{0xe2, 0x8a, 0xa1}},
1804 "sdote": {Name: "sdote", CodePoints: []int{10854}, Characters: []byte{0xe2, 0xa9, 0xa6}},
1805 "seArr": {Name: "seArr", CodePoints: []int{8664}, Characters: []byte{0xe2, 0x87, 0x98}},
1806 "searhk": {Name: "searhk", CodePoints: []int{10533}, Characters: []byte{0xe2, 0xa4, 0xa5}},
1807 "searr": {Name: "searr", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
1808 "searrow": {Name: "searrow", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
1809 "sect": {Name: "sect", CodePoints: []int{167}, Characters: []byte{0xc2, 0xa7}},
1810 "semi": {Name: "semi", CodePoints: []int{59}, Characters: []byte{0x3b}},
1811 "seswar": {Name: "seswar", CodePoints: []int{10537}, Characters: []byte{0xe2, 0xa4, 0xa9}},
1812 "setminus": {Name: "setminus", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
1813 "setmn": {Name: "setmn", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
1814 "sext": {Name: "sext", CodePoints: []int{10038}, Characters: []byte{0xe2, 0x9c, 0xb6}},
1815 "sfr": {Name: "sfr", CodePoints: []int{120112}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb0}},
1816 "sfrown": {Name: "sfrown", CodePoints: []int{8994}, Characters: []byte{0xe2, 0x8c, 0xa2}},
1817 "sharp": {Name: "sharp", CodePoints: []int{9839}, Characters: []byte{0xe2, 0x99, 0xaf}},
1818 "shchcy": {Name: "shchcy", CodePoints: []int{1097}, Characters: []byte{0xd1, 0x89}},
1819 "shcy": {Name: "shcy", CodePoints: []int{1096}, Characters: []byte{0xd1, 0x88}},
1820 "shortmid": {Name: "shortmid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
1821 "shortparallel": {Name: "shortparallel", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
1822 "shy": {Name: "shy", CodePoints: []int{173}, Characters: []byte{0xc2, 0xad}},
1823 "sigma": {Name: "sigma", CodePoints: []int{963}, Characters: []byte{0xcf, 0x83}},
1824 "sigmaf": {Name: "sigmaf", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
1825 "sigmav": {Name: "sigmav", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
1826 "sim": {Name: "sim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
1827 "simdot": {Name: "simdot", CodePoints: []int{10858}, Characters: []byte{0xe2, 0xa9, 0xaa}},
1828 "sime": {Name: "sime", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
1829 "simeq": {Name: "simeq", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
1830 "simg": {Name: "simg", CodePoints: []int{10910}, Characters: []byte{0xe2, 0xaa, 0x9e}},
1831 "simgE": {Name: "simgE", CodePoints: []int{10912}, Characters: []byte{0xe2, 0xaa, 0xa0}},
1832 "siml": {Name: "siml", CodePoints: []int{10909}, Characters: []byte{0xe2, 0xaa, 0x9d}},
1833 "simlE": {Name: "simlE", CodePoints: []int{10911}, Characters: []byte{0xe2, 0xaa, 0x9f}},
1834 "simne": {Name: "simne", CodePoints: []int{8774}, Characters: []byte{0xe2, 0x89, 0x86}},
1835 "simplus": {Name: "simplus", CodePoints: []int{10788}, Characters: []byte{0xe2, 0xa8, 0xa4}},
1836 "simrarr": {Name: "simrarr", CodePoints: []int{10610}, Characters: []byte{0xe2, 0xa5, 0xb2}},
1837 "slarr": {Name: "slarr", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
1838 "smallsetminus": {Name: "smallsetminus", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
1839 "smashp": {Name: "smashp", CodePoints: []int{10803}, Characters: []byte{0xe2, 0xa8, 0xb3}},
1840 "smeparsl": {Name: "smeparsl", CodePoints: []int{10724}, Characters: []byte{0xe2, 0xa7, 0xa4}},
1841 "smid": {Name: "smid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
1842 "smile": {Name: "smile", CodePoints: []int{8995}, Characters: []byte{0xe2, 0x8c, 0xa3}},
1843 "smt": {Name: "smt", CodePoints: []int{10922}, Characters: []byte{0xe2, 0xaa, 0xaa}},
1844 "smte": {Name: "smte", CodePoints: []int{10924}, Characters: []byte{0xe2, 0xaa, 0xac}},
1845 "smtes": {Name: "smtes", CodePoints: []int{10924, 65024}, Characters: []byte{0xe2, 0xaa, 0xac, 0xef, 0xb8, 0x80}},
1846 "softcy": {Name: "softcy", CodePoints: []int{1100}, Characters: []byte{0xd1, 0x8c}},
1847 "sol": {Name: "sol", CodePoints: []int{47}, Characters: []byte{0x2f}},
1848 "solb": {Name: "solb", CodePoints: []int{10692}, Characters: []byte{0xe2, 0xa7, 0x84}},
1849 "solbar": {Name: "solbar", CodePoints: []int{9023}, Characters: []byte{0xe2, 0x8c, 0xbf}},
1850 "sopf": {Name: "sopf", CodePoints: []int{120164}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa4}},
1851 "spades": {Name: "spades", CodePoints: []int{9824}, Characters: []byte{0xe2, 0x99, 0xa0}},
1852 "spadesuit": {Name: "spadesuit", CodePoints: []int{9824}, Characters: []byte{0xe2, 0x99, 0xa0}},
1853 "spar": {Name: "spar", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
1854 "sqcap": {Name: "sqcap", CodePoints: []int{8851}, Characters: []byte{0xe2, 0x8a, 0x93}},
1855 "sqcaps": {Name: "sqcaps", CodePoints: []int{8851, 65024}, Characters: []byte{0xe2, 0x8a, 0x93, 0xef, 0xb8, 0x80}},
1856 "sqcup": {Name: "sqcup", CodePoints: []int{8852}, Characters: []byte{0xe2, 0x8a, 0x94}},
1857 "sqcups": {Name: "sqcups", CodePoints: []int{8852, 65024}, Characters: []byte{0xe2, 0x8a, 0x94, 0xef, 0xb8, 0x80}},
1858 "sqsub": {Name: "sqsub", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
1859 "sqsube": {Name: "sqsube", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
1860 "sqsubset": {Name: "sqsubset", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
1861 "sqsubseteq": {Name: "sqsubseteq", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
1862 "sqsup": {Name: "sqsup", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
1863 "sqsupe": {Name: "sqsupe", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
1864 "sqsupset": {Name: "sqsupset", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
1865 "sqsupseteq": {Name: "sqsupseteq", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
1866 "squ": {Name: "squ", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
1867 "square": {Name: "square", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
1868 "squarf": {Name: "squarf", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
1869 "squf": {Name: "squf", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
1870 "srarr": {Name: "srarr", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
1871 "sscr": {Name: "sscr", CodePoints: []int{120008}, Characters: []byte{0xf0, 0x9d, 0x93, 0x88}},
1872 "ssetmn": {Name: "ssetmn", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
1873 "ssmile": {Name: "ssmile", CodePoints: []int{8995}, Characters: []byte{0xe2, 0x8c, 0xa3}},
1874 "sstarf": {Name: "sstarf", CodePoints: []int{8902}, Characters: []byte{0xe2, 0x8b, 0x86}},
1875 "star": {Name: "star", CodePoints: []int{9734}, Characters: []byte{0xe2, 0x98, 0x86}},
1876 "starf": {Name: "starf", CodePoints: []int{9733}, Characters: []byte{0xe2, 0x98, 0x85}},
1877 "straightepsilon": {Name: "straightepsilon", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
1878 "straightphi": {Name: "straightphi", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
1879 "strns": {Name: "strns", CodePoints: []int{175}, Characters: []byte{0xc2, 0xaf}},
1880 "sub": {Name: "sub", CodePoints: []int{8834}, Characters: []byte{0xe2, 0x8a, 0x82}},
1881 "subE": {Name: "subE", CodePoints: []int{10949}, Characters: []byte{0xe2, 0xab, 0x85}},
1882 "subdot": {Name: "subdot", CodePoints: []int{10941}, Characters: []byte{0xe2, 0xaa, 0xbd}},
1883 "sube": {Name: "sube", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
1884 "subedot": {Name: "subedot", CodePoints: []int{10947}, Characters: []byte{0xe2, 0xab, 0x83}},
1885 "submult": {Name: "submult", CodePoints: []int{10945}, Characters: []byte{0xe2, 0xab, 0x81}},
1886 "subnE": {Name: "subnE", CodePoints: []int{10955}, Characters: []byte{0xe2, 0xab, 0x8b}},
1887 "subne": {Name: "subne", CodePoints: []int{8842}, Characters: []byte{0xe2, 0x8a, 0x8a}},
1888 "subplus": {Name: "subplus", CodePoints: []int{10943}, Characters: []byte{0xe2, 0xaa, 0xbf}},
1889 "subrarr": {Name: "subrarr", CodePoints: []int{10617}, Characters: []byte{0xe2, 0xa5, 0xb9}},
1890 "subset": {Name: "subset", CodePoints: []int{8834}, Characters: []byte{0xe2, 0x8a, 0x82}},
1891 "subseteq": {Name: "subseteq", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
1892 "subseteqq": {Name: "subseteqq", CodePoints: []int{10949}, Characters: []byte{0xe2, 0xab, 0x85}},
1893 "subsetneq": {Name: "subsetneq", CodePoints: []int{8842}, Characters: []byte{0xe2, 0x8a, 0x8a}},
1894 "subsetneqq": {Name: "subsetneqq", CodePoints: []int{10955}, Characters: []byte{0xe2, 0xab, 0x8b}},
1895 "subsim": {Name: "subsim", CodePoints: []int{10951}, Characters: []byte{0xe2, 0xab, 0x87}},
1896 "subsub": {Name: "subsub", CodePoints: []int{10965}, Characters: []byte{0xe2, 0xab, 0x95}},
1897 "subsup": {Name: "subsup", CodePoints: []int{10963}, Characters: []byte{0xe2, 0xab, 0x93}},
1898 "succ": {Name: "succ", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
1899 "succapprox": {Name: "succapprox", CodePoints: []int{10936}, Characters: []byte{0xe2, 0xaa, 0xb8}},
1900 "succcurlyeq": {Name: "succcurlyeq", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
1901 "succeq": {Name: "succeq", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
1902 "succnapprox": {Name: "succnapprox", CodePoints: []int{10938}, Characters: []byte{0xe2, 0xaa, 0xba}},
1903 "succneqq": {Name: "succneqq", CodePoints: []int{10934}, Characters: []byte{0xe2, 0xaa, 0xb6}},
1904 "succnsim": {Name: "succnsim", CodePoints: []int{8937}, Characters: []byte{0xe2, 0x8b, 0xa9}},
1905 "succsim": {Name: "succsim", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
1906 "sum": {Name: "sum", CodePoints: []int{8721}, Characters: []byte{0xe2, 0x88, 0x91}},
1907 "sung": {Name: "sung", CodePoints: []int{9834}, Characters: []byte{0xe2, 0x99, 0xaa}},
1908 "sup": {Name: "sup", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
1909 "sup1": {Name: "sup1", CodePoints: []int{185}, Characters: []byte{0xc2, 0xb9}},
1910 "sup2": {Name: "sup2", CodePoints: []int{178}, Characters: []byte{0xc2, 0xb2}},
1911 "sup3": {Name: "sup3", CodePoints: []int{179}, Characters: []byte{0xc2, 0xb3}},
1912 "supE": {Name: "supE", CodePoints: []int{10950}, Characters: []byte{0xe2, 0xab, 0x86}},
1913 "supdot": {Name: "supdot", CodePoints: []int{10942}, Characters: []byte{0xe2, 0xaa, 0xbe}},
1914 "supdsub": {Name: "supdsub", CodePoints: []int{10968}, Characters: []byte{0xe2, 0xab, 0x98}},
1915 "supe": {Name: "supe", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
1916 "supedot": {Name: "supedot", CodePoints: []int{10948}, Characters: []byte{0xe2, 0xab, 0x84}},
1917 "suphsol": {Name: "suphsol", CodePoints: []int{10185}, Characters: []byte{0xe2, 0x9f, 0x89}},
1918 "suphsub": {Name: "suphsub", CodePoints: []int{10967}, Characters: []byte{0xe2, 0xab, 0x97}},
1919 "suplarr": {Name: "suplarr", CodePoints: []int{10619}, Characters: []byte{0xe2, 0xa5, 0xbb}},
1920 "supmult": {Name: "supmult", CodePoints: []int{10946}, Characters: []byte{0xe2, 0xab, 0x82}},
1921 "supnE": {Name: "supnE", CodePoints: []int{10956}, Characters: []byte{0xe2, 0xab, 0x8c}},
1922 "supne": {Name: "supne", CodePoints: []int{8843}, Characters: []byte{0xe2, 0x8a, 0x8b}},
1923 "supplus": {Name: "supplus", CodePoints: []int{10944}, Characters: []byte{0xe2, 0xab, 0x80}},
1924 "supset": {Name: "supset", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
1925 "supseteq": {Name: "supseteq", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
1926 "supseteqq": {Name: "supseteqq", CodePoints: []int{10950}, Characters: []byte{0xe2, 0xab, 0x86}},
1927 "supsetneq": {Name: "supsetneq", CodePoints: []int{8843}, Characters: []byte{0xe2, 0x8a, 0x8b}},
1928 "supsetneqq": {Name: "supsetneqq", CodePoints: []int{10956}, Characters: []byte{0xe2, 0xab, 0x8c}},
1929 "supsim": {Name: "supsim", CodePoints: []int{10952}, Characters: []byte{0xe2, 0xab, 0x88}},
1930 "supsub": {Name: "supsub", CodePoints: []int{10964}, Characters: []byte{0xe2, 0xab, 0x94}},
1931 "supsup": {Name: "supsup", CodePoints: []int{10966}, Characters: []byte{0xe2, 0xab, 0x96}},
1932 "swArr": {Name: "swArr", CodePoints: []int{8665}, Characters: []byte{0xe2, 0x87, 0x99}},
1933 "swarhk": {Name: "swarhk", CodePoints: []int{10534}, Characters: []byte{0xe2, 0xa4, 0xa6}},
1934 "swarr": {Name: "swarr", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
1935 "swarrow": {Name: "swarrow", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
1936 "swnwar": {Name: "swnwar", CodePoints: []int{10538}, Characters: []byte{0xe2, 0xa4, 0xaa}},
1937 "szlig": {Name: "szlig", CodePoints: []int{223}, Characters: []byte{0xc3, 0x9f}},
1938 "target": {Name: "target", CodePoints: []int{8982}, Characters: []byte{0xe2, 0x8c, 0x96}},
1939 "tau": {Name: "tau", CodePoints: []int{964}, Characters: []byte{0xcf, 0x84}},
1940 "tbrk": {Name: "tbrk", CodePoints: []int{9140}, Characters: []byte{0xe2, 0x8e, 0xb4}},
1941 "tcaron": {Name: "tcaron", CodePoints: []int{357}, Characters: []byte{0xc5, 0xa5}},
1942 "tcedil": {Name: "tcedil", CodePoints: []int{355}, Characters: []byte{0xc5, 0xa3}},
1943 "tcy": {Name: "tcy", CodePoints: []int{1090}, Characters: []byte{0xd1, 0x82}},
1944 "tdot": {Name: "tdot", CodePoints: []int{8411}, Characters: []byte{0xe2, 0x83, 0x9b}},
1945 "telrec": {Name: "telrec", CodePoints: []int{8981}, Characters: []byte{0xe2, 0x8c, 0x95}},
1946 "tfr": {Name: "tfr", CodePoints: []int{120113}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb1}},
1947 "there4": {Name: "there4", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
1948 "therefore": {Name: "therefore", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
1949 "theta": {Name: "theta", CodePoints: []int{952}, Characters: []byte{0xce, 0xb8}},
1950 "thetasym": {Name: "thetasym", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
1951 "thetav": {Name: "thetav", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
1952 "thickapprox": {Name: "thickapprox", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
1953 "thicksim": {Name: "thicksim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
1954 "thinsp": {Name: "thinsp", CodePoints: []int{8201}, Characters: []byte{0xe2, 0x80, 0x89}},
1955 "thkap": {Name: "thkap", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
1956 "thksim": {Name: "thksim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
1957 "thorn": {Name: "thorn", CodePoints: []int{254}, Characters: []byte{0xc3, 0xbe}},
1958 "tilde": {Name: "tilde", CodePoints: []int{732}, Characters: []byte{0xcb, 0x9c}},
1959 "times": {Name: "times", CodePoints: []int{215}, Characters: []byte{0xc3, 0x97}},
1960 "timesb": {Name: "timesb", CodePoints: []int{8864}, Characters: []byte{0xe2, 0x8a, 0xa0}},
1961 "timesbar": {Name: "timesbar", CodePoints: []int{10801}, Characters: []byte{0xe2, 0xa8, 0xb1}},
1962 "timesd": {Name: "timesd", CodePoints: []int{10800}, Characters: []byte{0xe2, 0xa8, 0xb0}},
1963 "tint": {Name: "tint", CodePoints: []int{8749}, Characters: []byte{0xe2, 0x88, 0xad}},
1964 "toea": {Name: "toea", CodePoints: []int{10536}, Characters: []byte{0xe2, 0xa4, 0xa8}},
1965 "top": {Name: "top", CodePoints: []int{8868}, Characters: []byte{0xe2, 0x8a, 0xa4}},
1966 "topbot": {Name: "topbot", CodePoints: []int{9014}, Characters: []byte{0xe2, 0x8c, 0xb6}},
1967 "topcir": {Name: "topcir", CodePoints: []int{10993}, Characters: []byte{0xe2, 0xab, 0xb1}},
1968 "topf": {Name: "topf", CodePoints: []int{120165}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa5}},
1969 "topfork": {Name: "topfork", CodePoints: []int{10970}, Characters: []byte{0xe2, 0xab, 0x9a}},
1970 "tosa": {Name: "tosa", CodePoints: []int{10537}, Characters: []byte{0xe2, 0xa4, 0xa9}},
1971 "tprime": {Name: "tprime", CodePoints: []int{8244}, Characters: []byte{0xe2, 0x80, 0xb4}},
1972 "trade": {Name: "trade", CodePoints: []int{8482}, Characters: []byte{0xe2, 0x84, 0xa2}},
1973 "triangle": {Name: "triangle", CodePoints: []int{9653}, Characters: []byte{0xe2, 0x96, 0xb5}},
1974 "triangledown": {Name: "triangledown", CodePoints: []int{9663}, Characters: []byte{0xe2, 0x96, 0xbf}},
1975 "triangleleft": {Name: "triangleleft", CodePoints: []int{9667}, Characters: []byte{0xe2, 0x97, 0x83}},
1976 "trianglelefteq": {Name: "trianglelefteq", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
1977 "triangleq": {Name: "triangleq", CodePoints: []int{8796}, Characters: []byte{0xe2, 0x89, 0x9c}},
1978 "triangleright": {Name: "triangleright", CodePoints: []int{9657}, Characters: []byte{0xe2, 0x96, 0xb9}},
1979 "trianglerighteq": {Name: "trianglerighteq", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
1980 "tridot": {Name: "tridot", CodePoints: []int{9708}, Characters: []byte{0xe2, 0x97, 0xac}},
1981 "trie": {Name: "trie", CodePoints: []int{8796}, Characters: []byte{0xe2, 0x89, 0x9c}},
1982 "triminus": {Name: "triminus", CodePoints: []int{10810}, Characters: []byte{0xe2, 0xa8, 0xba}},
1983 "triplus": {Name: "triplus", CodePoints: []int{10809}, Characters: []byte{0xe2, 0xa8, 0xb9}},
1984 "trisb": {Name: "trisb", CodePoints: []int{10701}, Characters: []byte{0xe2, 0xa7, 0x8d}},
1985 "tritime": {Name: "tritime", CodePoints: []int{10811}, Characters: []byte{0xe2, 0xa8, 0xbb}},
1986 "trpezium": {Name: "trpezium", CodePoints: []int{9186}, Characters: []byte{0xe2, 0x8f, 0xa2}},
1987 "tscr": {Name: "tscr", CodePoints: []int{120009}, Characters: []byte{0xf0, 0x9d, 0x93, 0x89}},
1988 "tscy": {Name: "tscy", CodePoints: []int{1094}, Characters: []byte{0xd1, 0x86}},
1989 "tshcy": {Name: "tshcy", CodePoints: []int{1115}, Characters: []byte{0xd1, 0x9b}},
1990 "tstrok": {Name: "tstrok", CodePoints: []int{359}, Characters: []byte{0xc5, 0xa7}},
1991 "twixt": {Name: "twixt", CodePoints: []int{8812}, Characters: []byte{0xe2, 0x89, 0xac}},
1992 "twoheadleftarrow": {Name: "twoheadleftarrow", CodePoints: []int{8606}, Characters: []byte{0xe2, 0x86, 0x9e}},
1993 "twoheadrightarrow": {Name: "twoheadrightarrow", CodePoints: []int{8608}, Characters: []byte{0xe2, 0x86, 0xa0}},
1994 "uArr": {Name: "uArr", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
1995 "uHar": {Name: "uHar", CodePoints: []int{10595}, Characters: []byte{0xe2, 0xa5, 0xa3}},
1996 "uacute": {Name: "uacute", CodePoints: []int{250}, Characters: []byte{0xc3, 0xba}},
1997 "uarr": {Name: "uarr", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
1998 "ubrcy": {Name: "ubrcy", CodePoints: []int{1118}, Characters: []byte{0xd1, 0x9e}},
1999 "ubreve": {Name: "ubreve", CodePoints: []int{365}, Characters: []byte{0xc5, 0xad}},
2000 "ucirc": {Name: "ucirc", CodePoints: []int{251}, Characters: []byte{0xc3, 0xbb}},
2001 "ucy": {Name: "ucy", CodePoints: []int{1091}, Characters: []byte{0xd1, 0x83}},
2002 "udarr": {Name: "udarr", CodePoints: []int{8645}, Characters: []byte{0xe2, 0x87, 0x85}},
2003 "udblac": {Name: "udblac", CodePoints: []int{369}, Characters: []byte{0xc5, 0xb1}},
2004 "udhar": {Name: "udhar", CodePoints: []int{10606}, Characters: []byte{0xe2, 0xa5, 0xae}},
2005 "ufisht": {Name: "ufisht", CodePoints: []int{10622}, Characters: []byte{0xe2, 0xa5, 0xbe}},
2006 "ufr": {Name: "ufr", CodePoints: []int{120114}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb2}},
2007 "ugrave": {Name: "ugrave", CodePoints: []int{249}, Characters: []byte{0xc3, 0xb9}},
2008 "uharl": {Name: "uharl", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
2009 "uharr": {Name: "uharr", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
2010 "uhblk": {Name: "uhblk", CodePoints: []int{9600}, Characters: []byte{0xe2, 0x96, 0x80}},
2011 "ulcorn": {Name: "ulcorn", CodePoints: []int{8988}, Characters: []byte{0xe2, 0x8c, 0x9c}},
2012 "ulcorner": {Name: "ulcorner", CodePoints: []int{8988}, Characters: []byte{0xe2, 0x8c, 0x9c}},
2013 "ulcrop": {Name: "ulcrop", CodePoints: []int{8975}, Characters: []byte{0xe2, 0x8c, 0x8f}},
2014 "ultri": {Name: "ultri", CodePoints: []int{9720}, Characters: []byte{0xe2, 0x97, 0xb8}},
2015 "umacr": {Name: "umacr", CodePoints: []int{363}, Characters: []byte{0xc5, 0xab}},
2016 "uml": {Name: "uml", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
2017 "uogon": {Name: "uogon", CodePoints: []int{371}, Characters: []byte{0xc5, 0xb3}},
2018 "uopf": {Name: "uopf", CodePoints: []int{120166}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa6}},
2019 "uparrow": {Name: "uparrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
2020 "updownarrow": {Name: "updownarrow", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
2021 "upharpoonleft": {Name: "upharpoonleft", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
2022 "upharpoonright": {Name: "upharpoonright", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
2023 "uplus": {Name: "uplus", CodePoints: []int{8846}, Characters: []byte{0xe2, 0x8a, 0x8e}},
2024 "upsi": {Name: "upsi", CodePoints: []int{965}, Characters: []byte{0xcf, 0x85}},
2025 "upsih": {Name: "upsih", CodePoints: []int{978}, Characters: []byte{0xcf, 0x92}},
2026 "upsilon": {Name: "upsilon", CodePoints: []int{965}, Characters: []byte{0xcf, 0x85}},
2027 "upuparrows": {Name: "upuparrows", CodePoints: []int{8648}, Characters: []byte{0xe2, 0x87, 0x88}},
2028 "urcorn": {Name: "urcorn", CodePoints: []int{8989}, Characters: []byte{0xe2, 0x8c, 0x9d}},
2029 "urcorner": {Name: "urcorner", CodePoints: []int{8989}, Characters: []byte{0xe2, 0x8c, 0x9d}},
2030 "urcrop": {Name: "urcrop", CodePoints: []int{8974}, Characters: []byte{0xe2, 0x8c, 0x8e}},
2031 "uring": {Name: "uring", CodePoints: []int{367}, Characters: []byte{0xc5, 0xaf}},
2032 "urtri": {Name: "urtri", CodePoints: []int{9721}, Characters: []byte{0xe2, 0x97, 0xb9}},
2033 "uscr": {Name: "uscr", CodePoints: []int{120010}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8a}},
2034 "utdot": {Name: "utdot", CodePoints: []int{8944}, Characters: []byte{0xe2, 0x8b, 0xb0}},
2035 "utilde": {Name: "utilde", CodePoints: []int{361}, Characters: []byte{0xc5, 0xa9}},
2036 "utri": {Name: "utri", CodePoints: []int{9653}, Characters: []byte{0xe2, 0x96, 0xb5}},
2037 "utrif": {Name: "utrif", CodePoints: []int{9652}, Characters: []byte{0xe2, 0x96, 0xb4}},
2038 "uuarr": {Name: "uuarr", CodePoints: []int{8648}, Characters: []byte{0xe2, 0x87, 0x88}},
2039 "uuml": {Name: "uuml", CodePoints: []int{252}, Characters: []byte{0xc3, 0xbc}},
2040 "uwangle": {Name: "uwangle", CodePoints: []int{10663}, Characters: []byte{0xe2, 0xa6, 0xa7}},
2041 "vArr": {Name: "vArr", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
2042 "vBar": {Name: "vBar", CodePoints: []int{10984}, Characters: []byte{0xe2, 0xab, 0xa8}},
2043 "vBarv": {Name: "vBarv", CodePoints: []int{10985}, Characters: []byte{0xe2, 0xab, 0xa9}},
2044 "vDash": {Name: "vDash", CodePoints: []int{8872}, Characters: []byte{0xe2, 0x8a, 0xa8}},
2045 "vangrt": {Name: "vangrt", CodePoints: []int{10652}, Characters: []byte{0xe2, 0xa6, 0x9c}},
2046 "varepsilon": {Name: "varepsilon", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
2047 "varkappa": {Name: "varkappa", CodePoints: []int{1008}, Characters: []byte{0xcf, 0xb0}},
2048 "varnothing": {Name: "varnothing", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
2049 "varphi": {Name: "varphi", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
2050 "varpi": {Name: "varpi", CodePoints: []int{982}, Characters: []byte{0xcf, 0x96}},
2051 "varpropto": {Name: "varpropto", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
2052 "varr": {Name: "varr", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
2053 "varrho": {Name: "varrho", CodePoints: []int{1009}, Characters: []byte{0xcf, 0xb1}},
2054 "varsigma": {Name: "varsigma", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
2055 "varsubsetneq": {Name: "varsubsetneq", CodePoints: []int{8842, 65024}, Characters: []byte{0xe2, 0x8a, 0x8a, 0xef, 0xb8, 0x80}},
2056 "varsubsetneqq": {Name: "varsubsetneqq", CodePoints: []int{10955, 65024}, Characters: []byte{0xe2, 0xab, 0x8b, 0xef, 0xb8, 0x80}},
2057 "varsupsetneq": {Name: "varsupsetneq", CodePoints: []int{8843, 65024}, Characters: []byte{0xe2, 0x8a, 0x8b, 0xef, 0xb8, 0x80}},
2058 "varsupsetneqq": {Name: "varsupsetneqq", CodePoints: []int{10956, 65024}, Characters: []byte{0xe2, 0xab, 0x8c, 0xef, 0xb8, 0x80}},
2059 "vartheta": {Name: "vartheta", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
2060 "vartriangleleft": {Name: "vartriangleleft", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
2061 "vartriangleright": {Name: "vartriangleright", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
2062 "vcy": {Name: "vcy", CodePoints: []int{1074}, Characters: []byte{0xd0, 0xb2}},
2063 "vdash": {Name: "vdash", CodePoints: []int{8866}, Characters: []byte{0xe2, 0x8a, 0xa2}},
2064 "vee": {Name: "vee", CodePoints: []int{8744}, Characters: []byte{0xe2, 0x88, 0xa8}},
2065 "veebar": {Name: "veebar", CodePoints: []int{8891}, Characters: []byte{0xe2, 0x8a, 0xbb}},
2066 "veeeq": {Name: "veeeq", CodePoints: []int{8794}, Characters: []byte{0xe2, 0x89, 0x9a}},
2067 "vellip": {Name: "vellip", CodePoints: []int{8942}, Characters: []byte{0xe2, 0x8b, 0xae}},
2068 "verbar": {Name: "verbar", CodePoints: []int{124}, Characters: []byte{0x7c}},
2069 "vert": {Name: "vert", CodePoints: []int{124}, Characters: []byte{0x7c}},
2070 "vfr": {Name: "vfr", CodePoints: []int{120115}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb3}},
2071 "vltri": {Name: "vltri", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
2072 "vnsub": {Name: "vnsub", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
2073 "vnsup": {Name: "vnsup", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
2074 "vopf": {Name: "vopf", CodePoints: []int{120167}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa7}},
2075 "vprop": {Name: "vprop", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
2076 "vrtri": {Name: "vrtri", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
2077 "vscr": {Name: "vscr", CodePoints: []int{120011}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8b}},
2078 "vsubnE": {Name: "vsubnE", CodePoints: []int{10955, 65024}, Characters: []byte{0xe2, 0xab, 0x8b, 0xef, 0xb8, 0x80}},
2079 "vsubne": {Name: "vsubne", CodePoints: []int{8842, 65024}, Characters: []byte{0xe2, 0x8a, 0x8a, 0xef, 0xb8, 0x80}},
2080 "vsupnE": {Name: "vsupnE", CodePoints: []int{10956, 65024}, Characters: []byte{0xe2, 0xab, 0x8c, 0xef, 0xb8, 0x80}},
2081 "vsupne": {Name: "vsupne", CodePoints: []int{8843, 65024}, Characters: []byte{0xe2, 0x8a, 0x8b, 0xef, 0xb8, 0x80}},
2082 "vzigzag": {Name: "vzigzag", CodePoints: []int{10650}, Characters: []byte{0xe2, 0xa6, 0x9a}},
2083 "wcirc": {Name: "wcirc", CodePoints: []int{373}, Characters: []byte{0xc5, 0xb5}},
2084 "wedbar": {Name: "wedbar", CodePoints: []int{10847}, Characters: []byte{0xe2, 0xa9, 0x9f}},
2085 "wedge": {Name: "wedge", CodePoints: []int{8743}, Characters: []byte{0xe2, 0x88, 0xa7}},
2086 "wedgeq": {Name: "wedgeq", CodePoints: []int{8793}, Characters: []byte{0xe2, 0x89, 0x99}},
2087 "weierp": {Name: "weierp", CodePoints: []int{8472}, Characters: []byte{0xe2, 0x84, 0x98}},
2088 "wfr": {Name: "wfr", CodePoints: []int{120116}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb4}},
2089 "wopf": {Name: "wopf", CodePoints: []int{120168}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa8}},
2090 "wp": {Name: "wp", CodePoints: []int{8472}, Characters: []byte{0xe2, 0x84, 0x98}},
2091 "wr": {Name: "wr", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
2092 "wreath": {Name: "wreath", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
2093 "wscr": {Name: "wscr", CodePoints: []int{120012}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8c}},
2094 "xcap": {Name: "xcap", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
2095 "xcirc": {Name: "xcirc", CodePoints: []int{9711}, Characters: []byte{0xe2, 0x97, 0xaf}},
2096 "xcup": {Name: "xcup", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
2097 "xdtri": {Name: "xdtri", CodePoints: []int{9661}, Characters: []byte{0xe2, 0x96, 0xbd}},
2098 "xfr": {Name: "xfr", CodePoints: []int{120117}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb5}},
2099 "xhArr": {Name: "xhArr", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
2100 "xharr": {Name: "xharr", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
2101 "xi": {Name: "xi", CodePoints: []int{958}, Characters: []byte{0xce, 0xbe}},
2102 "xlArr": {Name: "xlArr", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
2103 "xlarr": {Name: "xlarr", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
2104 "xmap": {Name: "xmap", CodePoints: []int{10236}, Characters: []byte{0xe2, 0x9f, 0xbc}},
2105 "xnis": {Name: "xnis", CodePoints: []int{8955}, Characters: []byte{0xe2, 0x8b, 0xbb}},
2106 "xodot": {Name: "xodot", CodePoints: []int{10752}, Characters: []byte{0xe2, 0xa8, 0x80}},
2107 "xopf": {Name: "xopf", CodePoints: []int{120169}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa9}},
2108 "xoplus": {Name: "xoplus", CodePoints: []int{10753}, Characters: []byte{0xe2, 0xa8, 0x81}},
2109 "xotime": {Name: "xotime", CodePoints: []int{10754}, Characters: []byte{0xe2, 0xa8, 0x82}},
2110 "xrArr": {Name: "xrArr", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
2111 "xrarr": {Name: "xrarr", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
2112 "xscr": {Name: "xscr", CodePoints: []int{120013}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8d}},
2113 "xsqcup": {Name: "xsqcup", CodePoints: []int{10758}, Characters: []byte{0xe2, 0xa8, 0x86}},
2114 "xuplus": {Name: "xuplus", CodePoints: []int{10756}, Characters: []byte{0xe2, 0xa8, 0x84}},
2115 "xutri": {Name: "xutri", CodePoints: []int{9651}, Characters: []byte{0xe2, 0x96, 0xb3}},
2116 "xvee": {Name: "xvee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
2117 "xwedge": {Name: "xwedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
2118 "yacute": {Name: "yacute", CodePoints: []int{253}, Characters: []byte{0xc3, 0xbd}},
2119 "yacy": {Name: "yacy", CodePoints: []int{1103}, Characters: []byte{0xd1, 0x8f}},
2120 "ycirc": {Name: "ycirc", CodePoints: []int{375}, Characters: []byte{0xc5, 0xb7}},
2121 "ycy": {Name: "ycy", CodePoints: []int{1099}, Characters: []byte{0xd1, 0x8b}},
2122 "yen": {Name: "yen", CodePoints: []int{165}, Characters: []byte{0xc2, 0xa5}},
2123 "yfr": {Name: "yfr", CodePoints: []int{120118}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb6}},
2124 "yicy": {Name: "yicy", CodePoints: []int{1111}, Characters: []byte{0xd1, 0x97}},
2125 "yopf": {Name: "yopf", CodePoints: []int{120170}, Characters: []byte{0xf0, 0x9d, 0x95, 0xaa}},
2126 "yscr": {Name: "yscr", CodePoints: []int{120014}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8e}},
2127 "yucy": {Name: "yucy", CodePoints: []int{1102}, Characters: []byte{0xd1, 0x8e}},
2128 "yuml": {Name: "yuml", CodePoints: []int{255}, Characters: []byte{0xc3, 0xbf}},
2129 "zacute": {Name: "zacute", CodePoints: []int{378}, Characters: []byte{0xc5, 0xba}},
2130 "zcaron": {Name: "zcaron", CodePoints: []int{382}, Characters: []byte{0xc5, 0xbe}},
2131 "zcy": {Name: "zcy", CodePoints: []int{1079}, Characters: []byte{0xd0, 0xb7}},
2132 "zdot": {Name: "zdot", CodePoints: []int{380}, Characters: []byte{0xc5, 0xbc}},
2133 "zeetrf": {Name: "zeetrf", CodePoints: []int{8488}, Characters: []byte{0xe2, 0x84, 0xa8}},
2134 "zeta": {Name: "zeta", CodePoints: []int{950}, Characters: []byte{0xce, 0xb6}},
2135 "zfr": {Name: "zfr", CodePoints: []int{120119}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb7}},
2136 "zhcy": {Name: "zhcy", CodePoints: []int{1078}, Characters: []byte{0xd0, 0xb6}},
2137 "zigrarr": {Name: "zigrarr", CodePoints: []int{8669}, Characters: []byte{0xe2, 0x87, 0x9d}},
2138 "zopf": {Name: "zopf", CodePoints: []int{120171}, Characters: []byte{0xf0, 0x9d, 0x95, 0xab}},
2139 "zscr": {Name: "zscr", CodePoints: []int{120015}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8f}},
2140 "zwj": {Name: "zwj", CodePoints: []int{8205}, Characters: []byte{0xe2, 0x80, 0x8d}},
2141 "zwnj": {Name: "zwnj", CodePoints: []int{8204}, Characters: []byte{0xe2, 0x80, 0x8c}},
2142}
diff --git a/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go b/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go
new file mode 100644
index 0000000..f0e6aa4
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go
@@ -0,0 +1,1534 @@
1package util
2
3var unicodeCaseFoldings = map[rune][]rune {
4 0x41 : []int32{97},
5 0x42 : []int32{98},
6 0x43 : []int32{99},
7 0x44 : []int32{100},
8 0x45 : []int32{101},
9 0x46 : []int32{102},
10 0x47 : []int32{103},
11 0x48 : []int32{104},
12 0x49 : []int32{105},
13 0x4a : []int32{106},
14 0x4b : []int32{107},
15 0x4c : []int32{108},
16 0x4d : []int32{109},
17 0x4e : []int32{110},
18 0x4f : []int32{111},
19 0x50 : []int32{112},
20 0x51 : []int32{113},
21 0x52 : []int32{114},
22 0x53 : []int32{115},
23 0x54 : []int32{116},
24 0x55 : []int32{117},
25 0x56 : []int32{118},
26 0x57 : []int32{119},
27 0x58 : []int32{120},
28 0x59 : []int32{121},
29 0x5a : []int32{122},
30 0xb5 : []int32{956},
31 0xc0 : []int32{224},
32 0xc1 : []int32{225},
33 0xc2 : []int32{226},
34 0xc3 : []int32{227},
35 0xc4 : []int32{228},
36 0xc5 : []int32{229},
37 0xc6 : []int32{230},
38 0xc7 : []int32{231},
39 0xc8 : []int32{232},
40 0xc9 : []int32{233},
41 0xca : []int32{234},
42 0xcb : []int32{235},
43 0xcc : []int32{236},
44 0xcd : []int32{237},
45 0xce : []int32{238},
46 0xcf : []int32{239},
47 0xd0 : []int32{240},
48 0xd1 : []int32{241},
49 0xd2 : []int32{242},
50 0xd3 : []int32{243},
51 0xd4 : []int32{244},
52 0xd5 : []int32{245},
53 0xd6 : []int32{246},
54 0xd8 : []int32{248},
55 0xd9 : []int32{249},
56 0xda : []int32{250},
57 0xdb : []int32{251},
58 0xdc : []int32{252},
59 0xdd : []int32{253},
60 0xde : []int32{254},
61 0xdf : []int32{115, 115},
62 0x100 : []int32{257},
63 0x102 : []int32{259},
64 0x104 : []int32{261},
65 0x106 : []int32{263},
66 0x108 : []int32{265},
67 0x10a : []int32{267},
68 0x10c : []int32{269},
69 0x10e : []int32{271},
70 0x110 : []int32{273},
71 0x112 : []int32{275},
72 0x114 : []int32{277},
73 0x116 : []int32{279},
74 0x118 : []int32{281},
75 0x11a : []int32{283},
76 0x11c : []int32{285},
77 0x11e : []int32{287},
78 0x120 : []int32{289},
79 0x122 : []int32{291},
80 0x124 : []int32{293},
81 0x126 : []int32{295},
82 0x128 : []int32{297},
83 0x12a : []int32{299},
84 0x12c : []int32{301},
85 0x12e : []int32{303},
86 0x130 : []int32{105, 775},
87 0x132 : []int32{307},
88 0x134 : []int32{309},
89 0x136 : []int32{311},
90 0x139 : []int32{314},
91 0x13b : []int32{316},
92 0x13d : []int32{318},
93 0x13f : []int32{320},
94 0x141 : []int32{322},
95 0x143 : []int32{324},
96 0x145 : []int32{326},
97 0x147 : []int32{328},
98 0x149 : []int32{700, 110},
99 0x14a : []int32{331},
100 0x14c : []int32{333},
101 0x14e : []int32{335},
102 0x150 : []int32{337},
103 0x152 : []int32{339},
104 0x154 : []int32{341},
105 0x156 : []int32{343},
106 0x158 : []int32{345},
107 0x15a : []int32{347},
108 0x15c : []int32{349},
109 0x15e : []int32{351},
110 0x160 : []int32{353},
111 0x162 : []int32{355},
112 0x164 : []int32{357},
113 0x166 : []int32{359},
114 0x168 : []int32{361},
115 0x16a : []int32{363},
116 0x16c : []int32{365},
117 0x16e : []int32{367},
118 0x170 : []int32{369},
119 0x172 : []int32{371},
120 0x174 : []int32{373},
121 0x176 : []int32{375},
122 0x178 : []int32{255},
123 0x179 : []int32{378},
124 0x17b : []int32{380},
125 0x17d : []int32{382},
126 0x17f : []int32{115},
127 0x181 : []int32{595},
128 0x182 : []int32{387},
129 0x184 : []int32{389},
130 0x186 : []int32{596},
131 0x187 : []int32{392},
132 0x189 : []int32{598},
133 0x18a : []int32{599},
134 0x18b : []int32{396},
135 0x18e : []int32{477},
136 0x18f : []int32{601},
137 0x190 : []int32{603},
138 0x191 : []int32{402},
139 0x193 : []int32{608},
140 0x194 : []int32{611},
141 0x196 : []int32{617},
142 0x197 : []int32{616},
143 0x198 : []int32{409},
144 0x19c : []int32{623},
145 0x19d : []int32{626},
146 0x19f : []int32{629},
147 0x1a0 : []int32{417},
148 0x1a2 : []int32{419},
149 0x1a4 : []int32{421},
150 0x1a6 : []int32{640},
151 0x1a7 : []int32{424},
152 0x1a9 : []int32{643},
153 0x1ac : []int32{429},
154 0x1ae : []int32{648},
155 0x1af : []int32{432},
156 0x1b1 : []int32{650},
157 0x1b2 : []int32{651},
158 0x1b3 : []int32{436},
159 0x1b5 : []int32{438},
160 0x1b7 : []int32{658},
161 0x1b8 : []int32{441},
162 0x1bc : []int32{445},
163 0x1c4 : []int32{454},
164 0x1c5 : []int32{454},
165 0x1c7 : []int32{457},
166 0x1c8 : []int32{457},
167 0x1ca : []int32{460},
168 0x1cb : []int32{460},
169 0x1cd : []int32{462},
170 0x1cf : []int32{464},
171 0x1d1 : []int32{466},
172 0x1d3 : []int32{468},
173 0x1d5 : []int32{470},
174 0x1d7 : []int32{472},
175 0x1d9 : []int32{474},
176 0x1db : []int32{476},
177 0x1de : []int32{479},
178 0x1e0 : []int32{481},
179 0x1e2 : []int32{483},
180 0x1e4 : []int32{485},
181 0x1e6 : []int32{487},
182 0x1e8 : []int32{489},
183 0x1ea : []int32{491},
184 0x1ec : []int32{493},
185 0x1ee : []int32{495},
186 0x1f0 : []int32{106, 780},
187 0x1f1 : []int32{499},
188 0x1f2 : []int32{499},
189 0x1f4 : []int32{501},
190 0x1f6 : []int32{405},
191 0x1f7 : []int32{447},
192 0x1f8 : []int32{505},
193 0x1fa : []int32{507},
194 0x1fc : []int32{509},
195 0x1fe : []int32{511},
196 0x200 : []int32{513},
197 0x202 : []int32{515},
198 0x204 : []int32{517},
199 0x206 : []int32{519},
200 0x208 : []int32{521},
201 0x20a : []int32{523},
202 0x20c : []int32{525},
203 0x20e : []int32{527},
204 0x210 : []int32{529},
205 0x212 : []int32{531},
206 0x214 : []int32{533},
207 0x216 : []int32{535},
208 0x218 : []int32{537},
209 0x21a : []int32{539},
210 0x21c : []int32{541},
211 0x21e : []int32{543},
212 0x220 : []int32{414},
213 0x222 : []int32{547},
214 0x224 : []int32{549},
215 0x226 : []int32{551},
216 0x228 : []int32{553},
217 0x22a : []int32{555},
218 0x22c : []int32{557},
219 0x22e : []int32{559},
220 0x230 : []int32{561},
221 0x232 : []int32{563},
222 0x23a : []int32{11365},
223 0x23b : []int32{572},
224 0x23d : []int32{410},
225 0x23e : []int32{11366},
226 0x241 : []int32{578},
227 0x243 : []int32{384},
228 0x244 : []int32{649},
229 0x245 : []int32{652},
230 0x246 : []int32{583},
231 0x248 : []int32{585},
232 0x24a : []int32{587},
233 0x24c : []int32{589},
234 0x24e : []int32{591},
235 0x345 : []int32{953},
236 0x370 : []int32{881},
237 0x372 : []int32{883},
238 0x376 : []int32{887},
239 0x37f : []int32{1011},
240 0x386 : []int32{940},
241 0x388 : []int32{941},
242 0x389 : []int32{942},
243 0x38a : []int32{943},
244 0x38c : []int32{972},
245 0x38e : []int32{973},
246 0x38f : []int32{974},
247 0x390 : []int32{953, 776, 769},
248 0x391 : []int32{945},
249 0x392 : []int32{946},
250 0x393 : []int32{947},
251 0x394 : []int32{948},
252 0x395 : []int32{949},
253 0x396 : []int32{950},
254 0x397 : []int32{951},
255 0x398 : []int32{952},
256 0x399 : []int32{953},
257 0x39a : []int32{954},
258 0x39b : []int32{955},
259 0x39c : []int32{956},
260 0x39d : []int32{957},
261 0x39e : []int32{958},
262 0x39f : []int32{959},
263 0x3a0 : []int32{960},
264 0x3a1 : []int32{961},
265 0x3a3 : []int32{963},
266 0x3a4 : []int32{964},
267 0x3a5 : []int32{965},
268 0x3a6 : []int32{966},
269 0x3a7 : []int32{967},
270 0x3a8 : []int32{968},
271 0x3a9 : []int32{969},
272 0x3aa : []int32{970},
273 0x3ab : []int32{971},
274 0x3b0 : []int32{965, 776, 769},
275 0x3c2 : []int32{963},
276 0x3cf : []int32{983},
277 0x3d0 : []int32{946},
278 0x3d1 : []int32{952},
279 0x3d5 : []int32{966},
280 0x3d6 : []int32{960},
281 0x3d8 : []int32{985},
282 0x3da : []int32{987},
283 0x3dc : []int32{989},
284 0x3de : []int32{991},
285 0x3e0 : []int32{993},
286 0x3e2 : []int32{995},
287 0x3e4 : []int32{997},
288 0x3e6 : []int32{999},
289 0x3e8 : []int32{1001},
290 0x3ea : []int32{1003},
291 0x3ec : []int32{1005},
292 0x3ee : []int32{1007},
293 0x3f0 : []int32{954},
294 0x3f1 : []int32{961},
295 0x3f4 : []int32{952},
296 0x3f5 : []int32{949},
297 0x3f7 : []int32{1016},
298 0x3f9 : []int32{1010},
299 0x3fa : []int32{1019},
300 0x3fd : []int32{891},
301 0x3fe : []int32{892},
302 0x3ff : []int32{893},
303 0x400 : []int32{1104},
304 0x401 : []int32{1105},
305 0x402 : []int32{1106},
306 0x403 : []int32{1107},
307 0x404 : []int32{1108},
308 0x405 : []int32{1109},
309 0x406 : []int32{1110},
310 0x407 : []int32{1111},
311 0x408 : []int32{1112},
312 0x409 : []int32{1113},
313 0x40a : []int32{1114},
314 0x40b : []int32{1115},
315 0x40c : []int32{1116},
316 0x40d : []int32{1117},
317 0x40e : []int32{1118},
318 0x40f : []int32{1119},
319 0x410 : []int32{1072},
320 0x411 : []int32{1073},
321 0x412 : []int32{1074},
322 0x413 : []int32{1075},
323 0x414 : []int32{1076},
324 0x415 : []int32{1077},
325 0x416 : []int32{1078},
326 0x417 : []int32{1079},
327 0x418 : []int32{1080},
328 0x419 : []int32{1081},
329 0x41a : []int32{1082},
330 0x41b : []int32{1083},
331 0x41c : []int32{1084},
332 0x41d : []int32{1085},
333 0x41e : []int32{1086},
334 0x41f : []int32{1087},
335 0x420 : []int32{1088},
336 0x421 : []int32{1089},
337 0x422 : []int32{1090},
338 0x423 : []int32{1091},
339 0x424 : []int32{1092},
340 0x425 : []int32{1093},
341 0x426 : []int32{1094},
342 0x427 : []int32{1095},
343 0x428 : []int32{1096},
344 0x429 : []int32{1097},
345 0x42a : []int32{1098},
346 0x42b : []int32{1099},
347 0x42c : []int32{1100},
348 0x42d : []int32{1101},
349 0x42e : []int32{1102},
350 0x42f : []int32{1103},
351 0x460 : []int32{1121},
352 0x462 : []int32{1123},
353 0x464 : []int32{1125},
354 0x466 : []int32{1127},
355 0x468 : []int32{1129},
356 0x46a : []int32{1131},
357 0x46c : []int32{1133},
358 0x46e : []int32{1135},
359 0x470 : []int32{1137},
360 0x472 : []int32{1139},
361 0x474 : []int32{1141},
362 0x476 : []int32{1143},
363 0x478 : []int32{1145},
364 0x47a : []int32{1147},
365 0x47c : []int32{1149},
366 0x47e : []int32{1151},
367 0x480 : []int32{1153},
368 0x48a : []int32{1163},
369 0x48c : []int32{1165},
370 0x48e : []int32{1167},
371 0x490 : []int32{1169},
372 0x492 : []int32{1171},
373 0x494 : []int32{1173},
374 0x496 : []int32{1175},
375 0x498 : []int32{1177},
376 0x49a : []int32{1179},
377 0x49c : []int32{1181},
378 0x49e : []int32{1183},
379 0x4a0 : []int32{1185},
380 0x4a2 : []int32{1187},
381 0x4a4 : []int32{1189},
382 0x4a6 : []int32{1191},
383 0x4a8 : []int32{1193},
384 0x4aa : []int32{1195},
385 0x4ac : []int32{1197},
386 0x4ae : []int32{1199},
387 0x4b0 : []int32{1201},
388 0x4b2 : []int32{1203},
389 0x4b4 : []int32{1205},
390 0x4b6 : []int32{1207},
391 0x4b8 : []int32{1209},
392 0x4ba : []int32{1211},
393 0x4bc : []int32{1213},
394 0x4be : []int32{1215},
395 0x4c0 : []int32{1231},
396 0x4c1 : []int32{1218},
397 0x4c3 : []int32{1220},
398 0x4c5 : []int32{1222},
399 0x4c7 : []int32{1224},
400 0x4c9 : []int32{1226},
401 0x4cb : []int32{1228},
402 0x4cd : []int32{1230},
403 0x4d0 : []int32{1233},
404 0x4d2 : []int32{1235},
405 0x4d4 : []int32{1237},
406 0x4d6 : []int32{1239},
407 0x4d8 : []int32{1241},
408 0x4da : []int32{1243},
409 0x4dc : []int32{1245},
410 0x4de : []int32{1247},
411 0x4e0 : []int32{1249},
412 0x4e2 : []int32{1251},
413 0x4e4 : []int32{1253},
414 0x4e6 : []int32{1255},
415 0x4e8 : []int32{1257},
416 0x4ea : []int32{1259},
417 0x4ec : []int32{1261},
418 0x4ee : []int32{1263},
419 0x4f0 : []int32{1265},
420 0x4f2 : []int32{1267},
421 0x4f4 : []int32{1269},
422 0x4f6 : []int32{1271},
423 0x4f8 : []int32{1273},
424 0x4fa : []int32{1275},
425 0x4fc : []int32{1277},
426 0x4fe : []int32{1279},
427 0x500 : []int32{1281},
428 0x502 : []int32{1283},
429 0x504 : []int32{1285},
430 0x506 : []int32{1287},
431 0x508 : []int32{1289},
432 0x50a : []int32{1291},
433 0x50c : []int32{1293},
434 0x50e : []int32{1295},
435 0x510 : []int32{1297},
436 0x512 : []int32{1299},
437 0x514 : []int32{1301},
438 0x516 : []int32{1303},
439 0x518 : []int32{1305},
440 0x51a : []int32{1307},
441 0x51c : []int32{1309},
442 0x51e : []int32{1311},
443 0x520 : []int32{1313},
444 0x522 : []int32{1315},
445 0x524 : []int32{1317},
446 0x526 : []int32{1319},
447 0x528 : []int32{1321},
448 0x52a : []int32{1323},
449 0x52c : []int32{1325},
450 0x52e : []int32{1327},
451 0x531 : []int32{1377},
452 0x532 : []int32{1378},
453 0x533 : []int32{1379},
454 0x534 : []int32{1380},
455 0x535 : []int32{1381},
456 0x536 : []int32{1382},
457 0x537 : []int32{1383},
458 0x538 : []int32{1384},
459 0x539 : []int32{1385},
460 0x53a : []int32{1386},
461 0x53b : []int32{1387},
462 0x53c : []int32{1388},
463 0x53d : []int32{1389},
464 0x53e : []int32{1390},
465 0x53f : []int32{1391},
466 0x540 : []int32{1392},
467 0x541 : []int32{1393},
468 0x542 : []int32{1394},
469 0x543 : []int32{1395},
470 0x544 : []int32{1396},
471 0x545 : []int32{1397},
472 0x546 : []int32{1398},
473 0x547 : []int32{1399},
474 0x548 : []int32{1400},
475 0x549 : []int32{1401},
476 0x54a : []int32{1402},
477 0x54b : []int32{1403},
478 0x54c : []int32{1404},
479 0x54d : []int32{1405},
480 0x54e : []int32{1406},
481 0x54f : []int32{1407},
482 0x550 : []int32{1408},
483 0x551 : []int32{1409},
484 0x552 : []int32{1410},
485 0x553 : []int32{1411},
486 0x554 : []int32{1412},
487 0x555 : []int32{1413},
488 0x556 : []int32{1414},
489 0x587 : []int32{1381, 1410},
490 0x10a0 : []int32{11520},
491 0x10a1 : []int32{11521},
492 0x10a2 : []int32{11522},
493 0x10a3 : []int32{11523},
494 0x10a4 : []int32{11524},
495 0x10a5 : []int32{11525},
496 0x10a6 : []int32{11526},
497 0x10a7 : []int32{11527},
498 0x10a8 : []int32{11528},
499 0x10a9 : []int32{11529},
500 0x10aa : []int32{11530},
501 0x10ab : []int32{11531},
502 0x10ac : []int32{11532},
503 0x10ad : []int32{11533},
504 0x10ae : []int32{11534},
505 0x10af : []int32{11535},
506 0x10b0 : []int32{11536},
507 0x10b1 : []int32{11537},
508 0x10b2 : []int32{11538},
509 0x10b3 : []int32{11539},
510 0x10b4 : []int32{11540},
511 0x10b5 : []int32{11541},
512 0x10b6 : []int32{11542},
513 0x10b7 : []int32{11543},
514 0x10b8 : []int32{11544},
515 0x10b9 : []int32{11545},
516 0x10ba : []int32{11546},
517 0x10bb : []int32{11547},
518 0x10bc : []int32{11548},
519 0x10bd : []int32{11549},
520 0x10be : []int32{11550},
521 0x10bf : []int32{11551},
522 0x10c0 : []int32{11552},
523 0x10c1 : []int32{11553},
524 0x10c2 : []int32{11554},
525 0x10c3 : []int32{11555},
526 0x10c4 : []int32{11556},
527 0x10c5 : []int32{11557},
528 0x10c7 : []int32{11559},
529 0x10cd : []int32{11565},
530 0x13f8 : []int32{5104},
531 0x13f9 : []int32{5105},
532 0x13fa : []int32{5106},
533 0x13fb : []int32{5107},
534 0x13fc : []int32{5108},
535 0x13fd : []int32{5109},
536 0x1c80 : []int32{1074},
537 0x1c81 : []int32{1076},
538 0x1c82 : []int32{1086},
539 0x1c83 : []int32{1089},
540 0x1c84 : []int32{1090},
541 0x1c85 : []int32{1090},
542 0x1c86 : []int32{1098},
543 0x1c87 : []int32{1123},
544 0x1c88 : []int32{42571},
545 0x1c90 : []int32{4304},
546 0x1c91 : []int32{4305},
547 0x1c92 : []int32{4306},
548 0x1c93 : []int32{4307},
549 0x1c94 : []int32{4308},
550 0x1c95 : []int32{4309},
551 0x1c96 : []int32{4310},
552 0x1c97 : []int32{4311},
553 0x1c98 : []int32{4312},
554 0x1c99 : []int32{4313},
555 0x1c9a : []int32{4314},
556 0x1c9b : []int32{4315},
557 0x1c9c : []int32{4316},
558 0x1c9d : []int32{4317},
559 0x1c9e : []int32{4318},
560 0x1c9f : []int32{4319},
561 0x1ca0 : []int32{4320},
562 0x1ca1 : []int32{4321},
563 0x1ca2 : []int32{4322},
564 0x1ca3 : []int32{4323},
565 0x1ca4 : []int32{4324},
566 0x1ca5 : []int32{4325},
567 0x1ca6 : []int32{4326},
568 0x1ca7 : []int32{4327},
569 0x1ca8 : []int32{4328},
570 0x1ca9 : []int32{4329},
571 0x1caa : []int32{4330},
572 0x1cab : []int32{4331},
573 0x1cac : []int32{4332},
574 0x1cad : []int32{4333},
575 0x1cae : []int32{4334},
576 0x1caf : []int32{4335},
577 0x1cb0 : []int32{4336},
578 0x1cb1 : []int32{4337},
579 0x1cb2 : []int32{4338},
580 0x1cb3 : []int32{4339},
581 0x1cb4 : []int32{4340},
582 0x1cb5 : []int32{4341},
583 0x1cb6 : []int32{4342},
584 0x1cb7 : []int32{4343},
585 0x1cb8 : []int32{4344},
586 0x1cb9 : []int32{4345},
587 0x1cba : []int32{4346},
588 0x1cbd : []int32{4349},
589 0x1cbe : []int32{4350},
590 0x1cbf : []int32{4351},
591 0x1e00 : []int32{7681},
592 0x1e02 : []int32{7683},
593 0x1e04 : []int32{7685},
594 0x1e06 : []int32{7687},
595 0x1e08 : []int32{7689},
596 0x1e0a : []int32{7691},
597 0x1e0c : []int32{7693},
598 0x1e0e : []int32{7695},
599 0x1e10 : []int32{7697},
600 0x1e12 : []int32{7699},
601 0x1e14 : []int32{7701},
602 0x1e16 : []int32{7703},
603 0x1e18 : []int32{7705},
604 0x1e1a : []int32{7707},
605 0x1e1c : []int32{7709},
606 0x1e1e : []int32{7711},
607 0x1e20 : []int32{7713},
608 0x1e22 : []int32{7715},
609 0x1e24 : []int32{7717},
610 0x1e26 : []int32{7719},
611 0x1e28 : []int32{7721},
612 0x1e2a : []int32{7723},
613 0x1e2c : []int32{7725},
614 0x1e2e : []int32{7727},
615 0x1e30 : []int32{7729},
616 0x1e32 : []int32{7731},
617 0x1e34 : []int32{7733},
618 0x1e36 : []int32{7735},
619 0x1e38 : []int32{7737},
620 0x1e3a : []int32{7739},
621 0x1e3c : []int32{7741},
622 0x1e3e : []int32{7743},
623 0x1e40 : []int32{7745},
624 0x1e42 : []int32{7747},
625 0x1e44 : []int32{7749},
626 0x1e46 : []int32{7751},
627 0x1e48 : []int32{7753},
628 0x1e4a : []int32{7755},
629 0x1e4c : []int32{7757},
630 0x1e4e : []int32{7759},
631 0x1e50 : []int32{7761},
632 0x1e52 : []int32{7763},
633 0x1e54 : []int32{7765},
634 0x1e56 : []int32{7767},
635 0x1e58 : []int32{7769},
636 0x1e5a : []int32{7771},
637 0x1e5c : []int32{7773},
638 0x1e5e : []int32{7775},
639 0x1e60 : []int32{7777},
640 0x1e62 : []int32{7779},
641 0x1e64 : []int32{7781},
642 0x1e66 : []int32{7783},
643 0x1e68 : []int32{7785},
644 0x1e6a : []int32{7787},
645 0x1e6c : []int32{7789},
646 0x1e6e : []int32{7791},
647 0x1e70 : []int32{7793},
648 0x1e72 : []int32{7795},
649 0x1e74 : []int32{7797},
650 0x1e76 : []int32{7799},
651 0x1e78 : []int32{7801},
652 0x1e7a : []int32{7803},
653 0x1e7c : []int32{7805},
654 0x1e7e : []int32{7807},
655 0x1e80 : []int32{7809},
656 0x1e82 : []int32{7811},
657 0x1e84 : []int32{7813},
658 0x1e86 : []int32{7815},
659 0x1e88 : []int32{7817},
660 0x1e8a : []int32{7819},
661 0x1e8c : []int32{7821},
662 0x1e8e : []int32{7823},
663 0x1e90 : []int32{7825},
664 0x1e92 : []int32{7827},
665 0x1e94 : []int32{7829},
666 0x1e96 : []int32{104, 817},
667 0x1e97 : []int32{116, 776},
668 0x1e98 : []int32{119, 778},
669 0x1e99 : []int32{121, 778},
670 0x1e9a : []int32{97, 702},
671 0x1e9b : []int32{7777},
672 0x1e9e : []int32{115, 115},
673 0x1ea0 : []int32{7841},
674 0x1ea2 : []int32{7843},
675 0x1ea4 : []int32{7845},
676 0x1ea6 : []int32{7847},
677 0x1ea8 : []int32{7849},
678 0x1eaa : []int32{7851},
679 0x1eac : []int32{7853},
680 0x1eae : []int32{7855},
681 0x1eb0 : []int32{7857},
682 0x1eb2 : []int32{7859},
683 0x1eb4 : []int32{7861},
684 0x1eb6 : []int32{7863},
685 0x1eb8 : []int32{7865},
686 0x1eba : []int32{7867},
687 0x1ebc : []int32{7869},
688 0x1ebe : []int32{7871},
689 0x1ec0 : []int32{7873},
690 0x1ec2 : []int32{7875},
691 0x1ec4 : []int32{7877},
692 0x1ec6 : []int32{7879},
693 0x1ec8 : []int32{7881},
694 0x1eca : []int32{7883},
695 0x1ecc : []int32{7885},
696 0x1ece : []int32{7887},
697 0x1ed0 : []int32{7889},
698 0x1ed2 : []int32{7891},
699 0x1ed4 : []int32{7893},
700 0x1ed6 : []int32{7895},
701 0x1ed8 : []int32{7897},
702 0x1eda : []int32{7899},
703 0x1edc : []int32{7901},
704 0x1ede : []int32{7903},
705 0x1ee0 : []int32{7905},
706 0x1ee2 : []int32{7907},
707 0x1ee4 : []int32{7909},
708 0x1ee6 : []int32{7911},
709 0x1ee8 : []int32{7913},
710 0x1eea : []int32{7915},
711 0x1eec : []int32{7917},
712 0x1eee : []int32{7919},
713 0x1ef0 : []int32{7921},
714 0x1ef2 : []int32{7923},
715 0x1ef4 : []int32{7925},
716 0x1ef6 : []int32{7927},
717 0x1ef8 : []int32{7929},
718 0x1efa : []int32{7931},
719 0x1efc : []int32{7933},
720 0x1efe : []int32{7935},
721 0x1f08 : []int32{7936},
722 0x1f09 : []int32{7937},
723 0x1f0a : []int32{7938},
724 0x1f0b : []int32{7939},
725 0x1f0c : []int32{7940},
726 0x1f0d : []int32{7941},
727 0x1f0e : []int32{7942},
728 0x1f0f : []int32{7943},
729 0x1f18 : []int32{7952},
730 0x1f19 : []int32{7953},
731 0x1f1a : []int32{7954},
732 0x1f1b : []int32{7955},
733 0x1f1c : []int32{7956},
734 0x1f1d : []int32{7957},
735 0x1f28 : []int32{7968},
736 0x1f29 : []int32{7969},
737 0x1f2a : []int32{7970},
738 0x1f2b : []int32{7971},
739 0x1f2c : []int32{7972},
740 0x1f2d : []int32{7973},
741 0x1f2e : []int32{7974},
742 0x1f2f : []int32{7975},
743 0x1f38 : []int32{7984},
744 0x1f39 : []int32{7985},
745 0x1f3a : []int32{7986},
746 0x1f3b : []int32{7987},
747 0x1f3c : []int32{7988},
748 0x1f3d : []int32{7989},
749 0x1f3e : []int32{7990},
750 0x1f3f : []int32{7991},
751 0x1f48 : []int32{8000},
752 0x1f49 : []int32{8001},
753 0x1f4a : []int32{8002},
754 0x1f4b : []int32{8003},
755 0x1f4c : []int32{8004},
756 0x1f4d : []int32{8005},
757 0x1f50 : []int32{965, 787},
758 0x1f52 : []int32{965, 787, 768},
759 0x1f54 : []int32{965, 787, 769},
760 0x1f56 : []int32{965, 787, 834},
761 0x1f59 : []int32{8017},
762 0x1f5b : []int32{8019},
763 0x1f5d : []int32{8021},
764 0x1f5f : []int32{8023},
765 0x1f68 : []int32{8032},
766 0x1f69 : []int32{8033},
767 0x1f6a : []int32{8034},
768 0x1f6b : []int32{8035},
769 0x1f6c : []int32{8036},
770 0x1f6d : []int32{8037},
771 0x1f6e : []int32{8038},
772 0x1f6f : []int32{8039},
773 0x1f80 : []int32{7936, 953},
774 0x1f81 : []int32{7937, 953},
775 0x1f82 : []int32{7938, 953},
776 0x1f83 : []int32{7939, 953},
777 0x1f84 : []int32{7940, 953},
778 0x1f85 : []int32{7941, 953},
779 0x1f86 : []int32{7942, 953},
780 0x1f87 : []int32{7943, 953},
781 0x1f88 : []int32{7936, 953},
782 0x1f89 : []int32{7937, 953},
783 0x1f8a : []int32{7938, 953},
784 0x1f8b : []int32{7939, 953},
785 0x1f8c : []int32{7940, 953},
786 0x1f8d : []int32{7941, 953},
787 0x1f8e : []int32{7942, 953},
788 0x1f8f : []int32{7943, 953},
789 0x1f90 : []int32{7968, 953},
790 0x1f91 : []int32{7969, 953},
791 0x1f92 : []int32{7970, 953},
792 0x1f93 : []int32{7971, 953},
793 0x1f94 : []int32{7972, 953},
794 0x1f95 : []int32{7973, 953},
795 0x1f96 : []int32{7974, 953},
796 0x1f97 : []int32{7975, 953},
797 0x1f98 : []int32{7968, 953},
798 0x1f99 : []int32{7969, 953},
799 0x1f9a : []int32{7970, 953},
800 0x1f9b : []int32{7971, 953},
801 0x1f9c : []int32{7972, 953},
802 0x1f9d : []int32{7973, 953},
803 0x1f9e : []int32{7974, 953},
804 0x1f9f : []int32{7975, 953},
805 0x1fa0 : []int32{8032, 953},
806 0x1fa1 : []int32{8033, 953},
807 0x1fa2 : []int32{8034, 953},
808 0x1fa3 : []int32{8035, 953},
809 0x1fa4 : []int32{8036, 953},
810 0x1fa5 : []int32{8037, 953},
811 0x1fa6 : []int32{8038, 953},
812 0x1fa7 : []int32{8039, 953},
813 0x1fa8 : []int32{8032, 953},
814 0x1fa9 : []int32{8033, 953},
815 0x1faa : []int32{8034, 953},
816 0x1fab : []int32{8035, 953},
817 0x1fac : []int32{8036, 953},
818 0x1fad : []int32{8037, 953},
819 0x1fae : []int32{8038, 953},
820 0x1faf : []int32{8039, 953},
821 0x1fb2 : []int32{8048, 953},
822 0x1fb3 : []int32{945, 953},
823 0x1fb4 : []int32{940, 953},
824 0x1fb6 : []int32{945, 834},
825 0x1fb7 : []int32{945, 834, 953},
826 0x1fb8 : []int32{8112},
827 0x1fb9 : []int32{8113},
828 0x1fba : []int32{8048},
829 0x1fbb : []int32{8049},
830 0x1fbc : []int32{945, 953},
831 0x1fbe : []int32{953},
832 0x1fc2 : []int32{8052, 953},
833 0x1fc3 : []int32{951, 953},
834 0x1fc4 : []int32{942, 953},
835 0x1fc6 : []int32{951, 834},
836 0x1fc7 : []int32{951, 834, 953},
837 0x1fc8 : []int32{8050},
838 0x1fc9 : []int32{8051},
839 0x1fca : []int32{8052},
840 0x1fcb : []int32{8053},
841 0x1fcc : []int32{951, 953},
842 0x1fd2 : []int32{953, 776, 768},
843 0x1fd3 : []int32{953, 776, 769},
844 0x1fd6 : []int32{953, 834},
845 0x1fd7 : []int32{953, 776, 834},
846 0x1fd8 : []int32{8144},
847 0x1fd9 : []int32{8145},
848 0x1fda : []int32{8054},
849 0x1fdb : []int32{8055},
850 0x1fe2 : []int32{965, 776, 768},
851 0x1fe3 : []int32{965, 776, 769},
852 0x1fe4 : []int32{961, 787},
853 0x1fe6 : []int32{965, 834},
854 0x1fe7 : []int32{965, 776, 834},
855 0x1fe8 : []int32{8160},
856 0x1fe9 : []int32{8161},
857 0x1fea : []int32{8058},
858 0x1feb : []int32{8059},
859 0x1fec : []int32{8165},
860 0x1ff2 : []int32{8060, 953},
861 0x1ff3 : []int32{969, 953},
862 0x1ff4 : []int32{974, 953},
863 0x1ff6 : []int32{969, 834},
864 0x1ff7 : []int32{969, 834, 953},
865 0x1ff8 : []int32{8056},
866 0x1ff9 : []int32{8057},
867 0x1ffa : []int32{8060},
868 0x1ffb : []int32{8061},
869 0x1ffc : []int32{969, 953},
870 0x2126 : []int32{969},
871 0x212a : []int32{107},
872 0x212b : []int32{229},
873 0x2132 : []int32{8526},
874 0x2160 : []int32{8560},
875 0x2161 : []int32{8561},
876 0x2162 : []int32{8562},
877 0x2163 : []int32{8563},
878 0x2164 : []int32{8564},
879 0x2165 : []int32{8565},
880 0x2166 : []int32{8566},
881 0x2167 : []int32{8567},
882 0x2168 : []int32{8568},
883 0x2169 : []int32{8569},
884 0x216a : []int32{8570},
885 0x216b : []int32{8571},
886 0x216c : []int32{8572},
887 0x216d : []int32{8573},
888 0x216e : []int32{8574},
889 0x216f : []int32{8575},
890 0x2183 : []int32{8580},
891 0x24b6 : []int32{9424},
892 0x24b7 : []int32{9425},
893 0x24b8 : []int32{9426},
894 0x24b9 : []int32{9427},
895 0x24ba : []int32{9428},
896 0x24bb : []int32{9429},
897 0x24bc : []int32{9430},
898 0x24bd : []int32{9431},
899 0x24be : []int32{9432},
900 0x24bf : []int32{9433},
901 0x24c0 : []int32{9434},
902 0x24c1 : []int32{9435},
903 0x24c2 : []int32{9436},
904 0x24c3 : []int32{9437},
905 0x24c4 : []int32{9438},
906 0x24c5 : []int32{9439},
907 0x24c6 : []int32{9440},
908 0x24c7 : []int32{9441},
909 0x24c8 : []int32{9442},
910 0x24c9 : []int32{9443},
911 0x24ca : []int32{9444},
912 0x24cb : []int32{9445},
913 0x24cc : []int32{9446},
914 0x24cd : []int32{9447},
915 0x24ce : []int32{9448},
916 0x24cf : []int32{9449},
917 0x2c00 : []int32{11312},
918 0x2c01 : []int32{11313},
919 0x2c02 : []int32{11314},
920 0x2c03 : []int32{11315},
921 0x2c04 : []int32{11316},
922 0x2c05 : []int32{11317},
923 0x2c06 : []int32{11318},
924 0x2c07 : []int32{11319},
925 0x2c08 : []int32{11320},
926 0x2c09 : []int32{11321},
927 0x2c0a : []int32{11322},
928 0x2c0b : []int32{11323},
929 0x2c0c : []int32{11324},
930 0x2c0d : []int32{11325},
931 0x2c0e : []int32{11326},
932 0x2c0f : []int32{11327},
933 0x2c10 : []int32{11328},
934 0x2c11 : []int32{11329},
935 0x2c12 : []int32{11330},
936 0x2c13 : []int32{11331},
937 0x2c14 : []int32{11332},
938 0x2c15 : []int32{11333},
939 0x2c16 : []int32{11334},
940 0x2c17 : []int32{11335},
941 0x2c18 : []int32{11336},
942 0x2c19 : []int32{11337},
943 0x2c1a : []int32{11338},
944 0x2c1b : []int32{11339},
945 0x2c1c : []int32{11340},
946 0x2c1d : []int32{11341},
947 0x2c1e : []int32{11342},
948 0x2c1f : []int32{11343},
949 0x2c20 : []int32{11344},
950 0x2c21 : []int32{11345},
951 0x2c22 : []int32{11346},
952 0x2c23 : []int32{11347},
953 0x2c24 : []int32{11348},
954 0x2c25 : []int32{11349},
955 0x2c26 : []int32{11350},
956 0x2c27 : []int32{11351},
957 0x2c28 : []int32{11352},
958 0x2c29 : []int32{11353},
959 0x2c2a : []int32{11354},
960 0x2c2b : []int32{11355},
961 0x2c2c : []int32{11356},
962 0x2c2d : []int32{11357},
963 0x2c2e : []int32{11358},
964 0x2c2f : []int32{11359},
965 0x2c60 : []int32{11361},
966 0x2c62 : []int32{619},
967 0x2c63 : []int32{7549},
968 0x2c64 : []int32{637},
969 0x2c67 : []int32{11368},
970 0x2c69 : []int32{11370},
971 0x2c6b : []int32{11372},
972 0x2c6d : []int32{593},
973 0x2c6e : []int32{625},
974 0x2c6f : []int32{592},
975 0x2c70 : []int32{594},
976 0x2c72 : []int32{11379},
977 0x2c75 : []int32{11382},
978 0x2c7e : []int32{575},
979 0x2c7f : []int32{576},
980 0x2c80 : []int32{11393},
981 0x2c82 : []int32{11395},
982 0x2c84 : []int32{11397},
983 0x2c86 : []int32{11399},
984 0x2c88 : []int32{11401},
985 0x2c8a : []int32{11403},
986 0x2c8c : []int32{11405},
987 0x2c8e : []int32{11407},
988 0x2c90 : []int32{11409},
989 0x2c92 : []int32{11411},
990 0x2c94 : []int32{11413},
991 0x2c96 : []int32{11415},
992 0x2c98 : []int32{11417},
993 0x2c9a : []int32{11419},
994 0x2c9c : []int32{11421},
995 0x2c9e : []int32{11423},
996 0x2ca0 : []int32{11425},
997 0x2ca2 : []int32{11427},
998 0x2ca4 : []int32{11429},
999 0x2ca6 : []int32{11431},
1000 0x2ca8 : []int32{11433},
1001 0x2caa : []int32{11435},
1002 0x2cac : []int32{11437},
1003 0x2cae : []int32{11439},
1004 0x2cb0 : []int32{11441},
1005 0x2cb2 : []int32{11443},
1006 0x2cb4 : []int32{11445},
1007 0x2cb6 : []int32{11447},
1008 0x2cb8 : []int32{11449},
1009 0x2cba : []int32{11451},
1010 0x2cbc : []int32{11453},
1011 0x2cbe : []int32{11455},
1012 0x2cc0 : []int32{11457},
1013 0x2cc2 : []int32{11459},
1014 0x2cc4 : []int32{11461},
1015 0x2cc6 : []int32{11463},
1016 0x2cc8 : []int32{11465},
1017 0x2cca : []int32{11467},
1018 0x2ccc : []int32{11469},
1019 0x2cce : []int32{11471},
1020 0x2cd0 : []int32{11473},
1021 0x2cd2 : []int32{11475},
1022 0x2cd4 : []int32{11477},
1023 0x2cd6 : []int32{11479},
1024 0x2cd8 : []int32{11481},
1025 0x2cda : []int32{11483},
1026 0x2cdc : []int32{11485},
1027 0x2cde : []int32{11487},
1028 0x2ce0 : []int32{11489},
1029 0x2ce2 : []int32{11491},
1030 0x2ceb : []int32{11500},
1031 0x2ced : []int32{11502},
1032 0x2cf2 : []int32{11507},
1033 0xa640 : []int32{42561},
1034 0xa642 : []int32{42563},
1035 0xa644 : []int32{42565},
1036 0xa646 : []int32{42567},
1037 0xa648 : []int32{42569},
1038 0xa64a : []int32{42571},
1039 0xa64c : []int32{42573},
1040 0xa64e : []int32{42575},
1041 0xa650 : []int32{42577},
1042 0xa652 : []int32{42579},
1043 0xa654 : []int32{42581},
1044 0xa656 : []int32{42583},
1045 0xa658 : []int32{42585},
1046 0xa65a : []int32{42587},
1047 0xa65c : []int32{42589},
1048 0xa65e : []int32{42591},
1049 0xa660 : []int32{42593},
1050 0xa662 : []int32{42595},
1051 0xa664 : []int32{42597},
1052 0xa666 : []int32{42599},
1053 0xa668 : []int32{42601},
1054 0xa66a : []int32{42603},
1055 0xa66c : []int32{42605},
1056 0xa680 : []int32{42625},
1057 0xa682 : []int32{42627},
1058 0xa684 : []int32{42629},
1059 0xa686 : []int32{42631},
1060 0xa688 : []int32{42633},
1061 0xa68a : []int32{42635},
1062 0xa68c : []int32{42637},
1063 0xa68e : []int32{42639},
1064 0xa690 : []int32{42641},
1065 0xa692 : []int32{42643},
1066 0xa694 : []int32{42645},
1067 0xa696 : []int32{42647},
1068 0xa698 : []int32{42649},
1069 0xa69a : []int32{42651},
1070 0xa722 : []int32{42787},
1071 0xa724 : []int32{42789},
1072 0xa726 : []int32{42791},
1073 0xa728 : []int32{42793},
1074 0xa72a : []int32{42795},
1075 0xa72c : []int32{42797},
1076 0xa72e : []int32{42799},
1077 0xa732 : []int32{42803},
1078 0xa734 : []int32{42805},
1079 0xa736 : []int32{42807},
1080 0xa738 : []int32{42809},
1081 0xa73a : []int32{42811},
1082 0xa73c : []int32{42813},
1083 0xa73e : []int32{42815},
1084 0xa740 : []int32{42817},
1085 0xa742 : []int32{42819},
1086 0xa744 : []int32{42821},
1087 0xa746 : []int32{42823},
1088 0xa748 : []int32{42825},
1089 0xa74a : []int32{42827},
1090 0xa74c : []int32{42829},
1091 0xa74e : []int32{42831},
1092 0xa750 : []int32{42833},
1093 0xa752 : []int32{42835},
1094 0xa754 : []int32{42837},
1095 0xa756 : []int32{42839},
1096 0xa758 : []int32{42841},
1097 0xa75a : []int32{42843},
1098 0xa75c : []int32{42845},
1099 0xa75e : []int32{42847},
1100 0xa760 : []int32{42849},
1101 0xa762 : []int32{42851},
1102 0xa764 : []int32{42853},
1103 0xa766 : []int32{42855},
1104 0xa768 : []int32{42857},
1105 0xa76a : []int32{42859},
1106 0xa76c : []int32{42861},
1107 0xa76e : []int32{42863},
1108 0xa779 : []int32{42874},
1109 0xa77b : []int32{42876},
1110 0xa77d : []int32{7545},
1111 0xa77e : []int32{42879},
1112 0xa780 : []int32{42881},
1113 0xa782 : []int32{42883},
1114 0xa784 : []int32{42885},
1115 0xa786 : []int32{42887},
1116 0xa78b : []int32{42892},
1117 0xa78d : []int32{613},
1118 0xa790 : []int32{42897},
1119 0xa792 : []int32{42899},
1120 0xa796 : []int32{42903},
1121 0xa798 : []int32{42905},
1122 0xa79a : []int32{42907},
1123 0xa79c : []int32{42909},
1124 0xa79e : []int32{42911},
1125 0xa7a0 : []int32{42913},
1126 0xa7a2 : []int32{42915},
1127 0xa7a4 : []int32{42917},
1128 0xa7a6 : []int32{42919},
1129 0xa7a8 : []int32{42921},
1130 0xa7aa : []int32{614},
1131 0xa7ab : []int32{604},
1132 0xa7ac : []int32{609},
1133 0xa7ad : []int32{620},
1134 0xa7ae : []int32{618},
1135 0xa7b0 : []int32{670},
1136 0xa7b1 : []int32{647},
1137 0xa7b2 : []int32{669},
1138 0xa7b3 : []int32{43859},
1139 0xa7b4 : []int32{42933},
1140 0xa7b6 : []int32{42935},
1141 0xa7b8 : []int32{42937},
1142 0xa7ba : []int32{42939},
1143 0xa7bc : []int32{42941},
1144 0xa7be : []int32{42943},
1145 0xa7c0 : []int32{42945},
1146 0xa7c2 : []int32{42947},
1147 0xa7c4 : []int32{42900},
1148 0xa7c5 : []int32{642},
1149 0xa7c6 : []int32{7566},
1150 0xa7c7 : []int32{42952},
1151 0xa7c9 : []int32{42954},
1152 0xa7d0 : []int32{42961},
1153 0xa7d6 : []int32{42967},
1154 0xa7d8 : []int32{42969},
1155 0xa7f5 : []int32{42998},
1156 0xab70 : []int32{5024},
1157 0xab71 : []int32{5025},
1158 0xab72 : []int32{5026},
1159 0xab73 : []int32{5027},
1160 0xab74 : []int32{5028},
1161 0xab75 : []int32{5029},
1162 0xab76 : []int32{5030},
1163 0xab77 : []int32{5031},
1164 0xab78 : []int32{5032},
1165 0xab79 : []int32{5033},
1166 0xab7a : []int32{5034},
1167 0xab7b : []int32{5035},
1168 0xab7c : []int32{5036},
1169 0xab7d : []int32{5037},
1170 0xab7e : []int32{5038},
1171 0xab7f : []int32{5039},
1172 0xab80 : []int32{5040},
1173 0xab81 : []int32{5041},
1174 0xab82 : []int32{5042},
1175 0xab83 : []int32{5043},
1176 0xab84 : []int32{5044},
1177 0xab85 : []int32{5045},
1178 0xab86 : []int32{5046},
1179 0xab87 : []int32{5047},
1180 0xab88 : []int32{5048},
1181 0xab89 : []int32{5049},
1182 0xab8a : []int32{5050},
1183 0xab8b : []int32{5051},
1184 0xab8c : []int32{5052},
1185 0xab8d : []int32{5053},
1186 0xab8e : []int32{5054},
1187 0xab8f : []int32{5055},
1188 0xab90 : []int32{5056},
1189 0xab91 : []int32{5057},
1190 0xab92 : []int32{5058},
1191 0xab93 : []int32{5059},
1192 0xab94 : []int32{5060},
1193 0xab95 : []int32{5061},
1194 0xab96 : []int32{5062},
1195 0xab97 : []int32{5063},
1196 0xab98 : []int32{5064},
1197 0xab99 : []int32{5065},
1198 0xab9a : []int32{5066},
1199 0xab9b : []int32{5067},
1200 0xab9c : []int32{5068},
1201 0xab9d : []int32{5069},
1202 0xab9e : []int32{5070},
1203 0xab9f : []int32{5071},
1204 0xaba0 : []int32{5072},
1205 0xaba1 : []int32{5073},
1206 0xaba2 : []int32{5074},
1207 0xaba3 : []int32{5075},
1208 0xaba4 : []int32{5076},
1209 0xaba5 : []int32{5077},
1210 0xaba6 : []int32{5078},
1211 0xaba7 : []int32{5079},
1212 0xaba8 : []int32{5080},
1213 0xaba9 : []int32{5081},
1214 0xabaa : []int32{5082},
1215 0xabab : []int32{5083},
1216 0xabac : []int32{5084},
1217 0xabad : []int32{5085},
1218 0xabae : []int32{5086},
1219 0xabaf : []int32{5087},
1220 0xabb0 : []int32{5088},
1221 0xabb1 : []int32{5089},
1222 0xabb2 : []int32{5090},
1223 0xabb3 : []int32{5091},
1224 0xabb4 : []int32{5092},
1225 0xabb5 : []int32{5093},
1226 0xabb6 : []int32{5094},
1227 0xabb7 : []int32{5095},
1228 0xabb8 : []int32{5096},
1229 0xabb9 : []int32{5097},
1230 0xabba : []int32{5098},
1231 0xabbb : []int32{5099},
1232 0xabbc : []int32{5100},
1233 0xabbd : []int32{5101},
1234 0xabbe : []int32{5102},
1235 0xabbf : []int32{5103},
1236 0xfb00 : []int32{102, 102},
1237 0xfb01 : []int32{102, 105},
1238 0xfb02 : []int32{102, 108},
1239 0xfb03 : []int32{102, 102, 105},
1240 0xfb04 : []int32{102, 102, 108},
1241 0xfb05 : []int32{115, 116},
1242 0xfb06 : []int32{115, 116},
1243 0xfb13 : []int32{1396, 1398},
1244 0xfb14 : []int32{1396, 1381},
1245 0xfb15 : []int32{1396, 1387},
1246 0xfb16 : []int32{1406, 1398},
1247 0xfb17 : []int32{1396, 1389},
1248 0xff21 : []int32{65345},
1249 0xff22 : []int32{65346},
1250 0xff23 : []int32{65347},
1251 0xff24 : []int32{65348},
1252 0xff25 : []int32{65349},
1253 0xff26 : []int32{65350},
1254 0xff27 : []int32{65351},
1255 0xff28 : []int32{65352},
1256 0xff29 : []int32{65353},
1257 0xff2a : []int32{65354},
1258 0xff2b : []int32{65355},
1259 0xff2c : []int32{65356},
1260 0xff2d : []int32{65357},
1261 0xff2e : []int32{65358},
1262 0xff2f : []int32{65359},
1263 0xff30 : []int32{65360},
1264 0xff31 : []int32{65361},
1265 0xff32 : []int32{65362},
1266 0xff33 : []int32{65363},
1267 0xff34 : []int32{65364},
1268 0xff35 : []int32{65365},
1269 0xff36 : []int32{65366},
1270 0xff37 : []int32{65367},
1271 0xff38 : []int32{65368},
1272 0xff39 : []int32{65369},
1273 0xff3a : []int32{65370},
1274 0x10400 : []int32{66600},
1275 0x10401 : []int32{66601},
1276 0x10402 : []int32{66602},
1277 0x10403 : []int32{66603},
1278 0x10404 : []int32{66604},
1279 0x10405 : []int32{66605},
1280 0x10406 : []int32{66606},
1281 0x10407 : []int32{66607},
1282 0x10408 : []int32{66608},
1283 0x10409 : []int32{66609},
1284 0x1040a : []int32{66610},
1285 0x1040b : []int32{66611},
1286 0x1040c : []int32{66612},
1287 0x1040d : []int32{66613},
1288 0x1040e : []int32{66614},
1289 0x1040f : []int32{66615},
1290 0x10410 : []int32{66616},
1291 0x10411 : []int32{66617},
1292 0x10412 : []int32{66618},
1293 0x10413 : []int32{66619},
1294 0x10414 : []int32{66620},
1295 0x10415 : []int32{66621},
1296 0x10416 : []int32{66622},
1297 0x10417 : []int32{66623},
1298 0x10418 : []int32{66624},
1299 0x10419 : []int32{66625},
1300 0x1041a : []int32{66626},
1301 0x1041b : []int32{66627},
1302 0x1041c : []int32{66628},
1303 0x1041d : []int32{66629},
1304 0x1041e : []int32{66630},
1305 0x1041f : []int32{66631},
1306 0x10420 : []int32{66632},
1307 0x10421 : []int32{66633},
1308 0x10422 : []int32{66634},
1309 0x10423 : []int32{66635},
1310 0x10424 : []int32{66636},
1311 0x10425 : []int32{66637},
1312 0x10426 : []int32{66638},
1313 0x10427 : []int32{66639},
1314 0x104b0 : []int32{66776},
1315 0x104b1 : []int32{66777},
1316 0x104b2 : []int32{66778},
1317 0x104b3 : []int32{66779},
1318 0x104b4 : []int32{66780},
1319 0x104b5 : []int32{66781},
1320 0x104b6 : []int32{66782},
1321 0x104b7 : []int32{66783},
1322 0x104b8 : []int32{66784},
1323 0x104b9 : []int32{66785},
1324 0x104ba : []int32{66786},
1325 0x104bb : []int32{66787},
1326 0x104bc : []int32{66788},
1327 0x104bd : []int32{66789},
1328 0x104be : []int32{66790},
1329 0x104bf : []int32{66791},
1330 0x104c0 : []int32{66792},
1331 0x104c1 : []int32{66793},
1332 0x104c2 : []int32{66794},
1333 0x104c3 : []int32{66795},
1334 0x104c4 : []int32{66796},
1335 0x104c5 : []int32{66797},
1336 0x104c6 : []int32{66798},
1337 0x104c7 : []int32{66799},
1338 0x104c8 : []int32{66800},
1339 0x104c9 : []int32{66801},
1340 0x104ca : []int32{66802},
1341 0x104cb : []int32{66803},
1342 0x104cc : []int32{66804},
1343 0x104cd : []int32{66805},
1344 0x104ce : []int32{66806},
1345 0x104cf : []int32{66807},
1346 0x104d0 : []int32{66808},
1347 0x104d1 : []int32{66809},
1348 0x104d2 : []int32{66810},
1349 0x104d3 : []int32{66811},
1350 0x10570 : []int32{66967},
1351 0x10571 : []int32{66968},
1352 0x10572 : []int32{66969},
1353 0x10573 : []int32{66970},
1354 0x10574 : []int32{66971},
1355 0x10575 : []int32{66972},
1356 0x10576 : []int32{66973},
1357 0x10577 : []int32{66974},
1358 0x10578 : []int32{66975},
1359 0x10579 : []int32{66976},
1360 0x1057a : []int32{66977},
1361 0x1057c : []int32{66979},
1362 0x1057d : []int32{66980},
1363 0x1057e : []int32{66981},
1364 0x1057f : []int32{66982},
1365 0x10580 : []int32{66983},
1366 0x10581 : []int32{66984},
1367 0x10582 : []int32{66985},
1368 0x10583 : []int32{66986},
1369 0x10584 : []int32{66987},
1370 0x10585 : []int32{66988},
1371 0x10586 : []int32{66989},
1372 0x10587 : []int32{66990},
1373 0x10588 : []int32{66991},
1374 0x10589 : []int32{66992},
1375 0x1058a : []int32{66993},
1376 0x1058c : []int32{66995},
1377 0x1058d : []int32{66996},
1378 0x1058e : []int32{66997},
1379 0x1058f : []int32{66998},
1380 0x10590 : []int32{66999},
1381 0x10591 : []int32{67000},
1382 0x10592 : []int32{67001},
1383 0x10594 : []int32{67003},
1384 0x10595 : []int32{67004},
1385 0x10c80 : []int32{68800},
1386 0x10c81 : []int32{68801},
1387 0x10c82 : []int32{68802},
1388 0x10c83 : []int32{68803},
1389 0x10c84 : []int32{68804},
1390 0x10c85 : []int32{68805},
1391 0x10c86 : []int32{68806},
1392 0x10c87 : []int32{68807},
1393 0x10c88 : []int32{68808},
1394 0x10c89 : []int32{68809},
1395 0x10c8a : []int32{68810},
1396 0x10c8b : []int32{68811},
1397 0x10c8c : []int32{68812},
1398 0x10c8d : []int32{68813},
1399 0x10c8e : []int32{68814},
1400 0x10c8f : []int32{68815},
1401 0x10c90 : []int32{68816},
1402 0x10c91 : []int32{68817},
1403 0x10c92 : []int32{68818},
1404 0x10c93 : []int32{68819},
1405 0x10c94 : []int32{68820},
1406 0x10c95 : []int32{68821},
1407 0x10c96 : []int32{68822},
1408 0x10c97 : []int32{68823},
1409 0x10c98 : []int32{68824},
1410 0x10c99 : []int32{68825},
1411 0x10c9a : []int32{68826},
1412 0x10c9b : []int32{68827},
1413 0x10c9c : []int32{68828},
1414 0x10c9d : []int32{68829},
1415 0x10c9e : []int32{68830},
1416 0x10c9f : []int32{68831},
1417 0x10ca0 : []int32{68832},
1418 0x10ca1 : []int32{68833},
1419 0x10ca2 : []int32{68834},
1420 0x10ca3 : []int32{68835},
1421 0x10ca4 : []int32{68836},
1422 0x10ca5 : []int32{68837},
1423 0x10ca6 : []int32{68838},
1424 0x10ca7 : []int32{68839},
1425 0x10ca8 : []int32{68840},
1426 0x10ca9 : []int32{68841},
1427 0x10caa : []int32{68842},
1428 0x10cab : []int32{68843},
1429 0x10cac : []int32{68844},
1430 0x10cad : []int32{68845},
1431 0x10cae : []int32{68846},
1432 0x10caf : []int32{68847},
1433 0x10cb0 : []int32{68848},
1434 0x10cb1 : []int32{68849},
1435 0x10cb2 : []int32{68850},
1436 0x118a0 : []int32{71872},
1437 0x118a1 : []int32{71873},
1438 0x118a2 : []int32{71874},
1439 0x118a3 : []int32{71875},
1440 0x118a4 : []int32{71876},
1441 0x118a5 : []int32{71877},
1442 0x118a6 : []int32{71878},
1443 0x118a7 : []int32{71879},
1444 0x118a8 : []int32{71880},
1445 0x118a9 : []int32{71881},
1446 0x118aa : []int32{71882},
1447 0x118ab : []int32{71883},
1448 0x118ac : []int32{71884},
1449 0x118ad : []int32{71885},
1450 0x118ae : []int32{71886},
1451 0x118af : []int32{71887},
1452 0x118b0 : []int32{71888},
1453 0x118b1 : []int32{71889},
1454 0x118b2 : []int32{71890},
1455 0x118b3 : []int32{71891},
1456 0x118b4 : []int32{71892},
1457 0x118b5 : []int32{71893},
1458 0x118b6 : []int32{71894},
1459 0x118b7 : []int32{71895},
1460 0x118b8 : []int32{71896},
1461 0x118b9 : []int32{71897},
1462 0x118ba : []int32{71898},
1463 0x118bb : []int32{71899},
1464 0x118bc : []int32{71900},
1465 0x118bd : []int32{71901},
1466 0x118be : []int32{71902},
1467 0x118bf : []int32{71903},
1468 0x16e40 : []int32{93792},
1469 0x16e41 : []int32{93793},
1470 0x16e42 : []int32{93794},
1471 0x16e43 : []int32{93795},
1472 0x16e44 : []int32{93796},
1473 0x16e45 : []int32{93797},
1474 0x16e46 : []int32{93798},
1475 0x16e47 : []int32{93799},
1476 0x16e48 : []int32{93800},
1477 0x16e49 : []int32{93801},
1478 0x16e4a : []int32{93802},
1479 0x16e4b : []int32{93803},
1480 0x16e4c : []int32{93804},
1481 0x16e4d : []int32{93805},
1482 0x16e4e : []int32{93806},
1483 0x16e4f : []int32{93807},
1484 0x16e50 : []int32{93808},
1485 0x16e51 : []int32{93809},
1486 0x16e52 : []int32{93810},
1487 0x16e53 : []int32{93811},
1488 0x16e54 : []int32{93812},
1489 0x16e55 : []int32{93813},
1490 0x16e56 : []int32{93814},
1491 0x16e57 : []int32{93815},
1492 0x16e58 : []int32{93816},
1493 0x16e59 : []int32{93817},
1494 0x16e5a : []int32{93818},
1495 0x16e5b : []int32{93819},
1496 0x16e5c : []int32{93820},
1497 0x16e5d : []int32{93821},
1498 0x16e5e : []int32{93822},
1499 0x16e5f : []int32{93823},
1500 0x1e900 : []int32{125218},
1501 0x1e901 : []int32{125219},
1502 0x1e902 : []int32{125220},
1503 0x1e903 : []int32{125221},
1504 0x1e904 : []int32{125222},
1505 0x1e905 : []int32{125223},
1506 0x1e906 : []int32{125224},
1507 0x1e907 : []int32{125225},
1508 0x1e908 : []int32{125226},
1509 0x1e909 : []int32{125227},
1510 0x1e90a : []int32{125228},
1511 0x1e90b : []int32{125229},
1512 0x1e90c : []int32{125230},
1513 0x1e90d : []int32{125231},
1514 0x1e90e : []int32{125232},
1515 0x1e90f : []int32{125233},
1516 0x1e910 : []int32{125234},
1517 0x1e911 : []int32{125235},
1518 0x1e912 : []int32{125236},
1519 0x1e913 : []int32{125237},
1520 0x1e914 : []int32{125238},
1521 0x1e915 : []int32{125239},
1522 0x1e916 : []int32{125240},
1523 0x1e917 : []int32{125241},
1524 0x1e918 : []int32{125242},
1525 0x1e919 : []int32{125243},
1526 0x1e91a : []int32{125244},
1527 0x1e91b : []int32{125245},
1528 0x1e91c : []int32{125246},
1529 0x1e91d : []int32{125247},
1530 0x1e91e : []int32{125248},
1531 0x1e91f : []int32{125249},
1532 0x1e920 : []int32{125250},
1533 0x1e921 : []int32{125251},
1534}
diff --git a/vendor/github.com/yuin/goldmark/util/util.go b/vendor/github.com/yuin/goldmark/util/util.go
new file mode 100644
index 0000000..88d2538
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util.go
@@ -0,0 +1,989 @@
1// Package util provides utility functions for the goldmark.
2package util
3
4import (
5 "bytes"
6 "io"
7 "net/url"
8 "regexp"
9 "sort"
10 "strconv"
11 "unicode"
12 "unicode/utf8"
13)
14
15// A CopyOnWriteBuffer is a byte buffer that copies buffer when
16// it need to be changed.
17type CopyOnWriteBuffer struct {
18 buffer []byte
19 copied bool
20}
21
22// NewCopyOnWriteBuffer returns a new CopyOnWriteBuffer.
23func NewCopyOnWriteBuffer(buffer []byte) CopyOnWriteBuffer {
24 return CopyOnWriteBuffer{
25 buffer: buffer,
26 copied: false,
27 }
28}
29
30// Write writes given bytes to the buffer.
31// Write allocate new buffer and clears it at the first time.
32func (b *CopyOnWriteBuffer) Write(value []byte) {
33 if !b.copied {
34 b.buffer = make([]byte, 0, len(b.buffer)+20)
35 b.copied = true
36 }
37 b.buffer = append(b.buffer, value...)
38}
39
40// WriteString writes given string to the buffer.
41// WriteString allocate new buffer and clears it at the first time.
42func (b *CopyOnWriteBuffer) WriteString(value string) {
43 b.Write(StringToReadOnlyBytes(value))
44}
45
46// Append appends given bytes to the buffer.
47// Append copy buffer at the first time.
48func (b *CopyOnWriteBuffer) Append(value []byte) {
49 if !b.copied {
50 tmp := make([]byte, len(b.buffer), len(b.buffer)+20)
51 copy(tmp, b.buffer)
52 b.buffer = tmp
53 b.copied = true
54 }
55 b.buffer = append(b.buffer, value...)
56}
57
58// AppendString appends given string to the buffer.
59// AppendString copy buffer at the first time.
60func (b *CopyOnWriteBuffer) AppendString(value string) {
61 b.Append(StringToReadOnlyBytes(value))
62}
63
64// WriteByte writes the given byte to the buffer.
65// WriteByte allocate new buffer and clears it at the first time.
66func (b *CopyOnWriteBuffer) WriteByte(c byte) {
67 if !b.copied {
68 b.buffer = make([]byte, 0, len(b.buffer)+20)
69 b.copied = true
70 }
71 b.buffer = append(b.buffer, c)
72}
73
74// AppendByte appends given bytes to the buffer.
75// AppendByte copy buffer at the first time.
76func (b *CopyOnWriteBuffer) AppendByte(c byte) {
77 if !b.copied {
78 tmp := make([]byte, len(b.buffer), len(b.buffer)+20)
79 copy(tmp, b.buffer)
80 b.buffer = tmp
81 b.copied = true
82 }
83 b.buffer = append(b.buffer, c)
84}
85
86// Bytes returns bytes of this buffer.
87func (b *CopyOnWriteBuffer) Bytes() []byte {
88 return b.buffer
89}
90
91// IsCopied returns true if buffer has been copied, otherwise false.
92func (b *CopyOnWriteBuffer) IsCopied() bool {
93 return b.copied
94}
95
96// IsEscapedPunctuation returns true if character at a given index i
97// is an escaped punctuation, otherwise false.
98func IsEscapedPunctuation(source []byte, i int) bool {
99 return source[i] == '\\' && i < len(source)-1 && IsPunct(source[i+1])
100}
101
102// ReadWhile read the given source while pred is true.
103func ReadWhile(source []byte, index [2]int, pred func(byte) bool) (int, bool) {
104 j := index[0]
105 ok := false
106 for ; j < index[1]; j++ {
107 c1 := source[j]
108 if pred(c1) {
109 ok = true
110 continue
111 }
112 break
113 }
114 return j, ok
115}
116
117// IsBlank returns true if the given string is all space characters.
118func IsBlank(bs []byte) bool {
119 for _, b := range bs {
120 if !IsSpace(b) {
121 return false
122 }
123 }
124 return true
125}
126
127// VisualizeSpaces visualize invisible space characters.
128func VisualizeSpaces(bs []byte) []byte {
129 bs = bytes.Replace(bs, []byte(" "), []byte("[SPACE]"), -1)
130 bs = bytes.Replace(bs, []byte("\t"), []byte("[TAB]"), -1)
131 bs = bytes.Replace(bs, []byte("\n"), []byte("[NEWLINE]\n"), -1)
132 bs = bytes.Replace(bs, []byte("\r"), []byte("[CR]"), -1)
133 bs = bytes.Replace(bs, []byte("\v"), []byte("[VTAB]"), -1)
134 bs = bytes.Replace(bs, []byte("\x00"), []byte("[NUL]"), -1)
135 bs = bytes.Replace(bs, []byte("\ufffd"), []byte("[U+FFFD]"), -1)
136 return bs
137}
138
139// TabWidth calculates actual width of a tab at the given position.
140func TabWidth(currentPos int) int {
141 return 4 - currentPos%4
142}
143
144// IndentPosition searches an indent position with the given width for the given line.
145// If the line contains tab characters, paddings may be not zero.
146// currentPos==0 and width==2:
147//
148// position: 0 1
149// [TAB]aaaa
150// width: 1234 5678
151//
152// width=2 is in the tab character. In this case, IndentPosition returns
153// (pos=1, padding=2)
154func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
155 return IndentPositionPadding(bs, currentPos, 0, width)
156}
157
158// IndentPositionPadding searches an indent position with the given width for the given line.
159// This function is mostly same as IndentPosition except this function
160// takes account into additional paddings.
161func IndentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
162 if width == 0 {
163 return 0, paddingv
164 }
165 w := 0
166 i := 0
167 l := len(bs)
168 for ; i < l; i++ {
169 if bs[i] == '\t' && w < width {
170 w += TabWidth(currentPos + w)
171 } else if bs[i] == ' ' && w < width {
172 w++
173 } else {
174 break
175 }
176 }
177 if w >= width {
178 return i - paddingv, w - width
179 }
180 return -1, -1
181}
182
183// DedentPosition dedents lines by the given width.
184//
185// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
186func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
187 if width == 0 {
188 return 0, 0
189 }
190 w := 0
191 l := len(bs)
192 i := 0
193 for ; i < l; i++ {
194 if bs[i] == '\t' {
195 w += TabWidth(currentPos + w)
196 } else if bs[i] == ' ' {
197 w++
198 } else {
199 break
200 }
201 }
202 if w >= width {
203 return i, w - width
204 }
205 return i, 0
206}
207
208// DedentPositionPadding dedents lines by the given width.
209// This function is mostly same as DedentPosition except this function
210// takes account into additional paddings.
211//
212// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
213func DedentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
214 if width == 0 {
215 return 0, paddingv
216 }
217
218 w := 0
219 i := 0
220 l := len(bs)
221 for ; i < l; i++ {
222 if bs[i] == '\t' {
223 w += TabWidth(currentPos + w)
224 } else if bs[i] == ' ' {
225 w++
226 } else {
227 break
228 }
229 }
230 if w >= width {
231 return i - paddingv, w - width
232 }
233 return i - paddingv, 0
234}
235
236// IndentWidth calculate an indent width for the given line.
237func IndentWidth(bs []byte, currentPos int) (width, pos int) {
238 l := len(bs)
239 for i := 0; i < l; i++ {
240 b := bs[i]
241 if b == ' ' {
242 width++
243 pos++
244 } else if b == '\t' {
245 width += TabWidth(currentPos + width)
246 pos++
247 } else {
248 break
249 }
250 }
251 return
252}
253
254// FirstNonSpacePosition returns a position line that is a first nonspace
255// character.
256func FirstNonSpacePosition(bs []byte) int {
257 i := 0
258 for ; i < len(bs); i++ {
259 c := bs[i]
260 if c == ' ' || c == '\t' {
261 continue
262 }
263 if c == '\n' {
264 return -1
265 }
266 return i
267 }
268 return -1
269}
270
271// FindClosure returns a position that closes the given opener.
272// If codeSpan is set true, it ignores characters in code spans.
273// If allowNesting is set true, closures correspond to nested opener will be
274// ignored.
275//
276// Deprecated: This function can not handle newlines. Many elements
277// can be existed over multiple lines(e.g. link labels).
278// Use text.Reader.FindClosure.
279func FindClosure(bs []byte, opener, closure byte, codeSpan, allowNesting bool) int {
280 i := 0
281 opened := 1
282 codeSpanOpener := 0
283 for i < len(bs) {
284 c := bs[i]
285 if codeSpan && codeSpanOpener != 0 && c == '`' {
286 codeSpanCloser := 0
287 for ; i < len(bs); i++ {
288 if bs[i] == '`' {
289 codeSpanCloser++
290 } else {
291 i--
292 break
293 }
294 }
295 if codeSpanCloser == codeSpanOpener {
296 codeSpanOpener = 0
297 }
298 } else if codeSpanOpener == 0 && c == '\\' && i < len(bs)-1 && IsPunct(bs[i+1]) {
299 i += 2
300 continue
301 } else if codeSpan && codeSpanOpener == 0 && c == '`' {
302 for ; i < len(bs); i++ {
303 if bs[i] == '`' {
304 codeSpanOpener++
305 } else {
306 i--
307 break
308 }
309 }
310 } else if (codeSpan && codeSpanOpener == 0) || !codeSpan {
311 if c == closure {
312 opened--
313 if opened == 0 {
314 return i
315 }
316 } else if c == opener {
317 if !allowNesting {
318 return -1
319 }
320 opened++
321 }
322 }
323 i++
324 }
325 return -1
326}
327
328// TrimLeft trims characters in the given s from head of the source.
329// bytes.TrimLeft offers same functionalities, but bytes.TrimLeft
330// allocates new buffer for the result.
331func TrimLeft(source, b []byte) []byte {
332 i := 0
333 for ; i < len(source); i++ {
334 c := source[i]
335 found := false
336 for j := 0; j < len(b); j++ {
337 if c == b[j] {
338 found = true
339 break
340 }
341 }
342 if !found {
343 break
344 }
345 }
346 return source[i:]
347}
348
349// TrimRight trims characters in the given s from tail of the source.
350func TrimRight(source, b []byte) []byte {
351 i := len(source) - 1
352 for ; i >= 0; i-- {
353 c := source[i]
354 found := false
355 for j := 0; j < len(b); j++ {
356 if c == b[j] {
357 found = true
358 break
359 }
360 }
361 if !found {
362 break
363 }
364 }
365 return source[:i+1]
366}
367
368// TrimLeftLength returns a length of leading specified characters.
369func TrimLeftLength(source, s []byte) int {
370 return len(source) - len(TrimLeft(source, s))
371}
372
373// TrimRightLength returns a length of trailing specified characters.
374func TrimRightLength(source, s []byte) int {
375 return len(source) - len(TrimRight(source, s))
376}
377
378// TrimLeftSpaceLength returns a length of leading space characters.
379func TrimLeftSpaceLength(source []byte) int {
380 i := 0
381 for ; i < len(source); i++ {
382 if !IsSpace(source[i]) {
383 break
384 }
385 }
386 return i
387}
388
389// TrimRightSpaceLength returns a length of trailing space characters.
390func TrimRightSpaceLength(source []byte) int {
391 l := len(source)
392 i := l - 1
393 for ; i >= 0; i-- {
394 if !IsSpace(source[i]) {
395 break
396 }
397 }
398 if i < 0 {
399 return l
400 }
401 return l - 1 - i
402}
403
404// TrimLeftSpace returns a subslice of the given string by slicing off all leading
405// space characters.
406func TrimLeftSpace(source []byte) []byte {
407 return TrimLeft(source, spaces)
408}
409
410// TrimRightSpace returns a subslice of the given string by slicing off all trailing
411// space characters.
412func TrimRightSpace(source []byte) []byte {
413 return TrimRight(source, spaces)
414}
415
416// DoFullUnicodeCaseFolding performs full unicode case folding to given bytes.
417func DoFullUnicodeCaseFolding(v []byte) []byte {
418 var rbuf []byte
419 cob := NewCopyOnWriteBuffer(v)
420 n := 0
421 for i := 0; i < len(v); i++ {
422 c := v[i]
423 if c < 0xb5 {
424 if c >= 0x41 && c <= 0x5a {
425 // A-Z to a-z
426 cob.Write(v[n:i])
427 cob.WriteByte(c + 32)
428 n = i + 1
429 }
430 continue
431 }
432
433 if !utf8.RuneStart(c) {
434 continue
435 }
436 r, length := utf8.DecodeRune(v[i:])
437 if r == utf8.RuneError {
438 continue
439 }
440 folded, ok := unicodeCaseFoldings[r]
441 if !ok {
442 continue
443 }
444
445 cob.Write(v[n:i])
446 if rbuf == nil {
447 rbuf = make([]byte, 4)
448 }
449 for _, f := range folded {
450 l := utf8.EncodeRune(rbuf, f)
451 cob.Write(rbuf[:l])
452 }
453 i += length - 1
454 n = i + 1
455 }
456 if cob.IsCopied() {
457 cob.Write(v[n:])
458 }
459 return cob.Bytes()
460}
461
462// ReplaceSpaces replaces sequence of spaces with the given repl.
463func ReplaceSpaces(source []byte, repl byte) []byte {
464 var ret []byte
465 start := -1
466 for i, c := range source {
467 iss := IsSpace(c)
468 if start < 0 && iss {
469 start = i
470 continue
471 } else if start >= 0 && iss {
472 continue
473 } else if start >= 0 {
474 if ret == nil {
475 ret = make([]byte, 0, len(source))
476 ret = append(ret, source[:start]...)
477 }
478 ret = append(ret, repl)
479 start = -1
480 }
481 if ret != nil {
482 ret = append(ret, c)
483 }
484 }
485 if start >= 0 && ret != nil {
486 ret = append(ret, repl)
487 }
488 if ret == nil {
489 return source
490 }
491 return ret
492}
493
494// ToRune decode given bytes start at pos and returns a rune.
495func ToRune(source []byte, pos int) rune {
496 i := pos
497 for ; i >= 0; i-- {
498 if utf8.RuneStart(source[i]) {
499 break
500 }
501 }
502 r, _ := utf8.DecodeRune(source[i:])
503 return r
504}
505
506// ToValidRune returns 0xFFFD if the given rune is invalid, otherwise v.
507func ToValidRune(v rune) rune {
508 if v == 0 || !utf8.ValidRune(v) {
509 return rune(0xFFFD)
510 }
511 return v
512}
513
514// ToLinkReference converts given bytes into a valid link reference string.
515// ToLinkReference performs unicode case folding, trims leading and trailing spaces, converts into lower
516// case and replace spaces with a single space character.
517func ToLinkReference(v []byte) string {
518 v = TrimLeftSpace(v)
519 v = TrimRightSpace(v)
520 v = DoFullUnicodeCaseFolding(v)
521 return string(ReplaceSpaces(v, ' '))
522}
523
524var htmlEscapeTable = [256][]byte{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("&quot;"), nil, nil, nil, []byte("&amp;"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("&lt;"), nil, []byte("&gt;"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}
525
526// EscapeHTMLByte returns HTML escaped bytes if the given byte should be escaped,
527// otherwise nil.
528func EscapeHTMLByte(b byte) []byte {
529 return htmlEscapeTable[b]
530}
531
532// EscapeHTML escapes characters that should be escaped in HTML text.
533func EscapeHTML(v []byte) []byte {
534 cob := NewCopyOnWriteBuffer(v)
535 n := 0
536 for i := 0; i < len(v); i++ {
537 c := v[i]
538 escaped := htmlEscapeTable[c]
539 if escaped != nil {
540 cob.Write(v[n:i])
541 cob.Write(escaped)
542 n = i + 1
543 }
544 }
545 if cob.IsCopied() {
546 cob.Write(v[n:])
547 }
548 return cob.Bytes()
549}
550
551// UnescapePunctuations unescapes blackslash escaped punctuations.
552func UnescapePunctuations(source []byte) []byte {
553 cob := NewCopyOnWriteBuffer(source)
554 limit := len(source)
555 n := 0
556 for i := 0; i < limit; {
557 c := source[i]
558 if i < limit-1 && c == '\\' && IsPunct(source[i+1]) {
559 cob.Write(source[n:i])
560 cob.WriteByte(source[i+1])
561 i += 2
562 n = i
563 continue
564 }
565 i++
566 }
567 if cob.IsCopied() {
568 cob.Write(source[n:])
569 }
570 return cob.Bytes()
571}
572
573// ResolveNumericReferences resolve numeric references like '&#1234;" .
574func ResolveNumericReferences(source []byte) []byte {
575 cob := NewCopyOnWriteBuffer(source)
576 buf := make([]byte, 6, 6)
577 limit := len(source)
578 ok := false
579 n := 0
580 for i := 0; i < limit; i++ {
581 if source[i] == '&' {
582 pos := i
583 next := i + 1
584 if next < limit && source[next] == '#' {
585 nnext := next + 1
586 if nnext < limit {
587 nc := source[nnext]
588 // code point like #x22;
589 if nnext < limit && nc == 'x' || nc == 'X' {
590 start := nnext + 1
591 i, ok = ReadWhile(source, [2]int{start, limit}, IsHexDecimal)
592 if ok && i < limit && source[i] == ';' {
593 v, _ := strconv.ParseUint(BytesToReadOnlyString(source[start:i]), 16, 32)
594 cob.Write(source[n:pos])
595 n = i + 1
596 runeSize := utf8.EncodeRune(buf, ToValidRune(rune(v)))
597 cob.Write(buf[:runeSize])
598 continue
599 }
600 // code point like #1234;
601 } else if nc >= '0' && nc <= '9' {
602 start := nnext
603 i, ok = ReadWhile(source, [2]int{start, limit}, IsNumeric)
604 if ok && i < limit && i-start < 8 && source[i] == ';' {
605 v, _ := strconv.ParseUint(BytesToReadOnlyString(source[start:i]), 0, 32)
606 cob.Write(source[n:pos])
607 n = i + 1
608 runeSize := utf8.EncodeRune(buf, ToValidRune(rune(v)))
609 cob.Write(buf[:runeSize])
610 continue
611 }
612 }
613 }
614 }
615 i = next - 1
616 }
617 }
618 if cob.IsCopied() {
619 cob.Write(source[n:])
620 }
621 return cob.Bytes()
622}
623
624// ResolveEntityNames resolve entity references like '&ouml;" .
625func ResolveEntityNames(source []byte) []byte {
626 cob := NewCopyOnWriteBuffer(source)
627 limit := len(source)
628 ok := false
629 n := 0
630 for i := 0; i < limit; i++ {
631 if source[i] == '&' {
632 pos := i
633 next := i + 1
634 if !(next < limit && source[next] == '#') {
635 start := next
636 i, ok = ReadWhile(source, [2]int{start, limit}, IsAlphaNumeric)
637 if ok && i < limit && source[i] == ';' {
638 name := BytesToReadOnlyString(source[start:i])
639 entity, ok := LookUpHTML5EntityByName(name)
640 if ok {
641 cob.Write(source[n:pos])
642 n = i + 1
643 cob.Write(entity.Characters)
644 continue
645 }
646 }
647 }
648 i = next - 1
649 }
650 }
651 if cob.IsCopied() {
652 cob.Write(source[n:])
653 }
654 return cob.Bytes()
655}
656
657var htmlSpace = []byte("%20")
658
659// URLEscape escape the given URL.
660// If resolveReference is set true:
661// 1. unescape punctuations
662// 2. resolve numeric references
663// 3. resolve entity references
664//
665// URL encoded values (%xx) are kept as is.
666func URLEscape(v []byte, resolveReference bool) []byte {
667 if resolveReference {
668 v = UnescapePunctuations(v)
669 v = ResolveNumericReferences(v)
670 v = ResolveEntityNames(v)
671 }
672 cob := NewCopyOnWriteBuffer(v)
673 limit := len(v)
674 n := 0
675
676 for i := 0; i < limit; {
677 c := v[i]
678 if urlEscapeTable[c] == 1 {
679 i++
680 continue
681 }
682 if c == '%' && i+2 < limit && IsHexDecimal(v[i+1]) && IsHexDecimal(v[i+1]) {
683 i += 3
684 continue
685 }
686 u8len := utf8lenTable[c]
687 if u8len == 99 { // invalid utf8 leading byte, skip it
688 i++
689 continue
690 }
691 if c == ' ' {
692 cob.Write(v[n:i])
693 cob.Write(htmlSpace)
694 i++
695 n = i
696 continue
697 }
698 if int(u8len) > len(v) {
699 u8len = int8(len(v) - 1)
700 }
701 if u8len == 0 {
702 i++
703 n = i
704 continue
705 }
706 cob.Write(v[n:i])
707 stop := i + int(u8len)
708 if stop > len(v) {
709 i++
710 n = i
711 continue
712 }
713 cob.Write(StringToReadOnlyBytes(url.QueryEscape(string(v[i:stop]))))
714 i += int(u8len)
715 n = i
716 }
717 if cob.IsCopied() && n < limit {
718 cob.Write(v[n:])
719 }
720 return cob.Bytes()
721}
722
723// FindURLIndex returns a stop index value if the given bytes seem an URL.
724// This function is equivalent to [A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]* .
725func FindURLIndex(b []byte) int {
726 i := 0
727 if !(len(b) > 0 && urlTable[b[i]]&7 == 7) {
728 return -1
729 }
730 i++
731 for ; i < len(b); i++ {
732 c := b[i]
733 if urlTable[c]&4 != 4 {
734 break
735 }
736 }
737 if i == 1 || i > 33 || i >= len(b) {
738 return -1
739 }
740 if b[i] != ':' {
741 return -1
742 }
743 i++
744 for ; i < len(b); i++ {
745 c := b[i]
746 if urlTable[c]&1 != 1 {
747 break
748 }
749 }
750 return i
751}
752
753var emailDomainRegexp = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*`)
754
755// FindEmailIndex returns a stop index value if the given bytes seem an email address.
756func FindEmailIndex(b []byte) int {
757 // TODO: eliminate regexps
758 i := 0
759 for ; i < len(b); i++ {
760 c := b[i]
761 if emailTable[c]&1 != 1 {
762 break
763 }
764 }
765 if i == 0 {
766 return -1
767 }
768 if i >= len(b) || b[i] != '@' {
769 return -1
770 }
771 i++
772 if i >= len(b) {
773 return -1
774 }
775 match := emailDomainRegexp.FindSubmatchIndex(b[i:])
776 if match == nil {
777 return -1
778 }
779 return i + match[1]
780}
781
782var spaces = []byte(" \t\n\x0b\x0c\x0d")
783
784var spaceTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
785
786var punctTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
787
788// a-zA-Z0-9, ;/?:@&=+$,-_.!~*'()#
789var urlEscapeTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
790
791var utf8lenTable = [256]int8{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 99, 99, 99, 99, 99, 99, 99, 99}
792
793var urlTable = [256]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 5, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 0, 1, 0, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
794
795var emailTable = [256]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
796
797// UTF8Len returns a byte length of the utf-8 character.
798func UTF8Len(b byte) int8 {
799 return utf8lenTable[b]
800}
801
802// IsPunct returns true if the given character is a punctuation, otherwise false.
803func IsPunct(c byte) bool {
804 return punctTable[c] == 1
805}
806
807// IsPunctRune returns true if the given rune is a punctuation, otherwise false.
808func IsPunctRune(r rune) bool {
809 return int32(r) <= 256 && IsPunct(byte(r)) || unicode.IsPunct(r)
810}
811
812// IsSpace returns true if the given character is a space, otherwise false.
813func IsSpace(c byte) bool {
814 return spaceTable[c] == 1
815}
816
817// IsSpaceRune returns true if the given rune is a space, otherwise false.
818func IsSpaceRune(r rune) bool {
819 return int32(r) <= 256 && IsSpace(byte(r)) || unicode.IsSpace(r)
820}
821
822// IsNumeric returns true if the given character is a numeric, otherwise false.
823func IsNumeric(c byte) bool {
824 return c >= '0' && c <= '9'
825}
826
827// IsHexDecimal returns true if the given character is a hexdecimal, otherwise false.
828func IsHexDecimal(c byte) bool {
829 return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F'
830}
831
832// IsAlphaNumeric returns true if the given character is a alphabet or a numeric, otherwise false.
833func IsAlphaNumeric(c byte) bool {
834 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'
835}
836
837// IsEastAsianWideRune returns trhe if the given rune is an east asian wide character, otherwise false.
838func IsEastAsianWideRune(r rune) bool {
839 return unicode.Is(unicode.Hiragana, r) ||
840 unicode.Is(unicode.Katakana, r) ||
841 unicode.Is(unicode.Han, r) ||
842 unicode.Is(unicode.Lm, r) ||
843 unicode.Is(unicode.Hangul, r)
844}
845
846// A BufWriter is a subset of the bufio.Writer .
847type BufWriter interface {
848 io.Writer
849 Available() int
850 Buffered() int
851 Flush() error
852 WriteByte(c byte) error
853 WriteRune(r rune) (size int, err error)
854 WriteString(s string) (int, error)
855}
856
857// A PrioritizedValue struct holds pair of an arbitrary value and a priority.
858type PrioritizedValue struct {
859 // Value is an arbitrary value that you want to prioritize.
860 Value interface{}
861 // Priority is a priority of the value.
862 Priority int
863}
864
865// PrioritizedSlice is a slice of the PrioritizedValues
866type PrioritizedSlice []PrioritizedValue
867
868// Sort sorts the PrioritizedSlice in ascending order.
869func (s PrioritizedSlice) Sort() {
870 sort.Slice(s, func(i, j int) bool {
871 return s[i].Priority < s[j].Priority
872 })
873}
874
875// Remove removes the given value from this slice.
876func (s PrioritizedSlice) Remove(v interface{}) PrioritizedSlice {
877 i := 0
878 found := false
879 for ; i < len(s); i++ {
880 if s[i].Value == v {
881 found = true
882 break
883 }
884 }
885 if !found {
886 return s
887 }
888 return append(s[:i], s[i+1:]...)
889}
890
891// Prioritized returns a new PrioritizedValue.
892func Prioritized(v interface{}, priority int) PrioritizedValue {
893 return PrioritizedValue{v, priority}
894}
895
896func bytesHash(b []byte) uint64 {
897 var hash uint64 = 5381
898 for _, c := range b {
899 hash = ((hash << 5) + hash) + uint64(c)
900 }
901 return hash
902}
903
904// BytesFilter is a efficient data structure for checking whether bytes exist or not.
905// BytesFilter is thread-safe.
906type BytesFilter interface {
907 // Add adds given bytes to this set.
908 Add([]byte)
909
910 // Contains return true if this set contains given bytes, otherwise false.
911 Contains([]byte) bool
912
913 // Extend copies this filter and adds given bytes to new filter.
914 Extend(...[]byte) BytesFilter
915}
916
917type bytesFilter struct {
918 chars [256]uint8
919 threshold int
920 slots [][][]byte
921}
922
923// NewBytesFilter returns a new BytesFilter.
924func NewBytesFilter(elements ...[]byte) BytesFilter {
925 s := &bytesFilter{
926 threshold: 3,
927 slots: make([][][]byte, 64),
928 }
929 for _, element := range elements {
930 s.Add(element)
931 }
932 return s
933}
934
935func (s *bytesFilter) Add(b []byte) {
936 l := len(b)
937 m := s.threshold
938 if l < s.threshold {
939 m = l
940 }
941 for i := 0; i < m; i++ {
942 s.chars[b[i]] |= 1 << uint8(i)
943 }
944 h := bytesHash(b) % uint64(len(s.slots))
945 slot := s.slots[h]
946 if slot == nil {
947 slot = [][]byte{}
948 }
949 s.slots[h] = append(slot, b)
950}
951
952func (s *bytesFilter) Extend(bs ...[]byte) BytesFilter {
953 newFilter := NewBytesFilter().(*bytesFilter)
954 newFilter.chars = s.chars
955 newFilter.threshold = s.threshold
956 for k, v := range s.slots {
957 newSlot := make([][]byte, len(v))
958 copy(newSlot, v)
959 newFilter.slots[k] = v
960 }
961 for _, b := range bs {
962 newFilter.Add(b)
963 }
964 return newFilter
965}
966
967func (s *bytesFilter) Contains(b []byte) bool {
968 l := len(b)
969 m := s.threshold
970 if l < s.threshold {
971 m = l
972 }
973 for i := 0; i < m; i++ {
974 if (s.chars[b[i]] & (1 << uint8(i))) == 0 {
975 return false
976 }
977 }
978 h := bytesHash(b) % uint64(len(s.slots))
979 slot := s.slots[h]
980 if slot == nil || len(slot) == 0 {
981 return false
982 }
983 for _, element := range slot {
984 if bytes.Equal(element, b) {
985 return true
986 }
987 }
988 return false
989}
diff --git a/vendor/github.com/yuin/goldmark/util/util_safe.go b/vendor/github.com/yuin/goldmark/util/util_safe.go
new file mode 100644
index 0000000..507a9d0
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util_safe.go
@@ -0,0 +1,13 @@
1// +build appengine js
2
3package util
4
5// BytesToReadOnlyString returns a string converted from given bytes.
6func BytesToReadOnlyString(b []byte) string {
7 return string(b)
8}
9
10// StringToReadOnlyBytes returns bytes converted from given string.
11func StringToReadOnlyBytes(s string) []byte {
12 return []byte(s)
13}
diff --git a/vendor/github.com/yuin/goldmark/util/util_unsafe.go b/vendor/github.com/yuin/goldmark/util/util_unsafe.go
new file mode 100644
index 0000000..d098811
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util_unsafe.go
@@ -0,0 +1,23 @@
1// +build !appengine,!js
2
3package util
4
5import (
6 "reflect"
7 "unsafe"
8)
9
10// BytesToReadOnlyString returns a string converted from given bytes.
11func BytesToReadOnlyString(b []byte) string {
12 return *(*string)(unsafe.Pointer(&b))
13}
14
15// StringToReadOnlyBytes returns bytes converted from given string.
16func StringToReadOnlyBytes(s string) (bs []byte) {
17 sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
18 bh := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
19 bh.Data = sh.Data
20 bh.Cap = sh.Len
21 bh.Len = sh.Len
22 return
23}