package source //go:generate go run generate_wiki.go import ( "fmt" "github.com/GeertJohan/go.rice" "github.com/pkg/errors" "github.com/russross/blackfriday/v2" "github.com/statping/statping/utils" "os" "path/filepath" "strings" ) var ( log = utils.Log.WithField("type", "source") TmplBox *rice.Box // HTML and other small files from the 'source/tmpl' directory, this will be loaded into '/assets' DefaultScss = []string{"scss/main.scss", "scss/base.scss", "scss/mobile.scss"} ) // Assets will load the Rice boxes containing the CSS, SCSS, JS, and HTML files. func Assets() error { var err error TmplBox, err = rice.FindBox("dist") return err } // HelpMarkdown will return the Markdown of help.md into HTML func HelpMarkdown() string { output := blackfriday.Run(CompiledWiki) return string(output) } func scssRendered(name string) string { spl := strings.Split(name, "/") path := spl[:len(spl)-2] file := spl[len(spl)-1] splFile := strings.Split(file, ".") return fmt.Sprintf("%s/css/%s.css", strings.Join(path, "/"), splFile[len(splFile)-2]) } // CompileSASS will attempt to compile the SASS files into CSS func CompileSASS(files ...string) error { sassBin := utils.Getenv("SASS", "sass").(string) for _, file := range files { scssFile := fmt.Sprintf("%v/assets/%v", utils.Directory, file) log.Infoln(fmt.Sprintf("Compiling SASS %v into %v", scssFile, scssRendered(scssFile))) stdout, stderr, err := utils.Command(sassBin, scssFile, scssRendered(scssFile)) if err != nil { log.Errorln(fmt.Sprintf("Failed to compile assets with SASS %v", err)) log.Errorln(fmt.Sprintf("%s %s %s", sassBin, scssFile, scssRendered(scssFile))) return errors.Wrapf(err, "failed to compile assets, %s %s %s", err, stdout, stderr) } if stdout != "" || stderr != "" { log.Errorln(fmt.Sprintf("Failed to compile assets with SASS %v %v %v", err, stdout, stderr)) return errors.Wrap(err, "failed to capture stdout or stderr") } if stdout != "" || stderr != "" { log.Infoln(fmt.Sprintf("out: %v | error: %v", stdout, stderr)) } } log.Infoln("SASS Compiling is complete!") return nil } // UsingAssets returns true if the '/assets' folder is found in the directory func UsingAssets(folder string) bool { if _, err := os.Stat(folder + "/assets"); err == nil { return true } else { useAssets := utils.Getenv("USE_ASSETS", false).(bool) if useAssets { log.Infoln("Environment variable USE_ASSETS was found.") if err := CreateAllAssets(folder); err != nil { log.Warnln(err) } err := CompileSASS(DefaultScss...) if err != nil { //CopyToPublic(CssBox, folder+"/css", "base.css") log.Warnln("Default 'base.css' was insert because SASS did not work.") return true } return true } } return false } // SaveAsset will save an asset to the '/assets/' folder. func SaveAsset(data []byte, path string) error { path = fmt.Sprintf("%s/assets/%s", utils.Directory, path) err := utils.SaveFile(path, data) if err != nil { log.Errorln(fmt.Sprintf("Failed to save %v, %v", path, err)) return err } return nil } // OpenAsset returns a file's contents as a string func OpenAsset(path string) string { path = fmt.Sprintf("%s/assets/%s", utils.Directory, path) data, err := utils.OpenFile(path) if err != nil { log.Errorln(fmt.Sprintf("Failed to open %v, %v", path, err)) return "" } return data } // CreateAllAssets will dump HTML, CSS, SCSS, and JS assets into the '/assets' directory func CreateAllAssets(folder string) error { log.Infoln(fmt.Sprintf("Dump Statping assets into %v/assets", folder)) fp := filepath.Join MakePublicFolder(fp(folder, "/assets")) MakePublicFolder(fp(folder, "assets", "js")) MakePublicFolder(fp(folder, "assets", "css")) MakePublicFolder(fp(folder, "assets", "scss")) MakePublicFolder(fp(folder, "assets", "font")) MakePublicFolder(fp(folder, "assets", "files")) log.Infoln("Inserting scss, css, and javascript files into assets folder") if err := CopyAllToPublic(TmplBox); err != nil { log.Errorln(err) return errors.Wrap(err, "copying all to public") } CopyToPublic(TmplBox, "", "robots.txt") CopyToPublic(TmplBox, "", "banner.png") CopyToPublic(TmplBox, "", "favicon.ico") CopyToPublic(TmplBox, "files", "swagger.json") CopyToPublic(TmplBox, "files", "postman.json") CopyToPublic(TmplBox, "files", "grafana.json") log.Infoln("Compiling CSS from SCSS style...") err := CompileSASS(DefaultScss...) log.Infoln("Statping assets have been inserted") return err } // DeleteAllAssets will delete the '/assets' folder func DeleteAllAssets(folder string) error { err := utils.DeleteDirectory(folder + "/assets") if err != nil { log.Infoln(fmt.Sprintf("There was an issue deleting Statping Assets, %v", err)) return err } log.Infoln("Statping assets have been deleted") return err } // CopyAllToPublic will copy all the files in a rice box into a local folder func CopyAllToPublic(box *rice.Box) error { exclude := map[string]bool{ "base.gohtml": true, "index.html": true, "swagger.json": true, "postman.json": true, "grafana.json": true, } err := box.Walk("/", func(path string, info os.FileInfo, err error) error { if info.Name() == "" { return nil } if exclude[info.Name()] { return nil } if info.IsDir() { return nil } utils.Log.Infoln(path) file, err := box.Bytes(path) if err != nil { return err } return SaveAsset(file, path) }) return err } // CopyToPublic will create a file from a rice Box to the '/assets' directory func CopyToPublic(box *rice.Box, path, file string) error { assetPath := fmt.Sprintf("%v/assets/%v/%v", utils.Directory, path, file) if path == "" { assetPath = fmt.Sprintf("%v/assets/%v", utils.Directory, file) } log.Infoln(fmt.Sprintf("Copying %v to %v", file, assetPath)) base, err := box.String(file) if err != nil { log.Errorln(fmt.Sprintf("Failed to copy %v to %v, %v.", file, assetPath, err)) return err } err = utils.SaveFile(assetPath, []byte(base)) if err != nil { log.Errorln(fmt.Sprintf("Failed to write file %v to %v, %v.", file, assetPath, err)) return err } return nil } // MakePublicFolder will create a new folder func MakePublicFolder(folder string) error { log.Infoln(fmt.Sprintf("Creating folder '%v'", folder)) if !utils.FolderExists(folder) { err := utils.CreateDirectory(folder) if err != nil { log.Errorln(fmt.Sprintf("Failed to created %v directory, %v", folder, err)) return err } } return nil }