From e20acb05fd33b8fbcfafee4b72734224093c2d20 Mon Sep 17 00:00:00 2001 From: Anhgelus Morhtuuzh Date: Tue, 30 Sep 2025 20:55:02 +0200 Subject: feat(markdown): ast supports modifier --- mardown/ast_modifier.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 mardown/ast_modifier.go (limited to 'mardown/ast_modifier.go') diff --git a/mardown/ast_modifier.go b/mardown/ast_modifier.go new file mode 100644 index 0000000..e505aef --- /dev/null +++ b/mardown/ast_modifier.go @@ -0,0 +1,104 @@ +package mardown + +import ( + "errors" + "fmt" + "html/template" +) + +var ( + ErrInternalError = errors.New("internal error") + ErrInvalidModifier = errors.Join(ErrInvalidParagraph, errors.New("invalid modifier organization")) + ErrInvalidTypeInModifier = errors.Join(ErrInvalidParagraph, errors.New("invalid type in modifier")) +) + +type modifierTag string + +const ( + boldTag modifierTag = "b" + emTag modifierTag = "em" + codeTag modifierTag = "code" +) + +type astModifier struct { + symbols string + tag modifierTag + content []block + parent *astModifier +} + +func (a *astModifier) Eval() (template.HTML, error) { + var content template.HTML + for _, c := range a.content { + ct, err := c.Eval() + if err != nil { + return "", err + } + content += ct + } + return template.HTML(fmt.Sprintf("<%s>%s", a.tag, content, a.tag)), nil +} + +func modifier(lxs lexers) (*astModifier, error) { + current := lxs.Current().Value + mod := modifierDetect(current) + modInside := mod + if len(mod.content) > 0 { + var ok bool + modInside, ok = mod.content[0].(*astModifier) + if modInside.content != nil && !ok { + return nil, ErrInternalError + } + // getting the last modifier + for len(modInside.content) > 0 { + modInside, ok = modInside.content[0].(*astModifier) + if modInside.content != nil && !ok { + return nil, ErrInternalError + } + } + } + n := len(modInside.symbols) + var s string + for lxs.Next() { + switch lxs.Current().Type { + case lexerLiteral: + s += lxs.Current().Value + case lexerModifier: + if len(lxs.Current().Value) < n { + return nil, ErrInvalidModifier + } + if lxs.Current().Value[:n] != modInside.symbols { + return nil, ErrInvalidModifier + } + modInside.content = append(modInside.content, astLiteral(s)) + s = "" + modInside = modInside.parent + default: + return nil, ErrInvalidTypeInModifier + } + } + return mod, nil +} + +func modifierDetect(val string) *astModifier { + mod := new(astModifier) + if len(val) == 1 { + mod.symbols = val + if val == "`" { + mod.tag = codeTag + } else { + mod.tag = emTag + } + return mod + } + if val[:2] == "**" || val[:2] == "__" { + mod.symbols = val + mod.tag = boldTag + } else { + mod = modifierDetect(val[:1]) + next := modifierDetect(val[1:]) + next.parent = mod + mod.content = append(mod.content, next) + } + return mod +} -- cgit v1.2.3