226 lines
6.3 KiB
Go
226 lines
6.3 KiB
Go
// Statup
|
|
// Copyright (C) 2018. Hunter Long and the project contributors
|
|
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
|
//
|
|
// https://github.com/hunterlong/statup
|
|
//
|
|
// The licenses for most software and other practical works are designed
|
|
// to take away your freedom to share and change the works. By contrast,
|
|
// the GNU General Public License is intended to guarantee your freedom to
|
|
// share and change all versions of a program--to make sure it remains free
|
|
// software for all its users.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package source
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/GeertJohan/go.rice"
|
|
"github.com/hunterlong/statup/utils"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
var (
|
|
SqlBox *rice.Box
|
|
CssBox *rice.Box
|
|
ScssBox *rice.Box
|
|
JsBox *rice.Box
|
|
TmplBox *rice.Box
|
|
UsingAssets bool
|
|
)
|
|
|
|
func Assets() {
|
|
SqlBox = rice.MustFindBox("sql")
|
|
CssBox = rice.MustFindBox("css")
|
|
ScssBox = rice.MustFindBox("scss")
|
|
JsBox = rice.MustFindBox("js")
|
|
TmplBox = rice.MustFindBox("tmpl")
|
|
}
|
|
|
|
func CompileSASS(folder string) error {
|
|
sassBin := os.Getenv("SASS")
|
|
if sassBin == "" {
|
|
sassBin = "sass"
|
|
}
|
|
|
|
scssFile := fmt.Sprintf("%v/%v", folder, "assets/scss/base.scss")
|
|
baseFile := fmt.Sprintf("%v/%v", folder, "assets/css/base.css")
|
|
|
|
utils.Log(1, fmt.Sprintf("Compiling SASS %v into %v", scssFile, baseFile))
|
|
command := fmt.Sprintf("%v %v %v", sassBin, scssFile, baseFile)
|
|
|
|
utils.Log(1, fmt.Sprintf("Command: sh -c %v", command))
|
|
|
|
testCmd := exec.Command("sh", "-c", command)
|
|
|
|
var stdout, stderr []byte
|
|
var errStdout, errStderr error
|
|
stdoutIn, _ := testCmd.StdoutPipe()
|
|
stderrIn, _ := testCmd.StderrPipe()
|
|
testCmd.Start()
|
|
|
|
go func() {
|
|
stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn)
|
|
}()
|
|
|
|
go func() {
|
|
stderr, errStderr = copyAndCapture(os.Stderr, stderrIn)
|
|
}()
|
|
|
|
err := testCmd.Wait()
|
|
if err != nil {
|
|
utils.Log(3, err)
|
|
return err
|
|
}
|
|
|
|
if errStdout != nil || errStderr != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to compile assets with SASS %v", err))
|
|
return errors.New("failed to capture stdout or stderr")
|
|
}
|
|
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to compile assets with SASS %v", err))
|
|
utils.Log(3, fmt.Sprintf("bash -c %v %v %v", sassBin, scssFile, baseFile))
|
|
return err
|
|
}
|
|
|
|
outStr, errStr := string(stdout), string(stderr)
|
|
utils.Log(1, fmt.Sprintf("out: %v | error: %v", outStr, errStr))
|
|
utils.Log(1, "SASS Compiling is complete!")
|
|
return err
|
|
}
|
|
|
|
func HasAssets(folder string) bool {
|
|
if _, err := os.Stat(folder + "/assets"); err == nil {
|
|
utils.Log(1, "Assets folder was found!")
|
|
UsingAssets = true
|
|
return true
|
|
} else {
|
|
assetEnv := os.Getenv("USE_ASSETS")
|
|
if assetEnv == "true" {
|
|
utils.Log(1, "Environment variable USE_ASSETS was found.")
|
|
CreateAllAssets(folder)
|
|
err := CompileSASS(folder)
|
|
if err != nil {
|
|
CopyToPublic(CssBox, folder+"/css", "base.css")
|
|
utils.Log(2, "Default 'base.css' was insert because SASS did not work.")
|
|
return true
|
|
}
|
|
UsingAssets = true
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func SaveAsset(data []byte, folder, file string) error {
|
|
utils.Log(1, fmt.Sprintf("Saving %v/%v into assets folder", folder, file))
|
|
err := ioutil.WriteFile(folder+"/assets/"+file, data, 0644)
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to save %v/%v, %v", folder, file, err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func OpenAsset(folder, file string) string {
|
|
dat, err := ioutil.ReadFile(folder + "/assets/" + file)
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to open %v, %v", file, err))
|
|
return ""
|
|
}
|
|
return string(dat)
|
|
}
|
|
|
|
func CreateAllAssets(folder string) error {
|
|
utils.Log(1, fmt.Sprintf("Dump Statup assets into %v/assets", folder))
|
|
MakePublicFolder(folder + "/assets")
|
|
MakePublicFolder(folder + "/assets/js")
|
|
MakePublicFolder(folder + "/assets/css")
|
|
MakePublicFolder(folder + "/assets/scss")
|
|
utils.Log(1, "Inserting scss, css, and javascript files into assets folder")
|
|
CopyToPublic(ScssBox, folder+"/assets/scss", "base.scss")
|
|
CopyToPublic(ScssBox, folder+"/assets/scss", "variables.scss")
|
|
CopyToPublic(ScssBox, folder+"/assets/scss", "mobile.scss")
|
|
CopyToPublic(CssBox, folder+"/assets/css", "bootstrap.min.css")
|
|
CopyToPublic(CssBox, folder+"/assets/css", "base.css")
|
|
CopyToPublic(JsBox, folder+"/assets/js", "bootstrap.min.js")
|
|
CopyToPublic(JsBox, folder+"/assets/js", "Chart.bundle.min.js")
|
|
CopyToPublic(JsBox, folder+"/assets/js", "jquery-3.3.1.slim.min.js")
|
|
CopyToPublic(JsBox, folder+"/assets/js", "main.js")
|
|
CopyToPublic(JsBox, folder+"/assets/js", "setup.js")
|
|
CopyToPublic(TmplBox, folder+"/assets", "robots.txt")
|
|
CopyToPublic(TmplBox, folder+"/assets", "statup.png")
|
|
utils.Log(1, "Compiling CSS from SCSS style...")
|
|
err := utils.Log(1, "Statup assets have been inserted")
|
|
return err
|
|
}
|
|
|
|
func DeleteAllAssets(folder string) error {
|
|
err := os.RemoveAll(folder + "/assets")
|
|
if err != nil {
|
|
utils.Log(1, fmt.Sprintf("There was an issue deleting Statup Assets, %v", err))
|
|
return err
|
|
}
|
|
utils.Log(1, "Statup assets have been deleted")
|
|
return err
|
|
}
|
|
|
|
func CopyToPublic(box *rice.Box, folder, file string) error {
|
|
assetFolder := fmt.Sprintf("%v/%v", folder, file)
|
|
utils.Log(1, fmt.Sprintf("Copying %v to %v", file, assetFolder))
|
|
base, err := box.String(file)
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to copy %v to %v, %v.", file, assetFolder, err))
|
|
return err
|
|
}
|
|
err = ioutil.WriteFile(assetFolder, []byte(base), 0644)
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to write file %v to %v, %v.", file, assetFolder, err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func MakePublicFolder(folder string) error {
|
|
utils.Log(1, fmt.Sprintf("Creating folder '%v'", folder))
|
|
if _, err := os.Stat(folder); os.IsNotExist(err) {
|
|
err = os.MkdirAll(folder, 0755)
|
|
if err != nil {
|
|
utils.Log(3, fmt.Sprintf("Failed to created %v directory, %v", folder, err))
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
|
|
var out []byte
|
|
buf := make([]byte, 1024, 1024)
|
|
for {
|
|
n, err := r.Read(buf[:])
|
|
if n > 0 {
|
|
d := buf[:n]
|
|
out = append(out, d...)
|
|
_, err := w.Write(d)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
}
|
|
if err != nil {
|
|
// Read returns io.EOF at the end of file, which is not an error for us
|
|
if err == io.EOF {
|
|
err = nil
|
|
}
|
|
return out, err
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|