@@ -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,62 @@ 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
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 {
212+ return ast .WalkContinue , nil
213+ }
214+ secondTextNode , ok := firstTextNode .NextSibling ().(* ast.Text )
215+ if ! ok {
216+ return ast .WalkContinue , nil
217+ }
218+ thirdTextNode , ok := secondTextNode .NextSibling ().(* ast.Text )
219+ if ! ok {
220+ return ast .WalkContinue , nil
211221 }
222+
223+ // make sure we adhere to the attention blockquote structure
224+ if string (firstTextNode .Segment .Value (reader .Source ())) != "[" ||
225+ ! attentionTypeRE .MatchString (string (secondTextNode .Segment .Value (reader .Source ()))) ||
226+ string (thirdTextNode .Segment .Value (reader .Source ())) != "]" {
227+ return ast .WalkContinue , nil
228+ }
229+
230+ // grab attention type from markdown source
231+ attentionType := strings .ToLower (strings .TrimPrefix (string (secondTextNode .Segment .Value (reader .Source ())), "!" ))
232+
233+ // color the blockquote
234+ v .SetAttributeString ("class" , []byte ("gt-py-3 attention attention-" + attentionType ))
235+
236+ // create an emphasis to make it bold
237+ emphasis := ast .NewEmphasis (2 )
238+ emphasis .SetAttributeString ("class" , []byte ("gt-font-bold attention-" + attentionType ))
239+ firstParagraph .InsertBefore (firstParagraph , firstTextNode , emphasis )
240+
241+ // capitalize first letter
242+ attentionText := ast .NewString ([]byte (strings .ToUpper (string (attentionType [0 ])) + string (attentionType [1 :])))
243+
244+ // replace the ![TYPE] with icon+Type
245+ emphasis .AppendChild (emphasis , attentionText )
246+ for i := 0 ; i < 2 ; i ++ {
247+ lineBreak := ast .NewText ()
248+ lineBreak .SetSoftLineBreak (true )
249+ firstParagraph .InsertAfter (firstParagraph , emphasis , lineBreak )
250+ }
251+ firstParagraph .InsertBefore (firstParagraph , emphasis , NewAttention (attentionType ))
252+ firstParagraph .RemoveChild (firstParagraph , firstTextNode )
253+ firstParagraph .RemoveChild (firstParagraph , secondTextNode )
254+ firstParagraph .RemoveChild (firstParagraph , thirdTextNode )
212255 }
213256 return ast .WalkContinue , nil
214257 })
@@ -346,10 +389,16 @@ func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast
346389
347390 var octiconType string
348391 switch n .AttentionType {
349- case AttentionNote :
392+ case "note" :
350393 octiconType = "info"
351- case AttentionWarning :
394+ case "tip" :
395+ octiconType = "light-bulb"
396+ case "important" :
397+ octiconType = "report"
398+ case "warning" :
352399 octiconType = "alert"
400+ case "caution" :
401+ octiconType = "stop"
353402 }
354403 _ , _ = w .WriteString (string (svg .RenderHTML ("octicon-" + octiconType )))
355404 } else {
@@ -417,7 +466,10 @@ func (r *HTMLRenderer) renderSummary(w util.BufWriter, source []byte, node ast.N
417466 return ast .WalkContinue , nil
418467}
419468
420- var validNameRE = regexp .MustCompile ("^[a-z ]+$" )
469+ var (
470+ validNameRE = regexp .MustCompile ("^[a-z ]+$" )
471+ attentionTypeRE = regexp .MustCompile ("^!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)$" )
472+ )
421473
422474func (r * HTMLRenderer ) renderIcon (w util.BufWriter , source []byte , node ast.Node , entering bool ) (ast.WalkStatus , error ) {
423475 if ! entering {
0 commit comments