package main import ( "bufio" "bytes" "compress/gzip" "encoding/base64" "errors" "fmt" "io" "io/ioutil" "log" "net/http" "os" "strings" "text/template" "time" ) const b64Width = 76 var ( webAssetsTmpl = template.Must(template.New("web_assets").Parse("" + "// WARNING: GENERATED FILE, NERDS! {{.Now}}\n" + "package conway\n" + "\n" + "const (\n" + " GAME_OF_LIFE_INDEX_HTML = `{{.IndexHTML}}`\n" + " NORMALIZE_CSS = `{{.NormalizeCSS}}`\n" + " JQUERY_MIN_JS = `{{.JqueryMinJS}}`\n" + ")\n")) normalizeCssUrl = "http://necolas.github.com/normalize.css/2.0.1/normalize.css" jqueryMinJsUrl = "http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" ) type webAssetStrings struct { IndexHTML string NormalizeCSS string JqueryMinJS string Now time.Time } func die(err error) { log.Fatal("CRUD:", err) } func toB64(input []byte) string { var ( err error out bytes.Buffer ) encoded := base64.StdEncoding.EncodeToString(input) lenEncoded := len(encoded) outbuf := bufio.NewWriter(&out) inbuf := strings.NewReader(encoded) outbuf.WriteByte('\n') if err != nil { die(err) } nWritten := 0 for { for n := 0; n < b64Width; n++ { c, err := inbuf.ReadByte() if err == io.EOF { break } if err != nil { die(err) } err = outbuf.WriteByte(c) if err != nil { die(err) } nWritten++ } _, err := inbuf.ReadByte() if err == io.EOF { break } if err != nil { die(err) } err = inbuf.UnreadByte() if err != nil { die(err) } err = outbuf.WriteByte('\n') if err != nil { die(err) } } if nWritten != lenEncoded { die(errors.New(fmt.Sprintf("base64-encoded length = %d, but wrote %d", lenEncoded, nWritten))) } outbuf.Flush() return string(out.Bytes()) } func toGz(input []byte) []byte { var buf bytes.Buffer zwriter, err := gzip.NewWriterLevel(&buf, gzip.BestCompression) if err != nil { die(err) } zbuf := bufio.NewWriter(zwriter) toWrite := len(input) for written := 0; written < toWrite; { n, err := zbuf.Write(input[written:]) if err != nil { die(err) } written += n } zbuf.Flush() zwriter.Close() return buf.Bytes() } func fetchUrl(url string) []byte { resp, err := http.Get(url) if err != nil { die(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { die(err) } return body } func fetchIndexHtml(indexHtmlPath string) []byte { fd, err := os.Open(indexHtmlPath) if err != nil { die(err) } body, err := ioutil.ReadAll(fd) if err != nil { die(err) } return body } func toB64Gz(input []byte) string { return string(toB64(toGz(input))) } func main() { if len(os.Args) < 2 { die(errors.New(fmt.Sprintf("Usage: %s ", os.Args[0]))) } assets := &webAssetStrings{ IndexHTML: toB64Gz(fetchIndexHtml(os.Args[1])), NormalizeCSS: toB64Gz(fetchUrl(normalizeCssUrl)), JqueryMinJS: toB64Gz(fetchUrl(jqueryMinJsUrl)), Now: time.Now(), } webAssetsTmpl.Execute(os.Stdout, assets) }