aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mardown/ast_modifier.go94
-rw-r--r--mardown/ast_modifier_test.go4
-rw-r--r--mardown/ast_paragraph.go3
-rw-r--r--mardown/ast_test.go6
-rw-r--r--mardown/lexer.go9
5 files changed, 65 insertions, 51 deletions
diff --git a/mardown/ast_modifier.go b/mardown/ast_modifier.go
index 46d5874..944cb4a 100644
--- a/mardown/ast_modifier.go
+++ b/mardown/ast_modifier.go
@@ -1,6 +1,7 @@
package mardown
import (
+ "encoding/json"
"errors"
"fmt"
"html/template"
@@ -23,7 +24,6 @@ type astModifier struct {
symbols string
tag modifierTag
content []block
- parent *astModifier
}
func (a *astModifier) Eval() (template.HTML, error) {
@@ -38,75 +38,79 @@ func (a *astModifier) Eval() (template.HTML, error) {
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 := 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
- }
- }
+ mod, err := modifierDetect(current)
+ if err != nil {
+ return nil, err
}
var s string
- for modInside != nil && lxs.Next() {
+ for lxs.Next() {
switch lxs.Current().Type {
- case lexerLiteral:
+ case lexerLiteral, lexerHeader:
s += lxs.Current().Value
case lexerModifier:
- n := len(modInside.symbols)
- if len(lxs.Current().Value) < n {
- return nil, ErrInvalidModifier
+ if lxs.Current().Value == mod.symbols {
+ mod.content = append(mod.content, astLiteral(s))
+ return mod, nil
}
- if lxs.Current().Value[:n] != modInside.symbols {
- return nil, ErrInvalidModifier
+ if len(s) != 0 {
+ mod.content = append(mod.content, astLiteral(s))
+ s = ""
+ }
+ c, err := modifier(lxs)
+ if err != nil {
+ return nil, err
}
- modInside.content = append(modInside.content, astLiteral(s))
- s = ""
- modInside = modInside.parent
+ mod.content = append(mod.content, c)
case lexerBreak:
- lxs.current-- // because we did not use it
+ 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:
- println(lxs.Current().Type, lxs.Current().Value)
return nil, ErrInvalidTypeInModifier
}
}
+ if len(s) != 0 {
+ return nil, ErrInvalidModifier
+ }
return mod, nil
}
-func modifierDetect(val string) *astModifier {
+func modifierDetect(val string) (*astModifier, error) {
mod := new(astModifier)
- if len(val) == 1 {
+ switch len(val) {
+ case 1:
mod.symbols = val
mod.tag = emTag
- return mod
- }
- if val[:2] == "**" || val[:2] == "__" {
- mod.symbols = val[:2]
+ return mod, nil
+ case 2:
+ mod.symbols = val
mod.tag = boldTag
- if len(val) > 2 {
- next := modifierDetect(val[2:])
- next.parent = mod
- mod.content = append(mod.content, next)
- }
- } else {
- mod = modifierDetect(val[:1])
- next := modifierDetect(val[1:])
- next.parent = mod
- mod.content = append(mod.content, next)
+ return mod, nil
+ default:
+ return nil, ErrInvalidModifier
}
- return mod
}
diff --git a/mardown/ast_modifier_test.go b/mardown/ast_modifier_test.go
index d805f22..1539aa4 100644
--- a/mardown/ast_modifier_test.go
+++ b/mardown/ast_modifier_test.go
@@ -4,7 +4,7 @@ import "testing"
func TestModifier(t *testing.T) {
content := `
-***bon*soir**
+**bo*n*soir**
`
lxs := lex(content)
tree, err := ast(lxs)
@@ -15,7 +15,7 @@ func TestModifier(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if c != "<p><b><em>bon</em>soir</b></p>" {
+ if c != "<p><b>bo<em>n</em>soir</b></p>" {
t.Errorf("failed, got %s", c)
t.Logf("lxs: %s\ntree: %s", lxs, tree)
}
diff --git a/mardown/ast_paragraph.go b/mardown/ast_paragraph.go
index 1a78ced..3e8d027 100644
--- a/mardown/ast_paragraph.go
+++ b/mardown/ast_paragraph.go
@@ -69,6 +69,9 @@ func paragraph(lxs *lexers, oneLine bool) (*astParagraph, error) {
//TODO: handle
case lexerExternal:
n = 0
+ if lxs.Current().Value == "!" {
+ tree.content = append(tree.content, astLiteral(lxs.Current().Value))
+ }
//TODO: handle
case lexerCode:
n = 0
diff --git a/mardown/ast_test.go b/mardown/ast_test.go
index 971e6ac..c0860f4 100644
--- a/mardown/ast_test.go
+++ b/mardown/ast_test.go
@@ -20,7 +20,7 @@ avec une source
var parsed = `
<h1>Je suis un titre</h1>
-<p>Avec une description classique, sur plusieurs lignes</p>
+<p>Avec une description classique, sur plusieurs lignes !</p>
<p>Et je peux mettre du texte en <b>gras</b>, en <em>italique</em> et les <b><em>deux en même temps</em></b> !</p>
<div class="quote"><blockquote>Je suis une magnifique citation sur plusieurs lignes</blockquote><p>avec une source</p></div>
`
@@ -37,7 +37,7 @@ func TestAst(t *testing.T) {
}
wanted := strings.ReplaceAll(parsed, "\n", "")
if string(res) != wanted {
- t.Errorf("invalid string, got %s", res)
- t.Logf("wanted %s", wanted)
+ t.Errorf("invalid string, got\n%s", res)
+ t.Logf("wanted\n%s", wanted)
}
}
diff --git a/mardown/lexer.go b/mardown/lexer.go
index f87e61c..8450032 100644
--- a/mardown/lexer.go
+++ b/mardown/lexer.go
@@ -74,7 +74,14 @@ func lex(s string) *lexers {
for _, c := range []rune(s) {
switch c {
case '*', '_':
- fn(c, lexerModifier)
+ if (currentType != lexerModifier && len(previous) > 0) ||
+ (len(previous) > 0 && []rune(previous)[0] != c) ||
+ len(previous) > 2 {
+ lexs = append(lexs, lexer{Type: currentType, Value: previous})
+ previous = ""
+ }
+ currentType = lexerModifier
+ previous += string(c)
case '`':
fn(c, lexerCode)
case '\n':