mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
3.2 KiB
98 lines
3.2 KiB
// Copyright 2024 The Gitea Authors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
|
|
package markdown |
|
|
|
import ( |
|
"strings" |
|
|
|
"code.gitea.io/gitea/modules/svg" |
|
|
|
"github.com/yuin/goldmark/ast" |
|
"github.com/yuin/goldmark/text" |
|
"github.com/yuin/goldmark/util" |
|
"golang.org/x/text/cases" |
|
"golang.org/x/text/language" |
|
) |
|
|
|
// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg |
|
func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { |
|
if entering { |
|
n := node.(*Attention) |
|
var octiconName string |
|
switch n.AttentionType { |
|
case "tip": |
|
octiconName = "light-bulb" |
|
case "important": |
|
octiconName = "report" |
|
case "warning": |
|
octiconName = "alert" |
|
case "caution": |
|
octiconName = "stop" |
|
default: // including "note" |
|
octiconName = "info" |
|
} |
|
_, _ = w.WriteString(string(svg.RenderHTML("octicon-"+octiconName, 16, "attention-icon attention-"+n.AttentionType))) |
|
} |
|
return ast.WalkContinue, nil |
|
} |
|
|
|
func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) { |
|
// We only want attention blockquotes when the AST looks like: |
|
// > Text("[") Text("!TYPE") Text("]") |
|
|
|
// grab these nodes and make sure we adhere to the attention blockquote structure |
|
firstParagraph := v.FirstChild() |
|
g.applyElementDir(firstParagraph) |
|
if firstParagraph.ChildCount() < 3 { |
|
return ast.WalkContinue, nil |
|
} |
|
node1, ok := firstParagraph.FirstChild().(*ast.Text) |
|
if !ok { |
|
return ast.WalkContinue, nil |
|
} |
|
node2, ok := node1.NextSibling().(*ast.Text) |
|
if !ok { |
|
return ast.WalkContinue, nil |
|
} |
|
node3, ok := node2.NextSibling().(*ast.Text) |
|
if !ok { |
|
return ast.WalkContinue, nil |
|
} |
|
val1 := string(node1.Segment.Value(reader.Source())) |
|
val2 := string(node2.Segment.Value(reader.Source())) |
|
val3 := string(node3.Segment.Value(reader.Source())) |
|
if val1 != "[" || val3 != "]" || !strings.HasPrefix(val2, "!") { |
|
return ast.WalkContinue, nil |
|
} |
|
|
|
// grab attention type from markdown source |
|
attentionType := strings.ToLower(val2[1:]) |
|
if !g.attentionTypes.Contains(attentionType) { |
|
return ast.WalkContinue, nil |
|
} |
|
|
|
// color the blockquote |
|
v.SetAttributeString("class", []byte("attention-header attention-"+attentionType)) |
|
|
|
// create an emphasis to make it bold |
|
attentionParagraph := ast.NewParagraph() |
|
g.applyElementDir(attentionParagraph) |
|
emphasis := ast.NewEmphasis(2) |
|
emphasis.SetAttributeString("class", []byte("attention-"+attentionType)) |
|
|
|
attentionAstString := ast.NewString([]byte(cases.Title(language.English).String(attentionType))) |
|
|
|
// replace the ![TYPE] with a dedicated paragraph of icon+Type |
|
emphasis.AppendChild(emphasis, attentionAstString) |
|
attentionParagraph.AppendChild(attentionParagraph, NewAttention(attentionType)) |
|
attentionParagraph.AppendChild(attentionParagraph, emphasis) |
|
firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph) |
|
firstParagraph.RemoveChild(firstParagraph, node1) |
|
firstParagraph.RemoveChild(firstParagraph, node2) |
|
firstParagraph.RemoveChild(firstParagraph, node3) |
|
if firstParagraph.ChildCount() == 0 { |
|
firstParagraph.Parent().RemoveChild(firstParagraph.Parent(), firstParagraph) |
|
} |
|
return ast.WalkContinue, nil |
|
}
|
|
|