Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions markdown/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func (c *ConfluenceExtension) Extend(m goldmark.Markdown) {
util.Prioritized(crenderer.NewConfluenceImageRenderer(c.Stdlib, c, c.Path), 100),
util.Prioritized(crenderer.NewConfluenceParagraphRenderer(), 100),
util.Prioritized(crenderer.NewConfluenceLinkRenderer(), 100),
util.Prioritized(crenderer.NewConfluenceMathLatexRenderer(), 100),
))

if slices.Contains(c.MarkConfig.Features, "mkdocsadmonitions") {
Expand All @@ -74,6 +75,7 @@ func (c *ConfluenceExtension) Extend(m goldmark.Markdown) {
// Must be registered with a higher priority than goldmark's linkParser to make sure goldmark doesn't parse
// the <ac:*/> tags.
util.Prioritized(cparser.NewConfluenceTagParser(), 199),
util.Prioritized(cparser.NewMathLatexParser(), 200),
))
}

Expand Down
160 changes: 160 additions & 0 deletions parser/mathlatex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package parser

import (
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
)

type MathLatexInline struct {
ast.BaseInline

Equation []byte
}

func (n *MathLatexInline) Inline() {}

func (n *MathLatexInline) IsBlank(source []byte) bool {
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
text := c.(*ast.Text).Segment
if !util.IsBlank(text.Value(source)) {
return false
}
}
return true
}

func (n *MathLatexInline) Dump(source []byte, level int) {
ast.DumpHelper(n, source, level, nil, nil)
}

var KindMathLatexInline = ast.NewNodeKind("MathLatexInline")

func (n *MathLatexInline) Kind() ast.NodeKind {
return KindMathLatexInline
}

type MathLatexBlock struct {
ast.BaseInline

Equation []byte
}

func (n *MathLatexBlock) IsBlank(source []byte) bool {
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
text := c.(*ast.Text).Segment
if !util.IsBlank(text.Value(source)) {
return false
}
}
return true
}

func (n *MathLatexBlock) Dump(source []byte, level int) {
ast.DumpHelper(n, source, level, nil, nil)
}

var KindMathLatexBlock = ast.NewNodeKind("MathLatexBlock")

func (n *MathLatexBlock) Kind() ast.NodeKind {
return KindMathLatexBlock
}

type MathLatexParser struct {
}

func NewMathLatexParser() parser.InlineParser {
return &MathLatexParser{}
}

func (s *MathLatexParser) Trigger() []byte {
return []byte{'$'}
}

func (s *MathLatexParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node {
buf := block.Source()
ln, pos := block.Position()

lstart := pos.Start
lend := pos.Stop
line := buf[lstart:lend]

var start, end, advance int

trigger := line[0]

display := len(line) > 1 && line[1] == trigger

if display { // Display
start = lstart + 2

offset := 2

L:
for x := 0; x < 20; x++ {
for j := offset; j < len(line); j++ {
if len(line) > j+1 && line[j] == trigger && line[j+1] == trigger {
end = lstart + j
advance = 2
break L
}
}
if lend == len(buf) {
break
}
if end == 0 {
rest := buf[lend:]
j := 1
for j < len(rest) && rest[j] != '\n' {
j++
}
lstart = lend
lend += j
line = buf[lstart:lend]
ln++
offset = 0
}
}

} else { // Inline
start = lstart + 1

for i := 1; i < len(line); i++ {
c := line[i]
if c == '\\' {
i++
continue
}
if c == trigger {
end = lstart + i
advance = 1
break
}
}
if end >= len(buf) || buf[end] != trigger {
return nil
}
}

if start >= end {
return nil
}

newpos := end + advance
if newpos < lend {
block.SetPosition(ln, text.NewSegment(newpos, lend))
} else {
block.Advance(newpos)
}

if display {
return &MathLatexBlock{
Equation: buf[start:end],
}
} else {
return &MathLatexInline{
Equation: buf[start:end],
}
}
}
58 changes: 58 additions & 0 deletions renderer/mathlatex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package renderer

import (
"fmt"

"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/util"

cparser "github.com/kovetskiy/mark/parser"
)

type ConfluenceMathLatexRenderer struct {
html.Config
}

// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
func NewConfluenceMathLatexRenderer(opts ...html.Option) renderer.NodeRenderer {
return &ConfluenceMathLatexRenderer{
Config: html.NewConfig(),
}
}

// RegisterFuncs implements NodeRenderer.RegisterFuncs .
func (r *ConfluenceMathLatexRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(cparser.KindMathLatexInline, r.renderInline)
reg.Register(cparser.KindMathLatexBlock, r.renderBlock)
}

func (r *ConfluenceMathLatexRenderer) renderInline(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering {
node := n.(*cparser.MathLatexInline)
quoteType := "ppl mathjax inline macro"

w.WriteString(fmt.Sprintf("<ac:structured-macro ac:name=\"%s\">", quoteType))

Check failure on line 36 in renderer/mathlatex.go

View workflow job for this annotation

GitHub Actions / ci-go-lint

Error return value of `w.WriteString` is not checked (errcheck)
w.WriteString("<ac:parameter ac:name=\"equation\">")

Check failure on line 37 in renderer/mathlatex.go

View workflow job for this annotation

GitHub Actions / ci-go-lint

Error return value of `w.WriteString` is not checked (errcheck)
w.Write(node.Equation)

Check failure on line 38 in renderer/mathlatex.go

View workflow job for this annotation

GitHub Actions / ci-go-lint

Error return value of `w.Write` is not checked (errcheck)
w.WriteString("</ac:parameter>")

Check failure on line 39 in renderer/mathlatex.go

View workflow job for this annotation

GitHub Actions / ci-go-lint

Error return value of `w.WriteString` is not checked (errcheck)
w.WriteString("</ac:structured-macro>")
}
return ast.WalkContinue, nil
}

func (r *ConfluenceMathLatexRenderer) renderBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering {
node := n.(*cparser.MathLatexBlock)
quoteType := "ppl mathjax block macro"

w.WriteString(fmt.Sprintf("<ac:structured-macro ac:name=\"%s\">", quoteType))
w.WriteString("<ac:plain-text-body><![CDATA[")
w.Write(node.Equation)

Check failure on line 52 in renderer/mathlatex.go

View workflow job for this annotation

GitHub Actions / ci-go-lint

Error return value of `w.Write` is not checked (errcheck)
w.WriteString("]]></ac:plain-text-body>")
w.WriteString("</ac:structured-macro>")
}

return ast.WalkContinue, nil
}
Loading