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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
package tuigen
import (
"testing"
)
func TestLexer_UnicodeSymbols(t *testing.T) {
type tc struct {
source string
expected []TokenType
}
tests := map[string]tc{
"arrow symbols in text": {
source: `<span>Use ↑/↓ to navigate</span>`,
expected: []TokenType{
TokenLAngle, TokenIdent, TokenRAngle,
TokenIdent, TokenSymbol, TokenSlash, TokenSymbol, TokenIdent, TokenIdent,
TokenLAngleSlash, TokenIdent, TokenRAngle,
TokenEOF,
},
},
"various unicode arrows": {
source: `<div>← → ↑ ↓</div>`,
expected: []TokenType{
TokenLAngle, TokenIdent, TokenRAngle,
TokenSymbol, TokenSymbol, TokenSymbol, TokenSymbol,
TokenLAngleSlash, TokenIdent, TokenRAngle,
TokenEOF,
},
},
"emoji in text": {
source: `<span>Hello 👋 World 🌍</span>`,
expected: []TokenType{
TokenLAngle, TokenIdent, TokenRAngle,
TokenIdent, TokenSymbol, TokenIdent, TokenSymbol,
TokenLAngleSlash, TokenIdent, TokenRAngle,
TokenEOF,
},
},
"mixed unicode and ascii": {
source: `<span>Count: 5 ↑</span>`,
expected: []TokenType{
TokenLAngle, TokenIdent, TokenRAngle,
TokenIdent, TokenColon, TokenInt, TokenSymbol,
TokenLAngleSlash, TokenIdent, TokenRAngle,
TokenEOF,
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
lexer := NewLexer("test.gsx", tt.source)
var tokens []TokenType
for {
tok := lexer.Next()
tokens = append(tokens, tok.Type)
if tok.Type == TokenEOF {
break
}
}
if len(tokens) != len(tt.expected) {
t.Errorf("expected %d tokens, got %d", len(tt.expected), len(tokens))
t.Logf("expected: %v", tt.expected)
t.Logf("got: %v", tokens)
return
}
for i, expected := range tt.expected {
if tokens[i] != expected {
t.Errorf("token %d: expected %s, got %s", i, expected, tokens[i])
}
}
if lexer.Errors().HasErrors() {
t.Errorf("unexpected lexer errors: %v", lexer.Errors())
}
})
}
}
func TestParser_UnicodeTextContent(t *testing.T) {
type tc struct {
source string
expectError bool
}
tests := map[string]tc{
"arrows in span text": {
source: `package test
templ Test() {
<span>Use ↑/↓ to navigate</span>
}`,
expectError: false,
},
"arrows in attribute string": {
source: `package test
templ Test() {
<span text="Use ↑/↓ to navigate"></span>
}`,
expectError: false,
},
"emoji in text": {
source: `package test
templ Test() {
<div>
<span>Hello 👋</span>
<span>World 🌍</span>
</div>
}`,
expectError: false,
},
"unicode in multiple elements": {
source: `package test
templ Test() {
<div>
<span>← Previous</span>
<span>Next →</span>
</div>
}`,
expectError: false,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
lexer := NewLexer("test.gsx", tt.source)
parser := NewParser(lexer)
_, _ = parser.ParseFile()
hasErrors := parser.Errors().HasErrors()
if hasErrors != tt.expectError {
if tt.expectError {
t.Errorf("expected errors but got none")
} else {
t.Errorf("unexpected errors: %v", parser.Errors())
}
}
})
}
}
|