// Package build makes the release: the files a site serves under // // and a static page links from one tag. // // Dist is the whole of it, a pure function of the tree it is handed, // so the same tree at the same version is the same bytes and the same // SHA256SUMS on anyone's machine. cmd/fiesta writes what Dist returns. package build import ( "bytes" "crypto/sha256" "encoding/hex" "fmt" "io/fs" "sort" "strings" ) // Banner is the one comment the release keeps, at the top of every // stylesheet and script: the version, the licence and where to read // more. Its /*! opener is the form minifiers keep by convention. func Banner(version string) string { return "/*! Fiesta " + version + " | MPL-2.0 | https://fiesta.rastrillo.org */\n" } // OneLinkLimit is the most a one-file theme may weigh gzipped: 25 KiB. // It is what a static page that links fiesta.css alone pays, so it is // the figure the size gate holds every bundle under. const OneLinkLimit = 25 * 1024 // Gzipped is the length of b compressed at gzip level 6, the level a // server or edge that compresses on the fly typically uses. func Gzipped(b []byte) int { return gzipped(b) } // defaultTheme is the theme fiesta.css carries; every other theme's // one-file form is fiesta-.css. const defaultTheme = "day" // svgNS is the namespace a standalone SVG document declares. The // inline icons leave it out, since HTML supplies it, and an or // a CSS url() will not draw an SVG without it. const svgNS = "http://www.w3.org/2000/svg" // bundleName is the one-file theme's file name for a theme. func bundleName(theme string) string { if theme == defaultTheme { return "fiesta.css" } return "fiesta-" + theme + ".css" } // bundlesIn is the one-file theme the dist owes for every theme it // carries: each top-level .css that is neither tokens.css, shell.css // nor a bundle is a theme's own file, and its bundle is bundleName of // it. Derived from the dist rather than listed, so a theme added to // css/themes/ cannot ship without its bundle passing the gate. func bundlesIn(dist map[string][]byte) []string { var names []string for name := range dist { if strings.Contains(name, "/") || !strings.HasSuffix(name, ".css") || name == "tokens.css" || name == "shell.css" || name == bundleName(defaultTheme) || strings.HasPrefix(name, "fiesta-") { continue } names = append(names, bundleName(strings.TrimSuffix(name, ".css"))) } sort.Strings(names) return names } // Dist builds the release from src, which needs LICENSE, css/, js/, // icons/ and i18n/ and is read for nothing else, keyed by path // relative to the version directory: // // - fiesta.css, fiesta-.css: the banner, then tokens.css and // the theme joined by a newline, stripped of comments; // - tokens.css, .css, shell.css: the banner and the stripped // file; // -