diff options
Diffstat (limited to 'markdown/ast_code.go')
| -rw-r--r-- | markdown/ast_code.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/markdown/ast_code.go b/markdown/ast_code.go new file mode 100644 index 0000000..85a3668 --- /dev/null +++ b/markdown/ast_code.go @@ -0,0 +1,66 @@ +package markdown + +import ( + "errors" + "fmt" + "html/template" +) + +var ( + ErrUnknownCodeType = errors.New("unkown code type") + ErrInvalidCodeFormat = errors.New("invalid code format") + ErrInvalidCodeBlockPosition = errors.Join(ErrInvalidParagraph, errors.New("invalid code block position")) +) + +type codeType uint + +const ( + codeOneLine codeType = 1 + codeMultiLine codeType = 2 +) + +type astCode struct { + content string + before string + codeType codeType +} + +func (a *astCode) Eval() (template.HTML, *ParseError) { + switch a.codeType { + case codeOneLine: + return template.HTML(fmt.Sprintf("<code>%s</code>", template.HTMLEscapeString(a.content))), nil + case codeMultiLine: + return template.HTML(fmt.Sprintf("<pre><code>%s</code></pre>", template.HTMLEscapeString(a.content))), nil + default: + return "", &ParseError{lxs: lexers{}, internal: ErrUnknownCodeType} + } +} + +func code(lxs *lexers) (*astCode, *ParseError) { + tree := new(astCode) + current := lxs.Current().Value + if len(current) == 3 { + tree.codeType = codeMultiLine + } else if len(current) == 1 { + tree.codeType = codeOneLine + } else { + return nil, &ParseError{lxs: *lxs, internal: ErrInvalidCodeFormat} + } + started := false + for lxs.Next() && lxs.Current().Value != current { + if lxs.Current().Type == lexerBreak { + if tree.codeType == codeOneLine { + return nil, &ParseError{lxs: *lxs, internal: ErrInvalidCodeFormat} + } + if !started { + started = true + } + } + if started || tree.codeType == codeOneLine { + tree.content += lxs.Current().Value + } else { + tree.before += lxs.Current().Value + } + } + return tree, nil +} |
