package jsbundler import ( "fmt" "os" "path/filepath" "regexp" "sort" "strconv" "strings" ) // Tree-shaken FontAwesome. Instead of shipping the 41.5 MB `all.min.js` kit and // looking icons up by runtime string, we scan the app for the icon names it // actually references and emit a registry of just those icons' SVG data, pulled // from the FontAwesome SVGs under the icon roots. Icons.tsx looks up that // registry exactly like it used to call FontAwesome.findIconDefinition. // FA prefix -> /. cdrateline renders classic far/fas; a Sharp // project (fasr/fass) would add "fasr": "sharp-regular", "fass": "sharp-solid". var faStyleDirs = map[string]string{ "far": "regular", "fas": "solid", } // The FA SVG source roots (iconsDirs — the app's kit, then kjol's) and the // generated registry output path (faOutPath) are resolved from Config — see // config.go. Only the styles in faStyleDirs are read; the rest of the kit is // unused. var ( // icon="name" / icon: "name" reIconAttr = regexp.MustCompile(`\bicon\s*(?:=|:)\s*"([a-z0-9][a-z0-9-]*)"`) // 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(`]*\bd="([^"]+)"`) // registerIcon("name", …) — custom (non-FontAwesome) icons defined in-app. reRegisterIcon = regexp.MustCompile(`registerIcon\(\s*"([a-z0-9][a-z0-9-]*)"`) ) // presentIconsDirs is iconsDirs filtered to the roots that actually exist, so a // missing kit is skipped rather than failing every icon lookup against it. func presentIconsDirs() []string { var roots []string for _, d := range iconsDirs() { if _, err := os.Stat(d); err == nil { roots = append(roots, d) } } return roots } // readIconSVG returns the first /