diff --git a/v3/Taskfile.yaml b/v3/Taskfile.yaml index fc145cf68..20075549b 100644 --- a/v3/Taskfile.yaml +++ b/v3/Taskfile.yaml @@ -134,3 +134,87 @@ tasks: - install-runtime-deps cmds: - task: build-runtime-all + + recreate-template-dir: + dir: internal/templates + internal: true + silent: true + cmds: + - rm -rf {{.TEMPLATE_DIR}} + - mkdir -p {{.TEMPLATE_DIR}} + + generate-template: + dir: internal/templates/{{.TEMPLATE}} + deps: + - task: recreate-template-dir + vars: + TEMPLATE_DIR: "{{.TEMPLATE}}" + silent: true + cmds: + - cmd: pnpm create vite frontend --template {{.TEMPLATE}} + - cmd: cp -rf ../_base/{{.TEMPLATE}}/* . + ignore_error: true + - cmd: cp -rf ../_base/default/* . + ignore_error: true + - cmd: rm frontend/public/vite.svg + - cmd: go run ../../../tasks/sed/sed.go replace -dir frontend -old Vite -new Wails -ext .ts,.js,.html -ignore vite.config.js,vite.config.ts,vite-env.d.ts + - cmd: go run ../../../tasks/sed/sed.go replace -dir frontend -old vite -new wails -ext .ts,.js,.html -ignore vite.config.js,vite.config.ts,vite-env.d.ts + - cmd: go run ../../../tasks/sed/sed.go replace -dir frontend -old wails.svg -new wails.png -ext .ts,.js,.html -ignore vite.config.js,vite.config.ts,vite-env.d.ts + - cmd: go run ../../../tasks/sed/sed.go replace -dir frontend -old wailsjs.dev -new wails.io -ext .ts,.js,.html -ignore vite.config.js,vite.config.ts,vite-env.d.ts + - cmd: go run ../../../tasks/sed/sed.go replace -dir frontend -old "framework powered by Wails" -new "framework powered by Vite" -ext .ts,.js,.html,.svelte -ignore vite.config.js,vite.config.ts,vite-env.d.ts + + reinstall-cli: + dir: cmd/wails + internal: true + cmds: + - go install + - echo "Reinstalled wails CLI" + + generate-templates: + dir: internal/templates/ + deps: + - task: generate-template + vars: + TEMPLATE: svelte + - task: generate-template + vars: + TEMPLATE: svelte-ts + - task: generate-template + vars: + TEMPLATE: vue + - task: generate-template + vars: + TEMPLATE: vue-ts + - task: generate-template + vars: + TEMPLATE: react + - task: generate-template + vars: + TEMPLATE: react-ts + - task: generate-template + vars: + TEMPLATE: preact + - task: generate-template + vars: + TEMPLATE: preact-ts + - task: generate-template + vars: + TEMPLATE: lit + - task: generate-template + vars: + TEMPLATE: lit-ts + - task: generate-template + vars: + TEMPLATE: vanilla + - task: generate-template + vars: + TEMPLATE: vanilla-ts + - task: generate-template + vars: + TEMPLATE: react-swc + - task: generate-template + vars: + TEMPLATE: react-swc-ts + cmds: + - task: reinstall-cli + - echo "Generated templates" diff --git a/v3/examples/build/Taskfile.yml b/v3/examples/build/Taskfile.yml index ed71e373c..67e1db618 100644 --- a/v3/examples/build/Taskfile.yml +++ b/v3/examples/build/Taskfile.yml @@ -20,10 +20,9 @@ tasks: generate-icons: summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build cmds: # Generates both .ico and .icns files - - wails generate icon -input appicon.png + - wails generate icons -input appicon.png build-prod: summary: Creates a production build of the application diff --git a/v3/go.mod b/v3/go.mod index 83a089d76..5bcbc2fc7 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -6,6 +6,7 @@ require ( github.com/go-task/task/v3 v3.20.0 github.com/jackmordaunt/icns/v2 v2.2.1 github.com/leaanthony/clir v1.5.0 + github.com/leaanthony/gosod v1.0.3 github.com/leaanthony/winicon v1.0.0 github.com/pterm/pterm v0.12.51 github.com/samber/lo v1.37.0 diff --git a/v3/go.sum b/v3/go.sum index 51f179243..7a5ef1a8f 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -49,6 +49,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.5.0 h1:zaH7fgsZ5OLfr0YwJBwQ+EYxCjXQsHF+CRudIiZb0KQ= github.com/leaanthony/clir v1.5.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= +github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= +github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= +github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= @@ -56,6 +60,7 @@ github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -114,8 +119,6 @@ github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/wailsapp/task/v3 v3.19.1 h1:syDKYaPBXgrXKKSJVEWcOEoSFtZzpvxqlHf90YRukRc= -github.com/wailsapp/task/v3 v3.19.1/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI= github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 h1:Wn+nhnS+VytzE0PegUzSh4T3hXJCtggKGD/4U5H9+wQ= github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= diff --git a/v3/internal/commands/icons.go b/v3/internal/commands/icons.go index dde3b8bfe..4eee8734f 100644 --- a/v3/internal/commands/icons.go +++ b/v3/internal/commands/icons.go @@ -15,17 +15,9 @@ import ( type IconsOptions struct { Example bool `description:"Generate example icon file (appicon.png) in the current directory"` Input string `description:"The input image file"` - Sizes string `description:"The sizes to generate in .ico file (comma separated)"` - WindowsFilename string `description:"The output filename for the Windows icon"` - MacFilename string `description:"The output filename for the Mac icon bundle"` -} - -func (i *IconsOptions) Default() *IconsOptions { - return &IconsOptions{ - Sizes: "256,128,64,48,32,16", - MacFilename: "icons.icns", - WindowsFilename: "icons.ico", - } + Sizes string `description:"The sizes to generate in .ico file (comma separated)" default:"256,128,64,48,32,16"` + WindowsFilename string `description:"The output filename for the Windows icon" default:"icon.ico"` + MacFilename string `description:"The output filename for the Mac icon bundle" default:"icons.icns"` } func GenerateIcons(options *IconsOptions) error { @@ -51,7 +43,6 @@ func GenerateIcons(options *IconsOptions) error { return err } } - iconData, err := os.ReadFile(options.Input) if err != nil { return err diff --git a/v3/internal/commands/init.go b/v3/internal/commands/init.go index 14248a4f3..6527460b4 100644 --- a/v3/internal/commands/init.go +++ b/v3/internal/commands/init.go @@ -1,8 +1,44 @@ package commands -type InitOptions struct { +import ( + "fmt" + + "github.com/wailsapp/wails/v3/internal/flags" + "github.com/wailsapp/wails/v3/internal/templates" + + "github.com/pterm/pterm" +) + +func Init(options *flags.Init) error { + if options.List { + return printTemplates() + } + + if options.Quiet { + pterm.DisableOutput() + } + + if options.ProjectName == "" { + return fmt.Errorf("please use the -n flag to specify a project name") + } + + if !templates.ValidTemplateName(options.TemplateName) { + return fmt.Errorf("invalid template name: %s. Use -l flag to view available templates", options.TemplateName) + } + + return templates.Install(options) } -func Init(options *InitOptions) error { - return nil +func printTemplates() error { + defaultTemplates := templates.GetDefaultTemplates() + + pterm.DefaultSection.Println("Available templates") + + table := pterm.TableData{{"Name", "Description"}} + for _, template := range defaultTemplates { + table = append(table, []string{template.Name, template.Description}) + } + err := pterm.DefaultTable.WithHasHeader(true).WithBoxed(true).WithData(table).Render() + pterm.Println() + return err } diff --git a/v3/internal/commands/task.go b/v3/internal/commands/task.go index d47395e37..ae33e9215 100644 --- a/v3/internal/commands/task.go +++ b/v3/internal/commands/task.go @@ -44,7 +44,7 @@ func ListTasks(options *ListTaskOptions) error { return err } if len(tasks) == 0 { - return fmt.Errorf("no tasks found. Ensure there is a `Taskfile.yml` in your project. You can generate a default takfile by running `wails generate defaults`") + return fmt.Errorf("no tasks found. Ensure there is a `Taskfile.tmpl.yml` in your project. You can generate a default takfile by running `wails generate defaults`") } tableData := [][]string{ {"Task", "Summary"}, diff --git a/v3/internal/flags/common.go b/v3/internal/flags/common.go new file mode 100644 index 000000000..e58eff411 --- /dev/null +++ b/v3/internal/flags/common.go @@ -0,0 +1,5 @@ +package flags + +type Common struct { + NoColour bool `description:"Disable colour in output"` +} diff --git a/v3/internal/flags/init.go b/v3/internal/flags/init.go new file mode 100644 index 000000000..97b80a98f --- /dev/null +++ b/v3/internal/flags/init.go @@ -0,0 +1,14 @@ +package flags + +type Init struct { + Common + + TemplateName string `name:"t" description:"Name of built-in template to use, path to template or template url" default:"vanilla"` + ProjectName string `name:"n" description:"Name of project" default:"."` + //CIMode bool `name:"ci" description:"CI Mode"` + ProjectDir string `name:"d" description:"Project directory" default:"."` + Quiet bool `name:"q" description:"Suppress output to console"` + //InitGit bool `name:"g" description:"Initialise git repository"` + //IDE string `name:"ide" description:"Generate IDE project files"` + List bool `name:"l" description:"List templates"` +} diff --git a/v3/internal/templates/_base/default/Taskfile.tmpl.yml b/v3/internal/templates/_base/default/Taskfile.tmpl.yml new file mode 100644 index 000000000..4d3d4b22d --- /dev/null +++ b/v3/internal/templates/_base/default/Taskfile.tmpl.yml @@ -0,0 +1,82 @@ +version: '3' + +vars: + APP_NAME: "{{.ProjectName}}" + +tasks: + + pre-build: + summary: Pre-build hooks + + post-build: + summary: Post-build hooks + + install-frontend-deps: + summary: Install frontend dependencies + dir: frontend + sources: + - package.json + - package-lock.json + generates: + - node_modules/* + preconditions: + - sh: npm version + msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" + cmds: + - npm install + + build-frontend: + summary: Build the frontend project + dir: frontend + deps: + - install-frontend-deps + cmds: + - npm run build + + build: + summary: Builds the application + cmds: + - task: pre-build + - task: build-frontend + - go build -gcflags=all="-N -l" -o build/bin/{{ "{{.APP_NAME}}" }} main.go + - task: post-build + env: + CGO_CFLAGS: "-mmacosx-version-min=10.13" + CGO_LDFLAGS: "-mmacosx-version-min=10.13" + + generate-icons: + summary: Generates Windows `.ico` and Mac `.icns` files from an image + dir: build + cmds: + # Generates both .ico and .icns files + - wails generate icons -input appicon.png + + build-app-prod-darwin: + summary: Creates a production build of the application + cmds: + - GOOS=darwin GOARCH={{ "{{.ARCH}}" }} go build -tags production -ldflags="-w -s" -o build/bin/{{ "{{.APP_NAME}}" }} + env: + CGO_CFLAGS: "-mmacosx-version-min=10.13" + CGO_LDFLAGS: "-mmacosx-version-min=10.13" + vars: + ARCH: $GOARCH + + + create-app-bundle: + summary: Builds a `.app` bundle + cmds: + - mkdir -p {{ "{{.APP_NAME}}" }}.app/Contents/{MacOS,Resources} + - cp build/icons.icns {{ "{{.APP_NAME}}" }}.app/Contents/Resources + - cp build/bin/{{ "{{.APP_NAME}}" }} {{ "{{.APP_NAME}}" }}.app/Contents/MacOS + - cp build/Info.plist {{ "{{.APP_NAME}}" }}.app/Contents + + package-darwin-arm64: + summary: Packages a production build of the application into a `.app` bundle + platform: darwin + deps: + - task: build-app-prod-darwin + vars: + ARCH: arm64 + - generate-icons + cmds: + - task: create-app-bundle \ No newline at end of file diff --git a/v3/internal/templates/_base/default/build/Info.plist.tmpl b/v3/internal/templates/_base/default/build/Info.plist.tmpl new file mode 100644 index 000000000..93d9a5bf1 --- /dev/null +++ b/v3/internal/templates/_base/default/build/Info.plist.tmpl @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{ "{{.Info.ProductName}}" }} + CFBundleExecutable + {{ "{{.ProjectName}}" }} + CFBundleIdentifier + com.wails.{{ "{{.ProjectName}}" }} + CFBundleVersion + v1.0.0 + CFBundleGetInfoString + This is a comment + CFBundleShortVersionString + v1.0.0 + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + (c) 2023 My Company Name + + \ No newline at end of file diff --git a/v3/internal/templates/_base/default/build/appicon.png b/v3/internal/templates/_base/default/build/appicon.png new file mode 100644 index 000000000..63617fe4f Binary files /dev/null and b/v3/internal/templates/_base/default/build/appicon.png differ diff --git a/v3/internal/templates/_base/default/build/info.json b/v3/internal/templates/_base/default/build/info.json new file mode 100644 index 000000000..1005eb5cb --- /dev/null +++ b/v3/internal/templates/_base/default/build/info.json @@ -0,0 +1,15 @@ +{ + "fixed": { + "file_version": "v1.0.0" + }, + "info": { + "0000": { + "ProductVersion": "v1.0.0", + "CompanyName": "My Company Name", + "FileDescription": "A thing that does a thing", + "LegalCopyright": "(c) 2023 My Company Name", + "ProductName": "My Product Name", + "Comments": "This is a comment" + } + } +} \ No newline at end of file diff --git a/v3/internal/templates/_base/default/go.mod.tmpl b/v3/internal/templates/_base/default/go.mod.tmpl new file mode 100644 index 000000000..270f8c6d7 --- /dev/null +++ b/v3/internal/templates/_base/default/go.mod.tmpl @@ -0,0 +1,13 @@ +module changeme + +go 1.19 + +require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 + +require ( + github.com/imdario/mergo v0.3.12 // indirect + github.com/leaanthony/slicer v1.5.0 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 // indirect + golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect +) diff --git a/v3/internal/templates/_base/default/main.tmpl.go b/v3/internal/templates/_base/default/main.tmpl.go new file mode 100644 index 000000000..ea8f138b8 --- /dev/null +++ b/v3/internal/templates/_base/default/main.tmpl.go @@ -0,0 +1,45 @@ +package main + +import ( + "embed" + _ "embed" + "log" + + "github.com/wailsapp/wails/v3/pkg/options" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +//go:embed frontend/dist +var assets embed.FS + +func main() { + app := application.New(options.Application{ + Name: "{{.ProjectName}}", + Description: "A demo of using raw HTML & CSS", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) + // Create window + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ + Title: "Plain Bundle", + CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, + Mac: options.MacWindow{ + InvisibleTitleBarHeight: 50, + Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset, + }, + + URL: "/", + Assets: options.Assets{ + FS: assets, + }, + }) + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/v3/internal/templates/_base/svelte/frontend/README.md b/v3/internal/templates/_base/svelte/frontend/README.md new file mode 100644 index 000000000..fd6a7082f --- /dev/null +++ b/v3/internal/templates/_base/svelte/frontend/README.md @@ -0,0 +1 @@ +# Wails + Svelte \ No newline at end of file diff --git a/v3/internal/templates/_base/svelte/frontend/src/App.svelte b/v3/internal/templates/_base/svelte/frontend/src/App.svelte new file mode 100644 index 000000000..c677e3838 --- /dev/null +++ b/v3/internal/templates/_base/svelte/frontend/src/App.svelte @@ -0,0 +1,45 @@ + + +
+
+ + + + + + +
+

Wails + Svelte

+ +
+ +
+ +

+ Check out SvelteKit, the official Svelte app framework powered by Wails! +

+ +

+ Click on the Wails and Svelte logos to learn more +

+
+ + diff --git a/v3/internal/templates/templates.go b/v3/internal/templates/templates.go new file mode 100644 index 000000000..465c08833 --- /dev/null +++ b/v3/internal/templates/templates.go @@ -0,0 +1,165 @@ +package templates + +import ( + "embed" + "fmt" + "io/fs" + "os" + + "github.com/wailsapp/wails/v3/internal/flags" + + "github.com/leaanthony/gosod" + + "github.com/samber/lo" +) + +//go:embed lit +var lit embed.FS + +//go:embed lit-ts +var litTS embed.FS + +//go:embed vue +var vue embed.FS + +//go:embed vue-ts +var vueTS embed.FS + +//go:embed react +var react embed.FS + +//go:embed react-ts +var reactTS embed.FS + +//go:embed react-swc +var reactSWC embed.FS + +//go:embed react-swc-ts +var reactSWCTS embed.FS + +//go:embed svelte +var svelte embed.FS + +//go:embed svelte-ts +var svelteTS embed.FS + +//go:embed preact +var preact embed.FS + +//go:embed preact-ts +var preactTS embed.FS + +//go:embed vanilla +var vanilla embed.FS + +//go:embed vanilla-ts +var vanillaTS embed.FS + +type TemplateData struct { + Name string + Description string + FS embed.FS +} + +var defaultTemplates = []TemplateData{ + { + Name: "lit", + Description: "Template using Lit Web Components: https://lit.dev", + FS: lit, + }, + { + Name: "lit-ts", + Description: "Template using Lit Web Components (TypeScript) : https://lit.dev", + FS: litTS, + }, + { + Name: "vue", + Description: "Template using Vue: https://vuejs.org", + FS: vue, + }, + { + Name: "vue-ts", + Description: "Template using Vue (TypeScript): https://vuejs.org", + FS: vueTS, + }, + { + Name: "react", + Description: "Template using React: https://reactjs.org", + FS: react, + }, + { + Name: "react-ts", + Description: "Template using React (TypeScript): https://reactjs.org", + FS: reactTS, + }, + { + Name: "react-swc", + Description: "Template using React with SWC: https://reactjs.org & https://swc.rs", + FS: reactSWC, + }, + { + Name: "react-swc-ts", + Description: "Template using React with SWC (TypeScript): https://reactjs.org & https://swc.rs", + FS: reactSWCTS, + }, + { + Name: "svelte", + Description: "Template using Svelte: https://svelte.dev", + FS: svelte, + }, + { + Name: "svelte-ts", + Description: "Template using Svelte (TypeScript): https://svelte.dev", + FS: svelteTS, + }, + { + Name: "preact", + Description: "Template using Preact: https://preactjs.com", + FS: preact, + }, + { + Name: "preact-ts", + Description: "Template using Preact (TypeScript): https://preactjs.com", + FS: preactTS, + }, + { + Name: "vanilla", + Description: "Template using Vanilla JS", + FS: vanilla, + }, + { + Name: "vanilla-ts", + Description: "Template using Vanilla JS (TypeScript)", + FS: vanillaTS, + }, +} + +func ValidTemplateName(name string) bool { + return lo.ContainsBy(defaultTemplates, func(template TemplateData) bool { + return template.Name == name + }) +} + +func GetDefaultTemplates() []TemplateData { + return defaultTemplates +} + +func Install(options *flags.Init) error { + template, found := lo.Find(defaultTemplates, func(template TemplateData) bool { + return template.Name == options.TemplateName + }) + if !found { + return fmt.Errorf("template '%s' not found", options.TemplateName) + } + + if options.ProjectDir == "." || options.ProjectDir == "" { + options.ProjectDir = lo.Must(os.Getwd()) + } + targetDir := fmt.Sprintf("%s/%s", options.ProjectDir, options.ProjectName) + fmt.Printf("Installing template '%s' into '%s'\n", options.TemplateName, targetDir) + tfs, err := fs.Sub(template.FS, options.TemplateName) + if err != nil { + return err + } + return gosod.New(tfs).Extract(targetDir, options) +} diff --git a/v3/internal/templates/templates_test.go b/v3/internal/templates/templates_test.go new file mode 100644 index 000000000..25fa790b5 --- /dev/null +++ b/v3/internal/templates/templates_test.go @@ -0,0 +1,34 @@ +package templates + +import ( + "testing" + + "github.com/wailsapp/wails/v3/internal/flags" +) + +func TestInstall(t *testing.T) { + type args struct { + } + tests := []struct { + name string + options *flags.Init + wantErr bool + }{ + { + name: "should install template", + options: &flags.Init{ + ProjectName: "test", + TemplateName: "svelte", + Quiet: false, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := Install(tt.options); (err != nil) != tt.wantErr { + t.Errorf("Install() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/v3/tasks/sed/sed.go b/v3/tasks/sed/sed.go new file mode 100644 index 000000000..12e55f8d3 --- /dev/null +++ b/v3/tasks/sed/sed.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/leaanthony/clir" + + "github.com/samber/lo" +) + +func main() { + app := clir.NewCli("sed", "A simple sed replacement", "v1") + app.NewSubCommandFunction("replace", "Replace a string in files", ReplaceInFiles) + err := app.Run() + if err != nil { + println(err.Error()) + os.Exit(1) + } +} + +type ReplaceInFilesOptions struct { + Dir string `name:"dir" help:"Directory to search in"` + OldString string `name:"old" description:"The string to replace"` + NewString string `name:"new" description:"The string to replace with"` + Extensions string `name:"ext" description:"The file extensions to process"` + Ignore string `name:"ignore" description:"The files to ignore"` +} + +func ReplaceInFiles(options *ReplaceInFilesOptions) error { + extensions := strings.Split(options.Extensions, ",") + ignore := strings.Split(options.Ignore, ",") + err := filepath.Walk(options.Dir, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + ext := filepath.Ext(path) + if !lo.Contains(extensions, ext) { + println("Skipping", path) + return nil + } + filename := filepath.Base(path) + if lo.Contains(ignore, filename) { + println("Ignoring:", path) + return nil + } + + println("Processing file:", path) + + content, err := os.ReadFile(path) + if err != nil { + return err + } + + newContent := strings.Replace(string(content), options.OldString, options.NewString, -1) + + return os.WriteFile(path, []byte(newContent), info.Mode()) + }) + + if err != nil { + return fmt.Errorf("Error while replacing in files: %v", err) + } + + return nil +}