mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
Fix typo and remove unnecessary conversion
This commit is contained in:
parent
8c219a7562
commit
2698d6168d
31 changed files with 1672 additions and 1692 deletions
|
|
@ -65,6 +65,7 @@ Import packages:
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
@ -106,6 +107,7 @@ Custom parser and renderer
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
"github.com/yuin/goldmark/extension"
|
"github.com/yuin/goldmark/extension"
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
|
|
|
||||||
16
ast/ast.go
16
ast/ast.go
|
|
@ -97,17 +97,17 @@ type Node interface {
|
||||||
SortChildren(comparator func(n1, n2 Node) int)
|
SortChildren(comparator func(n1, n2 Node) int)
|
||||||
|
|
||||||
// ReplaceChild replace a node v1 with a node insertee.
|
// ReplaceChild replace a node v1 with a node insertee.
|
||||||
// If v1 is not children of this node, ReplaceChild append a insetee to the
|
// If v1 is not children of this node, ReplaceChild append an insetee to the
|
||||||
// tail of the children.
|
// tail of the children.
|
||||||
ReplaceChild(self, v1, insertee Node)
|
ReplaceChild(self, v1, insertee Node)
|
||||||
|
|
||||||
// InsertBefore inserts a node insertee before a node v1.
|
// InsertBefore inserts a node insertee before a node v1.
|
||||||
// If v1 is not children of this node, InsertBefore append a insetee to the
|
// If v1 is not children of this node, InsertBefore append an insetee to the
|
||||||
// tail of the children.
|
// tail of the children.
|
||||||
InsertBefore(self, v1, insertee Node)
|
InsertBefore(self, v1, insertee Node)
|
||||||
|
|
||||||
// InsertAfterinserts a node insertee after a node v1.
|
// InsertAfter inserts a node insertee after a node v1.
|
||||||
// If v1 is not children of this node, InsertBefore append a insetee to the
|
// If v1 is not children of this node, InsertBefore append an insetee to the
|
||||||
// tail of the children.
|
// tail of the children.
|
||||||
InsertAfter(self, v1, insertee Node)
|
InsertAfter(self, v1, insertee Node)
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ type Node interface {
|
||||||
|
|
||||||
// Dump dumps an AST tree structure to stdout.
|
// Dump dumps an AST tree structure to stdout.
|
||||||
// This function completely aimed for debugging.
|
// This function completely aimed for debugging.
|
||||||
// level is a indent level. Implementer should indent informations with
|
// level is an indent level. Implementer should indent information with
|
||||||
// 2 * level spaces.
|
// 2 * level spaces.
|
||||||
Dump(source []byte, level int)
|
Dump(source []byte, level int)
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@ type Node interface {
|
||||||
RemoveAttributes()
|
RemoveAttributes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A BaseNode struct implements the Node interface partialliy.
|
// A BaseNode struct implements the Node interface partially.
|
||||||
type BaseNode struct {
|
type BaseNode struct {
|
||||||
firstChild Node
|
firstChild Node
|
||||||
lastChild Node
|
lastChild Node
|
||||||
|
|
@ -468,7 +468,7 @@ const (
|
||||||
// WalkStop indicates no more walking needed.
|
// WalkStop indicates no more walking needed.
|
||||||
WalkStop WalkStatus = iota + 1
|
WalkStop WalkStatus = iota + 1
|
||||||
|
|
||||||
// WalkSkipChildren indicates that Walk wont walk on children of current
|
// WalkSkipChildren indicates that Walk won't walk on children of current
|
||||||
// node.
|
// node.
|
||||||
WalkSkipChildren
|
WalkSkipChildren
|
||||||
|
|
||||||
|
|
@ -482,7 +482,7 @@ const (
|
||||||
// If Walker returns error, Walk function immediately stop walking.
|
// If Walker returns error, Walk function immediately stop walking.
|
||||||
type Walker func(n Node, entering bool) (WalkStatus, error)
|
type Walker func(n Node, entering bool) (WalkStatus, error)
|
||||||
|
|
||||||
// Walk walks a AST tree by the depth first search algorithm.
|
// Walk walks an AST tree by the depth first search algorithm.
|
||||||
func Walk(n Node, walker Walker) error {
|
func Walk(n Node, walker Walker) error {
|
||||||
_, err := walkHelper(n, walker)
|
_, err := walkHelper(n, walker)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
textm "github.com/yuin/goldmark/text"
|
textm "github.com/yuin/goldmark/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A BaseBlock struct implements the Node interface partialliy.
|
// A BaseBlock struct implements the Node interface partially.
|
||||||
type BaseBlock struct {
|
type BaseBlock struct {
|
||||||
BaseNode
|
BaseNode
|
||||||
blankPreviousLines bool
|
blankPreviousLines bool
|
||||||
|
|
@ -265,7 +265,7 @@ type FencedCodeBlock struct {
|
||||||
language []byte
|
language []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Language returns an language in an info string.
|
// Language returns a language in an info string.
|
||||||
// Language returns nil if this node does not have an info string.
|
// Language returns nil if this node does not have an info string.
|
||||||
func (n *FencedCodeBlock) Language(source []byte) []byte {
|
func (n *FencedCodeBlock) Language(source []byte) []byte {
|
||||||
if n.language == nil && n.Info != nil {
|
if n.language == nil && n.Info != nil {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A BaseInline struct implements the Node interface partialliy.
|
// A BaseInline struct implements the Node interface partially.
|
||||||
type BaseInline struct {
|
type BaseInline struct {
|
||||||
BaseNode
|
BaseNode
|
||||||
}
|
}
|
||||||
|
|
@ -378,9 +378,10 @@ type Link struct {
|
||||||
|
|
||||||
// Dump implements Node.Dump.
|
// Dump implements Node.Dump.
|
||||||
func (n *Link) Dump(source []byte, level int) {
|
func (n *Link) Dump(source []byte, level int) {
|
||||||
m := map[string]string{}
|
m := map[string]string{
|
||||||
m["Destination"] = string(n.Destination)
|
"Destination": string(n.Destination),
|
||||||
m["Title"] = string(n.Title)
|
"Title": string(n.Title),
|
||||||
|
}
|
||||||
DumpHelper(n, source, level, m, nil)
|
DumpHelper(n, source, level, m, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -409,9 +410,10 @@ type Image struct {
|
||||||
|
|
||||||
// Dump implements Node.Dump.
|
// Dump implements Node.Dump.
|
||||||
func (n *Image) Dump(source []byte, level int) {
|
func (n *Image) Dump(source []byte, level int) {
|
||||||
m := map[string]string{}
|
m := map[string]string{
|
||||||
m["Destination"] = string(n.Destination)
|
"Destination": string(n.Destination),
|
||||||
m["Title"] = string(n.Title)
|
"Title": string(n.Title),
|
||||||
|
}
|
||||||
DumpHelper(n, source, level, m, nil)
|
DumpHelper(n, source, level, m, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -522,13 +524,14 @@ func (n *RawHTML) Inline() {}
|
||||||
|
|
||||||
// Dump implements Node.Dump.
|
// Dump implements Node.Dump.
|
||||||
func (n *RawHTML) Dump(source []byte, level int) {
|
func (n *RawHTML) Dump(source []byte, level int) {
|
||||||
m := map[string]string{}
|
var t []string
|
||||||
t := []string{}
|
|
||||||
for i := 0; i < n.Segments.Len(); i++ {
|
for i := 0; i < n.Segments.Len(); i++ {
|
||||||
segment := n.Segments.At(i)
|
segment := n.Segments.At(i)
|
||||||
t = append(t, string(segment.Value(source)))
|
t = append(t, string(segment.Value(source)))
|
||||||
}
|
}
|
||||||
m["RawText"] = strings.Join(t, "")
|
m := map[string]string{
|
||||||
|
"RawText": strings.Join(t, ""),
|
||||||
|
}
|
||||||
DumpHelper(n, source, level, m, nil)
|
DumpHelper(n, source, level, m, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func TestSpec(t *testing.T) {
|
||||||
if err := json.Unmarshal(bs, &testCases); err != nil {
|
if err := json.Unmarshal(bs, &testCases); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
cases := []testutil.MarkdownTestCase{}
|
var cases []testutil.MarkdownTestCase
|
||||||
nos := testutil.ParseCliCaseArg()
|
nos := testutil.ParseCliCaseArg()
|
||||||
for _, c := range testCases {
|
for _, c := range testCases {
|
||||||
shouldAdd := len(nos) == 0
|
shouldAdd := len(nos) == 0
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
// Package goldmark implements functions to convert markdown text to a desired format.
|
// Package goldmark implements functions to convert Markdown text to a desired format.
|
||||||
package goldmark
|
package goldmark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
"github.com/yuin/goldmark/renderer"
|
"github.com/yuin/goldmark/renderer"
|
||||||
"github.com/yuin/goldmark/renderer/html"
|
"github.com/yuin/goldmark/renderer/html"
|
||||||
"github.com/yuin/goldmark/text"
|
"github.com/yuin/goldmark/text"
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultParser returns a new Parser that is configured by default values.
|
// DefaultParser returns a new Parser that is configured by default values.
|
||||||
|
|
@ -44,7 +45,7 @@ type Markdown interface {
|
||||||
// SetParser sets a Parser to this object.
|
// SetParser sets a Parser to this object.
|
||||||
SetParser(parser.Parser)
|
SetParser(parser.Parser)
|
||||||
|
|
||||||
// Parser returns a Renderer that will be used for conversion.
|
// Renderer returns a Renderer that will be used for conversion.
|
||||||
Renderer() renderer.Renderer
|
Renderer() renderer.Renderer
|
||||||
|
|
||||||
// SetRenderer sets a Renderer to this object.
|
// SetRenderer sets a Renderer to this object.
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func parseAttributeValue(reader text.Reader) (interface{}, bool) {
|
||||||
|
|
||||||
func parseAttributeArray(reader text.Reader) ([]interface{}, bool) {
|
func parseAttributeArray(reader text.Reader) ([]interface{}, bool) {
|
||||||
reader.Advance(1) // skip [
|
reader.Advance(1) // skip [
|
||||||
ret := []interface{}{}
|
var ret []interface{}
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
c := reader.Peek()
|
c := reader.Peek()
|
||||||
comma := false
|
comma := false
|
||||||
|
|
@ -243,11 +243,10 @@ func parseAttributeString(reader text.Reader) ([]byte, bool) {
|
||||||
func scanAttributeDecimal(reader text.Reader, w io.ByteWriter) {
|
func scanAttributeDecimal(reader text.Reader, w io.ByteWriter) {
|
||||||
for {
|
for {
|
||||||
c := reader.Peek()
|
c := reader.Peek()
|
||||||
if util.IsNumeric(c) {
|
if !util.IsNumeric(c) {
|
||||||
w.WriteByte(c)
|
|
||||||
} else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteByte(c)
|
||||||
reader.Advance(1)
|
reader.Advance(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type autoLinkParser struct {
|
type autoLinkParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultAutoLinkParser = &autoLinkParser{}
|
var defaultAutoLinkParser = &autoLinkParser{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,11 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type blockquoteParser struct {
|
type blockquoteParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultBlockquoteParser = &blockquoteParser{}
|
var defaultBlockquoteParser = &blockquoteParser{}
|
||||||
|
|
||||||
// NewBlockquoteParser returns a new BlockParser that
|
// NewBlockquoteParser returns a new BlockParser that parses blockquotes.
|
||||||
// parses blockquotes.
|
|
||||||
func NewBlockquoteParser() BlockParser {
|
func NewBlockquoteParser() BlockParser {
|
||||||
return defaultBlockquoteParser
|
return defaultBlockquoteParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,12 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type codeBlockParser struct {
|
type codeBlockParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
// CodeBlockParser is a BlockParser implementation that parses indented code blocks.
|
// CodeBlockParser is a BlockParser implementation that parses indented code blocks.
|
||||||
var defaultCodeBlockParser = &codeBlockParser{}
|
var defaultCodeBlockParser = &codeBlockParser{}
|
||||||
|
|
||||||
// NewCodeBlockParser returns a new BlockParser that
|
// NewCodeBlockParser returns a new BlockParser that parses code blocks.
|
||||||
// parses code blocks.
|
|
||||||
func NewCodeBlockParser() BlockParser {
|
func NewCodeBlockParser() BlockParser {
|
||||||
return defaultCodeBlockParser
|
return defaultCodeBlockParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ import (
|
||||||
"github.com/yuin/goldmark/text"
|
"github.com/yuin/goldmark/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type codeSpanParser struct {
|
type codeSpanParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultCodeSpanParser = &codeSpanParser{}
|
var defaultCodeSpanParser = &codeSpanParser{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A DelimiterProcessor interface provides a set of functions about
|
// A DelimiterProcessor interface provides a set of functions about Delimiter nodes.
|
||||||
// Delimiter nodes.
|
|
||||||
type DelimiterProcessor interface {
|
type DelimiterProcessor interface {
|
||||||
// IsDelimiter returns true if given character is a delimiter, otherwise false.
|
// IsDelimiter returns true if given character is a delimiter, otherwise false.
|
||||||
IsDelimiter(byte) bool
|
IsDelimiter(byte) bool
|
||||||
|
|
@ -82,9 +81,9 @@ func (d *Delimiter) ConsumeCharacters(n int) {
|
||||||
d.Segment = d.Segment.WithStop(d.Segment.Start + d.Length)
|
d.Segment = d.Segment.WithStop(d.Segment.Start + d.Length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalcComsumption calculates how many characters should be used for opening
|
// CalcConsumption calculates how many characters should be used for opening
|
||||||
// a new span correspond to given closer.
|
// a new span correspond to given closer.
|
||||||
func (d *Delimiter) CalcComsumption(closer *Delimiter) int {
|
func (d *Delimiter) CalcConsumption(closer *Delimiter) int {
|
||||||
if (d.CanClose || closer.CanOpen) && (d.OriginalLength+closer.OriginalLength)%3 == 0 && closer.OriginalLength%3 != 0 {
|
if (d.CanClose || closer.CanOpen) && (d.OriginalLength+closer.OriginalLength)%3 == 0 && closer.OriginalLength%3 != 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +149,7 @@ func ScanDelimiter(line []byte, before rune, min int, processor DelimiterProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessDelimiters processes the delimiter list in the context.
|
// ProcessDelimiters processes the delimiter list in the context.
|
||||||
// Processing will be stop when reaching the bottom.
|
// Processing will stop when reaching the bottom.
|
||||||
//
|
//
|
||||||
// If you implement an inline parser that can have other inline nodes as
|
// If you implement an inline parser that can have other inline nodes as
|
||||||
// children, you should call this function when nesting span has closed.
|
// children, you should call this function when nesting span has closed.
|
||||||
|
|
@ -188,7 +187,7 @@ func ProcessDelimiters(bottom ast.Node, pc Context) {
|
||||||
for opener = closer.PreviousDelimiter; opener != nil && opener != bottom; opener = opener.PreviousDelimiter {
|
for opener = closer.PreviousDelimiter; opener != nil && opener != bottom; opener = opener.PreviousDelimiter {
|
||||||
if opener.CanOpen && opener.Processor.CanOpenCloser(opener, closer) {
|
if opener.CanOpen && opener.Processor.CanOpenCloser(opener, closer) {
|
||||||
maybeOpener = true
|
maybeOpener = true
|
||||||
consume = opener.CalcComsumption(closer)
|
consume = opener.CalcConsumption(closer)
|
||||||
if consume > 0 {
|
if consume > 0 {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ import (
|
||||||
"github.com/yuin/goldmark/text"
|
"github.com/yuin/goldmark/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type emphasisDelimiterProcessor struct {
|
type emphasisDelimiterProcessor struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (p *emphasisDelimiterProcessor) IsDelimiter(b byte) bool {
|
func (p *emphasisDelimiterProcessor) IsDelimiter(b byte) bool {
|
||||||
return b == '*' || b == '_'
|
return b == '*' || b == '_'
|
||||||
|
|
@ -22,8 +21,7 @@ func (p *emphasisDelimiterProcessor) OnMatch(consumes int) ast.Node {
|
||||||
|
|
||||||
var defaultEmphasisDelimiterProcessor = &emphasisDelimiterProcessor{}
|
var defaultEmphasisDelimiterProcessor = &emphasisDelimiterProcessor{}
|
||||||
|
|
||||||
type emphasisParser struct {
|
type emphasisParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultEmphasisParser = &emphasisParser{}
|
var defaultEmphasisParser = &emphasisParser{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,11 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fencedCodeBlockParser struct {
|
type fencedCodeBlockParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultFencedCodeBlockParser = &fencedCodeBlockParser{}
|
var defaultFencedCodeBlockParser = &fencedCodeBlockParser{}
|
||||||
|
|
||||||
// NewFencedCodeBlockParser returns a new BlockParser that
|
// NewFencedCodeBlockParser returns a new BlockParser that parses fenced code blocks.
|
||||||
// parses fenced code blocks.
|
|
||||||
func NewFencedCodeBlockParser() BlockParser {
|
func NewFencedCodeBlockParser() BlockParser {
|
||||||
return defaultFencedCodeBlockParser
|
return defaultFencedCodeBlockParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,7 @@ type htmlBlockParser struct {
|
||||||
|
|
||||||
var defaultHTMLBlockParser = &htmlBlockParser{}
|
var defaultHTMLBlockParser = &htmlBlockParser{}
|
||||||
|
|
||||||
// NewHTMLBlockParser return a new BlockParser that can parse html
|
// NewHTMLBlockParser return a new BlockParser that can parse html blocks.
|
||||||
// blocks.
|
|
||||||
func NewHTMLBlockParser() BlockParser {
|
func NewHTMLBlockParser() BlockParser {
|
||||||
return defaultHTMLBlockParser
|
return defaultHTMLBlockParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,7 @@ func removeLinkLabelState(pc Context, d *linkLabelState) {
|
||||||
d.Last = nil
|
d.Last = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type linkParser struct {
|
type linkParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultLinkParser = &linkParser{}
|
var defaultLinkParser = &linkParser{}
|
||||||
|
|
||||||
|
|
@ -244,7 +243,7 @@ func (s *linkParser) processLinkLabel(parent ast.Node, link *ast.Link, last *lin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var linkFindClosureOptions text.FindClosureOptions = text.FindClosureOptions{
|
var linkFindClosureOptions = text.FindClosureOptions{
|
||||||
Nesting: false,
|
Nesting: false,
|
||||||
Newline: true,
|
Newline: true,
|
||||||
Advance: true,
|
Advance: true,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ var LinkReferenceParagraphTransformer = &linkReferenceParagraphTransformer{}
|
||||||
func (p *linkReferenceParagraphTransformer) Transform(node *ast.Paragraph, reader text.Reader, pc Context) {
|
func (p *linkReferenceParagraphTransformer) Transform(node *ast.Paragraph, reader text.Reader, pc Context) {
|
||||||
lines := node.Lines()
|
lines := node.Lines()
|
||||||
block := text.NewBlockReader(reader.Source(), lines)
|
block := text.NewBlockReader(reader.Source(), lines)
|
||||||
removes := [][2]int{}
|
var removes [][2]int
|
||||||
for {
|
for {
|
||||||
start, end := parseLinkReferenceDefinition(block, pc)
|
start, end := parseLinkReferenceDefinition(block, pc)
|
||||||
if start > -1 {
|
if start > -1 {
|
||||||
|
|
|
||||||
|
|
@ -109,13 +109,11 @@ func lastOffset(node ast.Node) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type listParser struct {
|
type listParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultListParser = &listParser{}
|
var defaultListParser = &listParser{}
|
||||||
|
|
||||||
// NewListParser returns a new BlockParser that
|
// NewListParser returns a new BlockParser that parses lists.
|
||||||
// parses lists.
|
|
||||||
// This parser must take precedence over the ListItemParser.
|
// This parser must take precedence over the ListItemParser.
|
||||||
func NewListParser() BlockParser {
|
func NewListParser() BlockParser {
|
||||||
return defaultListParser
|
return defaultListParser
|
||||||
|
|
@ -147,7 +145,7 @@ func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.
|
||||||
if typ == orderedList && start != 1 {
|
if typ == orderedList && start != 1 {
|
||||||
return nil, NoChildren
|
return nil, NoChildren
|
||||||
}
|
}
|
||||||
//an empty list item cannot interrupt a paragraph:
|
// an empty list item cannot interrupt a paragraph:
|
||||||
if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
|
if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
|
||||||
return nil, NoChildren
|
return nil, NoChildren
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,11 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type listItemParser struct {
|
type listItemParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultListItemParser = &listItemParser{}
|
var defaultListItemParser = &listItemParser{}
|
||||||
|
|
||||||
// NewListItemParser returns a new BlockParser that
|
// NewListItemParser returns a new BlockParser that parses list items.
|
||||||
// parses list items.
|
|
||||||
func NewListItemParser() BlockParser {
|
func NewListItemParser() BlockParser {
|
||||||
return defaultListItemParser
|
return defaultListItemParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ type paragraphParser struct {
|
||||||
|
|
||||||
var defaultParagraphParser = ¶graphParser{}
|
var defaultParagraphParser = ¶graphParser{}
|
||||||
|
|
||||||
// NewParagraphParser returns a new BlockParser that
|
// NewParagraphParser returns a new BlockParser that parses paragraphs.
|
||||||
// parses paragraphs.
|
|
||||||
func NewParagraphParser() BlockParser {
|
func NewParagraphParser() BlockParser {
|
||||||
return defaultParagraphParser
|
return defaultParagraphParser
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ func newIDs() IDs {
|
||||||
func (s *ids) Generate(value []byte, kind ast.NodeKind) []byte {
|
func (s *ids) Generate(value []byte, kind ast.NodeKind) []byte {
|
||||||
value = util.TrimLeftSpace(value)
|
value = util.TrimLeftSpace(value)
|
||||||
value = util.TrimRightSpace(value)
|
value = util.TrimRightSpace(value)
|
||||||
result := []byte{}
|
var result []byte
|
||||||
for i := 0; i < len(value); {
|
for i := 0; i < len(value); {
|
||||||
v := value[i]
|
v := value[i]
|
||||||
l := util.UTF8Len(v)
|
l := util.UTF8Len(v)
|
||||||
|
|
@ -162,7 +162,7 @@ type Context interface {
|
||||||
// BlockOffset returns -1 if current line is blank.
|
// BlockOffset returns -1 if current line is blank.
|
||||||
BlockOffset() int
|
BlockOffset() int
|
||||||
|
|
||||||
// BlockOffset sets a first non-space character position on current line.
|
// SetBlockOffset sets a first non-space character position on current line.
|
||||||
// This value is valid only for BlockParser.Open.
|
// This value is valid only for BlockParser.Open.
|
||||||
SetBlockOffset(int)
|
SetBlockOffset(int)
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ type Context interface {
|
||||||
// BlockIndent returns -1 if current line is blank.
|
// BlockIndent returns -1 if current line is blank.
|
||||||
BlockIndent() int
|
BlockIndent() int
|
||||||
|
|
||||||
// BlockIndent sets an indent width on current line.
|
// SetBlockIndent sets an indent width on current line.
|
||||||
// This value is valid only for BlockParser.Open.
|
// This value is valid only for BlockParser.Open.
|
||||||
SetBlockIndent(int)
|
SetBlockIndent(int)
|
||||||
|
|
||||||
|
|
@ -370,7 +370,7 @@ func (p *parseContext) References() []Reference {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parseContext) String() string {
|
func (p *parseContext) String() string {
|
||||||
refs := []string{}
|
var refs []string
|
||||||
for _, r := range p.refs {
|
for _, r := range p.refs {
|
||||||
refs = append(refs, r.String())
|
refs = append(refs, r.String())
|
||||||
}
|
}
|
||||||
|
|
@ -451,11 +451,10 @@ type Option interface {
|
||||||
// OptionName is a name of parser options.
|
// OptionName is a name of parser options.
|
||||||
type OptionName string
|
type OptionName string
|
||||||
|
|
||||||
// Attribute is an option name that spacify attributes of elements.
|
// Attribute is an option name that specifies attributes of elements.
|
||||||
const optAttribute OptionName = "Attribute"
|
const optAttribute OptionName = "Attribute"
|
||||||
|
|
||||||
type withAttribute struct {
|
type withAttribute struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (o *withAttribute) SetParserOption(c *Config) {
|
func (o *withAttribute) SetParserOption(c *Config) {
|
||||||
c.Options[optAttribute] = true
|
c.Options[optAttribute] = true
|
||||||
|
|
@ -471,7 +470,7 @@ type Parser interface {
|
||||||
// Parse parses the given Markdown text into AST nodes.
|
// Parse parses the given Markdown text into AST nodes.
|
||||||
Parse(reader text.Reader, opts ...ParseOption) ast.Node
|
Parse(reader text.Reader, opts ...ParseOption) ast.Node
|
||||||
|
|
||||||
// AddOption adds the given option to this parser.
|
// AddOptions adds the given option to this parser.
|
||||||
AddOptions(...Option)
|
AddOptions(...Option)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -499,7 +498,7 @@ type BlockParser interface {
|
||||||
//
|
//
|
||||||
// If Open has not been able to parse the current line, Open should returns
|
// If Open has not been able to parse the current line, Open should returns
|
||||||
// (nil, NoChildren). If Open has been able to parse the current line, Open
|
// (nil, NoChildren). If Open has been able to parse the current line, Open
|
||||||
// should returns a new Block node and returns HasChildren or NoChildren.
|
// should return a new Block node and returns HasChildren or NoChildren.
|
||||||
Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State)
|
Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State)
|
||||||
|
|
||||||
// Continue parses the current line and returns a result of parsing.
|
// Continue parses the current line and returns a result of parsing.
|
||||||
|
|
@ -509,9 +508,8 @@ type BlockParser interface {
|
||||||
// a reader position by consumed byte length.
|
// a reader position by consumed byte length.
|
||||||
//
|
//
|
||||||
// If Continue has not been able to parse the current line, Continue should
|
// If Continue has not been able to parse the current line, Continue should
|
||||||
// returns Close. If Continue has been able to parse the current line,
|
// return Close. If Continue has been able to parse the current line,
|
||||||
// Continue should returns (Continue | NoChildren) or
|
// Continue should return (Continue | NoChildren) or (Continue | HasChildren)
|
||||||
// (Continue | HasChildren)
|
|
||||||
Continue(node ast.Node, reader text.Reader, pc Context) State
|
Continue(node ast.Node, reader text.Reader, pc Context) State
|
||||||
|
|
||||||
// Close will be called when the parser returns Close.
|
// Close will be called when the parser returns Close.
|
||||||
|
|
@ -535,7 +533,7 @@ type InlineParser interface {
|
||||||
// a head of line
|
// a head of line
|
||||||
Trigger() []byte
|
Trigger() []byte
|
||||||
|
|
||||||
// Parse parse the given block into an inline node.
|
// Parse parses the given block into an inline node.
|
||||||
//
|
//
|
||||||
// Parse can parse beyond the current line.
|
// Parse can parse beyond the current line.
|
||||||
// If Parse has been able to parse the current line, it must advance a reader
|
// If Parse has been able to parse the current line, it must advance a reader
|
||||||
|
|
@ -907,7 +905,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *parser) openBlocks(parent ast.Node, blankLine bool, reader text.Reader, pc Context) blockOpenResult {
|
func (p *parser) openBlocks(parent ast.Node, blankLine bool, reader text.Reader, pc Context) blockOpenResult {
|
||||||
result := blockOpenResult(noBlocksOpened)
|
result := noBlocksOpened
|
||||||
continuable := false
|
continuable := false
|
||||||
lastBlock := pc.LastOpenedBlock()
|
lastBlock := pc.LastOpenedBlock()
|
||||||
if lastBlock.Node != nil {
|
if lastBlock.Node != nil {
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ type rawHTMLParser struct {
|
||||||
|
|
||||||
var defaultRawHTMLParser = &rawHTMLParser{}
|
var defaultRawHTMLParser = &rawHTMLParser{}
|
||||||
|
|
||||||
// NewRawHTMLParser return a new InlineParser that can parse
|
// NewRawHTMLParser return a new InlineParser that can parse inline htmls
|
||||||
// inline htmls
|
|
||||||
func NewRawHTMLParser() InlineParser {
|
func NewRawHTMLParser() InlineParser {
|
||||||
return defaultRawHTMLParser
|
return defaultRawHTMLParser
|
||||||
}
|
}
|
||||||
|
|
@ -153,9 +152,8 @@ func (s *rawHTMLParser) parseMultiLineRegexp(reg *regexp.Regexp, block text.Read
|
||||||
if l == eline {
|
if l == eline {
|
||||||
block.Advance(end - start)
|
block.Advance(end - start)
|
||||||
break
|
break
|
||||||
} else {
|
|
||||||
block.AdvanceLine()
|
|
||||||
}
|
}
|
||||||
|
block.AdvanceLine()
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,13 @@ import (
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type thematicBreakPraser struct {
|
type thematicBreakParser struct{}
|
||||||
}
|
|
||||||
|
|
||||||
var defaultThematicBreakPraser = &thematicBreakPraser{}
|
var defaultThematicBreakParser = &thematicBreakParser{}
|
||||||
|
|
||||||
// NewThematicBreakParser returns a new BlockParser that
|
// NewThematicBreakParser returns a new BlockParser that parses thematic breaks.
|
||||||
// parses thematic breaks.
|
|
||||||
func NewThematicBreakParser() BlockParser {
|
func NewThematicBreakParser() BlockParser {
|
||||||
return defaultThematicBreakPraser
|
return defaultThematicBreakParser
|
||||||
}
|
}
|
||||||
|
|
||||||
func isThematicBreak(line []byte, offset int) bool {
|
func isThematicBreak(line []byte, offset int) bool {
|
||||||
|
|
@ -45,11 +43,11 @@ func isThematicBreak(line []byte, offset int) bool {
|
||||||
return count > 2
|
return count > 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) Trigger() []byte {
|
func (b *thematicBreakParser) Trigger() []byte {
|
||||||
return []byte{'-', '*', '_'}
|
return []byte{'-', '*', '_'}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
|
func (b *thematicBreakParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
|
||||||
line, segment := reader.PeekLine()
|
line, segment := reader.PeekLine()
|
||||||
if isThematicBreak(line, reader.LineOffset()) {
|
if isThematicBreak(line, reader.LineOffset()) {
|
||||||
reader.Advance(segment.Len() - 1)
|
reader.Advance(segment.Len() - 1)
|
||||||
|
|
@ -58,18 +56,18 @@ func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Conte
|
||||||
return nil, NoChildren
|
return nil, NoChildren
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) Continue(node ast.Node, reader text.Reader, pc Context) State {
|
func (b *thematicBreakParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
|
||||||
return Close
|
return Close
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) Close(node ast.Node, reader text.Reader, pc Context) {
|
func (b *thematicBreakParser) Close(node ast.Node, reader text.Reader, pc Context) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) CanInterruptParagraph() bool {
|
func (b *thematicBreakParser) CanInterruptParagraph() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *thematicBreakPraser) CanAcceptIndentedLine() bool {
|
func (b *thematicBreakParser) CanAcceptIndentedLine() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,7 @@ func WithHardWraps() interface {
|
||||||
// XHTML is an option name used in WithXHTML.
|
// XHTML is an option name used in WithXHTML.
|
||||||
const optXHTML renderer.OptionName = "XHTML"
|
const optXHTML renderer.OptionName = "XHTML"
|
||||||
|
|
||||||
type withXHTML struct {
|
type withXHTML struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (o *withXHTML) SetConfig(c *renderer.Config) {
|
func (o *withXHTML) SetConfig(c *renderer.Config) {
|
||||||
c.Options[optXHTML] = true
|
c.Options[optXHTML] = true
|
||||||
|
|
@ -683,8 +682,7 @@ type Writer interface {
|
||||||
|
|
||||||
var replacementCharacter = []byte("\ufffd")
|
var replacementCharacter = []byte("\ufffd")
|
||||||
|
|
||||||
type defaultWriter struct {
|
type defaultWriter struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func escapeRune(writer util.BufWriter, r rune) {
|
func escapeRune(writer util.BufWriter, r rune) {
|
||||||
if r < 256 {
|
if r < 256 {
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ type NodeRendererFunc func(writer util.BufWriter, source []byte, n ast.Node, ent
|
||||||
|
|
||||||
// A NodeRenderer interface offers NodeRendererFuncs.
|
// A NodeRenderer interface offers NodeRendererFuncs.
|
||||||
type NodeRenderer interface {
|
type NodeRenderer interface {
|
||||||
// RendererFuncs registers NodeRendererFuncs to given NodeRendererFuncRegisterer.
|
// RegisterFuncs registers NodeRendererFuncs to given NodeRendererFuncRegisterer.
|
||||||
RegisterFuncs(NodeRendererFuncRegisterer)
|
RegisterFuncs(NodeRendererFuncRegisterer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ type MarkdownTestCaseOptions struct {
|
||||||
const attributeSeparator = "//- - - - - - - - -//"
|
const attributeSeparator = "//- - - - - - - - -//"
|
||||||
const caseSeparator = "//= = = = = = = = = = = = = = = = = = = = = = = =//"
|
const caseSeparator = "//= = = = = = = = = = = = = = = = = = = = = = = =//"
|
||||||
|
|
||||||
var optionsRegexp *regexp.Regexp = regexp.MustCompile(`(?i)\s*options:(.*)`)
|
var optionsRegexp = regexp.MustCompile(`(?i)\s*options:(.*)`)
|
||||||
|
|
||||||
// ParseCliCaseArg parses -case command line args.
|
// ParseCliCaseArg parses -case command line args.
|
||||||
func ParseCliCaseArg() []int {
|
func ParseCliCaseArg() []int {
|
||||||
ret := []int{}
|
var ret []int
|
||||||
for _, a := range os.Args {
|
for _, a := range os.Args {
|
||||||
if strings.HasPrefix(a, "case=") {
|
if strings.HasPrefix(a, "case=") {
|
||||||
parts := strings.Split(a, "=")
|
parts := strings.Split(a, "=")
|
||||||
|
|
@ -100,7 +100,7 @@ func DoTestCaseFile(m goldmark.Markdown, filename string, t TestingT, no ...int)
|
||||||
Markdown: "",
|
Markdown: "",
|
||||||
Expected: "",
|
Expected: "",
|
||||||
}
|
}
|
||||||
cases := []MarkdownTestCase{}
|
var cases []MarkdownTestCase
|
||||||
line := 0
|
line := 0
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line++
|
line++
|
||||||
|
|
@ -135,7 +135,7 @@ func DoTestCaseFile(m goldmark.Markdown, filename string, t TestingT, no ...int)
|
||||||
if scanner.Text() != attributeSeparator {
|
if scanner.Text() != attributeSeparator {
|
||||||
panic(fmt.Sprintf("%s: invalid separator '%s' at line %d", filename, scanner.Text(), line))
|
panic(fmt.Sprintf("%s: invalid separator '%s' at line %d", filename, scanner.Text(), line))
|
||||||
}
|
}
|
||||||
buf := []string{}
|
var buf []string
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line++
|
line++
|
||||||
text := scanner.Text()
|
text := scanner.Text()
|
||||||
|
|
@ -290,7 +290,7 @@ func simpleDiffAux(v1lines, v2lines [][]byte) []diff {
|
||||||
overlap = newOverlap
|
overlap = newOverlap
|
||||||
}
|
}
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
diffs := []diff{}
|
var diffs []diff
|
||||||
if len(v1lines) != 0 {
|
if len(v1lines) != 0 {
|
||||||
diffs = append(diffs, diff{diffRemoved, v1lines})
|
diffs = append(diffs, diff{diffRemoved, v1lines})
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +377,7 @@ func applyEscapeSequence(b []byte) []byte {
|
||||||
}
|
}
|
||||||
case 'u', 'U':
|
case 'u', 'U':
|
||||||
if len(b) > i+2 {
|
if len(b) > i+2 {
|
||||||
num := []byte{}
|
var num []byte
|
||||||
for j := i + 2; j < len(b); j++ {
|
for j := i + 2; j < len(b); j++ {
|
||||||
if util.IsHexDecimal(b[j]) {
|
if util.IsHexDecimal(b[j]) {
|
||||||
num = append(num, b[j])
|
num = append(num, b[j])
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,14 @@ type Reader interface {
|
||||||
// If it reaches EOF, returns false.
|
// If it reaches EOF, returns false.
|
||||||
SkipSpaces() (Segment, int, bool)
|
SkipSpaces() (Segment, int, bool)
|
||||||
|
|
||||||
// SkipSpaces skips blank lines and returns a non-blank line.
|
// SkipBlankLines skips blank lines and returns a non-blank line.
|
||||||
// If it reaches EOF, returns false.
|
// If it reaches EOF, returns false.
|
||||||
SkipBlankLines() (Segment, int, bool)
|
SkipBlankLines() (Segment, int, bool)
|
||||||
|
|
||||||
// Match performs regular expression matching to current line.
|
// Match performs regular expression matching to current line.
|
||||||
Match(reg *regexp.Regexp) bool
|
Match(reg *regexp.Regexp) bool
|
||||||
|
|
||||||
// Match performs regular expression searching to current line.
|
// FindSubMatch performs regular expression searching to current line.
|
||||||
FindSubMatch(reg *regexp.Regexp) [][]byte
|
FindSubMatch(reg *regexp.Regexp) [][]byte
|
||||||
|
|
||||||
// FindClosure finds corresponding closure.
|
// FindClosure finds corresponding closure.
|
||||||
|
|
@ -94,6 +94,7 @@ type FindClosureOptions struct {
|
||||||
Advance bool
|
Advance bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reader implements io.RuneReader interface
|
||||||
type reader struct {
|
type reader struct {
|
||||||
source []byte
|
source []byte
|
||||||
sourceLength int
|
sourceLength int
|
||||||
|
|
@ -153,7 +154,6 @@ func (r *reader) PeekLine() ([]byte, Segment) {
|
||||||
return nil, r.pos
|
return nil, r.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.RuneReader interface
|
|
||||||
func (r *reader) ReadRune() (rune, int, error) {
|
func (r *reader) ReadRune() (rune, int, error) {
|
||||||
return readRuneReader(r)
|
return readRuneReader(r)
|
||||||
}
|
}
|
||||||
|
|
@ -276,6 +276,7 @@ type BlockReader interface {
|
||||||
Reset(segment *Segments)
|
Reset(segment *Segments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blockReader implements io.RuneReader interface
|
||||||
type blockReader struct {
|
type blockReader struct {
|
||||||
source []byte
|
source []byte
|
||||||
segments *Segments
|
segments *Segments
|
||||||
|
|
@ -353,21 +354,20 @@ func (r *blockReader) Value(seg Segment) []byte {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.RuneReader interface
|
|
||||||
func (r *blockReader) ReadRune() (rune, int, error) {
|
func (r *blockReader) ReadRune() (rune, int, error) {
|
||||||
return readRuneReader(r)
|
return readRuneReader(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *blockReader) PrecendingCharacter() rune {
|
func (r *blockReader) PrecendingCharacter() rune {
|
||||||
if r.pos.Padding != 0 {
|
if r.pos.Padding != 0 {
|
||||||
return rune(' ')
|
return ' '
|
||||||
}
|
}
|
||||||
if r.segments.Len() < 1 {
|
if r.segments.Len() < 1 {
|
||||||
return rune('\n')
|
return '\n'
|
||||||
}
|
}
|
||||||
firstSegment := r.segments.At(0)
|
firstSegment := r.segments.At(0)
|
||||||
if r.line == 0 && r.pos.Start <= firstSegment.Start {
|
if r.line == 0 && r.pos.Start <= firstSegment.Start {
|
||||||
return rune('\n')
|
return '\n'
|
||||||
}
|
}
|
||||||
l := len(r.source)
|
l := len(r.source)
|
||||||
i := r.pos.Start - 1
|
i := r.pos.Start - 1
|
||||||
|
|
@ -377,7 +377,7 @@ func (r *blockReader) PrecendingCharacter() rune {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i < 0 || i >= l {
|
if i < 0 || i >= l {
|
||||||
return rune('\n')
|
return '\n'
|
||||||
}
|
}
|
||||||
rn, _ := utf8.DecodeRune(r.source[i:])
|
rn, _ := utf8.DecodeRune(r.source[i:])
|
||||||
return rn
|
return rn
|
||||||
|
|
@ -549,7 +549,7 @@ func findSubMatchReader(r Reader, reg *regexp.Regexp) [][]byte {
|
||||||
i += size
|
i += size
|
||||||
runes = append(runes, r)
|
runes = append(runes, r)
|
||||||
}
|
}
|
||||||
result := [][]byte{}
|
var result [][]byte
|
||||||
for i := 0; i < len(match); i += 2 {
|
for i := 0; i < len(match); i += 2 {
|
||||||
result = append(result, []byte(string(runes[match[i]:match[i+1]])))
|
result = append(result, []byte(string(runes[match[i]:match[i+1]])))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package text
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
// An HTML5Entity struct represents HTML5 entitites.
|
// An HTML5Entity struct represents HTML5 entities.
|
||||||
type HTML5Entity struct {
|
type HTML5Entity struct {
|
||||||
Name string
|
Name string
|
||||||
CodePoints []int
|
CodePoints []int
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
78
util/util.go
78
util/util.go
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// A CopyOnWriteBuffer is a byte buffer that copies buffer when
|
// A CopyOnWriteBuffer is a byte buffer that copies buffer when
|
||||||
// it need to be changed.
|
// it needs to be changed.
|
||||||
type CopyOnWriteBuffer struct {
|
type CopyOnWriteBuffer struct {
|
||||||
buffer []byte
|
buffer []byte
|
||||||
copied bool
|
copied bool
|
||||||
|
|
@ -184,25 +184,25 @@ func IndentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, pad
|
||||||
//
|
//
|
||||||
// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
|
// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
|
||||||
func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
w := 0
|
w := 0
|
||||||
l := len(bs)
|
l := len(bs)
|
||||||
i := 0
|
i := 0
|
||||||
for ; i < l; i++ {
|
for ; i < l; i++ {
|
||||||
if bs[i] == '\t' {
|
if bs[i] == '\t' {
|
||||||
w += TabWidth(currentPos + w)
|
w += TabWidth(currentPos + w)
|
||||||
} else if bs[i] == ' ' {
|
} else if bs[i] == ' ' {
|
||||||
w++
|
w++
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if w >= width {
|
if w >= width {
|
||||||
return i, w - width
|
return i, w - width
|
||||||
}
|
}
|
||||||
return i, 0
|
return i, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DedentPositionPadding dedents lines by the given width.
|
// DedentPositionPadding dedents lines by the given width.
|
||||||
|
|
@ -211,26 +211,26 @@ func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
||||||
//
|
//
|
||||||
// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
|
// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
|
||||||
func DedentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
|
func DedentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
return 0, paddingv
|
return 0, paddingv
|
||||||
}
|
}
|
||||||
|
|
||||||
w := 0
|
w := 0
|
||||||
i := 0
|
i := 0
|
||||||
l := len(bs)
|
l := len(bs)
|
||||||
for ; i < l; i++ {
|
for ; i < l; i++ {
|
||||||
if bs[i] == '\t' {
|
if bs[i] == '\t' {
|
||||||
w += TabWidth(currentPos + w)
|
w += TabWidth(currentPos + w)
|
||||||
} else if bs[i] == ' ' {
|
} else if bs[i] == ' ' {
|
||||||
w++
|
w++
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if w >= width {
|
if w >= width {
|
||||||
return i - paddingv, w - width
|
return i - paddingv, w - width
|
||||||
}
|
}
|
||||||
return i - paddingv, 0
|
return i - paddingv, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndentWidth calculate an indent width for the given line.
|
// IndentWidth calculate an indent width for the given line.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue