mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
commit
7950956e28
7 changed files with 96 additions and 96 deletions
|
|
@ -428,7 +428,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 algorighm.
|
// Walk walks a AST tree by the depth first search algorithm.
|
||||||
func Walk(n Node, walker Walker) error {
|
func Walk(n Node, walker Walker) error {
|
||||||
status, err := walker(n, true)
|
status, err := walker(n, true)
|
||||||
if err != nil || status == WalkStop {
|
if err != nil || status == WalkStop {
|
||||||
|
|
|
||||||
36
ast/block.go
36
ast/block.go
|
|
@ -54,7 +54,7 @@ type Document struct {
|
||||||
// KindDocument is a NodeKind of the Document node.
|
// KindDocument is a NodeKind of the Document node.
|
||||||
var KindDocument = NewNodeKind("Document")
|
var KindDocument = NewNodeKind("Document")
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *Document) Dump(source []byte, level int) {
|
func (n *Document) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ type TextBlock struct {
|
||||||
BaseBlock
|
BaseBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *TextBlock) Dump(source []byte, level int) {
|
func (n *TextBlock) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ type Paragraph struct {
|
||||||
BaseBlock
|
BaseBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *Paragraph) Dump(source []byte, level int) {
|
func (n *Paragraph) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +142,7 @@ type Heading struct {
|
||||||
Level int
|
Level int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *Heading) Dump(source []byte, level int) {
|
func (n *Heading) Dump(source []byte, level int) {
|
||||||
m := map[string]string{
|
m := map[string]string{
|
||||||
"Level": fmt.Sprintf("%d", n.Level),
|
"Level": fmt.Sprintf("%d", n.Level),
|
||||||
|
|
@ -166,27 +166,27 @@ func NewHeading(level int) *Heading {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ThemanticBreak struct represents a themantic break of Markdown text.
|
// A ThematicBreak struct represents a thematic break of Markdown text.
|
||||||
type ThemanticBreak struct {
|
type ThematicBreak struct {
|
||||||
BaseBlock
|
BaseBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *ThemanticBreak) Dump(source []byte, level int) {
|
func (n *ThematicBreak) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KindThemanticBreak is a NodeKind of the ThemanticBreak node.
|
// KindThematicBreak is a NodeKind of the ThematicBreak node.
|
||||||
var KindThemanticBreak = NewNodeKind("ThemanticBreak")
|
var KindThematicBreak = NewNodeKind("ThematicBreak")
|
||||||
|
|
||||||
// Kind implements Node.Kind.
|
// Kind implements Node.Kind.
|
||||||
func (n *ThemanticBreak) Kind() NodeKind {
|
func (n *ThematicBreak) Kind() NodeKind {
|
||||||
return KindThemanticBreak
|
return KindThematicBreak
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewThemanticBreak returns a new ThemanticBreak node.
|
// NewThematicBreak returns a new ThematicBreak node.
|
||||||
func NewThemanticBreak() *ThemanticBreak {
|
func NewThematicBreak() *ThematicBreak {
|
||||||
return &ThemanticBreak{
|
return &ThematicBreak{
|
||||||
BaseBlock: BaseBlock{},
|
BaseBlock: BaseBlock{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +201,7 @@ func (n *CodeBlock) IsRaw() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *CodeBlock) Dump(source []byte, level int) {
|
func (n *CodeBlock) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +252,7 @@ func (n *FencedCodeBlock) IsRaw() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *FencedCodeBlock) Dump(source []byte, level int) {
|
func (n *FencedCodeBlock) Dump(source []byte, level int) {
|
||||||
m := map[string]string{}
|
m := map[string]string{}
|
||||||
if n.Info != nil {
|
if n.Info != nil {
|
||||||
|
|
@ -282,7 +282,7 @@ type Blockquote struct {
|
||||||
BaseBlock
|
BaseBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump impelements Node.Dump .
|
// Dump implements Node.Dump .
|
||||||
func (n *Blockquote) Dump(source []byte, level int) {
|
func (n *Blockquote) Dump(source []byte, level int) {
|
||||||
DumpHelper(n, source, level, nil, nil)
|
DumpHelper(n, source, level, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,8 +162,8 @@ func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) Sta
|
||||||
}
|
}
|
||||||
return Continue | HasChildren
|
return Continue | HasChildren
|
||||||
}
|
}
|
||||||
// Themantic Breaks take precedence over lists
|
// Thematic Breaks take precedence over lists
|
||||||
if isThemanticBreak(line) {
|
if isThematicBreak(line) {
|
||||||
isHeading := false
|
isHeading := false
|
||||||
last := pc.LastOpenedBlock().Node
|
last := pc.LastOpenedBlock().Node
|
||||||
if ast.IsParagraph(last) {
|
if ast.IsParagraph(last) {
|
||||||
|
|
|
||||||
|
|
@ -520,7 +520,7 @@ type ASTTransformer interface {
|
||||||
// Priorities of default BlockParsers are:
|
// Priorities of default BlockParsers are:
|
||||||
//
|
//
|
||||||
// SetextHeadingParser, 100
|
// SetextHeadingParser, 100
|
||||||
// ThemanticBreakParser, 200
|
// ThematicBreakParser, 200
|
||||||
// ListParser, 300
|
// ListParser, 300
|
||||||
// ListItemParser, 400
|
// ListItemParser, 400
|
||||||
// CodeBlockParser, 500
|
// CodeBlockParser, 500
|
||||||
|
|
@ -532,7 +532,7 @@ type ASTTransformer interface {
|
||||||
func DefaultBlockParsers() []util.PrioritizedValue {
|
func DefaultBlockParsers() []util.PrioritizedValue {
|
||||||
return []util.PrioritizedValue{
|
return []util.PrioritizedValue{
|
||||||
util.Prioritized(NewSetextHeadingParser(), 100),
|
util.Prioritized(NewSetextHeadingParser(), 100),
|
||||||
util.Prioritized(NewThemanticBreakParser(), 200),
|
util.Prioritized(NewThematicBreakParser(), 200),
|
||||||
util.Prioritized(NewListParser(), 300),
|
util.Prioritized(NewListParser(), 300),
|
||||||
util.Prioritized(NewListItemParser(), 400),
|
util.Prioritized(NewListItemParser(), 400),
|
||||||
util.Prioritized(NewCodeBlockParser(), 500),
|
util.Prioritized(NewCodeBlockParser(), 500),
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/yuin/goldmark/ast"
|
|
||||||
"github.com/yuin/goldmark/text"
|
|
||||||
"github.com/yuin/goldmark/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
type themanticBreakParser struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultThemanticBreakParser = &themanticBreakParser{}
|
|
||||||
|
|
||||||
// NewThemanticBreakParser returns a new BlockParser that
|
|
||||||
// parses themantic breaks.
|
|
||||||
func NewThemanticBreakParser() BlockParser {
|
|
||||||
return defaultThemanticBreakParser
|
|
||||||
}
|
|
||||||
|
|
||||||
func isThemanticBreak(line []byte) bool {
|
|
||||||
w, pos := util.IndentWidth(line, 0)
|
|
||||||
if w > 3 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
mark := byte(0)
|
|
||||||
count := 0
|
|
||||||
for i := pos; i < len(line); i++ {
|
|
||||||
c := line[i]
|
|
||||||
if util.IsSpace(c) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if mark == 0 {
|
|
||||||
mark = c
|
|
||||||
count = 1
|
|
||||||
if mark == '*' || mark == '-' || mark == '_' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if c != mark {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
return count > 2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *themanticBreakParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
|
|
||||||
line, segment := reader.PeekLine()
|
|
||||||
if isThemanticBreak(line) {
|
|
||||||
reader.Advance(segment.Len() - 1)
|
|
||||||
return ast.NewThemanticBreak(), NoChildren
|
|
||||||
}
|
|
||||||
return nil, NoChildren
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *themanticBreakParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
|
|
||||||
return Close
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *themanticBreakParser) Close(node ast.Node, reader text.Reader, pc Context) {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *themanticBreakParser) CanInterruptParagraph() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *themanticBreakParser) CanAcceptIndentedLine() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
71
parser/thematic_break.go
Normal file
71
parser/thematic_break.go
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/yuin/goldmark/ast"
|
||||||
|
"github.com/yuin/goldmark/text"
|
||||||
|
"github.com/yuin/goldmark/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ThematicBreakParser struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultThematicBreakParser = &ThematicBreakParser{}
|
||||||
|
|
||||||
|
// NewThematicBreakParser returns a new BlockParser that
|
||||||
|
// parses thematic breaks.
|
||||||
|
func NewThematicBreakParser() BlockParser {
|
||||||
|
return defaultThematicBreakParser
|
||||||
|
}
|
||||||
|
|
||||||
|
func isThematicBreak(line []byte) bool {
|
||||||
|
w, pos := util.IndentWidth(line, 0)
|
||||||
|
if w > 3 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mark := byte(0)
|
||||||
|
count := 0
|
||||||
|
for i := pos; i < len(line); i++ {
|
||||||
|
c := line[i]
|
||||||
|
if util.IsSpace(c) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if mark == 0 {
|
||||||
|
mark = c
|
||||||
|
count = 1
|
||||||
|
if mark == '*' || mark == '-' || mark == '_' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c != mark {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return count > 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ThematicBreakParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
|
||||||
|
line, segment := reader.PeekLine()
|
||||||
|
if isThematicBreak(line) {
|
||||||
|
reader.Advance(segment.Len() - 1)
|
||||||
|
return ast.NewThematicBreak(), NoChildren
|
||||||
|
}
|
||||||
|
return nil, NoChildren
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ThematicBreakParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
|
||||||
|
return Close
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ThematicBreakParser) Close(node ast.Node, reader text.Reader, pc Context) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ThematicBreakParser) CanInterruptParagraph() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ThematicBreakParser) CanAcceptIndentedLine() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
@ -172,7 +172,7 @@ func (r *Renderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||||
reg.Register(ast.KindListItem, r.renderListItem)
|
reg.Register(ast.KindListItem, r.renderListItem)
|
||||||
reg.Register(ast.KindParagraph, r.renderParagraph)
|
reg.Register(ast.KindParagraph, r.renderParagraph)
|
||||||
reg.Register(ast.KindTextBlock, r.renderTextBlock)
|
reg.Register(ast.KindTextBlock, r.renderTextBlock)
|
||||||
reg.Register(ast.KindThemanticBreak, r.renderThemanticBreak)
|
reg.Register(ast.KindThematicBreak, r.renderThematicBreak)
|
||||||
|
|
||||||
// inlines
|
// inlines
|
||||||
|
|
||||||
|
|
@ -333,7 +333,7 @@ func (r *Renderer) renderTextBlock(w util.BufWriter, source []byte, n ast.Node,
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) renderThemanticBreak(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
|
func (r *Renderer) renderThematicBreak(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
if !entering {
|
if !entering {
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue