From 94dceb4f7c1740de9215b36ec183f93ca4337ee7 Mon Sep 17 00:00:00 2001 From: Anhgelus Morhtuuzh Date: Thu, 2 Oct 2025 19:52:38 +0200 Subject: style(markdown): fix typo in package name --- markdown/ast_modifier.go | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 markdown/ast_modifier.go (limited to 'markdown/ast_modifier.go') diff --git a/markdown/ast_modifier.go b/markdown/ast_modifier.go new file mode 100644 index 0000000..205786a --- /dev/null +++ b/markdown/ast_modifier.go @@ -0,0 +1,150 @@ +package markdown + +import ( + "encoding/json" + "errors" + "fmt" + "html/template" +) + +var ( + ErrInvalidUsage = errors.Join(ErrInvalidParagraph, errors.New("invalid modifier usage")) + ErrInvalidTypeInModifier = errors.Join(ErrInvalidParagraph, errors.New("invalid type in modifier")) +) + +type modifierTag string + +const ( + boldTag modifierTag = "b" + emTag modifierTag = "em" +) + +type astModifier struct { + symbols string + tag modifierTag + content []block + super bool +} + +func (a *astModifier) Eval() (template.HTML, *ParseError) { + var content template.HTML + for _, c := range a.content { + ct, err := c.Eval() + if err != nil { + return "", &ParseError{lxs: lexers{}, internal: err} + } + content += ct + } + if a.super { + return content, nil + } + return template.HTML(fmt.Sprintf("<%s>%s", a.tag, content, a.tag)), nil +} + +func (a *astModifier) String() string { + content := "[" + for _, c := range a.content { + content += "\n\t" + if v, ok := c.(fmt.Stringer); ok { + content += v.String() + } else { + b, _ := json.MarshalIndent(a.content, "\t", " ") + content += string(b) + } + content += ",\n\t" + } + content += "]" + return fmt.Sprintf("modifier{sym: %s, tag: %s, super: %v, content: %s\n}", a.symbols, a.tag, a.super, content) +} + +func modifier(lxs *lexers) (*astModifier, error) { + current := lxs.Current().Value + mod, err := modifierDetect(current) + if err != nil { + return nil, err + } + var s string + for lxs.Next() { + switch lxs.Current().Type { + case lexerLiteral, lexerHeader, lexerList: + s += lxs.Current().Value + case lexerModifier: + if mod.super && []rune(mod.symbols)[0] == []rune(lxs.Current().Value)[0] && + len(mod.symbols) >= len(lxs.Current().Value) { + mod.symbols = mod.symbols[len(lxs.Current().Value):] + subMod, err := modifierDetect(lxs.Current().Value) + if err != nil { + return nil, err + } + if !subMod.super { + subMod.content = append(subMod.content, astLiteral(s)) + mod, err = modifierDetect(mod.symbols) // this trick is so cool :D + if err != nil { + return nil, err + } + } else { + subMod, _ = modifierDetect("**") + subEm, _ := modifierDetect("*") + subEm.content = append(subEm.content, astLiteral(s)) + subMod.content = append(subMod.content, subEm) + } + s = "" + mod.content = append(mod.content, subMod) + if len(mod.symbols) == 0 { + return mod, nil + } + } else { + if lxs.Current().Value == mod.symbols { + mod.content = append(mod.content, astLiteral(s)) + return mod, nil + } else if len(s) != 0 { + mod.content = append(mod.content, astLiteral(s)) + s = "" + } + c, err := modifier(lxs) + if err != nil { + return nil, err + } + mod.content = append(mod.content, c) + } + case lexerBreak: + lxs.Before() // because we did not use it + if len(s) != 0 { + return nil, ErrInvalidUsage + } + return mod, nil + case lexerExternal: + if lxs.Current().Value == "!" { + s += lxs.Current().Value + } else { + ext, err := external(lxs) + if err != nil { + return nil, err + } + mod.content = append(mod.content, ext) + } + default: + return nil, ErrInvalidTypeInModifier + } + } + if len(s) != 0 { + return nil, ErrInvalidUsage + } + return mod, nil +} + +func modifierDetect(val string) (*astModifier, error) { + mod := new(astModifier) + mod.symbols = val + switch len(val) { + case 1: + mod.tag = emTag + case 2: + mod.tag = boldTag + case 3: + mod.super = true + default: + return nil, ErrInvalidUsage + } + return mod, nil +} -- cgit v1.2.3