~repos /gromer
git clone https://pyrossh.dev/repos/gromer.git
gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.
f2cc55aa
—
Peter John 3 years ago
fix for in component
- gsx/gsx.go +25 -26
- gsx/gsx_test.go +162 -147
- gsx/parser.go +1 -1
gsx/gsx.go
CHANGED
|
@@ -228,7 +228,7 @@ func populate(c *Context, tags []*Tag) []*Tag {
|
|
|
228
228
|
|
|
229
229
|
func populateTag(c *Context, tag *Tag) {
|
|
230
230
|
if tag.Name == "" {
|
|
231
|
-
if tag.Text.Ref != nil {
|
|
231
|
+
if tag.Text.Str == nil && tag.Text.Ref != nil {
|
|
232
232
|
value := getRefValue(c, *tag.Text.Ref)
|
|
233
233
|
children, ok := value.([]*Tag)
|
|
234
234
|
if ok {
|
|
@@ -250,48 +250,47 @@ func populateTag(c *Context, tag *Tag) {
|
|
|
250
250
|
compContext.data[loop.Index] = i
|
|
251
251
|
compContext.data[loop.Key] = v.Index(i).Interface()
|
|
252
252
|
newTags := populate(compContext, cloneTags(statement.Tags))
|
|
253
|
-
for _, t := range newTags {
|
|
254
|
-
|
|
253
|
+
tag.Children = append(tag.Children, newTags...)
|
|
255
|
-
}
|
|
256
254
|
}
|
|
257
255
|
}
|
|
258
256
|
}
|
|
259
257
|
} else {
|
|
260
258
|
if comp, ok := compMap[tag.Name]; ok {
|
|
259
|
+
tag.Name = "fragment"
|
|
261
260
|
if tag.SelfClosing {
|
|
262
261
|
tag.SelfClosing = false
|
|
263
262
|
}
|
|
264
|
-
compContext := c.Clone(
|
|
263
|
+
compContext := c.Clone(comp.Name)
|
|
265
264
|
nodes := comp.Render(compContext, tag)
|
|
266
265
|
populate(compContext, tag.Children)
|
|
267
266
|
compContext.Set("children", tag.Children)
|
|
267
|
+
populate(compContext, nodes)
|
|
268
268
|
tag.Children = nodes
|
|
269
|
-
populate(compContext, tag.Children)
|
|
270
269
|
} else {
|
|
271
|
-
|
|
270
|
+
for _, a := range tag.Attributes {
|
|
271
|
+
if a.Value.Str != nil {
|
|
272
|
+
if strings.Contains(*a.Value.Str, "{") {
|
|
273
|
+
subs := substituteString(c, removeQuotes(*a.Value.Str))
|
|
274
|
+
a.Value = &Literal{Str: &subs}
|
|
275
|
+
} else {
|
|
276
|
+
*a.Value.Str = removeQuotes(*a.Value.Str)
|
|
272
|
-
|
|
277
|
+
}
|
|
273
|
-
for _, a := range tag.Attributes {
|
|
274
|
-
|
|
278
|
+
} else if a.Value.Ref != nil {
|
|
275
|
-
if strings.Contains(*a.Value.Str, "{") {
|
|
276
|
-
subs := substituteString(c,
|
|
279
|
+
subs := substituteString(c, *a.Value.Ref)
|
|
277
280
|
a.Value = &Literal{Str: &subs}
|
|
281
|
+
} else if a.Key == "class" && a.Value.KV != nil {
|
|
278
|
-
|
|
282
|
+
classes := []string{}
|
|
283
|
+
for _, a := range a.Value.KV {
|
|
279
|
-
|
|
284
|
+
varValue := getRefValue(c, a.Value)
|
|
285
|
+
if varValue.(bool) {
|
|
286
|
+
classes = append(classes, removeQuotes(a.Key))
|
|
280
|
-
|
|
287
|
+
}
|
|
281
|
-
} else if a.Value.Ref != nil {
|
|
282
|
-
subs := substituteString(c, *a.Value.Ref)
|
|
283
|
-
a.Value = &Literal{Str: &subs}
|
|
284
|
-
} else if a.Key == "class" && a.Value.KV != nil {
|
|
285
|
-
classes := []string{}
|
|
286
|
-
for _, a := range a.Value.KV {
|
|
287
|
-
varValue := getRefValue(c, a.Value)
|
|
288
|
-
if varValue.(bool) {
|
|
289
|
-
classes = append(classes, removeQuotes(a.Key))
|
|
290
288
|
}
|
|
289
|
+
result := strings.Join(classes, " ")
|
|
290
|
+
a.Value.Str = &result
|
|
291
291
|
}
|
|
292
|
-
result := strings.Join(classes, " ")
|
|
293
|
-
a.Value.Str = &result
|
|
294
292
|
}
|
|
293
|
+
populate(c, tag.Children)
|
|
295
294
|
}
|
|
296
295
|
}
|
|
297
296
|
}
|
gsx/gsx_test.go
CHANGED
|
@@ -31,8 +31,12 @@ func Todo(c *Context, todo *TodoData) []*Tag {
|
|
|
31
31
|
|
|
32
32
|
func TodoList(c *Context, todos []*TodoData) []*Tag {
|
|
33
33
|
return c.Render(`
|
|
34
|
-
<ul id="todo-list" class="relative"
|
|
34
|
+
<ul id="todo-list" class="relative">
|
|
35
|
+
for i, v := range todos {
|
|
36
|
+
return (
|
|
35
|
-
|
|
37
|
+
<Todo todo={v}>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
36
40
|
</ul>
|
|
37
41
|
`)
|
|
38
42
|
}
|
|
@@ -71,54 +75,46 @@ func TestComponent(t *testing.T) {
|
|
|
71
75
|
`)
|
|
72
76
|
actual := RenderString(nodes)
|
|
73
77
|
expected := trimLeft(`
|
|
74
|
-
<Todo>
|
|
75
|
-
|
|
78
|
+
<li id="todo-4" class="completed">
|
|
76
|
-
|
|
79
|
+
<div class="upper">
|
|
77
|
-
<span>
|
|
78
|
-
My fourth todo
|
|
79
|
-
</span>
|
|
80
|
-
<span>
|
|
81
|
-
My fourth todo
|
|
82
|
-
</span>
|
|
83
|
-
</div>
|
|
84
80
|
<span>
|
|
85
81
|
My fourth todo
|
|
86
82
|
</span>
|
|
83
|
+
<span>
|
|
84
|
+
My fourth todo
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
<nil>
|
|
88
|
+
<div class="bottom">
|
|
89
|
+
<span>
|
|
90
|
+
true
|
|
91
|
+
</span>
|
|
87
92
|
<span>
|
|
88
93
|
true
|
|
89
94
|
</span>
|
|
95
|
+
</div>
|
|
96
|
+
</li>
|
|
90
97
|
|
|
98
|
+
<li id="todo-4" class="completed">
|
|
99
|
+
<div class="upper">
|
|
100
|
+
<span>
|
|
101
|
+
My fourth todo
|
|
102
|
+
</span>
|
|
103
|
+
<span>
|
|
104
|
+
My fourth todo
|
|
105
|
+
</span>
|
|
106
|
+
</div>
|
|
107
|
+
<nil>
|
|
91
|
-
|
|
108
|
+
<div class="bottom">
|
|
92
|
-
|
|
109
|
+
<span>
|
|
93
|
-
|
|
110
|
+
true
|
|
94
|
-
|
|
111
|
+
</span>
|
|
95
|
-
|
|
112
|
+
<span>
|
|
96
|
-
|
|
113
|
+
true
|
|
97
|
-
|
|
114
|
+
</span>
|
|
98
|
-
|
|
115
|
+
</div>
|
|
99
|
-
|
|
116
|
+
</li>
|
|
100
|
-
</Todo>
|
|
101
|
-
<Todo>
|
|
102
|
-
<li id="todo-4" class="completed">
|
|
103
|
-
<div class="upper">
|
|
104
|
-
<span>
|
|
105
|
-
My fourth todo
|
|
106
|
-
</span>
|
|
107
|
-
<span>
|
|
108
|
-
My fourth todo
|
|
109
|
-
</span>
|
|
110
|
-
</div>
|
|
111
117
|
|
|
112
|
-
<div class="bottom">
|
|
113
|
-
<span>
|
|
114
|
-
true
|
|
115
|
-
</span>
|
|
116
|
-
<span>
|
|
117
|
-
true
|
|
118
|
-
</span>
|
|
119
|
-
</div>
|
|
120
|
-
</li>
|
|
121
|
-
</Todo>
|
|
122
118
|
`)
|
|
123
119
|
r.Equal(expected, actual)
|
|
124
120
|
}
|
|
@@ -139,35 +135,33 @@ func TestMultipleComponent(t *testing.T) {
|
|
|
139
135
|
`)
|
|
140
136
|
actual := RenderString(nodes)
|
|
141
137
|
expected := trimLeft(`
|
|
142
|
-
<Todo>
|
|
143
|
-
|
|
138
|
+
<li id="todo-4" class="completed">
|
|
144
|
-
|
|
139
|
+
<div class="upper">
|
|
145
|
-
|
|
140
|
+
<span>
|
|
146
|
-
|
|
141
|
+
My fourth todo
|
|
147
|
-
|
|
142
|
+
</span>
|
|
148
|
-
|
|
143
|
+
<span>
|
|
149
|
-
|
|
144
|
+
My fourth todo
|
|
150
|
-
|
|
145
|
+
</span>
|
|
151
|
-
|
|
146
|
+
</div>
|
|
147
|
+
<nil>
|
|
148
|
+
<div class="bottom">
|
|
149
|
+
<span>
|
|
150
|
+
true
|
|
151
|
+
</span>
|
|
152
|
+
<span>
|
|
153
|
+
true
|
|
154
|
+
</span>
|
|
155
|
+
</div>
|
|
156
|
+
</li>
|
|
157
|
+
|
|
158
|
+
<span id="todo-count" class="todo-count" hx-swap-oob="true">
|
|
159
|
+
<strong>
|
|
160
|
+
10
|
|
161
|
+
</strong>
|
|
162
|
+
item left
|
|
163
|
+
</span>
|
|
152
164
|
|
|
153
|
-
<div class="bottom">
|
|
154
|
-
<span>
|
|
155
|
-
true
|
|
156
|
-
</span>
|
|
157
|
-
<span>
|
|
158
|
-
true
|
|
159
|
-
</span>
|
|
160
|
-
</div>
|
|
161
|
-
</li>
|
|
162
|
-
</Todo>
|
|
163
|
-
<TodoCount>
|
|
164
|
-
<span id="todo-count" class="todo-count" hx-swap-oob="true">
|
|
165
|
-
<strong>
|
|
166
|
-
10
|
|
167
|
-
</strong>
|
|
168
|
-
item left
|
|
169
|
-
</span>
|
|
170
|
-
</TodoCount>
|
|
171
165
|
`)
|
|
172
166
|
r.Equal(expected, actual)
|
|
173
167
|
}
|
|
@@ -252,7 +246,95 @@ func TestFor(t *testing.T) {
|
|
|
252
246
|
|
|
253
247
|
</ul>
|
|
254
248
|
<ol>
|
|
249
|
+
<li id="todo-1" class="completed">
|
|
250
|
+
<div class="upper">
|
|
251
|
+
<span>
|
|
252
|
+
My first todo
|
|
253
|
+
</span>
|
|
254
|
+
<span>
|
|
255
|
+
My first todo
|
|
256
|
+
</span>
|
|
257
|
+
</div>
|
|
258
|
+
<nil>
|
|
259
|
+
<div class="bottom">
|
|
260
|
+
<span>
|
|
261
|
+
true
|
|
262
|
+
</span>
|
|
263
|
+
<span>
|
|
264
|
+
true
|
|
265
|
+
</span>
|
|
266
|
+
</div>
|
|
267
|
+
</li>
|
|
268
|
+
|
|
255
|
-
<
|
|
269
|
+
<li id="todo-2">
|
|
270
|
+
<div class="upper">
|
|
271
|
+
<span>
|
|
272
|
+
My second todo
|
|
273
|
+
</span>
|
|
274
|
+
<span>
|
|
275
|
+
My second todo
|
|
276
|
+
</span>
|
|
277
|
+
</div>
|
|
278
|
+
<nil>
|
|
279
|
+
<div class="bottom">
|
|
280
|
+
<span>
|
|
281
|
+
false
|
|
282
|
+
</span>
|
|
283
|
+
<span>
|
|
284
|
+
false
|
|
285
|
+
</span>
|
|
286
|
+
</div>
|
|
287
|
+
</li>
|
|
288
|
+
|
|
289
|
+
<li id="todo-3">
|
|
290
|
+
<div class="upper">
|
|
291
|
+
<span>
|
|
292
|
+
My third todo
|
|
293
|
+
</span>
|
|
294
|
+
<span>
|
|
295
|
+
My third todo
|
|
296
|
+
</span>
|
|
297
|
+
</div>
|
|
298
|
+
<nil>
|
|
299
|
+
<div class="bottom">
|
|
300
|
+
<span>
|
|
301
|
+
false
|
|
302
|
+
</span>
|
|
303
|
+
<span>
|
|
304
|
+
false
|
|
305
|
+
</span>
|
|
306
|
+
</div>
|
|
307
|
+
</li>
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
</ol>
|
|
311
|
+
`)
|
|
312
|
+
r.Equal(expected, actual)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
func TestForComponent(t *testing.T) {
|
|
316
|
+
r := require.New(t)
|
|
317
|
+
RegisterComponent(Todo, nil, "todo")
|
|
318
|
+
RegisterComponent(TodoList, nil, "todos")
|
|
319
|
+
RegisterFunc(WebsiteName)
|
|
320
|
+
h := Context{
|
|
321
|
+
data: map[string]interface{}{
|
|
322
|
+
"todos": []*TodoData{
|
|
323
|
+
{ID: "1", Text: "My first todo", Completed: true},
|
|
324
|
+
{ID: "2", Text: "My second todo", Completed: false},
|
|
325
|
+
{ID: "3", Text: "My third todo", Completed: false},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
}
|
|
329
|
+
nodes := h.Render(`
|
|
330
|
+
<div>
|
|
331
|
+
<TodoList />
|
|
332
|
+
</div>
|
|
333
|
+
`)
|
|
334
|
+
actual := RenderString(nodes)
|
|
335
|
+
expected := trimLeft(`
|
|
336
|
+
<div>
|
|
337
|
+
<ul id="todo-list" class="relative">
|
|
256
338
|
<li id="todo-1" class="completed">
|
|
257
339
|
<div class="upper">
|
|
258
340
|
<span>
|
|
@@ -262,15 +344,7 @@ func TestFor(t *testing.T) {
|
|
|
262
344
|
My first todo
|
|
263
345
|
</span>
|
|
264
346
|
</div>
|
|
265
|
-
<div class="todo-panel">
|
|
266
|
-
|
|
347
|
+
<nil>
|
|
267
|
-
My first todo
|
|
268
|
-
</span>
|
|
269
|
-
<span>
|
|
270
|
-
true
|
|
271
|
-
</span>
|
|
272
|
-
</div>
|
|
273
|
-
|
|
274
348
|
<div class="bottom">
|
|
275
349
|
<span>
|
|
276
350
|
true
|
|
@@ -280,8 +354,7 @@ func TestFor(t *testing.T) {
|
|
|
280
354
|
</span>
|
|
281
355
|
</div>
|
|
282
356
|
</li>
|
|
283
|
-
|
|
357
|
+
|
|
284
|
-
<Todo todo="v">
|
|
285
358
|
<li id="todo-2">
|
|
286
359
|
<div class="upper">
|
|
287
360
|
<span>
|
|
@@ -291,15 +364,7 @@ func TestFor(t *testing.T) {
|
|
|
291
364
|
My second todo
|
|
292
365
|
</span>
|
|
293
366
|
</div>
|
|
294
|
-
<div class="todo-panel">
|
|
295
|
-
|
|
367
|
+
<nil>
|
|
296
|
-
My second todo
|
|
297
|
-
</span>
|
|
298
|
-
<span>
|
|
299
|
-
false
|
|
300
|
-
</span>
|
|
301
|
-
</div>
|
|
302
|
-
|
|
303
368
|
<div class="bottom">
|
|
304
369
|
<span>
|
|
305
370
|
false
|
|
@@ -309,8 +374,7 @@ func TestFor(t *testing.T) {
|
|
|
309
374
|
</span>
|
|
310
375
|
</div>
|
|
311
376
|
</li>
|
|
312
|
-
|
|
377
|
+
|
|
313
|
-
<Todo todo="v">
|
|
314
378
|
<li id="todo-3">
|
|
315
379
|
<div class="upper">
|
|
316
380
|
<span>
|
|
@@ -320,15 +384,7 @@ func TestFor(t *testing.T) {
|
|
|
320
384
|
My third todo
|
|
321
385
|
</span>
|
|
322
386
|
</div>
|
|
323
|
-
<div class="todo-panel">
|
|
324
|
-
|
|
387
|
+
<nil>
|
|
325
|
-
My third todo
|
|
326
|
-
</span>
|
|
327
|
-
<span>
|
|
328
|
-
false
|
|
329
|
-
</span>
|
|
330
|
-
</div>
|
|
331
|
-
|
|
332
388
|
<div class="bottom">
|
|
333
389
|
<span>
|
|
334
390
|
false
|
|
@@ -338,52 +394,11 @@ func TestFor(t *testing.T) {
|
|
|
338
394
|
</span>
|
|
339
395
|
</div>
|
|
340
396
|
</li>
|
|
341
|
-
</Todo>
|
|
342
397
|
|
|
398
|
+
|
|
343
|
-
</
|
|
399
|
+
</ul>
|
|
400
|
+
|
|
401
|
+
</div>
|
|
344
402
|
`)
|
|
345
403
|
r.Equal(expected, actual)
|
|
346
404
|
}
|
|
347
|
-
|
|
348
|
-
// func TestForComponent(t *testing.T) {
|
|
349
|
-
// r := require.New(t)
|
|
350
|
-
// RegisterComponent(Todo, nil, "todo")
|
|
351
|
-
// RegisterComponent(TodoList, nil, "todos")
|
|
352
|
-
// RegisterFunc(WebsiteName)
|
|
353
|
-
// h := Context{
|
|
354
|
-
// data: map[string]interface{}{
|
|
355
|
-
// "todos": []*TodoData{
|
|
356
|
-
// {ID: "1", Text: "My first todo", Completed: true},
|
|
357
|
-
// {ID: "2", Text: "My second todo", Completed: false},
|
|
358
|
-
// {ID: "3", Text: "My third todo", Completed: false},
|
|
359
|
-
// },
|
|
360
|
-
// },
|
|
361
|
-
// }
|
|
362
|
-
// actual := h.Render(`
|
|
363
|
-
// <div>
|
|
364
|
-
// <TodoList />
|
|
365
|
-
// </div>
|
|
366
|
-
// `).String()
|
|
367
|
-
// expected := stripWhitespace(`
|
|
368
|
-
// <div>
|
|
369
|
-
// <ul id="todo-list" class="relative" x-for="todo in todos">
|
|
370
|
-
// <li id="todo-1" class="completed">
|
|
371
|
-
// <div class="view"><span>My first todo</span><span>My first todo</span></div>
|
|
372
|
-
// <div class="todo-panel"><span>My first todo</span><span>true</span></div>
|
|
373
|
-
// <div class="count"><span>true</span><span>true</span></div>
|
|
374
|
-
// </li>
|
|
375
|
-
// <li id="todo-2" class="">
|
|
376
|
-
// <div class="view"><span>My second todo</span><span>My second todo</span></div>
|
|
377
|
-
// <div class="todo-panel"><span>My second todo</span><span>false</span></div>
|
|
378
|
-
// <div class="count"><span>false</span><span>false</span></div>
|
|
379
|
-
// </li>
|
|
380
|
-
// <li id="todo-3" class="">
|
|
381
|
-
// <div class="view"><span>My third todo</span><span>My third todo</span></div>
|
|
382
|
-
// <div class="todo-panel"><span>My third todo</span><span>false</span></div>
|
|
383
|
-
// <div class="count"><span>false</span><span>false</span></div>
|
|
384
|
-
// </li>
|
|
385
|
-
// </ul>
|
|
386
|
-
// </div>
|
|
387
|
-
// `)
|
|
388
|
-
// r.Equal(expected, actual)
|
|
389
|
-
// }
|
gsx/parser.go
CHANGED
|
@@ -205,7 +205,7 @@ func processTree(nodes []*AstNode) []*Tag {
|
|
|
205
205
|
if n.Close.Name == prevTag.Name {
|
|
206
206
|
prevTag, _ = stack.Pop()
|
|
207
207
|
} else {
|
|
208
|
-
panic(fmt.Errorf("Brackets not matching in line %d:%d", n.Close.Pos.Line, n.Close.Pos.Column))
|
|
208
|
+
panic(fmt.Errorf("Brackets not matching for tag %s in line %d:%d, prevTag: %s", n.Close.Name, n.Close.Pos.Line, n.Close.Pos.Column, prevTag.Name))
|
|
209
209
|
}
|
|
210
210
|
} else if n.Content != nil {
|
|
211
211
|
newTag := &Tag{
|