@@ -53,7 +53,6 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
5353 }
5454 }
5555
56- attentionMarkedBlockquotes := make (container.Set [* ast.Blockquote ])
5756 _ = ast .Walk (node , func (n ast.Node , entering bool ) (ast.WalkStatus , error ) {
5857 if ! entering {
5958 return ast .WalkContinue , nil
@@ -197,18 +196,55 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
197196 if css .ColorHandler (strings .ToLower (string (colorContent ))) {
198197 v .AppendChild (v , NewColorPreview (colorContent ))
199198 }
200- case * ast.Emphasis :
201- // check if inside blockquote for attention, expected hierarchy is
202- // Emphasis < Paragraph < Blockquote
203- blockquote , isInBlockquote := n .Parent ().Parent ().(* ast.Blockquote )
204- if isInBlockquote && ! attentionMarkedBlockquotes .Contains (blockquote ) {
205- fullText := string (n .Text (reader .Source ()))
206- if fullText == AttentionNote || fullText == AttentionWarning {
207- v .SetAttributeString ("class" , []byte ("attention-" + strings .ToLower (fullText )))
208- v .Parent ().InsertBefore (v .Parent (), v , NewAttention (fullText ))
209- attentionMarkedBlockquotes .Add (blockquote )
210- }
199+ case * ast.Blockquote :
200+ // We only want attention blockquotes when the AST looks like:
201+ // Text: "["
202+ // Text: "!TYPE"
203+ // Text(SoftLineBreak): "]"
204+
205+ // grab these nodes and make sure we adhere to the attention blockquote structure
206+ firstParagraph := v .FirstChild ()
207+ if firstParagraph .ChildCount () < 3 {
208+ return ast .WalkContinue , nil
209+ }
210+ firstTextNode , ok := firstParagraph .FirstChild ().(* ast.Text )
211+ if ! ok || string (firstTextNode .Segment .Value (reader .Source ())) != "[" {
212+ return ast .WalkContinue , nil
213+ }
214+ secondTextNode , ok := firstTextNode .NextSibling ().(* ast.Text )
215+ if ! ok || ! attentionTypeRE .MatchString (string (secondTextNode .Segment .Value (reader .Source ()))) {
216+ return ast .WalkContinue , nil
211217 }
218+ thirdTextNode , ok := secondTextNode .NextSibling ().(* ast.Text )
219+ if ! ok || string (thirdTextNode .Segment .Value (reader .Source ())) != "]" {
220+ return ast .WalkContinue , nil
221+ }
222+
223+ // grab attention type from markdown source
224+ attentionType := strings .ToLower (strings .TrimPrefix (string (secondTextNode .Segment .Value (reader .Source ())), "!" ))
225+
226+ // color the blockquote
227+ v .SetAttributeString ("class" , []byte ("gt-py-3 attention attention-" + attentionType ))
228+
229+ // create an emphasis to make it bold
230+ emphasis := ast .NewEmphasis (2 )
231+ emphasis .SetAttributeString ("class" , []byte ("attention-" + attentionType ))
232+ firstParagraph .InsertBefore (firstParagraph , firstTextNode , emphasis )
233+
234+ // capitalize first letter
235+ attentionText := ast .NewString ([]byte (strings .ToUpper (string (attentionType [0 ])) + attentionType [1 :]))
236+
237+ // replace the ![TYPE] with icon+Type
238+ emphasis .AppendChild (emphasis , attentionText )
239+ for i := 0 ; i < 2 ; i ++ {
240+ lineBreak := ast .NewText ()
241+ lineBreak .SetSoftLineBreak (true )
242+ firstParagraph .InsertAfter (firstParagraph , emphasis , lineBreak )
243+ }
244+ firstParagraph .InsertBefore (firstParagraph , emphasis , NewAttention (attentionType ))
245+ firstParagraph .RemoveChild (firstParagraph , firstTextNode )
246+ firstParagraph .RemoveChild (firstParagraph , secondTextNode )
247+ firstParagraph .RemoveChild (firstParagraph , thirdTextNode )
212248 }
213249 return ast .WalkContinue , nil
214250 })
@@ -339,17 +375,23 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod
339375// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg
340376func (r * HTMLRenderer ) renderAttention (w util.BufWriter , source []byte , node ast.Node , entering bool ) (ast.WalkStatus , error ) {
341377 if entering {
342- _ , _ = w .WriteString (`<span class="attention-icon attention-` )
378+ _ , _ = w .WriteString (`<span class="gt-mr-2 gt-vm attention-` )
343379 n := node .(* Attention )
344380 _ , _ = w .WriteString (strings .ToLower (n .AttentionType ))
345381 _ , _ = w .WriteString (`">` )
346382
347383 var octiconType string
348384 switch n .AttentionType {
349- case AttentionNote :
385+ case "note" :
350386 octiconType = "info"
351- case AttentionWarning :
387+ case "tip" :
388+ octiconType = "light-bulb"
389+ case "important" :
390+ octiconType = "report"
391+ case "warning" :
352392 octiconType = "alert"
393+ case "caution" :
394+ octiconType = "stop"
353395 }
354396 _ , _ = w .WriteString (string (svg .RenderHTML ("octicon-" + octiconType )))
355397 } else {
@@ -417,7 +459,10 @@ func (r *HTMLRenderer) renderSummary(w util.BufWriter, source []byte, node ast.N
417459 return ast .WalkContinue , nil
418460}
419461
420- var validNameRE = regexp .MustCompile ("^[a-z ]+$" )
462+ var (
463+ validNameRE = regexp .MustCompile ("^[a-z ]+$" )
464+ attentionTypeRE = regexp .MustCompile ("^!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)$" )
465+ )
421466
422467func (r * HTMLRenderer ) renderIcon (w util.BufWriter , source []byte , node ast.Node , entering bool ) (ast.WalkStatus , error ) {
423468 if ! entering {
0 commit comments