152 lines
3.9 KiB
Markdown
152 lines
3.9 KiB
Markdown
|
|
# AGENTS.md - Nebula Code Generator
|
||
|
|
|
||
|
|
> **Project**: Nebula - WebAwesome UI Library code generator for Go Templ
|
||
|
|
> **Module**: `github.com/sonr-io/nebula`
|
||
|
|
> **Go Version**: 1.25.5
|
||
|
|
|
||
|
|
## Build Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
go build -o nebula ./cmd/generate # Build binary
|
||
|
|
go run ./cmd/generate -input config.json -output pkg/wa # Run generator
|
||
|
|
go run ./cmd/generate -input config.json -output pkg/wa -verbose # Verbose
|
||
|
|
```
|
||
|
|
|
||
|
|
## Test Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
go test ./... # Run all tests
|
||
|
|
go test -v ./internal/generator # Single package
|
||
|
|
go test -v ./internal/generator -run TestToPascalCase # Single test by name
|
||
|
|
go test -cover ./... # With coverage
|
||
|
|
go test -coverprofile=coverage.out ./... && go tool cover -html=coverage.out
|
||
|
|
```
|
||
|
|
|
||
|
|
## Lint/Format
|
||
|
|
|
||
|
|
```bash
|
||
|
|
go fmt ./... # Format
|
||
|
|
gofmt -s -w . # Format with simplify
|
||
|
|
go vet ./... # Vet
|
||
|
|
staticcheck ./... # Static analysis (if installed)
|
||
|
|
golangci-lint run # Comprehensive lint (if installed)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Project Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
cmd/generate/main.go # CLI entry point
|
||
|
|
internal/generator/generator.go # Code generation with text/template
|
||
|
|
internal/generator/strings.go # String utilities (case conversion)
|
||
|
|
internal/parser/types.go # JSON schema types
|
||
|
|
config.json # WebAwesome web-types.json input
|
||
|
|
```
|
||
|
|
|
||
|
|
## Code Style
|
||
|
|
|
||
|
|
### Naming
|
||
|
|
|
||
|
|
| Element | Style | Example |
|
||
|
|
|---------|-------|---------|
|
||
|
|
| Exported | PascalCase | `Generator`, `ToPascalCase` |
|
||
|
|
| Unexported | camelCase | `funcMap`, `hasSlots` |
|
||
|
|
| Struct fields | PascalCase | `Element.Name` |
|
||
|
|
| JSON tags | kebab-case | `json:"doc-url"` |
|
||
|
|
| Files | lowercase | `strings.go` |
|
||
|
|
| Packages | lowercase, single word | `generator` |
|
||
|
|
|
||
|
|
### Imports
|
||
|
|
|
||
|
|
Standard library → blank line → external → blank line → internal:
|
||
|
|
|
||
|
|
```go
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
|
||
|
|
"github.com/sonr-io/nebula/internal/parser"
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Handling
|
||
|
|
|
||
|
|
```go
|
||
|
|
// Good: wrap with context
|
||
|
|
if err := tmpl.Execute(&buf, data); err != nil {
|
||
|
|
return fmt.Errorf("executing template: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bad: don't just log
|
||
|
|
if err != nil { log.Println(err) }
|
||
|
|
```
|
||
|
|
|
||
|
|
### Documentation
|
||
|
|
|
||
|
|
All exported functions MUST have doc comments starting with function name:
|
||
|
|
|
||
|
|
```go
|
||
|
|
// ToPascalCase converts kebab-case or snake_case to PascalCase
|
||
|
|
func ToPascalCase(s string) string {
|
||
|
|
```
|
||
|
|
|
||
|
|
### Struct Tags
|
||
|
|
|
||
|
|
```go
|
||
|
|
type Attribute struct {
|
||
|
|
Name string `json:"name"`
|
||
|
|
Description string `json:"description,omitempty"`
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Generator CLI Flags
|
||
|
|
|
||
|
|
| Flag | Default | Description |
|
||
|
|
|------|---------|-------------|
|
||
|
|
| `-input` | `web-types.json` | Input web-types.json path |
|
||
|
|
| `-output` | `pkg/wa` | Output directory |
|
||
|
|
| `-package` | `wa` | Generated package name |
|
||
|
|
| `-verbose` | `false` | Verbose output |
|
||
|
|
|
||
|
|
## Template Conventions
|
||
|
|
|
||
|
|
- Templates defined as string constants in `generator.go`
|
||
|
|
- Register functions via `template.FuncMap` in `generator.New()`
|
||
|
|
- Generated files header: `// Code generated by wa-generator. DO NOT EDIT.`
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
Use table-driven tests:
|
||
|
|
|
||
|
|
```go
|
||
|
|
func TestToPascalCase(t *testing.T) {
|
||
|
|
tests := []struct{ input, want string }{
|
||
|
|
{"wa-button", "WaButton"},
|
||
|
|
{"", ""},
|
||
|
|
}
|
||
|
|
for _, tt := range tests {
|
||
|
|
if got := ToPascalCase(tt.input); got != tt.want {
|
||
|
|
t.Errorf("ToPascalCase(%q) = %q, want %q", tt.input, got, tt.want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Generated Outputs
|
||
|
|
|
||
|
|
| File | Purpose |
|
||
|
|
|------|---------|
|
||
|
|
| `{component}.templ` | Individual component files |
|
||
|
|
| `types.go` | Shared types (Variant, Size, etc.) |
|
||
|
|
| `builders.go` | Builder pattern helpers |
|
||
|
|
| `cdn.templ` | CDN loader templates |
|
||
|
|
| `events.go` | Event constants and handlers |
|
||
|
|
|
||
|
|
## Do NOT
|
||
|
|
|
||
|
|
- Use `panic()` for recoverable errors - return errors
|
||
|
|
- Modify generated files - edit templates instead
|
||
|
|
- Use global variables - use struct methods
|
||
|
|
- Commit generated files without running generator
|
||
|
|
- Suppress type errors with unsafe patterns
|