333211d4d0
Signed-off-by: Tobias Erbshäußer <tobias@tesoft.dev>
110 lines
2.2 KiB
Go
110 lines
2.2 KiB
Go
package md
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/yuin/goldmark"
|
|
"github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/parser"
|
|
"github.com/yuin/goldmark/text"
|
|
"github.com/yuin/goldmark/util"
|
|
)
|
|
|
|
var propertiesContextKey = parser.NewContextKey()
|
|
|
|
type propertiesData struct {
|
|
properties map[string]string
|
|
Error error
|
|
}
|
|
|
|
type propertiesExtension struct {
|
|
}
|
|
|
|
func (e *propertiesExtension) Extend(m goldmark.Markdown) {
|
|
m.Parser().AddOptions(
|
|
parser.WithBlockParsers(
|
|
util.Prioritized(&propertiesParser{}, 0),
|
|
),
|
|
)
|
|
}
|
|
|
|
type propertiesParser struct {
|
|
}
|
|
|
|
func (p *propertiesParser) Trigger() []byte {
|
|
return []byte{'-'}
|
|
}
|
|
|
|
func (p *propertiesParser) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) {
|
|
lineNumber, _ := reader.Position()
|
|
if lineNumber != 0 {
|
|
return nil, parser.NoChildren
|
|
}
|
|
|
|
line, _ := reader.PeekLine()
|
|
if isSeparator(line) {
|
|
return ast.NewTextBlock(), parser.NoChildren
|
|
}
|
|
|
|
return nil, parser.NoChildren
|
|
}
|
|
|
|
func (p *propertiesParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
|
|
line, segment := reader.PeekLine()
|
|
if isSeparator(line) && !util.IsBlank(line) {
|
|
reader.Advance(segment.Len())
|
|
return parser.Close
|
|
}
|
|
|
|
node.Lines().Append(segment)
|
|
return parser.Continue | parser.NoChildren
|
|
}
|
|
|
|
func (p *propertiesParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {
|
|
lines := node.Lines()
|
|
|
|
data := &propertiesData{
|
|
make(map[string]string),
|
|
nil,
|
|
}
|
|
pc.Set(propertiesContextKey, data)
|
|
|
|
for i := 0; i < lines.Len(); i++ {
|
|
segment := lines.At(i)
|
|
line := string(segment.Value(reader.Source()))
|
|
|
|
index := strings.IndexRune(line, ':')
|
|
if index == -1 {
|
|
data.Error = errors.New("invalid property line")
|
|
break
|
|
}
|
|
|
|
key := strings.TrimSpace(line[:index])
|
|
value := strings.TrimSpace(line[index+1:])
|
|
data.properties[key] = value
|
|
}
|
|
|
|
node.Parent().RemoveChild(node.Parent(), node)
|
|
}
|
|
|
|
func (p *propertiesParser) CanInterruptParagraph() bool {
|
|
return false
|
|
}
|
|
|
|
func (p *propertiesParser) CanAcceptIndentedLine() bool {
|
|
return false
|
|
}
|
|
|
|
func isSeparator(line []byte) bool {
|
|
line = util.TrimRightSpace(util.TrimLeftSpace(line))
|
|
|
|
for i := 0; i < len(line); i++ {
|
|
if line[i] != '-' {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|