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.
Files changed (51) hide show
  1. package/README.md +88 -12
  2. package/package.json +8 -4
  3. package/src/codegen/expressions.js +520 -1717
  4. package/src/{codegen.js → codegen/index.js} +155 -184
  5. package/src/codegen/runtime.js +151 -0
  6. package/src/codegen/statements.js +305 -296
  7. package/src/codegen/stdlib/builder.js +36 -0
  8. package/src/codegen/stdlib/bytes.js +62 -0
  9. package/src/codegen/stdlib/errors.js +17 -0
  10. package/src/codegen/stdlib/fmt.js +101 -0
  11. package/src/codegen/stdlib/gom.js +152 -0
  12. package/src/codegen/stdlib/html.js +17 -0
  13. package/src/codegen/stdlib/index.js +95 -0
  14. package/src/codegen/stdlib/io.js +33 -0
  15. package/src/codegen/stdlib/maps.js +42 -0
  16. package/src/codegen/stdlib/math.js +53 -0
  17. package/src/codegen/stdlib/os.js +10 -0
  18. package/src/codegen/stdlib/path.js +31 -0
  19. package/src/codegen/stdlib/rand.js +24 -0
  20. package/src/codegen/stdlib/regexp.js +51 -0
  21. package/src/codegen/stdlib/slices.js +48 -0
  22. package/src/codegen/stdlib/sort.js +28 -0
  23. package/src/codegen/stdlib/strconv.js +30 -0
  24. package/src/codegen/stdlib/strings.js +83 -0
  25. package/src/codegen/stdlib/time.js +54 -0
  26. package/src/codegen/stdlib/unicode.js +22 -0
  27. package/src/codegen/stdlib/utf8.js +23 -0
  28. package/src/codegen/templ.js +281 -0
  29. package/src/compiler.js +102 -62
  30. package/src/dts-parser.js +355 -371
  31. package/src/index.js +22 -54
  32. package/src/lexer.js +200 -286
  33. package/src/minifier.js +305 -318
  34. package/src/parser/expressions.js +54 -36
  35. package/src/{parser.js → parser/index.js} +12 -5
  36. package/src/parser/statements.js +29 -35
  37. package/src/parser/types.js +31 -29
  38. package/src/templ-lexer.js +737 -0
  39. package/src/templ-parser.js +235 -0
  40. package/src/tokens.js +109 -0
  41. package/src/typechecker/assignability.js +258 -0
  42. package/src/typechecker/expressions.js +559 -549
  43. package/src/typechecker/index.js +555 -0
  44. package/src/typechecker/resolve.js +421 -0
  45. package/src/typechecker/statements.js +267 -280
  46. package/src/typechecker/stdlib/core.js +592 -0
  47. package/src/typechecker/stdlib/extended.js +332 -0
  48. package/src/typechecker/stdlib.js +9 -1060
  49. package/src/typechecker/termination.js +83 -0
  50. package/src/typechecker/types.js +6 -3
  51. 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`, `__cmul`, `__cdiv`, `__error`,
104
- `__errorIs`, `__timeFmt`, `__timeParse`, `__pathClean`) are tree-shaken: only emitted
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 three example apps — all implement the same todo app to show different aspects
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) // → Type error in src/main.go at line 5: cannot use int as string
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 (~1076 tests, no browser required)
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 # both
639
+ npm run test:all # both
567
640
  ```
568
641
 
569
- **Unit tests** (1076) cover language features, type errors, edge cases, DOM (jsdom),
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, and
573
- generics.
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** (74, Playwright) run all three example apps in a real browser and verify
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, and `gom.If` conditional rendering.
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.8",
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
- "test": "npm run test:unit && npm run test:e2e",
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:e2e": "playwright 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"