gofront 0.0.5 → 0.0.7
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 +104 -37
- package/package.json +7 -4
- package/src/codegen/expressions.js +589 -7
- package/src/codegen/source-map.js +13 -5
- package/src/codegen/statements.js +30 -26
- package/src/codegen.js +99 -22
- package/src/compiler.js +10 -3
- package/src/dev-server.js +83 -0
- package/src/index.js +35 -5
- package/src/parser.js +0 -10
- package/src/typechecker/expressions.js +38 -9
- package/src/typechecker/stdlib.js +764 -0
- package/src/typechecker/types.js +15 -20
- package/src/typechecker.js +34 -394
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
## About
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Go for the backend: simple, type-safe, no nonsense. JavaScript for the frontend: runs
|
|
4
|
+
everywhere, no setup. The problem is JavaScript's loose typing — and TypeScript never
|
|
5
|
+
quite felt like home either.
|
|
6
6
|
|
|
7
|
-
So I built GoFront. Go syntax
|
|
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
|
-
|
|
10
|
+
Probably not useful. Definitely fun to build.
|
|
11
11
|
|
|
12
12
|
```go
|
|
13
13
|
package main
|
|
@@ -184,7 +184,7 @@ The type checker enforces correctness; JavaScript doesn't need to know.
|
|
|
184
184
|
|
|
185
185
|
## Examples — Todo App
|
|
186
186
|
|
|
187
|
-
There are
|
|
187
|
+
There are three example apps — all implement the same todo app to show different aspects
|
|
188
188
|
of GoFront.
|
|
189
189
|
|
|
190
190
|
### Simple (vanilla DOM)
|
|
@@ -202,7 +202,7 @@ example/simple/
|
|
|
202
202
|
styles.go ← injectStyles() creates <style> element with all CSS
|
|
203
203
|
main.go ← createApp() builds DOM shell · setupEvents() · event delegation
|
|
204
204
|
utils/
|
|
205
|
-
utils.go ← Plural() · generic Filter
|
|
205
|
+
utils.go ← Plural() · generic Filter — cross-package import demo
|
|
206
206
|
browser.d.ts ← minimal external type declarations (sleep)
|
|
207
207
|
index.html ← bare HTML shell, loads app.js as ES module
|
|
208
208
|
app.js ← generated output
|
|
@@ -212,41 +212,99 @@ example/simple/
|
|
|
212
212
|
|
|
213
213
|
Same app rebuilt with [reactive.js](https://github.com/seriva/microtastic), a tiny
|
|
214
214
|
signals-based reactive framework. Demonstrates how GoFront integrates with external JS
|
|
215
|
-
libraries via `.d.ts` type declarations — the
|
|
216
|
-
|
|
217
|
-
all described in a hand-written `browser.d.ts` shim.
|
|
215
|
+
libraries via `.d.ts` type declarations — the entire reactive API surface is typed via a
|
|
216
|
+
hand-written `browser.d.ts` shim and exercised from GoFront source.
|
|
218
217
|
|
|
219
218
|
```
|
|
220
219
|
example/reactive/
|
|
221
220
|
src/
|
|
222
221
|
types.go ← Todo, Stats, AppElements structs
|
|
223
|
-
store.go ←
|
|
224
|
-
render.go ←
|
|
225
|
-
styles.go ←
|
|
226
|
-
main.go ←
|
|
222
|
+
store.go ← reactive state: Signals.create/computed/computedAsync/batch/update
|
|
223
|
+
render.go ← Reactive.Component lifecycle · ctx.bind* · setupStatsBar
|
|
224
|
+
styles.go ← per-section cssClass() scoped styles
|
|
225
|
+
main.go ← async boot, Reactive.mount loading placeholder, signal.subscribe/once
|
|
227
226
|
utils/
|
|
228
|
-
utils.go ← Plural() · generic Filter
|
|
229
|
-
browser.d.ts ← Signal
|
|
227
|
+
utils.go ← Plural() · generic Filter
|
|
228
|
+
browser.d.ts ← Signal · ComponentContext · Signals/Reactive namespaces · htmlTag
|
|
230
229
|
reactive.js ← signals framework (from microtastic)
|
|
231
|
-
index.html ← loads reactive.js
|
|
230
|
+
index.html ← loads reactive.js, exposes helpers, imports app.js
|
|
232
231
|
app.js ← generated output
|
|
233
232
|
```
|
|
234
233
|
|
|
234
|
+
The reactive example covers the full reactive.js API surface:
|
|
235
|
+
|
|
236
|
+
| Category | Features used |
|
|
237
|
+
|---|---|
|
|
238
|
+
| HTML helpers | `html` tagged template (via `htmlTag`), `trusted`, `join` |
|
|
239
|
+
| CSS | `cssClass` scoped styles with nested `&` selectors |
|
|
240
|
+
| Signals | `create`, `computed`, `computedAsync`, `batch`, `get`, `peek`, `set`, `update`, `subscribe`, `once` |
|
|
241
|
+
| Reactive namespace | `mount` (loading placeholder), `createComponent`, `scan` |
|
|
242
|
+
| Component context | `bind`, `bindAttr`, `bindBoolAttr`, `bindClass`, `bindText`, `bindStyle`, `bindMultiple`, `computed` |
|
|
243
|
+
| Component lifecycle | `state`, `template`, `styles`, `mount`, `mountTo`, `appendTo`, `refs` (via `data-ref`) |
|
|
244
|
+
| Component instance | `signal`, `effect`, `on` (auto-cleanup event listeners) |
|
|
245
|
+
| Scan attributes | `data-model`, `data-text`, `data-html`, `data-if`, `data-visible`, `data-class-*`, `data-attr-*`, `data-bool-*`, `data-on-*`, `data-ref` |
|
|
246
|
+
|
|
247
|
+
### gom (stdlib component library + todo app)
|
|
248
|
+
|
|
249
|
+
Browser-native declarative DOM components inspired by
|
|
250
|
+
[gomponents](https://www.gomponents.com). `gom` is a **built-in stdlib package** — no
|
|
251
|
+
import path needed, available in every GoFront program just like `fmt` or `strings`. It
|
|
252
|
+
uses **methods on named non-struct types** so that plain functions and slices can satisfy
|
|
253
|
+
the `Node` interface without any struct boilerplate.
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
example/gom/
|
|
257
|
+
src/
|
|
258
|
+
types.go ← Todo struct, filter/priority constants
|
|
259
|
+
store.go ← state, mutations, localStorage persistence
|
|
260
|
+
render.go ← gom node builders (pure node tree, no innerHTML)
|
|
261
|
+
styles.go ← appStyles() CSS string
|
|
262
|
+
main.go ← event setup, submitInput, entry point
|
|
263
|
+
utils/ ← Filter[T], Plural, HasText
|
|
264
|
+
app.js ← generated output
|
|
265
|
+
index.html ← HTML shell
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Key types and functions (all accessed as `gom.*`, no import needed):
|
|
269
|
+
- `gom.Node` — interface with a single `Mount(parent any)` method
|
|
270
|
+
- `gom.NodeFunc` — `type NodeFunc func(parent any)` with `Mount` method; any function becomes a `Node`
|
|
271
|
+
- `gom.Group` — `type Group []Node` with `Mount` method; composes children in order
|
|
272
|
+
- `gom.El(tag, children...)` — creates an element node
|
|
273
|
+
- `gom.Text(s)` — creates a text node
|
|
274
|
+
- `gom.Attr(name, val)` — generic attribute node; named shortcuts: `gom.Class`, `gom.Href`, `gom.Type`, etc.
|
|
275
|
+
- `gom.If(cond, node)` — conditionally renders a node
|
|
276
|
+
- `gom.Map(slice, fn)` — maps a slice to a `Group` of nodes
|
|
277
|
+
- `gom.Style(css)` — returns a `Node` that injects a `<style>` element; styles are part of the node tree
|
|
278
|
+
- `gom.Mount(selector, n)` — mounts a node into the DOM, replacing the element's content
|
|
279
|
+
- `gom.MountTo(selector, n)` — appends a node without clearing; used to inject styles into `<head>`
|
|
280
|
+
- HTML element helpers: `gom.Div`, `gom.Span`, `gom.Button`, `gom.Input`, `gom.Ul`, `gom.Li`, … (full HTML element set)
|
|
281
|
+
|
|
235
282
|
### Features demonstrated
|
|
236
283
|
|
|
237
|
-
|
|
238
|
-
slices, `for range`, `switch`, cross-package imports, multi-file
|
|
239
|
-
`async`/`await`, `defer`/`recover`, localStorage persistence,
|
|
240
|
-
utility functions (`Filter[T]`, `Map[T, U]`).
|
|
284
|
+
The simple and reactive examples cover: structs & methods, iota constants, named return
|
|
285
|
+
values, closures, slices, `for range`, `switch`, cross-package imports, multi-file
|
|
286
|
+
same-package compilation, `async`/`await`, `defer`/`recover`, localStorage persistence,
|
|
287
|
+
DOM APIs, and generic utility functions (`Filter[T]`, `Map[T, U]`).
|
|
241
288
|
|
|
242
289
|
The reactive example additionally demonstrates: external `.d.ts` type imports,
|
|
243
|
-
`declare namespace` patterns for typing JS libraries,
|
|
290
|
+
`declare namespace` patterns for typing JS libraries, the full reactive signal graph
|
|
291
|
+
(source signals → computed signals → async computed → DOM bindings), reactive UI with
|
|
292
|
+
no `querySelector` or `getElementById` in application code, and `Reactive.Component`
|
|
293
|
+
as the primary composition unit (state, template, styles, mount lifecycle, `data-ref`
|
|
294
|
+
element refs, auto-cleanup event listeners).
|
|
295
|
+
|
|
296
|
+
The gom example additionally demonstrates: **the `gom` built-in stdlib package**,
|
|
297
|
+
styles as nodes (`gom.Style` + `gom.MountTo`), `gom.Map` for list rendering, the
|
|
298
|
+
declarative node-tree pattern (no `innerHTML`, no `querySelector`), and full feature
|
|
299
|
+
parity with the other examples (priority mode, validation, localStorage persistence,
|
|
300
|
+
sync status, drag-and-drop reordering).
|
|
244
301
|
|
|
245
302
|
### Build and run
|
|
246
303
|
|
|
247
304
|
```sh
|
|
248
305
|
npm run build:simple # → example/simple/app.js
|
|
249
306
|
npm run build:reactive # → example/reactive/app.js
|
|
307
|
+
npm run build:gom # → example/gom/app.js
|
|
250
308
|
# open the respective index.html in a browser
|
|
251
309
|
```
|
|
252
310
|
|
|
@@ -258,16 +316,18 @@ npm run build:reactive # → example/reactive/app.js
|
|
|
258
316
|
gofront <file.go> compile single file → stdout
|
|
259
317
|
gofront <dir> compile all *.go in directory → stdout
|
|
260
318
|
gofront <input> -o out.js write output to file (prints elapsed compile time e.g. "15ms")
|
|
261
|
-
gofront <input> --check
|
|
262
|
-
gofront <input> --watch
|
|
263
|
-
gofront <input>
|
|
264
|
-
gofront <input> --
|
|
265
|
-
gofront <input> --
|
|
266
|
-
gofront <
|
|
267
|
-
gofront <
|
|
268
|
-
gofront
|
|
269
|
-
gofront --
|
|
270
|
-
gofront
|
|
319
|
+
gofront <input> --check type-check only
|
|
320
|
+
gofront <input> --watch watch for changes and recompile
|
|
321
|
+
gofront <input> -o out.js --serve watch + serve with live reload (default port 3000)
|
|
322
|
+
gofront <input> -o out.js --serve --port 8080 use a custom port
|
|
323
|
+
gofront <input> --source-map append inline source map (single file or directory; multi-file packages emit per-file mappings)
|
|
324
|
+
gofront <input> --minify minify output (built-in minifier)
|
|
325
|
+
gofront <input> --minify --mangle minify and rename local identifiers
|
|
326
|
+
gofront <file.go> --ast dump AST (debug)
|
|
327
|
+
gofront <file.go> --tokens dump tokens (debug)
|
|
328
|
+
gofront init [dir] scaffold a new project
|
|
329
|
+
gofront --version / -v print version
|
|
330
|
+
gofront --help / -h print this help
|
|
271
331
|
```
|
|
272
332
|
|
|
273
333
|
---
|
|
@@ -365,6 +425,7 @@ signatures into GoFront's internal type representation.
|
|
|
365
425
|
| `error` type | ✓ — interface `{ Error() string }`; custom error types, `errors.Is`/`Unwrap`, `%w` wrapping |
|
|
366
426
|
| Complex numbers (`complex64`, `complex128`, `3i`) | ✓ — `complex()`, `real()`, `imag()` builtins; `__cmul`/`__cdiv` helpers |
|
|
367
427
|
| Type definitions, type aliases (`type A = B`) | ✓ |
|
|
428
|
+
| Methods on named non-struct types | ✓ — `type T func(...)` or `type T []E` with methods; emitted as ES6 wrapper classes; satisfies interfaces |
|
|
368
429
|
| Type conversions, type assertions (plain & comma-ok) | ✓ |
|
|
369
430
|
| Type switch (`switch v := x.(type)`) | ✓ — compiles to `if/else if` with `typeof` / `instanceof` |
|
|
370
431
|
| Sized integers (`int8`–`int64`, `uint8`–`uint64`, `float32`) | ✓ — mapped to `number` at runtime |
|
|
@@ -403,16 +464,22 @@ signatures into GoFront's internal type representation.
|
|
|
403
464
|
|
|
404
465
|
| Package | Functions |
|
|
405
466
|
|---|---|
|
|
406
|
-
| `fmt` | `Sprintf`, `Printf`, `Println`, `Print`, `Errorf` — format verbs: `%v`, `%d`, `%s`, `%t`, `%x`, `%o`, `%b`, `%q`, `%e`, `%g`, `%w`, width/precision |
|
|
407
|
-
| `strings` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `LastIndex`, `Count`, `Repeat`, `Replace`, `ReplaceAll`, `ToUpper`, `ToLower`, `TrimSpace`, `Trim`, `TrimPrefix`, `TrimSuffix`, `TrimLeft`, `TrimRight`, `Split`, `Join`, `EqualFold` |
|
|
408
|
-
| `bytes` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `Join`, `Split`, `Replace`, `ToUpper`, `ToLower`, `TrimSpace`, `Equal`, `Count`, `Repeat` |
|
|
467
|
+
| `fmt` | `Sprintf`, `Printf`, `Println`, `Print`, `Errorf`, `Fprintf`, `Fprintln`, `Fprint` — format verbs: `%v`, `%d`, `%s`, `%t`, `%x`, `%o`, `%b`, `%q`, `%e`, `%g`, `%w`, width/precision |
|
|
468
|
+
| `strings` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `LastIndex`, `Count`, `Repeat`, `Replace`, `ReplaceAll`, `ToUpper`, `ToLower`, `TrimSpace`, `Trim`, `TrimPrefix`, `TrimSuffix`, `TrimLeft`, `TrimRight`, `Split`, `Join`, `EqualFold`; **`Builder`** type (`WriteString`, `WriteByte`, `WriteRune`, `Write`, `String`, `Len`, `Reset`, `Grow`) |
|
|
469
|
+
| `bytes` | `Contains`, `HasPrefix`, `HasSuffix`, `Index`, `Join`, `Split`, `Replace`, `ToUpper`, `ToLower`, `TrimSpace`, `Equal`, `Count`, `Repeat`; **`Buffer`** type (`WriteString`, `WriteByte`, `Write`, `String`, `Bytes`, `Len`, `Reset`) |
|
|
409
470
|
| `strconv` | `Itoa`, `Atoi`, `FormatBool`, `FormatInt`, `FormatFloat`, `ParseFloat`, `ParseInt`, `ParseBool` |
|
|
410
471
|
| `sort` | `Ints`, `Float64s`, `Strings`, `Slice`, `SliceStable`, `SliceIsSorted` |
|
|
411
472
|
| `math` | `Abs`, `Floor`, `Ceil`, `Round`, `Sqrt`, `Cbrt`, `Pow`, `Log`, `Log2`, `Log10`, trig functions + `Pi`, `E`, `MaxFloat64`, `MaxInt`, `MinInt` |
|
|
412
473
|
| `errors` | `New`, `Is`, `Unwrap` — custom error types via interface satisfaction |
|
|
413
474
|
| `time` | `Now`, `Since`, `Sleep` + `Millisecond`, `Second`, `Minute`, `Hour` constants |
|
|
475
|
+
| `html` | `EscapeString`, `UnescapeString` |
|
|
476
|
+
| `maps` | `Keys`, `Values`, `Clone`, `Copy`, `Equal`, `EqualFunc`, `Delete`, `DeleteFunc` |
|
|
477
|
+
| `slices` | `Contains`, `Index`, `Equal`, `Compare`, `Sort`, `SortFunc`, `SortStableFunc`, `IsSorted`, `IsSortedFunc`, `Reverse`, `Max`, `Min`, `MaxFunc`, `MinFunc`, `Clone`, `Compact`, `CompactFunc`, `Concat`, `Delete`, `DeleteFunc`, `Insert`, `Replace`, `Grow`, `Clip` |
|
|
478
|
+
| `regexp` | `MustCompile`, `Compile`, `MatchString`, `QuoteMeta`; **`*Regexp`** methods: `MatchString`, `FindString`, `FindStringIndex`, `FindAllString`, `FindStringSubmatch`, `FindAllStringSubmatch`, `ReplaceAllString`, `ReplaceAllLiteralString`, `Split`, `String`. Inline flags (`(?i)`, `(?m)`, `(?s)`) are extracted automatically into the JS `RegExp` constructor. |
|
|
414
479
|
| `unicode` | `IsLetter`, `IsDigit`, `IsSpace`, `IsUpper`, `IsLower`, `IsPunct`, `IsControl`, `IsPrint`, `IsGraphic`, `ToUpper`, `ToLower` |
|
|
415
480
|
| `os` | `Exit`, `Args`, `Getenv` |
|
|
481
|
+
| `io` | `Writer`, `Reader`, `ReadWriter`, `Closer` interface types — used for accepting `*strings.Builder`, `*bytes.Buffer`, or any compatible writer/reader |
|
|
482
|
+
| `gom` | Browser-native declarative DOM component library. **Types**: `Node` (interface), `NodeFunc`, `Group`. **Core**: `El(tag, children...)`, `Text(s)`, `Mount(sel, node)`, `MountTo(sel, node)`. **Attributes**: `Attr`, `Class`, `Href`, `Type`, `Src`, `Placeholder`, `DataAttr`, `Style`, `For`, `Name`, `Value`, `Target`, `Rel`, `Alt`, `Title`, `Draggable`, `Role`, `AriaLabel`, `StyleAttr`; boolean: `Disabled`, `Checked`, `Selected`, `Readonly`. **Logic**: `If(cond, node)`, `Map(slice, fn)`. **Elements**: full HTML element set (`Div`, `Span`, `Button`, `Input`, `Ul`, `Li`, `Table`, `Form`, `Img`, `A`, `H1`–`H6`, …) |
|
|
416
483
|
|
|
417
484
|
### Packages & imports
|
|
418
485
|
|
|
@@ -484,7 +551,7 @@ you know exactly what to expect.
|
|
|
484
551
|
|
|
485
552
|
See [`docs/ROADMAP.md`](docs/ROADMAP.md) for the full roadmap and release history.
|
|
486
553
|
Design documents for planned features are organised by release under `docs/v*/`
|
|
487
|
-
(e.g. [`docs/v0.0.
|
|
554
|
+
(e.g. [`docs/v0.0.8/`](docs/v0.0.8/), [`docs/v0.0.9/`](docs/v0.0.9/)).
|
|
488
555
|
|
|
489
556
|
---
|
|
490
557
|
|
|
@@ -494,7 +561,7 @@ Design documents for planned features are organised by release under `docs/v*/`
|
|
|
494
561
|
npm test
|
|
495
562
|
```
|
|
496
563
|
|
|
497
|
-
|
|
564
|
+
990 tests covering language features, type errors, edge cases, DOM (jsdom), external
|
|
498
565
|
`.d.ts`, npm resolver, multi-file compilation, embedded structs, string formatting, map
|
|
499
566
|
iteration order, integer overflow semantics, unused variable detection, unused import
|
|
500
567
|
detection, semantic difference verification, stdlib shim packages, generics (type params,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gofront",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"author": "Luuk van Venrooij",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -33,12 +33,15 @@
|
|
|
33
33
|
"scripts": {
|
|
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": "node test/unit/run.js",
|
|
37
38
|
"format": "biome format --write .",
|
|
38
|
-
"check": "biome check ."
|
|
39
|
+
"check": "biome check .",
|
|
40
|
+
"prepare": "husky"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
|
-
"@biomejs/biome": "^2.4.
|
|
43
|
+
"@biomejs/biome": "^2.4.12",
|
|
44
|
+
"husky": "^9.1.7",
|
|
42
45
|
"jsdom": "^29.0.2"
|
|
43
46
|
}
|
|
44
47
|
}
|