Compare commits

...

21 Commits

Author SHA1 Message Date
Lea Anthony
7661082d58 [v2] v2.0.0-alpha.71 2021-07-03 18:35:14 +10:00
Lea Anthony
34da4f056a [mac] Fix onTrayMenuOpen by being less aggressive with freeing memory 😀 2021-07-03 18:34:24 +10:00
Lea Anthony
642c1d5ec5 [v2] Target ARM on Apple Silicon, even if CLI is compiled for AMD64 2021-07-03 16:32:47 +10:00
Lea Anthony
1f3351ffa5 [v2] Get wails dev to compile again 2021-06-30 21:36:30 +10:00
Lea Anthony
30e96118b1 [v2] Remove debug statement 2021-06-30 21:00:09 +10:00
Lea Anthony
efd768ac5d [v2] Remove wails debug (now a build flag) 2021-06-30 20:52:18 +10:00
Lea Anthony
6dbcd4fc45 [v2] New Svelte template. Updates to vanilla. Improved wails generate template 2021-06-30 20:50:39 +10:00
Lea Anthony
11cd51c9ca [v2] v2.0.0-alpha.70 2021-06-29 23:45:13 +10:00
Lea Anthony
3de38003bf [v2] ARM64 fixes 2021-06-29 23:45:05 +10:00
Lea Anthony
418438b762 [v2] v2.0.0-alpha.69 2021-06-29 23:30:16 +10:00
Lea Anthony
0a5c43435e [mac] Fix memory leak wrt base64 images 2021-06-29 23:29:20 +10:00
Lea Anthony
d7bb831d7f [mac] Fix memory leak wrt updating menus 2021-06-29 22:52:32 +10:00
Lea Anthony
824256db6d [mac] Small memory leak fixes 2021-06-29 21:18:42 +10:00
Lea Anthony
2f311ee403 [mac] Fix memory leak with menu updates 2021-06-29 18:36:34 +10:00
Lea Anthony
e04db8775f [mac] Fix memory leak with menu item callback data 2021-06-29 15:49:44 +10:00
Lea Anthony
2fbc63b458 [mac] Fix C warnings 2021-06-29 15:49:16 +10:00
Lea Anthony
8ac69d6afd [v2] Tidy generate module 2021-06-27 20:26:37 +10:00
Lea Anthony
6dec097184 [v2] Support remote templates 2021-06-27 20:15:05 +10:00
Lea Anthony
c2015b1d72 [v2] Add wails generate template command 2021-06-27 20:15:05 +10:00
Lea Anthony
9c75e61704 [v2] Add CopyDirExtended 2021-06-27 20:15:05 +10:00
Lea Anthony
995d485a43 [v2] ldflags fix 2021-06-27 04:18:33 +10:00
61 changed files with 8122 additions and 306 deletions

View File

@@ -21,6 +21,7 @@ The build command processes the Wails project and generates an application binar
| -upx | Compress final binary with UPX (if installed) | |
| -upxflags "custom flags" | Flags to pass to upx | |
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
| -delve | If true, runs delve on the compiled binary | false |
## The Build Process
@@ -44,11 +45,4 @@ The build process is as follows:
- If the `-upx` flag was provided, `upx` is invoked to compress the binary. Custom flags may be provided using the `-upxflags` flag.
- If the `package` flag is given for a non Windows target, the application is bundled for the platform. On Mac, this creates a `.app` with the processed icons, the `Info.plist` in `build/darwin` and the compiled binary.
### Server Target
TBD
### Hybrid Target
TBD

View File

@@ -4,11 +4,16 @@ import (
"fmt"
"io"
"os"
"os/exec"
"runtime"
"strings"
"text/tabwriter"
"time"
"github.com/wailsapp/wails/v2/internal/system"
"github.com/wailsapp/wails/v2/internal/shell"
"github.com/leaanthony/clir"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/pkg/clilogger"
@@ -72,6 +77,9 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
webview2 := "download"
command.StringFlag("webview2", "WebView2 installer strategy: download,embed,browser,error.", &webview2)
runDelve := false
command.BoolFlag("delve", "Runs the built binary in delve for debugging", &runDelve)
command.Action(func() error {
quiet := verbosity == 0
@@ -116,6 +124,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
compress = false
}
// Lookup compiler path
compilerPath, err := exec.LookPath(compilerCommand)
if err != nil {
return fmt.Errorf("unable to find compiler: %s", compilerCommand)
}
// Tags
userTags := []string{}
for _, tag := range strings.Split(tags, " ") {
@@ -144,6 +158,11 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
}
}
// If we want to use delve we need to compile in DEBUG mode
if runDelve {
mode = build.Debug
}
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
@@ -160,16 +179,23 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
CompressFlags: compressFlags,
UserTags: userTags,
WebView2Strategy: wv2rtstrategy,
RunDelve: runDelve,
}
// Calculate platform and arch
platformSplit := strings.Split(platform, "/")
buildOptions.Platform = platformSplit[0]
buildOptions.Arch = runtime.GOARCH
if system.IsAppleSilicon() {
buildOptions.Arch = "arm64"
} else {
buildOptions.Arch = runtime.GOARCH
}
if len(platformSplit) == 2 {
buildOptions.Arch = platformSplit[1]
}
println("Build arch =", buildOptions.Arch)
// Start a new tabwriter
w := new(tabwriter.Writer)
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
@@ -184,7 +210,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
fmt.Fprintf(w, "App Type: \t%s\n", buildOptions.OutputType)
fmt.Fprintf(w, "Platform: \t%s\n", buildOptions.Platform)
fmt.Fprintf(w, "Arch: \t%s\n", buildOptions.Arch)
fmt.Fprintf(w, "Compiler: \t%s\n", buildOptions.Compiler)
fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
fmt.Fprintf(w, "Build Mode: \t%s\n", buildModeText)
fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
@@ -219,5 +245,40 @@ func doBuild(buildOptions *build.Options) error {
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.", outputFilename, elapsed.Round(time.Millisecond).String()))
buildOptions.Logger.Println("")
if buildOptions.RunDelve {
// Check delve exists
delveExists := shell.CommandExists("dlv")
if !delveExists {
return fmt.Errorf("cannot launch delve (Is it installed?)")
}
// Get cwd
cwd, err := os.Getwd()
if err != nil {
return err
}
// Launch delve
buildOptions.Logger.Println("Launching Delve on port 2345...")
cmdArgs := slicer.String([]string{"--listen=:2345", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", outputFilename})
if buildOptions.Verbosity == build.VERBOSE {
buildOptions.Logger.Println("\tRunning: dlv %s", cmdArgs.Join(" "))
}
stdout, stderr, err := shell.RunCommand(cwd, "dlv", cmdArgs.AsSlice()...)
if buildOptions.Verbosity == build.VERBOSE || err != nil {
trimstdout := strings.TrimSpace(stdout)
if trimstdout != "" {
buildOptions.Logger.Println(trimstdout)
}
trimstderr := strings.TrimSpace(stderr)
if trimstderr != "" {
buildOptions.Logger.Println(trimstderr)
}
}
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,123 +0,0 @@
package debug
import (
"fmt"
"github.com/wailsapp/wails/v2/internal/shell"
"io"
"os"
"runtime"
"strings"
"time"
"github.com/leaanthony/clir"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/pkg/clilogger"
"github.com/wailsapp/wails/v2/pkg/commands/build"
)
// AddSubcommand adds the `debug` command for the Wails application
func AddSubcommand(app *clir.Cli, w io.Writer) error {
outputType := "desktop"
validTargetTypes := slicer.String([]string{"desktop", "hybrid", "server"})
command := app.NewSubCommand("debug", "Builds the application then runs delve on the binary")
// Setup target type flag
description := "Type of application to build. Valid types: " + validTargetTypes.Join(",")
command.StringFlag("t", description, &outputType)
compilerCommand := "go"
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
quiet := false
command.BoolFlag("q", "Suppress output to console", &quiet)
// ldflags to pass to `go`
ldflags := ""
command.StringFlag("ldflags", "optional ldflags", &ldflags)
// Log to file
logFile := ""
command.StringFlag("l", "Log to file", &logFile)
command.Action(func() error {
// Create logger
logger := clilogger.New(w)
logger.Mute(quiet)
// Validate output type
if !validTargetTypes.Contains(outputType) {
return fmt.Errorf("output type '%s' is not valid", outputType)
}
if !quiet {
app.PrintBanner()
}
task := fmt.Sprintf("Building %s Application", strings.Title(outputType))
logger.Println(task)
logger.Println(strings.Repeat("-", len(task)))
// Setup mode
mode := build.Debug
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
OutputType: outputType,
Mode: mode,
Pack: false,
Platform: runtime.GOOS,
LDFlags: ldflags,
Compiler: compilerCommand,
KeepAssets: false,
}
outputFilename, err := doDebugBuild(buildOptions)
if err != nil {
return err
}
// Check delve exists
delveExists := shell.CommandExists("dlv")
if !delveExists {
return fmt.Errorf("cannot launch delve (Is it installed?)")
}
// Get cwd
cwd, err := os.Getwd()
if err != nil {
return err
}
// Launch delve
println("Launching Delve on port 2345...")
command := shell.CreateCommand(cwd, "dlv", "--listen=:2345", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", outputFilename)
return command.Run()
})
return nil
}
// doDebugBuild is our main build command
func doDebugBuild(buildOptions *build.Options) (string, error) {
// Start Time
start := time.Now()
outputFilename, err := build.Build(buildOptions)
if err != nil {
return "", err
}
// Output stats
elapsed := time.Since(start)
buildOptions.Logger.Println("")
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.", outputFilename, elapsed.Round(time.Millisecond).String()))
buildOptions.Logger.Println("")
return outputFilename, nil
}

View File

@@ -0,0 +1,18 @@
# Generate
The `generate` command provides the ability to generate various Wails related components.
## Usage
`wails generate [subcommand] [options]`
## Template
`wails generate template -name <name> [-frontend] [-q]`
Generate a starter template for you to customise.
| Flag | Details |
| :------------- | :----------- |
| -frontend | Copies all the files from the current directory into the template's `frontend` directory. Useful for converting frontend projects created by boilerplate generators. |
| -q | Suppress output |

View File

@@ -2,7 +2,8 @@ package generate
import (
"io"
"time"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate/template"
"github.com/leaanthony/clir"
"github.com/wailsapp/wails/v2/pkg/clilogger"
@@ -14,50 +15,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
command := app.NewSubCommand("generate", "Code Generation Tools")
// Backend API
backendAPI := command.NewSubCommand("module", "Generates a JS module for the frontend to interface with the backend")
//AddModuleCommand(app, command, w)
template.AddSubCommand(app, command, w)
// Quiet Init
quiet := false
backendAPI.BoolFlag("q", "Suppress output to console", &quiet)
backendAPI.Action(func() error {
// Create logger
logger := clilogger.New(w)
logger.Mute(quiet)
app.PrintBanner()
logger.Print("Generating Javascript module for Go code...")
// Start Time
start := time.Now()
p, err := parser.GenerateWailsFrontendPackage()
if err != nil {
return err
}
logger.Println("done.")
logger.Println("")
elapsed := time.Since(start)
packages := p.Packages
// Print report
for _, pkg := range p.Packages {
if pkg.ShouldGenerate() {
logPackage(pkg, logger)
}
}
logger.Println("%d packages parsed in %s.", len(packages), elapsed)
return nil
})
return nil
}

View File

@@ -0,0 +1,58 @@
package generate
import (
"io"
"time"
"github.com/leaanthony/clir"
"github.com/wailsapp/wails/v2/pkg/clilogger"
"github.com/wailsapp/wails/v2/pkg/parser"
)
func AddModuleCommand(app *clir.Cli, parent *clir.Command, w io.Writer) {
// Backend API
backendAPI := parent.NewSubCommand("module", "Generates a JS module for the frontend to interface with the backend")
// Quiet Init
quiet := false
backendAPI.BoolFlag("q", "Suppress output to console", &quiet)
backendAPI.Action(func() error {
// Create logger
logger := clilogger.New(w)
logger.Mute(quiet)
app.PrintBanner()
logger.Print("Generating Javascript module for Go code...")
// Start Time
start := time.Now()
p, err := parser.GenerateWailsFrontendPackage()
if err != nil {
return err
}
logger.Println("done.")
logger.Println("")
elapsed := time.Since(start)
packages := p.Packages
// Print report
for _, pkg := range p.Packages {
if pkg.ShouldGenerate() {
logPackage(pkg, logger)
}
}
logger.Println("%d packages parsed in %s.", len(packages), elapsed)
return nil
})
}

View File

@@ -0,0 +1,38 @@
# Next Steps
Congratulations on generating your template!
## Completing your template
The next steps to complete the template are:
1. Complete the fields in the `template.json` file.
2. Update `README.md`.
3. Edit `wails.tmpl.json` and ensure all fields are correct, especially:
- `html` - path to your `index.html`
- `frontend:install` - The command to install your frontend dependencies
- `frontend:build` - The command to build your frontend
4. Remove any `public` or `dist` directories.
5. Delete this file.
## Testing your template
You can test your template by running this command:
`wails init -name test -t {{.TemplateDir}}`
### Checklist
Once generated, do the following tests:
- Change into the new project directory and run `wails build`. A working binary should be generated in the `build/bin` project directory.
- Run `wails dev`. This will compile your backend and run it. You should be able to go into the frontend directory and run `npm run dev` (or whatever your dev command is) and this should run correctly. You should be able to then open a browser to your local dev server and the application should work.
## Publishing your template
You can publish a template to a git repository and use it as follows:
`wails init -name test -t https://your/git/url`
EG:
`wails init -name test -t https://github.com/leaanthony/testtemplate`

View File

@@ -0,0 +1,16 @@
# README
## About
About your template
## Building
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
To generate a platform native package, add the `-package` flag.
## Live Development
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
directory and run `npm run dev`. The frontend dev server will run on http://localhost:5000. Connect to this
in your browser and connect to your application.

View File

@@ -6,29 +6,29 @@ import (
"github.com/wailsapp/wails/v2"
)
// Basic application struct
type Basic struct {
// App struct
type App struct {
runtime *wails.Runtime
}
// NewBasic creates a new Basic application struct
func NewBasic() *Basic {
return &Basic{}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called at application startup
func (b *Basic) startup(runtime *wails.Runtime) {
func (b *App) startup(runtime *wails.Runtime) {
// Perform your setup here
b.runtime = runtime
runtime.Window.SetTitle("{{.ProjectName}}")
}
// shutdown is called at application termination
func (b *Basic) shutdown() {
func (b *App) shutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *Basic) Greet(name string) string {
func (b *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "vanilla",
"version": "1.0.0",
"description": "Vanilla Wails v2 template",
"main": "src/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv dist"
},
"author": "{{.AuthorName}}",
"license": "ISC",
"dependencies": {
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-image": "^2.0.6",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-url": "^6.0.0",
"@wails/runtime": "^1.3.20",
"rollup": "^2.50.4",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-terser": "^7.0.2",
"sirv-cli": "^1.0.12"
}
}

View File

@@ -0,0 +1,103 @@
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
import url from '@rollup/plugin-url';
import copy from 'rollup-plugin-copy';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'dist/main.js'
},
onwarn: handleRollupWarning,
plugins: [
image(),
copy({
targets: [
{ src: 'src/index.html', dest: 'dist' },
{ src: 'src/main.css', dest: 'dist' },
]
}),
// Embed binary files
url({
include: ['**/*.woff', '**/*.woff2'],
limit: Infinity,
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
}),
commonjs(),
// PostCSS preprocessing
postcss({
extensions: ['.css', '.scss'],
extract: true,
minimize: false,
use: [
['sass', {
includePaths: [
'./src',
'./node_modules'
]
}]
],
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('dist'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function handleRollupWarning(warning) {
console.error('ERROR: ' + warning.toString());
}
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}

View File

@@ -0,0 +1,18 @@
<html>
<head>
<link rel="stylesheet" href="/main.css">
</head>
<body data-wails-drag>
<div id="logo"></div>
<div id="input" data-wails-no-drag>
<input id="name" type="text">
<button onclick="greet()">Greet</button>
</div>
<div id="result"></div>
<script src="/main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import {ready} from '@wails/runtime';
ready( () => {
// Get input + focus
let nameElement = document.getElementById("name");
nameElement.focus();
// Setup the greet function
window.greet = function () {
// Get name
let name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
};
});

View File

@@ -0,0 +1,9 @@
module test
go 1.16
require (
github.com/wailsapp/wails/v2 v2.0.0-alpha
)
replace github.com/wailsapp/wails/v2 v2.0.0-alpha => {{.WailsDirectory}}

View File

@@ -0,0 +1,56 @@
package main
import (
"log"
"github.com/wailsapp/wails/v2/pkg/options/windows"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/mac"
)
func main() {
// Create application with options
app := NewApp()
err := wails.Run(&options.App{
Title: "{{.ProjectName}}",
Width: 800,
Height: 600,
MinWidth: 400,
MinHeight: 400,
MaxWidth: 1280,
MaxHeight: 1024,
DisableResize: false,
Fullscreen: false,
Frameless: false,
StartHidden: false,
HideWindowOnClose: false,
DevTools: false,
RGBA: 0x000000FF,
Windows: &windows.Options{
WebviewIsTransparent: true,
WindowBackgroundIsTranslucent: true,
DisableWindowIcon: true,
},
Mac: &mac.Options{
WebviewIsTransparent: true,
WindowBackgroundIsTranslucent: true,
TitleBar: mac.TitleBarHiddenInset(),
Menu: menu.DefaultMacMenu(),
},
LogLevel: logger.DEBUG,
Startup: app.startup,
Shutdown: app.shutdown,
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "Long name",
"shortname": "{{.Name}}",
"author": "",
"description": "Description of the template",
"helpurl": "URL for help with the template, eg homepage"
}

View File

@@ -0,0 +1,11 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"html": "frontend/dist/index.html",
"frontend:build": "npm run build",
"frontend:install": "npm install",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"
}
}

View File

@@ -0,0 +1,188 @@
package template
import (
"embed"
"io"
"os"
"path/filepath"
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/leaanthony/clir"
"github.com/tidwall/sjson"
)
//go:embed base
var base embed.FS
func AddSubCommand(app *clir.Cli, parent *clir.Command, w io.Writer) {
// command
command := parent.NewSubCommand("template", "Generates a wails template")
name := ""
command.StringFlag("name", "The name of the template", &name)
migrate := false
command.BoolFlag("migrate", "This indicates that the current directory is a frontend project and should be used by the template", &migrate)
// Quiet Init
quiet := false
command.BoolFlag("q", "Suppress output to console", &quiet)
command.Action(func() error {
// If the current directory is not empty, we create a new directory
cwd, err := os.Getwd()
if err != nil {
return err
}
templateDir := cwd
empty, err := fs.DirIsEmpty(templateDir)
if err != nil {
return err
}
if !empty {
templateDir = filepath.Join(cwd, name)
println("Creating new template directory:", name)
err = fs.Mkdir(templateDir)
if err != nil {
return err
}
}
// Create base template
baseTemplate, err := debme.FS(base, "base")
if err != nil {
return err
}
g := gosod.New(baseTemplate)
g.SetTemplateFilters([]string{".template"})
err = os.Chdir(templateDir)
if err != nil {
return err
}
type templateData struct {
Name string
Description string
TemplateDir string
}
println("Extracting base template files...")
err = g.Extract(templateDir, &templateData{
Name: name,
TemplateDir: templateDir,
})
if err != nil {
return err
}
// If we aren't migrating the files, just exit
if migrate == false {
return nil
}
// Remove frontend directory
frontendDir := filepath.Join(templateDir, "frontend")
err = os.RemoveAll(frontendDir)
if err != nil {
return err
}
// Move the files into a new frontend directory
println("Migrating files to frontend directory...")
err = fs.MoveDirExtended(cwd, frontendDir, []string{name})
if err != nil {
return err
}
// Process package.json
err = processPackageJSON(frontendDir)
if err != nil {
return err
}
// Process package-lock.json
err = processPackageLockJSON(frontendDir)
if err != nil {
return err
}
// Remove node_modules - ignore error, eg it doesn't exist
_ = os.RemoveAll(filepath.Join(frontendDir, "node_modules"))
return nil
})
}
func processPackageJSON(frontendDir string) error {
var err error
packageJSON := filepath.Join(frontendDir, "package.json")
if !fs.FileExists(packageJSON) {
println("No package.json found - cannot process.")
return nil
}
data, err := os.ReadFile(packageJSON)
if err != nil {
return err
}
json := string(data)
// We will ignore these errors - it's not critical
println("Updating package.json data...")
json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
json, _ = sjson.Set(json, "author", "{{.AuthorName}}")
err = os.WriteFile(packageJSON, []byte(json), 0644)
if err != nil {
return err
}
baseDir := filepath.Dir(packageJSON)
println("Renaming package.json -> package.tmpl.json...")
err = os.Rename(packageJSON, filepath.Join(baseDir, "package.tmpl.json"))
if err != nil {
return err
}
return nil
}
func processPackageLockJSON(frontendDir string) error {
var err error
filename := filepath.Join(frontendDir, "package-lock.json")
if !fs.FileExists(filename) {
println("No package-lock.json found - cannot process.")
return nil
}
data, err := os.ReadFile(filename)
if err != nil {
return err
}
json := string(data)
// We will ignore these errors - it's not critical
println("Updating package-lock.json data...")
json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
err = os.WriteFile(filename, []byte(json), 0644)
if err != nil {
return err
}
baseDir := filepath.Dir(filename)
println("Renaming package-lock.json -> package-lock.tmpl.json...")
err = os.Rename(filename, filepath.Join(baseDir, "package-lock.tmpl.json"))
if err != nil {
return err
}
return nil
}

View File

@@ -2,11 +2,12 @@ package initialise
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"io"
"strings"
"time"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise/templates"
"github.com/leaanthony/clir"
@@ -18,17 +19,11 @@ import (
// AddSubcommand adds the `init` command for the Wails application
func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Load the template shortnames
validShortNames, err := templates.TemplateShortNames()
if err != nil {
return err
}
command := app.NewSubCommand("init", "Initialise a new Wails project")
// Setup template name flag
templateName := "vanilla"
description := "Name of template to use. Valid tempates: " + validShortNames.Join(" ")
description := "Name of built-in template to use, path to template or template url."
command.StringFlag("t", description, &templateName)
// Setup project name
@@ -72,14 +67,6 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return err
}
// Validate output type
if !validShortNames.Contains(templateName) {
logger.Print(fmt.Sprintf("[ERROR] Template '%s' is not valid", templateName))
logger.Println("")
command.PrintHelp()
return nil
}
// Validate name
if len(projectName) == 0 {
logger.Println("ERROR: Project name required")
@@ -122,7 +109,7 @@ func initProject(options *templates.Options) error {
start := time.Now()
// Install the template
err := templates.Install(options)
remote, err := templates.Install(options)
if err != nil {
return err
}
@@ -152,6 +139,11 @@ func initProject(options *templates.Options) error {
if options.InitGit {
options.Logger.Println("Git repository initialised.")
}
if remote {
options.Logger.Println("\nNOTE: You have created a project using a remote template. The Wails project takes no responsibility for 3rd party templates. Only use remote templates that you trust.")
}
options.Logger.Println("")
options.Logger.Println(fmt.Sprintf("Initialised project '%s' in %s.", options.ProjectName, elapsed.Round(time.Millisecond).String()))
options.Logger.Println("")

View File

@@ -5,14 +5,19 @@ import (
"encoding/json"
"fmt"
gofs "io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-git/v5"
"github.com/pkg/errors"
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"github.com/leaanthony/slicer"
"github.com/olekukonko/tablewriter"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/pkg/clilogger"
@@ -74,7 +79,7 @@ func parseTemplate(template gofs.FS) (Template, error) {
var result Template
data, err := gofs.ReadFile(template, "template.json")
if err != nil {
return result, err
return result, errors.Wrap(err, "Error parsing template")
}
err = json.Unmarshal(data, &result)
if err != nil {
@@ -84,26 +89,6 @@ func parseTemplate(template gofs.FS) (Template, error) {
return result, nil
}
// TemplateShortNames returns a slicer of short template names
func TemplateShortNames() (*slicer.StringSlicer, error) {
var result slicer.StringSlicer
// If the cache isn't loaded, load it
if templateCache == nil {
err := loadTemplateCache()
if err != nil {
return nil, err
}
}
for _, template := range templateCache {
result.Add(template.ShortName)
}
return &result, nil
}
// List returns the list of available templates
func List() ([]Template, error) {
@@ -175,12 +160,12 @@ func loadTemplateCache() error {
return nil
}
// Install the given template
func Install(options *Options) error {
// Install the given template. Returns true if the template is remote.
func Install(options *Options) (bool, error) {
// Get cwd
cwd, err := os.Getwd()
if err != nil {
return err
return false, err
}
// Did the user want to install in current directory?
@@ -189,7 +174,7 @@ func Install(options *Options) error {
// If the current directory is empty, use it
isEmpty, err := fs.DirIsEmpty(cwd)
if err != nil {
return err
return false, err
}
if isEmpty {
@@ -198,7 +183,7 @@ func Install(options *Options) error {
} else {
options.TargetDir = filepath.Join(cwd, options.ProjectName)
if fs.DirExists(options.TargetDir) {
return fmt.Errorf("cannot create project directory. Dir exists: %s", options.TargetDir)
return false, fmt.Errorf("cannot create project directory. Dir exists: %s", options.TargetDir)
}
}
@@ -206,21 +191,47 @@ func Install(options *Options) error {
// Get the absolute path of the given directory
targetDir, err := filepath.Abs(filepath.Join(cwd, options.TargetDir))
if err != nil {
return err
return false, err
}
options.TargetDir = targetDir
if !fs.DirExists(options.TargetDir) {
err := fs.Mkdir(options.TargetDir)
if err != nil {
return err
return false, err
}
}
}
// Get template
// Flag to indicate remote template
remoteTemplate := false
// Is this a shortname?
template, err := getTemplateByShortname(options.TemplateName)
if err != nil {
return err
// Is this a filepath?
templatePath, err := filepath.Abs(options.TemplateName)
if fs.DirExists(templatePath) {
templateFS := os.DirFS(templatePath)
template, err = parseTemplate(templateFS)
if err != nil {
return false, errors.Wrap(err, "Error installing template")
}
} else {
// git clone to temporary dir
tempdir, err := gitclone(options)
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
log.Fatal(err)
}
}(tempdir)
templateFS := os.DirFS(tempdir)
template, err = parseTemplate(templateFS)
if err != nil {
return false, err
}
remoteTemplate = true
}
}
// Use Gosod to install the template
@@ -255,15 +266,30 @@ func Install(options *Options) error {
// Extract the template
err = installer.Extract(options.TargetDir, templateData)
if err != nil {
return err
return false, err
}
err = generateIDEFiles(options)
if err != nil {
return err
return false, err
}
return nil
return remoteTemplate, nil
}
// Clones the given uri and returns the temporary cloned directory
func gitclone(options *Options) (string, error) {
// Create temporary directory
dirname, err := ioutil.TempDir("", "wails-template-*")
if err != nil {
return "", err
}
_, err = git.PlainClone(dirname, false, &git.CloneOptions{
URL: options.TemplateName,
})
return dirname, err
}
// OutputList prints the list of available tempaltes to the given logger

View File

@@ -0,0 +1,24 @@
# README
## About
This is a basic Svelte template, using rollup to bundle the assets into a single JS file.
Rollup is configured to do the following:
- Convert imported images to base64 strings
- Convert `url()` in `@font-face` declarations to base64 strings
- Bundle all css into the JS bundle
- Copy `index.html` from `frontend/src/` to `frontend/dist/`
Clicking the button will call the backend
## Building
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
To generate a platform native package, add the `-package` flag.
## Live Development
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
directory and run `npm run dev`. The frontend dev server will run on http://localhost:5000. Connect to this
in your browser and connect to your application.

View File

@@ -0,0 +1,34 @@
package main
import (
"fmt"
"github.com/wailsapp/wails/v2"
)
// App application struct
type App struct {
runtime *wails.Runtime
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called at application startup
func (b *App) startup(runtime *wails.Runtime) {
// Perform your setup here
b.runtime = runtime
runtime.Window.SetTitle("{{.ProjectName}}")
}
// shutdown is called at application termination
func (b *App) shutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}

View File

@@ -0,0 +1,4 @@
/node_modules/
/dist/build/
.DS_Store

View File

@@ -0,0 +1,105 @@
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

View File

@@ -0,0 +1,27 @@
{
"name": "{{.ProjectName}}",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv dist --no-clear"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-image": "^2.0.6",
"@rollup/plugin-node-resolve": "^11.0.0",
"postcss": "^8.3.5",
"postcss-url": "^10.1.3",
"rollup": "^2.3.4",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0"
},
"dependencies": {
"sirv-cli": "^1.0.0"
}
,"author":"{{.AuthorName}}"}

View File

@@ -0,0 +1,91 @@
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import copy from 'rollup-plugin-copy';
import image from '@rollup/plugin-image';
import postcss from 'rollup-plugin-postcss'
import url from 'postcss-url';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'dist/bundle.js'
},
plugins: [
image({
include: './src/assets/images/**'
}),
svelte({
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
postcss({
minimize: true,
plugins: [
url({
url: "inline"
})
]
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
copy({
targets: [
{ src: 'src/index.html', dest: 'dist/' },
]
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `dist` directory and refresh the
// browser on changes when not in production
!production && livereload('dist'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};

View File

@@ -0,0 +1,121 @@
// @ts-check
/** This script modifies the project to support TS code in .svelte files like:
<script lang="ts">
export let name: string;
</script>
As well as validating the code for CI.
*/
/** To work on this script:
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
*/
const fs = require("fs")
const path = require("path")
const { argv } = require("process")
const projectRoot = argv[2] || path.join(__dirname, "..")
// Add deps to pkg.json
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
"svelte-check": "^2.0.0",
"svelte-preprocess": "^4.0.0",
"@rollup/plugin-typescript": "^8.0.0",
"typescript": "^4.0.0",
"tslib": "^2.0.0",
"@tsconfig/svelte": "^2.0.0"
})
// Add script for checking
packageJSON.scripts = Object.assign(packageJSON.scripts, {
"check": "svelte-check --tsconfig ./tsconfig.json"
})
// Write the package JSON
fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " "))
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
fs.renameSync(beforeMainJSPath, afterMainTSPath)
// Switch the app.svelte file to use TS
const appSveltePath = path.join(projectRoot, "src", "App.svelte")
let appFile = fs.readFileSync(appSveltePath, "utf8")
appFile = appFile.replace("<script>", '<script lang="ts">')
appFile = appFile.replace("export let name;", 'export let name: string;')
fs.writeFileSync(appSveltePath, appFile)
// Edit rollup config
const rollupConfigPath = path.join(projectRoot, "rollup.config.js")
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8")
// Edit imports
rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';`)
// Replace name of entry point
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
// Add preprocessor
rollupConfig = rollupConfig.replace(
'compilerOptions:',
'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:'
);
// Add TypeScript
rollupConfig = rollupConfig.replace(
'commonjs(),',
'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),'
);
fs.writeFileSync(rollupConfigPath, rollupConfig)
// Add TSConfig
const tsconfig = `{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}`
const tsconfigPath = path.join(projectRoot, "tsconfig.json")
fs.writeFileSync(tsconfigPath, tsconfig)
// Add global.d.ts
const dtsPath = path.join(projectRoot, "src", "global.d.ts")
fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`)
// Delete this script, but not during testing
if (!argv[2]) {
// Remove the script
fs.unlinkSync(path.join(__filename))
// Check for Mac's DS_store file, and if it's the only one left remove it
const remainingFiles = fs.readdirSync(path.join(__dirname))
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
fs.unlinkSync(path.join(__dirname, '.DS_store'))
}
// Check if the scripts folder is empty
if (fs.readdirSync(path.join(__dirname)).length === 0) {
// Remove the scripts folder
fs.rmdirSync(path.join(__dirname))
}
}
// Adds the extension recommendation
fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true })
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
"recommendations": ["svelte.svelte-vscode"]
}
`)
console.log("Converted to TypeScript.")
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
console.log("\nYou will need to re-run your dependency manager to get started.")
}

View File

@@ -0,0 +1,57 @@
<script>
let name = "";
let greeting = "";
function greet() {
window.backend.main.App.Greet(name).then((result) => {
greeting = result;
});
}
</script>
<main>
<div id="logo"></div>
<div id="input" data-wails-no-drag>
<input id="name" type="text" bind:value={name}>
<button class="button" on:click={greet}>Greet</button>
</div>
{#if greeting}
<div id="result">{greeting}</div>
{/if}
</main>
<style>
main {
height: 100%;
width: 100%;
}
#result {
margin-top: 1rem;
font-size: 1.5rem;
}
button {
-webkit-appearance: default-button;
padding: 6px;
}
#name {
border-radius: 3px;
outline: none;
-webkit-font-smoothing: antialiased;
}
#logo {
width: 40%;
height: 40%;
padding-top: 20%;
margin: auto;
display: block;
background-position: center;
background-repeat: no-repeat;
background-image: url("assets/images/logo-dark.svg");
}
</style>

View File

@@ -0,0 +1,93 @@
Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 551 436" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1.27527,0,0,1.27527,104.01,410.563)">
<path d="M0,-51.891L14.429,-51.891L13.043,-21.183L22.568,-51.891L34.226,-51.891L34.084,-21.183L42.365,-51.891L56.794,-51.891L38.526,0L25.198,0L25.34,-32.45L15.211,0L1.919,0L0,-51.891Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1.27527,0,0,1.27527,224.985,367.503)">
<path d="M0,15.639L5.793,15.639L5.971,-3.589L0,15.639ZM-20.187,33.765L-0.675,-18.126L16.42,-18.126L20.08,33.765L5.437,33.765L5.509,26.123L-3.057,26.123L-5.332,33.765L-20.187,33.765Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(0.19929,-1.2596,-1.2596,-0.19929,332.323,396.949)">
<path d="M-16.046,33.107L36.491,33.107L38.757,18.784L-13.785,18.82L-16.046,33.107Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1.27527,0,0,1.27527,353.217,344.388)">
<path d="M0,51.891L8.246,0L22.781,0L16.597,39.024L27.224,39.024L25.199,51.891L0,51.891Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1.27527,0,0,1.27527,427.939,364.922)">
<path d="M0,19.83C1.611,21.181 3.305,22.224 5.083,22.959C6.859,23.693 8.565,24.06 10.2,24.06C11.645,24.06 12.794,23.663 13.647,22.87C14.5,22.076 14.927,20.992 14.927,19.617C14.927,18.434 14.571,17.254 13.861,16.081C13.15,14.908 11.775,13.351 9.738,11.408C7.273,9.015 5.58,6.906 4.655,5.081C3.731,3.257 3.27,1.243 3.27,-0.96C3.27,-5.912 4.839,-9.846 7.979,-12.76C11.118,-15.674 15.377,-17.132 20.756,-17.132C22.936,-17.132 25.008,-16.889 26.975,-16.403C28.941,-15.917 30.943,-15.165 32.982,-14.146L30.92,-1.493C29.356,-2.583 27.834,-3.412 26.354,-3.981C24.872,-4.551 23.457,-4.835 22.106,-4.835C20.898,-4.835 19.943,-4.521 19.245,-3.894C18.546,-3.265 18.196,-2.406 18.196,-1.316C18.196,0.154 19.535,2.215 22.213,4.868C22.544,5.2 22.805,5.46 22.995,5.649C25.696,8.304 27.473,10.578 28.326,12.475C29.179,14.37 29.605,16.56 29.605,19.049C29.605,24.594 27.893,28.965 24.469,32.163C21.046,35.361 16.36,36.962 10.413,36.962C7.877,36.962 5.479,36.66 3.216,36.056C0.953,35.45 -0.948,34.615 -2.488,33.549L0,19.83Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(-166.599,4.57132,4.57132,166.599,147.403,167.648)">
<path d="M0.883,-0.081L0.121,0.081L0.256,-0.063L0.883,-0.081Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
</g>
<g transform="matrix(-106.443,-16.0669,-16.0669,106.443,428.19,188.033)">
<path d="M0.878,-0.285L-0.073,0.71L-1.186,0.542L0.015,0.207L-0.846,0.077L0.355,-0.258L-0.505,-0.388L0.649,-0.71L0.878,-0.285Z" style="fill:url(#_Linear2);fill-rule:nonzero;"/>
</g>
<g transform="matrix(-114.484,-162.408,-162.408,114.484,333.291,285.804)">
<path d="M0.44,-0.04L0.44,-0.04L0.44,-0.04L0.265,-0.056L0.177,0.437L-0.311,-0.255L0.262,-0.437L0.568,-0.437L0.44,-0.04Z" style="fill:url(#_Linear3);fill-rule:nonzero;"/>
</g>
<g transform="matrix(61.6919,58.8091,58.8091,-61.6919,258.631,180.413)">
<path d="M0.5,0L0.5,-0L0.5,0L0.5,0Z" style="fill:url(#_Linear4);fill-rule:nonzero;"/>
</g>
<g transform="matrix(238.126,298.893,298.893,-238.126,113.516,-150.536)">
<path d="M0.622,-0.115L0.761,-0.115L0.806,-0.013L0.826,0.182L0.622,-0.115Z" style="fill:url(#_Linear5);fill-rule:nonzero;"/>
</g>
<g transform="matrix(-369.529,-97.4118,-97.4118,369.529,582.38,94.027)">
<path d="M0.467,0.005L0.49,0.062L0.271,-0.062L0.467,0.005Z" style="fill:url(#_Linear6);fill-rule:nonzero;"/>
</g>
<g transform="matrix(-496.156,-53.9751,-53.9751,496.156,367.888,125.085)">
<path d="M0.2,0.001L0.219,-0.018L0.614,0.012L0.519,0.089L0.282,0.068L0.2,0.135L0.463,0.194L0.374,0.266L0.138,0.186L0.138,0.186L0.138,0.186L0.047,0.033L-0.131,-0.266L0.2,0.001Z" style="fill:url(#_Linear7);fill-rule:nonzero;"/>
</g>
<g transform="matrix(185.076,176.427,176.427,-185.076,153.446,80.1488)">
<path d="M0.735,-0L0.735,-0L0.735,0L0.735,-0Z" style="fill:url(#_Linear8);fill-rule:nonzero;"/>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,-3.46945e-18,-3.46945e-18,-1,0,-3.05761e-06)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,-1,0,-2.75467e-06)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,-1.11022e-16,-1.11022e-16,-1,0,-2.61861e-06)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,-5.55112e-17,-5.55112e-17,-1,0,-1.57562e-06)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-0.801899,-0.59746,-0.59746,0.801899,1.3495,0.447457)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,-2.77556e-17,-2.77556e-17,-1,0,-1.92826e-06)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear7" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,-1,0,9.68429e-07)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear8" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,-1,0,1.43665e-07)"><stop offset="0" style="stop-color:rgb(227,50,50);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(107,0,13);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -0,0 +1,24 @@
html {
text-align: center;
color: white;
background-color: rgba(1,1,1,0.1);
width: 100%;
height: 100%;
}
body {
color: white;
font-family: 'Nunito', -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
margin: 0;
width: 100%;
height: 100%;
}
@font-face {
font-family: 'Nunito';
font-style: normal;
font-weight: 400;
src: local(''),
url('./assets/fonts/nunito-v16-latin-regular.woff2') format('woff2')
}

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<script defer src='bundle.js'></script>
</head>
<body data-wails-drag>
</body>
</html>

View File

@@ -0,0 +1,9 @@
import App from './App.svelte';
import './global.css';
const app = new App({
target: document.body,
});
export default app;

View File

@@ -0,0 +1,9 @@
module test
go 1.16
require (
github.com/wailsapp/wails/v2 v2.0.0-alpha
)
replace github.com/wailsapp/wails/v2 v2.0.0-alpha => {{.WailsDirectory}}

View File

@@ -0,0 +1,56 @@
package main
import (
"log"
"github.com/wailsapp/wails/v2/pkg/options/windows"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/mac"
)
func main() {
// Create application with options
app := NewApp()
err := wails.Run(&options.App{
Title: "{{.ProjectName}}",
Width: 800,
Height: 600,
MinWidth: 400,
MinHeight: 400,
MaxWidth: 1280,
MaxHeight: 1024,
DisableResize: false,
Fullscreen: false,
Frameless: false,
StartHidden: false,
HideWindowOnClose: false,
DevTools: false,
RGBA: 0x000000FF,
Windows: &windows.Options{
WebviewIsTransparent: true,
WindowBackgroundIsTranslucent: true,
DisableWindowIcon: true,
},
Mac: &mac.Options{
WebviewIsTransparent: true,
WindowBackgroundIsTranslucent: true,
TitleBar: mac.TitleBarHiddenInset(),
Menu: menu.DefaultMacMenu(),
},
LogLevel: logger.DEBUG,
Startup: app.startup,
Shutdown: app.shutdown,
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "Basic Svelte + Rollup",
"shortname": "svelte",
"author": "Lea Anthony",
"description": "Svelte template using rollup to bundle css, images and fonts",
"helpurl": "https://github.com/wailsapp/wails"
}

View File

@@ -0,0 +1,11 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"html": "frontend/dist/index.html",
"frontend:build": "npm run build",
"frontend:install": "npm install",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"
}
}

View File

@@ -0,0 +1,34 @@
package main
import (
"fmt"
"github.com/wailsapp/wails/v2"
)
// App struct
type App struct {
runtime *wails.Runtime
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called at application startup
func (b *App) startup(runtime *wails.Runtime) {
// Perform your setup here
b.runtime = runtime
runtime.Window.SetTitle("{{.ProjectName}}")
}
// shutdown is called at application termination
func (b *App) shutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}

View File

@@ -12,9 +12,9 @@ ready( () => {
// Get name
let name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
// Call App.Greet(name)
window.backend.main.App.Greet(name).then((result) => {
// Update result with data back from App.Greet()
document.getElementById("result").innerText = result;
});
};

View File

@@ -1,9 +1,10 @@
package main
import (
"github.com/wailsapp/wails/v2/pkg/options/windows"
"log"
"github.com/wailsapp/wails/v2/pkg/options/windows"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/menu"
@@ -14,7 +15,7 @@ import (
func main() {
// Create application with options
app := NewBasic()
app := NewApp()
err := wails.Run(&options.App{
Title: "{{.ProjectName}}",

View File

@@ -3,7 +3,7 @@
"outputfilename": "{{.BinaryName}}",
"html": "frontend/dist/index.html",
"frontend:build": "npm run build",
"frontend:install": "npm ci",
"frontend:install": "npm install",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@@ -10,7 +10,6 @@ import (
"github.com/leaanthony/clir"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/build"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/debug"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/dev"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/doctor"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate"
@@ -40,10 +39,6 @@ func main() {
fatal(err.Error())
}
err = debug.AddSubcommand(app, os.Stdout)
if err != nil {
fatal(err.Error())
}
err = doctor.AddSubcommand(app, os.Stdout)
if err != nil {
fatal(err.Error())

View File

@@ -1,3 +1,3 @@
package main
var version = "v2.0.0-alpha.68"
var version = "v2.0.0-alpha.71"

View File

@@ -6,9 +6,14 @@ require (
github.com/Masterminds/semver v1.5.0
github.com/fatih/structtag v1.2.0
github.com/fsnotify/fsnotify v1.4.9
github.com/go-git/go-billy/v5 v5.2.0 // indirect
github.com/go-git/go-git/v5 v5.3.0
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/gorilla/websocket v1.4.1
github.com/imdario/mergo v0.3.11
github.com/imdario/mergo v0.3.12
github.com/jackmordaunt/icns v1.0.0
github.com/klauspost/compress v1.11.3 // indirect
github.com/leaanthony/clir v1.0.4
github.com/leaanthony/debme v1.2.1
github.com/leaanthony/go-ansi-parser v1.0.1
@@ -21,13 +26,18 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/olekukonko/tablewriter v0.0.4
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0 // indirect
github.com/tdewolff/minify v2.3.6+incompatible
github.com/tdewolff/parse v2.3.4+incompatible // indirect
github.com/tdewolff/test v1.0.6 // indirect
github.com/tidwall/sjson v1.1.7
github.com/wzshiming/ctc v1.2.3
github.com/xyproto/xpm v1.2.1
golang.org/x/net v0.0.0-20200822124328-c89045814202
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/mod v0.4.1 // indirect
golang.org/x/net v0.0.0-20210326060303-6b1517762897
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82
golang.org/x/text v0.3.5 // indirect
golang.org/x/tools v0.1.0
nhooyr.io/websocket v1.8.6
)

125
v2/go.sum
View File

@@ -1,15 +1,41 @@
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk=
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc=
github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@@ -26,23 +52,42 @@ github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ=
github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
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/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/debme v1.1.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
@@ -68,26 +113,46 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
github.com/tdewolff/parse v2.3.4+incompatible h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxpP46ghf0Qzh38=
github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8=
github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
@@ -96,46 +161,80 @@ github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDCc9OojJZCQMVRAbT3TTdUMP8WguXkY=
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ=
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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.0.0-20200902012652-d1954cc86c82 h1:shxDsb9Dz27xzk3A0DxP0JuJnZMpKrdg8+E14eiUAX4=
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=

View File

@@ -117,6 +117,7 @@ func (a *App) Run() error {
var subsystemWaitGroup sync.WaitGroup
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
ctx, cancel := context.WithCancel(parentContext)
defer cancel()
// Start the service bus
a.servicebus.Debug()
@@ -125,7 +126,7 @@ func (a *App) Run() error {
return err
}
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, nil)
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
if err != nil {
return err
}

View File

@@ -34,7 +34,15 @@ func (b BridgeClient) CallResult(message string) {
b.session.sendMessage("c" + message)
}
func (b BridgeClient) OpenDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
func (b BridgeClient) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
// Handled by dialog_client
}
func (b BridgeClient) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
// Handled by dialog_client
}
func (b BridgeClient) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
// Handled by dialog_client
}

View File

@@ -37,7 +37,11 @@ func (d *DialogClient) NotifyEvent(message string) {
func (d *DialogClient) CallResult(message string) {
}
func (d *DialogClient) OpenDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
func (d *DialogClient) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
}
func (d *DialogClient) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
}
func (d *DialogClient) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
}
func (d *DialogClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) {

View File

@@ -102,6 +102,7 @@ struct Application {
id mouseDownMonitor;
id mouseUpMonitor;
int activationPolicy;
id pool;
// Window Data
const char *title;
@@ -560,7 +561,7 @@ void ToggleFullscreen(struct Application *app) {
}
bool isFullScreen(struct Application *app) {
int mask = (int)msg_reg(app->mainWindow, s("styleMask"));
long mask = (long)msg_reg(app->mainWindow, s("styleMask"));
bool result = (mask & NSWindowStyleMaskFullscreen) == NSWindowStyleMaskFullscreen;
return result;
}
@@ -789,7 +790,7 @@ void MessageDialog(struct Application *app, char *callbackID, char *type, char *
// Run modal
char *buttonPressed;
int response = (int)msg_reg(alert, s("runModal"));
long response = (long)msg_reg(alert, s("runModal"));
if( response == NSAlertFirstButtonReturn ) {
buttonPressed = button1;
}
@@ -1451,6 +1452,7 @@ void processDialogIcons(struct hashmap_s *hashmap, const unsigned char *dialogIc
// Create the icon and add to the hashmap
id imageData = ((id(*)(id, SEL, const unsigned char *, int))objc_msgSend)(c("NSData"), s("dataWithBytes:length:"), data, length);
id dialogImage = ALLOC("NSImage");
msg_reg(dialogImage, s("autorelease"));
msg_id(dialogImage, s("initWithData:"), imageData);
hashmap_put(hashmap, (const char *)name, strlen((const char *)name), dialogImage);
}
@@ -1622,7 +1624,9 @@ void Run(struct Application *app, int argc, char **argv) {
MEMFREE(temp);
// Add code that sets up the initial state, EG: State Stores.
temp = concat(internalCode, getInitialState(app));
const char *initialState = getInitialState(app);
temp = concat(internalCode, initialState);
MEMFREE(initialState);
MEMFREE(internalCode);
internalCode = temp;
@@ -1723,7 +1727,10 @@ id createImageFromBase64Data(const char *data, bool isTemplateImage) {
imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(nsdata, s("initWithBase64EncodedString:options:"), str(BrokenImage), 0);
}
id result = ALLOC("NSImage");
msg_reg(result, s("autorelease"));
msg_id(result, s("initWithData:"), imageData);
msg_reg(nsdata, s("release"));
msg_reg(imageData, s("release"));
if( isTemplateImage ) {
msg_bool(result, s("setTemplate:"), YES);
@@ -1801,6 +1808,8 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
result->running = false;
result->pool = msg_reg(c("NSAutoreleasePool"), s("new"));
return (void*) result;
}

View File

@@ -85,13 +85,12 @@ void DeleteMenu(Menu *menu) {
menu->processedMenu = NULL;
}
// Release the vector memory
vec_deinit(&menu->callbackDataCache);
// Free nsmenu if we have it
if ( menu->menu != NULL ) {
msg_reg(menu->menu, s("release"));
// Release the callback data memory + vector
int i; MenuItemCallbackData* callbackData;
vec_foreach(&menu->callbackDataCache, callbackData, i) {
free(callbackData);
}
vec_deinit(&menu->callbackDataCache);
free(menu);
}
@@ -376,7 +375,7 @@ id createMenu(id title) {
id menu = ALLOC("NSMenu");
msg_id(menu, s("initWithTitle:"), title);
msg_bool(menu, s("setAutoenablesItems:"), NO);
// msg(menu, s("autorelease"));
msg_reg(menu, s("autorelease"));
return menu;
}
@@ -562,6 +561,7 @@ id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key) {
id item = ALLOC("NSMenuItem");
msg_reg(item, s("autorelease"));
// Store the item in the menu item map
hashmap_put(&menu->menuItemMap, (char*)menuid, strlen(menuid), item);
@@ -573,7 +573,6 @@ id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const c
msg_id(item, s("setRepresentedObject:"), wrappedId);
((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuItemCallback:"), str(key));
msg_bool(item, s("setEnabled:"), !disabled);
msg_reg(item, s("autorelease"));
msg_int(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff));
msg_id(parentmenu, s("addItem:"), item);
return item;
@@ -727,6 +726,7 @@ id createAttributedString(const char* title, const char* fontName, int fontSize,
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate, JsonNode* styledLabel) {
id item = ALLOC("NSMenuItem");
msg_reg(item, s("autorelease"));
// Create a MenuItemCallbackData
MenuItemCallbackData *callback = CreateMenuItemCallbackData(menu, item, menuid, Text);
@@ -763,7 +763,6 @@ id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char
//msg_id(item, s("setTitle:"), str(title));
msg_bool(item, s("setEnabled:"), !disabled);
msg_reg(item, s("autorelease"));
// Process modifiers
if( modifiers != NULL && !alternate) {

View File

@@ -155,6 +155,10 @@ void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
// Delete the old menu
DeleteMenu(currentMenu->menu);
if( currentMenu->delegate != NULL ) {
msg_reg(currentMenu->delegate, s("release"));
currentMenu->delegate = NULL;
}
// Set the new one
currentMenu->menu = newMenu->menu;
@@ -176,11 +180,12 @@ void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
void DeleteTrayMenu(TrayMenu* trayMenu) {
// printf("Freeing TrayMenu:\n");
// DumpTrayMenu(trayMenu);
// Delete the menu
DeleteMenu(trayMenu->menu);
if( trayMenu->delegate != NULL ) {
msg_reg(trayMenu->delegate, s("release"));
trayMenu->delegate = NULL;
}
// Free JSON
if (trayMenu->processedJSON != NULL ) {
@@ -195,8 +200,21 @@ void DeleteTrayMenu(TrayMenu* trayMenu) {
trayMenu->statusbaritem = NULL;
}
if ( trayMenu->delegate != NULL ) {
// Free the tray menu memory
MEMFREE(trayMenu);
}
void DeleteTrayMenuKeepStatusBarItem(TrayMenu* trayMenu) {
// Delete the menu
DeleteMenu(trayMenu->menu);
if( trayMenu->delegate != NULL ) {
msg_reg(trayMenu->delegate, s("release"));
trayMenu->delegate = NULL;
}
// Free JSON
if (trayMenu->processedJSON != NULL ) {
json_delete(trayMenu->processedJSON);
}
// Free the tray menu memory

View File

@@ -46,5 +46,6 @@ void LoadTrayIcons();
void UnloadTrayIcons();
void DeleteTrayMenu(TrayMenu* trayMenu);
void DeleteTrayMenuKeepStatusBarItem(TrayMenu* trayMenu);
#endif //TRAYMENU_DARWIN_H

View File

@@ -131,7 +131,7 @@ void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON) {
UpdateTrayLabel(menu, Label, fontName, fontSize, RGBA, tooltip, disabled, styledLabel);
json_delete(parsedUpdate);
}
void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
@@ -162,11 +162,7 @@ void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
pthread_mutex_unlock(&store->lock);
// Delete the current menu
DeleteMenu(currentMenu->menu);
currentMenu->menu = NULL;
// Free the tray menu memory
MEMFREE(currentMenu);
DeleteTrayMenuKeepStatusBarItem(currentMenu);
pthread_mutex_lock(&store->lock);
hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);

View File

@@ -215,10 +215,10 @@ func DirIsEmpty(dir string) (bool, error) {
return false, err // Either not empty or error, suits both cases
}
// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04
// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
// Symlinks are ignored and skipped.
// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04
func CopyDir(src string, dst string) (err error) {
src = filepath.Clean(src)
dst = filepath.Clean(dst)
@@ -273,3 +273,125 @@ func CopyDir(src string, dst string) (err error) {
return
}
// CopyDirExtended recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist. It ignores any files or
// directories that are given through the ignore parameter.
// Symlinks are ignored and skipped.
// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04
func CopyDirExtended(src string, dst string, ignore []string) (err error) {
ignoreList := slicer.String(ignore)
src = filepath.Clean(src)
dst = filepath.Clean(dst)
si, err := os.Stat(src)
if err != nil {
return err
}
if !si.IsDir() {
return fmt.Errorf("source is not a directory")
}
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return
}
if err == nil {
return fmt.Errorf("destination already exists")
}
err = MkDirs(dst)
if err != nil {
return
}
entries, err := ioutil.ReadDir(src)
if err != nil {
return
}
for _, entry := range entries {
if ignoreList.Contains(entry.Name()) {
continue
}
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
err = CopyDir(srcPath, dstPath)
if err != nil {
return
}
} else {
// Skip symlinks.
if entry.Mode()&os.ModeSymlink != 0 {
continue
}
err = CopyFile(srcPath, dstPath)
if err != nil {
return
}
}
}
return
}
// MoveDirExtended recursively moves a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist. It ignores any files or
// directories that are given through the ignore parameter.
// Symlinks are ignored and skipped.
func MoveDirExtended(src string, dst string, ignore []string) (err error) {
ignoreList := slicer.String(ignore)
src = filepath.Clean(src)
dst = filepath.Clean(dst)
si, err := os.Stat(src)
if err != nil {
return err
}
if !si.IsDir() {
return fmt.Errorf("source is not a directory")
}
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return
}
if err == nil {
return fmt.Errorf("destination already exists")
}
err = MkDirs(dst)
if err != nil {
return
}
entries, err := ioutil.ReadDir(src)
if err != nil {
return
}
for _, entry := range entries {
if ignoreList.Contains(entry.Name()) {
continue
}
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
// Skip symlinks.
if entry.Mode()&os.ModeSymlink != 0 {
continue
}
err := os.Rename(srcPath, dstPath)
if err != nil {
return err
}
}
return
}

View File

@@ -1,10 +1,12 @@
package system
import (
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
"os/exec"
"strings"
"syscall"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
)
// Info holds information about the current operating system,
@@ -105,3 +107,14 @@ func checkDocker() *packagemanager.Dependancy {
External: false,
}
}
// IsAppleSilicon returns true if the app is running on Apple Silicon
// Credit: https://www.yellowduck.be/posts/detecting-apple-silicon-via-go/
func IsAppleSilicon() bool {
r, err := syscall.Sysctl("sysctl.proc_translated")
if err != nil {
return false
}
return r == "\x00\x00\x00" || r == "\x01\x00\x00"
}

View File

@@ -171,6 +171,9 @@ func (b *BaseBuilder) OutputFilename(options *Options) string {
case "windows":
outputFile = target + ".exe"
case "darwin", "linux":
if b.options.Arch == "" {
b.options.Arch = runtime.GOARCH
}
outputFile = fmt.Sprintf("%s-%s-%s", target, b.options.Platform, b.options.Arch)
}
@@ -228,20 +231,26 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
commands.Add("-tags")
commands.Add(tags.Join(","))
// Strip binary in Production mode
// LDFlags
ldflags := slicer.String()
if options.LDFlags != "" {
ldflags.Add(options.LDFlags)
}
if options.Mode == Production {
// Different linker flags depending on platform
commands.Add("-ldflags")
switch runtime.GOOS {
case "windows":
commands.Add("-w -s -H windowsgui")
default:
commands.Add("-w -s")
ldflags.Add("-w", "-s")
if runtime.GOOS == "windows" {
ldflags.Add("-H windowsgui")
}
}
ldflags.Deduplicate()
if ldflags.Length() > 0 {
commands.Add("-ldflags")
commands.Add(ldflags.Join(" "))
}
// Get application build directory
appDir := options.BuildDirectory
if options.CleanBuildDirectory {
@@ -251,11 +260,6 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
}
}
if options.LDFlags != "" {
commands.Add("-ldflags")
commands.Add(options.LDFlags)
}
// Set up output filename
outputFile := b.OutputFilename(options)
compiledBinary := filepath.Join(appDir, outputFile)

View File

@@ -48,6 +48,7 @@ type Options struct {
CompressFlags string // Flags to pass to UPX
AppleIdentity string
WebView2Strategy string // WebView2 installer strategy
RunDelve bool // Indicates if we should run delve after the build
}
// Build the project!