factor out kjol auth

This commit is contained in:
2026-07-14 16:49:56 -04:00
parent 7d7b7354df
commit 023599a41b
7 changed files with 1930 additions and 2 deletions

View File

@@ -31,8 +31,12 @@ var faStyleDirs = map[string]string{
var (
// icon="name" / icon: "name"
reIconAttr = regexp.MustCompile(`\bicon\s*(?:=|:)\s*"([a-z0-9][a-z0-9-]*)"`)
// icon={ ... } — dynamic expressions; pull any string literals (ternaries etc.)
reIconBrace = regexp.MustCompile(`\bicon\s*=\s*\{([^}]*)\}`)
// icon={ ... } — a dynamic expression; pull any string literals out of it
// (ternaries etc.). The `$` is optional because both authoring styles in this
// codebase have to be seen: JSX writes icon={"bell"}, while a solid-js/html
// tagged template writes icon=${"bell"}. Missing the second form drops the
// icon from the registry silently — it simply renders blank at runtime.
reIconBrace = regexp.MustCompile(`\bicon\s*=\s*\$?\{([^}]*)\}`)
reStrLit = regexp.MustCompile(`"([a-z0-9][a-z0-9-]*)"`)
reViewBox = regexp.MustCompile(`viewBox="0 0 ([0-9.]+) ([0-9.]+)"`)
rePathD = regexp.MustCompile(`<path[^>]*\bd="([^"]+)"`)

View File

@@ -0,0 +1,70 @@
package jsbundler
import (
"os"
"path/filepath"
"testing"
)
// scanIconNames has to see every authoring style used across the apps. Both are
// live in the same file in practice: a page written as a solid-js/html tagged
// template says icon=${"bell"}, while a .tsx page says icon={"bell"} or
// icon="bell". An icon the scanner misses is not a build error — it is simply
// absent from the generated registry and renders as a blank space at runtime,
// which is exactly how a missing bell/circle-question went unnoticed.
func TestScanIconNamesAcrossAuthoringStyles(t *testing.T) {
dir := t.TempDir()
src := `
// plain attribute (JSX or template)
<Icon icon="notebook" size={25} />
// JSX dynamic expression
<Icon icon={"gear"} />
// solid-js/html tagged template — interpolated string
<${Icon} icon=${"bell"} size=${28} />
<${Icon} icon=${"circle-question"} size=${28} />
// object-literal property
const item = { icon: "chart-line", label: "Reports" };
// dynamic expressions: every string literal inside is a candidate
<Icon icon={open ? "chevron-up" : "chevron-down"} />
<${Icon} icon=${busy ? "spinner" : "check"} />
// an in-app custom icon
registerIcon("playground", "<svg/>");
`
if err := os.WriteFile(filepath.Join(dir, "page.tsx"), []byte(src), 0644); err != nil {
t.Fatal(err)
}
names, custom, err := scanIconNames([]string{dir})
if err != nil {
t.Fatalf("scanIconNames: %v", err)
}
found := make(map[string]bool, len(names))
for _, n := range names {
found[n] = true
}
for _, want := range []string{
"notebook", // icon="name"
"gear", // icon={"name"}
"bell", // icon=${"name"} <- the regression
"circle-question", // icon=${"name"} <- the regression
"chart-line", // icon: "name"
"chevron-up", "chevron-down", // JSX ternary
"spinner", "check", // template-literal ternary
} {
if !found[want] {
t.Errorf("icon %q was not scanned; it would render blank at runtime", want)
}
}
if !custom["playground"] {
t.Error("registerIcon(\"playground\") was not picked up as a custom icon")
}
}