rename packages, refactor out tailwind compiler,

This commit is contained in:
2026-07-13 15:06:09 -04:00
parent c5b14d7c41
commit d52151cc1a
62 changed files with 1446 additions and 460 deletions

View File

@@ -0,0 +1,87 @@
package webbundler
// esbuild silently resolves a `.js` import to a sibling `.ts`/`.tsx`/`.jsx`,
// which lets misnamed specifiers slip through. This check catches them up
// front so every import path names the file that actually exists on disk.
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)
type importViolation struct {
file string
line int
spec string // the written specifier, e.g. "./Icons.js"
actual string // the corrected specifier, e.g. "./Icons.ts"
}
// reImportSpec matches a quoted relative module specifier ending in ".js".
var reImportSpec = regexp.MustCompile(`(["'])((?:\.\.?/)[^"']*?\.js)["']`)
// tsExtensions are the non-.js source extensions a .js specifier may
// actually resolve to, in esbuild's resolution order.
var tsExtensions = []string{".ts", ".tsx", ".jsx"}
// checkImportExtensions scans every JS/TS source under frontend/src for
// relative import specifiers written with a ".js" extension whose literal
// target does not exist but a sibling ".ts"/".tsx"/".jsx" does. esbuild
// resolves these transparently, so they bundle fine — but the import path
// lies about the file it points to. Specifiers that resolve to a real ".js"
// file, and dangling specifiers with no sibling at all, are left for esbuild.
func checkImportExtensions() []importViolation {
var violations []importViolation
srcRoot := filepath.Join(frontendDir, "src")
filepath.WalkDir(srcRoot, func(path string, d os.DirEntry, err error) error {
if err != nil || d.IsDir() {
return err
}
switch filepath.Ext(path) {
case ".js", ".ts", ".tsx", ".jsx":
default:
return nil
}
raw, err := os.ReadFile(path)
if err != nil {
return err
}
dir := filepath.Dir(path)
for i, line := range strings.Split(string(raw), "\n") {
for _, m := range reImportSpec.FindAllStringSubmatch(line, -1) {
spec := m[2]
if _, statErr := os.Stat(filepath.Join(dir, spec)); statErr == nil {
continue // resolves to a real .js file — fine
}
base := strings.TrimSuffix(spec, ".js")
for _, ext := range tsExtensions {
if _, statErr := os.Stat(filepath.Join(dir, base+ext)); statErr == nil {
violations = append(violations, importViolation{
file: path,
line: i + 1,
spec: spec,
actual: base + ext,
})
break
}
}
}
}
return nil
})
return violations
}
func reportImportViolations(violations []importViolation) {
fmt.Fprintf(os.Stderr, "\nImport extension check failed: %d import(s) use a .js extension for a non-.js file.\n", len(violations))
for _, v := range violations {
fmt.Fprintf(os.Stderr, " %s:%d: %q should be %q\n", v.file, v.line, v.spec, v.actual)
}
fmt.Fprintln(os.Stderr, "Rename each specifier to match the file's real extension.")
}