Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support indented math block #16

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
88 changes: 59 additions & 29 deletions block.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package mathjax

import (
"bytes"

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

type mathJaxBlockParser struct {
Expand All @@ -13,7 +14,8 @@ type mathJaxBlockParser struct {
var defaultMathJaxBlockParser = &mathJaxBlockParser{}

type mathBlockData struct {
indent int
indent int
isInline bool
}

var mathBlockInfoKey = parser.NewContextKey()
Expand All @@ -28,43 +30,71 @@ func (b *mathJaxBlockParser) Open(parent ast.Node, reader text.Reader, pc parser
if pos == -1 {
return nil, parser.NoChildren
}
if line[pos] != '$' {
return nil, parser.NoChildren
}
i := pos
for ; i < len(line) && line[i] == '$'; i++ {
}
if i-pos < 2 {
return nil, parser.NoChildren

// Check for multi-line math block
if len(line) >= pos+2 && line[pos] == '$' && line[pos+1] == '$' {
pc.Set(mathBlockInfoKey, &mathBlockData{indent: pos, isInline: false})
node := NewMathBlock()
return node, parser.NoChildren
}
pc.Set(mathBlockInfoKey, &mathBlockData{indent: pos})
node := NewMathBlock()
return node, parser.NoChildren

return nil, parser.NoChildren
}

func (b *mathJaxBlockParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
line, segment := reader.PeekLine()
data := pc.Get(mathBlockInfoKey).(*mathBlockData)
w, pos := util.IndentWidth(line, 0)
if w < 4 {
i := pos
for ; i < len(line) && line[i] == '$'; i++ {
}
length := i - pos
if length >= 2 && util.IsBlank(line[i:]) {
reader.Advance(segment.Stop - segment.Start - segment.Padding)
return parser.Close
dataInterface := pc.Get(mathBlockInfoKey)
if dataInterface == nil {
return parser.Close
}

_, ok := dataInterface.(*mathBlockData)
if !ok {
return parser.Close
}

// Check for closing $$
if bytes.HasPrefix(bytes.TrimSpace(line), []byte("$$")) {
if !bytes.Equal(bytes.TrimSpace(line), []byte("$$")) {
// If there's content after $$, we need to split it
parts := bytes.SplitN(bytes.TrimSpace(line), []byte("$$"), 2)
if len(parts) > 1 && len(parts[1]) > 0 {
// Add the content after $$ to a new paragraph
para := ast.NewParagraph()
para.AppendChild(para, ast.NewTextSegment(text.NewSegment(segment.Start+bytes.Index(line, parts[1]), segment.Stop)))
node.Parent().InsertAfter(node.Parent(), node, para)
}
}
reader.Advance(segment.Stop - segment.Start)
return parser.Close
}

pos, padding := util.DedentPosition(line, 0, data.indent)
seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding)
node.Lines().Append(seg)
reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
node.(*MathBlock).Lines().Append(segment)
return parser.Continue | parser.NoChildren
}

func (b *mathJaxBlockParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {
mathBlock, ok := node.(*MathBlock)
if !ok {
return
}

// Remove leading and trailing $$ from the content
if mathBlock.Lines().Len() > 0 {
firstLine := mathBlock.Lines().At(0)
lastLine := mathBlock.Lines().At(mathBlock.Lines().Len() - 1)

firstLineContent := reader.Value(firstLine)
lastLineContent := reader.Value(lastLine)

if bytes.HasPrefix(firstLineContent, []byte("$$")) {
mathBlock.Lines().Set(0, text.NewSegment(firstLine.Start+2, firstLine.Stop))
}
if bytes.HasSuffix(lastLineContent, []byte("$$")) {
mathBlock.Lines().Set(mathBlock.Lines().Len()-1, text.NewSegment(lastLine.Start, lastLine.Stop-2))
}
}

pc.Set(mathBlockInfoKey, nil)
}

Expand All @@ -73,9 +103,9 @@ func (b *mathJaxBlockParser) CanInterruptParagraph() bool {
}

func (b *mathJaxBlockParser) CanAcceptIndentedLine() bool {
return false
return true
}

func (b *mathJaxBlockParser) Trigger() []byte {
return nil
return []byte{'$'}
}