summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/yuin/goldmark
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2021-01-28 17:56:38 +0100
committerGitHub <noreply@github.com>2021-01-28 17:56:38 +0100
commitd1353e1f7c9bf648cd72bd9731b4f843b0dc9a86 (patch)
treec41437643185d16ab257cf9856a3e1ae8a835112 /vendor/github.com/yuin/goldmark
parente45bf12a34d04b18f09663f179fb58aca9ffa192 (diff)
downloadgitea-d1353e1f7c9bf648cd72bd9731b4f843b0dc9a86.tar.gz
gitea-d1353e1f7c9bf648cd72bd9731b4f843b0dc9a86.zip
Vendor Update (#14496)
* update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 * update github.com/go-swagger/go-swagger v0.25.0 -> v0.26.0 * update github.com/google/uuid v1.1.2 -> v1.2.0 * update github.com/klauspost/compress v1.11.3 -> v1.11.7 * update github.com/lib/pq 083382b7e6fc -> v1.9.0 * update github.com/markbates/goth v1.65.0 -> v1.66.1 * update github.com/mattn/go-sqlite3 v1.14.4 -> v1.14.6 * update github.com/mgechev/revive 246eac737dc7 -> v1.0.3 * update github.com/minio/minio-go/v7 v7.0.6 -> v7.0.7 * update github.com/niklasfasching/go-org v1.3.2 -> v1.4.0 * update github.com/olivere/elastic/v7 v7.0.21 -> v7.0.22 * update github.com/pquerna/otp v1.2.0 -> v1.3.0 * update github.com/xanzy/go-gitlab v0.39.0 -> v0.42.0 * update github.com/yuin/goldmark v1.2.1 -> v1.3.1
Diffstat (limited to 'vendor/github.com/yuin/goldmark')
-rw-r--r--vendor/github.com/yuin/goldmark/README.md88
-rw-r--r--vendor/github.com/yuin/goldmark/ast/ast.go28
-rw-r--r--vendor/github.com/yuin/goldmark/ast/block.go23
-rw-r--r--vendor/github.com/yuin/goldmark/ast/inline.go2
-rw-r--r--vendor/github.com/yuin/goldmark/extension/ast/footnote.go35
-rw-r--r--vendor/github.com/yuin/goldmark/extension/footnote.go382
-rw-r--r--vendor/github.com/yuin/goldmark/extension/linkify.go4
-rw-r--r--vendor/github.com/yuin/goldmark/extension/table.go104
-rw-r--r--vendor/github.com/yuin/goldmark/go.mod2
-rw-r--r--vendor/github.com/yuin/goldmark/parser/link.go8
-rw-r--r--vendor/github.com/yuin/goldmark/parser/parser.go12
-rw-r--r--vendor/github.com/yuin/goldmark/parser/raw_html.go9
-rw-r--r--vendor/github.com/yuin/goldmark/util/util.go16
13 files changed, 632 insertions, 81 deletions
diff --git a/vendor/github.com/yuin/goldmark/README.md b/vendor/github.com/yuin/goldmark/README.md
index 8cf7c5a0eb..7f6a93e851 100644
--- a/vendor/github.com/yuin/goldmark/README.md
+++ b/vendor/github.com/yuin/goldmark/README.md
@@ -1,7 +1,7 @@
goldmark
==========================================
-[![http://godoc.org/github.com/yuin/goldmark](https://godoc.org/github.com/yuin/goldmark?status.svg)](http://godoc.org/github.com/yuin/goldmark)
+[![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)
[![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)
[![https://coveralls.io/github/yuin/goldmark](https://coveralls.io/repos/github/yuin/goldmark/badge.svg?branch=master)](https://coveralls.io/github/yuin/goldmark)
[![https://goreportcard.com/report/github.com/yuin/goldmark](https://goreportcard.com/badge/github.com/yuin/goldmark)](https://goreportcard.com/report/github.com/yuin/goldmark)
@@ -173,6 +173,7 @@ Parser and Renderer options
- This extension enables Table, Strikethrough, Linkify and TaskList.
- This extension does not filter tags defined in [6.11: Disallowed Raw HTML (extension)](https://github.github.com/gfm/#disallowed-raw-html-extension-).
If you need to filter HTML tags, see [Security](#security).
+ - If you need to parse github emojis, you can use [goldmark-emoji](https://github.com/yuin/goldmark-emoji) extension.
- `extension.DefinitionList`
- [PHP Markdown Extra: Definition lists](https://michelf.ca/projects/php-markdown/extra/#def-list)
- `extension.Footnote`
@@ -286,6 +287,89 @@ markdown := goldmark.New(
)
```
+### Footnotes extension
+
+The Footnote extension implements [PHP Markdown Extra: Footnotes](https://michelf.ca/projects/php-markdown/extra/#footnotes).
+
+This extension has some options:
+
+| Functional option | Type | Description |
+| ----------------- | ---- | ----------- |
+| `extension.WithFootnoteIDPrefix` | `[]byte` | a prefix for the id attributes.|
+| `extension.WithFootnoteIDPrefixFunction` | `func(gast.Node) []byte` | a function that determines the id attribute for given Node.|
+| `extension.WithFootnoteLinkTitle` | `[]byte` | an optional title attribute for footnote links.|
+| `extension.WithFootnoteBacklinkTitle` | `[]byte` | an optional title attribute for footnote backlinks. |
+| `extension.WithFootnoteLinkClass` | `[]byte` | a class for footnote links. This defaults to `footnote-ref`. |
+| `extension.WithFootnoteBacklinkClass` | `[]byte` | a class for footnote backlinks. This defaults to `footnote-backref`. |
+| `extension.WithFootnoteBacklinkHTML` | `[]byte` | a class for footnote backlinks. This defaults to `&#x21a9;&#xfe0e;`. |
+
+Some options can have special substitutions. Occurances of “^^” in the string will be replaced by the corresponding footnote number in the HTML output. Occurances of “%%” will be replaced by a number for the reference (footnotes can have multiple references).
+
+`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.
+
+`extension.WithFootnoteIDPrefix` sets fixed id prefix, so you may write codes like the following:
+
+```go
+for _, path := range files {
+ source := readAll(path)
+ prefix := getPrefix(path)
+
+ markdown := goldmark.New(
+ goldmark.WithExtensions(
+ NewFootnote(
+ WithFootnoteIDPrefix([]byte(path)),
+ ),
+ ),
+ )
+ var b bytes.Buffer
+ err := markdown.Convert(source, &b)
+ if err != nil {
+ t.Error(err.Error())
+ }
+}
+```
+
+`extension.WithFootnoteIDPrefixFunction` determines an id prefix by calling given function, so you may write codes like the following:
+
+```go
+markdown := goldmark.New(
+ goldmark.WithExtensions(
+ NewFootnote(
+ WithFootnoteIDPrefixFunction(func(n gast.Node) []byte {
+ v, ok := n.OwnerDocument().Meta()["footnote-prefix"]
+ if ok {
+ return util.StringToReadOnlyBytes(v.(string))
+ }
+ return nil
+ }),
+ ),
+ ),
+)
+
+for _, path := range files {
+ source := readAll(path)
+ var b bytes.Buffer
+
+ doc := markdown.Parser().Parse(text.NewReader(source))
+ doc.Meta()["footnote-prefix"] = getPrefix(path)
+ err := markdown.Renderer().Render(&b, source, doc)
+}
+```
+
+You can use [goldmark-meta](https://github.com/yuin/goldmark-meta) to define a id prefix in the markdown document:
+
+
+```markdown
+---
+title: document title
+slug: article1
+footnote-prefix: article1
+---
+
+# My article
+
+```
+
Security
--------------------
By default, goldmark does not render raw HTML or potentially-dangerous URLs.
@@ -336,6 +420,8 @@ Extensions
extension for the goldmark Markdown parser.
- [goldmark-highlighting](https://github.com/yuin/goldmark-highlighting): A syntax-highlighting extension
for the goldmark markdown parser.
+- [goldmark-emoji](https://github.com/yuin/goldmark-emoji): An emoji
+ extension for the goldmark Markdown parser.
- [goldmark-mathjax](https://github.com/litao91/goldmark-mathjax): Mathjax support for the goldmark markdown parser
goldmark internal(for extension developers)
diff --git a/vendor/github.com/yuin/goldmark/ast/ast.go b/vendor/github.com/yuin/goldmark/ast/ast.go
index 66059e94cc..3719ebbd8d 100644
--- a/vendor/github.com/yuin/goldmark/ast/ast.go
+++ b/vendor/github.com/yuin/goldmark/ast/ast.go
@@ -45,11 +45,6 @@ type Attribute struct {
Value interface{}
}
-var attrNameIDS = []byte("#")
-var attrNameID = []byte("id")
-var attrNameClassS = []byte(".")
-var attrNameClass = []byte("class")
-
// A Node interface defines basic AST node functionalities.
type Node interface {
// Type returns a type of this node.
@@ -116,6 +111,11 @@ type Node interface {
// tail of the children.
InsertAfter(self, v1, insertee Node)
+ // OwnerDocument returns this node's owner document.
+ // If this node is not a child of the Document node, OwnerDocument
+ // returns nil.
+ OwnerDocument() *Document
+
// Dump dumps an AST tree structure to stdout.
// This function completely aimed for debugging.
// level is a indent level. Implementer should indent informations with
@@ -169,7 +169,7 @@ type Node interface {
RemoveAttributes()
}
-// A BaseNode struct implements the Node interface.
+// A BaseNode struct implements the Node interface partialliy.
type BaseNode struct {
firstChild Node
lastChild Node
@@ -358,6 +358,22 @@ func (n *BaseNode) InsertBefore(self, v1, insertee Node) {
}
}
+// OwnerDocument implements Node.OwnerDocument
+func (n *BaseNode) OwnerDocument() *Document {
+ d := n.Parent()
+ for {
+ p := d.Parent()
+ if p == nil {
+ if v, ok := d.(*Document); ok {
+ return v
+ }
+ break
+ }
+ d = p
+ }
+ return nil
+}
+
// Text implements Node.Text .
func (n *BaseNode) Text(source []byte) []byte {
var buf bytes.Buffer
diff --git a/vendor/github.com/yuin/goldmark/ast/block.go b/vendor/github.com/yuin/goldmark/ast/block.go
index f5bca33fe9..fc0b3c2e02 100644
--- a/vendor/github.com/yuin/goldmark/ast/block.go
+++ b/vendor/github.com/yuin/goldmark/ast/block.go
@@ -7,7 +7,7 @@ import (
textm "github.com/yuin/goldmark/text"
)
-// A BaseBlock struct implements the Node interface.
+// A BaseBlock struct implements the Node interface partialliy.
type BaseBlock struct {
BaseNode
blankPreviousLines bool
@@ -50,6 +50,8 @@ func (b *BaseBlock) SetLines(v *textm.Segments) {
// A Document struct is a root node of Markdown text.
type Document struct {
BaseBlock
+
+ meta map[string]interface{}
}
// KindDocument is a NodeKind of the Document node.
@@ -70,10 +72,29 @@ func (n *Document) Kind() NodeKind {
return KindDocument
}
+// OwnerDocument implements Node.OwnerDocument
+func (n *Document) OwnerDocument() *Document {
+ return n
+}
+
+// Meta returns metadata of this document.
+func (n *Document) Meta() map[string]interface{} {
+ if n.meta == nil {
+ n.meta = map[string]interface{}{}
+ }
+ return n.meta
+}
+
+// SetMeta sets given metadata to this document.
+func (n *Document) SetMeta(meta map[string]interface{}) {
+ n.meta = meta
+}
+
// NewDocument returns a new Document node.
func NewDocument() *Document {
return &Document{
BaseBlock: BaseBlock{},
+ meta: nil,
}
}
diff --git a/vendor/github.com/yuin/goldmark/ast/inline.go b/vendor/github.com/yuin/goldmark/ast/inline.go
index 23dcad4bc9..b221695bd7 100644
--- a/vendor/github.com/yuin/goldmark/ast/inline.go
+++ b/vendor/github.com/yuin/goldmark/ast/inline.go
@@ -8,7 +8,7 @@ import (
"github.com/yuin/goldmark/util"
)
-// A BaseInline struct implements the Node interface.
+// A BaseInline struct implements the Node interface partialliy.
type BaseInline struct {
BaseNode
}
diff --git a/vendor/github.com/yuin/goldmark/extension/ast/footnote.go b/vendor/github.com/yuin/goldmark/extension/ast/footnote.go
index 835f8478b3..dedbab4f8b 100644
--- a/vendor/github.com/yuin/goldmark/extension/ast/footnote.go
+++ b/vendor/github.com/yuin/goldmark/extension/ast/footnote.go
@@ -2,6 +2,7 @@ package ast
import (
"fmt"
+
gast "github.com/yuin/goldmark/ast"
)
@@ -9,13 +10,15 @@ import (
// (PHP Markdown Extra) text.
type FootnoteLink struct {
gast.BaseInline
- Index int
+ Index int
+ RefCount int
}
// Dump implements Node.Dump.
func (n *FootnoteLink) Dump(source []byte, level int) {
m := map[string]string{}
m["Index"] = fmt.Sprintf("%v", n.Index)
+ m["RefCount"] = fmt.Sprintf("%v", n.RefCount)
gast.DumpHelper(n, source, level, m, nil)
}
@@ -30,36 +33,40 @@ func (n *FootnoteLink) Kind() gast.NodeKind {
// NewFootnoteLink returns a new FootnoteLink node.
func NewFootnoteLink(index int) *FootnoteLink {
return &FootnoteLink{
- Index: index,
+ Index: index,
+ RefCount: 0,
}
}
-// A FootnoteBackLink struct represents a link to a footnote of Markdown
+// A FootnoteBacklink struct represents a link to a footnote of Markdown
// (PHP Markdown Extra) text.
-type FootnoteBackLink struct {
+type FootnoteBacklink struct {
gast.BaseInline
- Index int
+ Index int
+ RefCount int
}
// Dump implements Node.Dump.
-func (n *FootnoteBackLink) Dump(source []byte, level int) {
+func (n *FootnoteBacklink) Dump(source []byte, level int) {
m := map[string]string{}
m["Index"] = fmt.Sprintf("%v", n.Index)
+ m["RefCount"] = fmt.Sprintf("%v", n.RefCount)
gast.DumpHelper(n, source, level, m, nil)
}
-// KindFootnoteBackLink is a NodeKind of the FootnoteBackLink node.
-var KindFootnoteBackLink = gast.NewNodeKind("FootnoteBackLink")
+// KindFootnoteBacklink is a NodeKind of the FootnoteBacklink node.
+var KindFootnoteBacklink = gast.NewNodeKind("FootnoteBacklink")
// Kind implements Node.Kind.
-func (n *FootnoteBackLink) Kind() gast.NodeKind {
- return KindFootnoteBackLink
+func (n *FootnoteBacklink) Kind() gast.NodeKind {
+ return KindFootnoteBacklink
}
-// NewFootnoteBackLink returns a new FootnoteBackLink node.
-func NewFootnoteBackLink(index int) *FootnoteBackLink {
- return &FootnoteBackLink{
- Index: index,
+// NewFootnoteBacklink returns a new FootnoteBacklink node.
+func NewFootnoteBacklink(index int) *FootnoteBacklink {
+ return &FootnoteBacklink{
+ Index: index,
+ RefCount: 0,
}
}
diff --git a/vendor/github.com/yuin/goldmark/extension/footnote.go b/vendor/github.com/yuin/goldmark/extension/footnote.go
index ede72db878..62f5ee61c6 100644
--- a/vendor/github.com/yuin/goldmark/extension/footnote.go
+++ b/vendor/github.com/yuin/goldmark/extension/footnote.go
@@ -2,6 +2,8 @@ package extension
import (
"bytes"
+ "strconv"
+
"github.com/yuin/goldmark"
gast "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/extension/ast"
@@ -10,10 +12,10 @@ import (
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
- "strconv"
)
var footnoteListKey = parser.NewContextKey()
+var footnoteLinkListKey = parser.NewContextKey()
type footnoteBlockParser struct {
}
@@ -164,7 +166,20 @@ func (s *footnoteParser) Parse(parent gast.Node, block text.Reader, pc parser.Co
return nil
}
- return ast.NewFootnoteLink(index)
+ fnlink := ast.NewFootnoteLink(index)
+ var fnlist []*ast.FootnoteLink
+ if tmp := pc.Get(footnoteLinkListKey); tmp != nil {
+ fnlist = tmp.([]*ast.FootnoteLink)
+ } else {
+ fnlist = []*ast.FootnoteLink{}
+ pc.Set(footnoteLinkListKey, fnlist)
+ }
+ pc.Set(footnoteLinkListKey, append(fnlist, fnlink))
+ if line[0] == '!' {
+ parent.AppendChild(parent, gast.NewTextSegment(text.NewSegment(segment.Start, segment.Start+1)))
+ }
+
+ return fnlink
}
type footnoteASTTransformer struct {
@@ -180,23 +195,46 @@ func NewFootnoteASTTransformer() parser.ASTTransformer {
func (a *footnoteASTTransformer) Transform(node *gast.Document, reader text.Reader, pc parser.Context) {
var list *ast.FootnoteList
- if tlist := pc.Get(footnoteListKey); tlist != nil {
- list = tlist.(*ast.FootnoteList)
- } else {
- return
+ var fnlist []*ast.FootnoteLink
+ if tmp := pc.Get(footnoteListKey); tmp != nil {
+ list = tmp.(*ast.FootnoteList)
}
+ if tmp := pc.Get(footnoteLinkListKey); tmp != nil {
+ fnlist = tmp.([]*ast.FootnoteLink)
+ }
+
pc.Set(footnoteListKey, nil)
+ pc.Set(footnoteLinkListKey, nil)
+
+ if list == nil {
+ return
+ }
+
+ counter := map[int]int{}
+ if fnlist != nil {
+ for _, fnlink := range fnlist {
+ if fnlink.Index >= 0 {
+ counter[fnlink.Index]++
+ }
+ }
+ for _, fnlink := range fnlist {
+ fnlink.RefCount = counter[fnlink.Index]
+ }
+ }
for footnote := list.FirstChild(); footnote != nil; {
var container gast.Node = footnote
next := footnote.NextSibling()
if fc := container.LastChild(); fc != nil && gast.IsParagraph(fc) {
container = fc
}
- index := footnote.(*ast.Footnote).Index
+ fn := footnote.(*ast.Footnote)
+ index := fn.Index
if index < 0 {
list.RemoveChild(list, footnote)
} else {
- container.AppendChild(container, ast.NewFootnoteBackLink(index))
+ backLink := ast.NewFootnoteBacklink(index)
+ backLink.RefCount = counter[index]
+ container.AppendChild(container, backLink)
}
footnote = next
}
@@ -214,19 +252,250 @@ func (a *footnoteASTTransformer) Transform(node *gast.Document, reader text.Read
node.AppendChild(node, list)
}
+// FootnoteConfig holds configuration values for the footnote extension.
+//
+// Link* and Backlink* configurations have some variables:
+// Occurrances of “^^” in the string will be replaced by the
+// corresponding footnote number in the HTML output.
+// Occurrances of “%%” will be replaced by a number for the
+// reference (footnotes can have multiple references).
+type FootnoteConfig struct {
+ html.Config
+
+ // IDPrefix is a prefix for the id attributes generated by footnotes.
+ IDPrefix []byte
+
+ // IDPrefix is a function that determines the id attribute for given Node.
+ IDPrefixFunction func(gast.Node) []byte
+
+ // LinkTitle is an optional title attribute for footnote links.
+ LinkTitle []byte
+
+ // BacklinkTitle is an optional title attribute for footnote backlinks.
+ BacklinkTitle []byte
+
+ // LinkClass is a class for footnote links.
+ LinkClass []byte
+
+ // BacklinkClass is a class for footnote backlinks.
+ BacklinkClass []byte
+
+ // BacklinkHTML is an HTML content for footnote backlinks.
+ BacklinkHTML []byte
+}
+
+// FootnoteOption interface is a functional option interface for the extension.
+type FootnoteOption interface {
+ renderer.Option
+ // SetFootnoteOption sets given option to the extension.
+ SetFootnoteOption(*FootnoteConfig)
+}
+
+// NewFootnoteConfig returns a new Config with defaults.
+func NewFootnoteConfig() FootnoteConfig {
+ return FootnoteConfig{
+ Config: html.NewConfig(),
+ LinkTitle: []byte(""),
+ BacklinkTitle: []byte(""),
+ LinkClass: []byte("footnote-ref"),
+ BacklinkClass: []byte("footnote-backref"),
+ BacklinkHTML: []byte("&#x21a9;&#xfe0e;"),
+ }
+}
+
+// SetOption implements renderer.SetOptioner.
+func (c *FootnoteConfig) SetOption(name renderer.OptionName, value interface{}) {
+ switch name {
+ case optFootnoteIDPrefixFunction:
+ c.IDPrefixFunction = value.(func(gast.Node) []byte)
+ case optFootnoteIDPrefix:
+ c.IDPrefix = value.([]byte)
+ case optFootnoteLinkTitle:
+ c.LinkTitle = value.([]byte)
+ case optFootnoteBacklinkTitle:
+ c.BacklinkTitle = value.([]byte)
+ case optFootnoteLinkClass:
+ c.LinkClass = value.([]byte)
+ case optFootnoteBacklinkClass:
+ c.BacklinkClass = value.([]byte)
+ case optFootnoteBacklinkHTML:
+ c.BacklinkHTML = value.([]byte)
+ default:
+ c.Config.SetOption(name, value)
+ }
+}
+
+type withFootnoteHTMLOptions struct {
+ value []html.Option
+}
+
+func (o *withFootnoteHTMLOptions) SetConfig(c *renderer.Config) {
+ if o.value != nil {
+ for _, v := range o.value {
+ v.(renderer.Option).SetConfig(c)
+ }
+ }
+}
+
+func (o *withFootnoteHTMLOptions) SetFootnoteOption(c *FootnoteConfig) {
+ if o.value != nil {
+ for _, v := range o.value {
+ v.SetHTMLOption(&c.Config)
+ }
+ }
+}
+
+// WithFootnoteHTMLOptions is functional option that wraps goldmark HTMLRenderer options.
+func WithFootnoteHTMLOptions(opts ...html.Option) FootnoteOption {
+ return &withFootnoteHTMLOptions{opts}
+}
+
+const optFootnoteIDPrefix renderer.OptionName = "FootnoteIDPrefix"
+
+type withFootnoteIDPrefix struct {
+ value []byte
+}
+
+func (o *withFootnoteIDPrefix) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteIDPrefix] = o.value
+}
+
+func (o *withFootnoteIDPrefix) SetFootnoteOption(c *FootnoteConfig) {
+ c.IDPrefix = o.value
+}
+
+// WithFootnoteIDPrefix is a functional option that is a prefix for the id attributes generated by footnotes.
+func WithFootnoteIDPrefix(a []byte) FootnoteOption {
+ return &withFootnoteIDPrefix{a}
+}
+
+const optFootnoteIDPrefixFunction renderer.OptionName = "FootnoteIDPrefixFunction"
+
+type withFootnoteIDPrefixFunction struct {
+ value func(gast.Node) []byte
+}
+
+func (o *withFootnoteIDPrefixFunction) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteIDPrefixFunction] = o.value
+}
+
+func (o *withFootnoteIDPrefixFunction) SetFootnoteOption(c *FootnoteConfig) {
+ c.IDPrefixFunction = o.value
+}
+
+// WithFootnoteIDPrefixFunction is a functional option that is a prefix for the id attributes generated by footnotes.
+func WithFootnoteIDPrefixFunction(a func(gast.Node) []byte) FootnoteOption {
+ return &withFootnoteIDPrefixFunction{a}
+}
+
+const optFootnoteLinkTitle renderer.OptionName = "FootnoteLinkTitle"
+
+type withFootnoteLinkTitle struct {
+ value []byte
+}
+
+func (o *withFootnoteLinkTitle) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteLinkTitle] = o.value
+}
+
+func (o *withFootnoteLinkTitle) SetFootnoteOption(c *FootnoteConfig) {
+ c.LinkTitle = o.value
+}
+
+// WithFootnoteLinkTitle is a functional option that is an optional title attribute for footnote links.
+func WithFootnoteLinkTitle(a []byte) FootnoteOption {
+ return &withFootnoteLinkTitle{a}
+}
+
+const optFootnoteBacklinkTitle renderer.OptionName = "FootnoteBacklinkTitle"
+
+type withFootnoteBacklinkTitle struct {
+ value []byte
+}
+
+func (o *withFootnoteBacklinkTitle) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteBacklinkTitle] = o.value
+}
+
+func (o *withFootnoteBacklinkTitle) SetFootnoteOption(c *FootnoteConfig) {
+ c.BacklinkTitle = o.value
+}
+
+// WithFootnoteBacklinkTitle is a functional option that is an optional title attribute for footnote backlinks.
+func WithFootnoteBacklinkTitle(a []byte) FootnoteOption {
+ return &withFootnoteBacklinkTitle{a}
+}
+
+const optFootnoteLinkClass renderer.OptionName = "FootnoteLinkClass"
+
+type withFootnoteLinkClass struct {
+ value []byte
+}
+
+func (o *withFootnoteLinkClass) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteLinkClass] = o.value
+}
+
+func (o *withFootnoteLinkClass) SetFootnoteOption(c *FootnoteConfig) {
+ c.LinkClass = o.value
+}
+
+// WithFootnoteLinkClass is a functional option that is a class for footnote links.
+func WithFootnoteLinkClass(a []byte) FootnoteOption {
+ return &withFootnoteLinkClass{a}
+}
+
+const optFootnoteBacklinkClass renderer.OptionName = "FootnoteBacklinkClass"
+
+type withFootnoteBacklinkClass struct {
+ value []byte
+}
+
+func (o *withFootnoteBacklinkClass) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteBacklinkClass] = o.value
+}
+
+func (o *withFootnoteBacklinkClass) SetFootnoteOption(c *FootnoteConfig) {
+ c.BacklinkClass = o.value
+}
+
+// WithFootnoteBacklinkClass is a functional option that is a class for footnote backlinks.
+func WithFootnoteBacklinkClass(a []byte) FootnoteOption {
+ return &withFootnoteBacklinkClass{a}
+}
+
+const optFootnoteBacklinkHTML renderer.OptionName = "FootnoteBacklinkHTML"
+
+type withFootnoteBacklinkHTML struct {
+ value []byte
+}
+
+func (o *withFootnoteBacklinkHTML) SetConfig(c *renderer.Config) {
+ c.Options[optFootnoteBacklinkHTML] = o.value
+}
+
+func (o *withFootnoteBacklinkHTML) SetFootnoteOption(c *FootnoteConfig) {
+ c.BacklinkHTML = o.value
+}
+
+// WithFootnoteBacklinkHTML is an HTML content for footnote backlinks.
+func WithFootnoteBacklinkHTML(a []byte) FootnoteOption {
+ return &withFootnoteBacklinkHTML{a}
+}
+
// FootnoteHTMLRenderer is a renderer.NodeRenderer implementation that
// renders FootnoteLink nodes.
type FootnoteHTMLRenderer struct {
- html.Config
+ FootnoteConfig
}
// NewFootnoteHTMLRenderer returns a new FootnoteHTMLRenderer.
-func NewFootnoteHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
+func NewFootnoteHTMLRenderer(opts ...FootnoteOption) renderer.NodeRenderer {
r := &FootnoteHTMLRenderer{
- Config: html.NewConfig(),
+ FootnoteConfig: NewFootnoteConfig(),
}
for _, opt := range opts {
- opt.SetHTMLOption(&r.Config)
+ opt.SetFootnoteOption(&r.FootnoteConfig)
}
return r
}
@@ -234,7 +503,7 @@ func NewFootnoteHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
func (r *FootnoteHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(ast.KindFootnoteLink, r.renderFootnoteLink)
- reg.Register(ast.KindFootnoteBackLink, r.renderFootnoteBackLink)
+ reg.Register(ast.KindFootnoteBacklink, r.renderFootnoteBacklink)
reg.Register(ast.KindFootnote, r.renderFootnote)
reg.Register(ast.KindFootnoteList, r.renderFootnoteList)
}
@@ -243,25 +512,45 @@ func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byt
if entering {
n := node.(*ast.FootnoteLink)
is := strconv.Itoa(n.Index)
- _, _ = w.WriteString(`<sup id="fnref:`)
+ _, _ = w.WriteString(`<sup id="`)
+ _, _ = w.Write(r.idPrefix(node))
+ _, _ = w.WriteString(`fnref:`)
_, _ = w.WriteString(is)
- _, _ = w.WriteString(`"><a href="#fn:`)
+ _, _ = w.WriteString(`"><a href="#`)
+ _, _ = w.Write(r.idPrefix(node))
+ _, _ = w.WriteString(`fn:`)
_, _ = w.WriteString(is)
- _, _ = w.WriteString(`" class="footnote-ref" role="doc-noteref">`)
+ _, _ = w.WriteString(`" class="`)
+ _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.LinkClass,
+ n.Index, n.RefCount))
+ if len(r.FootnoteConfig.LinkTitle) > 0 {
+ _, _ = w.WriteString(`" title="`)
+ _, _ = w.Write(util.EscapeHTML(applyFootnoteTemplate(r.FootnoteConfig.LinkTitle, n.Index, n.RefCount)))
+ }
+ _, _ = w.WriteString(`" role="doc-noteref">`)
+
_, _ = w.WriteString(is)
_, _ = w.WriteString(`</a></sup>`)
}
return gast.WalkContinue, nil
}
-func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
+func (r *FootnoteHTMLRenderer) renderFootnoteBacklink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
if entering {
- n := node.(*ast.FootnoteBackLink)
+ n := node.(*ast.FootnoteBacklink)
is := strconv.Itoa(n.Index)
- _, _ = w.WriteString(` <a href="#fnref:`)
+ _, _ = w.WriteString(` <a href="#`)
+ _, _ = w.Write(r.idPrefix(node))
+ _, _ = w.WriteString(`fnref:`)
_, _ = w.WriteString(is)
- _, _ = w.WriteString(`" class="footnote-backref" role="doc-backlink">`)
- _, _ = w.WriteString("&#x21a9;&#xfe0e;")
+ _, _ = w.WriteString(`" class="`)
+ _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkClass, n.Index, n.RefCount))
+ if len(r.FootnoteConfig.BacklinkTitle) > 0 {
+ _, _ = w.WriteString(`" title="`)
+ _, _ = w.Write(util.EscapeHTML(applyFootnoteTemplate(r.FootnoteConfig.BacklinkTitle, n.Index, n.RefCount)))
+ }
+ _, _ = w.WriteString(`" role="doc-backlink">`)
+ _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkHTML, n.Index, n.RefCount))
_, _ = w.WriteString(`</a>`)
}
return gast.WalkContinue, nil
@@ -271,7 +560,9 @@ func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, n
n := node.(*ast.Footnote)
is := strconv.Itoa(n.Index)
if entering {
- _, _ = w.WriteString(`<li id="fn:`)
+ _, _ = w.WriteString(`<li id="`)
+ _, _ = w.Write(r.idPrefix(node))
+ _, _ = w.WriteString(`fn:`)
_, _ = w.WriteString(is)
_, _ = w.WriteString(`" role="doc-endnote"`)
if node.Attributes() != nil {
@@ -312,11 +603,54 @@ func (r *FootnoteHTMLRenderer) renderFootnoteList(w util.BufWriter, source []byt
return gast.WalkContinue, nil
}
+func (r *FootnoteHTMLRenderer) idPrefix(node gast.Node) []byte {
+ if r.FootnoteConfig.IDPrefix != nil {
+ return r.FootnoteConfig.IDPrefix
+ }
+ if r.FootnoteConfig.IDPrefixFunction != nil {
+ return r.FootnoteConfig.IDPrefixFunction(node)
+ }
+ return []byte("")
+}
+
+func applyFootnoteTemplate(b []byte, index, refCount int) []byte {
+ fast := true
+ for i, c := range b {
+ if i != 0 {
+ if b[i-1] == '^' && c == '^' {
+ fast = false
+ break
+ }
+ if b[i-1] == '%' && c == '%' {
+ fast = false
+ break
+ }
+ }
+ }
+ if fast {
+ return b
+ }
+ is := []byte(strconv.Itoa(index))
+ rs := []byte(strconv.Itoa(refCount))
+ ret := bytes.Replace(b, []byte("^^"), is, -1)
+ return bytes.Replace(ret, []byte("%%"), rs, -1)
+}
+
type footnote struct {
+ options []FootnoteOption
}
// Footnote is an extension that allow you to use PHP Markdown Extra Footnotes.
-var Footnote = &footnote{}
+var Footnote = &footnote{
+ options: []FootnoteOption{},
+}
+
+// NewFootnote returns a new extension with given options.
+func NewFootnote(opts ...FootnoteOption) goldmark.Extender {
+ return &footnote{
+ options: opts,
+ }
+}
func (e *footnote) Extend(m goldmark.Markdown) {
m.Parser().AddOptions(
@@ -331,6 +665,6 @@ func (e *footnote) Extend(m goldmark.Markdown) {
),
)
m.Renderer().AddOptions(renderer.WithNodeRenderers(
- util.Prioritized(NewFootnoteHTMLRenderer(), 500),
+ util.Prioritized(NewFootnoteHTMLRenderer(e.options...), 500),
))
}
diff --git a/vendor/github.com/yuin/goldmark/extension/linkify.go b/vendor/github.com/yuin/goldmark/extension/linkify.go
index 9e68fa5349..31203a622f 100644
--- a/vendor/github.com/yuin/goldmark/extension/linkify.go
+++ b/vendor/github.com/yuin/goldmark/extension/linkify.go
@@ -11,9 +11,9 @@ import (
"github.com/yuin/goldmark/util"
)
-var wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]+(?:(?:/|[#?])[-a-zA-Z0-9@:%_\+.~#!?&//=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
+var wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]+(?:[/#?][-a-zA-Z0-9@:%_\+.~#!?&/=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
-var urlRegexp = regexp.MustCompile(`^(?:http|https|ftp):\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]+(?:(?:/|[#?])[-a-zA-Z0-9@:%_+.~#$!?&//=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
+var urlRegexp = regexp.MustCompile(`^(?:http|https|ftp)://[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]+(?::\d+)?(?:[/#?][-a-zA-Z0-9@:%_+.~#$!?&/=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
// An LinkifyConfig struct is a data structure that holds configuration of the
// Linkify extension.
diff --git a/vendor/github.com/yuin/goldmark/extension/table.go b/vendor/github.com/yuin/goldmark/extension/table.go
index f0e994e838..c40bdefc5c 100644
--- a/vendor/github.com/yuin/goldmark/extension/table.go
+++ b/vendor/github.com/yuin/goldmark/extension/table.go
@@ -15,6 +15,13 @@ import (
"github.com/yuin/goldmark/util"
)
+var escapedPipeCellListKey = parser.NewContextKey()
+
+type escapedPipeCell struct {
+ Cell *ast.TableCell
+ Pos []int
+}
+
// TableCellAlignMethod indicates how are table cells aligned in HTML format.indicates how are table cells aligned in HTML format.
type TableCellAlignMethod int
@@ -148,7 +155,7 @@ func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.
if alignments == nil {
continue
}
- header := b.parseRow(lines.At(i-1), alignments, true, reader)
+ header := b.parseRow(lines.At(i-1), alignments, true, reader, pc)
if header == nil || len(alignments) != header.ChildCount() {
return
}
@@ -156,7 +163,7 @@ func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.
table.Alignments = alignments
table.AppendChild(table, ast.NewTableHeader(header))
for j := i + 1; j < lines.Len(); j++ {
- table.AppendChild(table, b.parseRow(lines.At(j), alignments, false, reader))
+ table.AppendChild(table, b.parseRow(lines.At(j), alignments, false, reader, pc))
}
node.Lines().SetSliced(0, i-1)
node.Parent().InsertAfter(node.Parent(), node, table)
@@ -170,7 +177,7 @@ func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.
}
}
-func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []ast.Alignment, isHeader bool, reader text.Reader) *ast.TableRow {
+func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []ast.Alignment, isHeader bool, reader text.Reader, pc parser.Context) *ast.TableRow {
source := reader.Source()
line := segment.Value(source)
pos := 0
@@ -194,18 +201,39 @@ func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []
} else {
alignment = alignments[i]
}
- closure := util.FindClosure(line[pos:], byte(0), '|', true, false)
- if closure < 0 {
- closure = len(line[pos:])
- }
+
+ var escapedCell *escapedPipeCell
node := ast.NewTableCell()
- seg := text.NewSegment(segment.Start+pos, segment.Start+pos+closure)
+ node.Alignment = alignment
+ hasBacktick := false
+ closure := pos
+ for ; closure < limit; closure++ {
+ if line[closure] == '`' {
+ hasBacktick = true
+ }
+ if line[closure] == '|' {
+ if closure == 0 || line[closure-1] != '\\' {
+ break
+ } else if hasBacktick {
+ if escapedCell == nil {
+ escapedCell = &escapedPipeCell{node, []int{}}
+ escapedList := pc.ComputeIfAbsent(escapedPipeCellListKey,
+ func() interface{} {
+ return []*escapedPipeCell{}
+ }).([]*escapedPipeCell)
+ escapedList = append(escapedList, escapedCell)
+ pc.Set(escapedPipeCellListKey, escapedList)
+ }
+ escapedCell.Pos = append(escapedCell.Pos, segment.Start+closure-1)
+ }
+ }
+ }
+ seg := text.NewSegment(segment.Start+pos, segment.Start+closure)
seg = seg.TrimLeftSpace(source)
seg = seg.TrimRightSpace(source)
node.Lines().Append(seg)
- node.Alignment = alignment
row.AppendChild(row, node)
- pos += closure + 1
+ pos = closure + 1
}
for ; i < len(alignments); i++ {
row.AppendChild(row, ast.NewTableCell())
@@ -243,6 +271,49 @@ func (b *tableParagraphTransformer) parseDelimiter(segment text.Segment, reader
return alignments
}
+type tableASTTransformer struct {
+}
+
+var defaultTableASTTransformer = &tableASTTransformer{}
+
+// NewTableASTTransformer returns a parser.ASTTransformer for tables.
+func NewTableASTTransformer() parser.ASTTransformer {
+ return defaultTableASTTransformer
+}
+
+func (a *tableASTTransformer) Transform(node *gast.Document, reader text.Reader, pc parser.Context) {
+ lst := pc.Get(escapedPipeCellListKey)
+ if lst == nil {
+ return
+ }
+ pc.Set(escapedPipeCellListKey, nil)
+ for _, v := range lst.([]*escapedPipeCell) {
+ _ = gast.Walk(v.Cell, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
+ if n.Kind() != gast.KindCodeSpan {
+ return gast.WalkContinue, nil
+ }
+ c := n.FirstChild()
+ for c != nil {
+ next := c.NextSibling()
+ if c.Kind() == gast.KindText {
+ t := c.(*gast.Text)
+ for _, pos := range v.Pos {
+ if t.Segment.Start <= pos && t.Segment.Stop > pos {
+ n1 := gast.NewRawTextSegment(t.Segment.WithStop(pos))
+ n2 := gast.NewRawTextSegment(t.Segment.WithStart(pos + 1))
+ n.InsertAfter(n, c, n1)
+ n.InsertAfter(n, n1, n2)
+ n.RemoveChild(n, c)
+ }
+ }
+ }
+ c = next
+ }
+ return gast.WalkContinue, nil
+ })
+ }
+}
+
// TableHTMLRenderer is a renderer.NodeRenderer implementation that
// renders Table nodes.
type TableHTMLRenderer struct {
@@ -419,7 +490,7 @@ func (r *TableHTMLRenderer) renderTableCell(w util.BufWriter, source []byte, nod
cob.AppendByte(';')
}
style := fmt.Sprintf("text-align:%s", n.Alignment.String())
- cob.Append(util.StringToReadOnlyBytes(style))
+ cob.AppendString(style)
n.SetAttributeString("style", cob.Bytes())
}
}
@@ -454,9 +525,14 @@ func NewTable(opts ...TableOption) goldmark.Extender {
}
func (e *table) Extend(m goldmark.Markdown) {
- m.Parser().AddOptions(parser.WithParagraphTransformers(
- util.Prioritized(NewTableParagraphTransformer(), 200),
- ))
+ m.Parser().AddOptions(
+ parser.WithParagraphTransformers(
+ util.Prioritized(NewTableParagraphTransformer(), 200),
+ ),
+ parser.WithASTTransformers(
+ util.Prioritized(defaultTableASTTransformer, 0),
+ ),
+ )
m.Renderer().AddOptions(renderer.WithNodeRenderers(
util.Prioritized(NewTableHTMLRenderer(e.options...), 500),
))
diff --git a/vendor/github.com/yuin/goldmark/go.mod b/vendor/github.com/yuin/goldmark/go.mod
index a10efcad52..f76c1766fc 100644
--- a/vendor/github.com/yuin/goldmark/go.mod
+++ b/vendor/github.com/yuin/goldmark/go.mod
@@ -1,3 +1,3 @@
module github.com/yuin/goldmark
-go 1.13
+go 1.15
diff --git a/vendor/github.com/yuin/goldmark/parser/link.go b/vendor/github.com/yuin/goldmark/parser/link.go
index e7c6966f3d..c36cce5d90 100644
--- a/vendor/github.com/yuin/goldmark/parser/link.go
+++ b/vendor/github.com/yuin/goldmark/parser/link.go
@@ -2,7 +2,6 @@ package parser
import (
"fmt"
- "regexp"
"strings"
"github.com/yuin/goldmark/ast"
@@ -113,8 +112,6 @@ func (s *linkParser) Trigger() []byte {
return []byte{'!', '[', ']'}
}
-var linkDestinationRegexp = regexp.MustCompile(`\s*([^\s].+)`)
-var linkTitleRegexp = regexp.MustCompile(`\s+(\)|["'\(].+)`)
var linkBottom = NewContextKey()
func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
@@ -293,20 +290,17 @@ func (s *linkParser) parseLink(parent ast.Node, last *linkLabelState, block text
func parseLinkDestination(block text.Reader) ([]byte, bool) {
block.SkipSpaces()
line, _ := block.PeekLine()
- buf := []byte{}
if block.Peek() == '<' {
i := 1
for i < len(line) {
c := line[i]
if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
- buf = append(buf, '\\', line[i+1])
i += 2
continue
} else if c == '>' {
block.Advance(i + 1)
return line[1:i], true
}
- buf = append(buf, c)
i++
}
return nil, false
@@ -316,7 +310,6 @@ func parseLinkDestination(block text.Reader) ([]byte, bool) {
for i < len(line) {
c := line[i]
if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
- buf = append(buf, '\\', line[i+1])
i += 2
continue
} else if c == '(' {
@@ -329,7 +322,6 @@ func parseLinkDestination(block text.Reader) ([]byte, bool) {
} else if util.IsSpace(c) {
break
}
- buf = append(buf, c)
i++
}
block.Advance(i)
diff --git a/vendor/github.com/yuin/goldmark/parser/parser.go b/vendor/github.com/yuin/goldmark/parser/parser.go
index def13db666..e58b5ee936 100644
--- a/vendor/github.com/yuin/goldmark/parser/parser.go
+++ b/vendor/github.com/yuin/goldmark/parser/parser.go
@@ -138,6 +138,9 @@ type Context interface {
// Get returns a value associated with the given key.
Get(ContextKey) interface{}
+ // ComputeIfAbsent computes a value if a value associated with the given key is absent and returns the value.
+ ComputeIfAbsent(ContextKey, func() interface{}) interface{}
+
// Set sets the given value to the context.
Set(ContextKey, interface{})
@@ -252,6 +255,15 @@ func (p *parseContext) Get(key ContextKey) interface{} {
return p.store[key]
}
+func (p *parseContext) ComputeIfAbsent(key ContextKey, f func() interface{}) interface{} {
+ v := p.store[key]
+ if v == nil {
+ v = f()
+ p.store[key] = v
+ }
+ return v
+}
+
func (p *parseContext) Set(key ContextKey, value interface{}) {
p.store[key] = value
}
diff --git a/vendor/github.com/yuin/goldmark/parser/raw_html.go b/vendor/github.com/yuin/goldmark/parser/raw_html.go
index d7ba414ff2..7fd696cc2c 100644
--- a/vendor/github.com/yuin/goldmark/parser/raw_html.go
+++ b/vendor/github.com/yuin/goldmark/parser/raw_html.go
@@ -2,10 +2,11 @@ package parser
import (
"bytes"
+ "regexp"
+
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
- "regexp"
)
type rawHTMLParser struct {
@@ -67,8 +68,6 @@ func (s *rawHTMLParser) parseSingleLineRegexp(reg *regexp.Regexp, block text.Rea
return node
}
-var dummyMatch = [][]byte{}
-
func (s *rawHTMLParser) parseMultiLineRegexp(reg *regexp.Regexp, block text.Reader, pc Context) ast.Node {
sline, ssegment := block.Position()
if block.Match(reg) {
@@ -102,7 +101,3 @@ func (s *rawHTMLParser) parseMultiLineRegexp(reg *regexp.Regexp, block text.Read
}
return nil
}
-
-func (s *rawHTMLParser) CloseBlock(parent ast.Node, pc Context) {
- // nothing to do
-}
diff --git a/vendor/github.com/yuin/goldmark/util/util.go b/vendor/github.com/yuin/goldmark/util/util.go
index fc1438dc19..3ec73f54f3 100644
--- a/vendor/github.com/yuin/goldmark/util/util.go
+++ b/vendor/github.com/yuin/goldmark/util/util.go
@@ -37,6 +37,12 @@ func (b *CopyOnWriteBuffer) Write(value []byte) {
b.buffer = append(b.buffer, value...)
}
+// WriteString writes given string to the buffer.
+// WriteString allocate new buffer and clears it at the first time.
+func (b *CopyOnWriteBuffer) WriteString(value string) {
+ b.Write(StringToReadOnlyBytes(value))
+}
+
// Append appends given bytes to the buffer.
// Append copy buffer at the first time.
func (b *CopyOnWriteBuffer) Append(value []byte) {
@@ -49,6 +55,12 @@ func (b *CopyOnWriteBuffer) Append(value []byte) {
b.buffer = append(b.buffer, value...)
}
+// AppendString appends given string to the buffer.
+// AppendString copy buffer at the first time.
+func (b *CopyOnWriteBuffer) AppendString(value string) {
+ b.Append(StringToReadOnlyBytes(value))
+}
+
// WriteByte writes the given byte to the buffer.
// WriteByte allocate new buffer and clears it at the first time.
func (b *CopyOnWriteBuffer) WriteByte(c byte) {
@@ -804,7 +816,7 @@ func IsPunct(c byte) bool {
return punctTable[c] == 1
}
-// IsPunct returns true if the given rune is a punctuation, otherwise false.
+// IsPunctRune returns true if the given rune is a punctuation, otherwise false.
func IsPunctRune(r rune) bool {
return int32(r) <= 256 && IsPunct(byte(r)) || unicode.IsPunct(r)
}
@@ -814,7 +826,7 @@ func IsSpace(c byte) bool {
return spaceTable[c] == 1
}
-// IsSpace returns true if the given rune is a space, otherwise false.
+// IsSpaceRune returns true if the given rune is a space, otherwise false.
func IsSpaceRune(r rune) bool {
return int32(r) <= 256 && IsSpace(byte(r)) || unicode.IsSpace(r)
}