diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2024-12-06 20:00:24 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-06 20:00:24 +0800 |
commit | 3c4a06273f776df340459c3775d90eb8d20b71e5 (patch) | |
tree | 47dd440047c7171567afb051c22e697a67e89d42 /modules/markup/markdown | |
parent | b32f0cdfa05c3a0e34425e1b8a5dfa8b63914a01 (diff) | |
download | gitea-3c4a06273f776df340459c3775d90eb8d20b71e5.tar.gz gitea-3c4a06273f776df340459c3775d90eb8d20b71e5.zip |
Refactor markdown render (#32736)
and add some tests
Diffstat (limited to 'modules/markup/markdown')
-rw-r--r-- | modules/markup/markdown/markdown_math_test.go | 76 | ||||
-rw-r--r-- | modules/markup/markdown/math/block_node.go | 1 | ||||
-rw-r--r-- | modules/markup/markdown/math/block_parser.go | 40 | ||||
-rw-r--r-- | modules/markup/markdown/math/block_renderer.go | 6 | ||||
-rw-r--r-- | modules/markup/markdown/math/inline_parser.go | 8 |
5 files changed, 100 insertions, 31 deletions
diff --git a/modules/markup/markdown/markdown_math_test.go b/modules/markup/markdown/markdown_math_test.go index 0e5adeeac8..e371b1c74a 100644 --- a/modules/markup/markdown/markdown_math_test.go +++ b/modules/markup/markdown/markdown_math_test.go @@ -68,7 +68,7 @@ func TestMathRender(t *testing.T) { }, { "$$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", @@ -79,9 +79,13 @@ func TestMathRender(t *testing.T) { `<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, }, + { + `$\text{$b$}$`, + `<p><code class="language-math is-loading">\text{$b$}</code></p>` + nl, + }, } for _, test := range testcases { @@ -124,14 +128,36 @@ func TestMathRenderBlockIndent(t *testing.T) { `, }, { + "indent-2-mismatch", + ` + \[ +a + b + c + d + \] +`, + `<pre class="code-block is-loading"><code class="chroma language-math display"> +a +b +c + d +</code></pre> +`, + }, + { "indent-2", ` \[ - \alpha + a + b + c \] `, `<pre class="code-block is-loading"><code class="chroma language-math display"> -\alpha +a + b +c </code></pre> `, }, @@ -139,7 +165,7 @@ func TestMathRenderBlockIndent(t *testing.T) { "indent-0-oneline", `$$ x $$ 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> `, }, @@ -147,10 +173,48 @@ foo`, "indent-3-oneline", ` $$ x $$<SPACE> 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> `, }, + { + "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> +`, + }, } for _, test := range testcases { diff --git a/modules/markup/markdown/math/block_node.go b/modules/markup/markdown/math/block_node.go index 10d17ff8d3..d2293133cd 100644 --- a/modules/markup/markdown/math/block_node.go +++ b/modules/markup/markdown/math/block_node.go @@ -11,6 +11,7 @@ type Block struct { Dollars bool Indent int Closed bool + Inline bool } // KindBlock is the node kind for math blocks diff --git a/modules/markup/markdown/math/block_parser.go b/modules/markup/markdown/math/block_parser.go index f31cfb09ad..3f37ce8333 100644 --- a/modules/markup/markdown/math/block_parser.go +++ b/modules/markup/markdown/math/block_parser.go @@ -6,6 +6,8 @@ package math import ( "bytes" + giteaUtil "code.gitea.io/gitea/modules/util" + "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/text" @@ -13,13 +15,17 @@ import ( ) type blockParser struct { - parseDollars bool + parseDollars bool + endBytesDollars []byte + endBytesBracket []byte } // NewBlockParser creates a new math BlockParser func NewBlockParser(parseDollarBlocks bool) parser.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) // Now we need to check if the ending block is on the segment... - endBytes := []byte{'\\', ']'} - if dollars { - endBytes = []byte{'$', '$'} - } + endBytes := giteaUtil.Iif(dollars, b.endBytesDollars, b.endBytesBracket) idx := bytes.Index(line[pos+2:], endBytes) if idx >= 0 { // 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 node.Lines().Append(segment) node.Closed = true + node.Inline = true 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() - w, pos := util.IndentWidth(line, 0) + w, pos := util.IndentWidth(line, reader.LineOffset()) if w < 4 { - if block.Dollars { - 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) - block.Closed = true + endBytes := giteaUtil.Iif(block.Dollars, b.endBytesDollars, b.endBytesBracket) + if bytes.HasPrefix(line[pos:], endBytes) && util.IsBlank(line[pos+len(endBytes):]) { + if util.IsBlank(line[pos+len(endBytes):]) { + newline := giteaUtil.Iif(line[len(line)-1] != '\n', 0, 1) + reader.Advance(segment.Stop - segment.Start - newline + segment.Padding) 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 } } - - pos, padding := util.IndentPosition(line, 0, block.Indent) - seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding) + start := segment.Start + giteaUtil.Iif(pos > block.Indent, block.Indent, pos) + seg := text.NewSegmentPadding(start, segment.Stop, segment.Padding) node.Lines().Append(seg) return parser.Continue | parser.NoChildren } diff --git a/modules/markup/markdown/math/block_renderer.go b/modules/markup/markdown/math/block_renderer.go index 0d2a966102..a770efa01c 100644 --- a/modules/markup/markdown/math/block_renderer.go +++ b/modules/markup/markdown/math/block_renderer.go @@ -5,6 +5,7 @@ package math import ( "code.gitea.io/gitea/modules/markup/internal" + giteaUtil "code.gitea.io/gitea/modules/util" gast "github.com/yuin/goldmark/ast" "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) { n := node.(*Block) 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) } else { - _, _ = w.WriteString(`</code></pre>` + "\n") + _, _ = w.WriteString(`</code>` + giteaUtil.Iif(n.Inline, "", `</pre>`) + "\n") } return gast.WalkContinue, nil } diff --git a/modules/markup/markdown/math/inline_parser.go b/modules/markup/markdown/math/inline_parser.go index 56ae3d57eb..191d1e5a31 100644 --- a/modules/markup/markdown/math/inline_parser.go +++ b/modules/markup/markdown/math/inline_parser.go @@ -79,9 +79,10 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. opener := len(parser.start) // Now look for an ending line + depth := 0 ender := -1 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) if i+len(parser.end) < len(line) { succeedingCharacter = line[i+len(parser.end)] @@ -99,6 +100,11 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. i++ continue } + if line[i] == '{' { + depth++ + } else if line[i] == '}' { + depth-- + } } if ender == -1 { return nil |