aboutsummaryrefslogtreecommitdiff
path: root/mardown/ast_modifier.go
blob: 0107605f2f2cff8109cc45e701a6f1d0c535ddfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package mardown

import (
	"encoding/json"
	"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"
)

type astModifier struct {
	symbols string
	tag     modifierTag
	content []block
}

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 (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, content: %s\n}", a.symbols, a.tag, 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 lxs.Current().Value == mod.symbols {
				mod.content = append(mod.content, astLiteral(s))
				return mod, nil
			}
			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, ErrInvalidModifier
			}
			return mod, nil
		case lexerExternal:
			if lxs.Current().Value == "!" {
				s += lxs.Current().Value
			}
		default:
			return nil, ErrInvalidTypeInModifier
		}
	}
	if len(s) != 0 {
		return nil, ErrInvalidModifier
	}
	return mod, nil
}

func modifierDetect(val string) (*astModifier, error) {
	mod := new(astModifier)
	switch len(val) {
	case 1:
		mod.symbols = val
		mod.tag = emTag
		return mod, nil
	case 2:
		mod.symbols = val
		mod.tag = boldTag
		return mod, nil
	default:
		return nil, ErrInvalidModifier
	}
}