mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	| @@ -68,7 +68,7 @@ func TestMathRender(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"$$a$$", | 			"$$a$$", | ||||||
| 			`<pre class="code-block is-loading"><code class="chroma language-math display">a</code></pre>` + nl, | 			`<code class="chroma language-math display">a</code>` + nl, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"$$a$$ test", | 			"$$a$$ test", | ||||||
| @@ -79,9 +79,13 @@ func TestMathRender(t *testing.T) { | |||||||
| 			`<p>test <code class="language-math display is-loading">a</code></p>` + nl, | 			`<p>test <code class="language-math display is-loading">a</code></p>` + nl, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"foo $x=\\$$ bar", | 			`foo $x=\$$ bar`, | ||||||
| 			`<p>foo <code class="language-math is-loading">x=\$</code> bar</p>` + nl, | 			`<p>foo <code class="language-math is-loading">x=\$</code> bar</p>` + nl, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			`$\text{$b$}$`, | ||||||
|  | 			`<p><code class="language-math is-loading">\text{$b$}</code></p>` + nl, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, test := range testcases { | 	for _, test := range testcases { | ||||||
| @@ -124,14 +128,36 @@ func TestMathRenderBlockIndent(t *testing.T) { | |||||||
| `, | `, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"indent-2", | 			"indent-2-mismatch", | ||||||
| 			` | 			` | ||||||
|   \[ |   \[ | ||||||
|   \alpha | a | ||||||
|  |  b | ||||||
|  |   c | ||||||
|  |    d | ||||||
|   \] |   \] | ||||||
| `, | `, | ||||||
| 			`<pre class="code-block is-loading"><code class="chroma language-math display"> | 			`<pre class="code-block is-loading"><code class="chroma language-math display"> | ||||||
| \alpha | a | ||||||
|  | b | ||||||
|  | c | ||||||
|  |  d | ||||||
|  | </code></pre> | ||||||
|  | `, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"indent-2", | ||||||
|  | 			` | ||||||
|  |   \[ | ||||||
|  |   a | ||||||
|  |    b | ||||||
|  |   c | ||||||
|  |   \] | ||||||
|  | `, | ||||||
|  | 			`<pre class="code-block is-loading"><code class="chroma language-math display"> | ||||||
|  | a | ||||||
|  |  b | ||||||
|  | c | ||||||
| </code></pre> | </code></pre> | ||||||
| `, | `, | ||||||
| 		}, | 		}, | ||||||
| @@ -139,7 +165,7 @@ func TestMathRenderBlockIndent(t *testing.T) { | |||||||
| 			"indent-0-oneline", | 			"indent-0-oneline", | ||||||
| 			`$$ x $$ | 			`$$ x $$ | ||||||
| foo`, | foo`, | ||||||
| 			`<pre class="code-block is-loading"><code class="chroma language-math display"> x </code></pre> | 			`<code class="chroma language-math display"> x </code> | ||||||
| <p>foo</p> | <p>foo</p> | ||||||
| `, | `, | ||||||
| 		}, | 		}, | ||||||
| @@ -147,8 +173,46 @@ foo`, | |||||||
| 			"indent-3-oneline", | 			"indent-3-oneline", | ||||||
| 			`   $$ x $$<SPACE> | 			`   $$ x $$<SPACE> | ||||||
| foo`, | foo`, | ||||||
| 			`<pre class="code-block is-loading"><code class="chroma language-math display"> x </code></pre> | 			`<code class="chroma language-math display"> x </code> | ||||||
| <p>foo</p> | <p>foo</p> | ||||||
|  | `, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"quote-block", | ||||||
|  | 			` | ||||||
|  | > \[ | ||||||
|  | > a | ||||||
|  | > \] | ||||||
|  | > \[ | ||||||
|  | > b | ||||||
|  | > \] | ||||||
|  | `, | ||||||
|  | 			`<blockquote> | ||||||
|  | <pre class="code-block is-loading"><code class="chroma language-math display"> | ||||||
|  | a | ||||||
|  | </code></pre> | ||||||
|  | <pre class="code-block is-loading"><code class="chroma language-math display"> | ||||||
|  | b | ||||||
|  | </code></pre> | ||||||
|  | </blockquote> | ||||||
|  | `, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"list-block", | ||||||
|  | 			` | ||||||
|  | 1. a | ||||||
|  |    \[ | ||||||
|  |    x | ||||||
|  |    \] | ||||||
|  | 2. b`, | ||||||
|  | 			`<ol> | ||||||
|  | <li>a | ||||||
|  | <pre class="code-block is-loading"><code class="chroma language-math display"> | ||||||
|  | x | ||||||
|  | </code></pre> | ||||||
|  | </li> | ||||||
|  | <li>b</li> | ||||||
|  | </ol> | ||||||
| `, | `, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ type Block struct { | |||||||
| 	Dollars bool | 	Dollars bool | ||||||
| 	Indent  int | 	Indent  int | ||||||
| 	Closed  bool | 	Closed  bool | ||||||
|  | 	Inline  bool | ||||||
| } | } | ||||||
|  |  | ||||||
| // KindBlock is the node kind for math blocks | // KindBlock is the node kind for math blocks | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ package math | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  |  | ||||||
|  | 	giteaUtil "code.gitea.io/gitea/modules/util" | ||||||
|  |  | ||||||
| 	"github.com/yuin/goldmark/ast" | 	"github.com/yuin/goldmark/ast" | ||||||
| 	"github.com/yuin/goldmark/parser" | 	"github.com/yuin/goldmark/parser" | ||||||
| 	"github.com/yuin/goldmark/text" | 	"github.com/yuin/goldmark/text" | ||||||
| @@ -13,13 +15,17 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type blockParser struct { | type blockParser struct { | ||||||
| 	parseDollars bool | 	parseDollars    bool | ||||||
|  | 	endBytesDollars []byte | ||||||
|  | 	endBytesBracket []byte | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewBlockParser creates a new math BlockParser | // NewBlockParser creates a new math BlockParser | ||||||
| func NewBlockParser(parseDollarBlocks bool) parser.BlockParser { | func NewBlockParser(parseDollarBlocks bool) parser.BlockParser { | ||||||
| 	return &blockParser{ | 	return &blockParser{ | ||||||
| 		parseDollars: parseDollarBlocks, | 		parseDollars:    parseDollarBlocks, | ||||||
|  | 		endBytesDollars: []byte{'$', '$'}, | ||||||
|  | 		endBytesBracket: []byte{'\\', ']'}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -47,10 +53,7 @@ func (b *blockParser) Open(parent ast.Node, reader text.Reader, pc parser.Contex | |||||||
| 	node := NewBlock(dollars, pos) | 	node := NewBlock(dollars, pos) | ||||||
|  |  | ||||||
| 	// Now we need to check if the ending block is on the segment... | 	// Now we need to check if the ending block is on the segment... | ||||||
| 	endBytes := []byte{'\\', ']'} | 	endBytes := giteaUtil.Iif(dollars, b.endBytesDollars, b.endBytesBracket) | ||||||
| 	if dollars { |  | ||||||
| 		endBytes = []byte{'$', '$'} |  | ||||||
| 	} |  | ||||||
| 	idx := bytes.Index(line[pos+2:], endBytes) | 	idx := bytes.Index(line[pos+2:], endBytes) | ||||||
| 	if idx >= 0 { | 	if idx >= 0 { | ||||||
| 		// for case $$ ... $$ any other text | 		// for case $$ ... $$ any other text | ||||||
| @@ -63,6 +66,7 @@ func (b *blockParser) Open(parent ast.Node, reader text.Reader, pc parser.Contex | |||||||
| 		segment.Stop = segment.Start + idx | 		segment.Stop = segment.Start + idx | ||||||
| 		node.Lines().Append(segment) | 		node.Lines().Append(segment) | ||||||
| 		node.Closed = true | 		node.Closed = true | ||||||
|  | 		node.Inline = true | ||||||
| 		return node, parser.Close | parser.NoChildren | 		return node, parser.Close | parser.NoChildren | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -79,27 +83,19 @@ func (b *blockParser) Continue(node ast.Node, reader text.Reader, pc parser.Cont | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	line, segment := reader.PeekLine() | 	line, segment := reader.PeekLine() | ||||||
| 	w, pos := util.IndentWidth(line, 0) | 	w, pos := util.IndentWidth(line, reader.LineOffset()) | ||||||
| 	if w < 4 { | 	if w < 4 { | ||||||
| 		if block.Dollars { | 		endBytes := giteaUtil.Iif(block.Dollars, b.endBytesDollars, b.endBytesBracket) | ||||||
| 			i := pos | 		if bytes.HasPrefix(line[pos:], endBytes) && util.IsBlank(line[pos+len(endBytes):]) { | ||||||
| 			for ; i < len(line) && line[i] == '$'; i++ { | 			if util.IsBlank(line[pos+len(endBytes):]) { | ||||||
| 			} | 				newline := giteaUtil.Iif(line[len(line)-1] != '\n', 0, 1) | ||||||
| 			length := i - pos | 				reader.Advance(segment.Stop - segment.Start - newline + segment.Padding) | ||||||
| 			if length >= 2 && util.IsBlank(line[i:]) { |  | ||||||
| 				reader.Advance(segment.Stop - segment.Start - segment.Padding) |  | ||||||
| 				block.Closed = true |  | ||||||
| 				return parser.Close | 				return parser.Close | ||||||
| 			} | 			} | ||||||
| 		} else if len(line[pos:]) > 1 && line[pos] == '\\' && line[pos+1] == ']' && util.IsBlank(line[pos+2:]) { |  | ||||||
| 			reader.Advance(segment.Stop - segment.Start - segment.Padding) |  | ||||||
| 			block.Closed = true |  | ||||||
| 			return parser.Close |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	start := segment.Start + giteaUtil.Iif(pos > block.Indent, block.Indent, pos) | ||||||
| 	pos, padding := util.IndentPosition(line, 0, block.Indent) | 	seg := text.NewSegmentPadding(start, segment.Stop, segment.Padding) | ||||||
| 	seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding) |  | ||||||
| 	node.Lines().Append(seg) | 	node.Lines().Append(seg) | ||||||
| 	return parser.Continue | parser.NoChildren | 	return parser.Continue | parser.NoChildren | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ package math | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"code.gitea.io/gitea/modules/markup/internal" | 	"code.gitea.io/gitea/modules/markup/internal" | ||||||
|  | 	giteaUtil "code.gitea.io/gitea/modules/util" | ||||||
|  |  | ||||||
| 	gast "github.com/yuin/goldmark/ast" | 	gast "github.com/yuin/goldmark/ast" | ||||||
| 	"github.com/yuin/goldmark/renderer" | 	"github.com/yuin/goldmark/renderer" | ||||||
| @@ -37,10 +38,11 @@ func (r *BlockRenderer) writeLines(w util.BufWriter, source []byte, n gast.Node) | |||||||
| func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { | func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { | ||||||
| 	n := node.(*Block) | 	n := node.(*Block) | ||||||
| 	if entering { | 	if entering { | ||||||
| 		_ = r.renderInternal.FormatWithSafeAttrs(w, `<pre class="code-block is-loading"><code class="chroma language-math display">`) | 		code := giteaUtil.Iif(n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="chroma language-math display">` | ||||||
|  | 		_ = r.renderInternal.FormatWithSafeAttrs(w, code) | ||||||
| 		r.writeLines(w, source, n) | 		r.writeLines(w, source, n) | ||||||
| 	} else { | 	} else { | ||||||
| 		_, _ = w.WriteString(`</code></pre>` + "\n") | 		_, _ = w.WriteString(`</code>` + giteaUtil.Iif(n.Inline, "", `</pre>`) + "\n") | ||||||
| 	} | 	} | ||||||
| 	return gast.WalkContinue, nil | 	return gast.WalkContinue, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -79,9 +79,10 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. | |||||||
| 	opener := len(parser.start) | 	opener := len(parser.start) | ||||||
|  |  | ||||||
| 	// Now look for an ending line | 	// Now look for an ending line | ||||||
|  | 	depth := 0 | ||||||
| 	ender := -1 | 	ender := -1 | ||||||
| 	for i := opener; i < len(line); i++ { | 	for i := opener; i < len(line); i++ { | ||||||
| 		if bytes.HasPrefix(line[i:], parser.end) { | 		if depth == 0 && bytes.HasPrefix(line[i:], parser.end) { | ||||||
| 			succeedingCharacter := byte(0) | 			succeedingCharacter := byte(0) | ||||||
| 			if i+len(parser.end) < len(line) { | 			if i+len(parser.end) < len(line) { | ||||||
| 				succeedingCharacter = line[i+len(parser.end)] | 				succeedingCharacter = line[i+len(parser.end)] | ||||||
| @@ -99,6 +100,11 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. | |||||||
| 			i++ | 			i++ | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  | 		if line[i] == '{' { | ||||||
|  | 			depth++ | ||||||
|  | 		} else if line[i] == '}' { | ||||||
|  | 			depth-- | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	if ender == -1 { | 	if ender == -1 { | ||||||
| 		return nil | 		return nil | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user