gofront 0.0.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -12
- package/package.json +8 -4
- package/src/codegen/expressions.js +520 -1717
- package/src/{codegen.js → codegen/index.js} +155 -184
- package/src/codegen/runtime.js +151 -0
- package/src/codegen/statements.js +305 -296
- package/src/codegen/stdlib/builder.js +36 -0
- package/src/codegen/stdlib/bytes.js +62 -0
- package/src/codegen/stdlib/errors.js +17 -0
- package/src/codegen/stdlib/fmt.js +101 -0
- package/src/codegen/stdlib/gom.js +152 -0
- package/src/codegen/stdlib/html.js +17 -0
- package/src/codegen/stdlib/index.js +95 -0
- package/src/codegen/stdlib/io.js +33 -0
- package/src/codegen/stdlib/maps.js +42 -0
- package/src/codegen/stdlib/math.js +53 -0
- package/src/codegen/stdlib/os.js +10 -0
- package/src/codegen/stdlib/path.js +31 -0
- package/src/codegen/stdlib/rand.js +24 -0
- package/src/codegen/stdlib/regexp.js +51 -0
- package/src/codegen/stdlib/slices.js +48 -0
- package/src/codegen/stdlib/sort.js +28 -0
- package/src/codegen/stdlib/strconv.js +30 -0
- package/src/codegen/stdlib/strings.js +83 -0
- package/src/codegen/stdlib/time.js +54 -0
- package/src/codegen/stdlib/unicode.js +22 -0
- package/src/codegen/stdlib/utf8.js +23 -0
- package/src/codegen/templ.js +281 -0
- package/src/compiler.js +102 -62
- package/src/dts-parser.js +355 -371
- package/src/index.js +22 -54
- package/src/lexer.js +200 -286
- package/src/minifier.js +305 -318
- package/src/parser/expressions.js +54 -36
- package/src/{parser.js → parser/index.js} +12 -5
- package/src/parser/statements.js +29 -35
- package/src/parser/types.js +31 -29
- package/src/templ-lexer.js +737 -0
- package/src/templ-parser.js +235 -0
- package/src/tokens.js +109 -0
- package/src/typechecker/assignability.js +258 -0
- package/src/typechecker/expressions.js +559 -549
- package/src/typechecker/index.js +555 -0
- package/src/typechecker/resolve.js +421 -0
- package/src/typechecker/statements.js +267 -280
- package/src/typechecker/stdlib/core.js +592 -0
- package/src/typechecker/stdlib/extended.js +332 -0
- package/src/typechecker/stdlib.js +9 -1060
- package/src/typechecker/termination.js +83 -0
- package/src/typechecker/types.js +6 -3
- package/src/typechecker.js +0 -1271
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@ quite felt like home either.
|
|
|
7
7
|
So I built GoFront. Go syntax and type safety, compiling to plain ES modules. One language
|
|
8
8
|
front and back, no runtime, no framework, no tsconfig.json.
|
|
9
9
|
|
|
10
|
+
With built-in support for declarative DOM rendering via the [`gom`](https://www.gomponents.com) standard library, JSX-like [`.templ`](https://templ.guide/) files, and seamless integration with external JavaScript libraries through TypeScript definition files (`.d.ts`), GoFront is designed specifically as a frontend development target. Build complex, reactive user interfaces entirely in Go.
|
|
11
|
+
|
|
10
12
|
Probably not useful. Definitely fun to build.
|
|
11
13
|
|
|
12
14
|
```go
|
|
@@ -61,6 +63,12 @@ source text (.go files)
|
|
|
61
63
|
→ Parser recursive-descent → AST
|
|
62
64
|
→ Type Checker annotate AST with types + collect errors
|
|
63
65
|
→ Code Gen AST → JavaScript string
|
|
66
|
+
|
|
67
|
+
source text (.templ files)
|
|
68
|
+
→ TemplLexer dual-mode: Go mode for declarations, HTML mode inside templ bodies
|
|
69
|
+
→ TemplParser extends Parser; produces TemplDecl AST nodes with TemplNode children
|
|
70
|
+
→ Type Checker registers each templ component as func(...) gom.Node
|
|
71
|
+
→ Code Gen TemplDecl → direct DOM calls (createElement / setAttribute / appendChild)
|
|
64
72
|
```
|
|
65
73
|
|
|
66
74
|
### 1. Lexer (`src/lexer.js`)
|
|
@@ -100,9 +108,9 @@ operation on it is silently permitted, preventing cascading errors.
|
|
|
100
108
|
Walks the typed AST and emits clean, readable JavaScript. No intermediate representation
|
|
101
109
|
— the codegen writes directly to an output buffer with indentation tracking.
|
|
102
110
|
|
|
103
|
-
Runtime helpers (`__len`, `__append`, `__s`, `__sprintf`, `
|
|
104
|
-
`__errorIs`, `__timeFmt`, `__timeParse`, `__pathClean`) are tree-shaken: only
|
|
105
|
-
when actually used. Optional inline source maps are supported via VLQ-encoded mappings.
|
|
111
|
+
Runtime helpers (`__len`, `__append`, `__s`, `__sprintf`, `__equal`, `__cmul`, `__cdiv`,
|
|
112
|
+
`__error`, `__errorIs`, `__timeFmt`, `__timeParse`, `__pathClean`) are tree-shaken: only
|
|
113
|
+
emitted when actually used. Optional inline source maps are supported via VLQ-encoded mappings.
|
|
106
114
|
|
|
107
115
|
---
|
|
108
116
|
|
|
@@ -184,7 +192,7 @@ The type checker enforces correctness; JavaScript doesn't need to know.
|
|
|
184
192
|
|
|
185
193
|
## Examples — Todo App
|
|
186
194
|
|
|
187
|
-
There are
|
|
195
|
+
There are four example apps — all implement the same todo app to show different aspects
|
|
188
196
|
of GoFront.
|
|
189
197
|
|
|
190
198
|
### Simple (vanilla DOM)
|
|
@@ -244,6 +252,60 @@ The reactive example covers the full reactive.js API surface:
|
|
|
244
252
|
| Component instance | `signal`, `effect`, `on` (auto-cleanup event listeners) |
|
|
245
253
|
| Scan attributes | `data-model`, `data-text`, `data-html`, `data-if`, `data-visible`, `data-class-*`, `data-attr-*`, `data-bool-*`, `data-on-*`, `data-ref` |
|
|
246
254
|
|
|
255
|
+
### templ (template files + direct DOM codegen)
|
|
256
|
+
|
|
257
|
+
Same todo app using GoFront's `.templ` file format — a JSX-like syntax embedded directly
|
|
258
|
+
in `.go` packages. `templ` declarations compile to direct `document.createElement` calls
|
|
259
|
+
with no intermediate representation, producing `{Mount(p){}}` objects that are fully
|
|
260
|
+
compatible with the `gom.Node` interface.
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
example/templ/
|
|
264
|
+
src/
|
|
265
|
+
render.templ ← UI as templ declarations: TodoItem, TodoList, Header, InputRow, StatsBar, AppView, …
|
|
266
|
+
render.go ← helper functions (todoItemClass, filterLabel, …) + render() entry point
|
|
267
|
+
types.go ← Todo struct, filter/priority constants
|
|
268
|
+
store.go ← state, mutations, localStorage persistence
|
|
269
|
+
styles.go ← appStyles() CSS string
|
|
270
|
+
main.go ← event setup, entry point
|
|
271
|
+
utils/ ← Filter[T], Plural, HasText
|
|
272
|
+
app.js ← generated output
|
|
273
|
+
index.html ← HTML shell
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
`.templ` syntax at a glance:
|
|
277
|
+
|
|
278
|
+
```go
|
|
279
|
+
templ TodoItem(t Todo) {
|
|
280
|
+
<li class={ todoItemClass(t) } draggable="true" data-id={ t.id }>
|
|
281
|
+
<input type="checkbox" checked?={ t.done }/>
|
|
282
|
+
<span class="todo-text">{ t.text }</span>
|
|
283
|
+
if t.isUrgent() {
|
|
284
|
+
<span class="badge">urgent</span>
|
|
285
|
+
}
|
|
286
|
+
</li>
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
templ AppView() {
|
|
290
|
+
<div class="card">
|
|
291
|
+
@Header(highCount(), syncMsg, syncCls)
|
|
292
|
+
@TodoList(visibleTodos())
|
|
293
|
+
</div>
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Key syntax features:
|
|
298
|
+
- `{ expr }` — interpolate any Go expression (strings auto-cast, others use `String()`)
|
|
299
|
+
- `attr={ expr }` — dynamic attribute value (expression)
|
|
300
|
+
- `attr?={ expr }` — boolean attribute (present/absent based on truthiness)
|
|
301
|
+
- `@Component(args)` — call another templ component and mount it as a child
|
|
302
|
+
- `if cond { } else if cond { } else { }` — conditional rendering (arbitrary depth)
|
|
303
|
+
- `for _, v := range slice { }` — loop rendering inside template bodies
|
|
304
|
+
- `switch expr { case v: ... default: ... }` — switch rendering inside template bodies
|
|
305
|
+
- `@templ.Raw(htmlStr)` — inject raw/trusted HTML (uses `insertAdjacentHTML`)
|
|
306
|
+
- Components are called like regular functions (`AppView()`, `TodoItem(t)`) and return
|
|
307
|
+
a `gom.Node`-compatible object, so `gom.Mount("#app", AppView())` works directly.
|
|
308
|
+
|
|
247
309
|
### gom (stdlib component library + todo app)
|
|
248
310
|
|
|
249
311
|
Browser-native declarative DOM components inspired by
|
|
@@ -299,12 +361,19 @@ declarative node-tree pattern (no `innerHTML`, no `querySelector`), and full fea
|
|
|
299
361
|
parity with the other examples (priority mode, validation, localStorage persistence,
|
|
300
362
|
sync status, drag-and-drop reordering).
|
|
301
363
|
|
|
364
|
+
The templ example additionally demonstrates: **`.templ` file compilation**, template
|
|
365
|
+
components with parameters, `{ expr }` interpolation, `attr?={}` conditional boolean
|
|
366
|
+
attributes, `@Component()` calls inside templates, `if / else if / else` chains,
|
|
367
|
+
`switch` blocks, `for range` loops, and `@templ.Raw()` for trusted HTML injection —
|
|
368
|
+
all inside template bodies.
|
|
369
|
+
|
|
302
370
|
### Build and run
|
|
303
371
|
|
|
304
372
|
```sh
|
|
305
373
|
npm run build:simple # → example/simple/app.js
|
|
306
374
|
npm run build:reactive # → example/reactive/app.js
|
|
307
375
|
npm run build:gom # → example/gom/app.js
|
|
376
|
+
npm run build:templ # → example/templ/app.js
|
|
308
377
|
# open the respective index.html in a browser
|
|
309
378
|
```
|
|
310
379
|
|
|
@@ -377,7 +446,10 @@ func greet(name string) {
|
|
|
377
446
|
console.log("Hello, " + name)
|
|
378
447
|
}
|
|
379
448
|
|
|
380
|
-
greet(42)
|
|
449
|
+
greet(42)
|
|
450
|
+
// → Type error in src/main.go at line 5:7: cannot use int as string
|
|
451
|
+
// 5 | greet(42)
|
|
452
|
+
// ^
|
|
381
453
|
```
|
|
382
454
|
|
|
383
455
|
External TypeScript type definitions are supported via `js:` imports:
|
|
@@ -496,6 +568,7 @@ signatures into GoFront's internal type representation.
|
|
|
496
568
|
| Unused import detection | ✓ |
|
|
497
569
|
| External `.d.ts` types | ✓ |
|
|
498
570
|
| npm package type resolution | ✓ |
|
|
571
|
+
| `.templ` files in packages | ✓ — mix `.go` and `.templ` files freely; templ components visible across the whole package |
|
|
499
572
|
|
|
500
573
|
---
|
|
501
574
|
|
|
@@ -561,18 +634,21 @@ Design documents for planned features are organised by release under `docs/v*/`
|
|
|
561
634
|
## Tests
|
|
562
635
|
|
|
563
636
|
```sh
|
|
564
|
-
npm run test:unit # unit tests only (~
|
|
637
|
+
npm run test:unit # unit tests only (~1118 tests, no browser required)
|
|
565
638
|
npm run test:e2e # E2E tests (Playwright, headless Chromium)
|
|
566
|
-
npm test
|
|
639
|
+
npm run test:all # both
|
|
567
640
|
```
|
|
568
641
|
|
|
569
|
-
**Unit tests** (
|
|
642
|
+
**Unit tests** (~1118) cover language features, type errors, edge cases, DOM (jsdom),
|
|
570
643
|
external `.d.ts`, npm resolver, multi-file compilation, embedded structs, string
|
|
571
644
|
formatting, map iteration order, integer overflow semantics, unused variable detection,
|
|
572
|
-
unused import detection, semantic difference verification, stdlib shim packages,
|
|
573
|
-
|
|
645
|
+
unused import detection, semantic difference verification, stdlib shim packages, generics,
|
|
646
|
+
and `.templ` file compilation (element rendering, interpolation, boolean attrs, component
|
|
647
|
+
calls, `if/else/else-if` chains, `for range`, `switch/case/default`, `@templ.Raw()` raw
|
|
648
|
+
HTML injection, mixed `.go`+`.templ` packages).
|
|
574
649
|
|
|
575
|
-
**E2E tests** (
|
|
650
|
+
**E2E tests** (~104, Playwright) run all four example apps in a real browser and verify
|
|
576
651
|
CRUD, filtering, priority mode, persistence (reload), drag-and-drop reordering, and sync
|
|
577
652
|
status. Per-app suites check app-specific behaviour: scoped styles, stats bar, loading
|
|
578
|
-
placeholder,
|
|
653
|
+
placeholder, `gom.If` conditional rendering, and templ-specific features (`if/else`
|
|
654
|
+
priority hint, `for` loop rendering, conditional bool attributes).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gofront",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"author": "Luuk van Venrooij",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,16 +34,20 @@
|
|
|
34
34
|
"build:simple": "node src/index.js example/simple/src -o example/simple/app.js",
|
|
35
35
|
"build:reactive": "node src/index.js example/reactive/src -o example/reactive/app.js",
|
|
36
36
|
"build:gom": "node src/index.js example/gom/src -o example/gom/app.js",
|
|
37
|
-
"
|
|
37
|
+
"build:templ": "node src/index.js example/templ/src -o example/templ/app.js",
|
|
38
|
+
"build:all": "npm run build:simple && npm run build:reactive && npm run build:gom && npm run build:templ",
|
|
39
|
+
"test:all": "npm run test:unit && npm run test:e2e",
|
|
38
40
|
"test:unit": "node test/unit/run.js",
|
|
39
|
-
"test:
|
|
41
|
+
"test:coverage": "c8 --include='src/**' --reporter=text --reporter=lcov node test/unit/run.js",
|
|
42
|
+
"test:e2e": "npm run build:all && playwright test",
|
|
40
43
|
"format": "biome format --write .",
|
|
41
|
-
"check": "biome check . && node src/index.js example/simple/src --check && node src/index.js example/reactive/src --check && node src/index.js example/gom/src --check",
|
|
44
|
+
"check": "biome check . && sentrux check && sentrux gate && node src/index.js example/simple/src --check && node src/index.js example/reactive/src --check && node src/index.js example/gom/src --check && node src/index.js example/templ/src --check",
|
|
42
45
|
"prepare": "husky"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|
|
45
48
|
"@biomejs/biome": "^2.4.12",
|
|
46
49
|
"@playwright/test": "^1.59.1",
|
|
50
|
+
"c8": "^11.0.0",
|
|
47
51
|
"husky": "^9.1.7",
|
|
48
52
|
"jsdom": "^29.0.2",
|
|
49
53
|
"serve": "^14.2.6"
|