From efd1a4f717afa83d3d3609f0d70e4da151a8dc9b Mon Sep 17 00:00:00 2001
From: tobi <31960611+tsmethurst@users.noreply.github.com>
Date: Mon, 16 Sep 2024 14:00:23 +0200
Subject: [PATCH] [bugfix] Use better plaintext representation of status for
filtering (#3301)
* [bugfix] Use better plaintext representation of status for filtering
* add new deps to readme
* lint
* update tests
* update regexes
* address review comments
* remove now unused xxhash
* whoops, wrong logger
* Merge branch 'main' into status_filtering_bugfix
* put cache in caches struct
* pain
---
README.md | 1 +
go.mod | 1 +
go.sum | 2 +
internal/cache/cache.go | 20 +
internal/gtsmodel/filter.go | 19 +-
internal/typeutils/internaltofrontend.go | 87 +-
internal/typeutils/internaltofrontend_test.go | 24 +-
internal/typeutils/util.go | 62 +
internal/typeutils/util_test.go | 60 +
vendor/github.com/k3a/html2text/.travis.yml | 10 +
vendor/github.com/k3a/html2text/LICENSE | 21 +
vendor/github.com/k3a/html2text/README.md | 60 +
vendor/github.com/k3a/html2text/entity.go | 2046 +++++++++++++++++
vendor/github.com/k3a/html2text/html2text.go | 333 +++
vendor/modules.txt | 3 +
15 files changed, 2685 insertions(+), 64 deletions(-)
create mode 100644 vendor/github.com/k3a/html2text/.travis.yml
create mode 100644 vendor/github.com/k3a/html2text/LICENSE
create mode 100644 vendor/github.com/k3a/html2text/README.md
create mode 100644 vendor/github.com/k3a/html2text/entity.go
create mode 100644 vendor/github.com/k3a/html2text/html2text.go
diff --git a/README.md b/README.md
index 755a9f79f..989b7c1fa 100644
--- a/README.md
+++ b/README.md
@@ -273,6 +273,7 @@ The following open source libraries, frameworks, and tools are used by GoToSocia
- [jackc/pgconn](https://github.com/jackc/pgconn); Postgres driver. [MIT License](https://spdx.org/licenses/MIT.html).
- [jackc/pgx](https://github.com/jackc/pgx); Postgres driver and toolkit. [MIT License](https://spdx.org/licenses/MIT.html).
- [KimMachineGun/automemlimit](https://github.com/KimMachineGun/automemlimit); cgroups memory limit checking. [MIT License](https://spdx.org/licenses/MIT.html).
+- [k3a/html2text](https://github.com/k3a/html2text); HTML-to-text conversion. [MIT License](https://spdx.org/licenses/MIT.html).
- [mcuadros/go-syslog](https://github.com/mcuadros/go-syslog); Syslog server library. [MIT License](https://spdx.org/licenses/MIT.html).
- [microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday); HTML user-input sanitization. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [miekg/dns](https://github.com/miekg/dns); DNS utilities. [Go License](https://go.dev/LICENSE).
diff --git a/go.mod b/go.mod
index e8bab31f4..a9a4afa84 100644
--- a/go.mod
+++ b/go.mod
@@ -40,6 +40,7 @@ require (
github.com/gorilla/feeds v1.2.0
github.com/gorilla/websocket v1.5.2
github.com/jackc/pgx/v5 v5.7.1
+ github.com/k3a/html2text v1.2.1
github.com/microcosm-cc/bluemonday v1.0.27
github.com/miekg/dns v1.1.62
github.com/minio/minio-go/v7 v7.0.76
diff --git a/go.sum b/go.sum
index 0dd75c4bb..8940bb3b2 100644
--- a/go.sum
+++ b/go.sum
@@ -384,6 +384,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
+github.com/k3a/html2text v1.2.1 h1:nvnKgBvBR/myqrwfLuiqecUtaK1lB9hGziIJKatNFVY=
+github.com/k3a/html2text v1.2.1/go.mod h1:ieEXykM67iT8lTvEWBh6fhpH4B23kB9OMKPdIBmgUqA=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
diff --git a/internal/cache/cache.go b/internal/cache/cache.go
index 5554445b2..8291dec5a 100644
--- a/internal/cache/cache.go
+++ b/internal/cache/cache.go
@@ -47,6 +47,11 @@ type Caches struct {
// Webfinger provides access to the webfinger URL cache.
Webfinger *ttl.Cache[string, string] // TTL=24hr, sweep=5min
+ // TTL cache of statuses -> filterable text fields.
+ // To ensure up-to-date fields, cache is keyed as:
+ // `[status.ID][status.UpdatedAt.Unix()]`
+ StatusesFilterableFields *ttl.Cache[string, []string]
+
// prevent pass-by-value.
_ nocopy
}
@@ -109,6 +114,7 @@ func (c *Caches) Init() {
c.initUserMuteIDs()
c.initWebfinger()
c.initVisibility()
+ c.initStatusesFilterableFields()
}
// Start will start any caches that require a background
@@ -119,6 +125,10 @@ func (c *Caches) Start() {
tryUntil("starting webfinger cache", 5, func() bool {
return c.Webfinger.Start(5 * time.Minute)
})
+
+ tryUntil("starting statusesFilterableFields cache", 5, func() bool {
+ return c.StatusesFilterableFields.Start(5 * time.Minute)
+ })
}
// Stop will stop any caches that require a background
@@ -127,6 +137,7 @@ func (c *Caches) Stop() {
log.Infof(nil, "stop: %p", c)
tryUntil("stopping webfinger cache", 5, c.Webfinger.Stop)
+ tryUntil("stopping statusesFilterableFields cache", 5, c.StatusesFilterableFields.Stop)
}
// Sweep will sweep all the available caches to ensure none
@@ -204,3 +215,12 @@ func (c *Caches) initWebfinger() {
24*time.Hour,
)
}
+
+func (c *Caches) initStatusesFilterableFields() {
+ c.StatusesFilterableFields = new(ttl.Cache[string, []string])
+ c.StatusesFilterableFields.Init(
+ 0,
+ 512,
+ 1*time.Hour,
+ )
+}
diff --git a/internal/gtsmodel/filter.go b/internal/gtsmodel/filter.go
index e670e6fc0..95047a44f 100644
--- a/internal/gtsmodel/filter.go
+++ b/internal/gtsmodel/filter.go
@@ -20,6 +20,8 @@ package gtsmodel
import (
"regexp"
"time"
+
+ "github.com/superseriousbusiness/gotosocial/internal/util"
)
// Filter stores a filter created by a local account.
@@ -61,14 +63,23 @@ type FilterKeyword struct {
// Compile will compile this FilterKeyword as a prepared regular expression.
func (k *FilterKeyword) Compile() (err error) {
- var wordBreak string
- if k.WholeWord != nil && *k.WholeWord {
- wordBreak = `\b`
+ var (
+ wordBreakStart string
+ wordBreakEnd string
+ )
+
+ if util.PtrOrZero(k.WholeWord) {
+ // Either word boundary or
+ // whitespace or start of line.
+ wordBreakStart = `(?:\b|\s|^)`
+ // Either word boundary or
+ // whitespace or end of line.
+ wordBreakEnd = `(?:\b|\s|$)`
}
// Compile keyword filter regexp.
quoted := regexp.QuoteMeta(k.Keyword)
- k.Regexp, err = regexp.Compile(`(?i)` + wordBreak + quoted + wordBreak)
+ k.Regexp, err = regexp.Compile(`(?i)` + wordBreakStart + quoted + wordBreakEnd)
return // caller is expected to wrap this error
}
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index 55af2c1f1..fe49766fa 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -21,6 +21,8 @@ import (
"context"
"errors"
"fmt"
+ "slices"
+ "strconv"
"strings"
"time"
@@ -35,7 +37,6 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/language"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/media"
- "github.com/superseriousbusiness/gotosocial/internal/text"
"github.com/superseriousbusiness/gotosocial/internal/uris"
"github.com/superseriousbusiness/gotosocial/internal/util"
)
@@ -939,32 +940,48 @@ func (c *Converter) statusToAPIFilterResults(
return nil, nil
}
- // Extract text fields from the status that we will match filters against.
- fields := filterableTextFields(s)
+ // Key this status based on ID + last updated time,
+ // to ensure we always filter on latest version.
+ statusKey := s.ID + strconv.FormatInt(s.UpdatedAt.Unix(), 10)
+
+ // Check if we have filterable fields cached for this status.
+ cache := c.state.Caches.StatusesFilterableFields
+ fields, stored := cache.Get(statusKey)
+ if !stored {
+ // We don't have filterable fields
+ // cached, calculate + cache now.
+ fields = filterableFields(s)
+ cache.Set(statusKey, fields)
+ }
// Record all matching warn filters and the reasons they matched.
filterResults := make([]apimodel.FilterResult, 0, len(filters))
for _, filter := range filters {
if !filterAppliesInContext(filter, filterContext) {
- // Filter doesn't apply to this context.
- continue
- }
- if filter.Expired(now) {
+ // Filter doesn't apply
+ // to this context.
continue
}
- // List all matching keywords.
+ if filter.Expired(now) {
+ // Filter doesn't
+ // apply anymore.
+ continue
+ }
+
+ // Assemble matching keywords (if any) from this filter.
keywordMatches := make([]string, 0, len(filter.Keywords))
- for _, filterKeyword := range filter.Keywords {
- var isMatch bool
- for _, field := range fields {
- if filterKeyword.Regexp.MatchString(field) {
- isMatch = true
- break
- }
- }
- if isMatch {
- keywordMatches = append(keywordMatches, filterKeyword.Keyword)
+ for _, keyword := range filter.Keywords {
+ // Check if at least one filterable field
+ // in the status matches on this filter.
+ if slices.ContainsFunc(
+ fields,
+ func(field string) bool {
+ return keyword.Regexp.MatchString(field)
+ },
+ ) {
+ // At least one field matched on this filter.
+ keywordMatches = append(keywordMatches, keyword.Keyword)
}
}
@@ -1001,40 +1018,6 @@ func (c *Converter) statusToAPIFilterResults(
return filterResults, nil
}
-// filterableTextFields returns all text from a status that we might want to filter on:
-// - content
-// - content warning
-// - media descriptions
-// - poll options
-func filterableTextFields(s *gtsmodel.Status) []string {
- fieldCount := 2 + len(s.Attachments)
- if s.Poll != nil {
- fieldCount += len(s.Poll.Options)
- }
- fields := make([]string, 0, fieldCount)
-
- if s.Content != "" {
- fields = append(fields, text.SanitizeToPlaintext(s.Content))
- }
- if s.ContentWarning != "" {
- fields = append(fields, s.ContentWarning)
- }
- for _, attachment := range s.Attachments {
- if attachment.Description != "" {
- fields = append(fields, attachment.Description)
- }
- }
- if s.Poll != nil {
- for _, option := range s.Poll.Options {
- if option != "" {
- fields = append(fields, option)
- }
- }
- }
-
- return fields
-}
-
// filterAppliesInContext returns whether a given filter applies in a given context.
func filterAppliesInContext(filter *gtsmodel.Filter, filterContext statusfilter.FilterContext) bool {
switch filterContext {
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
index 651ff867d..a44afe67e 100644
--- a/internal/typeutils/internaltofrontend_test.go
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -1063,15 +1063,21 @@ func (suite *InternalToFrontendTestSuite) TestHideFilteredBoostToFrontend() {
// Test that a hashtag filter for a hashtag in Mastodon HTML content works the way most users would expect.
func (suite *InternalToFrontendTestSuite) testHashtagFilteredStatusToFrontend(wholeWord bool, boost bool) {
- testStatus := suite.testStatuses["admin_account_status_1"]
+ testStatus := new(gtsmodel.Status)
+ *testStatus = *suite.testStatuses["admin_account_status_1"]
testStatus.Content = `
doggo doggin' it
#dogsofmastodon
`
if boost {
- // Modify a fixture boost into a boost of the above status.
- boostStatus := suite.testStatuses["admin_account_status_4"]
- boostStatus.BoostOf = testStatus
- boostStatus.BoostOfID = testStatus.ID
- testStatus = boostStatus
+ boost, err := suite.typeconverter.StatusToBoost(
+ context.Background(),
+ testStatus,
+ suite.testAccounts["admin_account"],
+ "",
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ testStatus = boost
}
requestingAccount := suite.testAccounts["local_account_1"]
@@ -1103,9 +1109,11 @@ func (suite *InternalToFrontendTestSuite) testHashtagFilteredStatusToFrontend(wh
[]*gtsmodel.Filter{filter},
nil,
)
- if suite.NoError(err) {
- suite.NotEmpty(apiStatus.Filtered)
+ if err != nil {
+ suite.FailNow(err.Error())
}
+
+ suite.NotEmpty(apiStatus.Filtered)
}
func (suite *InternalToFrontendTestSuite) TestHashtagWholeWordFilteredStatusToFrontend() {
diff --git a/internal/typeutils/util.go b/internal/typeutils/util.go
index 3441e89a9..3a867ba35 100644
--- a/internal/typeutils/util.go
+++ b/internal/typeutils/util.go
@@ -27,6 +27,7 @@ import (
"strconv"
"strings"
+ "github.com/k3a/html2text"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
@@ -284,3 +285,64 @@ func ContentToContentLanguage(
return contentStr, langTagStr
}
+
+// filterableFields returns text fields from
+// a status that we might want to filter on:
+//
+// - content warning
+// - content (converted to plaintext from HTML)
+// - media descriptions
+// - poll options
+//
+// Each field should be filtered separately.
+// This avoids scenarios where false-positive
+// multiple-word matches can be made by matching
+// the last word of one field + the first word
+// of the next field together.
+func filterableFields(s *gtsmodel.Status) []string {
+ // Estimate length of fields.
+ fieldCount := 2 + len(s.Attachments)
+ if s.Poll != nil {
+ fieldCount += len(s.Poll.Options)
+ }
+ fields := make([]string, 0, fieldCount)
+
+ // Content warning / title.
+ if s.ContentWarning != "" {
+ fields = append(fields, s.ContentWarning)
+ }
+
+ // Status content. Though we have raw text
+ // available for statuses created on our
+ // instance, use the html2text version to
+ // remove markdown-formatting characters
+ // and ensure more consistent filtering.
+ if s.Content != "" {
+ text := html2text.HTML2TextWithOptions(
+ s.Content,
+ html2text.WithLinksInnerText(),
+ html2text.WithUnixLineBreaks(),
+ )
+ if text != "" {
+ fields = append(fields, text)
+ }
+ }
+
+ // Media descriptions.
+ for _, attachment := range s.Attachments {
+ if attachment.Description != "" {
+ fields = append(fields, attachment.Description)
+ }
+ }
+
+ // Poll options.
+ if s.Poll != nil {
+ for _, opt := range s.Poll.Options {
+ if opt != "" {
+ fields = append(fields, opt)
+ }
+ }
+ }
+
+ return fields
+}
diff --git a/internal/typeutils/util_test.go b/internal/typeutils/util_test.go
index 0f852d399..ea6667519 100644
--- a/internal/typeutils/util_test.go
+++ b/internal/typeutils/util_test.go
@@ -21,6 +21,7 @@ import (
"context"
"testing"
+ "github.com/stretchr/testify/assert"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/language"
@@ -158,3 +159,62 @@ func TestContentToContentLanguage(t *testing.T) {
}
}
}
+
+func TestFilterableText(t *testing.T) {
+ type testcase struct {
+ status *gtsmodel.Status
+ expectedFields []string
+ }
+
+ for _, testcase := range []testcase{
+ {
+ status: >smodel.Status{
+ ContentWarning: "This is a test status",
+ Content: `Import / export of account data via CSV files will be coming in 0.17.0 :) No more having to run scripts + CLI tools to import a list of accounts you follow, after doing a migration to a #GoToSocial instance.
`,
+ },
+ expectedFields: []string{
+ "This is a test status",
+ "Import / export of account data via CSV files will be coming in 0.17.0 :) No more having to run scripts + CLI tools to import a list of accounts you follow, after doing a migration to a #GoToSocial instance.",
+ },
+ },
+ {
+ status: >smodel.Status{
+ Content: `@zlatko currently we used modernc/sqlite3 for our sqlite driver, but we've been experimenting with wasm sqlite, and will likely move to that permanently in future; in the meantime, both options are available (the latter with a build tag)
https://github.com/superseriousbusiness/gotosocial/pull/2863
`,
+ },
+ expectedFields: []string{
+ "@zlatko currently we used modernc/sqlite3 for our sqlite driver, but we've been experimenting with wasm sqlite, and will likely move to that permanently in future; in the meantime, both options are available (the latter with a build tag)\n\nhttps://github.com/superseriousbusiness/gotosocial/pull/2863 ",
+ },
+ },
+ {
+ status: >smodel.Status{
+ ContentWarning: "Nerd stuff",
+ Content: `Latest graphs for #GoToSocial on Wasm sqlite3 with embedded Wasm ffmpeg, both running on Wazero, and configured with a 50MiB db cache target. This is the version we'll be releasing soonish, now we're happy with how we've tamed everything.
`,
+ Attachments: []*gtsmodel.MediaAttachment{
+ {
+ Description: `Graph showing GtS using between 150-300 MiB of memory, steadily, over a few days.`,
+ },
+ {
+ Description: `Another media attachment`,
+ },
+ },
+ Poll: >smodel.Poll{
+ Options: []string{
+ "Poll option 1",
+ "Poll option 2",
+ },
+ },
+ },
+ expectedFields: []string{
+ "Nerd stuff",
+ "Latest graphs for #GoToSocial on Wasm sqlite3 with embedded Wasm ffmpeg , both running on Wazero , and configured with a 50MiB db cache target . This is the version we'll be releasing soonish, now we're happy with how we've tamed everything.",
+ "Graph showing GtS using between 150-300 MiB of memory, steadily, over a few days.",
+ "Another media attachment",
+ "Poll option 1",
+ "Poll option 2",
+ },
+ },
+ } {
+ fields := filterableFields(testcase.status)
+ assert.Equal(t, testcase.expectedFields, fields)
+ }
+}
diff --git a/vendor/github.com/k3a/html2text/.travis.yml b/vendor/github.com/k3a/html2text/.travis.yml
new file mode 100644
index 000000000..c9f214d59
--- /dev/null
+++ b/vendor/github.com/k3a/html2text/.travis.yml
@@ -0,0 +1,10 @@
+language: go
+go:
+ - master
+before_install:
+ - go get github.com/axw/gocov/gocov
+ - go get github.com/mattn/goveralls
+ - if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
+script:
+ - $HOME/gopath/bin/goveralls -service=travis-ci
+
diff --git a/vendor/github.com/k3a/html2text/LICENSE b/vendor/github.com/k3a/html2text/LICENSE
new file mode 100644
index 000000000..4838b48ab
--- /dev/null
+++ b/vendor/github.com/k3a/html2text/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Mario K3A Hros (www.k3a.me)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/k3a/html2text/README.md b/vendor/github.com/k3a/html2text/README.md
new file mode 100644
index 000000000..892665905
--- /dev/null
+++ b/vendor/github.com/k3a/html2text/README.md
@@ -0,0 +1,60 @@
+[![GoDoc](https://godoc.org/github.com/k3a/html2text?status.svg)](https://godoc.org/github.com/k3a/html2text)
+[![Build Status](https://travis-ci.org/k3a/html2text.svg?branch=master)](https://travis-ci.org/k3a/html2text)
+[![Coverage Status](https://coveralls.io/repos/github/k3a/html2text/badge.svg?branch=master)](https://coveralls.io/github/k3a/html2text?branch=master)
+[![Report Card](https://goreportcard.com/badge/github.com/k3a/html2text)](https://goreportcard.com/report/github.com/k3a/html2text)
+
+# html2text
+
+A simple Golang package to convert HTML to plain text (without non-standard dependencies).
+
+It converts HTML tags to text and also parses HTML entities into characters they represent.
+A `` section of the HTML document, as well as most other tags are stripped out but
+links are properly converted into their href attribute.
+
+It can be used for converting HTML emails into text.
+
+Some tests are installed as well.
+Uses semantic versioning and no breaking changes are planned.
+
+Fell free to publish a pull request if you have suggestions for improvement but please note that the library can now be considered feature-complete and API stable. If you need more than this basic conversion, please use an alternative mentioned at the bottom.
+
+## Install
+```bash
+go get github.com/k3a/html2text
+```
+
+## Usage
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/k3a/html2text"
+)
+
+func main() {
+ html := `Goodclean text`
+
+ plain := html2text.HTML2Text(html)
+
+ fmt.Println(plain)
+}
+
+/* Outputs:
+
+ clean text
+*/
+
+```
+
+To see all features, please look info `html2text_test.go`.
+
+## Alternatives
+- https://github.com/jaytaylor/html2text (heavier, with more features)
+- https://git.alexwennerberg.com/nanohtml2text (rewrite of this module in Rust)
+
+## License
+
+MIT
+
diff --git a/vendor/github.com/k3a/html2text/entity.go b/vendor/github.com/k3a/html2text/entity.go
new file mode 100644
index 000000000..68f90068d
--- /dev/null
+++ b/vendor/github.com/k3a/html2text/entity.go
@@ -0,0 +1,2046 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html2text
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// https://html.spec.whatwg.org/multipage/named-characters.html
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Abreve": '\U00000102',
+ "Acirc": '\U000000C2',
+ "Acy": '\U00000410',
+ "Afr": '\U0001D504',
+ "Agrave": '\U000000C0',
+ "Alpha": '\U00000391',
+ "Amacr": '\U00000100',
+ "And": '\U00002A53',
+ "Aogon": '\U00000104',
+ "Aopf": '\U0001D538',
+ "ApplyFunction": '\U00002061',
+ "Aring": '\U000000C5',
+ "Ascr": '\U0001D49C',
+ "Assign": '\U00002254',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "Backslash": '\U00002216',
+ "Barv": '\U00002AE7',
+ "Barwed": '\U00002306',
+ "Bcy": '\U00000411',
+ "Because": '\U00002235',
+ "Bernoullis": '\U0000212C',
+ "Beta": '\U00000392',
+ "Bfr": '\U0001D505',
+ "Bopf": '\U0001D539',
+ "Breve": '\U000002D8',
+ "Bscr": '\U0000212C',
+ "Bumpeq": '\U0000224E',
+ "CHcy": '\U00000427',
+ "COPY": '\U000000A9',
+ "Cacute": '\U00000106',
+ "Cap": '\U000022D2',
+ "CapitalDifferentialD": '\U00002145',
+ "Cayleys": '\U0000212D',
+ "Ccaron": '\U0000010C',
+ "Ccedil": '\U000000C7',
+ "Ccirc": '\U00000108',
+ "Cconint": '\U00002230',
+ "Cdot": '\U0000010A',
+ "Cedilla": '\U000000B8',
+ "CenterDot": '\U000000B7',
+ "Cfr": '\U0000212D',
+ "Chi": '\U000003A7',
+ "CircleDot": '\U00002299',
+ "CircleMinus": '\U00002296',
+ "CirclePlus": '\U00002295',
+ "CircleTimes": '\U00002297',
+ "ClockwiseContourIntegral": '\U00002232',
+ "CloseCurlyDoubleQuote": '\U0000201D',
+ "CloseCurlyQuote": '\U00002019',
+ "Colon": '\U00002237',
+ "Colone": '\U00002A74',
+ "Congruent": '\U00002261',
+ "Conint": '\U0000222F',
+ "ContourIntegral": '\U0000222E',
+ "Copf": '\U00002102',
+ "Coproduct": '\U00002210',
+ "CounterClockwiseContourIntegral": '\U00002233',
+ "Cross": '\U00002A2F',
+ "Cscr": '\U0001D49E',
+ "Cup": '\U000022D3',
+ "CupCap": '\U0000224D',
+ "DD": '\U00002145',
+ "DDotrahd": '\U00002911',
+ "DJcy": '\U00000402',
+ "DScy": '\U00000405',
+ "DZcy": '\U0000040F',
+ "Dagger": '\U00002021',
+ "Darr": '\U000021A1',
+ "Dashv": '\U00002AE4',
+ "Dcaron": '\U0000010E',
+ "Dcy": '\U00000414',
+ "Del": '\U00002207',
+ "Delta": '\U00000394',
+ "Dfr": '\U0001D507',
+ "DiacriticalAcute": '\U000000B4',
+ "DiacriticalDot": '\U000002D9',
+ "DiacriticalDoubleAcute": '\U000002DD',
+ "DiacriticalGrave": '\U00000060',
+ "DiacriticalTilde": '\U000002DC',
+ "Diamond": '\U000022C4',
+ "DifferentialD": '\U00002146',
+ "Dopf": '\U0001D53B',
+ "Dot": '\U000000A8',
+ "DotDot": '\U000020DC',
+ "DotEqual": '\U00002250',
+ "DoubleContourIntegral": '\U0000222F',
+ "DoubleDot": '\U000000A8',
+ "DoubleDownArrow": '\U000021D3',
+ "DoubleLeftArrow": '\U000021D0',
+ "DoubleLeftRightArrow": '\U000021D4',
+ "DoubleLeftTee": '\U00002AE4',
+ "DoubleLongLeftArrow": '\U000027F8',
+ "DoubleLongLeftRightArrow": '\U000027FA',
+ "DoubleLongRightArrow": '\U000027F9',
+ "DoubleRightArrow": '\U000021D2',
+ "DoubleRightTee": '\U000022A8',
+ "DoubleUpArrow": '\U000021D1',
+ "DoubleUpDownArrow": '\U000021D5',
+ "DoubleVerticalBar": '\U00002225',
+ "DownArrow": '\U00002193',
+ "DownArrowBar": '\U00002913',
+ "DownArrowUpArrow": '\U000021F5',
+ "DownBreve": '\U00000311',
+ "DownLeftRightVector": '\U00002950',
+ "DownLeftTeeVector": '\U0000295E',
+ "DownLeftVector": '\U000021BD',
+ "DownLeftVectorBar": '\U00002956',
+ "DownRightTeeVector": '\U0000295F',
+ "DownRightVector": '\U000021C1',
+ "DownRightVectorBar": '\U00002957',
+ "DownTee": '\U000022A4',
+ "DownTeeArrow": '\U000021A7',
+ "Downarrow": '\U000021D3',
+ "Dscr": '\U0001D49F',
+ "Dstrok": '\U00000110',
+ "ENG": '\U0000014A',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecaron": '\U0000011A',
+ "Ecirc": '\U000000CA',
+ "Ecy": '\U0000042D',
+ "Edot": '\U00000116',
+ "Efr": '\U0001D508',
+ "Egrave": '\U000000C8',
+ "Element": '\U00002208',
+ "Emacr": '\U00000112',
+ "EmptySmallSquare": '\U000025FB',
+ "EmptyVerySmallSquare": '\U000025AB',
+ "Eogon": '\U00000118',
+ "Eopf": '\U0001D53C',
+ "Epsilon": '\U00000395',
+ "Equal": '\U00002A75',
+ "EqualTilde": '\U00002242',
+ "Equilibrium": '\U000021CC',
+ "Escr": '\U00002130',
+ "Esim": '\U00002A73',
+ "Eta": '\U00000397',
+ "Euml": '\U000000CB',
+ "Exists": '\U00002203',
+ "ExponentialE": '\U00002147',
+ "Fcy": '\U00000424',
+ "Ffr": '\U0001D509',
+ "FilledSmallSquare": '\U000025FC',
+ "FilledVerySmallSquare": '\U000025AA',
+ "Fopf": '\U0001D53D',
+ "ForAll": '\U00002200',
+ "Fouriertrf": '\U00002131',
+ "Fscr": '\U00002131',
+ "GJcy": '\U00000403',
+ "GT": '\U0000003E',
+ "Gamma": '\U00000393',
+ "Gammad": '\U000003DC',
+ "Gbreve": '\U0000011E',
+ "Gcedil": '\U00000122',
+ "Gcirc": '\U0000011C',
+ "Gcy": '\U00000413',
+ "Gdot": '\U00000120',
+ "Gfr": '\U0001D50A',
+ "Gg": '\U000022D9',
+ "Gopf": '\U0001D53E',
+ "GreaterEqual": '\U00002265',
+ "GreaterEqualLess": '\U000022DB',
+ "GreaterFullEqual": '\U00002267',
+ "GreaterGreater": '\U00002AA2',
+ "GreaterLess": '\U00002277',
+ "GreaterSlantEqual": '\U00002A7E',
+ "GreaterTilde": '\U00002273',
+ "Gscr": '\U0001D4A2',
+ "Gt": '\U0000226B',
+ "HARDcy": '\U0000042A',
+ "Hacek": '\U000002C7',
+ "Hat": '\U0000005E',
+ "Hcirc": '\U00000124',
+ "Hfr": '\U0000210C',
+ "HilbertSpace": '\U0000210B',
+ "Hopf": '\U0000210D',
+ "HorizontalLine": '\U00002500',
+ "Hscr": '\U0000210B',
+ "Hstrok": '\U00000126',
+ "HumpDownHump": '\U0000224E',
+ "HumpEqual": '\U0000224F',
+ "IEcy": '\U00000415',
+ "IJlig": '\U00000132',
+ "IOcy": '\U00000401',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Icy": '\U00000418',
+ "Idot": '\U00000130',
+ "Ifr": '\U00002111',
+ "Igrave": '\U000000CC',
+ "Im": '\U00002111',
+ "Imacr": '\U0000012A',
+ "ImaginaryI": '\U00002148',
+ "Implies": '\U000021D2',
+ "Int": '\U0000222C',
+ "Integral": '\U0000222B',
+ "Intersection": '\U000022C2',
+ "InvisibleComma": '\U00002063',
+ "InvisibleTimes": '\U00002062',
+ "Iogon": '\U0000012E',
+ "Iopf": '\U0001D540',
+ "Iota": '\U00000399',
+ "Iscr": '\U00002110',
+ "Itilde": '\U00000128',
+ "Iukcy": '\U00000406',
+ "Iuml": '\U000000CF',
+ "Jcirc": '\U00000134',
+ "Jcy": '\U00000419',
+ "Jfr": '\U0001D50D',
+ "Jopf": '\U0001D541',
+ "Jscr": '\U0001D4A5',
+ "Jsercy": '\U00000408',
+ "Jukcy": '\U00000404',
+ "KHcy": '\U00000425',
+ "KJcy": '\U0000040C',
+ "Kappa": '\U0000039A',
+ "Kcedil": '\U00000136',
+ "Kcy": '\U0000041A',
+ "Kfr": '\U0001D50E',
+ "Kopf": '\U0001D542',
+ "Kscr": '\U0001D4A6',
+ "LJcy": '\U00000409',
+ "LT": '\U0000003C',
+ "Lacute": '\U00000139',
+ "Lambda": '\U0000039B',
+ "Lang": '\U000027EA',
+ "Laplacetrf": '\U00002112',
+ "Larr": '\U0000219E',
+ "Lcaron": '\U0000013D',
+ "Lcedil": '\U0000013B',
+ "Lcy": '\U0000041B',
+ "LeftAngleBracket": '\U000027E8',
+ "LeftArrow": '\U00002190',
+ "LeftArrowBar": '\U000021E4',
+ "LeftArrowRightArrow": '\U000021C6',
+ "LeftCeiling": '\U00002308',
+ "LeftDoubleBracket": '\U000027E6',
+ "LeftDownTeeVector": '\U00002961',
+ "LeftDownVector": '\U000021C3',
+ "LeftDownVectorBar": '\U00002959',
+ "LeftFloor": '\U0000230A',
+ "LeftRightArrow": '\U00002194',
+ "LeftRightVector": '\U0000294E',
+ "LeftTee": '\U000022A3',
+ "LeftTeeArrow": '\U000021A4',
+ "LeftTeeVector": '\U0000295A',
+ "LeftTriangle": '\U000022B2',
+ "LeftTriangleBar": '\U000029CF',
+ "LeftTriangleEqual": '\U000022B4',
+ "LeftUpDownVector": '\U00002951',
+ "LeftUpTeeVector": '\U00002960',
+ "LeftUpVector": '\U000021BF',
+ "LeftUpVectorBar": '\U00002958',
+ "LeftVector": '\U000021BC',
+ "LeftVectorBar": '\U00002952',
+ "Leftarrow": '\U000021D0',
+ "Leftrightarrow": '\U000021D4',
+ "LessEqualGreater": '\U000022DA',
+ "LessFullEqual": '\U00002266',
+ "LessGreater": '\U00002276',
+ "LessLess": '\U00002AA1',
+ "LessSlantEqual": '\U00002A7D',
+ "LessTilde": '\U00002272',
+ "Lfr": '\U0001D50F',
+ "Ll": '\U000022D8',
+ "Lleftarrow": '\U000021DA',
+ "Lmidot": '\U0000013F',
+ "LongLeftArrow": '\U000027F5',
+ "LongLeftRightArrow": '\U000027F7',
+ "LongRightArrow": '\U000027F6',
+ "Longleftarrow": '\U000027F8',
+ "Longleftrightarrow": '\U000027FA',
+ "Longrightarrow": '\U000027F9',
+ "Lopf": '\U0001D543',
+ "LowerLeftArrow": '\U00002199',
+ "LowerRightArrow": '\U00002198',
+ "Lscr": '\U00002112',
+ "Lsh": '\U000021B0',
+ "Lstrok": '\U00000141',
+ "Lt": '\U0000226A',
+ "Map": '\U00002905',
+ "Mcy": '\U0000041C',
+ "MediumSpace": '\U0000205F',
+ "Mellintrf": '\U00002133',
+ "Mfr": '\U0001D510',
+ "MinusPlus": '\U00002213',
+ "Mopf": '\U0001D544',
+ "Mscr": '\U00002133',
+ "Mu": '\U0000039C',
+ "NJcy": '\U0000040A',
+ "Nacute": '\U00000143',
+ "Ncaron": '\U00000147',
+ "Ncedil": '\U00000145',
+ "Ncy": '\U0000041D',
+ "NegativeMediumSpace": '\U0000200B',
+ "NegativeThickSpace": '\U0000200B',
+ "NegativeThinSpace": '\U0000200B',
+ "NegativeVeryThinSpace": '\U0000200B',
+ "NestedGreaterGreater": '\U0000226B',
+ "NestedLessLess": '\U0000226A',
+ "NewLine": '\U0000000A',
+ "Nfr": '\U0001D511',
+ "NoBreak": '\U00002060',
+ "NonBreakingSpace": '\U000000A0',
+ "Nopf": '\U00002115',
+ "Not": '\U00002AEC',
+ "NotCongruent": '\U00002262',
+ "NotCupCap": '\U0000226D',
+ "NotDoubleVerticalBar": '\U00002226',
+ "NotElement": '\U00002209',
+ "NotEqual": '\U00002260',
+ "NotExists": '\U00002204',
+ "NotGreater": '\U0000226F',
+ "NotGreaterEqual": '\U00002271',
+ "NotGreaterLess": '\U00002279',
+ "NotGreaterTilde": '\U00002275',
+ "NotLeftTriangle": '\U000022EA',
+ "NotLeftTriangleEqual": '\U000022EC',
+ "NotLess": '\U0000226E',
+ "NotLessEqual": '\U00002270',
+ "NotLessGreater": '\U00002278',
+ "NotLessTilde": '\U00002274',
+ "NotPrecedes": '\U00002280',
+ "NotPrecedesSlantEqual": '\U000022E0',
+ "NotReverseElement": '\U0000220C',
+ "NotRightTriangle": '\U000022EB',
+ "NotRightTriangleEqual": '\U000022ED',
+ "NotSquareSubsetEqual": '\U000022E2',
+ "NotSquareSupersetEqual": '\U000022E3',
+ "NotSubsetEqual": '\U00002288',
+ "NotSucceeds": '\U00002281',
+ "NotSucceedsSlantEqual": '\U000022E1',
+ "NotSupersetEqual": '\U00002289',
+ "NotTilde": '\U00002241',
+ "NotTildeEqual": '\U00002244',
+ "NotTildeFullEqual": '\U00002247',
+ "NotTildeTilde": '\U00002249',
+ "NotVerticalBar": '\U00002224',
+ "Nscr": '\U0001D4A9',
+ "Ntilde": '\U000000D1',
+ "Nu": '\U0000039D',
+ "OElig": '\U00000152',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ocy": '\U0000041E',
+ "Odblac": '\U00000150',
+ "Ofr": '\U0001D512',
+ "Ograve": '\U000000D2',
+ "Omacr": '\U0000014C',
+ "Omega": '\U000003A9',
+ "Omicron": '\U0000039F',
+ "Oopf": '\U0001D546',
+ "OpenCurlyDoubleQuote": '\U0000201C',
+ "OpenCurlyQuote": '\U00002018',
+ "Or": '\U00002A54',
+ "Oscr": '\U0001D4AA',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Otimes": '\U00002A37',
+ "Ouml": '\U000000D6',
+ "OverBar": '\U0000203E',
+ "OverBrace": '\U000023DE',
+ "OverBracket": '\U000023B4',
+ "OverParenthesis": '\U000023DC',
+ "PartialD": '\U00002202',
+ "Pcy": '\U0000041F',
+ "Pfr": '\U0001D513',
+ "Phi": '\U000003A6',
+ "Pi": '\U000003A0',
+ "PlusMinus": '\U000000B1',
+ "Poincareplane": '\U0000210C',
+ "Popf": '\U00002119',
+ "Pr": '\U00002ABB',
+ "Precedes": '\U0000227A',
+ "PrecedesEqual": '\U00002AAF',
+ "PrecedesSlantEqual": '\U0000227C',
+ "PrecedesTilde": '\U0000227E',
+ "Prime": '\U00002033',
+ "Product": '\U0000220F',
+ "Proportion": '\U00002237',
+ "Proportional": '\U0000221D',
+ "Pscr": '\U0001D4AB',
+ "Psi": '\U000003A8',
+ "QUOT": '\U00000022',
+ "Qfr": '\U0001D514',
+ "Qopf": '\U0000211A',
+ "Qscr": '\U0001D4AC',
+ "RBarr": '\U00002910',
+ "REG": '\U000000AE',
+ "Racute": '\U00000154',
+ "Rang": '\U000027EB',
+ "Rarr": '\U000021A0',
+ "Rarrtl": '\U00002916',
+ "Rcaron": '\U00000158',
+ "Rcedil": '\U00000156',
+ "Rcy": '\U00000420',
+ "Re": '\U0000211C',
+ "ReverseElement": '\U0000220B',
+ "ReverseEquilibrium": '\U000021CB',
+ "ReverseUpEquilibrium": '\U0000296F',
+ "Rfr": '\U0000211C',
+ "Rho": '\U000003A1',
+ "RightAngleBracket": '\U000027E9',
+ "RightArrow": '\U00002192',
+ "RightArrowBar": '\U000021E5',
+ "RightArrowLeftArrow": '\U000021C4',
+ "RightCeiling": '\U00002309',
+ "RightDoubleBracket": '\U000027E7',
+ "RightDownTeeVector": '\U0000295D',
+ "RightDownVector": '\U000021C2',
+ "RightDownVectorBar": '\U00002955',
+ "RightFloor": '\U0000230B',
+ "RightTee": '\U000022A2',
+ "RightTeeArrow": '\U000021A6',
+ "RightTeeVector": '\U0000295B',
+ "RightTriangle": '\U000022B3',
+ "RightTriangleBar": '\U000029D0',
+ "RightTriangleEqual": '\U000022B5',
+ "RightUpDownVector": '\U0000294F',
+ "RightUpTeeVector": '\U0000295C',
+ "RightUpVector": '\U000021BE',
+ "RightUpVectorBar": '\U00002954',
+ "RightVector": '\U000021C0',
+ "RightVectorBar": '\U00002953',
+ "Rightarrow": '\U000021D2',
+ "Ropf": '\U0000211D',
+ "RoundImplies": '\U00002970',
+ "Rrightarrow": '\U000021DB',
+ "Rscr": '\U0000211B',
+ "Rsh": '\U000021B1',
+ "RuleDelayed": '\U000029F4',
+ "SHCHcy": '\U00000429',
+ "SHcy": '\U00000428',
+ "SOFTcy": '\U0000042C',
+ "Sacute": '\U0000015A',
+ "Sc": '\U00002ABC',
+ "Scaron": '\U00000160',
+ "Scedil": '\U0000015E',
+ "Scirc": '\U0000015C',
+ "Scy": '\U00000421',
+ "Sfr": '\U0001D516',
+ "ShortDownArrow": '\U00002193',
+ "ShortLeftArrow": '\U00002190',
+ "ShortRightArrow": '\U00002192',
+ "ShortUpArrow": '\U00002191',
+ "Sigma": '\U000003A3',
+ "SmallCircle": '\U00002218',
+ "Sopf": '\U0001D54A',
+ "Sqrt": '\U0000221A',
+ "Square": '\U000025A1',
+ "SquareIntersection": '\U00002293',
+ "SquareSubset": '\U0000228F',
+ "SquareSubsetEqual": '\U00002291',
+ "SquareSuperset": '\U00002290',
+ "SquareSupersetEqual": '\U00002292',
+ "SquareUnion": '\U00002294',
+ "Sscr": '\U0001D4AE',
+ "Star": '\U000022C6',
+ "Sub": '\U000022D0',
+ "Subset": '\U000022D0',
+ "SubsetEqual": '\U00002286',
+ "Succeeds": '\U0000227B',
+ "SucceedsEqual": '\U00002AB0',
+ "SucceedsSlantEqual": '\U0000227D',
+ "SucceedsTilde": '\U0000227F',
+ "SuchThat": '\U0000220B',
+ "Sum": '\U00002211',
+ "Sup": '\U000022D1',
+ "Superset": '\U00002283',
+ "SupersetEqual": '\U00002287',
+ "Supset": '\U000022D1',
+ "THORN": '\U000000DE',
+ "TRADE": '\U00002122',
+ "TSHcy": '\U0000040B',
+ "TScy": '\U00000426',
+ "Tab": '\U00000009',
+ "Tau": '\U000003A4',
+ "Tcaron": '\U00000164',
+ "Tcedil": '\U00000162',
+ "Tcy": '\U00000422',
+ "Tfr": '\U0001D517',
+ "Therefore": '\U00002234',
+ "Theta": '\U00000398',
+ "ThinSpace": '\U00002009',
+ "Tilde": '\U0000223C',
+ "TildeEqual": '\U00002243',
+ "TildeFullEqual": '\U00002245',
+ "TildeTilde": '\U00002248',
+ "Topf": '\U0001D54B',
+ "TripleDot": '\U000020DB',
+ "Tscr": '\U0001D4AF',
+ "Tstrok": '\U00000166',
+ "Uacute": '\U000000DA',
+ "Uarr": '\U0000219F',
+ "Uarrocir": '\U00002949',
+ "Ubrcy": '\U0000040E',
+ "Ubreve": '\U0000016C',
+ "Ucirc": '\U000000DB',
+ "Ucy": '\U00000423',
+ "Udblac": '\U00000170',
+ "Ufr": '\U0001D518',
+ "Ugrave": '\U000000D9',
+ "Umacr": '\U0000016A',
+ "UnderBar": '\U0000005F',
+ "UnderBrace": '\U000023DF',
+ "UnderBracket": '\U000023B5',
+ "UnderParenthesis": '\U000023DD',
+ "Union": '\U000022C3',
+ "UnionPlus": '\U0000228E',
+ "Uogon": '\U00000172',
+ "Uopf": '\U0001D54C',
+ "UpArrow": '\U00002191',
+ "UpArrowBar": '\U00002912',
+ "UpArrowDownArrow": '\U000021C5',
+ "UpDownArrow": '\U00002195',
+ "UpEquilibrium": '\U0000296E',
+ "UpTee": '\U000022A5',
+ "UpTeeArrow": '\U000021A5',
+ "Uparrow": '\U000021D1',
+ "Updownarrow": '\U000021D5',
+ "UpperLeftArrow": '\U00002196',
+ "UpperRightArrow": '\U00002197',
+ "Upsi": '\U000003D2',
+ "Upsilon": '\U000003A5',
+ "Uring": '\U0000016E',
+ "Uscr": '\U0001D4B0',
+ "Utilde": '\U00000168',
+ "Uuml": '\U000000DC',
+ "VDash": '\U000022AB',
+ "Vbar": '\U00002AEB',
+ "Vcy": '\U00000412',
+ "Vdash": '\U000022A9',
+ "Vdashl": '\U00002AE6',
+ "Vee": '\U000022C1',
+ "Verbar": '\U00002016',
+ "Vert": '\U00002016',
+ "VerticalBar": '\U00002223',
+ "VerticalLine": '\U0000007C',
+ "VerticalSeparator": '\U00002758',
+ "VerticalTilde": '\U00002240',
+ "VeryThinSpace": '\U0000200A',
+ "Vfr": '\U0001D519',
+ "Vopf": '\U0001D54D',
+ "Vscr": '\U0001D4B1',
+ "Vvdash": '\U000022AA',
+ "Wcirc": '\U00000174',
+ "Wedge": '\U000022C0',
+ "Wfr": '\U0001D51A',
+ "Wopf": '\U0001D54E',
+ "Wscr": '\U0001D4B2',
+ "Xfr": '\U0001D51B',
+ "Xi": '\U0000039E',
+ "Xopf": '\U0001D54F',
+ "Xscr": '\U0001D4B3',
+ "YAcy": '\U0000042F',
+ "YIcy": '\U00000407',
+ "YUcy": '\U0000042E',
+ "Yacute": '\U000000DD',
+ "Ycirc": '\U00000176',
+ "Ycy": '\U0000042B',
+ "Yfr": '\U0001D51C',
+ "Yopf": '\U0001D550',
+ "Yscr": '\U0001D4B4',
+ "Yuml": '\U00000178',
+ "ZHcy": '\U00000416',
+ "Zacute": '\U00000179',
+ "Zcaron": '\U0000017D',
+ "Zcy": '\U00000417',
+ "Zdot": '\U0000017B',
+ "ZeroWidthSpace": '\U0000200B',
+ "Zeta": '\U00000396',
+ "Zfr": '\U00002128',
+ "Zopf": '\U00002124',
+ "Zscr": '\U0001D4B5',
+ "aacute": '\U000000E1',
+ "abreve": '\U00000103',
+ "ac": '\U0000223E',
+ "acd": '\U0000223F',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "acy": '\U00000430',
+ "aelig": '\U000000E6',
+ "af": '\U00002061',
+ "afr": '\U0001D51E',
+ "agrave": '\U000000E0',
+ "alefsym": '\U00002135',
+ "aleph": '\U00002135',
+ "alpha": '\U000003B1',
+ "amacr": '\U00000101',
+ "amalg": '\U00002A3F',
+ "amp": '\U00000026',
+ "and": '\U00002227',
+ "andand": '\U00002A55',
+ "andd": '\U00002A5C',
+ "andslope": '\U00002A58',
+ "andv": '\U00002A5A',
+ "ang": '\U00002220',
+ "ange": '\U000029A4',
+ "angle": '\U00002220',
+ "angmsd": '\U00002221',
+ "angmsdaa": '\U000029A8',
+ "angmsdab": '\U000029A9',
+ "angmsdac": '\U000029AA',
+ "angmsdad": '\U000029AB',
+ "angmsdae": '\U000029AC',
+ "angmsdaf": '\U000029AD',
+ "angmsdag": '\U000029AE',
+ "angmsdah": '\U000029AF',
+ "angrt": '\U0000221F',
+ "angrtvb": '\U000022BE',
+ "angrtvbd": '\U0000299D',
+ "angsph": '\U00002222',
+ "angst": '\U000000C5',
+ "angzarr": '\U0000237C',
+ "aogon": '\U00000105',
+ "aopf": '\U0001D552',
+ "ap": '\U00002248',
+ "apE": '\U00002A70',
+ "apacir": '\U00002A6F',
+ "ape": '\U0000224A',
+ "apid": '\U0000224B',
+ "apos": '\U00000027',
+ "approx": '\U00002248',
+ "approxeq": '\U0000224A',
+ "aring": '\U000000E5',
+ "ascr": '\U0001D4B6',
+ "ast": '\U0000002A',
+ "asymp": '\U00002248',
+ "asympeq": '\U0000224D',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "awconint": '\U00002233',
+ "awint": '\U00002A11',
+ "bNot": '\U00002AED',
+ "backcong": '\U0000224C',
+ "backepsilon": '\U000003F6',
+ "backprime": '\U00002035',
+ "backsim": '\U0000223D',
+ "backsimeq": '\U000022CD',
+ "barvee": '\U000022BD',
+ "barwed": '\U00002305',
+ "barwedge": '\U00002305',
+ "bbrk": '\U000023B5',
+ "bbrktbrk": '\U000023B6',
+ "bcong": '\U0000224C',
+ "bcy": '\U00000431',
+ "bdquo": '\U0000201E',
+ "becaus": '\U00002235',
+ "because": '\U00002235',
+ "bemptyv": '\U000029B0',
+ "bepsi": '\U000003F6',
+ "bernou": '\U0000212C',
+ "beta": '\U000003B2',
+ "beth": '\U00002136',
+ "between": '\U0000226C',
+ "bfr": '\U0001D51F',
+ "bigcap": '\U000022C2',
+ "bigcirc": '\U000025EF',
+ "bigcup": '\U000022C3',
+ "bigodot": '\U00002A00',
+ "bigoplus": '\U00002A01',
+ "bigotimes": '\U00002A02',
+ "bigsqcup": '\U00002A06',
+ "bigstar": '\U00002605',
+ "bigtriangledown": '\U000025BD',
+ "bigtriangleup": '\U000025B3',
+ "biguplus": '\U00002A04',
+ "bigvee": '\U000022C1',
+ "bigwedge": '\U000022C0',
+ "bkarow": '\U0000290D',
+ "blacklozenge": '\U000029EB',
+ "blacksquare": '\U000025AA',
+ "blacktriangle": '\U000025B4',
+ "blacktriangledown": '\U000025BE',
+ "blacktriangleleft": '\U000025C2',
+ "blacktriangleright": '\U000025B8',
+ "blank": '\U00002423',
+ "blk12": '\U00002592',
+ "blk14": '\U00002591',
+ "blk34": '\U00002593',
+ "block": '\U00002588',
+ "bnot": '\U00002310',
+ "bopf": '\U0001D553',
+ "bot": '\U000022A5',
+ "bottom": '\U000022A5',
+ "bowtie": '\U000022C8',
+ "boxDL": '\U00002557',
+ "boxDR": '\U00002554',
+ "boxDl": '\U00002556',
+ "boxDr": '\U00002553',
+ "boxH": '\U00002550',
+ "boxHD": '\U00002566',
+ "boxHU": '\U00002569',
+ "boxHd": '\U00002564',
+ "boxHu": '\U00002567',
+ "boxUL": '\U0000255D',
+ "boxUR": '\U0000255A',
+ "boxUl": '\U0000255C',
+ "boxUr": '\U00002559',
+ "boxV": '\U00002551',
+ "boxVH": '\U0000256C',
+ "boxVL": '\U00002563',
+ "boxVR": '\U00002560',
+ "boxVh": '\U0000256B',
+ "boxVl": '\U00002562',
+ "boxVr": '\U0000255F',
+ "boxbox": '\U000029C9',
+ "boxdL": '\U00002555',
+ "boxdR": '\U00002552',
+ "boxdl": '\U00002510',
+ "boxdr": '\U0000250C',
+ "boxh": '\U00002500',
+ "boxhD": '\U00002565',
+ "boxhU": '\U00002568',
+ "boxhd": '\U0000252C',
+ "boxhu": '\U00002534',
+ "boxminus": '\U0000229F',
+ "boxplus": '\U0000229E',
+ "boxtimes": '\U000022A0',
+ "boxuL": '\U0000255B',
+ "boxuR": '\U00002558',
+ "boxul": '\U00002518',
+ "boxur": '\U00002514',
+ "boxv": '\U00002502',
+ "boxvH": '\U0000256A',
+ "boxvL": '\U00002561',
+ "boxvR": '\U0000255E',
+ "boxvh": '\U0000253C',
+ "boxvl": '\U00002524',
+ "boxvr": '\U0000251C',
+ "bprime": '\U00002035',
+ "breve": '\U000002D8',
+ "brvbar": '\U000000A6',
+ "bscr": '\U0001D4B7',
+ "bsemi": '\U0000204F',
+ "bsim": '\U0000223D',
+ "bsime": '\U000022CD',
+ "bsol": '\U0000005C',
+ "bsolb": '\U000029C5',
+ "bsolhsub": '\U000027C8',
+ "bull": '\U00002022',
+ "bullet": '\U00002022',
+ "bump": '\U0000224E',
+ "bumpE": '\U00002AAE',
+ "bumpe": '\U0000224F',
+ "bumpeq": '\U0000224F',
+ "cacute": '\U00000107',
+ "cap": '\U00002229',
+ "capand": '\U00002A44',
+ "capbrcup": '\U00002A49',
+ "capcap": '\U00002A4B',
+ "capcup": '\U00002A47',
+ "capdot": '\U00002A40',
+ "caret": '\U00002041',
+ "caron": '\U000002C7',
+ "ccaps": '\U00002A4D',
+ "ccaron": '\U0000010D',
+ "ccedil": '\U000000E7',
+ "ccirc": '\U00000109',
+ "ccups": '\U00002A4C',
+ "ccupssm": '\U00002A50',
+ "cdot": '\U0000010B',
+ "cedil": '\U000000B8',
+ "cemptyv": '\U000029B2',
+ "cent": '\U000000A2',
+ "centerdot": '\U000000B7',
+ "cfr": '\U0001D520',
+ "chcy": '\U00000447',
+ "check": '\U00002713',
+ "checkmark": '\U00002713',
+ "chi": '\U000003C7',
+ "cir": '\U000025CB',
+ "cirE": '\U000029C3',
+ "circ": '\U000002C6',
+ "circeq": '\U00002257',
+ "circlearrowleft": '\U000021BA',
+ "circlearrowright": '\U000021BB',
+ "circledR": '\U000000AE',
+ "circledS": '\U000024C8',
+ "circledast": '\U0000229B',
+ "circledcirc": '\U0000229A',
+ "circleddash": '\U0000229D',
+ "cire": '\U00002257',
+ "cirfnint": '\U00002A10',
+ "cirmid": '\U00002AEF',
+ "cirscir": '\U000029C2',
+ "clubs": '\U00002663',
+ "clubsuit": '\U00002663',
+ "colon": '\U0000003A',
+ "colone": '\U00002254',
+ "coloneq": '\U00002254',
+ "comma": '\U0000002C',
+ "commat": '\U00000040',
+ "comp": '\U00002201',
+ "compfn": '\U00002218',
+ "complement": '\U00002201',
+ "complexes": '\U00002102',
+ "cong": '\U00002245',
+ "congdot": '\U00002A6D',
+ "conint": '\U0000222E',
+ "copf": '\U0001D554',
+ "coprod": '\U00002210',
+ "copy": '\U000000A9',
+ "copysr": '\U00002117',
+ "crarr": '\U000021B5',
+ "cross": '\U00002717',
+ "cscr": '\U0001D4B8',
+ "csub": '\U00002ACF',
+ "csube": '\U00002AD1',
+ "csup": '\U00002AD0',
+ "csupe": '\U00002AD2',
+ "ctdot": '\U000022EF',
+ "cudarrl": '\U00002938',
+ "cudarrr": '\U00002935',
+ "cuepr": '\U000022DE',
+ "cuesc": '\U000022DF',
+ "cularr": '\U000021B6',
+ "cularrp": '\U0000293D',
+ "cup": '\U0000222A',
+ "cupbrcap": '\U00002A48',
+ "cupcap": '\U00002A46',
+ "cupcup": '\U00002A4A',
+ "cupdot": '\U0000228D',
+ "cupor": '\U00002A45',
+ "curarr": '\U000021B7',
+ "curarrm": '\U0000293C',
+ "curlyeqprec": '\U000022DE',
+ "curlyeqsucc": '\U000022DF',
+ "curlyvee": '\U000022CE',
+ "curlywedge": '\U000022CF',
+ "curren": '\U000000A4',
+ "curvearrowleft": '\U000021B6',
+ "curvearrowright": '\U000021B7',
+ "cuvee": '\U000022CE',
+ "cuwed": '\U000022CF',
+ "cwconint": '\U00002232',
+ "cwint": '\U00002231',
+ "cylcty": '\U0000232D',
+ "dArr": '\U000021D3',
+ "dHar": '\U00002965',
+ "dagger": '\U00002020',
+ "daleth": '\U00002138',
+ "darr": '\U00002193',
+ "dash": '\U00002010',
+ "dashv": '\U000022A3',
+ "dbkarow": '\U0000290F',
+ "dblac": '\U000002DD',
+ "dcaron": '\U0000010F',
+ "dcy": '\U00000434',
+ "dd": '\U00002146',
+ "ddagger": '\U00002021',
+ "ddarr": '\U000021CA',
+ "ddotseq": '\U00002A77',
+ "deg": '\U000000B0',
+ "delta": '\U000003B4',
+ "demptyv": '\U000029B1',
+ "dfisht": '\U0000297F',
+ "dfr": '\U0001D521',
+ "dharl": '\U000021C3',
+ "dharr": '\U000021C2',
+ "diam": '\U000022C4',
+ "diamond": '\U000022C4',
+ "diamondsuit": '\U00002666',
+ "diams": '\U00002666',
+ "die": '\U000000A8',
+ "digamma": '\U000003DD',
+ "disin": '\U000022F2',
+ "div": '\U000000F7',
+ "divide": '\U000000F7',
+ "divideontimes": '\U000022C7',
+ "divonx": '\U000022C7',
+ "djcy": '\U00000452',
+ "dlcorn": '\U0000231E',
+ "dlcrop": '\U0000230D',
+ "dollar": '\U00000024',
+ "dopf": '\U0001D555',
+ "dot": '\U000002D9',
+ "doteq": '\U00002250',
+ "doteqdot": '\U00002251',
+ "dotminus": '\U00002238',
+ "dotplus": '\U00002214',
+ "dotsquare": '\U000022A1',
+ "doublebarwedge": '\U00002306',
+ "downarrow": '\U00002193',
+ "downdownarrows": '\U000021CA',
+ "downharpoonleft": '\U000021C3',
+ "downharpoonright": '\U000021C2',
+ "drbkarow": '\U00002910',
+ "drcorn": '\U0000231F',
+ "drcrop": '\U0000230C',
+ "dscr": '\U0001D4B9',
+ "dscy": '\U00000455',
+ "dsol": '\U000029F6',
+ "dstrok": '\U00000111',
+ "dtdot": '\U000022F1',
+ "dtri": '\U000025BF',
+ "dtrif": '\U000025BE',
+ "duarr": '\U000021F5',
+ "duhar": '\U0000296F',
+ "dwangle": '\U000029A6',
+ "dzcy": '\U0000045F',
+ "dzigrarr": '\U000027FF',
+ "eDDot": '\U00002A77',
+ "eDot": '\U00002251',
+ "eacute": '\U000000E9',
+ "easter": '\U00002A6E',
+ "ecaron": '\U0000011B',
+ "ecir": '\U00002256',
+ "ecirc": '\U000000EA',
+ "ecolon": '\U00002255',
+ "ecy": '\U0000044D',
+ "edot": '\U00000117',
+ "ee": '\U00002147',
+ "efDot": '\U00002252',
+ "efr": '\U0001D522',
+ "eg": '\U00002A9A',
+ "egrave": '\U000000E8',
+ "egs": '\U00002A96',
+ "egsdot": '\U00002A98',
+ "el": '\U00002A99',
+ "elinters": '\U000023E7',
+ "ell": '\U00002113',
+ "els": '\U00002A95',
+ "elsdot": '\U00002A97',
+ "emacr": '\U00000113',
+ "empty": '\U00002205',
+ "emptyset": '\U00002205',
+ "emptyv": '\U00002205',
+ "emsp": '\U00002003',
+ "emsp13": '\U00002004',
+ "emsp14": '\U00002005',
+ "eng": '\U0000014B',
+ "ensp": '\U00002002',
+ "eogon": '\U00000119',
+ "eopf": '\U0001D556',
+ "epar": '\U000022D5',
+ "eparsl": '\U000029E3',
+ "eplus": '\U00002A71',
+ "epsi": '\U000003B5',
+ "epsilon": '\U000003B5',
+ "epsiv": '\U000003F5',
+ "eqcirc": '\U00002256',
+ "eqcolon": '\U00002255',
+ "eqsim": '\U00002242',
+ "eqslantgtr": '\U00002A96',
+ "eqslantless": '\U00002A95',
+ "equals": '\U0000003D',
+ "equest": '\U0000225F',
+ "equiv": '\U00002261',
+ "equivDD": '\U00002A78',
+ "eqvparsl": '\U000029E5',
+ "erDot": '\U00002253',
+ "erarr": '\U00002971',
+ "escr": '\U0000212F',
+ "esdot": '\U00002250',
+ "esim": '\U00002242',
+ "eta": '\U000003B7',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "euro": '\U000020AC',
+ "excl": '\U00000021',
+ "exist": '\U00002203',
+ "expectation": '\U00002130',
+ "exponentiale": '\U00002147',
+ "fallingdotseq": '\U00002252',
+ "fcy": '\U00000444',
+ "female": '\U00002640',
+ "ffilig": '\U0000FB03',
+ "fflig": '\U0000FB00',
+ "ffllig": '\U0000FB04',
+ "ffr": '\U0001D523',
+ "filig": '\U0000FB01',
+ "flat": '\U0000266D',
+ "fllig": '\U0000FB02',
+ "fltns": '\U000025B1',
+ "fnof": '\U00000192',
+ "fopf": '\U0001D557',
+ "forall": '\U00002200',
+ "fork": '\U000022D4',
+ "forkv": '\U00002AD9',
+ "fpartint": '\U00002A0D',
+ "frac12": '\U000000BD',
+ "frac13": '\U00002153',
+ "frac14": '\U000000BC',
+ "frac15": '\U00002155',
+ "frac16": '\U00002159',
+ "frac18": '\U0000215B',
+ "frac23": '\U00002154',
+ "frac25": '\U00002156',
+ "frac34": '\U000000BE',
+ "frac35": '\U00002157',
+ "frac38": '\U0000215C',
+ "frac45": '\U00002158',
+ "frac56": '\U0000215A',
+ "frac58": '\U0000215D',
+ "frac78": '\U0000215E',
+ "frasl": '\U00002044',
+ "frown": '\U00002322',
+ "fscr": '\U0001D4BB',
+ "gE": '\U00002267',
+ "gEl": '\U00002A8C',
+ "gacute": '\U000001F5',
+ "gamma": '\U000003B3',
+ "gammad": '\U000003DD',
+ "gap": '\U00002A86',
+ "gbreve": '\U0000011F',
+ "gcirc": '\U0000011D',
+ "gcy": '\U00000433',
+ "gdot": '\U00000121',
+ "ge": '\U00002265',
+ "gel": '\U000022DB',
+ "geq": '\U00002265',
+ "geqq": '\U00002267',
+ "geqslant": '\U00002A7E',
+ "ges": '\U00002A7E',
+ "gescc": '\U00002AA9',
+ "gesdot": '\U00002A80',
+ "gesdoto": '\U00002A82',
+ "gesdotol": '\U00002A84',
+ "gesles": '\U00002A94',
+ "gfr": '\U0001D524',
+ "gg": '\U0000226B',
+ "ggg": '\U000022D9',
+ "gimel": '\U00002137',
+ "gjcy": '\U00000453',
+ "gl": '\U00002277',
+ "glE": '\U00002A92',
+ "gla": '\U00002AA5',
+ "glj": '\U00002AA4',
+ "gnE": '\U00002269',
+ "gnap": '\U00002A8A',
+ "gnapprox": '\U00002A8A',
+ "gne": '\U00002A88',
+ "gneq": '\U00002A88',
+ "gneqq": '\U00002269',
+ "gnsim": '\U000022E7',
+ "gopf": '\U0001D558',
+ "grave": '\U00000060',
+ "gscr": '\U0000210A',
+ "gsim": '\U00002273',
+ "gsime": '\U00002A8E',
+ "gsiml": '\U00002A90',
+ "gt": '\U0000003E',
+ "gtcc": '\U00002AA7',
+ "gtcir": '\U00002A7A',
+ "gtdot": '\U000022D7',
+ "gtlPar": '\U00002995',
+ "gtquest": '\U00002A7C',
+ "gtrapprox": '\U00002A86',
+ "gtrarr": '\U00002978',
+ "gtrdot": '\U000022D7',
+ "gtreqless": '\U000022DB',
+ "gtreqqless": '\U00002A8C',
+ "gtrless": '\U00002277',
+ "gtrsim": '\U00002273',
+ "hArr": '\U000021D4',
+ "hairsp": '\U0000200A',
+ "half": '\U000000BD',
+ "hamilt": '\U0000210B',
+ "hardcy": '\U0000044A',
+ "harr": '\U00002194',
+ "harrcir": '\U00002948',
+ "harrw": '\U000021AD',
+ "hbar": '\U0000210F',
+ "hcirc": '\U00000125',
+ "hearts": '\U00002665',
+ "heartsuit": '\U00002665',
+ "hellip": '\U00002026',
+ "hercon": '\U000022B9',
+ "hfr": '\U0001D525',
+ "hksearow": '\U00002925',
+ "hkswarow": '\U00002926',
+ "hoarr": '\U000021FF',
+ "homtht": '\U0000223B',
+ "hookleftarrow": '\U000021A9',
+ "hookrightarrow": '\U000021AA',
+ "hopf": '\U0001D559',
+ "horbar": '\U00002015',
+ "hscr": '\U0001D4BD',
+ "hslash": '\U0000210F',
+ "hstrok": '\U00000127',
+ "hybull": '\U00002043',
+ "hyphen": '\U00002010',
+ "iacute": '\U000000ED',
+ "ic": '\U00002063',
+ "icirc": '\U000000EE',
+ "icy": '\U00000438',
+ "iecy": '\U00000435',
+ "iexcl": '\U000000A1',
+ "iff": '\U000021D4',
+ "ifr": '\U0001D526',
+ "igrave": '\U000000EC',
+ "ii": '\U00002148',
+ "iiiint": '\U00002A0C',
+ "iiint": '\U0000222D',
+ "iinfin": '\U000029DC',
+ "iiota": '\U00002129',
+ "ijlig": '\U00000133',
+ "imacr": '\U0000012B',
+ "image": '\U00002111',
+ "imagline": '\U00002110',
+ "imagpart": '\U00002111',
+ "imath": '\U00000131',
+ "imof": '\U000022B7',
+ "imped": '\U000001B5',
+ "in": '\U00002208',
+ "incare": '\U00002105',
+ "infin": '\U0000221E',
+ "infintie": '\U000029DD',
+ "inodot": '\U00000131',
+ "int": '\U0000222B',
+ "intcal": '\U000022BA',
+ "integers": '\U00002124',
+ "intercal": '\U000022BA',
+ "intlarhk": '\U00002A17',
+ "intprod": '\U00002A3C',
+ "iocy": '\U00000451',
+ "iogon": '\U0000012F',
+ "iopf": '\U0001D55A',
+ "iota": '\U000003B9',
+ "iprod": '\U00002A3C',
+ "iquest": '\U000000BF',
+ "iscr": '\U0001D4BE',
+ "isin": '\U00002208',
+ "isinE": '\U000022F9',
+ "isindot": '\U000022F5',
+ "isins": '\U000022F4',
+ "isinsv": '\U000022F3',
+ "isinv": '\U00002208',
+ "it": '\U00002062',
+ "itilde": '\U00000129',
+ "iukcy": '\U00000456',
+ "iuml": '\U000000EF',
+ "jcirc": '\U00000135',
+ "jcy": '\U00000439',
+ "jfr": '\U0001D527',
+ "jmath": '\U00000237',
+ "jopf": '\U0001D55B',
+ "jscr": '\U0001D4BF',
+ "jsercy": '\U00000458',
+ "jukcy": '\U00000454',
+ "kappa": '\U000003BA',
+ "kappav": '\U000003F0',
+ "kcedil": '\U00000137',
+ "kcy": '\U0000043A',
+ "kfr": '\U0001D528',
+ "kgreen": '\U00000138',
+ "khcy": '\U00000445',
+ "kjcy": '\U0000045C',
+ "kopf": '\U0001D55C',
+ "kscr": '\U0001D4C0',
+ "lAarr": '\U000021DA',
+ "lArr": '\U000021D0',
+ "lAtail": '\U0000291B',
+ "lBarr": '\U0000290E',
+ "lE": '\U00002266',
+ "lEg": '\U00002A8B',
+ "lHar": '\U00002962',
+ "lacute": '\U0000013A',
+ "laemptyv": '\U000029B4',
+ "lagran": '\U00002112',
+ "lambda": '\U000003BB',
+ "lang": '\U000027E8',
+ "langd": '\U00002991',
+ "langle": '\U000027E8',
+ "lap": '\U00002A85',
+ "laquo": '\U000000AB',
+ "larr": '\U00002190',
+ "larrb": '\U000021E4',
+ "larrbfs": '\U0000291F',
+ "larrfs": '\U0000291D',
+ "larrhk": '\U000021A9',
+ "larrlp": '\U000021AB',
+ "larrpl": '\U00002939',
+ "larrsim": '\U00002973',
+ "larrtl": '\U000021A2',
+ "lat": '\U00002AAB',
+ "latail": '\U00002919',
+ "late": '\U00002AAD',
+ "lbarr": '\U0000290C',
+ "lbbrk": '\U00002772',
+ "lbrace": '\U0000007B',
+ "lbrack": '\U0000005B',
+ "lbrke": '\U0000298B',
+ "lbrksld": '\U0000298F',
+ "lbrkslu": '\U0000298D',
+ "lcaron": '\U0000013E',
+ "lcedil": '\U0000013C',
+ "lceil": '\U00002308',
+ "lcub": '\U0000007B',
+ "lcy": '\U0000043B',
+ "ldca": '\U00002936',
+ "ldquo": '\U0000201C',
+ "ldquor": '\U0000201E',
+ "ldrdhar": '\U00002967',
+ "ldrushar": '\U0000294B',
+ "ldsh": '\U000021B2',
+ "le": '\U00002264',
+ "leftarrow": '\U00002190',
+ "leftarrowtail": '\U000021A2',
+ "leftharpoondown": '\U000021BD',
+ "leftharpoonup": '\U000021BC',
+ "leftleftarrows": '\U000021C7',
+ "leftrightarrow": '\U00002194',
+ "leftrightarrows": '\U000021C6',
+ "leftrightharpoons": '\U000021CB',
+ "leftrightsquigarrow": '\U000021AD',
+ "leftthreetimes": '\U000022CB',
+ "leg": '\U000022DA',
+ "leq": '\U00002264',
+ "leqq": '\U00002266',
+ "leqslant": '\U00002A7D',
+ "les": '\U00002A7D',
+ "lescc": '\U00002AA8',
+ "lesdot": '\U00002A7F',
+ "lesdoto": '\U00002A81',
+ "lesdotor": '\U00002A83',
+ "lesges": '\U00002A93',
+ "lessapprox": '\U00002A85',
+ "lessdot": '\U000022D6',
+ "lesseqgtr": '\U000022DA',
+ "lesseqqgtr": '\U00002A8B',
+ "lessgtr": '\U00002276',
+ "lesssim": '\U00002272',
+ "lfisht": '\U0000297C',
+ "lfloor": '\U0000230A',
+ "lfr": '\U0001D529',
+ "lg": '\U00002276',
+ "lgE": '\U00002A91',
+ "lhard": '\U000021BD',
+ "lharu": '\U000021BC',
+ "lharul": '\U0000296A',
+ "lhblk": '\U00002584',
+ "ljcy": '\U00000459',
+ "ll": '\U0000226A',
+ "llarr": '\U000021C7',
+ "llcorner": '\U0000231E',
+ "llhard": '\U0000296B',
+ "lltri": '\U000025FA',
+ "lmidot": '\U00000140',
+ "lmoust": '\U000023B0',
+ "lmoustache": '\U000023B0',
+ "lnE": '\U00002268',
+ "lnap": '\U00002A89',
+ "lnapprox": '\U00002A89',
+ "lne": '\U00002A87',
+ "lneq": '\U00002A87',
+ "lneqq": '\U00002268',
+ "lnsim": '\U000022E6',
+ "loang": '\U000027EC',
+ "loarr": '\U000021FD',
+ "lobrk": '\U000027E6',
+ "longleftarrow": '\U000027F5',
+ "longleftrightarrow": '\U000027F7',
+ "longmapsto": '\U000027FC',
+ "longrightarrow": '\U000027F6',
+ "looparrowleft": '\U000021AB',
+ "looparrowright": '\U000021AC',
+ "lopar": '\U00002985',
+ "lopf": '\U0001D55D',
+ "loplus": '\U00002A2D',
+ "lotimes": '\U00002A34',
+ "lowast": '\U00002217',
+ "lowbar": '\U0000005F',
+ "loz": '\U000025CA',
+ "lozenge": '\U000025CA',
+ "lozf": '\U000029EB',
+ "lpar": '\U00000028',
+ "lparlt": '\U00002993',
+ "lrarr": '\U000021C6',
+ "lrcorner": '\U0000231F',
+ "lrhar": '\U000021CB',
+ "lrhard": '\U0000296D',
+ "lrm": '\U0000200E',
+ "lrtri": '\U000022BF',
+ "lsaquo": '\U00002039',
+ "lscr": '\U0001D4C1',
+ "lsh": '\U000021B0',
+ "lsim": '\U00002272',
+ "lsime": '\U00002A8D',
+ "lsimg": '\U00002A8F',
+ "lsqb": '\U0000005B',
+ "lsquo": '\U00002018',
+ "lsquor": '\U0000201A',
+ "lstrok": '\U00000142',
+ "lt": '\U0000003C',
+ "ltcc": '\U00002AA6',
+ "ltcir": '\U00002A79',
+ "ltdot": '\U000022D6',
+ "lthree": '\U000022CB',
+ "ltimes": '\U000022C9',
+ "ltlarr": '\U00002976',
+ "ltquest": '\U00002A7B',
+ "ltrPar": '\U00002996',
+ "ltri": '\U000025C3',
+ "ltrie": '\U000022B4',
+ "ltrif": '\U000025C2',
+ "lurdshar": '\U0000294A',
+ "luruhar": '\U00002966',
+ "mDDot": '\U0000223A',
+ "macr": '\U000000AF',
+ "male": '\U00002642',
+ "malt": '\U00002720',
+ "maltese": '\U00002720',
+ "map": '\U000021A6',
+ "mapsto": '\U000021A6',
+ "mapstodown": '\U000021A7',
+ "mapstoleft": '\U000021A4',
+ "mapstoup": '\U000021A5',
+ "marker": '\U000025AE',
+ "mcomma": '\U00002A29',
+ "mcy": '\U0000043C',
+ "mdash": '\U00002014',
+ "measuredangle": '\U00002221',
+ "mfr": '\U0001D52A',
+ "mho": '\U00002127',
+ "micro": '\U000000B5',
+ "mid": '\U00002223',
+ "midast": '\U0000002A',
+ "midcir": '\U00002AF0',
+ "middot": '\U000000B7',
+ "minus": '\U00002212',
+ "minusb": '\U0000229F',
+ "minusd": '\U00002238',
+ "minusdu": '\U00002A2A',
+ "mlcp": '\U00002ADB',
+ "mldr": '\U00002026',
+ "mnplus": '\U00002213',
+ "models": '\U000022A7',
+ "mopf": '\U0001D55E',
+ "mp": '\U00002213',
+ "mscr": '\U0001D4C2',
+ "mstpos": '\U0000223E',
+ "mu": '\U000003BC',
+ "multimap": '\U000022B8',
+ "mumap": '\U000022B8',
+ "nLeftarrow": '\U000021CD',
+ "nLeftrightarrow": '\U000021CE',
+ "nRightarrow": '\U000021CF',
+ "nVDash": '\U000022AF',
+ "nVdash": '\U000022AE',
+ "nabla": '\U00002207',
+ "nacute": '\U00000144',
+ "nap": '\U00002249',
+ "napos": '\U00000149',
+ "napprox": '\U00002249',
+ "natur": '\U0000266E',
+ "natural": '\U0000266E',
+ "naturals": '\U00002115',
+ "nbsp": '\U000000A0',
+ "ncap": '\U00002A43',
+ "ncaron": '\U00000148',
+ "ncedil": '\U00000146',
+ "ncong": '\U00002247',
+ "ncup": '\U00002A42',
+ "ncy": '\U0000043D',
+ "ndash": '\U00002013',
+ "ne": '\U00002260',
+ "neArr": '\U000021D7',
+ "nearhk": '\U00002924',
+ "nearr": '\U00002197',
+ "nearrow": '\U00002197',
+ "nequiv": '\U00002262',
+ "nesear": '\U00002928',
+ "nexist": '\U00002204',
+ "nexists": '\U00002204',
+ "nfr": '\U0001D52B',
+ "nge": '\U00002271',
+ "ngeq": '\U00002271',
+ "ngsim": '\U00002275',
+ "ngt": '\U0000226F',
+ "ngtr": '\U0000226F',
+ "nhArr": '\U000021CE',
+ "nharr": '\U000021AE',
+ "nhpar": '\U00002AF2',
+ "ni": '\U0000220B',
+ "nis": '\U000022FC',
+ "nisd": '\U000022FA',
+ "niv": '\U0000220B',
+ "njcy": '\U0000045A',
+ "nlArr": '\U000021CD',
+ "nlarr": '\U0000219A',
+ "nldr": '\U00002025',
+ "nle": '\U00002270',
+ "nleftarrow": '\U0000219A',
+ "nleftrightarrow": '\U000021AE',
+ "nleq": '\U00002270',
+ "nless": '\U0000226E',
+ "nlsim": '\U00002274',
+ "nlt": '\U0000226E',
+ "nltri": '\U000022EA',
+ "nltrie": '\U000022EC',
+ "nmid": '\U00002224',
+ "nopf": '\U0001D55F',
+ "not": '\U000000AC',
+ "notin": '\U00002209',
+ "notinva": '\U00002209',
+ "notinvb": '\U000022F7',
+ "notinvc": '\U000022F6',
+ "notni": '\U0000220C',
+ "notniva": '\U0000220C',
+ "notnivb": '\U000022FE',
+ "notnivc": '\U000022FD',
+ "npar": '\U00002226',
+ "nparallel": '\U00002226',
+ "npolint": '\U00002A14',
+ "npr": '\U00002280',
+ "nprcue": '\U000022E0',
+ "nprec": '\U00002280',
+ "nrArr": '\U000021CF',
+ "nrarr": '\U0000219B',
+ "nrightarrow": '\U0000219B',
+ "nrtri": '\U000022EB',
+ "nrtrie": '\U000022ED',
+ "nsc": '\U00002281',
+ "nsccue": '\U000022E1',
+ "nscr": '\U0001D4C3',
+ "nshortmid": '\U00002224',
+ "nshortparallel": '\U00002226',
+ "nsim": '\U00002241',
+ "nsime": '\U00002244',
+ "nsimeq": '\U00002244',
+ "nsmid": '\U00002224',
+ "nspar": '\U00002226',
+ "nsqsube": '\U000022E2',
+ "nsqsupe": '\U000022E3',
+ "nsub": '\U00002284',
+ "nsube": '\U00002288',
+ "nsubseteq": '\U00002288',
+ "nsucc": '\U00002281',
+ "nsup": '\U00002285',
+ "nsupe": '\U00002289',
+ "nsupseteq": '\U00002289',
+ "ntgl": '\U00002279',
+ "ntilde": '\U000000F1',
+ "ntlg": '\U00002278',
+ "ntriangleleft": '\U000022EA',
+ "ntrianglelefteq": '\U000022EC',
+ "ntriangleright": '\U000022EB',
+ "ntrianglerighteq": '\U000022ED',
+ "nu": '\U000003BD',
+ "num": '\U00000023',
+ "numero": '\U00002116',
+ "numsp": '\U00002007',
+ "nvDash": '\U000022AD',
+ "nvHarr": '\U00002904',
+ "nvdash": '\U000022AC',
+ "nvinfin": '\U000029DE',
+ "nvlArr": '\U00002902',
+ "nvrArr": '\U00002903',
+ "nwArr": '\U000021D6',
+ "nwarhk": '\U00002923',
+ "nwarr": '\U00002196',
+ "nwarrow": '\U00002196',
+ "nwnear": '\U00002927',
+ "oS": '\U000024C8',
+ "oacute": '\U000000F3',
+ "oast": '\U0000229B',
+ "ocir": '\U0000229A',
+ "ocirc": '\U000000F4',
+ "ocy": '\U0000043E',
+ "odash": '\U0000229D',
+ "odblac": '\U00000151',
+ "odiv": '\U00002A38',
+ "odot": '\U00002299',
+ "odsold": '\U000029BC',
+ "oelig": '\U00000153',
+ "ofcir": '\U000029BF',
+ "ofr": '\U0001D52C',
+ "ogon": '\U000002DB',
+ "ograve": '\U000000F2',
+ "ogt": '\U000029C1',
+ "ohbar": '\U000029B5',
+ "ohm": '\U000003A9',
+ "oint": '\U0000222E',
+ "olarr": '\U000021BA',
+ "olcir": '\U000029BE',
+ "olcross": '\U000029BB',
+ "oline": '\U0000203E',
+ "olt": '\U000029C0',
+ "omacr": '\U0000014D',
+ "omega": '\U000003C9',
+ "omicron": '\U000003BF',
+ "omid": '\U000029B6',
+ "ominus": '\U00002296',
+ "oopf": '\U0001D560',
+ "opar": '\U000029B7',
+ "operp": '\U000029B9',
+ "oplus": '\U00002295',
+ "or": '\U00002228',
+ "orarr": '\U000021BB',
+ "ord": '\U00002A5D',
+ "order": '\U00002134',
+ "orderof": '\U00002134',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "origof": '\U000022B6',
+ "oror": '\U00002A56',
+ "orslope": '\U00002A57',
+ "orv": '\U00002A5B',
+ "oscr": '\U00002134',
+ "oslash": '\U000000F8',
+ "osol": '\U00002298',
+ "otilde": '\U000000F5',
+ "otimes": '\U00002297',
+ "otimesas": '\U00002A36',
+ "ouml": '\U000000F6',
+ "ovbar": '\U0000233D',
+ "par": '\U00002225',
+ "para": '\U000000B6',
+ "parallel": '\U00002225',
+ "parsim": '\U00002AF3',
+ "parsl": '\U00002AFD',
+ "part": '\U00002202',
+ "pcy": '\U0000043F',
+ "percnt": '\U00000025',
+ "period": '\U0000002E',
+ "permil": '\U00002030',
+ "perp": '\U000022A5',
+ "pertenk": '\U00002031',
+ "pfr": '\U0001D52D',
+ "phi": '\U000003C6',
+ "phiv": '\U000003D5',
+ "phmmat": '\U00002133',
+ "phone": '\U0000260E',
+ "pi": '\U000003C0',
+ "pitchfork": '\U000022D4',
+ "piv": '\U000003D6',
+ "planck": '\U0000210F',
+ "planckh": '\U0000210E',
+ "plankv": '\U0000210F',
+ "plus": '\U0000002B',
+ "plusacir": '\U00002A23',
+ "plusb": '\U0000229E',
+ "pluscir": '\U00002A22',
+ "plusdo": '\U00002214',
+ "plusdu": '\U00002A25',
+ "pluse": '\U00002A72',
+ "plusmn": '\U000000B1',
+ "plussim": '\U00002A26',
+ "plustwo": '\U00002A27',
+ "pm": '\U000000B1',
+ "pointint": '\U00002A15',
+ "popf": '\U0001D561',
+ "pound": '\U000000A3',
+ "pr": '\U0000227A',
+ "prE": '\U00002AB3',
+ "prap": '\U00002AB7',
+ "prcue": '\U0000227C',
+ "pre": '\U00002AAF',
+ "prec": '\U0000227A',
+ "precapprox": '\U00002AB7',
+ "preccurlyeq": '\U0000227C',
+ "preceq": '\U00002AAF',
+ "precnapprox": '\U00002AB9',
+ "precneqq": '\U00002AB5',
+ "precnsim": '\U000022E8',
+ "precsim": '\U0000227E',
+ "prime": '\U00002032',
+ "primes": '\U00002119',
+ "prnE": '\U00002AB5',
+ "prnap": '\U00002AB9',
+ "prnsim": '\U000022E8',
+ "prod": '\U0000220F',
+ "profalar": '\U0000232E',
+ "profline": '\U00002312',
+ "profsurf": '\U00002313',
+ "prop": '\U0000221D',
+ "propto": '\U0000221D',
+ "prsim": '\U0000227E',
+ "prurel": '\U000022B0',
+ "pscr": '\U0001D4C5',
+ "psi": '\U000003C8',
+ "puncsp": '\U00002008',
+ "qfr": '\U0001D52E',
+ "qint": '\U00002A0C',
+ "qopf": '\U0001D562',
+ "qprime": '\U00002057',
+ "qscr": '\U0001D4C6',
+ "quaternions": '\U0000210D',
+ "quatint": '\U00002A16',
+ "quest": '\U0000003F',
+ "questeq": '\U0000225F',
+ "quot": '\U00000022',
+ "rAarr": '\U000021DB',
+ "rArr": '\U000021D2',
+ "rAtail": '\U0000291C',
+ "rBarr": '\U0000290F',
+ "rHar": '\U00002964',
+ "racute": '\U00000155',
+ "radic": '\U0000221A',
+ "raemptyv": '\U000029B3',
+ "rang": '\U000027E9',
+ "rangd": '\U00002992',
+ "range": '\U000029A5',
+ "rangle": '\U000027E9',
+ "raquo": '\U000000BB',
+ "rarr": '\U00002192',
+ "rarrap": '\U00002975',
+ "rarrb": '\U000021E5',
+ "rarrbfs": '\U00002920',
+ "rarrc": '\U00002933',
+ "rarrfs": '\U0000291E',
+ "rarrhk": '\U000021AA',
+ "rarrlp": '\U000021AC',
+ "rarrpl": '\U00002945',
+ "rarrsim": '\U00002974',
+ "rarrtl": '\U000021A3',
+ "rarrw": '\U0000219D',
+ "ratail": '\U0000291A',
+ "ratio": '\U00002236',
+ "rationals": '\U0000211A',
+ "rbarr": '\U0000290D',
+ "rbbrk": '\U00002773',
+ "rbrace": '\U0000007D',
+ "rbrack": '\U0000005D',
+ "rbrke": '\U0000298C',
+ "rbrksld": '\U0000298E',
+ "rbrkslu": '\U00002990',
+ "rcaron": '\U00000159',
+ "rcedil": '\U00000157',
+ "rceil": '\U00002309',
+ "rcub": '\U0000007D',
+ "rcy": '\U00000440',
+ "rdca": '\U00002937',
+ "rdldhar": '\U00002969',
+ "rdquo": '\U0000201D',
+ "rdquor": '\U0000201D',
+ "rdsh": '\U000021B3',
+ "real": '\U0000211C',
+ "realine": '\U0000211B',
+ "realpart": '\U0000211C',
+ "reals": '\U0000211D',
+ "rect": '\U000025AD',
+ "reg": '\U000000AE',
+ "rfisht": '\U0000297D',
+ "rfloor": '\U0000230B',
+ "rfr": '\U0001D52F',
+ "rhard": '\U000021C1',
+ "rharu": '\U000021C0',
+ "rharul": '\U0000296C',
+ "rho": '\U000003C1',
+ "rhov": '\U000003F1',
+ "rightarrow": '\U00002192',
+ "rightarrowtail": '\U000021A3',
+ "rightharpoondown": '\U000021C1',
+ "rightharpoonup": '\U000021C0',
+ "rightleftarrows": '\U000021C4',
+ "rightleftharpoons": '\U000021CC',
+ "rightrightarrows": '\U000021C9',
+ "rightsquigarrow": '\U0000219D',
+ "rightthreetimes": '\U000022CC',
+ "ring": '\U000002DA',
+ "risingdotseq": '\U00002253',
+ "rlarr": '\U000021C4',
+ "rlhar": '\U000021CC',
+ "rlm": '\U0000200F',
+ "rmoust": '\U000023B1',
+ "rmoustache": '\U000023B1',
+ "rnmid": '\U00002AEE',
+ "roang": '\U000027ED',
+ "roarr": '\U000021FE',
+ "robrk": '\U000027E7',
+ "ropar": '\U00002986',
+ "ropf": '\U0001D563',
+ "roplus": '\U00002A2E',
+ "rotimes": '\U00002A35',
+ "rpar": '\U00000029',
+ "rpargt": '\U00002994',
+ "rppolint": '\U00002A12',
+ "rrarr": '\U000021C9',
+ "rsaquo": '\U0000203A',
+ "rscr": '\U0001D4C7',
+ "rsh": '\U000021B1',
+ "rsqb": '\U0000005D',
+ "rsquo": '\U00002019',
+ "rsquor": '\U00002019',
+ "rthree": '\U000022CC',
+ "rtimes": '\U000022CA',
+ "rtri": '\U000025B9',
+ "rtrie": '\U000022B5',
+ "rtrif": '\U000025B8',
+ "rtriltri": '\U000029CE',
+ "ruluhar": '\U00002968',
+ "rx": '\U0000211E',
+ "sacute": '\U0000015B',
+ "sbquo": '\U0000201A',
+ "sc": '\U0000227B',
+ "scE": '\U00002AB4',
+ "scap": '\U00002AB8',
+ "scaron": '\U00000161',
+ "sccue": '\U0000227D',
+ "sce": '\U00002AB0',
+ "scedil": '\U0000015F',
+ "scirc": '\U0000015D',
+ "scnE": '\U00002AB6',
+ "scnap": '\U00002ABA',
+ "scnsim": '\U000022E9',
+ "scpolint": '\U00002A13',
+ "scsim": '\U0000227F',
+ "scy": '\U00000441',
+ "sdot": '\U000022C5',
+ "sdotb": '\U000022A1',
+ "sdote": '\U00002A66',
+ "seArr": '\U000021D8',
+ "searhk": '\U00002925',
+ "searr": '\U00002198',
+ "searrow": '\U00002198',
+ "sect": '\U000000A7',
+ "semi": '\U0000003B',
+ "seswar": '\U00002929',
+ "setminus": '\U00002216',
+ "setmn": '\U00002216',
+ "sext": '\U00002736',
+ "sfr": '\U0001D530',
+ "sfrown": '\U00002322',
+ "sharp": '\U0000266F',
+ "shchcy": '\U00000449',
+ "shcy": '\U00000448',
+ "shortmid": '\U00002223',
+ "shortparallel": '\U00002225',
+ "shy": '\U000000AD',
+ "sigma": '\U000003C3',
+ "sigmaf": '\U000003C2',
+ "sigmav": '\U000003C2',
+ "sim": '\U0000223C',
+ "simdot": '\U00002A6A',
+ "sime": '\U00002243',
+ "simeq": '\U00002243',
+ "simg": '\U00002A9E',
+ "simgE": '\U00002AA0',
+ "siml": '\U00002A9D',
+ "simlE": '\U00002A9F',
+ "simne": '\U00002246',
+ "simplus": '\U00002A24',
+ "simrarr": '\U00002972',
+ "slarr": '\U00002190',
+ "smallsetminus": '\U00002216',
+ "smashp": '\U00002A33',
+ "smeparsl": '\U000029E4',
+ "smid": '\U00002223',
+ "smile": '\U00002323',
+ "smt": '\U00002AAA',
+ "smte": '\U00002AAC',
+ "softcy": '\U0000044C',
+ "sol": '\U0000002F',
+ "solb": '\U000029C4',
+ "solbar": '\U0000233F',
+ "sopf": '\U0001D564',
+ "spades": '\U00002660',
+ "spadesuit": '\U00002660',
+ "spar": '\U00002225',
+ "sqcap": '\U00002293',
+ "sqcup": '\U00002294',
+ "sqsub": '\U0000228F',
+ "sqsube": '\U00002291',
+ "sqsubset": '\U0000228F',
+ "sqsubseteq": '\U00002291',
+ "sqsup": '\U00002290',
+ "sqsupe": '\U00002292',
+ "sqsupset": '\U00002290',
+ "sqsupseteq": '\U00002292',
+ "squ": '\U000025A1',
+ "square": '\U000025A1',
+ "squarf": '\U000025AA',
+ "squf": '\U000025AA',
+ "srarr": '\U00002192',
+ "sscr": '\U0001D4C8',
+ "ssetmn": '\U00002216',
+ "ssmile": '\U00002323',
+ "sstarf": '\U000022C6',
+ "star": '\U00002606',
+ "starf": '\U00002605',
+ "straightepsilon": '\U000003F5',
+ "straightphi": '\U000003D5',
+ "strns": '\U000000AF',
+ "sub": '\U00002282',
+ "subE": '\U00002AC5',
+ "subdot": '\U00002ABD',
+ "sube": '\U00002286',
+ "subedot": '\U00002AC3',
+ "submult": '\U00002AC1',
+ "subnE": '\U00002ACB',
+ "subne": '\U0000228A',
+ "subplus": '\U00002ABF',
+ "subrarr": '\U00002979',
+ "subset": '\U00002282',
+ "subseteq": '\U00002286',
+ "subseteqq": '\U00002AC5',
+ "subsetneq": '\U0000228A',
+ "subsetneqq": '\U00002ACB',
+ "subsim": '\U00002AC7',
+ "subsub": '\U00002AD5',
+ "subsup": '\U00002AD3',
+ "succ": '\U0000227B',
+ "succapprox": '\U00002AB8',
+ "succcurlyeq": '\U0000227D',
+ "succeq": '\U00002AB0',
+ "succnapprox": '\U00002ABA',
+ "succneqq": '\U00002AB6',
+ "succnsim": '\U000022E9',
+ "succsim": '\U0000227F',
+ "sum": '\U00002211',
+ "sung": '\U0000266A',
+ "sup": '\U00002283',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "supE": '\U00002AC6',
+ "supdot": '\U00002ABE',
+ "supdsub": '\U00002AD8',
+ "supe": '\U00002287',
+ "supedot": '\U00002AC4',
+ "suphsol": '\U000027C9',
+ "suphsub": '\U00002AD7',
+ "suplarr": '\U0000297B',
+ "supmult": '\U00002AC2',
+ "supnE": '\U00002ACC',
+ "supne": '\U0000228B',
+ "supplus": '\U00002AC0',
+ "supset": '\U00002283',
+ "supseteq": '\U00002287',
+ "supseteqq": '\U00002AC6',
+ "supsetneq": '\U0000228B',
+ "supsetneqq": '\U00002ACC',
+ "supsim": '\U00002AC8',
+ "supsub": '\U00002AD4',
+ "supsup": '\U00002AD6',
+ "swArr": '\U000021D9',
+ "swarhk": '\U00002926',
+ "swarr": '\U00002199',
+ "swarrow": '\U00002199',
+ "swnwar": '\U0000292A',
+ "szlig": '\U000000DF',
+ "target": '\U00002316',
+ "tau": '\U000003C4',
+ "tbrk": '\U000023B4',
+ "tcaron": '\U00000165',
+ "tcedil": '\U00000163',
+ "tcy": '\U00000442',
+ "tdot": '\U000020DB',
+ "telrec": '\U00002315',
+ "tfr": '\U0001D531',
+ "there4": '\U00002234',
+ "therefore": '\U00002234',
+ "theta": '\U000003B8',
+ "thetasym": '\U000003D1',
+ "thetav": '\U000003D1',
+ "thickapprox": '\U00002248',
+ "thicksim": '\U0000223C',
+ "thinsp": '\U00002009',
+ "thkap": '\U00002248',
+ "thksim": '\U0000223C',
+ "thorn": '\U000000FE',
+ "tilde": '\U000002DC',
+ "times": '\U000000D7',
+ "timesb": '\U000022A0',
+ "timesbar": '\U00002A31',
+ "timesd": '\U00002A30',
+ "tint": '\U0000222D',
+ "toea": '\U00002928',
+ "top": '\U000022A4',
+ "topbot": '\U00002336',
+ "topcir": '\U00002AF1',
+ "topf": '\U0001D565',
+ "topfork": '\U00002ADA',
+ "tosa": '\U00002929',
+ "tprime": '\U00002034',
+ "trade": '\U00002122',
+ "triangle": '\U000025B5',
+ "triangledown": '\U000025BF',
+ "triangleleft": '\U000025C3',
+ "trianglelefteq": '\U000022B4',
+ "triangleq": '\U0000225C',
+ "triangleright": '\U000025B9',
+ "trianglerighteq": '\U000022B5',
+ "tridot": '\U000025EC',
+ "trie": '\U0000225C',
+ "triminus": '\U00002A3A',
+ "triplus": '\U00002A39',
+ "trisb": '\U000029CD',
+ "tritime": '\U00002A3B',
+ "trpezium": '\U000023E2',
+ "tscr": '\U0001D4C9',
+ "tscy": '\U00000446',
+ "tshcy": '\U0000045B',
+ "tstrok": '\U00000167',
+ "twixt": '\U0000226C',
+ "twoheadleftarrow": '\U0000219E',
+ "twoheadrightarrow": '\U000021A0',
+ "uArr": '\U000021D1',
+ "uHar": '\U00002963',
+ "uacute": '\U000000FA',
+ "uarr": '\U00002191',
+ "ubrcy": '\U0000045E',
+ "ubreve": '\U0000016D',
+ "ucirc": '\U000000FB',
+ "ucy": '\U00000443',
+ "udarr": '\U000021C5',
+ "udblac": '\U00000171',
+ "udhar": '\U0000296E',
+ "ufisht": '\U0000297E',
+ "ufr": '\U0001D532',
+ "ugrave": '\U000000F9',
+ "uharl": '\U000021BF',
+ "uharr": '\U000021BE',
+ "uhblk": '\U00002580',
+ "ulcorn": '\U0000231C',
+ "ulcorner": '\U0000231C',
+ "ulcrop": '\U0000230F',
+ "ultri": '\U000025F8',
+ "umacr": '\U0000016B',
+ "uml": '\U000000A8',
+ "uogon": '\U00000173',
+ "uopf": '\U0001D566',
+ "uparrow": '\U00002191',
+ "updownarrow": '\U00002195',
+ "upharpoonleft": '\U000021BF',
+ "upharpoonright": '\U000021BE',
+ "uplus": '\U0000228E',
+ "upsi": '\U000003C5',
+ "upsih": '\U000003D2',
+ "upsilon": '\U000003C5',
+ "upuparrows": '\U000021C8',
+ "urcorn": '\U0000231D',
+ "urcorner": '\U0000231D',
+ "urcrop": '\U0000230E',
+ "uring": '\U0000016F',
+ "urtri": '\U000025F9',
+ "uscr": '\U0001D4CA',
+ "utdot": '\U000022F0',
+ "utilde": '\U00000169',
+ "utri": '\U000025B5',
+ "utrif": '\U000025B4',
+ "uuarr": '\U000021C8',
+ "uuml": '\U000000FC',
+ "uwangle": '\U000029A7',
+ "vArr": '\U000021D5',
+ "vBar": '\U00002AE8',
+ "vBarv": '\U00002AE9',
+ "vDash": '\U000022A8',
+ "vangrt": '\U0000299C',
+ "varepsilon": '\U000003F5',
+ "varkappa": '\U000003F0',
+ "varnothing": '\U00002205',
+ "varphi": '\U000003D5',
+ "varpi": '\U000003D6',
+ "varpropto": '\U0000221D',
+ "varr": '\U00002195',
+ "varrho": '\U000003F1',
+ "varsigma": '\U000003C2',
+ "vartheta": '\U000003D1',
+ "vartriangleleft": '\U000022B2',
+ "vartriangleright": '\U000022B3',
+ "vcy": '\U00000432',
+ "vdash": '\U000022A2',
+ "vee": '\U00002228',
+ "veebar": '\U000022BB',
+ "veeeq": '\U0000225A',
+ "vellip": '\U000022EE',
+ "verbar": '\U0000007C',
+ "vert": '\U0000007C',
+ "vfr": '\U0001D533',
+ "vltri": '\U000022B2',
+ "vopf": '\U0001D567',
+ "vprop": '\U0000221D',
+ "vrtri": '\U000022B3',
+ "vscr": '\U0001D4CB',
+ "vzigzag": '\U0000299A',
+ "wcirc": '\U00000175',
+ "wedbar": '\U00002A5F',
+ "wedge": '\U00002227',
+ "wedgeq": '\U00002259',
+ "weierp": '\U00002118',
+ "wfr": '\U0001D534',
+ "wopf": '\U0001D568',
+ "wp": '\U00002118',
+ "wr": '\U00002240',
+ "wreath": '\U00002240',
+ "wscr": '\U0001D4CC',
+ "xcap": '\U000022C2',
+ "xcirc": '\U000025EF',
+ "xcup": '\U000022C3',
+ "xdtri": '\U000025BD',
+ "xfr": '\U0001D535',
+ "xhArr": '\U000027FA',
+ "xharr": '\U000027F7',
+ "xi": '\U000003BE',
+ "xlArr": '\U000027F8',
+ "xlarr": '\U000027F5',
+ "xmap": '\U000027FC',
+ "xnis": '\U000022FB',
+ "xodot": '\U00002A00',
+ "xopf": '\U0001D569',
+ "xoplus": '\U00002A01',
+ "xotime": '\U00002A02',
+ "xrArr": '\U000027F9',
+ "xrarr": '\U000027F6',
+ "xscr": '\U0001D4CD',
+ "xsqcup": '\U00002A06',
+ "xuplus": '\U00002A04',
+ "xutri": '\U000025B3',
+ "xvee": '\U000022C1',
+ "xwedge": '\U000022C0',
+ "yacute": '\U000000FD',
+ "yacy": '\U0000044F',
+ "ycirc": '\U00000177',
+ "ycy": '\U0000044B',
+ "yen": '\U000000A5',
+ "yfr": '\U0001D536',
+ "yicy": '\U00000457',
+ "yopf": '\U0001D56A',
+ "yscr": '\U0001D4CE',
+ "yucy": '\U0000044E',
+ "yuml": '\U000000FF',
+ "zacute": '\U0000017A',
+ "zcaron": '\U0000017E',
+ "zcy": '\U00000437',
+ "zdot": '\U0000017C',
+ "zeetrf": '\U00002128',
+ "zeta": '\U000003B6',
+ "zfr": '\U0001D537',
+ "zhcy": '\U00000436',
+ "zigrarr": '\U000021DD',
+ "zopf": '\U0001D56B',
+ "zscr": '\U0001D4CF',
+ "zwj": '\U0000200D',
+ "zwnj": '\U0000200C',
+}
diff --git a/vendor/github.com/k3a/html2text/html2text.go b/vendor/github.com/k3a/html2text/html2text.go
new file mode 100644
index 000000000..f79fbe395
--- /dev/null
+++ b/vendor/github.com/k3a/html2text/html2text.go
@@ -0,0 +1,333 @@
+package html2text
+
+import (
+ "bytes"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// Line break constants
+// Deprecated: Please use HTML2TextWithOptions(text, WithUnixLineBreak())
+const (
+ WIN_LBR = "\r\n"
+ UNIX_LBR = "\n"
+)
+
+var legacyLBR = WIN_LBR
+var badTagnamesRE = regexp.MustCompile(`^(head|script|style|a)($|\s+)`)
+var linkTagRE = regexp.MustCompile(`^(?i:a)(?:$|\s).*(?i:href)\s*=\s*('([^']*?)'|"([^"]*?)"|([^\s"'` + "`" + `=<>]+))`)
+var badLinkHrefRE = regexp.MustCompile(`javascript:`)
+var headersRE = regexp.MustCompile(`^(\/)?h[1-6]`)
+var numericEntityRE = regexp.MustCompile(`(?i)^#(x?[a-f0-9]+)$`)
+
+type options struct {
+ lbr string
+ linksInnerText bool
+ listPrefix string
+}
+
+func newOptions() *options {
+ // apply defaults
+ return &options{
+ lbr: WIN_LBR,
+ }
+}
+
+// Option is a functional option
+type Option func(*options)
+
+// WithUnixLineBreaks instructs the converter to use unix line breaks ("\n" instead of "\r\n" default)
+func WithUnixLineBreaks() Option {
+ return func(o *options) {
+ o.lbr = UNIX_LBR
+ }
+}
+
+// WithLinksInnerText instructs the converter to retain link tag inner text and append href URLs in angle brackets after the text
+// Example: click news
+func WithLinksInnerText() Option {
+ return func(o *options) {
+ o.linksInnerText = true
+ }
+}
+
+// WithListSupportPrefix formats and - lists with the specified prefix
+func WithListSupportPrefix(prefix string) Option {
+ return func(o *options) {
+ o.listPrefix = prefix
+ }
+}
+
+// WithListSupport formats
and - lists with " - " prefix
+func WithListSupport() Option {
+ return WithListSupportPrefix(" - ")
+}
+
+func parseHTMLEntity(entName string) (string, bool) {
+ if r, ok := entity[entName]; ok {
+ return string(r), true
+ }
+
+ if match := numericEntityRE.FindStringSubmatch(entName); len(match) == 2 {
+ var (
+ err error
+ n int64
+ digits = match[1]
+ )
+
+ if digits != "" && (digits[0] == 'x' || digits[0] == 'X') {
+ n, err = strconv.ParseInt(digits[1:], 16, 64)
+ } else {
+ n, err = strconv.ParseInt(digits, 10, 64)
+ }
+
+ if err == nil && (n == 9 || n == 10 || n == 13 || n > 31) {
+ return string(rune(n)), true
+ }
+ }
+
+ return "", false
+}
+
+// SetUnixLbr with argument true sets Unix-style line-breaks in output ("\n")
+// with argument false sets Windows-style line-breaks in output ("\r\n", the default)
+// Deprecated: Please use HTML2TextWithOptions(text, WithUnixLineBreak())
+func SetUnixLbr(b bool) {
+ if b {
+ legacyLBR = UNIX_LBR
+ } else {
+ legacyLBR = WIN_LBR
+ }
+}
+
+// HTMLEntitiesToText decodes HTML entities inside a provided
+// string and returns decoded text
+func HTMLEntitiesToText(htmlEntsText string) string {
+ outBuf := bytes.NewBufferString("")
+ inEnt := false
+
+ for i, r := range htmlEntsText {
+ switch {
+ case r == ';' && inEnt:
+ inEnt = false
+ continue
+
+ case r == '&': //possible html entity
+ entName := ""
+ isEnt := false
+
+ // parse the entity name - max 10 chars
+ chars := 0
+ for _, er := range htmlEntsText[i+1:] {
+ if er == ';' {
+ isEnt = true
+ break
+ } else {
+ entName += string(er)
+ }
+
+ chars++
+ if chars == 10 {
+ break
+ }
+ }
+
+ if isEnt {
+ if ent, isEnt := parseHTMLEntity(entName); isEnt {
+ outBuf.WriteString(ent)
+ inEnt = true
+ continue
+ }
+ }
+ }
+
+ if !inEnt {
+ outBuf.WriteRune(r)
+ }
+ }
+
+ return outBuf.String()
+}
+
+func writeSpace(outBuf *bytes.Buffer) {
+ bts := outBuf.Bytes()
+ if len(bts) > 0 && bts[len(bts)-1] != ' ' {
+ outBuf.WriteString(" ")
+ }
+}
+
+// HTML2Text converts html into a text form
+func HTML2Text(html string) string {
+ var opts []Option
+ if legacyLBR == UNIX_LBR {
+ opts = append(opts, WithUnixLineBreaks())
+ }
+ return HTML2TextWithOptions(html, opts...)
+}
+
+// HTML2TextWithOptions converts html into a text form with additional options
+func HTML2TextWithOptions(html string, reqOpts ...Option) string {
+ opts := newOptions()
+ for _, opt := range reqOpts {
+ opt(opts)
+ }
+
+ inLen := len(html)
+ tagStart := 0
+ inEnt := false
+ badTagStackDepth := 0 // if == 1 it means we are inside ...
+ shouldOutput := true
+ // maintain a stack of tag href links and output it after the tag's inner text (for opts.linksInnerText only)
+ hrefs := []string{}
+ // new line cannot be printed at the beginning or
+ // for
after a new line created by previous
+ canPrintNewline := false
+
+ outBuf := bytes.NewBufferString("")
+
+ for i, r := range html {
+ if inLen > 0 && i == inLen-1 {
+ // prevent new line at the end of the document
+ canPrintNewline = false
+ }
+
+ switch {
+ // skip new lines and spaces adding a single space if not there yet
+ case r <= 0xD, r == 0x85, r == 0x2028, r == 0x2029, // new lines
+ r == ' ', r >= 0x2008 && r <= 0x200B: // spaces
+ if shouldOutput && badTagStackDepth == 0 && !inEnt {
+ //outBuf.WriteString(fmt.Sprintf("{DBG r:%c, inEnt:%t, tag:%s}", r, inEnt, html[tagStart:i]))
+ writeSpace(outBuf)
+ }
+ continue
+
+ case r == ';' && inEnt: // end of html entity
+ inEnt = false
+ continue
+
+ case r == '&' && shouldOutput: // possible html entity
+ entName := ""
+ isEnt := false
+
+ // parse the entity name - max 10 chars
+ chars := 0
+ for _, er := range html[i+1:] {
+ if er == ';' {
+ isEnt = true
+ break
+ } else {
+ entName += string(er)
+ }
+
+ chars++
+ if chars == 10 {
+ break
+ }
+ }
+
+ if isEnt {
+ if ent, isEnt := parseHTMLEntity(entName); isEnt {
+ outBuf.WriteString(ent)
+ inEnt = true
+ continue
+ }
+ }
+
+ case r == '<': // start of a tag
+ tagStart = i + 1
+ shouldOutput = false
+ continue
+
+ case r == '>': // end of a tag
+ shouldOutput = true
+ tag := html[tagStart:i]
+ tagNameLowercase := strings.ToLower(tag)
+
+ if tagNameLowercase == "/ul" || tagNameLowercase == "/ol" {
+ outBuf.WriteString(opts.lbr)
+ } else if tagNameLowercase == "li" || tagNameLowercase == "li/" {
+ if opts.listPrefix != "" {
+ outBuf.WriteString(opts.lbr + opts.listPrefix)
+ } else {
+ outBuf.WriteString(opts.lbr)
+ }
+ } else if headersRE.MatchString(tagNameLowercase) {
+ if canPrintNewline {
+ outBuf.WriteString(opts.lbr + opts.lbr)
+ }
+ canPrintNewline = false
+ } else if tagNameLowercase == "br" || tagNameLowercase == "br/" {
+ // new line
+ outBuf.WriteString(opts.lbr)
+ } else if tagNameLowercase == "p" || tagNameLowercase == "/p" {
+ if canPrintNewline {
+ outBuf.WriteString(opts.lbr + opts.lbr)
+ }
+ canPrintNewline = false
+ } else if opts.linksInnerText && tagNameLowercase == "/a" {
+ // end of link
+ // links can be empty can happen if the link matches the badLinkHrefRE
+ if len(hrefs) > 0 {
+ outBuf.WriteString(" <")
+ outBuf.WriteString(HTMLEntitiesToText(hrefs[0]))
+ outBuf.WriteString(">")
+ hrefs = hrefs[1:]
+ }
+ } else if opts.linksInnerText && linkTagRE.MatchString(tagNameLowercase) {
+ // parse link href
+ // add special handling for a tags
+ m := linkTagRE.FindStringSubmatch(tag)
+ if len(m) == 5 {
+ link := m[2]
+ if len(link) == 0 {
+ link = m[3]
+ if len(link) == 0 {
+ link = m[4]
+ }
+ }
+
+ if opts.linksInnerText && !badLinkHrefRE.MatchString(link) {
+ hrefs = append(hrefs, link)
+ }
+ }
+ } else if badTagnamesRE.MatchString(tagNameLowercase) {
+ // unwanted block
+ badTagStackDepth++
+
+ // if link inner text preservation is not enabled
+ // and the current tag is a link tag, parse its href and output that
+ if !opts.linksInnerText {
+ // parse link href
+ m := linkTagRE.FindStringSubmatch(tag)
+ if len(m) == 5 {
+ link := m[2]
+ if len(link) == 0 {
+ link = m[3]
+ if len(link) == 0 {
+ link = m[4]
+ }
+ }
+
+ if !badLinkHrefRE.MatchString(link) {
+ outBuf.WriteString(HTMLEntitiesToText(link))
+ }
+ }
+ }
+ } else if len(tagNameLowercase) > 0 && tagNameLowercase[0] == '/' &&
+ badTagnamesRE.MatchString(tagNameLowercase[1:]) {
+ // end of unwanted block
+ badTagStackDepth--
+ }
+ continue
+
+ } // switch end
+
+ if shouldOutput && badTagStackDepth == 0 && !inEnt {
+ canPrintNewline = true
+ outBuf.WriteRune(r)
+ }
+ }
+
+ return outBuf.String()
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index dc1e4266b..adcfcef52 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -446,6 +446,9 @@ github.com/josharian/intern
# github.com/json-iterator/go v1.1.12
## explicit; go 1.12
github.com/json-iterator/go
+# github.com/k3a/html2text v1.2.1
+## explicit; go 1.16
+github.com/k3a/html2text
# github.com/klauspost/compress v1.17.9
## explicit; go 1.20
github.com/klauspost/compress