diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2026-02-05 10:50:12 +0100 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2026-02-05 16:36:41 +0000 |
| commit | d6e75145e54854484f2114398ff89787d243608a (patch) | |
| tree | e79dc8d4cc0a25767dff618405bb8d982800229a /markdown/ast_callout.go | |
| parent | cd3bd5dff64fa80c7170d7f5d2d05f610fec36ee (diff) | |
feat(markdown): interprate callout
Diffstat (limited to 'markdown/ast_callout.go')
| -rw-r--r-- | markdown/ast_callout.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/markdown/ast_callout.go b/markdown/ast_callout.go new file mode 100644 index 0000000..769d714 --- /dev/null +++ b/markdown/ast_callout.go @@ -0,0 +1,92 @@ +package markdown + +import ( + "errors" + "html/template" + "strings" + + "git.anhgelus.world/anhgelus/small-web/dom" +) + +var ( + ErrInvalidCallout = errors.New("invalid callout") +) + +type astCallout struct { + kind string + title *astParagraph + content []*astParagraph +} + +func (a *astCallout) Eval(opt *Option) (template.HTML, *ParseError) { + inner := dom.NewContentElement("div", make([]dom.Element, 0)) + for _, c := range a.content { + ct, err := c.Eval(opt) + if err != nil { + return "", err + } + inner.Contents = append(inner.Contents, dom.NewParagraph( + template.HTML(strings.TrimSpace(string(ct))), + )) + } + + titleContent, err := a.title.Eval(opt) + if err != nil { + return "", err + } + titleContent = template.HTML(strings.TrimSpace(string(titleContent))) + if len(titleContent) == 0 { + titleContent = template.HTML(a.kind) + } + title := dom.NewLiteralContentElement("h4", titleContent) + + callout := dom.NewContentElement("div", make([]dom.Element, 2)) + callout.Contents[0] = title + callout.Contents[1] = inner + callout.SetAttribute("data-kind", a.kind) + callout.ClassList().Add("callout") + return callout.Render(), nil +} + +func callout(lxs *lexers) (block, *ParseError) { + callout := new(astCallout) + if lxs.Current().Value != "[!" { + return paragraph(lxs, false) + } + if !lxs.Next() { + return nil, &ParseError{lxs: *lxs, internal: ErrInvalidCallout} + } + callout.kind = strings.ToLower(lxs.Current().Value) + if !lxs.Next() || lxs.Current().Type != lexerCallout || lxs.Current().Value != "]" { + return nil, &ParseError{lxs: *lxs, internal: ErrInvalidCallout} + } + var err *ParseError + callout.title, err = paragraph(lxs, true) + if err != nil { + return nil, err + } + n := 0 + for lxs.Next() && n < 2 { + current := lxs.Current() + n = 0 + switch current.Type { + case lexerBreak: + n = len(current.Value) + case lexerQuote: + case lexerLiteral, lexerModifier, lexerCode, lexerExternal: + p, err := paragraph(lxs, true) + if err != nil { + return nil, err + } + lxs.Before() + callout.content = append(callout.content, p) + n++ + default: + // because the code did not use it + lxs.Before() + return callout, nil + } + } + lxs.Before() + return callout, nil +} |
