aboutsummaryrefslogtreecommitdiff
path: root/mardown
diff options
context:
space:
mode:
Diffstat (limited to 'mardown')
-rw-r--r--mardown/ast_header.go2
-rw-r--r--mardown/ast_modifier.go104
-rw-r--r--mardown/ast_paragraph.go12
3 files changed, 115 insertions, 3 deletions
diff --git a/mardown/ast_header.go b/mardown/ast_header.go
index 07d7e1c..1526efa 100644
--- a/mardown/ast_header.go
+++ b/mardown/ast_header.go
@@ -25,7 +25,7 @@ func (a *astHeader) Eval() (template.HTML, error) {
return template.HTML(fmt.Sprintf("<h%d>%s</h%d>", a.level, content, a.level)), nil
}
-func header(lxs lexers) (block, error) {
+func header(lxs lexers) (*astHeader, error) {
b := &astHeader{level: uint(len(lxs.Current().Value))}
var err error
b.content, err = paragraph(lxs, true)
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</%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
+}
diff --git a/mardown/ast_paragraph.go b/mardown/ast_paragraph.go
index 04f2086..3c8f985 100644
--- a/mardown/ast_paragraph.go
+++ b/mardown/ast_paragraph.go
@@ -47,7 +47,11 @@ func paragraph(lxs lexers, oneLine bool) (*astParagraph, error) {
case lexerLiteral, lexerHeader:
tree.content = append(tree.content, astLiteral(lxs.Current().Value))
case lexerModifier:
- //TODO: handle
+ mod, err := modifier(lxs)
+ if err != nil {
+ return nil, err
+ }
+ tree.content = append(tree.content, mod)
case lexerQuote:
//TODO: handle
case lexerEscape:
@@ -62,7 +66,11 @@ func paragraph(lxs lexers, oneLine bool) (*astParagraph, error) {
lxs.current-- // because we do not use it before the next
return tree, nil
}
- //TODO: handle
+ mod, err := modifier(lxs)
+ if err != nil {
+ return nil, err
+ }
+ tree.content = append(tree.content, mod)
}
}
return tree, nil