mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
commit
615d5706c6
21 changed files with 50 additions and 44 deletions
|
|
@ -436,7 +436,7 @@ func Walk(n Node, walker Walker) error {
|
|||
}
|
||||
if status != WalkSkipChildren {
|
||||
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if err := Walk(c, walker); err != nil {
|
||||
if err = Walk(c, walker); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"testing"
|
||||
|
||||
. "github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
type commonmarkSpecTestCase struct {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestDefinitionList(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestFootnote(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestStrikethrough(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []
|
|||
closure = len(line[pos:])
|
||||
}
|
||||
node := ast.NewTableCell()
|
||||
segment := text.NewSegment(segment.Start+pos, segment.Start+pos+closure)
|
||||
segment = segment.TrimLeftSpace(source)
|
||||
segment = segment.TrimRightSpace(source)
|
||||
node.Lines().Append(segment)
|
||||
seg := text.NewSegment(segment.Start+pos, segment.Start+pos+closure)
|
||||
seg = seg.TrimLeftSpace(source)
|
||||
seg = seg.TrimRightSpace(source)
|
||||
node.Lines().Append(seg)
|
||||
node.Alignment = alignment
|
||||
row.AppendChild(row, node)
|
||||
pos += closure + 1
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestTaskList(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestTypographer(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ package fuzz
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
)
|
||||
|
||||
// Fuzz runs automated fuzzing against goldmark.
|
||||
func Fuzz(data []byte) int {
|
||||
markdown := goldmark.New(
|
||||
goldmark.WithRendererOptions(
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
. "github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/testutil"
|
||||
)
|
||||
|
||||
func TestAttributeAndAutoHeadingID(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package parser
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/yuin/goldmark/text"
|
||||
"github.com/yuin/goldmark/util"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var attrNameID = []byte("id")
|
||||
|
|
@ -104,7 +106,7 @@ func parseAttribute(reader text.Reader) (Attribute, bool) {
|
|||
}
|
||||
i := 0
|
||||
for ; i < len(line); i++ {
|
||||
c := line[i]
|
||||
c = line[i]
|
||||
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '_' || c == ':' || c == '.' || c == '-') {
|
||||
|
|
@ -125,7 +127,6 @@ func parseAttribute(reader text.Reader) (Attribute, bool) {
|
|||
return Attribute{}, false
|
||||
}
|
||||
return Attribute{Name: name, Value: value}, true
|
||||
|
||||
}
|
||||
|
||||
func parseAttributeValue(reader text.Reader) (interface{}, bool) {
|
||||
|
|
@ -153,7 +154,6 @@ func parseAttributeValue(reader text.Reader) (interface{}, bool) {
|
|||
return nil, false
|
||||
}
|
||||
return value, true
|
||||
|
||||
}
|
||||
|
||||
func parseAttributeArray(reader text.Reader) ([]interface{}, bool) {
|
||||
|
|
@ -228,7 +228,7 @@ func parseAttributeString(reader text.Reader) ([]byte, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
func scanAttributeDecimal(reader text.Reader, w *bytes.Buffer) {
|
||||
func scanAttributeDecimal(reader text.Reader, w io.ByteWriter) {
|
||||
for {
|
||||
c := reader.Peek()
|
||||
if util.IsNumeric(c) {
|
||||
|
|
|
|||
|
|
@ -108,19 +108,19 @@ func (b *atxHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context)
|
|||
start--
|
||||
closureClose := -1
|
||||
closureOpen := -1
|
||||
for i := start; i < stop; {
|
||||
c := line[i]
|
||||
if util.IsEscapedPunctuation(line, i) {
|
||||
i += 2
|
||||
} else if util.IsSpace(c) && i < stop-1 && line[i+1] == '#' {
|
||||
closureOpen = i + 1
|
||||
j := i + 1
|
||||
for ; j < stop && line[j] == '#'; j++ {
|
||||
for j := start; j < stop; {
|
||||
c := line[j]
|
||||
if util.IsEscapedPunctuation(line, j) {
|
||||
j += 2
|
||||
} else if util.IsSpace(c) && j < stop-1 && line[j+1] == '#' {
|
||||
closureOpen = j + 1
|
||||
k := j + 1
|
||||
for ; k < stop && line[k] == '#'; k++ {
|
||||
}
|
||||
closureClose = j
|
||||
closureClose = k
|
||||
break
|
||||
} else {
|
||||
i++
|
||||
j++
|
||||
}
|
||||
}
|
||||
if closureClose > 0 {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func (s *codeSpanParser) Parse(parent ast.Node, block text.Reader, pc Context) a
|
|||
}
|
||||
closure := i - oldi
|
||||
if closure == opener && (i+1 >= len(line) || line[i+1] != '`') {
|
||||
segment := segment.WithStop(segment.Start + i - closure)
|
||||
segment = segment.WithStop(segment.Start + i - closure)
|
||||
if !segment.IsEmpty() {
|
||||
node.AppendChild(node, ast.NewRawTextSegment(segment))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ package parser
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/text"
|
||||
"github.com/yuin/goldmark/util"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var allowedBlockTags = map[string]bool{
|
||||
|
|
@ -97,12 +98,12 @@ var htmlBlockType7Regexp = regexp.MustCompile(`^[ ]{0,3}<(/)?([a-zA-Z0-9]+)(` +
|
|||
type htmlBlockParser struct {
|
||||
}
|
||||
|
||||
var defaultHtmlBlockParser = &htmlBlockParser{}
|
||||
var defaultHTMLBlockParser = &htmlBlockParser{}
|
||||
|
||||
// NewHTMLBlockParser return a new BlockParser that can parse html
|
||||
// blocks.
|
||||
func NewHTMLBlockParser() BlockParser {
|
||||
return defaultHtmlBlockParser
|
||||
return defaultHTMLBlockParser
|
||||
}
|
||||
|
||||
func (b *htmlBlockParser) Trigger() []byte {
|
||||
|
|
@ -133,7 +134,7 @@ func (b *htmlBlockParser) Open(parent ast.Node, reader text.Reader, pc Context)
|
|||
isCloseTag := match[2] > -1 && bytes.Equal(line[match[2]:match[3]], []byte("/"))
|
||||
hasAttr := match[6] != match[7]
|
||||
tagName = strings.ToLower(string(line[match[4]:match[5]]))
|
||||
_, ok := allowedBlockTags[strings.ToLower(string(tagName))]
|
||||
_, ok := allowedBlockTags[tagName]
|
||||
if ok {
|
||||
node = ast.NewHTMLBlock(ast.HTMLBlockType6)
|
||||
} else if tagName != "script" && tagName != "style" && tagName != "pre" && !ast.IsParagraph(last) && !(isCloseTag && hasAttr) { // type 7 can not interrupt paragraph
|
||||
|
|
|
|||
|
|
@ -903,7 +903,7 @@ retry:
|
|||
if w > 3 && !bp.CanAcceptIndentedLine() {
|
||||
continue
|
||||
}
|
||||
lastBlock := pc.LastOpenedBlock()
|
||||
lastBlock = pc.LastOpenedBlock()
|
||||
last := lastBlock.Node
|
||||
node, state := bp.Open(parent, reader, pc)
|
||||
if node != nil {
|
||||
|
|
@ -1177,5 +1177,4 @@ func (p *parser) parseBlock(block text.BlockReader, parent ast.Node, pc Context)
|
|||
for _, ip := range p.closeBlockers {
|
||||
ip.CloseBlock(parent, block, pc)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ type thematicBreakPraser struct {
|
|||
|
||||
var defaultThematicBreakPraser = &thematicBreakPraser{}
|
||||
|
||||
// NewThematicBreakPraser returns a new BlockParser that
|
||||
// NewThematicBreakParser returns a new BlockParser that
|
||||
// parses thematic breaks.
|
||||
func NewThematicBreakParser() BlockParser {
|
||||
return defaultThematicBreakPraser
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ package renderer
|
|||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/util"
|
||||
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A Config struct is a data structure that holds configuration of the Renderer.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ type TestingT interface {
|
|||
FailNow()
|
||||
}
|
||||
|
||||
// MarkdownTestCase represents a test case.
|
||||
type MarkdownTestCase struct {
|
||||
No int
|
||||
Markdown string
|
||||
|
|
@ -30,6 +31,7 @@ type MarkdownTestCase struct {
|
|||
const attributeSeparator = "//- - - - - - - - -//"
|
||||
const caseSeparator = "//= = = = = = = = = = = = = = = = = = = = = = = =//"
|
||||
|
||||
// DoTestCaseFile runs test cases in a given file.
|
||||
func DoTestCaseFile(m goldmark.Markdown, filename string, t TestingT) {
|
||||
fp, err := os.Open(filename)
|
||||
if err != nil {
|
||||
|
|
@ -86,12 +88,14 @@ func DoTestCaseFile(m goldmark.Markdown, filename string, t TestingT) {
|
|||
DoTestCases(m, cases, t)
|
||||
}
|
||||
|
||||
// DoTestCases runs a set of test cases.
|
||||
func DoTestCases(m goldmark.Markdown, cases []MarkdownTestCase, t TestingT) {
|
||||
for _, testCase := range cases {
|
||||
DoTestCase(m, testCase, t)
|
||||
}
|
||||
}
|
||||
|
||||
// DoTestCase runs a test case.
|
||||
func DoTestCase(m goldmark.Markdown, testCase MarkdownTestCase, t TestingT) {
|
||||
var ok bool
|
||||
var out bytes.Buffer
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package text
|
||||
|
||||
import (
|
||||
"github.com/yuin/goldmark/util"
|
||||
"io"
|
||||
"regexp"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/yuin/goldmark/util"
|
||||
)
|
||||
|
||||
const invalidValue = -1
|
||||
|
|
@ -138,7 +139,7 @@ func (r *reader) LineOffset() int {
|
|||
if r.source[i] == '\t' {
|
||||
v += util.TabWidth(v)
|
||||
} else {
|
||||
v += 1
|
||||
v++
|
||||
}
|
||||
}
|
||||
r.lineOffset = v - r.pos.Padding
|
||||
|
|
@ -355,7 +356,7 @@ func (r *blockReader) LineOffset() int {
|
|||
if r.source[i] == '\t' {
|
||||
v += util.TabWidth(v)
|
||||
} else {
|
||||
v += 1
|
||||
v++
|
||||
}
|
||||
}
|
||||
r.lineOffset = v - r.pos.Padding
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ func URLEscape(v []byte, resolveReference bool) []byte {
|
|||
cob.Write(v[n:i])
|
||||
stop := i + int(u8len)
|
||||
if stop > len(v) {
|
||||
i += 1
|
||||
i++
|
||||
n = i
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue