| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package main
- import (
- "bytes"
- "fmt"
- "io"
- "log"
- "net/http"
- "os"
- "path/filepath"
- "strings"
- )
- func main() {
- if len(os.Args) <= 1 || os.Args[1] == "serve" {
- serve()
- return
- }
- switch os.Args[1] {
- case "build":
- out := "dist/xjs.js"
- if len(os.Args) >= 3 && strings.TrimSpace(os.Args[2]) != "" {
- out = os.Args[2]
- }
- if err := build(out); err != nil {
- log.Fatal(err)
- }
- log.Printf("Built %s\n", out)
- default:
- fmt.Println("Usage:")
- fmt.Println(" go run main.go serve # dev server (default)")
- fmt.Println(" go run main.go build [out.js] # bundle animal.js + layer.js into dist/xjs.js (or out.js)")
- os.Exit(2)
- }
- }
- func serve() {
- // Serve files from the current directory
- fs := http.FileServer(http.Dir("."))
- http.Handle("/", fs)
- log.Println("Listening on :8080...")
- if err := http.ListenAndServe(":8080", nil); err != nil {
- log.Fatal(err)
- }
- }
- func readFile(path string) ([]byte, error) {
- f, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer f.Close()
- return io.ReadAll(f)
- }
- func ensureDirForFile(out string) error {
- dir := filepath.Dir(out)
- if dir == "." || dir == "/" {
- return nil
- }
- return os.MkdirAll(dir, 0o755)
- }
- func build(out string) error {
- animal, err := readFile("animal.js")
- if err != nil {
- return fmt.Errorf("read animal.js: %w", err)
- }
- layer, err := readFile("layer.js")
- if err != nil {
- return fmt.Errorf("read layer.js: %w", err)
- }
- var buf bytes.Buffer
- buf.WriteString("// xjs.js - combined single-file build (animal + layer)\n")
- buf.WriteString("// Generated by `go run main.go build`.\n")
- buf.WriteString("// NOTE: Do not edit this file directly in development.\n")
- buf.WriteString("// Edit animal.js / layer.js instead.\n\n")
- // Keep layer first to match previous bundled layout; runtime lookups are lazy anyway.
- buf.WriteString("/* --- layer.js --- */\n")
- buf.Write(layer)
- if !bytes.HasSuffix(layer, []byte("\n")) {
- buf.WriteByte('\n')
- }
- buf.WriteString("\n/* --- animal.js --- */\n")
- buf.Write(animal)
- if !bytes.HasSuffix(animal, []byte("\n")) {
- buf.WriteByte('\n')
- }
- // Export globals expected by docs/users.
- buf.WriteString("\n;(function(g){\n")
- buf.WriteString(" try { if (g && g.animal && !g.xjs) g.xjs = g.animal; } catch {}\n")
- buf.WriteString(" try { if (g && g.XJS_GLOBAL_DOLLAR && !g.$ && g.xjs) g.$ = g.xjs; } catch {}\n")
- buf.WriteString("})(typeof window !== 'undefined' ? window : (typeof globalThis !== 'undefined' ? globalThis : this));\n")
- if err := ensureDirForFile(out); err != nil {
- return fmt.Errorf("mkdir %s: %w", filepath.Dir(out), err)
- }
- if err := os.WriteFile(out, buf.Bytes(), 0o644); err != nil {
- return fmt.Errorf("write %s: %w", out, err)
- }
- return nil
- }
|