Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
e87dfaf38b | |||
30f8be3d5d | |||
c356f34e21 | |||
734a6ce62e | |||
9e7f716be8 | |||
760decfb85 | |||
f081b97beb | |||
427e287895 | |||
8433170681 |
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Package",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}",
|
||||||
|
"args": ["generate"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
57
build.go
Normal file
57
build.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/evanw/esbuild/pkg/api"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildAction(ctx *cli.Context) error {
|
||||||
|
cfgPath, err := filepath.Abs(ctx.String("c"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Chdir(filepath.Dir(cfgPath))
|
||||||
|
opts := readCfg(cfgPath)
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if ctx.Bool("p") {
|
||||||
|
download(o)
|
||||||
|
}
|
||||||
|
purge(o)
|
||||||
|
cp(o)
|
||||||
|
|
||||||
|
esBuildCfg := cfgToESBuildCfg(o)
|
||||||
|
|
||||||
|
if ctx.Bool("p") {
|
||||||
|
esBuildCfg.MinifyIdentifiers = true
|
||||||
|
esBuildCfg.MinifySyntax = true
|
||||||
|
esBuildCfg.MinifyWhitespace = true
|
||||||
|
esBuildCfg.Sourcemap = api.SourceMapNone
|
||||||
|
}
|
||||||
|
|
||||||
|
api.Build(esBuildCfg)
|
||||||
|
replace(o)
|
||||||
|
|
||||||
|
if ctx.Bool("p") && o.ProductionBuildOptions.CmdPostBuild != "" {
|
||||||
|
fmt.Printf("Executing post production build command `%s`\n", o.ProductionBuildOptions.CmdPostBuild)
|
||||||
|
cmd := exec.Command("sh", "-c", o.ProductionBuildOptions.CmdPostBuild)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
err := cmd.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to execute post production build command `%s`: %+v\n", o.ProductionBuildOptions.CmdPostBuild, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
141
config.go
Normal file
141
config.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/evanw/esbuild/pkg/api"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cfgToESBuildCfg(cfg options) api.BuildOptions {
|
||||||
|
return api.BuildOptions{
|
||||||
|
EntryPoints: cfg.ESBuild.EntryPoints,
|
||||||
|
Outdir: cfg.ESBuild.Outdir,
|
||||||
|
Outfile: cfg.ESBuild.Outfile,
|
||||||
|
Sourcemap: api.SourceMap(cfg.ESBuild.Sourcemap),
|
||||||
|
Format: api.Format(cfg.ESBuild.Format),
|
||||||
|
Splitting: cfg.ESBuild.Splitting,
|
||||||
|
Platform: api.Platform(cfg.ESBuild.Platform),
|
||||||
|
Bundle: cfg.ESBuild.Bundle,
|
||||||
|
Write: cfg.ESBuild.Write,
|
||||||
|
LogLevel: api.LogLevel(cfg.ESBuild.LogLevel),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
ESBuild struct {
|
||||||
|
EntryPoints []string `yaml:"entryPoints"`
|
||||||
|
Outdir string `yaml:"outdir"`
|
||||||
|
Outfile string `yaml:"outfile"`
|
||||||
|
Sourcemap int `yaml:"sourcemap"`
|
||||||
|
Format int `yaml:"format"`
|
||||||
|
Splitting bool `yaml:"splitting"`
|
||||||
|
Platform int `yaml:"platform"`
|
||||||
|
Bundle bool `yaml:"bundle"`
|
||||||
|
Write bool `yaml:"write"`
|
||||||
|
LogLevel int `yaml:"logLevel"`
|
||||||
|
PurgeBeforeBuild bool `yaml:"purgeBeforeBuild"`
|
||||||
|
} `yaml:"esbuild"`
|
||||||
|
Watch struct {
|
||||||
|
Paths []string `yaml:"paths"`
|
||||||
|
Exclude []string `yaml:"exclude"`
|
||||||
|
}
|
||||||
|
Serve struct {
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
} `yaml:"serve"`
|
||||||
|
Copy []struct {
|
||||||
|
Src string `yaml:"src"`
|
||||||
|
Dest string `yaml:"dest"`
|
||||||
|
} `yaml:"copy"`
|
||||||
|
Download []struct {
|
||||||
|
Url string `yaml:"url"`
|
||||||
|
Dest string `yaml:"dest"`
|
||||||
|
} `yaml:"download"`
|
||||||
|
Replace []struct {
|
||||||
|
Pattern string `yaml:"pattern"`
|
||||||
|
Search string `yaml:"search"`
|
||||||
|
Replace string `yaml:"replace"`
|
||||||
|
} `yaml:"replace"`
|
||||||
|
Link struct {
|
||||||
|
From string `yaml:"from"`
|
||||||
|
To string `yaml:"to"`
|
||||||
|
} `yaml:"link"`
|
||||||
|
ProductionBuildOptions struct {
|
||||||
|
CmdPostBuild string `yaml:"cmdPostBuild"`
|
||||||
|
} `yaml:"productionBuildOptions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func readCfg(cfgPath string) []options {
|
||||||
|
if filepath.Ext(cfgPath) == ".json" {
|
||||||
|
jsonOpts := readJsonCfg(cfgPath)
|
||||||
|
|
||||||
|
data, err := yaml.Marshal(jsonOpts)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
yamlPath := strings.TrimSuffix(cfgPath, ".json") + ".yaml"
|
||||||
|
|
||||||
|
err = os.WriteFile(yamlPath, data, 0755)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgPath = yamlPath
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgContent, err := os.ReadFile(cfgPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
optsSetups := []options{}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(cfgContent, &optsSetups)
|
||||||
|
if err != nil {
|
||||||
|
opt := options{}
|
||||||
|
err = yaml.Unmarshal(cfgContent, &opt)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
optsSetups = append(optsSetups, opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return optsSetups
|
||||||
|
}
|
||||||
|
|
||||||
|
func readJsonCfg(cfgPath string) []options {
|
||||||
|
cfgContent, err := os.ReadFile(cfgPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
optsSetups := []options{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(cfgContent, &optsSetups)
|
||||||
|
if err != nil {
|
||||||
|
opt := options{}
|
||||||
|
err = json.Unmarshal(cfgContent, &opt)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
optsSetups = append(optsSetups, opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return optsSetups
|
||||||
|
}
|
74
go.mod
74
go.mod
@ -1,21 +1,73 @@
|
|||||||
module github.com/trading-peter/gowebbuild
|
module github.com/trading-peter/gowebbuild
|
||||||
|
|
||||||
go 1.18
|
go 1.22.0
|
||||||
|
|
||||||
|
toolchain go1.22.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/evanw/esbuild v0.14.50
|
github.com/Iilun/survey/v2 v2.5.1
|
||||||
github.com/goyek/goyek v0.6.3
|
github.com/evanw/esbuild v0.23.0
|
||||||
github.com/jaschaephraim/lrserver v0.0.0-20171129202958-50d19f603f71
|
github.com/jaschaephraim/lrserver v0.0.0-20240306232639-afed386b3640
|
||||||
github.com/otiai10/copy v1.7.0
|
github.com/kataras/iris/v12 v12.2.11
|
||||||
|
github.com/otiai10/copy v1.14.0
|
||||||
github.com/radovskyb/watcher v1.0.7
|
github.com/radovskyb/watcher v1.0.7
|
||||||
github.com/tidwall/gjson v1.14.1
|
github.com/tidwall/gjson v1.17.1
|
||||||
|
github.com/urfave/cli/v2 v2.27.2
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
|
||||||
|
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
|
||||||
|
github.com/Joker/jade v1.1.3 // indirect
|
||||||
|
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
|
||||||
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||||
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
|
github.com/flosch/pongo2/v4 v4.0.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/iris-contrib/schema v0.0.6 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/kataras/blocks v0.0.8 // indirect
|
||||||
|
github.com/kataras/golog v0.1.12 // indirect
|
||||||
|
github.com/kataras/pio v0.0.13 // indirect
|
||||||
|
github.com/kataras/sitemap v0.0.6 // indirect
|
||||||
|
github.com/kataras/tunnel v0.0.4 // indirect
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
|
github.com/mailgun/raymond/v2 v2.0.48 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/tdewolff/minify/v2 v2.20.37 // indirect
|
||||||
|
github.com/tdewolff/parse/v2 v2.7.15 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
|
github.com/yosssi/ace v0.0.5 // indirect
|
||||||
|
golang.org/x/crypto v0.25.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
|
||||||
|
golang.org/x/net v0.27.0 // indirect
|
||||||
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
|
golang.org/x/sys v0.22.0 // indirect
|
||||||
|
golang.org/x/term v0.22.0 // indirect
|
||||||
|
golang.org/x/text v0.16.0 // indirect
|
||||||
|
golang.org/x/time v0.5.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
)
|
)
|
||||||
|
270
go.sum
270
go.sum
@ -1,41 +1,251 @@
|
|||||||
github.com/evanw/esbuild v0.14.50 h1:h7sijkRPGB9ckpIOc6FMZ81/NMy/4g40LhsBAtPa3/I=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/evanw/esbuild v0.14.50/go.mod h1:dkwI35DCMf0iR+tJDiCEiPKZ4A+AotmmeLpPEv3dl9k=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
|
||||||
github.com/goyek/goyek v0.6.3 h1:t0h3gWdlvGeSChltiyAyka9Mlcp3CEPDRssRf0XHDTM=
|
github.com/Iilun/survey/v2 v2.5.1 h1:WBDYH5dHcH90iKu+4DmNhsyYGcNMmOCFnlELpBWeQGU=
|
||||||
github.com/goyek/goyek v0.6.3/go.mod h1:UGjZz3juJL2l2eMqRbxQYjG8ieyKb7WMYPv0KB0KVxA=
|
github.com/Iilun/survey/v2 v2.5.1/go.mod h1:mZL+0ztzqErbD7saTLuQIznMP0L1M+ZEwXhnLip0IMs=
|
||||||
github.com/jaschaephraim/lrserver v0.0.0-20171129202958-50d19f603f71 h1:24NdJ5N6gtrcoeS4JwLMeruKFmg20QdF/5UnX5S/j18=
|
github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
|
||||||
github.com/jaschaephraim/lrserver v0.0.0-20171129202958-50d19f603f71/go.mod h1:ozZLfjiLmXytkIUh200wMeuoQJ4ww06wN+KZtFP6j3g=
|
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||||
|
github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
|
||||||
|
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
|
||||||
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||||
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||||
|
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
|
||||||
|
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
|
||||||
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
|
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||||
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
|
||||||
|
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/evanw/esbuild v0.23.0 h1:PLUwTn2pzQfIBRrMKcD3M0g1ALOKIHMDefdFCk7avwM=
|
||||||
|
github.com/evanw/esbuild v0.23.0/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
|
||||||
|
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||||
|
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||||
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
|
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
||||||
|
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024 h1:saBP362Qm7zDdDXqv61kI4rzhmLFq3Z1gx34xpl6cWE=
|
||||||
|
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||||
|
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||||
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
|
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||||
|
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||||
|
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
|
||||||
|
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||||
|
github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
|
||||||
|
github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
|
||||||
|
github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
|
||||||
|
github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
|
||||||
|
github.com/jaschaephraim/lrserver v0.0.0-20240306232639-afed386b3640 h1:qxoA9wh1IZAbMhfFSE81tn8RsB48LNd7ecH6lFpxucc=
|
||||||
|
github.com/jaschaephraim/lrserver v0.0.0-20240306232639-afed386b3640/go.mod h1:1Dkfm1/kgjeZc+2TBUAyZ3TJeQ/HaKbj8ig+7nAHkws=
|
||||||
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
|
github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
|
||||||
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
|
github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
|
||||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
github.com/kataras/golog v0.1.12 h1:Bu7I/G4ilJlbfzjmU39O9N+2uO1pBcMK045fzZ4ytNg=
|
||||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
github.com/kataras/golog v0.1.12/go.mod h1:wrGSbOiBqbQSQznleVNX4epWM8rl9SJ/rmEacl0yqy4=
|
||||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk=
|
||||||
github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI=
|
github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w=
|
||||||
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
|
||||||
|
github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
|
||||||
|
github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
|
||||||
|
github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
|
||||||
|
github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
|
||||||
|
github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
|
||||||
|
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
|
||||||
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||||
|
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||||
|
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||||
|
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||||
|
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||||
|
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
|
github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
|
||||||
github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
|
github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
|
||||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
||||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||||
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
|
github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
|
||||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||||
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
|
||||||
|
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
|
||||||
|
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||||
|
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tdewolff/minify/v2 v2.20.37 h1:Q97cx4STXCh1dlWDlNHZniE8BJ2EBL0+2b0n92BJQhw=
|
||||||
|
github.com/tdewolff/minify/v2 v2.20.37/go.mod h1:L1VYef/jwKw6Wwyk5A+T0mBjjn3mMPgmjjA688RNsxU=
|
||||||
|
github.com/tdewolff/parse/v2 v2.7.15 h1:hysDXtdGZIRF5UZXwpfn3ZWRbm+ru4l53/ajBRGpCTw=
|
||||||
|
github.com/tdewolff/parse/v2 v2.7.15/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
|
||||||
|
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||||
|
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
|
||||||
|
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||||
|
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||||
|
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
||||||
|
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
|
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
||||||
|
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||||
|
github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
|
||||||
|
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
|
||||||
|
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||||
|
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||||
|
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
|
||||||
|
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||||
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||||
|
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||||
|
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||||
|
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||||
|
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
|
||||||
|
moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
|
||||||
|
210
helpers.go
Normal file
210
helpers.go
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/evanw/esbuild/pkg/api"
|
||||||
|
"github.com/otiai10/copy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func purge(opts options) {
|
||||||
|
if opts.ESBuild.PurgeBeforeBuild {
|
||||||
|
if opts.ESBuild.Outdir != "" {
|
||||||
|
fmt.Printf("Purging output folder %s\n", opts.ESBuild.Outdir)
|
||||||
|
os.RemoveAll(opts.ESBuild.Outdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ESBuild.Outfile != "" {
|
||||||
|
fmt.Printf("Purging output file %s\n", opts.ESBuild.Outfile)
|
||||||
|
os.Remove(opts.ESBuild.Outfile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func download(opts options) {
|
||||||
|
if len(opts.Download) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dl := range opts.Download {
|
||||||
|
if !isDir(filepath.Dir(dl.Dest)) {
|
||||||
|
fmt.Printf("Failed to find destination folder for downloading from %s\n", dl.Url)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Create(dl.Dest)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to create file for downloading from %s: %v\n", dl.Url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
client := http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||||
|
r.URL.Opaque = r.URL.Path
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Downloading %s to %s\n", dl.Url, dl.Dest)
|
||||||
|
resp, err := client.Get(dl.Url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to download file from %s: %v\n", dl.Url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(file, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to write file downloaded from %s: %v\n", dl.Url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cp(opts options) {
|
||||||
|
if len(opts.Copy) == 0 {
|
||||||
|
fmt.Println("Nothing to copy")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, op := range opts.Copy {
|
||||||
|
paths, err := filepath.Glob(op.Src)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Invalid glob pattern: %s\n", op.Src)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
destIsDir := isDir(op.Dest)
|
||||||
|
for _, p := range paths {
|
||||||
|
d := op.Dest
|
||||||
|
|
||||||
|
if destIsDir && isFile(p) {
|
||||||
|
d = filepath.Join(d, filepath.Base(p))
|
||||||
|
}
|
||||||
|
err := copy.Copy(p, d)
|
||||||
|
fmt.Printf("Copying %s to %s\n", p, d)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to copy %s: %v\n", p, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func replace(opts options) {
|
||||||
|
if len(opts.Replace) == 0 {
|
||||||
|
fmt.Println("Nothing to replace")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, op := range opts.Replace {
|
||||||
|
paths, err := filepath.Glob(op.Pattern)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Invalid glob pattern: %s\n", op.Pattern)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range paths {
|
||||||
|
if !isFile(p) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
read, err := os.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := op.Replace
|
||||||
|
if strings.HasPrefix(op.Replace, "$") {
|
||||||
|
r = os.ExpandEnv(op.Replace)
|
||||||
|
}
|
||||||
|
|
||||||
|
count := strings.Count(string(read), op.Search)
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
fmt.Printf("Replacing %d occurrences of '%s' with '%s' in %s\n", count, op.Search, r, p)
|
||||||
|
newContents := strings.ReplaceAll(string(read), op.Search, r)
|
||||||
|
err = os.WriteFile(p, []byte(newContents), 0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFile(path string) bool {
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !stat.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDir(path string) bool {
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
os.MkdirAll(path, 0755)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return err == nil && stat.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(opts options) {
|
||||||
|
result := api.Build(cfgToESBuildCfg(opts))
|
||||||
|
|
||||||
|
if len(result.Errors) == 0 {
|
||||||
|
triggerReload <- struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGoModuleName(root string) (string, error) {
|
||||||
|
modFile := filepath.Join(root, "go.mod")
|
||||||
|
|
||||||
|
if !isFile(modFile) {
|
||||||
|
return "", fmt.Errorf("go.mod file not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the go.mod file
|
||||||
|
file, err := os.Open(modFile)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error opening go.mod: %v", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Create a scanner to read the file line by line
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
// Iterate through the lines
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
// Check if the line starts with "module "
|
||||||
|
if strings.HasPrefix(line, "module ") {
|
||||||
|
// Extract the module name
|
||||||
|
moduleName := strings.TrimSpace(strings.TrimPrefix(line, "module "))
|
||||||
|
return moduleName, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for errors in scanning
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return "", fmt.Errorf("error scanning go.mod: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
35
linker.go
35
linker.go
@ -32,14 +32,20 @@ func link(from, to string) chan struct{} {
|
|||||||
name := gjson.Get(content, "name").String()
|
name := gjson.Get(content, "name").String()
|
||||||
|
|
||||||
if deps[name] {
|
if deps[name] {
|
||||||
packages[name] = filepath.Dir(packageFiles[i])
|
pp, err := filepath.Abs(filepath.Dir(packageFiles[i]))
|
||||||
|
if err == nil {
|
||||||
|
packages[name] = pp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Found %d npm packages to monitor for changes.\n", len(packages))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
w := watcher.New()
|
w := watcher.New()
|
||||||
w.SetMaxEvents(1)
|
w.SetMaxEvents(1)
|
||||||
w.FilterOps(watcher.Write, watcher.Rename, watcher.Move, watcher.Create, watcher.Remove)
|
w.FilterOps(watcher.Write, watcher.Rename, watcher.Move, watcher.Create, watcher.Remove)
|
||||||
|
w.IgnoreHiddenFiles(true)
|
||||||
|
|
||||||
if err := w.AddRecursive(from); err != nil {
|
if err := w.AddRecursive(from); err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
@ -54,12 +60,12 @@ func link(from, to string) chan struct{} {
|
|||||||
for k, v := range packages {
|
for k, v := range packages {
|
||||||
if strings.HasPrefix(event.Path, v) {
|
if strings.HasPrefix(event.Path, v) {
|
||||||
src := filepath.Dir(event.Path)
|
src := filepath.Dir(event.Path)
|
||||||
dest := filepath.Join(to, "node_modules", k)
|
subPath, _ := filepath.Rel(v, src)
|
||||||
|
dest := filepath.Join(to, "node_modules", k, subPath)
|
||||||
fmt.Printf("Copying %s to %s\n", src, dest)
|
fmt.Printf("Copying %s to %s\n", src, dest)
|
||||||
err := copy.Copy(src, dest, copy.Options{
|
err := copy.Copy(src, dest, copy.Options{
|
||||||
Skip: func(src string) (bool, error) {
|
Skip: func(stat fs.FileInfo, src, dest string) (bool, error) {
|
||||||
ok, _ := filepath.Match("*.js", filepath.Base(src))
|
if !isExcludedPath(src, "node_modules", ".git") && (stat.IsDir() || isIncludedExt(filepath.Base(src), "*.js", "*.ts")) {
|
||||||
if ok && !strings.Contains(src, "node_modules") {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +99,25 @@ func link(from, to string) chan struct{} {
|
|||||||
return requestBuildCh
|
return requestBuildCh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isExcludedPath(srcPath string, exPaths ...string) bool {
|
||||||
|
for _, exP := range exPaths {
|
||||||
|
if strings.Contains(srcPath, exP) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIncludedExt(srcPath string, extensions ...string) bool {
|
||||||
|
for _, ext := range extensions {
|
||||||
|
if ok, _ := filepath.Match(ext, srcPath); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func findFiles(root, name string) []string {
|
func findFiles(root, name string) []string {
|
||||||
paths := []string{}
|
paths := []string{}
|
||||||
|
|
||||||
|
396
main.go
396
main.go
@ -1,142 +1,117 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/evanw/esbuild/pkg/api"
|
|
||||||
"github.com/goyek/goyek"
|
|
||||||
"github.com/jaschaephraim/lrserver"
|
"github.com/jaschaephraim/lrserver"
|
||||||
"github.com/otiai10/copy"
|
|
||||||
"github.com/radovskyb/watcher"
|
"github.com/radovskyb/watcher"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var triggerReload = make(chan struct{})
|
var triggerReload = make(chan struct{})
|
||||||
|
|
||||||
type options struct {
|
|
||||||
ESBuild api.BuildOptions
|
|
||||||
Watch struct {
|
|
||||||
Path string
|
|
||||||
Exclude []string
|
|
||||||
}
|
|
||||||
Serve struct {
|
|
||||||
Path string
|
|
||||||
Port int
|
|
||||||
}
|
|
||||||
Copy []struct {
|
|
||||||
Src string
|
|
||||||
Dest string
|
|
||||||
}
|
|
||||||
Replace []struct {
|
|
||||||
Pattern string
|
|
||||||
Search string
|
|
||||||
Replace string
|
|
||||||
}
|
|
||||||
Link struct {
|
|
||||||
From string
|
|
||||||
To string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readCfg(cfgPath string) []options {
|
|
||||||
cfgContent, err := os.ReadFile(cfgPath)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%+v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
optsSetups := []options{}
|
|
||||||
|
|
||||||
err = json.Unmarshal(cfgContent, &optsSetups)
|
|
||||||
if err != nil {
|
|
||||||
opt := options{}
|
|
||||||
err = json.Unmarshal(cfgContent, &opt)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%+v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
optsSetups = append(optsSetups, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
return optsSetups
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flow := &goyek.Flow{}
|
cfgParam := &cli.StringFlag{
|
||||||
|
|
||||||
cfgPathParam := flow.RegisterStringParam(goyek.StringParam{
|
|
||||||
Name: "c",
|
Name: "c",
|
||||||
Usage: "Path to config file config file.",
|
Value: "./.gowebbuild.yaml",
|
||||||
Default: "./.gowebbuild.json",
|
Usage: "path to config file config file.",
|
||||||
})
|
|
||||||
|
|
||||||
prodParam := flow.RegisterBoolParam(goyek.BoolParam{
|
|
||||||
Name: "p",
|
|
||||||
Usage: "Use production ready build settings",
|
|
||||||
Default: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
buildOnly := goyek.Task{
|
|
||||||
Name: "build",
|
|
||||||
Usage: "",
|
|
||||||
Params: goyek.Params{cfgPathParam, prodParam},
|
|
||||||
Action: func(tf *goyek.TF) {
|
|
||||||
cfgPath := cfgPathParam.Get(tf)
|
|
||||||
os.Chdir(filepath.Dir(cfgPath))
|
|
||||||
opts := readCfg(cfgPath)
|
|
||||||
|
|
||||||
for _, o := range opts {
|
|
||||||
cp(o)
|
|
||||||
|
|
||||||
if prodParam.Get(tf) {
|
|
||||||
o.ESBuild.MinifyIdentifiers = true
|
|
||||||
o.ESBuild.MinifySyntax = true
|
|
||||||
o.ESBuild.MinifyWhitespace = true
|
|
||||||
o.ESBuild.Sourcemap = api.SourceMapNone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api.Build(o.ESBuild)
|
app := &cli.App{
|
||||||
replace(o)
|
Name: "gowebbuild",
|
||||||
}
|
Usage: "All in one tool to build web frontend projects.",
|
||||||
|
Version: "6.0.0",
|
||||||
|
Authors: []*cli.Author{{
|
||||||
|
Name: "trading-peter (https://github.com/trading-peter)",
|
||||||
|
}},
|
||||||
|
UsageText: `gowebbuild [global options] command [command options] [arguments...]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Watch project and rebuild if a files changes:
|
||||||
|
$ gowebbuild
|
||||||
|
|
||||||
|
Use a different name or path for the config file (working directory is always the location of the config file):
|
||||||
|
$ gowebbuild -c /path/to/gowebbuild.yaml watch
|
||||||
|
|
||||||
|
Production build:
|
||||||
|
$ gowebbuild build -p
|
||||||
|
|
||||||
|
Manually replace a string within some files (not limited to project directory):
|
||||||
|
$ gowebbuild replace *.go foo bar
|
||||||
|
`,
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
{
|
||||||
|
Name: "template",
|
||||||
|
Usage: "execute a template",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cfgParam,
|
||||||
|
},
|
||||||
|
Action: tplAction,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "build",
|
||||||
|
Usage: "build web sources one time and exit",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cfgParam,
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "p",
|
||||||
|
Value: false,
|
||||||
|
Usage: "use production ready build settings",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: buildAction,
|
||||||
},
|
},
|
||||||
}
|
|
||||||
|
|
||||||
watch := goyek.Task{
|
{
|
||||||
Name: "watch",
|
Name: "watch",
|
||||||
Usage: "",
|
Usage: "watch for changes and trigger the build",
|
||||||
Params: goyek.Params{cfgPathParam},
|
Flags: []cli.Flag{
|
||||||
Action: func(tf *goyek.TF) {
|
cfgParam,
|
||||||
cfgPath := cfgPathParam.Get(tf)
|
&cli.UintFlag{
|
||||||
os.Chdir(filepath.Dir(cfgPath))
|
Name: "lr-port",
|
||||||
optsSetups := readCfg(cfgPath)
|
Value: uint(lrserver.DefaultPort),
|
||||||
|
Usage: "port for the live reload server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: watchAction,
|
||||||
|
},
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
{
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
Name: "serve",
|
||||||
|
Usage: "serve a directory with a simply http server",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "root",
|
||||||
|
Value: "./",
|
||||||
|
Usage: "folder to serve",
|
||||||
|
},
|
||||||
|
&cli.UintFlag{
|
||||||
|
Name: "port",
|
||||||
|
Value: uint(8080),
|
||||||
|
Usage: "serve directory this on port",
|
||||||
|
},
|
||||||
|
&cli.UintFlag{
|
||||||
|
Name: "lr-port",
|
||||||
|
Value: uint(lrserver.DefaultPort),
|
||||||
|
Usage: "port for the live reload server",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
port := ctx.Uint("port")
|
||||||
|
root := ctx.String("root")
|
||||||
|
lrPort := ctx.Uint("lr-port")
|
||||||
|
|
||||||
for i := range optsSetups {
|
if lrPort != 0 {
|
||||||
opts := optsSetups[i]
|
go func() {
|
||||||
|
|
||||||
go func(opts options) {
|
|
||||||
w := watcher.New()
|
w := watcher.New()
|
||||||
w.SetMaxEvents(1)
|
w.SetMaxEvents(1)
|
||||||
w.FilterOps(watcher.Write, watcher.Rename, watcher.Move, watcher.Create, watcher.Remove)
|
w.FilterOps(watcher.Write, watcher.Rename, watcher.Move, watcher.Create, watcher.Remove)
|
||||||
|
|
||||||
if len(opts.Watch.Exclude) > 0 {
|
if err := w.AddRecursive(root); err != nil {
|
||||||
w.Ignore(opts.Watch.Exclude...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.AddRecursive(opts.Watch.Path); err != nil {
|
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -146,9 +121,7 @@ func main() {
|
|||||||
select {
|
select {
|
||||||
case event := <-w.Event:
|
case event := <-w.Event:
|
||||||
fmt.Printf("File %s changed\n", event.Name())
|
fmt.Printf("File %s changed\n", event.Name())
|
||||||
cp(opts)
|
triggerReload <- struct{}{}
|
||||||
build(opts)
|
|
||||||
replace(opts)
|
|
||||||
case err := <-w.Error:
|
case err := <-w.Error:
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
case <-w.Closed:
|
case <-w.Closed:
|
||||||
@ -157,52 +130,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fmt.Printf("Watching %d elements in %s\n", len(w.WatchedFiles()), opts.Watch.Path)
|
|
||||||
|
|
||||||
cp(opts)
|
|
||||||
build(opts)
|
|
||||||
replace(opts)
|
|
||||||
|
|
||||||
if err := w.Start(time.Millisecond * 100); err != nil {
|
if err := w.Start(time.Millisecond * 100); err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
}
|
}
|
||||||
}(opts)
|
|
||||||
|
|
||||||
if opts.Serve.Path != "" {
|
|
||||||
go func() {
|
|
||||||
port := 8888
|
|
||||||
if opts.Serve.Port != 0 {
|
|
||||||
port = opts.Serve.Port
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Handle("/", http.FileServer(http.Dir(opts.Serve.Path)))
|
|
||||||
|
|
||||||
fmt.Printf("Serving contents of %s at :%d\n", opts.Serve.Path, port)
|
|
||||||
err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%+v\n", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Link.From != "" {
|
|
||||||
reqBuildCh := link(opts.Link.From, opts.Link.To)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for range reqBuildCh {
|
lr := lrserver.New(lrserver.DefaultName, uint16(lrPort))
|
||||||
cp(opts)
|
|
||||||
build(opts)
|
|
||||||
replace(opts)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
fmt.Println("Starting live reload server")
|
|
||||||
lr := lrserver.New(lrserver.DefaultName, lrserver.DefaultPort)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -217,117 +151,73 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
<-c
|
return Serve(root, port)
|
||||||
fmt.Println("\nExit")
|
},
|
||||||
os.Exit(0)
|
|
||||||
},
|
},
|
||||||
}
|
|
||||||
|
|
||||||
flow.DefaultTask = flow.Register(watch)
|
{
|
||||||
flow.Register(buildOnly)
|
Name: "download",
|
||||||
flow.Main()
|
Usage: "execute downloads as configured",
|
||||||
}
|
Flags: []cli.Flag{
|
||||||
|
cfgParam,
|
||||||
func cp(opts options) {
|
},
|
||||||
if len(opts.Copy) == 0 {
|
Action: func(ctx *cli.Context) error {
|
||||||
fmt.Println("Nothing to copy")
|
cfgPath, err := filepath.Abs(ctx.String("c"))
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, op := range opts.Copy {
|
|
||||||
paths, err := filepath.Glob(op.Src)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Invalid glob pattern: %s\n", op.Src)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
destIsDir := isDir(op.Dest)
|
|
||||||
for _, p := range paths {
|
|
||||||
d := op.Dest
|
|
||||||
|
|
||||||
if destIsDir && isFile(p) {
|
|
||||||
d = filepath.Join(d, filepath.Base(p))
|
|
||||||
}
|
|
||||||
err := copy.Copy(p, d)
|
|
||||||
fmt.Printf("Copying %s to %s\n", p, d)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to copy %s: %v\n", p, err)
|
return err
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func replace(opts options) {
|
os.Chdir(filepath.Dir(cfgPath))
|
||||||
if len(opts.Replace) == 0 {
|
opts := readCfg(cfgPath)
|
||||||
fmt.Println("Nothing to replace")
|
|
||||||
return
|
for i := range opts {
|
||||||
|
download(opts[i])
|
||||||
}
|
}
|
||||||
for _, op := range opts.Replace {
|
return nil
|
||||||
paths, err := filepath.Glob(op.Pattern)
|
},
|
||||||
if err != nil {
|
},
|
||||||
fmt.Printf("Invalid glob pattern: %s\n", op.Pattern)
|
|
||||||
continue
|
{
|
||||||
|
Name: "replace",
|
||||||
|
ArgsUsage: "[glob file pattern] [search] [replace]",
|
||||||
|
Usage: "replace text in files",
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
files := ctx.Args().Get(0)
|
||||||
|
searchStr := ctx.Args().Get(1)
|
||||||
|
replaceStr := ctx.Args().Get(2)
|
||||||
|
|
||||||
|
if files == "" {
|
||||||
|
return fmt.Errorf("invalid file pattern")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range paths {
|
if searchStr == "" {
|
||||||
if !isFile(p) {
|
return fmt.Errorf("invalid search string")
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read, err := ioutil.ReadFile(p)
|
replace(options{
|
||||||
if err != nil {
|
Replace: []struct {
|
||||||
fmt.Printf("%+v\n", err)
|
Pattern string `yaml:"pattern"`
|
||||||
os.Exit(1)
|
Search string `yaml:"search"`
|
||||||
|
Replace string `yaml:"replace"`
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Pattern: files,
|
||||||
|
Search: searchStr,
|
||||||
|
Replace: replaceStr,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DefaultCommand: "watch",
|
||||||
}
|
}
|
||||||
|
|
||||||
r := op.Replace
|
if err := app.Run(os.Args); err != nil {
|
||||||
if strings.HasPrefix(op.Replace, "$") {
|
fmt.Println(err)
|
||||||
r = os.ExpandEnv(op.Replace)
|
|
||||||
}
|
|
||||||
|
|
||||||
count := strings.Count(string(read), op.Search)
|
|
||||||
|
|
||||||
if count > 0 {
|
|
||||||
fmt.Printf("Replacing %d occurrences of '%s' with '%s' in %s\n", count, op.Search, r, p)
|
|
||||||
newContents := strings.ReplaceAll(string(read), op.Search, r)
|
|
||||||
err = ioutil.WriteFile(p, []byte(newContents), 0)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%+v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isFile(path string) bool {
|
|
||||||
stat, err := os.Stat(path)
|
|
||||||
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return !stat.IsDir()
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDir(path string) bool {
|
|
||||||
stat, err := os.Stat(path)
|
|
||||||
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
os.MkdirAll(path, 0755)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return err == nil && stat.IsDir()
|
|
||||||
}
|
|
||||||
|
|
||||||
func build(opts options) {
|
|
||||||
result := api.Build(opts.ESBuild)
|
|
||||||
|
|
||||||
if len(result.Errors) == 0 {
|
|
||||||
triggerReload <- struct{}{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Watch": {
|
"Watch": {
|
||||||
"Path": "./frontend/src",
|
"Paths": [ "./frontend/src" ],
|
||||||
"Exclude": [ "./dist" ]
|
"Exclude": [ "./dist" ]
|
||||||
},
|
},
|
||||||
"Copy": [
|
"Copy": [
|
||||||
@ -45,5 +45,8 @@
|
|||||||
"Bundle": true,
|
"Bundle": true,
|
||||||
"Write": true,
|
"Write": true,
|
||||||
"LogLevel": 3
|
"LogLevel": 3
|
||||||
|
},
|
||||||
|
"ProductionBuildOptions": {
|
||||||
|
"CmdPostBuild": "my-build-script.sh"
|
||||||
}
|
}
|
||||||
}
|
}
|
22
serve.go
Normal file
22
serve.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Serve(root string, port uint) error {
|
||||||
|
app := iris.New()
|
||||||
|
app.HandleDir("/", iris.Dir(root), iris.DirOptions{
|
||||||
|
IndexName: "/index.html",
|
||||||
|
Compress: false,
|
||||||
|
ShowList: true,
|
||||||
|
ShowHidden: true,
|
||||||
|
Cache: iris.DirCacheOptions{
|
||||||
|
Enable: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return app.Listen(fmt.Sprintf(":%d", port))
|
||||||
|
}
|
99
templates.go
Normal file
99
templates.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/Iilun/survey/v2"
|
||||||
|
"github.com/kataras/golog"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed templates/tpl.gowebbuild.yaml
|
||||||
|
var sampleConfig string
|
||||||
|
|
||||||
|
//go:embed templates/docker_image.sh
|
||||||
|
var dockerImage string
|
||||||
|
|
||||||
|
//go:embed templates/Dockerfile
|
||||||
|
var dockerFile string
|
||||||
|
|
||||||
|
var qs = []*survey.Question{
|
||||||
|
{
|
||||||
|
Name: "tpl",
|
||||||
|
Prompt: &survey.Select{
|
||||||
|
Message: "Choose a template:",
|
||||||
|
Options: []string{".gowebbuild.yaml", "docker_image.sh", "Dockerfile"},
|
||||||
|
Default: "docker_image.sh",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func tplAction(ctx *cli.Context) error {
|
||||||
|
cfgPath, err := filepath.Abs(ctx.String("c"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Chdir(filepath.Dir(cfgPath))
|
||||||
|
|
||||||
|
answers := struct {
|
||||||
|
Template string `survey:"tpl"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
err = survey.Ask(qs, &answers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tpl string
|
||||||
|
var fileName string
|
||||||
|
|
||||||
|
switch answers.Template {
|
||||||
|
case ".gowebbuild.yaml":
|
||||||
|
tpl = sampleConfig
|
||||||
|
fileName = ".gowebbuild.yaml"
|
||||||
|
case "docker_image.sh":
|
||||||
|
tpl = dockerImage
|
||||||
|
fileName = "docker_image.sh"
|
||||||
|
case "Dockerfile":
|
||||||
|
tpl = dockerFile
|
||||||
|
fileName = "Dockerfile"
|
||||||
|
default:
|
||||||
|
golog.Fatal("Invalid template")
|
||||||
|
}
|
||||||
|
|
||||||
|
if isFile(fileName) {
|
||||||
|
fmt.Printf("File \"%s\" already exists.\n", fileName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile, err := os.Create(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
context := map[string]string{
|
||||||
|
"ProjectFolderName": filepath.Base(filepath.Dir(cfgPath)),
|
||||||
|
}
|
||||||
|
|
||||||
|
if moduleName, err := getGoModuleName(filepath.Dir(cfgPath)); err == nil {
|
||||||
|
context["GoModuleName"] = moduleName
|
||||||
|
}
|
||||||
|
|
||||||
|
err = template.Must(template.New("tpl").Parse(tpl)).Execute(outFile, context)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Created \"%s\" in project root.\n", fileName)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
22
templates/Dockerfile
Normal file
22
templates/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM alpine
|
||||||
|
|
||||||
|
RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
|
||||||
|
|
||||||
|
# Set timezone if necessary
|
||||||
|
#ENV TZ UTC
|
||||||
|
ENV USER=gouser
|
||||||
|
ENV UID=10001
|
||||||
|
|
||||||
|
RUN adduser \
|
||||||
|
--disabled-password \
|
||||||
|
--gecos "" \
|
||||||
|
--shell "/sbin/nologin" \
|
||||||
|
--no-create-home \
|
||||||
|
--uid "${UID}" \
|
||||||
|
"${USER}"
|
||||||
|
|
||||||
|
ADD {{.ProjectFolderName}} /app/{{.ProjectFolderName}}
|
||||||
|
WORKDIR /app
|
||||||
|
USER gouser:gouser
|
||||||
|
|
||||||
|
ENTRYPOINT ["./{{.ProjectFolderName}}"]
|
18
templates/docker_image.sh
Executable file
18
templates/docker_image.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
mkdir -p _build
|
||||||
|
cd _build
|
||||||
|
mkdir -p docker_out
|
||||||
|
rm -rf sources
|
||||||
|
git clone $(git remote get-url origin) sources
|
||||||
|
cd sources
|
||||||
|
git fetch --tags
|
||||||
|
ver=$(git describe --tags `git rev-list --tags --max-count=1`)
|
||||||
|
git checkout $ver
|
||||||
|
|
||||||
|
CGO_ENABLED=0 go build -ldflags="-s -w" -o ../{{.ProjectFolderName}} .
|
||||||
|
|
||||||
|
# A second run is needed to build the final image.
|
||||||
|
cd ..
|
||||||
|
docker build -f sources/Dockerfile --no-cache -t {{.GoModuleName}}:${ver} .
|
||||||
|
docker push {{.GoModuleName}}:${ver}
|
||||||
|
rm -rf sources {{.ProjectFolderName}}
|
34
templates/tpl.gowebbuild.yaml
Normal file
34
templates/tpl.gowebbuild.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
- esbuild:
|
||||||
|
entryPoints:
|
||||||
|
- frontend/the-app.js
|
||||||
|
outdir: ./frontend-dist
|
||||||
|
sourcemap: 1
|
||||||
|
format: 3
|
||||||
|
splitting: true
|
||||||
|
platform: 0
|
||||||
|
bundle: true
|
||||||
|
write: true
|
||||||
|
logLevel: 3
|
||||||
|
purgeBeforeBuild: false
|
||||||
|
watch:
|
||||||
|
paths:
|
||||||
|
- ./frontend/src
|
||||||
|
exclude: []
|
||||||
|
# serve: # Uncomment and set a path to enable
|
||||||
|
# path: ""
|
||||||
|
# port: 8080
|
||||||
|
copy:
|
||||||
|
- src: ./frontend/index.html
|
||||||
|
dest: ./frontend-dist
|
||||||
|
# download:
|
||||||
|
# - url: https://example.com/some-file-or-asset.js
|
||||||
|
# dest: ./frontend/src/vendor/some-file-or-asset.js
|
||||||
|
# replace:
|
||||||
|
# - pattern: "*.go|*.js|*.html"
|
||||||
|
# search: "Something"
|
||||||
|
# replace: "This"
|
||||||
|
# link:
|
||||||
|
# from: ../../web/tp-elements
|
||||||
|
# to: ./frontend
|
||||||
|
# productionBuildOptions:
|
||||||
|
# cmdPostBuild: ""
|
133
watch.go
Normal file
133
watch.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jaschaephraim/lrserver"
|
||||||
|
"github.com/radovskyb/watcher"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func watchAction(ctx *cli.Context) error {
|
||||||
|
cfgPath, err := filepath.Abs(ctx.String("c"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Chdir(filepath.Dir(cfgPath))
|
||||||
|
optsSetups := readCfg(cfgPath)
|
||||||
|
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
for i := range optsSetups {
|
||||||
|
opts := optsSetups[i]
|
||||||
|
|
||||||
|
go func(opts options) {
|
||||||
|
w := watcher.New()
|
||||||
|
w.SetMaxEvents(1)
|
||||||
|
w.FilterOps(watcher.Write, watcher.Rename, watcher.Move, watcher.Create, watcher.Remove)
|
||||||
|
|
||||||
|
if len(opts.Watch.Exclude) > 0 {
|
||||||
|
w.Ignore(opts.Watch.Exclude...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ESBuild.Outdir != "" {
|
||||||
|
w.Ignore(opts.ESBuild.Outdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range opts.Watch.Paths {
|
||||||
|
if err := w.AddRecursive(p); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event := <-w.Event:
|
||||||
|
fmt.Printf("File %s changed\n", event.Name())
|
||||||
|
purge(opts)
|
||||||
|
cp(opts)
|
||||||
|
build(opts)
|
||||||
|
replace(opts)
|
||||||
|
case err := <-w.Error:
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
case <-w.Closed:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Printf("Watching %d elements in %s\n", len(w.WatchedFiles()), opts.Watch.Paths)
|
||||||
|
|
||||||
|
purge(opts)
|
||||||
|
cp(opts)
|
||||||
|
build(opts)
|
||||||
|
replace(opts)
|
||||||
|
|
||||||
|
if err := w.Start(time.Millisecond * 100); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
}(opts)
|
||||||
|
|
||||||
|
if opts.Serve.Path != "" {
|
||||||
|
go func() {
|
||||||
|
port := 8080
|
||||||
|
if opts.Serve.Port != 0 {
|
||||||
|
port = opts.Serve.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
err := Serve(opts.Serve.Path, uint(port))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%+v\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Link.From != "" {
|
||||||
|
reqBuildCh := link(opts.Link.From, opts.Link.To)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for range reqBuildCh {
|
||||||
|
cp(opts)
|
||||||
|
build(opts)
|
||||||
|
replace(opts)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
fmt.Println("Starting live reload server")
|
||||||
|
port := ctx.Uint("lr-port")
|
||||||
|
lr := lrserver.New(lrserver.DefaultName, uint16(port))
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
<-triggerReload
|
||||||
|
lr.Reload("")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
lr.SetStatusLog(nil)
|
||||||
|
err := lr.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-c
|
||||||
|
fmt.Println("\nStopped watching")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user