Skip to content

Commit 7be636b

Browse files
committed
Fix alert blocks not following GitHub's behaviour with backslashes
Previously, these blocks would only get rendered if the markdown was `[!TYPE]`. Now they also render with `\[!TYPE\]`. Signed-off-by: Yarden Shoham <[email protected]>
1 parent 0f0db6a commit 7be636b

File tree

2 files changed

+69
-21
lines changed

2 files changed

+69
-21
lines changed

modules/markup/markdown/markdown_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,4 +1019,9 @@ func TestAttention(t *testing.T) {
10191019
test(`> [!important]`, renderAttention("important", "octicon-report")+"\n</blockquote>")
10201020
test(`> [!warning]`, renderAttention("warning", "octicon-alert")+"\n</blockquote>")
10211021
test(`> [!caution]`, renderAttention("caution", "octicon-stop")+"\n</blockquote>")
1022+
1023+
test(`
1024+
> \[!NOTE\]
1025+
> text
1026+
`, renderAttention("note", "octicon-info")+"\n<p>text</p>\n</blockquote>")
10221027
}

modules/markup/markdown/transform_blockquote.go

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package markdown
66
import (
77
"strings"
88

9+
"code.gitea.io/gitea/modules/markup/markdown/math"
910
"code.gitea.io/gitea/modules/svg"
1011

1112
"github.com/yuin/goldmark/ast"
@@ -37,41 +38,57 @@ func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast
3738
return ast.WalkContinue, nil
3839
}
3940

40-
func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) {
41-
// We only want attention blockquotes when the AST looks like:
42-
// > Text("[") Text("!TYPE") Text("]")
41+
func popAttentionTypeFromMathBlock(g *ASTTransformer, mathBlock *math.Block, reader text.Reader) string {
42+
line := mathBlock.Lines().At(0)
43+
innerText := line.Value(reader.Source())
4344

44-
// grab these nodes and make sure we adhere to the attention blockquote structure
45-
firstParagraph := v.FirstChild()
46-
g.applyElementDir(firstParagraph)
47-
if firstParagraph.ChildCount() < 3 {
48-
return ast.WalkContinue, nil
45+
// make sure it's a !TYPE
46+
if innerText[0] != '!' {
47+
return ""
48+
}
49+
attentionType := strings.ToLower(string(innerText[1:]))
50+
if !g.attentionTypes.Contains(attentionType) {
51+
return ""
52+
}
53+
return attentionType
54+
}
55+
56+
func popAttentionTypeFromParagraph(g *ASTTransformer, paragraph *ast.Paragraph, reader text.Reader) string {
57+
g.applyElementDir(paragraph)
58+
if paragraph.ChildCount() < 3 {
59+
return ""
4960
}
50-
node1, ok := firstParagraph.FirstChild().(*ast.Text)
61+
node1, ok := paragraph.FirstChild().(*ast.Text)
5162
if !ok {
52-
return ast.WalkContinue, nil
63+
return ""
5364
}
5465
node2, ok := node1.NextSibling().(*ast.Text)
5566
if !ok {
56-
return ast.WalkContinue, nil
67+
return ""
5768
}
5869
node3, ok := node2.NextSibling().(*ast.Text)
5970
if !ok {
60-
return ast.WalkContinue, nil
71+
return ""
6172
}
6273
val1 := string(node1.Segment.Value(reader.Source()))
6374
val2 := string(node2.Segment.Value(reader.Source()))
6475
val3 := string(node3.Segment.Value(reader.Source()))
6576
if val1 != "[" || val3 != "]" || !strings.HasPrefix(val2, "!") {
66-
return ast.WalkContinue, nil
77+
return ""
6778
}
6879

69-
// grab attention type from markdown source
7080
attentionType := strings.ToLower(val2[1:])
7181
if !g.attentionTypes.Contains(attentionType) {
72-
return ast.WalkContinue, nil
82+
return ""
7383
}
7484

85+
paragraph.RemoveChild(paragraph, node1)
86+
paragraph.RemoveChild(paragraph, node2)
87+
paragraph.RemoveChild(paragraph, node3)
88+
return attentionType
89+
}
90+
91+
func newAttentionParagraph(v *ast.Blockquote, attentionType string, g *ASTTransformer) *ast.Paragraph {
7592
// color the blockquote
7693
v.SetAttributeString("class", []byte("attention-header attention-"+attentionType))
7794

@@ -87,12 +104,38 @@ func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Read
87104
emphasis.AppendChild(emphasis, attentionAstString)
88105
attentionParagraph.AppendChild(attentionParagraph, NewAttention(attentionType))
89106
attentionParagraph.AppendChild(attentionParagraph, emphasis)
90-
firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph)
91-
firstParagraph.RemoveChild(firstParagraph, node1)
92-
firstParagraph.RemoveChild(firstParagraph, node2)
93-
firstParagraph.RemoveChild(firstParagraph, node3)
94-
if firstParagraph.ChildCount() == 0 {
95-
firstParagraph.Parent().RemoveChild(firstParagraph.Parent(), firstParagraph)
107+
return attentionParagraph
108+
}
109+
110+
func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) {
111+
// We only want attention blockquotes when the AST looks like:
112+
// > Text("[") Text("!TYPE") Text("]")
113+
//
114+
// or, in case of a math block: \[!TYPE\]
115+
116+
firstChild := v.FirstChild()
117+
var attentionType string
118+
119+
// grab attention type from markdown source
120+
if paragraph, ok := firstChild.(*ast.Paragraph); ok {
121+
attentionType = popAttentionTypeFromParagraph(g, paragraph, reader)
122+
} else {
123+
mathBlock, ok := firstChild.(*math.Block)
124+
if !ok {
125+
return ast.WalkContinue, nil
126+
}
127+
attentionType = popAttentionTypeFromMathBlock(g, mathBlock, reader)
128+
}
129+
130+
// it's possible this isn't an attention block
131+
if attentionType == "" {
132+
return ast.WalkContinue, nil
133+
}
134+
135+
attentionParagraph := newAttentionParagraph(v, attentionType, g)
136+
v.InsertBefore(v, firstChild, attentionParagraph)
137+
if firstChild.ChildCount() == 0 {
138+
v.RemoveChild(v, firstChild)
96139
}
97140
return ast.WalkContinue, nil
98141
}

0 commit comments

Comments
 (0)