+
+ 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
+}