diff --git a/.all-contributorsrc b/.all-contributorsrc
index 9c5e450b1..ced3b155b 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -158,7 +158,7 @@
]
},
{
- "login": "codydbentley",
+ "login": "sircodemane",
"name": "Cody Bentley",
"avatar_url": "https://avatars.githubusercontent.com/u/6968902?v=4",
"profile": "https://codybentley.dev/",
@@ -1348,6 +1348,517 @@
"contributions": [
"doc"
]
+ },
+ {
+ "login": "github-actions[bot]",
+ "name": "github-actions[bot]",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "profile": "https://github.com/apps/github-actions",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "OlegGulevskyy",
+ "name": "Oleg Gulevskyy",
+ "avatar_url": "https://avatars.githubusercontent.com/u/43781031?v=4",
+ "profile": "https://github.com/OlegGulevskyy",
+ "contributions": [
+ "code",
+ "doc",
+ "maintenance",
+ "platform"
+ ]
+ },
+ {
+ "login": "raguay",
+ "name": "Richard Guay",
+ "avatar_url": "https://avatars.githubusercontent.com/u/2487495?v=4",
+ "profile": "http://www.customct.com/",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "ATenderholt",
+ "name": "Adam Tenderholt",
+ "avatar_url": "https://avatars.githubusercontent.com/u/740623?v=4",
+ "profile": "https://github.com/ATenderholt",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "JulioDRF",
+ "name": "JulioDRF",
+ "avatar_url": "https://avatars.githubusercontent.com/u/15677708?v=4",
+ "profile": "https://github.com/JulioDRF",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "scottopell",
+ "name": "Scott Opell",
+ "avatar_url": "https://avatars.githubusercontent.com/u/996472?v=4",
+ "profile": "http://scottopell.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "avengerweb",
+ "name": "Vadim Shchepotev",
+ "avatar_url": "https://avatars.githubusercontent.com/u/2055581?v=4",
+ "profile": "https://aven.dev/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "willdot",
+ "name": "Will Andrews",
+ "avatar_url": "https://avatars.githubusercontent.com/u/4906530?v=4",
+ "profile": "https://willdot.net/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "gwynforthewyn",
+ "name": "Gwyn",
+ "avatar_url": "https://avatars.githubusercontent.com/u/434656?v=4",
+ "profile": "https://github.com/gwynforthewyn",
+ "contributions": [
+ "code",
+ "review",
+ "question",
+ "research"
+ ]
+ },
+ {
+ "login": "xijaja",
+ "name": "希嘉嘉",
+ "avatar_url": "https://avatars.githubusercontent.com/u/47017666?v=4",
+ "profile": "https://github.com/xijaja",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "almas1992",
+ "name": "ALMAS",
+ "avatar_url": "https://avatars.githubusercontent.com/u/9382335?v=4",
+ "profile": "https://www.almas.cc/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "o8x",
+ "name": "Alex",
+ "avatar_url": "https://avatars.githubusercontent.com/u/20666153?v=4",
+ "profile": "https://stdout.com.cn/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "arifali123",
+ "name": "Arif Ali",
+ "avatar_url": "https://avatars.githubusercontent.com/u/51419655?v=4",
+ "profile": "https://github.com/arifali123",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "hotafrika",
+ "name": "Artur Siarohau",
+ "avatar_url": "https://avatars.githubusercontent.com/u/18332839?v=4",
+ "profile": "https://github.com/hotafrika",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "binyamin",
+ "name": "Binyamin Aron Green",
+ "avatar_url": "https://avatars.githubusercontent.com/u/39805353?v=4",
+ "profile": "https://binyam.in/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "bdwyertech",
+ "name": "Brian Dwyer",
+ "avatar_url": "https://avatars.githubusercontent.com/u/2973273?v=4",
+ "profile": "http://bdwyertech.net/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "ckilb",
+ "name": "Christian Kilb",
+ "avatar_url": "https://avatars.githubusercontent.com/u/7283097?v=4",
+ "profile": "http://www.cilb.de/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "edwargix",
+ "name": "David Florness",
+ "avatar_url": "https://avatars.githubusercontent.com/u/22877007?v=4",
+ "profile": "https://github.com/edwargix",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "BuckeyeCoder",
+ "name": "David Walton",
+ "avatar_url": "https://avatars.githubusercontent.com/u/95933880?v=4",
+ "profile": "https://github.com/BuckeyeCoder",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Debdut",
+ "name": "Debdut Karmakar",
+ "avatar_url": "https://avatars.githubusercontent.com/u/7561070?v=4",
+ "profile": "https://github.com/Debdut",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "gotid",
+ "name": "Dieter Zhu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/4010854?v=4",
+ "profile": "https://github.com/gotid",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Holmqvist1990",
+ "name": "Fredrik Holmqvist",
+ "avatar_url": "https://avatars.githubusercontent.com/u/22743750?v=4",
+ "profile": "https://fredrikholmqvist.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "giopalma",
+ "name": "Giovanni Palma",
+ "avatar_url": "https://avatars.githubusercontent.com/u/33783684?v=4",
+ "profile": "https://github.com/giopalma",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Nexus26404",
+ "name": "Hao",
+ "avatar_url": "https://avatars.githubusercontent.com/u/83110373?v=4",
+ "profile": "https://github.com/Nexus26404",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "i7tsov",
+ "name": "Igor Sementsov",
+ "avatar_url": "https://avatars.githubusercontent.com/u/44977153?v=4",
+ "profile": "https://github.com/i7tsov",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "derhasi",
+ "name": "Johannes Haseitl",
+ "avatar_url": "https://avatars.githubusercontent.com/u/118502?v=4",
+ "profile": "https://github.com/derhasi",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "joshbuddy",
+ "name": "Joshua Hull",
+ "avatar_url": "https://avatars.githubusercontent.com/u/8898?v=4",
+ "profile": "https://github.com/joshbuddy",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "joshm998",
+ "name": "Joshua Mangiola",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1779737?v=4",
+ "profile": "https://github.com/joshm998",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "prurigro",
+ "name": "Kevin MacMartin",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1149238?v=4",
+ "profile": "https://github.com/prurigro",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "liang-li-dev",
+ "name": "Liang Li",
+ "avatar_url": "https://avatars.githubusercontent.com/u/112530363?v=4",
+ "profile": "https://github.com/liang-li-dev",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "marvinhosea",
+ "name": "Marvin Collins Hosea",
+ "avatar_url": "https://avatars.githubusercontent.com/u/7722584?v=4",
+ "profile": "https://appslab.co.ke/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "mholt",
+ "name": "Matt Holt",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1128849?v=4",
+ "profile": "https://matt.life/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Gurkengewuerz",
+ "name": "Niklas",
+ "avatar_url": "https://avatars.githubusercontent.com/u/10966337?v=4",
+ "profile": "https://github.com/Gurkengewuerz",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Xhofe",
+ "name": "Andy Hsu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/36558727?v=4",
+ "profile": "https://github.com/Xhofe",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "NullCode1337",
+ "name": "NullCode",
+ "avatar_url": "https://avatars.githubusercontent.com/u/70959549?v=4",
+ "profile": "https://github.com/NullCode1337",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "oSethoum",
+ "name": "Oussama Sethoum",
+ "avatar_url": "https://avatars.githubusercontent.com/u/88779394?v=4",
+ "profile": "https://github.com/oSethoum",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "ParkourLiu",
+ "name": "ParkourLiu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/33681340?v=4",
+ "profile": "https://github.com/ParkourLiu",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "zllovesuki",
+ "name": "Rachel Chen",
+ "avatar_url": "https://avatars.githubusercontent.com/u/298453?v=4",
+ "profile": "https://github.com/zllovesuki",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "rnice01",
+ "name": "Rob Nice",
+ "avatar_url": "https://avatars.githubusercontent.com/u/11394384?v=4",
+ "profile": "https://github.com/rnice01",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "RyoTagami",
+ "name": "Ryo TAGAMI",
+ "avatar_url": "https://avatars.githubusercontent.com/u/9672589?v=4",
+ "profile": "https://github.com/RyoTagami",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "SamHennessy",
+ "name": "Sam Hennessy",
+ "avatar_url": "https://avatars.githubusercontent.com/u/119867?v=4",
+ "profile": "https://github.com/SamHennessy",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "AlbinoDrought",
+ "name": "Sean",
+ "avatar_url": "https://avatars.githubusercontent.com/u/852873?v=4",
+ "profile": "https://albinodrought.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "sgosiaco",
+ "name": "Sean Gosiaco",
+ "avatar_url": "https://avatars.githubusercontent.com/u/212341?v=4",
+ "profile": "https://github.com/sgosiaco",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "SheetJSDev",
+ "name": "Eric P Sheets",
+ "avatar_url": "https://avatars.githubusercontent.com/u/6070939?v=4",
+ "profile": "https://sheetjs.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "SupianIDz",
+ "name": "Supian M",
+ "avatar_url": "https://avatars.githubusercontent.com/u/37969970?v=4",
+ "profile": "https://www.octopy.dev/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Watson-Sei",
+ "name": "Watson-Sei",
+ "avatar_url": "https://avatars.githubusercontent.com/u/55475145?v=4",
+ "profile": "https://github.com/Watson-Sei",
+ "contributions": [
+ "code",
+ "doc"
+ ]
+ },
+ {
+ "login": "shinshin86",
+ "name": "Yuki Shindo",
+ "avatar_url": "https://avatars.githubusercontent.com/u/8216064?v=4",
+ "profile": "https://shinshin86.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "cuigege",
+ "name": "cuigege",
+ "avatar_url": "https://avatars.githubusercontent.com/u/26080122?v=4",
+ "profile": "https://github.com/cuigege",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "cybertramp",
+ "name": "cybertramp",
+ "avatar_url": "https://avatars.githubusercontent.com/u/30935096?v=4",
+ "profile": "https://cybertramp.net/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "h8gi",
+ "name": "hiroki yagi",
+ "avatar_url": "https://avatars.githubusercontent.com/u/10811057?v=4",
+ "profile": "https://github.com/h8gi",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "imgbot[bot]",
+ "name": "imgbot[bot]",
+ "avatar_url": "https://avatars.githubusercontent.com/in/4706?v=4",
+ "profile": "https://github.com/apps/imgbot",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "tong3jie",
+ "name": "juju",
+ "avatar_url": "https://avatars.githubusercontent.com/u/14191774?v=4",
+ "profile": "https://github.com/tong3jie",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "meatherly",
+ "name": "Michael Eatherly",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1327960?v=4",
+ "profile": "http://meatherly.github.io/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "tk103331",
+ "name": "tk",
+ "avatar_url": "https://avatars.githubusercontent.com/u/4404609?v=4",
+ "profile": "https://github.com/tk103331",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "allcontributors[bot]",
+ "name": "allcontributors[bot]",
+ "avatar_url": "https://avatars.githubusercontent.com/in/23186?v=4",
+ "profile": "https://github.com/apps/allcontributors",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "wandercn",
+ "name": "wander",
+ "avatar_url": "https://avatars.githubusercontent.com/u/77320953?v=4",
+ "profile": "https://www.ffactory.org/",
+ "contributions": [
+ "doc"
+ ]
}
],
"contributorsPerLine": 8,
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 6b6c2075e..000000000
--- a/.eslintignore
+++ /dev/null
@@ -1 +0,0 @@
-runtime/assets/default.html
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index 570dfef81..000000000
--- a/.eslintrc
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "env": {
- "browser": true,
- "es6": true,
- "node": true,
- },
- "extends": "eslint:recommended",
- "parserOptions": {
- "ecmaVersion": 2016,
- "sourceType": "module",
- },
- "rules": {
- "indent": [
- "error",
- "tab"
- ],
- "linebreak-style": [
- "error",
- "unix"
- ],
- "quotes": [
- "error",
- "single"
- ],
- "semi": [
- "error",
- "always"
- ]
- }
-}
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 180057d45..9faf71704 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -7,7 +7,7 @@ body:
- type: markdown
attributes:
value: |
- ***Please note: No new bug reports are being accepted for Wails v1***
+ ***Please note: No bug reports are currently being accepted for Wails v3***
Before submitting this issue, please do the following:
- Do a web search for your error. This usually leads to a much better understanding of the issue.
- Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce.
@@ -70,7 +70,7 @@ body:
validations:
required: false
- type: textarea
- id: systemetails
+ id: systemdetails
attributes:
label: System Details
description: Please add the output of `wails doctor`.
@@ -84,4 +84,4 @@ body:
description: Add any other context about the problem here.
placeholder: Add any other context about the problem here.
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 7655d2651..e3632ecaa 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,9 @@
blank_issues_enabled: true
contact_links:
+ - name: Discord Chat
+ url: https://discord.gg/BrRSWTaxVK
+ about: Ask questions and discuss with other Wails users in real time.
+
- name: GitHub Community Discussions
url: https://github.com/wailsapp/wails/discussions
about: If your question is not a feature or a bug, please go to the discussion panel and retrieve if your question already exists before submitting.
diff --git a/.github/file-labeler.yml b/.github/file-labeler.yml
new file mode 100644
index 000000000..69494cbae
--- /dev/null
+++ b/.github/file-labeler.yml
@@ -0,0 +1,44 @@
+# File path specific labels
+v2-only:
+ - 'v2/**/*'
+
+v3-alpha:
+ - 'v3/**/*'
+
+windows:
+ - '**/*_windows.go'
+ - 'v2/internal/frontend/desktop/windows/**/*'
+
+macos:
+ - '**/*_darwin.go'
+ - 'v2/internal/frontend/desktop/darwin/**/*'
+
+linux:
+ - '**/*_linux.go'
+ - 'v2/internal/frontend/desktop/linux/**/*'
+
+cli:
+ - 'v2/cmd/**/*'
+ - 'v3/cmd/**/*'
+ - '**/cli/**/*'
+ - '**/commands/**/*'
+
+documentation:
+ - '**/*.md'
+ - 'docs/**/*'
+ - 'website/**/*'
+ - 'mkdocs-website/**/*'
+
+templates:
+ - '**/templates/**/*'
+ - '**/template/**/*'
+
+runtime:
+ - '**/runtime/**/*'
+ - 'v2/internal/runtime/**/*'
+ - 'v3/internal/runtime/**/*'
+
+bindings:
+ - 'v2/internal/binding/**/*'
+ - 'v3/internal/generator/**/*'
+
diff --git a/.github/issue-labeler.yml b/.github/issue-labeler.yml
new file mode 100644
index 000000000..0a7949051
--- /dev/null
+++ b/.github/issue-labeler.yml
@@ -0,0 +1,144 @@
+# Version labels
+v2-only:
+ - '\[v2\]'
+ - '\(v2\)'
+ - 'v2:'
+ - 'version 2'
+ - 'wails v2'
+ - 'using v2'
+ - 'master branch'
+
+v3-alpha:
+ - '\[v3\]'
+ - '\(v3\)'
+ - 'v3:'
+ - '\[v3-alpha\]'
+ - '\(v3-alpha\)'
+ - 'version 3'
+ - 'wails v3'
+ - 'using v3'
+ - 'v3-alpha branch'
+
+# Component labels
+webview2:
+ - 'webview2'
+ - 'windows'
+ - 'microsoft edge'
+ - 'edge browser'
+ - 'IE'
+ - 'Explorer'
+ - 'browser crashes'
+
+macos:
+ - 'macOS'
+ - 'mac OS'
+ - 'OS X'
+ - 'darwin'
+ - 'cocoa'
+ - 'Safari'
+ - 'Catalyst'
+ - 'Ventura'
+ - 'Sonoma'
+ - 'apple'
+
+linux:
+ - 'linux'
+ - 'ubuntu'
+ - 'debian'
+ - 'fedora'
+ - 'gtk'
+ - 'webkitgtk'
+ - 'webkit2gtk'
+ - 'gnome'
+ - 'x11'
+ - 'wayland'
+
+cli:
+ - 'cli'
+ - 'command line'
+ - 'wails doctor'
+ - 'wails init'
+ - 'wails build'
+ - 'wails dev'
+ - 'template'
+ - 'scaffolding'
+
+# Type labels
+bug:
+ - 'bug'
+ - 'crash'
+ - 'broken'
+ - 'failure'
+ - 'error'
+ - 'failed'
+ - 'panic'
+ - 'segfault'
+ - 'issue'
+ - 'not working'
+ - 'problem'
+
+enhancement:
+ - 'feature'
+ - 'enhancement'
+ - 'request'
+ - 'add'
+ - 'new'
+ - 'improve'
+ - 'functionality'
+ - 'support for'
+ - 'please add'
+ - 'would be nice'
+
+documentation:
+ - 'docs'
+ - 'documentation'
+ - 'readme'
+ - 'example'
+ - 'tutorial'
+ - 'guide'
+ - 'explanation'
+ - 'clarification'
+ - 'instructions'
+
+security:
+ - 'security'
+ - 'vulnerability'
+ - 'exploit'
+ - 'hack'
+ - 'CVE'
+ - 'secure'
+ - 'encryption'
+ - 'hardening'
+
+performance:
+ - 'performance'
+ - 'slow'
+ - 'speed'
+ - 'memory leak'
+ - 'cpu usage'
+ - 'high memory'
+ - 'lag'
+ - 'freeze'
+ - 'optimization'
+
+# Priority labels
+high-priority:
+ - 'urgent'
+ - 'critical'
+ - 'security'
+ - 'high priority'
+ - 'important'
+ - 'production'
+ - 'blocker'
+ - 'blocking'
+
+question:
+ - 'how to'
+ - 'how do i'
+ - 'can I'
+ - 'is it possible'
+ - 'question'
+ - 'help me'
+ - 'need help'
+ - 'assistance'
+ - 'confused'
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 000000000..d73efffa8
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,57 @@
+
+
+
+# Description
+
+Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
+
+Fixes # (issue)
+
+## Type of change
+
+Please select the option that is relevant.
+
+- [ ] Bug fix (non-breaking change which fixes an issue)
+- [ ] New feature (non-breaking change which adds functionality)
+- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
+- [ ] This change requires a documentation update
+
+# How Has This Been Tested?
+
+Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration using `wails doctor`.
+
+- [ ] Windows
+- [ ] macOS
+- [ ] Linux
+
+If you checked Linux, please specify the distro and version.
+
+## Test Configuration
+
+Please paste the output of `wails doctor`. If you are unable to run this command, please describe your environment in as much detail as possible.
+
+# Checklist:
+
+- [ ] I have updated `website/src/pages/changelog.mdx` with details of this PR
+- [ ] My code follows the general coding style of this project
+- [ ] I have performed a self-review of my own code
+- [ ] I have commented my code, particularly in hard-to-understand areas
+- [ ] I have made corresponding changes to the documentation
+- [ ] My changes generate no new warnings
+- [ ] I have added tests that prove my fix is effective or that my feature works
+- [ ] New and existing unit tests pass locally with my changes
diff --git a/.github/stale.yml b/.github/stale.yml
index 805bd589d..d8bcc83ec 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -1,7 +1,7 @@
# Number of days of inactivity before an issue becomes stale
-daysUntilStale: 30
+daysUntilStale: 45
# Number of days of inactivity before a stale issue is closed
-daysUntilClose: 7
+daysUntilClose: 10
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
@@ -9,14 +9,28 @@ exemptLabels:
- onhold
- inprogress
- "Selected For Development"
+ - bug
+ - enhancement
+ - v3-alpha
+ - high-priority
# Label to use when marking an issue as stale
-staleLabel: "Wont Fix"
+staleLabel: "stale"
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
- recent activity. It will be closed if no further activity occurs. Thank you
- for your contributions.
+ recent activity. It will be closed if no further activity occurs within the next 10 days.
+
+ If this issue is still relevant, please add a comment to keep it open.
+ Thank you for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
-closeComment: false
+closeComment: >
+ This issue has been automatically closed due to lack of activity.
+ Please feel free to reopen it if it's still relevant.
exemptMilestones: true
exemptAssignees: true
+# Only mark issues (not PRs)
+only: issues
+# Exempt issues created before a certain date
+exemptCreatedBefore: "2024-01-01T00:00:00Z"
+# Starts checking issues only after the specified date
+startDate: "2025-06-01T00:00:00Z"
diff --git a/.github/workflows/auto-label-issues.yml b/.github/workflows/auto-label-issues.yml
new file mode 100644
index 000000000..3d7a86450
--- /dev/null
+++ b/.github/workflows/auto-label-issues.yml
@@ -0,0 +1,33 @@
+name: Auto Label Issues
+
+on:
+ issues:
+ types: [opened, edited, reopened]
+ pull_request:
+ types: [opened, edited, reopened, synchronize]
+
+jobs:
+ auto-label:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ contents: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Label issues and PRs by content
+ uses: github/issue-labeler@v3.4
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ configuration-path: .github/issue-labeler.yml
+ enable-versioned-regex: 0
+ include-title: 1
+
+ - name: Label issues and PRs by file paths
+ uses: actions/labeler@v4
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ configuration-path: .github/file-labeler.yml
+ sync-labels: true
diff --git a/.github/workflows/build-and-test-v3.yml b/.github/workflows/build-and-test-v3.yml
new file mode 100644
index 000000000..bfcef85a3
--- /dev/null
+++ b/.github/workflows/build-and-test-v3.yml
@@ -0,0 +1,201 @@
+name: Build + Test v3
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
+ branches:
+ - v3-alpha
+ paths:
+ - 'v3/**'
+ pull_request_review:
+ types: [submitted]
+ branches:
+ - v3-alpha
+
+jobs:
+ check_approval:
+ name: Check PR Approval
+ runs-on: ubuntu-latest
+ if: github.base_ref == 'v3-alpha'
+ outputs:
+ approved: ${{ steps.check.outputs.approved }}
+ steps:
+ - name: Check if PR is approved
+ id: check
+ run: |
+ if [[ "${{ github.event.review.state }}" == "approved" || "${{ github.event.pull_request.approved }}" == "true" ]]; then
+ echo "approved=true" >> $GITHUB_OUTPUT
+ else
+ echo "approved=false" >> $GITHUB_OUTPUT
+ fi
+
+ test_go:
+ name: Run Go Tests v3
+ needs: check_approval
+ runs-on: ${{ matrix.os }}
+ if: github.base_ref == 'v3-alpha'
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-latest, ubuntu-latest, macos-latest]
+ go-version: [1.24]
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install linux dependencies
+ uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-latest'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config xvfb x11-xserver-utils at-spi2-core xdg-desktop-portal-gtk
+ version: 1.0
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: ${{ matrix.go-version }}
+ cache-dependency-path: "v3/go.sum"
+
+ - name: Install Task
+ uses: arduino/setup-task@v2
+ with:
+ version: 3.x
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build Examples
+ working-directory: v3
+ run: task test:examples
+
+ - name: Run tests (mac)
+ if: matrix.os == 'macos-latest'
+ env:
+ CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
+ working-directory: v3
+ run: go test -v ./...
+
+ - name: Run tests (windows)
+ if: matrix.os == 'windows-latest'
+ working-directory: v3
+ run: go test -v ./...
+
+ - name: Run tests (ubuntu)
+ if: matrix.os == 'ubuntu-latest'
+ working-directory: v3
+ run: >
+ xvfb-run --auto-servernum
+ sh -c '
+ dbus-update-activation-environment --systemd --all &&
+ go test -v ./...
+ '
+
+ - name: Typecheck binding generator output
+ working-directory: v3
+ run: task generator:test:check
+
+ test_js:
+ name: Run JS Tests
+ needs: check_approval
+ runs-on: ubuntu-latest
+ if: github.base_ref == 'v3-alpha'
+ strategy:
+ matrix:
+ node-version: [20.x]
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ - name: Install dependencies
+ run: npm install
+ working-directory: v2/internal/frontend/runtime
+
+ - name: Run tests
+ run: npm test
+ working-directory: v2/internal/frontend/runtime
+
+ test_templates:
+ name: Test Templates
+ needs: test_go
+ runs-on: ${{ matrix.os }}
+ if: github.base_ref == 'v3-alpha'
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ template:
+ - svelte
+ - svelte-ts
+ - vue
+ - vue-ts
+ - react
+ - react-ts
+ - preact
+ - preact-ts
+ - lit
+ - lit-ts
+ - vanilla
+ - vanilla-ts
+ go-version: [1.24]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Install linux dependencies
+ uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-latest'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
+ version: 1.0
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: ${{ matrix.go-version }}
+ cache-dependency-path: "v3/go.sum"
+
+ - name: Install Task
+ uses: arduino/setup-task@v2
+ with:
+ version: 3.x
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build Wails3 CLI
+ working-directory: v3
+ run: |
+ task install
+ wails3 doctor
+
+ - name: Generate template '${{ matrix.template }}'
+ run: |
+ mkdir -p ./test-${{ matrix.template }}
+ cd ./test-${{ matrix.template }}
+ wails3 init -n ${{ matrix.template }} -t ${{ matrix.template }}
+ cd ${{ matrix.template }}
+ wails3 build
+
+ build_results:
+ if: ${{ always() }}
+ runs-on: ubuntu-latest
+ name: v3 Build Results
+ needs: [test_go, test_js, test_templates]
+ steps:
+ - run: |
+ go_result="${{ needs.test_go.result }}"
+ js_result="${{ needs.test_js.result }}"
+ templates_result="${{ needs.test_templates.result }}"
+
+ if [[ $go_result == "success" || $go_result == "skipped" ]] && \
+ [[ $js_result == "success" || $js_result == "skipped" ]] && \
+ [[ $templates_result == "success" || $templates_result == "skipped" ]]; then
+ echo "All required jobs succeeded or were skipped"
+ exit 0
+ else
+ echo "One or more required jobs failed"
+ exit 1
+ fi
\ No newline at end of file
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 93fb12f02..8fe647c6f 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -1,8 +1,8 @@
-name: Build + Test
+name: Build + Test v2
on:
push:
- branches: [release/*, master]
+ branches: [release/*, master, bugfix/*]
workflow_dispatch:
jobs:
@@ -12,21 +12,30 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
- go-version: [1.18, 1.19]
+ os: [ubuntu-22.04, ubuntu-24.04, windows-latest, macos-latest]
+ go-version: ['1.22']
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- - name: Install linux dependencies
- if: matrix.os == 'ubuntu-latest'
- run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+ - uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-22.04'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+ version: 1.0
+
+ - uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-24.04'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config libegl1
+ version: 1.0
- name: Setup Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
+ cache-dependency-path: ./v2/go.sum
- name: Run tests (mac)
if: matrix.os == 'macos-latest'
@@ -36,21 +45,26 @@ jobs:
run: go test -v ./...
- name: Run tests (!mac)
- if: matrix.os != 'macos-latest'
+ if: matrix.os != 'macos-latest' && matrix.os != 'ubuntu-24.04'
working-directory: ./v2
run: go test -v ./...
+ - name: Run tests (Ubuntu 24.04)
+ if: matrix.os == 'ubuntu-24.04'
+ working-directory: ./v2
+ run: go test -v -tags webkit2_41 ./...
+
test_js:
name: Run JS Tests
if: github.repository == 'wailsapp/wails'
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [20.x]
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
@@ -72,7 +86,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
+ os: [ubuntu-22.04, windows-latest, macos-latest, ubuntu-24.04]
template:
[
svelte,
@@ -89,15 +103,16 @@ jobs:
vanilla-ts,
plain,
]
- go-version: [1.18, 1.19]
+ go-version: ['1.22']
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
+ cache-dependency-path: ./v2/go.sum
- name: Build Wails CLI
run: |
@@ -105,14 +120,41 @@ jobs:
go install
wails -help
- - name: Install linux dependencies
- if: matrix.os == 'ubuntu-latest'
- run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+ - uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-22.04'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+ version: 1.0
- - name: Generate template '${{ matrix.template }}'
+# - name: Install linux dependencies ( 22.04 )
+# if: matrix.os == 'ubuntu-22.04'
+# run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+
+ - uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-24.04'
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config libegl1
+ version: 1.0
+
+# - name: Install linux dependencies ( 24.04 )
+# if: matrix.os == 'ubuntu-24.04'
+# run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
+
+ - name: Generate & Build template '${{ matrix.template }}'
+ if: matrix.os != 'ubuntu-24.04'
run: |
mkdir -p ./test-${{ matrix.template }}
cd ./test-${{ matrix.template }}
wails init -n ${{ matrix.template }} -t ${{ matrix.template }} -ci
cd ${{ matrix.template }}
wails build -v 2
+
+ - name: Generate & Build template '${{ matrix.template }}' (ubuntu-24.04)
+ if: matrix.os == 'ubuntu-24.04'
+ run: |
+ mkdir -p ./test-${{ matrix.template }}
+ cd ./test-${{ matrix.template }}
+ wails init -n ${{ matrix.template }} -t ${{ matrix.template }} -ci
+ cd ${{ matrix.template }}
+ wails build -v 2 -tags webkit2_41
+
diff --git a/.github/workflows/build-cross-image.yml b/.github/workflows/build-cross-image.yml
new file mode 100644
index 000000000..83b40f2be
--- /dev/null
+++ b/.github/workflows/build-cross-image.yml
@@ -0,0 +1,423 @@
+name: Build Cross-Compiler Image
+
+on:
+ workflow_dispatch:
+ inputs:
+ branch:
+ description: 'Branch containing Dockerfile'
+ required: true
+ default: 'v3-alpha'
+ sdk_version:
+ description: 'macOS SDK version'
+ required: true
+ default: '14.5'
+ zig_version:
+ description: 'Zig version'
+ required: true
+ default: '0.14.0'
+ image_version:
+ description: 'Image version tag'
+ required: true
+ default: 'latest'
+ skip_tests:
+ description: 'Skip cross-compilation tests'
+ required: false
+ default: 'false'
+ type: boolean
+ push:
+ branches:
+ - v3-alpha
+ paths:
+ - 'v3/internal/commands/build_assets/docker/Dockerfile.cross'
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: wailsapp/wails-cross
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ outputs:
+ image_tag: ${{ steps.vars.outputs.image_version }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.branch || github.ref }}
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Set build variables
+ id: vars
+ run: |
+ echo "sdk_version=${{ inputs.sdk_version || '14.5' }}" >> $GITHUB_OUTPUT
+ echo "zig_version=${{ inputs.zig_version || '0.14.0' }}" >> $GITHUB_OUTPUT
+ echo "image_version=${{ inputs.image_version || 'latest' }}" >> $GITHUB_OUTPUT
+
+ - name: Extract metadata
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=raw,value=latest
+ type=raw,value=${{ steps.vars.outputs.image_version }}
+ type=raw,value=sdk-${{ steps.vars.outputs.sdk_version }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v5
+ with:
+ context: v3/internal/commands/build_assets/docker
+ file: v3/internal/commands/build_assets/docker/Dockerfile.cross
+ platforms: linux/amd64,linux/arm64
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: |
+ ${{ steps.meta.outputs.labels }}
+ io.wails.zig.version=${{ steps.vars.outputs.zig_version }}
+ io.wails.sdk.version=${{ steps.vars.outputs.sdk_version }}
+ build-args: |
+ ZIG_VERSION=${{ steps.vars.outputs.zig_version }}
+ MACOS_SDK_VERSION=${{ steps.vars.outputs.sdk_version }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+ # Test cross-compilation for all platforms
+ test-cross-compile:
+ needs: build
+ if: ${{ inputs.skip_tests != 'true' }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ # Darwin targets (Zig + macOS SDK) - no platform emulation needed
+ - os: darwin
+ arch: arm64
+ platform: ""
+ expected_file: "Mach-O 64-bit.*arm64"
+ - os: darwin
+ arch: amd64
+ platform: ""
+ expected_file: "Mach-O 64-bit.*x86_64"
+ # Linux targets (GCC) - need platform to match architecture
+ - os: linux
+ arch: amd64
+ platform: "linux/amd64"
+ expected_file: "ELF 64-bit LSB.*x86-64"
+ - os: linux
+ arch: arm64
+ platform: "linux/arm64"
+ expected_file: "ELF 64-bit LSB.*ARM aarch64"
+ # Windows targets (Zig + mingw) - no platform emulation needed
+ - os: windows
+ arch: amd64
+ platform: ""
+ expected_file: "PE32\\+ executable.*x86-64"
+ - os: windows
+ arch: arm64
+ platform: ""
+ expected_file: "PE32\\+ executable.*Aarch64"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.branch || github.ref }}
+
+ - name: Set up QEMU
+ if: matrix.platform != ''
+ uses: docker/setup-qemu-action@v3
+
+ - name: Log in to Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Create test CGO project
+ run: |
+ mkdir -p test-project
+ cd test-project
+
+ # Create a minimal CGO test program
+ cat > main.go << 'EOF'
+ package main
+
+ /*
+ #include
+
+ int add(int a, int b) {
+ return a + b;
+ }
+ */
+ import "C"
+ import "fmt"
+
+ func main() {
+ result := C.add(1, 2)
+ fmt.Printf("CGO test: 1 + 2 = %d\n", result)
+ }
+ EOF
+
+ cat > go.mod << 'EOF'
+ module test-cgo
+
+ go 1.21
+ EOF
+
+ - name: Build ${{ matrix.os }}/${{ matrix.arch }} (CGO)
+ run: |
+ cd test-project
+ PLATFORM_FLAG=""
+ if [ -n "${{ matrix.platform }}" ]; then
+ PLATFORM_FLAG="--platform ${{ matrix.platform }}"
+ fi
+
+ docker run --rm $PLATFORM_FLAG \
+ -v "$(pwd):/app" \
+ -e APP_NAME="test-cgo" \
+ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag || 'latest' }} \
+ ${{ matrix.os }} ${{ matrix.arch }}
+
+ - name: Verify binary format
+ run: |
+ cd test-project/bin
+ ls -la
+
+ # Find the built binary
+ if [ "${{ matrix.os }}" = "windows" ]; then
+ BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }}.exe 2>/dev/null || ls *.exe | head -1)
+ else
+ BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }} 2>/dev/null || ls test-cgo* | grep -v '.exe' | head -1)
+ fi
+
+ echo "Binary: $BINARY"
+ FILE_OUTPUT=$(file "$BINARY")
+ echo "File output: $FILE_OUTPUT"
+
+ # Verify the binary format matches expected
+ if echo "$FILE_OUTPUT" | grep -qE "${{ matrix.expected_file }}"; then
+ echo "✅ Binary format verified: ${{ matrix.os }}/${{ matrix.arch }}"
+ else
+ echo "❌ Binary format mismatch!"
+ echo "Expected pattern: ${{ matrix.expected_file }}"
+ echo "Got: $FILE_OUTPUT"
+ exit 1
+ fi
+
+ - name: Check library dependencies (Linux only)
+ if: matrix.os == 'linux'
+ run: |
+ cd test-project/bin
+ BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }} 2>/dev/null || ls test-cgo* | grep -v '.exe' | head -1)
+
+ echo "## Library Dependencies for $BINARY"
+ echo ""
+
+ # Use readelf to show dynamic dependencies
+ echo "### NEEDED libraries:"
+ readelf -d "$BINARY" | grep NEEDED || echo "No dynamic dependencies (statically linked)"
+
+ # Verify expected libraries are linked
+ echo ""
+ echo "### Verifying required libraries..."
+ NEEDED=$(readelf -d "$BINARY" | grep NEEDED)
+
+ MISSING=""
+ for lib in libwebkit2gtk-4.1.so libgtk-3.so libglib-2.0.so libc.so; do
+ if echo "$NEEDED" | grep -q "$lib"; then
+ echo "✅ $lib"
+ else
+ echo "❌ $lib MISSING"
+ MISSING="$MISSING $lib"
+ fi
+ done
+
+ if [ -n "$MISSING" ]; then
+ echo ""
+ echo "ERROR: Missing required libraries:$MISSING"
+ exit 1
+ fi
+
+ # Test non-CGO builds (pure Go cross-compilation)
+ test-non-cgo:
+ needs: build
+ if: ${{ inputs.skip_tests != 'true' }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: darwin
+ arch: arm64
+ expected_file: "Mach-O 64-bit.*arm64"
+ - os: darwin
+ arch: amd64
+ expected_file: "Mach-O 64-bit.*x86_64"
+ - os: linux
+ arch: amd64
+ expected_file: "ELF 64-bit LSB"
+ - os: linux
+ arch: arm64
+ expected_file: "ELF 64-bit LSB.*ARM aarch64"
+ - os: windows
+ arch: amd64
+ expected_file: "PE32\\+ executable.*x86-64"
+ - os: windows
+ arch: arm64
+ expected_file: "PE32\\+ executable.*Aarch64"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.branch || github.ref }}
+
+ - name: Log in to Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Create test non-CGO project
+ run: |
+ mkdir -p test-project
+ cd test-project
+
+ # Create a pure Go test program (no CGO)
+ cat > main.go << 'EOF'
+ package main
+
+ import "fmt"
+
+ func main() {
+ fmt.Println("Pure Go cross-compilation test")
+ }
+ EOF
+
+ cat > go.mod << 'EOF'
+ module test-pure-go
+
+ go 1.21
+ EOF
+
+ - name: Build ${{ matrix.os }}/${{ matrix.arch }} (non-CGO)
+ run: |
+ cd test-project
+
+ # For non-CGO, we can use any platform since Go handles cross-compilation
+ # We set CGO_ENABLED=0 to ensure pure Go build
+ docker run --rm \
+ -v "$(pwd):/app" \
+ -e APP_NAME="test-pure-go" \
+ -e CGO_ENABLED=0 \
+ --entrypoint /bin/sh \
+ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag || 'latest' }} \
+ -c "GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} go build -o bin/test-pure-go-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.os == 'windows' && '.exe' || '' }} ."
+
+ - name: Verify binary format
+ run: |
+ cd test-project/bin
+ ls -la
+
+ # Find the built binary
+ if [ "${{ matrix.os }}" = "windows" ]; then
+ BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}.exe"
+ else
+ BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}"
+ fi
+
+ echo "Binary: $BINARY"
+ FILE_OUTPUT=$(file "$BINARY")
+ echo "File output: $FILE_OUTPUT"
+
+ # Verify the binary format matches expected
+ if echo "$FILE_OUTPUT" | grep -qE "${{ matrix.expected_file }}"; then
+ echo "✅ Binary format verified: ${{ matrix.os }}/${{ matrix.arch }} (non-CGO)"
+ else
+ echo "❌ Binary format mismatch!"
+ echo "Expected pattern: ${{ matrix.expected_file }}"
+ echo "Got: $FILE_OUTPUT"
+ exit 1
+ fi
+
+ - name: Check library dependencies (Linux only)
+ if: matrix.os == 'linux'
+ run: |
+ cd test-project/bin
+ BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}"
+
+ echo "## Library Dependencies for $BINARY (non-CGO)"
+ echo ""
+
+ # Non-CGO builds should have minimal dependencies (just libc or statically linked)
+ echo "### NEEDED libraries:"
+ readelf -d "$BINARY" | grep NEEDED || echo "No dynamic dependencies (statically linked)"
+
+ # Verify NO GTK/WebKit libraries (since CGO is disabled)
+ NEEDED=$(readelf -d "$BINARY" | grep NEEDED || true)
+ if echo "$NEEDED" | grep -q "libwebkit\|libgtk"; then
+ echo "❌ ERROR: Non-CGO binary should not link to GTK/WebKit!"
+ exit 1
+ else
+ echo "✅ Confirmed: No GTK/WebKit dependencies (expected for non-CGO)"
+ fi
+
+ # Summary job
+ test-summary:
+ needs: [build, test-cross-compile, test-non-cgo]
+ if: always() && inputs.skip_tests != 'true'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check test results
+ run: |
+ echo "## Cross-Compilation Test Results" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [ "${{ needs.test-cross-compile.result }}" = "success" ]; then
+ echo "✅ **CGO Tests**: All passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **CGO Tests**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [ "${{ needs.test-non-cgo.result }}" = "success" ]; then
+ echo "✅ **Non-CGO Tests**: All passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Non-CGO Tests**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### Tested Platforms" >> $GITHUB_STEP_SUMMARY
+ echo "| Platform | Architecture | CGO | Non-CGO |" >> $GITHUB_STEP_SUMMARY
+ echo "|----------|-------------|-----|---------|" >> $GITHUB_STEP_SUMMARY
+ echo "| Darwin | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+ echo "| Darwin | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+ echo "| Linux | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+ echo "| Linux | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+ echo "| Windows | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+ echo "| Windows | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
+
+ # Fail if any test failed
+ if [ "${{ needs.test-cross-compile.result }}" != "success" ] || [ "${{ needs.test-non-cgo.result }}" != "success" ]; then
+ echo ""
+ echo "❌ Some tests failed. Check the individual job logs for details."
+ exit 1
+ fi
diff --git a/.github/workflows/changelog-v3.yml b/.github/workflows/changelog-v3.yml
new file mode 100644
index 000000000..688959b9e
--- /dev/null
+++ b/.github/workflows/changelog-v3.yml
@@ -0,0 +1,216 @@
+name: Changelog Validation (v3)
+
+on:
+ pull_request:
+ branches: [ v3-alpha ]
+ paths:
+ - 'docs/src/content/docs/changelog.mdx'
+ workflow_dispatch:
+ inputs:
+ pr_number:
+ description: 'PR number to validate'
+ required: true
+ type: string
+
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ actions: write
+
+ steps:
+ - name: Checkout PR code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.inputs.pr_number) }}
+ fetch-depth: 0
+ token: ${{ secrets.GITHUB_TOKEN || github.token }}
+
+ - name: Get REAL validation script from v3-alpha
+ run: |
+ echo "Fetching the REAL validation script from v3-alpha branch..."
+ git fetch origin v3-alpha
+ git checkout origin/v3-alpha -- v3/scripts/validate-changelog.go
+
+ echo "Validation script fetched successfully:"
+ ls -la v3/scripts/
+
+ - name: Setup Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: '1.23'
+
+ - name: Get PR information
+ id: pr_info
+ run: |
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
+ echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
+ echo "base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
+ else
+ echo "pr_number=${{ github.event.inputs.pr_number }}" >> $GITHUB_OUTPUT
+ echo "base_ref=v3-alpha" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Check changelog modifications
+ id: changelog_check
+ run: |
+ echo "Checking PR #${{ steps.pr_info.outputs.pr_number }} for changelog changes"
+ git fetch origin ${{ steps.pr_info.outputs.base_ref }}
+
+ if git diff --name-only origin/${{ steps.pr_info.outputs.base_ref }}..HEAD | grep -q "docs/src/content/docs/changelog.mdx"; then
+ echo "changelog_modified=true" >> $GITHUB_OUTPUT
+ echo "✅ Changelog was modified in this PR"
+ else
+ echo "changelog_modified=false" >> $GITHUB_OUTPUT
+ echo "ℹ️ Changelog was not modified - skipping validation"
+ fi
+
+ - name: Get changelog diff
+ id: get_diff
+ if: steps.changelog_check.outputs.changelog_modified == 'true'
+ run: |
+ echo "Getting diff for changelog changes..."
+ git diff origin/${{ steps.pr_info.outputs.base_ref }}..HEAD docs/src/content/docs/changelog.mdx | grep "^+" | grep -v "^+++" | sed 's/^+//' > /tmp/pr_added_lines.txt
+
+ echo "Lines added in this PR:"
+ cat /tmp/pr_added_lines.txt
+ echo "Total lines added: $(wc -l < /tmp/pr_added_lines.txt)"
+
+ - name: Validate changelog
+ id: validate
+ if: steps.changelog_check.outputs.changelog_modified == 'true'
+ run: |
+ echo "Running changelog validation..."
+ cd v3/scripts
+ OUTPUT=$(go run validate-changelog.go ../../docs/src/content/docs/changelog.mdx /tmp/pr_added_lines.txt 2>&1)
+ echo "$OUTPUT"
+
+ RESULT=$(echo "$OUTPUT" | grep "VALIDATION_RESULT=" | cut -d'=' -f2)
+ echo "result=$RESULT" >> $GITHUB_OUTPUT
+
+ - name: Commit fixes
+ id: commit_fixes
+ if: steps.validate.outputs.result == 'fixed'
+ run: |
+ echo "Committing automatic fixes..."
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+
+ # Check only the changelog file for changes
+ if git diff --quiet docs/src/content/docs/changelog.mdx; then
+ echo "No changes to commit"
+ echo "committed=false" >> $GITHUB_OUTPUT
+ else
+ # Ensure validation script doesn't get committed
+ echo "v3/scripts/validate-changelog.go" >> .git/info/exclude
+ # Get the correct branch name to push to
+ REPO_OWNER="wailsapp" # Always wailsapp for this repo
+
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
+ BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
+ else
+ # For manual workflow dispatch, get PR info
+ PR_INFO=$(gh pr view ${{ steps.pr_info.outputs.pr_number }} --json headRefName,headRepository)
+ BRANCH_NAME=$(echo "$PR_INFO" | jq -r '.headRefName')
+ HEAD_REPO=$(echo "$PR_INFO" | jq -r '.headRepository.name')
+
+ echo "🔍 PR source branch: $BRANCH_NAME"
+ echo "🔍 Head repository: $HEAD_REPO"
+
+ # Don't push if this is from a fork or if branch is v3-alpha (main branch)
+ if [ "$HEAD_REPO" != "wails" ] || [ "$BRANCH_NAME" = "v3-alpha" ]; then
+ echo "⚠️ Cannot push - either fork or direct v3-alpha branch. Manual fix required."
+ echo "committed=false" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+ fi
+
+ echo "Pushing to branch: $BRANCH_NAME in repo: $REPO_OWNER"
+
+ # Only commit the changelog changes, not the validation script
+ git add docs/src/content/docs/changelog.mdx
+ git commit -m "🤖 Fix changelog: move entries to Unreleased section"
+
+ # Only push if running on the main wailsapp repository
+ if [ "${{ github.repository }}" = "wailsapp/wails" ]; then
+ # Pull latest changes and rebase our commit
+ git fetch origin $BRANCH_NAME
+ git rebase origin/$BRANCH_NAME
+ git push origin HEAD:$BRANCH_NAME
+ else
+ echo "⚠️ Running on fork (${{ github.repository }}). Skipping push - manual fix required."
+ echo "committed=false" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+
+ echo "committed=true" >> $GITHUB_OUTPUT
+ echo "✅ Changes committed and pushed"
+ fi
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Get PR author for tagging
+ id: pr_author
+ if: steps.validate.outputs.result && github.event.inputs.pr_number
+ run: |
+ PR_AUTHOR=$(gh pr view ${{ steps.pr_info.outputs.pr_number }} --json author --jq '.author.login')
+ echo "author=$PR_AUTHOR" >> $GITHUB_OUTPUT
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Comment on PR
+ if: steps.validate.outputs.result && github.event.inputs.pr_number
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const result = '${{ steps.validate.outputs.result }}';
+ const committed = '${{ steps.commit_fixes.outputs.committed }}';
+ const author = '${{ steps.pr_author.outputs.author }}';
+
+ let message;
+ if (result === 'success') {
+ message = '## ✅ Changelog Validation Passed\n\nNo misplaced changelog entries detected.';
+ } else if (result === 'fixed' && committed === 'true') {
+ message = '## 🔧 Changelog Updated\n\nMisplaced entries were automatically moved to the `[Unreleased]` section. The changes have been committed to this PR.';
+ } else if (result === 'fixed' || result === 'cannot_fix' || result === 'error') {
+ // Read the fixed changelog content
+ const fs = require('fs');
+ let fixedContent = '';
+ try {
+ fixedContent = fs.readFileSync('docs/src/content/docs/changelog.mdx', 'utf8');
+ } catch (error) {
+ fixedContent = 'Error reading fixed changelog content';
+ }
+
+ message = '## ⚠️ Changelog Validation Issue\\n\\n' +
+ '@' + author + ' Your PR contains changelog entries that were added to already-released versions. These need to be moved to the `[Unreleased]` section.\\n\\n' +
+ (committed === 'true' ?
+ '✅ **Auto-fix applied**: The changes have been automatically committed to this PR.' :
+ '❌ **Manual fix required**: Please apply the changes shown below manually.') + '\\n\\n' +
+ '\\n' +
+ '📝 Click to see the corrected changelog content \\n\\n' +
+ '```mdx\\n' +
+ fixedContent +
+ '\\n```\\n\\n' +
+ ' \\n\\n' +
+ '**What happened?** \\n' +
+ 'The validation script detected that you added changelog entries to a version section that has already been released (like `v3.0.0-alpha.10`). All new entries should go in the `[Unreleased]` section under the appropriate category (`### Added`, `### Fixed`, etc.).\\n\\n' +
+ (committed !== 'true' ? '**Action needed:** Please copy the corrected content from above and replace your changelog file.' : '');
+ }
+
+ if (message) {
+ await github.rest.issues.createComment({
+ issue_number: ${{ steps.pr_info.outputs.pr_number }},
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: message
+ });
+ }
+
+ - name: Fail if validation failed
+ if: steps.validate.outputs.result == 'cannot_fix' || steps.validate.outputs.result == 'error'
+ run: |
+ echo "❌ Changelog validation failed"
+ exit 1
\ No newline at end of file
diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml
new file mode 100644
index 000000000..b5e8cfd4d
--- /dev/null
+++ b/.github/workflows/claude-code-review.yml
@@ -0,0 +1,44 @@
+name: Claude Code Review
+
+on:
+ pull_request:
+ types: [opened, synchronize, ready_for_review, reopened]
+ # Optional: Only run on specific file changes
+ # paths:
+ # - "src/**/*.ts"
+ # - "src/**/*.tsx"
+ # - "src/**/*.js"
+ # - "src/**/*.jsx"
+
+jobs:
+ claude-review:
+ # Optional: Filter by PR author
+ # if: |
+ # github.event.pull_request.user.login == 'external-contributor' ||
+ # github.event.pull_request.user.login == 'new-developer' ||
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code Review
+ id: claude-review
+ uses: anthropics/claude-code-action@v1
+ with:
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
+ plugins: 'code-review@claude-code-plugins'
+ prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
+ # or https://code.claude.com/docs/en/cli-reference for available options
+
diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 000000000..d300267f1
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,50 @@
+name: Claude Code
+
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+ issues:
+ types: [opened, assigned]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ claude:
+ if: |
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ actions: read # Required for Claude to read CI results on PRs
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code
+ id: claude
+ uses: anthropics/claude-code-action@v1
+ with:
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+
+ # This is an optional setting that allows Claude to read CI results on PRs
+ additional_permissions: |
+ actions: read
+
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
+ # prompt: 'Update the pull request description to include a summary of changes.'
+
+ # Optional: Add claude_args to customize behavior and configuration
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
+ # or https://code.claude.com/docs/en/cli-reference for available options
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
+
diff --git a/.github/workflows/generate-sponsor-image.yml b/.github/workflows/generate-sponsor-image.yml
index 5f3006d7e..56548ab43 100644
--- a/.github/workflows/generate-sponsor-image.yml
+++ b/.github/workflows/generate-sponsor-image.yml
@@ -16,7 +16,7 @@ jobs:
- name: Set Node
uses: actions/setup-node@v2
with:
- node-version: 16.x
+ node-version: 20.x
- name: Update Sponsors
run: cd scripts/sponsors && chmod 755 ./generate-sponsor-image.sh && ./generate-sponsor-image.sh
@@ -25,11 +25,16 @@ jobs:
SPONSORKIT_GITHUB_LOGIN: wailsapp
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v4
+ uses: peter-evans/create-pull-request@v6
with:
commit-message: "chore: update sponsors.svg"
add-paths: "website/static/img/sponsors.svg"
- title: Update Sponsor Image
- body: Generated new image
+ title: "chore: update sponsors.svg"
+ body: |
+ Auto-generated by the sponsor image workflow
+
+ [skip ci] [skip actions]
branch: update-sponsors
+ base: master
delete-branch: true
+ draft: false
diff --git a/.github/workflows/issue-triage-automation.yml b/.github/workflows/issue-triage-automation.yml
new file mode 100644
index 000000000..99159a2f5
--- /dev/null
+++ b/.github/workflows/issue-triage-automation.yml
@@ -0,0 +1,77 @@
+name: Issue Triage Automation
+
+on:
+ issues:
+ types: [opened]
+
+jobs:
+ triage:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ contents: read
+ steps:
+ # Request more info for unclear bug reports
+ - name: Request more info
+ uses: actions/github-script@v6
+ if: |
+ contains(github.event.issue.labels.*.name, 'bug') &&
+ !contains(github.event.issue.body, 'wails doctor') &&
+ !contains(github.event.issue.body, 'reproduction')
+ with:
+ script: |
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: `👋 Thanks for reporting this issue! To help us investigate, could you please:
+
+ 1. Add the output of \`wails doctor\` if not already included
+ 2. Provide clear steps to reproduce the issue
+ 3. If possible, create a minimal reproduction of the issue
+
+ This will help us resolve your issue much faster. Thank you!`
+ });
+ github.rest.issues.addLabels({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ labels: ['awaiting feedback']
+ });
+
+ # Prioritize security issues
+ - name: Prioritize security issues
+ uses: actions/github-script@v6
+ if: contains(github.event.issue.labels.*.name, 'security')
+ with:
+ script: |
+ github.rest.issues.addLabels({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ labels: ['high-priority']
+ });
+
+ # Tag version-specific issues for project boards
+ - name: Add to v2 project
+ uses: actions/github-script@v6
+ if: |
+ contains(github.event.issue.labels.*.name, 'v2-only') &&
+ !contains(github.event.issue.labels.*.name, 'v3-alpha')
+ with:
+ script: |
+ // Replace PROJECT_ID with your actual GitHub project ID
+ // This is a placeholder as the actual implementation would require
+ // GraphQL API calls to add to a project board
+ console.log('Would add to v2 project board');
+
+ # Tag version-specific issues for project boards
+ - name: Add to v3 project
+ uses: actions/github-script@v6
+ if: contains(github.event.issue.labels.*.name, 'v3-alpha')
+ with:
+ script: |
+ // Replace PROJECT_ID with your actual GitHub project ID
+ // This is a placeholder as the actual implementation would require
+ // GraphQL API calls to add to a project board
+ console.log('Would add to v3 project board');
diff --git a/.github/workflows/label-sponsors.yml b/.github/workflows/label-sponsors.yml
deleted file mode 100644
index 28bda63b8..000000000
--- a/.github/workflows/label-sponsors.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Label sponsors
-on:
- pull_request:
- types: [ opened ]
- issues:
- types: [ opened ]
-jobs:
- build:
- name: is-sponsor-label
- if: github.repository == 'wailsapp/wails'
- runs-on: ubuntu-latest
- steps:
- - uses: JasonEtco/is-sponsor-label-action@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/nightly-release-v3.yml b/.github/workflows/nightly-release-v3.yml
new file mode 100644
index 000000000..ae56ba7bc
--- /dev/null
+++ b/.github/workflows/nightly-release-v3.yml
@@ -0,0 +1,210 @@
+name: Nightly Release v3-alpha
+
+on:
+ schedule:
+ - cron: '0 2 * * *' # 2 AM UTC daily
+ workflow_dispatch:
+ inputs:
+ force_release:
+ description: 'Force release even if no changes detected'
+ required: false
+ default: false
+ type: boolean
+ dry_run:
+ description: 'Run in dry-run mode (no actual release)'
+ required: false
+ default: true
+ type: boolean
+
+jobs:
+ nightly-release:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: write
+ pull-requests: read
+ actions: write
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: v3-alpha
+ fetch-depth: 0
+ token: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
+
+ - name: Setup Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: '1.24'
+ cache: true
+ cache-dependency-path: 'v3/go.sum'
+
+ - name: Install Task
+ uses: arduino/setup-task@v2
+ with:
+ version: 3.x
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup Git
+ run: |
+ git config --global user.name "github-actions[bot]"
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
+
+ # Configure git to use the token for authentication
+ git config --global url."https://x-access-token:${{ secrets.WAILS_REPO_TOKEN || github.token }}@github.com/".insteadOf "https://github.com/"
+
+ - name: Check for existing release tag
+ id: check_tag
+ run: |
+ if git describe --tags --exact-match HEAD 2>/dev/null; then
+ echo "has_tag=true" >> $GITHUB_OUTPUT
+ echo "tag=$(git describe --tags --exact-match HEAD)" >> $GITHUB_OUTPUT
+ else
+ echo "has_tag=false" >> $GITHUB_OUTPUT
+ echo "tag=" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Check for unreleased changelog content
+ id: changelog_check
+ run: |
+ echo "🔍 Checking UNRELEASED_CHANGELOG.md for content..."
+
+ # Run the release script in check mode to see if there's content
+ cd v3/tasks/release
+
+ # Use the release script itself to check for content
+ if go run release.go --check-only 2>/dev/null; then
+ echo "has_unreleased_content=true" >> $GITHUB_OUTPUT
+ echo "✅ Found unreleased changelog content"
+ else
+ echo "has_unreleased_content=false" >> $GITHUB_OUTPUT
+ echo "ℹ️ No unreleased changelog content found"
+ fi
+
+ - name: Quick change detection and early exit
+ id: quick_check
+ run: |
+ echo "🔍 Quick check for changes to determine if we should continue..."
+
+ # First check if we have unreleased changelog content
+ if [ "${{ steps.changelog_check.outputs.has_unreleased_content }}" == "true" ]; then
+ echo "✅ Found unreleased changelog content, proceeding with release"
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "should_continue=true" >> $GITHUB_OUTPUT
+ echo "reason=Found unreleased changelog content" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+
+ # If no unreleased changelog content, check for git changes as fallback
+ echo "No unreleased changelog content found, checking for git changes..."
+
+ # Check if current commit has a release tag
+ if git describe --tags --exact-match HEAD 2>/dev/null; then
+ CURRENT_TAG=$(git describe --tags --exact-match HEAD)
+ echo "Current commit has release tag: $CURRENT_TAG"
+
+ # For tagged commits, check if there are changes since the tag
+ COMMIT_COUNT=$(git rev-list ${CURRENT_TAG}..HEAD --count)
+ if [ "$COMMIT_COUNT" -eq 0 ]; then
+ echo "has_changes=false" >> $GITHUB_OUTPUT
+ echo "should_continue=false" >> $GITHUB_OUTPUT
+ echo "reason=No changes since existing tag $CURRENT_TAG and no unreleased changelog content" >> $GITHUB_OUTPUT
+ else
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "should_continue=true" >> $GITHUB_OUTPUT
+ fi
+ else
+ # No current tag, check against latest release
+ LATEST_TAG=$(git tag --list "v3.0.0-alpha.*" | sort -V | tail -1)
+ if [ -z "$LATEST_TAG" ]; then
+ echo "No previous release found, proceeding with release"
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "should_continue=true" >> $GITHUB_OUTPUT
+ else
+ COMMIT_COUNT=$(git rev-list ${LATEST_TAG}..HEAD --count)
+ if [ "$COMMIT_COUNT" -gt 0 ]; then
+ echo "Found $COMMIT_COUNT commits since $LATEST_TAG"
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "should_continue=true" >> $GITHUB_OUTPUT
+ else
+ echo "has_changes=false" >> $GITHUB_OUTPUT
+ echo "should_continue=false" >> $GITHUB_OUTPUT
+ echo "reason=No changes since latest release $LATEST_TAG and no unreleased changelog content" >> $GITHUB_OUTPUT
+ fi
+ fi
+ fi
+
+ - name: Early exit - No changes detected
+ if: |
+ steps.quick_check.outputs.should_continue == 'false' &&
+ github.event.inputs.force_release != 'true'
+ run: |
+ echo "🛑 EARLY EXIT: ${{ steps.quick_check.outputs.reason }}"
+ echo ""
+ echo "ℹ️ No changes detected since last release and force_release is not enabled."
+ echo " Workflow will exit early to save resources."
+ echo ""
+ echo " To force a release anyway, run this workflow with 'force_release=true'"
+ echo ""
+ echo "## 🛑 Early Exit Summary" >> $GITHUB_STEP_SUMMARY
+ echo "**Reason:** ${{ steps.quick_check.outputs.reason }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Action:** Workflow exited early to save resources" >> $GITHUB_STEP_SUMMARY
+ echo "**Force Release:** Set 'force_release=true' to override this behavior" >> $GITHUB_STEP_SUMMARY
+ exit 0
+
+ - name: Continue with release process
+ if: |
+ steps.quick_check.outputs.should_continue == 'true' ||
+ github.event.inputs.force_release == 'true'
+ run: |
+ echo "✅ Proceeding with release process..."
+ if [ "${{ github.event.inputs.force_release }}" == "true" ]; then
+ echo "🔨 FORCE RELEASE: Overriding change detection"
+ fi
+
+ - name: Run release script
+ id: release
+ if: |
+ steps.quick_check.outputs.should_continue == 'true' ||
+ github.event.inputs.force_release == 'true'
+ env:
+ WAILS_REPO_TOKEN: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
+ GITHUB_TOKEN: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
+ run: |
+ cd v3/tasks/release
+ ARGS=()
+ if [ "${{ github.event.inputs.dry_run }}" == "true" ]; then
+ ARGS+=(--dry-run)
+ fi
+ go run release.go "${ARGS[@]}"
+
+ - name: Summary
+ if: always()
+ run: |
+ if [ "${{ github.event.inputs.dry_run }}" == "true" ]; then
+ echo "## 🧪 DRY RUN Release Summary" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "## 🚀 Nightly Release Summary" >> $GITHUB_STEP_SUMMARY
+ fi
+ echo "================================" >> $GITHUB_STEP_SUMMARY
+
+ if [ -n "${{ steps.release.outputs.release_version }}" ]; then
+ echo "- **Version:** ${{ steps.release.outputs.release_version }}" >> $GITHUB_STEP_SUMMARY
+ echo "- **Tag:** ${{ steps.release.outputs.release_tag }}" >> $GITHUB_STEP_SUMMARY
+ echo "- **Status:** ${{ steps.release.outcome == 'success' && '✅ Success' || '⚠️ Failed' }}" >> $GITHUB_STEP_SUMMARY
+ echo "- **Mode:** ${{ steps.release.outputs.release_dry_run == 'true' && '🧪 Dry Run' || '🚀 Live release' }}" >> $GITHUB_STEP_SUMMARY
+ if [ -n "${{ steps.release.outputs.release_url }}" ]; then
+ echo "- **Release URL:** ${{ steps.release.outputs.release_url }}" >> $GITHUB_STEP_SUMMARY
+ fi
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### Changelog" >> $GITHUB_STEP_SUMMARY
+ if [ "${{ steps.changelog_check.outputs.has_unreleased_content }}" == "true" ]; then
+ echo "✅ Unreleased changelog processed and reset." >> $GITHUB_STEP_SUMMARY
+ else
+ echo "ℹ️ No unreleased changelog content detected." >> $GITHUB_STEP_SUMMARY
+ fi
+ else
+ echo "- Release script did not run (skipped or failed before execution)." >> $GITHUB_STEP_SUMMARY
+ fi
+
diff --git a/.github/workflows/pr-master.yml b/.github/workflows/pr-master.yml
new file mode 100644
index 000000000..c961b4434
--- /dev/null
+++ b/.github/workflows/pr-master.yml
@@ -0,0 +1,104 @@
+# Updated to ensure "Run Go Tests" runs for pull requests as expected.
+# Key fix: the test_go job previously required github.event.review.state == 'approved'
+# which only exists on pull_request_review events. That prevented the job from
+# running for regular pull_request events (opened / synchronize / reopened).
+# New logic: run tests for pull_request events, and also allow running when a
+# pull_request_review is submitted with state == 'approved'.
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+ branches:
+ - master
+ pull_request_review:
+ types: [submitted]
+ branches:
+ - master
+ workflow_dispatch: {}
+
+name: PR Checks (master)
+
+jobs:
+ check_docs:
+ name: Check Docs
+ if: ${{ github.repository == 'wailsapp/wails' && github.base_ref == 'master' }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Verify Changed files
+ uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1
+ id: verify-changed-files
+ with:
+ files: |
+ website/**/*.mdx
+ website/**/*.md
+ - name: Run step only when files change.
+ if: steps.verify-changed-files.outputs.files_changed != 'true'
+ run: |
+ echo "::warning::Feature branch does not contain any changes to the website."
+
+ test_go:
+ name: Run Go Tests
+ runs-on: ${{ matrix.os }}
+ # Run when:
+ # - the event is a pull_request (opened/synchronize/reopened) OR
+ # - the event is a pull_request_review AND the review state is 'approved'
+ # plus other existing filters (not the update-sponsors branch, repo and base_ref)
+ if: >
+ github.repository == 'wailsapp/wails' &&
+ github.base_ref == 'master' &&
+ github.event.pull_request.head.ref != 'update-sponsors' &&
+ (
+ github.event_name == 'pull_request' ||
+ (github.event_name == 'pull_request_review' && github.event.review.state == 'approved')
+ )
+ strategy:
+ matrix:
+ os: [ubuntu-22.04, windows-latest, macos-latest, ubuntu-24.04]
+ go-version: ['1.23']
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Install linux dependencies (22.04)
+ if: matrix.os == 'ubuntu-22.04'
+ run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
+
+ - name: Install linux dependencies (24.04)
+ if: matrix.os == 'ubuntu-24.04'
+ run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
+
+ - name: Setup Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: ${{ matrix.go-version }}
+
+ - name: Run tests (mac)
+ if: matrix.os == 'macos-latest'
+ env:
+ CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
+ working-directory: ./v2
+ run: go test -v ./...
+
+ - name: Run tests (!mac)
+ if: matrix.os != 'macos-latest' && matrix.os != 'ubuntu-24.04'
+ working-directory: ./v2
+ run: go test -v ./...
+
+ - name: Run tests (Ubuntu 24.04)
+ if: matrix.os == 'ubuntu-24.04'
+ working-directory: ./v2
+ run: go test -v -tags webkit2_41 ./...
+
+ # This job will run instead of test_go for the update-sponsors branch
+ skip_tests:
+ name: Skip Tests (Sponsor Update)
+ if: github.event.pull_request.head.ref == 'update-sponsors'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Skip tests for sponsor updates
+ run: |
+ echo "Skipping tests for sponsor update branch"
+ echo "This is an automated update of the sponsors image."
+ continue-on-error: true
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
deleted file mode 100644
index 6db750b73..000000000
--- a/.github/workflows/pr.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-name: PR Checks
-
-on:
- pull_request:
- pull_request_review:
- types: [submitted]
-
-jobs:
- check_docs:
- name: Check Docs
- if: ${{github.repository == 'wailsapp/wails' && contains(github.head_ref,'feature/')}}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
-
- - name: Verify Changed files
- uses: tj-actions/verify-changed-files@v11.1
- id: verify-changed-files
- with:
- files: |
- website/**/*.mdx
- website/**/*.md
-
- - name: Run step only when files change.
- if: steps.verify-changed-files.outputs.files_changed != 'true'
- run: |
- echo "::warning::Feature branch does not contain any changes to the website."
-
- test_go:
- name: Run Go Tests
- runs-on: ${{ matrix.os }}
- if: github.event.review.state == 'approved'
- strategy:
- matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
- go-version: [1.18, 1.19]
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Install linux dependencies
- if: matrix.os == 'ubuntu-latest'
- run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
-
- - name: Setup Go
- uses: actions/setup-go@v3
- with:
- go-version: ${{ matrix.go-version }}
-
- - name: Run tests (mac)
- if: matrix.os == 'macos-latest'
- env:
- CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
- working-directory: ./v2
- run: go test -v ./...
-
- - name: Run tests (!mac)
- if: matrix.os != 'macos-latest'
- working-directory: ./v2
- run: go test -v ./...
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
deleted file mode 100644
index 916148e44..000000000
--- a/.github/workflows/push.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Push Checks
-
-on:
- push:
- branches: [master]
-
-jobs:
- push_files_to_crowdin:
- name: Push files to Crowdin
- if: github.repository == 'wailsapp/wails'
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
-
- - name: Verify Changed files
- uses: tj-actions/verify-changed-files@v11.1
- id: verify-changed-files
- with:
- files: |
- website/**/*.mdx
- website/**/*.md
- website/**/*.json
-
- - name: Set node
- if: steps.verify-changed-files.outputs.files_changed != 'true'
- uses: actions/setup-node@v2
- with:
- node-version: 16.x
-
- - name: Push files
- env:
- CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- run: |
- cd website
- corepack enable
- pnpm install
- pnpm run crowdin push -b master
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
new file mode 100644
index 000000000..a59818660
--- /dev/null
+++ b/.github/workflows/semgrep.yml
@@ -0,0 +1,25 @@
+on:
+ workflow_dispatch: {}
+ pull_request: {}
+ push:
+ branches:
+ - main
+ - master
+ - v3-alpha
+ paths:
+ - .github/workflows/semgrep.yml
+ schedule:
+ # random HH:MM to avoid a load spike on GitHub Actions at 00:00
+ - cron: 14 16 * * *
+name: Semgrep
+jobs:
+ semgrep:
+ name: semgrep/ci
+ runs-on: ubuntu-24.04
+ env:
+ SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
+ container:
+ image: returntocorp/semgrep
+ steps:
+ - uses: actions/checkout@v3
+ - run: semgrep ci
diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml
new file mode 100644
index 000000000..c4ffd25fe
--- /dev/null
+++ b/.github/workflows/stale-issues.yml
@@ -0,0 +1,57 @@
+name: Mark and Close Stale Issues
+
+on:
+ schedule:
+ - cron: '0 1 * * *' # Run at 1 AM UTC every day
+ workflow_dispatch: # Allow manual triggering
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+
+ steps:
+ - uses: actions/stale@v9
+ with:
+ # General settings
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ days-before-stale: 45
+ days-before-close: 10
+ stale-issue-label: 'stale'
+ operations-per-run: 250 # Increased from 50 to 250
+
+ # Issue specific settings
+ stale-issue-message: |
+ This issue has been automatically marked as stale because it has not had recent activity.
+ It will be closed if no further activity occurs within the next 10 days.
+
+ If this issue is still relevant, please add a comment to keep it open.
+ Thank you for your contributions.
+
+ close-issue-message: |
+ This issue has been automatically closed due to lack of activity.
+ Please feel free to reopen it if it's still relevant.
+
+ # PR specific settings - We will not mark PRs as stale
+ days-before-pr-stale: -1 # Disable PR staling
+ days-before-pr-close: -1 # Disable PR closing
+
+ # Exemptions
+ exempt-issue-labels: 'pinned,security,onhold,inprogress,Selected For Development,bug,enhancement,v3-alpha,high-priority'
+ exempt-all-issue-milestones: true
+ exempt-all-issue-assignees: true
+
+ # Protection for existing issues
+ exempt-issue-created-before: '2024-01-01T00:00:00Z'
+ start-date: '2025-06-01T00:00:00Z' # Don't start checking until June 1, 2025
+
+ # Only process issues, not PRs
+ only-labels: ''
+ any-of-labels: ''
+ remove-stale-when-updated: true
+
+ # Debug options
+ debug-only: false # Set to true to test without actually marking issues
+ ascending: true # Process older issues first
diff --git a/.github/workflows/sync-translated-documents.yml b/.github/workflows/sync-translated-documents.yml
index 5a8cd109a..0aa06f11e 100644
--- a/.github/workflows/sync-translated-documents.yml
+++ b/.github/workflows/sync-translated-documents.yml
@@ -1,7 +1,9 @@
-name: Sync Translated Documents
+name: Sync Translations
on:
workflow_dispatch:
+ schedule:
+ - cron: "0 0 * * *"
jobs:
sync-translated-documents:
@@ -10,22 +12,30 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set node
+ - name: Setup Nodejs
uses: actions/setup-node@v2
with:
- node-version: 16.x
+ node-version: 20.x
+
+ - name: Install Task
+ uses: arduino/setup-task@v1
+ with:
+ version: 3.x
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Sync Translated Documents
- run: cd scripts && chmod 755 ./sync-translated-documents.sh && ./sync-translated-documents.sh
env:
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+ working-directory: ./website
+ run: task crowdin:pull
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
- commit-message: "docs: sync documents"
- title: "docs: sync documents"
+ commit-message: "docs: sync translations"
+ title: "docs: sync translations"
body: "- [x] Sync translated documents"
- branch: feature/documents
+ branch: chore/sync-translations
+ labels: translation
delete-branch: true
draft: true
diff --git a/.github/workflows/test-nightly-releases.yml b/.github/workflows/test-nightly-releases.yml
new file mode 100644
index 000000000..63df09935
--- /dev/null
+++ b/.github/workflows/test-nightly-releases.yml
@@ -0,0 +1,216 @@
+name: Test Nightly Releases (Dry Run)
+
+on:
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Run in dry-run mode (no actual releases)'
+ required: false
+ default: true
+ type: boolean
+ test_branch:
+ description: 'Branch to test against'
+ required: false
+ default: 'master'
+ type: string
+
+env:
+ GO_VERSION: '1.24'
+
+jobs:
+ test-permissions:
+ name: Test Release Permissions
+ runs-on: ubuntu-latest
+ outputs:
+ authorized: ${{ steps.check.outputs.authorized }}
+ steps:
+ - name: Check if user is authorized
+ id: check
+ run: |
+ # Test authorization logic
+ AUTHORIZED_USERS="leaanthony"
+
+ if [[ "$AUTHORIZED_USERS" == *"${{ github.actor }}"* ]]; then
+ echo "✅ User ${{ github.actor }} is authorized"
+ echo "authorized=true" >> $GITHUB_OUTPUT
+ else
+ echo "❌ User ${{ github.actor }} is not authorized"
+ echo "authorized=false" >> $GITHUB_OUTPUT
+ fi
+
+ test-changelog-extraction:
+ name: Test Changelog Extraction
+ runs-on: ubuntu-latest
+ needs: test-permissions
+ if: needs.test-permissions.outputs.authorized == 'true'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.test_branch }}
+ fetch-depth: 0
+
+ - name: Test v2 changelog extraction
+ run: |
+ echo "🧪 Testing v2 changelog extraction..."
+ CHANGELOG_FILE="website/src/pages/changelog.mdx"
+
+ if [ ! -f "$CHANGELOG_FILE" ]; then
+ echo "❌ v2 changelog file not found"
+ exit 1
+ fi
+
+ # Extract unreleased section
+ awk '
+ /^## \[Unreleased\]/ { found=1; next }
+ found && /^## / { exit }
+ found && !/^$/ { print }
+ ' $CHANGELOG_FILE > v2_release_notes.md
+
+ echo "📝 v2 changelog content (first 10 lines):"
+ head -10 v2_release_notes.md || echo "No content found"
+ echo "Total lines: $(wc -l < v2_release_notes.md)"
+
+ - name: Test v3 changelog extraction (if accessible)
+ run: |
+ echo "🧪 Testing v3 changelog extraction..."
+
+ if git show v3-alpha:docs/src/content/docs/changelog.mdx > /dev/null 2>&1; then
+ echo "✅ v3 changelog accessible"
+
+ git show v3-alpha:docs/src/content/docs/changelog.mdx | awk '
+ /^## \[Unreleased\]/ { found=1; next }
+ found && /^## / { exit }
+ found && !/^$/ { print }
+ ' > v3_release_notes.md
+
+ echo "📝 v3 changelog content (first 10 lines):"
+ head -10 v3_release_notes.md || echo "No content found"
+ echo "Total lines: $(wc -l < v3_release_notes.md)"
+ else
+ echo "⚠️ v3 changelog not accessible from current context"
+ fi
+
+ test-version-detection:
+ name: Test Version Detection
+ runs-on: ubuntu-latest
+ needs: test-permissions
+ if: needs.test-permissions.outputs.authorized == 'true'
+ outputs:
+ v2_current_version: ${{ steps.versions.outputs.v2_current }}
+ v2_next_patch: ${{ steps.versions.outputs.v2_next_patch }}
+ v2_next_minor: ${{ steps.versions.outputs.v2_next_minor }}
+ v2_next_major: ${{ steps.versions.outputs.v2_next_major }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Test version detection logic
+ id: versions
+ run: |
+ echo "🧪 Testing version detection..."
+
+ # Test v2 version parsing
+ if [ -f "v2/cmd/wails/internal/version.txt" ]; then
+ CURRENT_V2=$(cat v2/cmd/wails/internal/version.txt | sed 's/^v//')
+ echo "Current v2 version: v$CURRENT_V2"
+ echo "v2_current=v$CURRENT_V2" >> $GITHUB_OUTPUT
+
+ # Parse and increment
+ IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_V2"
+ MAJOR=${VERSION_PARTS[0]}
+ MINOR=${VERSION_PARTS[1]}
+ PATCH=${VERSION_PARTS[2]}
+
+ PATCH_VERSION="v$MAJOR.$MINOR.$((PATCH + 1))"
+ MINOR_VERSION="v$MAJOR.$((MINOR + 1)).0"
+ MAJOR_VERSION="v$((MAJOR + 1)).0.0"
+
+ echo "v2_next_patch=$PATCH_VERSION" >> $GITHUB_OUTPUT
+ echo "v2_next_minor=$MINOR_VERSION" >> $GITHUB_OUTPUT
+ echo "v2_next_major=$MAJOR_VERSION" >> $GITHUB_OUTPUT
+
+ echo "✅ Patch: v$CURRENT_V2 → $PATCH_VERSION"
+ echo "✅ Minor: v$CURRENT_V2 → $MINOR_VERSION"
+ echo "✅ Major: v$CURRENT_V2 → $MAJOR_VERSION"
+ else
+ echo "❌ v2 version file not found"
+ fi
+
+ test-commit-analysis:
+ name: Test Commit Analysis
+ runs-on: ubuntu-latest
+ needs: test-permissions
+ if: needs.test-permissions.outputs.authorized == 'true'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Test commit analysis
+ run: |
+ echo "🧪 Testing commit analysis..."
+
+ # Get recent commits for testing
+ echo "Recent commits:"
+ git log --oneline -10
+
+ # Test conventional commit detection
+ RECENT_COMMITS=$(git log --oneline --since="7 days ago")
+ echo "Commits from last 7 days:"
+ echo "$RECENT_COMMITS"
+
+ # Analyze for release type
+ RELEASE_TYPE="patch"
+ if echo "$RECENT_COMMITS" | grep -q "feat!\|fix!\|BREAKING CHANGE:"; then
+ RELEASE_TYPE="major"
+ elif echo "$RECENT_COMMITS" | grep -q "feat\|BREAKING CHANGE"; then
+ RELEASE_TYPE="minor"
+ fi
+
+ echo "✅ Detected release type: $RELEASE_TYPE"
+
+ test-summary:
+ name: Test Summary
+ runs-on: ubuntu-latest
+ needs: [test-permissions, test-changelog-extraction, test-version-detection, test-commit-analysis]
+ if: always()
+ steps:
+ - name: Print test results
+ run: |
+ echo "# 🧪 Nightly Release Workflow Test Results" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [ "${{ needs.test-permissions.result }}" == "success" ]; then
+ echo "✅ **Permissions Test**: Passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Permissions Test**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [ "${{ needs.test-changelog-extraction.result }}" == "success" ]; then
+ echo "✅ **Changelog Extraction**: Passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Changelog Extraction**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [ "${{ needs.test-version-detection.result }}" == "success" ]; then
+ echo "✅ **Version Detection**: Passed" >> $GITHUB_STEP_SUMMARY
+ echo " - Current v2: ${{ needs.test-version-detection.outputs.v2_current_version }}" >> $GITHUB_STEP_SUMMARY
+ echo " - Next patch: ${{ needs.test-version-detection.outputs.v2_next_patch }}" >> $GITHUB_STEP_SUMMARY
+ echo " - Next minor: ${{ needs.test-version-detection.outputs.v2_next_minor }}" >> $GITHUB_STEP_SUMMARY
+ echo " - Next major: ${{ needs.test-version-detection.outputs.v2_next_major }}" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Version Detection**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [ "${{ needs.test-commit-analysis.result }}" == "success" ]; then
+ echo "✅ **Commit Analysis**: Passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Commit Analysis**: Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Note**: This was a dry-run test. No actual releases were created." >> $GITHUB_STEP_SUMMARY
\ No newline at end of file
diff --git a/.github/workflows/unreleased-changelog-trigger.yml b/.github/workflows/unreleased-changelog-trigger.yml
new file mode 100644
index 000000000..8cfe85de0
--- /dev/null
+++ b/.github/workflows/unreleased-changelog-trigger.yml
@@ -0,0 +1,129 @@
+name: Auto Release on Changelog Update
+
+on:
+ push:
+ branches:
+ - v3-alpha
+ paths:
+ - 'v3/UNRELEASED_CHANGELOG.md'
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Run in dry-run mode (no actual release)'
+ required: false
+ default: false
+ type: boolean
+
+jobs:
+ check-permissions:
+ name: Check Release Permissions
+ runs-on: ubuntu-latest
+ outputs:
+ authorized: ${{ steps.check.outputs.authorized }}
+ steps:
+ - name: Check if user is authorized for releases
+ id: check
+ run: |
+ # Only allow specific users to trigger releases
+ AUTHORIZED_USERS="leaanthony"
+
+ if [[ "$AUTHORIZED_USERS" == *"${{ github.actor }}"* ]]; then
+ echo "✅ User ${{ github.actor }} is authorized for releases"
+ echo "authorized=true" >> $GITHUB_OUTPUT
+ else
+ echo "❌ User ${{ github.actor }} is not authorized for releases"
+ echo "authorized=false" >> $GITHUB_OUTPUT
+ fi
+
+ trigger-release:
+ name: Trigger v3-alpha Release
+ permissions:
+ contents: read
+ actions: write
+ runs-on: ubuntu-latest
+ needs: check-permissions
+ if: needs.check-permissions.outputs.authorized == 'true'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: v3-alpha
+ fetch-depth: 0
+ token: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
+
+ - name: Check for unreleased changelog content
+ id: changelog_check
+ run: |
+ echo "🔍 Checking UNRELEASED_CHANGELOG.md for content..."
+
+ cd v3
+ # Check if UNRELEASED_CHANGELOG.md has actual content beyond the template
+ if [ -f "UNRELEASED_CHANGELOG.md" ]; then
+ # Use a simple check for actual content (bullet points starting with -)
+ CONTENT_LINES=$(grep -E "^\s*-\s+[^[:space:]]" UNRELEASED_CHANGELOG.md | wc -l)
+ if [ "$CONTENT_LINES" -gt 0 ]; then
+ echo "✅ Found $CONTENT_LINES content lines in UNRELEASED_CHANGELOG.md"
+ echo "has_content=true" >> $GITHUB_OUTPUT
+ else
+ echo "ℹ️ No actual content found in UNRELEASED_CHANGELOG.md"
+ echo "has_content=false" >> $GITHUB_OUTPUT
+ fi
+ else
+ echo "❌ UNRELEASED_CHANGELOG.md not found"
+ echo "has_content=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Trigger nightly release workflow
+ if: steps.changelog_check.outputs.has_content == 'true'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
+ script: |
+ const response = await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ workflow_id: 'nightly-release-v3.yml',
+ ref: 'v3-alpha',
+ inputs: {
+ force_release: 'true',
+ dry_run: '${{ github.event.inputs.dry_run || "false" }}'
+ }
+ });
+
+ console.log('🚀 Successfully triggered nightly release workflow');
+ console.log(`Workflow dispatch response status: ${response.status}`);
+
+ // Create a summary
+ core.summary
+ .addHeading('🚀 Auto Release Triggered')
+ .addRaw('The v3-alpha release workflow has been automatically triggered due to changes in UNRELEASED_CHANGELOG.md')
+ .addTable([
+ [{data: 'Trigger', header: true}, {data: 'Value', header: true}],
+ ['Repository', context.repo.repo],
+ ['Branch', 'v3-alpha'],
+ ['Actor', context.actor],
+ ['Dry Run', '${{ github.event.inputs.dry_run || "false" }}'],
+ ['Force Release', 'true']
+ ])
+ .addRaw('\n---\n*This release was automatically triggered by the unreleased-changelog-trigger workflow*')
+ .write();
+
+ - name: No content found
+ if: steps.changelog_check.outputs.has_content == 'false'
+ run: |
+ echo "ℹ️ No content found in UNRELEASED_CHANGELOG.md, skipping release trigger"
+ echo "## ℹ️ No Release Triggered" >> $GITHUB_STEP_SUMMARY
+ echo "**Reason:** UNRELEASED_CHANGELOG.md does not contain actual changelog content" >> $GITHUB_STEP_SUMMARY
+ echo "**Action:** No release workflow was triggered" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "To trigger a release, add actual changelog entries to the UNRELEASED_CHANGELOG.md file." >> $GITHUB_STEP_SUMMARY
+
+ - name: Unauthorized user
+ if: needs.check-permissions.outputs.authorized == 'false'
+ run: |
+ echo "❌ User ${{ github.actor }} is not authorized to trigger releases"
+ echo "## ❌ Unauthorized Release Attempt" >> $GITHUB_STEP_SUMMARY
+ echo "**User:** ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Action:** Release trigger was blocked due to insufficient permissions" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Only authorized users can trigger automatic releases via changelog updates." >> $GITHUB_STEP_SUMMARY
\ No newline at end of file
diff --git a/.github/workflows/upload-source-documents.yml b/.github/workflows/upload-source-documents.yml
new file mode 100644
index 000000000..69d6c3e48
--- /dev/null
+++ b/.github/workflows/upload-source-documents.yml
@@ -0,0 +1,41 @@
+name: Upload Source Documents
+
+on:
+ push:
+ branches: [master]
+ workflow_dispatch:
+
+jobs:
+ push_files_to_crowdin:
+ name: Push files to Crowdin
+ if: github.repository == 'wailsapp/wails'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Verify Changed files
+ id: changed-files
+ uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1
+ with:
+ files: |
+ website/**/*.mdx
+ website/**/*.md
+ website/**/*.json
+
+ - name: Setup Nodejs
+ uses: actions/setup-node@v2
+ with:
+ node-version: 20.x
+
+ - name: Setup Task
+ uses: arduino/setup-task@v1
+ with:
+ version: 3.x
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Upload source documents
+ if: steps.changed-files.outputs.any_changed == 'true'
+ env:
+ CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+ working-directory: ./website
+ run: task crowdin:push
diff --git a/.gitignore b/.gitignore
index 7da685641..e7888b44a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,11 @@ v2/test/kitchensink/frontend/package.json.md5
v2/cmd/wails/internal/commands/initialise/templates/testtemplates/
.env
/website/static/img/.cache.json
+
+/v3/.task
+/v3/examples/build/bin/testapp
+/websitev3/site/
+/v3/examples/plugins/bin/testapp
+
+# Temporary called mkdocs, should be renamed to more standard -website or similar
+/mkdocs-website/site
diff --git a/.goreleaser.yml b/.goreleaser.yml
deleted file mode 100644
index a5769985b..000000000
--- a/.goreleaser.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-# This is an example goreleaser.yaml file with some sane defaults.
-# Make sure to check the documentation at http://goreleaser.com
-
-builds:
-- env:
- - CGO_ENABLED=0
- goos:
- - windows
- - linux
- - darwin
- goarch:
- - 386
- - amd64
- ignore:
- - goos: darwin
- goarch: 386
- main: ./cmd/wails/main.go
-archive:
- replacements:
- darwin: Darwin
- linux: Linux
- windows: Windows
- 386: i386
- amd64: x86_64
-checksum:
- name_template: 'checksums.txt'
-snapshot:
- name_template: "{{ .Tag }}-next"
-changelog:
- sort: asc
- filters:
- exclude:
- - '^docs:'
- - '^test:'
diff --git a/.hound.yml b/.hound.yml
deleted file mode 100644
index c74b4a197..000000000
--- a/.hound.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-jshint:
- config_file: .jshintrc
-eslint:
- enabled: true
- config_file: .eslintrc
- ignore_file: .eslintignore
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 53b202cb9..000000000
--- a/.jshintrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "esversion": 6
-}
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..52b962c55
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+website
+v2
+v3
\ No newline at end of file
diff --git a/.prettierrc.yml b/.prettierrc.yml
new file mode 100644
index 000000000..685d8b6e7
--- /dev/null
+++ b/.prettierrc.yml
@@ -0,0 +1,6 @@
+overrides:
+ - files:
+ - "**/*.md"
+ options:
+ printWidth: 80
+ proseWrap: always
diff --git a/.replit b/.replit
new file mode 100644
index 000000000..619bd7227
--- /dev/null
+++ b/.replit
@@ -0,0 +1,8 @@
+modules = ["go-1.21", "web", "nodejs-20"]
+run = "go run v2/cmd/wails/main.go"
+
+[nix]
+channel = "stable-24_05"
+
+[deployment]
+run = ["sh", "-c", "go run v2/cmd/wails/main.go"]
diff --git a/README.de.md b/README.de.md
new file mode 100644
index 000000000..5df35de5b
--- /dev/null
+++ b/README.de.md
@@ -0,0 +1,160 @@
+
+
+
+
+
+Erschaffe Desktop Anwendungen mit Go & Web Technologien.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md)
+
+
+
+
+
+## Inhaltsverzeichnis
+
+- [Inhaltsverzeichnis](#inhaltsverzeichnis)
+- [Einführung](#einführung)
+- [Funktionen](#funktionen)
+ - [Roadmap](#roadmap)
+- [Loslegen](#loslegen)
+- [Sponsoren](#sponsoren)
+- [FAQ](#faq)
+- [Sterne Überblick](#sterne-überblick)
+- [Mitwirkende](#mitwirkende)
+- [Lizenz](#lizenz)
+- [Inspiration](#inspiration)
+
+## Einführung
+
+Die herkömmliche Methode zur Bereitstellung von Web-Interfaces für Go ist über einen eingebauten Webserver.
+Wails nutzt einen anderen Weg. Es kann sowohl Go-Code als auch ein Web-Frontend in eine einzige Datei bauen.
+Beigelieferte Werkzeuge übernehmen die Projekterstellung, den Kompilierungsprozess und das bauen.
+Du musst nur kreativ werden.
+
+## Funktionen
+
+- Nutze Standard Go für das Backend
+- Nutze eine Frontend Technologie mit der du dich bereits auskennst um dein UI zu bauen.
+- Erschaffe schnell und einfach Frontends mit vorgefertigten Vorlagen für deine Go-Programme
+- Nutze Javascript um Go Methoden aufzurufen
+- Automatisch generierte Typescript Definitionen für deine Go Strukturen und Methoden
+- Native Dialoge und Menüs
+- Native Dark-/Lightmode Unterstützung
+- Unterstützt moderne Transluzenz- und Milchglaseffekte
+- Vereinheitlichtes Eventsystem zwischen Go und Javascript
+- Leistungsstarkes CLI-Tool zum einfachen erstellen und bauen von Projekten
+- Multiplattformen
+- Nutze native Render-Engines - _keine eingebetteten Browser_!
+
+### Roadmap
+
+Die Projekt Roadmap kann [hier](https://github.com/wailsapp/wails/discussions/1484) gefunden werden. Bitte lies diese
+durch bevor du eine Idee vorschlägst
+
+## Loslegen
+
+Die Installationsinstruktionen sind auf der [offiziellen Website](https://wails.io/docs/gettingstarted/installation).
+
+## Sponsoren
+
+Dieses Projekt wird von diesen freundlichen Leuten und Firmen unterstützt:
+
+
+
+
+
+
+## FAQ
+
+- Ist das eine Alternative zu Electron?
+
+ Hängt von deinen Anforderungen ab. Wails wurde entwickelt um das Go-Programmieren leicht zu machen und effiziente
+ Desktop-Anwendungen zu erstellen oder ein Frontend zu einer bestehenden Anwendung hinzuzufügen.
+ Wails bietet native Elemente wie Dialoge und Menüs und könnte somit als eine leichte effiziente Electron-Alternative
+ betrachtet werden.
+
+- Für wen ist dieses projekt geeignet?
+
+ Go Entwickler, die ein HTML/CSS/JS-Frontend in ihre Anwendung integrieren möchten, ohne einen Webserver zu erstellen und
+ einen Browser öffnen zu müssen, um dieses zu sehen
+
+- Wie kam es zu diesem Namen?
+
+ Als ich WebView sah dachte ich "Was ich wirklich will, ist ein Werkzeug für die Erstellung von WebView Anwendungen so wie Rails für Ruby".
+ Also war es zunächst ein Wortspiel (Webview on Rails). Zufälligerweise ist es auch ein Homophon des englischen Namens des [Landes](https://en.wikipedia.org/wiki/Wales), aus dem ich komme.
+ Also ist es dabei geblieben.
+
+## Sterne Überblick
+
+
+
+
+
+
+
+
+
+## Mitwirkende
+
+Die Liste der Mitwirkenden wird zu groß für diese Readme. All die fantastischen Menschen, die zu diesem
+Projekt beigetragen haben, haben [hier](https://wails.io/credits#contributors) ihre eigene Seite.
+
+## Lizenz
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Inspiration
+
+Dieses Projekt wurde hauptsächlich zu den folgenden Alben entwickelt
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.es.md b/README.es.md
new file mode 100644
index 000000000..277d1c1fd
--- /dev/null
+++ b/README.es.md
@@ -0,0 +1,169 @@
+
+
+
+
+
+ Construye aplicaciones de escritorio usando Go y tecnologías web.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## Tabla de Contenidos
+
+- [Tabla de Contenidos](#tabla-de-contenidos)
+- [Introducción](#introducción)
+- [Funcionalidades](#funcionalidades)
+ - [Plan de Trabajo](#plan-de-trabajo)
+- [Empezando](#empezando)
+- [Patrocinadores](#patrocinadores)
+- [Preguntas Frecuentes](#preguntas-frecuentes)
+- [Estrellas a lo Largo del Tiempo](#estrellas-a-lo-largo-del-tiempo)
+- [Colaboradores](#colaboradores)
+- [Licencia](#licencia)
+- [Inspiración](#inspiración)
+
+## Introducción
+
+El método tradicional para proveer una interfaz web en programas hechos con Go
+es a través del servidor web incorporado. Wails ofrece un enfoque diferente al
+permitir combinar el código hecho en Go con un frontend web en un solo archivo
+binario. Las herramientas que proporcionamos facilitan este trabajo para ti, al
+crear, compilar y empaquetar tu proyecto. ¡Lo único que debes hacer es ponerte
+creativo!
+
+## Funcionalidades
+
+- Utiliza Go estándar para el backend
+- Utiliza cualquier tecnología frontend con la que ya estés familiarizado para
+ construir tu interfaz de usuario
+- Crea rápidamente interfaces de usuario enriquecidas para tus programas en Go
+ utilizando plantillas predefinidas
+- Invoca fácilmente métodos de Go desde Javascript
+- Definiciones de Typescript generadas automáticamente para tus structs y
+ métodos de Go
+- Diálogos y menús nativos
+- Soporte nativo de modo oscuro / claro
+- Soporte de translucidez y efectos de ventana esmerilada
+- Sistema de eventos unificado entre Go y Javascript
+- Herramienta CLI potente para generar y construir tus proyectos rápidamente
+- Multiplataforma
+- Usa motores de renderizado nativos - ¡_sin navegador integrado_!
+
+### Plan de Trabajo
+
+El plan de trabajo se puede encontrar
+[aqui](https://github.com/wailsapp/wails/discussions/1484). Por favor,
+consúltalo antes de abrir una solicitud de mejora.
+
+## Empezando
+
+Las instrucciones de instalacion se encuentran en nuestra
+[pagina web oficial](https://wails.io/docs/gettingstarted/installation).
+
+## Patrocinadores
+
+Este Proyecto cuenta con el apoyo de estas amables personas/ compañías:
+
+
+
+
+
+
+## Preguntas Frecuentes
+
+- ¿Es esta una alternativa a Electron?
+
+ Depende de tus requisitos. Está diseñado para facilitar a los programadores de
+ Go la creación de aplicaciones de escritorio livianas o agregar una interfaz
+ gráfica a sus aplicaciones existentes. Wails ofrece elementos nativos como
+ menús y diálogos, por lo que podría considerarse una alternativa liviana a
+ Electron.
+
+- ¿A quien esta dirigido este proyecto?
+
+ El proyecto esta dirigido a programadores de Go que desean integrar una
+ interfaz HMTL/JS/CSS en sus aplicaciones, sin tener que recurrir a la creación
+ de un servidor y abrir el navegador para visualizarla.
+
+- ¿Cual es el significado del nombre?
+
+ Cuando vi WebView, pensé: "Lo que realmente quiero es una herramienta para
+ construir una aplicación WebView, algo similar a lo que Rails es para Ruby".
+ Así que inicialmente fue un juego de palabras (WebView en Rails). Además, por
+ casualidad, también es homófono del nombre en inglés del
+ [país](https://en.wikipedia.org/wiki/Wales) del que provengo. Así que se quedó
+ con ese nombre.
+
+## Estrellas a lo Largo del Tiempo
+
+[](https://star-history.com/#wailsapp/wails&Date)
+
+## Colaboradores
+
+¡La lista de colaboradores se está volviendo demasiado grande para el archivo
+readme! Todas las personas increíbles que han contribuido a este proyecto tienen
+su propia página [aqui](https://wails.io/credits#contributors).
+
+## Licencia
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Inspiración
+
+Este proyecto fue construido mientras se escuchaban estos álbumes:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
+ [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.fr.md b/README.fr.md
new file mode 100644
index 000000000..61230f353
--- /dev/null
+++ b/README.fr.md
@@ -0,0 +1,144 @@
+
+
+
+
+
+ Créer des applications de bureau avec Go et les technologies Web.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## Sommaire
+
+- [Sommaire](#sommaire)
+- [Introduction](#introduction)
+- [Fonctionnalités](#fonctionnalités)
+ - [Feuille de route](#feuille-de-route)
+- [Démarrage](#démarrage)
+- [Les sponsors](#les-sponsors)
+- [Foire aux questions](#foire-aux-questions)
+- [Les étoiles au fil du temps](#les-étoiles-au-fil-du-temps)
+- [Les contributeurs](#les-contributeurs)
+- [License](#license)
+- [Inspiration](#inspiration)
+
+## Introduction
+
+La méthode traditionnelle pour fournir des interfaces web aux programmes Go consiste à utiliser un serveur web intégré. Wails propose une approche différente : il offre la possibilité d'intégrer à la fois le code Go et une interface web dans un seul binaire. Des outils sont fournis pour vous faciliter la tâche en gérant la création, la compilation et le regroupement des projets. Il ne vous reste plus qu'à faire preuve de créativité!
+
+## Fonctionnalités
+
+- Utiliser Go pour le backend
+- Utilisez n'importe quelle technologie frontend avec laquelle vous êtes déjà familier pour construire votre interface utilisateur.
+- Créez rapidement des interfaces riches pour vos programmes Go à l'aide de modèles prédéfinis.
+- Appeler facilement des méthodes Go à partir de Javascript
+- Définitions Typescript auto-générées pour vos structures et méthodes Go
+- Dialogues et menus natifs
+- Prise en charge native des modes sombre et clair
+- Prise en charge des effets modernes de translucidité et de "frosted window".
+- Système d'événements unifié entre Go et Javascript
+- Outil puissant pour générer et construire rapidement vos projets
+- Multiplateforme
+- Utilise des moteurs de rendu natifs - _pas de navigateur intégré_ !
+
+### Feuille de route
+
+La feuille de route du projet peut être consultée [ici](https://github.com/wailsapp/wails/discussions/1484). Veuillez consulter avant d'ouvrir une demande d'amélioration.
+
+## Démarrage
+
+Les instructions d'installation se trouvent sur le site [site officiel](https://wails.io/docs/gettingstarted/installation).
+
+## Les sponsors
+
+Ce projet est soutenu par ces personnes aimables et entreprises:
+
+
+
+
+
+
+## Foire aux questions
+
+- S'agit-il d'une alternative à Electron ?
+
+ Cela dépend de vos besoins. Il est conçu pour permettre aux programmeurs Go de créer facilement des applications de bureau légères ou d'ajouter une interface à leurs applications existantes. Wails offre des éléments natifs tels que des menus et des boîtes de dialogue, il peut donc être considéré comme une alternative légère à electron.
+
+- À qui s'adresse ce projet ?
+
+ Les programmeurs Go qui souhaitent intégrer une interface HTML/JS/CSS à leurs applications, sans avoir à créer un serveur et à ouvrir un navigateur pour l'afficher.
+
+- Pourquoi ce nom ??
+
+ Lorsque j'ai vu WebView, je me suis dit : "Ce que je veux vraiment, c'est un outil pour construire une application WebView, un peu comme Rails l'est pour Ruby". Au départ, il s'agissait donc d'un jeu de mots (Webview on Rails). Il se trouve que c'est aussi un homophone du nom anglais du [Pays](https://en.wikipedia.org/wiki/Wales) d'où je viens. Il s'est donc imposé.
+
+## Les étoiles au fil du temps
+
+[](https://star-history.com/#wailsapp/wails&Date)
+
+## Les contributeurs
+
+La liste des contributeurs devient trop importante pour le readme ! Toutes les personnes extraordinaires qui ont contribué à ce projet ont leur propre page [ici](https://wails.io/credits#contributors).
+
+## License
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Inspiration
+
+Ce projet a été principalement codé sur les albums suivants :
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.ja.md b/README.ja.md
index 64a6f8756..ffd9f8103 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -26,8 +26,8 @@
-
-
+
+
@@ -42,7 +42,10 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
@@ -52,16 +55,16 @@
- [目次](#目次)
- [はじめに](#はじめに)
- - [公式サイト](#公式サイト)
- - [ロードマップ](#ロードマップ)
- [特徴](#特徴)
-- [スポンサー](#スポンサー)
+ - [ロードマップ](#ロードマップ)
- [始め方](#始め方)
+- [スポンサー](#スポンサー)
- [FAQ](#faq)
+- [スター数の推移](#スター数の推移)
- [コントリビューター](#コントリビューター)
-- [特記事項](#特記事項)
-- [スペシャルサンクス](#スペシャルサンクス)
- [ライセンス](#ライセンス)
+- [インスピレーション](#インスピレーション)
+
## はじめに
@@ -69,44 +72,35 @@ Go プログラムにウェブインタフェースを提供する従来の方
Wails では Go のコードとウェブフロントエンドを単一のバイナリにまとめる機能を提供します。
また、プロジェクトの作成、コンパイル、ビルドを行うためのツールが提供されています。あなたがすべきことは創造性を発揮することです!
-### 公式サイト
-
-Version 2:
-
-Wails v2 が 3 つのプラットフォームでベータ版としてリリースされました。興味のある方は[新しいウェブサイト](https://wails.io)をご覧ください。
-
-レガシー版 v1:
-
-レガシー版 v1 のドキュメントは[https://wails.app](https://wails.app)で見ることができます。
-
-### ロードマップ
-
-プロジェクトのロードマップは[こちら](https://github.com/wailsapp/wails/discussions/1484)になります。
-機能拡張のリクエストを出す前にご覧ください。
-
## 特徴
- バックエンドには Go を利用しています
- 使い慣れたフロントエンド技術を利用して UI を構築できます
-- あらかじめ用意されたテンプレートを利用することで、リッチなフロントエンドを備えた Go プログラムを作成できます
+- あらかじめ用意されたテンプレートを利用することで、リッチなフロントエンドを備えた Go プログラムを素早く作成できます
- JavaScript から Go のメソッドを簡単に呼び出すことができます
- あなたの書いた Go の構造体やメソットに応じた TypeScript の定義が自動生成されます
- ネイティブのダイアログとメニューが利用できます
+- ネイティブなダーク/ライトモードをサポートします
- モダンな半透明や「frosted window」エフェクトをサポートしています
- Go と JavaScript 間で統一されたイベント・システムを備えています
- プロジェクトを素早く生成して構築する強力な cli ツールを用意しています
- マルチプラットフォームに対応しています
- ネイティブなレンダリングエンジンを使用しています - _つまりブラウザを埋め込んでいるわけではありません!_
-## スポンサー
+### ロードマップ
-このプロジェクトは、以下の方々・企業によって支えられています。
-
+プロジェクトのロードマップは[こちら](https://github.com/wailsapp/wails/discussions/1484)になります。
+機能拡張のリクエストを出す前にご覧ください。
## 始め方
インストール方法は[公式サイト](https://wails.io/docs/gettingstarted/installation)に掲載されています。
+## スポンサー
+
+このプロジェクトは、以下の方々・企業によって支えられています。
+
+
## FAQ
- Electron の代替品になりますか?
@@ -127,20 +121,18 @@ Wails v2 が 3 つのプラットフォームでベータ版としてリリー
## スター数の推移
-[](https://starchart.cc/wailsapp/wails)
+[](https://star-history.com/#wailsapp/wails&Date)
## コントリビューター
貢献してくれた方のリストが大きくなりすぎて、readme に入りきらなくなりました!
このプロジェクトに貢献してくれた素晴らしい方々のページは[こちら](https://wails.io/credits#contributors)です。
-## 特記事項
+## ライセンス
-このプロジェクトは以下の方々の協力がなければ、実現しなかったと思います。
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
-- [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - 彼のサポートとフィードバックはとても大きいものでした。
-- [Serge Zaitsev](https://github.com/zserge) - Wails のウィンドウで使用している[Webview](https://github.com/zserge/webview)の作者です。
-- [Byron](https://github.com/bh90210) - 時には Byron が一人でこのプロジェクトを存続させてくれたこともありました。彼の素晴らしいインプットがなければ v1 に到達することはなかったでしょう。
+## インスピレーション
プロジェクトを進める際に、以下のアルバムたちも支えてくれています。
@@ -158,20 +150,3 @@ Wails v2 が 3 つのプラットフォームでベータ版としてリリー
- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
-## スペシャルサンクス
-
-
-
- このプロジェクトを後援し、WailsをApple Siliconに移植する取り組みを支援してくれた Pace に とても 感謝しています!
- パワフルで素早く簡単に使えるプロジェクト管理ツールをお探しなら、ぜひチェックしてみてください!
-
-
-
- ライセンスを提供していただいたJetBrains社に感謝します!
- ロゴをクリックして、感謝の気持ちを伝えてください!
-
-
-
-## ライセンス
-
-[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
diff --git a/README.ko.md b/README.ko.md
index 95bb8eb36..075e04229 100644
--- a/README.ko.md
+++ b/README.ko.md
@@ -26,8 +26,8 @@
-
-
+
+
@@ -42,7 +42,10 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
@@ -57,6 +60,7 @@
- [시작하기](#시작하기)
- [스폰서](#스폰서)
- [FAQ](#faq)
+- [Stargazers 성장 추세](#stargazers-성장-추세)
- [기여자](#기여자)
- [라이센스](#라이센스)
- [영감](#영감)
diff --git a/README.md b/README.md
index 1787e0c70..5ab9309b4 100644
--- a/README.md
+++ b/README.md
@@ -24,8 +24,8 @@
-
-
+
+
@@ -40,7 +40,10 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
@@ -55,6 +58,7 @@
- [Getting Started](#getting-started)
- [Sponsors](#sponsors)
- [FAQ](#faq)
+- [Stargazers over time](#stargazers-over-time)
- [Contributors](#contributors)
- [License](#license)
- [Inspiration](#inspiration)
@@ -83,7 +87,7 @@ make this easy for you by handling project creation, compilation and bundling. A
### Roadmap
The project roadmap may be found [here](https://github.com/wailsapp/wails/discussions/1484). Please consult
-this before open up an enhancement request.
+it before creating an enhancement request.
## Getting Started
@@ -94,6 +98,10 @@ The installation instructions are on the [official website](https://wails.io/doc
This project is supported by these kind people / companies:
+## Powered By
+
+[](https://jb.gg/OpenSource)
+
## FAQ
- Is this an alternative to Electron?
@@ -115,7 +123,13 @@ This project is supported by these kind people / companies:
## Stargazers over time
-[](https://star-history.com/#wailsapp/wails&Date)
+
+
+
+
+
+
+
## Contributors
diff --git a/README.pt-br.md b/README.pt-br.md
new file mode 100644
index 000000000..0e3883352
--- /dev/null
+++ b/README.pt-br.md
@@ -0,0 +1,151 @@
+
+
+
+
+
+ Crie aplicativos de desktop usando Go e tecnologias Web.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## Índice
+
+- [Índice](#índice)
+- [Introdução](#introdução)
+- [Recursos e funcionalidades](#recursos-e-funcionalidades)
+ - [Plano de trabalho](#plano-de-trabalho)
+- [Iniciando](#iniciando)
+- [Patrocinadores](#patrocinadores)
+- [Perguntas frequentes](#perguntas-frequentes)
+- [Estrelas ao longo do tempo](#estrelas-ao-longo-do-tempo)
+- [Colaboradores](#colaboradores)
+- [Licença](#licença)
+- [Inspiração](#inspiração)
+
+## Introdução
+
+O método tradicional de fornecer interfaces da Web para programas Go é por meio de um servidor da Web integrado. Wails oferece uma
+abordagem: fornece a capacidade de agrupar o código Go e um front-end da Web em um único binário. As ferramentas são fornecidas para
+que torne isso mais fácil para você lidando com a criação, compilação e agrupamento de projetos. Tudo o que você precisa fazer é ser criativo!
+
+## Recursos e funcionalidades
+
+- Use Go padrão para o back-end
+- Use qualquer tecnologia de front-end com a qual você já esteja familiarizado para criar sua interface do usuário
+- Crie rapidamente um front-end avançado para seus programas Go usando modelos pré-construídos
+- Chame facilmente métodos Go com JavaScript
+- Definições TypeScript geradas automaticamente para suas estruturas e métodos Go
+- Diálogos e menus nativos
+- Suporte nativo ao modo escuro/claro
+- Suporta translucidez moderna e efeitos de "janela fosca"
+- Sistema de eventos unificado entre Go e JavaScript
+- Poderosa ferramenta cli para gerar e construir rapidamente seus projetos
+- Multiplataforma
+- Usa mecanismos de renderização nativos - _sem navegador incorporado_!
+
+### Plano de trabalho
+
+O plano de trabalho do projeto pode ser encontrado [aqui](https://github.com/wailsapp/wails/discussions/1484). Por favor consulte
+isso antes de abrir um pedido de melhoria.
+
+## Iniciando
+
+As instruções de instalação estão no [site oficial](https://wails.io/docs/gettingstarted/installation).
+
+## Patrocinadores
+
+Este projeto é apoiado por estas simpáticas pessoas/empresas:
+
+
+
+
+
+
+## Perguntas frequentes
+
+- Esta é uma alternativa ao Electron?
+
+ Depende de seus requisitos. Ele foi projetado para tornar mais fácil para os programadores Go criar aplicações desktop
+ e adicionar um front-end aos seus aplicativos existentes. O Wails oferece elementos nativos, como menus
+ e diálogos, por isso pode ser considerada uma alternativa leve, se comparado ao Electron.
+
+- A quem se destina este projeto?
+
+ Programadores Go que desejam agrupar um front-end HTML/JS/CSS com seus aplicativos, sem recorrer à criação de um
+ servidor e abrir um navegador para visualizá-lo.
+
+- Qual é o significado do nome?
+
+ Quando vi o WebView, pensei "O que eu realmente quero é ferramentas para construir um aplicativo WebView, algo semelhante ao que Rails é para Ruby". Portanto, inicialmente era um jogo de palavras (WebView on Rails). Por acaso, também era um homófono do
+ Nome em inglês para o [país](https://en.wikipedia.org/wiki/Wales) de onde eu sou. Então ficou com esse nome.
+
+## Estrelas ao longo do tempo
+
+[](https://star-history.com/#wailsapp/wails&Date)
+
+## Colaboradores
+
+A lista de colaboradores está ficando grande demais para o arquivo readme! Todas as pessoas incríveis que contribuíram para o
+projeto tem sua própria página [aqui](https://wails.io/credits#contributors).
+
+## Licença
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Inspiração
+
+Este projeto foi construído ouvindo esses álbuns:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.ru.md b/README.ru.md
new file mode 100644
index 000000000..76fa59d07
--- /dev/null
+++ b/README.ru.md
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Собирайте Desktop приложения используя Go и Web технологии
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## Содержание
+
+- [Содержание](#содержание)
+- [Вступление](#вступление)
+- [Особенности](#особенности)
+ - [Roadmap](#roadmap)
+- [Быстрый старт](#быстрый-старт)
+- [Спонсоры](#спонсоры)
+- [FAQ](#faq)
+- [График звёздочек](#график-звёздочек-репозитория-относительно-времени)
+- [Контребьюторы](#контребьюторы)
+- [Лицензия](#лицензия)
+- [Вдохновение](#вдохновение)
+
+## Вступление
+
+Обычно, веб-интерфейсы для программ Go - это встроенный веб-сервер и веб-браузер.
+У Walls другой подход: он оборачивает как код Go, так и веб-интерфейс в один бинарник (EXE файл).
+Облегчает вам создание вашего приложения, управляя созданием, компиляцией и объединением проектов.
+Все ограничивается лишь вашей фантазией!
+
+## Особенности
+
+- Использование Go для backend
+- Поддержка любой frontend технологии, с которой вы уже знакомы для создания вашего UI
+- Быстрое создание frontend для ваших программ, используя готовые шаблоны
+- Очень лёгкий вызов функций Go из JavaScript
+- Автогенерация TypeScript типов для Go структур и функций
+- Нативные диалоги и меню
+- Нативная поддержка тёмной и светлой темы
+- Поддержка современных эффектов прозрачности и "матового окна"
+- Единая система эвентов для Go и JavaScript
+- Мощный CLI для быстрого создания ваших проектов
+- Мультиплатформенность
+- Использование нативного движка рендеринга - нет встроенному браузеру!
+
+### Roadmap
+
+Roadmap проекта вы можете найти [здесь](https://github.com/wailsapp/wails/discussions/1484).
+Пожалуйста, проконсультируйтесь перед предложением улучшения.
+
+## Быстрый старт
+
+Инструкции по установке находятся на [официальном сайте](https://wails.io/docs/gettingstarted/installation).
+
+## Спонсоры
+
+Проект поддерживается этими добрыми людьми / компаниями:
+
+
+
+
+
+
+## FAQ
+
+- Это альтернатива Electron?
+
+ Зависит от ваших требований. Wails разработан для легкого создания Desktop приложений или
+ расширения интерфейсной части существующих приложений для программистов на Go. Wails действительно
+ предлагает встроенные элементы, такие как меню и диалоги, так что его можно считать облегченной альтернативой Electron.
+
+- Для кого предназначен этот проект?
+
+ Для Golang программистов, которые хотят создавать приложения, используя HTML, JS и CSS,
+ без создания веб-сервера и открытия браузера для их просмотра.
+
+- Что это за название?
+
+ Когда я увидел WebView, я подумал: "Что мне действительно нужно, так это инструменты для создания приложения WebView,
+ немного похожие на Rails для Ruby". Изначально это была игра слов (Webview on Rails). Просто так получилось, что это
+ также омофон английского названия для [Страны](https://en.wikipedia.org/wiki/Wales) от куда я родом. Так что это прижилось.
+
+## График звёздочек репозитория по времени
+
+[](https://star-history.com/#wailsapp/wails&Date)
+
+## Контрибьюторы
+
+Список участников слишком велик для README! У всех замечательных людей, которые внесли свой вклад в этот
+проект, есть своя [страничка](https://wails.io/credits#contributors).
+
+## Лицензия
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Вдохновение
+
+Этот проект был создан, в основном, под эти альбомы:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.tr.md b/README.tr.md
new file mode 100644
index 000000000..e9b16ca76
--- /dev/null
+++ b/README.tr.md
@@ -0,0 +1,156 @@
+
+
+
+
+
+ Go ve Web Teknolojilerini kullanarak masaüstü uygulamaları oluşturun.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## İçerik
+
+- [İçerik](#içerik)
+- [Giriş](#giriş)
+- [Özellikler](#özellikler)
+ - [Yol Haritası](#yol-haritası)
+- [Başlarken](#başlarken)
+- [Sponsorlar](#sponsorlar)
+- [Sıkça sorulan sorular](#sıkça-sorulan-sorular)
+- [Zaman içinda yıldızlayanlar](#zaman-içinde-yıldızlayanlar)
+- [Katkıda bulunanlar](#katkıda-bulunanlar)
+- [Lisans](#lisans)
+- [İlham](#ilham)
+
+## Giriş
+
+Go programlarına web arayüzleri sağlamak için geleneksel yöntem, yerleşik bir web sunucusu kullanmaktır. Wails, farklı bir yaklaşım sunar: Hem Go kodunu hem de bir web ön yüzünü tek bir ikili dosyada paketleme yeteneği sağlar. Proje oluşturma, derleme ve paketleme işlemlerini kolaylaştıran araçlar sunar. Tek yapmanız gereken yaratıcı olmaktır!
+
+## Özellikler
+
+- Backend için standart Go kullanın
+- Kullanıcı arayüzünüzü oluşturmak için zaten aşina olduğunuz herhangi bir frontend teknolojisini kullanın
+- Hazır şablonlar kullanarak Go programlarınız için hızlıca zengin ön yüzler oluşturun
+- Javascript'ten Go metodlarını kolayca çağırın
+- Go yapı ve metodlarınız için otomatik oluşturulan Typescript tanımları
+- Yerel Diyaloglar ve Menüler
+- Yerel Karanlık / Aydınlık mod desteği
+- Modern saydamlık ve "buzlu cam" efektlerini destekler
+- Go ve Javascript arasında birleşik olay sistemi
+- Projelerinizi hızlıca oluşturmak ve derlemek için güçlü bir komut satırı aracı
+- Çoklu platform desteği
+- Yerel render motorlarını kullanır - _gömülü tarayıcı yok_!
+
+
+### Yol Haritesı
+
+Proje yol haritasına [buradan](https://github.com/wailsapp/wails/discussions/1484) ulaşabilirsiniz. Lütfen bir iyileştirme talebi oluşturmadan önce danışın.
+
+
+## Başlarken
+
+Kurulum talimatları [resmi web sitesinde](https://wails.io/docs/gettingstarted/installation) bulunmaktadır.
+
+
+## Sponsorlar
+
+Bu proje, aşağıdaki nazik insanlar / şirketler tarafından desteklenmektedir:
+
+
+
+
+
+
+## Sıkça Sorulan Sorular
+
+- Bu Electron'a alternatif mi?
+
+ Gereksinimlerinize bağlıdır. Go programcılarının hafif masaüstü uygulamaları yapmasını veya mevcut uygulamalarına bir ön yüz eklemelerini kolaylaştırmak için tasarlanmıştır. Wails, menüler ve diyaloglar gibi yerel öğeler sunduğundan, hafif bir Electron alternatifi olarak kabul edilebilir.
+
+- Bu proje kimlere yöneliktir?
+
+ HTML/JS/CSS ön yüzünü uygulamalarıyla birlikte paketlemek isteyen, ancak bir sunucu oluşturup bir tarayıcı açmaya başvurmadan bunu yapmak isteyen Go programcıları için.
+
+- İsmin anlamı nedir?
+
+ WebView'i gördüğümde, "Aslında istediğim şey, WebView uygulaması oluşturmak için araçlar, biraz Rails'in Ruby için olduğu gibi" diye düşündüm. Bu nedenle başlangıçta kelime oyunu (Rails üzerinde Webview) olarak ortaya çıktı. Ayrıca, benim geldiğim [ülkenin](https://en.wikipedia.org/wiki/Wales) İngilizce adıyla homofon olması tesadüf oldu. Bu yüzden bu isim kaldı.
+
+
+## Zaman içinda yıldızlayanlar
+
+
+
+
+
+
+
+
+
+## Katkıda Bulunanlar
+
+Katkıda bulunanların listesi, README için çok büyük hale geldi! Bu projeye katkıda bulunan tüm harika insanların kendi sayfaları [burada](https://wails.io/credits#contributors) bulunmaktadır.
+
+
+## Lisans
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## İlham
+
+Bu proje esas olarak aşağıdaki albümler dinlenilerek kodlandı:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
+
diff --git a/README.uz.md b/README.uz.md
new file mode 100644
index 000000000..807262405
--- /dev/null
+++ b/README.uz.md
@@ -0,0 +1,159 @@
+
+
+
+
+
+ Go va Web texnologiyalaridan foydalangan holda ish stoli ilovalarini yarating
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
+
+
+
+
+
+## Tarkib
+
+- [Tarkib](#tarkib)
+- [Kirish](#kirish)
+- [Xususiyatlari](#xususiyatlari)
+ - [Yo'l xaritasi](#yol-xaritasi)
+- [Ishni boshlash](#ishni-boshlash)
+- [Homiylar](#homiylar)
+- [FAQ](#faq)
+- [Vaqt o'tishi bilan yulduzlar](#vaqt-otishi-bilan-yulduzlar)
+- [Ishtirokchilar](#homiylar)
+- [Litsenziya](#litsenziya)
+- [Ilhomlanish](#ilhomlanish)
+
+## Kirish
+
+Odatda, Go dasturlari uchun veb-interfeyslar o'rnatilgan veb-server va veb-brauzerdir.
+Walls boshqacha yondashuvni qo'llaydi: u Go kodini ham, veb-interfeysni ham bitta ikkilik (e.g: EXE)fayliga o'raydi.
+Loyihalarni yaratish, kompilyatsiya qilish va birlashtirishni boshqarish orqali ilovangizni yaratishni osonlashtiradi.
+Hamma narsa faqat sizning tasavvuringiz bilan cheklangan!
+
+## Xususiyatlari
+
+- Backend uchun standart Go dan foydalaning
+- UI yaratish uchun siz allaqachon tanish bo'lgan har qanday frontend texnologiyasidan foydalaning
+- Oldindan tayyorlangan shablonlardan foydalanib, Go dasturlaringiz uchun tezda boy frontendlarni yarating
+- Javascriptdan Go methodlarini osongina chaqiring
+- Go struktura va methodlari uchun avtomatik yaratilgan Typescript ta'riflari
+- Mahalliy Dialoglar va Menyular
+- Mahalliy Dark / Light rejimini qo'llab-quvvatlash
+- Zamonaviy shaffoflik va "muzli oyna" effektlarini qo'llab-quvvatlaydi
+- Go va Javascript o'rtasidagi yagona hodisa tizimi
+- Loyihalaringizni tezda yaratish va qurish uchun kuchli cli vositasi
+- Ko'p platformali
+- Mahalliy renderlash mexanizmlaridan foydalanadi - _o'rnatilgan brauzer yo'q_!
+
+### Yo'l xaritasi
+
+Loyihaning yoʻl xaritasini [bu yerdan](https://github.com/wailsapp/wails/discussions/1484) topish mumkin. Iltimos, maslahatlashing
+Buni yaxshilash so'rovini ochishdan oldin.
+
+## Ishni boshlash
+
+O'rnatish bo'yicha ko'rsatmalar [Rasmiy veb saytda](https://wails.io/docs/gettingstarted/installation) mavjud.
+
+## Homiylar
+
+Ushbu loyiha quyidagi mehribon odamlar / kompaniyalar tomonidan qo'llab-quvvatlanadi:
+
+
+
+
+
+
+## FAQ
+
+- Bu Elektronga muqobilmi?
+
+ Sizning talablaringizga bog'liq. Bu Go dasturchilariga yengil ish stoli yaratishni osonlashtirish uchun yaratilgan
+ ilovalar yoki ularning mavjud ilovalariga frontend qo'shing. Wails menyular kabi mahalliy elementlarni taklif qiladi
+ va dialoglar, shuning uchun uni yengil elektron muqobili deb hisoblash mumkin.
+
+- Ushbu loyiha kimlar uchun?
+
+ Server yaratmasdan va uni ko'rish uchun brauzerni ochmasdan, o'z ilovalari bilan HTML/JS/CSS orqali frontendini birlashtirmoqchi bo'lgan dasturchilar uchun.
+
+- Bu qanday nom?
+
+ Men WebViewni ko'rganimda, men shunday deb o'yladim: "Menga WebView ilovasini yaratish uchun vositalar kerak.
+ biroz Rails for Rubyga o'xshaydi." Demak, dastlab bu so'zlar ustida o'yin edi (Railsda Webview). Shunday bo'ldi.
+ u men kelgan [Mamlakat](https://en.wikipedia.org/wiki/Wales)ning inglizcha nomining omofonidir.
+
+## Vaqt o'tishi bilan yulduzlar
+
+
+
+
+
+
+
+
+
+## Ishtirokchilar
+
+Ishtirokchilar roʻyxati oʻqish uchun juda kattalashib bormoqda! Bunga hissa qo'shgan barcha ajoyib odamlarning
+loyihada o'z sahifasi bor [bu yerga](https://wails.io/credits#contributors).
+
+## Litsenziya
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Ilhomlanish
+
+Ushbu loyiha asosan quyidagi albomlar uchun kodlangan:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.zh-Hans.md b/README.zh-Hans.md
index 072ff5749..4c09d0c45 100644
--- a/README.zh-Hans.md
+++ b/README.zh-Hans.md
@@ -26,8 +26,8 @@
-
-
+
+
@@ -42,7 +42,10 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md) · [Português](README.pt-br.md) ·
+[Русский](README.ru.md) · [Francais](README.fr.md) · [Uzbek](README.uz.md) · [Deutsch](README.de.md) ·
+[Türkçe](README.tr.md)
@@ -57,6 +60,7 @@
- [快速入门](#快速入门)
- [赞助商](#赞助商)
- [常见问题](#常见问题)
+- [星星增长趋势](#星星增长趋势)
- [贡献者](#贡献者)
- [许可证](#许可证)
- [灵感](#灵感)
@@ -86,7 +90,7 @@
## 快速入门
-使用说明在 [官网](https://wails.io/docs/gettingstarted/installation)。
+使用说明在 [官网](https://wails.io/zh-Hans/docs/gettingstarted/installation/)。
## 赞助商
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..cb096f872
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,38 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+| ------- | ------------------ |
+| 2.x.x | :white_check_mark: |
+| 3.0.x-alpha | :x: |
+
+
+## Reporting a Vulnerability
+
+If you believe you have found a security vulnerability in our project, we encourage you to let us know right away.
+We will investigate all legitimate reports and do our best to quickly fix the problem.
+
+Before reporting though, please review our security policy below.
+
+### How to Report
+
+To report a security vulnerability, please use GitHub's [private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability) feature. If possible, please include as much information as possible.
+This may include steps to reproduce, impact of the vulnerability, and anything else you believe would help us understand the problem.
+**Please do not include any sensitive or personal information in your report**.
+
+### What to Expect
+
+When you report a vulnerability, here's what you can expect:
+
+- **Acknowledgement**: We will acknowledge your email within 48 hours, and you'll receive a more detailed response to your email within 72 hours indicating the next steps in handling your report.
+
+- **Updates**: After the initial reply to your report, our team will keep you informed of the progress being made towards a fix and full announcement. These updates will be sent at least once a week.
+
+- **Confidentiality**: We will maintain strict confidentiality of your report until the security issue is resolved.
+
+- **Issue Resolution**: If the issue is confirmed, we will release a patch as soon as possible depending on complexity of the fix.
+
+- **Recognition**: We recognize and appreciate every individual who helps us identify and fix vulnerabilities in our project. While we do not currently have a bounty program, we would be happy to publicly acknowledge your responsible disclosure.
+
+We strive to make Wails safe for everyone, and we greatly appreciate the assistance of security researchers and users in helping us identify and fix vulnerabilities. Thank you for your contribution to the security of this project.
diff --git a/Taskfile.yaml b/Taskfile.yaml
new file mode 100644
index 000000000..7cc165825
--- /dev/null
+++ b/Taskfile.yaml
@@ -0,0 +1,47 @@
+# https://taskfile.dev
+
+version: "3"
+
+includes:
+ website:
+ taskfile: website
+ dir: website
+
+ v2:
+ taskfile: v2
+ dir: v2
+ optional: true
+ v3:
+ taskfile: v3
+ dir: v3
+ optional: true
+
+tasks:
+ contributors:check:
+ cmds:
+ - npx -y all-contributors-cli check
+
+ contributors:update:
+ cmds:
+ - go run v3/tasks/contribs/main.go
+
+ contributors:build:
+ cmds:
+ - npx -y all-contributors-cli generate
+
+ format:md:
+ cmds:
+ - npx prettier --write "**/*.md"
+
+ format:
+ cmds:
+ - task: format:md
+
+ format-all-md:
+ cmds:
+ - task: format:md
+ - task: website:format:md
+ - task: v2:format:md
+ # - task: v2:website:format
+ - task: v3:format:md
+ # - task: v3:website:format:md
diff --git a/app.go b/app.go
deleted file mode 100644
index 95a8a7e82..000000000
--- a/app.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package wails
-
-import (
- "os"
- "syscall"
-
- "github.com/syossan27/tebata"
- "github.com/wailsapp/wails/cmd"
- "github.com/wailsapp/wails/lib/binding"
- "github.com/wailsapp/wails/lib/event"
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/ipc"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/renderer"
- wailsruntime "github.com/wailsapp/wails/runtime"
-)
-
-// -------------------------------- Compile time Flags ------------------------------
-
-// BuildMode indicates what mode we are in
-var BuildMode = cmd.BuildModeProd
-
-// Runtime is the Go Runtime struct
-type Runtime = wailsruntime.Runtime
-
-// Store is a state store used for syncing with
-// the front end
-type Store = wailsruntime.Store
-
-// CustomLogger is a specialised logger
-type CustomLogger = logger.CustomLogger
-
-// ----------------------------------------------------------------------------------
-
-// App defines the main application struct
-type App struct {
- config *AppConfig // The Application configuration object
- cli *cmd.Cli // In debug mode, we have a cli
- renderer interfaces.Renderer // The renderer is what we will render the app to
- logLevel string // The log level of the app
- ipc interfaces.IPCManager // Handles the IPC calls
- log *logger.CustomLogger // Logger
- bindingManager interfaces.BindingManager // Handles binding of Go code to renderer
- eventManager interfaces.EventManager // Handles all the events
- runtime interfaces.Runtime // The runtime object for registered structs
-}
-
-// CreateApp creates the application window with the given configuration
-// If none given, the defaults are used
-func CreateApp(optionalConfig ...*AppConfig) *App {
- var userConfig *AppConfig
- if len(optionalConfig) > 0 {
- userConfig = optionalConfig[0]
- }
-
- result := &App{
- logLevel: "debug",
- renderer: renderer.NewWebView(),
- ipc: ipc.NewManager(),
- bindingManager: binding.NewManager(),
- eventManager: event.NewManager(),
- log: logger.NewCustomLogger("App"),
- }
-
- appconfig, err := newConfig(userConfig)
- if err != nil {
- result.log.Fatalf("Cannot use custom HTML: %s", err.Error())
- }
- result.config = appconfig
-
- // Set up the CLI if not in release mode
- if BuildMode != cmd.BuildModeProd {
- result.cli = result.setupCli()
- } else {
- // Disable Inspector in release mode
- result.config.DisableInspector = true
- }
-
- // Platform specific init
- platformInit()
-
- return result
-}
-
-// Run the app
-func (a *App) Run() error {
-
- if BuildMode != cmd.BuildModeProd {
- return a.cli.Run()
- }
-
- a.logLevel = "error"
- err := a.start()
- if err != nil {
- a.log.Error(err.Error())
- }
- return err
-}
-
-func (a *App) start() error {
-
- // Set the log level
- logger.SetLogLevel(a.logLevel)
-
- // Log starup
- a.log.Info("Starting")
-
- // Check if we are to run in bridge mode
- if BuildMode == cmd.BuildModeBridge {
- a.renderer = renderer.NewBridge()
- }
-
- // Initialise the renderer
- err := a.renderer.Initialise(a.config, a.ipc, a.eventManager)
- if err != nil {
- return err
- }
-
- // Start signal handler
- t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
- t.Reserve(func() {
- a.log.Debug("SIGNAL CAUGHT! Starting Shutdown")
- a.renderer.Close()
- })
-
- // Start event manager and give it our renderer
- a.eventManager.Start(a.renderer)
-
- // Start the IPC Manager and give it the event manager and binding manager
- a.ipc.Start(a.eventManager, a.bindingManager)
-
- // Create the runtime
- a.runtime = wailsruntime.NewRuntime(a.eventManager, a.renderer)
-
- // Start binding manager and give it our renderer
- err = a.bindingManager.Start(a.renderer, a.runtime)
- if err != nil {
- return err
- }
-
- // Defer the shutdown
- defer a.shutdown()
-
- // Run the renderer
- err = a.renderer.Run()
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// shutdown the app
-func (a *App) shutdown() {
- // Make sure this is only called once
- a.log.Debug("Shutting down")
-
- // Shutdown Binding Manager
- a.bindingManager.Shutdown()
-
- // Shutdown IPC Manager
- a.ipc.Shutdown()
-
- // Shutdown Event Manager
- a.eventManager.Shutdown()
-
- a.log.Debug("Cleanly Shutdown")
-}
-
-// Bind allows the user to bind the given object
-// with the application
-func (a *App) Bind(object interface{}) {
- a.bindingManager.Bind(object)
-}
diff --git a/app_other.go b/app_other.go
deleted file mode 100644
index 9e0514350..000000000
--- a/app_other.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build linux || darwin || !windows
-// +build linux darwin !windows
-
-package wails
-
-func platformInit() {
-
-}
diff --git a/app_windows.go b/app_windows.go
deleted file mode 100644
index cf9472731..000000000
--- a/app_windows.go
+++ /dev/null
@@ -1,28 +0,0 @@
-//go:build windows || !linux || !darwin
-// +build windows !linux !darwin
-
-package wails
-
-import (
- "fmt"
- "log"
- "syscall"
-)
-
-func platformInit() {
- err := SetProcessDPIAware()
- if err != nil {
- log.Fatalf(err.Error())
- }
-}
-
-// SetProcessDPIAware via user32.dll
-// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiaware
-// Also, thanks Jack Mordaunt! https://github.com/wailsapp/wails/issues/293
-func SetProcessDPIAware() error {
- status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
- if status == 0 {
- return fmt.Errorf("exit status %d: %v %v", status, r, err)
- }
- return nil
-}
diff --git a/cli.go b/cli.go
deleted file mode 100644
index 1a26f68d9..000000000
--- a/cli.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package wails
-
-import (
- "github.com/wailsapp/wails/cmd"
-)
-
-// setupCli creates a new cli handler for the application
-func (app *App) setupCli() *cmd.Cli {
-
- // Create a new cli
- result := cmd.NewCli(app.config.Title, "Debug build")
- result.Version(cmd.Version)
-
- // Setup cli to handle loglevel
- result.
- StringFlag("loglevel", "Sets the log level [debug|info|error|panic|fatal]. Default debug", &app.logLevel).
- Action(app.start)
-
- // Banner
- result.PreRun(func(cli *cmd.Cli) error {
- log := cmd.NewLogger()
- log.YellowUnderline(app.config.Title + " - Debug Build")
- return nil
- })
-
- return result
-}
diff --git a/cmd/build.go b/cmd/build.go
deleted file mode 100644
index 945fbfc78..000000000
--- a/cmd/build.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package cmd
-
-const (
- // BuildModeProd indicates we are building for prod mode
- BuildModeProd = "prod"
- // BuildModeDebug indicates we are building for debug mode
- BuildModeDebug = "debug"
- // BuildModeBridge indicates we are building for bridge mode
- BuildModeBridge = "bridge"
-)
diff --git a/cmd/cli.go b/cmd/cli.go
deleted file mode 100644
index d52a44513..000000000
--- a/cmd/cli.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package cmd
-
-import (
- "flag"
- "fmt"
- "os"
- "strings"
-)
-
-// NewCli - Creates a new Cli application object
-func NewCli(name, description string) *Cli {
- result := &Cli{}
- result.rootCommand = NewCommand(name, description, result, "")
- result.log = NewLogger()
- return result
-}
-
-// Cli - The main application object
-type Cli struct {
- rootCommand *Command
- defaultCommand *Command
- preRunCommand func(*Cli) error
- log *Logger
-}
-
-// Version - Set the Application version string
-func (c *Cli) Version(version string) {
- c.rootCommand.AppVersion = version
-}
-
-// PrintHelp - Prints the application's help
-func (c *Cli) PrintHelp() {
- c.rootCommand.PrintHelp()
-}
-
-// Run - Runs the application with the given arguments
-func (c *Cli) Run(args ...string) error {
- if c.preRunCommand != nil {
- err := c.preRunCommand(c)
- if err != nil {
- return err
- }
- }
- if len(args) == 0 {
- args = os.Args[1:]
- }
- return c.rootCommand.Run(args)
-}
-
-// DefaultCommand - Sets the given command as the command to run when
-// no other commands given
-func (c *Cli) DefaultCommand(defaultCommand *Command) *Cli {
- c.defaultCommand = defaultCommand
- return c
-}
-
-// Command - Adds a command to the application
-func (c *Cli) Command(name, description string) *Command {
- return c.rootCommand.Command(name, description)
-}
-
-// PreRun - Calls the given function before running the specific command
-func (c *Cli) PreRun(callback func(*Cli) error) {
- c.preRunCommand = callback
-}
-
-// BoolFlag - Adds a boolean flag to the root command
-func (c *Cli) BoolFlag(name, description string, variable *bool) *Command {
- c.rootCommand.BoolFlag(name, description, variable)
- return c.rootCommand
-}
-
-// StringFlag - Adds a string flag to the root command
-func (c *Cli) StringFlag(name, description string, variable *string) *Command {
- c.rootCommand.StringFlag(name, description, variable)
- return c.rootCommand
-}
-
-// Action represents a function that gets calls when the command is called by
-// the user
-type Action func() error
-
-// Command represents a command that may be run by the user
-type Command struct {
- Name string
- CommandPath string
- Shortdescription string
- Longdescription string
- AppVersion string
- SubCommands []*Command
- SubCommandsMap map[string]*Command
- longestSubcommand int
- ActionCallback Action
- App *Cli
- Flags *flag.FlagSet
- flagCount int
- log *Logger
- helpFlag bool
- hidden bool
-}
-
-// NewCommand creates a new Command
-func NewCommand(name string, description string, app *Cli, parentCommandPath string) *Command {
- result := &Command{
- Name: name,
- Shortdescription: description,
- SubCommandsMap: make(map[string]*Command),
- App: app,
- log: NewLogger(),
- hidden: false,
- }
-
- // Set up command path
- if parentCommandPath != "" {
- result.CommandPath += parentCommandPath + " "
- }
- result.CommandPath += name
-
- // Set up flag set
- result.Flags = flag.NewFlagSet(result.CommandPath, flag.ContinueOnError)
- result.BoolFlag("help", "Get help on the '"+result.CommandPath+"' command.", &result.helpFlag)
-
- // result.Flags.Usage = result.PrintHelp
-
- return result
-}
-
-// parseFlags parses the given flags
-func (c *Command) parseFlags(args []string) error {
- // Parse flags
- tmp := os.Stderr
- os.Stderr = nil
- err := c.Flags.Parse(args)
- os.Stderr = tmp
- if err != nil {
- fmt.Printf("Error: %s\n\n", err.Error())
- c.PrintHelp()
- }
- return err
-}
-
-// Run - Runs the Command with the given arguments
-func (c *Command) Run(args []string) error {
-
- // If we have arguments, process them
- if len(args) > 0 {
- // Check for subcommand
- subcommand := c.SubCommandsMap[args[0]]
- if subcommand != nil {
- return subcommand.Run(args[1:])
- }
-
- // Parse flags
- err := c.parseFlags(args)
- if err != nil {
- fmt.Printf("Error: %s\n\n", err.Error())
- c.PrintHelp()
- return err
- }
-
- // Help takes precedence
- if c.helpFlag {
- c.PrintHelp()
- return nil
- }
- }
-
- // Do we have an action?
- if c.ActionCallback != nil {
- return c.ActionCallback()
- }
-
- // If we haven't specified a subcommand
- // check for an app level default command
- if c.App.defaultCommand != nil {
- // Prevent recursion!
- if c.App.defaultCommand != c {
- // only run default command if no args passed
- if len(args) == 0 {
- return c.App.defaultCommand.Run(args)
- }
- }
- }
-
- // Nothing left we can do
- c.PrintHelp()
-
- return nil
-}
-
-// Action - Define an action from this command
-func (c *Command) Action(callback Action) *Command {
- c.ActionCallback = callback
- return c
-}
-
-// PrintHelp - Output the help text for this command
-func (c *Command) PrintHelp() {
- c.log.PrintBanner()
-
- commandTitle := c.CommandPath
- if c.Shortdescription != "" {
- commandTitle += " - " + c.Shortdescription
- }
- // Ignore root command
- if c.CommandPath != c.Name {
- c.log.Yellow(commandTitle)
- }
- if c.Longdescription != "" {
- fmt.Println()
- fmt.Println(c.Longdescription + "\n")
- }
- if len(c.SubCommands) > 0 {
- c.log.White("Available commands:")
- fmt.Println("")
- for _, subcommand := range c.SubCommands {
- if subcommand.isHidden() {
- continue
- }
- spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
- isDefault := ""
- if subcommand.isDefaultCommand() {
- isDefault = "[default]"
- }
- fmt.Printf(" %s%s%s %s\n", subcommand.Name, spacer, subcommand.Shortdescription, isDefault)
- }
- fmt.Println("")
- }
- if c.flagCount > 0 {
- c.log.White("Flags:")
- fmt.Println()
- c.Flags.SetOutput(os.Stdout)
- c.Flags.PrintDefaults()
- c.Flags.SetOutput(os.Stderr)
-
- }
- fmt.Println()
-}
-
-// isDefaultCommand returns true if called on the default command
-func (c *Command) isDefaultCommand() bool {
- return c.App.defaultCommand == c
-}
-
-// isHidden returns true if the command is a hidden command
-func (c *Command) isHidden() bool {
- return c.hidden
-}
-
-// Hidden hides the command from the Help system
-func (c *Command) Hidden() {
- c.hidden = true
-}
-
-// Command - Defines a subcommand
-func (c *Command) Command(name, description string) *Command {
- result := NewCommand(name, description, c.App, c.CommandPath)
- result.log = c.log
- c.SubCommands = append(c.SubCommands, result)
- c.SubCommandsMap[name] = result
- if len(name) > c.longestSubcommand {
- c.longestSubcommand = len(name)
- }
- return result
-}
-
-// BoolFlag - Adds a boolean flag to the command
-func (c *Command) BoolFlag(name, description string, variable *bool) *Command {
- c.Flags.BoolVar(variable, name, *variable, description)
- c.flagCount++
- return c
-}
-
-// StringFlag - Adds a string flag to the command
-func (c *Command) StringFlag(name, description string, variable *string) *Command {
- c.Flags.StringVar(variable, name, *variable, description)
- c.flagCount++
- return c
-}
-
-// LongDescription - Sets the long description for the command
-func (c *Command) LongDescription(Longdescription string) *Command {
- c.Longdescription = Longdescription
- return c
-}
diff --git a/cmd/fs.go b/cmd/fs.go
deleted file mode 100644
index 030c6546f..000000000
--- a/cmd/fs.go
+++ /dev/null
@@ -1,240 +0,0 @@
-package cmd
-
-import (
- "bytes"
- "crypto/md5"
- "encoding/json"
- "fmt"
- "io"
- "log"
- "os"
- "path"
- "path/filepath"
- "runtime"
- "strings"
-
- "github.com/leaanthony/slicer"
-)
-
-// FSHelper - Wrapper struct for File System utility commands
-type FSHelper struct {
-}
-
-// NewFSHelper - Returns a new FSHelper
-func NewFSHelper() *FSHelper {
- result := &FSHelper{}
- return result
-}
-
-// DirExists - Returns true if the given path resolves to a directory on the filesystem
-func (fs *FSHelper) DirExists(path string) bool {
- fi, err := os.Lstat(path)
- if err != nil {
- return false
- }
-
- return fi.Mode().IsDir()
-}
-
-// FileExists returns a boolean value indicating whether
-// the given file exists
-func (fs *FSHelper) FileExists(path string) bool {
- fi, err := os.Lstat(path)
- if err != nil {
- return false
- }
-
- return fi.Mode().IsRegular()
-}
-
-// FindFile returns the first occurrence of match inside path.
-func (fs *FSHelper) FindFile(path, match string) (string, error) {
- files, err := os.ReadDir(path)
- if err != nil {
- return "", err
- }
-
- for _, f := range files {
- if !f.IsDir() && strings.Contains(f.Name(), match) {
- return f.Name(), nil
- }
- }
-
- return "", fmt.Errorf("file not found")
-}
-
-// CreateFile creates a file at the given filename location with the contents
-// set to the given data. It will create intermediary directories if needed.
-func (fs *FSHelper) CreateFile(filename string, data []byte) error {
- // Ensure directory exists
- fs.MkDirs(filepath.Dir(filename))
- return os.WriteFile(filename, data, 0644)
-}
-
-// MkDirs creates the given nested directories.
-// Returns error on failure
-func (fs *FSHelper) MkDirs(fullPath string, mode ...os.FileMode) error {
- var perms os.FileMode
- perms = 0700
- if len(mode) == 1 {
- perms = mode[0]
- }
- return os.MkdirAll(fullPath, perms)
-}
-
-// CopyFile from source to target
-func (fs *FSHelper) CopyFile(source, target string) error {
- s, err := os.Open(source)
- if err != nil {
- return err
- }
- defer s.Close()
- d, err := os.Create(target)
- if err != nil {
- return err
- }
- if _, err := io.Copy(d, s); err != nil {
- d.Close()
- return err
- }
- return d.Close()
-}
-
-// Cwd returns the current working directory
-// Aborts on Failure
-func (fs *FSHelper) Cwd() string {
- cwd, err := os.Getwd()
- if err != nil {
- log.Fatal("Unable to get working directory!")
- }
- return cwd
-}
-
-// RemoveFile removes the given filename
-func (fs *FSHelper) RemoveFile(filename string) error {
- return os.Remove(filename)
-}
-
-// RemoveFiles removes the given filenames
-func (fs *FSHelper) RemoveFiles(files []string, continueOnError bool) error {
- for _, filename := range files {
- err := os.Remove(filename)
- if err != nil && !continueOnError {
- return err
- }
- }
- return nil
-}
-
-// Dir holds information about a directory
-type Dir struct {
- localPath string
- fullPath string
-}
-
-// Directory creates a new Dir struct with the given directory path
-func (fs *FSHelper) Directory(dir string) (*Dir, error) {
- fullPath, err := filepath.Abs(dir)
- return &Dir{fullPath: fullPath}, err
-}
-
-// LocalDir creates a new Dir struct based on a path relative to the caller
-func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
- _, filename, _, _ := runtime.Caller(1)
- fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), dir))
- return &Dir{
- localPath: dir,
- fullPath: fullPath,
- }, err
-}
-
-// GetSubdirs will return a list of FQPs to subdirectories in the given directory
-func (d *Dir) GetSubdirs() (map[string]string, error) {
-
- // Read in the directory information
- fileInfo, err := os.ReadDir(d.fullPath)
- if err != nil {
- return nil, err
- }
-
- // Allocate space for the list
- subdirs := make(map[string]string)
-
- // Pull out the directories and store in the map as
- // map["directoryName"] = "path/to/directoryName"
- for _, file := range fileInfo {
- if file.IsDir() {
- subdirs[file.Name()] = filepath.Join(d.fullPath, file.Name())
- }
- }
- return subdirs, nil
-}
-
-// GetAllFilenames returns all filename in and below this directory
-func (d *Dir) GetAllFilenames() (*slicer.StringSlicer, error) {
- result := slicer.String()
- err := filepath.Walk(d.fullPath, func(dir string, info os.FileInfo, err error) error {
- if dir == d.fullPath {
- return nil
- }
- if err != nil {
- return err
- }
-
- // Don't copy template metadata
- result.Add(dir)
-
- return nil
- })
- return result, err
-}
-
-// MkDir creates the given directory.
-// Returns error on failure
-func (fs *FSHelper) MkDir(dir string) error {
- return os.Mkdir(dir, 0700)
-}
-
-// SaveAsJSON saves the JSON representation of the given data to the given filename
-func (fs *FSHelper) SaveAsJSON(data interface{}, filename string) error {
-
- var buf bytes.Buffer
- e := json.NewEncoder(&buf)
- e.SetEscapeHTML(false)
- e.SetIndent("", " ")
- e.Encode(data)
-
- err := os.WriteFile(filename, buf.Bytes(), 0755)
- if err != nil {
- return err
- }
- return nil
-}
-
-// LoadAsString will attempt to load the given file and return
-// its contents as a string
-func (fs *FSHelper) LoadAsString(filename string) (string, error) {
- bytes, err := fs.LoadAsBytes(filename)
- return string(bytes), err
-}
-
-// LoadAsBytes returns the contents of the file as a byte slice
-func (fs *FSHelper) LoadAsBytes(filename string) ([]byte, error) {
- return os.ReadFile(filename)
-}
-
-// FileMD5 returns the md5sum of the given file
-func (fs *FSHelper) FileMD5(filename string) (string, error) {
- f, err := os.Open(filename)
- if err != nil {
- return "", err
- }
- defer f.Close()
-
- h := md5.New()
- if _, err := io.Copy(h, f); err != nil {
- return "", err
- }
-
- return fmt.Sprintf("%x", h.Sum(nil)), nil
-}
diff --git a/cmd/github.go b/cmd/github.go
deleted file mode 100644
index a048a17f4..000000000
--- a/cmd/github.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package cmd
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "sort"
-)
-
-// GitHubHelper is a utility class for interacting with GitHub
-type GitHubHelper struct {
-}
-
-// NewGitHubHelper returns a new GitHub Helper
-func NewGitHubHelper() *GitHubHelper {
- return &GitHubHelper{}
-}
-
-// GetVersionTags gets the list of tags on the Wails repo
-// It returns a list of sorted tags in descending order
-func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
-
- result := []*SemanticVersion{}
- var err error
-
- resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/releases")
- if err != nil {
- return result, err
- }
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- return result, err
- }
-
- data := []map[string]interface{}{}
- err = json.Unmarshal(body, &data)
- if err != nil {
- return result, err
- }
-
- // Convert tag data to Version structs
- for _, tag := range data {
- version := tag["name"].(string)
- semver, err := NewSemanticVersion(version)
- if err != nil {
- return result, err
- }
- result = append(result, semver)
- }
-
- // Reverse Sort
- sort.Sort(sort.Reverse(SemverCollection(result)))
-
- return result, err
-}
-
-// GetLatestStableRelease gets the latest stable release on GitHub
-func (g *GitHubHelper) GetLatestStableRelease() (result *SemanticVersion, err error) {
-
- tags, err := g.GetVersionTags()
- if err != nil {
- return nil, err
- }
-
- for _, tag := range tags {
- if tag.IsRelease() {
- return tag, nil
- }
- }
-
- return nil, fmt.Errorf("no release tag found")
-}
-
-// GetLatestPreRelease gets the latest prerelease on GitHub
-func (g *GitHubHelper) GetLatestPreRelease() (result *SemanticVersion, err error) {
-
- tags, err := g.GetVersionTags()
- if err != nil {
- return nil, err
- }
-
- for _, tag := range tags {
- if tag.IsPreRelease() {
- return tag, nil
- }
- }
-
- return nil, fmt.Errorf("no prerelease tag found")
-}
-
-// IsValidTag returns true if the given string is a valid tag
-func (g *GitHubHelper) IsValidTag(tagVersion string) (bool, error) {
- if tagVersion[0] == 'v' {
- tagVersion = tagVersion[1:]
- }
- tags, err := g.GetVersionTags()
- if err != nil {
- return false, err
- }
-
- for _, tag := range tags {
- if tag.String() == tagVersion {
- return true, nil
- }
- }
- return false, nil
-}
diff --git a/cmd/gomod.go b/cmd/gomod.go
deleted file mode 100644
index a9ca7d93c..000000000
--- a/cmd/gomod.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package cmd
-
-import (
- "fmt"
- "path/filepath"
- "regexp"
-
- "github.com/Masterminds/semver"
-)
-
-func GetWailsVersion() (*semver.Version, error) {
- var FS = NewFSHelper()
- var result *semver.Version
-
- // Load file
- var err error
- goModFile, err := filepath.Abs(filepath.Join(".", "go.mod"))
- if err != nil {
- return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
- }
- goMod, err := FS.LoadAsString(goModFile)
- if err != nil {
- return nil, fmt.Errorf("Unable to load go.mod")
- }
-
- // Find wails version
- versionRegexp := regexp.MustCompile(`.*github.com/wailsapp/wails.*(v\d+.\d+.\d+(?:-pre\d+)?)`)
- versions := versionRegexp.FindStringSubmatch(goMod)
-
- if len(versions) != 2 {
- return nil, fmt.Errorf("Unable to determine Wails version")
- }
-
- version := versions[1]
- result, err = semver.NewVersion(version)
- if err != nil {
- return nil, fmt.Errorf("Unable to parse Wails version: %s", version)
- }
- return result, nil
-
-}
-
-func GetCurrentVersion() (*semver.Version, error) {
- result, err := semver.NewVersion(Version)
- if err != nil {
- return nil, fmt.Errorf("Unable to parse Wails version: %s", Version)
- }
- return result, nil
-}
-
-func GoModOutOfSync() (bool, error) {
- gomodversion, err := GetWailsVersion()
- if err != nil {
- return true, err
- }
- currentVersion, err := GetCurrentVersion()
- if err != nil {
- return true, err
- }
- result := !currentVersion.Equal(gomodversion)
- return result, nil
-}
-
-func UpdateGoModVersion() error {
- currentVersion, err := GetCurrentVersion()
- if err != nil {
- return err
- }
- currentVersionString := currentVersion.String()
-
- requireLine := "-require=github.com/wailsapp/wails@v" + currentVersionString
-
- // Issue: go mod edit -require=github.com/wailsapp/wails@1.0.2-pre5
- helper := NewProgramHelper()
- command := []string{"go", "mod", "edit", requireLine}
- return helper.RunCommandArray(command)
-
-}
diff --git a/cmd/helpers.go b/cmd/helpers.go
deleted file mode 100644
index fdcad93a8..000000000
--- a/cmd/helpers.go
+++ /dev/null
@@ -1,542 +0,0 @@
-package cmd
-
-import (
- "fmt"
- "os"
- "os/exec"
- "os/user"
- "path/filepath"
- "runtime"
- "strconv"
- "strings"
- "time"
-
- "github.com/leaanthony/slicer"
- "github.com/leaanthony/spinner"
- wailsruntime "github.com/wailsapp/wails/runtime"
-)
-
-const xgoVersion = "1.16.3"
-
-var fs = NewFSHelper()
-
-// ValidateFrontendConfig checks if the frontend config is valid
-func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
- if projectOptions.FrontEnd.Dir == "" {
- return fmt.Errorf("Frontend directory not set in project.json")
- }
- if projectOptions.FrontEnd.Build == "" {
- return fmt.Errorf("Frontend build command not set in project.json")
- }
- if projectOptions.FrontEnd.Install == "" {
- return fmt.Errorf("Frontend install command not set in project.json")
- }
- if projectOptions.FrontEnd.Bridge == "" {
- return fmt.Errorf("Frontend bridge config not set in project.json")
- }
-
- return nil
-}
-
-// InstallGoDependencies will run go get in the current directory
-func InstallGoDependencies(verbose bool) error {
- var depSpinner *spinner.Spinner
- if !verbose {
- depSpinner = spinner.New("Ensuring Dependencies are up to date...")
- depSpinner.SetSpinSpeed(50)
- depSpinner.Start()
- }
- err := NewProgramHelper(verbose).RunCommand("go mod tidy")
- if err != nil {
- if !verbose {
- depSpinner.Error()
- }
- return err
- }
- if !verbose {
- depSpinner.Success()
- }
- return nil
-}
-
-func InitializeCrossCompilation(verbose bool) error {
- // Check Docker
- if err := CheckIfInstalled("docker"); err != nil {
- return err
- }
-
- var packSpinner *spinner.Spinner
- msg := fmt.Sprintf("Pulling wailsapp/xgo:%s docker image... (may take a while)", xgoVersion)
- if !verbose {
- packSpinner = spinner.New(msg)
- packSpinner.SetSpinSpeed(50)
- packSpinner.Start()
- } else {
- println(msg)
- }
-
- err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
- "pull", fmt.Sprintf("wailsapp/xgo:%s", xgoVersion)})
-
- if err != nil {
- if packSpinner != nil {
- packSpinner.Error()
- }
- return err
- }
- if packSpinner != nil {
- packSpinner.Success()
- }
-
- return nil
-}
-
-// BuildDocker builds the project using the cross compiling wailsapp/xgo: container
-func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
- var packSpinner *spinner.Spinner
- if buildMode == BuildModeBridge {
- return fmt.Errorf("you cant serve the application in cross-compilation")
- }
-
- // Check build directory
- buildDirectory := filepath.Join(fs.Cwd(), "build")
- if !fs.DirExists(buildDirectory) {
- err := fs.MkDir(buildDirectory)
- if err != nil {
- return err
- }
- }
-
- buildCommand := slicer.String()
- userid := 1000
- currentUser, _ := user.Current()
- if i, err := strconv.Atoi(currentUser.Uid); err == nil {
- userid = i
- }
- for _, arg := range []string{
- "docker",
- "run",
- "--rm",
- "-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
- "-v", fmt.Sprintf("%s:/source", fs.Cwd()),
- "-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
- "-e", fmt.Sprintf("FLAG_TAGS=%s", projectOptions.Tags),
- "-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
- "-e", "FLAG_V=false",
- "-e", "FLAG_X=false",
- "-e", "FLAG_RACE=false",
- "-e", "FLAG_BUILDMODE=default",
- "-e", "FLAG_TRIMPATH=false",
- "-e", fmt.Sprintf("TARGETS=%s/%s", projectOptions.Platform, projectOptions.Architecture),
- "-e", "GOPROXY=",
- "-e", "GO111MODULE=on",
- } {
- buildCommand.Add(arg)
- }
-
- if projectOptions.GoPath != "" {
- buildCommand.Add("-v")
- buildCommand.Add(fmt.Sprintf("%s:/go", projectOptions.GoPath))
- }
-
- buildCommand.Add(fmt.Sprintf("wailsapp/xgo:%s", xgoVersion))
- buildCommand.Add(".")
-
- compileMessage := fmt.Sprintf(
- "Packing + Compiling project for %s/%s using docker image wailsapp/xgo:%s",
- projectOptions.Platform, projectOptions.Architecture, xgoVersion)
-
- if buildMode == BuildModeDebug {
- compileMessage += " (Debug Mode)"
- }
-
- if !projectOptions.Verbose {
- packSpinner = spinner.New(compileMessage + "...")
- packSpinner.SetSpinSpeed(50)
- packSpinner.Start()
- } else {
- println(compileMessage)
- }
-
- err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
- if err != nil {
- if packSpinner != nil {
- packSpinner.Error()
- }
- return err
- }
- if packSpinner != nil {
- packSpinner.Success()
- }
-
- return nil
-}
-
-// BuildNative builds on the target platform itself.
-func BuildNative(binaryName string, forceRebuild bool, buildMode string, projectOptions *ProjectOptions) error {
-
- if err := CheckWindres(); err != nil {
- return err
- }
-
- compileMessage := "Packing + Compiling project"
-
- if buildMode == BuildModeDebug {
- compileMessage += " (Debug Mode)"
- }
-
- var packSpinner *spinner.Spinner
- if !projectOptions.Verbose {
- packSpinner = spinner.New(compileMessage + "...")
- packSpinner.SetSpinSpeed(50)
- packSpinner.Start()
- } else {
- println(compileMessage)
- }
-
- buildCommand := slicer.String()
- buildCommand.Add("go")
-
- buildCommand.Add("build")
-
- if binaryName != "" {
- // Alter binary name based on OS
- switch projectOptions.Platform {
- case "windows":
- if !strings.HasSuffix(binaryName, ".exe") {
- binaryName += ".exe"
- }
- default:
- if strings.HasSuffix(binaryName, ".exe") {
- binaryName = strings.TrimSuffix(binaryName, ".exe")
- }
- }
- buildCommand.Add("-o", filepath.Join("build", binaryName))
- }
-
- // If we are forcing a rebuild
- if forceRebuild {
- buildCommand.Add("-a")
- }
-
- buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
-
- if projectOptions.Tags != "" {
- buildCommand.AddSlice([]string{"--tags", projectOptions.Tags})
- }
-
- if projectOptions.Verbose {
- fmt.Printf("Command: %v\n", buildCommand.AsSlice())
- }
-
- err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
- if err != nil {
- if packSpinner != nil {
- packSpinner.Error()
- }
- return err
- }
- if packSpinner != nil {
- packSpinner.Success()
- }
-
- return nil
-}
-
-// BuildApplication will attempt to build the project based on the given inputs
-func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
- var err error
-
- if projectOptions.CrossCompile {
- if err := InitializeCrossCompilation(projectOptions.Verbose); err != nil {
- return err
- }
- }
-
- helper := NewPackageHelper(projectOptions.Platform)
-
- // Generate windows resources
- if projectOptions.Platform == "windows" {
- if err := helper.PackageWindows(projectOptions, false); err != nil {
- return err
- }
- }
-
- if projectOptions.CrossCompile {
- err = BuildDocker(binaryName, buildMode, projectOptions)
- } else {
- err = BuildNative(binaryName, forceRebuild, buildMode, projectOptions)
- }
- if err != nil {
- return err
- }
-
- if packageApp {
- err = PackageApplication(projectOptions)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// PackageApplication will attempt to package the application in a platform dependent way
-func PackageApplication(projectOptions *ProjectOptions) error {
- var packageSpinner *spinner.Spinner
- if projectOptions.Verbose {
- packageSpinner = spinner.New("Packaging application...")
- packageSpinner.SetSpinSpeed(50)
- packageSpinner.Start()
- }
-
- err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
- if err != nil {
- if packageSpinner != nil {
- packageSpinner.Error()
- }
- return err
- }
- if packageSpinner != nil {
- packageSpinner.Success()
- }
- return nil
-}
-
-// BuildFrontend runs the given build command
-func BuildFrontend(projectOptions *ProjectOptions) error {
- var buildFESpinner *spinner.Spinner
- if !projectOptions.Verbose {
- buildFESpinner = spinner.New("Building frontend...")
- buildFESpinner.SetSpinSpeed(50)
- buildFESpinner.Start()
- } else {
- println("Building frontend...")
- }
- err := NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Build)
- if err != nil {
- if buildFESpinner != nil {
- buildFESpinner.Error()
- }
- return err
- }
- if buildFESpinner != nil {
- buildFESpinner.Success()
- }
- return nil
-}
-
-// CheckWindres checks if Windres is installed and if not, aborts
-func CheckWindres() (err error) {
- if runtime.GOOS != "windows" { // FIXME: Handle windows cross-compile for windows!
- return nil
- }
- programHelper := NewProgramHelper()
- if !programHelper.IsInstalled("windres") {
- return fmt.Errorf("windres not installed. It comes by default with mingw. Ensure you have installed mingw correctly")
- }
- return nil
-}
-
-// CheckIfInstalled returns if application is installed
-func CheckIfInstalled(application string) (err error) {
- programHelper := NewProgramHelper()
- if !programHelper.IsInstalled(application) {
- return fmt.Errorf("%s not installed. Ensure you have installed %s correctly", application, application)
- }
- return nil
-}
-
-// InstallFrontendDeps attempts to install the frontend dependencies based on the given options
-func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
-
- // Install frontend deps
- err := os.Chdir(projectOptions.FrontEnd.Dir)
- if err != nil {
- return err
- }
-
- // Check if frontend deps have been updated
- var feSpinner *spinner.Spinner
- if !projectOptions.Verbose {
- feSpinner = spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
- feSpinner.SetSpinSpeed(50)
- feSpinner.Start()
- } else {
- println("Ensuring frontend dependencies are up to date (This may take a while)")
- }
-
- requiresNPMInstall := true
-
- // Read in package.json MD5
- fs := NewFSHelper()
- packageJSONMD5, err := fs.FileMD5("package.json")
- if err != nil {
- return err
- }
-
- const md5sumFile = "package.json.md5"
-
- // If node_modules does not exist, force a rebuild.
- nodeModulesPath, err := filepath.Abs(filepath.Join(".", "node_modules"))
- if err != nil {
- return err
- }
- if !fs.DirExists(nodeModulesPath) {
- forceRebuild = true
- }
-
- // If we aren't forcing the install and the md5sum file exists
- if !forceRebuild && fs.FileExists(md5sumFile) {
- // Yes - read contents
- savedMD5sum, err := fs.LoadAsString(md5sumFile)
- // File exists
- if err == nil {
- // Compare md5
- if savedMD5sum == packageJSONMD5 {
- // Same - no need for reinstall
- requiresNPMInstall = false
- if feSpinner != nil {
- feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
- } else {
- println("Skipped frontend dependencies (-f to force rebuild)")
- }
- }
- }
- }
-
- // Md5 sum package.json
- // Different? Build
- if requiresNPMInstall || forceRebuild {
- // Install dependencies
- err = NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Install)
- if err != nil {
- if feSpinner != nil {
- feSpinner.Error()
- }
- return err
- }
- if feSpinner != nil {
- feSpinner.Success()
- }
-
- // Update md5sum file
- err := os.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
- if err != nil {
- return err
- }
- }
-
- // Install the runtime
- if caller == "build" {
- err = InstallProdRuntime(projectDir, projectOptions)
- } else {
- err = InstallBridge(projectDir, projectOptions)
- }
- if err != nil {
- return err
- }
-
- // Build frontend
- err = BuildFrontend(projectOptions)
- if err != nil {
- return err
- }
- return nil
-}
-
-// InstallBridge installs the relevant bridge javascript library
-func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
- bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
- err := fs.CreateFile(bridgeFileTarget, wailsruntime.BridgeJS)
- return err
-}
-
-// InstallProdRuntime installs the production runtime
-func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
- bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
- err := fs.CreateFile(bridgeFileTarget, wailsruntime.InitJS)
- return err
-}
-
-// ServeProject attempts to serve up the current project so that it may be connected to
-// via the Wails bridge
-func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
- go func() {
- time.Sleep(2 * time.Second)
- if projectOptions.Platform == "windows" {
- logger.Yellow("*** Please note: Windows builds use mshtml which is only compatible with IE11. We strongly recommend only using IE11 when running 'wails serve'! For more information, please read https://wails.app/guides/windows/ ***")
- }
- logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
- }()
- location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName))
- if err != nil {
- return err
- }
-
- logger.Yellow("Serving Application: " + location)
- var args []string
- if len(os.Args) > 2 {
- foundArgSep := false
- for index, arg := range os.Args[2:] {
- if arg == "--" {
- foundArgSep = true
- continue
- }
- if foundArgSep {
- args = os.Args[index:]
- break
- }
- }
- logger.Yellow("Passing arguments: %+v", args)
- }
- cmd := exec.Command(location, args...)
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- err = cmd.Run()
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func ldFlags(po *ProjectOptions, buildMode string) string {
- // Setup ld flags
- ldflags := "-w -s "
- if buildMode == BuildModeDebug {
- ldflags = ""
- }
-
- // Add windows flags
- if po.Platform == "windows" && buildMode == BuildModeProd {
- ldflags += "-H windowsgui "
- }
-
- if po.UseFirebug {
- ldflags += "-X github.com/wailsapp/wails/lib/renderer.UseFirebug=true "
- }
-
- ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
-
- // Add additional ldflags passed in via the `ldflags` cli flag
- if len(po.LdFlags) > 0 {
- ldflags += " " + po.LdFlags
- }
-
- // If we wish to generate typescript
- if po.typescriptDefsFilename != "" {
- cwd, err := os.Getwd()
- if err == nil {
- filename := filepath.Join(cwd, po.FrontEnd.Dir, po.typescriptDefsFilename)
- ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
- }
- }
- return ldflags
-}
-
-func getGitConfigValue(key string) (string, error) {
- output, err := exec.Command("git", "config", "--get", "--null", key).Output()
- // When using --null git appends a null character (\u0000) to the command output
- return strings.TrimRight(string(output), "\u0000"), err
-}
diff --git a/cmd/linux.go b/cmd/linux.go
deleted file mode 100644
index 5795797ef..000000000
--- a/cmd/linux.go
+++ /dev/null
@@ -1,343 +0,0 @@
-package cmd
-
-import (
- "fmt"
- "net/url"
- "os"
- "runtime"
- "strings"
-
- "github.com/pkg/browser"
-)
-
-// LinuxDistribution is of type int
-type LinuxDistribution int
-
-const (
- // Unknown is the catch-all distro
- Unknown LinuxDistribution = iota
- // Debian distribution
- Debian
- // Ubuntu distribution
- Ubuntu
- // Arch linux distribution
- Arch
- // CentOS linux distribution
- CentOS
- // Fedora linux distribution
- Fedora
- // Gentoo distribution
- Gentoo
- // Zorin distribution
- Zorin
- // Parrot distribution
- Parrot
- // Linuxmint distribution
- Linuxmint
- // VoidLinux distribution
- VoidLinux
- // Elementary distribution
- Elementary
- // Kali distribution
- Kali
- // Neon distribution
- Neon
- // ArcoLinux distribution
- ArcoLinux
- // Manjaro distribution
- Manjaro
- // ManjaroARM distribution
- ManjaroARM
- // Deepin distribution
- Deepin
- // Raspbian distribution
- Raspbian
- // Tumbleweed (OpenSUSE) distribution
- Tumbleweed
- // Leap (OpenSUSE) distribution
- Leap
- // ArchLabs distribution
- ArchLabs
- // PopOS distribution
- PopOS
- // Solus distribution
- Solus
- // Ctlos Linux distribution
- Ctlos
- // EndeavourOS linux distribution
- EndeavourOS
- // Crux linux distribution
- Crux
- // RHEL distribution
- RHEL
- // NixOS distribution
- NixOS
- // Artix linux distribution
- ArtixLinux
- //Uos distribution
- Uos
-)
-
-// DistroInfo contains all the information relating to a linux distribution
-type DistroInfo struct {
- Distribution LinuxDistribution
- Name string
- ID string
- Description string
- Release string
-}
-
-// GetLinuxDistroInfo returns information about the running linux distribution
-func GetLinuxDistroInfo() *DistroInfo {
- result := &DistroInfo{
- Distribution: Unknown,
- ID: "unknown",
- Name: "Unknown",
- }
- _, err := os.Stat("/etc/os-release")
- if !os.IsNotExist(err) {
- osRelease, _ := os.ReadFile("/etc/os-release")
- result = parseOsRelease(string(osRelease))
- }
- return result
-}
-
-// parseOsRelease parses the given os-release data and returns
-// a DistroInfo struct with the details
-func parseOsRelease(osRelease string) *DistroInfo {
- result := &DistroInfo{Distribution: Unknown}
-
- // Default value
- osID := "unknown"
- osNAME := "Unknown"
- version := ""
-
- // Split into lines
- lines := strings.Split(osRelease, "\n")
- // Iterate lines
- for _, line := range lines {
- // Split each line by the equals char
- splitLine := strings.SplitN(line, "=", 2)
- // Check we have
- if len(splitLine) != 2 {
- continue
- }
- switch splitLine[0] {
- case "ID":
- osID = strings.ToLower(strings.Trim(splitLine[1], "\""))
- case "NAME":
- osNAME = strings.Trim(splitLine[1], "\"")
- case "VERSION_ID":
- version = strings.Trim(splitLine[1], "\"")
- }
- }
-
- // Check distro name against list of distros
- switch osID {
- case "fedora":
- result.Distribution = Fedora
- case "centos":
- result.Distribution = CentOS
- case "rhel":
- result.Distribution = RHEL
- case "arch":
- result.Distribution = Arch
- case "archlabs":
- result.Distribution = ArchLabs
- case "ctlos":
- result.Distribution = Ctlos
- case "debian":
- result.Distribution = Debian
- case "ubuntu":
- result.Distribution = Ubuntu
- case "gentoo":
- result.Distribution = Gentoo
- case "zorin":
- result.Distribution = Zorin
- case "parrot":
- result.Distribution = Parrot
- case "linuxmint":
- result.Distribution = Linuxmint
- case "void":
- result.Distribution = VoidLinux
- case "elementary":
- result.Distribution = Elementary
- case "kali":
- result.Distribution = Kali
- case "neon":
- result.Distribution = Neon
- case "arcolinux":
- result.Distribution = ArcoLinux
- case "manjaro":
- result.Distribution = Manjaro
- case "manjaro-arm":
- result.Distribution = ManjaroARM
- case "deepin":
- result.Distribution = Deepin
- case "raspbian":
- result.Distribution = Raspbian
- case "opensuse-tumbleweed":
- result.Distribution = Tumbleweed
- case "opensuse-leap":
- result.Distribution = Leap
- case "pop":
- result.Distribution = PopOS
- case "solus":
- result.Distribution = Solus
- case "endeavouros":
- result.Distribution = EndeavourOS
- case "crux":
- result.Distribution = Crux
- case "nixos":
- result.Distribution = NixOS
- case "artix":
- result.Distribution = ArtixLinux
- case "uos":
- result.Distribution = Uos
- default:
- result.Distribution = Unknown
- }
-
- result.Name = osNAME
- result.ID = osID
- result.Release = version
-
- return result
-}
-
-// CheckPkgInstalled is all functions that use local programs to see if a package is installed
-type CheckPkgInstalled func(string) (bool, error)
-
-// EqueryInstalled uses equery to see if a package is installed
-func EqueryInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- equery := program.FindProgram("equery")
- if equery == nil {
- return false, fmt.Errorf("cannont check dependencies: equery not found")
- }
- _, _, exitCode, _ := equery.Run("l", packageName)
- return exitCode == 0, nil
-}
-
-// DpkgInstalled uses dpkg to see if a package is installed
-func DpkgInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- dpkg := program.FindProgram("dpkg")
- if dpkg == nil {
- return false, fmt.Errorf("cannot check dependencies: dpkg not found")
- }
- _, _, exitCode, _ := dpkg.Run("-L", packageName)
- return exitCode == 0, nil
-}
-
-// EOpkgInstalled uses dpkg to see if a package is installed
-func EOpkgInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- eopkg := program.FindProgram("eopkg")
- if eopkg == nil {
- return false, fmt.Errorf("cannot check dependencies: eopkg not found")
- }
- stdout, _, _, _ := eopkg.Run("info", packageName)
- return strings.HasPrefix(stdout, "Installed"), nil
-}
-
-// PacmanInstalled uses pacman to see if a package is installed.
-func PacmanInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- pacman := program.FindProgram("pacman")
- if pacman == nil {
- return false, fmt.Errorf("cannot check dependencies: pacman not found")
- }
- _, _, exitCode, _ := pacman.Run("-Qs", packageName)
- return exitCode == 0, nil
-}
-
-// XbpsInstalled uses pacman to see if a package is installed.
-func XbpsInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- xbpsQuery := program.FindProgram("xbps-query")
- if xbpsQuery == nil {
- return false, fmt.Errorf("cannot check dependencies: xbps-query not found")
- }
- _, _, exitCode, _ := xbpsQuery.Run("-S", packageName)
- return exitCode == 0, nil
-}
-
-// RpmInstalled uses rpm to see if a package is installed
-func RpmInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- rpm := program.FindProgram("rpm")
- if rpm == nil {
- return false, fmt.Errorf("cannot check dependencies: rpm not found")
- }
- _, _, exitCode, _ := rpm.Run("--query", packageName)
- return exitCode == 0, nil
-}
-
-// PrtGetInstalled uses prt-get to see if a package is installed
-func PrtGetInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- prtget := program.FindProgram("prt-get")
- if prtget == nil {
- return false, fmt.Errorf("cannot check dependencies: prt-get not found")
- }
- _, _, exitCode, _ := prtget.Run("isinst", packageName)
- return exitCode == 0, nil
-}
-
-// NixEnvInstalled uses nix-env to see if a package is installed
-func NixEnvInstalled(packageName string) (bool, error) {
- program := NewProgramHelper()
- nixEnv := program.FindProgram("nix-env")
- if nixEnv == nil {
- return false, fmt.Errorf("cannot check dependencies: nix-env not found")
- }
- packageName = strings.ReplaceAll(packageName, "+", `\+`)
- _, _, exitCode, _ := nixEnv.Run("-q", packageName)
- return exitCode == 0, nil
-}
-
-// RequestSupportForDistribution promts the user to submit a request to support their
-// currently unsupported distribution
-func RequestSupportForDistribution(distroInfo *DistroInfo) error {
- var logger = NewLogger()
- defaultError := fmt.Errorf("unable to check libraries on distribution '%s'", distroInfo.Name)
-
- logger.Yellow("Distribution '%s' is not currently supported, but we would love to!", distroInfo.Name)
- q := fmt.Sprintf("Would you like to submit a request to support distribution '%s'?", distroInfo.Name)
- result := Prompt(q, "yes")
- if strings.ToLower(result) != "yes" {
- return defaultError
- }
-
- title := fmt.Sprintf("Support Distribution '%s'", distroInfo.Name)
-
- var str strings.Builder
-
- gomodule, exists := os.LookupEnv("GO111MODULE")
- if !exists {
- gomodule = "(Not Set)"
- }
-
- str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
- str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", Version))
- str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
- str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
- str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
- str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
- str.WriteString(fmt.Sprintf("| Distribution ID | %s |\n", distroInfo.ID))
- str.WriteString(fmt.Sprintf("| Distribution Name | %s |\n", distroInfo.Name))
- str.WriteString(fmt.Sprintf("| Distribution Version | %s |\n", distroInfo.Release))
-
- body := fmt.Sprintf("**Description**\nDistribution '%s' is currently unsupported.\n\n**Further Information**\n\n%s\n\n*Please add any extra information here, EG: libraries that are needed to make the distribution work, or commands to install them*", distroInfo.ID, str.String())
- fullURL := "https://github.com/wailsapp/wails/issues/new?"
- params := "title=" + title + "&body=" + body
-
- fmt.Println("Opening browser to file request.")
- browser.OpenURL(fullURL + url.PathEscape(params))
- result = Prompt("We have a guide for adding support for your distribution. Would you like to view it?", "yes")
- if strings.ToLower(result) == "yes" {
- browser.OpenURL("https://wails.app/guides/distro/")
- }
- return nil
-}
diff --git a/cmd/linux_test.go b/cmd/linux_test.go
deleted file mode 100644
index 73f7eec43..000000000
--- a/cmd/linux_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package cmd
-
-import "testing"
-
-func TestUbuntuDetection(t *testing.T) {
- osrelease := `
-NAME="Ubuntu"
-VERSION="18.04.2 LTS (Bionic Beaver)"
-ID=ubuntu
-ID_LIKE=debian
-PRETTY_NAME="Ubuntu 18.04.2 LTS"
-VERSION_ID="18.04"
-HOME_URL="https://www.ubuntu.com/"
-SUPPORT_URL="https://help.ubuntu.com/"
-BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
-PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
-VERSION_CODENAME=bionic
-UBUNTU_CODENAME=bionic
-`
-
- result := parseOsRelease(osrelease)
- if result.Distribution != Ubuntu {
- t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
- }
-}
-
-func TestTumbleweedDetection(t *testing.T) {
- osrelease := `
-NAME="openSUSE Tumbleweed"
-# VERSION="20200414"
-ID="opensuse-tumbleweed"
-ID_LIKE="opensuse suse"
-VERSION_ID="20200414"
-PRETTY_NAME="openSUSE Tumbleweed"
-ANSI_COLOR="0;32"
-CPE_NAME="cpe:/o:opensuse:tumbleweed:20200414"
-BUG_REPORT_URL="https://bugs.opensuse.org"
-HOME_URL="https://www.opensuse.org/"
-LOGO="distributor-logo"
-`
-
- result := parseOsRelease(osrelease)
- if result.Distribution != Tumbleweed {
- t.Errorf("expected 'Tumbleweed' ID but got '%d'", result.Distribution)
- }
-}
diff --git a/cmd/linuxdb.go b/cmd/linuxdb.go
deleted file mode 100644
index ca7c368e3..000000000
--- a/cmd/linuxdb.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package cmd
-
-import (
- _ "embed"
- "log"
-
- "gopkg.in/yaml.v3"
-)
-
-//go:embed linuxdb.yaml
-var LinuxDBYaml []byte
-
-// LinuxDB is the database for linux distribution data.
-type LinuxDB struct {
- Distributions map[string]*Distribution `yaml:"distributions"`
-}
-
-// Distribution holds the os-release ID and a map of releases.
-type Distribution struct {
- ID string `yaml:"id"`
- Releases map[string]*Release `yaml:"releases"`
-}
-
-// GetRelease attempts to return the specific Release information
-// for the given release name. If there is no specific match, the
-// default release data is returned.
-func (d *Distribution) GetRelease(version string) *Release {
- result := d.Releases[version]
- if result == nil {
- result = d.Releases["default"]
- }
- return result
-}
-
-// Release holds the name and version of the release as given by
-// os-release. Programs is a slice of dependant programs required
-// to be present on the local installation for Wails to function.
-// Libraries is a slice of libraries that must be present for Wails
-// applications to compile.
-type Release struct {
- Name string `yaml:"name"`
- Version string `yaml:"version"`
- GccVersionCommand string `yaml:"gccversioncommand"`
- Programs []*Prerequisite `yaml:"programs"`
- Libraries []*Prerequisite `yaml:"libraries"`
-}
-
-// Prerequisite is a simple struct containing a program/library name
-// plus the distribution specific help text indicating how to install
-// it.
-type Prerequisite struct {
- Name string `yaml:"name"`
- Help string `yaml:"help,omitempty"`
-}
-
-// Load will load the given filename from disk and attempt to
-// import the data into the LinuxDB.
-func (l *LinuxDB) Load(filename string) error {
- if fs.FileExists(filename) {
- data, err := fs.LoadAsBytes(filename)
- if err != nil {
- return err
- }
- return l.ImportData(data)
- }
- return nil
-}
-
-// ImportData will unmarshal the given YAML formatted data
-// into the LinuxDB
-func (l *LinuxDB) ImportData(data []byte) error {
- return yaml.Unmarshal(data, l)
-}
-
-// GetDistro returns the Distribution information for the
-// given distribution name. If the distribution is not supported,
-// nil is returned.
-func (l *LinuxDB) GetDistro(distro string) *Distribution {
- return l.Distributions[distro]
-}
-
-// NewLinuxDB creates a new LinuxDB instance from the bundled
-// linuxdb.yaml file.
-func NewLinuxDB() *LinuxDB {
- result := LinuxDB{
- Distributions: make(map[string]*Distribution),
- }
- err := result.ImportData(LinuxDBYaml)
- if err != nil {
- log.Fatal(err)
- }
- return &result
-}
diff --git a/cmd/linuxdb.yaml b/cmd/linuxdb.yaml
deleted file mode 100644
index 03b8239f2..000000000
--- a/cmd/linuxdb.yaml
+++ /dev/null
@@ -1,384 +0,0 @@
----
-distributions:
- debian:
- id: debian
- releases:
- default:
- name: Debian
- version: default
- gccversioncommand: &gccdumpversion -dumpversion
- programs: &debiandefaultprograms
- - name: gcc
- help: Please install with `sudo apt-get install build-essential` and try again
- - name: pkg-config
- help: Please install with `sudo apt-get install pkg-config` and try again
- - name: npm
- help: Please install with `curl -sL https://deb.nodesource.com/setup_12.x | sudo bash - && sudo apt-get install -y nodejs` and try again
- libraries: &debiandefaultlibraries
- - name: libgtk-3-dev
- help: Please install with `sudo apt-get install libgtk-3-dev` and try again
- - name: libwebkit2gtk-4.0-dev
- help: Please install with `sudo apt-get install libwebkit2gtk-4.0-dev` and try again
- ubuntu:
- id: ubuntu
- releases:
- default:
- version: default
- name: Ubuntu
- gccversioncommand: &gccdumpfullversion -dumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- pop:
- id: pop
- releases:
- default:
- version: default
- name: Pop!_OS
- gccversioncommand: &gccdumpfullversion -dumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- kali:
- id: kali
- releases:
- default:
- version: default
- name: Kali GNU/Linux
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- parrot:
- id: parrot
- releases:
- default:
- version: default
- name: Parrot GNU/Linux
- gccversioncommand: *gccdumpversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- zorin:
- id: zorin
- releases:
- default:
- version: default
- name: Zorin
- gccversioncommand: *gccdumpversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- linuxmint:
- id: linuxmint
- releases:
- default:
- version: default
- name: Linux Mint
- gccversioncommand: *gccdumpversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- elementary:
- id: elementary
- releases:
- default:
- version: default
- name: elementary OS
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- neon:
- id: neon
- releases:
- default:
- version: default
- name: KDE neon
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- deepin:
- id: deepin
- releases:
- default:
- version: default
- name: Deepin
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- uos:
- id: uos
- releases:
- default:
- version: default
- name: Uos
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- void:
- id: void
- releases:
- default:
- version: default
- name: VoidLinux
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install with `xbps-install base-devel` and try again
- - name: pkg-config
- help: Please install with `xbps-install pkg-config` and try again
- - name: npm
- help: Please install with `xbps-install nodejs` and try again
- libraries:
- - name: gtk+3-devel
- help: Please install with `xbps-install gtk+3-devel` and try again
- - name: webkit2gtk-devel
- help: Please install with `xbps-install webkit2gtk-devel` and try again
- centos:
- id: centos
- releases:
- default:
- version: default
- name: CentOS Linux
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install with `sudo yum install gcc-c++ make` and try again
- - name: pkg-config
- help: Please install with `sudo yum install pkgconf-pkg-config` and try again
- - name: npm
- help: Please install with `sudo yum install epel-release && sudo yum install nodejs` and try again
- libraries:
- - name: gtk3-devel
- help: Please install with `sudo yum install gtk3-devel` and try again
- - name: webkitgtk3-devel
- help: Please install with `sudo yum install webkitgtk3-devel` and try again
- rhel:
- id: rhel
- releases:
- default:
- version: default
- name: Red Hat Enterprise Linux
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install with `sudo yum install gcc-c++ make` and try again
- - name: pkg-config
- help: Please install with `sudo yum install pkgconf-pkg-config` and try again
- - name: npm
- help: Please install with `sudo yum install epel-release && sudo yum install nodejs` and try again
- libraries:
- - name: gtk3-devel
- help: Please install with `sudo yum install gtk3-devel` and try again
- - name: webkitgtk3-devel
- help: Please install with `sudo yum install webkitgtk3-devel` and try again
- fedora:
- id: fedora
- releases:
- default:
- version: default
- name: Fedora
- gccversioncommand: *gccdumpfullversion
- programs:
- - name: gcc
- help: Please install with `sudo yum install gcc-c++ make` and try again
- - name: pkg-config
- help: Please install with `sudo yum install pkgconf-pkg-config` and try again
- - name: npm
- help: Please install `sudo yum install nodejs` and try again
- libraries:
- - name: gtk3-devel
- help: Please install with `sudo yum install gtk3-devel` and try again
- - name: webkit2gtk3-devel
- help: Please install with `sudo yum install webkit2gtk3-devel` and try again
- arch:
- id: arch
- releases:
- default:
- version: default
- name: Arch Linux
- gccversioncommand: *gccdumpversion
- programs: &archdefaultprograms
- - name: gcc
- help: Please install with `sudo pacman -S gcc` and try again
- - name: pkgconf
- help: Please install with `sudo pacman -S pkgconf` and try again
- - name: npm
- help: Please install with `sudo pacman -S npm` and try again
- libraries: &archdefaultlibraries
- - name: gtk3
- help: Please install with `sudo pacman -S gtk3` and try again
- - name: webkit2gtk
- help: Please install with `sudo pacman -S webkit2gtk` and try again
- arcolinux:
- id: arcolinux
- releases:
- default:
- version: default
- name: ArcoLinux
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- archlabs:
- id: archlabs
- releases:
- default:
- version: default
- name: ArchLabs
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- artix:
- id: artix
- releases:
- default:
- version: default
- name: Artix Linux
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- ctlos:
- id: ctlos
- releases:
- default:
- version: default
- name: Ctlos Linux
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- endeavouros:
- id: endeavouros
- releases:
- default:
- version: default
- name: EndeavourOS
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- manjaro:
- id: manjaro
- releases:
- default:
- version: default
- name: Manjaro Linux
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- manjaro-arm:
- id: manjaro-arm
- releases:
- default:
- version: default
- name: Manjaro-ARM
- gccversioncommand: *gccdumpversion
- programs: *archdefaultprograms
- libraries: *archdefaultlibraries
- gentoo:
- id: gentoo
- releases:
- default:
- version: default
- name: Gentoo
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install using your system's package manager
- - name: pkg-config
- help: Please install using your system's package manager
- - name: npm
- help: Please install using your system's package manager
- libraries:
- - name: gtk+:3
- help: Please install with `sudo emerge gtk+:3` and try again
- - name: webkit-gtk
- help: Please install with `sudo emerge webkit-gtk` and try again
-
- raspbian:
- id: raspbian
- releases:
- default:
- version: default
- name: Raspbian
- gccversioncommand: *gccdumpfullversion
- programs: *debiandefaultprograms
- libraries: *debiandefaultlibraries
- solus:
- id: solus
- releases:
- default:
- version: default
- name: Solus
- gccversioncommand: *gccdumpfullversion
- programs: &solusdefaultprograms
- - name: gcc
- help: Please install with `sudo eopkg it -c system.devel` and try again
- - name: pkg-config
- help: Please install with `sudo eopkg it -c system.devel` and try again
- - name: npm
- help: Please install with `sudo eopkg it nodejs` and try again
- libraries: &solusdefaultlibraries
- - name: libgtk-3-devel
- help: Please install with `sudo eopkg it libgtk-3-devel` and try again
- - name: libwebkit-gtk-devel
- help: Please install with `sudo eopkg it libwebkit-gtk-devel` and try again
-
- opensuse-tumbleweed:
- id: opensuse-tumbleweed
- releases:
- default:
- version: default
- name: openSUSE Tumbleweed
- gccversioncommand: *gccdumpfullversion
- programs: &opensusedefaultprograms
- - name: gcc
- help: Please install with `sudo zypper in gcc-c++` and try again
- - name: pkg-config
- help: Please install with `sudo zypper in pkgconf-pkg-config` and try again
- - name: npm
- help: Please install `sudo zypper in nodejs` and try again
- libraries: &opensusedefaultlibraries
- - name: gtk3-devel
- help: Please install with `sudo zypper in gtk3-devel` and try again
- - name: webkit2gtk3-devel
- help: Please install with `sudo zypper in webkit2gtk3-devel` and try again
- opensuse-leap:
- id: opensuse-leap
- releases:
- default:
- version: default
- name: openSUSE Leap
- gccversioncommand: *gccdumpfullversion
- programs: *opensusedefaultprograms
- libraries: *opensusedefaultlibraries
- crux:
- id: crux
- releases:
- default:
- version: default
- name: Crux Linux
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install with `sudo prt-get depinst gcc-c++ make` and try again
- - name: pkg-config
- help: Please install with `sudo prt-get depinst pkg-config` and try again
- - name: npm
- help: Please install with `sudo prt-get depinst nodejs` and try again
- libraries:
- - name: gtk3
- help: Please install with `sudo prt-get depinst gtk3` and try again
- - name: webkitgtk
- help: Please install with `sudo prt-get depinst webkitgtk` and try again
- nixos:
- id: nixos
- releases:
- default:
- version: default
- name: NixOS
- gccversioncommand: *gccdumpversion
- programs:
- - name: gcc
- help: Please install with `nix-env -iA nixos.gcc`
- - name: pkg-config
- help: Please install with `nix-env -iA nixos.pkg-config`
- - name: npm
- help: Please install with `nix-env -iA nixos.nodejs`
- libraries:
- - name: gtk+3
- help: Please install with `nix-env -iA nixos.gtk3`
- - name: webkitgtk
- help: Please install with `nix-env -iA nixos.nodePackages.webkitgtk`
diff --git a/cmd/linuxdb_test.go b/cmd/linuxdb_test.go
deleted file mode 100644
index 795a010d2..000000000
--- a/cmd/linuxdb_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package cmd
-
-import "testing"
-
-func TestNewLinuxDB(t *testing.T) {
- _ = NewLinuxDB()
-}
-
-func TestKnownDistro(t *testing.T) {
- var linuxDB = NewLinuxDB()
- result := linuxDB.GetDistro("ubuntu")
- if result == nil {
- t.Error("Cannot get distro 'ubuntu'")
- }
-}
-
-func TestUnknownDistro(t *testing.T) {
- var linuxDB = NewLinuxDB()
- result := linuxDB.GetDistro("unknown")
- if result != nil {
- t.Error("Should get nil for distribution 'unknown'")
- }
-}
-
-func TestDefaultRelease(t *testing.T) {
- var linuxDB = NewLinuxDB()
- result := linuxDB.GetDistro("ubuntu")
- if result == nil {
- t.Error("Cannot get distro 'ubuntu'")
- }
-
- release := result.GetRelease("default")
- if release == nil {
- t.Error("Cannot get release 'default' for distro 'ubuntu'")
- }
-}
-
-func TestUnknownRelease(t *testing.T) {
- var linuxDB = NewLinuxDB()
- result := linuxDB.GetDistro("ubuntu")
- if result == nil {
- t.Error("Cannot get distro 'ubuntu'")
- }
-
- release := result.GetRelease("16.04")
- if release == nil {
- t.Error("Failed to get release 'default' for unknown release version '16.04'")
- }
-
- if release.Version != "default" {
- t.Errorf("Got version '%s' instead of 'default' for unknown release version '16.04'", result.ID)
- }
-}
-
-func TestGetPrerequisites(t *testing.T) {
- var linuxDB = NewLinuxDB()
- result := linuxDB.GetDistro("debian")
- if result == nil {
- t.Error("Cannot get distro 'debian'")
- }
-
- release := result.GetRelease("default")
- if release == nil {
- t.Error("Failed to get release 'default' for unknown release version '16.04'")
- }
-
- if release.Version != "default" {
- t.Errorf("Got version '%s' instead of 'default' for unknown release version '16.04'", result.ID)
- }
-
- if release.Name != "Debian" {
- t.Errorf("Got Release Name '%s' instead of 'debian' for unknown release version '16.04'", release.Name)
- }
-
- if len(release.Programs) != 3 {
- t.Errorf("Expected %d programs for unknown release version '16.04'", len(release.Programs))
- }
- if len(release.Libraries) != 2 {
- t.Errorf("Expected %d libraries for unknown release version '16.04'", len(release.Libraries))
- }
-}
diff --git a/cmd/log.go b/cmd/log.go
deleted file mode 100644
index 416383935..000000000
--- a/cmd/log.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package cmd
-
-import (
- "fmt"
- "strings"
-
- "github.com/fatih/color"
-)
-
-// Logger struct
-type Logger struct {
- errorOnly bool
-}
-
-// NewLogger creates a new logger!
-func NewLogger() *Logger {
- return &Logger{errorOnly: false}
-}
-
-// SetErrorOnly ensures that only errors are logged out
-func (l *Logger) SetErrorOnly(errorOnly bool) {
- l.errorOnly = errorOnly
-}
-
-// Yellow - Outputs yellow text
-func (l *Logger) Yellow(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
- color.New(color.FgHiYellow).PrintfFunc()(format+"\n", a...)
-}
-
-// Yellowf - Outputs yellow text without the newline
-func (l *Logger) Yellowf(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- color.New(color.FgHiYellow).PrintfFunc()(format, a...)
-}
-
-// Green - Outputs Green text
-func (l *Logger) Green(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- color.New(color.FgHiGreen).PrintfFunc()(format+"\n", a...)
-}
-
-// White - Outputs White text
-func (l *Logger) White(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- color.New(color.FgHiWhite).PrintfFunc()(format+"\n", a...)
-}
-
-// WhiteUnderline - Outputs White text with underline
-func (l *Logger) WhiteUnderline(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- l.White(format, a...)
- l.White(l.underline(format))
-}
-
-// YellowUnderline - Outputs Yellow text with underline
-func (l *Logger) YellowUnderline(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- l.Yellow(format, a...)
- l.Yellow(l.underline(format))
-}
-
-// underline returns a string of a line, the length of the message given to it
-func (l *Logger) underline(message string) string {
- if l.errorOnly {
- return ""
- }
-
- return strings.Repeat("-", len(message))
-}
-
-// Red - Outputs Red text
-func (l *Logger) Red(format string, a ...interface{}) {
- if l.errorOnly {
- return
- }
-
- color.New(color.FgHiRed).PrintfFunc()(format+"\n", a...)
-}
-
-// Error - Outputs an Error message
-func (l *Logger) Error(format string, a ...interface{}) {
- color.New(color.FgHiRed).PrintfFunc()("Error: "+format+"\n", a...)
-}
-
-// PrintSmallBanner prints a condensed banner
-func (l *Logger) PrintSmallBanner(message ...string) {
- yellow := color.New(color.FgYellow).SprintFunc()
- red := color.New(color.FgRed).SprintFunc()
- msg := ""
- if len(message) > 0 {
- msg = " - " + message[0]
- }
- fmt.Printf("%s %s%s\n", yellow("Wails"), red(Version), msg)
-}
-
-// PrintBanner prints the Wails banner before running commands
-func (l *Logger) PrintBanner() error {
- banner1 := ` _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ ` + "`" + `/ / / ___/
-| |/ |/ / /_/ / / (__ ) `
- banner2 := `|__/|__/\__,_/_/_/____/ `
-
- l.Yellowf(banner1)
- l.Red(Version)
- l.Yellowf(banner2)
- l.Green("https://wails.app")
- l.White("The lightweight framework for web-like apps")
- fmt.Println()
-
- return nil
-}
diff --git a/cmd/package.go b/cmd/package.go
deleted file mode 100644
index b3ec05239..000000000
--- a/cmd/package.go
+++ /dev/null
@@ -1,427 +0,0 @@
-package cmd
-
-import (
- "bufio"
- "bytes"
- "encoding/binary"
- "fmt"
- "image"
- "image/png"
- "os"
- "path"
- "path/filepath"
- "runtime"
- "strings"
- "text/template"
- "time"
-
- "github.com/jackmordaunt/icns"
- "golang.org/x/image/draw"
-)
-
-// PackageHelper helps with the 'wails package' command
-type PackageHelper struct {
- platform string
- fs *FSHelper
- log *Logger
- system *SystemHelper
-}
-
-// NewPackageHelper creates a new PackageHelper!
-func NewPackageHelper(platform string) *PackageHelper {
- return &PackageHelper{
- platform: platform,
- fs: NewFSHelper(),
- log: NewLogger(),
- system: NewSystemHelper(),
- }
-}
-
-type plistData struct {
- Title string
- Exe string
- PackageID string
- Version string
- Author string
- Date string
-}
-
-func newPlistData(title, exe, packageID, version, author string) *plistData {
- now := time.Now().Format(time.RFC822)
- return &plistData{
- Title: title,
- Exe: exe,
- Version: version,
- PackageID: packageID,
- Author: author,
- Date: now,
- }
-}
-
-type windowsIcoHeader struct {
- _ uint16
- imageType uint16
- imageCount uint16
-}
-
-type windowsIcoDescriptor struct {
- width uint8
- height uint8
- colours uint8
- _ uint8
- planes uint16
- bpp uint16
- size uint32
- offset uint32
-}
-
-type windowsIcoContainer struct {
- Header windowsIcoDescriptor
- Data []byte
-}
-
-func generateWindowsIcon(pngFilename string, iconfile string) error {
- sizes := []int{256, 128, 64, 48, 32, 16}
-
- pngfile, err := os.Open(pngFilename)
- if err != nil {
- return err
- }
- defer pngfile.Close()
-
- pngdata, err := png.Decode(pngfile)
- if err != nil {
- return err
- }
-
- icons := []windowsIcoContainer{}
-
- for _, size := range sizes {
- rect := image.Rect(0, 0, int(size), int(size))
- rawdata := image.NewRGBA(rect)
- scale := draw.CatmullRom
- scale.Scale(rawdata, rect, pngdata, pngdata.Bounds(), draw.Over, nil)
-
- icondata := new(bytes.Buffer)
- writer := bufio.NewWriter(icondata)
- err = png.Encode(writer, rawdata)
- if err != nil {
- return err
- }
- writer.Flush()
-
- imgSize := size
- if imgSize >= 256 {
- imgSize = 0
- }
-
- data := icondata.Bytes()
-
- icn := windowsIcoContainer{
- Header: windowsIcoDescriptor{
- width: uint8(imgSize),
- height: uint8(imgSize),
- planes: 1,
- bpp: 32,
- size: uint32(len(data)),
- },
- Data: data,
- }
- icons = append(icons, icn)
- }
-
- outfile, err := os.Create(iconfile)
- if err != nil {
- return err
- }
- defer outfile.Close()
-
- ico := windowsIcoHeader{
- imageType: 1,
- imageCount: uint16(len(sizes)),
- }
- err = binary.Write(outfile, binary.LittleEndian, ico)
- if err != nil {
- return err
- }
-
- offset := uint32(6 + 16*len(sizes))
- for _, icon := range icons {
- icon.Header.offset = offset
- err = binary.Write(outfile, binary.LittleEndian, icon.Header)
- if err != nil {
- return err
- }
- offset += icon.Header.size
- }
- for _, icon := range icons {
- _, err = outfile.Write(icon.Data)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func defaultString(val string, defaultVal string) string {
- if val != "" {
- return val
- }
- return defaultVal
-}
-
-func (b *PackageHelper) getPackageFileBaseDir() string {
- // Calculate template base dir
- _, filename, _, _ := runtime.Caller(1)
- return filepath.Join(path.Dir(filename), "packages", b.platform)
-}
-
-// Package the application into a platform specific package
-func (b *PackageHelper) Package(po *ProjectOptions) error {
- switch b.platform {
- case "darwin":
- return b.packageOSX(po)
- case "windows":
- return b.PackageWindows(po, true)
- case "linux":
- return b.packageLinux(po)
- default:
- return fmt.Errorf("platform '%s' not supported for bundling yet", b.platform)
- }
-}
-
-func (b *PackageHelper) packageLinux(po *ProjectOptions) error {
- return nil
-}
-
-// Package the application for OSX
-func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
- build := path.Join(b.fs.Cwd(), "build")
-
- system := NewSystemHelper()
- config, err := system.LoadConfig()
- if err != nil {
- return err
- }
-
- name := defaultString(po.Name, "WailsTest")
- exe := defaultString(po.BinaryName, name)
- version := defaultString(po.Version, "0.1.0")
- author := defaultString(config.Name, "Anonymous")
- packageID := strings.Join([]string{"wails", name, version}, ".")
- plistData := newPlistData(name, exe, packageID, version, author)
- appname := po.Name + ".app"
- plistFilename := path.Join(build, appname, "Contents", "Info.plist")
- customPlist := path.Join(b.fs.Cwd(), "info.plist")
-
- // Check binary exists
- source := path.Join(build, exe)
- if po.CrossCompile == true {
- file, err := b.fs.FindFile(build, "darwin")
- if err != nil {
- return err
- }
- source = path.Join(build, file)
- }
-
- if !b.fs.FileExists(source) {
- // We need to build!
- return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", source)
- }
- // Remove the existing package
- os.RemoveAll(appname)
-
- // Create directories
- exeDir := path.Join(build, appname, "/Contents/MacOS")
- b.fs.MkDirs(exeDir, 0755)
- resourceDir := path.Join(build, appname, "/Contents/Resources")
- b.fs.MkDirs(resourceDir, 0755)
-
- // Do we have a custom plist in the project directory?
- if !fs.FileExists(customPlist) {
-
- // No - create a new plist from our defaults
- tmpl := template.New("infoPlist")
- plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
- infoPlist, err := os.ReadFile(plistFile)
- if err != nil {
- return err
- }
- tmpl.Parse(string(infoPlist))
-
- // Write the template to a buffer
- var tpl bytes.Buffer
- err = tmpl.Execute(&tpl, plistData)
- if err != nil {
- return err
- }
-
- // Save to the package
- err = os.WriteFile(plistFilename, tpl.Bytes(), 0644)
- if err != nil {
- return err
- }
-
- // Also write to project directory for customisation
- err = os.WriteFile(customPlist, tpl.Bytes(), 0644)
- if err != nil {
- return err
- }
- } else {
- // Yes - we have a plist. Copy it to the package verbatim
- err = fs.CopyFile(customPlist, plistFilename)
- if err != nil {
- return err
- }
- }
-
- // Copy executable
- target := path.Join(exeDir, exe)
- err = b.fs.CopyFile(source, target)
- if err != nil {
- return err
- }
-
- err = os.Chmod(target, 0755)
- if err != nil {
- return err
- }
- err = b.packageIconOSX(resourceDir)
- return err
-}
-
-// CleanWindows removes any windows related files found in the directory
-func (b *PackageHelper) CleanWindows(po *ProjectOptions) {
- pdir := b.fs.Cwd()
- basename := strings.TrimSuffix(po.BinaryName, ".exe")
- exts := []string{".ico", ".exe.manifest", ".rc", "-res.syso"}
- rsrcs := []string{}
- for _, ext := range exts {
- rsrcs = append(rsrcs, filepath.Join(pdir, basename+ext))
- }
- b.fs.RemoveFiles(rsrcs, true)
-}
-
-// PackageWindows packages the application for windows platforms
-func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
- outputDir := b.fs.Cwd()
- basename := strings.TrimSuffix(po.BinaryName, ".exe")
-
- // Copy default icon if needed
- icon, err := b.copyIcon()
- if err != nil {
- return err
- }
-
- // Generate icon from PNG if it doesn't exist
- if !fs.FileExists(basename + ".ico") {
- err = generateWindowsIcon(icon, basename+".ico")
- if err != nil {
- return err
- }
- }
-
- // Copy manifest
- tgtManifestFile := filepath.Join(outputDir, basename+".exe.manifest")
- if !b.fs.FileExists(tgtManifestFile) {
- srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
- err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
- if err != nil {
- return err
- }
- }
-
- // Copy rc file
- tgtRCFile := filepath.Join(outputDir, basename+".rc")
- if !b.fs.FileExists(tgtRCFile) {
- srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
- rcfilebytes, err := os.ReadFile(srcRCfile)
- if err != nil {
- return err
- }
- rcfiledata := strings.Replace(string(rcfilebytes), "$NAME$", basename, -1)
- err = os.WriteFile(tgtRCFile, []byte(rcfiledata), 0755)
- if err != nil {
- return err
- }
- }
-
- // Build syso
- sysofile := filepath.Join(outputDir, basename+"-res.syso")
-
- // cross-compile
- if b.platform != runtime.GOOS {
- args := []string{
- "docker", "run", "--rm",
- "-v", outputDir + ":/build",
- "--entrypoint", "/bin/sh",
- "wailsapp/xgo:1.16.3",
- "-c", "/usr/bin/x86_64-w64-mingw32-windres -o /build/" + basename + "-res.syso /build/" + basename + ".rc",
- }
- if err := NewProgramHelper().RunCommandArray(args); err != nil {
- return err
- }
- } else {
- batfile, err := fs.LocalDir(".")
- if err != nil {
- return err
- }
-
- windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
- windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
- err = NewProgramHelper().RunCommandArray(windresCommand)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (b *PackageHelper) copyIcon() (string, error) {
-
- // TODO: Read this from project.json
- const appIconFilename = "appicon.png"
- srcIcon := path.Join(b.fs.Cwd(), appIconFilename)
-
- // Check if appicon.png exists
- if !b.fs.FileExists(srcIcon) {
-
- // Install default icon
- iconfile := filepath.Join(b.getPackageFileBaseDir(), "icon.png")
- iconData, err := os.ReadFile(iconfile)
- if err != nil {
- return "", err
- }
- err = os.WriteFile(srcIcon, iconData, 0644)
- if err != nil {
- return "", err
- }
- }
- return srcIcon, nil
-}
-
-func (b *PackageHelper) packageIconOSX(resourceDir string) error {
-
- srcIcon, err := b.copyIcon()
- if err != nil {
- return err
- }
- tgtBundle := path.Join(resourceDir, "iconfile.icns")
- imageFile, err := os.Open(srcIcon)
- if err != nil {
- return err
- }
- defer imageFile.Close()
- srcImg, _, err := image.Decode(imageFile)
- if err != nil {
- return err
-
- }
- dest, err := os.Create(tgtBundle)
- if err != nil {
- return err
-
- }
- defer dest.Close()
- return icns.Encode(dest, srcImg)
-}
diff --git a/cmd/packages/darwin/icon.png b/cmd/packages/darwin/icon.png
deleted file mode 100644
index 95e14df6e..000000000
Binary files a/cmd/packages/darwin/icon.png and /dev/null differ
diff --git a/cmd/packages/darwin/info.plist b/cmd/packages/darwin/info.plist
deleted file mode 100644
index c7289870f..000000000
--- a/cmd/packages/darwin/info.plist
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- CFBundlePackageType APPL
- CFBundleName {{.Title}}
- CFBundleExecutable {{.Exe}}
- CFBundleIdentifier {{.PackageID}}
- CFBundleVersion {{.Version}}
- CFBundleGetInfoString Built by {{.Author}} at {{.Date}} using Wails (https://wails.app)
- CFBundleShortVersionString {{.Version}}
- CFBundleIconFile iconfile
- NSHighResolutionCapable true
-
\ No newline at end of file
diff --git a/cmd/packages/windows/icon.png b/cmd/packages/windows/icon.png
deleted file mode 100644
index 95e14df6e..000000000
Binary files a/cmd/packages/windows/icon.png and /dev/null differ
diff --git a/cmd/packages/windows/wails.exe.manifest b/cmd/packages/windows/wails.exe.manifest
deleted file mode 100644
index b236d268f..000000000
--- a/cmd/packages/windows/wails.exe.manifest
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
- true/pm
- permonitorv2,permonitor
- true
-
-
-
\ No newline at end of file
diff --git a/cmd/packages/windows/wails.ico b/cmd/packages/windows/wails.ico
deleted file mode 100644
index 9b62ac5b4..000000000
Binary files a/cmd/packages/windows/wails.ico and /dev/null differ
diff --git a/cmd/packages/windows/wails.rc b/cmd/packages/windows/wails.rc
deleted file mode 100644
index 633bd214a..000000000
--- a/cmd/packages/windows/wails.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-100 ICON "$NAME$.ico"
-110 24 "$NAME$.exe.manifest"
\ No newline at end of file
diff --git a/cmd/prerequisites.go b/cmd/prerequisites.go
deleted file mode 100644
index 3f88ae8ce..000000000
--- a/cmd/prerequisites.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package cmd
-
-import (
- "fmt"
- "runtime"
-)
-
-func newPrerequisite(name, help string) *Prerequisite {
- return &Prerequisite{Name: name, Help: help}
-}
-
-// Prerequisites is a list of things required to use Wails
-type Prerequisites []*Prerequisite
-
-// Add given prereq object to list
-func (p *Prerequisites) Add(prereq *Prerequisite) {
- *p = append(*p, prereq)
-}
-
-// GetRequiredPrograms returns a list of programs required for the platform
-func GetRequiredPrograms() (*Prerequisites, error) {
- switch runtime.GOOS {
- case "darwin":
- return getRequiredProgramsOSX(), nil
- case "linux":
- return getRequiredProgramsLinux(), nil
- case "windows":
- return getRequiredProgramsWindows(), nil
- default:
- return nil, fmt.Errorf("platform '%s' not supported at this time", runtime.GOOS)
- }
-}
-
-func getRequiredProgramsOSX() *Prerequisites {
- result := &Prerequisites{}
- result.Add(newPrerequisite("clang", "Please install with `xcode-select --install` and try again"))
- result.Add(newPrerequisite("npm", "Please install from https://nodejs.org/en/download/ and try again"))
- return result
-}
-
-func getRequiredProgramsLinux() *Prerequisites {
- result := &Prerequisites{}
- distroInfo := GetLinuxDistroInfo()
- if distroInfo.Distribution != Unknown {
- var linuxDB = NewLinuxDB()
- distro := linuxDB.GetDistro(distroInfo.ID)
- release := distro.GetRelease(distroInfo.Release)
- for _, program := range release.Programs {
- result.Add(program)
- }
- }
- return result
-}
-
-// TODO: Test this on Windows
-func getRequiredProgramsWindows() *Prerequisites {
- result := &Prerequisites{}
- result.Add(newPrerequisite("gcc", "Please install gcc from here and try again: http://tdm-gcc.tdragon.net/download. You will need to add the bin directory to your path, EG: C:\\TDM-GCC-64\\bin\\"))
- result.Add(newPrerequisite("npm", "Please install node/npm from here and try again: https://nodejs.org/en/download/"))
- return result
-}
-
-// GetRequiredLibraries returns a list of libraries (packages) required for the platform
-func GetRequiredLibraries() (*Prerequisites, error) {
- switch runtime.GOOS {
- case "darwin":
- return getRequiredLibrariesOSX()
- case "linux":
- return getRequiredLibrariesLinux()
- case "windows":
- return getRequiredLibrariesWindows()
- default:
- return nil, fmt.Errorf("platform '%s' not supported at this time", runtime.GOOS)
- }
-}
-
-func getRequiredLibrariesOSX() (*Prerequisites, error) {
- result := &Prerequisites{}
- return result, nil
-}
-
-func getRequiredLibrariesLinux() (*Prerequisites, error) {
- result := &Prerequisites{}
- // The Linux Distribution DB
- distroInfo := GetLinuxDistroInfo()
- if distroInfo.Distribution != Unknown {
- var linuxDB = NewLinuxDB()
- distro := linuxDB.GetDistro(distroInfo.ID)
- release := distro.GetRelease(distroInfo.Release)
- for _, library := range release.Libraries {
- result.Add(library)
- }
- }
- return result, nil
-}
-
-func getRequiredLibrariesWindows() (*Prerequisites, error) {
- result := &Prerequisites{}
- return result, nil
-}
diff --git a/cmd/program.go b/cmd/program.go
deleted file mode 100644
index 733bd51a7..000000000
--- a/cmd/program.go
+++ /dev/null
@@ -1,162 +0,0 @@
-package cmd
-
-import (
- "bytes"
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- "syscall"
-)
-
-// ProgramHelper - Utility functions around installed applications
-type ProgramHelper struct {
- shell *ShellHelper
- verbose bool
-}
-
-// NewProgramHelper - Creates a new ProgramHelper
-func NewProgramHelper(verbose ...bool) *ProgramHelper {
- result := &ProgramHelper{
- shell: NewShellHelper(),
- }
- if len(verbose) > 0 {
- result.verbose = verbose[0]
- if result.verbose {
- result.shell.SetVerbose()
- }
- }
- return result
-}
-
-// IsInstalled tries to determine if the given binary name is installed
-func (p *ProgramHelper) IsInstalled(programName string) bool {
- _, err := exec.LookPath(programName)
- return err == nil
-}
-
-// Program - A struct to define an installed application/binary
-type Program struct {
- Name string `json:"name"`
- Path string `json:"path"`
- verbose bool
-}
-
-// FindProgram attempts to find the given program on the system.FindProgram
-// Returns a struct with the name and path to the program
-func (p *ProgramHelper) FindProgram(programName string) *Program {
- path, err := exec.LookPath(programName)
- if err != nil {
- return nil
- }
- path, err = filepath.Abs(path)
- if err != nil {
- return nil
- }
- return &Program{
- Name: programName,
- Path: path,
- verbose: p.verbose,
- }
-}
-
-// GetFullPathToBinary returns the full path the the current binary
-func (p *Program) GetFullPathToBinary() (string, error) {
- return filepath.Abs(p.Path)
-}
-
-// Run will execute the program with the given parameters
-// Returns stdout + stderr as strings and an error if one occurred
-func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err error) {
- command, err := p.GetFullPathToBinary()
- if err != nil {
- return "", "", 1, err
- }
- cmd := exec.Command(command, vars...)
- if !p.verbose {
- var stdo, stde bytes.Buffer
- cmd.Stdout = &stdo
- cmd.Stderr = &stde
- err = cmd.Run()
- stdout = string(stdo.Bytes())
- stderr = string(stde.Bytes())
- } else {
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- err = cmd.Run()
- }
-
- // https://stackoverflow.com/questions/10385551/get-exit-code-go
- if err != nil {
- // try to get the exit code
- if exitError, ok := err.(*exec.ExitError); ok {
- ws := exitError.Sys().(syscall.WaitStatus)
- exitCode = ws.ExitStatus()
- } else {
- exitCode = 1
- if stderr == "" {
- stderr = err.Error()
- }
- }
- } else {
- // success, exitCode should be 0 if go is ok
- ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
- exitCode = ws.ExitStatus()
- }
- return
-}
-
-// InstallGoPackage installs the given Go package
-func (p *ProgramHelper) InstallGoPackage(packageName string) error {
- args := strings.Split("get "+packageName, " ")
- _, stderr, err := p.shell.Run("go", args...)
- if err != nil {
- fmt.Println(stderr)
- }
- return err
-}
-
-// InstallNPMPackage installs the given npm package
-func (p *ProgramHelper) InstallNPMPackage(packageName string, save bool) error {
- args := strings.Split("install "+packageName, " ")
- if save {
- args = append(args, "--save")
- }
- _, stderr, err := p.shell.Run("npm", args...)
- if err != nil {
- fmt.Println(stderr)
- }
- return err
-}
-
-// RunCommand runs the given command
-func (p *ProgramHelper) RunCommand(command string) error {
- args := strings.Split(command, " ")
- return p.RunCommandArray(args)
-}
-
-// RunCommandArray runs the command specified in the array
-func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
- programCommand := args[0]
- // TODO: Run FindProgram here and get the full path to the exe
- program, err := exec.LookPath(programCommand)
- if err != nil {
- fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", programCommand)
- return err
- }
-
- args = args[1:]
- var stderr string
- var stdout string
- if len(dir) > 0 {
- stdout, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
- } else {
- stdout, stderr, err = p.shell.Run(program, args...)
- }
- if err != nil {
- fmt.Println(stderr)
- fmt.Println(stdout)
- }
- return err
-}
diff --git a/cmd/project.go b/cmd/project.go
deleted file mode 100644
index 22ecca3c0..000000000
--- a/cmd/project.go
+++ /dev/null
@@ -1,406 +0,0 @@
-package cmd
-
-import (
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "runtime"
- "sort"
- "strings"
-
- "github.com/leaanthony/slicer"
-)
-
-// PackageManager indicates different package managers
-type PackageManager int
-
-const (
- // UNKNOWN package manager
- UNKNOWN PackageManager = iota
- // NPM package manager
- NPM
- // YARN package manager
- YARN
-)
-
-type author struct {
- Name string `json:"name"`
- Email string `json:"email"`
-}
-
-type frontend struct {
- Dir string `json:"dir"`
- Install string `json:"install"`
- Build string `json:"build"`
- Bridge string `json:"bridge"`
- Serve string `json:"serve"`
-}
-
-type framework struct {
- Name string `json:"name"`
- BuildTag string `json:"buildtag"`
- Options map[string]string `json:"options,omitempty"`
-}
-
-// ProjectHelper is a helper struct for managing projects
-type ProjectHelper struct {
- log *Logger
- system *SystemHelper
- templates *TemplateHelper
-}
-
-// NewProjectHelper creates a new Project helper struct
-func NewProjectHelper() *ProjectHelper {
- return &ProjectHelper{
- log: NewLogger(),
- system: NewSystemHelper(),
- templates: NewTemplateHelper(),
- }
-}
-
-// GenerateProject generates a new project using the options given
-func (ph *ProjectHelper) GenerateProject(projectOptions *ProjectOptions) error {
-
- // Calculate project path
- projectPath, err := filepath.Abs(projectOptions.OutputDirectory)
- if err != nil {
- return err
- }
-
- _ = projectPath
-
- if fs.DirExists(projectPath) {
- return fmt.Errorf("directory '%s' already exists", projectPath)
- }
-
- // Create project directory
- err = fs.MkDir(projectPath)
- if err != nil {
- return err
- }
-
- // Create and save project config
- err = projectOptions.WriteProjectConfig()
- if err != nil {
- return err
- }
-
- err = ph.templates.InstallTemplate(projectPath, projectOptions)
- if err != nil {
- return err
- }
-
- // // If we are on windows, dump a windows_resource.json
- // if runtime.GOOS == "windows" {
- // ph.GenerateWindowsResourceConfig(projectOptions)
- // }
-
- return nil
-}
-
-// // GenerateWindowsResourceConfig generates the default windows resource file
-// func (ph *ProjectHelper) GenerateWindowsResourceConfig(po *ProjectOptions) {
-
-// fmt.Println(buffer.String())
-
-// // vi.Build()
-// // vi.Walk()
-// // err := vi.WriteSyso(outPath, runtime.GOARCH)
-// }
-
-// LoadProjectConfig loads the project config from the given directory
-func (ph *ProjectHelper) LoadProjectConfig(dir string) (*ProjectOptions, error) {
- po := ph.NewProjectOptions()
- err := po.LoadConfig(dir)
- return po, err
-}
-
-// NewProjectOptions creates a new default set of project options
-func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
- result := ProjectOptions{
- Name: "",
- Description: "Enter your project description",
- Version: "0.1.0",
- BinaryName: "",
- system: ph.system,
- log: ph.log,
- templates: ph.templates,
- Author: &author{},
- }
-
- // Populate system config
- config, err := ph.system.LoadConfig()
- if err == nil {
- result.Author.Name = config.Name
- result.Author.Email = config.Email
- }
-
- return &result
-}
-
-// ProjectOptions holds all the options available for a project
-type ProjectOptions struct {
- Name string `json:"name"`
- Description string `json:"description"`
- Author *author `json:"author,omitempty"`
- Version string `json:"version"`
- OutputDirectory string `json:"-"`
- UseDefaults bool `json:"-"`
- Template string `json:"-"`
- BinaryName string `json:"binaryname"`
- FrontEnd *frontend `json:"frontend,omitempty"`
- Tags string `json:"tags"`
- NPMProjectName string `json:"-"`
- system *SystemHelper
- log *Logger
- templates *TemplateHelper
- selectedTemplate *TemplateDetails
- WailsVersion string
- typescriptDefsFilename string
- Verbose bool `json:"-"`
- CrossCompile bool
- Platform string
- Architecture string
- LdFlags string
- GoPath string
- UseFirebug bool
-
- // Supported platforms
- Platforms []string `json:"platforms,omitempty"`
-}
-
-// PlatformSupported returns true if the template is supported
-// on the current platform
-func (po *ProjectOptions) PlatformSupported() bool {
-
- // Default is all platforms supported
- if len(po.Platforms) == 0 {
- return true
- }
-
- // Check that the platform is in the list
- platformsSupported := slicer.String(po.Platforms)
- return platformsSupported.Contains(runtime.GOOS)
-}
-
-// Defaults sets the default project template
-func (po *ProjectOptions) Defaults() {
- po.Template = "vuebasic"
- po.WailsVersion = Version
-}
-
-// SetTypescriptDefsFilename indicates that we want to generate typescript bindings to the given file
-func (po *ProjectOptions) SetTypescriptDefsFilename(filename string) {
- po.typescriptDefsFilename = filename
-}
-
-// GetNPMBinaryName returns the type of package manager used by the project
-func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) {
- if po.FrontEnd == nil {
- return UNKNOWN, fmt.Errorf("No frontend specified in project options")
- }
-
- if strings.Index(po.FrontEnd.Install, "npm") > -1 {
- return NPM, nil
- }
-
- if strings.Index(po.FrontEnd.Install, "yarn") > -1 {
- return YARN, nil
- }
-
- return UNKNOWN, nil
-}
-
-// PromptForInputs asks the user to input project details
-func (po *ProjectOptions) PromptForInputs() error {
-
- processProjectName(po)
-
- processBinaryName(po)
-
- err := processOutputDirectory(po)
- if err != nil {
- return err
- }
-
- // Process Templates
- templateList := slicer.Interface()
- options := slicer.String()
- templateDetails, err := po.templates.GetTemplateDetails()
- if err != nil {
- return err
- }
-
- if po.Template != "" {
- // Check template is valid if given
- if templateDetails[po.Template] == nil {
- keys := make([]string, 0, len(templateDetails))
- for k := range templateDetails {
- keys = append(keys, k)
- }
- return fmt.Errorf("invalid template name '%s'. Valid options: %s", po.Template, strings.Join(keys, ", "))
- }
- po.selectedTemplate = templateDetails[po.Template]
- } else {
-
- keys := make([]string, 0)
- for k := range templateDetails {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- templateDetail := templateDetails[k]
- templateList.Add(templateDetail)
- if !templateDetail.Metadata.PlatformSupported() {
- templateDetail.Metadata.Name = "* " + templateDetail.Metadata.Name
- }
- options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription))
- }
-
- templateIndex := 0
-
- if len(options.AsSlice()) > 1 {
- templateIndex = PromptSelection("Please select a template (* means unsupported on current platform)", options.AsSlice(), 0)
- }
-
- if len(templateList.AsSlice()) == 0 {
- return fmt.Errorf("aborting: no templates found")
- }
-
- // After selection do this....
- po.selectedTemplate = templateList.AsSlice()[templateIndex].(*TemplateDetails)
- }
-
- po.selectedTemplate.Metadata.Name = strings.TrimPrefix(po.selectedTemplate.Metadata.Name, "* ")
- if !po.selectedTemplate.Metadata.PlatformSupported() {
- println("WARNING: This template is unsupported on this platform!")
- }
- fmt.Println("Template: " + po.selectedTemplate.Metadata.Name)
-
- // Setup NPM Project name
- po.NPMProjectName = strings.ToLower(strings.Replace(po.Name, " ", "_", -1))
-
- // Fix template name
- po.Template = strings.Split(po.selectedTemplate.Path, string(os.PathSeparator))[0]
-
- // // Populate template details
- templateMetadata := po.selectedTemplate.Metadata
-
- err = processTemplateMetadata(templateMetadata, po)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// WriteProjectConfig writes the project configuration into
-// the project directory
-func (po *ProjectOptions) WriteProjectConfig() error {
- targetDir, err := filepath.Abs(po.OutputDirectory)
- if err != nil {
- return err
- }
-
- targetFile := filepath.Join(targetDir, "project.json")
- filedata, err := json.MarshalIndent(po, "", " ")
- if err != nil {
- return err
- }
-
- return os.WriteFile(targetFile, filedata, 0600)
-}
-
-// LoadConfig loads the project configuration file from the
-// given directory
-func (po *ProjectOptions) LoadConfig(projectDir string) error {
- targetFile := filepath.Join(projectDir, "project.json")
- rawBytes, err := os.ReadFile(targetFile)
- if err != nil {
- return err
- }
- return json.Unmarshal(rawBytes, po)
-}
-
-func computeBinaryName(projectName string) string {
- if projectName == "" {
- return ""
- }
- var binaryNameComputed = strings.ToLower(projectName)
- binaryNameComputed = strings.Replace(binaryNameComputed, " ", "-", -1)
- binaryNameComputed = strings.Replace(binaryNameComputed, string(filepath.Separator), "-", -1)
- binaryNameComputed = strings.Replace(binaryNameComputed, ":", "-", -1)
- return binaryNameComputed
-}
-
-func processOutputDirectory(po *ProjectOptions) error {
- // po.OutputDirectory
- if po.OutputDirectory == "" {
- po.OutputDirectory = PromptRequired("Project directory name", computeBinaryName(po.Name))
- }
- projectPath, err := filepath.Abs(po.OutputDirectory)
- if err != nil {
- return err
- }
-
- if NewFSHelper().DirExists(projectPath) {
- return fmt.Errorf("directory '%s' already exists", projectPath)
- }
-
- fmt.Println("Project Directory: " + po.OutputDirectory)
- return nil
-}
-
-func processProjectName(po *ProjectOptions) {
- if po.Name == "" {
- po.Name = Prompt("The name of the project", "My Project")
- }
- fmt.Println("Project Name: " + po.Name)
-}
-
-func processBinaryName(po *ProjectOptions) {
- if po.BinaryName == "" {
- var binaryNameComputed = computeBinaryName(po.Name)
- po.BinaryName = Prompt("The output binary name", binaryNameComputed)
- }
- fmt.Println("Output binary Name: " + po.BinaryName)
-}
-
-func processTemplateMetadata(templateMetadata *TemplateMetadata, po *ProjectOptions) error {
- if templateMetadata.FrontendDir != "" {
- po.FrontEnd = &frontend{}
- po.FrontEnd.Dir = templateMetadata.FrontendDir
- }
- if templateMetadata.Install != "" {
- if po.FrontEnd == nil {
- return fmt.Errorf("install set in template metadata but not frontenddir")
- }
- po.FrontEnd.Install = templateMetadata.Install
- }
- if templateMetadata.Build != "" {
- if po.FrontEnd == nil {
- return fmt.Errorf("build set in template metadata but not frontenddir")
- }
- po.FrontEnd.Build = templateMetadata.Build
- }
-
- if templateMetadata.Bridge != "" {
- if po.FrontEnd == nil {
- return fmt.Errorf("bridge set in template metadata but not frontenddir")
- }
- po.FrontEnd.Bridge = templateMetadata.Bridge
- }
-
- if templateMetadata.Serve != "" {
- if po.FrontEnd == nil {
- return fmt.Errorf("serve set in template metadata but not frontenddir")
- }
- po.FrontEnd.Serve = templateMetadata.Serve
- }
-
- // Save platforms
- po.Platforms = templateMetadata.Platforms
-
- return nil
-}
diff --git a/cmd/prompt.go b/cmd/prompt.go
deleted file mode 100644
index dac324fe4..000000000
--- a/cmd/prompt.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package cmd
-
-import (
- "bufio"
- "fmt"
- "os"
- "strconv"
- "strings"
-)
-
-// Prompt asks the user for a value
-func Prompt(question string, defaultValue ...string) string {
- var answer string
-
- if len(defaultValue) > 0 {
- answer = defaultValue[0]
- question = fmt.Sprintf("%s (%s)", question, answer)
- }
- fmt.Printf(question + ": ")
- reader := bufio.NewReader(os.Stdin)
- input, _ := reader.ReadString('\n')
- input = strings.TrimSpace(input)
-
- if input != "" {
- answer = input
- }
-
- return answer
-}
-
-// PromptRequired calls Prompt repeatedly until a value is given
-func PromptRequired(question string, defaultValue ...string) string {
- for {
- result := Prompt(question, defaultValue...)
- if result != "" {
- return result
- }
- }
-}
-
-// PromptSelection asks the user to choose an option
-func PromptSelection(question string, options []string, optionalDefaultValue ...int) int {
-
- defaultValue := -1
- message := "Please choose an option"
- fmt.Println(question + ":")
-
- if len(optionalDefaultValue) > 0 {
- defaultValue = optionalDefaultValue[0] + 1
- message = fmt.Sprintf("%s [%d]", message, defaultValue)
- }
-
- for index, option := range options {
- fmt.Printf(" %d: %s\n", index+1, option)
- }
-
- selectedValue := -1
-
- for {
- choice := Prompt(message)
- if choice == "" && defaultValue > -1 {
- selectedValue = defaultValue - 1
- break
- }
-
- // index
- number, err := strconv.Atoi(choice)
- if err == nil {
- if number > 0 && number <= len(options) {
- selectedValue = number - 1
- break
- } else {
- continue
- }
- }
-
- }
-
- return selectedValue
-}
diff --git a/cmd/semver.go b/cmd/semver.go
deleted file mode 100644
index ab9405292..000000000
--- a/cmd/semver.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package cmd
-
-import (
- "fmt"
-
- "github.com/Masterminds/semver"
-)
-
-// SemanticVersion is a struct containing a semantic version
-type SemanticVersion struct {
- Version *semver.Version
-}
-
-// NewSemanticVersion creates a new SemanticVersion object with the given version string
-func NewSemanticVersion(version string) (*SemanticVersion, error) {
- semverVersion, err := semver.NewVersion(version)
- if err != nil {
- return nil, err
- }
- return &SemanticVersion{
- Version: semverVersion,
- }, nil
-}
-
-// IsRelease returns true if it's a release version
-func (s *SemanticVersion) IsRelease() bool {
- // Limit to v1
- if s.Version.Major() != 1 {
- return false
- }
- return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0
-}
-
-// IsPreRelease returns true if it's a prerelease version
-func (s *SemanticVersion) IsPreRelease() bool {
- // Limit to v1
- if s.Version.Major() != 1 {
- return false
- }
- return len(s.Version.Prerelease()) > 0
-}
-
-func (s *SemanticVersion) String() string {
- return s.Version.String()
-}
-
-// IsGreaterThan returns true if this version is greater than the given version
-func (s *SemanticVersion) IsGreaterThan(version *SemanticVersion) (bool, error) {
- // Set up new constraint
- constraint, err := semver.NewConstraint("> " + version.Version.String())
- if err != nil {
- return false, err
- }
-
- // Check if the desired one is greater than the requested on
- success, msgs := constraint.Validate(s.Version)
- if !success {
- return false, msgs[0]
- }
- return true, nil
-}
-
-// IsGreaterThanOrEqual returns true if this version is greater than or equal the given version
-func (s *SemanticVersion) IsGreaterThanOrEqual(version *SemanticVersion) (bool, error) {
- // Set up new constraint
- constraint, err := semver.NewConstraint(">= " + version.Version.String())
- if err != nil {
- return false, err
- }
-
- // Check if the desired one is greater than the requested on
- success, msgs := constraint.Validate(s.Version)
- if !success {
- return false, msgs[0]
- }
- return true, nil
-}
-
-// MainVersion returns the main version of any version+prerelease+metadata
-// EG: MainVersion("1.2.3-pre") => "1.2.3"
-func (s *SemanticVersion) MainVersion() *SemanticVersion {
- mainVersion := fmt.Sprintf("%d.%d.%d", s.Version.Major(), s.Version.Minor(), s.Version.Patch())
- result, _ := NewSemanticVersion(mainVersion)
- return result
-}
-
-// SemverCollection is a collection of SemanticVersion objects
-type SemverCollection []*SemanticVersion
-
-// Len returns the length of a collection. The number of Version instances
-// on the slice.
-func (c SemverCollection) Len() int {
- return len(c)
-}
-
-// Less is needed for the sort interface to compare two Version objects on the
-// slice. If checks if one is less than the other.
-func (c SemverCollection) Less(i, j int) bool {
- return c[i].Version.LessThan(c[j].Version)
-}
-
-// Swap is needed for the sort interface to replace the Version objects
-// at two different positions in the slice.
-func (c SemverCollection) Swap(i, j int) {
- c[i], c[j] = c[j], c[i]
-}
diff --git a/cmd/semver_test.go b/cmd/semver_test.go
deleted file mode 100644
index 54261b6f7..000000000
--- a/cmd/semver_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package cmd
-
-import (
- "testing"
-)
-
-func TestSemanticVersion_IsPreRelease(t *testing.T) {
- tests := []struct {
- name string
- version string
- want bool
- }{
- {"v1.6.7-pre0", "v1.6.7-pre0", true},
- {"v2.6.7+pre0", "v2.6.7+pre0", false},
- {"v2.6.7", "v2.6.7", false},
- {"v2.0.0+alpha.1", "v2.0.0+alpha.1", false},
- {"v2.0.0-alpha.1", "v2.0.0-alpha.1", false},
- {"v1.6.7", "v1.6.7", false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- semanticversion, err := NewSemanticVersion(tt.version)
- if err != nil {
- t.Errorf("Invalid semantic version: %s", semanticversion)
- return
- }
- s := &SemanticVersion{
- Version: semanticversion.Version,
- }
- if got := s.IsPreRelease(); got != tt.want {
- t.Errorf("IsPreRelease() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestSemanticVersion_IsRelease(t *testing.T) {
- tests := []struct {
- name string
- version string
- want bool
- }{
- {"v1.6.7", "v1.6.7", true},
- {"v2.6.7-pre0", "v2.6.7-pre0", false},
- {"v2.6.7", "v2.6.7", false},
- {"v2.6.7+release", "v2.6.7+release", false},
- {"v2.0.0-alpha.1", "v2.0.0-alpha.1", false},
- {"v1.6.7-pre0", "v1.6.7-pre0", false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- semanticversion, err := NewSemanticVersion(tt.version)
- if err != nil {
- t.Errorf("Invalid semantic version: %s", semanticversion)
- return
- }
- s := &SemanticVersion{
- Version: semanticversion.Version,
- }
- if got := s.IsRelease(); got != tt.want {
- t.Errorf("IsRelease() = %v, want %v", got, tt.want)
- }
- })
- }
-}
diff --git a/cmd/shell.go b/cmd/shell.go
deleted file mode 100644
index 53c227de0..000000000
--- a/cmd/shell.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package cmd
-
-import (
- "bytes"
- "os"
- "os/exec"
-)
-
-// ShellHelper helps with Shell commands
-type ShellHelper struct {
- verbose bool
-}
-
-// NewShellHelper creates a new ShellHelper!
-func NewShellHelper() *ShellHelper {
- return &ShellHelper{}
-}
-
-// SetVerbose sets the verbose flag
-func (sh *ShellHelper) SetVerbose() {
- sh.verbose = true
-}
-
-// Run the given command
-func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
- cmd := exec.Command(command, vars...)
- cmd.Env = append(os.Environ(), "GO111MODULE=on")
- if !sh.verbose {
- var stdo, stde bytes.Buffer
- cmd.Stdout = &stdo
- cmd.Stderr = &stde
- err = cmd.Run()
- stdout = string(stdo.Bytes())
- stderr = string(stde.Bytes())
- } else {
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- err = cmd.Run()
- }
- return
-}
-
-// RunInDirectory runs the given command in the given directory
-func (sh *ShellHelper) RunInDirectory(dir string, command string, vars ...string) (stdout, stderr string, err error) {
- cmd := exec.Command(command, vars...)
- cmd.Dir = dir
- cmd.Env = append(os.Environ(), "GO111MODULE=on")
- if !sh.verbose {
- var stdo, stde bytes.Buffer
- cmd.Stdout = &stdo
- cmd.Stderr = &stde
- err = cmd.Run()
- stdout = string(stdo.Bytes())
- stderr = string(stde.Bytes())
- } else {
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- err = cmd.Run()
- }
- return
-}
diff --git a/cmd/system.go b/cmd/system.go
deleted file mode 100644
index 3652b5c86..000000000
--- a/cmd/system.go
+++ /dev/null
@@ -1,317 +0,0 @@
-package cmd
-
-import (
- "encoding/json"
- "fmt"
- "log"
- "os"
- "path/filepath"
- "runtime"
- "strconv"
- "time"
-)
-
-// SystemHelper - Defines everything related to the system
-type SystemHelper struct {
- log *Logger
- fs *FSHelper
- configFilename string
- homeDir string
- wailsSystemDir string
- wailsSystemConfig string
-}
-
-// NewSystemHelper - Creates a new System Helper
-func NewSystemHelper() *SystemHelper {
- result := &SystemHelper{
- fs: NewFSHelper(),
- log: NewLogger(),
- configFilename: "wails.json",
- }
- result.setSystemDirs()
- return result
-}
-
-// Internal
-// setSystemDirs calculates the system directories it is interested in
-func (s *SystemHelper) setSystemDirs() {
- var err error
- s.homeDir, err = os.UserHomeDir()
- if err != nil {
- log.Fatal("Cannot find home directory! Please file a bug report!")
- }
-
- // TODO: A better config system
- s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
- s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
-}
-
-// ConfigFileExists - Returns true if it does!
-func (s *SystemHelper) ConfigFileExists() bool {
- return s.fs.FileExists(s.wailsSystemConfig)
-}
-
-// SystemDirExists - Returns true if it does!
-func (s *SystemHelper) systemDirExists() bool {
- return s.fs.DirExists(s.wailsSystemDir)
-}
-
-// LoadConfig attempts to load the Wails system config
-func (s *SystemHelper) LoadConfig() (*SystemConfig, error) {
- return NewSystemConfig(s.wailsSystemConfig)
-}
-
-// ConfigFileIsValid checks if the config file is valid
-func (s *SystemHelper) ConfigFileIsValid() bool {
- _, err := NewSystemConfig(s.wailsSystemConfig)
- return err == nil
-}
-
-// GetAuthor returns a formatted string of the user's name and email
-func (s *SystemHelper) GetAuthor() (string, error) {
- var config *SystemConfig
- config, err := s.LoadConfig()
- if err != nil {
- return "", err
- }
-
- return fmt.Sprintf("%s <%s>", config.Name, config.Email), nil
-}
-
-// BackupConfig attempts to backup the system config file
-func (s *SystemHelper) BackupConfig() (string, error) {
- now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
- backupFilename := s.wailsSystemConfig + "." + now
- err := s.fs.CopyFile(s.wailsSystemConfig, backupFilename)
- if err != nil {
- return "", err
- }
- return backupFilename, nil
-}
-
-func (s *SystemHelper) setup() error {
-
- systemConfig := make(map[string]string)
-
- // Try to load current values - ignore errors
- config, _ := s.LoadConfig()
-
- if config.Name != "" {
- systemConfig["name"] = PromptRequired("What is your name", config.Name)
- } else if n, err := getGitConfigValue("user.name"); err == nil && n != "" {
- systemConfig["name"] = PromptRequired("What is your name", n)
- } else {
- systemConfig["name"] = PromptRequired("What is your name")
- }
-
- if config.Email != "" {
- systemConfig["email"] = PromptRequired("What is your email address", config.Email)
- } else if e, err := getGitConfigValue("user.email"); err == nil && e != "" {
- systemConfig["email"] = PromptRequired("What is your email address", e)
- } else {
- systemConfig["email"] = PromptRequired("What is your email address")
- }
-
- // Create the directory
- err := s.fs.MkDirs(s.wailsSystemDir)
- if err != nil {
- return err
- }
-
- // Save
- configData, err := json.Marshal(&systemConfig)
- if err != nil {
- return err
- }
- err = os.WriteFile(s.wailsSystemConfig, configData, 0755)
- if err != nil {
- return err
- }
- fmt.Println()
- s.log.White("Wails config saved to: " + s.wailsSystemConfig)
- s.log.White("Feel free to customise these settings.")
- fmt.Println()
-
- return nil
-}
-
-const introText = `
-Wails is a lightweight framework for creating web-like desktop apps in Go.
-I'll need to ask you a few questions so I can fill in your project templates and then I will try and see if you have the correct dependencies installed. If you don't have the right tools installed, I'll try and suggest how to install them.
-`
-
-// CheckInitialised checks if the system has been set up
-// and if not, runs setup
-func (s *SystemHelper) CheckInitialised() error {
- if !s.systemDirExists() {
- s.log.Yellow("System not initialised. Running setup.")
- return s.setup()
- }
- return nil
-}
-
-// Initialise attempts to set up the Wails system.
-// An error is returns if there is a problem
-func (s *SystemHelper) Initialise() error {
-
- // System dir doesn't exist
- if !s.systemDirExists() {
- s.log.Green("Welcome to Wails!")
- s.log.Green(introText)
- return s.setup()
- }
-
- // Config doesn't exist
- if !s.ConfigFileExists() {
- s.log.Green("Looks like the system config is missing.")
- s.log.Green("To get you back on track, I'll need to ask you a few things...")
- return s.setup()
- }
-
- // Config exists but isn't valid.
- if !s.ConfigFileIsValid() {
- s.log.Green("Looks like the system config got corrupted.")
- backupFile, err := s.BackupConfig()
- if err != nil {
- s.log.Green("I tried to backup your config file but got this error: %s", err.Error())
- } else {
- s.log.Green("Just in case you needed it, I backed up your config file here: %s", backupFile)
- }
- s.log.Green("To get you back on track, I'll need to ask you a few things...")
- return s.setup()
- }
-
- return s.setup()
-}
-
-// SystemConfig - Defines system wide configuration data
-type SystemConfig struct {
- Name string `json:"name"`
- Email string `json:"email"`
-}
-
-// NewSystemConfig - Creates a new SystemConfig helper object
-func NewSystemConfig(filename string) (*SystemConfig, error) {
- result := &SystemConfig{}
- err := result.load(filename)
- return result, err
-}
-
-// Save - Saves the system config to the given filename
-func (sc *SystemConfig) Save(filename string) error {
- // Convert config to JSON string
- theJSON, err := json.MarshalIndent(sc, "", " ")
- if err != nil {
- return err
- }
-
- // Write it out to the config file
- return os.WriteFile(filename, theJSON, 0644)
-}
-
-func (sc *SystemConfig) load(filename string) error {
- configData, err := os.ReadFile(filename)
- if err != nil {
- return err
- }
- // Load and unmarshall!
- err = json.Unmarshal(configData, &sc)
- if err != nil {
- return err
- }
- return nil
-}
-
-// CheckDependenciesSilent checks for dependencies but
-// only outputs if there's an error
-func CheckDependenciesSilent(logger *Logger) (bool, error) {
- logger.SetErrorOnly(true)
- result, err := CheckDependencies(logger)
- logger.SetErrorOnly(false)
- return result, err
-}
-
-// CheckDependencies will look for Wails dependencies on the system
-// Errors are reported in error and the bool return value is whether
-// the dependencies are all installed.
-func CheckDependencies(logger *Logger) (bool, error) {
-
- switch runtime.GOOS {
- case "darwin":
- logger.Yellow("Detected Platform: OSX")
- case "windows":
- logger.Yellow("Detected Platform: Windows")
- case "linux":
- logger.Yellow("Detected Platform: Linux")
- default:
- return false, fmt.Errorf("Platform %s is currently not supported", runtime.GOOS)
- }
-
- logger.Yellow("Checking for prerequisites...")
- // Check we have a cgo capable environment
-
- requiredPrograms, err := GetRequiredPrograms()
- if err != nil {
- return false, nil
- }
- errors := false
- programHelper := NewProgramHelper()
- for _, program := range *requiredPrograms {
- bin := programHelper.FindProgram(program.Name)
- if bin == nil {
- errors = true
- logger.Error("Program '%s' not found. %s", program.Name, program.Help)
- } else {
- logger.Green("Program '%s' found: %s", program.Name, bin.Path)
- }
- }
-
- // Linux has library deps
- if runtime.GOOS == "linux" {
- // Check library prerequisites
- requiredLibraries, err := GetRequiredLibraries()
- if err != nil {
- return false, err
- }
-
- var libraryChecker CheckPkgInstalled
- distroInfo := GetLinuxDistroInfo()
-
- switch distroInfo.Distribution {
- case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS, Uos:
- libraryChecker = DpkgInstalled
- case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS, ArtixLinux:
- libraryChecker = PacmanInstalled
- case CentOS, Fedora, Tumbleweed, Leap, RHEL:
- libraryChecker = RpmInstalled
- case Gentoo:
- libraryChecker = EqueryInstalled
- case VoidLinux:
- libraryChecker = XbpsInstalled
- case Solus:
- libraryChecker = EOpkgInstalled
- case Crux:
- libraryChecker = PrtGetInstalled
- case NixOS:
- libraryChecker = NixEnvInstalled
- default:
- return false, RequestSupportForDistribution(distroInfo)
- }
-
- for _, library := range *requiredLibraries {
- installed, err := libraryChecker(library.Name)
- if err != nil {
- return false, err
- }
- if !installed {
- errors = true
- logger.Error("Library '%s' not found. %s", library.Name, library.Help)
- } else {
- logger.Green("Library '%s' installed.", library.Name)
- }
- }
- }
- logger.White("")
-
- return !errors, err
-}
diff --git a/cmd/templates.go b/cmd/templates.go
deleted file mode 100644
index 29c3d49f5..000000000
--- a/cmd/templates.go
+++ /dev/null
@@ -1,270 +0,0 @@
-package cmd
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "log"
- "os"
- "path/filepath"
- "runtime"
- "strings"
- "text/template"
-
- "github.com/kennygrant/sanitize"
- "github.com/leaanthony/slicer"
-)
-
-// TemplateMetadata holds all the metadata for a Wails template
-type TemplateMetadata struct {
- Name string `json:"name"`
- Version string `json:"version"`
- ShortDescription string `json:"shortdescription"`
- Description string `json:"description"`
- Install string `json:"install"`
- Build string `json:"build"`
- Author string `json:"author"`
- Created string `json:"created"`
- FrontendDir string `json:"frontenddir"`
- Serve string `json:"serve"`
- Bridge string `json:"bridge"`
- WailsDir string `json:"wailsdir"`
- TemplateDependencies []*TemplateDependency `json:"dependencies,omitempty"`
-
- // List of platforms that this template is supported on.
- // No value means all platforms. A platform name is the same string
- // as `runtime.GOOS` will return, eg: "darwin". NOTE: This is
- // case sensitive.
- Platforms []string `json:"platforms,omitempty"`
-}
-
-// PlatformSupported returns true if this template supports the
-// currently running platform
-func (m *TemplateMetadata) PlatformSupported() bool {
-
- // Default is all platforms supported
- if len(m.Platforms) == 0 {
- return true
- }
-
- // Check that the platform is in the list
- platformsSupported := slicer.String(m.Platforms)
- return platformsSupported.Contains(runtime.GOOS)
-}
-
-// TemplateDependency defines a binary dependency for the template
-// EG: ng for angular
-type TemplateDependency struct {
- Bin string `json:"bin"`
- Help string `json:"help"`
-}
-
-// TemplateDetails holds information about a specific template
-type TemplateDetails struct {
- Name string
- Path string
- Metadata *TemplateMetadata
- fs *FSHelper
-}
-
-// TemplateHelper is a utility object to help with processing templates
-type TemplateHelper struct {
- templateDir *Dir
- fs *FSHelper
- metadataFilename string
-}
-
-// NewTemplateHelper creates a new template helper
-func NewTemplateHelper() *TemplateHelper {
-
- templateDir, err := fs.LocalDir("./templates")
- if err != nil {
- log.Fatal("Unable to find the template directory. Please reinstall Wails.")
- }
-
- return &TemplateHelper{
- templateDir: templateDir,
- metadataFilename: "template.json",
- }
-}
-
-// IsValidTemplate returns true if the given template name resides on disk
-func (t *TemplateHelper) IsValidTemplate(templateName string) bool {
- pathToTemplate := filepath.Join(t.templateDir.fullPath, templateName)
- return t.fs.DirExists(pathToTemplate)
-}
-
-// SanitizeFilename sanitizes the given string to make a valid filename
-func (t *TemplateHelper) SanitizeFilename(name string) string {
- return sanitize.Name(name)
-}
-
-// CreateNewTemplate creates a new template based on the given directory name and string
-func (t *TemplateHelper) CreateNewTemplate(dirname string, details *TemplateMetadata) (string, error) {
-
- // Check if this template has already been created
- if t.IsValidTemplate(dirname) {
- return "", fmt.Errorf("cannot create template in directory '%s' - already exists", dirname)
- }
-
- targetDir := filepath.Join(t.templateDir.fullPath, dirname)
- err := t.fs.MkDir(targetDir)
- if err != nil {
- return "", err
- }
- targetMetadata := filepath.Join(targetDir, t.metadataFilename)
- err = t.fs.SaveAsJSON(details, targetMetadata)
-
- return targetDir, err
-}
-
-// LoadMetadata loads the template's 'metadata.json' file
-func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
- templateFile := filepath.Join(dir, t.metadataFilename)
- result := &TemplateMetadata{}
- if !t.fs.FileExists(templateFile) {
- return nil, nil
- }
- rawJSON, err := os.ReadFile(templateFile)
- if err != nil {
- return nil, err
- }
- err = json.Unmarshal(rawJSON, &result)
- return result, err
-}
-
-// GetTemplateDetails returns a map of Template structs containing details
-// of the found templates
-func (t *TemplateHelper) GetTemplateDetails() (map[string]*TemplateDetails, error) {
-
- // Get the subdirectory details
- templateDirs, err := t.templateDir.GetSubdirs()
- if err != nil {
- return nil, err
- }
-
- result := make(map[string]*TemplateDetails)
-
- for name, dir := range templateDirs {
- result[name] = &TemplateDetails{
- Path: dir,
- }
- metadata, err := t.LoadMetadata(dir)
- if err != nil {
- return nil, err
- }
-
- result[name].Metadata = metadata
- if metadata.Name != "" {
- result[name].Name = metadata.Name
- } else {
- // Ignore bad templates?
- result[name] = nil
- }
- }
-
- return result, nil
-}
-
-// GetTemplateFilenames returns all the filenames of the given template
-func (t *TemplateHelper) GetTemplateFilenames(template *TemplateDetails) (*slicer.StringSlicer, error) {
-
- // Get the subdirectory details
- templateDir, err := t.fs.Directory(template.Path)
- if err != nil {
- return nil, err
- }
- return templateDir.GetAllFilenames()
-}
-
-// InstallTemplate installs the template given in the project options to the
-// project path given
-func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error {
-
- // Check dependencies before installing
- dependencies := projectOptions.selectedTemplate.Metadata.TemplateDependencies
- if dependencies != nil {
- programHelper := NewProgramHelper()
- logger := NewLogger()
- errors := []string{}
- for _, dep := range dependencies {
- program := programHelper.FindProgram(dep.Bin)
- if program == nil {
- errors = append(errors, dep.Help)
- }
- }
- if len(errors) > 0 {
- mainError := "template dependencies not installed"
- if len(errors) == 1 {
- mainError = errors[0]
- } else {
- for _, error := range errors {
- logger.Red(error)
- }
- }
- return fmt.Errorf(mainError)
- }
- }
-
- // Get template files
- templateFilenames, err := t.GetTemplateFilenames(projectOptions.selectedTemplate)
- if err != nil {
- return err
- }
-
- templatePath := projectOptions.selectedTemplate.Path
-
- // Save the version
- projectOptions.WailsVersion = Version
-
- templateJSONFilename := filepath.Join(templatePath, t.metadataFilename)
-
- templateFiles := templateFilenames.Filter(func(filename string) bool {
- filename = filepath.FromSlash(filename)
- return strings.HasPrefix(filename, templatePath) && filename != templateJSONFilename
- })
-
- templateFiles.Each(func(templateFile string) {
-
- // Setup filenames
- relativeFilename := strings.TrimPrefix(templateFile, templatePath)[1:]
- targetFilename, err := filepath.Abs(filepath.Join(projectOptions.OutputDirectory, relativeFilename))
- if err != nil {
- return
- }
- filedata, err := t.fs.LoadAsBytes(templateFile)
- if err != nil {
- return
- }
-
- // If file is a template, process it
- if strings.HasSuffix(templateFile, ".template") {
- templateData := string(filedata)
- tmpl := template.New(templateFile)
- tmpl.Parse(templateData)
- var tpl bytes.Buffer
- err = tmpl.Execute(&tpl, projectOptions)
- if err != nil {
- return
- }
-
- // Remove template suffix
- targetFilename = strings.TrimSuffix(targetFilename, ".template")
-
- // Set the filedata to the template result
- filedata = tpl.Bytes()
- }
-
- // Normal file, just copy it
- err = fs.CreateFile(targetFilename, filedata)
- if err != nil {
- return
- }
- })
-
- if err != nil {
- return err
- }
-
- return nil
-}
diff --git a/cmd/templates/angular-template/frontend/.editorconfig b/cmd/templates/angular-template/frontend/.editorconfig
deleted file mode 100644
index e89330a61..000000000
--- a/cmd/templates/angular-template/frontend/.editorconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-# Editor configuration, see https://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-max_line_length = off
-trim_trailing_whitespace = false
diff --git a/cmd/templates/angular-template/frontend/.gitignore b/cmd/templates/angular-template/frontend/.gitignore
deleted file mode 100644
index 2d5d82ccd..000000000
--- a/cmd/templates/angular-template/frontend/.gitignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-# Only exists if Bazel was run
-/bazel-out
-
-# dependencies
-/node_modules
-
-# profiling files
-chrome-profiler-events.json
-speed-measure-plugin.json
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-.history/*
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
-.editorcinfig
diff --git a/cmd/templates/angular-template/frontend/README.md b/cmd/templates/angular-template/frontend/README.md
deleted file mode 100644
index f5aa03f4c..000000000
--- a/cmd/templates/angular-template/frontend/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# MyApp
-
-This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.3.
-
-## Development server
-
-Run `npx ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
-
-## Code scaffolding
-
-Run `npx ng generate component component-name` to generate a new component. You can also use `npx ng generate directive|pipe|service|class|guard|interface|enum|module`.
-
-## Build
-
-Run `npx ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
-
-## Running unit tests
-
-Run `npx ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
-
-## Running end-to-end tests
-
-Run `npx ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
-
-## Further help
-
-To get more help on the Angular CLI use `npx ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/cmd/templates/angular-template/frontend/angular.json b/cmd/templates/angular-template/frontend/angular.json
deleted file mode 100644
index 73d12e71f..000000000
--- a/cmd/templates/angular-template/frontend/angular.json
+++ /dev/null
@@ -1,121 +0,0 @@
-{
- "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
- "version": 1,
- "newProjectRoot": "projects",
- "projects": {
- "my-app": {
- "projectType": "application",
- "schematics": {},
- "root": "",
- "sourceRoot": "src",
- "prefix": "app",
- "architect": {
- "build": {
- "builder": "ngx-build-plus:browser",
- "options": {
- "outputPath": "dist/my-app",
- "index": "src/index.html",
- "main": "src/main.ts",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "tsconfig.app.json",
- "aot": false,
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
- "styles": [
- "src/styles.css"
- ],
- "scripts": []
- },
- "configurations": {
- "production": {
- "fileReplacements": [
- {
- "replace": "src/environments/environment.ts",
- "with": "src/environments/environment.prod.ts"
- }
- ],
- "optimization": true,
- "outputHashing": "all",
- "sourceMap": false,
- "extractCss": true,
- "namedChunks": false,
- "aot": true,
- "extractLicenses": true,
- "vendorChunk": false,
- "buildOptimizer": true,
- "budgets": [
- {
- "type": "initial",
- "maximumWarning": "2mb",
- "maximumError": "5mb"
- }
- ]
- }
- }
- },
- "serve": {
- "builder": "ngx-build-plus:dev-server",
- "options": {
- "browserTarget": "my-app:build"
- },
- "configurations": {
- "production": {
- "browserTarget": "my-app:build:production"
- }
- }
- },
- "extract-i18n": {
- "builder": "@angular-devkit/build-angular:extract-i18n",
- "options": {
- "browserTarget": "my-app:build"
- }
- },
- "test": {
- "builder": "ngx-build-plus:karma",
- "options": {
- "main": "src/test.ts",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "tsconfig.spec.json",
- "karmaConfig": "karma.conf.js",
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
- "styles": [
- "src/styles.css"
- ],
- "scripts": []
- }
- },
- "lint": {
- "builder": "@angular-devkit/build-angular:tslint",
- "options": {
- "tsConfig": [
- "tsconfig.app.json",
- "tsconfig.spec.json",
- "e2e/tsconfig.json"
- ],
- "exclude": [
- "**/node_modules/**"
- ]
- }
- },
- "e2e": {
- "builder": "@angular-devkit/build-angular:protractor",
- "options": {
- "protractorConfig": "e2e/protractor.conf.js",
- "devServerTarget": "my-app:serve"
- },
- "configurations": {
- "production": {
- "devServerTarget": "my-app:serve:production"
- }
- }
- }
- }
- }
- },
- "defaultProject": "my-app"
-}
\ No newline at end of file
diff --git a/cmd/templates/angular-template/frontend/browserslist b/cmd/templates/angular-template/frontend/browserslist
deleted file mode 100644
index 3cb56d100..000000000
--- a/cmd/templates/angular-template/frontend/browserslist
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
-# For additional information regarding the format and rule options, please see:
-# https://github.com/browserslist/browserslist#queries
-
-# You can see what browsers were selected by your queries by running:
-# npx browserslist
-
-> 0.5%
-last 2 versions
-Firefox ESR
-not dead
-IE 9-11 # For IE 9-11 support, remove 'not'.
diff --git a/cmd/templates/angular-template/frontend/e2e/protractor.conf.js b/cmd/templates/angular-template/frontend/e2e/protractor.conf.js
deleted file mode 100644
index 73e4e6806..000000000
--- a/cmd/templates/angular-template/frontend/e2e/protractor.conf.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// @ts-check
-// Protractor configuration file, see link for more information
-// https://github.com/angular/protractor/blob/master/lib/config.ts
-
-const { SpecReporter } = require('jasmine-spec-reporter');
-
-/**
- * @type { import("protractor").Config }
- */
-exports.config = {
- allScriptsTimeout: 11000,
- specs: [
- './src/**/*.e2e-spec.ts'
- ],
- capabilities: {
- 'browserName': 'chrome'
- },
- directConnect: true,
- baseUrl: 'http://localhost:4200/',
- framework: 'jasmine',
- jasmineNodeOpts: {
- showColors: true,
- defaultTimeoutInterval: 30000,
- print: function() {}
- },
- onPrepare() {
- require('ts-node').register({
- project: require('path').join(__dirname, './tsconfig.json')
- });
- jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
- }
-};
\ No newline at end of file
diff --git a/cmd/templates/angular-template/frontend/e2e/src/app.e2e-spec.ts b/cmd/templates/angular-template/frontend/e2e/src/app.e2e-spec.ts
deleted file mode 100644
index 3b79f7c47..000000000
--- a/cmd/templates/angular-template/frontend/e2e/src/app.e2e-spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { AppPage } from './app.po';
-import { browser, logging } from 'protractor';
-
-describe('workspace-project App', () => {
- let page: AppPage;
-
- beforeEach(() => {
- page = new AppPage();
- });
-
- it('should display welcome message', () => {
- page.navigateTo();
- expect(page.getTitleText()).toEqual('Welcome to my-app!');
- });
-
- afterEach(async () => {
- // Assert that there are no errors emitted from the browser
- const logs = await browser.manage().logs().get(logging.Type.BROWSER);
- expect(logs).not.toContain(jasmine.objectContaining({
- level: logging.Level.SEVERE,
- } as logging.Entry));
- });
-});
diff --git a/cmd/templates/angular-template/frontend/e2e/src/app.po.ts b/cmd/templates/angular-template/frontend/e2e/src/app.po.ts
deleted file mode 100644
index 5776aa9eb..000000000
--- a/cmd/templates/angular-template/frontend/e2e/src/app.po.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { browser, by, element } from 'protractor';
-
-export class AppPage {
- navigateTo() {
- return browser.get(browser.baseUrl) as Promise;
- }
-
- getTitleText() {
- return element(by.css('app-root h1')).getText() as Promise;
- }
-}
diff --git a/cmd/templates/angular-template/frontend/e2e/tsconfig.json b/cmd/templates/angular-template/frontend/e2e/tsconfig.json
deleted file mode 100644
index 39b800f78..000000000
--- a/cmd/templates/angular-template/frontend/e2e/tsconfig.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/e2e",
- "module": "commonjs",
- "target": "es5",
- "types": [
- "jasmine",
- "jasminewd2",
- "node"
- ]
- }
-}
diff --git a/cmd/templates/angular-template/frontend/karma.conf.js b/cmd/templates/angular-template/frontend/karma.conf.js
deleted file mode 100644
index b0d5cbe01..000000000
--- a/cmd/templates/angular-template/frontend/karma.conf.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Karma configuration file, see link for more information
-// https://karma-runner.github.io/1.0/config/configuration-file.html
-
-module.exports = function (config) {
- config.set({
- basePath: '',
- frameworks: ['jasmine', '@angular-devkit/build-angular'],
- plugins: [
- require('karma-jasmine'),
- require('karma-chrome-launcher'),
- require('karma-jasmine-html-reporter'),
- require('karma-coverage-istanbul-reporter'),
- require('@angular-devkit/build-angular/plugins/karma')
- ],
- client: {
- clearContext: false // leave Jasmine Spec Runner output visible in browser
- },
- coverageIstanbulReporter: {
- dir: require('path').join(__dirname, './coverage/my-app'),
- reports: ['html', 'lcovonly', 'text-summary'],
- fixWebpackSourcePaths: true
- },
- reporters: ['progress', 'kjhtml'],
- port: 9876,
- colors: true,
- logLevel: config.LOG_INFO,
- autoWatch: true,
- browsers: ['Chrome'],
- singleRun: false,
- restartOnFileChange: true
- });
-};
diff --git a/cmd/templates/angular-template/frontend/package.json.template b/cmd/templates/angular-template/frontend/package.json.template
deleted file mode 100644
index ee5c0d053..000000000
--- a/cmd/templates/angular-template/frontend/package.json.template
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "name": "my-app",
- "version": "0.0.0",
- "scripts": {
- "ng": "npx ng",
- "serve": "npx ng serve --poll=2000 --host=0.0.0.0",
- "build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
- "test": "npx ng test",
- "lint": "npx ng lint",
- "e2e": "npx ng e2e"
- },
- "private": true,
- "dependencies": {
- "@angular/animations": "^8.0.2",
- "@angular/cdk": "^8.0.1",
- "@angular/common": "~8.0.1",
- "@angular/compiler": "~8.0.1",
- "@angular/core": "~8.0.1",
- "@angular/forms": "~8.0.1",
- "@angular/material": "^8.0.1",
- "@angular/platform-browser": "~8.0.1",
- "@angular/platform-browser-dynamic": "~8.0.1",
- "@angular/router": "~8.0.1",
- "@wailsapp/runtime": "^1.0.0",
- "core-js": "^3.4.4",
- "ngx-build-plus": "^8.0.3",
- "rxjs": "~6.4.0",
- "tslib": "^1.9.0",
- "zone.js": "~0.9.1"
- },
- "devDependencies": {
- "@angular-devkit/build-angular": "~0.800.0",
- "@angular/cli": "~8.0.3",
- "@angular/compiler-cli": "~8.0.1",
- "@angular/language-service": "~8.0.1",
- "@types/node": "~8.9.4",
- "@types/jasmine": "~3.3.8",
- "@types/jasminewd2": "~2.0.3",
- "codelyzer": "^5.0.0",
- "jasmine-core": "~3.4.0",
- "jasmine-spec-reporter": "~4.2.1",
- "karma": "~4.1.0",
- "karma-chrome-launcher": "~2.2.0",
- "karma-coverage-istanbul-reporter": "~2.0.1",
- "karma-jasmine": "~2.0.1",
- "karma-jasmine-html-reporter": "^1.4.0",
- "protractor": "~5.4.0",
- "ts-node": "~7.0.0",
- "tslint": "~5.15.0",
- "typescript": "~3.4.3"
- }
-}
diff --git a/cmd/templates/angular-template/frontend/src/app/app-routing.module.ts b/cmd/templates/angular-template/frontend/src/app/app-routing.module.ts
deleted file mode 100644
index 249a14a5c..000000000
--- a/cmd/templates/angular-template/frontend/src/app/app-routing.module.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
-
-const routes: Routes = [];
-
-@NgModule({
- imports: [
- RouterModule.forRoot(routes,{useHash:true})
- ],
- exports: [RouterModule]
-})
-
-export class AppRoutingModule { }
diff --git a/cmd/templates/angular-template/frontend/src/app/app.component.css b/cmd/templates/angular-template/frontend/src/app/app.component.css
deleted file mode 100644
index e69de29bb..000000000
diff --git a/cmd/templates/angular-template/frontend/src/app/app.component.html b/cmd/templates/angular-template/frontend/src/app/app.component.html
deleted file mode 100644
index 4a0437517..000000000
--- a/cmd/templates/angular-template/frontend/src/app/app.component.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- Welcome to {{ title }}!
-
-
-
-
-
Hello
-
{{clickMessage}}
-
-
-
diff --git a/cmd/templates/angular-template/frontend/src/app/app.component.spec.ts b/cmd/templates/angular-template/frontend/src/app/app.component.spec.ts
deleted file mode 100644
index 3fe58ce0f..000000000
--- a/cmd/templates/angular-template/frontend/src/app/app.component.spec.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { TestBed, async } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
-import { AppComponent } from './app.component';
-
-describe('AppComponent', () => {
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- imports: [
- RouterTestingModule
- ],
- declarations: [
- AppComponent
- ],
- }).compileComponents();
- }));
-
- it('should create the app', () => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.debugElement.componentInstance;
- expect(app).toBeTruthy();
- });
-
- it(`should have as title 'my-app'`, () => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.debugElement.componentInstance;
- expect(app.title).toEqual('my-app');
- });
-
- it('should render title in a h1 tag', () => {
- const fixture = TestBed.createComponent(AppComponent);
- fixture.detectChanges();
- const compiled = fixture.debugElement.nativeElement;
- expect(compiled.querySelector('h1').textContent).toContain('Welcome to my-app!');
- });
-});
diff --git a/cmd/templates/angular-template/frontend/src/app/app.component.ts b/cmd/templates/angular-template/frontend/src/app/app.component.ts
deleted file mode 100644
index e91b91686..000000000
--- a/cmd/templates/angular-template/frontend/src/app/app.component.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Component } from '@angular/core';
-
-@Component({
- selector: '[id="app"]',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
-})
-export class AppComponent {
- title = 'my-app';
-
- clickMessage = '';
-
- onClickMe() {
- // @ts-ignore
- window.backend.basic().then(result =>
- this.clickMessage = result
- );
- }
-}
diff --git a/cmd/templates/angular-template/frontend/src/app/app.module.ts b/cmd/templates/angular-template/frontend/src/app/app.module.ts
deleted file mode 100644
index 4c082cefe..000000000
--- a/cmd/templates/angular-template/frontend/src/app/app.module.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
-
-import { AppRoutingModule } from './app-routing.module';
-import { AppComponent } from './app.component';
-
-import { APP_BASE_HREF } from '@angular/common';
-
-@NgModule({
- declarations: [
- AppComponent
- ],
- imports: [
- BrowserModule,
- AppRoutingModule
- ],
- providers: [{provide: APP_BASE_HREF, useValue : '/' }],
- bootstrap: [AppComponent]
-})
-export class AppModule { }
diff --git a/cmd/templates/angular-template/frontend/src/assets/.gitkeep b/cmd/templates/angular-template/frontend/src/assets/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/cmd/templates/angular-template/frontend/src/environments/environment.prod.ts b/cmd/templates/angular-template/frontend/src/environments/environment.prod.ts
deleted file mode 100644
index 3612073bc..000000000
--- a/cmd/templates/angular-template/frontend/src/environments/environment.prod.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const environment = {
- production: true
-};
diff --git a/cmd/templates/angular-template/frontend/src/environments/environment.ts b/cmd/templates/angular-template/frontend/src/environments/environment.ts
deleted file mode 100644
index 7b4f817ad..000000000
--- a/cmd/templates/angular-template/frontend/src/environments/environment.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// This file can be replaced during build by using the `fileReplacements` array.
-// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
-// The list of file replacements can be found in `angular.json`.
-
-export const environment = {
- production: false
-};
-
-/*
- * For easier debugging in development mode, you can import the following file
- * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
- *
- * This import should be commented out in production mode because it will have a negative impact
- * on performance if an error is thrown.
- */
-// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/cmd/templates/angular-template/frontend/src/favicon.ico b/cmd/templates/angular-template/frontend/src/favicon.ico
deleted file mode 100644
index 8081c7cea..000000000
Binary files a/cmd/templates/angular-template/frontend/src/favicon.ico and /dev/null differ
diff --git a/cmd/templates/angular-template/frontend/src/index.html.template b/cmd/templates/angular-template/frontend/src/index.html.template
deleted file mode 100644
index df56c4116..000000000
--- a/cmd/templates/angular-template/frontend/src/index.html.template
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-my-app
-
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/angular-template/frontend/src/main.ts b/cmd/templates/angular-template/frontend/src/main.ts
deleted file mode 100644
index 49f44bfbd..000000000
--- a/cmd/templates/angular-template/frontend/src/main.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'core-js/stable';
-import { enableProdMode } from '@angular/core';
-import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
-
-import { AppModule } from './app/app.module';
-import { environment } from './environments/environment';
-
-import 'zone.js'
-
-import * as Wails from '@wailsapp/runtime';
-
-if (environment.production) {
- enableProdMode();
-}
-
-Wails.Init(() => {
- platformBrowserDynamic().bootstrapModule(AppModule)
- .catch(err => console.error(err));
-});
diff --git a/cmd/templates/angular-template/frontend/src/polyfills.ts b/cmd/templates/angular-template/frontend/src/polyfills.ts
deleted file mode 100644
index 22a5df87d..000000000
--- a/cmd/templates/angular-template/frontend/src/polyfills.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * This file includes polyfills needed by Angular and is loaded before the app.
- * You can add your own extra polyfills to this file.
- *
- * This file is divided into 2 sections:
- * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
- * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
- * file.
- *
- * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
- * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
- * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
- *
- * Learn more in https://angular.io/guide/browser-support
- */
-
-/***************************************************************************************************
- * BROWSER POLYFILLS
- */
-
-/** IE10 and IE11 requires the following for NgClass support on SVG elements */
-// import 'classlist.js'; // Run `npm install --save classlist.js`.
-
-/**
- * Web Animations `@angular/platform-browser/animations`
- * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
- * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
- */
-// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
-
-/**
- * By default, zone.js will patch all possible macroTask and DomEvents
- * user can disable parts of macroTask/DomEvents patch by setting following flags
- * because those flags need to be set before `zone.js` being loaded, and webpack
- * will put import in the top of bundle, so user need to create a separate file
- * in this directory (for example: zone-flags.ts), and put the following flags
- * into that file, and then add the following code before importing zone.js.
- * import './zone-flags.ts';
- *
- * The flags allowed in zone-flags.ts are listed here.
- *
- * The following flags will work for all browsers.
- *
- * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
- * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
- * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
- *
- * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
- * with the following flag, it will bypass `zone.js` patch for IE/Edge
- *
- * (window as any).__Zone_enable_cross_context_check = true;
- *
- */
-
-/***************************************************************************************************
- * Zone JS is required by default for Angular itself.
- */
-//import 'zone.js/dist/zone'; // Included with Angular CLI.
-
-
-/***************************************************************************************************
- * APPLICATION IMPORTS
- */
diff --git a/cmd/templates/angular-template/frontend/src/styles.css b/cmd/templates/angular-template/frontend/src/styles.css
deleted file mode 100644
index 4cf0ed8d1..000000000
--- a/cmd/templates/angular-template/frontend/src/styles.css
+++ /dev/null
@@ -1,24 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
- "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-
- background-color: #282c34;
-}
-
-p {
- color: white
-}
-
-h1 {
- color: white
-}
-
-button {
- background-color: white;
- color: black;
-}
diff --git a/cmd/templates/angular-template/frontend/src/test.ts b/cmd/templates/angular-template/frontend/src/test.ts
deleted file mode 100644
index 16317897b..000000000
--- a/cmd/templates/angular-template/frontend/src/test.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'zone.js/dist/zone-testing';
-import { getTestBed } from '@angular/core/testing';
-import {
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
-
-declare const require: any;
-
-// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting()
-);
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().map(context);
diff --git a/cmd/templates/angular-template/frontend/tsconfig.app.json b/cmd/templates/angular-template/frontend/tsconfig.app.json
deleted file mode 100644
index 31f8397ac..000000000
--- a/cmd/templates/angular-template/frontend/tsconfig.app.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "./out-tsc/app",
- "types": []
- },
- "include": [
- "src/**/*.ts"
- ],
- "exclude": [
- "src/test.ts",
- "src/**/*.spec.ts"
- ]
-}
diff --git a/cmd/templates/angular-template/frontend/tsconfig.json b/cmd/templates/angular-template/frontend/tsconfig.json
deleted file mode 100644
index 16195ad5f..000000000
--- a/cmd/templates/angular-template/frontend/tsconfig.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "compileOnSave": false,
- "compilerOptions": {
- "baseUrl": "./",
- "outDir": "./dist/out-tsc",
- "sourceMap": true,
- "declaration": false,
- "downlevelIteration": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "module": "esnext",
- "moduleResolution": "node",
- "importHelpers": true,
- "target": "es5",
- "typeRoots": [
- "node_modules/@types"
- ],
- "lib": [
- "es2018",
- "dom"
- ]
- }
-}
\ No newline at end of file
diff --git a/cmd/templates/angular-template/frontend/tsconfig.spec.json b/cmd/templates/angular-template/frontend/tsconfig.spec.json
deleted file mode 100644
index 6400fde7d..000000000
--- a/cmd/templates/angular-template/frontend/tsconfig.spec.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "./out-tsc/spec",
- "types": [
- "jasmine",
- "node"
- ]
- },
- "files": [
- "src/test.ts",
- "src/polyfills.ts"
- ],
- "include": [
- "src/**/*.spec.ts",
- "src/**/*.d.ts"
- ]
-}
diff --git a/cmd/templates/angular-template/frontend/tslint.json b/cmd/templates/angular-template/frontend/tslint.json
deleted file mode 100644
index 188bd78d3..000000000
--- a/cmd/templates/angular-template/frontend/tslint.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "extends": "tslint:recommended",
- "rules": {
- "array-type": false,
- "arrow-parens": false,
- "deprecation": {
- "severity": "warn"
- },
- "component-class-suffix": true,
- "contextual-lifecycle": true,
- "directive-class-suffix": true,
- "directive-selector": [
- true,
- "attribute",
- "app",
- "camelCase"
- ],
- "component-selector": [
- true,
- "element",
- "app",
- "kebab-case"
- ],
- "import-blacklist": [
- true,
- "rxjs/Rx"
- ],
- "interface-name": false,
- "max-classes-per-file": false,
- "max-line-length": [
- true,
- 140
- ],
- "member-access": false,
- "member-ordering": [
- true,
- {
- "order": [
- "static-field",
- "instance-field",
- "static-method",
- "instance-method"
- ]
- }
- ],
- "no-consecutive-blank-lines": false,
- "no-console": [
- true,
- "debug",
- "info",
- "time",
- "timeEnd",
- "trace"
- ],
- "no-empty": false,
- "no-inferrable-types": [
- true,
- "ignore-params"
- ],
- "no-non-null-assertion": true,
- "no-redundant-jsdoc": true,
- "no-switch-case-fall-through": true,
- "no-use-before-declare": true,
- "no-var-requires": false,
- "object-literal-key-quotes": [
- true,
- "as-needed"
- ],
- "object-literal-sort-keys": false,
- "ordered-imports": false,
- "quotemark": [
- true,
- "single"
- ],
- "trailing-comma": false,
- "no-conflicting-lifecycle": true,
- "no-host-metadata-property": true,
- "no-input-rename": true,
- "no-inputs-metadata-property": true,
- "no-output-native": true,
- "no-output-on-prefix": true,
- "no-output-rename": true,
- "no-outputs-metadata-property": true,
- "template-banana-in-box": true,
- "template-no-negated-async": true,
- "use-lifecycle-interface": true,
- "use-pipe-transform-interface": true
- },
- "rulesDirectory": [
- "codelyzer"
- ]
-}
\ No newline at end of file
diff --git a/cmd/templates/angular-template/go.mod.template b/cmd/templates/angular-template/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/angular-template/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/angular-template/main.go.template b/cmd/templates/angular-template/main.go.template
deleted file mode 100644
index 9f2ae4f3f..000000000
--- a/cmd/templates/angular-template/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "World!"
-}
-
-//go:embed frontend/dist/my-app/main.js
-var js string
-
-//go:embed frontend/dist/my-app/styles.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/angular-template/template.json b/cmd/templates/angular-template/template.json
deleted file mode 100644
index c2b258328..000000000
--- a/cmd/templates/angular-template/template.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "Angular",
- "version": "1.0.0",
- "shortdescription": "Angular 8 template (Requires node 10.8+)",
- "description": "Angular projects w/ @angular/cli - Note: in order to reach the cli use npx like this: npx ng",
- "dependencies": [
- {
- "bin": "npx",
- "help": "This template requires 'npx'. Please install with 'npm install -g npx'"
- }
- ],
- "install": "npm install",
- "build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
- "author": "bh90210 ",
- "created": "2019-06-15 18:23:48.666414555 +0300 EEST m=+223.934866008",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": ""
-}
\ No newline at end of file
diff --git a/cmd/templates/create-react-app/.jshint b/cmd/templates/create-react-app/.jshint
deleted file mode 100644
index 0557edf11..000000000
--- a/cmd/templates/create-react-app/.jshint
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "esversion": 6
-}
\ No newline at end of file
diff --git a/cmd/templates/create-react-app/frontend/.gitignore b/cmd/templates/create-react-app/frontend/.gitignore
deleted file mode 100644
index 4d29575de..000000000
--- a/cmd/templates/create-react-app/frontend/.gitignore
+++ /dev/null
@@ -1,23 +0,0 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
-/node_modules
-/.pnp
-.pnp.js
-
-# testing
-/coverage
-
-# production
-/build
-
-# misc
-.DS_Store
-.env.local
-.env.development.local
-.env.test.local
-.env.production.local
-
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
diff --git a/cmd/templates/create-react-app/frontend/README.md b/cmd/templates/create-react-app/frontend/README.md
deleted file mode 100644
index 9d9614c4f..000000000
--- a/cmd/templates/create-react-app/frontend/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
-
-## Available Scripts
-
-In the project directory, you can run:
-
-### `npm start`
-
-Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
-
-The page will reload if you make edits.
-You will also see any lint errors in the console.
-
-### `npm test`
-
-Launches the test runner in the interactive watch mode.
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
-
-### `npm run build`
-
-Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance.
-
-The build is minified and the filenames include the hashes.
-Your app is ready to be deployed!
-
-See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
-
-### `npm run eject`
-
-**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
-
-If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
-
-Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
-
-You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
-
-## Learn More
-
-You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
-
-To learn React, check out the [React documentation](https://reactjs.org/).
-
-### Code Splitting
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
-
-### Analyzing the Bundle Size
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
-
-### Making a Progressive Web App
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
-
-### Advanced Configuration
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
-
-### Deployment
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
-
-### `npm run build` fails to minify
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
diff --git a/cmd/templates/create-react-app/frontend/package.json.template b/cmd/templates/create-react-app/frontend/package.json.template
deleted file mode 100644
index a940d3d17..000000000
--- a/cmd/templates/create-react-app/frontend/package.json.template
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "version": "0.1.0",
- "private": true,
- "dependencies": {
- "core-js": "^3.6.4",
- "react": "^16.13.1",
- "react-dom": "^16.13.1",
- "wails-react-scripts": "3.0.1-2",
- "react-modal": "3.11.2",
- "@wailsapp/runtime": "^1.0.10"
- },
- "scripts": {
- "serve": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
- "eject": "react-scripts eject"
- },
- "eslintConfig": {
- "extends": "react-app"
- },
- "browserslist": {
- "production": [
- ">0.2%",
- "not dead",
- "not op_mini all"
- ],
- "development": [
- "last 1 chrome version",
- "last 1 firefox version",
- "last 1 safari version"
- ]
- }
-}
diff --git a/cmd/templates/create-react-app/frontend/public/favicon.ico b/cmd/templates/create-react-app/frontend/public/favicon.ico
deleted file mode 100644
index bcd5dfd67..000000000
Binary files a/cmd/templates/create-react-app/frontend/public/favicon.ico and /dev/null differ
diff --git a/cmd/templates/create-react-app/frontend/public/index.html b/cmd/templates/create-react-app/frontend/public/index.html
deleted file mode 100644
index 4bf3c2570..000000000
--- a/cmd/templates/create-react-app/frontend/public/index.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- React App
-
-
-
- You need to enable JavaScript to run this app.
-
-
-
-
-
\ No newline at end of file
diff --git a/cmd/templates/create-react-app/frontend/public/logo192.png b/cmd/templates/create-react-app/frontend/public/logo192.png
deleted file mode 100644
index b0c28d8f5..000000000
Binary files a/cmd/templates/create-react-app/frontend/public/logo192.png and /dev/null differ
diff --git a/cmd/templates/create-react-app/frontend/public/logo512.png b/cmd/templates/create-react-app/frontend/public/logo512.png
deleted file mode 100644
index 867231742..000000000
Binary files a/cmd/templates/create-react-app/frontend/public/logo512.png and /dev/null differ
diff --git a/cmd/templates/create-react-app/frontend/public/manifest.json b/cmd/templates/create-react-app/frontend/public/manifest.json
deleted file mode 100644
index 080d6c77a..000000000
--- a/cmd/templates/create-react-app/frontend/public/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "short_name": "React App",
- "name": "Create React App Sample",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff"
-}
diff --git a/cmd/templates/create-react-app/frontend/public/robots.txt b/cmd/templates/create-react-app/frontend/public/robots.txt
deleted file mode 100644
index e9e57dc4d..000000000
--- a/cmd/templates/create-react-app/frontend/public/robots.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# https://www.robotstxt.org/robotstxt.html
-User-agent: *
-Disallow:
diff --git a/cmd/templates/create-react-app/frontend/src/App.css b/cmd/templates/create-react-app/frontend/src/App.css
deleted file mode 100644
index 74b5e0534..000000000
--- a/cmd/templates/create-react-app/frontend/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/cmd/templates/create-react-app/frontend/src/App.js b/cmd/templates/create-react-app/frontend/src/App.js
deleted file mode 100644
index 3c6bc564c..000000000
--- a/cmd/templates/create-react-app/frontend/src/App.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import React from 'react';
-import logo from './logo.png';
-import './App.css';
-import HelloWorld from './components/HelloWorld';
-
-function App() {
- return (
-
- );
-}
-
-export default App;
diff --git a/cmd/templates/create-react-app/frontend/src/App.test.js b/cmd/templates/create-react-app/frontend/src/App.test.js
deleted file mode 100644
index a754b201b..000000000
--- a/cmd/templates/create-react-app/frontend/src/App.test.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import App from './App';
-
-it('renders without crashing', () => {
- const div = document.createElement('div');
- ReactDOM.render( , div);
- ReactDOM.unmountComponentAtNode(div);
-});
diff --git a/cmd/templates/create-react-app/frontend/src/components/HelloWorld.js b/cmd/templates/create-react-app/frontend/src/components/HelloWorld.js
deleted file mode 100644
index 26be1aea1..000000000
--- a/cmd/templates/create-react-app/frontend/src/components/HelloWorld.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, { useState } from 'react';
-import Modal from 'react-modal';
-
-function HelloWorld() {
- const [showModal, setShowModal] = useState(false);
- const [result, setResult] = useState(null);
-
- const handleOpenModal = () => {
- setShowModal(true);
-
- window.backend.basic().then((result) => setResult(result));
- };
-
- const handleCloseModal = () => {
- setShowModal(false);
- };
-
- return (
-
-
handleOpenModal()} type="button">
- Hello
-
-
- {result}
- handleCloseModal()}>Close Modal
-
-
- );
-}
-
-export default HelloWorld;
diff --git a/cmd/templates/create-react-app/frontend/src/index.css b/cmd/templates/create-react-app/frontend/src/index.css
deleted file mode 100644
index 4a1df4db7..000000000
--- a/cmd/templates/create-react-app/frontend/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
- "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
- monospace;
-}
diff --git a/cmd/templates/create-react-app/frontend/src/index.js b/cmd/templates/create-react-app/frontend/src/index.js
deleted file mode 100644
index 4e64f604e..000000000
--- a/cmd/templates/create-react-app/frontend/src/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import 'core-js/stable';
-import './index.css';
-import App from './App';
-import * as serviceWorker from './serviceWorker';
-
-import * as Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- ReactDOM.render(
-
-
- ,
- document.getElementById("app")
- );
-});
-
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: https://bit.ly/CRA-PWA
-serviceWorker.unregister();
diff --git a/cmd/templates/create-react-app/frontend/src/logo.png b/cmd/templates/create-react-app/frontend/src/logo.png
deleted file mode 100644
index 519867396..000000000
Binary files a/cmd/templates/create-react-app/frontend/src/logo.png and /dev/null differ
diff --git a/cmd/templates/create-react-app/frontend/src/serviceWorker.js b/cmd/templates/create-react-app/frontend/src/serviceWorker.js
deleted file mode 100644
index f8c7e50c2..000000000
--- a/cmd/templates/create-react-app/frontend/src/serviceWorker.js
+++ /dev/null
@@ -1,135 +0,0 @@
-// This optional code is used to register a service worker.
-// register() is not called by default.
-
-// This lets the app load faster on subsequent visits in production, and gives
-// it offline capabilities. However, it also means that developers (and users)
-// will only see deployed updates on subsequent visits to a page, after all the
-// existing tabs open on the page have been closed, since previously cached
-// resources are updated in the background.
-
-// To learn more about the benefits of this model and instructions on how to
-// opt-in, read https://bit.ly/CRA-PWA
-
-const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.1/8 is considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
- )
-);
-
-export function register(config) {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
- // The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebook/create-react-app/issues/2374
- return;
- }
-
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
-
- if (isLocalhost) {
- // This is running on localhost. Let's check if a service worker still exists or not.
- checkValidServiceWorker(swUrl, config);
-
- // Add some additional logging to localhost, pointing developers to the
- // service worker/PWA documentation.
- navigator.serviceWorker.ready.then(() => {
- console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
- );
- });
- } else {
- // Is not localhost. Just register service worker
- registerValidSW(swUrl, config);
- }
- });
- }
-}
-
-function registerValidSW(swUrl, config) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- if (installingWorker == null) {
- return;
- }
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the updated precached content has been fetched,
- // but the previous service worker will still serve the older
- // content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
- );
-
- // Execute callback
- if (config && config.onUpdate) {
- config.onUpdate(registration);
- }
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
-
- // Execute callback
- if (config && config.onSuccess) {
- config.onSuccess(registration);
- }
- }
- }
- };
- };
- })
- .catch(error => {
- console.error('Error during service worker registration:', error);
- });
-}
-
-function checkValidServiceWorker(swUrl, config) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl)
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- const contentType = response.headers.get('content-type');
- if (
- response.status === 404 ||
- (contentType != null && contentType.indexOf('javascript') === -1)
- ) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload();
- });
- });
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl, config);
- }
- })
- .catch(() => {
- console.log(
- 'No internet connection found. App is running in offline mode.'
- );
- });
-}
-
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister();
- });
- }
-}
diff --git a/cmd/templates/create-react-app/go.mod.template b/cmd/templates/create-react-app/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/create-react-app/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/create-react-app/main.go.template b/cmd/templates/create-react-app/main.go.template
deleted file mode 100644
index d6d1be03e..000000000
--- a/cmd/templates/create-react-app/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "World!"
-}
-
-//go:embed frontend/build/static/js/main.js
-var js string
-
-//go:embed frontend/build/static/css/main.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/create-react-app/template.json b/cmd/templates/create-react-app/template.json
deleted file mode 100755
index ea6acbed2..000000000
--- a/cmd/templates/create-react-app/template.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "React JS",
- "version": "1.0.0",
- "shortdescription": "Create React App v4 template",
- "description": "Create React App v4 standard tooling",
- "install": "npm install",
- "build": "npm run build",
- "author": "bh90210 ",
- "created": "2019-06-07 18:23:48.666414555 +0300 EEST m=+223.934866008",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": ""
-}
diff --git a/cmd/templates/svelte/frontend/.gitignore b/cmd/templates/svelte/frontend/.gitignore
deleted file mode 100644
index da93220bc..000000000
--- a/cmd/templates/svelte/frontend/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/node_modules/
-/public/build/
-
-.DS_Store
diff --git a/cmd/templates/svelte/frontend/README.md b/cmd/templates/svelte/frontend/README.md
deleted file mode 100644
index 360f27156..000000000
--- a/cmd/templates/svelte/frontend/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-*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`.
-
-
-## 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"
-```
-
-## 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
-```
diff --git a/cmd/templates/svelte/frontend/package.json.template b/cmd/templates/svelte/frontend/package.json.template
deleted file mode 100644
index d833ead13..000000000
--- a/cmd/templates/svelte/frontend/package.json.template
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "scripts": {
- "build": "rollup -c",
- "serve": "rollup -c -w",
- "start": "sirv public"
- },
- "devDependencies": {
- "@babel/core": "^7.11.6",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-transform-runtime": "^7.11.5",
- "@babel/preset-env": "^7.11.5",
- "@rollup/plugin-commonjs": "^14.0.0",
- "@rollup/plugin-image": "^2.0.5",
- "@rollup/plugin-node-resolve": "^8.0.0",
- "core-js": "^3.6.5",
- "rollup": "^2.3.4",
- "rollup-plugin-babel": "^4.4.0",
- "rollup-plugin-livereload": "^2.0.0",
- "rollup-plugin-polyfill": "^3.0.0",
- "rollup-plugin-svelte": "^6.0.0",
- "rollup-plugin-terser": "^7.0.0",
- "svelte": "^3.0.0"
- },
- "dependencies": {
- "sirv-cli": "^1.0.0",
- "@wailsapp/runtime": "^1.0.10",
- "svelte-simple-modal": "^0.6.0"
- }
-}
diff --git a/cmd/templates/svelte/frontend/public/favicon.png b/cmd/templates/svelte/frontend/public/favicon.png
deleted file mode 100644
index 90c84247d..000000000
Binary files a/cmd/templates/svelte/frontend/public/favicon.png and /dev/null differ
diff --git a/cmd/templates/svelte/frontend/public/index.html b/cmd/templates/svelte/frontend/public/index.html
deleted file mode 100644
index a9c8fd65d..000000000
--- a/cmd/templates/svelte/frontend/public/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
- Svelte app
-
-
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/svelte/frontend/rollup.config.js b/cmd/templates/svelte/frontend/rollup.config.js
deleted file mode 100644
index 6d0a0a12d..000000000
--- a/cmd/templates/svelte/frontend/rollup.config.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import svelte from 'rollup-plugin-svelte';
-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 image from '@rollup/plugin-image';
-import babel from 'rollup-plugin-babel';
-import polyfill from 'rollup-plugin-polyfill';
-
-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: 'public/build/bundle.js'
- },
- plugins: [
- image(),
- svelte({
- // enable run-time checks when not in production
- dev: !production,
- // we'll extract any component CSS out into
- // a separate file - better for performance
- css: css => {
- css.write('bundle.css');
- }
- }),
-
- // 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', 'svelte/transition', 'svelte/internal']
- }),
- commonjs(),
-
- // 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('public'),
-
- // Credit: https://blog.az.sg/posts/svelte-and-ie11/
- babel({
- extensions: [ '.js', '.jsx', '.es6', '.es', '.mjs', '.svelte', '.html' ],
- runtimeHelpers: true,
- exclude: [ 'node_modules/@babel/**', 'node_modules/core-js/**' ],
- presets: [
- [
- '@babel/preset-env',
- {
- targets: '> 0.25%, not dead, IE 11',
- modules: false,
- useBuiltIns: 'usage',
- forceAllTransforms: true,
- corejs: 3,
- },
-
- ]
- ],
- plugins: [
- '@babel/plugin-syntax-dynamic-import',
- [
- '@babel/plugin-transform-runtime',
- {
- useESModules: true
- }
- ]
- ]
- }),
- polyfill(['@webcomponents/webcomponentsjs']),
-
- // If we're building for production (npm run build
- // instead of npm run dev), minify
- production && terser()
- ],
- watch: {
- clearScreen: false
- }
-};
diff --git a/cmd/templates/svelte/frontend/src/App.svelte b/cmd/templates/svelte/frontend/src/App.svelte
deleted file mode 100644
index dbc1c3ecc..000000000
--- a/cmd/templates/svelte/frontend/src/App.svelte
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/cmd/templates/svelte/frontend/src/components/HelloWorld.svelte b/cmd/templates/svelte/frontend/src/components/HelloWorld.svelte
deleted file mode 100644
index 10948498d..000000000
--- a/cmd/templates/svelte/frontend/src/components/HelloWorld.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- Hello
-
-
-
\ No newline at end of file
diff --git a/cmd/templates/svelte/frontend/src/components/ModalContent.svelte b/cmd/templates/svelte/frontend/src/components/ModalContent.svelte
deleted file mode 100644
index 37ce80fbb..000000000
--- a/cmd/templates/svelte/frontend/src/components/ModalContent.svelte
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- {message}
-
\ No newline at end of file
diff --git a/cmd/templates/svelte/frontend/src/logo.png b/cmd/templates/svelte/frontend/src/logo.png
deleted file mode 100644
index 519867396..000000000
Binary files a/cmd/templates/svelte/frontend/src/logo.png and /dev/null differ
diff --git a/cmd/templates/svelte/frontend/src/main.js b/cmd/templates/svelte/frontend/src/main.js
deleted file mode 100644
index 2646517ec..000000000
--- a/cmd/templates/svelte/frontend/src/main.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import App from './App.svelte';
-
-import * as Wails from '@wailsapp/runtime';
-
-let app;
-
-Wails.Init(() => {
- app = new App({
- target: document.body,
- });
-});
-
-export default app;
\ No newline at end of file
diff --git a/cmd/templates/svelte/go.mod.template b/cmd/templates/svelte/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/svelte/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/svelte/main.go.template b/cmd/templates/svelte/main.go.template
deleted file mode 100644
index 238d947cc..000000000
--- a/cmd/templates/svelte/main.go.template
+++ /dev/null
@@ -1,31 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "World!"
-}
-
-//go:embed frontend/public/build/bundle.js
-var js string
-
-//go:embed frontend/public/build/bundle.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
-
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/svelte/template.json b/cmd/templates/svelte/template.json
deleted file mode 100755
index dea6ed191..000000000
--- a/cmd/templates/svelte/template.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "Svelte",
- "version": "1.0.0",
- "shortdescription": "A basic Svelte template",
- "description": "A basic Svelte template",
- "install": "npm install",
- "build": "npm run build",
- "author": "Tim Kipp ",
- "created": "2020-09-06 13:06:10.469848 -0700 PDT m=+213.578828559",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": ""
-}
diff --git a/cmd/templates/vanilla/README.md b/cmd/templates/vanilla/README.md
deleted file mode 100644
index 4762fa49c..000000000
--- a/cmd/templates/vanilla/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# README
-
-This is an experimental template for vanilla HTML/JS/CSS.
-
-The webpack rules may need to be adjusted to correctly embed all assets. Babel may also need to be setup correctly.
\ No newline at end of file
diff --git a/cmd/templates/vanilla/counter.go b/cmd/templates/vanilla/counter.go
deleted file mode 100644
index ec93892cf..000000000
--- a/cmd/templates/vanilla/counter.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package main
-
-import (
- "math/rand"
-
- "github.com/wailsapp/wails"
-)
-
-// Counter is what we use for counting
-type Counter struct {
- r *wails.Runtime
- store *wails.Store
-}
-
-// WailsInit is called when the component is being initialised
-func (c *Counter) WailsInit(runtime *wails.Runtime) error {
- c.r = runtime
- c.store = runtime.Store.New("Counter", 0)
- return nil
-}
-
-// RandomValue sets the counter to a random value
-func (c *Counter) RandomValue() {
- c.store.Set(rand.Intn(1000))
-}
-
-// Increment will increment the counter
-func (c *Counter) Increment() {
-
- increment := func(data int) int {
- return data + 1
- }
-
- // Update the store using the increment function
- c.store.Update(increment)
-}
-
-// Decrement will decrement the counter
-func (c *Counter) Decrement() {
-
- decrement := func(data int) int {
- return data - 1
- }
- // Update the store using the decrement function
- c.store.Update(decrement)
-}
diff --git a/cmd/templates/vanilla/frontend/package.json.template b/cmd/templates/vanilla/frontend/package.json.template
deleted file mode 100644
index 174e5ac93..000000000
--- a/cmd/templates/vanilla/frontend/package.json.template
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "name": "vanilla",
- "author": "Lea",
- "private": true,
- "scripts": {
- "serve": "webpack-dev-server",
- "build": "npx webpack"
- },
- "dependencies": {
- "core-js": "^3.6.4",
- "regenerator-runtime": "^0.13.3",
- "@wailsapp/runtime": "^1.0.10"
- },
- "devDependencies": {
- "babel-eslint": "^10.1.0",
- "copy-webpack-plugin": "^6.0.2",
- "eslint": "^6.8.0",
- "eventsource-polyfill": "^0.9.6",
- "webpack": "^4.43.0",
- "webpack-cli": "^3.3.11",
- "webpack-dev-server": "^3.11.0",
- "webpack-hot-middleware": "^2.25.0"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "eslint:recommended"
- ],
- "rules": {},
- "parserOptions": {
- "parser": "babel-eslint"
- }
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not ie <= 8"
- ]
-}
diff --git a/cmd/templates/vanilla/frontend/src/index.html b/cmd/templates/vanilla/frontend/src/index.html
deleted file mode 100644
index c7eb55539..000000000
--- a/cmd/templates/vanilla/frontend/src/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/cmd/templates/vanilla/frontend/src/main.css b/cmd/templates/vanilla/frontend/src/main.css
deleted file mode 100644
index cbfc4313a..000000000
--- a/cmd/templates/vanilla/frontend/src/main.css
+++ /dev/null
@@ -1,45 +0,0 @@
-
-html,
-body {
- background-color: white;
- color: black;
- width: 100%;
- height: 100%;
- margin: 0;
-}
-
-input {
- background-color: rgb(254,254,254);
- color: black;
-}
-
-.container {
- display: block;
- width:100%;
- text-align: center;
- margin-top: 1rem;
- font-size: 2rem;
-}
-
-button {
- font-size: 1rem;
- background-color: white;
- color: black;
-}
-
-.result {
- margin-top: 1rem;
- text-align: center;
- font-size: 2rem;
-}
-
-.logo {
- display: block;
- margin-left: auto;
- margin-right: auto;
- width: 50%;
- height: 50%;
- background-image: url(data:image/png;base64,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);
- background-size: cover;
- background-position: 50% center;
-}
diff --git a/cmd/templates/vanilla/frontend/src/main.js b/cmd/templates/vanilla/frontend/src/main.js
deleted file mode 100644
index 609e55e43..000000000
--- a/cmd/templates/vanilla/frontend/src/main.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import 'core-js/stable';
-const runtime = require('@wailsapp/runtime');
-
-// Main entry point
-function start() {
-
- var mystore = runtime.Store.New('Counter');
-
- // Ensure the default app div is 100% wide/high
- var app = document.getElementById('app');
- app.style.width = '100%';
- app.style.height = '100%';
-
- // Inject html
- app.innerHTML = `
-
-
-
- Increment Counter
-
-
- Decrement Counter
-
-
- Counter:
-
-
- Set Counter Value
- Set to Random Value
-
- `;
-
- // Connect counter value button to Go method
- document.getElementById('setvalue').onclick = function() {
- let newValue = parseInt(document.getElementById('newCounter').value,10);
- mystore.set(newValue);
- };
-
- mystore.subscribe( function(state) {
- document.getElementById('counter').innerText = state;
- });
-
- mystore.set(0);
-};
-
-// We provide our entrypoint as a callback for runtime.Init
-runtime.Init(start);
\ No newline at end of file
diff --git a/cmd/templates/vanilla/frontend/webpack.config.js b/cmd/templates/vanilla/frontend/webpack.config.js
deleted file mode 100644
index c5490acce..000000000
--- a/cmd/templates/vanilla/frontend/webpack.config.js
+++ /dev/null
@@ -1,56 +0,0 @@
-const path = require('path');
-const CopyWebpackPlugin = require('copy-webpack-plugin');
-
-let imageSizeLimit = 9007199254740991; // Number.MAX_SAFE_INTEGER
-let sourceDir = path.resolve(__dirname, 'src');
-let buildDir = path.resolve(__dirname, 'build');
-
-module.exports = {
- entry: {
- index: path.resolve(sourceDir, 'main.js')
- },
- output: {
- path: buildDir,
- filename: 'main.js'
- },
- optimization: {
- splitChunks: false
- },
- devServer: {
- disableHostCheck: true,
- contentBase: path.join(__dirname, 'src'),
- compress: true,
- open: true,
- port: 8090
- },
- mode: 'production',
- module: {
- rules: [
- {
- test: /\.(png|gif|jpg|woff2?|eot|ttf|otf|svg)(\?.*)?$/i,
- use: [
- {
- loader: 'url-loader',
- options: {
- limit: imageSizeLimit
- }
- }
- ],
- }
- ]
- },
- plugins: [
- new CopyWebpackPlugin({
- patterns: [
- {
- from: path.resolve(sourceDir, 'main.css'),
- to: path.resolve(buildDir, 'main.css')
- },
- {
- from: path.resolve(sourceDir, 'index.html'),
- to: path.resolve(buildDir, 'index.html')
- },
- ]
- })
- ]
-};
diff --git a/cmd/templates/vanilla/go.mod.template b/cmd/templates/vanilla/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vanilla/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vanilla/main.go.template b/cmd/templates/vanilla/main.go.template
deleted file mode 100644
index e4dbbbc00..000000000
--- a/cmd/templates/vanilla/main.go.template
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-//go:embed frontend/build/main.js
-var js string
-
-//go:embed frontend/build/main.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(&Counter{})
- app.Run()
-}
diff --git a/cmd/templates/vanilla/template.json b/cmd/templates/vanilla/template.json
deleted file mode 100644
index 2bad445ef..000000000
--- a/cmd/templates/vanilla/template.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "Vanilla",
- "shortdescription": "A Vanilla HTML/JS template",
- "description": "A basic template using plain html/js and bundled using Webpack 4",
- "author": "Lea Anthony",
- "created": "2020-06-14",
- "frontenddir": "frontend",
- "install": "npm install",
- "build": "npm run build",
- "serve": "npm run serve",
- "bridge": "src"
-}
diff --git a/cmd/templates/vue3-full/frontend/.browserslistrc b/cmd/templates/vue3-full/frontend/.browserslistrc
deleted file mode 100644
index 214388fe4..000000000
--- a/cmd/templates/vue3-full/frontend/.browserslistrc
+++ /dev/null
@@ -1,3 +0,0 @@
-> 1%
-last 2 versions
-not dead
diff --git a/cmd/templates/vue3-full/frontend/.eslintrc.js b/cmd/templates/vue3-full/frontend/.eslintrc.js
deleted file mode 100644
index bf594a121..000000000
--- a/cmd/templates/vue3-full/frontend/.eslintrc.js
+++ /dev/null
@@ -1,29 +0,0 @@
-module.exports = {
- root: true,
- env: {
- node: true
- },
- 'extends': [
- 'plugin:vue/vue3-essential',
- 'eslint:recommended',
- '@vue/typescript/recommended'
- ],
- parserOptions: {
- ecmaVersion: 2020
- },
- rules: {
- 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
- 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
- },
- overrides: [
- {
- files: [
- '**/__tests__/*.{j,t}s?(x)',
- '**/tests/unit/**/*.spec.{j,t}s?(x)'
- ],
- env: {
- mocha: true
- }
- }
- ]
-}
diff --git a/cmd/templates/vue3-full/frontend/.gitignore b/cmd/templates/vue3-full/frontend/.gitignore
deleted file mode 100644
index 185e66319..000000000
--- a/cmd/templates/vue3-full/frontend/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw*
diff --git a/cmd/templates/vue3-full/frontend/README.md b/cmd/templates/vue3-full/frontend/README.md
deleted file mode 100644
index 6953f66d0..000000000
--- a/cmd/templates/vue3-full/frontend/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# vue basic
-
-## Project setup
-
-```
-npm install
-```
-
-### Compiles and hot-reloads for development
-
-```
-npm run serve
-```
-
-### Compiles and minifies for production
-
-```
-npm run build
-```
-
-### Run your tests
-
-```
-npm run test
-```
-
-### Lints and fixes files
-
-```
-npm run lint
-```
-
-### Customize configuration
-
-See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/cmd/templates/vue3-full/frontend/package.json.template b/cmd/templates/vue3-full/frontend/package.json.template
deleted file mode 100644
index dc7eef41e..000000000
--- a/cmd/templates/vue3-full/frontend/package.json.template
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "private": true,
- "scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "test:unit": "vue-cli-service test:unit",
- "lint": "vue-cli-service lint"
- },
- "dependencies": {
- "vue": "^3.0.0-0",
- "vue-router": "^4.0.0-0",
- "regenerator-runtime": "^0.13.7",
- "@wailsapp/runtime": "^1.1.1"
- },
- "devDependencies": {
- "@types/chai": "^4.2.12",
- "@types/mocha": "^8.0.3",
- "@typescript-eslint/eslint-plugin": "^4.3.0",
- "@typescript-eslint/parser": "^4.3.0",
- "@vue/cli-plugin-eslint": "~4.5.9",
- "@vue/cli-plugin-router": "~4.5.9",
- "@vue/cli-plugin-typescript": "~4.5.9",
- "@vue/cli-plugin-unit-mocha": "~4.5.9",
- "@vue/cli-service": "~4.5.9",
- "@vue/compiler-sfc": "^3.0.0",
- "@vue/eslint-config-typescript": "^7.0.0",
- "@vue/test-utils": "^2.0.0-0",
- "chai": "^4.2.0",
- "eslint": "<7.0.0",
- "eslint-plugin-vue": "^7.0.0",
- "node-sass": "^4.14.1",
- "sass-loader": "^10.0.2",
- "typescript": "~4.0.3"
- }
-}
diff --git a/cmd/templates/vue3-full/frontend/src/App.vue b/cmd/templates/vue3-full/frontend/src/App.vue
deleted file mode 100644
index 6939bbb9b..000000000
--- a/cmd/templates/vue3-full/frontend/src/App.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
diff --git a/cmd/templates/vue3-full/frontend/src/assets/appicon.png b/cmd/templates/vue3-full/frontend/src/assets/appicon.png
deleted file mode 100644
index 95e14df6e..000000000
Binary files a/cmd/templates/vue3-full/frontend/src/assets/appicon.png and /dev/null differ
diff --git a/cmd/templates/vue3-full/frontend/src/components/HelloWorld.vue b/cmd/templates/vue3-full/frontend/src/components/HelloWorld.vue
deleted file mode 100644
index 92d381cd8..000000000
--- a/cmd/templates/vue3-full/frontend/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
{{ msg }}
-
-
-
-
-
-
-
diff --git a/cmd/templates/vue3-full/frontend/src/main.ts b/cmd/templates/vue3-full/frontend/src/main.ts
deleted file mode 100644
index 0d2c5a90b..000000000
--- a/cmd/templates/vue3-full/frontend/src/main.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { createApp } from 'vue';
-import App from './App.vue';
-import router from './router';
-import * as Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- createApp(App).use(router).mount('#app');
-});
diff --git a/cmd/templates/vue3-full/frontend/src/router/index.ts b/cmd/templates/vue3-full/frontend/src/router/index.ts
deleted file mode 100644
index 73c740289..000000000
--- a/cmd/templates/vue3-full/frontend/src/router/index.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { createRouter, createMemoryHistory, RouteRecordRaw } from 'vue-router'
-import Home from '../views/Home.vue'
-import About from '../views/About.vue'
-
-const routes: Array = [
- {
- path: '/',
- name: 'Home',
- component: Home
- },
- {
- path: '/about',
- name: 'About',
- // route level code-splitting
- // this generates a separate chunk (about.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- // component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
- component: About
- }
-]
-
-const router = createRouter({
- history: createMemoryHistory(),
- routes
-})
-
-export default router
diff --git a/cmd/templates/vue3-full/frontend/src/shims-vue.d.ts b/cmd/templates/vue3-full/frontend/src/shims-vue.d.ts
deleted file mode 100644
index 32a1b5cd4..000000000
--- a/cmd/templates/vue3-full/frontend/src/shims-vue.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-declare module '*.vue' {
- import { defineComponent } from 'vue'
- const component: ReturnType
- export default component
-}
diff --git a/cmd/templates/vue3-full/frontend/src/views/About.vue b/cmd/templates/vue3-full/frontend/src/views/About.vue
deleted file mode 100644
index 3fa28070d..000000000
--- a/cmd/templates/vue3-full/frontend/src/views/About.vue
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
This is an about page
-
-
diff --git a/cmd/templates/vue3-full/frontend/src/views/Home.vue b/cmd/templates/vue3-full/frontend/src/views/Home.vue
deleted file mode 100644
index cc6aac4cb..000000000
--- a/cmd/templates/vue3-full/frontend/src/views/Home.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vue3-full/frontend/tests/unit/example.spec.ts b/cmd/templates/vue3-full/frontend/tests/unit/example.spec.ts
deleted file mode 100644
index bbb728f18..000000000
--- a/cmd/templates/vue3-full/frontend/tests/unit/example.spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { expect } from 'chai';
-import { describe, it } from 'mocha';
-import { shallowMount } from '@vue/test-utils';
-import HelloWorld from '@/components/HelloWorld.vue';
-
-describe('HelloWorld.vue', () => {
- it('renders props.msg when passed', () => {
- const msg = 'new message';
- const wrapper = shallowMount(HelloWorld, {
- props: { msg }
- });
- expect(wrapper.text()).to.include(msg);
- });
-});
diff --git a/cmd/templates/vue3-full/frontend/tsconfig.json b/cmd/templates/vue3-full/frontend/tsconfig.json
deleted file mode 100644
index e4ba95a15..000000000
--- a/cmd/templates/vue3-full/frontend/tsconfig.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "compilerOptions": {
- "target": "es5",
- "module": "esnext",
- "strict": true,
- "jsx": "preserve",
- "importHelpers": true,
- "moduleResolution": "node",
- "skipLibCheck": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "sourceMap": true,
- "baseUrl": ".",
- "types": [
- "webpack-env",
- "mocha",
- "chai"
- ],
- "paths": {
- "@/*": [
- "src/*"
- ]
- },
- "lib": [
- "esnext",
- "dom",
- "dom.iterable",
- "scripthost"
- ]
- },
- "include": [
- "src/**/*.ts",
- "src/**/*.tsx",
- "src/**/*.vue",
- "tests/**/*.ts",
- "tests/**/*.tsx"
- ],
- "exclude": [
- "node_modules"
- ]
-}
diff --git a/cmd/templates/vue3-full/frontend/vue.config.js b/cmd/templates/vue3-full/frontend/vue.config.js
deleted file mode 100644
index 8dcf3e339..000000000
--- a/cmd/templates/vue3-full/frontend/vue.config.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let cssConfig = {};
-
-if (process.env.NODE_ENV == 'production') {
- cssConfig = {
- extract: {
- filename: '[name].css',
- chunkFilename: '[name].css'
- }
- };
-}
-
-module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule('images')
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .tap(options => Object.assign(options, { limit: limit }));
- config.module
- .rule('fonts')
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: '[name].js'
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
-};
diff --git a/cmd/templates/vue3-full/go.mod.template b/cmd/templates/vue3-full/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vue3-full/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vue3-full/main.go.template b/cmd/templates/vue3-full/main.go.template
deleted file mode 100644
index 5c5453943..000000000
--- a/cmd/templates/vue3-full/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "Hello World!"
-}
-
-//go:embed frontend/dist/app.js
-var js string
-
-//go:embed frontend/dist/app.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/vue3-full/template.json b/cmd/templates/vue3-full/template.json
deleted file mode 100755
index a4e0cb520..000000000
--- a/cmd/templates/vue3-full/template.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "name": "Vue3 Full",
- "version": "1.0.0",
- "shortdescription": "Vue 3, Vuex, Vue-router, and Webpack4",
- "description": "Vue3.0.0 Vuex, Vue-router, and Webpack 4",
- "install": "npm install",
- "build": "npm run build",
- "author": "Kyle Muchmore ",
- "created": "2020-09-24 21:18:55.09417 +0000 UTC m=+90.125590001",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": "",
- "platforms": ["linux", "darwin"]
-}
diff --git a/cmd/templates/vue3-js/frontend/.gitignore b/cmd/templates/vue3-js/frontend/.gitignore
deleted file mode 100644
index 403adbc1e..000000000
--- a/cmd/templates/vue3-js/frontend/.gitignore
+++ /dev/null
@@ -1,23 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/cmd/templates/vue3-js/frontend/README.md b/cmd/templates/vue3-js/frontend/README.md
deleted file mode 100644
index f56df6be7..000000000
--- a/cmd/templates/vue3-js/frontend/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# vue-js
-
-## Project setup
-
-```
-npm install
-```
-
-### Compiles and hot-reloads for development
-
-```
-npm run serve
-```
-
-### Compiles and minifies for production
-
-```
-npm run build
-```
-
-### Lints and fixes files
-
-```
-npm run lint
-```
-
-### Customize configuration
-
-See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/cmd/templates/vue3-js/frontend/babel.config.js b/cmd/templates/vue3-js/frontend/babel.config.js
deleted file mode 100644
index c94e72931..000000000
--- a/cmd/templates/vue3-js/frontend/babel.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- presets: [
- '@vue/cli-plugin-babel/preset'
- ]
-}
diff --git a/cmd/templates/vue3-js/frontend/package-lock.json b/cmd/templates/vue3-js/frontend/package-lock.json
deleted file mode 100644
index 6431cfe4d..000000000
--- a/cmd/templates/vue3-js/frontend/package-lock.json
+++ /dev/null
@@ -1,12312 +0,0 @@
-{
- "name": "vue-js",
- "version": "0.1.0",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.12.13.tgz?cache=0&sync_timestamp=1612314620252&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.12.13.tgz",
- "integrity": "sha1-3PyCa+72XnXFDiHTg319lXmN1lg=",
- "dev": true,
- "requires": {
- "@babel/highlight": "^7.12.13"
- }
- },
- "@babel/compat-data": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/compat-data/download/@babel/compat-data-7.14.4.tgz?cache=0&sync_timestamp=1622221249104&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.14.4.tgz",
- "integrity": "sha1-RXIP4M7PP9QgGeHRLMPSf63JjVg=",
- "dev": true
- },
- "@babel/core": {
- "version": "7.14.3",
- "resolved": "https://registry.nlark.com/@babel/core/download/@babel/core-7.14.3.tgz",
- "integrity": "sha1-U5XjBAXwd2Bn+9nPCITxW/t3Cjg=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.12.13",
- "@babel/generator": "^7.14.3",
- "@babel/helper-compilation-targets": "^7.13.16",
- "@babel/helper-module-transforms": "^7.14.2",
- "@babel/helpers": "^7.14.0",
- "@babel/parser": "^7.14.3",
- "@babel/template": "^7.12.13",
- "@babel/traverse": "^7.14.2",
- "@babel/types": "^7.14.2",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.1.2",
- "semver": "^6.3.0",
- "source-map": "^0.5.0"
- }
- },
- "@babel/generator": {
- "version": "7.14.3",
- "resolved": "https://registry.nlark.com/@babel/generator/download/@babel/generator-7.14.3.tgz",
- "integrity": "sha1-DCZS2R973at8zMa6gVfk9A3O25E=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.14.2",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
- }
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.12.13.tgz?cache=0&sync_timestamp=1612314684390&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-annotate-as-pure%2Fdownload%2F%40babel%2Fhelper-annotate-as-pure-7.12.13.tgz",
- "integrity": "sha1-D1jobfxLs7H819uAZXDhd9Q5tqs=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz",
- "integrity": "sha1-a8IDYciLCnTQUTemXKyNPL9vYfw=",
- "dev": true,
- "requires": {
- "@babel/helper-explode-assignable-expression": "^7.12.13",
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.14.4.tgz?cache=0&sync_timestamp=1622221254097&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-compilation-targets%2Fdownload%2F%40babel%2Fhelper-compilation-targets-7.14.4.tgz",
- "integrity": "sha1-M+vQ/8NCSAUe4giTUKkpqwLypRY=",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.14.4",
- "@babel/helper-validator-option": "^7.12.17",
- "browserslist": "^4.16.6",
- "semver": "^6.3.0"
- }
- },
- "@babel/helper-create-class-features-plugin": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.14.4.tgz?cache=0&sync_timestamp=1622221254182&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-create-class-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-class-features-plugin-7.14.4.tgz",
- "integrity": "sha1-q/iI2DakQavueDx1IpJ5dIcF3EI=",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.12.13",
- "@babel/helper-function-name": "^7.14.2",
- "@babel/helper-member-expression-to-functions": "^7.13.12",
- "@babel/helper-optimise-call-expression": "^7.12.13",
- "@babel/helper-replace-supers": "^7.14.4",
- "@babel/helper-split-export-declaration": "^7.12.13"
- }
- },
- "@babel/helper-create-regexp-features-plugin": {
- "version": "7.14.3",
- "resolved": "https://registry.nlark.com/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.14.3.tgz?cache=0&sync_timestamp=1621284706846&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-create-regexp-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-regexp-features-plugin-7.14.3.tgz",
- "integrity": "sha1-FJqm14wBbjGMQ+JAmgrpwTaoZog=",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.12.13",
- "regexpu-core": "^4.7.1"
- }
- },
- "@babel/helper-define-polyfill-provider": {
- "version": "0.2.3",
- "resolved": "https://registry.nlark.com/@babel/helper-define-polyfill-provider/download/@babel/helper-define-polyfill-provider-0.2.3.tgz?cache=0&sync_timestamp=1622025470416&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-define-polyfill-provider%2Fdownload%2F%40babel%2Fhelper-define-polyfill-provider-0.2.3.tgz",
- "integrity": "sha1-BSXt7FCUZTooJojTTYRuTHXpwLY=",
- "dev": true,
- "requires": {
- "@babel/helper-compilation-targets": "^7.13.0",
- "@babel/helper-module-imports": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/traverse": "^7.13.0",
- "debug": "^4.1.1",
- "lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2",
- "semver": "^6.1.2"
- }
- },
- "@babel/helper-explode-assignable-expression": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.13.0.tgz?cache=0&sync_timestamp=1614034233759&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-explode-assignable-expression%2Fdownload%2F%40babel%2Fhelper-explode-assignable-expression-7.13.0.tgz",
- "integrity": "sha1-F7XFn/Rz2flW9A71cM86dsoSZX8=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.13.0"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/helper-function-name/download/@babel/helper-function-name-7.14.2.tgz",
- "integrity": "sha1-OXaItZB2C273cltfCGDIJCfrqsI=",
- "dev": true,
- "requires": {
- "@babel/helper-get-function-arity": "^7.12.13",
- "@babel/template": "^7.12.13",
- "@babel/types": "^7.14.2"
- }
- },
- "@babel/helper-get-function-arity": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.12.13.tgz?cache=0&sync_timestamp=1612314652298&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-get-function-arity%2Fdownload%2F%40babel%2Fhelper-get-function-arity-7.12.13.tgz",
- "integrity": "sha1-vGNFHUA6OzCCuX4diz/lvUCR5YM=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.13.16",
- "resolved": "https://registry.nlark.com/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.13.16.tgz",
- "integrity": "sha1-GxZRJJ6UtR+PDTNDmEPjPjl3WzA=",
- "dev": true,
- "requires": {
- "@babel/traverse": "^7.13.15",
- "@babel/types": "^7.13.16"
- }
- },
- "@babel/helper-member-expression-to-functions": {
- "version": "7.13.12",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.13.12.tgz?cache=0&sync_timestamp=1616428111276&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-member-expression-to-functions%2Fdownload%2F%40babel%2Fhelper-member-expression-to-functions-7.13.12.tgz",
- "integrity": "sha1-3+No8m1CagcpnY1lE4IXaCFubXI=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.13.12"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.13.12",
- "resolved": "https://registry.nlark.com/@babel/helper-module-imports/download/@babel/helper-module-imports-7.13.12.tgz?cache=0&sync_timestamp=1618846791460&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-module-imports%2Fdownload%2F%40babel%2Fhelper-module-imports-7.13.12.tgz",
- "integrity": "sha1-xqNppvNiHLJdoBQHhoTakZa2GXc=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.13.12"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.14.2.tgz?cache=0&sync_timestamp=1620839398699&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-module-transforms%2Fdownload%2F%40babel%2Fhelper-module-transforms-7.14.2.tgz",
- "integrity": "sha1-rBzDDuR7lF4+DE2xL6DFOJUJ3+U=",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.13.12",
- "@babel/helper-replace-supers": "^7.13.12",
- "@babel/helper-simple-access": "^7.13.12",
- "@babel/helper-split-export-declaration": "^7.12.13",
- "@babel/helper-validator-identifier": "^7.14.0",
- "@babel/template": "^7.12.13",
- "@babel/traverse": "^7.14.2",
- "@babel/types": "^7.14.2"
- }
- },
- "@babel/helper-optimise-call-expression": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.12.13.tgz?cache=0&sync_timestamp=1612314687212&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-optimise-call-expression%2Fdownload%2F%40babel%2Fhelper-optimise-call-expression-7.12.13.tgz",
- "integrity": "sha1-XALRcbTIYVsecWP4iMHIHDCiquo=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.13.0.tgz",
- "integrity": "sha1-gGUmzhJa7QM3O8QWqCgyHjpqM68=",
- "dev": true
- },
- "@babel/helper-remap-async-to-generator": {
- "version": "7.13.0",
- "resolved": "https://registry.nlark.com/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.13.0.tgz",
- "integrity": "sha1-N2p2DZ97SyB3qd0Fqpw5J8rbIgk=",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.12.13",
- "@babel/helper-wrap-function": "^7.13.0",
- "@babel/types": "^7.13.0"
- }
- },
- "@babel/helper-replace-supers": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.14.4.tgz?cache=0&sync_timestamp=1622221254092&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-replace-supers%2Fdownload%2F%40babel%2Fhelper-replace-supers-7.14.4.tgz",
- "integrity": "sha1-sqsWh13uz/89381Tm8MV9ymY2DY=",
- "dev": true,
- "requires": {
- "@babel/helper-member-expression-to-functions": "^7.13.12",
- "@babel/helper-optimise-call-expression": "^7.12.13",
- "@babel/traverse": "^7.14.2",
- "@babel/types": "^7.14.4"
- }
- },
- "@babel/helper-simple-access": {
- "version": "7.13.12",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.13.12.tgz?cache=0&sync_timestamp=1616428063009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-simple-access%2Fdownload%2F%40babel%2Fhelper-simple-access-7.13.12.tgz",
- "integrity": "sha1-3WxTivthgZ0gWgEsMXkqOcel6vY=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.13.12"
- }
- },
- "@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.12.1",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-skip-transparent-expression-wrappers/download/@babel/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
- "integrity": "sha1-Ri3GOn5DWt6EaDhcY9K4TM5LPL8=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.1"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.12.13.tgz?cache=0&sync_timestamp=1612314686094&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-split-export-declaration%2Fdownload%2F%40babel%2Fhelper-split-export-declaration-7.12.13.tgz",
- "integrity": "sha1-6UML4AuvPoiw4T5vnU6vITY3KwU=",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.14.0.tgz?cache=0&sync_timestamp=1619727549370&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.14.0.tgz",
- "integrity": "sha1-0mytikfGUoaxXfFUcxml0Lzycog="
- },
- "@babel/helper-validator-option": {
- "version": "7.12.17",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-option/download/@babel/helper-validator-option-7.12.17.tgz",
- "integrity": "sha1-0fvwEuGnm37rv9xtJwuq+NnrmDE=",
- "dev": true
- },
- "@babel/helper-wrap-function": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.13.0.tgz?cache=0&sync_timestamp=1614034233760&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-wrap-function%2Fdownload%2F%40babel%2Fhelper-wrap-function-7.13.0.tgz",
- "integrity": "sha1-vbXGb9qFJuwjWriUrVOhI1x5/MQ=",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.12.13",
- "@babel/template": "^7.12.13",
- "@babel/traverse": "^7.13.0",
- "@babel/types": "^7.13.0"
- }
- },
- "@babel/helpers": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/helpers/download/@babel/helpers-7.14.0.tgz?cache=0&sync_timestamp=1619727432208&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelpers%2Fdownload%2F%40babel%2Fhelpers-7.14.0.tgz",
- "integrity": "sha1-6ptr6UeKE9b5Ydu182v3Xi87j2I=",
- "dev": true,
- "requires": {
- "@babel/template": "^7.12.13",
- "@babel/traverse": "^7.14.0",
- "@babel/types": "^7.14.0"
- }
- },
- "@babel/highlight": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/highlight/download/@babel/highlight-7.14.0.tgz?cache=0&sync_timestamp=1619727182056&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhighlight%2Fdownload%2F%40babel%2Fhighlight-7.14.0.tgz",
- "integrity": "sha1-MZfjdXEe9r+DTmfQ2uyI5PRhE88=",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.14.0",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.14.4.tgz",
- "integrity": "sha1-pcVg1tts2ObtNCNo3qgDkjLLqxg="
- },
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.13.12",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/download/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz",
- "integrity": "sha1-o0hNhNC1SfP8kWuZ7keD8m+rrSo=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1",
- "@babel/plugin-proposal-optional-chaining": "^7.13.12"
- }
- },
- "@babel/plugin-proposal-async-generator-functions": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.14.2.tgz?cache=0&sync_timestamp=1620839417583&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-async-generator-functions%2Fdownload%2F%40babel%2Fplugin-proposal-async-generator-functions-7.14.2.tgz",
- "integrity": "sha1-OiCFq79dX5YtSA28gTRzhe1i6x4=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-remap-async-to-generator": "^7.13.0",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
- }
- },
- "@babel/plugin-proposal-class-properties": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.13.0.tgz?cache=0&sync_timestamp=1614035098704&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-class-properties%2Fdownload%2F%40babel%2Fplugin-proposal-class-properties-7.13.0.tgz",
- "integrity": "sha1-FGN2AAuU79AB5XpAqIpSWvqrnzc=",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.13.0",
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-proposal-class-static-block": {
- "version": "7.14.3",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-class-static-block/download/@babel/plugin-proposal-class-static-block-7.14.3.tgz",
- "integrity": "sha1-WlJ+LK5KR1MRnDo+f2TsrozPE2A=",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.14.3",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-class-static-block": "^7.12.13"
- }
- },
- "@babel/plugin-proposal-decorators": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.14.2.tgz?cache=0&sync_timestamp=1620839996248&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-decorators%2Fdownload%2F%40babel%2Fplugin-proposal-decorators-7.14.2.tgz",
- "integrity": "sha1-5ow8XkpqCINEVlaCVvw+cbk1kM8=",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.14.2",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-decorators": "^7.12.13"
- }
- },
- "@babel/plugin-proposal-dynamic-import": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.14.2.tgz",
- "integrity": "sha1-Aeur18OBz/Ix+kPjApOaneW+nZ8=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-export-namespace-from": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-export-namespace-from/download/@babel/plugin-proposal-export-namespace-from-7.14.2.tgz",
- "integrity": "sha1-YlQvlKqc6Pbbp57saYryIRIlN5E=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-json-strings": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.14.2.tgz?cache=0&sync_timestamp=1620840046817&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-json-strings%2Fdownload%2F%40babel%2Fplugin-proposal-json-strings-7.14.2.tgz",
- "integrity": "sha1-gwtOJCanguiyh4+/4suoW3DL+Yw=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-logical-assignment-operators/download/@babel/plugin-proposal-logical-assignment-operators-7.14.2.tgz",
- "integrity": "sha1-IiNIwIChZ44OdOpj/nbydYgtH9c=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz",
- "integrity": "sha1-QlsR3GL8JpOaKrQsu6aAvfVzRUY=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-numeric-separator": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.14.2.tgz?cache=0&sync_timestamp=1620839422175&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-numeric-separator%2Fdownload%2F%40babel%2Fplugin-proposal-numeric-separator-7.14.2.tgz",
- "integrity": "sha1-grTMBlcRQ/r1BiYQSzNd1xuqT54=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-object-rest-spread": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.14.4.tgz?cache=0&sync_timestamp=1622221269189&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-object-rest-spread%2Fdownload%2F%40babel%2Fplugin-proposal-object-rest-spread-7.14.4.tgz",
- "integrity": "sha1-DitN5BmRXcC0CTeOgpQS4gMXd8Q=",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.14.4",
- "@babel/helper-compilation-targets": "^7.14.4",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.14.2"
- }
- },
- "@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.14.2.tgz",
- "integrity": "sha1-FQ1OWOUlsWqaFDG9UybE7thw1xc=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-optional-chaining": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.14.2.tgz?cache=0&sync_timestamp=1620839998724&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-optional-chaining%2Fdownload%2F%40babel%2Fplugin-proposal-optional-chaining-7.14.2.tgz",
- "integrity": "sha1-34FxqLnEPr9MHavmMRtDLYPhs04=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-private-methods": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.13.0.tgz?cache=0&sync_timestamp=1614035100398&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-private-methods%2Fdownload%2F%40babel%2Fplugin-proposal-private-methods-7.13.0.tgz",
- "integrity": "sha1-BL1MbUD25rv6L1fi2AlLrZAO94c=",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.13.0",
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-proposal-private-property-in-object": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-proposal-private-property-in-object/download/@babel/plugin-proposal-private-property-in-object-7.14.0.tgz?cache=0&sync_timestamp=1619727655656&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-private-property-in-object%2Fdownload%2F%40babel%2Fplugin-proposal-private-property-in-object-7.14.0.tgz",
- "integrity": "sha1-saHyAwWGudNInMJhedLrWIMndjY=",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.12.13",
- "@babel/helper-create-class-features-plugin": "^7.14.0",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.0"
- }
- },
- "@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.12.13.tgz",
- "integrity": "sha1-vr3lEzm+gpwXqqrO0YZB3rYrObo=",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha1-qYP7Gusuw/btBCohD2QOkOeG/g0=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha1-tcmHJ0xKOoK4lxR5aTGmtTVErhA=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-syntax-class-static-block": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-syntax-class-static-block/download/@babel/plugin-syntax-class-static-block-7.12.13.tgz?cache=0&sync_timestamp=1619727671263&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-syntax-class-static-block%2Fdownload%2F%40babel%2Fplugin-syntax-class-static-block-7.12.13.tgz",
- "integrity": "sha1-jj1nSwYT5nl1zqwndsl7YMr8XJw=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-syntax-decorators": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.12.13.tgz?cache=0&sync_timestamp=1612314725413&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-decorators%2Fdownload%2F%40babel%2Fplugin-syntax-decorators-7.12.13.tgz",
- "integrity": "sha1-+sgpvzx+9KG8kWJXtAPljGva9kg=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-export-namespace-from/download/@babel/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha1-AolkqbqA28CUyRXEh618TnpmRlo=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
- }
- },
- "@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-jsx": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.12.13.tgz",
- "integrity": "sha1-BE+4HrrWaY/mLEeIdVdby7m3DxU=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.nlark.com/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha1-ypHvRjA1MESLkGZSusLp/plB9pk=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.nlark.com/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha1-Fn7XA2iIYIH3S1w2xlqIwDtm0ak=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha1-ubBws+M1cM2f0Hun+pHA3Te5r5c=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha1-YRGiZbz7Ag6579D9/X0mQCue1sE=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.nlark.com/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-syntax-private-property-in-object/download/@babel/plugin-syntax-private-property-in-object-7.14.0.tgz",
- "integrity": "sha1-dipLq+xhF2/sbIhIDexANysUDAs=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-syntax-top-level-await": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.12.13.tgz",
- "integrity": "sha1-xfD6biSfW3OXJ/kjVAz3qAYTAXg=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-arrow-functions": {
- "version": "7.13.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.13.0.tgz",
- "integrity": "sha1-EKWb661S1jegJ6+mkujVzv9ePa4=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-async-to-generator": {
- "version": "7.13.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.13.0.tgz",
- "integrity": "sha1-jhEr9ncbgr8el05eJoBsXJmqUW8=",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-remap-async-to-generator": "^7.13.0"
- }
- },
- "@babel/plugin-transform-block-scoped-functions": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.12.13.tgz",
- "integrity": "sha1-qb8YNvKjm062zwmWdzneKepL9MQ=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-block-scoping": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.14.4.tgz?cache=0&sync_timestamp=1622221249143&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.14.4.tgz",
- "integrity": "sha1-yvFAsLLiRixQlVPRQObQq++2Htg=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-classes": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.14.4.tgz",
- "integrity": "sha1-qDwVUD/HGg+Z6Hb9zn2tvGV17Do=",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.12.13",
- "@babel/helper-function-name": "^7.14.2",
- "@babel/helper-optimise-call-expression": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-replace-supers": "^7.14.4",
- "@babel/helper-split-export-declaration": "^7.12.13",
- "globals": "^11.1.0"
- }
- },
- "@babel/plugin-transform-computed-properties": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.13.0.tgz?cache=0&sync_timestamp=1614034212505&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-computed-properties%2Fdownload%2F%40babel%2Fplugin-transform-computed-properties-7.13.0.tgz",
- "integrity": "sha1-hFxui5u1U3ax+guS7wvcjqBmRO0=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-destructuring": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.14.4.tgz",
- "integrity": "sha1-rL7FAumVHzD0RB6sodLynvreWe0=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-dotall-regex": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.12.13.tgz",
- "integrity": "sha1-PxYBzCmQW/y2f1ORDxl66v67Ja0=",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-duplicate-keys": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.12.13.tgz?cache=0&sync_timestamp=1612314817333&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-duplicate-keys%2Fdownload%2F%40babel%2Fplugin-transform-duplicate-keys-7.12.13.tgz",
- "integrity": "sha1-bwa4eouAP9ko5UuBwljwoAM5BN4=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-exponentiation-operator": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.12.13.tgz",
- "integrity": "sha1-TVI5C5onPmUeSrpq7knvQOgM0KE=",
- "dev": true,
- "requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-for-of": {
- "version": "7.13.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.13.0.tgz",
- "integrity": "sha1-x5n4gagJGsJrVIZ6hFw+l9JpYGI=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-function-name": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.12.13.tgz",
- "integrity": "sha1-uwJEUvmq7YYdN0yOeiQlLOOlAFE=",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-literals": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.12.13.tgz?cache=0&sync_timestamp=1612314818038&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-literals%2Fdownload%2F%40babel%2Fplugin-transform-literals-7.12.13.tgz",
- "integrity": "sha1-LKRbr+SoIBl88xV5Sk0mVg/kvbk=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-member-expression-literals": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.12.13.tgz?cache=0&sync_timestamp=1612314834575&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-member-expression-literals%2Fdownload%2F%40babel%2Fplugin-transform-member-expression-literals-7.12.13.tgz",
- "integrity": "sha1-X/pmzVm54ZExTJ8fgDuTjowIHkA=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-modules-amd": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.14.2.tgz",
- "integrity": "sha1-ZiKAb+GnwHoTiERCIu+VNfLKF7A=",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.14.2",
- "@babel/helper-plugin-utils": "^7.13.0",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-commonjs": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.14.0.tgz?cache=0&sync_timestamp=1619727184331&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.14.0.tgz",
- "integrity": "sha1-UrwZnLWB4Jku26Dw+ANWRnWH8WE=",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.14.0",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-simple-access": "^7.13.12",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-systemjs": {
- "version": "7.13.8",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.13.8.tgz?cache=0&sync_timestamp=1614382839114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-systemjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-systemjs-7.13.8.tgz",
- "integrity": "sha1-bQZu4r/zx7PWC/KN7Baa2ZODGuM=",
- "dev": true,
- "requires": {
- "@babel/helper-hoist-variables": "^7.13.0",
- "@babel/helper-module-transforms": "^7.13.0",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-validator-identifier": "^7.12.11",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-umd": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.14.0.tgz?cache=0&sync_timestamp=1619727183056&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-modules-umd%2Fdownload%2F%40babel%2Fplugin-transform-modules-umd-7.14.0.tgz",
- "integrity": "sha1-L4F50bvJJjZlzkpl8wVSay6orDQ=",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.14.0",
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.12.13.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-named-capturing-groups-regex%2Fdownload%2F%40babel%2Fplugin-transform-named-capturing-groups-regex-7.12.13.tgz",
- "integrity": "sha1-IhNyWl9bu+NktQw7pZmMlZnFydk=",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.12.13"
- }
- },
- "@babel/plugin-transform-new-target": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.12.13.tgz?cache=0&sync_timestamp=1612314816557&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-new-target%2Fdownload%2F%40babel%2Fplugin-transform-new-target-7.12.13.tgz",
- "integrity": "sha1-4i2MOvJLFQ3VKMvW5oXnmb8cNRw=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-object-super": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.12.13.tgz?cache=0&sync_timestamp=1612314795746&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-object-super%2Fdownload%2F%40babel%2Fplugin-transform-object-super-7.12.13.tgz",
- "integrity": "sha1-tEFqLWO4974xTz00m9VanBtRcfc=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13",
- "@babel/helper-replace-supers": "^7.12.13"
- }
- },
- "@babel/plugin-transform-parameters": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-parameters%2Fdownload%2F%40babel%2Fplugin-transform-parameters-7.14.2.tgz",
- "integrity": "sha1-5CkPcuDp6DEADQZkJ8RmcJjezDE=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-property-literals": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.12.13.tgz",
- "integrity": "sha1-TmqeN4ZNjxs7wOLc57+IV9uLGoE=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-regenerator": {
- "version": "7.13.15",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.13.15.tgz",
- "integrity": "sha1-5esolFv4tlY+f4GJRflmqNKZfzk=",
- "dev": true,
- "requires": {
- "regenerator-transform": "^0.14.2"
- }
- },
- "@babel/plugin-transform-reserved-words": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-reserved-words/download/@babel/plugin-transform-reserved-words-7.12.13.tgz?cache=0&sync_timestamp=1612314845661&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-reserved-words%2Fdownload%2F%40babel%2Fplugin-transform-reserved-words-7.12.13.tgz",
- "integrity": "sha1-fZmI1PBuD+aX6h2YAxiKoYtHJpU=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-runtime": {
- "version": "7.14.3",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.14.3.tgz?cache=0&sync_timestamp=1621284741103&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-runtime%2Fdownload%2F%40babel%2Fplugin-transform-runtime-7.14.3.tgz",
- "integrity": "sha1-H9iFotDeHTwiN5Wk6b5ywttFFc8=",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.13.12",
- "@babel/helper-plugin-utils": "^7.13.0",
- "babel-plugin-polyfill-corejs2": "^0.2.0",
- "babel-plugin-polyfill-corejs3": "^0.2.0",
- "babel-plugin-polyfill-regenerator": "^0.2.0",
- "semver": "^6.3.0"
- }
- },
- "@babel/plugin-transform-shorthand-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.12.13.tgz?cache=0&sync_timestamp=1612314820265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-shorthand-properties%2Fdownload%2F%40babel%2Fplugin-transform-shorthand-properties-7.12.13.tgz",
- "integrity": "sha1-23VXMrcMU51QTGOQ2c6Q/mSv960=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-spread": {
- "version": "7.13.0",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.13.0.tgz?cache=0&sync_timestamp=1614034217488&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-spread%2Fdownload%2F%40babel%2Fplugin-transform-spread-7.13.0.tgz",
- "integrity": "sha1-hIh3EOJzwYFaznrkWfb0Kl0x1f0=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1"
- }
- },
- "@babel/plugin-transform-sticky-regex": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.12.13.tgz",
- "integrity": "sha1-dg/9k2+s5z+GCuZG+4bugvPQbR8=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-template-literals": {
- "version": "7.13.0",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.13.0.tgz",
- "integrity": "sha1-o2BJEnl3rZRDje50Q1mNHO/fQJ0=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0"
- }
- },
- "@babel/plugin-transform-typeof-symbol": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.12.13.tgz?cache=0&sync_timestamp=1612314820235&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-typeof-symbol%2Fdownload%2F%40babel%2Fplugin-transform-typeof-symbol-7.12.13.tgz",
- "integrity": "sha1-eF3Weh8upXnZwr5yLejITLhfWn8=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-unicode-escapes": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-escapes/download/@babel/plugin-transform-unicode-escapes-7.12.13.tgz?cache=0&sync_timestamp=1612314845292&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-unicode-escapes%2Fdownload%2F%40babel%2Fplugin-transform-unicode-escapes-7.12.13.tgz",
- "integrity": "sha1-hAztO4FtO1En3R0S3O3F3q0aXnQ=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/plugin-transform-unicode-regex": {
- "version": "7.12.13",
- "resolved": "https://registry.nlark.com/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.12.13.tgz",
- "integrity": "sha1-tSUhaFgE4VWxIC6D/BiNNLtw9aw=",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@babel/preset-env": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/preset-env/download/@babel/preset-env-7.14.4.tgz?cache=0&sync_timestamp=1622222650513&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.14.4.tgz",
- "integrity": "sha1-c/wyKMWXJ+XpdDGRVvME8NZoWi0=",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.14.4",
- "@babel/helper-compilation-targets": "^7.14.4",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/helper-validator-option": "^7.12.17",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.13.12",
- "@babel/plugin-proposal-async-generator-functions": "^7.14.2",
- "@babel/plugin-proposal-class-properties": "^7.13.0",
- "@babel/plugin-proposal-class-static-block": "^7.14.3",
- "@babel/plugin-proposal-dynamic-import": "^7.14.2",
- "@babel/plugin-proposal-export-namespace-from": "^7.14.2",
- "@babel/plugin-proposal-json-strings": "^7.14.2",
- "@babel/plugin-proposal-logical-assignment-operators": "^7.14.2",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.2",
- "@babel/plugin-proposal-numeric-separator": "^7.14.2",
- "@babel/plugin-proposal-object-rest-spread": "^7.14.4",
- "@babel/plugin-proposal-optional-catch-binding": "^7.14.2",
- "@babel/plugin-proposal-optional-chaining": "^7.14.2",
- "@babel/plugin-proposal-private-methods": "^7.13.0",
- "@babel/plugin-proposal-private-property-in-object": "^7.14.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.12.13",
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.12.13",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.0",
- "@babel/plugin-syntax-top-level-await": "^7.12.13",
- "@babel/plugin-transform-arrow-functions": "^7.13.0",
- "@babel/plugin-transform-async-to-generator": "^7.13.0",
- "@babel/plugin-transform-block-scoped-functions": "^7.12.13",
- "@babel/plugin-transform-block-scoping": "^7.14.4",
- "@babel/plugin-transform-classes": "^7.14.4",
- "@babel/plugin-transform-computed-properties": "^7.13.0",
- "@babel/plugin-transform-destructuring": "^7.14.4",
- "@babel/plugin-transform-dotall-regex": "^7.12.13",
- "@babel/plugin-transform-duplicate-keys": "^7.12.13",
- "@babel/plugin-transform-exponentiation-operator": "^7.12.13",
- "@babel/plugin-transform-for-of": "^7.13.0",
- "@babel/plugin-transform-function-name": "^7.12.13",
- "@babel/plugin-transform-literals": "^7.12.13",
- "@babel/plugin-transform-member-expression-literals": "^7.12.13",
- "@babel/plugin-transform-modules-amd": "^7.14.2",
- "@babel/plugin-transform-modules-commonjs": "^7.14.0",
- "@babel/plugin-transform-modules-systemjs": "^7.13.8",
- "@babel/plugin-transform-modules-umd": "^7.14.0",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13",
- "@babel/plugin-transform-new-target": "^7.12.13",
- "@babel/plugin-transform-object-super": "^7.12.13",
- "@babel/plugin-transform-parameters": "^7.14.2",
- "@babel/plugin-transform-property-literals": "^7.12.13",
- "@babel/plugin-transform-regenerator": "^7.13.15",
- "@babel/plugin-transform-reserved-words": "^7.12.13",
- "@babel/plugin-transform-shorthand-properties": "^7.12.13",
- "@babel/plugin-transform-spread": "^7.13.0",
- "@babel/plugin-transform-sticky-regex": "^7.12.13",
- "@babel/plugin-transform-template-literals": "^7.13.0",
- "@babel/plugin-transform-typeof-symbol": "^7.12.13",
- "@babel/plugin-transform-unicode-escapes": "^7.12.13",
- "@babel/plugin-transform-unicode-regex": "^7.12.13",
- "@babel/preset-modules": "^0.1.4",
- "@babel/types": "^7.14.4",
- "babel-plugin-polyfill-corejs2": "^0.2.0",
- "babel-plugin-polyfill-corejs3": "^0.2.0",
- "babel-plugin-polyfill-regenerator": "^0.2.0",
- "core-js-compat": "^3.9.0",
- "semver": "^6.3.0"
- }
- },
- "@babel/preset-modules": {
- "version": "0.1.4",
- "resolved": "https://registry.npm.taobao.org/@babel/preset-modules/download/@babel/preset-modules-0.1.4.tgz",
- "integrity": "sha1-Ni8raMZihClw/bXiVP/I/BwuQV4=",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
- }
- },
- "@babel/runtime": {
- "version": "7.14.0",
- "resolved": "https://registry.nlark.com/@babel/runtime/download/@babel/runtime-7.14.0.tgz?cache=0&sync_timestamp=1619727414495&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.14.0.tgz",
- "integrity": "sha1-RnlLwgthLF915i3QceJN/ZXxy+Y=",
- "dev": true,
- "requires": {
- "regenerator-runtime": "^0.13.4"
- }
- },
- "@babel/template": {
- "version": "7.12.13",
- "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.12.13.tgz",
- "integrity": "sha1-UwJlvooliduzdSOETFvLVZR/syc=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.12.13",
- "@babel/parser": "^7.12.13",
- "@babel/types": "^7.12.13"
- }
- },
- "@babel/traverse": {
- "version": "7.14.2",
- "resolved": "https://registry.nlark.com/@babel/traverse/download/@babel/traverse-7.14.2.tgz?cache=0&sync_timestamp=1620839391311&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.14.2.tgz",
- "integrity": "sha1-kgGo2RJyOoMcJnnH678v4UFtdls=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.12.13",
- "@babel/generator": "^7.14.2",
- "@babel/helper-function-name": "^7.14.2",
- "@babel/helper-split-export-declaration": "^7.12.13",
- "@babel/parser": "^7.14.2",
- "@babel/types": "^7.14.2",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- }
- },
- "@babel/types": {
- "version": "7.14.4",
- "resolved": "https://registry.nlark.com/@babel/types/download/@babel/types-7.14.4.tgz?cache=0&sync_timestamp=1622221256190&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.14.4.tgz",
- "integrity": "sha1-v9aYAQgWhZOziz60iiSqAmuRm8A=",
- "requires": {
- "@babel/helper-validator-identifier": "^7.14.0",
- "to-fast-properties": "^2.0.0"
- }
- },
- "@hapi/address": {
- "version": "2.1.4",
- "resolved": "https://registry.nlark.com/@hapi/address/download/@hapi/address-2.1.4.tgz",
- "integrity": "sha1-XWftQ/P9QaadS5/3tW58DR0KgeU=",
- "dev": true
- },
- "@hapi/bourne": {
- "version": "1.3.2",
- "resolved": "https://registry.nlark.com/@hapi/bourne/download/@hapi/bourne-1.3.2.tgz",
- "integrity": "sha1-CnCVreoGckPOMoPhtWuKj0U7JCo=",
- "dev": true
- },
- "@hapi/hoek": {
- "version": "8.5.1",
- "resolved": "https://registry.nlark.com/@hapi/hoek/download/@hapi/hoek-8.5.1.tgz",
- "integrity": "sha1-/elgZMpEbeyMVajC8TCVewcMbgY=",
- "dev": true
- },
- "@hapi/joi": {
- "version": "15.1.1",
- "resolved": "https://registry.npm.taobao.org/@hapi/joi/download/@hapi/joi-15.1.1.tgz?cache=0&sync_timestamp=1615984328397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Fjoi%2Fdownload%2F%40hapi%2Fjoi-15.1.1.tgz",
- "integrity": "sha1-xnW4pxKW8Cgz+NbSQ7NMV7jOGdc=",
- "dev": true,
- "requires": {
- "@hapi/address": "2.x.x",
- "@hapi/bourne": "1.x.x",
- "@hapi/hoek": "8.x.x",
- "@hapi/topo": "3.x.x"
- }
- },
- "@hapi/topo": {
- "version": "3.1.6",
- "resolved": "https://registry.npm.taobao.org/@hapi/topo/download/@hapi/topo-3.1.6.tgz",
- "integrity": "sha1-aNk1+j6uf91asNf5U/MgXYsr/Ck=",
- "dev": true,
- "requires": {
- "@hapi/hoek": "^8.3.0"
- }
- },
- "@intervolga/optimize-cssnano-plugin": {
- "version": "1.0.6",
- "resolved": "https://registry.npm.taobao.org/@intervolga/optimize-cssnano-plugin/download/@intervolga/optimize-cssnano-plugin-1.0.6.tgz",
- "integrity": "sha1-vnx4RhKLiPapsdEmGgrQbrXA/fg=",
- "dev": true,
- "requires": {
- "cssnano": "^4.0.0",
- "cssnano-preset-default": "^4.0.0",
- "postcss": "^7.0.0"
- }
- },
- "@mrmlnc/readdir-enhanced": {
- "version": "2.2.1",
- "resolved": "https://registry.npm.taobao.org/@mrmlnc/readdir-enhanced/download/@mrmlnc/readdir-enhanced-2.2.1.tgz",
- "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=",
- "dev": true,
- "requires": {
- "call-me-maybe": "^1.0.1",
- "glob-to-regexp": "^0.3.0"
- }
- },
- "@nodelib/fs.stat": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/@nodelib/fs.stat/download/@nodelib/fs.stat-1.1.3.tgz",
- "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=",
- "dev": true
- },
- "@soda/friendly-errors-webpack-plugin": {
- "version": "1.8.0",
- "resolved": "https://registry.npm.taobao.org/@soda/friendly-errors-webpack-plugin/download/@soda/friendly-errors-webpack-plugin-1.8.0.tgz?cache=0&sync_timestamp=1607927438775&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40soda%2Ffriendly-errors-webpack-plugin%2Fdownload%2F%40soda%2Ffriendly-errors-webpack-plugin-1.8.0.tgz",
- "integrity": "sha1-hHUdgqkwGdXJLAzw5FrFkIfNIkA=",
- "dev": true,
- "requires": {
- "chalk": "^2.4.2",
- "error-stack-parser": "^2.0.2",
- "string-width": "^2.0.0",
- "strip-ansi": "^5"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/string-width/download/string-width-2.1.1.tgz",
- "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
- "dev": true,
- "requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
- },
- "dependencies": {
- "strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^3.0.0"
- }
- }
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
- "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
- "dev": true
- }
- }
- }
- }
- },
- "@soda/get-current-script": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/@soda/get-current-script/download/@soda/get-current-script-1.0.2.tgz",
- "integrity": "sha1-pTUV2yXYA4N0OBtzryC7Ty5QjYc=",
- "dev": true
- },
- "@types/body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.nlark.com/@types/body-parser/download/@types/body-parser-1.19.0.tgz?cache=0&sync_timestamp=1621240602575&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fbody-parser%2Fdownload%2F%40types%2Fbody-parser-1.19.0.tgz",
- "integrity": "sha1-BoWzxH6zAG/+0RfN1VFkth+AU48=",
- "dev": true,
- "requires": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "@types/connect": {
- "version": "3.4.34",
- "resolved": "https://registry.nlark.com/@types/connect/download/@types/connect-3.4.34.tgz",
- "integrity": "sha1-FwpAIjptZmAG2TyhKK8r6x2bGQE=",
- "dev": true,
- "requires": {
- "@types/node": "*"
- }
- },
- "@types/connect-history-api-fallback": {
- "version": "1.3.4",
- "resolved": "https://registry.nlark.com/@types/connect-history-api-fallback/download/@types/connect-history-api-fallback-1.3.4.tgz?cache=0&sync_timestamp=1621240807633&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fconnect-history-api-fallback%2Fdownload%2F%40types%2Fconnect-history-api-fallback-1.3.4.tgz",
- "integrity": "sha1-jA8Obl2CUraZ9aZi9Rvfgv2di7g=",
- "dev": true,
- "requires": {
- "@types/express-serve-static-core": "*",
- "@types/node": "*"
- }
- },
- "@types/express": {
- "version": "4.17.12",
- "resolved": "https://registry.nlark.com/@types/express/download/@types/express-4.17.12.tgz?cache=0&sync_timestamp=1621962565565&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fexpress%2Fdownload%2F%40types%2Fexpress-4.17.12.tgz",
- "integrity": "sha1-S8G/PNDP5tP28oU2SLQNt9VN41A=",
- "dev": true,
- "requires": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.18",
- "@types/qs": "*",
- "@types/serve-static": "*"
- }
- },
- "@types/express-serve-static-core": {
- "version": "4.17.20",
- "resolved": "https://registry.nlark.com/@types/express-serve-static-core/download/@types/express-serve-static-core-4.17.20.tgz?cache=0&sync_timestamp=1621962788076&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fexpress-serve-static-core%2Fdownload%2F%40types%2Fexpress-serve-static-core-4.17.20.tgz",
- "integrity": "sha1-RMruAp8sJsRnEdpehFzcEhZ61y0=",
- "dev": true,
- "requires": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*"
- }
- },
- "@types/glob": {
- "version": "7.1.3",
- "resolved": "https://registry.nlark.com/@types/glob/download/@types/glob-7.1.3.tgz",
- "integrity": "sha1-5rqA82t9qtLGhazZJmOC5omFwYM=",
- "dev": true,
- "requires": {
- "@types/minimatch": "*",
- "@types/node": "*"
- }
- },
- "@types/http-proxy": {
- "version": "1.17.6",
- "resolved": "https://registry.nlark.com/@types/http-proxy/download/@types/http-proxy-1.17.6.tgz",
- "integrity": "sha1-Ytw/reIn1qwoYsjxnuDanan9hhY=",
- "dev": true,
- "requires": {
- "@types/node": "*"
- }
- },
- "@types/json-schema": {
- "version": "7.0.7",
- "resolved": "https://registry.nlark.com/@types/json-schema/download/@types/json-schema-7.0.7.tgz",
- "integrity": "sha1-mKmTUWyFnrDVxMjwmDF6nqaNua0=",
- "dev": true
- },
- "@types/mime": {
- "version": "1.3.2",
- "resolved": "https://registry.nlark.com/@types/mime/download/@types/mime-1.3.2.tgz",
- "integrity": "sha1-k+Jb+e51/g/YC1lLxP6w6GIRG1o=",
- "dev": true
- },
- "@types/minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.nlark.com/@types/minimatch/download/@types/minimatch-3.0.4.tgz?cache=0&sync_timestamp=1621241982882&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fminimatch%2Fdownload%2F%40types%2Fminimatch-3.0.4.tgz",
- "integrity": "sha1-8Owl2/Lw5LGGRzE6wDETTKWySyE=",
- "dev": true
- },
- "@types/minimist": {
- "version": "1.2.1",
- "resolved": "https://registry.nlark.com/@types/minimist/download/@types/minimist-1.2.1.tgz?cache=0&sync_timestamp=1621241867849&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fminimist%2Fdownload%2F%40types%2Fminimist-1.2.1.tgz",
- "integrity": "sha1-KD9mn/dte4Jg34q3pCYsyD2YglY=",
- "dev": true
- },
- "@types/node": {
- "version": "15.6.1",
- "resolved": "https://registry.nlark.com/@types/node/download/@types/node-15.6.1.tgz?cache=0&sync_timestamp=1621901244878&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-15.6.1.tgz",
- "integrity": "sha1-MtQzkNXGLFtuxIapvJxZVE3jmgg=",
- "dev": true
- },
- "@types/normalize-package-data": {
- "version": "2.4.0",
- "resolved": "https://registry.nlark.com/@types/normalize-package-data/download/@types/normalize-package-data-2.4.0.tgz?cache=0&sync_timestamp=1621242064742&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnormalize-package-data%2Fdownload%2F%40types%2Fnormalize-package-data-2.4.0.tgz",
- "integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=",
- "dev": true
- },
- "@types/q": {
- "version": "1.5.4",
- "resolved": "https://registry.nlark.com/@types/q/download/@types/q-1.5.4.tgz?cache=0&sync_timestamp=1621242400776&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fq%2Fdownload%2F%40types%2Fq-1.5.4.tgz",
- "integrity": "sha1-FZJUFOCtLNdlv+9YhC9+JqesyyQ=",
- "dev": true
- },
- "@types/qs": {
- "version": "6.9.6",
- "resolved": "https://registry.nlark.com/@types/qs/download/@types/qs-6.9.6.tgz?cache=0&sync_timestamp=1621242292262&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fqs%2Fdownload%2F%40types%2Fqs-6.9.6.tgz",
- "integrity": "sha1-35w8izGiR+wxXmmWVmvjFx30s7E=",
- "dev": true
- },
- "@types/range-parser": {
- "version": "1.2.3",
- "resolved": "https://registry.nlark.com/@types/range-parser/download/@types/range-parser-1.2.3.tgz?cache=0&sync_timestamp=1621242291785&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Frange-parser%2Fdownload%2F%40types%2Frange-parser-1.2.3.tgz",
- "integrity": "sha1-fuMwunyq+5gJC+zoal7kQRWQTCw=",
- "dev": true
- },
- "@types/serve-static": {
- "version": "1.13.9",
- "resolved": "https://registry.nlark.com/@types/serve-static/download/@types/serve-static-1.13.9.tgz?cache=0&sync_timestamp=1621242658422&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fserve-static%2Fdownload%2F%40types%2Fserve-static-1.13.9.tgz",
- "integrity": "sha1-qs8oqFoF7imhH7fD6tk1rFbzPk4=",
- "dev": true,
- "requires": {
- "@types/mime": "^1",
- "@types/node": "*"
- }
- },
- "@types/source-list-map": {
- "version": "0.1.2",
- "resolved": "https://registry.nlark.com/@types/source-list-map/download/@types/source-list-map-0.1.2.tgz",
- "integrity": "sha1-AHiDYGP/rxdBI0m7o2QIfgrALsk=",
- "dev": true
- },
- "@types/tapable": {
- "version": "1.0.7",
- "resolved": "https://registry.nlark.com/@types/tapable/download/@types/tapable-1.0.7.tgz?cache=0&sync_timestamp=1621243788434&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Ftapable%2Fdownload%2F%40types%2Ftapable-1.0.7.tgz",
- "integrity": "sha1-VFFYNC+Uno/Tv9gTIklx7N3D+sQ=",
- "dev": true
- },
- "@types/uglify-js": {
- "version": "3.13.0",
- "resolved": "https://registry.nlark.com/@types/uglify-js/download/@types/uglify-js-3.13.0.tgz",
- "integrity": "sha1-HK2N8fsLFDxaugjeVxLqnR/3ESQ=",
- "dev": true,
- "requires": {
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "@types/webpack": {
- "version": "4.41.29",
- "resolved": "https://registry.nlark.com/@types/webpack/download/@types/webpack-4.41.29.tgz?cache=0&sync_timestamp=1621533733988&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fwebpack%2Fdownload%2F%40types%2Fwebpack-4.41.29.tgz",
- "integrity": "sha1-LmbB3oIjxEA2ZGlBXFCkfZdiV3M=",
- "dev": true,
- "requires": {
- "@types/node": "*",
- "@types/tapable": "^1",
- "@types/uglify-js": "*",
- "@types/webpack-sources": "*",
- "anymatch": "^3.0.0",
- "source-map": "^0.6.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "@types/webpack-dev-server": {
- "version": "3.11.4",
- "resolved": "https://registry.nlark.com/@types/webpack-dev-server/download/@types/webpack-dev-server-3.11.4.tgz",
- "integrity": "sha1-kNR91mC2ltQJQxq4wen6NhUQOgc=",
- "dev": true,
- "requires": {
- "@types/connect-history-api-fallback": "*",
- "@types/express": "*",
- "@types/serve-static": "*",
- "@types/webpack": "^4",
- "http-proxy-middleware": "^1.0.0"
- }
- },
- "@types/webpack-sources": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/@types/webpack-sources/download/@types/webpack-sources-2.1.0.tgz?cache=0&sync_timestamp=1621243863278&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fwebpack-sources%2Fdownload%2F%40types%2Fwebpack-sources-2.1.0.tgz",
- "integrity": "sha1-iIKwvWLR4M5i8YPQ0Bty5ugujBA=",
- "dev": true,
- "requires": {
- "@types/node": "*",
- "@types/source-list-map": "*",
- "source-map": "^0.7.3"
- },
- "dependencies": {
- "source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.7.3.tgz",
- "integrity": "sha1-UwL4FpAxc1ImVECS5kmB91F1A4M=",
- "dev": true
- }
- }
- },
- "@vue/babel-helper-vue-jsx-merge-props": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-helper-vue-jsx-merge-props/download/@vue/babel-helper-vue-jsx-merge-props-1.2.1.tgz?cache=0&sync_timestamp=1602851122331&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fbabel-helper-vue-jsx-merge-props%2Fdownload%2F%40vue%2Fbabel-helper-vue-jsx-merge-props-1.2.1.tgz",
- "integrity": "sha1-MWJKelBfsU2h1YAjclpMXycOaoE=",
- "dev": true
- },
- "@vue/babel-helper-vue-transform-on": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/@vue/babel-helper-vue-transform-on/download/@vue/babel-helper-vue-transform-on-1.0.2.tgz",
- "integrity": "sha1-m5xpHNBvyFUiGiR1w8yDHXdLx9w=",
- "dev": true
- },
- "@vue/babel-plugin-jsx": {
- "version": "1.0.6",
- "resolved": "https://registry.nlark.com/@vue/babel-plugin-jsx/download/@vue/babel-plugin-jsx-1.0.6.tgz?cache=0&sync_timestamp=1619929844730&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40vue%2Fbabel-plugin-jsx%2Fdownload%2F%40vue%2Fbabel-plugin-jsx-1.0.6.tgz",
- "integrity": "sha1-GEvzVBq279vlB5q4sgwZ4q8QC/s=",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.0.0",
- "@babel/template": "^7.0.0",
- "@babel/traverse": "^7.0.0",
- "@babel/types": "^7.0.0",
- "@vue/babel-helper-vue-transform-on": "^1.0.2",
- "camelcase": "^6.0.0",
- "html-tags": "^3.1.0",
- "svg-tags": "^1.0.0"
- }
- },
- "@vue/babel-plugin-transform-vue-jsx": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-plugin-transform-vue-jsx/download/@vue/babel-plugin-transform-vue-jsx-1.2.1.tgz?cache=0&sync_timestamp=1602851121024&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fbabel-plugin-transform-vue-jsx%2Fdownload%2F%40vue%2Fbabel-plugin-transform-vue-jsx-1.2.1.tgz",
- "integrity": "sha1-ZGBGxlLC8CQnJ/NFGdkXsGQEHtc=",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "html-tags": "^2.0.0",
- "lodash.kebabcase": "^4.1.1",
- "svg-tags": "^1.0.0"
- },
- "dependencies": {
- "html-tags": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/html-tags/download/html-tags-2.0.0.tgz",
- "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
- "dev": true
- }
- }
- },
- "@vue/babel-preset-app": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/babel-preset-app/download/@vue/babel-preset-app-4.5.13.tgz",
- "integrity": "sha1-y0dTIeTHP38RDawppIwqnLgK/rY=",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.0",
- "@babel/helper-compilation-targets": "^7.9.6",
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/plugin-proposal-class-properties": "^7.8.3",
- "@babel/plugin-proposal-decorators": "^7.8.3",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3",
- "@babel/plugin-transform-runtime": "^7.11.0",
- "@babel/preset-env": "^7.11.0",
- "@babel/runtime": "^7.11.0",
- "@vue/babel-plugin-jsx": "^1.0.3",
- "@vue/babel-preset-jsx": "^1.2.4",
- "babel-plugin-dynamic-import-node": "^2.3.3",
- "core-js": "^3.6.5",
- "core-js-compat": "^3.6.5",
- "semver": "^6.1.0"
- }
- },
- "@vue/babel-preset-jsx": {
- "version": "1.2.4",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-preset-jsx/download/@vue/babel-preset-jsx-1.2.4.tgz",
- "integrity": "sha1-kv6nnbbxOwHoDToAmeKSS9y+Toc=",
- "dev": true,
- "requires": {
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
- "@vue/babel-sugar-composition-api-inject-h": "^1.2.1",
- "@vue/babel-sugar-composition-api-render-instance": "^1.2.4",
- "@vue/babel-sugar-functional-vue": "^1.2.2",
- "@vue/babel-sugar-inject-h": "^1.2.2",
- "@vue/babel-sugar-v-model": "^1.2.3",
- "@vue/babel-sugar-v-on": "^1.2.3"
- }
- },
- "@vue/babel-sugar-composition-api-inject-h": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-composition-api-inject-h/download/@vue/babel-sugar-composition-api-inject-h-1.2.1.tgz?cache=0&sync_timestamp=1602851211529&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fbabel-sugar-composition-api-inject-h%2Fdownload%2F%40vue%2Fbabel-sugar-composition-api-inject-h-1.2.1.tgz",
- "integrity": "sha1-BdbgxDJxDjdYKyvppgSbaJtvA+s=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0"
- }
- },
- "@vue/babel-sugar-composition-api-render-instance": {
- "version": "1.2.4",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-composition-api-render-instance/download/@vue/babel-sugar-composition-api-render-instance-1.2.4.tgz",
- "integrity": "sha1-5MvGmXw0T6wnF4WteikyXFHWjRk=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0"
- }
- },
- "@vue/babel-sugar-functional-vue": {
- "version": "1.2.2",
- "resolved": "https://registry.nlark.com/@vue/babel-sugar-functional-vue/download/@vue/babel-sugar-functional-vue-1.2.2.tgz",
- "integrity": "sha1-JnqayNeHyW7b8Dzj85LEnam9Jlg=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0"
- }
- },
- "@vue/babel-sugar-inject-h": {
- "version": "1.2.2",
- "resolved": "https://registry.nlark.com/@vue/babel-sugar-inject-h/download/@vue/babel-sugar-inject-h-1.2.2.tgz",
- "integrity": "sha1-1zjTyJM2fshJHcu2abAAkZKT46o=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0"
- }
- },
- "@vue/babel-sugar-v-model": {
- "version": "1.2.3",
- "resolved": "https://registry.npm.taobao.org/@vue/babel-sugar-v-model/download/@vue/babel-sugar-v-model-1.2.3.tgz?cache=0&sync_timestamp=1603182488740&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fbabel-sugar-v-model%2Fdownload%2F%40vue%2Fbabel-sugar-v-model-1.2.3.tgz",
- "integrity": "sha1-+h8pulHr8KoabDX6ZtU5vEWaGPI=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
- "camelcase": "^5.0.0",
- "html-tags": "^2.0.0",
- "svg-tags": "^1.0.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.nlark.com/camelcase/download/camelcase-5.3.1.tgz",
- "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=",
- "dev": true
- },
- "html-tags": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/html-tags/download/html-tags-2.0.0.tgz",
- "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
- "dev": true
- }
- }
- },
- "@vue/babel-sugar-v-on": {
- "version": "1.2.3",
- "resolved": "https://registry.nlark.com/@vue/babel-sugar-v-on/download/@vue/babel-sugar-v-on-1.2.3.tgz",
- "integrity": "sha1-NCNnF4WGpp85LwS/ujICHQKROto=",
- "dev": true,
- "requires": {
- "@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
- "camelcase": "^5.0.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.nlark.com/camelcase/download/camelcase-5.3.1.tgz",
- "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=",
- "dev": true
- }
- }
- },
- "@vue/cli-overlay": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-overlay/download/@vue/cli-overlay-4.5.13.tgz",
- "integrity": "sha1-Tx/SFhvo9p1suoB58/DX3E3uR6c=",
- "dev": true
- },
- "@vue/cli-plugin-babel": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-plugin-babel/download/@vue/cli-plugin-babel-4.5.13.tgz",
- "integrity": "sha1-qJxILtzE6h0TVkXOxQKn9f1MMOc=",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.0",
- "@vue/babel-preset-app": "^4.5.13",
- "@vue/cli-shared-utils": "^4.5.13",
- "babel-loader": "^8.1.0",
- "cache-loader": "^4.1.0",
- "thread-loader": "^2.1.3",
- "webpack": "^4.0.0"
- }
- },
- "@vue/cli-plugin-eslint": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-plugin-eslint/download/@vue/cli-plugin-eslint-4.5.13.tgz",
- "integrity": "sha1-i68i0NltdnIMdQZka5b09iwFvfo=",
- "dev": true,
- "requires": {
- "@vue/cli-shared-utils": "^4.5.13",
- "eslint-loader": "^2.2.1",
- "globby": "^9.2.0",
- "inquirer": "^7.1.0",
- "webpack": "^4.0.0",
- "yorkie": "^2.0.0"
- }
- },
- "@vue/cli-plugin-router": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-plugin-router/download/@vue/cli-plugin-router-4.5.13.tgz",
- "integrity": "sha1-C2fIiYor8TKUGRmiouXzqsvZ/74=",
- "dev": true,
- "requires": {
- "@vue/cli-shared-utils": "^4.5.13"
- }
- },
- "@vue/cli-plugin-vuex": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-plugin-vuex/download/@vue/cli-plugin-vuex-4.5.13.tgz",
- "integrity": "sha1-mGRti8HmnPbGpsui/tPqzgNWw2A=",
- "dev": true
- },
- "@vue/cli-service": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-service/download/@vue/cli-service-4.5.13.tgz?cache=0&sync_timestamp=1620981774837&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40vue%2Fcli-service%2Fdownload%2F%40vue%2Fcli-service-4.5.13.tgz",
- "integrity": "sha1-oJ5oSoAWhLbiTlQUrTBlCXDuye0=",
- "dev": true,
- "requires": {
- "@intervolga/optimize-cssnano-plugin": "^1.0.5",
- "@soda/friendly-errors-webpack-plugin": "^1.7.1",
- "@soda/get-current-script": "^1.0.0",
- "@types/minimist": "^1.2.0",
- "@types/webpack": "^4.0.0",
- "@types/webpack-dev-server": "^3.11.0",
- "@vue/cli-overlay": "^4.5.13",
- "@vue/cli-plugin-router": "^4.5.13",
- "@vue/cli-plugin-vuex": "^4.5.13",
- "@vue/cli-shared-utils": "^4.5.13",
- "@vue/component-compiler-utils": "^3.1.2",
- "@vue/preload-webpack-plugin": "^1.1.0",
- "@vue/web-component-wrapper": "^1.2.0",
- "acorn": "^7.4.0",
- "acorn-walk": "^7.1.1",
- "address": "^1.1.2",
- "autoprefixer": "^9.8.6",
- "browserslist": "^4.12.0",
- "cache-loader": "^4.1.0",
- "case-sensitive-paths-webpack-plugin": "^2.3.0",
- "cli-highlight": "^2.1.4",
- "clipboardy": "^2.3.0",
- "cliui": "^6.0.0",
- "copy-webpack-plugin": "^5.1.1",
- "css-loader": "^3.5.3",
- "cssnano": "^4.1.10",
- "debug": "^4.1.1",
- "default-gateway": "^5.0.5",
- "dotenv": "^8.2.0",
- "dotenv-expand": "^5.1.0",
- "file-loader": "^4.2.0",
- "fs-extra": "^7.0.1",
- "globby": "^9.2.0",
- "hash-sum": "^2.0.0",
- "html-webpack-plugin": "^3.2.0",
- "launch-editor-middleware": "^2.2.1",
- "lodash.defaultsdeep": "^4.6.1",
- "lodash.mapvalues": "^4.6.0",
- "lodash.transform": "^4.6.0",
- "mini-css-extract-plugin": "^0.9.0",
- "minimist": "^1.2.5",
- "pnp-webpack-plugin": "^1.6.4",
- "portfinder": "^1.0.26",
- "postcss-loader": "^3.0.0",
- "ssri": "^8.0.1",
- "terser-webpack-plugin": "^1.4.4",
- "thread-loader": "^2.1.3",
- "url-loader": "^2.2.0",
- "vue-loader": "^15.9.2",
- "vue-loader-v16": "npm:vue-loader@^16.1.0",
- "vue-style-loader": "^4.1.2",
- "webpack": "^4.0.0",
- "webpack-bundle-analyzer": "^3.8.0",
- "webpack-chain": "^6.4.0",
- "webpack-dev-server": "^3.11.0",
- "webpack-merge": "^4.2.2"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.nlark.com/acorn/download/acorn-7.4.1.tgz",
- "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
- "dev": true
- },
- "ssri": {
- "version": "8.0.1",
- "resolved": "https://registry.nlark.com/ssri/download/ssri-8.0.1.tgz?cache=0&sync_timestamp=1621364626710&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
- "integrity": "sha1-Y45OQ54v+9LNKJd21cpFfE9Roq8=",
- "dev": true,
- "requires": {
- "minipass": "^3.1.1"
- }
- }
- }
- },
- "@vue/cli-shared-utils": {
- "version": "4.5.13",
- "resolved": "https://registry.nlark.com/@vue/cli-shared-utils/download/@vue/cli-shared-utils-4.5.13.tgz",
- "integrity": "sha1-rNQPMbR5DxY0KSvapfypXcHg/1A=",
- "dev": true,
- "requires": {
- "@hapi/joi": "^15.0.1",
- "chalk": "^2.4.2",
- "execa": "^1.0.0",
- "launch-editor": "^2.2.1",
- "lru-cache": "^5.1.1",
- "node-ipc": "^9.1.1",
- "open": "^6.3.0",
- "ora": "^3.4.0",
- "read-pkg": "^5.1.1",
- "request": "^2.88.2",
- "semver": "^6.1.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "@vue/compiler-core": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/compiler-core/download/@vue/compiler-core-3.0.11.tgz",
- "integrity": "sha1-XvV55G17M2uHNSKHWNHCxQWq5po=",
- "requires": {
- "@babel/parser": "^7.12.0",
- "@babel/types": "^7.12.0",
- "@vue/shared": "3.0.11",
- "estree-walker": "^2.0.1",
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM="
- }
- }
- },
- "@vue/compiler-dom": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/compiler-dom/download/@vue/compiler-dom-3.0.11.tgz",
- "integrity": "sha1-sV/ByQk3H9ZxdGAgulW12rSnMO4=",
- "requires": {
- "@vue/compiler-core": "3.0.11",
- "@vue/shared": "3.0.11"
- }
- },
- "@vue/compiler-sfc": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/compiler-sfc/download/@vue/compiler-sfc-3.0.11.tgz",
- "integrity": "sha1-zYyiFUuIlntSH1rTsQ9fi2tmVnk=",
- "dev": true,
- "requires": {
- "@babel/parser": "^7.13.9",
- "@babel/types": "^7.13.0",
- "@vue/compiler-core": "3.0.11",
- "@vue/compiler-dom": "3.0.11",
- "@vue/compiler-ssr": "3.0.11",
- "@vue/shared": "3.0.11",
- "consolidate": "^0.16.0",
- "estree-walker": "^2.0.1",
- "hash-sum": "^2.0.0",
- "lru-cache": "^5.1.1",
- "magic-string": "^0.25.7",
- "merge-source-map": "^1.1.0",
- "postcss": "^8.1.10",
- "postcss-modules": "^4.0.0",
- "postcss-selector-parser": "^6.0.4",
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "consolidate": {
- "version": "0.16.0",
- "resolved": "https://registry.npm.taobao.org/consolidate/download/consolidate-0.16.0.tgz",
- "integrity": "sha1-oRhkdokw8vGUMWYKZZBmaPX73BY=",
- "dev": true,
- "requires": {
- "bluebird": "^3.7.2"
- }
- },
- "postcss": {
- "version": "8.3.0",
- "resolved": "https://registry.nlark.com/postcss/download/postcss-8.3.0.tgz?cache=0&sync_timestamp=1621568644827&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss%2Fdownload%2Fpostcss-8.3.0.tgz",
- "integrity": "sha1-sacT9hcspCfj8F7xMD3otlaDMl8=",
- "dev": true,
- "requires": {
- "colorette": "^1.2.2",
- "nanoid": "^3.1.23",
- "source-map-js": "^0.6.2"
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "@vue/compiler-ssr": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/compiler-ssr/download/@vue/compiler-ssr-3.0.11.tgz",
- "integrity": "sha1-rFoF/RJXQS+mYHnII9ggO2qImhM=",
- "dev": true,
- "requires": {
- "@vue/compiler-dom": "3.0.11",
- "@vue/shared": "3.0.11"
- }
- },
- "@vue/component-compiler-utils": {
- "version": "3.2.0",
- "resolved": "https://registry.npm.taobao.org/@vue/component-compiler-utils/download/@vue/component-compiler-utils-3.2.0.tgz",
- "integrity": "sha1-j4UYLO7Sjps8dTE95mn4MWbRHl0=",
- "dev": true,
- "requires": {
- "consolidate": "^0.15.1",
- "hash-sum": "^1.0.2",
- "lru-cache": "^4.1.2",
- "merge-source-map": "^1.1.0",
- "postcss": "^7.0.14",
- "postcss-selector-parser": "^6.0.2",
- "prettier": "^1.18.2",
- "source-map": "~0.6.1",
- "vue-template-es2015-compiler": "^1.9.0"
- },
- "dependencies": {
- "hash-sum": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
- "dev": true
- },
- "lru-cache": {
- "version": "4.1.5",
- "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-4.1.5.tgz",
- "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
- "dev": true,
- "requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- },
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
- "dev": true
- }
- }
- },
- "@vue/devtools-api": {
- "version": "6.0.0-beta.12",
- "resolved": "https://registry.nlark.com/@vue/devtools-api/download/@vue/devtools-api-6.0.0-beta.12.tgz",
- "integrity": "sha1-aT/8d7+2awgOXJV2q7V4bIVHCjI="
- },
- "@vue/preload-webpack-plugin": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.2.tgz",
- "integrity": "sha1-zrkktOyzucQ4ccekKaAvhCPmIas=",
- "dev": true
- },
- "@vue/reactivity": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/reactivity/download/@vue/reactivity-3.0.11.tgz",
- "integrity": "sha1-B7WINJ/QViaxfzUAy+99S9tNvQs=",
- "requires": {
- "@vue/shared": "3.0.11"
- }
- },
- "@vue/runtime-core": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/runtime-core/download/@vue/runtime-core-3.0.11.tgz",
- "integrity": "sha1-xS38as8yFUk2I1UsHCkZCAxWLkQ=",
- "requires": {
- "@vue/reactivity": "3.0.11",
- "@vue/shared": "3.0.11"
- }
- },
- "@vue/runtime-dom": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/runtime-dom/download/@vue/runtime-dom-3.0.11.tgz",
- "integrity": "sha1-elUt8hkHlCch/raWHEGOIippkzc=",
- "requires": {
- "@vue/runtime-core": "3.0.11",
- "@vue/shared": "3.0.11",
- "csstype": "^2.6.8"
- }
- },
- "@vue/shared": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/@vue/shared/download/@vue/shared-3.0.11.tgz",
- "integrity": "sha1-INIt0Np9NYuyHBf5vehigVJkLHc="
- },
- "@vue/web-component-wrapper": {
- "version": "1.3.0",
- "resolved": "https://registry.npm.taobao.org/@vue/web-component-wrapper/download/@vue/web-component-wrapper-1.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fweb-component-wrapper%2Fdownload%2F%40vue%2Fweb-component-wrapper-1.3.0.tgz",
- "integrity": "sha1-trQKdiVCnSvXwigd26YB7QXcfxo=",
- "dev": true
- },
- "@wailsapp/runtime": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/@wailsapp/runtime/download/@wailsapp/runtime-1.1.1.tgz",
- "integrity": "sha1-Mj99KQN40wzs7KeR6wpUWyhEE0k="
- },
- "@webassemblyjs/ast": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ast/download/@webassemblyjs/ast-1.9.0.tgz?cache=0&sync_timestamp=1610041327965&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fast%2Fdownload%2F%40webassemblyjs%2Fast-1.9.0.tgz",
- "integrity": "sha1-vYUGBLQEJFmlpBzX0zjL7Wle2WQ=",
- "dev": true,
- "requires": {
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0"
- }
- },
- "@webassemblyjs/floating-point-hex-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/floating-point-hex-parser/download/@webassemblyjs/floating-point-hex-parser-1.9.0.tgz?cache=0&sync_timestamp=1610043274676&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Ffloating-point-hex-parser%2Fdownload%2F%40webassemblyjs%2Ffloating-point-hex-parser-1.9.0.tgz",
- "integrity": "sha1-PD07Jxvd/ITesA9xNEQ4MR1S/7Q=",
- "dev": true
- },
- "@webassemblyjs/helper-api-error": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-api-error/download/@webassemblyjs/helper-api-error-1.9.0.tgz?cache=0&sync_timestamp=1610041334619&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-api-error%2Fdownload%2F%40webassemblyjs%2Fhelper-api-error-1.9.0.tgz",
- "integrity": "sha1-ID9nbjM7lsnaLuqzzO8zxFkotqI=",
- "dev": true
- },
- "@webassemblyjs/helper-buffer": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-buffer/download/@webassemblyjs/helper-buffer-1.9.0.tgz?cache=0&sync_timestamp=1610041334130&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-buffer%2Fdownload%2F%40webassemblyjs%2Fhelper-buffer-1.9.0.tgz",
- "integrity": "sha1-oUQtJpxf6yP8vJ73WdrDVH8p3gA=",
- "dev": true
- },
- "@webassemblyjs/helper-code-frame": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-code-frame/download/@webassemblyjs/helper-code-frame-1.9.0.tgz?cache=0&sync_timestamp=1610041493871&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-code-frame%2Fdownload%2F%40webassemblyjs%2Fhelper-code-frame-1.9.0.tgz",
- "integrity": "sha1-ZH+Iks0gQ6gqwMjF51w28dkVnyc=",
- "dev": true,
- "requires": {
- "@webassemblyjs/wast-printer": "1.9.0"
- }
- },
- "@webassemblyjs/helper-fsm": {
- "version": "1.9.0",
- "resolved": "https://registry.nlark.com/@webassemblyjs/helper-fsm/download/@webassemblyjs/helper-fsm-1.9.0.tgz",
- "integrity": "sha1-wFJWtxJEIUZx9LCOwQitY7cO3bg=",
- "dev": true
- },
- "@webassemblyjs/helper-module-context": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-module-context/download/@webassemblyjs/helper-module-context-1.9.0.tgz",
- "integrity": "sha1-JdiIS3aDmHGgimxvgGw5ee9xLwc=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0"
- }
- },
- "@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-bytecode/download/@webassemblyjs/helper-wasm-bytecode-1.9.0.tgz?cache=0&sync_timestamp=1610041334247&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-wasm-bytecode%2Fdownload%2F%40webassemblyjs%2Fhelper-wasm-bytecode-1.9.0.tgz",
- "integrity": "sha1-T+2L6sm4wU+MWLcNEk1UndH+V5A=",
- "dev": true
- },
- "@webassemblyjs/helper-wasm-section": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-section/download/@webassemblyjs/helper-wasm-section-1.9.0.tgz?cache=0&sync_timestamp=1610041332602&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-wasm-section%2Fdownload%2F%40webassemblyjs%2Fhelper-wasm-section-1.9.0.tgz",
- "integrity": "sha1-WkE41aYpK6GLBMWuSXF+QWeWU0Y=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0"
- }
- },
- "@webassemblyjs/ieee754": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ieee754/download/@webassemblyjs/ieee754-1.9.0.tgz?cache=0&sync_timestamp=1610041334740&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fieee754%2Fdownload%2F%40webassemblyjs%2Fieee754-1.9.0.tgz",
- "integrity": "sha1-Fceg+6roP7JhQ7us9tbfFwKtOeQ=",
- "dev": true,
- "requires": {
- "@xtuc/ieee754": "^1.2.0"
- }
- },
- "@webassemblyjs/leb128": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/leb128/download/@webassemblyjs/leb128-1.9.0.tgz",
- "integrity": "sha1-8Zygt2ptxVYjoJz/p2noOPoeHJU=",
- "dev": true,
- "requires": {
- "@xtuc/long": "4.2.2"
- }
- },
- "@webassemblyjs/utf8": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/utf8/download/@webassemblyjs/utf8-1.9.0.tgz?cache=0&sync_timestamp=1610041334838&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Futf8%2Fdownload%2F%40webassemblyjs%2Futf8-1.9.0.tgz",
- "integrity": "sha1-BNM7Y2945qaBMifoJAL3Y3tiKas=",
- "dev": true
- },
- "@webassemblyjs/wasm-edit": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-edit/download/@webassemblyjs/wasm-edit-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-edit%2Fdownload%2F%40webassemblyjs%2Fwasm-edit-1.9.0.tgz",
- "integrity": "sha1-P+bXnT8PkiGDqoYALELdJWz+6c8=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/helper-wasm-section": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-opt": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "@webassemblyjs/wast-printer": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-gen": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-gen/download/@webassemblyjs/wasm-gen-1.9.0.tgz?cache=0&sync_timestamp=1610041335808&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-gen%2Fdownload%2F%40webassemblyjs%2Fwasm-gen-1.9.0.tgz",
- "integrity": "sha1-ULxw7Gje2OJ2OwGhQYv0NJGnpJw=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-opt": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-opt/download/@webassemblyjs/wasm-opt-1.9.0.tgz?cache=0&sync_timestamp=1610041336191&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-opt%2Fdownload%2F%40webassemblyjs%2Fwasm-opt-1.9.0.tgz",
- "integrity": "sha1-IhEYHlsxMmRDzIES658LkChyGmE=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-parser/download/@webassemblyjs/wasm-parser-1.9.0.tgz?cache=0&sync_timestamp=1610041328345&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-parser%2Fdownload%2F%40webassemblyjs%2Fwasm-parser-1.9.0.tgz",
- "integrity": "sha1-nUjkSCbfSmWYKUqmyHRp1kL/9l4=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
- }
- },
- "@webassemblyjs/wast-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-parser/download/@webassemblyjs/wast-parser-1.9.0.tgz?cache=0&sync_timestamp=1610041489596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwast-parser%2Fdownload%2F%40webassemblyjs%2Fwast-parser-1.9.0.tgz",
- "integrity": "sha1-MDERXXmsW9JhVWzsw/qQo+9FGRQ=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/floating-point-hex-parser": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-code-frame": "1.9.0",
- "@webassemblyjs/helper-fsm": "1.9.0",
- "@xtuc/long": "4.2.2"
- }
- },
- "@webassemblyjs/wast-printer": {
- "version": "1.9.0",
- "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-printer/download/@webassemblyjs/wast-printer-1.9.0.tgz?cache=0&sync_timestamp=1610041335289&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwast-printer%2Fdownload%2F%40webassemblyjs%2Fwast-printer-1.9.0.tgz",
- "integrity": "sha1-STXVTIX+9jewDOn1I3dFHQDUeJk=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0",
- "@xtuc/long": "4.2.2"
- }
- },
- "@xtuc/ieee754": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz",
- "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=",
- "dev": true
- },
- "@xtuc/long": {
- "version": "4.2.2",
- "resolved": "https://registry.npm.taobao.org/@xtuc/long/download/@xtuc/long-4.2.2.tgz",
- "integrity": "sha1-0pHGpOl5ibXGHZrPOWrk/hM6cY0=",
- "dev": true
- },
- "accepts": {
- "version": "1.3.7",
- "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
- "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
- "dev": true,
- "requires": {
- "mime-types": "~2.1.24",
- "negotiator": "0.6.2"
- }
- },
- "acorn": {
- "version": "6.4.2",
- "resolved": "https://registry.nlark.com/acorn/download/acorn-6.4.2.tgz",
- "integrity": "sha1-NYZv1xBSjpLeEM8GAWSY5H454eY=",
- "dev": true
- },
- "acorn-jsx": {
- "version": "5.3.1",
- "resolved": "https://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.3.1.tgz?cache=0&sync_timestamp=1599499155970&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn-jsx%2Fdownload%2Facorn-jsx-5.3.1.tgz",
- "integrity": "sha1-/IZh4Rt6wVOcR9v+oucrOvNNJns=",
- "dev": true
- },
- "acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.nlark.com/acorn-walk/download/acorn-walk-7.2.0.tgz",
- "integrity": "sha1-DeiJpgEgOQmw++B7iTjcIdLpZ7w=",
- "dev": true
- },
- "address": {
- "version": "1.1.2",
- "resolved": "https://registry.npm.taobao.org/address/download/address-1.1.2.tgz",
- "integrity": "sha1-vxEWycdYxRt6kz0pa3LCIe2UKLY=",
- "dev": true
- },
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.nlark.com/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1621517694340&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
- "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ajv-errors": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/ajv-errors/download/ajv-errors-1.0.1.tgz",
- "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=",
- "dev": true
- },
- "ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz",
- "integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
- "dev": true
- },
- "alphanum-sort": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/alphanum-sort/download/alphanum-sort-1.0.2.tgz",
- "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
- "dev": true
- },
- "ansi-colors": {
- "version": "3.2.4",
- "resolved": "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz",
- "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=",
- "dev": true
- },
- "ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.nlark.com/ansi-escapes/download/ansi-escapes-4.3.2.tgz?cache=0&sync_timestamp=1618847144938&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-escapes%2Fdownload%2Fansi-escapes-4.3.2.tgz",
- "integrity": "sha1-ayKR0dt9mLZSHV8e+kLQ86n+tl4=",
- "dev": true,
- "requires": {
- "type-fest": "^0.21.3"
- },
- "dependencies": {
- "type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.nlark.com/type-fest/download/type-fest-0.21.3.tgz?cache=0&sync_timestamp=1621402446336&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.21.3.tgz",
- "integrity": "sha1-0mCiSwGYQ24TP6JqUkptZfo7Ljc=",
- "dev": true
- }
- }
- },
- "ansi-html": {
- "version": "0.0.7",
- "resolved": "https://registry.nlark.com/ansi-html/download/ansi-html-0.0.7.tgz",
- "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
- "dev": true
- },
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
- "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-3.2.1.tgz",
- "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.nlark.com/any-promise/download/any-promise-1.3.0.tgz",
- "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
- "dev": true
- },
- "anymatch": {
- "version": "3.1.2",
- "resolved": "https://registry.nlark.com/anymatch/download/anymatch-3.1.2.tgz",
- "integrity": "sha1-wFV8CWrzLxBhmPT04qODU343hxY=",
- "dev": true,
- "requires": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- }
- },
- "aproba": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/aproba/download/aproba-1.2.0.tgz",
- "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=",
- "dev": true
- },
- "arch": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/arch/download/arch-2.2.0.tgz",
- "integrity": "sha1-G8R4GPMFdk8jqzMGsL/AhsWinRE=",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz",
- "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/arr-diff/download/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
- },
- "arr-flatten": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/arr-flatten/download/arr-flatten-1.1.0.tgz?cache=0&sync_timestamp=1618846805394&other_urls=https%3A%2F%2Fregistry.nlark.com%2Farr-flatten%2Fdownload%2Farr-flatten-1.1.0.tgz",
- "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
- "dev": true
- },
- "arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/arr-union/download/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
- "dev": true
- },
- "array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/array-flatten/download/array-flatten-1.1.1.tgz",
- "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
- "dev": true
- },
- "array-union": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz?cache=0&sync_timestamp=1614624407140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-union%2Fdownload%2Farray-union-1.0.2.tgz",
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
- "dev": true,
- "requires": {
- "array-uniq": "^1.0.1"
- }
- },
- "array-uniq": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/array-uniq/download/array-uniq-1.0.3.tgz?cache=0&sync_timestamp=1620042121153&other_urls=https%3A%2F%2Fregistry.nlark.com%2Farray-uniq%2Fdownload%2Farray-uniq-1.0.3.tgz",
- "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
- "dev": true
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.nlark.com/array-unique/download/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
- },
- "asn1": {
- "version": "0.2.4",
- "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz",
- "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
- "dev": true,
- "requires": {
- "safer-buffer": "~2.1.0"
- }
- },
- "asn1.js": {
- "version": "5.4.1",
- "resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-5.4.1.tgz",
- "integrity": "sha1-EamAuE67kXgc41sP3C7ilON4Pwc=",
- "dev": true,
- "requires": {
- "bn.js": "^4.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "safer-buffer": "^2.1.0"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "assert": {
- "version": "1.5.0",
- "resolved": "https://registry.nlark.com/assert/download/assert-1.5.0.tgz?cache=0&sync_timestamp=1618847153747&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fassert%2Fdownload%2Fassert-1.5.0.tgz",
- "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=",
- "dev": true,
- "requires": {
- "object-assign": "^4.1.1",
- "util": "0.10.3"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.1.tgz",
- "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
- "dev": true
- },
- "util": {
- "version": "0.10.3",
- "resolved": "https://registry.nlark.com/util/download/util-0.10.3.tgz?cache=0&sync_timestamp=1622213047493&other_urls=https%3A%2F%2Fregistry.nlark.com%2Futil%2Fdownload%2Futil-0.10.3.tgz",
- "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
- "dev": true,
- "requires": {
- "inherits": "2.0.1"
- }
- }
- }
- },
- "assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/assert-plus/download/assert-plus-1.0.0.tgz",
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
- "dev": true
- },
- "assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
- "dev": true
- },
- "astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/astral-regex/download/astral-regex-1.0.0.tgz",
- "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=",
- "dev": true
- },
- "async": {
- "version": "2.6.3",
- "resolved": "https://registry.nlark.com/async/download/async-2.6.3.tgz",
- "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=",
- "dev": true,
- "requires": {
- "lodash": "^4.17.14"
- }
- },
- "async-each": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz",
- "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=",
- "dev": true
- },
- "async-limiter": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz",
- "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
- "dev": true
- },
- "asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.nlark.com/asynckit/download/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
- "dev": true
- },
- "atob": {
- "version": "2.1.2",
- "resolved": "https://registry.nlark.com/atob/download/atob-2.1.2.tgz",
- "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=",
- "dev": true
- },
- "autoprefixer": {
- "version": "9.8.6",
- "resolved": "https://registry.nlark.com/autoprefixer/download/autoprefixer-9.8.6.tgz?cache=0&sync_timestamp=1622039586788&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fautoprefixer%2Fdownload%2Fautoprefixer-9.8.6.tgz",
- "integrity": "sha1-O3NZTKG/kmYyDFrPFYjXTep0IQ8=",
- "dev": true,
- "requires": {
- "browserslist": "^4.12.0",
- "caniuse-lite": "^1.0.30001109",
- "colorette": "^1.2.1",
- "normalize-range": "^0.1.2",
- "num2fraction": "^1.2.2",
- "postcss": "^7.0.32",
- "postcss-value-parser": "^4.1.0"
- }
- },
- "aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz",
- "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
- "dev": true
- },
- "aws4": {
- "version": "1.11.0",
- "resolved": "https://registry.nlark.com/aws4/download/aws4-1.11.0.tgz",
- "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
- "dev": true
- },
- "babel-eslint": {
- "version": "10.1.0",
- "resolved": "https://registry.nlark.com/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1618846971799&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz",
- "integrity": "sha1-aWjlaKkQt4+zd5zdi2rC9HmUMjI=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "@babel/parser": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0",
- "eslint-visitor-keys": "^1.0.0",
- "resolve": "^1.12.0"
- }
- },
- "babel-loader": {
- "version": "8.2.2",
- "resolved": "https://registry.nlark.com/babel-loader/download/babel-loader-8.2.2.tgz",
- "integrity": "sha1-k2POhMEMmkDmx1N0jhRBtgyKC4E=",
- "dev": true,
- "requires": {
- "find-cache-dir": "^3.3.1",
- "loader-utils": "^1.4.0",
- "make-dir": "^3.1.0",
- "schema-utils": "^2.6.5"
- }
- },
- "babel-plugin-dynamic-import-node": {
- "version": "2.3.3",
- "resolved": "https://registry.nlark.com/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.3.3.tgz?cache=0&sync_timestamp=1618846790496&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-plugin-dynamic-import-node%2Fdownload%2Fbabel-plugin-dynamic-import-node-2.3.3.tgz",
- "integrity": "sha1-hP2hnJduxcbe/vV/lCez3vZuF6M=",
- "dev": true,
- "requires": {
- "object.assign": "^4.1.0"
- }
- },
- "babel-plugin-polyfill-corejs2": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/babel-plugin-polyfill-corejs2/download/babel-plugin-polyfill-corejs2-0.2.2.tgz?cache=0&sync_timestamp=1622023904181&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-plugin-polyfill-corejs2%2Fdownload%2Fbabel-plugin-polyfill-corejs2-0.2.2.tgz",
- "integrity": "sha1-6RJHheb9lPlLYYp5VOVpMFO/Uyc=",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.13.11",
- "@babel/helper-define-polyfill-provider": "^0.2.2",
- "semver": "^6.1.1"
- }
- },
- "babel-plugin-polyfill-corejs3": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/babel-plugin-polyfill-corejs3/download/babel-plugin-polyfill-corejs3-0.2.2.tgz?cache=0&sync_timestamp=1622023907017&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-plugin-polyfill-corejs3%2Fdownload%2Fbabel-plugin-polyfill-corejs3-0.2.2.tgz",
- "integrity": "sha1-dCShaC7kS67IFzJ3ELGwlOX49/U=",
- "dev": true,
- "requires": {
- "@babel/helper-define-polyfill-provider": "^0.2.2",
- "core-js-compat": "^3.9.1"
- }
- },
- "babel-plugin-polyfill-regenerator": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/babel-plugin-polyfill-regenerator/download/babel-plugin-polyfill-regenerator-0.2.2.tgz?cache=0&sync_timestamp=1622023907940&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-plugin-polyfill-regenerator%2Fdownload%2Fbabel-plugin-polyfill-regenerator-0.2.2.tgz",
- "integrity": "sha1-sxDI1kKsraNIwfo7Pmzg6FG+4Hc=",
- "dev": true,
- "requires": {
- "@babel/helper-define-polyfill-provider": "^0.2.2"
- }
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbalanced-match%2Fdownload%2Fbalanced-match-1.0.2.tgz",
- "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=",
- "dev": true
- },
- "base": {
- "version": "0.11.2",
- "resolved": "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz",
- "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
- "dev": true,
- "requires": {
- "cache-base": "^1.0.1",
- "class-utils": "^0.3.5",
- "component-emitter": "^1.2.1",
- "define-property": "^1.0.0",
- "isobject": "^3.0.1",
- "mixin-deep": "^1.2.0",
- "pascalcase": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
- "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.nlark.com/base64-js/download/base64-js-1.5.1.tgz",
- "integrity": "sha1-GxtEAWClv3rUC2UPCVljSBkDkwo=",
- "dev": true
- },
- "batch": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz",
- "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
- "dev": true
- },
- "bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
- "dev": true,
- "requires": {
- "tweetnacl": "^0.14.3"
- }
- },
- "bfj": {
- "version": "6.1.2",
- "resolved": "https://registry.npm.taobao.org/bfj/download/bfj-6.1.2.tgz",
- "integrity": "sha1-MlyGGoIryzWKQceKM7jm4ght3n8=",
- "dev": true,
- "requires": {
- "bluebird": "^3.5.5",
- "check-types": "^8.0.3",
- "hoopy": "^0.1.4",
- "tryer": "^1.0.1"
- }
- },
- "big.js": {
- "version": "5.2.2",
- "resolved": "https://registry.nlark.com/big.js/download/big.js-5.2.2.tgz",
- "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=",
- "dev": true
- },
- "binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.nlark.com/binary-extensions/download/binary-extensions-2.2.0.tgz",
- "integrity": "sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0=",
- "dev": true,
- "optional": true
- },
- "bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.nlark.com/bindings/download/bindings-1.5.0.tgz",
- "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=",
- "dev": true,
- "optional": true,
- "requires": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.nlark.com/bluebird/download/bluebird-3.7.2.tgz?cache=0&sync_timestamp=1618847007562&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbluebird%2Fdownload%2Fbluebird-3.7.2.tgz",
- "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=",
- "dev": true
- },
- "bn.js": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.2.0.tgz",
- "integrity": "sha1-NYhgZ0OWxpl3canQUfzBtX1K4AI=",
- "dev": true
- },
- "body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz",
- "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=",
- "dev": true,
- "requires": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "qs": {
- "version": "6.7.0",
- "resolved": "https://registry.nlark.com/qs/download/qs-6.7.0.tgz",
- "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=",
- "dev": true
- }
- }
- },
- "bonjour": {
- "version": "3.5.0",
- "resolved": "https://registry.nlark.com/bonjour/download/bonjour-3.5.0.tgz",
- "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
- "dev": true,
- "requires": {
- "array-flatten": "^2.1.0",
- "deep-equal": "^1.0.1",
- "dns-equal": "^1.0.0",
- "dns-txt": "^2.0.2",
- "multicast-dns": "^6.0.1",
- "multicast-dns-service-types": "^1.1.0"
- },
- "dependencies": {
- "array-flatten": {
- "version": "2.1.2",
- "resolved": "https://registry.nlark.com/array-flatten/download/array-flatten-2.1.2.tgz",
- "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=",
- "dev": true
- }
- }
- },
- "boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/boolbase/download/boolbase-1.0.0.tgz",
- "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.nlark.com/brace-expansion/download/brace-expansion-1.1.11.tgz",
- "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz",
- "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/brorand/download/brorand-1.1.0.tgz",
- "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
- "dev": true
- },
- "browserify-aes": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/browserify-aes/download/browserify-aes-1.2.0.tgz",
- "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=",
- "dev": true,
- "requires": {
- "buffer-xor": "^1.0.3",
- "cipher-base": "^1.0.0",
- "create-hash": "^1.1.0",
- "evp_bytestokey": "^1.0.3",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "browserify-cipher": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/browserify-cipher/download/browserify-cipher-1.0.1.tgz",
- "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=",
- "dev": true,
- "requires": {
- "browserify-aes": "^1.0.4",
- "browserify-des": "^1.0.0",
- "evp_bytestokey": "^1.0.0"
- }
- },
- "browserify-des": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/browserify-des/download/browserify-des-1.0.2.tgz",
- "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.1",
- "des.js": "^1.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "browserify-rsa": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/browserify-rsa/download/browserify-rsa-4.1.0.tgz",
- "integrity": "sha1-sv0Gtbda4pf3zi3GUfkY9b4VjI0=",
- "dev": true,
- "requires": {
- "bn.js": "^5.0.0",
- "randombytes": "^2.0.1"
- }
- },
- "browserify-sign": {
- "version": "4.2.1",
- "resolved": "https://registry.nlark.com/browserify-sign/download/browserify-sign-4.2.1.tgz",
- "integrity": "sha1-6vSt1G3VS+O7OzbAzxWrvrp5VsM=",
- "dev": true,
- "requires": {
- "bn.js": "^5.1.1",
- "browserify-rsa": "^4.0.1",
- "create-hash": "^1.2.0",
- "create-hmac": "^1.1.7",
- "elliptic": "^6.5.3",
- "inherits": "^2.0.4",
- "parse-asn1": "^5.1.5",
- "readable-stream": "^3.6.0",
- "safe-buffer": "^5.2.0"
- },
- "dependencies": {
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.nlark.com/readable-stream/download/readable-stream-3.6.0.tgz",
- "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- },
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.2.1.tgz",
- "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=",
- "dev": true
- }
- }
- },
- "browserify-zlib": {
- "version": "0.2.0",
- "resolved": "https://registry.nlark.com/browserify-zlib/download/browserify-zlib-0.2.0.tgz",
- "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
- "dev": true,
- "requires": {
- "pako": "~1.0.5"
- }
- },
- "browserslist": {
- "version": "4.16.6",
- "resolved": "https://registry.nlark.com/browserslist/download/browserslist-4.16.6.tgz?cache=0&sync_timestamp=1619789101558&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.16.6.tgz",
- "integrity": "sha1-15ASd6WojlVO0wWxg+ybDAj2b6I=",
- "dev": true,
- "requires": {
- "caniuse-lite": "^1.0.30001219",
- "colorette": "^1.2.2",
- "electron-to-chromium": "^1.3.723",
- "escalade": "^3.1.1",
- "node-releases": "^1.1.71"
- }
- },
- "buffer": {
- "version": "4.9.2",
- "resolved": "https://registry.nlark.com/buffer/download/buffer-4.9.2.tgz",
- "integrity": "sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg=",
- "dev": true,
- "requires": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4",
- "isarray": "^1.0.0"
- }
- },
- "buffer-from": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz",
- "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=",
- "dev": true
- },
- "buffer-indexof": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/buffer-indexof/download/buffer-indexof-1.1.1.tgz",
- "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=",
- "dev": true
- },
- "buffer-json": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/buffer-json/download/buffer-json-2.0.0.tgz",
- "integrity": "sha1-9z4TseQvGW/i/WfQAcfXEH7dfCM=",
- "dev": true
- },
- "buffer-xor": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz",
- "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
- "dev": true
- },
- "builtin-status-codes": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz",
- "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
- "dev": true
- },
- "bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz",
- "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=",
- "dev": true
- },
- "cacache": {
- "version": "12.0.4",
- "resolved": "https://registry.nlark.com/cacache/download/cacache-12.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcacache%2Fdownload%2Fcacache-12.0.4.tgz",
- "integrity": "sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw=",
- "dev": true,
- "requires": {
- "bluebird": "^3.5.5",
- "chownr": "^1.1.1",
- "figgy-pudding": "^3.5.1",
- "glob": "^7.1.4",
- "graceful-fs": "^4.1.15",
- "infer-owner": "^1.0.3",
- "lru-cache": "^5.1.1",
- "mississippi": "^3.0.0",
- "mkdirp": "^0.5.1",
- "move-concurrently": "^1.0.1",
- "promise-inflight": "^1.0.1",
- "rimraf": "^2.6.3",
- "ssri": "^6.0.1",
- "unique-filename": "^1.1.1",
- "y18n": "^4.0.0"
- }
- },
- "cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz",
- "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
- "dev": true,
- "requires": {
- "collection-visit": "^1.0.0",
- "component-emitter": "^1.2.1",
- "get-value": "^2.0.6",
- "has-value": "^1.0.0",
- "isobject": "^3.0.1",
- "set-value": "^2.0.0",
- "to-object-path": "^0.3.0",
- "union-value": "^1.0.0",
- "unset-value": "^1.0.0"
- }
- },
- "cache-loader": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/cache-loader/download/cache-loader-4.1.0.tgz",
- "integrity": "sha1-mUjK41OuwKH8ser9ojAIFuyFOH4=",
- "dev": true,
- "requires": {
- "buffer-json": "^2.0.0",
- "find-cache-dir": "^3.0.0",
- "loader-utils": "^1.2.3",
- "mkdirp": "^0.5.1",
- "neo-async": "^2.6.1",
- "schema-utils": "^2.0.0"
- }
- },
- "call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/call-bind/download/call-bind-1.0.2.tgz",
- "integrity": "sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw=",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- }
- },
- "call-me-maybe": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/call-me-maybe/download/call-me-maybe-1.0.1.tgz",
- "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
- "dev": true
- },
- "caller-callsite": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/caller-callsite/download/caller-callsite-2.0.0.tgz",
- "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
- "dev": true,
- "requires": {
- "callsites": "^2.0.0"
- }
- },
- "caller-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz",
- "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
- "dev": true,
- "requires": {
- "caller-callsite": "^2.0.0"
- }
- },
- "callsites": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz",
- "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
- "dev": true
- },
- "camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/camel-case/download/camel-case-3.0.0.tgz?cache=0&sync_timestamp=1606867297052&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamel-case%2Fdownload%2Fcamel-case-3.0.0.tgz",
- "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
- "dev": true,
- "requires": {
- "no-case": "^2.2.0",
- "upper-case": "^1.1.1"
- }
- },
- "camelcase": {
- "version": "6.2.0",
- "resolved": "https://registry.nlark.com/camelcase/download/camelcase-6.2.0.tgz",
- "integrity": "sha1-kkr4gcnVJaydh/QNlk5c6pgqGAk=",
- "dev": true
- },
- "caniuse-api": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/caniuse-api/download/caniuse-api-3.0.0.tgz",
- "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "caniuse-lite": "^1.0.0",
- "lodash.memoize": "^4.1.2",
- "lodash.uniq": "^4.5.0"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001231",
- "resolved": "https://registry.nlark.com/caniuse-lite/download/caniuse-lite-1.0.30001231.tgz",
- "integrity": "sha1-bB+bSfwnzDaLiU5kubKLOe+AYDs=",
- "dev": true
- },
- "case-sensitive-paths-webpack-plugin": {
- "version": "2.4.0",
- "resolved": "https://registry.nlark.com/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
- "integrity": "sha1-22QGbGQi7tLgjMFLmGykN5bbxtQ=",
- "dev": true
- },
- "caseless": {
- "version": "0.12.0",
- "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz",
- "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
- "dev": true
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.nlark.com/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz",
- "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "chardet": {
- "version": "0.7.0",
- "resolved": "https://registry.nlark.com/chardet/download/chardet-0.7.0.tgz",
- "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=",
- "dev": true
- },
- "check-types": {
- "version": "8.0.3",
- "resolved": "https://registry.nlark.com/check-types/download/check-types-8.0.3.tgz",
- "integrity": "sha1-M1bMoZyIlUTy16le1JzlCKDs9VI=",
- "dev": true
- },
- "chokidar": {
- "version": "3.5.1",
- "resolved": "https://registry.nlark.com/chokidar/download/chokidar-3.5.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-3.5.1.tgz",
- "integrity": "sha1-7pznu+vSt59J8wR5nVRo4x4U5oo=",
- "dev": true,
- "optional": true,
- "requires": {
- "anymatch": "~3.1.1",
- "braces": "~3.0.2",
- "fsevents": "~2.3.1",
- "glob-parent": "~5.1.0",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.5.0"
- },
- "dependencies": {
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
- "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
- "dev": true,
- "optional": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz",
- "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
- "dev": true,
- "optional": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.nlark.com/is-number/download/is-number-7.0.0.tgz",
- "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=",
- "dev": true,
- "optional": true
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.nlark.com/to-regex-range/download/to-regex-range-5.0.1.tgz",
- "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- }
- }
- },
- "chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/chownr/download/chownr-1.1.4.tgz",
- "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=",
- "dev": true
- },
- "chrome-trace-event": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/chrome-trace-event/download/chrome-trace-event-1.0.3.tgz",
- "integrity": "sha1-EBXs7UdB4V0GZkqVfbv1DQQeJqw=",
- "dev": true
- },
- "ci-info": {
- "version": "1.6.0",
- "resolved": "https://registry.nlark.com/ci-info/download/ci-info-1.6.0.tgz?cache=0&sync_timestamp=1622039942508&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fci-info%2Fdownload%2Fci-info-1.6.0.tgz",
- "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc=",
- "dev": true
- },
- "cipher-base": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/cipher-base/download/cipher-base-1.0.4.tgz",
- "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "class-utils": {
- "version": "0.3.6",
- "resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz",
- "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "clean-css": {
- "version": "4.2.3",
- "resolved": "https://registry.npm.taobao.org/clean-css/download/clean-css-4.2.3.tgz?cache=0&sync_timestamp=1616153455026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fclean-css%2Fdownload%2Fclean-css-4.2.3.tgz",
- "integrity": "sha1-UHtd59l7SO5T2ErbAWD/YhY4D3g=",
- "dev": true,
- "requires": {
- "source-map": "~0.6.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "cli-cursor": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz",
- "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
- "dev": true,
- "requires": {
- "restore-cursor": "^2.0.0"
- }
- },
- "cli-highlight": {
- "version": "2.1.11",
- "resolved": "https://registry.npm.taobao.org/cli-highlight/download/cli-highlight-2.1.11.tgz?cache=0&sync_timestamp=1616955054342&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcli-highlight%2Fdownload%2Fcli-highlight-2.1.11.tgz",
- "integrity": "sha1-SXNvpFLwqvT65YDjCssmgo0twb8=",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "highlight.js": "^10.7.1",
- "mz": "^2.4.0",
- "parse5": "^5.1.1",
- "parse5-htmlparser2-tree-adapter": "^6.0.0",
- "yargs": "^16.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
- "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
- "dev": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "4.1.1",
- "resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.1.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.1.tgz",
- "integrity": "sha1-yAs/qyi/Y3HmhjMl7uZ+YYt35q0=",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
- "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
- "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
- "dev": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1618559676170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
- "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
- "dev": true
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
- "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "cli-spinners": {
- "version": "2.6.0",
- "resolved": "https://registry.npm.taobao.org/cli-spinners/download/cli-spinners-2.6.0.tgz?cache=0&sync_timestamp=1616091572272&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcli-spinners%2Fdownload%2Fcli-spinners-2.6.0.tgz",
- "integrity": "sha1-NsfcmPtqmna9YjjsP3fiQlYn6Tk=",
- "dev": true
- },
- "cli-width": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/cli-width/download/cli-width-3.0.0.tgz",
- "integrity": "sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=",
- "dev": true
- },
- "clipboardy": {
- "version": "2.3.0",
- "resolved": "https://registry.npm.taobao.org/clipboardy/download/clipboardy-2.3.0.tgz",
- "integrity": "sha1-PCkDZQxo5GqRs4iYW8J3QofbopA=",
- "dev": true,
- "requires": {
- "arch": "^2.1.1",
- "execa": "^1.0.0",
- "is-wsl": "^2.1.1"
- },
- "dependencies": {
- "is-wsl": {
- "version": "2.2.0",
- "resolved": "https://registry.nlark.com/is-wsl/download/is-wsl-2.2.0.tgz",
- "integrity": "sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE=",
- "dev": true,
- "requires": {
- "is-docker": "^2.0.0"
- }
- }
- }
- },
- "cliui": {
- "version": "6.0.0",
- "resolved": "https://registry.nlark.com/cliui/download/cliui-6.0.0.tgz",
- "integrity": "sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE=",
- "dev": true,
- "requires": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
- "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
- "dev": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
- "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
- "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
- "dev": true
- },
- "wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz",
- "integrity": "sha1-6Tk7oHEC5skaOyIUePAlfNKFblM=",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- }
- }
- }
- },
- "clone": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/clone/download/clone-1.0.4.tgz",
- "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
- "dev": true
- },
- "coa": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/coa/download/coa-2.0.2.tgz",
- "integrity": "sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM=",
- "dev": true,
- "requires": {
- "@types/q": "^1.5.1",
- "chalk": "^2.4.1",
- "q": "^1.1.2"
- }
- },
- "collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/collection-visit/download/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
- "dev": true,
- "requires": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
- }
- },
- "color": {
- "version": "3.1.3",
- "resolved": "https://registry.nlark.com/color/download/color-3.1.3.tgz?cache=0&sync_timestamp=1618846945133&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcolor%2Fdownload%2Fcolor-3.1.3.tgz",
- "integrity": "sha1-ymf7TnuX1hHc3jns7tQiBn2RWW4=",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.1",
- "color-string": "^1.5.4"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz",
- "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "color-string": {
- "version": "1.5.5",
- "resolved": "https://registry.nlark.com/color-string/download/color-string-1.5.5.tgz",
- "integrity": "sha1-ZUdKjw50OWJfPSemoZ2J/EUiMBQ=",
- "dev": true,
- "requires": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "colorette": {
- "version": "1.2.2",
- "resolved": "https://registry.npm.taobao.org/colorette/download/colorette-1.2.2.tgz?cache=0&sync_timestamp=1614259623635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolorette%2Fdownload%2Fcolorette-1.2.2.tgz",
- "integrity": "sha1-y8x51emcrqLb8Q6zom/Ys+as+pQ=",
- "dev": true
- },
- "combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz",
- "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=",
- "dev": true,
- "requires": {
- "delayed-stream": "~1.0.0"
- }
- },
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.nlark.com/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1622446257852&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz",
- "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=",
- "dev": true
- },
- "commondir": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz",
- "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
- "dev": true
- },
- "component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.nlark.com/component-emitter/download/component-emitter-1.3.0.tgz",
- "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=",
- "dev": true
- },
- "compressible": {
- "version": "2.0.18",
- "resolved": "https://registry.nlark.com/compressible/download/compressible-2.0.18.tgz",
- "integrity": "sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o=",
- "dev": true,
- "requires": {
- "mime-db": ">= 1.43.0 < 2"
- }
- },
- "compression": {
- "version": "1.7.4",
- "resolved": "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompression%2Fdownload%2Fcompression-1.7.4.tgz",
- "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=",
- "dev": true,
- "requires": {
- "accepts": "~1.3.5",
- "bytes": "3.0.0",
- "compressible": "~2.0.16",
- "debug": "2.6.9",
- "on-headers": "~1.0.2",
- "safe-buffer": "5.1.2",
- "vary": "~1.1.2"
- },
- "dependencies": {
- "bytes": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz",
- "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
- "dev": true
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.nlark.com/concat-map/download/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.nlark.com/concat-stream/download/concat-stream-1.6.2.tgz",
- "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
- "connect-history-api-fallback": {
- "version": "1.6.0",
- "resolved": "https://registry.nlark.com/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz?cache=0&sync_timestamp=1618847040596&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fconnect-history-api-fallback%2Fdownload%2Fconnect-history-api-fallback-1.6.0.tgz",
- "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=",
- "dev": true
- },
- "console-browserify": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/console-browserify/download/console-browserify-1.2.0.tgz",
- "integrity": "sha1-ZwY871fOts9Jk6KrOlWECujEkzY=",
- "dev": true
- },
- "consolidate": {
- "version": "0.15.1",
- "resolved": "https://registry.npm.taobao.org/consolidate/download/consolidate-0.15.1.tgz",
- "integrity": "sha1-IasEMjXHGgfUXZqtmFk7DbpWurc=",
- "dev": true,
- "requires": {
- "bluebird": "^3.1.1"
- }
- },
- "constants-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/constants-browserify/download/constants-browserify-1.0.0.tgz",
- "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
- "dev": true
- },
- "content-disposition": {
- "version": "0.5.3",
- "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
- "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/content-type/download/content-type-1.0.4.tgz",
- "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
- "dev": true
- },
- "convert-source-map": {
- "version": "1.7.0",
- "resolved": "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.7.0.tgz",
- "integrity": "sha1-F6LLiC1/d9NJBYXizmxSRCSjpEI=",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.1"
- }
- },
- "cookie": {
- "version": "0.4.0",
- "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz",
- "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=",
- "dev": true
- },
- "cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
- "dev": true
- },
- "copy-concurrently": {
- "version": "1.0.5",
- "resolved": "https://registry.nlark.com/copy-concurrently/download/copy-concurrently-1.0.5.tgz",
- "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1",
- "fs-write-stream-atomic": "^1.0.8",
- "iferr": "^0.1.5",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.0"
- }
- },
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
- "dev": true
- },
- "copy-webpack-plugin": {
- "version": "5.1.2",
- "resolved": "https://registry.nlark.com/copy-webpack-plugin/download/copy-webpack-plugin-5.1.2.tgz?cache=0&sync_timestamp=1621607252385&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcopy-webpack-plugin%2Fdownload%2Fcopy-webpack-plugin-5.1.2.tgz",
- "integrity": "sha1-ioieHcr6bJHGzUvhrRWPHTgjuuI=",
- "dev": true,
- "requires": {
- "cacache": "^12.0.3",
- "find-cache-dir": "^2.1.0",
- "glob-parent": "^3.1.0",
- "globby": "^7.1.1",
- "is-glob": "^4.0.1",
- "loader-utils": "^1.2.3",
- "minimatch": "^3.0.4",
- "normalize-path": "^3.0.0",
- "p-limit": "^2.2.1",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^4.0.0",
- "webpack-log": "^2.0.0"
- },
- "dependencies": {
- "find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz",
- "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
- }
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz",
- "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1620073321855&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "globby": {
- "version": "7.1.1",
- "resolved": "https://registry.nlark.com/globby/download/globby-7.1.1.tgz",
- "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
- "dev": true,
- "requires": {
- "array-union": "^1.0.1",
- "dir-glob": "^2.0.0",
- "glob": "^7.1.2",
- "ignore": "^3.3.5",
- "pify": "^3.0.0",
- "slash": "^1.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- }
- }
- },
- "ignore": {
- "version": "3.3.10",
- "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz",
- "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=",
- "dev": true
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
- "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz",
- "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=",
- "dev": true,
- "requires": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/p-locate/download/p-locate-3.0.0.tgz",
- "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-3.0.0.tgz",
- "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0"
- }
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz",
- "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
- "dev": true
- },
- "slash": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/slash/download/slash-1.0.0.tgz",
- "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
- "dev": true
- }
- }
- },
- "core-js": {
- "version": "3.13.1",
- "resolved": "https://registry.nlark.com/core-js/download/core-js-3.13.1.tgz",
- "integrity": "sha1-MDA/q9U2OIkgYti06ALKx1men7c="
- },
- "core-js-compat": {
- "version": "3.13.1",
- "resolved": "https://registry.nlark.com/core-js-compat/download/core-js-compat-3.13.1.tgz?cache=0&sync_timestamp=1622278867592&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcore-js-compat%2Fdownload%2Fcore-js-compat-3.13.1.tgz",
- "integrity": "sha1-BURMqo8VO+DGfbA8+K247Alk5Y4=",
- "dev": true,
- "requires": {
- "browserslist": "^4.16.6",
- "semver": "7.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "7.0.0",
- "resolved": "https://registry.nlark.com/semver/download/semver-7.0.0.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-7.0.0.tgz",
- "integrity": "sha1-XzyjV2HkfgWyBsba/yz4FPAxa44=",
- "dev": true
- }
- }
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/core-util-is/download/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true
- },
- "cosmiconfig": {
- "version": "5.2.1",
- "resolved": "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz",
- "integrity": "sha1-BA9yaAnFked6F8CjYmykW08Wixo=",
- "dev": true,
- "requires": {
- "import-fresh": "^2.0.0",
- "is-directory": "^0.3.1",
- "js-yaml": "^3.13.1",
- "parse-json": "^4.0.0"
- },
- "dependencies": {
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/parse-json/download/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- }
- }
- },
- "create-ecdh": {
- "version": "4.0.4",
- "resolved": "https://registry.nlark.com/create-ecdh/download/create-ecdh-4.0.4.tgz",
- "integrity": "sha1-1uf0v/pmc2CFoHYv06YyaE2rzE4=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "elliptic": "^6.5.3"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "create-hash": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz",
- "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.1",
- "inherits": "^2.0.1",
- "md5.js": "^1.3.4",
- "ripemd160": "^2.0.1",
- "sha.js": "^2.4.0"
- }
- },
- "create-hmac": {
- "version": "1.1.7",
- "resolved": "https://registry.nlark.com/create-hmac/download/create-hmac-1.1.7.tgz",
- "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.3",
- "create-hash": "^1.1.0",
- "inherits": "^2.0.1",
- "ripemd160": "^2.0.0",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- }
- },
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz",
- "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=",
- "dev": true,
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz",
- "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
- "dev": true
- }
- }
- },
- "crypto-browserify": {
- "version": "3.12.0",
- "resolved": "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz",
- "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
- "dev": true,
- "requires": {
- "browserify-cipher": "^1.0.0",
- "browserify-sign": "^4.0.0",
- "create-ecdh": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.0",
- "diffie-hellman": "^5.0.0",
- "inherits": "^2.0.1",
- "pbkdf2": "^3.0.3",
- "public-encrypt": "^4.0.0",
- "randombytes": "^2.0.0",
- "randomfill": "^1.0.3"
- }
- },
- "css": {
- "version": "2.2.4",
- "resolved": "https://registry.npm.taobao.org/css/download/css-2.2.4.tgz",
- "integrity": "sha1-xkZ1XHOXHyu6amAeLPL9cbEpiSk=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "source-map": "^0.6.1",
- "source-map-resolve": "^0.5.2",
- "urix": "^0.1.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "css-color-names": {
- "version": "0.0.4",
- "resolved": "https://registry.nlark.com/css-color-names/download/css-color-names-0.0.4.tgz",
- "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
- "dev": true
- },
- "css-declaration-sorter": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/css-declaration-sorter/download/css-declaration-sorter-4.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcss-declaration-sorter%2Fdownload%2Fcss-declaration-sorter-4.0.1.tgz",
- "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.1",
- "timsort": "^0.3.0"
- }
- },
- "css-loader": {
- "version": "3.6.0",
- "resolved": "https://registry.nlark.com/css-loader/download/css-loader-3.6.0.tgz?cache=0&sync_timestamp=1621865043272&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcss-loader%2Fdownload%2Fcss-loader-3.6.0.tgz",
- "integrity": "sha1-Lkssfm4tJ/jI8o9hv/zS5ske9kU=",
- "dev": true,
- "requires": {
- "camelcase": "^5.3.1",
- "cssesc": "^3.0.0",
- "icss-utils": "^4.1.1",
- "loader-utils": "^1.2.3",
- "normalize-path": "^3.0.0",
- "postcss": "^7.0.32",
- "postcss-modules-extract-imports": "^2.0.0",
- "postcss-modules-local-by-default": "^3.0.2",
- "postcss-modules-scope": "^2.2.0",
- "postcss-modules-values": "^3.0.0",
- "postcss-value-parser": "^4.1.0",
- "schema-utils": "^2.7.0",
- "semver": "^6.3.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.nlark.com/camelcase/download/camelcase-5.3.1.tgz",
- "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=",
- "dev": true
- }
- }
- },
- "css-parse": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/css-parse/download/css-parse-2.0.0.tgz",
- "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=",
- "dev": true,
- "requires": {
- "css": "^2.0.0"
- }
- },
- "css-select": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/css-select/download/css-select-2.1.0.tgz?cache=0&sync_timestamp=1618846786574&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcss-select%2Fdownload%2Fcss-select-2.1.0.tgz",
- "integrity": "sha1-ajRlM1ZjWTSoG6ymjQJVQyEF2+8=",
- "dev": true,
- "requires": {
- "boolbase": "^1.0.0",
- "css-what": "^3.2.1",
- "domutils": "^1.7.0",
- "nth-check": "^1.0.2"
- }
- },
- "css-select-base-adapter": {
- "version": "0.1.1",
- "resolved": "https://registry.npm.taobao.org/css-select-base-adapter/download/css-select-base-adapter-0.1.1.tgz",
- "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=",
- "dev": true
- },
- "css-tree": {
- "version": "1.0.0-alpha.37",
- "resolved": "https://registry.nlark.com/css-tree/download/css-tree-1.0.0-alpha.37.tgz",
- "integrity": "sha1-mL69YsTB2flg7DQM+fdSLjBwmiI=",
- "dev": true,
- "requires": {
- "mdn-data": "2.0.4",
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "css-what": {
- "version": "3.4.2",
- "resolved": "https://registry.nlark.com/css-what/download/css-what-3.4.2.tgz",
- "integrity": "sha1-6nAm/LAXd+295SEk4h8yfnrpUOQ=",
- "dev": true
- },
- "cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz",
- "integrity": "sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4=",
- "dev": true
- },
- "cssnano": {
- "version": "4.1.11",
- "resolved": "https://registry.nlark.com/cssnano/download/cssnano-4.1.11.tgz",
- "integrity": "sha1-x7X1uB2iacsf2YLLlgwSAJEMmpk=",
- "dev": true,
- "requires": {
- "cosmiconfig": "^5.0.0",
- "cssnano-preset-default": "^4.0.8",
- "is-resolvable": "^1.0.0",
- "postcss": "^7.0.0"
- }
- },
- "cssnano-preset-default": {
- "version": "4.0.8",
- "resolved": "https://registry.nlark.com/cssnano-preset-default/download/cssnano-preset-default-4.0.8.tgz",
- "integrity": "sha1-kgYisfwelaNOiDggPxOXpQTy0/8=",
- "dev": true,
- "requires": {
- "css-declaration-sorter": "^4.0.1",
- "cssnano-util-raw-cache": "^4.0.1",
- "postcss": "^7.0.0",
- "postcss-calc": "^7.0.1",
- "postcss-colormin": "^4.0.3",
- "postcss-convert-values": "^4.0.1",
- "postcss-discard-comments": "^4.0.2",
- "postcss-discard-duplicates": "^4.0.2",
- "postcss-discard-empty": "^4.0.1",
- "postcss-discard-overridden": "^4.0.1",
- "postcss-merge-longhand": "^4.0.11",
- "postcss-merge-rules": "^4.0.3",
- "postcss-minify-font-values": "^4.0.2",
- "postcss-minify-gradients": "^4.0.2",
- "postcss-minify-params": "^4.0.2",
- "postcss-minify-selectors": "^4.0.2",
- "postcss-normalize-charset": "^4.0.1",
- "postcss-normalize-display-values": "^4.0.2",
- "postcss-normalize-positions": "^4.0.2",
- "postcss-normalize-repeat-style": "^4.0.2",
- "postcss-normalize-string": "^4.0.2",
- "postcss-normalize-timing-functions": "^4.0.2",
- "postcss-normalize-unicode": "^4.0.1",
- "postcss-normalize-url": "^4.0.1",
- "postcss-normalize-whitespace": "^4.0.2",
- "postcss-ordered-values": "^4.1.2",
- "postcss-reduce-initial": "^4.0.3",
- "postcss-reduce-transforms": "^4.0.2",
- "postcss-svgo": "^4.0.3",
- "postcss-unique-selectors": "^4.0.1"
- }
- },
- "cssnano-util-get-arguments": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/cssnano-util-get-arguments/download/cssnano-util-get-arguments-4.0.0.tgz",
- "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
- "dev": true
- },
- "cssnano-util-get-match": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/cssnano-util-get-match/download/cssnano-util-get-match-4.0.0.tgz",
- "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
- "dev": true
- },
- "cssnano-util-raw-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npm.taobao.org/cssnano-util-raw-cache/download/cssnano-util-raw-cache-4.0.1.tgz",
- "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "cssnano-util-same-parent": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/cssnano-util-same-parent/download/cssnano-util-same-parent-4.0.1.tgz",
- "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=",
- "dev": true
- },
- "csso": {
- "version": "4.2.0",
- "resolved": "https://registry.npm.taobao.org/csso/download/csso-4.2.0.tgz?cache=0&sync_timestamp=1606408777341&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcsso%2Fdownload%2Fcsso-4.2.0.tgz",
- "integrity": "sha1-6jpWE0bo3J9UbW/r7dUBh884lSk=",
- "dev": true,
- "requires": {
- "css-tree": "^1.1.2"
- },
- "dependencies": {
- "css-tree": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/css-tree/download/css-tree-1.1.3.tgz",
- "integrity": "sha1-60hw+2/XcHMn7JXC/yqwm16NuR0=",
- "dev": true,
- "requires": {
- "mdn-data": "2.0.14",
- "source-map": "^0.6.1"
- }
- },
- "mdn-data": {
- "version": "2.0.14",
- "resolved": "https://registry.nlark.com/mdn-data/download/mdn-data-2.0.14.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmdn-data%2Fdownload%2Fmdn-data-2.0.14.tgz",
- "integrity": "sha1-cRP8QoGRfWPOKbQ0RvcB5owlulA=",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "csstype": {
- "version": "2.6.17",
- "resolved": "https://registry.nlark.com/csstype/download/csstype-2.6.17.tgz?cache=0&sync_timestamp=1618818466657&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcsstype%2Fdownload%2Fcsstype-2.6.17.tgz",
- "integrity": "sha1-TPMOuH4dGgBdi2UQ+VKSQT9qHA4="
- },
- "cyclist": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/cyclist/download/cyclist-1.0.1.tgz",
- "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
- "dev": true
- },
- "dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz?cache=0&sync_timestamp=1601073454623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdashdash%2Fdownload%2Fdashdash-1.14.1.tgz",
- "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
- "dev": true,
- "requires": {
- "assert-plus": "^1.0.0"
- }
- },
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.nlark.com/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
- "integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/decamelize/download/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
- },
- "decode-uri-component": {
- "version": "0.2.0",
- "resolved": "https://registry.nlark.com/decode-uri-component/download/decode-uri-component-0.2.0.tgz",
- "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
- "dev": true
- },
- "deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.1.1.tgz?cache=0&sync_timestamp=1606859714626&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeep-equal%2Fdownload%2Fdeep-equal-1.1.1.tgz",
- "integrity": "sha1-tcmMlCzv+vfLBR4k4UNKJaLmB2o=",
- "dev": true,
- "requires": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- }
- },
- "deep-is": {
- "version": "0.1.3",
- "resolved": "https://registry.nlark.com/deep-is/download/deep-is-0.1.3.tgz",
- "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
- "dev": true
- },
- "deepmerge": {
- "version": "1.5.2",
- "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
- "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=",
- "dev": true
- },
- "default-gateway": {
- "version": "5.0.5",
- "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-5.0.5.tgz?cache=0&sync_timestamp=1610365756089&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-5.0.5.tgz",
- "integrity": "sha1-T9a9XShV05s0zFpZUFSG6ar8mxA=",
- "dev": true,
- "requires": {
- "execa": "^3.3.0"
- },
- "dependencies": {
- "cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-7.0.3.tgz",
- "integrity": "sha1-9zqFudXUHQRVUcF34ogtSshXKKY=",
- "dev": true,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "execa": {
- "version": "3.4.0",
- "resolved": "https://registry.nlark.com/execa/download/execa-3.4.0.tgz?cache=0&sync_timestamp=1622396637949&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fexeca%2Fdownload%2Fexeca-3.4.0.tgz",
- "integrity": "sha1-wI7UVQ72XYWPrCaf/IVyRG8364k=",
- "dev": true,
- "requires": {
- "cross-spawn": "^7.0.0",
- "get-stream": "^5.0.0",
- "human-signals": "^1.1.1",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.0",
- "onetime": "^5.1.0",
- "p-finally": "^2.0.0",
- "signal-exit": "^3.0.2",
- "strip-final-newline": "^2.0.0"
- }
- },
- "get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-5.2.0.tgz",
- "integrity": "sha1-SWaheV7lrOZecGxLe+txJX1uItM=",
- "dev": true,
- "requires": {
- "pump": "^3.0.0"
- }
- },
- "is-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/is-stream/download/is-stream-2.0.0.tgz",
- "integrity": "sha1-venDJoDW+uBBKdasnZIc54FfeOM=",
- "dev": true
- },
- "mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz",
- "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=",
- "dev": true
- },
- "npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-4.0.1.tgz",
- "integrity": "sha1-t+zR5e1T2o43pV4cImnguX7XSOo=",
- "dev": true,
- "requires": {
- "path-key": "^3.0.0"
- }
- },
- "onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz",
- "integrity": "sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=",
- "dev": true,
- "requires": {
- "mimic-fn": "^2.1.0"
- }
- },
- "p-finally": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-2.0.1.tgz",
- "integrity": "sha1-vW/KqcVZoJa2gIBvTWV7Pw8kBWE=",
- "dev": true
- },
- "path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-3.1.1.tgz?cache=0&sync_timestamp=1617971695678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-key%2Fdownload%2Fpath-key-3.1.1.tgz",
- "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=",
- "dev": true
- },
- "shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-2.0.0.tgz",
- "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=",
- "dev": true,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-3.0.0.tgz",
- "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=",
- "dev": true
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.nlark.com/which/download/which-2.0.2.tgz",
- "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "defaults": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz",
- "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
- "dev": true,
- "requires": {
- "clone": "^1.0.2"
- }
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/define-properties/download/define-properties-1.1.3.tgz?cache=0&sync_timestamp=1618847174317&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdefine-properties%2Fdownload%2Fdefine-properties-1.1.3.tgz",
- "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz",
- "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
- "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "del": {
- "version": "4.1.1",
- "resolved": "https://registry.npm.taobao.org/del/download/del-4.1.1.tgz?cache=0&sync_timestamp=1601076882347&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdel%2Fdownload%2Fdel-4.1.1.tgz",
- "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=",
- "dev": true,
- "requires": {
- "@types/glob": "^7.1.1",
- "globby": "^6.1.0",
- "is-path-cwd": "^2.0.0",
- "is-path-in-cwd": "^2.0.0",
- "p-map": "^2.0.0",
- "pify": "^4.0.1",
- "rimraf": "^2.6.3"
- },
- "dependencies": {
- "globby": {
- "version": "6.1.0",
- "resolved": "https://registry.nlark.com/globby/download/globby-6.1.0.tgz",
- "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
- "dev": true,
- "requires": {
- "array-union": "^1.0.1",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- }
- }
- },
- "delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
- "dev": true
- },
- "depd": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/depd/download/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
- "dev": true
- },
- "des.js": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz",
- "integrity": "sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
- }
- },
- "destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/destroy/download/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
- "dev": true
- },
- "detect-node": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/detect-node/download/detect-node-2.1.0.tgz?cache=0&sync_timestamp=1621147029891&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdetect-node%2Fdownload%2Fdetect-node-2.1.0.tgz",
- "integrity": "sha1-yccHdaScPQO8LAbZpzvlUPl4+LE=",
- "dev": true
- },
- "diffie-hellman": {
- "version": "5.0.3",
- "resolved": "https://registry.nlark.com/diffie-hellman/download/diffie-hellman-5.0.3.tgz",
- "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "miller-rabin": "^4.0.0",
- "randombytes": "^2.0.0"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "dir-glob": {
- "version": "2.2.2",
- "resolved": "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz",
- "integrity": "sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ=",
- "dev": true,
- "requires": {
- "path-type": "^3.0.0"
- }
- },
- "dns-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/dns-equal/download/dns-equal-1.0.0.tgz",
- "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
- "dev": true
- },
- "dns-packet": {
- "version": "1.3.4",
- "resolved": "https://registry.nlark.com/dns-packet/download/dns-packet-1.3.4.tgz",
- "integrity": "sha1-40VQZYJKJQe6iGxVqJljuxB97G8=",
- "dev": true,
- "requires": {
- "ip": "^1.1.0",
- "safe-buffer": "^5.0.1"
- }
- },
- "dns-txt": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz",
- "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
- "dev": true,
- "requires": {
- "buffer-indexof": "^1.0.0"
- }
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/doctrine/download/doctrine-3.0.0.tgz",
- "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "dom-converter": {
- "version": "0.2.0",
- "resolved": "https://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz",
- "integrity": "sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g=",
- "dev": true,
- "requires": {
- "utila": "~0.4"
- }
- },
- "dom-serializer": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/dom-serializer/download/dom-serializer-0.2.2.tgz?cache=0&sync_timestamp=1621256830355&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdom-serializer%2Fdownload%2Fdom-serializer-0.2.2.tgz",
- "integrity": "sha1-GvuB9TNxcXXUeGVd68XjMtn5u1E=",
- "dev": true,
- "requires": {
- "domelementtype": "^2.0.1",
- "entities": "^2.0.0"
- },
- "dependencies": {
- "domelementtype": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.2.0.tgz?cache=0&sync_timestamp=1617298554829&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-2.2.0.tgz",
- "integrity": "sha1-mgtsJ4LtahxzI9QiZxg9+b2LHVc=",
- "dev": true
- }
- }
- },
- "domain-browser": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/domain-browser/download/domain-browser-1.2.0.tgz",
- "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=",
- "dev": true
- },
- "domelementtype": {
- "version": "1.3.1",
- "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz?cache=0&sync_timestamp=1617298554829&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-1.3.1.tgz",
- "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=",
- "dev": true
- },
- "domhandler": {
- "version": "2.4.2",
- "resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz?cache=0&sync_timestamp=1618563954924&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomhandler%2Fdownload%2Fdomhandler-2.4.2.tgz",
- "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=",
- "dev": true,
- "requires": {
- "domelementtype": "1"
- }
- },
- "domutils": {
- "version": "1.7.0",
- "resolved": "https://registry.nlark.com/domutils/download/domutils-1.7.0.tgz",
- "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=",
- "dev": true,
- "requires": {
- "dom-serializer": "0",
- "domelementtype": "1"
- }
- },
- "dot-prop": {
- "version": "5.3.0",
- "resolved": "https://registry.nlark.com/dot-prop/download/dot-prop-5.3.0.tgz",
- "integrity": "sha1-kMzOcIzZzYLMTcjD3dmr3VWyDog=",
- "dev": true,
- "requires": {
- "is-obj": "^2.0.0"
- }
- },
- "dotenv": {
- "version": "8.6.0",
- "resolved": "https://registry.nlark.com/dotenv/download/dotenv-8.6.0.tgz?cache=0&sync_timestamp=1621627076012&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdotenv%2Fdownload%2Fdotenv-8.6.0.tgz",
- "integrity": "sha1-Bhr2ZNGff02PxuT/m1hM4jety4s=",
- "dev": true
- },
- "dotenv-expand": {
- "version": "5.1.0",
- "resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz?cache=0&sync_timestamp=1603163578680&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdotenv-expand%2Fdownload%2Fdotenv-expand-5.1.0.tgz",
- "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
- "dev": true
- },
- "duplexer": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz",
- "integrity": "sha1-Or5DrvODX4rgd9E23c4PJ2sEAOY=",
- "dev": true
- },
- "duplexify": {
- "version": "3.7.1",
- "resolved": "https://registry.nlark.com/duplexify/download/duplexify-3.7.1.tgz",
- "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0",
- "stream-shift": "^1.0.0"
- }
- },
- "easy-stack": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/easy-stack/download/easy-stack-1.0.1.tgz",
- "integrity": "sha1-iv5CZGJpiMq7EfPHBMzQyDVBEGY=",
- "dev": true
- },
- "ecc-jsbn": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz",
- "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
- "dev": true,
- "requires": {
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.1.0"
- }
- },
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
- "dev": true
- },
- "ejs": {
- "version": "2.7.4",
- "resolved": "https://registry.nlark.com/ejs/download/ejs-2.7.4.tgz",
- "integrity": "sha1-SGYSh1c9zFPjZsehrlLDoSDuybo=",
- "dev": true
- },
- "electron-to-chromium": {
- "version": "1.3.742",
- "resolved": "https://registry.nlark.com/electron-to-chromium/download/electron-to-chromium-1.3.742.tgz?cache=0&sync_timestamp=1622240108830&other_urls=https%3A%2F%2Fregistry.nlark.com%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.742.tgz",
- "integrity": "sha1-ciMhWsu9OlKEli68tt+F2IuV8gA=",
- "dev": true
- },
- "elliptic": {
- "version": "6.5.4",
- "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz",
- "integrity": "sha1-2jfOvTHnmhNn6UG1ku0fvr1Yq7s=",
- "dev": true,
- "requires": {
- "bn.js": "^4.11.9",
- "brorand": "^1.1.0",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.1",
- "inherits": "^2.0.4",
- "minimalistic-assert": "^1.0.1",
- "minimalistic-crypto-utils": "^1.0.1"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.nlark.com/emoji-regex/download/emoji-regex-8.0.0.tgz",
- "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=",
- "dev": true
- },
- "emojis-list": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz",
- "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=",
- "dev": true
- },
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "dev": true
- },
- "end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.nlark.com/end-of-stream/download/end-of-stream-1.4.4.tgz",
- "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=",
- "dev": true,
- "requires": {
- "once": "^1.4.0"
- }
- },
- "enhanced-resolve": {
- "version": "4.5.0",
- "resolved": "https://registry.nlark.com/enhanced-resolve/download/enhanced-resolve-4.5.0.tgz?cache=0&sync_timestamp=1620663108627&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.5.0.tgz",
- "integrity": "sha1-Lzz9hNvjtIfxjy2y7x4GSlccpew=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "memory-fs": "^0.5.0",
- "tapable": "^1.0.0"
- },
- "dependencies": {
- "memory-fs": {
- "version": "0.5.0",
- "resolved": "https://registry.nlark.com/memory-fs/download/memory-fs-0.5.0.tgz",
- "integrity": "sha1-MkwBKIuIZSlm0WHbd4OHIIRajjw=",
- "dev": true,
- "requires": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
- }
- }
- }
- },
- "entities": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/entities/download/entities-2.2.0.tgz",
- "integrity": "sha1-CY3JDruD2N/6CJ1VJWs1HTTE2lU=",
- "dev": true
- },
- "errno": {
- "version": "0.1.8",
- "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.8.tgz",
- "integrity": "sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8=",
- "dev": true,
- "requires": {
- "prr": "~1.0.1"
- }
- },
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.nlark.com/error-ex/download/error-ex-1.3.2.tgz",
- "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "error-stack-parser": {
- "version": "2.0.6",
- "resolved": "https://registry.npm.taobao.org/error-stack-parser/download/error-stack-parser-2.0.6.tgz",
- "integrity": "sha1-WpmnB716TFinl5AtSNgoA+3mqtg=",
- "dev": true,
- "requires": {
- "stackframe": "^1.1.1"
- }
- },
- "es-abstract": {
- "version": "1.18.3",
- "resolved": "https://registry.nlark.com/es-abstract/download/es-abstract-1.18.3.tgz",
- "integrity": "sha1-JcTDOAonqiA8RLK2hbupTaMbY+A=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.2",
- "is-callable": "^1.2.3",
- "is-negative-zero": "^2.0.1",
- "is-regex": "^1.1.3",
- "is-string": "^1.0.6",
- "object-inspect": "^1.10.3",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.2",
- "string.prototype.trimend": "^1.0.4",
- "string.prototype.trimstart": "^1.0.4",
- "unbox-primitive": "^1.0.1"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.1.tgz",
- "integrity": "sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo=",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npm.taobao.org/escalade/download/escalade-3.1.1.tgz?cache=0&sync_timestamp=1602567306925&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescalade%2Fdownload%2Fescalade-3.1.1.tgz",
- "integrity": "sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA=",
- "dev": true
- },
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
- "dev": true
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "eslint": {
- "version": "6.8.0",
- "resolved": "https://registry.nlark.com/eslint/download/eslint-6.8.0.tgz",
- "integrity": "sha1-YiYtZylzn5J1cjgkMC+yJ8jJP/s=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "ajv": "^6.10.0",
- "chalk": "^2.1.0",
- "cross-spawn": "^6.0.5",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "eslint-scope": "^5.0.0",
- "eslint-utils": "^1.4.3",
- "eslint-visitor-keys": "^1.1.0",
- "espree": "^6.1.2",
- "esquery": "^1.0.1",
- "esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "inquirer": "^7.0.0",
- "is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.3.0",
- "lodash": "^4.17.14",
- "minimatch": "^3.0.4",
- "mkdirp": "^0.5.1",
- "natural-compare": "^1.4.0",
- "optionator": "^0.8.3",
- "progress": "^2.0.0",
- "regexpp": "^2.0.1",
- "semver": "^6.1.2",
- "strip-ansi": "^5.2.0",
- "strip-json-comments": "^3.0.1",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- },
- "dependencies": {
- "eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-5.1.1.tgz?cache=0&sync_timestamp=1599933693172&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-5.1.1.tgz",
- "integrity": "sha1-54blmmbLkrP2wfsNUIqrF0hI9Iw=",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- }
- },
- "globals": {
- "version": "12.4.0",
- "resolved": "https://registry.nlark.com/globals/download/globals-12.4.0.tgz",
- "integrity": "sha1-oYgTV2pBsAokqX5/gVkYwuGZJfg=",
- "dev": true,
- "requires": {
- "type-fest": "^0.8.1"
- }
- },
- "import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-3.3.0.tgz?cache=0&sync_timestamp=1608469561643&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-3.3.0.tgz",
- "integrity": "sha1-NxYsJfy566oublPVtNiM4X2eDCs=",
- "dev": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- }
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/resolve-from/download/resolve-from-4.0.0.tgz",
- "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- },
- "type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.nlark.com/type-fest/download/type-fest-0.8.1.tgz?cache=0&sync_timestamp=1621402446336&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.8.1.tgz",
- "integrity": "sha1-CeJJ696FHTseSNJ8EFREZn8XuD0=",
- "dev": true
- }
- }
- },
- "eslint-loader": {
- "version": "2.2.1",
- "resolved": "https://registry.npm.taobao.org/eslint-loader/download/eslint-loader-2.2.1.tgz?cache=0&sync_timestamp=1601214436656&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-loader%2Fdownload%2Feslint-loader-2.2.1.tgz",
- "integrity": "sha1-KLnBLaVAV68IReKmEScBova/gzc=",
- "dev": true,
- "requires": {
- "loader-fs-cache": "^1.0.0",
- "loader-utils": "^1.0.2",
- "object-assign": "^4.0.1",
- "object-hash": "^1.1.4",
- "rimraf": "^2.6.1"
- }
- },
- "eslint-plugin-vue": {
- "version": "7.10.0",
- "resolved": "https://registry.nlark.com/eslint-plugin-vue/download/eslint-plugin-vue-7.10.0.tgz",
- "integrity": "sha1-JRdJqpngieCFJ18BEELG50GJ+Jo=",
- "dev": true,
- "requires": {
- "eslint-utils": "^2.1.0",
- "natural-compare": "^1.4.0",
- "semver": "^7.3.2",
- "vue-eslint-parser": "^7.6.0"
- },
- "dependencies": {
- "eslint-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/eslint-utils/download/eslint-utils-2.1.0.tgz?cache=0&sync_timestamp=1620975590529&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint-utils%2Fdownload%2Feslint-utils-2.1.0.tgz",
- "integrity": "sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc=",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.1.0"
- }
- },
- "lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-6.0.0.tgz",
- "integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=",
- "dev": true,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.nlark.com/semver/download/semver-7.3.5.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-7.3.5.tgz",
- "integrity": "sha1-C2Ich5NI2JmOSw5L6Us/EuYBjvc=",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
- "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
- "dev": true
- }
- }
- },
- "eslint-scope": {
- "version": "4.0.3",
- "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz?cache=0&sync_timestamp=1599933693172&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-4.0.3.tgz",
- "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=",
- "dev": true,
- "requires": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-utils": {
- "version": "1.4.3",
- "resolved": "https://registry.nlark.com/eslint-utils/download/eslint-utils-1.4.3.tgz?cache=0&sync_timestamp=1620975590529&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint-utils%2Fdownload%2Feslint-utils-1.4.3.tgz",
- "integrity": "sha1-dP7HxU0Hdrb2fgJRBAtYBlZOmB8=",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.1.0"
- }
- },
- "eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.nlark.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha1-MOvR73wv3/AcOk8VEESvJfqwUj4=",
- "dev": true
- },
- "espree": {
- "version": "6.2.1",
- "resolved": "https://registry.npm.taobao.org/espree/download/espree-6.2.1.tgz?cache=0&sync_timestamp=1607143966756&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fespree%2Fdownload%2Fespree-6.2.1.tgz",
- "integrity": "sha1-d/xy4f10SiBSwg84pbV1gy6Cc0o=",
- "dev": true,
- "requires": {
- "acorn": "^7.1.1",
- "acorn-jsx": "^5.2.0",
- "eslint-visitor-keys": "^1.1.0"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.nlark.com/acorn/download/acorn-7.4.1.tgz",
- "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
- "dev": true
- }
- }
- },
- "esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz",
- "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=",
- "dev": true
- },
- "esquery": {
- "version": "1.4.0",
- "resolved": "https://registry.nlark.com/esquery/download/esquery-1.4.0.tgz",
- "integrity": "sha1-IUj/w4uC6McFff7UhCWz5h8PJKU=",
- "dev": true,
- "requires": {
- "estraverse": "^5.1.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.2.0",
- "resolved": "https://registry.nlark.com/estraverse/download/estraverse-5.2.0.tgz",
- "integrity": "sha1-MH30JUfmzHMk088DwVXVzbjFOIA=",
- "dev": true
- }
- }
- },
- "esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npm.taobao.org/esrecurse/download/esrecurse-4.3.0.tgz",
- "integrity": "sha1-eteWTWeauyi+5yzsY3WLHF0smSE=",
- "dev": true,
- "requires": {
- "estraverse": "^5.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.2.0",
- "resolved": "https://registry.nlark.com/estraverse/download/estraverse-5.2.0.tgz",
- "integrity": "sha1-MH30JUfmzHMk088DwVXVzbjFOIA=",
- "dev": true
- }
- }
- },
- "estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/estraverse/download/estraverse-4.3.0.tgz",
- "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=",
- "dev": true
- },
- "estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz?cache=0&sync_timestamp=1611956983677&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festree-walker%2Fdownload%2Festree-walker-2.0.2.tgz",
- "integrity": "sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw="
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz",
- "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=",
- "dev": true
- },
- "etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
- "dev": true
- },
- "event-pubsub": {
- "version": "4.3.0",
- "resolved": "https://registry.npm.taobao.org/event-pubsub/download/event-pubsub-4.3.0.tgz?cache=0&sync_timestamp=1606361507592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fevent-pubsub%2Fdownload%2Fevent-pubsub-4.3.0.tgz",
- "integrity": "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24=",
- "dev": true
- },
- "eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.nlark.com/eventemitter3/download/eventemitter3-4.0.7.tgz",
- "integrity": "sha1-Lem2j2Uo1WRO9cWVJqG0oHMGFp8=",
- "dev": true
- },
- "events": {
- "version": "3.3.0",
- "resolved": "https://registry.npm.taobao.org/events/download/events-3.3.0.tgz",
- "integrity": "sha1-Mala0Kkk4tLEGagTrrLE6HjqdAA=",
- "dev": true
- },
- "eventsource": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/eventsource/download/eventsource-1.1.0.tgz?cache=0&sync_timestamp=1616041710425&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feventsource%2Fdownload%2Feventsource-1.1.0.tgz",
- "integrity": "sha1-AOjKfJIQnpSw3fMtrGd9hBAoz68=",
- "dev": true,
- "requires": {
- "original": "^1.0.0"
- }
- },
- "evp_bytestokey": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz",
- "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
- "dev": true,
- "requires": {
- "md5.js": "^1.3.4",
- "safe-buffer": "^5.1.1"
- }
- },
- "execa": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/execa/download/execa-1.0.0.tgz?cache=0&sync_timestamp=1622396637949&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fexeca%2Fdownload%2Fexeca-1.0.0.tgz",
- "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=",
- "dev": true,
- "requires": {
- "cross-spawn": "^6.0.0",
- "get-stream": "^4.0.0",
- "is-stream": "^1.1.0",
- "npm-run-path": "^2.0.0",
- "p-finally": "^1.0.0",
- "signal-exit": "^3.0.0",
- "strip-eof": "^1.0.0"
- }
- },
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "dev": true,
- "requires": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "express": {
- "version": "4.17.1",
- "resolved": "https://registry.nlark.com/express/download/express-4.17.1.tgz?cache=0&sync_timestamp=1618847120573&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fexpress%2Fdownload%2Fexpress-4.17.1.tgz",
- "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=",
- "dev": true,
- "requires": {
- "accepts": "~1.3.7",
- "array-flatten": "1.1.1",
- "body-parser": "1.19.0",
- "content-disposition": "0.5.3",
- "content-type": "~1.0.4",
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.1.2",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.5",
- "qs": "6.7.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.1.2",
- "send": "0.17.1",
- "serve-static": "1.14.1",
- "setprototypeof": "1.1.1",
- "statuses": "~1.5.0",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "qs": {
- "version": "6.7.0",
- "resolved": "https://registry.nlark.com/qs/download/qs-6.7.0.tgz",
- "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=",
- "dev": true
- }
- }
- },
- "extend": {
- "version": "3.0.2",
- "resolved": "https://registry.nlark.com/extend/download/extend-3.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fextend%2Fdownload%2Fextend-3.0.2.tgz",
- "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=",
- "dev": true
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "dev": true,
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz",
- "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "external-editor": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/external-editor/download/external-editor-3.1.0.tgz",
- "integrity": "sha1-ywP3QL764D6k0oPK7SdBqD8zVJU=",
- "dev": true,
- "requires": {
- "chardet": "^0.7.0",
- "iconv-lite": "^0.4.24",
- "tmp": "^0.0.33"
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.nlark.com/extglob/download/extglob-2.0.4.tgz",
- "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
- "dev": true,
- "requires": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
- "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz",
- "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
- "dev": true
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=",
- "dev": true
- },
- "fast-glob": {
- "version": "2.2.7",
- "resolved": "https://registry.npm.taobao.org/fast-glob/download/fast-glob-2.2.7.tgz?cache=0&sync_timestamp=1610876605854&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-glob%2Fdownload%2Ffast-glob-2.2.7.tgz",
- "integrity": "sha1-aVOFfDr6R1//ku5gFdUtpwpM050=",
- "dev": true,
- "requires": {
- "@mrmlnc/readdir-enhanced": "^2.2.1",
- "@nodelib/fs.stat": "^1.1.2",
- "glob-parent": "^3.1.0",
- "is-glob": "^4.0.0",
- "merge2": "^1.2.3",
- "micromatch": "^3.1.10"
- },
- "dependencies": {
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1620073321855&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- }
- }
- },
- "fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=",
- "dev": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.nlark.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
- "dev": true
- },
- "faye-websocket": {
- "version": "0.11.4",
- "resolved": "https://registry.nlark.com/faye-websocket/download/faye-websocket-0.11.4.tgz",
- "integrity": "sha1-fw2Sdc/dhqHJY9yLZfzEUe3Lsdo=",
- "dev": true,
- "requires": {
- "websocket-driver": ">=0.5.1"
- }
- },
- "figgy-pudding": {
- "version": "3.5.2",
- "resolved": "https://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.2.tgz",
- "integrity": "sha1-tO7oFIq7Adzx0aw0Nn1Z4S+mHW4=",
- "dev": true
- },
- "figures": {
- "version": "3.2.0",
- "resolved": "https://registry.nlark.com/figures/download/figures-3.2.0.tgz",
- "integrity": "sha1-YlwYvSk8YE3EqN2y/r8MiDQXRq8=",
- "dev": true,
- "requires": {
- "escape-string-regexp": "^1.0.5"
- }
- },
- "file-entry-cache": {
- "version": "5.0.1",
- "resolved": "https://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-5.0.1.tgz?cache=0&sync_timestamp=1613794357372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffile-entry-cache%2Fdownload%2Ffile-entry-cache-5.0.1.tgz",
- "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=",
- "dev": true,
- "requires": {
- "flat-cache": "^2.0.1"
- }
- },
- "file-loader": {
- "version": "4.3.0",
- "resolved": "https://registry.npm.taobao.org/file-loader/download/file-loader-4.3.0.tgz?cache=0&sync_timestamp=1603900022388&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffile-loader%2Fdownload%2Ffile-loader-4.3.0.tgz",
- "integrity": "sha1-eA8ED3KbPRgBnyBgX3I+hEuKWK8=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.2.3",
- "schema-utils": "^2.5.0"
- }
- },
- "file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=",
- "dev": true,
- "optional": true
- },
- "filesize": {
- "version": "3.6.1",
- "resolved": "https://registry.nlark.com/filesize/download/filesize-3.6.1.tgz",
- "integrity": "sha1-CQuz7gG2+AGoqL6Z0xcQs0Irsxc=",
- "dev": true
- },
- "fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz",
- "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "find-cache-dir": {
- "version": "3.3.1",
- "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz",
- "integrity": "sha1-ibM/rUpGcNqpT4Vff74x1thP6IA=",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^3.0.2",
- "pkg-dir": "^4.1.0"
- }
- },
- "find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-4.1.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-4.1.0.tgz",
- "integrity": "sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk=",
- "dev": true,
- "requires": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- }
- },
- "flat-cache": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/flat-cache/download/flat-cache-2.0.1.tgz",
- "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=",
- "dev": true,
- "requires": {
- "flatted": "^2.0.0",
- "rimraf": "2.6.3",
- "write": "1.0.3"
- },
- "dependencies": {
- "rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.6.3.tgz?cache=0&sync_timestamp=1614946161596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.6.3.tgz",
- "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- }
- }
- },
- "flatted": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/flatted/download/flatted-2.0.2.tgz?cache=0&sync_timestamp=1611061273899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflatted%2Fdownload%2Fflatted-2.0.2.tgz",
- "integrity": "sha1-RXWyHivO50NKqb5mL0t7X5wrUTg=",
- "dev": true
- },
- "flush-write-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz",
- "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "readable-stream": "^2.3.6"
- }
- },
- "follow-redirects": {
- "version": "1.14.1",
- "resolved": "https://registry.nlark.com/follow-redirects/download/follow-redirects-1.14.1.tgz",
- "integrity": "sha1-2RFN7Qoc/dM04WTmZirQK/2R/0M=",
- "dev": true
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
- "dev": true
- },
- "forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz",
- "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
- "dev": true
- },
- "form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz",
- "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=",
- "dev": true,
- "requires": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- }
- },
- "forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
- "dev": true
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.nlark.com/fragment-cache/download/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "dev": true,
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
- "dev": true
- },
- "from2": {
- "version": "2.3.0",
- "resolved": "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz",
- "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0"
- }
- },
- "fs-extra": {
- "version": "7.0.1",
- "resolved": "https://registry.nlark.com/fs-extra/download/fs-extra-7.0.1.tgz",
- "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- }
- },
- "fs-write-stream-atomic": {
- "version": "1.0.10",
- "resolved": "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz",
- "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "iferr": "^0.1.5",
- "imurmurhash": "^0.1.4",
- "readable-stream": "1 || 2"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/fs.realpath/download/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz",
- "integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
- "dev": true,
- "optional": true
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz",
- "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=",
- "dev": true
- },
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz?cache=0&sync_timestamp=1618847182644&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffunctional-red-black-tree%2Fdownload%2Ffunctional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
- "generic-names": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/generic-names/download/generic-names-2.0.1.tgz?cache=0&sync_timestamp=1603542269880&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgeneric-names%2Fdownload%2Fgeneric-names-2.0.1.tgz",
- "integrity": "sha1-+KN46tLMqno08DF7BVVIMq5BuHI=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.1.0"
- }
- },
- "gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA=",
- "dev": true
- },
- "get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz",
- "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=",
- "dev": true
- },
- "get-intrinsic": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/get-intrinsic/download/get-intrinsic-1.1.1.tgz",
- "integrity": "sha1-FfWfN2+FXERpY5SPDSTNNje0q8Y=",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1"
- }
- },
- "get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz",
- "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=",
- "dev": true,
- "requires": {
- "pump": "^3.0.0"
- }
- },
- "get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.nlark.com/get-value/download/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
- "dev": true
- },
- "getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.nlark.com/getpass/download/getpass-0.1.7.tgz",
- "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
- "dev": true,
- "requires": {
- "assert-plus": "^1.0.0"
- }
- },
- "glob": {
- "version": "7.1.7",
- "resolved": "https://registry.nlark.com/glob/download/glob-7.1.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob%2Fdownload%2Fglob-7.1.7.tgz",
- "integrity": "sha1-Oxk+kjPwHULQs/eClLvutBj5SpA=",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1620073321855&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz",
- "integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- },
- "glob-to-regexp": {
- "version": "0.3.0",
- "resolved": "https://registry.npm.taobao.org/glob-to-regexp/download/glob-to-regexp-0.3.0.tgz",
- "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
- "dev": true
- },
- "globals": {
- "version": "11.12.0",
- "resolved": "https://registry.nlark.com/globals/download/globals-11.12.0.tgz",
- "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=",
- "dev": true
- },
- "globby": {
- "version": "9.2.0",
- "resolved": "https://registry.nlark.com/globby/download/globby-9.2.0.tgz",
- "integrity": "sha1-/QKacGxwPSm90XD0tts6P3p8tj0=",
- "dev": true,
- "requires": {
- "@types/glob": "^7.1.1",
- "array-union": "^1.0.2",
- "dir-glob": "^2.2.2",
- "fast-glob": "^2.2.6",
- "glob": "^7.1.3",
- "ignore": "^4.0.3",
- "pify": "^4.0.1",
- "slash": "^2.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.6",
- "resolved": "https://registry.nlark.com/graceful-fs/download/graceful-fs-4.2.6.tgz",
- "integrity": "sha1-/wQLKwhTsjw9MQJ1I3BvGIXXa+4=",
- "dev": true
- },
- "gzip-size": {
- "version": "5.1.1",
- "resolved": "https://registry.npm.taobao.org/gzip-size/download/gzip-size-5.1.1.tgz?cache=0&sync_timestamp=1605523244597&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgzip-size%2Fdownload%2Fgzip-size-5.1.1.tgz",
- "integrity": "sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ=",
- "dev": true,
- "requires": {
- "duplexer": "^0.1.1",
- "pify": "^4.0.1"
- }
- },
- "handle-thing": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/handle-thing/download/handle-thing-2.0.1.tgz",
- "integrity": "sha1-hX95zjWVgMNA1DCBzGSJcNC7I04=",
- "dev": true
- },
- "har-schema": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/har-schema/download/har-schema-2.0.0.tgz",
- "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
- "dev": true
- },
- "har-validator": {
- "version": "5.1.5",
- "resolved": "https://registry.nlark.com/har-validator/download/har-validator-5.1.5.tgz",
- "integrity": "sha1-HwgDufjLIMD6E4It8ezds2veHv0=",
- "dev": true,
- "requires": {
- "ajv": "^6.12.3",
- "har-schema": "^2.0.0"
- }
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz",
- "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-bigints": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/has-bigints/download/has-bigints-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-bigints%2Fdownload%2Fhas-bigints-1.0.1.tgz",
- "integrity": "sha1-ZP5qywIGc+O3jbA1pa9pqp0HsRM=",
- "dev": true
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz?cache=0&sync_timestamp=1618559676170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
- "has-symbols": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.2.tgz?cache=0&sync_timestamp=1614443484522&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-symbols%2Fdownload%2Fhas-symbols-1.0.2.tgz",
- "integrity": "sha1-Fl0wcMADCXUqEjakeTMeOsVvFCM=",
- "dev": true
- },
- "has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
- }
- },
- "has-values": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz",
- "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "hash-base": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz",
- "integrity": "sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.4",
- "readable-stream": "^3.6.0",
- "safe-buffer": "^5.2.0"
- },
- "dependencies": {
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.nlark.com/readable-stream/download/readable-stream-3.6.0.tgz",
- "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- },
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.2.1.tgz",
- "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=",
- "dev": true
- }
- }
- },
- "hash-sum": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-2.0.0.tgz",
- "integrity": "sha1-gdAbtd6OpKIUrV1urRtSNGCwtFo=",
- "dev": true
- },
- "hash.js": {
- "version": "1.1.7",
- "resolved": "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz",
- "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "minimalistic-assert": "^1.0.1"
- }
- },
- "he": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
- "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=",
- "dev": true
- },
- "hex-color-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/hex-color-regex/download/hex-color-regex-1.1.0.tgz",
- "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=",
- "dev": true
- },
- "highlight.js": {
- "version": "10.7.2",
- "resolved": "https://registry.nlark.com/highlight.js/download/highlight.js-10.7.2.tgz",
- "integrity": "sha1-iTGbhh7cZsSIVO0ebaIeqJ+Ec2A=",
- "dev": true
- },
- "hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/hmac-drbg/download/hmac-drbg-1.0.1.tgz",
- "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
- "dev": true,
- "requires": {
- "hash.js": "^1.0.3",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "hoopy": {
- "version": "0.1.4",
- "resolved": "https://registry.nlark.com/hoopy/download/hoopy-0.1.4.tgz",
- "integrity": "sha1-YJIH1mEQADOpqUAq096mdzgcGx0=",
- "dev": true
- },
- "hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz",
- "integrity": "sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k=",
- "dev": true
- },
- "hpack.js": {
- "version": "2.1.6",
- "resolved": "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz",
- "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "obuf": "^1.0.0",
- "readable-stream": "^2.0.1",
- "wbuf": "^1.1.0"
- }
- },
- "hsl-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/hsl-regex/download/hsl-regex-1.0.0.tgz",
- "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
- "dev": true
- },
- "hsla-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/hsla-regex/download/hsla-regex-1.0.0.tgz",
- "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
- "dev": true
- },
- "html-entities": {
- "version": "1.4.0",
- "resolved": "https://registry.nlark.com/html-entities/download/html-entities-1.4.0.tgz",
- "integrity": "sha1-z70bAdKvr5rcobEK59/6uYxx0tw=",
- "dev": true
- },
- "html-minifier": {
- "version": "3.5.21",
- "resolved": "https://registry.npm.taobao.org/html-minifier/download/html-minifier-3.5.21.tgz",
- "integrity": "sha1-0AQOBUcw41TbAIRjWTGUAVIS0gw=",
- "dev": true,
- "requires": {
- "camel-case": "3.0.x",
- "clean-css": "4.2.x",
- "commander": "2.17.x",
- "he": "1.2.x",
- "param-case": "2.1.x",
- "relateurl": "0.2.x",
- "uglify-js": "3.4.x"
- },
- "dependencies": {
- "commander": {
- "version": "2.17.1",
- "resolved": "https://registry.nlark.com/commander/download/commander-2.17.1.tgz?cache=0&sync_timestamp=1622446257852&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcommander%2Fdownload%2Fcommander-2.17.1.tgz",
- "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=",
- "dev": true
- }
- }
- },
- "html-tags": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/html-tags/download/html-tags-3.1.0.tgz",
- "integrity": "sha1-e15vfmZen7QfMAB+2eDUHpf7IUA=",
- "dev": true
- },
- "html-webpack-plugin": {
- "version": "3.2.0",
- "resolved": "https://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz",
- "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
- "dev": true,
- "requires": {
- "html-minifier": "^3.2.3",
- "loader-utils": "^0.2.16",
- "lodash": "^4.17.3",
- "pretty-error": "^2.0.2",
- "tapable": "^1.0.0",
- "toposort": "^1.0.0",
- "util.promisify": "1.0.0"
- },
- "dependencies": {
- "big.js": {
- "version": "3.2.0",
- "resolved": "https://registry.nlark.com/big.js/download/big.js-3.2.0.tgz",
- "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=",
- "dev": true
- },
- "emojis-list": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz",
- "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
- "dev": true
- },
- "json5": {
- "version": "0.5.1",
- "resolved": "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz",
- "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
- "dev": true
- },
- "loader-utils": {
- "version": "0.2.17",
- "resolved": "https://registry.nlark.com/loader-utils/download/loader-utils-0.2.17.tgz?cache=0&sync_timestamp=1618846812625&other_urls=https%3A%2F%2Fregistry.nlark.com%2Floader-utils%2Fdownload%2Floader-utils-0.2.17.tgz",
- "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
- "dev": true,
- "requires": {
- "big.js": "^3.1.3",
- "emojis-list": "^2.0.0",
- "json5": "^0.5.0",
- "object-assign": "^4.0.1"
- }
- },
- "util.promisify": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz?cache=0&sync_timestamp=1610159895694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil.promisify%2Fdownload%2Futil.promisify-1.0.0.tgz",
- "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "object.getownpropertydescriptors": "^2.0.3"
- }
- }
- }
- },
- "htmlparser2": {
- "version": "3.10.1",
- "resolved": "https://registry.nlark.com/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1618846794076&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz",
- "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=",
- "dev": true,
- "requires": {
- "domelementtype": "^1.3.1",
- "domhandler": "^2.3.0",
- "domutils": "^1.5.1",
- "entities": "^1.1.1",
- "inherits": "^2.0.1",
- "readable-stream": "^3.1.1"
- },
- "dependencies": {
- "entities": {
- "version": "1.1.2",
- "resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz",
- "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=",
- "dev": true
- },
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.nlark.com/readable-stream/download/readable-stream-3.6.0.tgz",
- "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- }
- }
- },
- "http-deceiver": {
- "version": "1.2.7",
- "resolved": "https://registry.nlark.com/http-deceiver/download/http-deceiver-1.2.7.tgz",
- "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
- "dev": true
- },
- "http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz",
- "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=",
- "dev": true,
- "requires": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- }
- }
- },
- "http-parser-js": {
- "version": "0.5.3",
- "resolved": "https://registry.npm.taobao.org/http-parser-js/download/http-parser-js-0.5.3.tgz",
- "integrity": "sha1-AdJwnHnUFpi7AdTezF6dpOSgM9k=",
- "dev": true
- },
- "http-proxy": {
- "version": "1.18.1",
- "resolved": "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.1.tgz",
- "integrity": "sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk=",
- "dev": true,
- "requires": {
- "eventemitter3": "^4.0.0",
- "follow-redirects": "^1.0.0",
- "requires-port": "^1.0.0"
- }
- },
- "http-proxy-middleware": {
- "version": "1.3.1",
- "resolved": "https://registry.nlark.com/http-proxy-middleware/download/http-proxy-middleware-1.3.1.tgz?cache=0&sync_timestamp=1620409720336&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-1.3.1.tgz",
- "integrity": "sha1-Q3ANbZ7st0Gb8IahKND3IF2etmU=",
- "dev": true,
- "requires": {
- "@types/http-proxy": "^1.17.5",
- "http-proxy": "^1.18.1",
- "is-glob": "^4.0.1",
- "is-plain-obj": "^3.0.0",
- "micromatch": "^4.0.2"
- },
- "dependencies": {
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
- "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz",
- "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
- "dev": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.nlark.com/is-number/download/is-number-7.0.0.tgz",
- "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=",
- "dev": true
- },
- "micromatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-4.0.4.tgz?cache=0&sync_timestamp=1618054787196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmicromatch%2Fdownload%2Fmicromatch-4.0.4.tgz",
- "integrity": "sha1-iW1Rnf6dsl/OlM63pQCRm/iB6/k=",
- "dev": true,
- "requires": {
- "braces": "^3.0.1",
- "picomatch": "^2.2.3"
- }
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.nlark.com/to-regex-range/download/to-regex-range-5.0.1.tgz",
- "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
- "dev": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- }
- }
- },
- "http-signature": {
- "version": "1.2.0",
- "resolved": "https://registry.nlark.com/http-signature/download/http-signature-1.2.0.tgz",
- "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
- "dev": true,
- "requires": {
- "assert-plus": "^1.0.0",
- "jsprim": "^1.2.2",
- "sshpk": "^1.7.0"
- }
- },
- "https-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/https-browserify/download/https-browserify-1.0.0.tgz",
- "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
- "dev": true
- },
- "human-signals": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz",
- "integrity": "sha1-xbHNFPUK6uCatsWf5jujOV/k36M=",
- "dev": true
- },
- "iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.nlark.com/iconv-lite/download/iconv-lite-0.4.24.tgz",
- "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
- "dev": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "icss-replace-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz",
- "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
- "dev": true
- },
- "icss-utils": {
- "version": "4.1.1",
- "resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-4.1.1.tgz?cache=0&sync_timestamp=1605801291394&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-4.1.1.tgz",
- "integrity": "sha1-IRcLU3ie4nRHwvR91oMIFAP5pGc=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.14"
- }
- },
- "ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.nlark.com/ieee754/download/ieee754-1.2.1.tgz",
- "integrity": "sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I=",
- "dev": true
- },
- "iferr": {
- "version": "0.1.5",
- "resolved": "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz",
- "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
- "dev": true
- },
- "ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz",
- "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=",
- "dev": true
- },
- "import-cwd": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/import-cwd/download/import-cwd-2.1.0.tgz?cache=0&sync_timestamp=1618846826220&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fimport-cwd%2Fdownload%2Fimport-cwd-2.1.0.tgz",
- "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
- "dev": true,
- "requires": {
- "import-from": "^2.1.0"
- }
- },
- "import-fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz?cache=0&sync_timestamp=1608469561643&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-2.0.0.tgz",
- "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
- "dev": true,
- "requires": {
- "caller-path": "^2.0.0",
- "resolve-from": "^3.0.0"
- }
- },
- "import-from": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/import-from/download/import-from-2.1.0.tgz",
- "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
- "dev": true,
- "requires": {
- "resolve-from": "^3.0.0"
- }
- },
- "import-local": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/import-local/download/import-local-2.0.0.tgz",
- "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=",
- "dev": true,
- "requires": {
- "pkg-dir": "^3.0.0",
- "resolve-cwd": "^2.0.0"
- },
- "dependencies": {
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz",
- "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
- "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/p-locate/download/p-locate-3.0.0.tgz",
- "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-3.0.0.tgz",
- "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0"
- }
- }
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
- },
- "indexes-of": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz",
- "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
- "dev": true
- },
- "infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz",
- "integrity": "sha1-xM78qo5RBRwqQLos6KPScpWvlGc=",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.4.tgz",
- "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=",
- "dev": true
- },
- "inquirer": {
- "version": "7.3.3",
- "resolved": "https://registry.nlark.com/inquirer/download/inquirer-7.3.3.tgz?cache=0&sync_timestamp=1621629105005&other_urls=https%3A%2F%2Fregistry.nlark.com%2Finquirer%2Fdownload%2Finquirer-7.3.3.tgz",
- "integrity": "sha1-BNF2sq8Er8FXqD/XwQDpjuCq0AM=",
- "dev": true,
- "requires": {
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.1.0",
- "cli-cursor": "^3.1.0",
- "cli-width": "^3.0.0",
- "external-editor": "^3.0.3",
- "figures": "^3.0.0",
- "lodash": "^4.17.19",
- "mute-stream": "0.0.8",
- "run-async": "^2.4.0",
- "rxjs": "^6.6.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0",
- "through": "^2.3.6"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
- "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
- "dev": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "4.1.1",
- "resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.1.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.1.tgz",
- "integrity": "sha1-yAs/qyi/Y3HmhjMl7uZ+YYt35q0=",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-3.1.0.tgz",
- "integrity": "sha1-JkMFp65JDR0Dvwybp8kl0XU68wc=",
- "dev": true,
- "requires": {
- "restore-cursor": "^3.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
- "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
- "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
- "dev": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1618559676170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
- "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
- "dev": true
- },
- "mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz",
- "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=",
- "dev": true
- },
- "onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz",
- "integrity": "sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=",
- "dev": true,
- "requires": {
- "mimic-fn": "^2.1.0"
- }
- },
- "restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/restore-cursor/download/restore-cursor-3.1.0.tgz",
- "integrity": "sha1-OfZ8VLOnpYzqUjbZXPADQjljH34=",
- "dev": true,
- "requires": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- }
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
- "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "internal-ip": {
- "version": "4.3.0",
- "resolved": "https://registry.npm.taobao.org/internal-ip/download/internal-ip-4.3.0.tgz?cache=0&sync_timestamp=1605885528721&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finternal-ip%2Fdownload%2Finternal-ip-4.3.0.tgz",
- "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=",
- "dev": true,
- "requires": {
- "default-gateway": "^4.2.0",
- "ipaddr.js": "^1.9.0"
- },
- "dependencies": {
- "default-gateway": {
- "version": "4.2.0",
- "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1610365756089&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz",
- "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=",
- "dev": true,
- "requires": {
- "execa": "^1.0.0",
- "ip-regex": "^2.1.0"
- }
- }
- }
- },
- "ip": {
- "version": "1.1.5",
- "resolved": "https://registry.nlark.com/ip/download/ip-1.1.5.tgz",
- "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
- "dev": true
- },
- "ip-regex": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/ip-regex/download/ip-regex-2.1.0.tgz",
- "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
- "dev": true
- },
- "ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.1.tgz",
- "integrity": "sha1-v/OFQ+64mEglB5/zoqjmy9RngbM=",
- "dev": true
- },
- "is-absolute-url": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/is-absolute-url/download/is-absolute-url-2.1.0.tgz",
- "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=",
- "dev": true
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-arguments": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/is-arguments/download/is-arguments-1.1.0.tgz",
- "integrity": "sha1-YjUwMd++4HzrNGVqa95Z7+yujdk=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.0"
- }
- },
- "is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
- "is-bigint": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/is-bigint/download/is-bigint-1.0.2.tgz",
- "integrity": "sha1-/7OBRCUDI1rSReqJ5Fs9v/BA7lo=",
- "dev": true
- },
- "is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-2.1.0.tgz",
- "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=",
- "dev": true,
- "optional": true,
- "requires": {
- "binary-extensions": "^2.0.0"
- }
- },
- "is-boolean-object": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/is-boolean-object/download/is-boolean-object-1.1.1.tgz",
- "integrity": "sha1-PAh48DXLghIo01DS4eNnGXFqPeg=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2"
- }
- },
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.nlark.com/is-buffer/download/is-buffer-1.1.6.tgz",
- "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
- "dev": true
- },
- "is-callable": {
- "version": "1.2.3",
- "resolved": "https://registry.nlark.com/is-callable/download/is-callable-1.2.3.tgz",
- "integrity": "sha1-ix4FALc6HXbHBIdjbzaOUZ3o244=",
- "dev": true
- },
- "is-ci": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/is-ci/download/is-ci-1.2.1.tgz?cache=0&sync_timestamp=1613632023079&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-ci%2Fdownload%2Fis-ci-1.2.1.tgz",
- "integrity": "sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw=",
- "dev": true,
- "requires": {
- "ci-info": "^1.5.0"
- }
- },
- "is-color-stop": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/is-color-stop/download/is-color-stop-1.1.0.tgz",
- "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=",
- "dev": true,
- "requires": {
- "css-color-names": "^0.0.4",
- "hex-color-regex": "^1.1.0",
- "hsl-regex": "^1.0.0",
- "hsla-regex": "^1.0.0",
- "rgb-regex": "^1.0.1",
- "rgba-regex": "^1.0.0"
- }
- },
- "is-core-module": {
- "version": "2.4.0",
- "resolved": "https://registry.nlark.com/is-core-module/download/is-core-module-2.4.0.tgz?cache=0&sync_timestamp=1620592570629&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-core-module%2Fdownload%2Fis-core-module-2.4.0.tgz",
- "integrity": "sha1-jp/I4VAnsBFBgCbpjw5vTYYwXME=",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-date-object": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/is-date-object/download/is-date-object-1.0.4.tgz?cache=0&sync_timestamp=1620451921850&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-date-object%2Fdownload%2Fis-date-object-1.0.4.tgz",
- "integrity": "sha1-VQz8wDr62gXuo90wmBx7CVUfc+U=",
- "dev": true
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz",
- "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-5.1.0.tgz",
- "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
- "dev": true
- }
- }
- },
- "is-directory": {
- "version": "0.3.1",
- "resolved": "https://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz",
- "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
- "dev": true
- },
- "is-docker": {
- "version": "2.2.1",
- "resolved": "https://registry.nlark.com/is-docker/download/is-docker-2.2.1.tgz",
- "integrity": "sha1-M+6r4jz+hvFL3kQIoCwM+4U6zao=",
- "dev": true
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
- "dev": true
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=",
- "dev": true
- },
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-4.0.1.tgz",
- "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-negative-zero": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/is-negative-zero/download/is-negative-zero-2.0.1.tgz",
- "integrity": "sha1-PedGwY3aIxkkGlNnWQjY92bxHCQ=",
- "dev": true
- },
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/is-number/download/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-number-object": {
- "version": "1.0.5",
- "resolved": "https://registry.nlark.com/is-number-object/download/is-number-object-1.0.5.tgz",
- "integrity": "sha1-bt+u7XlQz/Ga/tzp+/yp7m3Sies=",
- "dev": true
- },
- "is-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz",
- "integrity": "sha1-Rz+wXZc3BeP9liBUUBjKjiLvSYI=",
- "dev": true
- },
- "is-path-cwd": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-2.2.0.tgz",
- "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=",
- "dev": true
- },
- "is-path-in-cwd": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/is-path-in-cwd/download/is-path-in-cwd-2.1.0.tgz?cache=0&sync_timestamp=1620047110449&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-path-in-cwd%2Fdownload%2Fis-path-in-cwd-2.1.0.tgz",
- "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=",
- "dev": true,
- "requires": {
- "is-path-inside": "^2.1.0"
- }
- },
- "is-path-inside": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/is-path-inside/download/is-path-inside-2.1.0.tgz?cache=0&sync_timestamp=1620046845369&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-path-inside%2Fdownload%2Fis-path-inside-2.1.0.tgz",
- "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=",
- "dev": true,
- "requires": {
- "path-is-inside": "^1.0.2"
- }
- },
- "is-plain-obj": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-3.0.0.tgz",
- "integrity": "sha1-r28uoUrFpkYYOlu9tbqrvBVq2dc=",
- "dev": true
- },
- "is-plain-object": {
- "version": "2.0.4",
- "resolved": "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz",
- "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "is-regex": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/is-regex/download/is-regex-1.1.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-regex%2Fdownload%2Fis-regex-1.1.3.tgz",
- "integrity": "sha1-0Cn5r/ZEi5Prvj8z2scVEf3L758=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "has-symbols": "^1.0.2"
- }
- },
- "is-resolvable": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz",
- "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=",
- "dev": true
- },
- "is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/is-stream/download/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
- "dev": true
- },
- "is-string": {
- "version": "1.0.6",
- "resolved": "https://registry.nlark.com/is-string/download/is-string-1.0.6.tgz",
- "integrity": "sha1-P+XVmS+w2TQE8yWE1LAXmnG1Sl8=",
- "dev": true
- },
- "is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/is-symbol/download/is-symbol-1.0.4.tgz?cache=0&sync_timestamp=1620501174327&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-symbol%2Fdownload%2Fis-symbol-1.0.4.tgz",
- "integrity": "sha1-ptrJO2NbBjymhyI23oiRClevE5w=",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.2"
- }
- },
- "is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
- "dev": true
- },
- "is-windows": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/is-windows/download/is-windows-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-windows%2Fdownload%2Fis-windows-1.0.2.tgz",
- "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=",
- "dev": true
- },
- "is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/is-wsl/download/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
- "dev": true
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/isexe/download/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
- "dev": true
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- },
- "isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.nlark.com/isstream/download/isstream-0.1.2.tgz",
- "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
- "dev": true
- },
- "javascript-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/javascript-stringify/download/javascript-stringify-2.1.0.tgz",
- "integrity": "sha1-J8dlOb4U2L0Sghmi1zGwkzeQTnk=",
- "dev": true
- },
- "js-message": {
- "version": "1.0.7",
- "resolved": "https://registry.npm.taobao.org/js-message/download/js-message-1.0.7.tgz",
- "integrity": "sha1-+93QU8ekcCGHG7iyyVOXzBfCDkc=",
- "dev": true
- },
- "js-queue": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/js-queue/download/js-queue-2.0.2.tgz",
- "integrity": "sha1-C+WQM4+QOzbHPTPDGIOoIUEs1II=",
- "dev": true,
- "requires": {
- "easy-stack": "^1.0.1"
- }
- },
- "js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1619345098261&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz",
- "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=",
- "dev": true
- },
- "js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.1.tgz?cache=0&sync_timestamp=1618435004368&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-yaml%2Fdownload%2Fjs-yaml-3.14.1.tgz",
- "integrity": "sha1-2ugS/bOCX6MGYJqHFzg8UMNqBTc=",
- "dev": true,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.nlark.com/jsbn/download/jsbn-0.1.1.tgz",
- "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
- "dev": true
- },
- "jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.nlark.com/jsesc/download/jsesc-2.5.2.tgz",
- "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=",
- "dev": true
- },
- "json-parse-better-errors": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=",
- "dev": true
- },
- "json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.nlark.com/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha1-fEeAWpQxmSjgV3dAXcEuH3pO4C0=",
- "dev": true
- },
- "json-schema": {
- "version": "0.2.3",
- "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553637722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz",
- "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
- "dev": true
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz?cache=0&sync_timestamp=1607998264311&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema-traverse%2Fdownload%2Fjson-schema-traverse-0.4.1.tgz",
- "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
- "dev": true
- },
- "json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
- "dev": true
- },
- "json3": {
- "version": "3.3.3",
- "resolved": "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz",
- "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=",
- "dev": true
- },
- "json5": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.2.0.tgz",
- "integrity": "sha1-Lf7+cgxrpSXZ69kJlQ8FFTFsiaM=",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161843950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz",
- "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.6"
- }
- },
- "jsprim": {
- "version": "1.4.1",
- "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz",
- "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.2.3",
- "verror": "1.10.0"
- }
- },
- "killable": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/killable/download/killable-1.0.1.tgz",
- "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=",
- "dev": true
- },
- "kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-6.0.3.tgz",
- "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
- "dev": true
- },
- "launch-editor": {
- "version": "2.2.1",
- "resolved": "https://registry.npm.taobao.org/launch-editor/download/launch-editor-2.2.1.tgz",
- "integrity": "sha1-hxtaPuOdZoD8wm03kwtu7aidsMo=",
- "dev": true,
- "requires": {
- "chalk": "^2.3.0",
- "shell-quote": "^1.6.1"
- }
- },
- "launch-editor-middleware": {
- "version": "2.2.1",
- "resolved": "https://registry.npm.taobao.org/launch-editor-middleware/download/launch-editor-middleware-2.2.1.tgz",
- "integrity": "sha1-4UsH5scVSwpLhqD9NFeE5FgEwVc=",
- "dev": true,
- "requires": {
- "launch-editor": "^2.2.1"
- }
- },
- "levn": {
- "version": "0.3.0",
- "resolved": "https://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz",
- "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
- "dev": true,
- "requires": {
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2"
- }
- },
- "lines-and-columns": {
- "version": "1.1.6",
- "resolved": "https://registry.nlark.com/lines-and-columns/download/lines-and-columns-1.1.6.tgz",
- "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
- "dev": true
- },
- "loader-fs-cache": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/loader-fs-cache/download/loader-fs-cache-1.0.3.tgz",
- "integrity": "sha1-8IZXZG1gcHi+LwoDL4vWndbyd9k=",
- "dev": true,
- "requires": {
- "find-cache-dir": "^0.1.1",
- "mkdirp": "^0.5.1"
- },
- "dependencies": {
- "find-cache-dir": {
- "version": "0.1.1",
- "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-0.1.1.tgz",
- "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "mkdirp": "^0.5.1",
- "pkg-dir": "^1.0.0"
- }
- },
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-1.1.2.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "^2.0.0"
- }
- },
- "pkg-dir": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-1.0.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-1.0.0.tgz",
- "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
- "dev": true,
- "requires": {
- "find-up": "^1.0.0"
- }
- }
- }
- },
- "loader-runner": {
- "version": "2.4.0",
- "resolved": "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz?cache=0&sync_timestamp=1610027908268&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-runner%2Fdownload%2Floader-runner-2.4.0.tgz",
- "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=",
- "dev": true
- },
- "loader-utils": {
- "version": "1.4.0",
- "resolved": "https://registry.nlark.com/loader-utils/download/loader-utils-1.4.0.tgz?cache=0&sync_timestamp=1618846812625&other_urls=https%3A%2F%2Fregistry.nlark.com%2Floader-utils%2Fdownload%2Floader-utils-1.4.0.tgz",
- "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=",
- "dev": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^1.0.1"
- },
- "dependencies": {
- "json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz",
- "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- }
- }
- },
- "locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz",
- "integrity": "sha1-Gvujlq/WdqbUJQTQpno6frn2KqA=",
- "dev": true,
- "requires": {
- "p-locate": "^4.1.0"
- }
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.nlark.com/lodash/download/lodash-4.17.21.tgz",
- "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=",
- "dev": true
- },
- "lodash.camelcase": {
- "version": "4.3.0",
- "resolved": "https://registry.npm.taobao.org/lodash.camelcase/download/lodash.camelcase-4.3.0.tgz",
- "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
- "dev": true
- },
- "lodash.clonedeep": {
- "version": "4.5.0",
- "resolved": "https://registry.npm.taobao.org/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz?cache=0&sync_timestamp=1599054271708&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.clonedeep%2Fdownload%2Flodash.clonedeep-4.5.0.tgz",
- "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
- "dev": true
- },
- "lodash.debounce": {
- "version": "4.0.8",
- "resolved": "https://registry.npm.taobao.org/lodash.debounce/download/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
- "dev": true
- },
- "lodash.defaultsdeep": {
- "version": "4.6.1",
- "resolved": "https://registry.nlark.com/lodash.defaultsdeep/download/lodash.defaultsdeep-4.6.1.tgz",
- "integrity": "sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY=",
- "dev": true
- },
- "lodash.kebabcase": {
- "version": "4.1.1",
- "resolved": "https://registry.nlark.com/lodash.kebabcase/download/lodash.kebabcase-4.1.1.tgz",
- "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=",
- "dev": true
- },
- "lodash.mapvalues": {
- "version": "4.6.0",
- "resolved": "https://registry.npm.taobao.org/lodash.mapvalues/download/lodash.mapvalues-4.6.0.tgz",
- "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=",
- "dev": true
- },
- "lodash.memoize": {
- "version": "4.1.2",
- "resolved": "https://registry.nlark.com/lodash.memoize/download/lodash.memoize-4.1.2.tgz",
- "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
- "dev": true
- },
- "lodash.transform": {
- "version": "4.6.0",
- "resolved": "https://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz",
- "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=",
- "dev": true
- },
- "lodash.uniq": {
- "version": "4.5.0",
- "resolved": "https://registry.nlark.com/lodash.uniq/download/lodash.uniq-4.5.0.tgz",
- "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
- "dev": true
- },
- "log-symbols": {
- "version": "2.2.0",
- "resolved": "https://registry.nlark.com/log-symbols/download/log-symbols-2.2.0.tgz?cache=0&sync_timestamp=1618847128438&other_urls=https%3A%2F%2Fregistry.nlark.com%2Flog-symbols%2Fdownload%2Flog-symbols-2.2.0.tgz",
- "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=",
- "dev": true,
- "requires": {
- "chalk": "^2.0.1"
- }
- },
- "loglevel": {
- "version": "1.7.1",
- "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.7.1.tgz?cache=0&sync_timestamp=1606314031897&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.7.1.tgz",
- "integrity": "sha1-AF/eL15uRwaPk1/yhXPhJe9y8Zc=",
- "dev": true
- },
- "lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npm.taobao.org/lower-case/download/lower-case-1.1.4.tgz?cache=0&sync_timestamp=1606867333511&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flower-case%2Fdownload%2Flower-case-1.1.4.tgz",
- "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
- "dev": true
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-5.1.1.tgz",
- "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=",
- "dev": true,
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "magic-string": {
- "version": "0.25.7",
- "resolved": "https://registry.npm.taobao.org/magic-string/download/magic-string-0.25.7.tgz",
- "integrity": "sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE=",
- "dev": true,
- "requires": {
- "sourcemap-codec": "^1.4.4"
- }
- },
- "make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz",
- "integrity": "sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8=",
- "dev": true,
- "requires": {
- "semver": "^6.0.0"
- }
- },
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/map-cache/download/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
- "dev": true
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/map-visit/download/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
- "dev": true,
- "requires": {
- "object-visit": "^1.0.0"
- }
- },
- "md5.js": {
- "version": "1.3.5",
- "resolved": "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz",
- "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=",
- "dev": true,
- "requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "mdn-data": {
- "version": "2.0.4",
- "resolved": "https://registry.nlark.com/mdn-data/download/mdn-data-2.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmdn-data%2Fdownload%2Fmdn-data-2.0.4.tgz",
- "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=",
- "dev": true
- },
- "media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.nlark.com/media-typer/download/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
- "dev": true
- },
- "memory-fs": {
- "version": "0.4.1",
- "resolved": "https://registry.nlark.com/memory-fs/download/memory-fs-0.4.1.tgz",
- "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
- "dev": true,
- "requires": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
- }
- },
- "merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/merge-descriptors/download/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
- "dev": true
- },
- "merge-source-map": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/merge-source-map/download/merge-source-map-1.1.0.tgz",
- "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=",
- "dev": true,
- "requires": {
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/merge-stream/download/merge-stream-2.0.0.tgz",
- "integrity": "sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=",
- "dev": true
- },
- "merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npm.taobao.org/merge2/download/merge2-1.4.1.tgz",
- "integrity": "sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=",
- "dev": true
- },
- "methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
- "dev": true
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz?cache=0&sync_timestamp=1618054787196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmicromatch%2Fdownload%2Fmicromatch-3.1.10.tgz",
- "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- }
- },
- "miller-rabin": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/miller-rabin/download/miller-rabin-4.0.1.tgz",
- "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
- "dev": true,
- "requires": {
- "bn.js": "^4.0.0",
- "brorand": "^1.0.1"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "mime": {
- "version": "2.5.2",
- "resolved": "https://registry.npm.taobao.org/mime/download/mime-2.5.2.tgz",
- "integrity": "sha1-bj3GzCuVEGQ4MOXxnVy3U9pe6r4=",
- "dev": true
- },
- "mime-db": {
- "version": "1.47.0",
- "resolved": "https://registry.nlark.com/mime-db/download/mime-db-1.47.0.tgz",
- "integrity": "sha1-jLMT5Zll08Bc+/iYkVomevRqM1w=",
- "dev": true
- },
- "mime-types": {
- "version": "2.1.30",
- "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.30.tgz",
- "integrity": "sha1-bnvotMR5gl+F7WMmaV23P5MF1i0=",
- "dev": true,
- "requires": {
- "mime-db": "1.47.0"
- }
- },
- "mimic-fn": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz",
- "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=",
- "dev": true
- },
- "mini-css-extract-plugin": {
- "version": "0.9.0",
- "resolved": "https://registry.nlark.com/mini-css-extract-plugin/download/mini-css-extract-plugin-0.9.0.tgz?cache=0&sync_timestamp=1619783320763&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmini-css-extract-plugin%2Fdownload%2Fmini-css-extract-plugin-0.9.0.tgz",
- "integrity": "sha1-R/LPB6oWWrNXM7H8l9TEbAVkM54=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.1.0",
- "normalize-url": "1.9.1",
- "schema-utils": "^1.0.0",
- "webpack-sources": "^1.1.0"
- },
- "dependencies": {
- "normalize-url": {
- "version": "1.9.1",
- "resolved": "https://registry.nlark.com/normalize-url/download/normalize-url-1.9.1.tgz",
- "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
- "dev": true,
- "requires": {
- "object-assign": "^4.0.1",
- "prepend-http": "^1.0.0",
- "query-string": "^4.1.0",
- "sort-keys": "^1.0.0"
- }
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- }
- }
- },
- "minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=",
- "dev": true
- },
- "minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
- "dev": true
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz",
- "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.nlark.com/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1618847017774&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
- "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=",
- "dev": true
- },
- "minipass": {
- "version": "3.1.3",
- "resolved": "https://registry.npm.taobao.org/minipass/download/minipass-3.1.3.tgz",
- "integrity": "sha1-fUL/HzljVILhX5zbUxhN7r1YFf0=",
- "dev": true,
- "requires": {
- "yallist": "^4.0.0"
- },
- "dependencies": {
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
- "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
- "dev": true
- }
- }
- },
- "mississippi": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz",
- "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=",
- "dev": true,
- "requires": {
- "concat-stream": "^1.5.0",
- "duplexify": "^3.4.2",
- "end-of-stream": "^1.1.0",
- "flush-write-stream": "^1.0.0",
- "from2": "^2.1.0",
- "parallel-transform": "^1.1.0",
- "pump": "^3.0.0",
- "pumpify": "^1.3.3",
- "stream-each": "^1.1.0",
- "through2": "^2.0.0"
- }
- },
- "mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz",
- "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=",
- "dev": true,
- "requires": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz",
- "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz",
- "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "move-concurrently": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/move-concurrently/download/move-concurrently-1.0.1.tgz",
- "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1",
- "copy-concurrently": "^1.0.0",
- "fs-write-stream-atomic": "^1.0.8",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.3"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
- "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=",
- "dev": true
- },
- "multicast-dns": {
- "version": "6.2.3",
- "resolved": "https://registry.nlark.com/multicast-dns/download/multicast-dns-6.2.3.tgz",
- "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=",
- "dev": true,
- "requires": {
- "dns-packet": "^1.3.1",
- "thunky": "^1.0.2"
- }
- },
- "multicast-dns-service-types": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz",
- "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
- "dev": true
- },
- "mute-stream": {
- "version": "0.0.8",
- "resolved": "https://registry.nlark.com/mute-stream/download/mute-stream-0.0.8.tgz",
- "integrity": "sha1-FjDEKyJR/4HiooPelqVJfqkuXg0=",
- "dev": true
- },
- "mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz",
- "integrity": "sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=",
- "dev": true,
- "requires": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
- "nan": {
- "version": "2.14.2",
- "resolved": "https://registry.nlark.com/nan/download/nan-2.14.2.tgz",
- "integrity": "sha1-9TdkAGlRaPTMaUrJOT0MlYXu6hk=",
- "dev": true,
- "optional": true
- },
- "nanoid": {
- "version": "3.1.23",
- "resolved": "https://registry.nlark.com/nanoid/download/nanoid-3.1.23.tgz",
- "integrity": "sha1-90QIbOfCvEfuCoRyV01ceOQYOoE=",
- "dev": true
- },
- "nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.nlark.com/nanomatch/download/nanomatch-1.2.13.tgz",
- "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "fragment-cache": "^0.2.1",
- "is-windows": "^1.0.2",
- "kind-of": "^6.0.2",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- }
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
- "dev": true
- },
- "negotiator": {
- "version": "0.6.2",
- "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
- "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=",
- "dev": true
- },
- "neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.nlark.com/neo-async/download/neo-async-2.6.2.tgz",
- "integrity": "sha1-tKr7k+OustgXTKU88WOrfXMIMF8=",
- "dev": true
- },
- "nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz?cache=0&sync_timestamp=1614510016909&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnice-try%2Fdownload%2Fnice-try-1.0.5.tgz",
- "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=",
- "dev": true
- },
- "no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npm.taobao.org/no-case/download/no-case-2.3.2.tgz",
- "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=",
- "dev": true,
- "requires": {
- "lower-case": "^1.1.1"
- }
- },
- "node-forge": {
- "version": "0.10.0",
- "resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.10.0.tgz?cache=0&sync_timestamp=1599054189018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.10.0.tgz",
- "integrity": "sha1-Mt6ir7Ppkm8C7lzoeUkCaRpna/M=",
- "dev": true
- },
- "node-ipc": {
- "version": "9.1.4",
- "resolved": "https://registry.nlark.com/node-ipc/download/node-ipc-9.1.4.tgz",
- "integrity": "sha1-Ks+WJoGv2sJgKHbZj+ZDTVTZvTw=",
- "dev": true,
- "requires": {
- "event-pubsub": "4.3.0",
- "js-message": "1.0.7",
- "js-queue": "2.0.2"
- }
- },
- "node-libs-browser": {
- "version": "2.2.1",
- "resolved": "https://registry.nlark.com/node-libs-browser/download/node-libs-browser-2.2.1.tgz",
- "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=",
- "dev": true,
- "requires": {
- "assert": "^1.1.1",
- "browserify-zlib": "^0.2.0",
- "buffer": "^4.3.0",
- "console-browserify": "^1.1.0",
- "constants-browserify": "^1.0.0",
- "crypto-browserify": "^3.11.0",
- "domain-browser": "^1.1.1",
- "events": "^3.0.0",
- "https-browserify": "^1.0.0",
- "os-browserify": "^0.3.0",
- "path-browserify": "0.0.1",
- "process": "^0.11.10",
- "punycode": "^1.2.4",
- "querystring-es3": "^0.2.0",
- "readable-stream": "^2.3.3",
- "stream-browserify": "^2.0.1",
- "stream-http": "^2.7.2",
- "string_decoder": "^1.0.0",
- "timers-browserify": "^2.0.4",
- "tty-browserify": "0.0.0",
- "url": "^0.11.0",
- "util": "^0.11.0",
- "vm-browserify": "^1.0.1"
- },
- "dependencies": {
- "punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.nlark.com/punycode/download/punycode-1.4.1.tgz",
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
- "dev": true
- }
- }
- },
- "node-releases": {
- "version": "1.1.72",
- "resolved": "https://registry.nlark.com/node-releases/download/node-releases-1.1.72.tgz?cache=0&sync_timestamp=1620978655178&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.72.tgz",
- "integrity": "sha1-FIAqtrEDmnmgx9ZithClu9durL4=",
- "dev": true
- },
- "normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.nlark.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz",
- "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz",
- "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
- "dev": true
- }
- }
- },
- "normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
- "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
- "dev": true
- },
- "normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/normalize-range/download/normalize-range-0.1.2.tgz",
- "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
- "dev": true
- },
- "normalize-url": {
- "version": "3.3.0",
- "resolved": "https://registry.nlark.com/normalize-url/download/normalize-url-3.3.0.tgz",
- "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
- "dev": true
- },
- "npm-run-path": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz",
- "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
- "dev": true,
- "requires": {
- "path-key": "^2.0.0"
- }
- },
- "nth-check": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/nth-check/download/nth-check-1.0.2.tgz",
- "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=",
- "dev": true,
- "requires": {
- "boolbase": "~1.0.0"
- }
- },
- "num2fraction": {
- "version": "1.2.2",
- "resolved": "https://registry.npm.taobao.org/num2fraction/download/num2fraction-1.2.2.tgz",
- "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
- "dev": true
- },
- "oauth-sign": {
- "version": "0.9.0",
- "resolved": "https://registry.nlark.com/oauth-sign/download/oauth-sign-0.9.0.tgz",
- "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=",
- "dev": true
- },
- "object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.nlark.com/object-assign/download/object-assign-4.1.1.tgz?cache=0&sync_timestamp=1618847043548&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fobject-assign%2Fdownload%2Fobject-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
- },
- "object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
- "dev": true,
- "requires": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "object-hash": {
- "version": "1.3.1",
- "resolved": "https://registry.nlark.com/object-hash/download/object-hash-1.3.1.tgz",
- "integrity": "sha1-/eRSCYqVHLFF8Dm7fUVUSd3BJt8=",
- "dev": true
- },
- "object-inspect": {
- "version": "1.10.3",
- "resolved": "https://registry.nlark.com/object-inspect/download/object-inspect-1.10.3.tgz",
- "integrity": "sha1-wqp9LQn1DJk3VwT3oK3yTFeC02k=",
- "dev": true
- },
- "object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npm.taobao.org/object-is/download/object-is-1.1.5.tgz?cache=0&sync_timestamp=1613857698573&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-is%2Fdownload%2Fobject-is-1.1.5.tgz",
- "integrity": "sha1-ud7qpfx/GEag+uzc7sE45XePU6w=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/object-keys/download/object-keys-1.1.1.tgz",
- "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=",
- "dev": true
- },
- "object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/object-visit/download/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.0"
- }
- },
- "object.assign": {
- "version": "4.1.2",
- "resolved": "https://registry.nlark.com/object.assign/download/object.assign-4.1.2.tgz",
- "integrity": "sha1-DtVKNC7Os3s4/3brgxoOeIy2OUA=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.0",
- "define-properties": "^1.1.3",
- "has-symbols": "^1.0.1",
- "object-keys": "^1.1.1"
- }
- },
- "object.getownpropertydescriptors": {
- "version": "2.1.2",
- "resolved": "https://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.1.2.tgz?cache=0&sync_timestamp=1613860004199&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.getownpropertydescriptors%2Fdownload%2Fobject.getownpropertydescriptors-2.1.2.tgz",
- "integrity": "sha1-G9Y66s8NXS0vMbXjk7A6fGAaI/c=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.18.0-next.2"
- }
- },
- "object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "object.values": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/object.values/download/object.values-1.1.4.tgz?cache=0&sync_timestamp=1622070620040&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fobject.values%2Fdownload%2Fobject.values-1.1.4.tgz",
- "integrity": "sha1-DSc3YoM+gWtpOmN9MAc+cFFTWzA=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.18.2"
- }
- },
- "obuf": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/obuf/download/obuf-1.1.2.tgz",
- "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=",
- "dev": true
- },
- "on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/on-finished/download/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "dev": true,
- "requires": {
- "ee-first": "1.1.1"
- }
- },
- "on-headers": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/on-headers/download/on-headers-1.0.2.tgz",
- "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=",
- "dev": true
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.nlark.com/once/download/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "onetime": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz",
- "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
- "dev": true,
- "requires": {
- "mimic-fn": "^1.0.0"
- }
- },
- "open": {
- "version": "6.4.0",
- "resolved": "https://registry.nlark.com/open/download/open-6.4.0.tgz",
- "integrity": "sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk=",
- "dev": true,
- "requires": {
- "is-wsl": "^1.1.0"
- }
- },
- "opener": {
- "version": "1.5.2",
- "resolved": "https://registry.npm.taobao.org/opener/download/opener-1.5.2.tgz",
- "integrity": "sha1-XTfh81B3udysQwE3InGv3rKhNZg=",
- "dev": true
- },
- "opn": {
- "version": "5.5.0",
- "resolved": "https://registry.nlark.com/opn/download/opn-5.5.0.tgz",
- "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=",
- "dev": true,
- "requires": {
- "is-wsl": "^1.1.0"
- }
- },
- "optionator": {
- "version": "0.8.3",
- "resolved": "https://registry.nlark.com/optionator/download/optionator-0.8.3.tgz",
- "integrity": "sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU=",
- "dev": true,
- "requires": {
- "deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.6",
- "levn": "~0.3.0",
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2",
- "word-wrap": "~1.2.3"
- }
- },
- "ora": {
- "version": "3.4.0",
- "resolved": "https://registry.nlark.com/ora/download/ora-3.4.0.tgz",
- "integrity": "sha1-vwdSSRBZo+8+1MhQl1Md6f280xg=",
- "dev": true,
- "requires": {
- "chalk": "^2.4.2",
- "cli-cursor": "^2.1.0",
- "cli-spinners": "^2.0.0",
- "log-symbols": "^2.2.0",
- "strip-ansi": "^5.2.0",
- "wcwidth": "^1.0.1"
- },
- "dependencies": {
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "original": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/original/download/original-1.0.2.tgz",
- "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=",
- "dev": true,
- "requires": {
- "url-parse": "^1.4.3"
- }
- },
- "os-browserify": {
- "version": "0.3.0",
- "resolved": "https://registry.nlark.com/os-browserify/download/os-browserify-0.3.0.tgz",
- "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
- "dev": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz",
- "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
- "dev": true
- },
- "p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz",
- "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
- "dev": true
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/p-limit/download/p-limit-2.3.0.tgz",
- "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/p-locate/download/p-locate-4.1.0.tgz",
- "integrity": "sha1-o0KLtwiLOmApL2aRkni3wpetTwc=",
- "dev": true,
- "requires": {
- "p-limit": "^2.2.0"
- }
- },
- "p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/p-map/download/p-map-2.1.0.tgz",
- "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=",
- "dev": true
- },
- "p-retry": {
- "version": "3.0.1",
- "resolved": "https://registry.npm.taobao.org/p-retry/download/p-retry-3.0.1.tgz",
- "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=",
- "dev": true,
- "requires": {
- "retry": "^0.12.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz",
- "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=",
- "dev": true
- },
- "pako": {
- "version": "1.0.11",
- "resolved": "https://registry.nlark.com/pako/download/pako-1.0.11.tgz",
- "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8=",
- "dev": true
- },
- "parallel-transform": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.2.0.tgz",
- "integrity": "sha1-kEnKN9bLIYLDsdLHIL6U0UpYFPw=",
- "dev": true,
- "requires": {
- "cyclist": "^1.0.1",
- "inherits": "^2.0.3",
- "readable-stream": "^2.1.5"
- }
- },
- "param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/param-case/download/param-case-2.1.1.tgz",
- "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
- "dev": true,
- "requires": {
- "no-case": "^2.2.0"
- }
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/parent-module/download/parent-module-1.0.1.tgz",
- "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=",
- "dev": true,
- "requires": {
- "callsites": "^3.0.0"
- },
- "dependencies": {
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz",
- "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=",
- "dev": true
- }
- }
- },
- "parse-asn1": {
- "version": "5.1.6",
- "resolved": "https://registry.nlark.com/parse-asn1/download/parse-asn1-5.1.6.tgz",
- "integrity": "sha1-OFCAo+wTy2KmLTlAnLPoiETNrtQ=",
- "dev": true,
- "requires": {
- "asn1.js": "^5.2.0",
- "browserify-aes": "^1.0.0",
- "evp_bytestokey": "^1.0.0",
- "pbkdf2": "^3.0.3",
- "safe-buffer": "^5.1.1"
- }
- },
- "parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.nlark.com/parse-json/download/parse-json-5.2.0.tgz",
- "integrity": "sha1-x2/Gbe5UIxyWKyK8yKcs8vmXU80=",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- }
- },
- "parse5": {
- "version": "5.1.1",
- "resolved": "https://registry.nlark.com/parse5/download/parse5-5.1.1.tgz",
- "integrity": "sha1-9o5OW6GFKsLK3AD0VV//bCq7YXg=",
- "dev": true
- },
- "parse5-htmlparser2-tree-adapter": {
- "version": "6.0.1",
- "resolved": "https://registry.npm.taobao.org/parse5-htmlparser2-tree-adapter/download/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
- "integrity": "sha1-LN+a2CMyEUA3DU2/XT6Sx8jdxuY=",
- "dev": true,
- "requires": {
- "parse5": "^6.0.1"
- },
- "dependencies": {
- "parse5": {
- "version": "6.0.1",
- "resolved": "https://registry.nlark.com/parse5/download/parse5-6.0.1.tgz",
- "integrity": "sha1-4aHAhcVps9wIMhGE8Zo5zCf3wws=",
- "dev": true
- }
- }
- },
- "parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz?cache=0&sync_timestamp=1599054201722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparseurl%2Fdownload%2Fparseurl-1.3.3.tgz",
- "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=",
- "dev": true
- },
- "pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
- "dev": true
- },
- "path-browserify": {
- "version": "0.0.1",
- "resolved": "https://registry.nlark.com/path-browserify/download/path-browserify-0.0.1.tgz",
- "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=",
- "dev": true
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
- "dev": true
- },
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-4.0.0.tgz",
- "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=",
- "dev": true
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
- },
- "path-is-inside": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/path-is-inside/download/path-is-inside-1.0.2.tgz",
- "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
- "dev": true
- },
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz?cache=0&sync_timestamp=1617971695678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-key%2Fdownload%2Fpath-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
- "dev": true
- },
- "path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.nlark.com/path-parse/download/path-parse-1.0.7.tgz",
- "integrity": "sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU=",
- "dev": true
- },
- "path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.nlark.com/path-to-regexp/download/path-to-regexp-0.1.7.tgz?cache=0&sync_timestamp=1618846809278&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
- "dev": true
- },
- "path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz?cache=0&sync_timestamp=1611752107592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-type%2Fdownload%2Fpath-type-3.0.0.tgz",
- "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=",
- "dev": true,
- "requires": {
- "pify": "^3.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- }
- }
- },
- "pbkdf2": {
- "version": "3.1.2",
- "resolved": "https://registry.nlark.com/pbkdf2/download/pbkdf2-3.1.2.tgz",
- "integrity": "sha1-3YIqoIh1gOUvGgOdw+2hCO+uMHU=",
- "dev": true,
- "requires": {
- "create-hash": "^1.1.2",
- "create-hmac": "^1.1.4",
- "ripemd160": "^2.0.1",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- }
- },
- "performance-now": {
- "version": "2.1.0",
- "resolved": "https://registry.nlark.com/performance-now/download/performance-now-2.1.0.tgz",
- "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
- "dev": true
- },
- "picomatch": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz",
- "integrity": "sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI=",
- "dev": true
- },
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz",
- "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=",
- "dev": true
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/pinkie-promise/download/pinkie-promise-2.0.1.tgz?cache=0&sync_timestamp=1618847023792&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpinkie-promise%2Fdownload%2Fpinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "dev": true,
- "requires": {
- "pinkie": "^2.0.0"
- }
- },
- "pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-4.2.0.tgz",
- "integrity": "sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM=",
- "dev": true,
- "requires": {
- "find-up": "^4.0.0"
- }
- },
- "pnp-webpack-plugin": {
- "version": "1.6.4",
- "resolved": "https://registry.npm.taobao.org/pnp-webpack-plugin/download/pnp-webpack-plugin-1.6.4.tgz",
- "integrity": "sha1-yXEaxNxIpoXauvyG+Lbdn434QUk=",
- "dev": true,
- "requires": {
- "ts-pnp": "^1.1.6"
- }
- },
- "portfinder": {
- "version": "1.0.28",
- "resolved": "https://registry.nlark.com/portfinder/download/portfinder-1.0.28.tgz",
- "integrity": "sha1-Z8RiKFK9U3TdHdkA93n1NGL6x3g=",
- "dev": true,
- "requires": {
- "async": "^2.6.2",
- "debug": "^3.1.1",
- "mkdirp": "^0.5.5"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.nlark.com/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz",
- "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
- }
- },
- "posix-character-classes": {
- "version": "0.1.1",
- "resolved": "https://registry.nlark.com/posix-character-classes/download/posix-character-classes-0.1.1.tgz",
- "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
- "dev": true
- },
- "postcss": {
- "version": "7.0.35",
- "resolved": "https://registry.nlark.com/postcss/download/postcss-7.0.35.tgz?cache=0&sync_timestamp=1621568644827&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss%2Fdownload%2Fpostcss-7.0.35.tgz",
- "integrity": "sha1-0r4AuZj38hHYonaXQHny6SuXDiQ=",
- "dev": true,
- "requires": {
- "chalk": "^2.4.2",
- "source-map": "^0.6.1",
- "supports-color": "^6.1.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- },
- "supports-color": {
- "version": "6.1.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz",
- "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "postcss-calc": {
- "version": "7.0.5",
- "resolved": "https://registry.npm.taobao.org/postcss-calc/download/postcss-calc-7.0.5.tgz?cache=0&sync_timestamp=1609689139608&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-calc%2Fdownload%2Fpostcss-calc-7.0.5.tgz",
- "integrity": "sha1-+KbpnxLmGcLrwjz2xIb9wVhgkz4=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.27",
- "postcss-selector-parser": "^6.0.2",
- "postcss-value-parser": "^4.0.2"
- }
- },
- "postcss-colormin": {
- "version": "4.0.3",
- "resolved": "https://registry.nlark.com/postcss-colormin/download/postcss-colormin-4.0.3.tgz",
- "integrity": "sha1-rgYLzpPteUrHEmTwgTLVUJVr04E=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "color": "^3.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-convert-values": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-convert-values/download/postcss-convert-values-4.0.1.tgz?cache=0&sync_timestamp=1621449733448&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-convert-values%2Fdownload%2Fpostcss-convert-values-4.0.1.tgz",
- "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-discard-comments": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-discard-comments/download/postcss-discard-comments-4.0.2.tgz?cache=0&sync_timestamp=1621449558287&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-discard-comments%2Fdownload%2Fpostcss-discard-comments-4.0.2.tgz",
- "integrity": "sha1-H7q9LCRr/2qq15l7KwkY9NevQDM=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "postcss-discard-duplicates": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-discard-duplicates/download/postcss-discard-duplicates-4.0.2.tgz?cache=0&sync_timestamp=1621449558296&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-discard-duplicates%2Fdownload%2Fpostcss-discard-duplicates-4.0.2.tgz",
- "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "postcss-discard-empty": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-discard-empty/download/postcss-discard-empty-4.0.1.tgz?cache=0&sync_timestamp=1621449733074&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-discard-empty%2Fdownload%2Fpostcss-discard-empty-4.0.1.tgz",
- "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "postcss-discard-overridden": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-discard-overridden/download/postcss-discard-overridden-4.0.1.tgz?cache=0&sync_timestamp=1621449732464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-discard-overridden%2Fdownload%2Fpostcss-discard-overridden-4.0.1.tgz",
- "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "postcss-load-config": {
- "version": "2.1.2",
- "resolved": "https://registry.nlark.com/postcss-load-config/download/postcss-load-config-2.1.2.tgz?cache=0&sync_timestamp=1618847231779&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-load-config%2Fdownload%2Fpostcss-load-config-2.1.2.tgz",
- "integrity": "sha1-xepQTyxK7zPHNZo03jVzdyrXUCo=",
- "dev": true,
- "requires": {
- "cosmiconfig": "^5.0.0",
- "import-cwd": "^2.0.0"
- }
- },
- "postcss-loader": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/postcss-loader/download/postcss-loader-3.0.0.tgz",
- "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.1.0",
- "postcss": "^7.0.0",
- "postcss-load-config": "^2.0.0",
- "schema-utils": "^1.0.0"
- },
- "dependencies": {
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- }
- }
- },
- "postcss-merge-longhand": {
- "version": "4.0.11",
- "resolved": "https://registry.nlark.com/postcss-merge-longhand/download/postcss-merge-longhand-4.0.11.tgz?cache=0&sync_timestamp=1621449731452&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-merge-longhand%2Fdownload%2Fpostcss-merge-longhand-4.0.11.tgz",
- "integrity": "sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ=",
- "dev": true,
- "requires": {
- "css-color-names": "0.0.4",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "stylehacks": "^4.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-merge-rules": {
- "version": "4.0.3",
- "resolved": "https://registry.nlark.com/postcss-merge-rules/download/postcss-merge-rules-4.0.3.tgz",
- "integrity": "sha1-NivqT/Wh+Y5AdacTxsslrv75plA=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "caniuse-api": "^3.0.0",
- "cssnano-util-same-parent": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0",
- "vendors": "^1.0.0"
- },
- "dependencies": {
- "postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.nlark.com/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&sync_timestamp=1620752939806&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz",
- "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=",
- "dev": true,
- "requires": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
- }
- }
- }
- },
- "postcss-minify-font-values": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-minify-font-values/download/postcss-minify-font-values-4.0.2.tgz?cache=0&sync_timestamp=1621449734134&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-minify-font-values%2Fdownload%2Fpostcss-minify-font-values-4.0.2.tgz",
- "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-minify-gradients": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-minify-gradients/download/postcss-minify-gradients-4.0.2.tgz",
- "integrity": "sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE=",
- "dev": true,
- "requires": {
- "cssnano-util-get-arguments": "^4.0.0",
- "is-color-stop": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-minify-params": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-minify-params/download/postcss-minify-params-4.0.2.tgz?cache=0&sync_timestamp=1621449735393&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-minify-params%2Fdownload%2Fpostcss-minify-params-4.0.2.tgz",
- "integrity": "sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ=",
- "dev": true,
- "requires": {
- "alphanum-sort": "^1.0.0",
- "browserslist": "^4.0.0",
- "cssnano-util-get-arguments": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "uniqs": "^2.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-minify-selectors": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-minify-selectors/download/postcss-minify-selectors-4.0.2.tgz?cache=0&sync_timestamp=1621449558355&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-minify-selectors%2Fdownload%2Fpostcss-minify-selectors-4.0.2.tgz",
- "integrity": "sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g=",
- "dev": true,
- "requires": {
- "alphanum-sort": "^1.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.nlark.com/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&sync_timestamp=1620752939806&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz",
- "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=",
- "dev": true,
- "requires": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
- }
- }
- }
- },
- "postcss-modules": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/postcss-modules/download/postcss-modules-4.0.0.tgz",
- "integrity": "sha1-K8fydquI8/Gw+t9svXdy1DtfO5s=",
- "dev": true,
- "requires": {
- "generic-names": "^2.0.1",
- "icss-replace-symbols": "^1.1.0",
- "lodash.camelcase": "^4.3.0",
- "postcss-modules-extract-imports": "^3.0.0",
- "postcss-modules-local-by-default": "^4.0.0",
- "postcss-modules-scope": "^3.0.0",
- "postcss-modules-values": "^4.0.0",
- "string-hash": "^1.1.1"
- },
- "dependencies": {
- "icss-utils": {
- "version": "5.1.0",
- "resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-5.1.0.tgz?cache=0&sync_timestamp=1605801291394&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-5.1.0.tgz",
- "integrity": "sha1-xr5oWKvQE9do6YNmrkfiXViHsa4=",
- "dev": true
- },
- "postcss-modules-extract-imports": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-3.0.0.tgz?cache=0&sync_timestamp=1602588245463&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-extract-imports%2Fdownload%2Fpostcss-modules-extract-imports-3.0.0.tgz",
- "integrity": "sha1-zaHwR8CugMl9vijD52pDuIAldB0=",
- "dev": true
- },
- "postcss-modules-local-by-default": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/postcss-modules-local-by-default/download/postcss-modules-local-by-default-4.0.0.tgz",
- "integrity": "sha1-67tU+uFZjuz99pGgKz/zs5ClpRw=",
- "dev": true,
- "requires": {
- "icss-utils": "^5.0.0",
- "postcss-selector-parser": "^6.0.2",
- "postcss-value-parser": "^4.1.0"
- }
- },
- "postcss-modules-scope": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-3.0.0.tgz?cache=0&sync_timestamp=1602593260387&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-3.0.0.tgz",
- "integrity": "sha1-nvMVFFbTu/oSDKRImN/Kby+gHwY=",
- "dev": true,
- "requires": {
- "postcss-selector-parser": "^6.0.4"
- }
- },
- "postcss-modules-values": {
- "version": "4.0.0",
- "resolved": "https://registry.nlark.com/postcss-modules-values/download/postcss-modules-values-4.0.0.tgz",
- "integrity": "sha1-18Xn5ow7s8myfL9Iyguz/7RgLJw=",
- "dev": true,
- "requires": {
- "icss-utils": "^5.0.0"
- }
- }
- }
- },
- "postcss-modules-extract-imports": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-2.0.0.tgz?cache=0&sync_timestamp=1602588245463&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-extract-imports%2Fdownload%2Fpostcss-modules-extract-imports-2.0.0.tgz",
- "integrity": "sha1-gYcZoa4doyX5gyRGsBE27rSTzX4=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.5"
- }
- },
- "postcss-modules-local-by-default": {
- "version": "3.0.3",
- "resolved": "https://registry.nlark.com/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.3.tgz",
- "integrity": "sha1-uxTgzHgnnVBNvcv9fgyiiZP/u7A=",
- "dev": true,
- "requires": {
- "icss-utils": "^4.1.1",
- "postcss": "^7.0.32",
- "postcss-selector-parser": "^6.0.2",
- "postcss-value-parser": "^4.1.0"
- }
- },
- "postcss-modules-scope": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-2.2.0.tgz?cache=0&sync_timestamp=1602593260387&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-2.2.0.tgz",
- "integrity": "sha1-OFyuATzHdD9afXYC0Qc6iequYu4=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.6",
- "postcss-selector-parser": "^6.0.0"
- }
- },
- "postcss-modules-values": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/postcss-modules-values/download/postcss-modules-values-3.0.0.tgz",
- "integrity": "sha1-W1AA1uuuKbQlUwG0o6VFdEI+fxA=",
- "dev": true,
- "requires": {
- "icss-utils": "^4.0.0",
- "postcss": "^7.0.6"
- }
- },
- "postcss-normalize-charset": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-normalize-charset/download/postcss-normalize-charset-4.0.1.tgz?cache=0&sync_timestamp=1621449558308&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-charset%2Fdownload%2Fpostcss-normalize-charset-4.0.1.tgz",
- "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0"
- }
- },
- "postcss-normalize-display-values": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-display-values/download/postcss-normalize-display-values-4.0.2.tgz?cache=0&sync_timestamp=1621449652268&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-display-values%2Fdownload%2Fpostcss-normalize-display-values-4.0.2.tgz",
- "integrity": "sha1-Db4EpM6QY9RmftK+R2u4MMglk1o=",
- "dev": true,
- "requires": {
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-positions": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-positions/download/postcss-normalize-positions-4.0.2.tgz?cache=0&sync_timestamp=1621449826472&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-positions%2Fdownload%2Fpostcss-normalize-positions-4.0.2.tgz",
- "integrity": "sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8=",
- "dev": true,
- "requires": {
- "cssnano-util-get-arguments": "^4.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-repeat-style": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-repeat-style/download/postcss-normalize-repeat-style-4.0.2.tgz?cache=0&sync_timestamp=1621449651580&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-repeat-style%2Fdownload%2Fpostcss-normalize-repeat-style-4.0.2.tgz",
- "integrity": "sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw=",
- "dev": true,
- "requires": {
- "cssnano-util-get-arguments": "^4.0.0",
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-string": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-string/download/postcss-normalize-string-4.0.2.tgz?cache=0&sync_timestamp=1621449646930&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-string%2Fdownload%2Fpostcss-normalize-string-4.0.2.tgz",
- "integrity": "sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw=",
- "dev": true,
- "requires": {
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-timing-functions": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-timing-functions/download/postcss-normalize-timing-functions-4.0.2.tgz?cache=0&sync_timestamp=1621449827577&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-timing-functions%2Fdownload%2Fpostcss-normalize-timing-functions-4.0.2.tgz",
- "integrity": "sha1-jgCcoqOUnNr4rSPmtquZy159KNk=",
- "dev": true,
- "requires": {
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-unicode": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-normalize-unicode/download/postcss-normalize-unicode-4.0.1.tgz?cache=0&sync_timestamp=1621449825612&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-unicode%2Fdownload%2Fpostcss-normalize-unicode-4.0.1.tgz",
- "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-url": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-normalize-url/download/postcss-normalize-url-4.0.1.tgz?cache=0&sync_timestamp=1621449733814&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-url%2Fdownload%2Fpostcss-normalize-url-4.0.1.tgz",
- "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=",
- "dev": true,
- "requires": {
- "is-absolute-url": "^2.0.0",
- "normalize-url": "^3.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-normalize-whitespace": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-normalize-whitespace/download/postcss-normalize-whitespace-4.0.2.tgz?cache=0&sync_timestamp=1621449646853&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-normalize-whitespace%2Fdownload%2Fpostcss-normalize-whitespace-4.0.2.tgz",
- "integrity": "sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-ordered-values": {
- "version": "4.1.2",
- "resolved": "https://registry.nlark.com/postcss-ordered-values/download/postcss-ordered-values-4.1.2.tgz?cache=0&sync_timestamp=1621449735687&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-ordered-values%2Fdownload%2Fpostcss-ordered-values-4.1.2.tgz",
- "integrity": "sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4=",
- "dev": true,
- "requires": {
- "cssnano-util-get-arguments": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-reduce-initial": {
- "version": "4.0.3",
- "resolved": "https://registry.nlark.com/postcss-reduce-initial/download/postcss-reduce-initial-4.0.3.tgz?cache=0&sync_timestamp=1621449728984&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-reduce-initial%2Fdownload%2Fpostcss-reduce-initial-4.0.3.tgz",
- "integrity": "sha1-f9QuvqXpyBRgljniwuhK4nC6SN8=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "caniuse-api": "^3.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0"
- }
- },
- "postcss-reduce-transforms": {
- "version": "4.0.2",
- "resolved": "https://registry.nlark.com/postcss-reduce-transforms/download/postcss-reduce-transforms-4.0.2.tgz?cache=0&sync_timestamp=1621449730895&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-reduce-transforms%2Fdownload%2Fpostcss-reduce-transforms-4.0.2.tgz",
- "integrity": "sha1-F++kBerMbge+NBSlyi0QdGgdTik=",
- "dev": true,
- "requires": {
- "cssnano-util-get-match": "^4.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-selector-parser": {
- "version": "6.0.6",
- "resolved": "https://registry.nlark.com/postcss-selector-parser/download/postcss-selector-parser-6.0.6.tgz?cache=0&sync_timestamp=1620752939806&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-6.0.6.tgz",
- "integrity": "sha1-LFu6gXSsL2mBq2MaQqsO5UrzMuo=",
- "dev": true,
- "requires": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- }
- },
- "postcss-svgo": {
- "version": "4.0.3",
- "resolved": "https://registry.nlark.com/postcss-svgo/download/postcss-svgo-4.0.3.tgz",
- "integrity": "sha1-NDos26yVBdQWJD1Jb3JPOIlMlB4=",
- "dev": true,
- "requires": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "svgo": "^1.0.0"
- },
- "dependencies": {
- "postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-3.3.1.tgz",
- "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
- "dev": true
- }
- }
- },
- "postcss-unique-selectors": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/postcss-unique-selectors/download/postcss-unique-selectors-4.0.1.tgz?cache=0&sync_timestamp=1621449730035&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-unique-selectors%2Fdownload%2Fpostcss-unique-selectors-4.0.1.tgz",
- "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=",
- "dev": true,
- "requires": {
- "alphanum-sort": "^1.0.0",
- "postcss": "^7.0.0",
- "uniqs": "^2.0.0"
- }
- },
- "postcss-value-parser": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-4.1.0.tgz",
- "integrity": "sha1-RD9qIM7WSBor2k+oUypuVdeJoss=",
- "dev": true
- },
- "prelude-ls": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/prelude-ls/download/prelude-ls-1.1.2.tgz",
- "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
- "dev": true
- },
- "prepend-http": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/prepend-http/download/prepend-http-1.0.4.tgz",
- "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
- "dev": true
- },
- "prettier": {
- "version": "1.19.1",
- "resolved": "https://registry.nlark.com/prettier/download/prettier-1.19.1.tgz?cache=0&sync_timestamp=1620594183343&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fprettier%2Fdownload%2Fprettier-1.19.1.tgz",
- "integrity": "sha1-99f1/4qc2HKnvkyhQglZVqYHl8s=",
- "dev": true,
- "optional": true
- },
- "pretty-error": {
- "version": "2.1.2",
- "resolved": "https://registry.nlark.com/pretty-error/download/pretty-error-2.1.2.tgz",
- "integrity": "sha1-von4LYGxyG7I/fvDhQRYgnJ/k7Y=",
- "dev": true,
- "requires": {
- "lodash": "^4.17.20",
- "renderkid": "^2.0.4"
- }
- },
- "process": {
- "version": "0.11.10",
- "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz",
- "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
- "dev": true
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
- "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=",
- "dev": true
- },
- "progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz?cache=0&sync_timestamp=1599054255267&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fprogress%2Fdownload%2Fprogress-2.0.3.tgz",
- "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=",
- "dev": true
- },
- "promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/promise-inflight/download/promise-inflight-1.0.1.tgz",
- "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
- "dev": true
- },
- "proxy-addr": {
- "version": "2.0.6",
- "resolved": "https://registry.nlark.com/proxy-addr/download/proxy-addr-2.0.6.tgz",
- "integrity": "sha1-/cIzZQVEfT8vLGOO0nLK9hS7sr8=",
- "dev": true,
- "requires": {
- "forwarded": "~0.1.2",
- "ipaddr.js": "1.9.1"
- }
- },
- "prr": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/prr/download/prr-1.0.1.tgz",
- "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
- "dev": true
- },
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
- "dev": true
- },
- "psl": {
- "version": "1.8.0",
- "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz",
- "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=",
- "dev": true
- },
- "public-encrypt": {
- "version": "4.0.3",
- "resolved": "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz",
- "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "parse-asn1": "^5.0.0",
- "randombytes": "^2.0.1",
- "safe-buffer": "^5.1.2"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
- "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og=",
- "dev": true
- }
- }
- },
- "pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz",
- "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz",
- "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=",
- "dev": true,
- "requires": {
- "duplexify": "^3.6.0",
- "inherits": "^2.0.3",
- "pump": "^2.0.0"
- },
- "dependencies": {
- "pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz",
- "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- }
- }
- },
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/punycode/download/punycode-2.1.1.tgz",
- "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=",
- "dev": true
- },
- "q": {
- "version": "1.5.1",
- "resolved": "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz?cache=0&sync_timestamp=1599054212574&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fq%2Fdownload%2Fq-1.5.1.tgz",
- "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
- "dev": true
- },
- "qs": {
- "version": "6.5.2",
- "resolved": "https://registry.nlark.com/qs/download/qs-6.5.2.tgz",
- "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=",
- "dev": true
- },
- "query-string": {
- "version": "4.3.4",
- "resolved": "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz",
- "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
- "dev": true,
- "requires": {
- "object-assign": "^4.1.0",
- "strict-uri-encode": "^1.0.0"
- }
- },
- "querystring": {
- "version": "0.2.0",
- "resolved": "https://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz?cache=0&sync_timestamp=1613399913000&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquerystring%2Fdownload%2Fquerystring-0.2.0.tgz",
- "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
- "dev": true
- },
- "querystring-es3": {
- "version": "0.2.1",
- "resolved": "https://registry.nlark.com/querystring-es3/download/querystring-es3-0.2.1.tgz",
- "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
- "dev": true
- },
- "querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npm.taobao.org/querystringify/download/querystringify-2.2.0.tgz",
- "integrity": "sha1-M0WUG0FTy50ILY7uTNogFqmu9/Y=",
- "dev": true
- },
- "randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frandombytes%2Fdownload%2Frandombytes-2.1.0.tgz",
- "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=",
- "dev": true,
- "requires": {
- "safe-buffer": "^5.1.0"
- }
- },
- "randomfill": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/randomfill/download/randomfill-1.0.4.tgz",
- "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=",
- "dev": true,
- "requires": {
- "randombytes": "^2.0.5",
- "safe-buffer": "^5.1.0"
- }
- },
- "range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz",
- "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=",
- "dev": true
- },
- "raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.nlark.com/raw-body/download/raw-body-2.4.0.tgz",
- "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=",
- "dev": true,
- "requires": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- }
- },
- "read-pkg": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-5.2.0.tgz",
- "integrity": "sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w=",
- "dev": true,
- "requires": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^2.5.0",
- "parse-json": "^5.0.0",
- "type-fest": "^0.6.0"
- }
- },
- "readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.nlark.com/readable-stream/download/readable-stream-2.3.7.tgz",
- "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "readdirp": {
- "version": "3.5.0",
- "resolved": "https://registry.nlark.com/readdirp/download/readdirp-3.5.0.tgz",
- "integrity": "sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4=",
- "dev": true,
- "optional": true,
- "requires": {
- "picomatch": "^2.2.1"
- }
- },
- "regenerate": {
- "version": "1.4.2",
- "resolved": "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.2.tgz?cache=0&sync_timestamp=1604218353677&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerate%2Fdownload%2Fregenerate-1.4.2.tgz",
- "integrity": "sha1-uTRtiCfo9aMve6KWN9OYtpAUhIo=",
- "dev": true
- },
- "regenerate-unicode-properties": {
- "version": "8.2.0",
- "resolved": "https://registry.nlark.com/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz",
- "integrity": "sha1-5d5xEdZV57pgwFfb6f83yH5lzew=",
- "dev": true,
- "requires": {
- "regenerate": "^1.4.0"
- }
- },
- "regenerator-runtime": {
- "version": "0.13.7",
- "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz",
- "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U=",
- "dev": true
- },
- "regenerator-transform": {
- "version": "0.14.5",
- "resolved": "https://registry.nlark.com/regenerator-transform/download/regenerator-transform-0.14.5.tgz",
- "integrity": "sha1-yY2hVGg2ccnE3LFuznNlF+G3/rQ=",
- "dev": true,
- "requires": {
- "@babel/runtime": "^7.8.4"
- }
- },
- "regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/regex-not/download/regex-not-1.0.2.tgz",
- "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "regexp.prototype.flags": {
- "version": "1.3.1",
- "resolved": "https://registry.nlark.com/regexp.prototype.flags/download/regexp.prototype.flags-1.3.1.tgz",
- "integrity": "sha1-fvNSro0VnnWMDq3Kb4/LTu8HviY=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- }
- },
- "regexpp": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/regexpp/download/regexpp-2.0.1.tgz",
- "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=",
- "dev": true
- },
- "regexpu-core": {
- "version": "4.7.1",
- "resolved": "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.1.tgz?cache=0&sync_timestamp=1600413461940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexpu-core%2Fdownload%2Fregexpu-core-4.7.1.tgz",
- "integrity": "sha1-LepamgcjMpj78NuR+pq8TG4PitY=",
- "dev": true,
- "requires": {
- "regenerate": "^1.4.0",
- "regenerate-unicode-properties": "^8.2.0",
- "regjsgen": "^0.5.1",
- "regjsparser": "^0.6.4",
- "unicode-match-property-ecmascript": "^1.0.4",
- "unicode-match-property-value-ecmascript": "^1.2.0"
- }
- },
- "regjsgen": {
- "version": "0.5.2",
- "resolved": "https://registry.nlark.com/regjsgen/download/regjsgen-0.5.2.tgz",
- "integrity": "sha1-kv8pX7He7L9uzaslQ9IH6RqjNzM=",
- "dev": true
- },
- "regjsparser": {
- "version": "0.6.9",
- "resolved": "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.9.tgz?cache=0&sync_timestamp=1616544864193&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregjsparser%2Fdownload%2Fregjsparser-0.6.9.tgz",
- "integrity": "sha1-tInu98mizkNydicBFCnPgzpxg+Y=",
- "dev": true,
- "requires": {
- "jsesc": "~0.5.0"
- },
- "dependencies": {
- "jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.nlark.com/jsesc/download/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
- "dev": true
- }
- }
- },
- "relateurl": {
- "version": "0.2.7",
- "resolved": "https://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz",
- "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
- "dev": true
- },
- "remove-trailing-separator": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz",
- "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
- "dev": true
- },
- "renderkid": {
- "version": "2.0.5",
- "resolved": "https://registry.npm.taobao.org/renderkid/download/renderkid-2.0.5.tgz?cache=0&sync_timestamp=1609588663632&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frenderkid%2Fdownload%2Frenderkid-2.0.5.tgz",
- "integrity": "sha1-SDsaxZxmAaswp6WWpZZcq8z90KU=",
- "dev": true,
- "requires": {
- "css-select": "^2.0.2",
- "dom-converter": "^0.2",
- "htmlparser2": "^3.10.1",
- "lodash": "^4.17.20",
- "strip-ansi": "^3.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
- }
- },
- "repeat-element": {
- "version": "1.1.4",
- "resolved": "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.4.tgz",
- "integrity": "sha1-vmgVIIR6tYx1aKx1+/rSjtQtOek=",
- "dev": true
- },
- "repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true
- },
- "request": {
- "version": "2.88.2",
- "resolved": "https://registry.nlark.com/request/download/request-2.88.2.tgz",
- "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=",
- "dev": true,
- "requires": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~2.3.2",
- "har-validator": "~5.1.3",
- "http-signature": "~1.2.0",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "oauth-sign": "~0.9.0",
- "performance-now": "^2.1.0",
- "qs": "~6.5.2",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "~2.5.0",
- "tunnel-agent": "^0.6.0",
- "uuid": "^3.3.2"
- }
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/require-directory/download/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz",
- "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=",
- "dev": true
- },
- "requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz",
- "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
- "dev": true
- },
- "resolve": {
- "version": "1.20.0",
- "resolved": "https://registry.nlark.com/resolve/download/resolve-1.20.0.tgz",
- "integrity": "sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=",
- "dev": true,
- "requires": {
- "is-core-module": "^2.2.0",
- "path-parse": "^1.0.6"
- }
- },
- "resolve-cwd": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/resolve-cwd/download/resolve-cwd-2.0.0.tgz",
- "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
- "dev": true,
- "requires": {
- "resolve-from": "^3.0.0"
- }
- },
- "resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/resolve-from/download/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
- "dev": true
- },
- "resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.nlark.com/resolve-url/download/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
- "dev": true
- },
- "restore-cursor": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/restore-cursor/download/restore-cursor-2.0.0.tgz",
- "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
- "dev": true,
- "requires": {
- "onetime": "^2.0.0",
- "signal-exit": "^3.0.2"
- }
- },
- "ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz",
- "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=",
- "dev": true
- },
- "retry": {
- "version": "0.12.0",
- "resolved": "https://registry.nlark.com/retry/download/retry-0.12.0.tgz",
- "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
- "dev": true
- },
- "rgb-regex": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz",
- "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=",
- "dev": true
- },
- "rgba-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/rgba-regex/download/rgba-regex-1.0.0.tgz",
- "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
- "dev": true
- },
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz?cache=0&sync_timestamp=1614946161596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.7.1.tgz",
- "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.nlark.com/ripemd160/download/ripemd160-2.0.2.tgz",
- "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
- "dev": true,
- "requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1"
- }
- },
- "run-async": {
- "version": "2.4.1",
- "resolved": "https://registry.nlark.com/run-async/download/run-async-2.4.1.tgz",
- "integrity": "sha1-hEDsz5nqPnC9QJ1JqriOEMGJpFU=",
- "dev": true
- },
- "run-queue": {
- "version": "1.0.3",
- "resolved": "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz",
- "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1"
- }
- },
- "rxjs": {
- "version": "6.6.7",
- "resolved": "https://registry.nlark.com/rxjs/download/rxjs-6.6.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frxjs%2Fdownload%2Frxjs-6.6.7.tgz",
- "integrity": "sha1-kKwBisq/SRv2UEQjXVhjxNq4BMk=",
- "dev": true,
- "requires": {
- "tslib": "^1.9.0"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.1.2.tgz",
- "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=",
- "dev": true
- },
- "safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/safe-regex/download/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
- "dev": true,
- "requires": {
- "ret": "~0.1.10"
- }
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.nlark.com/safer-buffer/download/safer-buffer-2.1.2.tgz",
- "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
- "dev": true
- },
- "sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz",
- "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=",
- "dev": true
- },
- "schema-utils": {
- "version": "2.7.1",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.1.tgz",
- "integrity": "sha1-HKTzLRskxZDCA7jnpQvw6kzTlNc=",
- "dev": true,
- "requires": {
- "@types/json-schema": "^7.0.5",
- "ajv": "^6.12.4",
- "ajv-keywords": "^3.5.2"
- }
- },
- "select-hose": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/select-hose/download/select-hose-2.0.0.tgz",
- "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
- "dev": true
- },
- "selfsigned": {
- "version": "1.10.11",
- "resolved": "https://registry.nlark.com/selfsigned/download/selfsigned-1.10.11.tgz",
- "integrity": "sha1-JJKc2Qb+D0S20B+yOZmnOVN6y+k=",
- "dev": true,
- "requires": {
- "node-forge": "^0.10.0"
- }
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.nlark.com/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz",
- "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=",
- "dev": true
- },
- "send": {
- "version": "0.17.1",
- "resolved": "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz",
- "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "destroy": "~1.0.4",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "~1.7.2",
- "mime": "1.6.0",
- "ms": "2.1.1",
- "on-finished": "~2.3.0",
- "range-parser": "~1.2.1",
- "statuses": "~1.5.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- },
- "dependencies": {
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz",
- "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=",
- "dev": true
- },
- "ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.1.tgz",
- "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=",
- "dev": true
- }
- }
- },
- "serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-4.0.0.tgz?cache=0&sync_timestamp=1599742605902&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-4.0.0.tgz",
- "integrity": "sha1-tSXhI4SJpez8Qq+sw/6Z5mb0sao=",
- "dev": true,
- "requires": {
- "randombytes": "^2.1.0"
- }
- },
- "serve-index": {
- "version": "1.9.1",
- "resolved": "https://registry.nlark.com/serve-index/download/serve-index-1.9.1.tgz",
- "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
- "dev": true,
- "requires": {
- "accepts": "~1.3.4",
- "batch": "0.6.1",
- "debug": "2.6.9",
- "escape-html": "~1.0.3",
- "http-errors": "~1.6.2",
- "mime-types": "~2.1.17",
- "parseurl": "~1.3.2"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "http-errors": {
- "version": "1.6.3",
- "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz",
- "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
- "dev": true,
- "requires": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.0",
- "statuses": ">= 1.4.0 < 2"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "setprototypeof": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz",
- "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=",
- "dev": true
- }
- }
- },
- "serve-static": {
- "version": "1.14.1",
- "resolved": "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserve-static%2Fdownload%2Fserve-static-1.14.1.tgz",
- "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=",
- "dev": true,
- "requires": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.17.1"
- }
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/set-blocking/download/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
- },
- "set-value": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/set-value/download/set-value-2.0.1.tgz",
- "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
- "dev": true
- },
- "setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
- "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=",
- "dev": true
- },
- "sha.js": {
- "version": "2.4.11",
- "resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz",
- "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
- "dev": true,
- "requires": {
- "shebang-regex": "^1.0.0"
- }
- },
- "shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
- "dev": true
- },
- "shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.7.2.tgz",
- "integrity": "sha1-Z6fQLHbJ2iT5nSCAj8re0ODgS+I=",
- "dev": true
- },
- "signal-exit": {
- "version": "3.0.3",
- "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz?cache=0&sync_timestamp=1614858571178&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsignal-exit%2Fdownload%2Fsignal-exit-3.0.3.tgz",
- "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw=",
- "dev": true
- },
- "simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.nlark.com/simple-swizzle/download/simple-swizzle-0.2.2.tgz",
- "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.3.1"
- },
- "dependencies": {
- "is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.3.2.tgz",
- "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=",
- "dev": true
- }
- }
- },
- "slash": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/slash/download/slash-2.0.0.tgz",
- "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=",
- "dev": true
- },
- "slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/slice-ansi/download/slice-ansi-2.1.0.tgz?cache=0&sync_timestamp=1618555008681&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fslice-ansi%2Fdownload%2Fslice-ansi-2.1.0.tgz",
- "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
- },
- "dependencies": {
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- }
- }
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz",
- "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=",
- "dev": true,
- "requires": {
- "base": "^0.11.1",
- "debug": "^2.2.0",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "map-cache": "^0.2.2",
- "source-map": "^0.5.6",
- "source-map-resolve": "^0.5.0",
- "use": "^3.1.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "snapdragon-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz",
- "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
- "dev": true,
- "requires": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
- "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.nlark.com/snapdragon-util/download/snapdragon-util-3.0.1.tgz",
- "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
- "dev": true,
- "requires": {
- "kind-of": "^3.2.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "sockjs": {
- "version": "0.3.21",
- "resolved": "https://registry.nlark.com/sockjs/download/sockjs-0.3.21.tgz",
- "integrity": "sha1-s0/7mOeWkwtgoM+hGQTWozmn1Bc=",
- "dev": true,
- "requires": {
- "faye-websocket": "^0.11.3",
- "uuid": "^3.4.0",
- "websocket-driver": "^0.7.4"
- }
- },
- "sockjs-client": {
- "version": "1.5.1",
- "resolved": "https://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.5.1.tgz?cache=0&sync_timestamp=1616686717128&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsockjs-client%2Fdownload%2Fsockjs-client-1.5.1.tgz",
- "integrity": "sha1-JWkI9tWt+5Tau9vQLGY2LMoPnqY=",
- "dev": true,
- "requires": {
- "debug": "^3.2.6",
- "eventsource": "^1.0.7",
- "faye-websocket": "^0.11.3",
- "inherits": "^2.0.4",
- "json3": "^3.3.3",
- "url-parse": "^1.5.1"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.nlark.com/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz",
- "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
- }
- },
- "sort-keys": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/sort-keys/download/sort-keys-1.1.2.tgz",
- "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
- "dev": true,
- "requires": {
- "is-plain-obj": "^1.0.0"
- },
- "dependencies": {
- "is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
- "dev": true
- }
- }
- },
- "source-list-map": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/source-list-map/download/source-list-map-2.0.1.tgz",
- "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=",
- "dev": true
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "source-map-js": {
- "version": "0.6.2",
- "resolved": "https://registry.npm.taobao.org/source-map-js/download/source-map-js-0.6.2.tgz",
- "integrity": "sha1-C7XeYxtBz72mz7qL0FqA79/SOF4=",
- "dev": true
- },
- "source-map-resolve": {
- "version": "0.5.3",
- "resolved": "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz",
- "integrity": "sha1-GQhmvs51U+H48mei7oLGBrVQmho=",
- "dev": true,
- "requires": {
- "atob": "^2.1.2",
- "decode-uri-component": "^0.2.0",
- "resolve-url": "^0.2.1",
- "source-map-url": "^0.4.0",
- "urix": "^0.1.0"
- }
- },
- "source-map-support": {
- "version": "0.5.19",
- "resolved": "https://registry.nlark.com/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz",
- "integrity": "sha1-qYti+G3K9PZzmWSMCFKRq56P7WE=",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "source-map-url": {
- "version": "0.4.1",
- "resolved": "https://registry.nlark.com/source-map-url/download/source-map-url-0.4.1.tgz",
- "integrity": "sha1-CvZmBadFpaL5HPG7+KevvCg97FY=",
- "dev": true
- },
- "sourcemap-codec": {
- "version": "1.4.8",
- "resolved": "https://registry.npm.taobao.org/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha1-6oBL2UhXQC5pktBaOO8a41qatMQ=",
- "dev": true
- },
- "spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz",
- "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=",
- "dev": true,
- "requires": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=",
- "dev": true
- },
- "spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=",
- "dev": true,
- "requires": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-license-ids": {
- "version": "3.0.9",
- "resolved": "https://registry.nlark.com/spdx-license-ids/download/spdx-license-ids-3.0.9.tgz?cache=0&sync_timestamp=1621652583280&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.9.tgz",
- "integrity": "sha1-illRNd75WSvaaXCUdPHL7qfCRn8=",
- "dev": true
- },
- "spdy": {
- "version": "4.0.2",
- "resolved": "https://registry.npm.taobao.org/spdy/download/spdy-4.0.2.tgz",
- "integrity": "sha1-t09GYgOj7aRSwCSSuR+56EonZ3s=",
- "dev": true,
- "requires": {
- "debug": "^4.1.0",
- "handle-thing": "^2.0.0",
- "http-deceiver": "^1.2.7",
- "select-hose": "^2.0.0",
- "spdy-transport": "^3.0.0"
- }
- },
- "spdy-transport": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/spdy-transport/download/spdy-transport-3.0.0.tgz",
- "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=",
- "dev": true,
- "requires": {
- "debug": "^4.1.0",
- "detect-node": "^2.0.4",
- "hpack.js": "^2.1.6",
- "obuf": "^1.1.2",
- "readable-stream": "^3.0.6",
- "wbuf": "^1.7.3"
- },
- "dependencies": {
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.nlark.com/readable-stream/download/readable-stream-3.6.0.tgz",
- "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- }
- }
- },
- "split-string": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz",
- "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.0"
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/sprintf-js/download/sprintf-js-1.0.3.tgz?cache=0&sync_timestamp=1618847174560&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsprintf-js%2Fdownload%2Fsprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
- "dev": true
- },
- "sshpk": {
- "version": "1.16.1",
- "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz",
- "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=",
- "dev": true,
- "requires": {
- "asn1": "~0.2.3",
- "assert-plus": "^1.0.0",
- "bcrypt-pbkdf": "^1.0.0",
- "dashdash": "^1.12.0",
- "ecc-jsbn": "~0.1.1",
- "getpass": "^0.1.1",
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.0.2",
- "tweetnacl": "~0.14.0"
- }
- },
- "ssri": {
- "version": "6.0.2",
- "resolved": "https://registry.nlark.com/ssri/download/ssri-6.0.2.tgz?cache=0&sync_timestamp=1621364626710&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fssri%2Fdownload%2Fssri-6.0.2.tgz",
- "integrity": "sha1-FXk5E08gRk5zAd26PpD/qPdyisU=",
- "dev": true,
- "requires": {
- "figgy-pudding": "^3.5.1"
- }
- },
- "stable": {
- "version": "0.1.8",
- "resolved": "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz",
- "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=",
- "dev": true
- },
- "stackframe": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/stackframe/download/stackframe-1.2.0.tgz",
- "integrity": "sha1-UkKUktY8YuuYmATBFVLj0i53kwM=",
- "dev": true
- },
- "static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
- "dev": true,
- "requires": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1609654014762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
- "dev": true
- },
- "stream-browserify": {
- "version": "2.0.2",
- "resolved": "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz",
- "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=",
- "dev": true,
- "requires": {
- "inherits": "~2.0.1",
- "readable-stream": "^2.0.2"
- }
- },
- "stream-each": {
- "version": "1.2.3",
- "resolved": "https://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz",
- "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "stream-shift": "^1.0.0"
- }
- },
- "stream-http": {
- "version": "2.8.3",
- "resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz?cache=0&sync_timestamp=1618430946341&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-http%2Fdownload%2Fstream-http-2.8.3.tgz",
- "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
- "dev": true,
- "requires": {
- "builtin-status-codes": "^3.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.3.6",
- "to-arraybuffer": "^1.0.0",
- "xtend": "^4.0.0"
- }
- },
- "stream-shift": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz",
- "integrity": "sha1-1wiCgVWasneEJCebCHfaPDktWj0=",
- "dev": true
- },
- "strict-uri-encode": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz",
- "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
- "dev": true
- },
- "string-hash": {
- "version": "1.1.3",
- "resolved": "https://registry.npm.taobao.org/string-hash/download/string-hash-1.1.3.tgz",
- "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
- "dev": true
- },
- "string-width": {
- "version": "4.2.2",
- "resolved": "https://registry.nlark.com/string-width/download/string-width-4.2.2.tgz",
- "integrity": "sha1-2v1PlVmnWFz7pSnGoKT3NIjr1MU=",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.4",
- "resolved": "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.4.tgz?cache=0&sync_timestamp=1614127461586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimend%2Fdownload%2Fstring.prototype.trimend-1.0.4.tgz",
- "integrity": "sha1-51rpDClCxjUEaGwYsoe0oLGkX4A=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- }
- },
- "string.prototype.trimstart": {
- "version": "1.0.4",
- "resolved": "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.4.tgz?cache=0&sync_timestamp=1614127357785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimstart%2Fdownload%2Fstring.prototype.trimstart-1.0.4.tgz",
- "integrity": "sha1-s2OZr0qymZtMnGSL16P7K7Jv7u0=",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz",
- "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-6.0.0.tgz",
- "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-5.0.0.tgz",
- "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=",
- "dev": true
- }
- }
- },
- "strip-eof": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/strip-eof/download/strip-eof-1.0.0.tgz",
- "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
- "dev": true
- },
- "strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/strip-final-newline/download/strip-final-newline-2.0.0.tgz",
- "integrity": "sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0=",
- "dev": true
- },
- "strip-indent": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/strip-indent/download/strip-indent-2.0.0.tgz?cache=0&sync_timestamp=1620053310624&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-indent%2Fdownload%2Fstrip-indent-2.0.0.tgz",
- "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
- "dev": true
- },
- "strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-3.1.1.tgz",
- "integrity": "sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY=",
- "dev": true
- },
- "stylehacks": {
- "version": "4.0.3",
- "resolved": "https://registry.nlark.com/stylehacks/download/stylehacks-4.0.3.tgz?cache=0&sync_timestamp=1621449652268&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstylehacks%2Fdownload%2Fstylehacks-4.0.3.tgz",
- "integrity": "sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU=",
- "dev": true,
- "requires": {
- "browserslist": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0"
- },
- "dependencies": {
- "postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.nlark.com/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&sync_timestamp=1620752939806&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz",
- "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=",
- "dev": true,
- "requires": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
- }
- }
- }
- },
- "stylus": {
- "version": "0.54.8",
- "resolved": "https://registry.nlark.com/stylus/download/stylus-0.54.8.tgz",
- "integrity": "sha1-PaPmWWa8Vnp7BEv+DuzmU+CZ0Uc=",
- "dev": true,
- "requires": {
- "css-parse": "~2.0.0",
- "debug": "~3.1.0",
- "glob": "^7.1.6",
- "mkdirp": "~1.0.4",
- "safer-buffer": "^2.1.2",
- "sax": "~1.2.4",
- "semver": "^6.3.0",
- "source-map": "^0.7.3"
- },
- "dependencies": {
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1618847042350&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz",
- "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-1.0.4.tgz",
- "integrity": "sha1-PrXtYmInVteaXw4qIh3+utdcL34=",
- "dev": true
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433950466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.7.3.tgz",
- "integrity": "sha1-UwL4FpAxc1ImVECS5kmB91F1A4M=",
- "dev": true
- }
- }
- },
- "stylus-loader": {
- "version": "3.0.2",
- "resolved": "https://registry.nlark.com/stylus-loader/download/stylus-loader-3.0.2.tgz",
- "integrity": "sha1-J6cGQgsFo44DjnyssVNXjUUFE8Y=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.0.2",
- "lodash.clonedeep": "^4.5.0",
- "when": "~3.6.x"
- }
- },
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz",
- "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "svg-tags": {
- "version": "1.0.0",
- "resolved": "https://registry.nlark.com/svg-tags/download/svg-tags-1.0.0.tgz",
- "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
- "dev": true
- },
- "svgo": {
- "version": "1.3.2",
- "resolved": "https://registry.nlark.com/svgo/download/svgo-1.3.2.tgz",
- "integrity": "sha1-ttxRHAYzRsnkFbgeQ0ARRbltQWc=",
- "dev": true,
- "requires": {
- "chalk": "^2.4.1",
- "coa": "^2.0.2",
- "css-select": "^2.0.0",
- "css-select-base-adapter": "^0.1.1",
- "css-tree": "1.0.0-alpha.37",
- "csso": "^4.0.2",
- "js-yaml": "^3.13.1",
- "mkdirp": "~0.5.1",
- "object.values": "^1.1.0",
- "sax": "~1.2.4",
- "stable": "^0.1.8",
- "unquote": "~1.1.1",
- "util.promisify": "~1.0.0"
- }
- },
- "table": {
- "version": "5.4.6",
- "resolved": "https://registry.nlark.com/table/download/table-5.4.6.tgz",
- "integrity": "sha1-EpLRlQDOP4YFOwXw6Ofko7shB54=",
- "dev": true,
- "requires": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
- },
- "dependencies": {
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.nlark.com/emoji-regex/download/emoji-regex-7.0.3.tgz",
- "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/string-width/download/string-width-3.1.0.tgz",
- "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "tapable": {
- "version": "1.1.3",
- "resolved": "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz",
- "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=",
- "dev": true
- },
- "terser": {
- "version": "4.8.0",
- "resolved": "https://registry.nlark.com/terser/download/terser-4.8.0.tgz",
- "integrity": "sha1-YwVjQ9fHC7KfOvZlhlpG/gOg3xc=",
- "dev": true,
- "requires": {
- "commander": "^2.20.0",
- "source-map": "~0.6.1",
- "source-map-support": "~0.5.12"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "terser-webpack-plugin": {
- "version": "1.4.5",
- "resolved": "https://registry.nlark.com/terser-webpack-plugin/download/terser-webpack-plugin-1.4.5.tgz?cache=0&sync_timestamp=1620830646135&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-1.4.5.tgz",
- "integrity": "sha1-oheu+uozDnNP+sthIOwfoxLWBAs=",
- "dev": true,
- "requires": {
- "cacache": "^12.0.2",
- "find-cache-dir": "^2.1.0",
- "is-wsl": "^1.1.0",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^4.0.0",
- "source-map": "^0.6.1",
- "terser": "^4.1.2",
- "webpack-sources": "^1.4.0",
- "worker-farm": "^1.7.0"
- },
- "dependencies": {
- "find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz",
- "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
- }
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz",
- "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
- "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz",
- "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=",
- "dev": true,
- "requires": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/p-locate/download/p-locate-3.0.0.tgz",
- "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-3.0.0.tgz",
- "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0"
- }
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz",
- "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.nlark.com/text-table/download/text-table-0.2.0.tgz?cache=0&sync_timestamp=1618847142316&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftext-table%2Fdownload%2Ftext-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
- "dev": true
- },
- "thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.nlark.com/thenify/download/thenify-3.3.1.tgz",
- "integrity": "sha1-iTLmhqQGYDigFt2eLKRq3Zg4qV8=",
- "dev": true,
- "requires": {
- "any-promise": "^1.0.0"
- }
- },
- "thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.nlark.com/thenify-all/download/thenify-all-1.6.0.tgz",
- "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
- "dev": true,
- "requires": {
- "thenify": ">= 3.1.0 < 4"
- }
- },
- "thread-loader": {
- "version": "2.1.3",
- "resolved": "https://registry.nlark.com/thread-loader/download/thread-loader-2.1.3.tgz",
- "integrity": "sha1-y9LBOfwrLebp0o9iKGq3cMGsvdo=",
- "dev": true,
- "requires": {
- "loader-runner": "^2.3.1",
- "loader-utils": "^1.1.0",
- "neo-async": "^2.6.0"
- }
- },
- "through": {
- "version": "2.3.8",
- "resolved": "https://registry.nlark.com/through/download/through-2.3.8.tgz",
- "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
- "dev": true
- },
- "through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz",
- "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=",
- "dev": true,
- "requires": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
- }
- },
- "thunky": {
- "version": "1.1.0",
- "resolved": "https://registry.nlark.com/thunky/download/thunky-1.1.0.tgz",
- "integrity": "sha1-Wrr3FKlAXbBQRzK7zNLO3Z75U30=",
- "dev": true
- },
- "timers-browserify": {
- "version": "2.0.12",
- "resolved": "https://registry.nlark.com/timers-browserify/download/timers-browserify-2.0.12.tgz",
- "integrity": "sha1-RKRcEfv0B/NPl7zNFXfGUjYbAO4=",
- "dev": true,
- "requires": {
- "setimmediate": "^1.0.4"
- }
- },
- "timsort": {
- "version": "0.3.0",
- "resolved": "https://registry.nlark.com/timsort/download/timsort-0.3.0.tgz",
- "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
- "dev": true
- },
- "tmp": {
- "version": "0.0.33",
- "resolved": "https://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz",
- "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
- "dev": true,
- "requires": {
- "os-tmpdir": "~1.0.2"
- }
- },
- "to-arraybuffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz",
- "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
- "dev": true
- },
- "to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/to-fast-properties/download/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
- },
- "to-object-path": {
- "version": "0.3.0",
- "resolved": "https://registry.nlark.com/to-object-path/download/to-object-path-0.3.0.tgz",
- "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.nlark.com/kind-of/download/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.nlark.com/to-regex/download/to-regex-3.0.2.tgz",
- "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=",
- "dev": true,
- "requires": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/to-regex-range/download/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
- }
- },
- "toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz",
- "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=",
- "dev": true
- },
- "toposort": {
- "version": "1.0.7",
- "resolved": "https://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz",
- "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
- "dev": true
- },
- "tough-cookie": {
- "version": "2.5.0",
- "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz",
- "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=",
- "dev": true,
- "requires": {
- "psl": "^1.1.28",
- "punycode": "^2.1.1"
- }
- },
- "tryer": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/tryer/download/tryer-1.0.1.tgz",
- "integrity": "sha1-8shUBoALmw90yfdGW4HqrSQSUvg=",
- "dev": true
- },
- "ts-pnp": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/ts-pnp/download/ts-pnp-1.2.0.tgz",
- "integrity": "sha1-pQCtCEsHmPHDBxrzkeZZEshrypI=",
- "dev": true
- },
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.nlark.com/tslib/download/tslib-1.14.1.tgz?cache=0&sync_timestamp=1618846758811&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftslib%2Fdownload%2Ftslib-1.14.1.tgz",
- "integrity": "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=",
- "dev": true
- },
- "tty-browserify": {
- "version": "0.0.0",
- "resolved": "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz",
- "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
- "dev": true
- },
- "tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.nlark.com/tunnel-agent/download/tunnel-agent-0.6.0.tgz",
- "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
- "dev": true,
- "requires": {
- "safe-buffer": "^5.0.1"
- }
- },
- "tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz",
- "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
- "dev": true
- },
- "type-check": {
- "version": "0.3.2",
- "resolved": "https://registry.nlark.com/type-check/download/type-check-0.3.2.tgz",
- "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
- "dev": true,
- "requires": {
- "prelude-ls": "~1.1.2"
- }
- },
- "type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.nlark.com/type-fest/download/type-fest-0.6.0.tgz?cache=0&sync_timestamp=1621402446336&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.6.0.tgz",
- "integrity": "sha1-jSojcNPfiG61yQraHFv2GIrPg4s=",
- "dev": true
- },
- "type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.nlark.com/type-is/download/type-is-1.6.18.tgz",
- "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
- "dev": true,
- "requires": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- }
- },
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
- "uglify-js": {
- "version": "3.4.10",
- "resolved": "https://registry.nlark.com/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1622033899313&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz",
- "integrity": "sha1-mtlWPY6zrN+404WX0q8dgV9qdV8=",
- "dev": true,
- "requires": {
- "commander": "~2.19.0",
- "source-map": "~0.6.1"
- },
- "dependencies": {
- "commander": {
- "version": "2.19.0",
- "resolved": "https://registry.nlark.com/commander/download/commander-2.19.0.tgz?cache=0&sync_timestamp=1622446257852&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz",
- "integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "unbox-primitive": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/unbox-primitive/download/unbox-primitive-1.0.1.tgz",
- "integrity": "sha1-CF4hViXsMWJXTciFmr7nilmxRHE=",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1",
- "has-bigints": "^1.0.1",
- "has-symbols": "^1.0.2",
- "which-boxed-primitive": "^1.0.2"
- }
- },
- "unicode-canonical-property-names-ecmascript": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
- "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=",
- "dev": true
- },
- "unicode-match-property-ecmascript": {
- "version": "1.0.4",
- "resolved": "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz",
- "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=",
- "dev": true,
- "requires": {
- "unicode-canonical-property-names-ecmascript": "^1.0.4",
- "unicode-property-aliases-ecmascript": "^1.0.4"
- }
- },
- "unicode-match-property-value-ecmascript": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz",
- "integrity": "sha1-DZH2AO7rMJaqlisdb8iIduZOpTE=",
- "dev": true
- },
- "unicode-property-aliases-ecmascript": {
- "version": "1.1.0",
- "resolved": "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz",
- "integrity": "sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ=",
- "dev": true
- },
- "union-value": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/union-value/download/union-value-1.0.1.tgz",
- "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- }
- },
- "uniq": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/uniq/download/uniq-1.0.1.tgz",
- "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
- "dev": true
- },
- "uniqs": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/uniqs/download/uniqs-2.0.0.tgz",
- "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
- "dev": true
- },
- "unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz",
- "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=",
- "dev": true,
- "requires": {
- "unique-slug": "^2.0.0"
- }
- },
- "unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.nlark.com/unique-slug/download/unique-slug-2.0.2.tgz",
- "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=",
- "dev": true,
- "requires": {
- "imurmurhash": "^0.1.4"
- }
- },
- "universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&sync_timestamp=1603180037346&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz",
- "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=",
- "dev": true
- },
- "unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
- "dev": true
- },
- "unquote": {
- "version": "1.1.1",
- "resolved": "https://registry.nlark.com/unquote/download/unquote-1.1.1.tgz",
- "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
- "dev": true
- },
- "unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
- "dev": true,
- "requires": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "dev": true,
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
- "dev": true
- }
- }
- },
- "upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz",
- "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=",
- "dev": true
- },
- "upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.nlark.com/upper-case/download/upper-case-1.1.3.tgz",
- "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
- "dev": true
- },
- "uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.4.1.tgz?cache=0&sync_timestamp=1610237742114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furi-js%2Fdownload%2Furi-js-4.4.1.tgz",
- "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.nlark.com/urix/download/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
- "dev": true
- },
- "url": {
- "version": "0.11.0",
- "resolved": "https://registry.nlark.com/url/download/url-0.11.0.tgz?cache=0&sync_timestamp=1618847135337&other_urls=https%3A%2F%2Fregistry.nlark.com%2Furl%2Fdownload%2Furl-0.11.0.tgz",
- "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
- "dev": true,
- "requires": {
- "punycode": "1.3.2",
- "querystring": "0.2.0"
- },
- "dependencies": {
- "punycode": {
- "version": "1.3.2",
- "resolved": "https://registry.nlark.com/punycode/download/punycode-1.3.2.tgz",
- "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
- "dev": true
- }
- }
- },
- "url-loader": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/url-loader/download/url-loader-2.3.0.tgz",
- "integrity": "sha1-4OLvZY8APvuMpBsPP/v3a6uIZYs=",
- "dev": true,
- "requires": {
- "loader-utils": "^1.2.3",
- "mime": "^2.4.4",
- "schema-utils": "^2.5.0"
- }
- },
- "url-parse": {
- "version": "1.5.1",
- "resolved": "https://registry.npm.taobao.org/url-parse/download/url-parse-1.5.1.tgz?cache=0&sync_timestamp=1613659652440&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furl-parse%2Fdownload%2Furl-parse-1.5.1.tgz",
- "integrity": "sha1-1fqYkK+KXh8nSiyYN2UQ9kJfbjs=",
- "dev": true,
- "requires": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
- "use": {
- "version": "3.1.1",
- "resolved": "https://registry.nlark.com/use/download/use-3.1.1.tgz",
- "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=",
- "dev": true
- },
- "util": {
- "version": "0.11.1",
- "resolved": "https://registry.nlark.com/util/download/util-0.11.1.tgz?cache=0&sync_timestamp=1622213047493&other_urls=https%3A%2F%2Fregistry.nlark.com%2Futil%2Fdownload%2Futil-0.11.1.tgz",
- "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- }
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/util-deprecate/download/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
- },
- "util.promisify": {
- "version": "1.0.1",
- "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.1.tgz?cache=0&sync_timestamp=1610159895694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil.promisify%2Fdownload%2Futil.promisify-1.0.1.tgz",
- "integrity": "sha1-a693dLgO6w91INi4HQeYKlmruu4=",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.2",
- "has-symbols": "^1.0.1",
- "object.getownpropertydescriptors": "^2.1.0"
- }
- },
- "utila": {
- "version": "0.4.0",
- "resolved": "https://registry.nlark.com/utila/download/utila-0.4.0.tgz",
- "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
- "dev": true
- },
- "utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/utils-merge/download/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
- "dev": true
- },
- "uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.nlark.com/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1622213185460&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz",
- "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=",
- "dev": true
- },
- "v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.nlark.com/v8-compile-cache/download/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha1-LeGWGMZtwkfc+2+ZM4A12CRaLO4=",
- "dev": true
- },
- "validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.nlark.com/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=",
- "dev": true,
- "requires": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "vary": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/vary/download/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
- "dev": true
- },
- "vendors": {
- "version": "1.0.4",
- "resolved": "https://registry.nlark.com/vendors/download/vendors-1.0.4.tgz",
- "integrity": "sha1-4rgApT56Kbk1BsPPQRANFsTErY4=",
- "dev": true
- },
- "verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz",
- "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
- "dev": true,
- "requires": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- }
- },
- "vm-browserify": {
- "version": "1.1.2",
- "resolved": "https://registry.nlark.com/vm-browserify/download/vm-browserify-1.1.2.tgz",
- "integrity": "sha1-eGQcSIuObKkadfUR56OzKobl3aA=",
- "dev": true
- },
- "vue": {
- "version": "3.0.11",
- "resolved": "https://registry.nlark.com/vue/download/vue-3.0.11.tgz?cache=0&sync_timestamp=1622239280610&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue%2Fdownload%2Fvue-3.0.11.tgz",
- "integrity": "sha1-yC+VlMv03MhpJB1MjdPgjZqPS18=",
- "requires": {
- "@vue/compiler-dom": "3.0.11",
- "@vue/runtime-dom": "3.0.11",
- "@vue/shared": "3.0.11"
- }
- },
- "vue-eslint-parser": {
- "version": "7.6.0",
- "resolved": "https://registry.nlark.com/vue-eslint-parser/download/vue-eslint-parser-7.6.0.tgz",
- "integrity": "sha1-AeoaKTL1gf8kQzZWXXEoAfj3JWE=",
- "dev": true,
- "requires": {
- "debug": "^4.1.1",
- "eslint-scope": "^5.0.0",
- "eslint-visitor-keys": "^1.1.0",
- "espree": "^6.2.1",
- "esquery": "^1.4.0",
- "lodash": "^4.17.15"
- },
- "dependencies": {
- "eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-5.1.1.tgz?cache=0&sync_timestamp=1599933693172&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-5.1.1.tgz",
- "integrity": "sha1-54blmmbLkrP2wfsNUIqrF0hI9Iw=",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- }
- }
- }
- },
- "vue-hot-reload-api": {
- "version": "2.3.4",
- "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz",
- "integrity": "sha1-UylVzB6yCKPZkLOp+acFdGV+CPI=",
- "dev": true
- },
- "vue-loader": {
- "version": "15.9.7",
- "resolved": "https://registry.nlark.com/vue-loader/download/vue-loader-15.9.7.tgz",
- "integrity": "sha1-FbBXdcPgw4QHZ5OTws5t9nOwEEQ=",
- "dev": true,
- "requires": {
- "@vue/component-compiler-utils": "^3.1.0",
- "hash-sum": "^1.0.2",
- "loader-utils": "^1.1.0",
- "vue-hot-reload-api": "^2.3.0",
- "vue-style-loader": "^4.1.0"
- },
- "dependencies": {
- "hash-sum": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
- "dev": true
- }
- }
- },
- "vue-loader-v16": {
- "version": "npm:vue-loader@16.2.0",
- "resolved": "https://registry.nlark.com/vue-loader/download/vue-loader-16.2.0.tgz",
- "integrity": "sha1-BGpTMI3Ufljv4g3ewe3sAnzjtG4=",
- "dev": true,
- "optional": true,
- "requires": {
- "chalk": "^4.1.0",
- "hash-sum": "^2.0.0",
- "loader-utils": "^2.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
- "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
- "dev": true,
- "optional": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "4.1.1",
- "resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.1.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.1.tgz",
- "integrity": "sha1-yAs/qyi/Y3HmhjMl7uZ+YYt35q0=",
- "dev": true,
- "optional": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
- "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
- "dev": true,
- "optional": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
- "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
- "dev": true,
- "optional": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1618559676170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
- "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
- "dev": true,
- "optional": true
- },
- "loader-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/loader-utils/download/loader-utils-2.0.0.tgz?cache=0&sync_timestamp=1618846812625&other_urls=https%3A%2F%2Fregistry.nlark.com%2Floader-utils%2Fdownload%2Floader-utils-2.0.0.tgz",
- "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
- "dev": true,
- "optional": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^2.1.2"
- }
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
- "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
- "dev": true,
- "optional": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "vue-router": {
- "version": "4.0.8",
- "resolved": "https://registry.nlark.com/vue-router/download/vue-router-4.0.8.tgz?cache=0&sync_timestamp=1620899536020&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue-router%2Fdownload%2Fvue-router-4.0.8.tgz",
- "integrity": "sha1-VdQpCjEiRE7byRo80kkrsdDO9JQ=",
- "requires": {
- "@vue/devtools-api": "^6.0.0-beta.10"
- }
- },
- "vue-style-loader": {
- "version": "4.1.3",
- "resolved": "https://registry.nlark.com/vue-style-loader/download/vue-style-loader-4.1.3.tgz",
- "integrity": "sha1-bVWGOlH6dXqyTonZNxRlByqnvDU=",
- "dev": true,
- "requires": {
- "hash-sum": "^1.0.2",
- "loader-utils": "^1.0.2"
- },
- "dependencies": {
- "hash-sum": {
- "version": "1.0.2",
- "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
- "dev": true
- }
- }
- },
- "vue-template-es2015-compiler": {
- "version": "1.9.1",
- "resolved": "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz",
- "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
- "dev": true
- },
- "vuex": {
- "version": "4.0.1",
- "resolved": "https://registry.nlark.com/vuex/download/vuex-4.0.1.tgz",
- "integrity": "sha1-6DxUHW8xFzlp76uyxdHEZbaCiH4=",
- "requires": {
- "@vue/devtools-api": "^6.0.0-beta.11"
- }
- },
- "watchpack": {
- "version": "1.7.5",
- "resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437868630&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz",
- "integrity": "sha1-EmfmxV4Lm1vkTCAjrtVDeiwmxFM=",
- "dev": true,
- "requires": {
- "chokidar": "^3.4.1",
- "graceful-fs": "^4.1.2",
- "neo-async": "^2.5.0",
- "watchpack-chokidar2": "^2.0.1"
- }
- },
- "watchpack-chokidar2": {
- "version": "2.0.1",
- "resolved": "https://registry.nlark.com/watchpack-chokidar2/download/watchpack-chokidar2-2.0.1.tgz",
- "integrity": "sha1-OFAAcu5uzmbzdpk2lQ6hdxvhyVc=",
- "dev": true,
- "optional": true,
- "requires": {
- "chokidar": "^2.1.8"
- },
- "dependencies": {
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/anymatch/download/anymatch-2.0.0.tgz",
- "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
- "dev": true,
- "optional": true,
- "requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "optional": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.nlark.com/binary-extensions/download/binary-extensions-1.13.1.tgz",
- "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=",
- "dev": true,
- "optional": true
- },
- "chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.nlark.com/chokidar/download/chokidar-2.1.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz",
- "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=",
- "dev": true,
- "optional": true,
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- }
- },
- "fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz",
- "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=",
- "dev": true,
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
- },
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1620073321855&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "dev": true,
- "optional": true,
- "requires": {
- "binary-extensions": "^1.0.0"
- }
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.nlark.com/readdirp/download/readdirp-2.2.1.tgz",
- "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
- "dev": true,
- "optional": true,
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- }
- }
- }
- },
- "wbuf": {
- "version": "1.7.3",
- "resolved": "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz",
- "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=",
- "dev": true,
- "requires": {
- "minimalistic-assert": "^1.0.0"
- }
- },
- "wcwidth": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/wcwidth/download/wcwidth-1.0.1.tgz",
- "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
- "dev": true,
- "requires": {
- "defaults": "^1.0.3"
- }
- },
- "webpack": {
- "version": "4.46.0",
- "resolved": "https://registry.nlark.com/webpack/download/webpack-4.46.0.tgz?cache=0&sync_timestamp=1622151377755&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack%2Fdownload%2Fwebpack-4.46.0.tgz",
- "integrity": "sha1-v5tEBOogoHNgXgoBHRiNd8tq1UI=",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/wasm-edit": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "acorn": "^6.4.1",
- "ajv": "^6.10.2",
- "ajv-keywords": "^3.4.1",
- "chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^4.5.0",
- "eslint-scope": "^4.0.3",
- "json-parse-better-errors": "^1.0.2",
- "loader-runner": "^2.4.0",
- "loader-utils": "^1.2.3",
- "memory-fs": "^0.4.1",
- "micromatch": "^3.1.10",
- "mkdirp": "^0.5.3",
- "neo-async": "^2.6.1",
- "node-libs-browser": "^2.2.1",
- "schema-utils": "^1.0.0",
- "tapable": "^1.1.3",
- "terser-webpack-plugin": "^1.4.3",
- "watchpack": "^1.7.4",
- "webpack-sources": "^1.4.1"
- },
- "dependencies": {
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- }
- }
- },
- "webpack-bundle-analyzer": {
- "version": "3.9.0",
- "resolved": "https://registry.nlark.com/webpack-bundle-analyzer/download/webpack-bundle-analyzer-3.9.0.tgz?cache=0&sync_timestamp=1621259099265&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack-bundle-analyzer%2Fdownload%2Fwebpack-bundle-analyzer-3.9.0.tgz",
- "integrity": "sha1-9vlNsQj7V05BWtMT3kGicH0z7zw=",
- "dev": true,
- "requires": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1",
- "bfj": "^6.1.1",
- "chalk": "^2.4.1",
- "commander": "^2.18.0",
- "ejs": "^2.6.1",
- "express": "^4.16.3",
- "filesize": "^3.6.1",
- "gzip-size": "^5.0.0",
- "lodash": "^4.17.19",
- "mkdirp": "^0.5.1",
- "opener": "^1.5.1",
- "ws": "^6.0.0"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.nlark.com/acorn/download/acorn-7.4.1.tgz",
- "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
- "dev": true
- }
- }
- },
- "webpack-chain": {
- "version": "6.5.1",
- "resolved": "https://registry.npm.taobao.org/webpack-chain/download/webpack-chain-6.5.1.tgz",
- "integrity": "sha1-TycoTLu2N+PI+970Pu9YjU2GEgY=",
- "dev": true,
- "requires": {
- "deepmerge": "^1.5.2",
- "javascript-stringify": "^2.0.1"
- }
- },
- "webpack-dev-middleware": {
- "version": "3.7.3",
- "resolved": "https://registry.nlark.com/webpack-dev-middleware/download/webpack-dev-middleware-3.7.3.tgz?cache=0&sync_timestamp=1621437646566&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack-dev-middleware%2Fdownload%2Fwebpack-dev-middleware-3.7.3.tgz",
- "integrity": "sha1-Bjk3KxQyYuK4SrldO5GnWXBhwsU=",
- "dev": true,
- "requires": {
- "memory-fs": "^0.4.1",
- "mime": "^2.4.4",
- "mkdirp": "^0.5.1",
- "range-parser": "^1.2.1",
- "webpack-log": "^2.0.0"
- }
- },
- "webpack-dev-server": {
- "version": "3.11.2",
- "resolved": "https://registry.nlark.com/webpack-dev-server/download/webpack-dev-server-3.11.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack-dev-server%2Fdownload%2Fwebpack-dev-server-3.11.2.tgz",
- "integrity": "sha1-aV687Xakkp8NXef9c/r+GF/jNwg=",
- "dev": true,
- "requires": {
- "ansi-html": "0.0.7",
- "bonjour": "^3.5.0",
- "chokidar": "^2.1.8",
- "compression": "^1.7.4",
- "connect-history-api-fallback": "^1.6.0",
- "debug": "^4.1.1",
- "del": "^4.1.1",
- "express": "^4.17.1",
- "html-entities": "^1.3.1",
- "http-proxy-middleware": "0.19.1",
- "import-local": "^2.0.0",
- "internal-ip": "^4.3.0",
- "ip": "^1.1.5",
- "is-absolute-url": "^3.0.3",
- "killable": "^1.0.1",
- "loglevel": "^1.6.8",
- "opn": "^5.5.0",
- "p-retry": "^3.0.1",
- "portfinder": "^1.0.26",
- "schema-utils": "^1.0.0",
- "selfsigned": "^1.10.8",
- "semver": "^6.3.0",
- "serve-index": "^1.9.1",
- "sockjs": "^0.3.21",
- "sockjs-client": "^1.5.0",
- "spdy": "^4.0.2",
- "strip-ansi": "^3.0.1",
- "supports-color": "^6.1.0",
- "url": "^0.11.0",
- "webpack-dev-middleware": "^3.7.2",
- "webpack-log": "^2.0.0",
- "ws": "^6.2.1",
- "yargs": "^13.3.2"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.nlark.com/anymatch/download/anymatch-2.0.0.tgz",
- "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
- "dev": true,
- "requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.nlark.com/binary-extensions/download/binary-extensions-1.13.1.tgz",
- "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=",
- "dev": true
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.nlark.com/camelcase/download/camelcase-5.3.1.tgz",
- "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=",
- "dev": true
- },
- "chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.nlark.com/chokidar/download/chokidar-2.1.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz",
- "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=",
- "dev": true,
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- }
- },
- "cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.nlark.com/cliui/download/cliui-5.0.0.tgz",
- "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=",
- "dev": true,
- "requires": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
- "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.nlark.com/emoji-regex/download/emoji-regex-7.0.3.tgz",
- "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=",
- "dev": true
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz",
- "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz",
- "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=",
- "dev": true,
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
- },
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1620073321855&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "http-proxy-middleware": {
- "version": "0.19.1",
- "resolved": "https://registry.nlark.com/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz?cache=0&sync_timestamp=1620409720336&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-0.19.1.tgz",
- "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=",
- "dev": true,
- "requires": {
- "http-proxy": "^1.17.0",
- "is-glob": "^4.0.0",
- "lodash": "^4.17.11",
- "micromatch": "^3.1.10"
- }
- },
- "is-absolute-url": {
- "version": "3.0.3",
- "resolved": "https://registry.nlark.com/is-absolute-url/download/is-absolute-url-3.0.3.tgz",
- "integrity": "sha1-lsaiK2ojkpsR6gr7GDbDatSl1pg=",
- "dev": true
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "dev": true,
- "requires": {
- "binary-extensions": "^1.0.0"
- }
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
- "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/p-locate/download/p-locate-3.0.0.tgz",
- "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.nlark.com/readdirp/download/readdirp-2.2.1.tgz",
- "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- }
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
- "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.nlark.com/string-width/download/string-width-3.1.0.tgz",
- "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
- "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "supports-color": {
- "version": "6.1.0",
- "resolved": "https://registry.nlark.com/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz",
- "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "wrap-ansi": {
- "version": "5.1.0",
- "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-5.1.0.tgz",
- "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.0",
- "string-width": "^3.0.0",
- "strip-ansi": "^5.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
- "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553320591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
- "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "yargs": {
- "version": "13.3.2",
- "resolved": "https://registry.nlark.com/yargs/download/yargs-13.3.2.tgz?cache=0&sync_timestamp=1620086465147&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz",
- "integrity": "sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=",
- "dev": true,
- "requires": {
- "cliui": "^5.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.1.2"
- }
- },
- "yargs-parser": {
- "version": "13.1.2",
- "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.2.tgz",
- "integrity": "sha1-Ew8JcC667vJlDVTObj5XBvek+zg=",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
- }
- }
- },
- "webpack-log": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/webpack-log/download/webpack-log-2.0.0.tgz?cache=0&sync_timestamp=1615477439589&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-log%2Fdownload%2Fwebpack-log-2.0.0.tgz",
- "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=",
- "dev": true,
- "requires": {
- "ansi-colors": "^3.0.0",
- "uuid": "^3.3.2"
- }
- },
- "webpack-merge": {
- "version": "4.2.2",
- "resolved": "https://registry.npm.taobao.org/webpack-merge/download/webpack-merge-4.2.2.tgz?cache=0&sync_timestamp=1608705506214&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-merge%2Fdownload%2Fwebpack-merge-4.2.2.tgz",
- "integrity": "sha1-onxS6ng9E5iv0gh/VH17nS9DY00=",
- "dev": true,
- "requires": {
- "lodash": "^4.17.15"
- }
- },
- "webpack-sources": {
- "version": "1.4.3",
- "resolved": "https://registry.nlark.com/webpack-sources/download/webpack-sources-1.4.3.tgz?cache=0&sync_timestamp=1622110325575&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack-sources%2Fdownload%2Fwebpack-sources-1.4.3.tgz",
- "integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=",
- "dev": true,
- "requires": {
- "source-list-map": "^2.0.0",
- "source-map": "~0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
- "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
- "dev": true
- }
- }
- },
- "websocket-driver": {
- "version": "0.7.4",
- "resolved": "https://registry.nlark.com/websocket-driver/download/websocket-driver-0.7.4.tgz",
- "integrity": "sha1-ia1Slbv2S0gKvLox5JU6ynBvV2A=",
- "dev": true,
- "requires": {
- "http-parser-js": ">=0.5.1",
- "safe-buffer": ">=5.1.0",
- "websocket-extensions": ">=0.1.1"
- }
- },
- "websocket-extensions": {
- "version": "0.1.4",
- "resolved": "https://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.4.tgz",
- "integrity": "sha1-f4RzvIOd/YdgituV1+sHUhFXikI=",
- "dev": true
- },
- "when": {
- "version": "3.6.4",
- "resolved": "https://registry.npm.taobao.org/when/download/when-3.6.4.tgz",
- "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
- "dev": true
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.nlark.com/which/download/which-1.3.1.tgz",
- "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/which-boxed-primitive/download/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha1-E3V7yJsgmwSf5dhkMOIc9AqJqOY=",
- "dev": true,
- "requires": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- }
- },
- "which-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
- "dev": true
- },
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.nlark.com/word-wrap/download/word-wrap-1.2.3.tgz",
- "integrity": "sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=",
- "dev": true
- },
- "worker-farm": {
- "version": "1.7.0",
- "resolved": "https://registry.nlark.com/worker-farm/download/worker-farm-1.7.0.tgz?cache=0&sync_timestamp=1618846953836&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fworker-farm%2Fdownload%2Fworker-farm-1.7.0.tgz",
- "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=",
- "dev": true,
- "requires": {
- "errno": "~0.1.7"
- }
- },
- "wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-7.0.0.tgz",
- "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
- "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
- "dev": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
- "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
- "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
- "dev": true
- }
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
- },
- "write": {
- "version": "1.0.3",
- "resolved": "https://registry.nlark.com/write/download/write-1.0.3.tgz",
- "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=",
- "dev": true,
- "requires": {
- "mkdirp": "^0.5.1"
- }
- },
- "ws": {
- "version": "6.2.1",
- "resolved": "https://registry.nlark.com/ws/download/ws-6.2.1.tgz?cache=0&sync_timestamp=1621962892726&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fws%2Fdownload%2Fws-6.2.1.tgz",
- "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=",
- "dev": true,
- "requires": {
- "async-limiter": "~1.0.0"
- }
- },
- "xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz",
- "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=",
- "dev": true
- },
- "y18n": {
- "version": "4.0.3",
- "resolved": "https://registry.npm.taobao.org/y18n/download/y18n-4.0.3.tgz?cache=0&sync_timestamp=1617822684820&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fy18n%2Fdownload%2Fy18n-4.0.3.tgz",
- "integrity": "sha1-tfJZyCzW4zaSHv17/Yv1YN6e7t8=",
- "dev": true
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz",
- "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=",
- "dev": true
- },
- "yargs": {
- "version": "16.2.0",
- "resolved": "https://registry.nlark.com/yargs/download/yargs-16.2.0.tgz?cache=0&sync_timestamp=1620086465147&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyargs%2Fdownload%2Fyargs-16.2.0.tgz",
- "integrity": "sha1-HIK/D2tqZur85+8w43b0mhJHf2Y=",
- "dev": true,
- "requires": {
- "cliui": "^7.0.2",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.0",
- "y18n": "^5.0.5",
- "yargs-parser": "^20.2.2"
- },
- "dependencies": {
- "cliui": {
- "version": "7.0.4",
- "resolved": "https://registry.nlark.com/cliui/download/cliui-7.0.4.tgz",
- "integrity": "sha1-oCZe5lVHb8gHrqnfPfjfd4OAi08=",
- "dev": true,
- "requires": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^7.0.0"
- }
- },
- "y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npm.taobao.org/y18n/download/y18n-5.0.8.tgz?cache=0&sync_timestamp=1617822684820&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fy18n%2Fdownload%2Fy18n-5.0.8.tgz",
- "integrity": "sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU=",
- "dev": true
- }
- }
- },
- "yargs-parser": {
- "version": "20.2.7",
- "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-20.2.7.tgz",
- "integrity": "sha1-Yd+FwRPt+1p6TjbriqYO9CPLyQo=",
- "dev": true
- },
- "yorkie": {
- "version": "2.0.0",
- "resolved": "https://registry.npm.taobao.org/yorkie/download/yorkie-2.0.0.tgz",
- "integrity": "sha1-kkEZEtQ1IU4SxRwq4Qk+VLa7g9k=",
- "dev": true,
- "requires": {
- "execa": "^0.8.0",
- "is-ci": "^1.0.10",
- "normalize-path": "^1.0.0",
- "strip-indent": "^2.0.0"
- },
- "dependencies": {
- "cross-spawn": {
- "version": "5.1.0",
- "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz",
- "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
- "dev": true,
- "requires": {
- "lru-cache": "^4.0.1",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "execa": {
- "version": "0.8.0",
- "resolved": "https://registry.nlark.com/execa/download/execa-0.8.0.tgz?cache=0&sync_timestamp=1622396637949&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fexeca%2Fdownload%2Fexeca-0.8.0.tgz",
- "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
- "dev": true,
- "requires": {
- "cross-spawn": "^5.0.1",
- "get-stream": "^3.0.0",
- "is-stream": "^1.1.0",
- "npm-run-path": "^2.0.0",
- "p-finally": "^1.0.0",
- "signal-exit": "^3.0.0",
- "strip-eof": "^1.0.0"
- }
- },
- "get-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz",
- "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
- "dev": true
- },
- "lru-cache": {
- "version": "4.1.5",
- "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-4.1.5.tgz",
- "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
- "dev": true,
- "requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
- "normalize-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-1.0.0.tgz",
- "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
- "dev": true
- },
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
- "dev": true
- }
- }
- }
- }
-}
diff --git a/cmd/templates/vue3-js/frontend/package.json.template b/cmd/templates/vue3-js/frontend/package.json.template
deleted file mode 100644
index 942f672da..000000000
--- a/cmd/templates/vue3-js/frontend/package.json.template
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "version": "1.0.0",
- "private": true,
- "scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "lint": "vue-cli-service lint"
- },
- "dependencies": {
- "@wailsapp/runtime": "^1.1.1",
- "core-js": "^3.6.5",
- "vue": "^3.0.0",
- "vue-router": "^4.0.0-0",
- "vuex": "^4.0.0-0"
- },
- "devDependencies": {
- "@vue/cli-plugin-babel": "~4.5.0",
- "@vue/cli-plugin-eslint": "~4.5.0",
- "@vue/cli-plugin-router": "~4.5.0",
- "@vue/cli-plugin-vuex": "~4.5.0",
- "@vue/cli-service": "~4.5.0",
- "@vue/compiler-sfc": "^3.0.0",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.7.2",
- "eslint-plugin-vue": "^7.0.0",
- "stylus": "^0.54.7",
- "stylus-loader": "^3.0.2"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "plugin:vue/vue3-essential",
- "eslint:recommended"
- ],
- "parserOptions": {
- "parser": "babel-eslint"
- },
- "rules": {}
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not dead"
- ]
-}
diff --git a/cmd/templates/vue3-js/frontend/public/favicon.ico b/cmd/templates/vue3-js/frontend/public/favicon.ico
deleted file mode 100644
index df36fcfb7..000000000
Binary files a/cmd/templates/vue3-js/frontend/public/favicon.ico and /dev/null differ
diff --git a/cmd/templates/vue3-js/frontend/public/index.html b/cmd/templates/vue3-js/frontend/public/index.html
deleted file mode 100644
index 6ba8b205d..000000000
--- a/cmd/templates/vue3-js/frontend/public/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
- <%= htmlWebpackPlugin.options.title %>
-
-
-
- We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
- Please enable it to continue.
-
-
-
-
-
diff --git a/cmd/templates/vue3-js/frontend/src/App.vue b/cmd/templates/vue3-js/frontend/src/App.vue
deleted file mode 100644
index 6d7594d66..000000000
--- a/cmd/templates/vue3-js/frontend/src/App.vue
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
- Home |
- About
-
-
-
-
-
diff --git a/cmd/templates/vue3-js/frontend/src/assets/appicon.png b/cmd/templates/vue3-js/frontend/src/assets/appicon.png
deleted file mode 100644
index 66120ec80..000000000
Binary files a/cmd/templates/vue3-js/frontend/src/assets/appicon.png and /dev/null differ
diff --git a/cmd/templates/vue3-js/frontend/src/assets/logo.png b/cmd/templates/vue3-js/frontend/src/assets/logo.png
deleted file mode 100644
index 7fc8c8fde..000000000
Binary files a/cmd/templates/vue3-js/frontend/src/assets/logo.png and /dev/null differ
diff --git a/cmd/templates/vue3-js/frontend/src/components/HelloWorld.vue b/cmd/templates/vue3-js/frontend/src/components/HelloWorld.vue
deleted file mode 100644
index 0a5f13afe..000000000
--- a/cmd/templates/vue3-js/frontend/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
{{ msg }}
-
-
-
-
-
-
-
diff --git a/cmd/templates/vue3-js/frontend/src/main.js b/cmd/templates/vue3-js/frontend/src/main.js
deleted file mode 100644
index fb6c9ce07..000000000
--- a/cmd/templates/vue3-js/frontend/src/main.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import {createApp} from 'vue'
-import App from './App.vue'
-import router from './router'
-import store from './store'
-
-// import wails runtime
-import * as Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- createApp(App)
- .use(store)
- .use(router)
- .mount('#app')
-})
diff --git a/cmd/templates/vue3-js/frontend/src/router/index.js b/cmd/templates/vue3-js/frontend/src/router/index.js
deleted file mode 100644
index 41f7ce976..000000000
--- a/cmd/templates/vue3-js/frontend/src/router/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import {createMemoryHistory, createRouter} from 'vue-router'
-import Home from '../views/Home.vue'
-import About from '../views/About.vue'
-
-
-const routes = [
- {
- path: '/',
- name: 'Home',
- component: Home
- },
- {
- path: '/about',
- name: 'About',
- // You can only use pre-loading to add routes, not the on-demand loading method.
- component: About
- }
-]
-
-const router = createRouter({
- history: createMemoryHistory(),
- routes
-})
-
-export default router
diff --git a/cmd/templates/vue3-js/frontend/src/store/index.js b/cmd/templates/vue3-js/frontend/src/store/index.js
deleted file mode 100644
index a747c1ce9..000000000
--- a/cmd/templates/vue3-js/frontend/src/store/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import {createStore} from 'vuex'
-
-export default createStore({
- state: {},
- mutations: {},
- actions: {},
- modules: {}
-})
diff --git a/cmd/templates/vue3-js/frontend/src/views/About.vue b/cmd/templates/vue3-js/frontend/src/views/About.vue
deleted file mode 100644
index 3fa28070d..000000000
--- a/cmd/templates/vue3-js/frontend/src/views/About.vue
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
This is an about page
-
-
diff --git a/cmd/templates/vue3-js/frontend/src/views/Home.vue b/cmd/templates/vue3-js/frontend/src/views/Home.vue
deleted file mode 100644
index ca38da0dc..000000000
--- a/cmd/templates/vue3-js/frontend/src/views/Home.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vue3-js/frontend/vue.config.js b/cmd/templates/vue3-js/frontend/vue.config.js
deleted file mode 100644
index 72e4fd1d5..000000000
--- a/cmd/templates/vue3-js/frontend/vue.config.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let cssConfig = {};
-
-if (process.env.NODE_ENV == 'production') {
- cssConfig = {
- extract: {
- filename: '[name].css',
- chunkFilename: '[name].css'
- }
- };
-}
-
-module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule('images')
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .tap(options => Object.assign(options, {limit: limit}));
- config.module
- .rule('fonts')
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: '[name].js'
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
-};
diff --git a/cmd/templates/vue3-js/go.mod.template b/cmd/templates/vue3-js/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vue3-js/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vue3-js/main.go.template b/cmd/templates/vue3-js/main.go.template
deleted file mode 100644
index 5c5453943..000000000
--- a/cmd/templates/vue3-js/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "Hello World!"
-}
-
-//go:embed frontend/dist/app.js
-var js string
-
-//go:embed frontend/dist/app.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/vue3-js/template.json b/cmd/templates/vue3-js/template.json
deleted file mode 100644
index 8cde55215..000000000
--- a/cmd/templates/vue3-js/template.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "Vue3 JS",
- "version": "1.0.0",
- "shortdescription": "A template based on Vue 3, Vue-router, Vuex, and Webpack5",
- "description": "A template based on Vue 3, Vue-router, Vuex, and Webpack5",
- "install": "npm install",
- "build": "npm run build",
- "author": "Misitebao ",
- "created": "2021-05-02 17:25:55",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": "",
- "platforms": [
- "linux",
- "darwin"
- ]
-}
diff --git a/cmd/templates/vuebasic/.jshint b/cmd/templates/vuebasic/.jshint
deleted file mode 100644
index 0557edf11..000000000
--- a/cmd/templates/vuebasic/.jshint
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "esversion": 6
-}
\ No newline at end of file
diff --git a/cmd/templates/vuebasic/frontend/.gitignore b/cmd/templates/vuebasic/frontend/.gitignore
deleted file mode 100644
index 185e66319..000000000
--- a/cmd/templates/vuebasic/frontend/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw*
diff --git a/cmd/templates/vuebasic/frontend/README.md b/cmd/templates/vuebasic/frontend/README.md
deleted file mode 100644
index 6953f66d0..000000000
--- a/cmd/templates/vuebasic/frontend/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# vue basic
-
-## Project setup
-
-```
-npm install
-```
-
-### Compiles and hot-reloads for development
-
-```
-npm run serve
-```
-
-### Compiles and minifies for production
-
-```
-npm run build
-```
-
-### Run your tests
-
-```
-npm run test
-```
-
-### Lints and fixes files
-
-```
-npm run lint
-```
-
-### Customize configuration
-
-See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/cmd/templates/vuebasic/frontend/babel.config.js b/cmd/templates/vuebasic/frontend/babel.config.js
deleted file mode 100644
index a6106c484..000000000
--- a/cmd/templates/vuebasic/frontend/babel.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- presets: [
- [ '@vue/app', { useBuiltIns: 'entry' } ]
- ]
-}
diff --git a/cmd/templates/vuebasic/frontend/package.json.template b/cmd/templates/vuebasic/frontend/package.json.template
deleted file mode 100644
index 1e51d9f38..000000000
--- a/cmd/templates/vuebasic/frontend/package.json.template
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "private": true,
- "scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "lint": "vue-cli-service lint"
- },
- "dependencies": {
- "core-js": "^3.6.4",
- "regenerator-runtime": "^0.13.3",
- "vue": "^2.6.11",
- "@wailsapp/runtime": "^1.0.10"
- },
- "devDependencies": {
- "@vue/cli-plugin-babel": "^4.2.3",
- "@vue/cli-plugin-eslint": "^4.2.3",
- "@vue/cli-service": "^4.2.3",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.8.0",
- "eslint-plugin-vue": "^6.2.1",
- "eventsource-polyfill": "^0.9.6",
- "vue-template-compiler": "^2.6.11",
- "webpack-hot-middleware": "^2.25.0"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "plugin:vue/essential",
- "eslint:recommended"
- ],
- "rules": {},
- "parserOptions": {
- "parser": "babel-eslint"
- }
- },
- "postcss": {
- "plugins": {
- "autoprefixer": {}
- }
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not ie <= 8"
- ]
-}
diff --git a/cmd/templates/vuebasic/frontend/src/App.vue b/cmd/templates/vuebasic/frontend/src/App.vue
deleted file mode 100644
index 4700f3a71..000000000
--- a/cmd/templates/vuebasic/frontend/src/App.vue
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vuebasic/frontend/src/assets/css/main.css b/cmd/templates/vuebasic/frontend/src/assets/css/main.css
deleted file mode 100644
index ae5df813d..000000000
--- a/cmd/templates/vuebasic/frontend/src/assets/css/main.css
+++ /dev/null
@@ -1,38 +0,0 @@
-#app {
- font-family: "Roboto", Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-align: center;
- color: #eee;
- margin-top: 60px;
-}
-
-html {
- height: 100%;
- overflow: hidden;
- background-color: #131313;
- background-size: 20px 20px;
-}
-
-.logo {
- width: 16em;
-}
-
-/* roboto-regular - latin */
-@font-face {
- font-family: "Roboto";
- font-style: normal;
- font-weight: 400;
- src: url("../fonts/roboto/roboto-v18-latin-regular.eot"); /* IE9 Compat Modes */
- src: local("Roboto"), local("Roboto-Regular"),
- url("../fonts/roboto/roboto-v18-latin-regular.eot?#iefix")
- format("embedded-opentype"),
- /* IE6-IE8 */ url("../fonts/roboto/roboto-v18-latin-regular.woff2")
- format("woff2"),
- /* Super Modern Browsers */
- url("../fonts/roboto/roboto-v18-latin-regular.woff") format("woff"),
- /* Modern Browsers */ url("../fonts/roboto/roboto-v18-latin-regular.ttf")
- format("truetype"),
- /* Safari, Android, iOS */
- url("../fonts/roboto/roboto-v18-latin-regular.svg#Roboto") format("svg"); /* Legacy iOS */
-}
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/LICENSE.txt b/cmd/templates/vuebasic/frontend/src/assets/fonts/LICENSE.txt
deleted file mode 100644
index 75b52484e..000000000
--- a/cmd/templates/vuebasic/frontend/src/assets/fonts/LICENSE.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.eot b/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.eot
deleted file mode 100644
index a0780d6e3..000000000
Binary files a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.eot and /dev/null differ
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.svg b/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.svg
deleted file mode 100644
index a04a14447..000000000
--- a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.ttf b/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.ttf
deleted file mode 100644
index b91bf3f7e..000000000
Binary files a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.ttf and /dev/null differ
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff b/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff
deleted file mode 100644
index 92dfacc61..000000000
Binary files a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff and /dev/null differ
diff --git a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff2 b/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff2
deleted file mode 100644
index 7e854e669..000000000
Binary files a/cmd/templates/vuebasic/frontend/src/assets/fonts/roboto/roboto-v18-latin-regular.woff2 and /dev/null differ
diff --git a/cmd/templates/vuebasic/frontend/src/assets/images/logo.png b/cmd/templates/vuebasic/frontend/src/assets/images/logo.png
deleted file mode 100644
index e466f4ec0..000000000
Binary files a/cmd/templates/vuebasic/frontend/src/assets/images/logo.png and /dev/null differ
diff --git a/cmd/templates/vuebasic/frontend/src/components/HelloWorld.vue b/cmd/templates/vuebasic/frontend/src/components/HelloWorld.vue
deleted file mode 100644
index 722175f7b..000000000
--- a/cmd/templates/vuebasic/frontend/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vuebasic/frontend/src/main.js b/cmd/templates/vuebasic/frontend/src/main.js
deleted file mode 100644
index ce05741b7..000000000
--- a/cmd/templates/vuebasic/frontend/src/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'core-js/stable';
-import 'regenerator-runtime/runtime';
-import Vue from 'vue';
-import App from './App.vue';
-
-Vue.config.productionTip = false;
-Vue.config.devtools = true;
-
-import * as Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- new Vue({
- render: h => h(App)
- }).$mount('#app');
-});
diff --git a/cmd/templates/vuebasic/frontend/vue.config.js b/cmd/templates/vuebasic/frontend/vue.config.js
deleted file mode 100644
index a2691b1f7..000000000
--- a/cmd/templates/vuebasic/frontend/vue.config.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let cssConfig = {};
-
-if (process.env.NODE_ENV == "production") {
- cssConfig = {
- extract: {
- filename: "[name].css",
- chunkFilename: "[name].css"
- }
- };
-}
-
-module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule("images")
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use("url-loader")
- .loader("url-loader")
- .tap(options => Object.assign(options, { limit: limit }));
- config.module
- .rule("fonts")
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use("url-loader")
- .loader("url-loader")
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: "[name].js"
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
-};
diff --git a/cmd/templates/vuebasic/go.mod.template b/cmd/templates/vuebasic/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vuebasic/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vuebasic/main.go.template b/cmd/templates/vuebasic/main.go.template
deleted file mode 100644
index 5c5453943..000000000
--- a/cmd/templates/vuebasic/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "Hello World!"
-}
-
-//go:embed frontend/dist/app.js
-var js string
-
-//go:embed frontend/dist/app.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/vuebasic/template.json b/cmd/templates/vuebasic/template.json
deleted file mode 100644
index f2d017823..000000000
--- a/cmd/templates/vuebasic/template.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "Vue2/Webpack Basic",
- "shortdescription": "A basic Vue2/WebPack4 template",
- "description": "A basic template using Vue 2 and bundled using Webpack 4",
- "author": "Lea Anthony",
- "created": "2018-12-01",
- "frontenddir": "frontend",
- "install": "npm install",
- "build": "npm run build",
- "serve": "npm run serve",
- "bridge": "src"
-}
diff --git a/cmd/templates/vuetify-basic/.jshint b/cmd/templates/vuetify-basic/.jshint
deleted file mode 100644
index 0557edf11..000000000
--- a/cmd/templates/vuetify-basic/.jshint
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "esversion": 6
-}
\ No newline at end of file
diff --git a/cmd/templates/vuetify-basic/frontend/.gitignore b/cmd/templates/vuetify-basic/frontend/.gitignore
deleted file mode 100644
index 185e66319..000000000
--- a/cmd/templates/vuetify-basic/frontend/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw*
diff --git a/cmd/templates/vuetify-basic/frontend/babel.config.js b/cmd/templates/vuetify-basic/frontend/babel.config.js
deleted file mode 100644
index a6106c484..000000000
--- a/cmd/templates/vuetify-basic/frontend/babel.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- presets: [
- [ '@vue/app', { useBuiltIns: 'entry' } ]
- ]
-}
diff --git a/cmd/templates/vuetify-basic/frontend/package.json.template b/cmd/templates/vuetify-basic/frontend/package.json.template
deleted file mode 100644
index 430566f67..000000000
--- a/cmd/templates/vuetify-basic/frontend/package.json.template
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "private": true,
- "scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "lint": "vue-cli-service lint"
- },
-"dependencies": {
- "core-js": "^3.6.4",
- "regenerator-runtime": "^0.13.3",
- "material-design-icons-iconfont": "^5.0.1",
- "vue": "^2.5.22",
- "vuetify": "^1.5.14",
- "@wailsapp/runtime": "^1.0.10"
- },
- "devDependencies": {
- "@vue/cli-plugin-babel": "^4.2.3",
- "@vue/cli-plugin-eslint": "^4.2.3",
- "@vue/cli-service": "^4.2.3",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.8.0",
- "eslint-plugin-vue": "^6.2.1",
- "eventsource-polyfill": "^0.9.6",
- "vue-template-compiler": "^2.6.11",
- "webpack-hot-middleware": "^2.25.0"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "plugin:vue/essential",
- "eslint:recommended"
- ],
- "rules": {},
- "parserOptions": {
- "parser": "babel-eslint"
- }
- },
- "postcss": {
- "plugins": {
- "autoprefixer": {}
- }
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not ie <= 8"
- ]
-}
diff --git a/cmd/templates/vuetify-basic/frontend/src/App.vue b/cmd/templates/vuetify-basic/frontend/src/App.vue
deleted file mode 100644
index 6522b31e0..000000000
--- a/cmd/templates/vuetify-basic/frontend/src/App.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
- dashboard
-
-
- Dashboard
-
-
-
-
- settings
-
-
- Settings
-
-
-
-
-
-
- Application
-
-
-
-
-
-
-
-
-
- © You
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/cmd/templates/vuetify-basic/frontend/src/assets/images/logo.png b/cmd/templates/vuetify-basic/frontend/src/assets/images/logo.png
deleted file mode 100644
index e466f4ec0..000000000
Binary files a/cmd/templates/vuetify-basic/frontend/src/assets/images/logo.png and /dev/null differ
diff --git a/cmd/templates/vuetify-basic/frontend/src/components/HelloWorld.vue b/cmd/templates/vuetify-basic/frontend/src/components/HelloWorld.vue
deleted file mode 100644
index 28487aa06..000000000
--- a/cmd/templates/vuetify-basic/frontend/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Press Me
-
-
-
-
-
-
-
-
- Message from Go
- {{message}}
-
-
-
- Awesome
-
-
-
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vuetify-basic/frontend/src/main.js b/cmd/templates/vuetify-basic/frontend/src/main.js
deleted file mode 100644
index bbe42e116..000000000
--- a/cmd/templates/vuetify-basic/frontend/src/main.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import 'core-js/stable';
-import 'regenerator-runtime/runtime';
-import Vue from 'vue';
-
-// Setup Vuetify
-import Vuetify from 'vuetify';
-Vue.use(Vuetify);
-import 'vuetify/dist/vuetify.min.css';
-import 'material-design-icons-iconfont';
-
-import App from './App.vue';
-
-Vue.config.productionTip = false;
-Vue.config.devtools = true;
-
-import * as Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- new Vue({
- render: h => h(App)
- }).$mount('#app');
-});
diff --git a/cmd/templates/vuetify-basic/frontend/vue.config.js b/cmd/templates/vuetify-basic/frontend/vue.config.js
deleted file mode 100644
index a2691b1f7..000000000
--- a/cmd/templates/vuetify-basic/frontend/vue.config.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let cssConfig = {};
-
-if (process.env.NODE_ENV == "production") {
- cssConfig = {
- extract: {
- filename: "[name].css",
- chunkFilename: "[name].css"
- }
- };
-}
-
-module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule("images")
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use("url-loader")
- .loader("url-loader")
- .tap(options => Object.assign(options, { limit: limit }));
- config.module
- .rule("fonts")
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use("url-loader")
- .loader("url-loader")
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: "[name].js"
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
-};
diff --git a/cmd/templates/vuetify-basic/go.mod.template b/cmd/templates/vuetify-basic/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vuetify-basic/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vuetify-basic/main.go.template b/cmd/templates/vuetify-basic/main.go.template
deleted file mode 100644
index 5c5453943..000000000
--- a/cmd/templates/vuetify-basic/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "Hello World!"
-}
-
-//go:embed frontend/dist/app.js
-var js string
-
-//go:embed frontend/dist/app.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/vuetify-basic/template.json b/cmd/templates/vuetify-basic/template.json
deleted file mode 100755
index b58b5b041..000000000
--- a/cmd/templates/vuetify-basic/template.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "Vuetify1.5/Webpack Basic",
- "version": "1.0.0",
- "shortdescription": "A basic Vuetify1.5/Webpack4 template",
- "description": "Basic template using Vuetify v1.5 and bundled using Webpack",
- "install": "npm install",
- "build": "npm run build",
- "author": "lea ",
- "created": "2019-05-25 09:39:40.009307 +1000 AEST m=+59.539991073",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": ""
-}
diff --git a/cmd/templates/vuetify2-basic/.jshint b/cmd/templates/vuetify2-basic/.jshint
deleted file mode 100644
index 0557edf11..000000000
--- a/cmd/templates/vuetify2-basic/.jshint
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "esversion": 6
-}
\ No newline at end of file
diff --git a/cmd/templates/vuetify2-basic/frontend/.gitignore b/cmd/templates/vuetify2-basic/frontend/.gitignore
deleted file mode 100644
index 185e66319..000000000
--- a/cmd/templates/vuetify2-basic/frontend/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw*
diff --git a/cmd/templates/vuetify2-basic/frontend/babel.config.js b/cmd/templates/vuetify2-basic/frontend/babel.config.js
deleted file mode 100644
index 57e6d0a51..000000000
--- a/cmd/templates/vuetify2-basic/frontend/babel.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- presets: [
- [ '@vue/app', { useBuiltIns: 'entry' } ]
- ]
-};
diff --git a/cmd/templates/vuetify2-basic/frontend/package.json.template b/cmd/templates/vuetify2-basic/frontend/package.json.template
deleted file mode 100644
index 0913c632d..000000000
--- a/cmd/templates/vuetify2-basic/frontend/package.json.template
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "name": "{{.NPMProjectName}}",
- "author": "{{.Author.Name}}<{{.Author.Email}}>",
- "private": true,
- "scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "lint": "vue-cli-service lint"
- },
- "dependencies": {
- "core-js": "^3.6.4",
- "regenerator-runtime": "^0.13.3",
- "vue": "^2.6.11",
- "vuetify": "^2.3.15",
- "@wailsapp/runtime": "^1.0.10"
- },
- "devDependencies": {
- "@mdi/font": "^4.9.95",
- "@vue/cli-plugin-babel": "^4.2.3",
- "@vue/cli-plugin-eslint": "^4.2.3",
- "@vue/cli-service": "^4.2.3",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.8.0",
- "eslint-plugin-vue": "^6.2.1",
- "eventsource-polyfill": "^0.9.6",
- "vue-template-compiler": "^2.6.11",
- "webpack-hot-middleware": "^2.25.0"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "plugin:vue/essential",
- "eslint:recommended"
- ],
- "rules": {},
- "parserOptions": {
- "parser": "babel-eslint"
- }
- },
- "postcss": {
- "plugins": {
- "autoprefixer": {}
- }
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not ie <= 8"
- ]
-}
diff --git a/cmd/templates/vuetify2-basic/frontend/src/App.vue b/cmd/templates/vuetify2-basic/frontend/src/App.vue
deleted file mode 100644
index 759c1fba4..000000000
--- a/cmd/templates/vuetify2-basic/frontend/src/App.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
- mdi-view-dashboard
-
-
- Dashboard
-
-
-
-
- mdi-settings
-
-
- Settings
-
-
-
-
-
-
- Application
-
-
-
-
-
-
-
-
-
- © You
-
-
-
-
-
-
-
diff --git a/cmd/templates/vuetify2-basic/frontend/src/assets/images/logo.png b/cmd/templates/vuetify2-basic/frontend/src/assets/images/logo.png
deleted file mode 100644
index e466f4ec0..000000000
Binary files a/cmd/templates/vuetify2-basic/frontend/src/assets/images/logo.png and /dev/null differ
diff --git a/cmd/templates/vuetify2-basic/frontend/src/components/HelloWorld.vue b/cmd/templates/vuetify2-basic/frontend/src/components/HelloWorld.vue
deleted file mode 100644
index 84708401c..000000000
--- a/cmd/templates/vuetify2-basic/frontend/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Press Me
-
-
-
-
-
-
-
-
- Message from Go
- {{message}}
-
-
-
- Awesome
-
-
-
-
-
-
-
-
-
-
-
diff --git a/cmd/templates/vuetify2-basic/frontend/src/main.js b/cmd/templates/vuetify2-basic/frontend/src/main.js
deleted file mode 100644
index 245eb1e03..000000000
--- a/cmd/templates/vuetify2-basic/frontend/src/main.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import 'core-js/stable';
-import 'regenerator-runtime/runtime';
-import '@mdi/font/css/materialdesignicons.css';
-import Vue from 'vue';
-import Vuetify from 'vuetify';
-import 'vuetify/dist/vuetify.min.css';
-
-Vue.use(Vuetify);
-
-import App from './App.vue';
-
-Vue.config.productionTip = false;
-Vue.config.devtools = true;
-
-import Wails from '@wailsapp/runtime';
-
-Wails.Init(() => {
- new Vue({
- vuetify: new Vuetify({
- icons: {
- iconfont: 'mdi'
- },
- theme: {
- dark: true
- }
- }),
- render: h => h(App)
- }).$mount('#app');
-});
diff --git a/cmd/templates/vuetify2-basic/frontend/vue.config.js b/cmd/templates/vuetify2-basic/frontend/vue.config.js
deleted file mode 100644
index 8dcf3e339..000000000
--- a/cmd/templates/vuetify2-basic/frontend/vue.config.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let cssConfig = {};
-
-if (process.env.NODE_ENV == 'production') {
- cssConfig = {
- extract: {
- filename: '[name].css',
- chunkFilename: '[name].css'
- }
- };
-}
-
-module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule('images')
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .tap(options => Object.assign(options, { limit: limit }));
- config.module
- .rule('fonts')
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: '[name].js'
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
-};
diff --git a/cmd/templates/vuetify2-basic/go.mod.template b/cmd/templates/vuetify2-basic/go.mod.template
deleted file mode 100644
index 780381065..000000000
--- a/cmd/templates/vuetify2-basic/go.mod.template
+++ /dev/null
@@ -1,5 +0,0 @@
-module {{.BinaryName}}
-
-require (
- github.com/wailsapp/wails {{.WailsVersion}}
-)
\ No newline at end of file
diff --git a/cmd/templates/vuetify2-basic/main.go.template b/cmd/templates/vuetify2-basic/main.go.template
deleted file mode 100644
index 5c5453943..000000000
--- a/cmd/templates/vuetify2-basic/main.go.template
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- _ "embed"
- "github.com/wailsapp/wails"
-)
-
-func basic() string {
- return "Hello World!"
-}
-
-//go:embed frontend/dist/app.js
-var js string
-
-//go:embed frontend/dist/app.css
-var css string
-
-func main() {
-
- app := wails.CreateApp(&wails.AppConfig{
- Width: 1024,
- Height: 768,
- Title: "{{.Name}}",
- JS: js,
- CSS: css,
- Colour: "#131313",
- })
- app.Bind(basic)
- app.Run()
-}
diff --git a/cmd/templates/vuetify2-basic/template.json b/cmd/templates/vuetify2-basic/template.json
deleted file mode 100755
index a33450fe5..000000000
--- a/cmd/templates/vuetify2-basic/template.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "Vuetify2/Webpack Basic",
- "version": "1.0.0",
- "shortdescription": "A basic Vuetify2/Webpack4 template",
- "description": "Basic template using Vuetify v2 and bundled using Webpack",
- "install": "npm install",
- "build": "npm run build",
- "author": "Michael Hipp ",
- "created": "2019-09-06",
- "frontenddir": "frontend",
- "serve": "npm run serve",
- "bridge": "src",
- "wailsdir": ""
-}
diff --git a/cmd/version.go b/cmd/version.go
deleted file mode 100644
index 79744dacd..000000000
--- a/cmd/version.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package cmd
-
-// Version - Wails version
-const Version = "v1.16.9"
diff --git a/cmd/wails/0_setup.go b/cmd/wails/0_setup.go
deleted file mode 100644
index 394f565a7..000000000
--- a/cmd/wails/0_setup.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package main
-
-import (
- "runtime"
-
- "github.com/wailsapp/wails/cmd"
-)
-
-func init() {
-
- commandDescription := `Sets up your local environment to develop Wails apps.`
-
- setupCommand := app.Command("setup", "Setup the Wails environment").
- LongDescription(commandDescription)
-
- app.DefaultCommand(setupCommand)
-
- setupCommand.Action(func() error {
-
- logger.PrintBanner()
-
- var err error
-
- system := cmd.NewSystemHelper()
- err = system.Initialise()
- if err != nil {
- return err
- }
-
- var successMessage = `Ready for take off!
-Create your first project by running 'wails init'.`
- if runtime.GOOS != "windows" {
- successMessage = "🚀 " + successMessage
- }
-
- // Chrck for programs and libraries dependencies
- errors, err := cmd.CheckDependencies(logger)
- if err != nil {
- return err
- }
-
- // Check for errors
- // CheckDependencies() returns !errors
- // so to get the right message in this
- // check we have to do it in reversed
- if errors {
- logger.Yellow(successMessage)
- }
-
- return err
- })
-}
diff --git a/cmd/wails/10.1_dev_newtemplate.go b/cmd/wails/10.1_dev_newtemplate.go
deleted file mode 100644
index 17e4a4c1e..000000000
--- a/cmd/wails/10.1_dev_newtemplate.go
+++ /dev/null
@@ -1,122 +0,0 @@
-//go:build dev
-// +build dev
-
-package main
-
-import (
- "fmt"
- "time"
-
- "github.com/wailsapp/wails/cmd"
- "gopkg.in/AlecAivazis/survey.v1"
-)
-
-var templateHelper = cmd.NewTemplateHelper()
-
-var qs = []*survey.Question{
- {
- Name: "Name",
- Prompt: &survey.Input{Message: "Please enter the name of your template (eg: React/Webpack Basic):"},
- Validate: survey.Required,
- },
- {
- Name: "ShortDescription",
- Prompt: &survey.Input{Message: "Please enter a short description for the template (eg: React with Webpack 4):"},
- Validate: survey.Required,
- },
- {
- Name: "Description",
- Prompt: &survey.Input{Message: "Please enter a long description:"},
- Validate: survey.Required,
- },
- {
- Name: "FrontendDir",
- Prompt: &survey.Input{Message: "Please enter the name of the directory the frontend code resides (eg: frontend):"},
- Validate: survey.Required,
- },
- {
- Name: "Install",
- Prompt: &survey.Input{Message: "Please enter the install command (eg: npm install):"},
- Validate: survey.Required,
- },
- {
- Name: "Build",
- Prompt: &survey.Input{Message: "Please enter the build command (eg: npm run build):"},
- Validate: survey.Required,
- },
- {
- Name: "Serve",
- Prompt: &survey.Input{Message: "Please enter the serve command (eg: npm run serve):"},
- Validate: survey.Required,
- },
- {
- Name: "Bridge",
- Prompt: &survey.Input{Message: "Please enter the name of the directory to copy the wails bridge runtime (eg: src):"},
- Validate: survey.Required,
- },
-}
-
-func newTemplate(devCommand *cmd.Command) {
-
- commandDescription := `This command scaffolds everything needed to develop a new template.`
- newTemplate := devCommand.Command("newtemplate", "Generate a new template").
- LongDescription(commandDescription)
-
- newTemplate.Action(func() error {
- logger.PrintSmallBanner("Generating new project template")
- fmt.Println()
-
- var answers cmd.TemplateMetadata
-
- // perform the questions
- err := survey.Ask(qs, &answers)
- if err != nil {
- fmt.Println(err.Error())
- return err
- }
-
- dirname := templateHelper.SanitizeFilename(answers.Name)
- prompt := []*survey.Question{{
- Prompt: &survey.Input{
- Message: "Please enter a directory name for the template:",
- Default: dirname,
- },
- Validate: func(val interface{}) error {
- err := survey.Required(val)
- if err != nil {
- return err
- }
- if templateHelper.IsValidTemplate(val.(string)) {
- return fmt.Errorf("template directory already exists")
- }
- if templateHelper.SanitizeFilename(val.(string)) != val.(string) {
- return fmt.Errorf("invalid directory name '%s'", val.(string))
- }
- return nil
- },
- }}
- err = survey.Ask(prompt, &dirname)
- if err != nil {
- return err
- }
-
- answers.Version = "1.0.0"
- answers.Created = time.Now().String()
-
- // Get Author info from system info
- system := cmd.NewSystemHelper()
- author, err := system.GetAuthor()
- if err == nil {
- answers.Author = author
- }
-
- templateDirectory, err := templateHelper.CreateNewTemplate(dirname, &answers)
- if err != nil {
- return err
- }
-
- logger.Green("Created new template '%s' in directory '%s'", answers.Name, templateDirectory)
-
- return nil
- })
-}
diff --git a/cmd/wails/10_dev.go b/cmd/wails/10_dev.go
deleted file mode 100644
index ea0af0976..000000000
--- a/cmd/wails/10_dev.go
+++ /dev/null
@@ -1,19 +0,0 @@
-//go:build dev
-// +build dev
-
-package main
-
-func init() {
-
- commandDescription := `This command provides access to developer tooling.`
- devCommand := app.Command("dev", "A selection of developer tools").
- LongDescription(commandDescription)
-
- // Add subcommands
- newTemplate(devCommand)
-
- devCommand.Action(func() error {
- devCommand.PrintHelp()
- return nil
- })
-}
diff --git a/cmd/wails/15_migrate.go b/cmd/wails/15_migrate.go
deleted file mode 100644
index c2d4def51..000000000
--- a/cmd/wails/15_migrate.go
+++ /dev/null
@@ -1,384 +0,0 @@
-package main
-
-import (
- "bufio"
- "fmt"
- "log"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/Masterminds/semver"
- "github.com/leaanthony/spinner"
- "github.com/wailsapp/wails/cmd"
-)
-
-// Constants
-var checkSpinner = spinner.NewSpinner()
-var migrateProjectOptions = &cmd.ProjectOptions{}
-var migrateFS = cmd.NewFSHelper()
-var migrateGithub = cmd.NewGitHubHelper()
-var programHelper = cmd.NewProgramHelper()
-var lessThanV1 *semver.Constraints
-
-// The user's go.mod
-var goMod string
-var goModFile string
-
-// The user's main.js
-var mainJSFile string
-var mainJSContents string
-
-// Frontend directory
-var frontEndDir string
-
-func init() {
-
- var dryrun bool
- var err error
-
- lessThanV1, err = semver.NewConstraint("< v1.0.0")
- if err != nil {
- log.Fatal(err)
- }
-
- // var forceRebuild = false
- checkSpinner.SetSpinSpeed(50)
-
- commandDescription := `EXPERIMENTAL - This command attempts to migrate projects to the latest Wails version.`
- updateCmd := app.Command("migrate", "Migrate projects to latest Wails release").
- LongDescription(commandDescription).
- BoolFlag("dryrun", "Only display what would be done", &dryrun)
-
- updateCmd.Action(func() error {
-
- message := "Migrate Project"
- logger.PrintSmallBanner(message)
- logger.Red("WARNING: This is an experimental command. Ensure you have backups of your project!")
- logger.Red("It currently only supports npm based projects.")
- fmt.Println()
-
- // Check project directory
- err := checkProjectDirectory()
- if err != nil {
- return err
- }
-
- // Find Wails version from go.mod
- wailsVersion, err := getWailsVersion()
- if err != nil {
- return err
- }
-
- // Get latest stable version
- var latestVersion *semver.Version
- latestVersion, err = getLatestWailsVersion()
- if err != nil {
- return err
- }
-
- var canMigrate bool
- canMigrate, err = canMigrateVersion(wailsVersion, latestVersion)
- if err != nil {
- return err
- }
-
- if !canMigrate {
- return nil
- }
-
- // Check for wailsbridge
- wailsBridge, err := checkWailsBridge()
- if err != nil {
- return err
- }
-
- // Is main.js using bridge.Init()
- canUpdateMainJS, err := checkMainJS()
- if err != nil {
- return err
- }
-
- // TODO: Check if we are using legacy js runtime
-
- // Operations
- logger.Yellow("Operations to perform:")
-
- logger.Yellowf(" - Update to Wails v%s\n", latestVersion)
-
- if len(wailsBridge) > 0 {
- logger.Yellow(" - Delete wailsbridge.js")
- }
-
- if canUpdateMainJS {
- logger.Yellow(" - Patch main.js")
- }
-
- logger.Yellow(" - Ensure '@wailsapp/runtime` module is installed")
-
- if dryrun {
- logger.White("Exiting: Dry Run")
- return nil
- }
-
- logger.Red("*WARNING* About to modify your project!")
- logger.Red("Type 'YES' to continue: ")
- scanner := bufio.NewScanner(os.Stdin)
- scanner.Scan()
- input := scanner.Text()
- if input != "YES" {
- logger.Red("ABORTED!")
- return nil
- }
-
- logger.Yellow("Let's do this!")
-
- err = updateWailsVersion(wailsVersion, latestVersion)
- if err != nil {
- return err
- }
-
- if len(wailsBridge) > 0 {
- err = deleteWailsBridge(wailsBridge)
- if err != nil {
- return err
- }
- }
-
- if canUpdateMainJS {
- err = patchMainJS()
- if err != nil {
- return err
- }
- }
-
- // Install runtime
- err = installWailsRuntime()
- if err != nil {
- return err
- }
-
- fmt.Println()
- logger.Yellow("Migration complete! Check project by running `wails build`.")
- return nil
- })
-}
-
-func checkProjectDirectory() error {
- // Get versions
- checkSpinner.Start("Check Project Directory")
-
- // Check we are in project directory
- err := migrateProjectOptions.LoadConfig(migrateFS.Cwd())
- if err != nil {
- checkSpinner.Error()
- return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
- }
-
- checkSpinner.Success()
- return nil
-}
-
-func getWailsVersion() (*semver.Version, error) {
- checkSpinner.Start("Get Wails Version")
-
- result, err := cmd.GetWailsVersion()
-
- if err != nil {
- checkSpinner.Error(err.Error())
- return nil, err
- }
- return result, nil
-
-}
-
-func canMigrateVersion(wailsVersion *semver.Version, latestVersion *semver.Version) (bool, error) {
- checkSpinner.Start("Checking ability to Migrate")
-
- // Check if we are at the latest version!!!!
- if wailsVersion.Equal(latestVersion) || wailsVersion.GreaterThan(latestVersion) {
- checkSpinner.Errorf("Checking ability to Migrate: No! (v%s >= v%s)", wailsVersion, latestVersion)
- return false, nil
- }
-
- // Check for < v1.0.0
- if lessThanV1.Check(wailsVersion) {
- checkSpinner.Successf("Checking ability to Migrate: Yes! (v%s < v1.0.0)", wailsVersion)
- return true, nil
- }
- checkSpinner.Error("Unable to migrate")
- return false, fmt.Errorf("No migration rules for version %s", wailsVersion)
-}
-
-func checkWailsBridge() (string, error) {
- checkSpinner.Start("Checking if legacy Wails Bridge present")
-
- // Check frontend dir is available
- if migrateProjectOptions.FrontEnd == nil ||
- len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
- !migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
- checkSpinner.Error("Unable to determine frontend directory")
- return "", fmt.Errorf("Unable to determine frontend directory")
- }
-
- frontEndDir = migrateProjectOptions.FrontEnd.Dir
-
- wailsBridgePath, err := filepath.Abs(filepath.Join(".", frontEndDir, "src", "wailsbridge.js"))
- if err != nil {
- checkSpinner.Error(err.Error())
- return "", err
- }
-
- // If it doesn't exist, return blank string
- if !migrateFS.FileExists(wailsBridgePath) {
- checkSpinner.Success("Checking if legacy Wails Bridge present: No")
- return "", nil
- }
-
- checkSpinner.Success("Checking if legacy Wails Bridge present: Yes")
- return wailsBridgePath, nil
-
-}
-
-// This function determines if the main.js file using wailsbridge can be auto-updated
-func checkMainJS() (bool, error) {
-
- checkSpinner.Start("Checking if main.js can be migrated")
- var err error
-
- // Check main.js is there
- if migrateProjectOptions.FrontEnd == nil ||
- len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
- !migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
- checkSpinner.Error("Unable to determine frontend directory")
- return false, fmt.Errorf("Unable to determine frontend directory")
- }
-
- frontEndDir = migrateProjectOptions.FrontEnd.Dir
-
- mainJSFile, err = filepath.Abs(filepath.Join(".", frontEndDir, "src", "main.js"))
- if err != nil {
- checkSpinner.Error("Unable to find main.js")
- return false, err
- }
-
- mainJSContents, err = migrateFS.LoadAsString(mainJSFile)
- if err != nil {
- checkSpinner.Error("Unable to load main.js")
- return false, err
- }
-
- // Check we have a line like: import Bridge from "./wailsbridge";
- if strings.Index(mainJSContents, `import Bridge from "./wailsbridge";`) == -1 {
- checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `import Bridge`")
- return false, nil
- }
-
- // Check we have a line like: Bridge.Start(() => {
- if strings.Index(mainJSContents, `Bridge.Start(`) == -1 {
- checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `Bridge.Start`")
- return false, nil
- }
- checkSpinner.Success("Checking if main.js can be migrated: Yes")
- return true, nil
-}
-
-func getLatestWailsVersion() (*semver.Version, error) {
- checkSpinner.Start("Checking GitHub for latest Wails version")
- version, err := migrateGithub.GetLatestStableRelease()
- if err != nil {
- checkSpinner.Error("Checking GitHub for latest Wails version: Failed")
- return nil, err
- }
-
- checkSpinner.Successf("Checking GitHub for latest Wails version: v%s", version)
- return version.Version, nil
-}
-
-func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
- // Patch go.mod
- checkSpinner.Start("Patching go.mod")
-
- wailsModule := "github.com/wailsapp/wails"
- old := fmt.Sprintf("%s v%s", wailsModule, currentVersion)
- new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
-
- goMod = strings.Replace(goMod, old, new, -1)
- err := os.WriteFile(goModFile, []byte(goMod), 0600)
- if err != nil {
- checkSpinner.Error()
- return err
- }
-
- checkSpinner.Success()
- return nil
-}
-
-func deleteWailsBridge(bridgeFilename string) error {
- // Patch go.mod
- checkSpinner.Start("Delete legacy wailsbridge.js")
-
- err := migrateFS.RemoveFile(bridgeFilename)
- if err != nil {
- checkSpinner.Error()
- return err
- }
-
- checkSpinner.Success()
- return nil
-}
-
-func patchMainJS() error {
- // Patch main.js
- checkSpinner.Start("Patching main.js")
-
- // Patch import line
- oldImportLine := `import Bridge from "./wailsbridge";`
- newImportLine := `import * as Wails from "@wailsapp/runtime";`
- mainJSContents = strings.Replace(mainJSContents, oldImportLine, newImportLine, -1)
-
- // Patch Start line
- oldStartLine := `Bridge.Start`
- newStartLine := `Wails.Init`
- mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
-
- err := os.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
- if err != nil {
- checkSpinner.Error()
- return err
- }
-
- checkSpinner.Success()
- return nil
-}
-
-func installWailsRuntime() error {
-
- checkSpinner.Start("Installing @wailsapp/runtime module")
-
- // Change to the frontend directory
- err := os.Chdir(frontEndDir)
- if err != nil {
- checkSpinner.Error()
- return nil
- }
-
- // Determine package manager
- packageManager, err := migrateProjectOptions.GetNPMBinaryName()
- if err != nil {
- checkSpinner.Error()
- return nil
- }
-
- switch packageManager {
- case cmd.NPM:
- // npm install --save @wailsapp/runtime
- programHelper.InstallNPMPackage("@wailsapp/runtime", true)
- default:
- checkSpinner.Error()
- return fmt.Errorf("Unknown package manager")
- }
-
- checkSpinner.Success()
- return nil
-}
diff --git a/cmd/wails/2_init.go b/cmd/wails/2_init.go
deleted file mode 100644
index eac708fde..000000000
--- a/cmd/wails/2_init.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package main
-
-import (
- "fmt"
- "os"
- "path/filepath"
-
- "github.com/leaanthony/spinner"
- "github.com/wailsapp/wails/cmd"
-)
-
-func init() {
-
- projectHelper := cmd.NewProjectHelper()
- projectOptions := projectHelper.NewProjectOptions()
- commandDescription := `Generates a new Wails project using the given flags.
-Any flags that are required and not given will be prompted for.`
- build := false
-
- initCommand := app.Command("init", "Initialises a new Wails project").
- LongDescription(commandDescription).
- BoolFlag("f", "Use defaults", &projectOptions.UseDefaults).
- StringFlag("dir", "Directory to create project in", &projectOptions.OutputDirectory).
- StringFlag("template", "Template name", &projectOptions.Template).
- StringFlag("name", "Project name", &projectOptions.Name).
- StringFlag("description", "Project description", &projectOptions.Description).
- StringFlag("output", "Output binary name", &projectOptions.BinaryName).
- BoolFlag("build", "Build project after generating", &build)
-
- initCommand.Action(func() error {
-
- logger.PrintSmallBanner("Initialising project")
- fmt.Println()
-
- // Check if the system is initialised
- system := cmd.NewSystemHelper()
- err := system.CheckInitialised()
- if err != nil {
- return err
- }
-
- success, err := cmd.CheckDependenciesSilent(logger)
- if !success {
- return err
- }
-
- // Do we want to just force defaults?
- if projectOptions.UseDefaults {
- // Use defaults
- projectOptions.Defaults()
- } else {
- err = projectOptions.PromptForInputs()
- if err != nil {
- return err
- }
- }
-
- genSpinner := spinner.NewSpinner()
- genSpinner.SetSpinSpeed(50)
- genSpinner.Start("Generating project...")
-
- // Generate the project
- err = projectHelper.GenerateProject(projectOptions)
- if err != nil {
- genSpinner.Error()
- return err
- }
- genSpinner.Success()
- if !build {
- logger.Yellow("Project '%s' initialised. Run `wails build` to build it.", projectOptions.Name)
- return nil
- }
-
- // Build the project
- cwd, _ := os.Getwd()
- projectDir := filepath.Join(cwd, projectOptions.OutputDirectory)
- program := cmd.NewProgramHelper()
- buildSpinner := spinner.NewSpinner()
- buildSpinner.SetSpinSpeed(50)
- buildSpinner.Start("Building project (this may take a while)...")
- err = program.RunCommandArray([]string{"wails", "build"}, projectDir)
- if err != nil {
- buildSpinner.Error(err.Error())
- return err
- }
- buildSpinner.Success()
- logger.Yellow("Project '%s' built in directory '%s'!", projectOptions.Name, projectOptions.OutputDirectory)
-
- return err
- })
-}
diff --git a/cmd/wails/4_build.go b/cmd/wails/4_build.go
deleted file mode 100644
index 65c8adf57..000000000
--- a/cmd/wails/4_build.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "runtime"
- "strings"
-
- "github.com/leaanthony/spinner"
- "github.com/wailsapp/wails/cmd"
-)
-
-// getSupportedPlatforms returns a slice of platform/architecture
-// targets that are buildable using the cross-platform 'x' option.
-func getSupportedPlatforms() []string {
- return []string{
- "darwin/amd64",
- "linux/amd64",
- "linux/arm-7",
- "windows/amd64",
- }
-}
-
-func init() {
-
- var packageApp = false
- var forceRebuild = false
- var debugMode = false
- var usefirebug = false
- var gopath = ""
- var typescriptFilename = ""
- var verbose = false
- var platform = ""
- var ldflags = ""
- var tags = ""
-
- buildSpinner := spinner.NewSpinner()
- buildSpinner.SetSpinSpeed(50)
-
- commandDescription := `This command will check to ensure all pre-requistes are installed prior to building. If not, it will attempt to install them. Building comprises of a number of steps: install frontend dependencies, build frontend, pack frontend, compile main application.`
- initCmd := app.Command("build", "Builds your Wails project").
- LongDescription(commandDescription).
- BoolFlag("p", "Package application on successful build", &packageApp).
- BoolFlag("f", "Force rebuild of application components", &forceRebuild).
- BoolFlag("d", "Build in Debug mode", &debugMode).
- BoolFlag("firebug", "Enable firebug console for debug builds", &usefirebug).
- BoolFlag("verbose", "Verbose output", &verbose).
- StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename).
- StringFlag("ldflags", "Extra options for -ldflags", &ldflags).
- StringFlag("gopath", "Specify your GOPATH location. Mounted to /go during cross-compilation.", &gopath).
- StringFlag("tags", "Build tags to pass to the go compiler (quoted and space separated)", &tags)
-
- var b strings.Builder
- for _, plat := range getSupportedPlatforms() {
- _, err := fmt.Fprintf(&b, " - %s\n", plat)
- if err != nil {
- log.Fatal(err)
- }
- }
- initCmd.StringFlag("x",
- fmt.Sprintf("Cross-compile application to specified platform via xgo\n%s", b.String()),
- &platform)
-
- initCmd.Action(func() error {
-
- message := "Building Application"
- if packageApp {
- message = "Packaging Application"
- }
- if forceRebuild {
- message += " (force rebuild)"
- }
- logger.PrintSmallBanner(message)
- fmt.Println()
-
- // Project options
- projectOptions := &cmd.ProjectOptions{}
- projectOptions.Verbose = verbose
- projectOptions.UseFirebug = usefirebug
-
- // Check we are in project directory
- // Check project.json loads correctly
- fs := cmd.NewFSHelper()
- err := projectOptions.LoadConfig(fs.Cwd())
- if err != nil {
- return fmt.Errorf("unable to find 'project.json'. Please check you are in a Wails project directory")
- }
-
- // Set firebug flag
- projectOptions.UseFirebug = usefirebug
-
- // Check that this platform is supported
- if !projectOptions.PlatformSupported() {
- logger.Yellow("WARNING: This project is unsupported on %s - it probably won't work!\n Valid platforms: %s\n", runtime.GOOS, strings.Join(projectOptions.Platforms, ", "))
- }
-
- // Set cross-compile
- projectOptions.Platform = runtime.GOOS
- if len(platform) > 0 {
- supported := false
- for _, plat := range getSupportedPlatforms() {
- if plat == platform {
- supported = true
- }
- }
- if !supported {
- return fmt.Errorf("unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options", platform)
- }
-
- projectOptions.CrossCompile = true
- plat := strings.Split(platform, "/")
- projectOptions.Platform = plat[0]
- projectOptions.Architecture = plat[1]
- }
-
- // Add ldflags
- projectOptions.LdFlags = ldflags
- projectOptions.GoPath = gopath
-
- // Add tags
- projectOptions.Tags = tags
-
- // Validate config
- // Check if we have a frontend
- err = cmd.ValidateFrontendConfig(projectOptions)
- if err != nil {
- return err
- }
-
- // Program checker
- program := cmd.NewProgramHelper()
-
- if projectOptions.FrontEnd != nil {
- // npm
- if !program.IsInstalled("npm") {
- return fmt.Errorf("it appears npm is not installed. Please install and run again")
- }
- }
-
- // Save project directory
- projectDir := fs.Cwd()
-
- // Install deps
- if projectOptions.FrontEnd != nil {
- err = cmd.InstallFrontendDeps(projectDir, projectOptions, forceRebuild, "build")
- if err != nil {
- return err
- }
- }
-
- // Move to project directory
- err = os.Chdir(projectDir)
- if err != nil {
- return err
- }
-
- // Install dependencies
- err = cmd.InstallGoDependencies(projectOptions.Verbose)
- if err != nil {
- return err
- }
-
- // Build application
- buildMode := cmd.BuildModeProd
- if debugMode {
- buildMode = cmd.BuildModeDebug
- }
-
- // Save if we wish to dump typescript or not
- if typescriptFilename != "" {
- projectOptions.SetTypescriptDefsFilename(typescriptFilename)
- }
-
- // Update go.mod if it is out of sync with current version
- outofsync, err := cmd.GoModOutOfSync()
- if err != nil {
- return err
- }
- gomodVersion, err := cmd.GetWailsVersion()
- if err != nil {
- return err
- }
- if outofsync {
- syncMessage := fmt.Sprintf("Updating go.mod (Wails version %s => %s)", gomodVersion, cmd.Version)
- buildSpinner := spinner.NewSpinner(syncMessage)
- buildSpinner.Start()
- err := cmd.UpdateGoModVersion()
- if err != nil {
- buildSpinner.Error(err.Error())
- return err
- }
- buildSpinner.Success()
- }
-
- err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
- if err != nil {
- return err
- }
-
- if projectOptions.Platform == "windows" {
- logger.Yellow("*** Please note: Windows builds use mshtml which is only compatible with IE11. For more information, please read https://wails.app/guides/windows/ ***")
- }
-
- logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
-
- return nil
-
- })
-}
diff --git a/cmd/wails/6_serve.go b/cmd/wails/6_serve.go
deleted file mode 100644
index 6e289685f..000000000
--- a/cmd/wails/6_serve.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package main
-
-import (
- "fmt"
- "runtime"
-
- "github.com/leaanthony/spinner"
- "github.com/wailsapp/wails/cmd"
-)
-
-func init() {
-
- var forceRebuild = false
- var verbose = false
- buildSpinner := spinner.NewSpinner()
- buildSpinner.SetSpinSpeed(50)
-
- commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
- initCmd := app.Command("serve", "Run your Wails project in bridge mode").
- LongDescription(commandDescription).
- BoolFlag("verbose", "Verbose output", &verbose).
- BoolFlag("f", "Force rebuild of application components", &forceRebuild)
-
- initCmd.Action(func() error {
-
- message := "Serving Application"
- logger.PrintSmallBanner(message)
- fmt.Println()
-
- // Project options
- projectOptions := &cmd.ProjectOptions{}
-
- // Check we are in project directory
- // Check project.json loads correctly
- fs := cmd.NewFSHelper()
- err := projectOptions.LoadConfig(fs.Cwd())
- if err != nil {
- return err
- }
-
- // Set project options
- projectOptions.Verbose = verbose
- projectOptions.Platform = runtime.GOOS
-
- // Save project directory
- projectDir := fs.Cwd()
-
- // Install the bridge library
- err = cmd.InstallBridge(projectDir, projectOptions)
- if err != nil {
- return err
- }
-
- // Install dependencies
- err = cmd.InstallGoDependencies(projectOptions.Verbose)
- if err != nil {
- return err
- }
-
- buildMode := cmd.BuildModeBridge
- err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, false, projectOptions)
- if err != nil {
- return err
- }
-
- logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
-
- return cmd.ServeProject(projectOptions, logger)
- })
-}
diff --git a/cmd/wails/8_update.go b/cmd/wails/8_update.go
deleted file mode 100644
index 70224aa49..000000000
--- a/cmd/wails/8_update.go
+++ /dev/null
@@ -1,164 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
-
- "github.com/leaanthony/spinner"
- "github.com/wailsapp/wails/cmd"
-)
-
-func init() {
-
- var prereleaseRequired bool
- var specificVersion string
-
- // var forceRebuild = false
- checkSpinner := spinner.NewSpinner()
- checkSpinner.SetSpinSpeed(50)
-
- commandDescription := `This command allows you to update your version of Wails.`
- updateCmd := app.Command("update", "Update to newer [pre]releases or specific versions").
- LongDescription(commandDescription).
- BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired).
- StringFlag("version", "Install a specific version (Overrides other flags)", &specificVersion)
-
- updateCmd.Action(func() error {
-
- message := "Checking for updates..."
- logger.PrintSmallBanner(message)
- fmt.Println()
-
- // Get versions
- checkSpinner.Start(message)
-
- github := cmd.NewGitHubHelper()
- var desiredVersion *cmd.SemanticVersion
- var err error
- var valid bool
-
- if len(specificVersion) > 0 {
- // Check if this is a valid version
- valid, err = github.IsValidTag(specificVersion)
- if err == nil {
- if !valid {
- err = fmt.Errorf("version '%s' is invalid", specificVersion)
- } else {
- desiredVersion, err = cmd.NewSemanticVersion(specificVersion)
- }
- }
- } else {
- if prereleaseRequired {
- desiredVersion, err = github.GetLatestPreRelease()
- } else {
- desiredVersion, err = github.GetLatestStableRelease()
- }
- }
- if err != nil {
- checkSpinner.Error(err.Error())
- return err
- }
- checkSpinner.Success()
- fmt.Println()
-
- fmt.Println(" Current Version : " + cmd.Version)
-
- if len(specificVersion) > 0 {
- fmt.Printf(" Desired Version : v%s\n", desiredVersion)
- } else {
- if prereleaseRequired {
- fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion)
- } else {
- fmt.Printf(" Latest Release : v%s\n", desiredVersion)
- }
- }
-
- return updateToVersion(desiredVersion, len(specificVersion) > 0)
- })
-}
-
-func updateToVersion(targetVersion *cmd.SemanticVersion, force bool) error {
-
- var targetVersionString = "v" + targetVersion.String()
-
- // Early exit
- if targetVersionString == cmd.Version {
- logger.Green("Looks like you're up to date!")
- return nil
- }
-
- var desiredVersion string
-
- if !force {
-
- compareVersion := cmd.Version
-
- currentVersion, err := cmd.NewSemanticVersion(compareVersion)
- if err != nil {
- return err
- }
-
- var success bool
-
- // Release -> Pre-Release = Massage current version to prerelease format
- if targetVersion.IsPreRelease() && currentVersion.IsRelease() {
- testVersion, err := cmd.NewSemanticVersion(compareVersion + "-0")
- if err != nil {
- return err
- }
- success, _ = targetVersion.IsGreaterThan(testVersion)
- }
- // Pre-Release -> Release = Massage target version to prerelease format
- if targetVersion.IsRelease() && currentVersion.IsPreRelease() {
- // We are ok with greater than or equal
- mainversion := currentVersion.MainVersion()
- targetVersion, err = cmd.NewSemanticVersion(targetVersion.String())
- if err != nil {
- return err
- }
- success, _ = targetVersion.IsGreaterThanOrEqual(mainversion)
- }
-
- // Release -> Release = Standard check
- if (targetVersion.IsRelease() && currentVersion.IsRelease()) ||
- (targetVersion.IsPreRelease() && currentVersion.IsPreRelease()) {
-
- success, _ = targetVersion.IsGreaterThan(currentVersion)
- }
-
- // Compare
- if !success {
- logger.Red("The requested version is lower than the current version.")
- logger.Red("If this is what you really want to do, use `wails update -version %s`", targetVersionString)
- return nil
- }
-
- desiredVersion = "v" + targetVersion.String()
-
- } else {
- desiredVersion = "v" + targetVersion.String()
- }
-
- fmt.Println()
- updateSpinner := spinner.NewSpinner()
- updateSpinner.SetSpinSpeed(40)
- updateSpinner.Start("Installing Wails " + desiredVersion)
-
- // Run command in non module directory
- homeDir, err := os.UserHomeDir()
- if err != nil {
- log.Fatal("Cannot find home directory! Please file a bug report!")
- }
-
- err = cmd.NewProgramHelper().RunCommandArray([]string{"go", "get", "github.com/wailsapp/wails/cmd/wails@" + desiredVersion}, homeDir)
- if err != nil {
- updateSpinner.Error(err.Error())
- return err
- }
- updateSpinner.Success()
- fmt.Println()
- logger.Green("Wails updated to " + desiredVersion)
-
- return nil
-}
diff --git a/cmd/wails/9_issue.go b/cmd/wails/9_issue.go
deleted file mode 100644
index ec0efdbb2..000000000
--- a/cmd/wails/9_issue.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package main
-
-import (
- "fmt"
- "io"
- "net/http"
- "net/url"
- "os"
- "runtime"
- "strings"
-
- "github.com/pkg/browser"
-
- "github.com/wailsapp/wails/cmd"
-)
-
-func init() {
-
- commandDescription := `Generates an issue in Github using the given title, description and system report.`
-
- initCommand := app.Command("issue", "Generates an issue in Github").
- LongDescription(commandDescription)
-
- initCommand.Action(func() error {
-
- logger.PrintSmallBanner("Generate Issue")
- fmt.Println()
- message := `Thanks for taking the time to submit an issue!
-
-To help you in this process, we will ask for some information, add Go/Wails details automatically, then prepare the issue for your editing and submission.
-`
-
- logger.Yellow(message)
-
- title := cmd.Prompt("Issue Title")
- description := cmd.Prompt("Issue Description")
-
- var str strings.Builder
-
- gomodule, exists := os.LookupEnv("GO111MODULE")
- if !exists {
- gomodule = "(Not Set)"
- }
-
- // get version numbers for GCC, node & npm
- program := cmd.NewProgramHelper()
- // string helpers
- var gccVersion, nodeVersion, npmVersion string
-
- // choose between OS (mac,linux,win)
- switch runtime.GOOS {
- case "darwin":
- gcc := program.FindProgram("gcc")
- if gcc != nil {
- stdout, _, _, _ := gcc.Run("-dumpversion")
- gccVersion = strings.TrimSpace(stdout)
- }
- case "linux":
- // for linux we have to collect
- // the distribution name
- distroInfo := cmd.GetLinuxDistroInfo()
- linuxDB := cmd.NewLinuxDB()
- distro := linuxDB.GetDistro(distroInfo.ID)
- release := distro.GetRelease(distroInfo.Release)
- gccVersionCommand := release.GccVersionCommand
-
- gcc := program.FindProgram("gcc")
- if gcc != nil {
- stdout, _, _, _ := gcc.Run(gccVersionCommand)
- gccVersion = strings.TrimSpace(stdout)
- }
- case "windows":
- gcc := program.FindProgram("gcc")
- if gcc != nil {
- stdout, _, _, _ := gcc.Run("-dumpversion")
- gccVersion = strings.TrimSpace(stdout)
- }
- }
-
- npm := program.FindProgram("npm")
- if npm != nil {
- stdout, _, _, _ := npm.Run("--version")
- npmVersion = stdout
- npmVersion = npmVersion[:len(npmVersion)-1]
- npmVersion = strings.TrimSpace(npmVersion)
- }
-
- node := program.FindProgram("node")
- if node != nil {
- stdout, _, _, _ := node.Run("--version")
- nodeVersion = stdout
- nodeVersion = nodeVersion[:len(nodeVersion)-1]
- }
-
- str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
- str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", cmd.Version))
- str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
- str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
- str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
- str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
- str.WriteString(fmt.Sprintf("| GCC | %s |\n", gccVersion))
- str.WriteString(fmt.Sprintf("| Npm | %s |\n", npmVersion))
- str.WriteString(fmt.Sprintf("| Node | %s |\n", nodeVersion))
-
- fmt.Println()
- fmt.Println("Processing template and preparing for upload.")
-
- // Grab issue template
- resp, err := http.Get("https://raw.githubusercontent.com/wailsapp/wails/master/.github/ISSUE_TEMPLATE/bug_report.md")
- if err != nil {
- logger.Red("Unable to read in issue template. Are you online?")
- os.Exit(1)
- }
- defer resp.Body.Close()
- template, _ := io.ReadAll(resp.Body)
- body := string(template)
- body = "**Description**\n" + (strings.Split(body, "**Description**")[1])
- fullURL := "https://github.com/wailsapp/wails/issues/new?"
- body = strings.Replace(body, "A clear and concise description of what the bug is.", description, -1)
- body = strings.Replace(body, "Please provide your platform, GO version and variables, etc", str.String(), -1)
- params := "title=" + title + "&body=" + body
-
- fmt.Println("Opening browser to file issue.")
- browser.OpenURL(fullURL + url.PathEscape(params))
- return nil
- })
-}
diff --git a/cmd/wails/main.go b/cmd/wails/main.go
deleted file mode 100644
index bbcc94b32..000000000
--- a/cmd/wails/main.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-import (
- "os"
- "os/exec"
-
- "github.com/wailsapp/wails/cmd"
-)
-
-// Create Logger
-var logger = cmd.NewLogger()
-
-// Create main app
-var app = cmd.NewCli("wails", "A cli tool for building Wails applications.")
-
-// Main!
-func main() {
- err := app.Run()
- if err != nil {
- logger.Error(err.Error())
- if exitErr, ok := err.(*exec.ExitError); ok {
- os.Exit(exitErr.ExitCode())
- }
- os.Exit(1)
- }
-}
diff --git a/cmd/windows.go b/cmd/windows.go
deleted file mode 100644
index 1a85f13c1..000000000
--- a/cmd/windows.go
+++ /dev/null
@@ -1,20 +0,0 @@
-//go:build windows
-// +build windows
-
-package cmd
-
-import (
- "os"
-
- "golang.org/x/sys/windows"
-)
-
-// Credit: https://stackoverflow.com/a/52579002
-
-func init() {
- stdout := windows.Handle(os.Stdout.Fd())
- var originalMode uint32
-
- _ = windows.GetConsoleMode(stdout, &originalMode)
- _ = windows.SetConsoleMode(stdout, originalMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
-}
diff --git a/cmd/windres.bat b/cmd/windres.bat
deleted file mode 100644
index 1ce33a4a8..000000000
--- a/cmd/windres.bat
+++ /dev/null
@@ -1 +0,0 @@
-windres.exe -o %1 %2
\ No newline at end of file
diff --git a/config.go b/config.go
deleted file mode 100644
index 0fc80c255..000000000
--- a/config.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package wails
-
-import (
- "net/url"
- "strings"
-
- "github.com/wailsapp/wails/runtime"
-)
-
-// AppConfig is the configuration structure used when creating a Wails App object
-type AppConfig struct {
- // The width and height of your application in pixels
- Width, Height int
-
- // The title to put in the title bar
- Title string
-
- // The HTML your app should use. If you leave it blank, a default will be used:
- //
- HTML string
-
- // The Javascript your app should use. Normally this should be generated by a bundler.
- JS string
-
- // The CSS your app should use. Normally this should be generated by a bundler.
- CSS string
-
- // The colour of your window. Can take "#fff", "rgb(255,255,255)", "rgba(255,255,255,1)" formats
- Colour string
-
- // Indicates whether your app should be resizable
- Resizable bool
-
- // Minimum width of a resizable window. If set, MinHeight should also be set.
- MinWidth int
-
- // Minimum height of a resizable window. If set, MinWidth should also be set.
- MinHeight int
-
- // Maximum width of a resizable window. If set, MaxHeight should also be set.
- MaxWidth int
-
- // Maximum height of a resizable window. If set, MaxWidth should also be set.
- MaxHeight int
-
- // Indicated if the devtools should be disabled
- DisableInspector bool
-}
-
-// GetWidth returns the desired width
-func (a *AppConfig) GetWidth() int {
- return a.Width
-}
-
-// GetHeight returns the desired height
-func (a *AppConfig) GetHeight() int {
- return a.Height
-}
-
-// GetTitle returns the desired window title
-func (a *AppConfig) GetTitle() string {
- return a.Title
-}
-
-// GetHTML returns the default HTML
-func (a *AppConfig) GetHTML() string {
- if len(a.HTML) > 0 {
- a.HTML = url.QueryEscape(a.HTML)
- a.HTML = "data:text/html," + strings.ReplaceAll(a.HTML, "+", "%20")
- a.HTML = strings.ReplaceAll(a.HTML, "%3D", "=")
- }
- return a.HTML
-}
-
-// GetResizable returns true if the window should be resizable
-func (a *AppConfig) GetResizable() bool {
- return a.Resizable
-}
-
-// GetMinWidth returns the minimum width of the window
-func (a *AppConfig) GetMinWidth() int {
- return a.MinWidth
-}
-
-// GetMinHeight returns the minimum height of the window
-func (a *AppConfig) GetMinHeight() int {
- return a.MinHeight
-}
-
-// GetMaxWidth returns the maximum width of the window
-func (a *AppConfig) GetMaxWidth() int {
- return a.MaxWidth
-}
-
-// GetMaxHeight returns the maximum height of the window
-func (a *AppConfig) GetMaxHeight() int {
- return a.MaxHeight
-}
-
-// GetDisableInspector returns true if the inspector should be disabled
-func (a *AppConfig) GetDisableInspector() bool {
- return a.DisableInspector
-}
-
-// GetColour returns the colour
-func (a *AppConfig) GetColour() string {
- return a.Colour
-}
-
-// GetCSS returns the user CSS
-func (a *AppConfig) GetCSS() string {
- return a.CSS
-}
-
-// GetJS returns the user Javascript
-func (a *AppConfig) GetJS() string {
- return a.JS
-}
-
-func (a *AppConfig) merge(in *AppConfig) error {
- if in.CSS != "" {
- a.CSS = in.CSS
- }
- if in.Title != "" {
- a.Title = runtime.ProcessEncoding(in.Title)
- }
-
- if in.Colour != "" {
- a.Colour = in.Colour
- }
-
- if in.HTML != "" {
- a.HTML = in.HTML
- }
-
- if in.JS != "" {
- a.JS = in.JS
- }
-
- if in.HTML != "" {
- a.HTML = in.HTML
- }
-
- if in.Width != 0 {
- a.Width = in.Width
- }
- if in.Height != 0 {
- a.Height = in.Height
- }
-
- if in.MinWidth != 0 {
- a.MinWidth = in.MinWidth
- }
-
- if in.MinHeight != 0 {
- a.MinHeight = in.MinHeight
- }
-
- if in.MaxWidth != 0 {
- a.MaxWidth = in.MaxWidth
- }
-
- if in.MaxHeight != 0 {
- a.MaxHeight = in.MaxHeight
- }
-
- a.Resizable = in.Resizable
- a.DisableInspector = in.DisableInspector
-
- return nil
-}
-
-// Creates the default configuration
-func newConfig(userConfig *AppConfig) (*AppConfig, error) {
- result := &AppConfig{
- Width: 800,
- Height: 600,
- Resizable: true,
- MinWidth: -1,
- MinHeight: -1,
- MaxWidth: -1,
- MaxHeight: -1,
- Title: "My Wails App",
- Colour: "",
- HTML: defaultHTML,
- }
-
- if userConfig != nil {
- err := result.merge(userConfig)
- if err != nil {
- return nil, err
- }
- }
-
- return result, nil
-}
-
-var defaultHTML = `
-
-
-
-
-
-
-
-
-
-
-
-`
diff --git a/go.mod b/go.mod
deleted file mode 100644
index de1bbf336..000000000
--- a/go.mod
+++ /dev/null
@@ -1,29 +0,0 @@
-module github.com/wailsapp/wails
-
-require (
- github.com/Masterminds/semver v1.4.2
- github.com/abadojack/whatlanggo v1.0.1
- github.com/fatih/color v1.7.0
- github.com/go-playground/colors v1.2.0
- github.com/gorilla/websocket v1.4.1
- github.com/jackmordaunt/icns v1.0.0
- github.com/kennygrant/sanitize v1.2.4
- github.com/leaanthony/slicer v1.4.0
- github.com/leaanthony/spinner v0.5.3
- github.com/mattn/go-colorable v0.1.1 // indirect
- github.com/mattn/go-isatty v0.0.7 // indirect
- github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
- github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
- github.com/pkg/errors v0.8.1 // indirect
- github.com/sirupsen/logrus v1.8.1
- github.com/stretchr/testify v1.3.0 // indirect
- github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
- golang.org/x/image v0.0.0-20200430140353-33d19683fad8
- golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
- golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
- golang.org/x/text v0.3.0
- gopkg.in/AlecAivazis/survey.v1 v1.8.4
- gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
-)
-
-go 1.16
diff --git a/go.sum b/go.sum
deleted file mode 100644
index 6883f786a..000000000
--- a/go.sum
+++ /dev/null
@@ -1,85 +0,0 @@
-github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
-github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
-github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
-github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
-github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
-github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
-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/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
-github.com/go-playground/colors v1.2.0/go.mod h1:miw1R2JIE19cclPxsXqNdzLZsk4DP4iF+m88bRc7kfM=
-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/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
-github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
-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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
-github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
-github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
-github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
-github.com/leaanthony/slicer v1.4.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
-github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
-github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
-github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
-github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
-github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
-github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
-github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
-github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
-github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
-github.com/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/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
-github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.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/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
-github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
-golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
-gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 h1:0efs3hwEZhFKsCoP8l6dDB1AZWMgnEl3yWXWRZTOaEA=
-gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/lib/binding/function.go b/lib/binding/function.go
deleted file mode 100644
index 9a41f0e79..000000000
--- a/lib/binding/function.go
+++ /dev/null
@@ -1,170 +0,0 @@
-package binding
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "reflect"
- "runtime"
- "strings"
-
- "github.com/wailsapp/wails/lib/logger"
-)
-
-type boundFunction struct {
- fullName string
- function reflect.Value
- functionType reflect.Type
- inputs []reflect.Type
- returnTypes []reflect.Type
- log *logger.CustomLogger
- hasErrorReturnType bool
-}
-
-// Creates a new bound function based on the given method + type
-func newBoundFunction(object interface{}) (*boundFunction, error) {
-
- objectValue := reflect.ValueOf(object)
- objectType := reflect.TypeOf(object)
-
- name := runtime.FuncForPC(objectValue.Pointer()).Name()
- if strings.Contains(name, "/") {
- parts := strings.Split(name, "/")
- name = parts[len(parts)-1]
- }
-
- result := &boundFunction{
- fullName: name,
- function: objectValue,
- functionType: objectType,
- log: logger.NewCustomLogger(name),
- }
-
- err := result.processParameters()
-
- return result, err
-}
-
-func (b *boundFunction) processParameters() error {
-
- // Param processing
- functionType := b.functionType
-
- // Input parameters
- inputParamCount := functionType.NumIn()
- if inputParamCount > 0 {
- b.inputs = make([]reflect.Type, inputParamCount)
- // We start at 1 as the first param is the struct
- for index := 0; index < inputParamCount; index++ {
- param := functionType.In(index)
- name := param.Name()
- kind := param.Kind()
- b.inputs[index] = param
- typ := param
- index := index
- b.log.DebugFields("Input param", logger.Fields{
- "index": index,
- "name": name,
- "kind": kind,
- "typ": typ,
- })
- }
- }
-
- // Process return/output declarations
- returnParamsCount := functionType.NumOut()
- // Guard against bad number of return types
- switch returnParamsCount {
- case 0:
- case 1:
- // Check if it's an error type
- param := functionType.Out(0)
- paramName := param.Name()
- if paramName == "error" {
- b.hasErrorReturnType = true
- }
- // Save return type
- b.returnTypes = append(b.returnTypes, param)
- case 2:
- // Check the second return type is an error
- secondParam := functionType.Out(1)
- secondParamName := secondParam.Name()
- if secondParamName != "error" {
- return fmt.Errorf("last return type of method '%s' must be an error (got %s)", b.fullName, secondParamName)
- }
-
- // Check the second return type is an error
- firstParam := functionType.Out(0)
- firstParamName := firstParam.Name()
- if firstParamName == "error" {
- return fmt.Errorf("first return type of method '%s' must not be an error", b.fullName)
- }
- b.hasErrorReturnType = true
-
- // Save return types
- b.returnTypes = append(b.returnTypes, firstParam)
- b.returnTypes = append(b.returnTypes, secondParam)
-
- default:
- return fmt.Errorf("cannot register method '%s' with %d return parameters. Please use up to 2", b.fullName, returnParamsCount)
- }
-
- return nil
-}
-
-// call the method with the given data
-func (b *boundFunction) call(data string) ([]reflect.Value, error) {
-
- // The data will be an array of values so we will decode the
- // input data into
- var jsArgs []interface{}
- d := json.NewDecoder(bytes.NewBufferString(data))
- // d.UseNumber()
- err := d.Decode(&jsArgs)
- if err != nil {
- return nil, fmt.Errorf("Invalid data passed to method call: %s", err.Error())
- }
-
- // Check correct number of inputs
- if len(jsArgs) != len(b.inputs) {
- return nil, fmt.Errorf("Invalid number of parameters given to %s. Expected %d but got %d", b.fullName, len(b.inputs), len(jsArgs))
- }
-
- // Set up call
- args := make([]reflect.Value, len(b.inputs))
- for index := 0; index < len(b.inputs); index++ {
-
- // Set the input values
- value, err := b.setInputValue(index, b.inputs[index], jsArgs[index])
- if err != nil {
- return nil, err
- }
- args[index] = value
- }
- b.log.Debugf("Unmarshalled Args: %+v\n", jsArgs)
- b.log.Debugf("Converted Args: %+v\n", args)
- results := b.function.Call(args)
-
- b.log.Debugf("results = %+v", results)
- return results, nil
-}
-
-// Attempts to set the method input for parameter with the given value
-func (b *boundFunction) setInputValue(index int, typ reflect.Type, val interface{}) (result reflect.Value, err error) {
-
- // Catch type conversion panics thrown by convert
- defer func() {
- if r := recover(); r != nil {
- // Modify error
- err = fmt.Errorf("%s for parameter %d of function %s", r.(string)[23:], index+1, b.fullName)
- }
- }()
-
- // Translate javascript null values
- if val == nil {
- result = reflect.Zero(typ)
- } else {
- result = reflect.ValueOf(val).Convert(typ)
- }
- return result, err
-}
diff --git a/lib/binding/internal.go b/lib/binding/internal.go
deleted file mode 100644
index ef6cf4341..000000000
--- a/lib/binding/internal.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package binding
-
-import (
- "fmt"
- "strings"
-
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
- "github.com/wailsapp/wails/runtime"
-)
-
-type internalMethods struct {
- log *logger.CustomLogger
- browser *runtime.Browser
-}
-
-func newInternalMethods() *internalMethods {
- return &internalMethods{
- log: logger.NewCustomLogger("InternalCall"),
- browser: runtime.NewBrowser(),
- }
-}
-
-func (i *internalMethods) processCall(callData *messages.CallData) (interface{}, error) {
- if !strings.HasPrefix(callData.BindingName, ".wails.") {
- return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
- }
-
- // Strip prefix
- var splitCall = strings.Split(callData.BindingName, ".")[2:]
- if len(splitCall) != 2 {
- return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
- }
-
- group := splitCall[0]
- switch group {
- case "Browser":
- return i.processBrowserCommand(splitCall[1], callData.Data)
- default:
- return nil, fmt.Errorf("Unknown internal command group '%s'", group)
- }
-}
-
-func (i *internalMethods) processBrowserCommand(command string, data interface{}) (interface{}, error) {
- switch command {
- case "OpenURL":
- url := data.(string)
- // Strip string quotes. Credit: https://stackoverflow.com/a/44222648
- if url[0] == '"' {
- url = url[1:]
- }
- if i := len(url) - 1; url[i] == '"' {
- url = url[:i]
- }
- i.log.Debugf("Calling Browser.OpenURL with '%s'", url)
- return nil, i.browser.OpenURL(url)
- case "OpenFile":
- filename := data.(string)
- // Strip string quotes. Credit: https://stackoverflow.com/a/44222648
- if filename[0] == '"' {
- filename = filename[1:]
- }
- if i := len(filename) - 1; filename[i] == '"' {
- filename = filename[:i]
- }
- i.log.Debugf("Calling Browser.OpenFile with '%s'", filename)
- return nil, i.browser.OpenFile(filename)
- default:
- return nil, fmt.Errorf("Unknown Browser command '%s'", command)
- }
-}
diff --git a/lib/binding/manager.go b/lib/binding/manager.go
deleted file mode 100644
index 70d82ddbf..000000000
--- a/lib/binding/manager.go
+++ /dev/null
@@ -1,371 +0,0 @@
-package binding
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "reflect"
- "strings"
- "unicode"
-
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
-)
-
-var typescriptDefinitionFilename = ""
-
-// Manager handles method binding
-type Manager struct {
- methods map[string]*boundMethod
- functions map[string]*boundFunction
- internalMethods *internalMethods
- initMethods []*boundMethod
- shutdownMethods []*boundMethod
- log *logger.CustomLogger
- renderer interfaces.Renderer
- runtime interfaces.Runtime // The runtime object to pass to bound structs
- objectsToBind []interface{}
- bindPackageNames bool // Package name should be considered when binding
- structList map[string][]string // structList["mystruct"] = []string{"Method1", "Method2"}
-}
-
-// NewManager creates a new Manager struct
-func NewManager() interfaces.BindingManager {
-
- result := &Manager{
- methods: make(map[string]*boundMethod),
- functions: make(map[string]*boundFunction),
- log: logger.NewCustomLogger("Bind"),
- internalMethods: newInternalMethods(),
- structList: make(map[string][]string),
- }
- return result
-}
-
-// BindPackageNames sets a flag to indicate package names should be considered when binding
-func (b *Manager) BindPackageNames() {
- b.bindPackageNames = true
-}
-
-// Start the binding manager
-func (b *Manager) Start(renderer interfaces.Renderer, runtime interfaces.Runtime) error {
- b.log.Info("Starting")
- b.renderer = renderer
- b.runtime = runtime
- err := b.initialise()
- if err != nil {
- b.log.Errorf("Binding error: %s", err.Error())
- return err
- }
- err = b.callWailsInitMethods()
- return err
-}
-
-func (b *Manager) initialise() error {
-
- var err error
- // var binding *boundMethod
-
- b.log.Info("Binding Go Functions/Methods")
-
- // Create bindings for objects
- for _, object := range b.objectsToBind {
-
- // Safeguard against nils
- if object == nil {
- return fmt.Errorf("attempted to bind nil object")
- }
-
- // Determine kind of object
- objectType := reflect.TypeOf(object)
- objectKind := objectType.Kind()
-
- switch objectKind {
- case reflect.Ptr:
- err = b.bindMethod(object)
- case reflect.Func:
- // spew.Dump(result.objectType.String())
- err = b.bindFunction(object)
- default:
- err = fmt.Errorf("cannot bind object of type '%s'", objectKind.String())
- }
-
- // Return error if set
- if err != nil {
- return err
- }
- }
-
- // If we wish to generate a typescript definition file...
- if typescriptDefinitionFilename != "" {
- err := b.generateTypescriptDefinitions()
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// Generate typescript
-func (b *Manager) generateTypescriptDefinitions() error {
-
- var output strings.Builder
-
- for structname, methodList := range b.structList {
- structname = strings.SplitN(structname, ".", 2)[1]
- output.WriteString(fmt.Sprintf("interface %s {\n", structname))
- for _, method := range methodList {
- output.WriteString(fmt.Sprintf("\t%s(...args : any[]):Promise\n", method))
- }
- output.WriteString("}\n")
- }
-
- output.WriteString("\n")
- output.WriteString("interface Backend {\n")
-
- for structname := range b.structList {
- structname = strings.SplitN(structname, ".", 2)[1]
- output.WriteString(fmt.Sprintf("\t%[1]s: %[1]s\n", structname))
- }
- output.WriteString("}\n")
-
- globals := `
-declare global {
- interface Window {
- backend: Backend;
- }
-}
-export {};`
- output.WriteString(globals)
-
- b.log.Info("Written Typescript file: " + typescriptDefinitionFilename)
-
- dir := filepath.Dir(typescriptDefinitionFilename)
- os.MkdirAll(dir, 0755)
- return os.WriteFile(typescriptDefinitionFilename, []byte(output.String()), 0755)
-}
-
-// bind the given struct method
-func (b *Manager) bindMethod(object interface{}) error {
-
- objectType := reflect.TypeOf(object)
- baseName := objectType.String()
-
- // Strip pointer if there
- if baseName[0] == '*' {
- baseName = baseName[1:]
- }
-
- b.log.Debugf("Processing struct: %s", baseName)
-
- // Calc actual name
- actualName := strings.TrimPrefix(baseName, "main.")
- if b.structList[actualName] == nil {
- b.structList[actualName] = []string{}
- }
-
- // Iterate over method definitions
- for i := 0; i < objectType.NumMethod(); i++ {
-
- // Get method definition
- methodDef := objectType.Method(i)
- methodName := methodDef.Name
- fullMethodName := baseName + "." + methodName
- method := reflect.ValueOf(object).MethodByName(methodName)
-
- b.structList[actualName] = append(b.structList[actualName], methodName)
-
- // Skip unexported methods
- if !unicode.IsUpper([]rune(methodName)[0]) {
- continue
- }
-
- // Create a new boundMethod
- newMethod, err := newBoundMethod(methodName, fullMethodName, method, objectType)
- if err != nil {
- return err
- }
-
- // Check if it's a wails init function
- if newMethod.isWailsInit {
- b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
- b.initMethods = append(b.initMethods, newMethod)
- } else if newMethod.isWailsShutdown {
- b.log.Debugf("Detected WailsShutdown function: %s", fullMethodName)
- b.shutdownMethods = append(b.shutdownMethods, newMethod)
- } else {
- // Save boundMethod
- b.log.Infof("Bound Method: %s()", fullMethodName)
- b.methods[fullMethodName] = newMethod
-
- // Inform renderer of new binding
- b.renderer.NewBinding(fullMethodName)
- }
- }
-
- return nil
-}
-
-// bind the given function object
-func (b *Manager) bindFunction(object interface{}) error {
-
- newFunction, err := newBoundFunction(object)
- if err != nil {
- return err
- }
-
- // Save method
- b.log.Infof("Bound Function: %s()", newFunction.fullName)
- b.functions[newFunction.fullName] = newFunction
-
- // Register with Renderer
- b.renderer.NewBinding(newFunction.fullName)
-
- return nil
-}
-
-// Bind saves the given object to be bound at start time
-func (b *Manager) Bind(object interface{}) {
- // Store binding
- b.objectsToBind = append(b.objectsToBind, object)
-}
-
-func (b *Manager) processInternalCall(callData *messages.CallData) (interface{}, error) {
- // Strip prefix
- return b.internalMethods.processCall(callData)
-}
-
-func (b *Manager) processFunctionCall(callData *messages.CallData) (interface{}, error) {
- // Return values
- var result []reflect.Value
- var err error
-
- function := b.functions[callData.BindingName]
- if function == nil {
- return nil, fmt.Errorf("Invalid function name '%s'", callData.BindingName)
- }
- result, err = function.call(callData.Data)
- if err != nil {
- return nil, err
- }
-
- // Do we have an error return type?
- if function.hasErrorReturnType {
- // We do - last result is an error type
- // Check if the last result was nil
- b.log.Debugf("# of return types: %d", len(function.returnTypes))
- b.log.Debugf("# of results: %d", len(result))
- errorResult := result[len(function.returnTypes)-1]
- if !errorResult.IsNil() {
- // It wasn't - we have an error
- return nil, errorResult.Interface().(error)
- }
- }
- // fmt.Printf("result = '%+v'\n", result)
- if len(result) > 0 {
- return result[0].Interface(), nil
- }
- return nil, nil
-}
-
-func (b *Manager) processMethodCall(callData *messages.CallData) (interface{}, error) {
- // Return values
- var result []reflect.Value
- var err error
-
- // do we have this method?
- method := b.methods[callData.BindingName]
- if method == nil {
- return nil, fmt.Errorf("Invalid method name '%s'", callData.BindingName)
- }
-
- result, err = method.call(callData.Data)
- if err != nil {
- return nil, err
- }
-
- // Do we have an error return type?
- if method.hasErrorReturnType {
- // We do - last result is an error type
- // Check if the last result was nil
- b.log.Debugf("# of return types: %d", len(method.returnTypes))
- b.log.Debugf("# of results: %d", len(result))
- errorResult := result[len(method.returnTypes)-1]
- if !errorResult.IsNil() {
- // It wasn't - we have an error
- return nil, errorResult.Interface().(error)
- }
- }
- if result != nil {
- return result[0].Interface(), nil
- }
- return nil, nil
-}
-
-// ProcessCall processes the given call request
-func (b *Manager) ProcessCall(callData *messages.CallData) (result interface{}, err error) {
- b.log.Debugf("Wanting to call %s", callData.BindingName)
-
- // Determine if this is function call or method call by the number of
- // dots in the binding name
- dotCount := 0
- for _, character := range callData.BindingName {
- if character == '.' {
- dotCount++
- }
- }
-
- // We need to catch reflect related panics and return
- // a decent error message
- // TODO: DEBUG THIS!
-
- defer func() {
- if r := recover(); r != nil {
- err = fmt.Errorf("%s", r.(string))
- }
- }()
-
- switch dotCount {
- case 1:
- result, err = b.processFunctionCall(callData)
- case 2:
- result, err = b.processMethodCall(callData)
- case 3:
- result, err = b.processInternalCall(callData)
- default:
- result = nil
- err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
- }
- return
-}
-
-// callWailsInitMethods calls all of the WailsInit methods that were
-// registered with the runtime object
-func (b *Manager) callWailsInitMethods() error {
- // Create reflect value for runtime object
- runtimeValue := reflect.ValueOf(b.runtime)
- params := []reflect.Value{runtimeValue}
-
- // Iterate initMethods
- for _, initMethod := range b.initMethods {
- // Call
- result := initMethod.method.Call(params)
- // Check errors
- err := result[0].Interface()
- if err != nil {
- return err.(error)
- }
- }
- return nil
-}
-
-// Shutdown the binding manager
-func (b *Manager) Shutdown() {
- b.log.Debug("Shutdown called")
- for _, method := range b.shutdownMethods {
- b.log.Debugf("Calling Shutdown for method: %s", method.fullName)
- method.call("[]")
- }
- b.log.Debug("Shutdown complete")
-}
diff --git a/lib/binding/method.go b/lib/binding/method.go
deleted file mode 100644
index 9a0a32603..000000000
--- a/lib/binding/method.go
+++ /dev/null
@@ -1,236 +0,0 @@
-package binding
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "reflect"
-
- "github.com/wailsapp/wails/lib/logger"
-)
-
-type boundMethod struct {
- Name string
- fullName string
- method reflect.Value
- inputs []reflect.Type
- returnTypes []reflect.Type
- log *logger.CustomLogger
- hasErrorReturnType bool // Indicates if there is an error return type
- isWailsInit bool
- isWailsShutdown bool
-}
-
-// Creates a new bound method based on the given method + type
-func newBoundMethod(name string, fullName string, method reflect.Value, objectType reflect.Type) (*boundMethod, error) {
- result := &boundMethod{
- Name: name,
- method: method,
- fullName: fullName,
- }
-
- // Setup logger
- result.log = logger.NewCustomLogger(result.fullName)
-
- // Check if Parameters are valid
- err := result.processParameters()
-
- // Are we a WailsInit method?
- if result.Name == "WailsInit" {
- err = result.processWailsInit()
- }
-
- // Are we a WailsShutdown method?
- if result.Name == "WailsShutdown" {
- err = result.processWailsShutdown()
- }
-
- return result, err
-}
-
-func (b *boundMethod) processParameters() error {
-
- // Param processing
- methodType := b.method.Type()
-
- // Input parameters
- inputParamCount := methodType.NumIn()
- if inputParamCount > 0 {
- b.inputs = make([]reflect.Type, inputParamCount)
- // We start at 1 as the first param is the struct
- for index := 0; index < inputParamCount; index++ {
- param := methodType.In(index)
- name := param.Name()
- kind := param.Kind()
- b.inputs[index] = param
- typ := param
- index := index
- b.log.DebugFields("Input param", logger.Fields{
- "index": index,
- "name": name,
- "kind": kind,
- "typ": typ,
- })
- }
- }
-
- // Process return/output declarations
- returnParamsCount := methodType.NumOut()
- // Guard against bad number of return types
- switch returnParamsCount {
- case 0:
- case 1:
- // Check if it's an error type
- param := methodType.Out(0)
- paramName := param.Name()
- if paramName == "error" {
- b.hasErrorReturnType = true
- }
- // Save return type
- b.returnTypes = append(b.returnTypes, param)
- case 2:
- // Check the second return type is an error
- secondParam := methodType.Out(1)
- secondParamName := secondParam.Name()
- if secondParamName != "error" {
- return fmt.Errorf("last return type of method '%s' must be an error (got %s)", b.Name, secondParamName)
- }
-
- // Check the second return type is an error
- firstParam := methodType.Out(0)
- firstParamName := firstParam.Name()
- if firstParamName == "error" {
- return fmt.Errorf("first return type of method '%s' must not be an error", b.Name)
- }
- b.hasErrorReturnType = true
-
- // Save return types
- b.returnTypes = append(b.returnTypes, firstParam)
- b.returnTypes = append(b.returnTypes, secondParam)
-
- default:
- return fmt.Errorf("cannot register method '%s' with %d return parameters. Please use up to 2", b.Name, returnParamsCount)
- }
-
- return nil
-}
-
-// call the method with the given data
-func (b *boundMethod) call(data string) ([]reflect.Value, error) {
-
- // The data will be an array of values so we will decode the
- // input data into
- var jsArgs []interface{}
- d := json.NewDecoder(bytes.NewBufferString(data))
- // d.UseNumber()
- err := d.Decode(&jsArgs)
- if err != nil {
- return nil, fmt.Errorf("Invalid data passed to method call: %s", err.Error())
- }
-
- // Check correct number of inputs
- if len(jsArgs) != len(b.inputs) {
- return nil, fmt.Errorf("Invalid number of parameters given to %s. Expected %d but got %d", b.fullName, len(b.inputs), len(jsArgs))
- }
-
- // Set up call
- args := make([]reflect.Value, len(b.inputs))
- for index := 0; index < len(b.inputs); index++ {
-
- // Set the input values
- value, err := b.setInputValue(index, b.inputs[index], jsArgs[index])
- if err != nil {
- return nil, err
- }
- args[index] = value
- }
- b.log.Debugf("Unmarshalled Args: %+v\n", jsArgs)
- b.log.Debugf("Converted Args: %+v\n", args)
- results := b.method.Call(args)
-
- b.log.Debugf("results = %+v", results)
- return results, nil
-}
-
-// Attempts to set the method input for parameter with the given value
-func (b *boundMethod) setInputValue(index int, typ reflect.Type, val interface{}) (result reflect.Value, err error) {
-
- // Catch type conversion panics thrown by convert
- defer func() {
- if r := recover(); r != nil {
- // Modify error
- fmt.Printf("Recovery message: %+v\n", r)
- err = fmt.Errorf("%s for parameter %d of method %s", r.(string)[23:], index+1, b.fullName)
- }
- }()
-
- // Do the conversion
- // Handle nil values
- if val == nil {
- switch typ.Kind() {
- case reflect.Chan,
- reflect.Func,
- reflect.Interface,
- reflect.Map,
- reflect.Ptr,
- reflect.Slice:
- b.log.Debug("Converting nil to type")
- result = reflect.ValueOf(val).Convert(typ)
- default:
- b.log.Debug("Cannot convert nil to type, returning error")
- return reflect.Zero(typ), fmt.Errorf("Unable to use null value for parameter %d of method %s", index+1, b.fullName)
- }
- } else {
- result = reflect.ValueOf(val).Convert(typ)
- }
-
- return result, err
-}
-
-func (b *boundMethod) processWailsInit() error {
- // We must have only 1 input, it must be *wails.Runtime
- if len(b.inputs) != 1 {
- return fmt.Errorf("Invalid WailsInit() definition. Expected 1 input, but got %d", len(b.inputs))
- }
-
- // It must be *wails.Runtime
- inputName := b.inputs[0].String()
- b.log.Debugf("WailsInit input type: %s", inputName)
- if inputName != "*runtime.Runtime" {
- return fmt.Errorf("Invalid WailsInit() definition. Expected input to be wails.Runtime, but got %s", inputName)
- }
-
- // We must have only 1 output, it must be error
- if len(b.returnTypes) != 1 {
- return fmt.Errorf("Invalid WailsInit() definition. Expected 1 return type, but got %d", len(b.returnTypes))
- }
-
- // It must be *wails.Runtime
- outputName := b.returnTypes[0].String()
- b.log.Debugf("WailsInit output type: %s", outputName)
- if outputName != "error" {
- return fmt.Errorf("Invalid WailsInit() definition. Expected input to be error, but got %s", outputName)
- }
-
- // We are indeed a wails Init method
- b.isWailsInit = true
-
- return nil
-}
-
-func (b *boundMethod) processWailsShutdown() error {
- // We must not have any inputs
- if len(b.inputs) != 0 {
- return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
- }
-
- // We must have only 1 output, it must be error
- if len(b.returnTypes) != 0 {
- return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 return types, but got %d", len(b.returnTypes))
- }
-
- // We are indeed a wails Shutdown method
- b.isWailsShutdown = true
-
- return nil
-}
diff --git a/lib/event/manager.go b/lib/event/manager.go
deleted file mode 100644
index e4f69946e..000000000
--- a/lib/event/manager.go
+++ /dev/null
@@ -1,180 +0,0 @@
-package event
-
-import (
- "fmt"
- "sync"
-
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
-)
-
-// Manager handles and processes events
-type Manager struct {
- incomingEvents chan *messages.EventData
- quitChannel chan struct{}
- listeners map[string][]*eventListener
- running bool
- log *logger.CustomLogger
- renderer interfaces.Renderer // Messages will be dispatched to the frontend
- wg sync.WaitGroup
- mu sync.Mutex
-}
-
-// NewManager creates a new event manager with a 100 event buffer
-func NewManager() interfaces.EventManager {
- return &Manager{
- incomingEvents: make(chan *messages.EventData, 100),
- quitChannel: make(chan struct{}, 1),
- listeners: make(map[string][]*eventListener),
- running: false,
- log: logger.NewCustomLogger("Events"),
- }
-}
-
-// PushEvent places the given event on to the event queue
-func (e *Manager) PushEvent(eventData *messages.EventData) {
- e.incomingEvents <- eventData
-}
-
-// eventListener holds a callback function which is invoked when
-// the event listened for is emitted. It has a counter which indicates
-// how the total number of events it is interested in. A value of zero
-// means it does not expire (default).
-type eventListener struct {
- callback func(...interface{}) // Function to call with emitted event data
- counter uint // Expire after counter callbacks. 0 = infinite
- expired bool // Indicates if the listener has expired
-}
-
-// Creates a new event listener from the given callback function
-func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter uint) error {
-
- // Sanity check inputs
- if callback == nil {
- return fmt.Errorf("nil callback bassed to addEventListener")
- }
-
- // Create the callback
- listener := &eventListener{
- callback: callback,
- counter: counter,
- }
- e.mu.Lock()
- // Check event has been registered before
- if e.listeners[eventName] == nil {
- e.listeners[eventName] = []*eventListener{}
- }
-
- // Register listener
- e.listeners[eventName] = append(e.listeners[eventName], listener)
- e.mu.Unlock()
- // All good mate
- return nil
-}
-
-// On adds a listener for the given event
-func (e *Manager) On(eventName string, callback func(...interface{})) {
- // Add a persistent eventListener (counter = 0)
- err := e.addEventListener(eventName, callback, 0)
- if err != nil {
- e.log.Error(err.Error())
- }
-}
-
-// Once adds a listener for the given event that will auto remove
-// after one callback
-func (e *Manager) Once(eventName string, callback func(...interface{})) {
- // Add a persistent eventListener (counter = 0)
- err := e.addEventListener(eventName, callback, 1)
- if err != nil {
- e.log.Error(err.Error())
- }
-}
-
-// OnMultiple adds a listener for the given event that will trigger
-// at most times.
-func (e *Manager) OnMultiple(eventName string, callback func(...interface{}), counter uint) {
- // Add a persistent eventListener (counter = 0)
- err := e.addEventListener(eventName, callback, counter)
- if err != nil {
- e.log.Error(err.Error())
- }
-}
-
-// Emit broadcasts the given event to the subscribed listeners
-func (e *Manager) Emit(eventName string, optionalData ...interface{}) {
- e.incomingEvents <- &messages.EventData{Name: eventName, Data: optionalData}
-}
-
-// Start the event manager's queue processing
-func (e *Manager) Start(renderer interfaces.Renderer) {
-
- e.log.Info("Starting")
-
- // Store renderer
- e.renderer = renderer
-
- // Set up waitgroup so we can wait for goroutine to quit
- e.running = true
- e.wg.Add(1)
-
- // Run main loop in separate goroutine
- go func() {
- e.log.Info("Listening")
- for e.running {
- // TODO: Listen for application exit
- select {
- case event := <-e.incomingEvents:
- e.log.DebugFields("Got Event", logger.Fields{
- "data": event.Data,
- "name": event.Name,
- })
-
- // Notify renderer
- err := e.renderer.NotifyEvent(event)
- if err != nil {
- e.log.Error(err.Error())
- }
-
- e.mu.Lock()
-
- // Iterate listeners
- for _, listener := range e.listeners[event.Name] {
-
- if !listener.expired {
- // Call listener, perhaps with data
- if event.Data == nil {
- go listener.callback()
- } else {
- unpacked := event.Data.([]interface{})
- go listener.callback(unpacked...)
- }
- }
-
- // Update listen counter
- if listener.counter > 0 {
- listener.counter = listener.counter - 1
- if listener.counter == 0 {
- listener.expired = true
- }
- }
- }
-
- e.mu.Unlock()
-
- case <-e.quitChannel:
- e.running = false
- }
- }
- e.wg.Done()
- }()
-}
-
-// Shutdown is called when exiting the Application
-func (e *Manager) Shutdown() {
- e.log.Debug("Shutting Down")
- e.quitChannel <- struct{}{}
- e.log.Debug("Waiting for main loop to exit")
- e.wg.Wait()
-}
diff --git a/lib/interfaces/appconfig.go b/lib/interfaces/appconfig.go
deleted file mode 100644
index 2feb157a8..000000000
--- a/lib/interfaces/appconfig.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package interfaces
-
-// AppConfig is the application config interface
-type AppConfig interface {
- GetWidth() int
- GetHeight() int
- GetTitle() string
- GetMinWidth() int
- GetMinHeight() int
- GetMaxWidth() int
- GetMaxHeight() int
- GetResizable() bool
- GetHTML() string
- GetDisableInspector() bool
- GetColour() string
- GetCSS() string
- GetJS() string
-}
diff --git a/lib/interfaces/bindingmanager.go b/lib/interfaces/bindingmanager.go
deleted file mode 100644
index e145d3b95..000000000
--- a/lib/interfaces/bindingmanager.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package interfaces
-
-import "github.com/wailsapp/wails/lib/messages"
-
-// BindingManager is the binding manager interface
-type BindingManager interface {
- Bind(object interface{})
- Start(renderer Renderer, runtime Runtime) error
- ProcessCall(callData *messages.CallData) (result interface{}, err error)
- Shutdown()
-}
diff --git a/lib/interfaces/eventmanager.go b/lib/interfaces/eventmanager.go
deleted file mode 100644
index 4805ee2b2..000000000
--- a/lib/interfaces/eventmanager.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package interfaces
-
-import "github.com/wailsapp/wails/lib/messages"
-
-// EventManager is the event manager interface
-type EventManager interface {
- PushEvent(*messages.EventData)
- Emit(eventName string, optionalData ...interface{})
- OnMultiple(eventName string, callback func(...interface{}), counter uint)
- Once(eventName string, callback func(...interface{}))
- On(eventName string, callback func(...interface{}))
- Start(Renderer)
- Shutdown()
-}
diff --git a/lib/interfaces/ipcmanager.go b/lib/interfaces/ipcmanager.go
deleted file mode 100644
index bc6a3cc00..000000000
--- a/lib/interfaces/ipcmanager.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package interfaces
-
-// CallbackFunc defines the signature of a function required to be provided to the
-// Dispatch function so that the response may be returned
-type CallbackFunc func(string) error
-
-// IPCManager is the event manager interface
-type IPCManager interface {
- BindRenderer(Renderer)
- Dispatch(message string, f CallbackFunc)
- Start(eventManager EventManager, bindingManager BindingManager)
- Shutdown()
-}
diff --git a/lib/interfaces/renderer.go b/lib/interfaces/renderer.go
deleted file mode 100644
index 8f5dbfb36..000000000
--- a/lib/interfaces/renderer.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package interfaces
-
-import (
- "github.com/wailsapp/wails/lib/messages"
-)
-
-// Renderer is an interface describing a Wails target to render the app to
-type Renderer interface {
- Initialise(AppConfig, IPCManager, EventManager) error
- Run() error
-
- // Binding
- NewBinding(bindingName string) error
-
- // Events
- NotifyEvent(eventData *messages.EventData) error
-
- // Dialog Runtime
- SelectFile(title string, filter string) string
- SelectDirectory() string
- SelectSaveFile(title string, filter string) string
-
- // Window Runtime
- SetColour(string) error
-
- SetMinSize(width, height int)
- SetMaxSize(width, height int)
-
- Fullscreen()
- UnFullscreen()
- SetTitle(title string)
- Close()
-}
diff --git a/lib/interfaces/runtime.go b/lib/interfaces/runtime.go
deleted file mode 100644
index dfc0e6bc0..000000000
--- a/lib/interfaces/runtime.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package interfaces
-
-// Runtime interface
-type Runtime interface{}
diff --git a/lib/ipc/call.go b/lib/ipc/call.go
deleted file mode 100644
index f332e7407..000000000
--- a/lib/ipc/call.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package ipc
-
-import (
- "fmt"
-
- "github.com/wailsapp/wails/lib/messages"
-)
-
-func init() {
- messageProcessors["call"] = processCallData
-}
-
-func processCallData(message *ipcMessage) (*ipcMessage, error) {
-
- var payload messages.CallData
-
- // Decode binding call data
- payloadMap := message.Payload.(map[string]interface{})
-
- // Check for binding name
- if payloadMap["bindingName"] == nil {
- return nil, fmt.Errorf("bindingName not given in call")
- }
- payload.BindingName = payloadMap["bindingName"].(string)
-
- // Check for data
- if payloadMap["data"] != nil {
- payload.Data = payloadMap["data"].(string)
- }
-
- // Reassign payload to decoded data
- message.Payload = &payload
-
- return message, nil
-}
diff --git a/lib/ipc/event.go b/lib/ipc/event.go
deleted file mode 100644
index 9dc9b1afc..000000000
--- a/lib/ipc/event.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package ipc
-
-import (
- "encoding/json"
-
- "github.com/wailsapp/wails/lib/messages"
-)
-
-// Register the message handler
-func init() {
- messageProcessors["event"] = processEventData
-}
-
-// This processes the given event message
-func processEventData(message *ipcMessage) (*ipcMessage, error) {
-
- // TODO: Is it worth double checking this is actually an event message,
- // even though that's done by the caller?
- var payload messages.EventData
-
- // Decode event data
- payloadMap := message.Payload.(map[string]interface{})
- payload.Name = payloadMap["name"].(string)
-
- // decode the payload data
- var data []interface{}
- err := json.Unmarshal([]byte(payloadMap["data"].(string)), &data)
- if err != nil {
- return nil, err
- }
- payload.Data = data
-
- // Reassign payload to decoded data
- message.Payload = &payload
-
- return message, nil
-}
diff --git a/lib/ipc/log.go b/lib/ipc/log.go
deleted file mode 100644
index 4bf75a9a9..000000000
--- a/lib/ipc/log.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package ipc
-
-import "github.com/wailsapp/wails/lib/messages"
-
-// Register the message handler
-func init() {
- messageProcessors["log"] = processLogData
-}
-
-// This processes the given log message
-func processLogData(message *ipcMessage) (*ipcMessage, error) {
-
- var payload messages.LogData
-
- // Decode event data
- payloadMap := message.Payload.(map[string]interface{})
- payload.Level = payloadMap["level"].(string)
- payload.Message = payloadMap["message"].(string)
-
- // Reassign payload to decoded data
- message.Payload = &payload
-
- return message, nil
-}
diff --git a/lib/ipc/manager.go b/lib/ipc/manager.go
deleted file mode 100644
index 8cff6e3db..000000000
--- a/lib/ipc/manager.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package ipc
-
-import (
- "fmt"
- "sync"
-
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
-)
-
-// Manager manages the IPC subsystem
-type Manager struct {
- renderer interfaces.Renderer // The renderer
- messageQueue chan *ipcMessage
- quitChannel chan struct{}
- // signals chan os.Signal
- log *logger.CustomLogger
- eventManager interfaces.EventManager
- bindingManager interfaces.BindingManager
- running bool
- wg sync.WaitGroup
-}
-
-// NewManager creates a new IPC Manager
-func NewManager() interfaces.IPCManager {
- result := &Manager{
- messageQueue: make(chan *ipcMessage, 100),
- quitChannel: make(chan struct{}),
- // signals: make(chan os.Signal, 1),
- log: logger.NewCustomLogger("IPC"),
- }
- return result
-}
-
-// BindRenderer sets the renderer, returns the dispatch function
-func (i *Manager) BindRenderer(renderer interfaces.Renderer) {
- i.renderer = renderer
-}
-
-// Start the IPC Manager
-func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager interfaces.BindingManager) {
-
- // Store manager references
- i.eventManager = eventManager
- i.bindingManager = bindingManager
-
- i.log.Info("Starting")
- // signal.Notify(manager.signals, os.Interrupt)
- i.running = true
-
- // Keep track of this goroutine
- i.wg.Add(1)
- go func() {
- for i.running {
- select {
- case incomingMessage := <-i.messageQueue:
- i.log.DebugFields("Processing message", logger.Fields{
- "1D": &incomingMessage,
- })
- switch incomingMessage.Type {
- case "call":
- callData := incomingMessage.Payload.(*messages.CallData)
- i.log.DebugFields("Processing call", logger.Fields{
- "1D": &incomingMessage,
- "bindingName": callData.BindingName,
- "data": callData.Data,
- })
- go func() {
- result, err := bindingManager.ProcessCall(callData)
- i.log.DebugFields("processed call", logger.Fields{"result": result, "err": err})
- if err != nil {
- incomingMessage.ReturnError(err.Error())
- } else {
- incomingMessage.ReturnSuccess(result)
- }
- i.log.DebugFields("Finished processing call", logger.Fields{
- "1D": &incomingMessage,
- })
- }()
- case "event":
-
- // Extract event data
- eventData := incomingMessage.Payload.(*messages.EventData)
-
- // Log
- i.log.DebugFields("Processing event", logger.Fields{
- "name": eventData.Name,
- "data": eventData.Data,
- })
-
- // Push the event to the event manager
- i.eventManager.PushEvent(eventData)
-
- // Log
- i.log.DebugFields("Finished processing event", logger.Fields{
- "name": eventData.Name,
- })
- case "log":
- logdata := incomingMessage.Payload.(*messages.LogData)
- switch logdata.Level {
- case "info":
- logger.GlobalLogger.Info(logdata.Message)
- case "debug":
- logger.GlobalLogger.Debug(logdata.Message)
- case "warning":
- logger.GlobalLogger.Warn(logdata.Message)
- case "error":
- logger.GlobalLogger.Error(logdata.Message)
- case "fatal":
- logger.GlobalLogger.Fatal(logdata.Message)
- default:
- logger.ErrorFields("Invalid log level sent", logger.Fields{
- "level": logdata.Level,
- "message": logdata.Message,
- })
- }
- default:
- i.log.Debugf("bad message sent to MessageQueue! Unknown type: %s", incomingMessage.Type)
- }
-
- // Log
- i.log.DebugFields("Finished processing message", logger.Fields{
- "1D": &incomingMessage,
- })
- case <-i.quitChannel:
- i.running = false
- }
- }
- i.log.Debug("Stopping")
- i.wg.Done()
- }()
-}
-
-// Dispatch receives JSON encoded messages from the renderer.
-// It processes the message to ensure that it is valid and places
-// the processed message on the message queue
-func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) {
-
- // Create a new IPC Message
- incomingMessage, err := newIPCMessage(message, i.SendResponse(cb))
- if err != nil {
- i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{
- "message": message,
- "error": err,
- })
- return
- }
-
- // Put message on queue
- i.log.DebugFields("Message received", map[string]interface{}{
- "type": incomingMessage.Type,
- "payload": incomingMessage.Payload,
- })
-
- // Put incoming message on the message queue
- i.messageQueue <- incomingMessage
-}
-
-// SendResponse sends the given response back to the frontend
-// It sends the data back to the correct renderer by way of the provided callback function
-func (i *Manager) SendResponse(cb interfaces.CallbackFunc) func(i *ipcResponse) error {
-
- return func(response *ipcResponse) error {
- // Serialise the Message
- data, err := response.Serialise()
- if err != nil {
- fmt.Printf(err.Error())
- return err
- }
- return cb(data)
- }
-
-}
-
-// Shutdown is called when exiting the Application
-func (i *Manager) Shutdown() {
- i.log.Debug("Shutdown called")
- i.quitChannel <- struct{}{}
- i.log.Debug("Waiting of main loop shutdown")
- i.wg.Wait()
-}
diff --git a/lib/ipc/message.go b/lib/ipc/message.go
deleted file mode 100644
index 8c09ab988..000000000
--- a/lib/ipc/message.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package ipc
-
-import (
- "encoding/json"
- "fmt"
-)
-
-// Message handler
-type messageProcessorFunc func(*ipcMessage) (*ipcMessage, error)
-
-var messageProcessors = make(map[string]messageProcessorFunc)
-
-// ipcMessage is the struct version of the Message sent from the frontend.
-// The payload has the specialised message data
-type ipcMessage struct {
- Type string `json:"type"`
- Payload interface{} `json:"payload"`
- CallbackID string `json:"callbackid,omitempty"`
- sendResponse func(*ipcResponse) error
-}
-
-func parseMessage(incomingMessage string) (*ipcMessage, error) {
- // Parse message
- var message ipcMessage
- err := json.Unmarshal([]byte(incomingMessage), &message)
- return &message, err
-}
-
-func newIPCMessage(incomingMessage string, responseFunction func(*ipcResponse) error) (*ipcMessage, error) {
-
- // Parse the Message
- message, err := parseMessage(incomingMessage)
- if err != nil {
- return nil, err
- }
-
- // Check message type is valid
- messageProcessor := messageProcessors[message.Type]
- if messageProcessor == nil {
- return nil, fmt.Errorf("unknown message type: %s", message.Type)
- }
-
- // Process message payload
- message, err = messageProcessor(message)
- if err != nil {
- return nil, err
- }
-
- // Set the response function
- message.sendResponse = responseFunction
-
- return message, nil
-}
-
-// hasCallbackID checks if the message can send an error back to the frontend
-func (m *ipcMessage) hasCallbackID() error {
- if m.CallbackID == "" {
- return fmt.Errorf("attempted to return error to message with no Callback ID")
- }
- return nil
-}
-
-// ReturnError returns an error back to the frontend
-func (m *ipcMessage) ReturnError(format string, args ...interface{}) error {
-
- // Ignore ReturnError if no callback ID given
- err := m.hasCallbackID()
- if err != nil {
- return err
- }
-
- // Create response
- response := newErrorResponse(m.CallbackID, fmt.Sprintf(format, args...))
-
- // Send response
- return m.sendResponse(response)
-}
-
-// ReturnSuccess returns a success message back with the given data
-func (m *ipcMessage) ReturnSuccess(data interface{}) error {
-
- // Ignore ReturnSuccess if no callback ID given
- err := m.hasCallbackID()
- if err != nil {
- return err
- }
-
- // Create the response
- response := newSuccessResponse(m.CallbackID, data)
-
- // Send response
- return m.sendResponse(response)
-}
diff --git a/lib/ipc/response.go b/lib/ipc/response.go
deleted file mode 100644
index 3006b3bbb..000000000
--- a/lib/ipc/response.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package ipc
-
-import (
- "encoding/hex"
- "encoding/json"
-)
-
-// ipcResponse contains the response data from an RPC call
-type ipcResponse struct {
- CallbackID string `json:"callbackid"`
- ErrorMessage string `json:"error,omitempty"`
- Data interface{} `json:"data,omitempty"`
-}
-
-// newErrorResponse returns the given error message to the frontend with the callbackid
-func newErrorResponse(callbackID string, errorMessage string) *ipcResponse {
- // Create response object
- result := &ipcResponse{
- CallbackID: callbackID,
- ErrorMessage: errorMessage,
- }
- return result
-}
-
-// newSuccessResponse returns the given data to the frontend with the callbackid
-func newSuccessResponse(callbackID string, data interface{}) *ipcResponse {
-
- // Create response object
- result := &ipcResponse{
- CallbackID: callbackID,
- Data: data,
- }
-
- return result
-}
-
-// Serialise formats the response to a string
-func (i *ipcResponse) Serialise() (string, error) {
- b, err := json.Marshal(i)
- if err != nil {
- return "", err
- }
- result := hex.EncodeToString(b)
- return result, err
-}
diff --git a/lib/logger/custom.go b/lib/logger/custom.go
deleted file mode 100644
index fd055d0e8..000000000
--- a/lib/logger/custom.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package logger
-
-// CustomLogger is a wrapper object to logrus
-type CustomLogger struct {
- prefix string
- errorOnly bool
-}
-
-// NewCustomLogger creates a new custom logger with the given prefix
-func NewCustomLogger(prefix string) *CustomLogger {
- return &CustomLogger{
- prefix: "[" + prefix + "] ",
- }
-}
-
-// Info level message
-func (c *CustomLogger) Info(message string) {
- GlobalLogger.Info(c.prefix + message)
-}
-
-// Infof - formatted message
-func (c *CustomLogger) Infof(message string, args ...interface{}) {
- GlobalLogger.Infof(c.prefix+message, args...)
-}
-
-// InfoFields - message with fields
-func (c *CustomLogger) InfoFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Info(c.prefix + message)
-}
-
-// Debug level message
-func (c *CustomLogger) Debug(message string) {
- GlobalLogger.Debug(c.prefix + message)
-}
-
-// Debugf - formatted message
-func (c *CustomLogger) Debugf(message string, args ...interface{}) {
- GlobalLogger.Debugf(c.prefix+message, args...)
-}
-
-// DebugFields - message with fields
-func (c *CustomLogger) DebugFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Debug(c.prefix + message)
-}
-
-// Warn level message
-func (c *CustomLogger) Warn(message string) {
- GlobalLogger.Warn(c.prefix + message)
-}
-
-// Warnf - formatted message
-func (c *CustomLogger) Warnf(message string, args ...interface{}) {
- GlobalLogger.Warnf(c.prefix+message, args...)
-}
-
-// WarnFields - message with fields
-func (c *CustomLogger) WarnFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Warn(c.prefix + message)
-}
-
-// Error level message
-func (c *CustomLogger) Error(message string) {
- GlobalLogger.Error(c.prefix + message)
-}
-
-// Errorf - formatted message
-func (c *CustomLogger) Errorf(message string, args ...interface{}) {
- GlobalLogger.Errorf(c.prefix+message, args...)
-}
-
-// ErrorFields - message with fields
-func (c *CustomLogger) ErrorFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Error(c.prefix + message)
-}
-
-// Fatal level message
-func (c *CustomLogger) Fatal(message string) {
- GlobalLogger.Fatal(c.prefix + message)
-}
-
-// Fatalf - formatted message
-func (c *CustomLogger) Fatalf(message string, args ...interface{}) {
- GlobalLogger.Fatalf(c.prefix+message, args...)
-}
-
-// FatalFields - message with fields
-func (c *CustomLogger) FatalFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Fatal(c.prefix + message)
-}
-
-// Panic level message
-func (c *CustomLogger) Panic(message string) {
- GlobalLogger.Panic(c.prefix + message)
-}
-
-// Panicf - formatted message
-func (c *CustomLogger) Panicf(message string, args ...interface{}) {
- GlobalLogger.Panicf(c.prefix+message, args...)
-}
-
-// PanicFields - message with fields
-func (c *CustomLogger) PanicFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Panic(c.prefix + message)
-}
diff --git a/lib/logger/log.go b/lib/logger/log.go
deleted file mode 100644
index 791328645..000000000
--- a/lib/logger/log.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package logger
-
-import (
- "os"
- "strings"
-
- "github.com/sirupsen/logrus"
-)
-
-// GlobalLogger is the global logger
-var GlobalLogger = logrus.New()
-
-// Fields is used by the customLogger object to output
-// fields along with a message
-type Fields map[string]interface{}
-
-// Default options for the global logger
-func init() {
- GlobalLogger.SetOutput(os.Stdout)
- GlobalLogger.SetLevel(logrus.DebugLevel)
-}
-
-// ErrorFields is a helper for logging fields to the global logger
-func ErrorFields(message string, fields Fields) {
- GlobalLogger.WithFields(map[string]interface{}(fields)).Error(message)
-}
-
-// SetLogLevel sets the log level to the given level
-func SetLogLevel(level string) {
- switch strings.ToLower(level) {
- case "info":
- GlobalLogger.SetLevel(logrus.InfoLevel)
- case "debug":
- GlobalLogger.SetLevel(logrus.DebugLevel)
- case "warn":
- GlobalLogger.SetLevel(logrus.WarnLevel)
- case "error":
- GlobalLogger.SetLevel(logrus.ErrorLevel)
- case "fatal":
- GlobalLogger.SetLevel(logrus.FatalLevel)
- case "panic":
- GlobalLogger.SetLevel(logrus.PanicLevel)
- default:
- GlobalLogger.SetLevel(logrus.DebugLevel)
- GlobalLogger.Warnf("Log level '%s' not recognised. Setting to Debug.", level)
- }
-}
diff --git a/lib/messages/calldata.go b/lib/messages/calldata.go
deleted file mode 100644
index d3da1d414..000000000
--- a/lib/messages/calldata.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package messages
-
-// CallData represents a call to a Go function/method
-type CallData struct {
- BindingName string `json:"bindingName"`
- Data string `json:"data,omitempty"`
-}
diff --git a/lib/messages/eventdata.go b/lib/messages/eventdata.go
deleted file mode 100644
index c15ba08c1..000000000
--- a/lib/messages/eventdata.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package messages
-
-// EventData represents an event sent from the frontend
-type EventData struct {
- Name string `json:"name"`
- Data interface{} `json:"data"`
-}
diff --git a/lib/messages/logdata.go b/lib/messages/logdata.go
deleted file mode 100644
index 068b6a709..000000000
--- a/lib/messages/logdata.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package messages
-
-// LogData represents a call to log from the frontend
-type LogData struct {
- Level string `json:"level"`
- Message string `json:"string"`
-}
diff --git a/lib/renderer/bridge.go b/lib/renderer/bridge.go
deleted file mode 100644
index 44da78495..000000000
--- a/lib/renderer/bridge.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package renderer
-
-import (
- bridge "github.com/wailsapp/wails/lib/renderer/bridge"
-)
-
-// NewBridge returns a new Bridge struct
-func NewBridge() *bridge.Bridge {
- return &bridge.Bridge{}
-}
diff --git a/lib/renderer/bridge/bridge.go b/lib/renderer/bridge/bridge.go
deleted file mode 100644
index 3fd3646cb..000000000
--- a/lib/renderer/bridge/bridge.go
+++ /dev/null
@@ -1,230 +0,0 @@
-package renderer
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
- "sync"
-
- "github.com/gorilla/websocket"
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
-)
-
-type messageType int
-
-const (
- jsMessage messageType = iota
- cssMessage
- htmlMessage
- notifyMessage
- bindingMessage
- callbackMessage
- wailsRuntimeMessage
-)
-
-func (m messageType) toString() string {
- return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
-}
-
-// Bridge is a backend that opens a local web server
-// and renders the files over a websocket
-type Bridge struct {
- // Common
- log *logger.CustomLogger
- ipcManager interfaces.IPCManager
- appConfig interfaces.AppConfig
- eventManager interfaces.EventManager
- bindingCache []string
-
- // Bridge specific
- server *http.Server
-
- lock sync.Mutex
- sessions map[string]*session
-}
-
-// Initialise the Bridge Renderer
-func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
- h.sessions = map[string]*session{}
- h.ipcManager = ipcManager
- h.appConfig = appConfig
- h.eventManager = eventManager
- ipcManager.BindRenderer(h)
- h.log = logger.NewCustomLogger("Bridge")
- return nil
-}
-
-func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
- conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
- if err != nil {
- http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
- }
- h.log.Infof("Connection from frontend accepted [%s].", conn.RemoteAddr().String())
- h.startSession(conn)
-}
-
-func (h *Bridge) startSession(conn *websocket.Conn) {
- s := newSession(conn,
- h.bindingCache,
- h.ipcManager,
- logger.NewCustomLogger("BridgeSession"),
- h.eventManager)
-
- conn.SetCloseHandler(func(int, string) error {
- h.log.Infof("Connection dropped [%s].", s.Identifier())
- h.eventManager.Emit("wails:bridge:session:closed", s.Identifier())
- h.lock.Lock()
- defer h.lock.Unlock()
- delete(h.sessions, s.Identifier())
- return nil
- })
-
- h.lock.Lock()
- defer h.lock.Unlock()
- go s.start(len(h.sessions) == 0)
- h.sessions[s.Identifier()] = s
-}
-
-// Run the app in Bridge mode!
-func (h *Bridge) Run() error {
- h.server = &http.Server{Addr: ":34115"}
- http.HandleFunc("/bridge", h.wsBridgeHandler)
-
- h.log.Info("Bridge mode started.")
- h.log.Info("The frontend will connect automatically.")
-
- err := h.server.ListenAndServe()
- if err != nil && err != http.ErrServerClosed {
- h.log.Fatal(err.Error())
- }
- return err
-}
-
-// NewBinding creates a new binding with the frontend
-func (h *Bridge) NewBinding(methodName string) error {
- h.bindingCache = append(h.bindingCache, methodName)
- return nil
-}
-
-// SelectFile is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SelectFile(title string, filter string) string {
- h.log.Warn("SelectFile() unsupported in bridge mode")
- return ""
-}
-
-// SelectDirectory is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SelectDirectory() string {
- h.log.Warn("SelectDirectory() unsupported in bridge mode")
- return ""
-}
-
-// SelectSaveFile is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SelectSaveFile(title string, filter string) string {
- h.log.Warn("SelectSaveFile() unsupported in bridge mode")
- return ""
-}
-
-// NotifyEvent notifies the frontend of an event
-func (h *Bridge) NotifyEvent(event *messages.EventData) error {
-
- // Look out! Nils about!
- var err error
- if event == nil {
- err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
- h.log.Error(err.Error())
- return err
- }
-
- // Default data is a blank array
- data := []byte("[]")
-
- // Process event data
- if event.Data != nil {
- // Marshall the data
- data, err = json.Marshal(event.Data)
- if err != nil {
- h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
- return err
- }
- }
-
- // Double encode data to ensure everything is escaped correctly.
- data, err = json.Marshal(string(data))
- if err != nil {
- h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
- return err
- }
-
- message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
- dead := []*session{}
- for _, session := range h.sessions {
- err := session.evalJS(message, notifyMessage)
- if err != nil {
- h.log.Debugf("Failed to send message to %s - Removing listener : %v", session.Identifier(), err)
- h.log.Infof("Connection from [%v] unresponsive - dropping", session.Identifier())
- dead = append(dead, session)
- }
- }
- h.lock.Lock()
- defer h.lock.Unlock()
- for _, session := range dead {
- delete(h.sessions, session.Identifier())
- }
-
- return nil
-}
-
-// SetColour is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SetColour(colour string) error {
- h.log.WarnFields("SetColour ignored for Bridge more", logger.Fields{"col": colour})
- return nil
-}
-
-// SetMinSize is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SetMinSize(width, height int) {
- h.log.Warn("SetMinSize() unsupported in bridge mode")
-}
-
-// SetMaxSize is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SetMaxSize(width, height int) {
- h.log.Warn("SetMaxSize() unsupported in bridge mode")
-}
-
-// Fullscreen is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) Fullscreen() {
- h.log.Warn("Fullscreen() unsupported in bridge mode")
-}
-
-// UnFullscreen is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) UnFullscreen() {
- h.log.Warn("UnFullscreen() unsupported in bridge mode")
-}
-
-// SetTitle is currently unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) SetTitle(title string) {
- h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
-}
-
-// Close is unsupported for Bridge but required
-// for the Renderer interface
-func (h *Bridge) Close() {
- h.log.Debug("Shutting down")
- for _, session := range h.sessions {
- session.Shutdown()
- }
- err := h.server.Close()
- if err != nil {
- h.log.Errorf(err.Error())
- }
-}
diff --git a/lib/renderer/bridge/session.go b/lib/renderer/bridge/session.go
deleted file mode 100644
index c85839342..000000000
--- a/lib/renderer/bridge/session.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package renderer
-
-import (
- "time"
-
- "github.com/wailsapp/wails/runtime"
-
- "github.com/gorilla/websocket"
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
-)
-
-// TODO Move this back into bridge.go
-
-// session represents a single websocket session
-type session struct {
- bindingCache []string
- conn *websocket.Conn
- eventManager interfaces.EventManager
- log *logger.CustomLogger
- ipc interfaces.IPCManager
-
- // Mutex for writing to the socket
- shutdown chan bool
- writeChan chan []byte
-
- done bool
-}
-
-func newSession(conn *websocket.Conn, bindingCache []string, ipc interfaces.IPCManager, logger *logger.CustomLogger, eventMgr interfaces.EventManager) *session {
- return &session{
- conn: conn,
- bindingCache: bindingCache,
- ipc: ipc,
- log: logger,
- eventManager: eventMgr,
- shutdown: make(chan bool),
- writeChan: make(chan []byte, 100),
- }
-}
-
-// Identifier returns a string identifier for the remote connection.
-// Taking the form of the client's :.
-func (s *session) Identifier() string {
- if s.conn != nil {
- return s.conn.RemoteAddr().String()
- }
- return ""
-}
-
-func (s *session) sendMessage(msg string) error {
- if !s.done {
- s.writeChan <- []byte(msg)
- }
- return nil
-}
-
-func (s *session) start(firstSession bool) {
- s.log.Infof("Connected to frontend.")
- go s.writePump()
-
- s.evalJS(runtime.WailsJS, wailsRuntimeMessage)
-
- // Inject bindings
- for _, binding := range s.bindingCache {
- s.evalJS(binding, bindingMessage)
- }
- s.eventManager.Emit("wails:bridge:session:started", s.Identifier())
-
- // Emit that everything is loaded and ready
- if firstSession {
- s.eventManager.Emit("wails:ready")
- }
-
- for {
- messageType, buffer, err := s.conn.ReadMessage()
- if messageType == -1 {
- return
- }
- if err != nil {
- s.log.Errorf("Error reading message: %v", err)
- continue
- }
-
- s.log.Debugf("Got message: %#v\n", string(buffer))
-
- s.ipc.Dispatch(string(buffer), s.Callback)
-
- if s.done {
- break
- }
- }
-}
-
-// Callback sends a callback to the frontend
-func (s *session) Callback(data string) error {
- return s.evalJS(data, callbackMessage)
-}
-
-func (s *session) evalJS(js string, mtype messageType) error {
- // Prepend message type to message
- return s.sendMessage(mtype.toString() + js)
-}
-
-// Shutdown
-func (s *session) Shutdown() {
- s.done = true
- s.shutdown <- true
- s.log.Debugf("session %v exit", s.Identifier())
-}
-
-// writePump pulls messages from the writeChan and sends them to the client
-// since it uses a channel to read the messages the socket is protected without locks
-func (s *session) writePump() {
- s.log.Debugf("Session %v - writePump start", s.Identifier())
- for {
- select {
- case msg, ok := <-s.writeChan:
- s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
- if !ok {
- s.log.Debug("writeChan was closed!")
- s.conn.WriteMessage(websocket.CloseMessage, []byte{})
- return
- }
-
- if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
- s.log.Debug(err.Error())
- return
- }
- case <-s.shutdown:
- break
- }
- }
- s.log.Debug("writePump exiting...")
-}
diff --git a/lib/renderer/webview.go b/lib/renderer/webview.go
deleted file mode 100644
index 777a8560c..000000000
--- a/lib/renderer/webview.go
+++ /dev/null
@@ -1,463 +0,0 @@
-package renderer
-
-import (
- "encoding/json"
- "fmt"
- "math/rand"
- "strings"
- "sync"
- "time"
-
- "github.com/wailsapp/wails/runtime"
-
- "github.com/go-playground/colors"
- "github.com/wailsapp/wails/lib/interfaces"
- "github.com/wailsapp/wails/lib/logger"
- "github.com/wailsapp/wails/lib/messages"
- wv "github.com/wailsapp/wails/lib/renderer/webview"
-)
-
-// WebView defines the main webview application window
-// Default values in []
-
-// UseFirebug indicates whether to inject the firebug console
-var UseFirebug = ""
-
-type WebView struct {
- window wv.WebView // The webview object
- ipc interfaces.IPCManager
- log *logger.CustomLogger
- config interfaces.AppConfig
- eventManager interfaces.EventManager
- bindingCache []string
- maximumSizeSet bool
-}
-
-// NewWebView returns a new WebView struct
-func NewWebView() *WebView {
- return &WebView{}
-}
-
-// Initialise sets up the WebView
-func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCManager, eventManager interfaces.EventManager) error {
-
- // Store reference to eventManager
- w.eventManager = eventManager
-
- // Set up logger
- w.log = logger.NewCustomLogger("WebView")
-
- // Set up the dispatcher function
- w.ipc = ipc
- ipc.BindRenderer(w)
-
- // Save the config
- w.config = config
-
- width := config.GetWidth()
- height := config.GetHeight()
-
- // Clamp width and height
- minWidth, minHeight := config.GetMinWidth(), config.GetMinHeight()
- maxWidth, maxHeight := config.GetMaxWidth(), config.GetMaxHeight()
- setMinSize := minWidth != -1 && minHeight != -1
- setMaxSize := maxWidth != -1 && maxHeight != -1
-
- if setMinSize {
- if width < minWidth {
- width = minWidth
- }
- if height < minHeight {
- height = minHeight
- }
- }
-
- if setMaxSize {
- if width > maxWidth {
- width = maxWidth
- }
- if height > maxHeight {
- height = maxHeight
- }
- }
-
- // Create the WebView instance
- w.window = wv.NewWebview(wv.Settings{
- Width: width,
- Height: height,
- Title: config.GetTitle(),
- Resizable: config.GetResizable(),
- URL: config.GetHTML(),
- Debug: !config.GetDisableInspector(),
- ExternalInvokeCallback: func(_ wv.WebView, message string) {
- w.ipc.Dispatch(message, w.callback)
- },
- })
-
- // Set minimum and maximum sizes
- if setMinSize {
- w.SetMinSize(minWidth, minHeight)
- }
- if setMaxSize {
- w.SetMaxSize(maxWidth, maxHeight)
- }
-
- // Set minimum and maximum sizes
- if setMinSize {
- w.SetMinSize(minWidth, minHeight)
- }
- if setMaxSize {
- w.SetMaxSize(maxWidth, maxHeight)
- }
-
- // SignalManager.OnExit(w.Exit)
-
- // Set colour
- color := config.GetColour()
- if color != "" {
- err := w.SetColour(color)
- if err != nil {
- return err
- }
- }
-
- w.log.Info("Initialised")
- return nil
-}
-
-// SetColour sets the window colour
-func (w *WebView) SetColour(colour string) error {
- color, err := colors.Parse(colour)
- if err != nil {
- return err
- }
- rgba := color.ToRGBA()
- alpha := uint8(255 * rgba.A)
- w.window.Dispatch(func() {
- w.window.SetColor(rgba.R, rgba.G, rgba.B, alpha)
- })
-
- return nil
-}
-
-// evalJS evaluates the given js in the WebView
-// I should rename this to evilJS lol
-func (w *WebView) evalJS(js string) error {
- outputJS := fmt.Sprintf("%.45s", js)
- if len(js) > 45 {
- outputJS += "..."
- }
- w.log.DebugFields("Eval", logger.Fields{"js": outputJS})
- //
- w.window.Dispatch(func() {
- w.window.Eval(js)
- })
- return nil
-}
-
-// Escape the Javascripts!
-func escapeJS(js string) (string, error) {
- result := strings.Replace(js, "\\", "\\\\", -1)
- result = strings.Replace(result, "'", "\\'", -1)
- result = strings.Replace(result, "\n", "\\n", -1)
- return result, nil
-}
-
-// evalJSSync evaluates the given js in the WebView synchronously
-// Do not call this from the main thread or you'll nuke your app because
-// you won't get the callback.
-func (w *WebView) evalJSSync(js string) error {
-
- minified, err := escapeJS(js)
-
- if err != nil {
- return err
- }
-
- outputJS := fmt.Sprintf("%.45s", js)
- if len(js) > 45 {
- outputJS += "..."
- }
- w.log.DebugFields("EvalSync", logger.Fields{"js": outputJS})
-
- ID := fmt.Sprintf("syncjs:%d:%d", time.Now().Unix(), rand.Intn(9999))
- var wg sync.WaitGroup
- wg.Add(1)
-
- go func() {
- exit := false
- // We are done when we receive the Callback ID
- w.log.Debug("SyncJS: sending with ID = " + ID)
- w.eventManager.On(ID, func(...interface{}) {
- w.log.Debug("SyncJS: Got callback ID = " + ID)
- wg.Done()
- exit = true
- })
- command := fmt.Sprintf("wails._.AddScript('%s', '%s')", minified, ID)
- w.window.Dispatch(func() {
- w.window.Eval(command)
- })
- for exit == false {
- time.Sleep(time.Millisecond * 1)
- }
- }()
-
- wg.Wait()
-
- return nil
-}
-
-// injectCSS adds the given CSS to the WebView
-func (w *WebView) injectCSS(css string) {
- w.window.Dispatch(func() {
- w.window.InjectCSS(css)
- })
-}
-
-// Exit closes the window
-func (w *WebView) Exit() {
- w.window.Exit()
-}
-
-// Run the window main loop
-func (w *WebView) Run() error {
-
- w.log.Info("Running...")
-
- // Inject firebug in debug mode on Windows
- if UseFirebug != "" {
- w.log.Debug("Injecting Firebug")
- w.evalJS(`window.usefirebug=true;`)
- }
-
- // Runtime assets
- w.log.DebugFields("Injecting wails JS runtime", logger.Fields{"js": runtime.WailsJS})
- w.evalJS(runtime.WailsJS)
-
- // Ping the wait channel when the wails runtime is loaded
- w.eventManager.On("wails:loaded", func(...interface{}) {
-
- // Run this in a different go routine to free up the main process
- go func() {
-
- // Inject Bindings
- for _, binding := range w.bindingCache {
- w.evalJSSync(binding)
- }
-
- // Inject user CSS
- if w.config.GetCSS() != "" {
- outputCSS := fmt.Sprintf("%.45s", w.config.GetCSS())
- if len(outputCSS) > 45 {
- outputCSS += "..."
- }
- w.log.DebugFields("Inject User CSS", logger.Fields{"css": outputCSS})
- w.injectCSS(w.config.GetCSS())
- } else {
- // Use default wails css
-
- w.log.Debug("Injecting Default Wails CSS: " + runtime.WailsCSS)
- w.injectCSS(runtime.WailsCSS)
- }
-
- // Inject user JS
- if w.config.GetJS() != "" {
- outputJS := fmt.Sprintf("%.45s", w.config.GetJS())
- if len(outputJS) > 45 {
- outputJS += "..."
- }
- w.log.DebugFields("Inject User JS", logger.Fields{"js": outputJS})
- w.evalJSSync(w.config.GetJS())
- }
-
- // Emit that everything is loaded and ready
- w.eventManager.Emit("wails:ready")
- }()
- })
-
- // Kick off main window loop
- w.window.Run()
-
- return nil
-}
-
-// NewBinding registers a new binding with the frontend
-func (w *WebView) NewBinding(methodName string) error {
- objectCode := fmt.Sprintf("window.wails._.NewBinding('%s');", methodName)
- w.bindingCache = append(w.bindingCache, objectCode)
- return nil
-}
-
-// SelectFile opens a dialog that allows the user to select a file
-func (w *WebView) SelectFile(title string, filter string) string {
- var result string
-
- // We need to run this on the main thread, however Dispatch is
- // non-blocking so we launch this in a goroutine and wait for
- // dispatch to finish before returning the result
- var wg sync.WaitGroup
- wg.Add(1)
- go func() {
- w.window.Dispatch(func() {
- result = w.window.Dialog(wv.DialogTypeOpen, 0, title, "", filter)
- wg.Done()
- })
- }()
-
- defer w.focus() // Ensure the main window is put back into focus afterwards
-
- wg.Wait()
- return result
-}
-
-// SelectDirectory opens a dialog that allows the user to select a directory
-func (w *WebView) SelectDirectory() string {
- var result string
- // We need to run this on the main thread, however Dispatch is
- // non-blocking so we launch this in a goroutine and wait for
- // dispatch to finish before returning the result
- var wg sync.WaitGroup
- wg.Add(1)
- go func() {
- w.window.Dispatch(func() {
- result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "", "")
- wg.Done()
- })
- }()
-
- defer w.focus() // Ensure the main window is put back into focus afterwards
-
- wg.Wait()
- return result
-}
-
-// SelectSaveFile opens a dialog that allows the user to select a file to save
-func (w *WebView) SelectSaveFile(title string, filter string) string {
- var result string
- // We need to run this on the main thread, however Dispatch is
- // non-blocking so we launch this in a goroutine and wait for
- // dispatch to finish before returning the result
- var wg sync.WaitGroup
- wg.Add(1)
- go func() {
- w.window.Dispatch(func() {
- result = w.window.Dialog(wv.DialogTypeSave, 0, title, "", filter)
- wg.Done()
- })
- }()
-
- defer w.focus() // Ensure the main window is put back into focus afterwards
-
- wg.Wait()
- return result
-}
-
-// focus puts the main window into focus
-func (w *WebView) focus() {
- w.window.Dispatch(func() {
- w.window.Focus()
- })
-}
-
-// callback sends a callback to the frontend
-func (w *WebView) callback(data string) error {
- callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
- return w.evalJS(callbackCMD)
-}
-
-// NotifyEvent notifies the frontend about a backend runtime event
-func (w *WebView) NotifyEvent(event *messages.EventData) error {
-
- // Look out! Nils about!
- var err error
- if event == nil {
- err = fmt.Errorf("Sent nil event to renderer.WebView")
- w.log.Error(err.Error())
- return err
- }
-
- // Default data is a blank array
- data := []byte("[]")
-
- // Process event data
- if event.Data != nil {
- // Marshall the data
- data, err = json.Marshal(event.Data)
- if err != nil {
- w.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
- return err
- }
- }
-
- // Double encode data to ensure everything is escaped correctly.
- data, err = json.Marshal(string(data))
- if err != nil {
- w.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
- return err
- }
-
- message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
- return w.evalJS(message)
-}
-
-// SetMinSize sets the minimum size of a resizable window
-func (w *WebView) SetMinSize(width, height int) {
- if w.config.GetResizable() == false {
- w.log.Warn("Cannot call SetMinSize() - App.Resizable = false")
- return
- }
- w.window.Dispatch(func() {
- w.window.SetMinSize(width, height)
- })
-}
-
-// SetMaxSize sets the maximum size of a resizable window
-func (w *WebView) SetMaxSize(width, height int) {
- if w.config.GetResizable() == false {
- w.log.Warn("Cannot call SetMaxSize() - App.Resizable = false")
- return
- }
- w.maximumSizeSet = true
- w.window.Dispatch(func() {
- w.window.SetMaxSize(width, height)
- })
-}
-
-// Fullscreen makes the main window go fullscreen
-func (w *WebView) Fullscreen() {
- if w.config.GetResizable() == false {
- w.log.Warn("Cannot call Fullscreen() - App.Resizable = false")
- return
- } else if w.maximumSizeSet {
- w.log.Warn("Cannot call Fullscreen() - Maximum size of window set")
- return
- }
- w.window.Dispatch(func() {
- w.window.SetFullscreen(true)
- })
-}
-
-// UnFullscreen returns the window to the position prior to a fullscreen call
-func (w *WebView) UnFullscreen() {
- if w.config.GetResizable() == false {
- w.log.Warn("Cannot call UnFullscreen() - App.Resizable = false")
- return
- }
- w.window.Dispatch(func() {
- w.window.SetFullscreen(false)
- })
-}
-
-// SetTitle sets the window title
-func (w *WebView) SetTitle(title string) {
- w.window.Dispatch(func() {
- w.window.SetTitle(title)
- })
-}
-
-// Close closes the window
-func (w *WebView) Close() {
- w.window.Dispatch(func() {
- w.window.Terminate()
- })
-}
diff --git a/lib/renderer/webview/LICENSE b/lib/renderer/webview/LICENSE
deleted file mode 100644
index b18604bf4..000000000
--- a/lib/renderer/webview/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 Serge Zaitsev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/lib/renderer/webview/webview.go b/lib/renderer/webview/webview.go
deleted file mode 100755
index 60ce89e26..000000000
--- a/lib/renderer/webview/webview.go
+++ /dev/null
@@ -1,411 +0,0 @@
-// Package webview implements Go bindings to https://github.com/zserge/webview C library.
-// It is a modified version of webview.go from that repository
-// Bindings closely repeat the C APIs and include both, a simplified
-// single-function API to just open a full-screen webview window, and a more
-// advanced and featureful set of APIs, including Go-to-JavaScript bindings.
-//
-// The library uses gtk-webkit, Cocoa/Webkit and MSHTML (IE8..11) as a browser
-// engine and supports Linux, MacOS and Windows 7..10 respectively.
-//
-package webview
-
-/*
-#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations
-#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
-
-#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 -std=c99
-#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
-
-#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c
-#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit
-
-#include
-#include
-#define WEBVIEW_STATIC
-#define WEBVIEW_IMPLEMENTATION
-#include "webview.h"
-
-extern void _webviewExternalInvokeCallback(void *, void *);
-
-static inline void CgoWebViewFree(void *w) {
- free((void *)((struct webview *)w)->title);
- free((void *)((struct webview *)w)->url);
- free(w);
-}
-
-static inline void *CgoWebViewCreate(int width, int height, char *title, char *url, int resizable, int debug) {
- struct webview *w = (struct webview *) calloc(1, sizeof(*w));
- w->width = width;
- w->height = height;
- w->title = title;
- w->url = url;
- w->resizable = resizable;
- w->debug = debug;
- w->external_invoke_cb = (webview_external_invoke_cb_t) _webviewExternalInvokeCallback;
- if (webview_init(w) != 0) {
- CgoWebViewFree(w);
- return NULL;
- }
- return (void *)w;
-}
-
-static inline int CgoWebViewLoop(void *w, int blocking) {
- return webview_loop((struct webview *)w, blocking);
-}
-
-static inline void CgoWebViewTerminate(void *w) {
- webview_terminate((struct webview *)w);
-}
-
-static inline void CgoWebViewExit(void *w) {
- webview_exit((struct webview *)w);
-}
-
-static inline void CgoWebViewSetTitle(void *w, char *title) {
- webview_set_title((struct webview *)w, title);
-}
-
-static inline void CgoWebViewFocus(void *w) {
- webview_focus((struct webview *)w);
-}
-
-static inline void CgoWebViewMinSize(void *w, int width, int height) {
- webview_minsize((struct webview *)w, width, height);
-}
-
-static inline void CgoWebViewMaxSize(void *w, int width, int height) {
- webview_maxsize((struct webview *)w, width, height);
-}
-
-static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
- webview_set_fullscreen((struct webview *)w, fullscreen);
-}
-
-static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
- webview_set_color((struct webview *)w, r, g, b, a);
-}
-
-static inline void CgoDialog(void *w, int dlgtype, int flags,
-char *title, char *arg, char *res, size_t ressz, char *filter) {
- webview_dialog(w, dlgtype, flags,
- (const char*)title, (const char*) arg, res, ressz, filter);
-}
-
-static inline int CgoWebViewEval(void *w, char *js) {
- return webview_eval((struct webview *)w, js);
-}
-
-static inline void CgoWebViewInjectCSS(void *w, char *css) {
- webview_inject_css((struct webview *)w, css);
-}
-
-extern void _webviewDispatchGoCallback(void *);
-static inline void _webview_dispatch_cb(struct webview *w, void *arg) {
- _webviewDispatchGoCallback(arg);
-}
-static inline void CgoWebViewDispatch(void *w, uintptr_t arg) {
- webview_dispatch((struct webview *)w, _webview_dispatch_cb, (void *)arg);
-}
-*/
-import "C"
-import (
- "errors"
- "runtime"
- "sync"
- "unsafe"
-)
-
-func init() {
- // Ensure that main.main is called from the main thread
- runtime.LockOSThread()
-}
-
-// Open is a simplified API to open a single native window with a full-size webview in
-// it. It can be helpful if you want to communicate with the core app using XHR
-// or WebSockets (as opposed to using JavaScript bindings).
-//
-// Window appearance can be customized using title, width, height and resizable parameters.
-// URL must be provided and can user either a http or https protocol, or be a
-// local file:// URL. On some platforms "data:" URLs are also supported
-// (Linux/MacOS).
-func Open(title, url string, w, h int, resizable bool) error {
- titleStr := C.CString(title)
- defer C.free(unsafe.Pointer(titleStr))
- urlStr := C.CString(url)
- defer C.free(unsafe.Pointer(urlStr))
- resize := C.int(0)
- if resizable {
- resize = C.int(1)
- }
-
- r := C.webview(titleStr, urlStr, C.int(w), C.int(h), resize)
- if r != 0 {
- return errors.New("failed to create webview")
- }
- return nil
-}
-
-// ExternalInvokeCallbackFunc is a function type that is called every time
-// "window.external.invoke()" is called from JavaScript. Data is the only
-// obligatory string parameter passed into the "invoke(data)" function from
-// JavaScript. To pass more complex data serialized JSON or base64 encoded
-// string can be used.
-type ExternalInvokeCallbackFunc func(w WebView, data string)
-
-// Settings is a set of parameters to customize the initial WebView appearance
-// and behavior. It is passed into the webview.New() constructor.
-type Settings struct {
- // WebView main window title
- Title string
- // URL to open in a webview
- URL string
- // Window width in pixels
- Width int
- // Window height in pixels
- Height int
- // Allows/disallows window resizing
- Resizable bool
- // Enable debugging tools (Linux/BSD/MacOS, on Windows use Firebug)
- Debug bool
- // A callback that is executed when JavaScript calls "window.external.invoke()"
- ExternalInvokeCallback ExternalInvokeCallbackFunc
-}
-
-// WebView is an interface that wraps the basic methods for controlling the UI
-// loop, handling multithreading and providing JavaScript bindings.
-type WebView interface {
- // Run() starts the main UI loop until the user closes the webview window or
- // Terminate() is called.
- Run()
- // Loop() runs a single iteration of the main UI.
- Loop(blocking bool) bool
- // SetTitle() changes window title. This method must be called from the main
- // thread only. See Dispatch() for more details.
- SetTitle(title string)
-
- // Focus() puts the main window into focus
- Focus()
-
- // SetMinSize() sets the minimum size of the window
- SetMinSize(width, height int)
-
- // SetMaxSize() sets the maximum size of the window
- SetMaxSize(width, height int)
-
- // SetFullscreen() controls window full-screen mode. This method must be
- // called from the main thread only. See Dispatch() for more details.
- SetFullscreen(fullscreen bool)
- // SetColor() changes window background color. This method must be called from
- // the main thread only. See Dispatch() for more details.
- SetColor(r, g, b, a uint8)
- // Eval() evaluates an arbitrary JS code inside the webview. This method must
- // be called from the main thread only. See Dispatch() for more details.
- Eval(js string) error
- // InjectJS() injects an arbitrary block of CSS code using the JS API. This
- // method must be called from the main thread only. See Dispatch() for more
- // details.
- InjectCSS(css string)
- // Dialog() opens a system dialog of the given type and title. String
- // argument can be provided for certain dialogs, such as alert boxes. For
- // alert boxes argument is a message inside the dialog box.
- Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string
- // Terminate() breaks the main UI loop. This method must be called from the main thread
- // only. See Dispatch() for more details.
- Terminate()
- // Dispatch() schedules some arbitrary function to be executed on the main UI
- // thread. This may be helpful if you want to run some JavaScript from
- // background threads/goroutines, or to terminate the app.
- Dispatch(func())
- // Exit() closes the window and cleans up the resources. Use Terminate() to
- // forcefully break out of the main UI loop.
- Exit()
-}
-
-// DialogType is an enumeration of all supported system dialog types
-type DialogType int
-
-const (
- // DialogTypeOpen is a system file open dialog
- DialogTypeOpen DialogType = iota
- // DialogTypeSave is a system file save dialog
- DialogTypeSave
- // DialogTypeAlert is a system alert dialog (message box)
- DialogTypeAlert
-)
-
-const (
- // DialogFlagFile is a normal file picker dialog
- DialogFlagFile = C.WEBVIEW_DIALOG_FLAG_FILE
- // DialogFlagDirectory is an open directory dialog
- DialogFlagDirectory = C.WEBVIEW_DIALOG_FLAG_DIRECTORY
- // DialogFlagInfo is an info alert dialog
- DialogFlagInfo = C.WEBVIEW_DIALOG_FLAG_INFO
- // DialogFlagWarning is a warning alert dialog
- DialogFlagWarning = C.WEBVIEW_DIALOG_FLAG_WARNING
- // DialogFlagError is an error dialog
- DialogFlagError = C.WEBVIEW_DIALOG_FLAG_ERROR
-)
-
-var (
- m sync.Mutex
- index uintptr
- fns = map[uintptr]func(){}
- cbs = map[WebView]ExternalInvokeCallbackFunc{}
-)
-
-type webview struct {
- w unsafe.Pointer
-}
-
-var _ WebView = &webview{}
-
-func boolToInt(b bool) int {
- if b {
- return 1
- }
- return 0
-}
-
-// NewWebview creates and opens a new webview window using the given settings. The
-// returned object implements the WebView interface. This function returns nil
-// if a window can not be created.
-func NewWebview(settings Settings) WebView {
- if settings.Width == 0 {
- settings.Width = 640
- }
- if settings.Height == 0 {
- settings.Height = 480
- }
- if settings.Title == "" {
- settings.Title = "WebView"
- }
- w := &webview{}
- w.w = C.CgoWebViewCreate(C.int(settings.Width), C.int(settings.Height),
- C.CString(settings.Title), C.CString(settings.URL),
- C.int(boolToInt(settings.Resizable)), C.int(boolToInt(settings.Debug)))
- m.Lock()
- if settings.ExternalInvokeCallback != nil {
- cbs[w] = settings.ExternalInvokeCallback
- } else {
- cbs[w] = func(w WebView, data string) {}
- }
- m.Unlock()
- return w
-}
-
-func (w *webview) Loop(blocking bool) bool {
- block := C.int(0)
- if blocking {
- block = 1
- }
- return C.CgoWebViewLoop(w.w, block) == 0
-}
-
-func (w *webview) Run() {
- for w.Loop(true) {
- }
-}
-
-func (w *webview) Exit() {
- C.CgoWebViewExit(w.w)
-}
-
-func (w *webview) Dispatch(f func()) {
- m.Lock()
- for ; fns[index] != nil; index++ {
- }
- fns[index] = f
- m.Unlock()
- C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
-}
-
-func (w *webview) SetTitle(title string) {
- p := C.CString(title)
- defer C.free(unsafe.Pointer(p))
- C.CgoWebViewSetTitle(w.w, p)
-}
-
-func (w *webview) SetColor(r, g, b, a uint8) {
- C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
-}
-
-func (w *webview) Focus() {
- C.CgoWebViewFocus(w.w)
-}
-
-func (w *webview) SetMinSize(width, height int) {
- C.CgoWebViewMinSize(w.w, C.int(width), C.int(height))
-}
-
-func (w *webview) SetMaxSize(width, height int) {
- C.CgoWebViewMaxSize(w.w, C.int(width), C.int(height))
-}
-
-func (w *webview) SetFullscreen(fullscreen bool) {
- C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
-}
-
-func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string {
- const maxPath = 4096
- titlePtr := C.CString(title)
- defer C.free(unsafe.Pointer(titlePtr))
- argPtr := C.CString(arg)
- defer C.free(unsafe.Pointer(argPtr))
- resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
- defer C.free(unsafe.Pointer(resultPtr))
- filterPtr := C.CString(filter)
- defer C.free(unsafe.Pointer(filterPtr))
- C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
- argPtr, resultPtr, C.size_t(maxPath), filterPtr)
- return C.GoString(resultPtr)
-}
-
-func (w *webview) Eval(js string) error {
- p := C.CString(js)
- defer C.free(unsafe.Pointer(p))
- switch C.CgoWebViewEval(w.w, p) {
- case -1:
- return errors.New("evaluation failed")
- }
- return nil
-}
-
-func (w *webview) InjectCSS(css string) {
- p := C.CString(css)
- defer C.free(unsafe.Pointer(p))
- C.CgoWebViewInjectCSS(w.w, p)
-}
-
-func (w *webview) Terminate() {
- C.CgoWebViewTerminate(w.w)
-}
-
-//export _webviewDispatchGoCallback
-func _webviewDispatchGoCallback(index unsafe.Pointer) {
- var f func()
- m.Lock()
- f = fns[uintptr(index)]
- delete(fns, uintptr(index))
- m.Unlock()
- if f != nil {
- f()
- }
-}
-
-//export _webviewExternalInvokeCallback
-func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) {
- m.Lock()
- var (
- cb ExternalInvokeCallbackFunc
- wv WebView
- )
- for wv, cb = range cbs {
- if wv.(*webview).w == w {
- break
- }
- }
- m.Unlock()
- if cb != nil {
- cb(wv, C.GoString((*C.char)(data)))
- }
-}
diff --git a/lib/renderer/webview/webview.h b/lib/renderer/webview/webview.h
deleted file mode 100644
index 2fb3b62d3..000000000
--- a/lib/renderer/webview/webview.h
+++ /dev/null
@@ -1,2505 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 Serge Zaitsev
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef WEBVIEW_H
-#define WEBVIEW_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#ifdef WEBVIEW_STATIC
-#define WEBVIEW_API static
-#else
-#define WEBVIEW_API extern
-#endif
-
-#include
-#include
-#include
-
-#if defined(WEBVIEW_GTK)
-#include
-#include
-#include
-
- struct webview_priv
- {
- GtkWidget *window;
- GtkWidget *scroller;
- GtkWidget *webview;
- GtkWidget *inspector_window;
- GAsyncQueue *queue;
- int ready;
- int js_busy;
- int should_exit;
-
- int min_width;
- int min_height;
- int max_width;
- int max_height;
- };
-#elif defined(WEBVIEW_WINAPI)
-#define CINTERFACE
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-struct webview_priv
-{
- HWND hwnd;
- IOleObject **browser;
- BOOL is_fullscreen;
- DWORD saved_style;
- DWORD saved_ex_style;
- RECT saved_rect;
-
- int min_width;
- int min_height;
- int max_width;
- int max_height;
-};
-#elif defined(WEBVIEW_COCOA)
-#import
-#import
-#import
-
-struct webview_priv
-{
- NSAutoreleasePool *pool;
- NSWindow *window;
- WebView *webview;
- id delegate;
- int should_exit;
-};
-#else
-#error "Define one of: WEBVIEW_GTK, WEBVIEW_COCOA or WEBVIEW_WINAPI"
-#endif
-
- struct webview;
-
- typedef void (*webview_external_invoke_cb_t)(struct webview *w,
- const char *arg);
-
- struct webview
- {
- const char *url;
- const char *title;
- int width;
- int height;
- int resizable;
- int transparentTitlebar;
- int debug;
- webview_external_invoke_cb_t external_invoke_cb;
- struct webview_priv priv;
- void *userdata;
- };
-
- enum webview_dialog_type
- {
- WEBVIEW_DIALOG_TYPE_OPEN = 0,
- WEBVIEW_DIALOG_TYPE_SAVE = 1,
- WEBVIEW_DIALOG_TYPE_ALERT = 2
- };
-
-#define WEBVIEW_DIALOG_FLAG_FILE (0 << 0)
-#define WEBVIEW_DIALOG_FLAG_DIRECTORY (1 << 0)
-
-#define WEBVIEW_DIALOG_FLAG_INFO (1 << 1)
-#define WEBVIEW_DIALOG_FLAG_WARNING (2 << 1)
-#define WEBVIEW_DIALOG_FLAG_ERROR (3 << 1)
-#define WEBVIEW_DIALOG_FLAG_ALERT_MASK (3 << 1)
-
- typedef void (*webview_dispatch_fn)(struct webview *w, void *arg);
-
- struct webview_dispatch_arg
- {
- webview_dispatch_fn fn;
- struct webview *w;
- void *arg;
- };
-
-#define DEFAULT_URL \
- "data:text/" \
- "html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%20lang=%22en%22%3E%0A%3Chead%3E%" \
- "3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22IE=edge%22%" \
- "20content=%22IE=edge%22%3E%3C%2Fhead%3E%0A%3Cbody%3E%3Cdiv%20id=%22app%22%" \
- "3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \
- "3C%2Fbody%3E%0A%3C%2Fhtml%3E"
-
-#define CSS_INJECT_FUNCTION \
- "(function(e){var " \
- "t=document.createElement('style'),d=document.head||document." \
- "getElementsByTagName('head')[0];t.setAttribute('type','text/" \
- "css'),t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document." \
- "createTextNode(e)),d.appendChild(t)})"
-
- static const char *webview_check_url(const char *url)
- {
- if (url == NULL || strlen(url) == 0)
- {
- return DEFAULT_URL;
- }
- return url;
- }
-
- WEBVIEW_API int webview(const char *title, const char *url, int width,
- int height, int resizable);
-
- WEBVIEW_API int webview_init(struct webview *w);
- WEBVIEW_API int webview_loop(struct webview *w, int blocking);
- WEBVIEW_API int webview_eval(struct webview *w, const char *js);
- WEBVIEW_API int webview_inject_css(struct webview *w, const char *css);
- WEBVIEW_API void webview_set_title(struct webview *w, const char *title);
- WEBVIEW_API void webview_focus(struct webview *w);
- WEBVIEW_API void webview_minsize(struct webview *w, int width, int height);
- WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height);
- WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen);
- WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
- uint8_t b, uint8_t a);
- WEBVIEW_API void webview_dialog(struct webview *w,
- enum webview_dialog_type dlgtype, int flags,
- const char *title, const char *arg,
- char *result, size_t resultsz, char *filter);
- WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
- void *arg);
- WEBVIEW_API void webview_terminate(struct webview *w);
- WEBVIEW_API void webview_exit(struct webview *w);
- WEBVIEW_API void webview_debug(const char *format, ...);
- WEBVIEW_API void webview_print_log(const char *s);
-
-#ifdef WEBVIEW_IMPLEMENTATION
-#undef WEBVIEW_IMPLEMENTATION
-
- WEBVIEW_API int webview(const char *title, const char *url, int width,
- int height, int resizable)
- {
- struct webview webview;
- memset(&webview, 0, sizeof(webview));
- webview.title = title;
- webview.url = url;
- webview.width = width;
- webview.height = height;
- webview.resizable = resizable;
- int r = webview_init(&webview);
- if (r != 0)
- {
- return r;
- }
- while (webview_loop(&webview, 1) == 0)
- {
- }
- webview_exit(&webview);
- return 0;
- }
-
- WEBVIEW_API void webview_debug(const char *format, ...)
- {
- char buf[4096];
- va_list ap;
- va_start(ap, format);
- vsnprintf(buf, sizeof(buf), format, ap);
- webview_print_log(buf);
- va_end(ap);
- }
-
- static int webview_js_encode(const char *s, char *esc, size_t n)
- {
- int r = 1; /* At least one byte for trailing zero */
- for (; *s; s++)
- {
- const unsigned char c = *s;
- if (c >= 0x20 && c < 0x80 && strchr("<>\\'\"", c) == NULL)
- {
- if (n > 0)
- {
- *esc++ = c;
- n--;
- }
- r++;
- }
- else
- {
- if (n > 0)
- {
- snprintf(esc, n, "\\x%02x", (int)c);
- esc += 4;
- n -= 4;
- }
- r += 4;
- }
- }
- return r;
- }
-
- WEBVIEW_API int webview_inject_css(struct webview *w, const char *css)
- {
- int n = webview_js_encode(css, NULL, 0);
- char *esc = (char *)calloc(1, sizeof(CSS_INJECT_FUNCTION) + n + 4);
- if (esc == NULL)
- {
- return -1;
- }
- char *js = (char *)calloc(1, n);
- webview_js_encode(css, js, n);
- snprintf(esc, sizeof(CSS_INJECT_FUNCTION) + n + 4, "%s(\"%s\")",
- CSS_INJECT_FUNCTION, js);
- int r = webview_eval(w, esc);
- free(js);
- free(esc);
- return r;
- }
-
-#if defined(WEBVIEW_GTK)
- static void external_message_received_cb(WebKitUserContentManager *m,
- WebKitJavascriptResult *r,
- gpointer arg)
- {
- (void)m;
- struct webview *w = (struct webview *)arg;
- if (w->external_invoke_cb == NULL)
- {
- return;
- }
- JSGlobalContextRef context = webkit_javascript_result_get_global_context(r);
- JSValueRef value = webkit_javascript_result_get_value(r);
- JSStringRef js = JSValueToStringCopy(context, value, NULL);
- size_t n = JSStringGetMaximumUTF8CStringSize(js);
- char *s = g_new(char, n);
- JSStringGetUTF8CString(js, s, n);
- w->external_invoke_cb(w, s);
- JSStringRelease(js);
- g_free(s);
- }
-
- static void webview_load_changed_cb(WebKitWebView *webview,
- WebKitLoadEvent event, gpointer arg)
- {
- (void)webview;
- struct webview *w = (struct webview *)arg;
- if (event == WEBKIT_LOAD_FINISHED)
- {
- w->priv.ready = 1;
- }
- }
-
- static void webview_destroy_cb(GtkWidget *widget, gpointer arg)
- {
- (void)widget;
- struct webview *w = (struct webview *)arg;
- webview_terminate(w);
- }
-
- static gboolean webview_context_menu_cb(WebKitWebView *webview,
- GtkWidget *default_menu,
- WebKitHitTestResult *hit_test_result,
- gboolean triggered_with_keyboard,
- gpointer userdata)
- {
- (void)webview;
- (void)default_menu;
- (void)hit_test_result;
- (void)triggered_with_keyboard;
- (void)userdata;
- return TRUE;
- }
-
- WEBVIEW_API int webview_init(struct webview *w)
- {
- if (gtk_init_check(0, NULL) == FALSE)
- {
- return -1;
- }
-
- w->priv.ready = 0;
- w->priv.should_exit = 0;
- w->priv.queue = g_async_queue_new();
- w->priv.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- w->priv.min_width = -1;
- w->priv.min_height = -1;
- w->priv.max_width = -1;
- w->priv.max_height = -1;
-
- gtk_window_set_title(GTK_WINDOW(w->priv.window), w->title);
-
- if (w->resizable)
- {
- gtk_window_set_default_size(GTK_WINDOW(w->priv.window), w->width,
- w->height);
- }
- else
- {
- gtk_widget_set_size_request(w->priv.window, w->width, w->height);
- }
- gtk_window_set_resizable(GTK_WINDOW(w->priv.window), !!w->resizable);
- gtk_window_set_position(GTK_WINDOW(w->priv.window), GTK_WIN_POS_CENTER);
-
- w->priv.scroller = gtk_scrolled_window_new(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(w->priv.window), w->priv.scroller);
-
- WebKitUserContentManager *m = webkit_user_content_manager_new();
- webkit_user_content_manager_register_script_message_handler(m, "external");
- g_signal_connect(m, "script-message-received::external",
- G_CALLBACK(external_message_received_cb), w);
-
- w->priv.webview = webkit_web_view_new_with_user_content_manager(m);
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(w->priv.webview),
- webview_check_url(w->url));
- g_signal_connect(G_OBJECT(w->priv.webview), "load-changed",
- G_CALLBACK(webview_load_changed_cb), w);
- gtk_container_add(GTK_CONTAINER(w->priv.scroller), w->priv.webview);
-
- if (w->debug)
- {
- WebKitSettings *settings =
- webkit_web_view_get_settings(WEBKIT_WEB_VIEW(w->priv.webview));
- webkit_settings_set_enable_write_console_messages_to_stdout(settings, true);
- webkit_settings_set_enable_developer_extras(settings, true);
- webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS);
- }
- else
- {
- g_signal_connect(G_OBJECT(w->priv.webview), "context-menu",
- G_CALLBACK(webview_context_menu_cb), w);
- }
-
- gtk_widget_show_all(w->priv.window);
-
- webkit_web_view_run_javascript(
- WEBKIT_WEB_VIEW(w->priv.webview),
- "window.external={invoke:function(x){"
- "window.webkit.messageHandlers.external.postMessage(x);}}",
- NULL, NULL, NULL);
-
- g_signal_connect(G_OBJECT(w->priv.window), "destroy",
- G_CALLBACK(webview_destroy_cb), w);
- return 0;
- }
-
- WEBVIEW_API int webview_loop(struct webview *w, int blocking)
- {
- gtk_main_iteration_do(blocking);
- return w->priv.should_exit;
- }
-
- WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
- {
- gtk_window_set_title(GTK_WINDOW(w->priv.window), title);
- }
-
- WEBVIEW_API void webview_focus(struct webview *w)
- {
- gtk_window_present(GTK_WINDOW(w->priv.window));
- }
-
- WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
-
- w->priv.min_width = width;
- w->priv.min_height = height;
-
- GdkGeometry hints;
- GdkWindowHints usedHints = (GdkWindowHints) GDK_HINT_MIN_SIZE;
-
- hints.min_width = w->priv.min_width;
- hints.min_height = w->priv.min_height;
- if (w->priv.max_width != -1) {
- hints.max_width = w->priv.max_width;
- hints.max_height = w->priv.max_height;
- usedHints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
- }
-
- gtk_window_set_geometry_hints(GTK_WINDOW(w->priv.window), w->priv.window, &hints, usedHints);
- }
-
- WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
-
- w->priv.max_width = width;
- w->priv.max_height = height;
-
- GdkGeometry hints;
- GdkWindowHints usedHints = (GdkWindowHints) GDK_HINT_MAX_SIZE;
-
- if (w->priv.min_width != -1) {
- hints.min_width = w->priv.min_width;
- hints.min_height = w->priv.min_height;
- usedHints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
- }
- hints.max_width = w->priv.max_width;
- hints.max_height = w->priv.max_height;
-
- gtk_window_set_geometry_hints(GTK_WINDOW(w->priv.window), w->priv.window, &hints, usedHints);
- }
-
- WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
- {
- if (fullscreen)
- {
- gtk_window_fullscreen(GTK_WINDOW(w->priv.window));
- }
- else
- {
- gtk_window_unfullscreen(GTK_WINDOW(w->priv.window));
- }
- }
-
- WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
- uint8_t b, uint8_t a)
- {
- GdkRGBA color = {r / 255.0, g / 255.0, b / 255.0, a / 255.0};
- webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(w->priv.webview),
- &color);
- }
-
- WEBVIEW_API void webview_dialog(struct webview *w,
- enum webview_dialog_type dlgtype, int flags,
- const char *title, const char *arg,
- char *result, size_t resultsz, char *filter)
- {
- GtkWidget *dlg;
- if (result != NULL)
- {
- result[0] = '\0';
- }
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
- dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
- {
- dlg = gtk_file_chooser_dialog_new(
- title, GTK_WINDOW(w->priv.window),
- (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN
- ? (flags & WEBVIEW_DIALOG_FLAG_DIRECTORY
- ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
- : GTK_FILE_CHOOSER_ACTION_OPEN)
- : GTK_FILE_CHOOSER_ACTION_SAVE),
- "_Cancel", GTK_RESPONSE_CANCEL,
- (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"),
- GTK_RESPONSE_ACCEPT, NULL);
- if (filter[0] != '\0') {
- GtkFileFilter *file_filter = gtk_file_filter_new();
- gchar **filters = g_strsplit(filter, ",", -1);
- gint i;
- for(i = 0; filters && filters[i]; i++) {
- gtk_file_filter_add_pattern(file_filter, filters[i]);
- }
- gtk_file_filter_set_name(file_filter, filter);
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dlg), file_filter);
- g_strfreev(filters);
- }
- gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE);
- gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dlg), TRUE);
- gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dlg), TRUE);
- gint response = gtk_dialog_run(GTK_DIALOG(dlg));
- if (response == GTK_RESPONSE_ACCEPT)
- {
- gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
- g_strlcpy(result, filename, resultsz);
- g_free(filename);
- }
- gtk_widget_destroy(dlg);
- }
- else if (dlgtype == WEBVIEW_DIALOG_TYPE_ALERT)
- {
- GtkMessageType type = GTK_MESSAGE_OTHER;
- switch (flags & WEBVIEW_DIALOG_FLAG_ALERT_MASK)
- {
- case WEBVIEW_DIALOG_FLAG_INFO:
- type = GTK_MESSAGE_INFO;
- break;
- case WEBVIEW_DIALOG_FLAG_WARNING:
- type = GTK_MESSAGE_WARNING;
- break;
- case WEBVIEW_DIALOG_FLAG_ERROR:
- type = GTK_MESSAGE_ERROR;
- break;
- }
- dlg = gtk_message_dialog_new(GTK_WINDOW(w->priv.window), GTK_DIALOG_MODAL,
- type, GTK_BUTTONS_OK, "%s", title);
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dlg), "%s",
- arg);
- gtk_dialog_run(GTK_DIALOG(dlg));
- gtk_widget_destroy(dlg);
- }
- }
-
- static void webview_eval_finished(GObject *object, GAsyncResult *result,
- gpointer userdata)
- {
- (void)object;
- (void)result;
- struct webview *w = (struct webview *)userdata;
- w->priv.js_busy = 0;
- }
-
- WEBVIEW_API int webview_eval(struct webview *w, const char *js)
- {
- while (w->priv.ready == 0)
- {
- g_main_context_iteration(NULL, TRUE);
- }
- w->priv.js_busy = 1;
- webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(w->priv.webview), js, NULL,
- webview_eval_finished, w);
- while (w->priv.js_busy)
- {
- g_main_context_iteration(NULL, TRUE);
- }
- return 0;
- }
-
- static gboolean webview_dispatch_wrapper(gpointer userdata)
- {
- struct webview *w = (struct webview *)userdata;
- for (;;)
- {
- struct webview_dispatch_arg *arg =
- (struct webview_dispatch_arg *)g_async_queue_try_pop(w->priv.queue);
- if (arg == NULL)
- {
- break;
- }
- (arg->fn)(w, arg->arg);
- g_free(arg);
- }
- return FALSE;
- }
-
- WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
- void *arg)
- {
- struct webview_dispatch_arg *context =
- (struct webview_dispatch_arg *)g_new(struct webview_dispatch_arg *, 1);
- context->w = w;
- context->arg = arg;
- context->fn = fn;
- g_async_queue_lock(w->priv.queue);
- g_async_queue_push_unlocked(w->priv.queue, context);
- if (g_async_queue_length_unlocked(w->priv.queue) == 1)
- {
- gdk_threads_add_idle(webview_dispatch_wrapper, w);
- }
- g_async_queue_unlock(w->priv.queue);
- }
-
- WEBVIEW_API void webview_terminate(struct webview *w)
- {
- w->priv.should_exit = 1;
- }
-
- WEBVIEW_API void webview_exit(struct webview *w) { (void)w; }
- WEBVIEW_API void webview_print_log(const char *s)
- {
- fprintf(stderr, "%s\n", s);
- }
-
-#endif /* WEBVIEW_GTK */
-
-#if defined(WEBVIEW_WINAPI)
-
-#pragma comment(lib, "user32.lib")
-#pragma comment(lib, "ole32.lib")
-#pragma comment(lib, "oleaut32.lib")
-
-#define WM_WEBVIEW_DISPATCH (WM_APP + 1)
-
- typedef struct
- {
- IOleInPlaceFrame frame;
- HWND window;
- } _IOleInPlaceFrameEx;
-
- typedef struct
- {
- IOleInPlaceSite inplace;
- _IOleInPlaceFrameEx frame;
- } _IOleInPlaceSiteEx;
-
- typedef struct
- {
- IDocHostUIHandler ui;
- } _IDocHostUIHandlerEx;
-
- typedef struct
- {
- IOleClientSite client;
- _IOleInPlaceSiteEx inplace;
- _IDocHostUIHandlerEx ui;
- IDispatch external;
- } _IOleClientSiteEx;
-
-#ifdef __cplusplus
-#define iid_ref(x) &(x)
-#define iid_unref(x) *(x)
-#else
-#define iid_ref(x) (x)
-#define iid_unref(x) (x)
-#endif
-
- static inline WCHAR *webview_to_utf16(const char *s)
- {
- DWORD size = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0);
- WCHAR *ws = (WCHAR *)GlobalAlloc(GMEM_FIXED, sizeof(WCHAR) * size);
- if (ws == NULL)
- {
- return NULL;
- }
- MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, size);
- return ws;
- }
-
- static inline char *webview_from_utf16(WCHAR *ws)
- {
- int n = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
- char *s = (char *)GlobalAlloc(GMEM_FIXED, n);
- if (s == NULL)
- {
- return NULL;
- }
- WideCharToMultiByte(CP_UTF8, 0, ws, -1, s, n, NULL, NULL);
- return s;
- }
-
- static int iid_eq(REFIID a, const IID *b)
- {
- return memcmp((const void *)iid_ref(a), (const void *)b, sizeof(GUID)) == 0;
- }
-
- static HRESULT STDMETHODCALLTYPE JS_QueryInterface(IDispatch FAR *This,
- REFIID riid,
- LPVOID FAR *ppvObj)
- {
- if (iid_eq(riid, &IID_IDispatch))
- {
- *ppvObj = This;
- return S_OK;
- }
- *ppvObj = 0;
- return E_NOINTERFACE;
- }
- static ULONG STDMETHODCALLTYPE JS_AddRef(IDispatch FAR *This) { return 1; }
- static ULONG STDMETHODCALLTYPE JS_Release(IDispatch FAR *This) { return 1; }
- static HRESULT STDMETHODCALLTYPE JS_GetTypeInfoCount(IDispatch FAR *This,
- UINT *pctinfo)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE JS_GetTypeInfo(IDispatch FAR *This,
- UINT iTInfo, LCID lcid,
- ITypeInfo **ppTInfo)
- {
- return S_OK;
- }
-#define WEBVIEW_JS_INVOKE_ID 0x1000
- static HRESULT STDMETHODCALLTYPE JS_GetIDsOfNames(IDispatch FAR *This,
- REFIID riid,
- LPOLESTR *rgszNames,
- UINT cNames, LCID lcid,
- DISPID *rgDispId)
- {
- if (cNames != 1)
- {
- return S_FALSE;
- }
- if (wcscmp(rgszNames[0], L"invoke") == 0)
- {
- rgDispId[0] = WEBVIEW_JS_INVOKE_ID;
- return S_OK;
- }
- return S_FALSE;
- }
-
- static HRESULT STDMETHODCALLTYPE
- JS_Invoke(IDispatch FAR *This, DISPID dispIdMember, REFIID riid, LCID lcid,
- WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
- EXCEPINFO *pExcepInfo, UINT *puArgErr)
- {
- size_t offset = (size_t) & ((_IOleClientSiteEx *)NULL)->external;
- _IOleClientSiteEx *ex = (_IOleClientSiteEx *)((char *)(This)-offset);
- struct webview *w = (struct webview *)GetWindowLongPtr(
- ex->inplace.frame.window, GWLP_USERDATA);
- if (pDispParams->cArgs == 1 && pDispParams->rgvarg[0].vt == VT_BSTR)
- {
- BSTR bstr = pDispParams->rgvarg[0].bstrVal;
- char *s = webview_from_utf16(bstr);
- if (s != NULL)
- {
- if (dispIdMember == WEBVIEW_JS_INVOKE_ID)
- {
- if (w->external_invoke_cb != NULL)
- {
- w->external_invoke_cb(w, s);
- }
- }
- else
- {
- return S_FALSE;
- }
- GlobalFree(s);
- }
- }
- return S_OK;
- }
-
- static IDispatchVtbl ExternalDispatchTable = {
- JS_QueryInterface, JS_AddRef, JS_Release, JS_GetTypeInfoCount,
- JS_GetTypeInfo, JS_GetIDsOfNames, JS_Invoke};
-
- static ULONG STDMETHODCALLTYPE Site_AddRef(IOleClientSite FAR *This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE Site_Release(IOleClientSite FAR *This)
- {
- return 1;
- }
- static HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite FAR *This)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite FAR *This,
- DWORD dwAssign,
- DWORD dwWhichMoniker,
- IMoniker **ppmk)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- Site_GetContainer(IOleClientSite FAR *This, LPOLECONTAINER FAR *ppContainer)
- {
- *ppContainer = 0;
- return E_NOINTERFACE;
- }
- static HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite FAR *This)
- {
- return NOERROR;
- }
- static HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite FAR *This,
- BOOL fShow)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- Site_RequestNewObjectLayout(IOleClientSite FAR *This)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR *This,
- REFIID riid,
- void **ppvObject)
- {
- if (iid_eq(riid, &IID_IUnknown) || iid_eq(riid, &IID_IOleClientSite))
- {
- *ppvObject = &((_IOleClientSiteEx *)This)->client;
- }
- else if (iid_eq(riid, &IID_IOleInPlaceSite))
- {
- *ppvObject = &((_IOleClientSiteEx *)This)->inplace;
- }
- else if (iid_eq(riid, &IID_IDocHostUIHandler))
- {
- *ppvObject = &((_IOleClientSiteEx *)This)->ui;
- }
- else
- {
- *ppvObject = 0;
- return (E_NOINTERFACE);
- }
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(
- IOleInPlaceSite FAR *This, REFIID riid, LPVOID FAR *ppvObj)
- {
- return (Site_QueryInterface(
- (IOleClientSite *)((char *)This - sizeof(IOleClientSite)), riid, ppvObj));
- }
- static ULONG STDMETHODCALLTYPE InPlace_AddRef(IOleInPlaceSite FAR *This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE InPlace_Release(IOleInPlaceSite FAR *This)
- {
- return 1;
- }
- static HRESULT STDMETHODCALLTYPE InPlace_GetWindow(IOleInPlaceSite FAR *This,
- HWND FAR *lphwnd)
- {
- *lphwnd = ((_IOleInPlaceSiteEx FAR *)This)->frame.window;
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_ContextSensitiveHelp(IOleInPlaceSite FAR *This, BOOL fEnterMode)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_CanInPlaceActivate(IOleInPlaceSite FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_OnInPlaceActivate(IOleInPlaceSite FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_OnUIActivate(IOleInPlaceSite FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE InPlace_GetWindowContext(
- IOleInPlaceSite FAR *This, LPOLEINPLACEFRAME FAR *lplpFrame,
- LPOLEINPLACEUIWINDOW FAR *lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect,
- LPOLEINPLACEFRAMEINFO lpFrameInfo)
- {
- *lplpFrame = (LPOLEINPLACEFRAME) & ((_IOleInPlaceSiteEx *)This)->frame;
- *lplpDoc = 0;
- lpFrameInfo->fMDIApp = FALSE;
- lpFrameInfo->hwndFrame = ((_IOleInPlaceFrameEx *)*lplpFrame)->window;
- lpFrameInfo->haccel = 0;
- lpFrameInfo->cAccelEntries = 0;
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE InPlace_Scroll(IOleInPlaceSite FAR *This,
- SIZE scrollExtent)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_OnUIDeactivate(IOleInPlaceSite FAR *This, BOOL fUndoable)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_OnInPlaceDeactivate(IOleInPlaceSite FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_DiscardUndoState(IOleInPlaceSite FAR *This)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_DeactivateAndUndo(IOleInPlaceSite FAR *This)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE
- InPlace_OnPosRectChange(IOleInPlaceSite FAR *This, LPCRECT lprcPosRect)
- {
- IOleObject *browserObject;
- IOleInPlaceObject *inplace;
- browserObject = *((IOleObject **)((char *)This - sizeof(IOleObject *) -
- sizeof(IOleClientSite)));
- if (!browserObject->lpVtbl->QueryInterface(browserObject,
- iid_unref(&IID_IOleInPlaceObject),
- (void **)&inplace))
- {
- inplace->lpVtbl->SetObjectRects(inplace, lprcPosRect, lprcPosRect);
- inplace->lpVtbl->Release(inplace);
- }
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE Frame_QueryInterface(
- IOleInPlaceFrame FAR *This, REFIID riid, LPVOID FAR *ppvObj)
- {
- return E_NOTIMPL;
- }
- static ULONG STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame FAR *This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame FAR *This)
- {
- return 1;
- }
- static HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame FAR *This,
- HWND FAR *lphwnd)
- {
- *lphwnd = ((_IOleInPlaceFrameEx *)This)->window;
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- Frame_ContextSensitiveHelp(IOleInPlaceFrame FAR *This, BOOL fEnterMode)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame FAR *This,
- LPRECT lprectBorder)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(
- IOleInPlaceFrame FAR *This, LPCBORDERWIDTHS pborderwidths)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(
- IOleInPlaceFrame FAR *This, LPCBORDERWIDTHS pborderwidths)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(
- IOleInPlaceFrame FAR *This, IOleInPlaceActiveObject *pActiveObject,
- LPCOLESTR pszObjName)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- Frame_InsertMenus(IOleInPlaceFrame FAR *This, HMENU hmenuShared,
- LPOLEMENUGROUPWIDTHS lpMenuWidths)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame FAR *This,
- HMENU hmenuShared,
- HOLEMENU holemenu,
- HWND hwndActiveObject)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame FAR *This,
- HMENU hmenuShared)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame FAR *This,
- LPCOLESTR pszStatusText)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- Frame_EnableModeless(IOleInPlaceFrame FAR *This, BOOL fEnable)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- Frame_TranslateAccelerator(IOleInPlaceFrame FAR *This, LPMSG lpmsg, WORD wID)
- {
- return E_NOTIMPL;
- }
- static HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler FAR *This,
- REFIID riid,
- LPVOID FAR *ppvObj)
- {
- return (Site_QueryInterface((IOleClientSite *)((char *)This -
- sizeof(IOleClientSite) -
- sizeof(_IOleInPlaceSiteEx)),
- riid, ppvObj));
- }
- static ULONG STDMETHODCALLTYPE UI_AddRef(IDocHostUIHandler FAR *This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE UI_Release(IDocHostUIHandler FAR *This)
- {
- return 1;
- }
- static HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(
- IDocHostUIHandler FAR *This, DWORD dwID, POINT __RPC_FAR *ppt,
- IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_GetHostInfo(IDocHostUIHandler FAR *This, DOCHOSTUIINFO __RPC_FAR *pInfo)
- {
- pInfo->cbSize = sizeof(DOCHOSTUIINFO);
- pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
- pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE UI_ShowUI(
- IDocHostUIHandler FAR *This, DWORD dwID,
- IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
- IOleCommandTarget __RPC_FAR *pCommandTarget,
- IOleInPlaceFrame __RPC_FAR *pFrame, IOleInPlaceUIWindow __RPC_FAR *pDoc)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler FAR *This)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler FAR *This,
- BOOL fEnable)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_OnDocWindowActivate(IDocHostUIHandler FAR *This, BOOL fActivate)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_OnFrameWindowActivate(IDocHostUIHandler FAR *This, BOOL fActivate)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_ResizeBorder(IDocHostUIHandler FAR *This, LPCRECT prcBorder,
- IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow)
- {
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_TranslateAccelerator(IDocHostUIHandler FAR *This, LPMSG lpMsg,
- const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID)
- {
- return S_FALSE;
- }
- static HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(
- IDocHostUIHandler FAR *This, LPOLESTR __RPC_FAR *pchKey, DWORD dw)
- {
- return S_FALSE;
- }
- static HRESULT STDMETHODCALLTYPE UI_GetDropTarget(
- IDocHostUIHandler FAR *This, IDropTarget __RPC_FAR *pDropTarget,
- IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget)
- {
- return S_FALSE;
- }
- static HRESULT STDMETHODCALLTYPE UI_GetExternal(
- IDocHostUIHandler FAR *This, IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
- {
- *ppDispatch = (IDispatch *)(This + 1);
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE UI_TranslateUrl(
- IDocHostUIHandler FAR *This, DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn,
- OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut)
- {
- *ppchURLOut = 0;
- return S_FALSE;
- }
- static HRESULT STDMETHODCALLTYPE
- UI_FilterDataObject(IDocHostUIHandler FAR *This, IDataObject __RPC_FAR *pDO,
- IDataObject __RPC_FAR *__RPC_FAR *ppDORet)
- {
- *ppDORet = 0;
- return S_FALSE;
- }
-
- static const TCHAR *classname = TEXT("WebView");
- static const SAFEARRAYBOUND ArrayBound = {1, 0};
-
- static IOleClientSiteVtbl MyIOleClientSiteTable = {
- Site_QueryInterface, Site_AddRef, Site_Release,
- Site_SaveObject, Site_GetMoniker, Site_GetContainer,
- Site_ShowObject, Site_OnShowWindow, Site_RequestNewObjectLayout};
- static IOleInPlaceSiteVtbl MyIOleInPlaceSiteTable = {
- InPlace_QueryInterface,
- InPlace_AddRef,
- InPlace_Release,
- InPlace_GetWindow,
- InPlace_ContextSensitiveHelp,
- InPlace_CanInPlaceActivate,
- InPlace_OnInPlaceActivate,
- InPlace_OnUIActivate,
- InPlace_GetWindowContext,
- InPlace_Scroll,
- InPlace_OnUIDeactivate,
- InPlace_OnInPlaceDeactivate,
- InPlace_DiscardUndoState,
- InPlace_DeactivateAndUndo,
- InPlace_OnPosRectChange};
-
- static IOleInPlaceFrameVtbl MyIOleInPlaceFrameTable = {
- Frame_QueryInterface,
- Frame_AddRef,
- Frame_Release,
- Frame_GetWindow,
- Frame_ContextSensitiveHelp,
- Frame_GetBorder,
- Frame_RequestBorderSpace,
- Frame_SetBorderSpace,
- Frame_SetActiveObject,
- Frame_InsertMenus,
- Frame_SetMenu,
- Frame_RemoveMenus,
- Frame_SetStatusText,
- Frame_EnableModeless,
- Frame_TranslateAccelerator};
-
- static IDocHostUIHandlerVtbl MyIDocHostUIHandlerTable = {
- UI_QueryInterface,
- UI_AddRef,
- UI_Release,
- UI_ShowContextMenu,
- UI_GetHostInfo,
- UI_ShowUI,
- UI_HideUI,
- UI_UpdateUI,
- UI_EnableModeless,
- UI_OnDocWindowActivate,
- UI_OnFrameWindowActivate,
- UI_ResizeBorder,
- UI_TranslateAccelerator,
- UI_GetOptionKeyPath,
- UI_GetDropTarget,
- UI_GetExternal,
- UI_TranslateUrl,
- UI_FilterDataObject};
-
- static void UnEmbedBrowserObject(struct webview *w)
- {
- if (w->priv.browser != NULL)
- {
- (*w->priv.browser)->lpVtbl->Close(*w->priv.browser, OLECLOSE_NOSAVE);
- (*w->priv.browser)->lpVtbl->Release(*w->priv.browser);
- GlobalFree(w->priv.browser);
- w->priv.browser = NULL;
- }
- }
-
- static int EmbedBrowserObject(struct webview *w)
- {
- RECT rect;
- IWebBrowser2 *webBrowser2 = NULL;
- LPCLASSFACTORY pClassFactory = NULL;
- _IOleClientSiteEx *_iOleClientSiteEx = NULL;
- IOleObject **browser = (IOleObject **)GlobalAlloc(
- GMEM_FIXED, sizeof(IOleObject *) + sizeof(_IOleClientSiteEx));
- if (browser == NULL)
- {
- goto error;
- }
- w->priv.browser = browser;
-
- _iOleClientSiteEx = (_IOleClientSiteEx *)(browser + 1);
- _iOleClientSiteEx->client.lpVtbl = &MyIOleClientSiteTable;
- _iOleClientSiteEx->inplace.inplace.lpVtbl = &MyIOleInPlaceSiteTable;
- _iOleClientSiteEx->inplace.frame.frame.lpVtbl = &MyIOleInPlaceFrameTable;
- _iOleClientSiteEx->inplace.frame.window = w->priv.hwnd;
- _iOleClientSiteEx->ui.ui.lpVtbl = &MyIDocHostUIHandlerTable;
- _iOleClientSiteEx->external.lpVtbl = &ExternalDispatchTable;
-
- if (CoGetClassObject(iid_unref(&CLSID_WebBrowser),
- CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, NULL,
- iid_unref(&IID_IClassFactory),
- (void **)&pClassFactory) != S_OK)
- {
- goto error;
- }
-
- if (pClassFactory == NULL)
- {
- goto error;
- }
-
- if (pClassFactory->lpVtbl->CreateInstance(pClassFactory, 0,
- iid_unref(&IID_IOleObject),
- (void **)browser) != S_OK)
- {
- goto error;
- }
- pClassFactory->lpVtbl->Release(pClassFactory);
- if ((*browser)->lpVtbl->SetClientSite(
- *browser, (IOleClientSite *)_iOleClientSiteEx) != S_OK)
- {
- goto error;
- }
- (*browser)->lpVtbl->SetHostNames(*browser, L"My Host Name", 0);
-
- if (OleSetContainedObject((struct IUnknown *)(*browser), TRUE) != S_OK)
- {
- goto error;
- }
- GetClientRect(w->priv.hwnd, &rect);
- if ((*browser)->lpVtbl->DoVerb((*browser), OLEIVERB_SHOW, NULL,
- (IOleClientSite *)_iOleClientSiteEx, -1,
- w->priv.hwnd, &rect) != S_OK)
- {
- goto error;
- }
- if ((*browser)->lpVtbl->QueryInterface((*browser),
- iid_unref(&IID_IWebBrowser2),
- (void **)&webBrowser2) != S_OK)
- {
- goto error;
- }
-
- webBrowser2->lpVtbl->put_Left(webBrowser2, 0);
- webBrowser2->lpVtbl->put_Top(webBrowser2, 0);
- webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right);
- webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom);
- webBrowser2->lpVtbl->Release(webBrowser2);
-
- return 0;
- error:
- UnEmbedBrowserObject(w);
- if (pClassFactory != NULL)
- {
- pClassFactory->lpVtbl->Release(pClassFactory);
- }
- if (browser != NULL)
- {
- GlobalFree(browser);
- }
- return -1;
- }
-
-#define WEBVIEW_DATA_URL_PREFIX "data:text/html,"
- static int DisplayHTMLPage(struct webview *w)
- {
- IWebBrowser2 *webBrowser2;
- VARIANT myURL;
- LPDISPATCH lpDispatch;
- IHTMLDocument2 *htmlDoc2;
- BSTR bstr;
- IOleObject *browserObject;
- SAFEARRAY *sfArray;
- VARIANT *pVar;
- browserObject = *w->priv.browser;
- int isDataURL = 0;
- const char *webview_url = webview_check_url(w->url);
- if (!browserObject->lpVtbl->QueryInterface(
- browserObject, iid_unref(&IID_IWebBrowser2), (void **)&webBrowser2))
- {
- LPCSTR webPageName;
- isDataURL = (strncmp(webview_url, WEBVIEW_DATA_URL_PREFIX,
- strlen(WEBVIEW_DATA_URL_PREFIX)) == 0);
- if (isDataURL)
- {
- webPageName = "about:blank";
- }
- else
- {
- webPageName = (LPCSTR)webview_url;
- }
- VariantInit(&myURL);
- myURL.vt = VT_BSTR;
- // #ifndef UNICODE
- {
- wchar_t *buffer = webview_to_utf16(webPageName);
- if (buffer == NULL)
- {
- goto badalloc;
- }
- myURL.bstrVal = SysAllocString(buffer);
- GlobalFree(buffer);
- }
- // #else
- // myURL.bstrVal = SysAllocString(webPageName);
- // #endif
- if (!myURL.bstrVal)
- {
- badalloc:
- webBrowser2->lpVtbl->Release(webBrowser2);
- return (-6);
- }
- webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0);
- VariantClear(&myURL);
- if (!isDataURL)
- {
- return 0;
- }
-
- char *url = (char *)calloc(1, strlen(webview_url) + 1);
- char *q = url;
- for (const char *p = webview_url + strlen(WEBVIEW_DATA_URL_PREFIX); *q = *p;
- p++, q++)
- {
- if (*q == '%' && *(p + 1) && *(p + 2))
- {
- sscanf(p + 1, "%02x", q);
- p = p + 2;
- }
- }
-
- if (webBrowser2->lpVtbl->get_Document(webBrowser2, &lpDispatch) == S_OK)
- {
- if (lpDispatch->lpVtbl->QueryInterface(lpDispatch,
- iid_unref(&IID_IHTMLDocument2),
- (void **)&htmlDoc2) == S_OK)
- {
- if ((sfArray = SafeArrayCreate(VT_VARIANT, 1,
- (SAFEARRAYBOUND *)&ArrayBound)))
- {
- if (!SafeArrayAccessData(sfArray, (void **)&pVar))
- {
- pVar->vt = VT_BSTR;
- // #ifndef UNICODE
- {
- wchar_t *buffer = webview_to_utf16(url);
- if (buffer == NULL)
- {
- goto release;
- }
- bstr = SysAllocString(buffer);
- GlobalFree(buffer);
- }
- // #else
- // bstr = SysAllocString(url);
- // #endif
- if ((pVar->bstrVal = bstr))
- {
- htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
- htmlDoc2->lpVtbl->close(htmlDoc2);
- }
- }
- SafeArrayDestroy(sfArray);
- }
- release:
- free(url);
- htmlDoc2->lpVtbl->Release(htmlDoc2);
- }
- lpDispatch->lpVtbl->Release(lpDispatch);
- }
- webBrowser2->lpVtbl->Release(webBrowser2);
- return (0);
- }
- return (-5);
- }
-
- static LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam)
- {
- struct webview *w = (struct webview *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- switch (uMsg)
- {
- case WM_CREATE:
- w = (struct webview *)((CREATESTRUCT *)lParam)->lpCreateParams;
- w->priv.hwnd = hwnd;
-
- return EmbedBrowserObject(w);
- case WM_GETMINMAXINFO:
- {
- if (w != NULL) {
- // get pixel density
- HDC hDC = GetDC(NULL);
- double DPIScaleX = GetDeviceCaps(hDC, 88)/96.0;
- double DPIScaleY = GetDeviceCaps(hDC, 90)/96.0;
- ReleaseDC(NULL, hDC);
-
- RECT rcClient, rcWind;
- POINT ptDiff;
- GetClientRect(hwnd, &rcClient);
- GetWindowRect(hwnd, &rcWind);
-
- int widthExtra = (rcWind.right - rcWind.left) - rcClient.right;
- int heightExtra = (rcWind.bottom - rcWind.top) - rcClient.bottom;
-
- LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
-
- if (w->priv.min_width != -1) {
- lpMMI->ptMinTrackSize.x = w->priv.min_width * DPIScaleX + widthExtra;
- lpMMI->ptMinTrackSize.y = w->priv.min_height * DPIScaleY + heightExtra;
- }
- if (w->priv.max_width != -1) {
- lpMMI->ptMaxTrackSize.x = w->priv.max_width * DPIScaleX + widthExtra;
- lpMMI->ptMaxTrackSize.y = w->priv.max_height * DPIScaleY + heightExtra;
- }
- }
-
- return 0;
- }
- case WM_DESTROY:
- UnEmbedBrowserObject(w);
- PostQuitMessage(0);
- return TRUE;
- case WM_SIZE:
- {
- IWebBrowser2 *webBrowser2;
- IOleObject *browser = *w->priv.browser;
- if (browser->lpVtbl->QueryInterface(browser, iid_unref(&IID_IWebBrowser2),
- (void **)&webBrowser2) == S_OK)
- {
- RECT rect;
- GetClientRect(hwnd, &rect);
- webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right);
- webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom);
- }
- return TRUE;
- }
- case WM_WEBVIEW_DISPATCH:
- {
- webview_dispatch_fn f = (webview_dispatch_fn)wParam;
- void *arg = (void *)lParam;
- (*f)(w, arg);
- return TRUE;
- }
- }
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
-
-#define WEBVIEW_KEY_FEATURE_BROWSER_EMULATION \
- "Software\\Microsoft\\Internet " \
- "Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION"
-
- static int webview_fix_ie_compat_mode()
- {
- HKEY hKey;
- DWORD ie_version = 11000;
- TCHAR appname[MAX_PATH + 1];
- TCHAR *p;
- if (GetModuleFileName(NULL, appname, MAX_PATH + 1) == 0)
- {
- return -1;
- }
- for (p = &appname[strlen(appname) - 1]; p != appname && *p != '\\'; p--)
- {
- }
- p++;
- if (RegCreateKey(HKEY_CURRENT_USER, WEBVIEW_KEY_FEATURE_BROWSER_EMULATION,
- &hKey) != ERROR_SUCCESS)
- {
- return -1;
- }
- if (RegSetValueEx(hKey, p, 0, REG_DWORD, (BYTE *)&ie_version,
- sizeof(ie_version)) != ERROR_SUCCESS)
- {
- RegCloseKey(hKey);
- return -1;
- }
- RegCloseKey(hKey);
- return 0;
- }
-
- WEBVIEW_API int webview_init(struct webview *w)
- {
- w->priv.min_width = -1;
- w->priv.max_width = -1;
-
- WNDCLASSEX wc;
- HINSTANCE hInstance;
- DWORD style;
- RECT clientRect;
- RECT rect;
-
- if (webview_fix_ie_compat_mode() < 0)
- {
- return -1;
- }
-
- hInstance = GetModuleHandle(NULL);
- if (hInstance == NULL)
- {
- return -1;
- }
- if (OleInitialize(NULL) != S_OK)
- {
- return -1;
- }
-
- ZeroMemory(&wc, sizeof(WNDCLASSEX));
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.hInstance = hInstance;
- wc.lpfnWndProc = wndproc;
- wc.lpszClassName = classname;
- wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
- wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(100));
- RegisterClassEx(&wc);
-
- style = WS_OVERLAPPEDWINDOW;
- if (!w->resizable)
- {
- style = WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
- }
-
- // Scale
- // Credit: https://github.com/webview/webview/issues/54#issuecomment-379528243
- HDC hDC = GetDC(NULL);
- w->width = GetDeviceCaps(hDC, 88)*w->width/96.0;
- w->height = GetDeviceCaps(hDC, 90)*w->height/96.0;
- ReleaseDC(NULL, hDC);
-
- rect.left = 0;
- rect.top = 0;
- rect.right = w->width;
- rect.bottom = w->height;
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, 0);
-
- GetClientRect(GetDesktopWindow(), &clientRect);
- int left = (clientRect.right / 2) - ((rect.right - rect.left) / 2);
- int top = (clientRect.bottom / 2) - ((rect.bottom - rect.top) / 2);
- rect.right = rect.right - rect.left + left;
- rect.left = left;
- rect.bottom = rect.bottom - rect.top + top;
- rect.top = top;
-
-#ifdef UNICODE
- wchar_t *u16title = webview_to_utf16(w->title);
- if (u16title == NULL)
- {
- return -1;
- }
-
- w->priv.hwnd =
- CreateWindowEx(0, classname, u16title, style, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top,
- HWND_DESKTOP, NULL, hInstance, (void *)w);
-#else
- w->priv.hwnd =
- CreateWindowEx(0, classname, w->title, style, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top,
- HWND_DESKTOP, NULL, hInstance, (void *)w);
-#endif
-
- if (w->priv.hwnd == 0)
- {
- OleUninitialize();
- return -1;
- }
-
- SetWindowLongPtr(w->priv.hwnd, GWLP_USERDATA, (LONG_PTR)w);
-
- DisplayHTMLPage(w);
-
-#ifdef UNICODE
- SetWindowText(w->priv.hwnd, u16title);
- GlobalFree(u16title);
-#else
- SetWindowText(w->priv.hwnd, w->title);
-#endif
-
- ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT);
- UpdateWindow(w->priv.hwnd);
- SetFocus(w->priv.hwnd);
-
- return 0;
- }
-
- WEBVIEW_API int webview_loop(struct webview *w, int blocking)
- {
- MSG msg;
- if (blocking)
- {
- GetMessage(&msg, 0, 0, 0);
- }
- else
- {
- PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
- }
- switch (msg.message)
- {
- case WM_QUIT:
- return -1;
- case WM_COMMAND:
- case WM_KEYDOWN:
- case WM_KEYUP:
- {
- // Disable refresh when pressing F5 on windows
- if (msg.wParam == VK_F5)
- {
- break;
- }
- HRESULT r = S_OK;
- IWebBrowser2 *webBrowser2;
- IOleObject *browser = *w->priv.browser;
- if (browser->lpVtbl->QueryInterface(browser, iid_unref(&IID_IWebBrowser2),
- (void **)&webBrowser2) == S_OK)
- {
- IOleInPlaceActiveObject *pIOIPAO;
- if (browser->lpVtbl->QueryInterface(
- browser, iid_unref(&IID_IOleInPlaceActiveObject),
- (void **)&pIOIPAO) == S_OK)
- {
- r = pIOIPAO->lpVtbl->TranslateAccelerator(pIOIPAO, &msg);
- pIOIPAO->lpVtbl->Release(pIOIPAO);
- }
- webBrowser2->lpVtbl->Release(webBrowser2);
- }
- if (r != S_FALSE)
- {
- break;
- }
- }
- default:
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
-
- WEBVIEW_API int webview_eval(struct webview *w, const char *js)
- {
- IWebBrowser2 *webBrowser2;
- IHTMLDocument2 *htmlDoc2;
- IDispatch *docDispatch;
- IDispatch *scriptDispatch;
- if ((*w->priv.browser)
- ->lpVtbl->QueryInterface((*w->priv.browser),
- iid_unref(&IID_IWebBrowser2),
- (void **)&webBrowser2) != S_OK)
- {
- return -1;
- }
-
- if (webBrowser2->lpVtbl->get_Document(webBrowser2, &docDispatch) != S_OK)
- {
- return -1;
- }
- if (docDispatch->lpVtbl->QueryInterface(docDispatch,
- iid_unref(&IID_IHTMLDocument2),
- (void **)&htmlDoc2) != S_OK)
- {
- return -1;
- }
- if (htmlDoc2->lpVtbl->get_Script(htmlDoc2, &scriptDispatch) != S_OK)
- {
- return -1;
- }
- DISPID dispid;
- BSTR evalStr = SysAllocString(L"eval");
- if (scriptDispatch->lpVtbl->GetIDsOfNames(
- scriptDispatch, iid_unref(&IID_NULL), &evalStr, 1,
- LOCALE_SYSTEM_DEFAULT, &dispid) != S_OK)
- {
- SysFreeString(evalStr);
- return -1;
- }
- SysFreeString(evalStr);
-
- DISPPARAMS params;
- VARIANT arg;
- VARIANT result;
- EXCEPINFO excepInfo;
- UINT nArgErr = (UINT)-1;
- params.cArgs = 1;
- params.cNamedArgs = 0;
- params.rgvarg = &arg;
- arg.vt = VT_BSTR;
- static const char *prologue = "(function(){";
- static const char *epilogue = ";})();";
- int n = strlen(prologue) + strlen(epilogue) + strlen(js) + 1;
- char *eval = (char *)malloc(n);
- snprintf(eval, n, "%s%s%s", prologue, js, epilogue);
- wchar_t *buf = webview_to_utf16(eval);
- if (buf == NULL)
- {
- return -1;
- }
- arg.bstrVal = SysAllocString(buf);
- if (scriptDispatch->lpVtbl->Invoke(
- scriptDispatch, dispid, iid_unref(&IID_NULL), 0, DISPATCH_METHOD,
- ¶ms, &result, &excepInfo, &nArgErr) != S_OK)
- {
- return -1;
- }
- SysFreeString(arg.bstrVal);
- free(eval);
- scriptDispatch->lpVtbl->Release(scriptDispatch);
- htmlDoc2->lpVtbl->Release(htmlDoc2);
- docDispatch->lpVtbl->Release(docDispatch);
- return 0;
- }
-
- WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
- void *arg)
- {
- PostMessageW(w->priv.hwnd, WM_WEBVIEW_DISPATCH, (WPARAM)fn, (LPARAM)arg);
- }
-
- WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
- {
-#ifdef UNICODE
- wchar_t *u16title = webview_to_utf16(title);
- if (u16title == NULL)
- {
- return;
- }
- SetWindowText(w->priv.hwnd, u16title);
- GlobalFree(u16title);
-#else
- SetWindowText(w->priv.hwnd, title);
-#endif
- }
-
- WEBVIEW_API void webview_focus(struct webview *w)
- {
- SetFocus(w->priv.hwnd);
- }
-
- WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
- w->priv.min_width = width;
- w->priv.min_height = height;
- }
-
- WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
- w->priv.max_width = width;
- w->priv.max_height = height;
- }
-
- WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
- {
- if (w->priv.is_fullscreen == !!fullscreen)
- {
- return;
- }
- if (w->priv.is_fullscreen == 0)
- {
- w->priv.saved_style = GetWindowLong(w->priv.hwnd, GWL_STYLE);
- w->priv.saved_ex_style = GetWindowLong(w->priv.hwnd, GWL_EXSTYLE);
- GetWindowRect(w->priv.hwnd, &w->priv.saved_rect);
- }
- w->priv.is_fullscreen = !!fullscreen;
- if (fullscreen)
- {
- MONITORINFO monitor_info;
- SetWindowLong(w->priv.hwnd, GWL_STYLE,
- w->priv.saved_style & ~(WS_CAPTION | WS_THICKFRAME));
- SetWindowLong(w->priv.hwnd, GWL_EXSTYLE,
- w->priv.saved_ex_style &
- ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE |
- WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(MonitorFromWindow(w->priv.hwnd, MONITOR_DEFAULTTONEAREST),
- &monitor_info);
- RECT r;
- r.left = monitor_info.rcMonitor.left;
- r.top = monitor_info.rcMonitor.top;
- r.right = monitor_info.rcMonitor.right;
- r.bottom = monitor_info.rcMonitor.bottom;
- SetWindowPos(w->priv.hwnd, NULL, r.left, r.top, r.right - r.left,
- r.bottom - r.top,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- }
- else
- {
- SetWindowLong(w->priv.hwnd, GWL_STYLE, w->priv.saved_style);
- SetWindowLong(w->priv.hwnd, GWL_EXSTYLE, w->priv.saved_ex_style);
- SetWindowPos(w->priv.hwnd, NULL, w->priv.saved_rect.left,
- w->priv.saved_rect.top,
- w->priv.saved_rect.right - w->priv.saved_rect.left,
- w->priv.saved_rect.bottom - w->priv.saved_rect.top,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- }
- }
-
- WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
- uint8_t b, uint8_t a)
- {
- HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
- SetClassLongPtr(w->priv.hwnd, GCLP_HBRBACKGROUND, (LONG_PTR)brush);
- }
-
-/* These are missing parts from MinGW */
-#ifndef __IFileDialog_INTERFACE_DEFINED__
-#define __IFileDialog_INTERFACE_DEFINED__
- enum _FILEOPENDIALOGOPTIONS
- {
- FOS_OVERWRITEPROMPT = 0x2,
- FOS_STRICTFILETYPES = 0x4,
- FOS_NOCHANGEDIR = 0x8,
- FOS_PICKFOLDERS = 0x20,
- FOS_FORCEFILESYSTEM = 0x40,
- FOS_ALLNONSTORAGEITEMS = 0x80,
- FOS_NOVALIDATE = 0x100,
- FOS_ALLOWMULTISELECT = 0x200,
- FOS_PATHMUSTEXIST = 0x800,
- FOS_FILEMUSTEXIST = 0x1000,
- FOS_CREATEPROMPT = 0x2000,
- FOS_SHAREAWARE = 0x4000,
- FOS_NOREADONLYRETURN = 0x8000,
- FOS_NOTESTFILECREATE = 0x10000,
- FOS_HIDEMRUPLACES = 0x20000,
- FOS_HIDEPINNEDPLACES = 0x40000,
- FOS_NODEREFERENCELINKS = 0x100000,
- FOS_DONTADDTORECENT = 0x2000000,
- FOS_FORCESHOWHIDDEN = 0x10000000,
- FOS_DEFAULTNOMINIMODE = 0x20000000,
- FOS_FORCEPREVIEWPANEON = 0x40000000
- };
- typedef DWORD FILEOPENDIALOGOPTIONS;
- typedef enum FDAP
- {
- FDAP_BOTTOM = 0,
- FDAP_TOP = 1
- } FDAP;
- DEFINE_GUID(IID_IFileDialog, 0x42f85136, 0xdb7e, 0x439c, 0x85, 0xf1, 0xe4, 0x07,
- 0x5d, 0x13, 0x5f, 0xc8);
- typedef struct IFileDialogVtbl
- {
- BEGIN_INTERFACE
- HRESULT(STDMETHODCALLTYPE *QueryInterface)
- (IFileDialog *This, REFIID riid, void **ppvObject);
- ULONG(STDMETHODCALLTYPE *AddRef)
- (IFileDialog *This);
- ULONG(STDMETHODCALLTYPE *Release)
- (IFileDialog *This);
- HRESULT(STDMETHODCALLTYPE *Show)
- (IFileDialog *This, HWND hwndOwner);
- HRESULT(STDMETHODCALLTYPE *SetFileTypes)
- (IFileDialog *This, UINT cFileTypes, const COMDLG_FILTERSPEC *rgFilterSpec);
- HRESULT(STDMETHODCALLTYPE *SetFileTypeIndex)
- (IFileDialog *This, UINT iFileType);
- HRESULT(STDMETHODCALLTYPE *GetFileTypeIndex)
- (IFileDialog *This, UINT *piFileType);
- HRESULT(STDMETHODCALLTYPE *Advise)
- (IFileDialog *This, IFileDialogEvents *pfde, DWORD *pdwCookie);
- HRESULT(STDMETHODCALLTYPE *Unadvise)
- (IFileDialog *This, DWORD dwCookie);
- HRESULT(STDMETHODCALLTYPE *SetOptions)
- (IFileDialog *This, FILEOPENDIALOGOPTIONS fos);
- HRESULT(STDMETHODCALLTYPE *GetOptions)
- (IFileDialog *This, FILEOPENDIALOGOPTIONS *pfos);
- HRESULT(STDMETHODCALLTYPE *SetDefaultFolder)
- (IFileDialog *This, IShellItem *psi);
- HRESULT(STDMETHODCALLTYPE *SetFolder)
- (IFileDialog *This, IShellItem *psi);
- HRESULT(STDMETHODCALLTYPE *GetFolder)
- (IFileDialog *This, IShellItem **ppsi);
- HRESULT(STDMETHODCALLTYPE *GetCurrentSelection)
- (IFileDialog *This, IShellItem **ppsi);
- HRESULT(STDMETHODCALLTYPE *SetFileName)
- (IFileDialog *This, LPCWSTR pszName);
- HRESULT(STDMETHODCALLTYPE *GetFileName)
- (IFileDialog *This, LPWSTR *pszName);
- HRESULT(STDMETHODCALLTYPE *SetTitle)
- (IFileDialog *This, LPCWSTR pszTitle);
- HRESULT(STDMETHODCALLTYPE *SetOkButtonLabel)
- (IFileDialog *This, LPCWSTR pszText);
- HRESULT(STDMETHODCALLTYPE *SetFileNameLabel)
- (IFileDialog *This, LPCWSTR pszLabel);
- HRESULT(STDMETHODCALLTYPE *GetResult)
- (IFileDialog *This, IShellItem **ppsi);
- HRESULT(STDMETHODCALLTYPE *AddPlace)
- (IFileDialog *This, IShellItem *psi, FDAP fdap);
- HRESULT(STDMETHODCALLTYPE *SetDefaultExtension)
- (IFileDialog *This, LPCWSTR pszDefaultExtension);
- HRESULT(STDMETHODCALLTYPE *Close)
- (IFileDialog *This, HRESULT hr);
- HRESULT(STDMETHODCALLTYPE *SetClientGuid)
- (IFileDialog *This, REFGUID guid);
- HRESULT(STDMETHODCALLTYPE *ClearClientData)
- (IFileDialog *This);
- HRESULT(STDMETHODCALLTYPE *SetFilter)
- (IFileDialog *This, IShellItemFilter *pFilter);
- END_INTERFACE
- } IFileDialogVtbl;
- interface IFileDialog
- {
- CONST_VTBL IFileDialogVtbl *lpVtbl;
- };
- DEFINE_GUID(IID_IFileOpenDialog, 0xd57c7288, 0xd4ad, 0x4768, 0xbe, 0x02, 0x9d,
- 0x96, 0x95, 0x32, 0xd9, 0x60);
- DEFINE_GUID(IID_IFileSaveDialog, 0x84bccd23, 0x5fde, 0x4cdb, 0xae, 0xa4, 0xaf,
- 0x64, 0xb8, 0x3d, 0x78, 0xab);
-#endif
-
- WEBVIEW_API void webview_dialog(struct webview *w,
- enum webview_dialog_type dlgtype, int flags,
- const char *title, const char *arg,
- char *result, size_t resultsz, char *filter)
- {
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
- dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
- {
- IFileDialog *dlg = NULL;
- IShellItem *res = NULL;
- WCHAR *ws = NULL;
- char *s = NULL;
- FILEOPENDIALOGOPTIONS opts, add_opts;
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN)
- {
- if (CoCreateInstance(
- iid_unref(&CLSID_FileOpenDialog), NULL, CLSCTX_INPROC_SERVER,
- iid_unref(&IID_IFileOpenDialog), (void **)&dlg) != S_OK)
- {
- goto error_dlg;
- }
- if (flags & WEBVIEW_DIALOG_FLAG_DIRECTORY)
- {
- add_opts |= FOS_PICKFOLDERS;
- }
- add_opts |= FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE |
- FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE |
- FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS |
- FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE;
- }
- else
- {
- if (CoCreateInstance(
- iid_unref(&CLSID_FileSaveDialog), NULL, CLSCTX_INPROC_SERVER,
- iid_unref(&IID_IFileSaveDialog), (void **)&dlg) != S_OK)
- {
- goto error_dlg;
- }
- add_opts |= FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR |
- FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_SHAREAWARE |
- FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS |
- FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE;
- }
- if (filter[0] != '\0')
- {
- int count;
- int i=0;
- char* token;
- char* filter_dup = strdup(filter);
- for (count=1; filter[count]; filter[count]==',' ? count++ : *filter++);
- COMDLG_FILTERSPEC rgSpec[count];
- char* filters[count];
- token = strtok(filter_dup, ",");
- while(token != NULL)
- {
- filters[i] = token;
- token = strtok(NULL, ",");
- i++;
- }
- for (int i=0; i < count; i++) {
- wchar_t *wFilter = (wchar_t *)malloc(4096);
- MultiByteToWideChar(CP_ACP, 0, filters[i], -1, wFilter, 4096);
- rgSpec[i].pszName = wFilter;
- rgSpec[i].pszSpec = wFilter;
- }
- if (dlg->lpVtbl->SetFileTypes(dlg, count, rgSpec) != S_OK) {
- goto error_dlg;
- }
- }
- if (dlg->lpVtbl->GetOptions(dlg, &opts) != S_OK)
- {
- goto error_dlg;
- }
- opts &= ~FOS_NOREADONLYRETURN;
- opts |= add_opts;
- if (dlg->lpVtbl->SetOptions(dlg, opts) != S_OK)
- {
- goto error_dlg;
- }
- if (dlg->lpVtbl->Show(dlg, w->priv.hwnd) != S_OK)
- {
- goto error_dlg;
- }
- if (dlg->lpVtbl->GetResult(dlg, &res) != S_OK)
- {
- goto error_dlg;
- }
- if (res->lpVtbl->GetDisplayName(res, SIGDN_FILESYSPATH, &ws) != S_OK)
- {
- goto error_result;
- }
- s = webview_from_utf16(ws);
- strncpy(result, s, resultsz);
- result[resultsz - 1] = '\0';
- CoTaskMemFree(ws);
- error_result:
- res->lpVtbl->Release(res);
- error_dlg:
- dlg->lpVtbl->Release(dlg);
- return;
- }
- else if (dlgtype == WEBVIEW_DIALOG_TYPE_ALERT)
- {
-#if 0
- /* MinGW often doesn't contain TaskDialog, we'll use MessageBox for now */
- WCHAR *wtitle = webview_to_utf16(title);
- WCHAR *warg = webview_to_utf16(arg);
- TaskDialog(w->priv.hwnd, NULL, NULL, wtitle, warg, 0, NULL, NULL);
- GlobalFree(warg);
- GlobalFree(wtitle);
-#else
- UINT type = MB_OK;
- switch (flags & WEBVIEW_DIALOG_FLAG_ALERT_MASK)
- {
- case WEBVIEW_DIALOG_FLAG_INFO:
- type |= MB_ICONINFORMATION;
- break;
- case WEBVIEW_DIALOG_FLAG_WARNING:
- type |= MB_ICONWARNING;
- break;
- case WEBVIEW_DIALOG_FLAG_ERROR:
- type |= MB_ICONERROR;
- break;
- }
- MessageBox(w->priv.hwnd, arg, title, type);
-#endif
- }
- }
-
- WEBVIEW_API void webview_terminate(struct webview *w) { PostQuitMessage(0); }
- WEBVIEW_API void webview_exit(struct webview *w) { OleUninitialize(); }
- WEBVIEW_API void webview_print_log(const char *s) { OutputDebugString(s); }
-
-#endif /* WEBVIEW_WINAPI */
-
-#if defined(WEBVIEW_COCOA)
-#if (!defined MAC_OS_X_VERSION_10_12) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-#define NSAlertStyleWarning NSWarningAlertStyle
-#define NSAlertStyleCritical NSCriticalAlertStyle
-#define NSWindowStyleMaskResizable NSResizableWindowMask
-#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
-#define NSWindowStyleMaskTitled NSTitledWindowMask
-#define NSWindowStyleMaskClosable NSClosableWindowMask
-#define NSWindowStyleMaskFullScreen NSFullScreenWindowMask
-#define NSEventMaskAny NSAnyEventMask
-#define NSEventModifierFlagCommand NSCommandKeyMask
-#define NSEventModifierFlagOption NSAlternateKeyMask
-#define NSAlertStyleInformational NSInformationalAlertStyle
-#endif /* MAC_OS_X_VERSION_10_12 */
-#if (!defined MAC_OS_X_VERSION_10_13) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
-#define NSModalResponseOK NSFileHandlingPanelOKButton
-#endif /* MAC_OS_X_VERSION_10_12, MAC_OS_X_VERSION_10_13 */
- static void webview_window_will_close(id self, SEL cmd, id notification)
- {
- struct webview *w =
- (struct webview *)objc_getAssociatedObject(self, "webview");
- webview_terminate(w);
- }
-
- static BOOL webview_is_selector_excluded_from_web_script(id self, SEL cmd,
- SEL selector)
- {
- return selector != @selector(invoke:);
- }
-
- static NSString *webview_webscript_name_for_selector(id self, SEL cmd,
- SEL selector)
- {
- return selector == @selector(invoke:) ? @"invoke" : nil;
- }
-
- static void webview_did_clear_window_object(id self, SEL cmd, id webview,
- id script, id frame)
- {
- [script setValue:self forKey:@"external"];
- }
-
- static void webview_run_input_open_panel(id self, SEL cmd, id webview,
- id listener, BOOL allowMultiple)
- {
- char filename[256] = "";
- struct webview *w =
- (struct webview *)objc_getAssociatedObject(self, "webview");
-
- webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
- filename, 255, "");
- filename[255] = '\0';
- if (strlen(filename) > 0)
- {
- [listener chooseFilename:[NSString stringWithUTF8String:filename]];
- }
- else
- {
- [listener cancel];
- }
- }
-
- static void webview_external_invoke(id self, SEL cmd, id arg)
- {
- struct webview *w =
- (struct webview *)objc_getAssociatedObject(self, "webview");
- if (w == NULL || w->external_invoke_cb == NULL)
- {
- return;
- }
- if ([arg isKindOfClass:[NSString class]] == NO)
- {
- return;
- }
- w->external_invoke_cb(w, [(NSString *)(arg) UTF8String]);
- }
-
- WEBVIEW_API int webview_init(struct webview *w)
- {
- w->priv.pool = [[NSAutoreleasePool alloc] init];
- [NSApplication sharedApplication];
-
- Class webViewDelegateClass =
- objc_allocateClassPair([NSObject class], "WebViewDelegate", 0);
- class_addMethod(webViewDelegateClass, sel_registerName("windowWillClose:"),
- (IMP)webview_window_will_close, "v@:@");
- class_addMethod(object_getClass(webViewDelegateClass),
- sel_registerName("isSelectorExcludedFromWebScript:"),
- (IMP)webview_is_selector_excluded_from_web_script, "c@::");
- class_addMethod(object_getClass(webViewDelegateClass),
- sel_registerName("webScriptNameForSelector:"),
- (IMP)webview_webscript_name_for_selector, "c@::");
- class_addMethod(webViewDelegateClass,
- sel_registerName("webView:didClearWindowObject:forFrame:"),
- (IMP)webview_did_clear_window_object, "v@:@@@");
- class_addMethod(
- webViewDelegateClass,
- sel_registerName("webView:runOpenPanelForFileButtonWithResultListener:"
- "allowMultipleFiles:"),
- (IMP)webview_run_input_open_panel, "v@:@@c");
- class_addMethod(webViewDelegateClass, sel_registerName("invoke:"),
- (IMP)webview_external_invoke, "v@:@");
- objc_registerClassPair(webViewDelegateClass);
-
- w->priv.delegate = [[webViewDelegateClass alloc] init];
- objc_setAssociatedObject(w->priv.delegate, "webview", (id)(w),
- OBJC_ASSOCIATION_ASSIGN);
-
- // Disable damn smart quotes
- // Credit: https://stackoverflow.com/a/31640511
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSAutomaticQuoteSubstitutionEnabled"];
-
- NSRect r = NSMakeRect(0, 0, w->width, w->height);
- NSUInteger style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskMiniaturizable;
- if (w->resizable)
- {
- style = style | NSWindowStyleMaskResizable;
- // style = style | NSTexturedBackgroundWindowMask;
- // style = style | NSUnifiedTitleAndToolbarWindowMask;
- }
-
- // Transparent title bar
- // if (w->transparentTitlebar) {
- // style = style | NSFullSizeContentViewWindowMask | NSUnifiedTitleAndToolbarWindowMask | NSTexturedBackgroundWindowMask;
- // }
-
- w->priv.window = [[NSWindow alloc] initWithContentRect:r
- styleMask:style
- backing:NSBackingStoreBuffered
- defer:NO];
- [w->priv.window autorelease];
-
- // Title
- NSString *nsTitle = [NSString stringWithUTF8String:w->title];
- [w->priv.window setTitle:nsTitle];
-
- [w->priv.window setDelegate:w->priv.delegate];
- [w->priv.window center];
-
- // NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"];
- // toolbar.showsBaselineSeparator = NO;
- // [w->priv.window setToolbar:toolbar];
-
- // if (w->transparentTitlebar) {
-
- // // Configure window look with hidden toolbar
- // [w->priv.window setTitlebarAppearsTransparent:YES];
- // [w->priv.window setTitleVisibility:NSWindowTitleHidden];
- // // w->priv.window.isMovableByWindowBackground = true;
- // }
-
- [[NSUserDefaults standardUserDefaults] setBool:!!w->debug
- forKey:@"WebKitDeveloperExtras"];
- [[NSUserDefaults standardUserDefaults] synchronize];
- w->priv.webview =
- [[WebView alloc] initWithFrame:r
- frameName:@"WebView"
- groupName:nil];
- NSURL *nsURL = [NSURL
- URLWithString:[NSString stringWithUTF8String:webview_check_url(w->url)]];
- [[w->priv.webview mainFrame] loadRequest:[NSURLRequest requestWithURL:nsURL]];
-
- [w->priv.webview setAutoresizesSubviews:YES];
- [w->priv.webview
- setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- w->priv.webview.frameLoadDelegate = w->priv.delegate;
- w->priv.webview.UIDelegate = w->priv.delegate;
- [[w->priv.window contentView] addSubview:w->priv.webview];
- [w->priv.window orderFrontRegardless];
-
- // Disable scrolling - make this configurable
- // [[[w->priv.webview mainFrame] frameView] setAllowsScrolling:NO];
-
- // ----> Enables WebGL but won't pass the app store guidelines
- //
- // WebPreferences *p = [w->priv.webview preferences];
- // if ([p respondsToSelector:@selector(setWebGLEnabled:)]) {
- // [p setWebGLEnabled:YES];
- // }
-
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
- [NSApp finishLaunching];
- [NSApp activateIgnoringOtherApps:YES];
-
- NSMenu *menubar = [[[NSMenu alloc] initWithTitle:@""] autorelease];
-
- NSMenuItem *appMenuItem =
- [[[NSMenuItem alloc] initWithTitle:@"wails app" action:NULL keyEquivalent:@""]
- autorelease];
- NSMenu *appMenu = [[[NSMenu alloc] initWithTitle:@"wails app"] autorelease];
- [appMenuItem setSubmenu:appMenu];
- [menubar addItem:appMenuItem];
-
- NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:@"Hide"
- action:@selector(hide:)
- keyEquivalent:@"h"] autorelease];
- [appMenu addItem:item];
- item = [[[NSMenuItem alloc] initWithTitle:@"Hide Others"
- action:@selector(hideOtherApplications:)
- keyEquivalent:@"h"] autorelease];
- [item setKeyEquivalentModifierMask:(NSEventModifierFlagOption |
- NSEventModifierFlagCommand)];
- [appMenu addItem:item];
- item = [[[NSMenuItem alloc] initWithTitle:@"Show All"
- action:@selector(unhideAllApplications:)
- keyEquivalent:@""] autorelease];
- [appMenu addItem:item];
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- NSMenuItem *editMenuItem =
- [[[NSMenuItem alloc] initWithTitle:@"Edit" action:NULL keyEquivalent:@""]
- autorelease];
- NSMenu *editMenu = [[[NSMenu alloc] initWithTitle:@"Edit"] autorelease];
- [editMenuItem setSubmenu:editMenu];
- [menubar addItem:editMenuItem];
-
- item = [[[NSMenuItem alloc] initWithTitle:@"Cut"
- action:@selector(cut:)
- keyEquivalent:@"x"] autorelease];
- [editMenu addItem:item];
-
- item = [[[NSMenuItem alloc] initWithTitle:@"Copy"
- action:@selector(copy:)
- keyEquivalent:@"c"] autorelease];
- [editMenu addItem:item];
-
- item = [[[NSMenuItem alloc] initWithTitle:@"Paste"
- action:@selector(paste:)
- keyEquivalent:@"v"] autorelease];
- [editMenu addItem:item];
-
- item = [[[NSMenuItem alloc] initWithTitle:@"Select All"
- action:@selector(selectAll:)
- keyEquivalent:@"a"] autorelease];
- [editMenu addItem:item];
-
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- item = [[[NSMenuItem alloc] initWithTitle:@"Quit"
- action:@selector(terminate:)
- keyEquivalent:@"q"] autorelease];
- [appMenu addItem:item];
-
- [NSApp setMainMenu:menubar];
-
- w->priv.should_exit = 0;
- return 0;
- }
-
- WEBVIEW_API int webview_loop(struct webview *w, int blocking)
- {
- NSDate *until = (blocking ? [NSDate distantFuture] : [NSDate distantPast]);
- NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
- untilDate:until
- inMode:NSDefaultRunLoopMode
- dequeue:YES];
- if (event)
- {
- [NSApp sendEvent:event];
- }
- return w->priv.should_exit;
- }
-
- WEBVIEW_API int webview_eval(struct webview *w, const char *js)
- {
- NSString *nsJS = [NSString stringWithUTF8String:js];
- [[w->priv.webview windowScriptObject] evaluateWebScript:nsJS];
- return 0;
- }
-
- WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
- {
- NSString *nsTitle = [NSString stringWithUTF8String:title];
- [w->priv.window setTitle:nsTitle];
- }
-
- WEBVIEW_API void webview_focus(struct webview *w)
- {
- [w->priv.window makeKeyWindow];
- }
-
- WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
- NSSize size;
- size.width = width;
- size.height = height;
- [w->priv.window setMinSize:size];
- }
-
- WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
- NSSize size;
- size.width = width;
- size.height = height;
- [w->priv.window setMaxSize:size];
-
- NSButton *button = [w->priv.window standardWindowButton:NSWindowZoomButton];
- [button performSelectorOnMainThread:@selector(setEnabled:) withObject:NO
- waitUntilDone:NO];
- }
-
- WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
- {
- int b = ((([w->priv.window styleMask] & NSWindowStyleMaskFullScreen) ==
- NSWindowStyleMaskFullScreen)
- ? 1
- : 0);
- if (b != fullscreen)
- {
- [w->priv.window toggleFullScreen:nil];
- }
- }
-
- WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
- uint8_t b, uint8_t a)
- {
- [w->priv.window setBackgroundColor:[NSColor colorWithRed:(CGFloat)r / 255.0
- green:(CGFloat)g / 255.0
- blue:(CGFloat)b / 255.0
- alpha:(CGFloat)a / 255.0]];
- if (0.5 >= ((r / 255.0 * 299.0) + (g / 255.0 * 587.0) + (b / 255.0 * 114.0)) /
- 1000.0)
- {
- [w->priv.window
- setAppearance:[NSAppearance
- appearanceNamed:NSAppearanceNameVibrantDark]];
- }
- else
- {
- [w->priv.window
- setAppearance:[NSAppearance
- appearanceNamed:NSAppearanceNameVibrantLight]];
- }
- [w->priv.window setOpaque:NO];
- [w->priv.window setTitlebarAppearsTransparent:YES];
- [w->priv.webview setDrawsBackground:NO];
- }
-
- WEBVIEW_API void webview_dialog(struct webview *w,
- enum webview_dialog_type dlgtype, int flags,
- const char *title, const char *arg,
- char *result, size_t resultsz, char *filter)
- {
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
- dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
- {
- NSSavePanel *panel;
- NSString *filter_str = [NSString stringWithUTF8String:filter];
- filter_str = [filter_str stringByReplacingOccurrencesOfString:@"*."
- withString:@""];
- NSArray *fileTypes = [filter_str componentsSeparatedByString:@","];
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN)
- {
- NSOpenPanel *openPanel = [NSOpenPanel openPanel];
- if (flags & WEBVIEW_DIALOG_FLAG_DIRECTORY)
- {
- [openPanel setCanChooseFiles:NO];
- [openPanel setCanChooseDirectories:YES];
- }
- else
- {
- [openPanel setCanChooseFiles:YES];
- [openPanel setCanChooseDirectories:NO];
- if(filter[0] != NULL)
- {
- [openPanel setAllowedFileTypes:fileTypes];
- }
- }
- [openPanel setResolvesAliases:NO];
- [openPanel setAllowsMultipleSelection:NO];
- panel = openPanel;
- }
- else
- {
- panel = [NSSavePanel savePanel];
- }
- [panel setCanCreateDirectories:YES];
- [panel setShowsHiddenFiles:YES];
- [panel setExtensionHidden:NO];
- [panel setCanSelectHiddenExtension:NO];
- if(filter[0] != NULL)
- {
- [panel setAllowedFileTypes:fileTypes];
- }
- [panel setTreatsFilePackagesAsDirectories:YES];
- [panel setNameFieldStringValue:@"Temp"]; // Necessary to prevent crash when replacing files
- [panel setNameFieldStringValue:@"Untitled"];
- [panel beginSheetModalForWindow:w->priv.window
- completionHandler:^(NSInteger result) {
- [NSApp stopModalWithCode:result];
- }];
- if ([NSApp runModalForWindow:panel] == NSModalResponseOK)
- {
- const char *filename = [[[panel URL] path] UTF8String];
- strlcpy(result, filename, resultsz);
- }
- }
- else if (dlgtype == WEBVIEW_DIALOG_TYPE_ALERT)
- {
- NSAlert *a = [NSAlert new];
- switch (flags & WEBVIEW_DIALOG_FLAG_ALERT_MASK)
- {
- case WEBVIEW_DIALOG_FLAG_INFO:
- [a setAlertStyle:NSAlertStyleInformational];
- break;
- case WEBVIEW_DIALOG_FLAG_WARNING:
- NSLog(@"warning");
- [a setAlertStyle:NSAlertStyleWarning];
- break;
- case WEBVIEW_DIALOG_FLAG_ERROR:
- NSLog(@"error");
- [a setAlertStyle:NSAlertStyleCritical];
- break;
- }
- [a setShowsHelp:NO];
- [a setShowsSuppressionButton:NO];
- [a setMessageText:[NSString stringWithUTF8String:title]];
- [a setInformativeText:[NSString stringWithUTF8String:arg]];
- [a addButtonWithTitle:@"OK"];
- [a runModal];
- [a release];
- }
- }
-
- static void webview_dispatch_cb(void *arg)
- {
- struct webview_dispatch_arg *context = (struct webview_dispatch_arg *)arg;
- (context->fn)(context->w, context->arg);
- free(context);
- }
-
- WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
- void *arg)
- {
- struct webview_dispatch_arg *context = (struct webview_dispatch_arg *)malloc(
- sizeof(struct webview_dispatch_arg));
- context->w = w;
- context->arg = arg;
- context->fn = fn;
- dispatch_async_f(dispatch_get_main_queue(), context, webview_dispatch_cb);
- }
-
- WEBVIEW_API void webview_terminate(struct webview *w)
- {
- w->priv.should_exit = 1;
- }
- WEBVIEW_API void webview_exit(struct webview *w) { [NSApp terminate:NSApp]; }
- WEBVIEW_API void webview_print_log(const char *s) { NSLog(@"%s", s); }
-
-#endif /* WEBVIEW_COCOA */
-
-#endif /* WEBVIEW_IMPLEMENTATION */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WEBVIEW_H */
diff --git a/licenses/github.com/dchest/cssmin/LICENSE b/licenses/github.com/dchest/cssmin/LICENSE
deleted file mode 100644
index c9b4ec5dd..000000000
--- a/licenses/github.com/dchest/cssmin/LICENSE
+++ /dev/null
@@ -1,29 +0,0 @@
-Go Port:
-Copyright (c) 2013 Dmitry Chestnykh
-
-Original:
-Copyright (c) 2008 Ryan Grove
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of this project nor the names of its contributors may be
- used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/github.com/dchest/htmlmin/LICENSE b/licenses/github.com/dchest/htmlmin/LICENSE
deleted file mode 100644
index 9ddea1fd3..000000000
--- a/licenses/github.com/dchest/htmlmin/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2013 Dmitry Chestnykh. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/github.com/fatih/color/LICENSE.md b/licenses/github.com/fatih/color/LICENSE.md
deleted file mode 100644
index 25fdaf639..000000000
--- a/licenses/github.com/fatih/color/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Fatih Arslan
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/licenses/github.com/go-playground/colors/LICENSE b/licenses/github.com/go-playground/colors/LICENSE
deleted file mode 100644
index 6a2ae9aa4..000000000
--- a/licenses/github.com/go-playground/colors/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Dean Karn
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/licenses/github.com/gorilla/websocket/LICENSE b/licenses/github.com/gorilla/websocket/LICENSE
deleted file mode 100644
index 9171c9722..000000000
--- a/licenses/github.com/gorilla/websocket/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/github.com/jackmordaunt/icns/LICENSE b/licenses/github.com/jackmordaunt/icns/LICENSE
deleted file mode 100644
index 787939ec2..000000000
--- a/licenses/github.com/jackmordaunt/icns/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 Jack Mordaunt
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/licenses/github.com/konsorten/go-windows-terminal-sequences/LICENSE b/licenses/github.com/konsorten/go-windows-terminal-sequences/LICENSE
deleted file mode 100644
index 14127cd83..000000000
--- a/licenses/github.com/konsorten/go-windows-terminal-sequences/LICENSE
+++ /dev/null
@@ -1,9 +0,0 @@
-(The MIT License)
-
-Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/licenses/github.com/leaanthony/mewn/LICENSE b/licenses/github.com/leaanthony/mewn/LICENSE
deleted file mode 100644
index 1cf398a90..000000000
--- a/licenses/github.com/leaanthony/mewn/LICENSE
+++ /dev/null
@@ -1,7 +0,0 @@
-© 2019-Present Lea Anthony
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/licenses/github.com/leaanthony/slicer/LICENSE b/licenses/github.com/leaanthony/slicer/LICENSE
deleted file mode 100644
index 558a6a271..000000000
--- a/licenses/github.com/leaanthony/slicer/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 Lea Anthony
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/licenses/github.com/leaanthony/spinner/LICENSE b/licenses/github.com/leaanthony/spinner/LICENSE
deleted file mode 100644
index 7e01c45c9..000000000
--- a/licenses/github.com/leaanthony/spinner/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2018 Lea Anthony
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/licenses/github.com/leaanthony/synx/LICENSE b/licenses/github.com/leaanthony/synx/LICENSE
deleted file mode 100644
index 75ba4230d..000000000
--- a/licenses/github.com/leaanthony/synx/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2018-Present Lea Anthony
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/licenses/github.com/leaanthony/wincursor/LICENSE b/licenses/github.com/leaanthony/wincursor/LICENSE
deleted file mode 100644
index 75ba4230d..000000000
--- a/licenses/github.com/leaanthony/wincursor/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2018-Present Lea Anthony
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/licenses/github.com/mattn/go-colorable/LICENSE b/licenses/github.com/mattn/go-colorable/LICENSE
deleted file mode 100644
index 91b5cef30..000000000
--- a/licenses/github.com/mattn/go-colorable/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Yasuhiro Matsumoto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/licenses/github.com/mattn/go-isatty/LICENSE b/licenses/github.com/mattn/go-isatty/LICENSE
deleted file mode 100644
index 65dc692b6..000000000
--- a/licenses/github.com/mattn/go-isatty/LICENSE
+++ /dev/null
@@ -1,9 +0,0 @@
-Copyright (c) Yasuhiro MATSUMOTO
-
-MIT License (Expat)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/licenses/github.com/mitchellh/go-homedir/LICENSE b/licenses/github.com/mitchellh/go-homedir/LICENSE
deleted file mode 100644
index f9c841a51..000000000
--- a/licenses/github.com/mitchellh/go-homedir/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Mitchell Hashimoto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/licenses/github.com/nfnt/resize/LICENSE b/licenses/github.com/nfnt/resize/LICENSE
deleted file mode 100644
index 7836cad5f..000000000
--- a/licenses/github.com/nfnt/resize/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright (c) 2012, Jan Schlicht
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
diff --git a/licenses/github.com/pkg/errors/LICENSE b/licenses/github.com/pkg/errors/LICENSE
deleted file mode 100644
index 835ba3e75..000000000
--- a/licenses/github.com/pkg/errors/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright (c) 2015, Dave Cheney
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/github.com/sirupsen/logrus/LICENSE b/licenses/github.com/sirupsen/logrus/LICENSE
deleted file mode 100644
index f090cb42f..000000000
--- a/licenses/github.com/sirupsen/logrus/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Simon Eskildsen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/licenses/github.com/wailsapp/webview/LICENSE b/licenses/github.com/wailsapp/webview/LICENSE
deleted file mode 100644
index b18604bf4..000000000
--- a/licenses/github.com/wailsapp/webview/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 Serge Zaitsev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/licenses/golang.org/x/crypto/LICENSE b/licenses/golang.org/x/crypto/LICENSE
deleted file mode 100644
index 6a66aea5e..000000000
--- a/licenses/golang.org/x/crypto/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/golang.org/x/net/LICENSE b/licenses/golang.org/x/net/LICENSE
deleted file mode 100644
index 6a66aea5e..000000000
--- a/licenses/golang.org/x/net/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/licenses/golang.org/x/sys/LICENSE b/licenses/golang.org/x/sys/LICENSE
deleted file mode 100644
index 6a66aea5e..000000000
--- a/licenses/golang.org/x/sys/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/runtime/assets.go b/runtime/assets.go
deleted file mode 100644
index 96aaad29b..000000000
--- a/runtime/assets.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package runtime
-
-import _ "embed"
-
-//go:embed assets/bridge.js
-var BridgeJS []byte
-
-//go:embed assets/wails.js
-var WailsJS string
-
-//go:embed assets/wails.css
-var WailsCSS string
-
-//go:embed js/runtime/init.js
-var InitJS []byte
diff --git a/runtime/assets/bridge.js b/runtime/assets/bridge.js
deleted file mode 100644
index 5c2f73ee3..000000000
--- a/runtime/assets/bridge.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-function init() {
- // Bridge object
- window.wailsbridge = {
- reconnectOverlay: null,
- reconnectTimer: 300,
- wsURL: 'ws://' + window.location.hostname + ':34115/bridge',
- connectionState: null,
- config: {},
- websocket: null,
- callback: null,
- overlayHTML:
- 'Wails Bridge
Waiting for backend
',
- overlayCSS:
- '.wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}',
- log: function (message) {
- // eslint-disable-next-line
- console.log(
- '%c wails bridge %c ' + message + ' ',
- 'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
- 'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
- );
- }
- };
-}
-
-// Adapted from webview - thanks zserge!
-function injectCSS(css) {
- var elem = document.createElement('style');
- elem.setAttribute('type', 'text/css');
- if (elem.styleSheet) {
- elem.styleSheet.cssText = css;
- } else {
- elem.appendChild(document.createTextNode(css));
- }
- var head = document.head || document.getElementsByTagName('head')[0];
- head.appendChild(elem);
-}
-
-// Creates a node in the Dom
-function createNode(parent, elementType, id, className, content) {
- var d = document.createElement(elementType);
- if (id) {
- d.id = id;
- }
- if (className) {
- d.className = className;
- }
- if (content) {
- d.innerHTML = content;
- }
- parent.appendChild(d);
- return d;
-}
-
-// Sets up the overlay
-function setupOverlay() {
- var body = document.body;
- var wailsBridgeNode = createNode(body, 'div', 'wails-bridge');
- wailsBridgeNode.innerHTML = window.wailsbridge.overlayHTML;
-
- // Inject the overlay CSS
- injectCSS(window.wailsbridge.overlayCSS);
-}
-
-// Start the Wails Bridge
-function startBridge() {
- // Setup the overlay
- setupOverlay();
-
- window.wailsbridge.websocket = null;
- window.wailsbridge.connectTimer = null;
- window.wailsbridge.reconnectOverlay = document.querySelector(
- '.wails-reconnect-overlay'
- );
- window.wailsbridge.connectionState = 'disconnected';
-
- // Shows the overlay
- function showReconnectOverlay() {
- window.wailsbridge.reconnectOverlay.style.display = 'block';
- }
-
- // Hides the overlay
- function hideReconnectOverlay() {
- window.wailsbridge.reconnectOverlay.style.display = 'none';
- }
-
- // Adds a script to the Dom.
- // Removes it if second parameter is true.
- function addScript(script, remove) {
- var s = document.createElement('script');
- s.setAttribute('type', 'text/javascript');
- s.textContent = script;
- document.head.appendChild(s);
-
- // Remove internal messages from the DOM
- if (remove) {
- s.parentNode.removeChild(s);
- }
- }
-
- // Handles incoming websocket connections
- function handleConnect() {
- window.wailsbridge.log('Connected to backend');
- hideReconnectOverlay();
- clearInterval(window.wailsbridge.connectTimer);
- window.wailsbridge.websocket.onclose = handleDisconnect;
- window.wailsbridge.websocket.onmessage = handleMessage;
- window.wailsbridge.connectionState = 'connected';
- }
-
- // Handles websocket disconnects
- function handleDisconnect() {
- window.wailsbridge.log('Disconnected from backend');
- window.wailsbridge.websocket = null;
- window.wailsbridge.connectionState = 'disconnected';
- showReconnectOverlay();
- connect();
- }
-
- // Try to connect to the backend every 300ms (default value).
- // Change this value in the main wailsbridge object.
- function connect() {
- window.wailsbridge.connectTimer = setInterval(function () {
- if (window.wailsbridge.websocket == null) {
- window.wailsbridge.websocket = new WebSocket(window.wailsbridge.wsURL);
- window.wailsbridge.websocket.onopen = handleConnect;
- window.wailsbridge.websocket.onerror = function (e) {
- e.stopImmediatePropagation();
- e.stopPropagation();
- e.preventDefault();
- window.wailsbridge.websocket = null;
- return false;
- };
- }
- }, window.wailsbridge.reconnectTimer);
- }
-
- function handleMessage(message) {
- // As a bridge we ignore js and css injections
- switch (message.data[0]) {
- // Wails library - inject!
- case 'w':
- addScript(message.data.slice(1));
-
- // Now wails runtime is loaded, wails for the ready event
- // and callback to the main app
- window.wails.Events.On('wails:loaded', function () {
- window.wailsbridge.log('Wails Ready');
- if (window.wailsbridge.callback) {
- window.wailsbridge.log('Notifying application');
- window.wailsbridge.callback(window.wails);
- }
- });
- window.wailsbridge.log('Loaded Wails Runtime');
- break;
- // Notifications
- case 'n':
- addScript(message.data.slice(1), true);
- break;
- // Binding
- case 'b':
- var binding = message.data.slice(1);
- //log("Binding: " + binding)
- window.wails._.NewBinding(binding);
- break;
- // Call back
- case 'c':
- var callbackData = message.data.slice(1);
- window.wails._.Callback(callbackData);
- break;
- default:
- window.wails.Log.Error('Unknown message type received: ' + message.data[0]);
- }
- }
-
- // Start by showing the overlay...
- showReconnectOverlay();
-
- // ...and attempt to connect
- connect();
-}
-
-function start(callback) {
-
- // Set up the bridge
- init();
-
- // Save the callback
- window.wailsbridge.callback = callback;
-
- // Start Bridge
- startBridge();
-}
-
-function Init(callback) {
- start(callback);
-}
-
-module.exports = Init;
diff --git a/runtime/assets/console.js b/runtime/assets/console.js
deleted file mode 100644
index e64867d25..000000000
--- a/runtime/assets/console.js
+++ /dev/null
@@ -1,175 +0,0 @@
-(function () {
-
- window.wailsconsole = {};
-
- var debugconsole = document.createElement("div");
- var header = document.createElement("div");
- var consoleOut = document.createElement("div");
-
-
- document.addEventListener('keyup', logKey);
-
- debugconsole.id = "wailsdebug";
- debugconsole.style.fontSize = "18px";
- debugconsole.style.width = "100%";
- debugconsole.style.height = "35%";
- debugconsole.style.maxHeight = "35%";
- debugconsole.style.position = "fixed";
- debugconsole.style.left = "0px";
- debugconsole.style.backgroundColor = "rgba(255,255,255,0.8)";
- debugconsole.style.borderTop = '1px solid black';
- debugconsole.style.color = "black";
- debugconsole.style.display = "none";
-
- header.style.width = "100%";
- header.style.height = "30px";
- header.style.display = "block";
- // header.style.paddingTop = "3px";
- header.style.verticalAlign = "middle";
- header.style.paddingLeft = "10px";
- header.style.background = "rgba(255,255,255,0.8)";
- header.innerHTML = " Wails Console > Clear ";
-
- consoleOut.style.position = "absolute";
- consoleOut.style.width = "100%";
- consoleOut.style.height = "auto";
- consoleOut.style.top = "30px";
- // consoleOut.style.paddingLeft = "10px";
- consoleOut.style.bottom = "0px";
- consoleOut.style.backgroundColor = "rgba(200,200,200,1)";
- consoleOut.style.overflowY = "scroll";
- consoleOut.style.msOverflowStyle = "-ms-autohiding-scrollbar";
-
- debugconsole.appendChild(header);
- debugconsole.appendChild(consoleOut);
- document.body.appendChild(debugconsole);
- console.log(debugconsole.style.display)
-
- function logKey(e) {
- var conin = document.getElementById('conin');
- if (e.which == 27 && e.shiftKey) {
- toggleConsole(conin);
- }
- if (e.which == 13 && consoleVisible()) {
- var command = conin.value.trim();
- if (command.length > 0) {
- console.log("> " + command)
- try {
- evaluateInput(command);
- } catch (e) {
- console.error(e.message);
- }
- conin.value = "";
- }
- }
- };
-
-
- function consoleVisible() {
- return debugconsole.style.display == "block";
- }
-
- function toggleConsole(conin) {
- var display = "none"
- if (debugconsole.style.display == "none") display = "block";
- debugconsole.style.display = display;
- if (display == "block") {
- conin.focus();
- }
- }
-
- function evaluateExpression(expression) {
-
- var pathSegments = [].concat(expression.split('.'));
- if (pathSegments[0] == 'window') {
- pathSegments.shift()
- }
- var currentObject = window;
- for (var i = 0; i < pathSegments.length; i++) {
- var pathSegment = pathSegments[i];
- if (currentObject[pathSegment] == undefined) {
- return false;
- }
- currentObject = currentObject[pathSegment];
- }
- console.log(JSON.stringify(currentObject));
-
- return true;
- }
-
- function evaluateInput(command) {
- try {
- if (evaluateExpression(command)) {
- return
- } else {
- eval(command);
- }
- } catch (e) {
- console.error(e.message)
- }
- }
-
-
- // Set us up as a listener
- function hookIntoIPC() {
- if (window.wails && window.wails._ && window.wails._.AddIPCListener) {
- window.wails._.AddIPCListener(processIPCMessage);
- } else {
- setTimeout(hookIntoIPC, 100);
- }
- }
- hookIntoIPC();
-
- function processIPCMessage(message) {
- console.log(message);
- var parsedMessage;
- try {
- parsedMessage = JSON.parse(message);
- } catch (e) {
- console.error("Error in parsing IPC message: " + e.message);
- return false;
- }
- var logmessage = "[IPC] "
- switch (parsedMessage.type) {
- case 'call':
- logmessage += " Call: " + parsedMessage.payload.bindingName;
- var params = "";
- var parsedParams = JSON.parse(parsedMessage.payload.data);
- if (parsedParams.length > 0) {
- params = parsedParams;
- }
- logmessage += "(" + params + ")";
- break;
- case 'log':
- logmessage += "Log (" + parsedMessage.payload.level + "): " + parsedMessage.payload.message;
- break;
- default:
- logmessage = message;
- }
- console.log(logmessage);
- }
-
- window.wailsconsole.clearConsole = function () {
- consoleOut.innerHTML = "";
- }
-
- console.log = function (message) {
- consoleOut.innerHTML = consoleOut.innerHTML + "" + message + ' ';
- consoleOut.scrollTop = consoleOut.scrollHeight;
-
- };
- console.error = function (message) {
- consoleOut.innerHTML = consoleOut.innerHTML + " Error: " + message + ' ';
- consoleOut.scrollTop = consoleOut.scrollHeight;
- };
- // var h = document.getElementsByTagName("html")[0];
- // console.log("html margin: " + h.style.marginLeft);
- // console.log("html padding: " + h.style.paddingLeft);
-
- // setInterval(function() { console.log("test");}, 1000);
- // setInterval(function() { console.error("oops");}, 3000);
- // var script = document.createElement('script');
- // script.src = "https://cdnjs.cloudflare.com/ajax/libs/firebug-lite/1.4.0/firebug-lite.js#startOpened=true";
- // document.body.appendChild(script);
-
-})();
\ No newline at end of file
diff --git a/runtime/assets/wails.css b/runtime/assets/wails.css
deleted file mode 100644
index b807abe69..000000000
--- a/runtime/assets/wails.css
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- Some css from https://gist.github.com/abelaska/9c9eda70d31315f27a564be2ee490cf4
- Many thanks!
-*/
-
-/* https://fonts.google.com/specimen/Roboto?selection.family=Roboto:300,400,500,700 https://www.fontsquirrel.com/tools/webfont-generator */
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 300;
- src:url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
-}
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 400;
- src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
-}
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 500;
- src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
-}
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 700;
- src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
-}
-
-html {
- font-family: 'Roboto'
-}
-
-.wails-logo {
- background-image: url(data:image/png;base64,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);
- background-size: cover;
-}
\ No newline at end of file
diff --git a/runtime/assets/wails.js b/runtime/assets/wails.js
deleted file mode 100644
index 0971f49ea..000000000
--- a/runtime/assets/wails.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(n){var e={};function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:r})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(r,o,function(e){return n[e]}.bind(null,o));return r},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){"use strict";t.r(e),t.d(e,"Init",(function(){return L}));var r={};t.r(r),t.d(r,"Debug",(function(){return l})),t.d(r,"Info",(function(){return s})),t.d(r,"Warning",(function(){return d})),t.d(r,"Error",(function(){return f})),t.d(r,"Fatal",(function(){return w}));var o={};t.r(o),t.d(o,"OpenURL",(function(){return h})),t.d(o,"OpenFile",(function(){return y}));var i={};t.r(i),t.d(i,"New",(function(){return N}));var a=[];function c(n,e,t){var r={type:n,callbackID:t,payload:e};!function(n){if(window.wailsbridge?window.wailsbridge.websocket.send(n):window.external.invoke(n),a.length>0)for(var e=0;e0)var a=setTimeout((function(){o(Error("Call to "+n+" timed out. Request ID: "+i))}),t);v[i]={timeoutHandle:a,reject:o,resolve:r};try{c("call",{bindingName:n,data:JSON.stringify(e)},i)}catch(n){console.error(n)}}))}function b(n,e){return g(".wails."+n,e)}function h(n){return b("Browser.OpenURL",n)}function y(n){return b("Browser.OpenFile",n)}p=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()};var m=function n(e,t){!function(n,e){if(!(n instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),t=t||-1,this.Callback=function(n){return e.apply(null,n),-1!==t&&0===(t-=1)}},E={};function O(n,e,t){E[n]=E[n]||[];var r=new m(e,t);E[n].push(r)}function S(n){var e=JSON.stringify([].slice.apply(arguments).slice(1)),t={name:n,data:e};c("event",t)}var j={};function k(n){try{return new Function("var "+n),!0}catch(n){return!1}}function N(n,e){var t,r=this;if(!window.wails)throw Error("Wails is not initialised");var o=[];return this.subscribe=function(n){o.push(n)},this.set=function(e){t=e,window.wails.Events.Emit("wails:sync:store:updatedbyfrontend:"+n,JSON.stringify(t)),o.forEach((function(n){n(t)}))},this.update=function(n){var e=n(t);r.set(e)},window.wails.Events.On("wails:sync:store:updatedbybackend:"+n,(function(n){n=JSON.parse(n),t=n,o.forEach((function(n){n(t)}))})),e&&this.set(e),this}function C(){return(C=Object.assign||function(n){for(var e=1;e1)for(var r=0;r 0 {
- title = params[0]
- }
- if len(params) > 1 {
- filter = strings.Replace(params[1], " ", "", -1)
- }
- return r.renderer.SelectFile(title, filter)
-}
-
-// SelectDirectory prompts the user to select a directory
-func (r *Dialog) SelectDirectory() string {
- return r.renderer.SelectDirectory()
-}
-
-// SelectSaveFile prompts the user to select a file for saving
-func (r *Dialog) SelectSaveFile(params ...string) string {
- title := "Select Save"
- filter := ""
- if len(params) > 0 {
- title = params[0]
- }
- if len(params) > 1 {
- filter = strings.Replace(params[1], " ", "", -1)
- }
- return r.renderer.SelectSaveFile(title, filter)
-}
diff --git a/runtime/events.go b/runtime/events.go
deleted file mode 100644
index ffbeaa5a7..000000000
--- a/runtime/events.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package runtime
-
-import "github.com/wailsapp/wails/lib/interfaces"
-
-// Events exposes the events interface
-type Events struct {
- eventManager interfaces.EventManager
-}
-
-// NewEvents creates a new Events struct
-func NewEvents(eventManager interfaces.EventManager) *Events {
- return &Events{
- eventManager: eventManager,
- }
-}
-
-// On pass through
-func (r *Events) On(eventName string, callback func(optionalData ...interface{})) {
- r.eventManager.On(eventName, callback)
-}
-
-// Once pass through
-func (r *Events) Once(eventName string, callback func(optionalData ...interface{})) {
- r.eventManager.Once(eventName, callback)
-}
-
-// OnMultiple pass through
-func (r *Events) OnMultiple(eventName string, callback func(optionalData ...interface{}), counter uint) {
- r.eventManager.OnMultiple(eventName, callback, counter)
-}
-
-// Emit pass through
-func (r *Events) Emit(eventName string, optionalData ...interface{}) {
- r.eventManager.Emit(eventName, optionalData...)
-}
diff --git a/runtime/filesystem.go b/runtime/filesystem.go
deleted file mode 100644
index ebb4feda0..000000000
--- a/runtime/filesystem.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package runtime
-
-import "os"
-
-// FileSystem exposes file system utilities to the runtime
-type FileSystem struct{}
-
-// NewFileSystem creates a new FileSystem struct
-func NewFileSystem() *FileSystem {
- return &FileSystem{}
-}
-
-// HomeDir returns the user's home directory
-func (r *FileSystem) HomeDir() (string, error) {
- return os.UserHomeDir()
-}
diff --git a/runtime/js/.eslintrc b/runtime/js/.eslintrc
deleted file mode 100644
index 426ccc63d..000000000
--- a/runtime/js/.eslintrc
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "env": {
- "browser": true,
- "es6": true,
- "amd": true,
- "node": true
- },
- "extends": "eslint:recommended",
- "parserOptions": {
- "ecmaVersion": 2016,
- "sourceType": "module"
- },
- "rules": {
- "indent": [
- "error",
- "tab"
- ],
- "linebreak-style": 0,
- "quotes": [
- "error",
- "single"
- ],
- "semi": [
- "error",
- "always"
- ]
- }
-}
diff --git a/runtime/js/babel.config.js b/runtime/js/babel.config.js
deleted file mode 100644
index 39d867cc4..000000000
--- a/runtime/js/babel.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* eslint-disable */
-
-module.exports = function (api) {
- api.cache(true);
-
- const presets = [
- [
- "@babel/preset-env",
- {
- "useBuiltIns": "entry",
- "corejs": {
- "version": 3,
- "proposals": true
- }
- }
- ]
- ];
-
- return {
- presets,
- };
-}
\ No newline at end of file
diff --git a/runtime/js/core/bindings.js b/runtime/js/core/bindings.js
deleted file mode 100644
index 32df6161f..000000000
--- a/runtime/js/core/bindings.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-import { Call } from './calls';
-
-window.backend = {};
-
-/**
- * Determines if the given identifier is valid Javascript
- *
- * @param {boolean} name
- * @returns
- */
-function isValidIdentifier(name) {
- // Don't xss yourself :-)
- try {
- new Function('var ' + name);
- return true;
- } catch (e) {
- return false;
- }
-}
-
-/**
- * NewBinding creates a new binding from the given binding name
- *
- * @export
- * @param {string} bindingName
- * @returns
- */
-// eslint-disable-next-line max-lines-per-function
-export function NewBinding(bindingName) {
-
- // Get all the sections of the binding
- var bindingSections = [].concat(bindingName.split('.').splice(1));
- var pathToBinding = window.backend;
-
- // Check if we have a path (IE Struct)
- if (bindingSections.length > 1) {
- // Iterate over binding sections, adding them to the window.backend object
- for (let index = 0; index < bindingSections.length-1; index += 1) {
- const name = bindingSections[index];
- // Is name a valid javascript identifier?
- if (!isValidIdentifier(name)) {
- return new Error(`${name} is not a valid javascript identifier.`);
- }
- if (!pathToBinding[name]) {
- pathToBinding[name] = {};
- }
- pathToBinding = pathToBinding[name];
- }
- }
-
- // Get the actual function/method call name
- const name = bindingSections.pop();
-
- // Is name a valid javascript identifier?
- if (!isValidIdentifier(name)) {
- return new Error(`${name} is not a valid javascript identifier.`);
- }
-
- // Add binding call
- pathToBinding[name] = function () {
-
- // No timeout by default
- var timeout = 0;
-
- // Actual function
- function dynamic() {
- var args = [].slice.call(arguments);
- return Call(bindingName, args, timeout);
- }
-
- // Allow setting timeout to function
- dynamic.setTimeout = function (newTimeout) {
- timeout = newTimeout;
- };
-
- // Allow getting timeout to function
- dynamic.getTimeout = function () {
- return timeout;
- };
-
- return dynamic;
- }();
-}
diff --git a/runtime/js/core/browser.js b/runtime/js/core/browser.js
deleted file mode 100644
index dd7856897..000000000
--- a/runtime/js/core/browser.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-import { SystemCall } from './calls';
-
-/**
- * Opens the given URL in the system browser
- *
- * @export
- * @param {string} url
- * @returns
- */
-export function OpenURL(url) {
- return SystemCall('Browser.OpenURL', url);
-}
-
-/**
- * Opens the given filename using the system's default file handler
- *
- * @export
- * @param {string} filename
- * @returns
- */
-export function OpenFile(filename) {
- return SystemCall('Browser.OpenFile', filename);
-}
diff --git a/runtime/js/core/calls.js b/runtime/js/core/calls.js
deleted file mode 100644
index 9919ff803..000000000
--- a/runtime/js/core/calls.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-import { Debug } from './log';
-import { SendMessage } from './ipc';
-
-var callbacks = {};
-
-/**
- * Returns a number from the native browser random function
- *
- * @returns number
- */
-function cryptoRandom() {
- var array = new Uint32Array(1);
- return window.crypto.getRandomValues(array)[0];
-}
-
-/**
- * Returns a number using da old-skool Math.Random
- * I likes to call it LOLRandom
- *
- * @returns number
- */
-function basicRandom() {
- return Math.random() * 9007199254740991;
-}
-
-// Pick a random number function based on browser capability
-var randomFunc;
-if (window.crypto) {
- randomFunc = cryptoRandom;
-} else {
- randomFunc = basicRandom;
-}
-
-
-
-
-/**
- * Call sends a message to the backend to call the binding with the
- * given data. A promise is returned and will be completed when the
- * backend responds. This will be resolved when the call was successful
- * or rejected if an error is passed back.
- * There is a timeout mechanism. If the call doesn't respond in the given
- * time (in milliseconds) then the promise is rejected.
- *
- * @export
- * @param {string} bindingName
- * @param {string} data
- * @param {number=} timeout
- * @returns
- */
-export function Call(bindingName, data, timeout) {
-
- // Timeout infinite by default
- if (timeout == null) {
- timeout = 0;
- }
-
- // Create a promise
- return new Promise(function (resolve, reject) {
-
- // Create a unique callbackID
- var callbackID;
- do {
- callbackID = bindingName + '-' + randomFunc();
- } while (callbacks[callbackID]);
-
- // Set timeout
- if (timeout > 0) {
- var timeoutHandle = setTimeout(function () {
- reject(Error('Call to ' + bindingName + ' timed out. Request ID: ' + callbackID));
- }, timeout);
- }
-
- // Store callback
- callbacks[callbackID] = {
- timeoutHandle: timeoutHandle,
- reject: reject,
- resolve: resolve
- };
-
- try {
- const payload = {
- bindingName: bindingName,
- data: JSON.stringify(data),
- };
-
- // Make the call
- SendMessage('call', payload, callbackID);
- } catch (e) {
- // eslint-disable-next-line
- console.error(e);
- }
- });
-}
-
-
-
-/**
- * Called by the backend to return data to a previously called
- * binding invocation
- *
- * @export
- * @param {string} incomingMessage
- */
-export function Callback(incomingMessage) {
-
- // Decode the message - Credit: https://stackoverflow.com/a/13865680
- incomingMessage = decodeURIComponent(incomingMessage.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));
-
- // Parse the message
- var message;
- try {
- message = JSON.parse(incomingMessage);
- } catch (e) {
- const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
- Debug(error);
- throw new Error(error);
- }
- var callbackID = message.callbackid;
- var callbackData = callbacks[callbackID];
- if (!callbackData) {
- const error = `Callback '${callbackID}' not registed!!!`;
- console.error(error); // eslint-disable-line
- throw new Error(error);
- }
- clearTimeout(callbackData.timeoutHandle);
-
- delete callbacks[callbackID];
-
- if (message.error) {
- callbackData.reject(message.error);
- } else {
- callbackData.resolve(message.data);
- }
-}
-
-/**
- * SystemCall is used to call wails methods from the frontend
- *
- * @export
- * @param {string} method
- * @param {any[]=} data
- * @returns
- */
-export function SystemCall(method, data) {
- return Call('.wails.' + method, data);
-}
\ No newline at end of file
diff --git a/runtime/js/core/events.js b/runtime/js/core/events.js
deleted file mode 100644
index 81a663bdc..000000000
--- a/runtime/js/core/events.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-import { Error } from './log';
-import { SendMessage } from './ipc';
-
-// Defines a single listener with a maximum number of times to callback
-/**
- * The Listener class defines a listener! :-)
- *
- * @class Listener
- */
-class Listener {
- /**
- * Creates an instance of Listener.
- * @param {function} callback
- * @param {number} maxCallbacks
- * @memberof Listener
- */
- constructor(callback, maxCallbacks) {
- // Default of -1 means infinite
- maxCallbacks = maxCallbacks || -1;
- // Callback invokes the callback with the given data
- // Returns true if this listener should be destroyed
- this.Callback = (data) => {
- callback.apply(null, data);
- // If maxCallbacks is infinite, return false (do not destroy)
- if (maxCallbacks === -1) {
- return false;
- }
- // Decrement maxCallbacks. Return true if now 0, otherwise false
- maxCallbacks -= 1;
- return maxCallbacks === 0;
- };
- }
-}
-
-var eventListeners = {};
-
-/**
- * Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- * @param {number} maxCallbacks
- */
-export function OnMultiple(eventName, callback, maxCallbacks) {
- eventListeners[eventName] = eventListeners[eventName] || [];
- const thisListener = new Listener(callback, maxCallbacks);
- eventListeners[eventName].push(thisListener);
-}
-
-/**
- * Registers an event listener that will be invoked every time the event is emitted
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- */
-export function On(eventName, callback) {
- OnMultiple(eventName, callback);
-}
-
-/**
- * Registers an event listener that will be invoked once then destroyed
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- */
-export function Once(eventName, callback) {
- OnMultiple(eventName, callback, 1);
-}
-
-/**
- * Notify informs frontend listeners that an event was emitted with the given data
- *
- * @export
- * @param {string} eventName
- * @param {string} data
- */
-export function Notify(eventName, data) {
-
- // Check if we have any listeners for this event
- if (eventListeners[eventName]) {
-
- // Keep a list of listener indexes to destroy
- const newEventListenerList = eventListeners[eventName].slice();
-
- // Iterate listeners
- for (let count = 0; count < eventListeners[eventName].length; count += 1) {
-
- // Get next listener
- const listener = eventListeners[eventName][count];
-
- // Parse data if we have it
- var parsedData = [];
- if (data) {
- try {
- parsedData = JSON.parse(data);
- } catch (e) {
- Error('Invalid JSON data sent to notify. Event name = ' + eventName);
- }
- }
- // Do the callback
- const destroy = listener.Callback(parsedData);
- if (destroy) {
- // if the listener indicated to destroy itself, add it to the destroy list
- newEventListenerList.splice(count, 1);
- }
- }
-
- // Update callbacks with new list of listners
- eventListeners[eventName] = newEventListenerList;
- }
-}
-
-/**
- * Emit an event with the given name and data
- *
- * @export
- * @param {string} eventName
- */
-export function Emit(eventName) {
-
- // Calculate the data
- var data = JSON.stringify([].slice.apply(arguments).slice(1));
-
- // Notify backend
- const payload = {
- name: eventName,
- data: data,
- };
- SendMessage('event', payload);
-}
-
-// Callbacks for the heartbeat calls
-const heartbeatCallbacks = {};
-
-/**
- * Heartbeat emits the event `eventName`, every `timeInMilliseconds` milliseconds until
- * the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
- *
- * @export
- * @param {string} eventName
- * @param {number} timeInMilliseconds
- * @param {function} callback
- */
-export function Heartbeat(eventName, timeInMilliseconds, callback) {
-
- // Declare interval variable
- let interval = null;
-
- // Setup callback
- function dynamicCallback() {
- // Kill interval
- clearInterval(interval);
- // Callback
- callback();
- }
-
- // Register callback
- heartbeatCallbacks[eventName] = dynamicCallback;
-
- // Start emitting the event
- interval = setInterval(function () {
- Emit(eventName);
- }, timeInMilliseconds);
-}
-
-/**
- * Acknowledges a heartbeat event by name
- *
- * @export
- * @param {string} eventName
- */
-export function Acknowledge(eventName) {
- // If we are waiting for acknowledgement for this event type
- if (heartbeatCallbacks[eventName]) {
- // Acknowledge!
- heartbeatCallbacks[eventName]();
- } else {
- throw new Error(`Cannot acknowledge unknown heartbeat '${eventName}'`);
- }
-}
\ No newline at end of file
diff --git a/runtime/js/core/ipc.js b/runtime/js/core/ipc.js
deleted file mode 100644
index b453d3ac7..000000000
--- a/runtime/js/core/ipc.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-// IPC Listeners
-var listeners = [];
-
-/**
- * Adds a listener to IPC messages
- * @param {function} callback
- */
-export function AddIPCListener(callback) {
- listeners.push(callback);
-}
-
-/**
- * Invoke sends the given message to the backend
- *
- * @param {string} message
- */
-function Invoke(message) {
- if (window.wailsbridge) {
- window.wailsbridge.websocket.send(message);
- } else {
- window.external.invoke(message);
- }
-
- // Also send to listeners
- if (listeners.length > 0) {
- for (var i = 0; i < listeners.length; i++) {
- listeners[i](message);
- }
- }
-}
-
-/**
- * Sends a message to the backend based on the given type, payload and callbackID
- *
- * @export
- * @param {string} type
- * @param {Object} payload
- * @param {string=} callbackID
- */
-export function SendMessage(type, payload, callbackID) {
- const message = {
- type,
- callbackID,
- payload
- };
-
- Invoke(JSON.stringify(message));
-}
diff --git a/runtime/js/core/log.js b/runtime/js/core/log.js
deleted file mode 100644
index e113e8731..000000000
--- a/runtime/js/core/log.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-
-/* jshint esversion: 6 */
-
-import { SendMessage } from './ipc';
-
-/**
- * Sends a log message to the backend with the given level + message
- *
- * @param {string} level
- * @param {string} message
- */
-function sendLogMessage(level, message) {
-
- // Log Message
- const payload = {
- level: level,
- message: message,
- };
- SendMessage('log', payload);
-}
-
-/**
- * Log the given debug message with the backend
- *
- * @export
- * @param {string} message
- */
-export function Debug(message) {
- sendLogMessage('debug', message);
-}
-
-/**
- * Log the given info message with the backend
- *
- * @export
- * @param {string} message
- */
-export function Info(message) {
- sendLogMessage('info', message);
-}
-
-/**
- * Log the given warning message with the backend
- *
- * @export
- * @param {string} message
- */
-export function Warning(message) {
- sendLogMessage('warning', message);
-}
-
-/**
- * Log the given error message with the backend
- *
- * @export
- * @param {string} message
- */
-export function Error(message) {
- sendLogMessage('error', message);
-}
-
-/**
- * Log the given fatal message with the backend
- *
- * @export
- * @param {string} message
- */
-export function Fatal(message) {
- sendLogMessage('fatal', message);
-}
-
diff --git a/runtime/js/core/main.js b/runtime/js/core/main.js
deleted file mode 100644
index 51581aadc..000000000
--- a/runtime/js/core/main.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-import * as Log from './log';
-import * as Browser from './browser';
-import {Acknowledge, Emit, Heartbeat, Notify, On, OnMultiple} from './events';
-import {NewBinding} from './bindings';
-import {Callback} from './calls';
-import {AddScript, InjectCSS, InjectFirebug} from './utils';
-import {AddIPCListener} from './ipc';
-import * as Store from './store';
-
-// Initialise global if not already
-window.wails = window.wails || {};
-window.backend = {};
-
-// On webkit2gtk >= 2.32, the external object is not passed to the window context.
-// However, IE will throw a strict mode error if window.external is assigned to
-// so we need to make sure that line of code isn't reached in IE
-
-// Using !window.external transpiles to `window.external = window.external || ...`
-// so we have to use an explicit if statement to prevent webpack from optimizing the code.
-if (window.external == undefined) {
- window.external = {
- invoke: function (x) {
- window.webkit.messageHandlers.external.postMessage(x);
- }
- };
-}
-
-// Setup internal calls
-var internal = {
- NewBinding,
- Callback,
- Notify,
- AddScript,
- InjectCSS,
- Init,
- AddIPCListener,
-};
-
-// Setup runtime structure
-var runtime = {
- Log,
- Browser,
- Events: {
- On,
- OnMultiple,
- Emit,
- Heartbeat,
- Acknowledge,
- },
- Store,
- _: internal,
-};
-
-// Augment global
-Object.assign(window.wails, runtime);
-
-// Setup global error handler
-window.onerror = function (msg, url, lineNo, columnNo, error) {
- window.wails.Log.Error('**** Caught Unhandled Error ****');
- window.wails.Log.Error('Message: ' + msg);
- window.wails.Log.Error('URL: ' + url);
- window.wails.Log.Error('Line No: ' + lineNo);
- window.wails.Log.Error('Column No: ' + columnNo);
- window.wails.Log.Error('error: ' + error);
-};
-
-// Use firebug?
-if (window.usefirebug) {
- InjectFirebug();
-}
-
-// Emit loaded event
-Emit('wails:loaded');
-
-// Nothing to init in production
-export function Init(callback) {
- callback();
-}
diff --git a/runtime/js/core/store.js b/runtime/js/core/store.js
deleted file mode 100644
index 58e471781..000000000
--- a/runtime/js/core/store.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-/**
- * Creates a new sync store with the given name and optional default value
- *
- * @export
- * @param {string} name
- * @param {*} optionalDefault
- */
-export function New(name, optionalDefault) {
-
- var data;
-
- // Check we are initialised
- if( !window.wails) {
- throw Error('Wails is not initialised');
- }
-
- // Store for the callbacks
- let callbacks = [];
-
- // Subscribe to updates by providing a callback
- this.subscribe = (callback) => {
- callbacks.push(callback);
- };
-
- // sets the store data to the provided `newdata` value
- this.set = (newdata) => {
-
- data = newdata;
-
- // Emit a notification to back end
- window.wails.Events.Emit('wails:sync:store:updatedbyfrontend:'+name, JSON.stringify(data));
-
- // Notify callbacks
- callbacks.forEach( function(callback) {
- callback(data);
- });
- };
-
- // update mutates the value in the store by calling the
- // provided method with the current value. The value returned
- // by the updater function will be set as the new store value
- this.update = (updater) => {
- var newValue = updater(data);
- this.set(newValue);
- };
-
- // Setup event callback
- window.wails.Events.On('wails:sync:store:updatedbybackend:'+name, function(result) {
-
- // Parse data
- result = JSON.parse(result);
-
- // Todo: Potential preprocessing?
-
- // Save data
- data = result;
-
- // Notify callbacks
- callbacks.forEach( function(callback) {
- callback(data);
- });
-
- });
-
- // Set to the optional default if set
- if( optionalDefault ) {
- this.set(optionalDefault);
- }
-
- return this;
-}
\ No newline at end of file
diff --git a/runtime/js/core/utils.js b/runtime/js/core/utils.js
deleted file mode 100644
index 425fe1f04..000000000
--- a/runtime/js/core/utils.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-import { Emit } from './events';
-
-export function AddScript(js, callbackID) {
- var script = document.createElement('script');
- script.text = js;
- document.body.appendChild(script);
- if (callbackID) {
- Emit(callbackID);
- }
-}
-
-export function InjectFirebug() {
- // set the debug attribute on HTML
- var html = document.getElementsByTagName('html')[0];
- html.setAttribute('debug', 'true');
- var firebugURL = 'https://wails.app/assets/js/firebug-lite.js#startOpened=true,disableWhenFirebugActive=false';
- var script = document.createElement('script');
- script.src = firebugURL;
- script.type = 'application/javascript';
- document.head.appendChild(script);
- window.wails.Log.Info('Injected firebug');
-}
-
-// Adapted from webview - thanks zserge!
-export function InjectCSS(css) {
- var elem = document.createElement('style');
- elem.setAttribute('type', 'text/css');
- if (elem.styleSheet) {
- elem.styleSheet.cssText = css;
- } else {
- elem.appendChild(document.createTextNode(css));
- }
- var head = document.head || document.getElementsByTagName('head')[0];
- head.appendChild(elem);
-}
diff --git a/runtime/js/package-lock.json b/runtime/js/package-lock.json
deleted file mode 100644
index 6b037a2bf..000000000
--- a/runtime/js/package-lock.json
+++ /dev/null
@@ -1,6625 +0,0 @@
-{
- "name": "wails-runtime",
- "version": "1.0.0",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "@babel/cli": {
- "version": "7.11.6",
- "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.11.6.tgz",
- "integrity": "sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg==",
- "dev": true,
- "requires": {
- "chokidar": "^2.1.8",
- "commander": "^4.0.1",
- "convert-source-map": "^1.1.0",
- "fs-readdir-recursive": "^1.1.0",
- "glob": "^7.0.0",
- "lodash": "^4.17.19",
- "make-dir": "^2.1.0",
- "slash": "^2.0.0",
- "source-map": "^0.5.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
- }
- },
- "@babel/code-frame": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
- "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
- "dev": true,
- "requires": {
- "@babel/highlight": "^7.10.4"
- }
- },
- "@babel/compat-data": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
- "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
- "dev": true,
- "requires": {
- "browserslist": "^4.12.0",
- "invariant": "^2.2.4",
- "semver": "^5.5.0"
- }
- },
- "@babel/core": {
- "version": "7.11.6",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
- "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.11.6",
- "@babel/helper-module-transforms": "^7.11.0",
- "@babel/helpers": "^7.10.4",
- "@babel/parser": "^7.11.5",
- "@babel/template": "^7.10.4",
- "@babel/traverse": "^7.11.5",
- "@babel/types": "^7.11.5",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.1",
- "json5": "^2.1.2",
- "lodash": "^4.17.19",
- "resolve": "^1.3.2",
- "semver": "^5.4.1",
- "source-map": "^0.5.0"
- },
- "dependencies": {
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
- }
- },
- "@babel/generator": {
- "version": "7.11.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
- "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.5",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
- }
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
- "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
- "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
- "dev": true,
- "requires": {
- "@babel/helper-explode-assignable-expression": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
- "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.10.4",
- "browserslist": "^4.12.0",
- "invariant": "^2.2.4",
- "levenary": "^1.1.1",
- "semver": "^5.5.0"
- }
- },
- "@babel/helper-create-class-features-plugin": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
- "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-member-expression-to-functions": "^7.10.5",
- "@babel/helper-optimise-call-expression": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-replace-supers": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.10.4"
- }
- },
- "@babel/helper-create-regexp-features-plugin": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
- "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.10.4",
- "@babel/helper-regex": "^7.10.4",
- "regexpu-core": "^4.7.0"
- }
- },
- "@babel/helper-define-map": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
- "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.4",
- "@babel/types": "^7.10.5",
- "lodash": "^4.17.19"
- }
- },
- "@babel/helper-explode-assignable-expression": {
- "version": "7.11.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz",
- "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
- "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
- "dev": true,
- "requires": {
- "@babel/helper-get-function-arity": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-get-function-arity": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
- "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
- "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-member-expression-to-functions": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
- "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.0"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
- "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
- "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.10.4",
- "@babel/helper-replace-supers": "^7.10.4",
- "@babel/helper-simple-access": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.11.0",
- "lodash": "^4.17.19"
- }
- },
- "@babel/helper-optimise-call-expression": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
- "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
- "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
- "dev": true
- },
- "@babel/helper-regex": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz",
- "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==",
- "dev": true,
- "requires": {
- "lodash": "^4.17.19"
- }
- },
- "@babel/helper-remap-async-to-generator": {
- "version": "7.11.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz",
- "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.10.4",
- "@babel/helper-wrap-function": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-replace-supers": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
- "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
- "dev": true,
- "requires": {
- "@babel/helper-member-expression-to-functions": "^7.10.4",
- "@babel/helper-optimise-call-expression": "^7.10.4",
- "@babel/traverse": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-simple-access": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
- "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz",
- "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.0"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
- "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.0"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
- "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
- "dev": true
- },
- "@babel/helper-wrap-function": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
- "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/traverse": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helpers": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
- "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.10.4",
- "@babel/traverse": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/highlight": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
- "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.11.5",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
- "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
- "dev": true
- },
- "@babel/plugin-proposal-async-generator-functions": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz",
- "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-remap-async-to-generator": "^7.10.4",
- "@babel/plugin-syntax-async-generators": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-class-properties": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
- "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-dynamic-import": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
- "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-dynamic-import": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-export-namespace-from": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
- "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-json-strings": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
- "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
- "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- },
- "dependencies": {
- "jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
- },
- "regexpu-core": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz",
- "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==",
- "requires": {
- "regenerate": "^1.4.0",
- "regenerate-unicode-properties": "^8.0.2",
- "regjsgen": "^0.5.0",
- "regjsparser": "^0.6.0",
- "unicode-match-property-ecmascript": "^1.0.4",
- "unicode-match-property-value-ecmascript": "^1.1.0"
- },
- "dependencies": {
- "regenerate": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
- "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A=="
- },
- "regenerate-unicode-properties": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
- "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
- "requires": {
- "regenerate": "^1.4.0"
- }
- },
- "unicode-match-property-ecmascript": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
- "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
- "requires": {
- "unicode-canonical-property-names-ecmascript": "^1.0.4",
- "unicode-property-aliases-ecmascript": "^1.0.4"
- }
- },
- "unicode-match-property-value-ecmascript": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
- "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ=="
- }
- }
- },
- "regjsgen": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz",
- "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA=="
- },
- "regjsparser": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
- "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
- "requires": {
- "jsesc": "~0.5.0"
- }
- }
- }
- },
- "@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
- "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-object-rest-spread": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
- "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
- "@babel/plugin-transform-parameters": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz",
- "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-optional-chaining": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
- "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
- "@babel/plugin-syntax-optional-chaining": "^7.8.0"
- }
- },
- "@babel/plugin-proposal-private-methods": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
- "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
- "dev": true,
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
- "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-class-properties": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
- "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
- }
- },
- "@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-top-level-await": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz",
- "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-arrow-functions": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz",
- "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-async-to-generator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz",
- "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==",
- "dev": true,
- "requires": {
- "@babel/helper-module-imports": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-remap-async-to-generator": "^7.10.4"
- }
- },
- "@babel/plugin-transform-block-scoped-functions": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz",
- "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-block-scoping": {
- "version": "7.11.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz",
- "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-classes": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz",
- "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.10.4",
- "@babel/helper-define-map": "^7.10.4",
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-optimise-call-expression": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-replace-supers": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.10.4",
- "globals": "^11.1.0"
- }
- },
- "@babel/plugin-transform-computed-properties": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz",
- "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-destructuring": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz",
- "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-dotall-regex": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz",
- "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-duplicate-keys": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz",
- "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-exponentiation-operator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz",
- "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==",
- "dev": true,
- "requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-for-of": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz",
- "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-function-name": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz",
- "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-literals": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz",
- "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-member-expression-literals": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz",
- "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-modules-amd": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz",
- "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.10.5",
- "@babel/helper-plugin-utils": "^7.10.4",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-commonjs": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz",
- "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-simple-access": "^7.10.4",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-systemjs": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz",
- "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==",
- "dev": true,
- "requires": {
- "@babel/helper-hoist-variables": "^7.10.4",
- "@babel/helper-module-transforms": "^7.10.5",
- "@babel/helper-plugin-utils": "^7.10.4",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
- "@babel/plugin-transform-modules-umd": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz",
- "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz",
- "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.4"
- }
- },
- "@babel/plugin-transform-new-target": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz",
- "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-object-assign": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.10.4.tgz",
- "integrity": "sha512-6zccDhYEICfMeQqIjuY5G09/yhKzG30DKHJeYBQUHIsJH7c2jXSGvgwRalufLAXAq432OSlsEfAOLlzEsQzxVw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-object-super": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz",
- "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-replace-supers": "^7.10.4"
- }
- },
- "@babel/plugin-transform-parameters": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz",
- "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==",
- "dev": true,
- "requires": {
- "@babel/helper-get-function-arity": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-property-literals": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz",
- "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-regenerator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz",
- "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==",
- "dev": true,
- "requires": {
- "regenerator-transform": "^0.14.2"
- }
- },
- "@babel/plugin-transform-reserved-words": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz",
- "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-shorthand-properties": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz",
- "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-spread": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz",
- "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0"
- }
- },
- "@babel/plugin-transform-sticky-regex": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz",
- "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/helper-regex": "^7.10.4"
- }
- },
- "@babel/plugin-transform-template-literals": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz",
- "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-typeof-symbol": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz",
- "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-unicode-escapes": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
- "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/plugin-transform-unicode-regex": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
- "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@babel/preset-env": {
- "version": "7.11.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz",
- "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.11.0",
- "@babel/helper-compilation-targets": "^7.10.4",
- "@babel/helper-module-imports": "^7.10.4",
- "@babel/helper-plugin-utils": "^7.10.4",
- "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
- "@babel/plugin-proposal-class-properties": "^7.10.4",
- "@babel/plugin-proposal-dynamic-import": "^7.10.4",
- "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
- "@babel/plugin-proposal-json-strings": "^7.10.4",
- "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
- "@babel/plugin-proposal-numeric-separator": "^7.10.4",
- "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
- "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
- "@babel/plugin-proposal-optional-chaining": "^7.11.0",
- "@babel/plugin-proposal-private-methods": "^7.10.4",
- "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
- "@babel/plugin-syntax-async-generators": "^7.8.0",
- "@babel/plugin-syntax-class-properties": "^7.10.4",
- "@babel/plugin-syntax-dynamic-import": "^7.8.0",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-json-strings": "^7.8.0",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
- "@babel/plugin-syntax-optional-chaining": "^7.8.0",
- "@babel/plugin-syntax-top-level-await": "^7.10.4",
- "@babel/plugin-transform-arrow-functions": "^7.10.4",
- "@babel/plugin-transform-async-to-generator": "^7.10.4",
- "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
- "@babel/plugin-transform-block-scoping": "^7.10.4",
- "@babel/plugin-transform-classes": "^7.10.4",
- "@babel/plugin-transform-computed-properties": "^7.10.4",
- "@babel/plugin-transform-destructuring": "^7.10.4",
- "@babel/plugin-transform-dotall-regex": "^7.10.4",
- "@babel/plugin-transform-duplicate-keys": "^7.10.4",
- "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
- "@babel/plugin-transform-for-of": "^7.10.4",
- "@babel/plugin-transform-function-name": "^7.10.4",
- "@babel/plugin-transform-literals": "^7.10.4",
- "@babel/plugin-transform-member-expression-literals": "^7.10.4",
- "@babel/plugin-transform-modules-amd": "^7.10.4",
- "@babel/plugin-transform-modules-commonjs": "^7.10.4",
- "@babel/plugin-transform-modules-systemjs": "^7.10.4",
- "@babel/plugin-transform-modules-umd": "^7.10.4",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
- "@babel/plugin-transform-new-target": "^7.10.4",
- "@babel/plugin-transform-object-super": "^7.10.4",
- "@babel/plugin-transform-parameters": "^7.10.4",
- "@babel/plugin-transform-property-literals": "^7.10.4",
- "@babel/plugin-transform-regenerator": "^7.10.4",
- "@babel/plugin-transform-reserved-words": "^7.10.4",
- "@babel/plugin-transform-shorthand-properties": "^7.10.4",
- "@babel/plugin-transform-spread": "^7.11.0",
- "@babel/plugin-transform-sticky-regex": "^7.10.4",
- "@babel/plugin-transform-template-literals": "^7.10.4",
- "@babel/plugin-transform-typeof-symbol": "^7.10.4",
- "@babel/plugin-transform-unicode-escapes": "^7.10.4",
- "@babel/plugin-transform-unicode-regex": "^7.10.4",
- "@babel/preset-modules": "^0.1.3",
- "@babel/types": "^7.11.5",
- "browserslist": "^4.12.0",
- "core-js-compat": "^3.6.2",
- "invariant": "^2.2.2",
- "levenary": "^1.1.1",
- "semver": "^5.5.0"
- }
- },
- "@babel/preset-modules": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
- "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
- }
- },
- "@babel/runtime": {
- "version": "7.11.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
- "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
- "dev": true,
- "requires": {
- "regenerator-runtime": "^0.13.4"
- }
- },
- "@babel/template": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
- "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/parser": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/traverse": {
- "version": "7.11.5",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
- "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.11.5",
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/parser": "^7.11.5",
- "@babel/types": "^7.11.5",
- "debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.19"
- },
- "dependencies": {
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- }
- }
- },
- "@babel/types": {
- "version": "7.11.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
- "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
- "lodash": "^4.17.19",
- "to-fast-properties": "^2.0.0"
- }
- },
- "@eslint/eslintrc": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
- "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
- "dev": true,
- "requires": {
- "ajv": "^6.12.4",
- "debug": "^4.1.1",
- "espree": "^7.3.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.2.1",
- "js-yaml": "^3.13.1",
- "lodash": "^4.17.19",
- "minimatch": "^3.0.4",
- "strip-json-comments": "^3.1.1"
- },
- "dependencies": {
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
- "dev": true,
- "requires": {
- "type-fest": "^0.8.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- }
- }
- },
- "@types/color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
- "dev": true
- },
- "@types/json-schema": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
- "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
- "dev": true
- },
- "@webassemblyjs/ast": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
- "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0"
- }
- },
- "@webassemblyjs/floating-point-hex-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
- "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
- "dev": true
- },
- "@webassemblyjs/helper-api-error": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
- "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
- "dev": true
- },
- "@webassemblyjs/helper-buffer": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
- "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
- "dev": true
- },
- "@webassemblyjs/helper-code-frame": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
- "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/wast-printer": "1.9.0"
- }
- },
- "@webassemblyjs/helper-fsm": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
- "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
- "dev": true
- },
- "@webassemblyjs/helper-module-context": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
- "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0"
- },
- "dependencies": {
- "@webassemblyjs/ast": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
- "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0"
- }
- },
- "@webassemblyjs/helper-module-context": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
- "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g=="
- }
- }
- },
- "@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
- "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
- "dev": true
- },
- "@webassemblyjs/helper-wasm-section": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
- "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0"
- }
- },
- "@webassemblyjs/ieee754": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
- "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
- "dev": true,
- "requires": {
- "@xtuc/ieee754": "^1.2.0"
- }
- },
- "@webassemblyjs/leb128": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
- "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
- "dev": true,
- "requires": {
- "@xtuc/long": "4.2.2"
- }
- },
- "@webassemblyjs/utf8": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
- "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
- "dev": true
- },
- "@webassemblyjs/wasm-edit": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
- "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/helper-wasm-section": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-opt": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "@webassemblyjs/wast-printer": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-gen": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
- "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-opt": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
- "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0"
- }
- },
- "@webassemblyjs/wasm-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
- "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
- }
- },
- "@webassemblyjs/wast-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
- "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/floating-point-hex-parser": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-code-frame": "1.9.0",
- "@webassemblyjs/helper-fsm": "1.9.0",
- "@xtuc/long": "4.2.2"
- }
- },
- "@webassemblyjs/wast-printer": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
- "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0",
- "@xtuc/long": "4.2.2"
- }
- },
- "@xtuc/ieee754": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
- "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
- "dev": true
- },
- "@xtuc/long": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
- "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
- "dev": true
- },
- "acorn": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
- "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
- "dev": true
- },
- "acorn-jsx": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
- "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
- "dev": true
- },
- "ajv": {
- "version": "6.12.4",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
- "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ajv-errors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
- "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true
- },
- "ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
- },
- "ansi-colors": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
- "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
- "dev": true
- },
- "ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "dev": true,
- "optional": true,
- "requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "optional": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "aproba": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
- "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
- },
- "arr-flatten": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
- "dev": true
- },
- "arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
- "dev": true
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
- },
- "asn1.js": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
- "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
- "dev": true,
- "requires": {
- "bn.js": "^4.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "safer-buffer": "^2.1.0"
- }
- },
- "assert": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
- "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
- "dev": true,
- "requires": {
- "object-assign": "^4.1.1",
- "util": "0.10.3"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
- "dev": true
- },
- "util": {
- "version": "0.10.3",
- "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
- "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
- "dev": true,
- "requires": {
- "inherits": "2.0.1"
- }
- }
- }
- },
- "assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
- "dev": true
- },
- "astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
- "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
- "dev": true
- },
- "async-each": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
- "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
- "dev": true,
- "optional": true
- },
- "atob": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
- "dev": true
- },
- "babel-helper-evaluate-path": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz",
- "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==",
- "dev": true
- },
- "babel-helper-flip-expressions": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz",
- "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=",
- "dev": true
- },
- "babel-helper-is-nodes-equiv": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz",
- "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=",
- "dev": true
- },
- "babel-helper-is-void-0": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz",
- "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=",
- "dev": true
- },
- "babel-helper-mark-eval-scopes": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz",
- "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=",
- "dev": true
- },
- "babel-helper-remove-or-void": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz",
- "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=",
- "dev": true
- },
- "babel-helper-to-multiple-sequence-expressions": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz",
- "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==",
- "dev": true
- },
- "babel-loader": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
- "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
- "dev": true,
- "requires": {
- "find-cache-dir": "^2.1.0",
- "loader-utils": "^1.4.0",
- "mkdirp": "^0.5.3",
- "pify": "^4.0.1",
- "schema-utils": "^2.6.5"
- }
- },
- "babel-plugin-dynamic-import-node": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
- "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
- "dev": true,
- "requires": {
- "object.assign": "^4.1.0"
- }
- },
- "babel-plugin-minify-builtins": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz",
- "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==",
- "dev": true
- },
- "babel-plugin-minify-constant-folding": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz",
- "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==",
- "dev": true,
- "requires": {
- "babel-helper-evaluate-path": "^0.5.0"
- }
- },
- "babel-plugin-minify-dead-code-elimination": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz",
- "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==",
- "dev": true,
- "requires": {
- "babel-helper-evaluate-path": "^0.5.0",
- "babel-helper-mark-eval-scopes": "^0.4.3",
- "babel-helper-remove-or-void": "^0.4.3",
- "lodash": "^4.17.11"
- }
- },
- "babel-plugin-minify-flip-comparisons": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz",
- "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=",
- "dev": true,
- "requires": {
- "babel-helper-is-void-0": "^0.4.3"
- }
- },
- "babel-plugin-minify-guarded-expressions": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz",
- "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==",
- "dev": true,
- "requires": {
- "babel-helper-evaluate-path": "^0.5.0",
- "babel-helper-flip-expressions": "^0.4.3"
- }
- },
- "babel-plugin-minify-infinity": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz",
- "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=",
- "dev": true
- },
- "babel-plugin-minify-mangle-names": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz",
- "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==",
- "dev": true,
- "requires": {
- "babel-helper-mark-eval-scopes": "^0.4.3"
- }
- },
- "babel-plugin-minify-numeric-literals": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz",
- "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=",
- "dev": true
- },
- "babel-plugin-minify-replace": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz",
- "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==",
- "dev": true
- },
- "babel-plugin-minify-simplify": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz",
- "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==",
- "dev": true,
- "requires": {
- "babel-helper-evaluate-path": "^0.5.0",
- "babel-helper-flip-expressions": "^0.4.3",
- "babel-helper-is-nodes-equiv": "^0.0.1",
- "babel-helper-to-multiple-sequence-expressions": "^0.5.0"
- }
- },
- "babel-plugin-minify-type-constructors": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz",
- "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=",
- "dev": true,
- "requires": {
- "babel-helper-is-void-0": "^0.4.3"
- }
- },
- "babel-plugin-transform-inline-consecutive-adds": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz",
- "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=",
- "dev": true
- },
- "babel-plugin-transform-member-expression-literals": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz",
- "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=",
- "dev": true
- },
- "babel-plugin-transform-merge-sibling-variables": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz",
- "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=",
- "dev": true
- },
- "babel-plugin-transform-minify-booleans": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz",
- "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=",
- "dev": true
- },
- "babel-plugin-transform-property-literals": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz",
- "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "babel-plugin-transform-regexp-constructors": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz",
- "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=",
- "dev": true
- },
- "babel-plugin-transform-remove-console": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz",
- "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=",
- "dev": true
- },
- "babel-plugin-transform-remove-debugger": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz",
- "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=",
- "dev": true
- },
- "babel-plugin-transform-remove-undefined": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz",
- "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==",
- "dev": true,
- "requires": {
- "babel-helper-evaluate-path": "^0.5.0"
- }
- },
- "babel-plugin-transform-simplify-comparison-operators": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz",
- "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=",
- "dev": true
- },
- "babel-plugin-transform-undefined-to-void": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz",
- "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=",
- "dev": true
- },
- "babel-preset-minify": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz",
- "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==",
- "dev": true,
- "requires": {
- "babel-plugin-minify-builtins": "^0.5.0",
- "babel-plugin-minify-constant-folding": "^0.5.0",
- "babel-plugin-minify-dead-code-elimination": "^0.5.1",
- "babel-plugin-minify-flip-comparisons": "^0.4.3",
- "babel-plugin-minify-guarded-expressions": "^0.4.4",
- "babel-plugin-minify-infinity": "^0.4.3",
- "babel-plugin-minify-mangle-names": "^0.5.0",
- "babel-plugin-minify-numeric-literals": "^0.4.3",
- "babel-plugin-minify-replace": "^0.5.0",
- "babel-plugin-minify-simplify": "^0.5.1",
- "babel-plugin-minify-type-constructors": "^0.4.3",
- "babel-plugin-transform-inline-consecutive-adds": "^0.4.3",
- "babel-plugin-transform-member-expression-literals": "^6.9.4",
- "babel-plugin-transform-merge-sibling-variables": "^6.9.4",
- "babel-plugin-transform-minify-booleans": "^6.9.4",
- "babel-plugin-transform-property-literals": "^6.9.4",
- "babel-plugin-transform-regexp-constructors": "^0.4.3",
- "babel-plugin-transform-remove-console": "^6.9.4",
- "babel-plugin-transform-remove-debugger": "^6.9.4",
- "babel-plugin-transform-remove-undefined": "^0.5.0",
- "babel-plugin-transform-simplify-comparison-operators": "^6.9.4",
- "babel-plugin-transform-undefined-to-void": "^6.9.4",
- "lodash": "^4.17.11"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
- },
- "base": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
- "dev": true,
- "requires": {
- "cache-base": "^1.0.1",
- "class-utils": "^0.3.5",
- "component-emitter": "^1.2.1",
- "define-property": "^1.0.0",
- "isobject": "^3.0.1",
- "mixin-deep": "^1.2.0",
- "pascalcase": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "base64-js": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
- "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
- "dev": true
- },
- "big.js": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
- "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
- "dev": true
- },
- "binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
- "dev": true,
- "optional": true
- },
- "bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "dev": true
- },
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
- "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
- "dev": true
- },
- "browserify-aes": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
- "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
- "dev": true,
- "requires": {
- "buffer-xor": "^1.0.3",
- "cipher-base": "^1.0.0",
- "create-hash": "^1.1.0",
- "evp_bytestokey": "^1.0.3",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "browserify-cipher": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
- "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
- "dev": true,
- "requires": {
- "browserify-aes": "^1.0.4",
- "browserify-des": "^1.0.0",
- "evp_bytestokey": "^1.0.0"
- }
- },
- "browserify-des": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
- "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.1",
- "des.js": "^1.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "browserify-rsa": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
- "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "randombytes": "^2.0.1"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "browserify-sign": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
- "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.1",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.2",
- "elliptic": "^6.0.0",
- "inherits": "^2.0.1",
- "parse-asn1": "^5.0.0"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "browserify-zlib": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
- "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
- "dev": true,
- "requires": {
- "pako": "~1.0.5"
- }
- },
- "browserslist": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz",
- "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==",
- "dev": true,
- "requires": {
- "caniuse-lite": "^1.0.30001111",
- "electron-to-chromium": "^1.3.523",
- "escalade": "^3.0.2",
- "node-releases": "^1.1.60"
- }
- },
- "buffer": {
- "version": "4.9.2",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
- "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
- "dev": true,
- "requires": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4",
- "isarray": "^1.0.0"
- }
- },
- "buffer-from": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
- "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
- "dev": true
- },
- "buffer-xor": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
- "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
- "dev": true
- },
- "builtin-status-codes": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
- "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
- "dev": true
- },
- "cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
- "dev": true,
- "requires": {
- "collection-visit": "^1.0.0",
- "component-emitter": "^1.2.1",
- "get-value": "^2.0.6",
- "has-value": "^1.0.0",
- "isobject": "^3.0.1",
- "set-value": "^2.0.0",
- "to-object-path": "^0.3.0",
- "union-value": "^1.0.0",
- "unset-value": "^1.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
- },
- "caniuse-lite": {
- "version": "1.0.30001124",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001124.tgz",
- "integrity": "sha512-zQW8V3CdND7GHRH6rxm6s59Ww4g/qGWTheoboW9nfeMg7sUoopIfKCcNZUjwYRCOrvereh3kwDpZj4VLQ7zGtA==",
- "dev": true
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
- "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
- "dev": true,
- "optional": true,
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- },
- "dependencies": {
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- }
- }
- },
- "chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true
- },
- "chrome-trace-event": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
- "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
- "dev": true,
- "requires": {
- "tslib": "^1.9.0"
- }
- },
- "cipher-base": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
- "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "class-utils": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
- "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
- "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
- "dev": true,
- "requires": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
- "dev": true,
- "requires": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "commander": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true
- },
- "commondir": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
- "dev": true
- },
- "component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
- "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
- "console-browserify": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
- "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
- "dev": true,
- "requires": {
- "date-now": "^0.1.4"
- }
- },
- "constants-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
- "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
- "dev": true
- },
- "convert-source-map": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
- "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.1"
- }
- },
- "copy-concurrently": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
- "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1",
- "fs-write-stream-atomic": "^1.0.8",
- "iferr": "^0.1.5",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.0"
- }
- },
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
- "dev": true
- },
- "core-js": {
- "version": "3.6.5",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
- "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
- "dev": true
- },
- "core-js-compat": {
- "version": "3.6.5",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
- "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
- "dev": true,
- "requires": {
- "browserslist": "^4.8.5",
- "semver": "7.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
- "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
- "dev": true
- }
- }
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true
- },
- "create-ecdh": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
- "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "elliptic": "^6.5.3"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "create-hash": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
- "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.1",
- "inherits": "^2.0.1",
- "md5.js": "^1.3.4",
- "ripemd160": "^2.0.1",
- "sha.js": "^2.4.0"
- }
- },
- "create-hmac": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
- "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
- "dev": true,
- "requires": {
- "cipher-base": "^1.0.3",
- "create-hash": "^1.1.0",
- "inherits": "^2.0.1",
- "ripemd160": "^2.0.0",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- }
- },
- "cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "crypto-browserify": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
- "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
- "dev": true,
- "requires": {
- "browserify-cipher": "^1.0.0",
- "browserify-sign": "^4.0.0",
- "create-ecdh": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.0",
- "diffie-hellman": "^5.0.0",
- "inherits": "^2.0.1",
- "pbkdf2": "^3.0.3",
- "public-encrypt": "^4.0.0",
- "randombytes": "^2.0.0",
- "randomfill": "^1.0.3"
- }
- },
- "cyclist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
- "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
- "dev": true
- },
- "date-now": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
- "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
- "dev": true
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
- },
- "decode-uri-component": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
- "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
- "dev": true
- },
- "deep-is": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
- "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
- "dev": true
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "des.js": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
- "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
- }
- },
- "detect-file": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
- "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
- "dev": true
- },
- "diffie-hellman": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
- "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "miller-rabin": "^4.0.0",
- "randombytes": "^2.0.0"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "domain-browser": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
- "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
- "dev": true
- },
- "duplexify": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
- "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0",
- "stream-shift": "^1.0.0"
- }
- },
- "electron-to-chromium": {
- "version": "1.3.562",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.562.tgz",
- "integrity": "sha512-WhRe6liQ2q/w1MZc8mD8INkenHivuHdrr4r5EQHNomy3NJux+incP6M6lDMd0paShP3MD0WGe5R1TWmEClf+Bg==",
- "dev": true
- },
- "elliptic": {
- "version": "6.5.4",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
- "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
- "dev": true,
- "requires": {
- "bn.js": "^4.11.9",
- "brorand": "^1.1.0",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.1",
- "inherits": "^2.0.4",
- "minimalistic-assert": "^1.0.1",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "emojis-list": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
- "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
- "dev": true
- },
- "end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "dev": true,
- "requires": {
- "once": "^1.4.0"
- }
- },
- "enhanced-resolve": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
- "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "memory-fs": "^0.5.0",
- "tapable": "^1.0.0"
- },
- "dependencies": {
- "memory-fs": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
- "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
- "dev": true,
- "requires": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
- }
- }
- }
- },
- "enquirer": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
- "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
- "dev": true,
- "requires": {
- "ansi-colors": "^4.1.1"
- }
- },
- "errno": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
- "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
- "dev": true,
- "requires": {
- "prr": "~1.0.1"
- }
- },
- "escalade": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz",
- "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==",
- "dev": true
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "eslint": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.8.1.tgz",
- "integrity": "sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "@eslint/eslintrc": "^0.1.3",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "enquirer": "^2.3.5",
- "eslint-scope": "^5.1.0",
- "eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^1.3.0",
- "espree": "^7.3.0",
- "esquery": "^1.2.0",
- "esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash": "^4.17.19",
- "minimatch": "^3.0.4",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "progress": "^2.0.0",
- "regexpp": "^3.1.0",
- "semver": "^7.2.1",
- "strip-ansi": "^6.0.0",
- "strip-json-comments": "^3.1.0",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
- "dev": true,
- "requires": {
- "@types/color-name": "^1.1.1",
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
- "dev": true,
- "requires": {
- "type-fest": "^0.8.1"
- }
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "semver": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
- "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
- "dev": true
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "eslint-scope": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
- "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
- "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.1.0"
- }
- },
- "eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true
- },
- "espree": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
- "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
- "dev": true,
- "requires": {
- "acorn": "^7.4.0",
- "acorn-jsx": "^5.2.0",
- "eslint-visitor-keys": "^1.3.0"
- }
- },
- "esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true
- },
- "esquery": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
- "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
- "dev": true,
- "requires": {
- "estraverse": "^5.1.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
- "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
- "dev": true
- }
- }
- },
- "esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "requires": {
- "estraverse": "^5.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
- "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
- "dev": true
- }
- }
- },
- "estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true
- },
- "events": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
- "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
- "dev": true
- },
- "evp_bytestokey": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
- "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
- "dev": true,
- "requires": {
- "md5.js": "^1.3.4",
- "safe-buffer": "^5.1.1"
- }
- },
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "dev": true,
- "requires": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
- },
- "shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
- "requires": {
- "shebang-regex": "^1.0.0"
- }
- },
- "shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "expand-tilde": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
- "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
- "dev": true,
- "requires": {
- "homedir-polyfill": "^1.0.1"
- }
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "dev": true,
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
- "dev": true,
- "requires": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
- "dev": true
- },
- "figgy-pudding": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
- "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
- "dev": true
- },
- "file-entry-cache": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
- "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
- "dev": true,
- "requires": {
- "flat-cache": "^2.0.1"
- }
- },
- "file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "dev": true,
- "optional": true
- },
- "fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
- "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
- }
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "findup-sync": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
- "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
- "dev": true,
- "requires": {
- "detect-file": "^1.0.0",
- "is-glob": "^4.0.0",
- "micromatch": "^3.0.4",
- "resolve-dir": "^1.0.1"
- },
- "dependencies": {
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "dev": true,
- "requires": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- }
- },
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
- "dev": true,
- "requires": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
- },
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
- "dev": true
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- }
- }
- }
- },
- "flat-cache": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
- "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
- "dev": true,
- "requires": {
- "flatted": "^2.0.0",
- "rimraf": "2.6.3",
- "write": "1.0.3"
- }
- },
- "flatted": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
- "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
- "dev": true
- },
- "flush-write-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
- "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "readable-stream": "^2.3.6"
- }
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
- "dev": true
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "dev": true,
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "from2": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
- "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0"
- }
- },
- "fs-readdir-recursive": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
- "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
- "dev": true
- },
- "fs-write-stream-atomic": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
- "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "iferr": "^0.1.5",
- "imurmurhash": "^0.1.4",
- "readable-stream": "1 || 2"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "dev": true,
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
- "gensync": {
- "version": "1.0.0-beta.1",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
- "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
- "dev": true
- },
- "get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
- },
- "get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
- "dev": true
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
- "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- },
- "global-modules": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
- "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
- "dev": true,
- "requires": {
- "global-prefix": "^3.0.0"
- },
- "dependencies": {
- "global-prefix": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
- "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
- "dev": true,
- "requires": {
- "ini": "^1.3.5",
- "kind-of": "^6.0.2",
- "which": "^1.3.1"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
- "dev": true
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "global-prefix": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
- "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
- "dev": true,
- "requires": {
- "expand-tilde": "^2.0.2",
- "homedir-polyfill": "^1.0.1",
- "ini": "^1.3.4",
- "is-windows": "^1.0.1",
- "which": "^1.2.14"
- },
- "dependencies": {
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true
- },
- "graceful-fs": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
- "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
- "dev": true
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
- },
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
- "has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "has-values": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
- "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "dependencies": {
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "hash-base": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
- "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "hash.js": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
- "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "minimalistic-assert": "^1.0.1"
- }
- },
- "hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
- "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
- "dev": true,
- "requires": {
- "hash.js": "^1.0.3",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "homedir-polyfill": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
- "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
- "dev": true,
- "requires": {
- "parse-passwd": "^1.0.0"
- }
- },
- "https-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
- "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
- "dev": true
- },
- "ieee754": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
- "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
- "dev": true
- },
- "iferr": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
- "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
- "dev": true
- },
- "ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
- "dev": true
- },
- "import-fresh": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
- "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
- "dev": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- }
- },
- "import-local": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
- "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
- "dev": true,
- "requires": {
- "pkg-dir": "^3.0.0",
- "resolve-cwd": "^2.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
- },
- "infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true
- },
- "interpret": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
- "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
- "dev": true
- },
- "invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
- "dev": true,
- "requires": {
- "loose-envify": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "dev": true,
- "optional": true,
- "requires": {
- "binary-extensions": "^1.0.0"
- }
- },
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
- }
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-plain-object": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
- "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "is-windows": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
- "dev": true
- },
- "is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
- "dev": true
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- },
- "js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "js-yaml": {
- "version": "3.14.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
- "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
- "dev": true,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true
- },
- "json-parse-better-errors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
- "dev": true
- },
- "json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
- },
- "leven": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "dev": true
- },
- "levenary": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
- "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
- "dev": true,
- "requires": {
- "leven": "^3.1.0"
- }
- },
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "loader-runner": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
- "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
- "dev": true
- },
- "loader-utils": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
- "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
- "dev": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^1.0.1"
- },
- "dependencies": {
- "json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- }
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "requires": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- }
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
- "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
- "dev": true,
- "requires": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
- }
- },
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
- "dev": true
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
- "dev": true,
- "requires": {
- "object-visit": "^1.0.0"
- }
- },
- "md5.js": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
- "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
- "dev": true,
- "requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "memory-fs": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
- "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
- "dev": true,
- "requires": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
- }
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- }
- },
- "miller-rabin": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
- "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
- "dev": true,
- "requires": {
- "bn.js": "^4.0.0",
- "brorand": "^1.0.1"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
- "dev": true
- },
- "minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
- "dev": true
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
- "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
- "dev": true
- },
- "mississippi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
- "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
- "dev": true,
- "requires": {
- "concat-stream": "^1.5.0",
- "duplexify": "^3.4.2",
- "end-of-stream": "^1.1.0",
- "flush-write-stream": "^1.0.0",
- "from2": "^2.1.0",
- "parallel-transform": "^1.1.0",
- "pump": "^3.0.0",
- "pumpify": "^1.3.3",
- "stream-each": "^1.1.0",
- "through2": "^2.0.0"
- }
- },
- "mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
- "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
- "dev": true,
- "requires": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "move-concurrently": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
- "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1",
- "copy-concurrently": "^1.0.0",
- "fs-write-stream-atomic": "^1.0.8",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.3"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "nan": {
- "version": "2.14.1",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
- "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
- "dev": true,
- "optional": true
- },
- "nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "fragment-cache": "^0.2.1",
- "is-windows": "^1.0.2",
- "kind-of": "^6.0.2",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
- "dev": true
- }
- }
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
- "dev": true
- },
- "neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
- },
- "nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
- },
- "node-libs-browser": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
- "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
- "dev": true,
- "requires": {
- "assert": "^1.1.1",
- "browserify-zlib": "^0.2.0",
- "buffer": "^4.3.0",
- "console-browserify": "^1.1.0",
- "constants-browserify": "^1.0.0",
- "crypto-browserify": "^3.11.0",
- "domain-browser": "^1.1.1",
- "events": "^3.0.0",
- "https-browserify": "^1.0.0",
- "os-browserify": "^0.3.0",
- "path-browserify": "0.0.1",
- "process": "^0.11.10",
- "punycode": "^1.2.4",
- "querystring-es3": "^0.2.0",
- "readable-stream": "^2.3.3",
- "stream-browserify": "^2.0.1",
- "stream-http": "^2.7.2",
- "string_decoder": "^1.0.0",
- "timers-browserify": "^2.0.4",
- "tty-browserify": "0.0.0",
- "url": "^0.11.0",
- "util": "^0.11.0",
- "vm-browserify": "^1.0.1"
- },
- "dependencies": {
- "punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
- "dev": true
- }
- }
- },
- "node-releases": {
- "version": "1.1.60",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz",
- "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==",
- "dev": true
- },
- "normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
- }
- }
- },
- "object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
- },
- "object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
- "dev": true,
- "requires": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- },
- "object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
- }
- },
- "object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "dev": true,
- "requires": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- },
- "dependencies": {
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true
- },
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- }
- }
- },
- "os-browserify": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
- "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
- "dev": true
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- },
- "pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "dev": true
- },
- "parallel-transform": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
- "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
- "dev": true,
- "requires": {
- "cyclist": "^1.0.1",
- "inherits": "^2.0.3",
- "readable-stream": "^2.1.5"
- }
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "requires": {
- "callsites": "^3.0.0"
- }
- },
- "parse-asn1": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
- "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
- "dev": true,
- "requires": {
- "asn1.js": "^5.2.0",
- "browserify-aes": "^1.0.0",
- "evp_bytestokey": "^1.0.0",
- "pbkdf2": "^3.0.3",
- "safe-buffer": "^5.1.1"
- }
- },
- "parse-passwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
- "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
- "dev": true
- },
- "pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
- "dev": true
- },
- "path-browserify": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
- "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
- "dev": true
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
- "dev": true,
- "optional": true
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
- },
- "path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true
- },
- "path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
- "dev": true
- },
- "pbkdf2": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
- "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
- "dev": true,
- "requires": {
- "create-hash": "^1.1.2",
- "create-hmac": "^1.1.4",
- "ripemd160": "^2.0.1",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- }
- },
- "picomatch": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
- "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
- "dev": true,
- "optional": true
- },
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
- },
- "pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0"
- }
- },
- "posix-character-classes": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
- "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
- "dev": true
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true
- },
- "process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
- "dev": true
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
- },
- "progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true
- },
- "promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
- "dev": true
- },
- "prr": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
- "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
- "dev": true
- },
- "public-encrypt": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
- "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.0",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "parse-asn1": "^5.0.0",
- "randombytes": "^2.0.1",
- "safe-buffer": "^5.1.2"
- },
- "dependencies": {
- "bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
- "dev": true
- }
- }
- },
- "pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
- "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
- "dev": true,
- "requires": {
- "duplexify": "^3.6.0",
- "inherits": "^2.0.3",
- "pump": "^2.0.0"
- },
- "dependencies": {
- "pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- }
- }
- },
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true
- },
- "querystring": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
- "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
- "dev": true
- },
- "querystring-es3": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
- "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
- "dev": true
- },
- "randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
- "requires": {
- "safe-buffer": "^5.1.0"
- }
- },
- "randomfill": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
- "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
- "dev": true,
- "requires": {
- "randombytes": "^2.0.5",
- "safe-buffer": "^5.1.0"
- }
- },
- "readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- }
- },
- "regenerate": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
- "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==",
- "dev": true
- },
- "regenerate-unicode-properties": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
- "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
- "dev": true,
- "requires": {
- "regenerate": "^1.4.0"
- }
- },
- "regenerator-runtime": {
- "version": "0.13.7",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
- "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
- "dev": true
- },
- "regenerator-transform": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
- "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
- "dev": true,
- "requires": {
- "@babel/runtime": "^7.8.4"
- }
- },
- "regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "regexpp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
- "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
- "dev": true
- },
- "regexpu-core": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
- "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
- "dev": true,
- "requires": {
- "regenerate": "^1.4.0",
- "regenerate-unicode-properties": "^8.2.0",
- "regjsgen": "^0.5.1",
- "regjsparser": "^0.6.4",
- "unicode-match-property-ecmascript": "^1.0.4",
- "unicode-match-property-value-ecmascript": "^1.2.0"
- }
- },
- "regjsgen": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
- "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
- "dev": true
- },
- "regjsparser": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz",
- "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==",
- "dev": true,
- "requires": {
- "jsesc": "~0.5.0"
- },
- "dependencies": {
- "jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
- "dev": true
- }
- }
- },
- "remove-trailing-separator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
- "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
- "dev": true,
- "optional": true
- },
- "repeat-element": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
- "dev": true
- },
- "repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
- "dev": true
- },
- "resolve": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
- "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
- "dev": true,
- "requires": {
- "path-parse": "^1.0.6"
- }
- },
- "resolve-cwd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
- "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
- "dev": true,
- "requires": {
- "resolve-from": "^3.0.0"
- },
- "dependencies": {
- "resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
- "dev": true
- }
- }
- },
- "resolve-dir": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
- "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
- "dev": true,
- "requires": {
- "expand-tilde": "^2.0.0",
- "global-modules": "^1.0.0"
- },
- "dependencies": {
- "global-modules": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
- "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
- "dev": true,
- "requires": {
- "global-prefix": "^1.0.1",
- "is-windows": "^1.0.1",
- "resolve-dir": "^1.0.0"
- }
- }
- }
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- },
- "resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
- "dev": true
- },
- "ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
- "dev": true
- },
- "rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
- "dev": true,
- "requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1"
- }
- },
- "run-queue": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
- "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
- "dev": true,
- "requires": {
- "aproba": "^1.1.1"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
- "safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
- "dev": true,
- "requires": {
- "ret": "~0.1.10"
- }
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
- },
- "schema-utils": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
- "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
- "dev": true,
- "requires": {
- "@types/json-schema": "^7.0.5",
- "ajv": "^6.12.4",
- "ajv-keywords": "^3.5.2"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
- },
- "serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
- "dev": true,
- "requires": {
- "randombytes": "^2.1.0"
- }
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
- },
- "set-value": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
- "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
- "dev": true
- },
- "sha.js": {
- "version": "2.4.11",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
- "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true
- },
- "slash": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
- "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
- "dev": true
- },
- "slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
- "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
- }
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
- "dev": true,
- "requires": {
- "base": "^0.11.1",
- "debug": "^2.2.0",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "map-cache": "^0.2.2",
- "source-map": "^0.5.6",
- "source-map-resolve": "^0.5.0",
- "use": "^3.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
- }
- },
- "snapdragon-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
- "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
- "dev": true,
- "requires": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
- "dev": true,
- "requires": {
- "kind-of": "^3.2.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "source-list-map": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
- "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- },
- "source-map-resolve": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
- "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
- "dev": true,
- "requires": {
- "atob": "^2.1.2",
- "decode-uri-component": "^0.2.0",
- "resolve-url": "^0.2.1",
- "source-map-url": "^0.4.0",
- "urix": "^0.1.0"
- }
- },
- "source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "source-map-url": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
- "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
- "dev": true
- },
- "split-string": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
- "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.0"
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
- "dev": true
- },
- "ssri": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
- "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
- "dev": true,
- "requires": {
- "figgy-pudding": "^3.5.1"
- }
- },
- "static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
- "dev": true,
- "requires": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "stream-browserify": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
- "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
- "dev": true,
- "requires": {
- "inherits": "~2.0.1",
- "readable-stream": "^2.0.2"
- }
- },
- "stream-each": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
- "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "stream-shift": "^1.0.0"
- }
- },
- "stream-http": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
- "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
- "dev": true,
- "requires": {
- "builtin-status-codes": "^3.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.3.6",
- "to-arraybuffer": "^1.0.0",
- "xtend": "^4.0.0"
- }
- },
- "stream-shift": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
- "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- },
- "strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true
- },
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "table": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
- "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
- "dev": true,
- "requires": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
- }
- },
- "tapable": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
- "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
- "dev": true
- },
- "terser": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz",
- "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==",
- "dev": true,
- "requires": {
- "commander": "^2.20.0",
- "source-map": "~0.6.1",
- "source-map-support": "~0.5.12"
- },
- "dependencies": {
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- }
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
- "dev": true
- },
- "through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
- "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
- "dev": true,
- "requires": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
- }
- },
- "timers-browserify": {
- "version": "2.0.10",
- "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
- "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
- "dev": true,
- "requires": {
- "setimmediate": "^1.0.4"
- }
- },
- "to-arraybuffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
- "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
- "dev": true
- },
- "to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
- "dev": true
- },
- "to-object-path": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
- "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
- "dev": true,
- "requires": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
- },
- "dependencies": {
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "tslib": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
- "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
- "dev": true
- },
- "tty-browserify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
- "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
- "dev": true
- },
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- },
- "type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "dev": true
- },
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
- "unicode-canonical-property-names-ecmascript": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
- "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ=="
- },
- "unicode-match-property-ecmascript": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
- "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
- "dev": true,
- "requires": {
- "unicode-canonical-property-names-ecmascript": "^1.0.4",
- "unicode-property-aliases-ecmascript": "^1.0.4"
- }
- },
- "unicode-match-property-value-ecmascript": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
- "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==",
- "dev": true
- },
- "unicode-property-aliases-ecmascript": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
- "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg=="
- },
- "union-value": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
- "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- }
- },
- "unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "dev": true,
- "requires": {
- "unique-slug": "^2.0.0"
- }
- },
- "unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "dev": true,
- "requires": {
- "imurmurhash": "^0.1.4"
- }
- },
- "unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
- "dev": true,
- "requires": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "dev": true,
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
- "dev": true
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- }
- }
- },
- "upath": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
- "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
- "dev": true,
- "optional": true
- },
- "uri-js": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
- "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
- "dev": true
- },
- "url": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
- "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
- "dev": true,
- "requires": {
- "punycode": "1.3.2",
- "querystring": "0.2.0"
- },
- "dependencies": {
- "punycode": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
- "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
- "dev": true
- }
- }
- },
- "use": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
- "dev": true
- },
- "util": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
- "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- }
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
- },
- "v8-compile-cache": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
- "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
- "dev": true
- },
- "vm-browserify": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
- "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
- "dev": true
- },
- "watchpack": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
- "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
- "dev": true,
- "requires": {
- "chokidar": "^3.4.1",
- "graceful-fs": "^4.1.2",
- "neo-async": "^2.5.0",
- "watchpack-chokidar2": "^2.0.0"
- },
- "dependencies": {
- "anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
- "dev": true,
- "optional": true,
- "requires": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "binary-extensions": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
- "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
- "dev": true,
- "optional": true
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "optional": true,
- "requires": {
- "fill-range": "^7.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- }
- },
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
- }
- }
- },
- "chokidar": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
- "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
- "dev": true,
- "optional": true,
- "requires": {
- "anymatch": "~3.1.1",
- "braces": "~3.0.2",
- "fsevents": "~2.1.2",
- "glob-parent": "~5.1.0",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.4.0"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
- "glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "optional": true,
- "requires": {
- "binary-extensions": "^2.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "optional": true
- },
- "readdirp": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
- "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "picomatch": "^2.2.1"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- }
- }
- },
- "watchpack-chokidar2": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
- "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
- "dev": true,
- "optional": true,
- "requires": {
- "chokidar": "^2.1.8"
- }
- },
- "webpack": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz",
- "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/wasm-edit": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "acorn": "^6.4.1",
- "ajv": "^6.10.2",
- "ajv-keywords": "^3.4.1",
- "chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^4.3.0",
- "eslint-scope": "^4.0.3",
- "json-parse-better-errors": "^1.0.2",
- "loader-runner": "^2.4.0",
- "loader-utils": "^1.2.3",
- "memory-fs": "^0.4.1",
- "micromatch": "^3.1.10",
- "mkdirp": "^0.5.3",
- "neo-async": "^2.6.1",
- "node-libs-browser": "^2.2.1",
- "schema-utils": "^1.0.0",
- "tapable": "^1.1.3",
- "terser-webpack-plugin": "^1.4.3",
- "watchpack": "^1.7.4",
- "webpack-sources": "^1.4.1"
- },
- "dependencies": {
- "acorn": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
- "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
- "dev": true
- },
- "cacache": {
- "version": "12.0.4",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
- "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
- "dev": true,
- "requires": {
- "bluebird": "^3.5.5",
- "chownr": "^1.1.1",
- "figgy-pudding": "^3.5.1",
- "glob": "^7.1.4",
- "graceful-fs": "^4.1.15",
- "infer-owner": "^1.0.3",
- "lru-cache": "^5.1.1",
- "mississippi": "^3.0.0",
- "mkdirp": "^0.5.1",
- "move-concurrently": "^1.0.1",
- "promise-inflight": "^1.0.1",
- "rimraf": "^2.6.3",
- "ssri": "^6.0.1",
- "unique-filename": "^1.1.1",
- "y18n": "^4.0.0"
- }
- },
- "eslint-scope": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
- "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
- }
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- },
- "terser-webpack-plugin": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
- "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
- "dev": true,
- "requires": {
- "cacache": "^12.0.2",
- "find-cache-dir": "^2.1.0",
- "is-wsl": "^1.1.0",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^4.0.0",
- "source-map": "^0.6.1",
- "terser": "^4.1.2",
- "webpack-sources": "^1.4.0",
- "worker-farm": "^1.7.0"
- }
- }
- }
- },
- "webpack-cli": {
- "version": "3.3.12",
- "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz",
- "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==",
- "dev": true,
- "requires": {
- "chalk": "^2.4.2",
- "cross-spawn": "^6.0.5",
- "enhanced-resolve": "^4.1.1",
- "findup-sync": "^3.0.0",
- "global-modules": "^2.0.0",
- "import-local": "^2.0.0",
- "interpret": "^1.4.0",
- "loader-utils": "^1.4.0",
- "supports-color": "^6.1.0",
- "v8-compile-cache": "^2.1.1",
- "yargs": "^13.3.2"
- },
- "dependencies": {
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "dev": true,
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
- "dev": true
- },
- "shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
- "dev": true,
- "requires": {
- "shebang-regex": "^1.0.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
- "dev": true
- },
- "supports-color": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
- "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "webpack-sources": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
- "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
- "dev": true,
- "requires": {
- "source-list-map": "^2.0.0",
- "source-map": "~0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "which-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
- "dev": true
- },
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true
- },
- "worker-farm": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
- "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
- "dev": true,
- "requires": {
- "errno": "~0.1.7"
- }
- },
- "wrap-ansi": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
- "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.0",
- "string-width": "^3.0.0",
- "strip-ansi": "^5.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
- },
- "write": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
- "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
- "dev": true,
- "requires": {
- "mkdirp": "^0.5.1"
- }
- },
- "xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true
- },
- "y18n": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
- "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
- "dev": true
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "yargs": {
- "version": "13.3.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
- "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
- "dev": true,
- "requires": {
- "cliui": "^5.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.1.2"
- }
- },
- "yargs-parser": {
- "version": "13.1.2",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
- "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
- }
- }
-}
diff --git a/runtime/js/package.json b/runtime/js/package.json
deleted file mode 100644
index f5426cac0..000000000
--- a/runtime/js/package.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "name": "wails-runtime",
- "version": "1.0.0",
- "description": "The Javascript Wails Runtime",
- "main": "index.js",
- "scripts": {
- "build": "./node_modules/.bin/eslint core/ && npm run build:prod",
- "build:prod": "./node_modules/.bin/webpack --env prod --colors",
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/wailsapp/runtime.git"
- },
- "keywords": [
- "Wails",
- "Go",
- "Javascript",
- "Runtime"
- ],
- "browserslist": [
- "> 5%",
- "IE 9"
- ],
- "author": "Lea Anthony ",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/wailsapp/runtime/issues"
- },
- "homepage": "https://github.com/wailsapp/runtime#readme",
- "devDependencies": {
- "@babel/cli": "^7.11.5",
- "@babel/core": "^7.11.5",
- "@babel/plugin-transform-object-assign": "^7.10.4",
- "@babel/preset-env": "^7.11.5",
- "babel-loader": "^8.1.0",
- "babel-preset-minify": "^0.5.1",
- "core-js": "^3.6.5",
- "eslint": "^7.8.1",
- "webpack": "^4.44.1",
- "webpack-cli": "^3.3.12"
- }
-}
diff --git a/runtime/js/runtime/.npmignore b/runtime/js/runtime/.npmignore
deleted file mode 100644
index 945ce43a9..000000000
--- a/runtime/js/runtime/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-index.js
\ No newline at end of file
diff --git a/runtime/js/runtime/README.md b/runtime/js/runtime/README.md
deleted file mode 100644
index bb608fdca..000000000
--- a/runtime/js/runtime/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Wails Runtime
-
-This module is the Javascript runtime library for the [Wails](https://wails.app) framework. It is intended to be installed as part of a [Wails](https://wails.app) project, not a standalone module.
diff --git a/runtime/js/runtime/browser.js b/runtime/js/runtime/browser.js
deleted file mode 100644
index 70167883f..000000000
--- a/runtime/js/runtime/browser.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-/**
- * Opens the given URL in the system browser
- *
- * @export
- * @param {string} url
- * @returns
- */
-function OpenURL(url) {
- return window.wails.Browser.OpenURL(url);
-}
-
-/**
- * Opens the given filename using the system's default file handler
- *
- * @export
- * @param {sting} filename
- * @returns
- */
-function OpenFile(filename) {
- return window.wails.Browser.OpenFile(filename);
-}
-
-module.exports = {
- OpenURL: OpenURL,
- OpenFile: OpenFile
-};
\ No newline at end of file
diff --git a/runtime/js/runtime/events.js b/runtime/js/runtime/events.js
deleted file mode 100644
index 30a23a01e..000000000
--- a/runtime/js/runtime/events.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-
-/**
- * Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- * @param {number} maxCallbacks
- */
-function OnMultiple(eventName, callback, maxCallbacks) {
- window.wails.Events.OnMultiple(eventName, callback, maxCallbacks);
-}
-
-/**
- * Registers an event listener that will be invoked every time the event is emitted
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- */
-function On(eventName, callback) {
- OnMultiple(eventName, callback);
-}
-
-/**
- * Registers an event listener that will be invoked once then destroyed
- *
- * @export
- * @param {string} eventName
- * @param {function} callback
- */
-function Once(eventName, callback) {
- OnMultiple(eventName, callback, 1);
-}
-
-
-/**
- * Emit an event with the given name and data
- *
- * @export
- * @param {string} eventName
- */
-function Emit(eventName) {
- var args = [eventName].slice.call(arguments);
- return window.wails.Events.Emit.apply(null, args);
-}
-
-
-/**
- * Heartbeat emits the event `eventName`, every `timeInMilliseconds` milliseconds until
- * the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
- *
- * @export
- * @param {string} eventName
- * @param {number} timeInMilliseconds
- * @param {function} callback
- */
-function Heartbeat(eventName, timeInMilliseconds, callback) {
- window.wails.Events.Heartbeat(eventName, timeInMilliseconds, callback);
-}
-
-/**
- * Acknowledges a heartbeat event by name
- *
- * @export
- * @param {string} eventName
- */
-function Acknowledge(eventName) {
- return window.wails.Events.Acknowledge(eventName);
-}
-
-module.exports = {
- OnMultiple: OnMultiple,
- On: On,
- Once: Once,
- Emit: Emit,
- Heartbeat: Heartbeat,
- Acknowledge: Acknowledge
-};
\ No newline at end of file
diff --git a/runtime/js/runtime/init.js b/runtime/js/runtime/init.js
deleted file mode 100644
index 14de18624..000000000
--- a/runtime/js/runtime/init.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-/**
- * Initialises the Wails runtime
- *
- * @param {function} callback
- */
-function Init(callback) {
- window.wails._.Init(callback);
-}
-
-module.exports = Init;
diff --git a/runtime/js/runtime/log.js b/runtime/js/runtime/log.js
deleted file mode 100644
index 2defed8f7..000000000
--- a/runtime/js/runtime/log.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-
-/* jshint esversion: 6 */
-
-
-/**
- * Log the given debug message with the backend
- *
- * @export
- * @param {string} message
- */
-function Debug(message) {
- window.wails.Log.Debug(message);
-}
-
-/**
- * Log the given info message with the backend
- *
- * @export
- * @param {string} message
- */
-function Info(message) {
- window.wails.Log.Info(message);
-}
-
-/**
- * Log the given warning message with the backend
- *
- * @export
- * @param {string} message
- */
-function Warning(message) {
- window.wails.Log.Warning(message);
-}
-
-/**
- * Log the given error message with the backend
- *
- * @export
- * @param {string} message
- */
-function Error(message) {
- window.wails.Log.Error(message);
-}
-
-/**
- * Log the given fatal message with the backend
- *
- * @export
- * @param {string} message
- */
-function Fatal(message) {
- window.wails.Log.Fatal(message);
-}
-
-module.exports = {
- Debug: Debug,
- Info: Info,
- Warning: Warning,
- Error: Error,
- Fatal: Fatal
-};
diff --git a/runtime/js/runtime/main.js b/runtime/js/runtime/main.js
deleted file mode 100644
index 9310b8099..000000000
--- a/runtime/js/runtime/main.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-/* jshint esversion: 6 */
-
-const Log = require('./log');
-const Browser = require('./browser');
-const Events = require('./events');
-const Init = require('./init');
-const Store = require('./store');
-
-module.exports = {
- Log: Log,
- Browser: Browser,
- Events: Events,
- Init: Init,
- Store: Store,
-};
\ No newline at end of file
diff --git a/runtime/js/runtime/package-lock.json b/runtime/js/runtime/package-lock.json
deleted file mode 100644
index 1efda3274..000000000
--- a/runtime/js/runtime/package-lock.json
+++ /dev/null
@@ -1,492 +0,0 @@
-{
- "name": "@wailsapp/runtime",
- "version": "1.1.1",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "camelcase": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
- "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
- "dev": true
- },
- "cliui": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
- "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
- "dev": true,
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wrap-ansi": "^2.0.0"
- }
- },
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
- },
- "dts-dom": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/dts-dom/-/dts-dom-3.6.0.tgz",
- "integrity": "sha512-on5jxTgt+A6r0Zyyz6ZRHXaAO7J1VPnOd6+AmvI1vH440AlAZZNc5rUHzgPuTjGlrVr1rOWQYNl7ZJK6rDohbw==",
- "dev": true
- },
- "dts-gen": {
- "version": "0.5.8",
- "resolved": "https://registry.npmjs.org/dts-gen/-/dts-gen-0.5.8.tgz",
- "integrity": "sha512-kIAV6dlHaF7r5J+tIuOC1BJls2P72YM0cyWQUR88zcJEpX2ccRZe+HmXLfkkvfPwjvSO3FEqUiyC8On/grx5qw==",
- "dev": true,
- "requires": {
- "dts-dom": "^3.6.0",
- "parse-git-config": "^1.1.1",
- "typescript": "^3.5.1",
- "yargs": "^4.8.1"
- }
- },
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "fs-exists-sync": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
- "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
- "dev": true
- },
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
- "dev": true
- },
- "git-config-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz",
- "integrity": "sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "fs-exists-sync": "^0.1.0",
- "homedir-polyfill": "^1.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
- "dev": true
- },
- "homedir-polyfill": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
- "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
- "dev": true,
- "requires": {
- "parse-passwd": "^1.0.0"
- }
- },
- "hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true
- },
- "ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true
- },
- "invert-kv": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
- "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
- "dev": true
- },
- "is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "is-utf8": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
- "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
- "dev": true
- },
- "lcid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
- "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
- "dev": true,
- "requires": {
- "invert-kv": "^1.0.0"
- }
- },
- "load-json-file": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
- "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "strip-bom": "^2.0.0"
- }
- },
- "lodash.assign": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
- "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
- "dev": true
- },
- "normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
- },
- "os-locale": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
- "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
- "dev": true,
- "requires": {
- "lcid": "^1.0.0"
- }
- },
- "parse-git-config": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-1.1.1.tgz",
- "integrity": "sha1-06mYQxcTL1c5hxK7pDjhKVkN34w=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "fs-exists-sync": "^0.1.0",
- "git-config-path": "^1.0.1",
- "ini": "^1.3.4"
- }
- },
- "parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
- "dev": true,
- "requires": {
- "error-ex": "^1.2.0"
- }
- },
- "parse-passwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
- "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
- "dev": true
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "^2.0.0"
- }
- },
- "path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "path-type": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
- "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "dev": true,
- "requires": {
- "pinkie": "^2.0.0"
- }
- },
- "read-pkg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
- "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
- "dev": true,
- "requires": {
- "load-json-file": "^1.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^1.0.0"
- }
- },
- "read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
- "dev": true,
- "requires": {
- "find-up": "^1.0.0",
- "read-pkg": "^1.0.0"
- }
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
- "dev": true
- },
- "resolve": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
- "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
- "dev": true,
- "requires": {
- "path-parse": "^1.0.6"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
- },
- "spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
- "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
- "dev": true,
- "requires": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
- },
- "spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "requires": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-license-ids": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
- "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
- "dev": true
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-bom": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
- "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
- "dev": true,
- "requires": {
- "is-utf8": "^0.2.0"
- }
- },
- "typescript": {
- "version": "3.9.7",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
- "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
- "dev": true
- },
- "validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "requires": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "which-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
- "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
- "dev": true
- },
- "window-size": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
- "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
- "dev": true
- },
- "wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "dev": true,
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- }
- },
- "y18n": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
- "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==",
- "dev": true
- },
- "yargs": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz",
- "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=",
- "dev": true,
- "requires": {
- "cliui": "^3.2.0",
- "decamelize": "^1.1.1",
- "get-caller-file": "^1.0.1",
- "lodash.assign": "^4.0.3",
- "os-locale": "^1.4.0",
- "read-pkg-up": "^1.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^1.0.1",
- "which-module": "^1.0.0",
- "window-size": "^0.2.0",
- "y18n": "^3.2.1",
- "yargs-parser": "^2.4.1"
- }
- },
- "yargs-parser": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz",
- "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=",
- "dev": true,
- "requires": {
- "camelcase": "^3.0.0",
- "lodash.assign": "^4.0.6"
- }
- }
- }
-}
diff --git a/runtime/js/runtime/package.json b/runtime/js/runtime/package.json
deleted file mode 100644
index 835d176ac..000000000
--- a/runtime/js/runtime/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "@wailsapp/runtime",
- "version": "1.1.1",
- "description": "Wails Javascript runtime library",
- "main": "main.js",
- "types": "runtime.d.ts",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/wailsapp/wails.git"
- },
- "keywords": [
- "Wails",
- "Javascript",
- "Go"
- ],
- "author": "Lea Anthony ",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/wailsapp/wails/issues"
- },
- "homepage": "https://github.com/wailsapp/wails#readme",
- "devDependencies": {
- "dts-gen": "^0.5.8"
- }
-}
diff --git a/runtime/js/runtime/runtime.d.ts b/runtime/js/runtime/runtime.d.ts
deleted file mode 100644
index 21e07da5b..000000000
--- a/runtime/js/runtime/runtime.d.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export = wailsapp__runtime;
-
-declare const wailsapp__runtime: {
- Browser: {
- OpenFile(filename: string): Promise;
- OpenURL(url: string): Promise;
- };
- Events: {
- Acknowledge(eventName: string): void;
- Emit(eventName: string, data?: any): void;
- Heartbeat(eventName: string, timeInMilliseconds: number, callback: (data?: any) => void): void;
- On(eventName: string, callback: (data?: any) => void): void;
- OnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
- Once(eventName: string, callback: (data?: any) => void): void;
- };
- Init(callback: () => void): void;
- Log: {
- Debug(message: string): void;
- Error(message: string): void;
- Fatal(message: string): void;
- Info(message: string): void;
- Warning(message: string): void;
- };
- Store: {
- New(name: string, optionalDefault?: any): any;
- };
-};
-
-
diff --git a/runtime/js/runtime/store.js b/runtime/js/runtime/store.js
deleted file mode 100644
index 3f12fe93b..000000000
--- a/runtime/js/runtime/store.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The lightweight framework for web-like apps
-(c) Lea Anthony 2019-present
-*/
-
-/* jshint esversion: 6 */
-
-
-/**
- * Create a new Store with the given name and optional default value
- *
- * @export
- * @param {string} name
- * @param {*} optionalDefault
- */
-function New(name, optionalDefault) {
- return window.wails.Store.New(name, optionalDefault);
-}
-
-module.exports = {
- New: New,
-};
diff --git a/runtime/js/webpack.config.js b/runtime/js/webpack.config.js
deleted file mode 100644
index 62cb81a20..000000000
--- a/runtime/js/webpack.config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* eslint-disable */
-module.exports = (env) => {
- return require(`./webpack.${env}.js`);
-};
\ No newline at end of file
diff --git a/runtime/js/webpack.prod.js b/runtime/js/webpack.prod.js
deleted file mode 100644
index 8821d9c56..000000000
--- a/runtime/js/webpack.prod.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* eslint-disable */
-
-const path = require('path');
-
-module.exports = {
- entry: './core/main',
- mode: 'production',
- output: {
- path: path.resolve(__dirname, '..', 'assets'),
- filename: 'wails.js'
- },
- module: {
- rules: [
- {
- test: /\.m?js$/,
- exclude: /(node_modules|bower_components)/,
- use: {
- loader: 'babel-loader',
- options: {
- plugins: ['@babel/plugin-transform-object-assign'],
- presets: [
- [
- '@babel/preset-env',
- {
- 'useBuiltIns': 'entry',
- 'corejs': {
- 'version': 3,
- 'proposals': true
- }
- }
- ]
- ]
- }
- }
- }
- ]
- }
-};
diff --git a/runtime/log.go b/runtime/log.go
deleted file mode 100644
index dd609ce51..000000000
--- a/runtime/log.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package runtime
-
-import "github.com/wailsapp/wails/lib/logger"
-
-// Log exposes the logging interface to the runtime
-type Log struct{}
-
-// NewLog creates a new Log struct
-func NewLog() *Log {
- return &Log{}
-}
-
-// New creates a new logger
-func (r *Log) New(prefix string) *logger.CustomLogger {
- return logger.NewCustomLogger(prefix)
-}
diff --git a/runtime/runtime.go b/runtime/runtime.go
deleted file mode 100644
index 7097de7a1..000000000
--- a/runtime/runtime.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package runtime
-
-import "github.com/wailsapp/wails/lib/interfaces"
-
-// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
-type Runtime struct {
- Events *Events
- Log *Log
- Dialog *Dialog
- Window *Window
- Browser *Browser
- FileSystem *FileSystem
- Store *StoreProvider
-}
-
-// NewRuntime creates a new Runtime struct
-func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
- result := &Runtime{
- Events: NewEvents(eventManager),
- Log: NewLog(),
- Dialog: NewDialog(renderer),
- Window: NewWindow(renderer),
- Browser: NewBrowser(),
- FileSystem: NewFileSystem(),
- }
- // We need a reference to itself
- result.Store = NewStoreProvider(result)
- return result
-}
diff --git a/runtime/store.go b/runtime/store.go
deleted file mode 100644
index 4468296b1..000000000
--- a/runtime/store.go
+++ /dev/null
@@ -1,298 +0,0 @@
-// Package runtime contains all the methods and data structures related to the
-// runtime library of Wails. This includes both Go and JS runtimes.
-package runtime
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "log"
- "reflect"
- "sync"
-)
-
-// Options defines the optional data that may be used
-// when creating a Store
-type Options struct {
-
- // The name of the store
- Name string
-
- // The runtime to attach the store to
- Runtime *Runtime
-
- // Indicates if notifying Go listeners should be notified of updates
- // synchronously (on the current thread) or asynchronously using
- // goroutines
- NotifySynchronously bool
-}
-
-// StoreProvider is a struct that creates Stores
-type StoreProvider struct {
- runtime *Runtime
-}
-
-// NewStoreProvider creates new stores using the provided Runtime reference.
-func NewStoreProvider(runtime *Runtime) *StoreProvider {
- return &StoreProvider{
- runtime: runtime,
- }
-}
-
-// Store is where we keep named data
-type Store struct {
- name string
- data reflect.Value
- dataType reflect.Type
- eventPrefix string
- callbacks []reflect.Value
- runtime *Runtime
- notifySynchronously bool
-
- // Lock
- mux sync.Mutex
-
- // Error handler
- errorHandler func(error)
-}
-
-// New creates a new store
-func (p *StoreProvider) New(name string, defaultValue interface{}) *Store {
-
- dataType := reflect.TypeOf(defaultValue)
-
- result := Store{
- name: name,
- runtime: p.runtime,
- data: reflect.ValueOf(defaultValue),
- dataType: dataType,
- }
-
- // Setup the sync listener
- result.setupListener()
-
- return &result
-}
-
-// OnError takes a function that will be called
-// whenever an error occurs
-func (s *Store) OnError(callback func(error)) {
- s.errorHandler = callback
-}
-
-// Processes the updates sent by the front end
-func (s *Store) processUpdatedData(data string) error {
-
- // Decode incoming data
- var rawdata json.RawMessage
- d := json.NewDecoder(bytes.NewBufferString(data))
- err := d.Decode(&rawdata)
- if err != nil {
- return err
- }
-
- // Create a new instance of our data and unmarshal
- // the received value into it
- newData := reflect.New(s.dataType).Interface()
- err = json.Unmarshal(rawdata, &newData)
- if err != nil {
- return err
- }
-
- // Lock mutex for writing
- s.mux.Lock()
-
- // Handle nulls
- if newData == nil {
- s.data = reflect.Zero(s.dataType)
- } else {
- // Store the resultant value in the data store
- s.data = reflect.ValueOf(newData).Elem()
- }
-
- // Unlock mutex
- s.mux.Unlock()
-
- return nil
-}
-
-// Setup listener for front end changes
-func (s *Store) setupListener() {
-
- // Listen for updates from the front end
- s.runtime.Events.On("wails:sync:store:updatedbyfrontend:"+s.name, func(data ...interface{}) {
-
- // Process the incoming data
- err := s.processUpdatedData(data[0].(string))
-
- if err != nil {
- if s.errorHandler != nil {
- s.errorHandler(err)
- return
- }
- }
-
- // Notify listeners
- s.notify()
- })
-}
-
-// notify the listeners of the current data state
-func (s *Store) notify() {
-
- // Execute callbacks
- for _, callback := range s.callbacks {
-
- // Build args
- args := []reflect.Value{s.data}
-
- if s.notifySynchronously {
- callback.Call(args)
- } else {
- go callback.Call(args)
- }
-
- }
-}
-
-// Set will update the data held by the store
-// and notify listeners of the change
-func (s *Store) Set(data interface{}) error {
-
- inType := reflect.TypeOf(data)
-
- if inType != s.dataType {
- return fmt.Errorf("invalid data given in Store.Set(). Expected %s, got %s", s.dataType.String(), inType.String())
- }
-
- // Save data
- s.mux.Lock()
- s.data = reflect.ValueOf(data)
- s.mux.Unlock()
-
- // Stringify data
- newdata, err := json.Marshal(data)
- if err != nil {
- if s.errorHandler != nil {
- return err
- }
- }
-
- // Emit event to front end
- s.runtime.Events.Emit("wails:sync:store:updatedbybackend:"+s.name, string(newdata))
-
- // Notify subscribers
- s.notify()
-
- return nil
-}
-
-// callbackCheck ensures the given function to Subscribe() is
-// of the correct signature. Absolutely cannot wait for
-// generics to land rather than writing this nonsense.
-func (s *Store) callbackCheck(callback interface{}) error {
-
- // Get type
- callbackType := reflect.TypeOf(callback)
-
- // Check callback is a function
- if callbackType.Kind() != reflect.Func {
- return fmt.Errorf("invalid value given to store.Subscribe(). Expected 'func(%s)'", s.dataType.String())
- }
-
- // Check input param
- if callbackType.NumIn() != 1 {
- return fmt.Errorf("invalid number of parameters given in callback function. Expected 1")
- }
-
- // Check input data type
- if callbackType.In(0) != s.dataType {
- return fmt.Errorf("invalid type for input parameter given in callback function. Expected %s, got %s", s.dataType.String(), callbackType.In(0))
- }
-
- // Check output param
- if callbackType.NumOut() != 0 {
- return fmt.Errorf("invalid number of return parameters given in callback function. Expected 0")
- }
-
- return nil
-}
-
-// Subscribe will subscribe to updates to the store by
-// providing a callback. Any updates to the store are sent
-// to the callback
-func (s *Store) Subscribe(callback interface{}) {
-
- err := s.callbackCheck(callback)
- if err != nil {
- log.Fatal(err)
- }
-
- callbackFunc := reflect.ValueOf(callback)
-
- s.callbacks = append(s.callbacks, callbackFunc)
-}
-
-// updaterCheck ensures the given function to Update() is
-// of the correct signature. Absolutely cannot wait for
-// generics to land rather than writing this nonsense.
-func (s *Store) updaterCheck(updater interface{}) error {
-
- // Get type
- updaterType := reflect.TypeOf(updater)
-
- // Check updater is a function
- if updaterType.Kind() != reflect.Func {
- return fmt.Errorf("invalid value given to store.Update(). Expected 'func(%s) %s'", s.dataType.String(), s.dataType.String())
- }
-
- // Check input param
- if updaterType.NumIn() != 1 {
- return fmt.Errorf("invalid number of parameters given in updater function. Expected 1")
- }
-
- // Check input data type
- if updaterType.In(0) != s.dataType {
- return fmt.Errorf("invalid type for input parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.In(0))
- }
-
- // Check output param
- if updaterType.NumOut() != 1 {
- return fmt.Errorf("invalid number of return parameters given in updater function. Expected 1")
- }
-
- // Check output data type
- if updaterType.Out(0) != s.dataType {
- return fmt.Errorf("invalid type for return parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.Out(0))
- }
-
- return nil
-}
-
-// Update takes a function that is passed the current state.
-// The result of that function is then set as the new state
-// of the store. This will notify listeners of the change
-func (s *Store) Update(updater interface{}) {
-
- err := s.updaterCheck(updater)
- if err != nil {
- log.Fatal(err)
- }
-
- // Build args
- args := []reflect.Value{s.data}
-
- // Make call
- results := reflect.ValueOf(updater).Call(args)
-
- // We will only have 1 result. Set the store to it
- err = s.Set(results[0].Interface())
- if err != nil && s.errorHandler != nil {
- s.errorHandler(err)
- }
-}
-
-// Get returns the value of the data that's kept in the current state / Store
-func (s *Store) Get() interface{} {
- return s.data.Interface()
-}
diff --git a/runtime/window.go b/runtime/window.go
deleted file mode 100644
index 3665cbaaf..000000000
--- a/runtime/window.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package runtime
-
-import (
- "bytes"
- "runtime"
-
- "github.com/abadojack/whatlanggo"
- "github.com/wailsapp/wails/lib/interfaces"
- "golang.org/x/text/encoding"
- "golang.org/x/text/encoding/japanese"
- "golang.org/x/text/encoding/korean"
- "golang.org/x/text/encoding/simplifiedchinese"
- "golang.org/x/text/transform"
-)
-
-func detectEncoding(text string) (encoding.Encoding, string) {
- // korean
- var enc encoding.Encoding
- info := whatlanggo.Detect(text)
- //fmt.Println("Language:", info.Lang.String(), " Script:", whatlanggo.Scripts[info.Script], " Confidence: ", info.Confidence)
- switch info.Lang.String() {
- case "Korean":
- enc = korean.EUCKR
- case "Mandarin":
- enc = simplifiedchinese.GBK
- case "Japanese":
- enc = japanese.EUCJP
- }
- return enc, info.Lang.String()
-}
-
-// ProcessEncoding attempts to convert CKJ strings to UTF-8
-func ProcessEncoding(text string) string {
- if runtime.GOOS != "windows" {
- return text
- }
-
- encoding, _ := detectEncoding(text)
- if encoding != nil {
- var bufs bytes.Buffer
- wr := transform.NewWriter(&bufs, encoding.NewEncoder())
- _, err := wr.Write([]byte(text))
- defer wr.Close()
- if err != nil {
- return ""
- }
-
- return bufs.String()
- }
- return text
-}
-
-// Window exposes an interface for manipulating the window
-type Window struct {
- renderer interfaces.Renderer
-}
-
-// NewWindow creates a new Window struct
-func NewWindow(renderer interfaces.Renderer) *Window {
- return &Window{
- renderer: renderer,
- }
-}
-
-// SetColour sets the the window colour
-func (r *Window) SetColour(colour string) error {
- return r.renderer.SetColour(colour)
-}
-
-// SetMinSize sets the minimum size of a resizable window
-func (r *Window) SetMinSize(width, height int) {
- r.renderer.SetMinSize(width, height)
-}
-
-// SetMaxSize sets the maximum size of a resizable window
-func (r *Window) SetMaxSize(width, height int) {
- r.renderer.SetMaxSize(width, height)
-}
-
-// Fullscreen makes the window fullscreen
-func (r *Window) Fullscreen() {
- r.renderer.Fullscreen()
-}
-
-// UnFullscreen attempts to restore the window to the size/position before fullscreen
-func (r *Window) UnFullscreen() {
- r.renderer.UnFullscreen()
-}
-
-// SetTitle sets the the window title
-func (r *Window) SetTitle(title string) {
- title = ProcessEncoding(title)
- r.renderer.SetTitle(title)
-}
-
-// Close shuts down the window and therefore the app
-func (r *Window) Close() {
- r.renderer.Close()
-}
diff --git a/scripts/AUTOMATION-README.md b/scripts/AUTOMATION-README.md
new file mode 100644
index 000000000..4096b1781
--- /dev/null
+++ b/scripts/AUTOMATION-README.md
@@ -0,0 +1,123 @@
+# Wails Issue Management Automation
+
+This directory contains automation workflows and scripts to help manage the Wails project with minimal time investment.
+
+## GitHub Workflow Files
+
+### 1. Auto-Label Issues (`auto-label-issues.yml`)
+- Automatically labels issues and PRs based on their content and modified files
+- Labels are defined in `issue-labeler.yml` and `file-labeler.yml`
+- Activates when issues are opened, edited, or reopened
+
+### 2. Issue Triage Automation (`issue-triage-automation.yml`)
+- Performs automated actions for issue triage
+- Requests more info for incomplete bug reports
+- Prioritizes security issues
+- Adds issues to appropriate project boards
+
+## Configuration Files
+
+### 1. Issue Content Labeler (`issue-labeler.yml`)
+- Defines patterns to match in issue title/body
+- Categorizes by version (v2/v3), component, type, and priority
+- Customize patterns as needed for your project
+
+### 2. File Path Labeler (`file-labeler.yml`)
+- Labels PRs based on which files they modify
+- Helps identify which areas of the codebase are affected
+- Customize file patterns as needed
+
+### 3. Stale Issues Config (`stale.yml`)
+- Marks issues as stale after 45 days of inactivity
+- Closes stale issues after an additional 10 days
+- Exempts issues with important labels
+
+## Helper Scripts
+
+### 1. Issue Triage Script (`scripts/issue-triage.ps1`)
+- PowerShell script to quickly triage issues
+- Lists recent issues needing attention
+- Provides easy keyboard shortcuts for common actions
+- Run during your dedicated issue triage time
+
+### 2. PR Review Helper (`scripts/pr-review-helper.ps1`)
+- PowerShell script to efficiently review PRs
+- Generates review checklists
+- Provides easy shortcuts for common review actions
+- Run during your dedicated PR review time
+
+## How to Use This System
+
+### Daily Workflow (2 hours max)
+
+**Monday (120 min):**
+1. Run `scripts/issue-triage.ps1` (30 min)
+2. Run `scripts/pr-review-helper.ps1` (30 min)
+3. Check Discord for critical discussions (30 min)
+4. Plan your week (30 min)
+
+**Tuesday-Wednesday (120 min/day):**
+1. Quick check for urgent issues (10 min)
+2. v3 development (110 min)
+
+**Thursday (120 min):**
+1. v2 maintenance (90 min)
+2. Documentation updates (30 min)
+
+**Friday (120 min):**
+1. Run `scripts/pr-review-helper.ps1` (60 min)
+2. Discord updates/newsletter (30 min)
+3. Weekly reflection (30 min)
+
+## Installation
+
+1. The GitHub workflow files should be placed in `.github/workflows/`
+2. Configuration files should be placed in `.github/`
+3. Helper scripts should be placed in `scripts/`
+4. Make sure you have GitHub CLI (`gh`) installed and authenticated
+
+## Customization
+
+Feel free to modify the configuration files and scripts to better suit your project's needs:
+
+1. **Adding New Label Categories**:
+ - Add new patterns to `issue-labeler.yml` for additional components or types
+ - Update `file-labeler.yml` if you add new directories or file types
+
+2. **Adjusting Automation Thresholds**:
+ - Modify `stale.yml` to change how long issues remain active
+ - Update `issue-triage-automation.yml` to change conditions for automated actions
+
+3. **Customizing Scripts**:
+ - Update the scripts with your specific GitHub username
+ - Add additional actions based on your workflow preferences
+ - Adjust time allocations based on which tasks need more attention
+
+## Benefits
+
+This automated issue management system will:
+
+1. **Save Time**: Reduce manual triage of most common issues
+2. **Improve Consistency**: Apply the same categorization rules every time
+3. **Increase Visibility**: Clear categorization helps community members find issues
+4. **Focus Development**: Clearer separation of v2 and v3 work
+5. **Reduce Backlog**: Better management of stale issues
+6. **Streamline Reviews**: Faster PR processing with guided workflows
+
+## Requirements
+
+- GitHub CLI (`gh`) installed and authenticated
+- PowerShell 5.1+ for Windows scripts
+- GitHub Actions enabled on your repository
+- Appropriate permissions to modify workflows
+
+## Maintenance
+
+This system requires minimal maintenance:
+
+- Periodically review and update label patterns as your project evolves
+- Adjust time allocations based on where you need to focus
+- Update scripts if GitHub CLI commands change
+- Customize the workflow as you find pain points in your process
+
+Remember that the goal is to maximize your limited time (2 hours per day) by automating repetitive tasks and streamlining essential ones.
diff --git a/scripts/build.go b/scripts/build.go
deleted file mode 100644
index 046bc97c3..000000000
--- a/scripts/build.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "os/exec"
- "path/filepath"
-)
-
-func runCommand(command string, args ...string) {
- cmd := exec.Command(command, args...)
- output, err := cmd.CombinedOutput()
- fmt.Println(string(output))
- if err != nil {
- log.Println(string(output))
- log.Fatal(err)
- }
- fmt.Println(string(output))
-}
-
-// A build step that requires additional params, or platform specific steps for example
-func main() {
-
- dir, _ := os.Getwd()
-
- // Build Runtime
- fmt.Println("**** Building Runtime ****")
- runtimeDir, _ := filepath.Abs(filepath.Join(dir, "..", "runtime", "js"))
- err := os.Chdir(runtimeDir)
- if err != nil {
- log.Fatal(err)
- }
- runCommand("npm", "install")
- runCommand("npm", "run", "build")
-
- // Install Wails
- fmt.Println("**** Installing Wails locally ****")
- execDir, _ := filepath.Abs(filepath.Join(dir, "..", "cmd", "wails"))
- err = os.Chdir(execDir)
- if err != nil {
- log.Fatal(err)
- }
- runCommand("go", "install")
-
- baseDir, _ := filepath.Abs(filepath.Join(dir, ".."))
- err = os.Chdir(baseDir)
- if err != nil {
- log.Fatal(err)
- }
- runCommand("go", "mod", "tidy")
-}
diff --git a/scripts/build.sh b/scripts/build.sh
deleted file mode 100755
index e99ad26ed..000000000
--- a/scripts/build.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-
-echo "**** Checking if Wails passes unit tests ****"
-if ! go test ./lib/... ./runtime/... ./cmd/...
-then
- echo ""
- echo "ERROR: Unit tests failed!"
- exit 1;
-fi
-
-# Build runtime
-echo "**** Building Runtime ****"
-cd runtime/js
-npm install
-npm run build
-cd ../..
-
-cd cmd/wails
-echo "**** Checking if Wails compiles ****"
-if ! go build .
-then
- echo ""
- echo "ERROR: Build failed!"
- exit 1;
-fi
-
-echo "**** Installing Wails locally ****"
-if ! go install
-then
- echo ""
- echo "ERROR: Install failed!"
- exit 1;
-fi
-cd ../..
-
-echo "**** Tidying the mods! ****"
-go mod tidy
-
-echo "**** WE ARE DONE! ****"
diff --git a/scripts/issue-triage.ps1 b/scripts/issue-triage.ps1
new file mode 100644
index 000000000..6f6edd3ad
--- /dev/null
+++ b/scripts/issue-triage.ps1
@@ -0,0 +1,108 @@
+# issue-triage.ps1 - Script to help with quick issue triage
+# Run this at the start of your GitHub time to quickly process issues
+
+# Set your GitHub username
+$GITHUB_USERNAME = "your-username"
+
+# Get the latest 10 open issues that aren't assigned and aren't labeled as "awaiting feedback"
+Write-Host "Fetching recent unprocessed issues..."
+gh issue list --repo wailsapp/wails --limit 10 --json number,title,labels,assignees | Out-File -Encoding utf8 -FilePath "issues_temp.json"
+$issues = Get-Content -Raw -Path "issues_temp.json" | ConvertFrom-Json
+$newIssues = $issues | Where-Object {
+ $_.assignees.Count -eq 0 -and
+ ($_.labels.Count -eq 0 -or -not ($_.labels | Where-Object { $_.name -eq "awaiting feedback" }))
+}
+
+# Process each issue
+Write-Host "`n===== Issues Needing Triage =====`n"
+foreach ($issue in $newIssues) {
+ $number = $issue.number
+ $title = $issue.title
+ $labelNames = $issue.labels | ForEach-Object { $_.name }
+ $labelsStr = if ($labelNames) { $labelNames -join ", " } else { "none" }
+
+ Write-Host "Issue #$number`: $title"
+ Write-Host "Labels: $labelsStr`n"
+
+ $continue = $true
+ while ($continue) {
+ Write-Host "Options:"
+ Write-Host " [v] View issue in browser"
+ Write-Host " [2] Add v2-only label"
+ Write-Host " [3] Add v3-alpha label"
+ Write-Host " [b] Add bug label"
+ Write-Host " [e] Add enhancement label"
+ Write-Host " [d] Add documentation label"
+ Write-Host " [w] Add webview2 label"
+ Write-Host " [f] Request more info (awaiting feedback)"
+ Write-Host " [c] Close issue (duplicate/invalid)"
+ Write-Host " [a] Assign to yourself"
+ Write-Host " [s] Skip to next issue"
+ Write-Host " [q] Quit script"
+ $action = Read-Host "Enter action"
+
+ switch ($action) {
+ "v" {
+ gh issue view $number --repo wailsapp/wails --web
+ }
+ "2" {
+ Write-Host "Adding v2-only label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "v2-only"
+ }
+ "3" {
+ Write-Host "Adding v3-alpha label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "v3-alpha"
+ }
+ "b" {
+ Write-Host "Adding bug label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Bug"
+ }
+ "e" {
+ Write-Host "Adding enhancement label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Enhancement"
+ }
+ "d" {
+ Write-Host "Adding documentation label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Documentation"
+ }
+ "w" {
+ Write-Host "Adding webview2 label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "webview2"
+ }
+ "f" {
+ Write-Host "Requesting more info..."
+ gh issue comment $number --repo wailsapp/wails --body "Thank you for reporting this issue. Could you please provide additional information to help us investigate?`n`n- [Specific details needed]`n`nThis will help us address your issue more effectively."
+ gh issue edit $number --repo wailsapp/wails --add-label "awaiting feedback"
+ }
+ "c" {
+ $reason = Read-Host "Reason for closing (duplicate/invalid/etc)"
+ gh issue comment $number --repo wailsapp/wails --body "Closing this issue: $reason"
+ gh issue close $number --repo wailsapp/wails
+ }
+ "a" {
+ Write-Host "Assigning to yourself..."
+ gh issue edit $number --repo wailsapp/wails --add-assignee "$GITHUB_USERNAME"
+ }
+ "s" {
+ Write-Host "Skipping to next issue..."
+ $continue = $false
+ }
+ "q" {
+ Write-Host "Exiting script."
+ exit
+ }
+ default {
+ Write-Host "Invalid option. Please try again."
+ }
+ }
+
+ Write-Host ""
+ }
+
+ Write-Host "--------------------------------`n"
+}
+
+Write-Host "No more issues to triage!"
+
+# Clean up temp file
+Remove-Item -Path "issues_temp.json"
diff --git a/scripts/issue-triage.sh b/scripts/issue-triage.sh
new file mode 100644
index 000000000..5809b43a1
--- /dev/null
+++ b/scripts/issue-triage.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+# issue-triage.sh - Script to help with quick issue triage
+# Run this at the start of your GitHub time to quickly process issues
+
+# Set your GitHub username
+GITHUB_USERNAME="your-username"
+
+# Get the latest 10 open issues that aren't assigned and aren't labeled as "awaiting feedback"
+echo "Fetching recent unprocessed issues..."
+gh issue list --repo wailsapp/wails --limit 10 --json number,title,labels,assignees --jq '.[] | select(.assignees | length == 0) | select(any(.labels[]; .name != "awaiting feedback"))' > new_issues.json
+
+# Process each issue
+echo -e "\n===== Issues Needing Triage =====\n"
+cat new_issues.json | jq -c '.[]' | while read -r issue; do
+ number=$(echo $issue | jq -r '.number')
+ title=$(echo $issue | jq -r '.title')
+ labels=$(echo $issue | jq -r '.labels[] | .name' 2>/dev/null | tr '\n' ', ' | sed 's/,$//')
+
+ if [ -z "$labels" ]; then
+ labels="none"
+ fi
+
+ echo -e "Issue #$number: $title"
+ echo -e "Labels: $labels\n"
+
+ while true; do
+ echo "Options:"
+ echo " [v] View issue in browser"
+ echo " [2] Add v2-only label"
+ echo " [3] Add v3-alpha label"
+ echo " [b] Add bug label"
+ echo " [e] Add enhancement label"
+ echo " [d] Add documentation label"
+ echo " [w] Add webview2 label"
+ echo " [f] Request more info (awaiting feedback)"
+ echo " [c] Close issue (duplicate/invalid)"
+ echo " [a] Assign to yourself"
+ echo " [s] Skip to next issue"
+ echo " [q] Quit script"
+ read -p "Enter action: " action
+
+ case $action in
+ v)
+ gh issue view $number --repo wailsapp/wails --web
+ ;;
+ 2)
+ echo "Adding v2-only label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "v2-only"
+ ;;
+ 3)
+ echo "Adding v3-alpha label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "v3-alpha"
+ ;;
+ b)
+ echo "Adding bug label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Bug"
+ ;;
+ e)
+ echo "Adding enhancement label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Enhancement"
+ ;;
+ d)
+ echo "Adding documentation label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "Documentation"
+ ;;
+ w)
+ echo "Adding webview2 label..."
+ gh issue edit $number --repo wailsapp/wails --add-label "webview2"
+ ;;
+ f)
+ echo "Requesting more info..."
+ gh issue comment $number --repo wailsapp/wails --body "Thank you for reporting this issue. Could you please provide additional information to help us investigate?\n\n- [Specific details needed]\n\nThis will help us address your issue more effectively."
+ gh issue edit $number --repo wailsapp/wails --add-label "awaiting feedback"
+ ;;
+ c)
+ read -p "Reason for closing (duplicate/invalid/etc): " reason
+ gh issue comment $number --repo wailsapp/wails --body "Closing this issue: $reason"
+ gh issue close $number --repo wailsapp/wails
+ ;;
+ a)
+ echo "Assigning to yourself..."
+ gh issue edit $number --repo wailsapp/wails --add-assignee "$GITHUB_USERNAME"
+ ;;
+ s)
+ echo "Skipping to next issue..."
+ break
+ ;;
+ q)
+ echo "Exiting script."
+ exit 0
+ ;;
+ *)
+ echo "Invalid option. Please try again."
+ ;;
+ esac
+
+ echo ""
+ done
+
+ echo -e "--------------------------------\n"
+done
+
+echo "No more issues to triage!"
diff --git a/scripts/pr-review-helper.ps1 b/scripts/pr-review-helper.ps1
new file mode 100644
index 000000000..75fae4c3b
--- /dev/null
+++ b/scripts/pr-review-helper.ps1
@@ -0,0 +1,152 @@
+# pr-review-helper.ps1 - Script to help with efficient PR reviews
+# Run this during your PR review time
+
+# Set your GitHub username
+$GITHUB_USERNAME = "your-username"
+
+# Get open PRs that are ready for review
+Write-Host "Fetching PRs ready for review..."
+gh pr list --repo wailsapp/wails --json number,title,author,labels,reviewDecision,additions,deletions,baseRefName,headRefName --limit 10 | Out-File -Encoding utf8 -FilePath "prs_temp.json"
+$prs = Get-Content -Raw -Path "prs_temp.json" | ConvertFrom-Json
+
+# Process each PR
+Write-Host "`n===== PRs Needing Review =====`n"
+foreach ($pr in $prs) {
+ $number = $pr.number
+ $title = $pr.title
+ $author = $pr.author.login
+ $labels = if ($pr.labels) { $pr.labels | ForEach-Object { $_.name } | Join-String -Separator ", " } else { "none" }
+ $reviewState = if ($pr.reviewDecision) { $pr.reviewDecision } else { "PENDING" }
+ $baseRef = $pr.baseRefName
+ $headRef = $pr.headRefName
+ $changes = $pr.additions + $pr.deletions
+
+ Write-Host "PR #$number`: $title"
+ Write-Host "Author: $author"
+ Write-Host "Labels: $labels"
+ Write-Host "Branch: $headRef -> $baseRef"
+ Write-Host "Changes: +$($pr.additions)/-$($pr.deletions) lines"
+ Write-Host "Review state: $reviewState`n"
+
+ # Determine complexity based on size
+ $complexity = if ($changes -lt 50) {
+ "Quick review"
+ } elseif ($changes -lt 300) {
+ "Moderate review"
+ } else {
+ "Extensive review"
+ }
+
+ Write-Host "Complexity: $complexity"
+
+ $continue = $true
+ while ($continue) {
+ Write-Host "`nOptions:"
+ Write-Host " [v] View PR in browser"
+ Write-Host " [d] View diff in browser"
+ Write-Host " [c] Generate review checklist"
+ Write-Host " [a] Approve PR"
+ Write-Host " [r] Request changes"
+ Write-Host " [m] Add comment"
+ Write-Host " [l] Add labels"
+ Write-Host " [s] Skip to next PR"
+ Write-Host " [q] Quit script"
+ $action = Read-Host "Enter action"
+
+ switch ($action) {
+ "v" {
+ gh pr view $number --repo wailsapp/wails --web
+ }
+ "d" {
+ gh pr diff $number --repo wailsapp/wails --web
+ }
+ "c" {
+ # Generate review checklist
+ $checklist = @"
+## PR Review: $title
+
+### Basic Checks:
+- [ ] PR title is descriptive
+- [ ] PR description explains the changes
+- [ ] Related issues are linked
+
+### Technical Checks:
+- [ ] Code follows project style
+- [ ] No unnecessary commented code
+- [ ] Error handling is appropriate
+- [ ] Documentation updated (if needed)
+- [ ] Tests included (if needed)
+
+### Impact Assessment:
+- [ ] Changes are backward compatible (if applicable)
+- [ ] No breaking changes to public APIs
+- [ ] Performance impact considered
+
+### Version Specific:
+"@
+
+ if ($baseRef -eq "master") {
+ $checklist += @"
+
+- [ ] Appropriate for v2 maintenance
+- [ ] No features that should be v3-only
+"@
+ } elseif ($baseRef -eq "v3-alpha") {
+ $checklist += @"
+
+- [ ] Appropriate for v3 development
+- [ ] Aligns with v3 roadmap
+"@
+ }
+
+ # Write to clipboard
+ $checklist | Set-Clipboard
+ Write-Host "`nReview checklist copied to clipboard!`n"
+ }
+ "a" {
+ $comment = Read-Host "Approval comment (blank for none)"
+ if ($comment) {
+ gh pr review $number --repo wailsapp/wails --approve --body $comment
+ } else {
+ gh pr review $number --repo wailsapp/wails --approve
+ }
+ }
+ "r" {
+ $comment = Read-Host "Feedback for changes requested"
+ gh pr review $number --repo wailsapp/wails --request-changes --body $comment
+ }
+ "m" {
+ $comment = Read-Host "Comment text"
+ gh pr comment $number --repo wailsapp/wails --body $comment
+ }
+ "l" {
+ $labels = Read-Host "Labels to add (comma-separated)"
+ $labelArray = $labels -split ","
+ foreach ($label in $labelArray) {
+ $labelTrimmed = $label.Trim()
+ if ($labelTrimmed) {
+ gh pr edit $number --repo wailsapp/wails --add-label $labelTrimmed
+ }
+ }
+ }
+ "s" {
+ Write-Host "Skipping to next PR..."
+ $continue = $false
+ }
+ "q" {
+ Write-Host "Exiting script."
+ exit
+ }
+ default {
+ Write-Host "Invalid option. Please try again."
+ }
+ }
+ }
+
+ Write-Host "--------------------------------`n"
+}
+
+Write-Host "No more PRs to review!"
+
+# Clean up temp file
+Remove-Item -Path "prs_temp.json"
diff --git a/scripts/sponsors/generate-sponsor-image.sh b/scripts/sponsors/generate-sponsor-image.sh
index be90c8299..b034a0176 100755
--- a/scripts/sponsors/generate-sponsor-image.sh
+++ b/scripts/sponsors/generate-sponsor-image.sh
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
-npm install sponsorkit@0.6.1
+npm install sponsorkit@16.4.2
npx sponsorkit -o ../../website/static/img/
diff --git a/scripts/sponsors/package-lock.json b/scripts/sponsors/package-lock.json
index 3a10700de..2bb15b685 100644
--- a/scripts/sponsors/package-lock.json
+++ b/scripts/sponsors/package-lock.json
@@ -9,239 +9,478 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
- "sponsorkit": "^0.6.1"
+ "sponsorkit": "^16.5.0"
+ },
+ "engines": {
+ "node": ">=22.0.0"
}
},
- "node_modules/@antfu/utils": {
- "version": "0.5.2",
- "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.5.2.tgz",
- "integrity": "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA=="
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "node_modules/@emnapi/runtime": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz",
+ "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==",
+ "license": "MIT",
+ "optional": true,
"dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
+ "tslib": "^2.4.0"
}
},
- "node_modules/ansi-escape-sequences": {
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz",
+ "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz",
+ "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz",
+ "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz",
+ "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz",
+ "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz",
+ "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz",
+ "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz",
+ "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz",
+ "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz",
+ "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz",
+ "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz",
+ "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz",
+ "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz",
+ "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz",
+ "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz",
+ "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz",
+ "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz",
+ "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.0"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz",
+ "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.4.4"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz",
+ "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz",
+ "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz",
+ "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@quansync/fs": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.3.tgz",
+ "integrity": "sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg==",
+ "license": "MIT",
+ "dependencies": {
+ "quansync": "^0.2.10"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ },
+ "node_modules/ansis": {
"version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz",
- "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==",
- "dependencies": {
- "array-back": "^3.0.1"
- },
+ "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz",
+ "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==",
+ "license": "ISC",
"engines": {
- "node": ">=8.0.0"
+ "node": ">=14"
}
},
- "node_modules/ansi-escape-sequences/node_modules/array-back": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/array-back/-/array-back-3.1.0.tgz",
- "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-regex": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-3.0.1.tgz",
- "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/array-back": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/array-back/-/array-back-2.0.0.tgz",
- "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
- "dependencies": {
- "typical": "^2.6.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/asn1": {
- "version": "0.2.6",
- "resolved": "https://registry.npmmirror.com/asn1/-/asn1-0.2.6.tgz",
- "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
- "dependencies": {
- "safer-buffer": "~2.1.0"
- }
- },
- "node_modules/assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npmmirror.com/aws-sign2/-/aws-sign2-0.7.0.tgz",
- "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws4": {
- "version": "1.11.0",
- "resolved": "https://registry.npmmirror.com/aws4/-/aws4-1.11.0.tgz",
- "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
- },
- "node_modules/bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
- "dependencies": {
- "tweetnacl": "^0.14.3"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
- "engines": {
- "node": ">=10.16.0"
- }
- },
- "node_modules/camelcase": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-4.1.0.tgz",
- "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/caseless": {
- "version": "0.12.0",
- "resolved": "https://registry.npmmirror.com/caseless/-/caseless-0.12.0.tgz",
- "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
- },
- "node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
- },
- "node_modules/cliss": {
- "version": "0.0.2",
- "resolved": "https://registry.npmmirror.com/cliss/-/cliss-0.0.2.tgz",
- "integrity": "sha512-6rj9pgdukjT994Md13JCUAgTk91abAKrygL9sAvmHY4F6AKMOV8ccGaxhUUfcBuyg3sundWnn3JE0Mc9W6ZYqw==",
- "dependencies": {
- "command-line-usage": "^4.0.1",
- "deepmerge": "^2.0.0",
- "get-stdin": "^5.0.1",
- "inspect-parameters-declaration": "0.0.9",
- "object-to-arguments": "0.0.8",
- "pipe-functions": "^1.3.0",
- "strip-ansi": "^4.0.0",
- "yargs-parser": "^7.0.0"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/color": {
"version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/color/-/color-4.2.3.tgz",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
@@ -252,8 +491,9 @@
},
"node_modules/color-convert": {
"version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -263,1111 +503,115 @@
},
"node_modules/color-name": {
"version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/color-string": {
"version": "1.9.1",
- "resolved": "https://registry.npmmirror.com/color-string/-/color-string-1.9.1.tgz",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "license": "MIT",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/command-line-usage": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/command-line-usage/-/command-line-usage-4.1.0.tgz",
- "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==",
- "dependencies": {
- "ansi-escape-sequences": "^4.0.0",
- "array-back": "^2.0.0",
- "table-layout": "^0.4.2",
- "typical": "^2.6.1"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
"node_modules/consola": {
- "version": "2.15.3",
- "resolved": "https://registry.npmmirror.com/consola/-/consola-2.15.3.tgz",
- "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw=="
- },
- "node_modules/core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
- },
- "node_modules/css-select": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.1.0.tgz",
- "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
- }
- },
- "node_modules/css-what": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz",
- "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
+ "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
+ "license": "MIT",
"engines": {
- "node": ">= 6"
- }
- },
- "node_modules/dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmmirror.com/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
- "dependencies": {
- "assert-plus": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/deepmerge": {
- "version": "2.2.1",
- "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-2.2.1.tgz",
- "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
- "engines": {
- "node": ">=0.10.0"
+ "node": "^14.18.0 || >=16.10.0"
}
},
"node_modules/defu": {
- "version": "6.1.1",
- "resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.1.tgz",
- "integrity": "sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA=="
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "engines": {
- "node": ">=0.4.0"
- }
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
},
"node_modules/destr": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/destr/-/destr-1.2.1.tgz",
- "integrity": "sha512-ud8w0qMLlci6iFG7CNgeRr8OcbUWMsbfjtWft1eJ5Luqrz/M8Ebqk/KCzne8rKUlIQWWfLv0wD6QHrqOf4GshA=="
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz",
+ "integrity": "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==",
+ "license": "MIT"
},
"node_modules/detect-libc": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.1.tgz",
- "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+ "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+ "license": "Apache-2.0",
"engines": {
"node": ">=8"
}
},
- "node_modules/dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
- }
- },
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
- },
- "node_modules/domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "dependencies": {
- "domelementtype": "^2.3.0"
- },
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/domutils": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.0.1.tgz",
- "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
- "dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.1"
- }
- },
"node_modules/dotenv": {
- "version": "16.0.3",
- "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.0.3.tgz",
- "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=12"
- }
- },
- "node_modules/ecc-jsbn": {
- "version": "0.1.2",
- "resolved": "https://registry.npmmirror.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
- "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
- "dependencies": {
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.1.0"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
- },
- "node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/entities": {
- "version": "4.4.0",
- "resolved": "https://registry.npmmirror.com/entities/-/entities-4.4.0.tgz",
- "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
- "engines": {
- "node": ">=0.12"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
- },
- "node_modules/extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
- "engines": [
- "node >=0.6.0"
- ]
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
- },
- "node_modules/find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
- "dependencies": {
- "locate-path": "^2.0.0"
},
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/for-each-property": {
- "version": "0.0.4",
- "resolved": "https://registry.npmmirror.com/for-each-property/-/for-each-property-0.0.4.tgz",
- "integrity": "sha512-xYs28PM0CKXETFzuGC6ZooH0voZlsSDZwidJcy92flQJi3PK7i3gZx23xHXCPOaD4zmet3bDo+wS7E7SujrlCw==",
- "dependencies": {
- "get-prototype-chain": "^1.0.1"
- }
- },
- "node_modules/for-each-property-deep": {
- "version": "0.0.3",
- "resolved": "https://registry.npmmirror.com/for-each-property-deep/-/for-each-property-deep-0.0.3.tgz",
- "integrity": "sha512-qzP8QkODWVVRPpWiBZacSbBl67cTTWoBfxMG0wE46AsS1yl7qv05sGN+dHvD4s4tnvl/goe6Sp4qBI+rlVBgNg==",
- "dependencies": {
- "for-each-property": "0.0.4"
- }
- },
- "node_modules/forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmmirror.com/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmmirror.com/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
- },
- "node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-prototype-chain": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz",
- "integrity": "sha512-2m7WZ0jveIg/dAbCbpUxEToaJ8Dmti5EkgDP8YM3UpHUT6SAORjE2odP8XQGNVGXMHi8q8cCCoy3HTByTaTVTw==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/get-stdin": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-5.0.1.tgz",
- "integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.npmmirror.com/getpass/-/getpass-0.1.7.tgz",
- "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
- "dependencies": {
- "assert-plus": "^1.0.0"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
- },
- "node_modules/har-schema": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/har-schema/-/har-schema-2.0.0.tgz",
- "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/har-validator": {
- "version": "5.1.5",
- "resolved": "https://registry.npmmirror.com/har-validator/-/har-validator-5.1.5.tgz",
- "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
- "deprecated": "this library is no longer supported",
- "dependencies": {
- "ajv": "^6.12.3",
- "har-schema": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "bin": {
- "he": "bin/he"
- }
- },
- "node_modules/http-signature": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/http-signature/-/http-signature-1.2.0.tgz",
- "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "jsprim": "^1.2.2",
- "sshpk": "^1.7.0"
- },
- "engines": {
- "node": ">=0.8",
- "npm": ">=1.3.7"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
- },
- "node_modules/image-data-uri": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/image-data-uri/-/image-data-uri-2.0.1.tgz",
- "integrity": "sha512-BZh721F2Q5TwBdwpiqrBrHEdj8daj8KuMZK/DOCyqQlz1CqFhhuZWbK5ZCUnAvFJr8LaKHTaWl9ja3/a3DC2Ew==",
- "dependencies": {
- "fs-extra": "^0.26.7",
- "magicli": "0.0.8",
- "mime-types": "^2.1.18",
- "request": "^2.88.0"
- },
- "bin": {
- "image-data-uri": "bin/magicli.js"
- }
- },
- "node_modules/image-data-uri/node_modules/fs-extra": {
- "version": "0.26.7",
- "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-0.26.7.tgz",
- "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==",
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^2.1.0",
- "klaw": "^1.0.0",
- "path-is-absolute": "^1.0.0",
- "rimraf": "^2.2.8"
- }
- },
- "node_modules/image-data-uri/node_modules/jsonfile": {
- "version": "2.4.0",
- "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-2.4.0.tgz",
- "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
- },
- "node_modules/inspect-function": {
- "version": "0.3.4",
- "resolved": "https://registry.npmmirror.com/inspect-function/-/inspect-function-0.3.4.tgz",
- "integrity": "sha512-s0RsbJqK/sNZ+U1mykGoTickog3ea1A9Qk4mXniogOBu4PgkkZ56elScO7QC/r8D94lhGmJ2NyDI1ipOA/uq/g==",
- "dependencies": {
- "inspect-parameters-declaration": "0.0.8",
- "magicli": "0.0.8",
- "split-skip": "0.0.1",
- "stringify-parameters": "0.0.4",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "inspect-function": "bin/magicli.js"
- }
- },
- "node_modules/inspect-function/node_modules/inspect-function": {
- "version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/inspect-function/-/inspect-function-0.2.2.tgz",
- "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
- "dependencies": {
- "split-skip": "0.0.1",
- "unpack-string": "0.0.2"
- }
- },
- "node_modules/inspect-function/node_modules/inspect-parameters-declaration": {
- "version": "0.0.8",
- "resolved": "https://registry.npmmirror.com/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.8.tgz",
- "integrity": "sha512-W4QzN1LgFmasKOM+NoLlDd2OAZM3enNZlVUOXoGQKmYBDFgxoPDOyebF55ALaf8avyM9TavNwibXxg347RrzCg==",
- "dependencies": {
- "magicli": "0.0.5",
- "split-skip": "0.0.2",
- "stringify-parameters": "0.0.4",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "inspect-parameters-declaration": "bin/cli.js"
- }
- },
- "node_modules/inspect-function/node_modules/inspect-parameters-declaration/node_modules/magicli": {
- "version": "0.0.5",
- "resolved": "https://registry.npmmirror.com/magicli/-/magicli-0.0.5.tgz",
- "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
- "dependencies": {
- "commander": "^2.9.0",
- "get-stdin": "^5.0.1",
- "inspect-function": "^0.2.1",
- "pipe-functions": "^1.2.0"
- }
- },
- "node_modules/inspect-function/node_modules/inspect-parameters-declaration/node_modules/split-skip": {
- "version": "0.0.2",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.2.tgz",
- "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
- },
- "node_modules/inspect-function/node_modules/split-skip": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.1.tgz",
- "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
- },
- "node_modules/inspect-parameters-declaration": {
- "version": "0.0.9",
- "resolved": "https://registry.npmmirror.com/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.9.tgz",
- "integrity": "sha512-c3jrKKA1rwwrsjdGMAo2hFWV0vNe3/RKHxpE/OBt41LP3ynOVI1qmgxpZYK5SQu3jtWCyaho8L7AZzCjJ4mEUw==",
- "dependencies": {
- "magicli": "0.0.5",
- "split-skip": "0.0.2",
- "stringify-parameters": "0.0.4",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "inspect-parameters-declaration": "bin/cli.js"
- }
- },
- "node_modules/inspect-parameters-declaration/node_modules/inspect-function": {
- "version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/inspect-function/-/inspect-function-0.2.2.tgz",
- "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
- "dependencies": {
- "split-skip": "0.0.1",
- "unpack-string": "0.0.2"
- }
- },
- "node_modules/inspect-parameters-declaration/node_modules/inspect-function/node_modules/split-skip": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.1.tgz",
- "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
- },
- "node_modules/inspect-parameters-declaration/node_modules/magicli": {
- "version": "0.0.5",
- "resolved": "https://registry.npmmirror.com/magicli/-/magicli-0.0.5.tgz",
- "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
- "dependencies": {
- "commander": "^2.9.0",
- "get-stdin": "^5.0.1",
- "inspect-function": "^0.2.1",
- "pipe-functions": "^1.2.0"
- }
- },
- "node_modules/inspect-property": {
- "version": "0.0.6",
- "resolved": "https://registry.npmmirror.com/inspect-property/-/inspect-property-0.0.6.tgz",
- "integrity": "sha512-LgjHkRl9W6bj2n+kWrAOgvCYPTYt+LanE4rtd/vKNq6yEb+SvVV7UTLzoSPpDX6/U1cAz7VfqPr+lPAIz7wHaQ==",
- "dependencies": {
- "for-each-property": "0.0.4",
- "for-each-property-deep": "0.0.3",
- "inspect-function": "^0.3.1"
+ "funding": {
+ "url": "https://dotenvx.com"
}
},
"node_modules/is-arrayish": {
"version": "0.3.2",
- "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
- },
- "node_modules/isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.npmmirror.com/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "license": "MIT"
},
"node_modules/jiti": {
- "version": "1.16.0",
- "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.16.0.tgz",
- "integrity": "sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+ "license": "MIT",
"bin": {
- "jiti": "bin/jiti.js"
+ "jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-0.1.1.tgz",
- "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
- },
- "node_modules/json-schema": {
- "version": "0.4.0",
- "resolved": "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz",
- "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
- },
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
- },
- "node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/jsprim": {
- "version": "1.4.2",
- "resolved": "https://registry.npmmirror.com/jsprim/-/jsprim-1.4.2.tgz",
- "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
- "dependencies": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.4.0",
- "verror": "1.10.0"
- },
- "engines": {
- "node": ">=0.6.0"
- }
- },
- "node_modules/klaw": {
- "version": "1.3.1",
- "resolved": "https://registry.npmmirror.com/klaw/-/klaw-1.3.1.tgz",
- "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
- "optionalDependencies": {
- "graceful-fs": "^4.1.9"
- }
- },
- "node_modules/locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
- "dependencies": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/lodash.padend": {
- "version": "4.6.1",
- "resolved": "https://registry.npmmirror.com/lodash.padend/-/lodash.padend-4.6.1.tgz",
- "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw=="
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/magicli": {
- "version": "0.0.8",
- "resolved": "https://registry.npmmirror.com/magicli/-/magicli-0.0.8.tgz",
- "integrity": "sha512-x/eBenweAHF+DsYy172sK4doRxZl0yrJnfxhLJiN7H6hPM3Ya0PfI6uBZshZ3ScFFSQD7HXgBqMdbnXKEZsO1g==",
- "dependencies": {
- "cliss": "0.0.2",
- "find-up": "^2.1.0",
- "for-each-property": "0.0.4",
- "inspect-property": "0.0.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.7",
- "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.7.tgz",
- "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
- },
- "node_modules/napi-build-utils": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
- "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
- },
- "node_modules/node-abi": {
- "version": "3.30.0",
- "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.30.0.tgz",
- "integrity": "sha512-qWO5l3SCqbwQavymOmtTVuCWZE23++S+rxyoHjXqUmPyzRcaoI4lA2gO55/drddGnedAyjA7sk76SfQ5lfUMnw==",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-5.0.0.tgz",
- "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA=="
- },
"node_modules/node-fetch-native": {
- "version": "0.1.8",
- "resolved": "https://registry.npmmirror.com/node-fetch-native/-/node-fetch-native-0.1.8.tgz",
- "integrity": "sha512-ZNaury9r0NxaT2oL65GvdGDy+5PlSaHTovT6JV5tOW07k1TQmgC0olZETa4C9KZg0+6zBr99ctTYa3Utqj9P/Q=="
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
+ "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==",
+ "license": "MIT"
},
- "node_modules/node-html-parser": {
- "version": "6.1.4",
- "resolved": "https://registry.npmmirror.com/node-html-parser/-/node-html-parser-6.1.4.tgz",
- "integrity": "sha512-3muP9Uy/Pz7bQa9TNYVQzWJhNZMqyCx7xJle8kz2/y1UgzAUyXXShc1IcPaJy6u07CE3K5rQcRwlvHzmlySRjg==",
+ "node_modules/ofetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz",
+ "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==",
+ "license": "MIT",
"dependencies": {
- "css-select": "^5.1.0",
- "he": "1.2.0"
+ "destr": "^2.0.3",
+ "node-fetch-native": "^1.6.4",
+ "ufo": "^1.5.4"
}
},
- "node_modules/nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "dependencies": {
- "boolbase": "^1.0.0"
- }
- },
- "node_modules/oauth-sign": {
- "version": "0.9.0",
- "resolved": "https://registry.npmmirror.com/oauth-sign/-/oauth-sign-0.9.0.tgz",
- "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/object-to-arguments": {
- "version": "0.0.8",
- "resolved": "https://registry.npmmirror.com/object-to-arguments/-/object-to-arguments-0.0.8.tgz",
- "integrity": "sha512-BfWfuAwuhdH1bhMG5EG90WE/eckkBhBvnke8eSEkCDXoLE9Jk5JwYGTbCx1ehGwV48HvBkn62VukPBdlMUOY9w==",
- "dependencies": {
- "inspect-parameters-declaration": "0.0.10",
- "magicli": "0.0.5",
- "split-skip": "0.0.2",
- "stringify-parameters": "0.0.4",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "object-to-arguments": "bin/cli.js"
- }
- },
- "node_modules/object-to-arguments/node_modules/inspect-function": {
- "version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/inspect-function/-/inspect-function-0.2.2.tgz",
- "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
- "dependencies": {
- "split-skip": "0.0.1",
- "unpack-string": "0.0.2"
- }
- },
- "node_modules/object-to-arguments/node_modules/inspect-function/node_modules/split-skip": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.1.tgz",
- "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
- },
- "node_modules/object-to-arguments/node_modules/inspect-parameters-declaration": {
- "version": "0.0.10",
- "resolved": "https://registry.npmmirror.com/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.10.tgz",
- "integrity": "sha512-L8/Bvt9iDXQTZ63xY5/MAyvzz+FagR/qGh1kIXvUpsno3AAE0Z95d6QO51zrcMGaEGpwh/57idfMxTxbvRmytg==",
- "dependencies": {
- "magicli": "0.0.5",
- "split-skip": "0.0.2",
- "stringify-parameters": "0.0.4",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "inspect-parameters-declaration": "bin/cli.js"
- }
- },
- "node_modules/object-to-arguments/node_modules/magicli": {
- "version": "0.0.5",
- "resolved": "https://registry.npmmirror.com/magicli/-/magicli-0.0.5.tgz",
- "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
- "dependencies": {
- "commander": "^2.9.0",
- "get-stdin": "^5.0.1",
- "inspect-function": "^0.2.1",
- "pipe-functions": "^1.2.0"
- }
- },
- "node_modules/ohmyfetch": {
- "version": "0.4.21",
- "resolved": "https://registry.npmmirror.com/ohmyfetch/-/ohmyfetch-0.4.21.tgz",
- "integrity": "sha512-VG7f/JRvqvBOYvL0tHyEIEG7XHWm7OqIfAs6/HqwWwDfjiJ1g0huIpe5sFEmyb+7hpFa1EGNH2aERWR72tlClw==",
- "dependencies": {
- "destr": "^1.2.0",
- "node-fetch-native": "^0.1.8",
- "ufo": "^0.8.6",
- "undici": "^5.12.0"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
- "dependencies": {
- "p-try": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
- "dependencies": {
- "p-limit": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/performance-now": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
- },
- "node_modules/pipe-functions": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/pipe-functions/-/pipe-functions-1.3.0.tgz",
- "integrity": "sha512-6Rtbp7criZRwedlvWbUYxqlqJoAlMvYHo2UcRWq79xZ54vZcaNHpVBOcWkX3ErT2aUA69tv+uiv4zKJbhD/Wgg=="
- },
- "node_modules/prebuild-install": {
- "version": "7.1.1",
- "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.1.tgz",
- "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^1.0.1",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/psl": {
- "version": "1.9.0",
- "resolved": "https://registry.npmmirror.com/psl/-/psl-1.9.0.tgz",
- "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
- },
- "node_modules/pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/qs": {
- "version": "6.5.3",
- "resolved": "https://registry.npmmirror.com/qs/-/qs-6.5.3.tgz",
- "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/reduce-flatten": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
- "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/request": {
- "version": "2.88.2",
- "resolved": "https://registry.npmmirror.com/request/-/request-2.88.2.tgz",
- "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
- "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
- "dependencies": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~2.3.2",
- "har-validator": "~5.1.3",
- "http-signature": "~1.2.0",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "oauth-sign": "~0.9.0",
- "performance-now": "^2.1.0",
- "qs": "~6.5.2",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "~2.5.0",
- "tunnel-agent": "^0.6.0",
- "uuid": "^3.3.2"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ "node_modules/quansync": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
+ "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
},
"node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -1376,444 +620,103 @@
}
},
"node_modules/sharp": {
- "version": "0.31.2",
- "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.31.2.tgz",
- "integrity": "sha512-DUdNVEXgS5A97cTagSLIIp8dUZ/lZtk78iNVZgHdHbx1qnQR7JAHY0BnXnwwH39Iw+VKhO08CTYhIg0p98vQ5Q==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz",
+ "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==",
"hasInstallScript": true,
+ "license": "Apache-2.0",
"dependencies": {
"color": "^4.2.3",
- "detect-libc": "^2.0.1",
- "node-addon-api": "^5.0.0",
- "prebuild-install": "^7.1.1",
- "semver": "^7.3.8",
- "simple-get": "^4.0.1",
- "tar-fs": "^2.1.1",
- "tunnel-agent": "^0.6.0"
+ "detect-libc": "^2.0.4",
+ "semver": "^7.7.2"
},
"engines": {
- "node": ">=14.15.0"
- }
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.3",
+ "@img/sharp-darwin-x64": "0.34.3",
+ "@img/sharp-libvips-darwin-arm64": "1.2.0",
+ "@img/sharp-libvips-darwin-x64": "1.2.0",
+ "@img/sharp-libvips-linux-arm": "1.2.0",
+ "@img/sharp-libvips-linux-arm64": "1.2.0",
+ "@img/sharp-libvips-linux-ppc64": "1.2.0",
+ "@img/sharp-libvips-linux-s390x": "1.2.0",
+ "@img/sharp-libvips-linux-x64": "1.2.0",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.0",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.0",
+ "@img/sharp-linux-arm": "0.34.3",
+ "@img/sharp-linux-arm64": "0.34.3",
+ "@img/sharp-linux-ppc64": "0.34.3",
+ "@img/sharp-linux-s390x": "0.34.3",
+ "@img/sharp-linux-x64": "0.34.3",
+ "@img/sharp-linuxmusl-arm64": "0.34.3",
+ "@img/sharp-linuxmusl-x64": "0.34.3",
+ "@img/sharp-wasm32": "0.34.3",
+ "@img/sharp-win32-arm64": "0.34.3",
+ "@img/sharp-win32-ia32": "0.34.3",
+ "@img/sharp-win32-x64": "0.34.3"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "license": "MIT",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
- "node_modules/split-skip": {
- "version": "0.0.2",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.2.tgz",
- "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
- },
"node_modules/sponsorkit": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/sponsorkit/-/sponsorkit-0.6.1.tgz",
- "integrity": "sha512-KPctw94EI/n/ynCC1GNUYOcXyHDV3C7pnbH9fRHc7LuME4KDMLJCzKC+DsNHH684nyKRNQKU41v5BCfZPjfw+w==",
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/sponsorkit/-/sponsorkit-16.5.0.tgz",
+ "integrity": "sha512-GvlLg88eAEbKzROwAspT+PQTMfHN9KQ+zgPqBBvV1W2jQmKxOtnv9vjgByXvXA2dvTjnksdvbTuwqhJZllyLQA==",
+ "license": "MIT",
"dependencies": {
- "consola": "^2.15.3",
- "dotenv": "^16.0.3",
- "fs-extra": "^10.1.0",
- "image-data-uri": "^2.0.1",
- "node-html-parser": "^6.1.1",
- "ohmyfetch": "^0.4.20",
- "picocolors": "^1.0.0",
- "sharp": "^0.31.1",
- "unconfig": "^0.3.7",
- "yargs": "^17.6.0"
+ "ansis": "^4.1.0",
+ "cac": "^6.7.14",
+ "consola": "^3.4.2",
+ "dotenv": "^16.5.0",
+ "ofetch": "^1.4.1",
+ "sharp": "^0.34.2",
+ "unconfig": "^7.3.2"
},
"bin": {
- "sponsorkit": "bin/sponsorkit.js"
+ "sponsorkit": "bin/sponsorkit.mjs"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
- "node_modules/sshpk": {
- "version": "1.17.0",
- "resolved": "https://registry.npmmirror.com/sshpk/-/sshpk-1.17.0.tgz",
- "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
- "dependencies": {
- "asn1": "~0.2.3",
- "assert-plus": "^1.0.0",
- "bcrypt-pbkdf": "^1.0.0",
- "dashdash": "^1.12.0",
- "ecc-jsbn": "~0.1.1",
- "getpass": "^0.1.1",
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.0.2",
- "tweetnacl": "~0.14.0"
- },
- "bin": {
- "sshpk-conv": "bin/sshpk-conv",
- "sshpk-sign": "bin/sshpk-sign",
- "sshpk-verify": "bin/sshpk-verify"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/streamsearch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz",
- "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/stringify-parameters": {
- "version": "0.0.4",
- "resolved": "https://registry.npmmirror.com/stringify-parameters/-/stringify-parameters-0.0.4.tgz",
- "integrity": "sha512-H3L90ERn5UPtkpO8eugnKcLgpIVlvTyUTrcLGm607AV5JDH6z0GymtNLr3gjGlP6I6NB/mxNX9QpY6jEQGLPdQ==",
- "dependencies": {
- "magicli": "0.0.5",
- "unpack-string": "0.0.2"
- },
- "bin": {
- "stringify-parameters": "bin/cli.js"
- }
- },
- "node_modules/stringify-parameters/node_modules/inspect-function": {
- "version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/inspect-function/-/inspect-function-0.2.2.tgz",
- "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
- "dependencies": {
- "split-skip": "0.0.1",
- "unpack-string": "0.0.2"
- }
- },
- "node_modules/stringify-parameters/node_modules/magicli": {
- "version": "0.0.5",
- "resolved": "https://registry.npmmirror.com/magicli/-/magicli-0.0.5.tgz",
- "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
- "dependencies": {
- "commander": "^2.9.0",
- "get-stdin": "^5.0.1",
- "inspect-function": "^0.2.1",
- "pipe-functions": "^1.2.0"
- }
- },
- "node_modules/stringify-parameters/node_modules/split-skip": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/split-skip/-/split-skip-0.0.1.tgz",
- "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
- },
- "node_modules/strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
- "dependencies": {
- "ansi-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/table-layout": {
- "version": "0.4.5",
- "resolved": "https://registry.npmmirror.com/table-layout/-/table-layout-0.4.5.tgz",
- "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==",
- "dependencies": {
- "array-back": "^2.0.0",
- "deep-extend": "~0.6.0",
- "lodash.padend": "^4.6.1",
- "typical": "^2.6.1",
- "wordwrapjs": "^3.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.1.tgz",
- "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tough-cookie": {
- "version": "2.5.0",
- "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-2.5.0.tgz",
- "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
- "dependencies": {
- "psl": "^1.1.28",
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmmirror.com/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
- },
- "node_modules/typical": {
- "version": "2.6.1",
- "resolved": "https://registry.npmmirror.com/typical/-/typical-2.6.1.tgz",
- "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg=="
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD",
+ "optional": true
},
"node_modules/ufo": {
- "version": "0.8.6",
- "resolved": "https://registry.npmmirror.com/ufo/-/ufo-0.8.6.tgz",
- "integrity": "sha512-fk6CmUgwKCfX79EzcDQQpSCMxrHstvbLswFChHS0Vump+kFkw7nJBfTZoC1j0bOGoY9I7R3n2DGek5ajbcYnOw=="
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
+ "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
+ "license": "MIT"
},
"node_modules/unconfig": {
- "version": "0.3.7",
- "resolved": "https://registry.npmmirror.com/unconfig/-/unconfig-0.3.7.tgz",
- "integrity": "sha512-1589b7oGa8ILBYpta7TndM5mLHLzHUqBfhszeZxuUBrjO/RoQ52VGVWsS3w0C0GLNxO9RPmqkf6BmIvBApaRdA==",
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.3.2.tgz",
+ "integrity": "sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg==",
+ "license": "MIT",
"dependencies": {
- "@antfu/utils": "^0.5.2",
- "defu": "^6.1.0",
- "jiti": "^1.16.0"
- }
- },
- "node_modules/undici": {
- "version": "5.13.0",
- "resolved": "https://registry.npmmirror.com/undici/-/undici-5.13.0.tgz",
- "integrity": "sha512-UDZKtwb2k7KRsK4SdXWG7ErXiL7yTGgLWvk2AXO1JMjgjh404nFo6tWSCM2xMpJwMPx3J8i/vfqEh1zOqvj82Q==",
- "dependencies": {
- "busboy": "^1.6.0"
+ "@quansync/fs": "^0.1.1",
+ "defu": "^6.1.4",
+ "jiti": "^2.4.2",
+ "quansync": "^0.2.8"
},
- "engines": {
- "node": ">=12.18"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz",
- "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpack-string": {
- "version": "0.0.2",
- "resolved": "https://registry.npmmirror.com/unpack-string/-/unpack-string-0.0.2.tgz",
- "integrity": "sha512-2ZFjp5aY7QwHE6HAp47RnKYfvgAQ5+NwbKq/ZVtty85RDb3/UaTeCfizo5L/fXzM7UkMP/zDtbV+kGW/iJiK6w=="
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
- "bin": {
- "uuid": "bin/uuid"
- }
- },
- "node_modules/verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npmmirror.com/verror/-/verror-1.10.0.tgz",
- "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
- "engines": [
- "node >=0.6.0"
- ],
- "dependencies": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- }
- },
- "node_modules/wordwrapjs": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz",
- "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==",
- "dependencies": {
- "reduce-flatten": "^1.0.1",
- "typical": "^2.6.1"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
- },
- "node_modules/yargs": {
- "version": "17.6.2",
- "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.6.2.tgz",
- "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-7.0.0.tgz",
- "integrity": "sha512-WhzC+xgstid9MbVUktco/bf+KJG+Uu6vMX0LN1sLJvwmbCQVxb4D8LzogobonKycNasCZLdOzTAk1SK7+K7swg==",
- "dependencies": {
- "camelcase": "^4.1.0"
- }
- },
- "node_modules/yargs/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "engines": {
- "node": ">=12"
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
}
}
}
diff --git a/scripts/sponsors/package.json b/scripts/sponsors/package.json
index 38dc1ad7b..c9f000b90 100644
--- a/scripts/sponsors/package.json
+++ b/scripts/sponsors/package.json
@@ -10,6 +10,9 @@
"author": "",
"license": "ISC",
"dependencies": {
- "sponsorkit": "^0.6.1"
+ "sponsorkit": "^16.5.0"
+ },
+ "engines": {
+ "node": ">=22.0.0"
}
}
diff --git a/scripts/sync-translated-documents.sh b/scripts/sync-translated-documents.sh
deleted file mode 100755
index 70e442861..000000000
--- a/scripts/sync-translated-documents.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-cd ../website
-
-npx @crowdin/cli@latest pull -b master
\ No newline at end of file
diff --git a/scripts/updateversion.sh b/scripts/updateversion.sh
deleted file mode 100755
index e0c4b6e82..000000000
--- a/scripts/updateversion.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-if [ "$#" != "1" ]; then
- echo "Tag required"
- exit 1
-fi
-TAG=${1}
-cat << EOF > cmd/version.go
-package cmd
-
-// Version - Wails version
-const Version = "${TAG}"
-EOF
-
-# Build runtime
-cd runtime/js
-npm run build
-
-cd ../..
-
-git add cmd/version.go
-git commit cmd/version.go -m "Bump to ${TAG}"
-git tag ${TAG}
diff --git a/v2/.golangci.yml b/v2/.golangci.yml
new file mode 100644
index 000000000..66b77ba7f
--- /dev/null
+++ b/v2/.golangci.yml
@@ -0,0 +1,162 @@
+# Options for analysis runner.
+run:
+ # Custom concurrency value
+ concurrency: 4
+
+ # Execution timeout
+ timeout: 10m
+
+ # Exit code when an issue is found.
+ issues-exit-code: 1
+
+ # Inclusion of test files
+ tests: false
+
+ modules-download-mode: readonly
+
+ allow-parallel-runners: false
+
+ go: '1.21'
+
+
+output:
+ # Runner output format
+ format: tab
+
+ # Print line of issue code
+ print-issued-lines: false
+
+ # Append linter to the output
+ print-linter-name: true
+
+ # Separate issues by line
+ uniq-by-line: true
+
+ # Output path prefixing
+ path-prefix: ""
+
+ # Sort results
+ sort-results: true
+
+
+# Specific linter configs
+linters-settings:
+ errcheck:
+ check-type-assertions: false
+ check-blank: false
+ ignore: fmt:.*
+ disable-default-exclusions: false
+
+ gofmt:
+ simplify: true
+
+ gofumpt:
+ extra-rules: false
+
+linters:
+ fast: false
+ # Enable all available linters.
+ enable-all: true
+ # Disable specific linters
+ disable:
+ - asasalint
+ - asciicheck
+ - bidichk
+ - bodyclose
+ - containedctx
+ - contextcheck
+ - cyclop
+ - deadcode
+ - decorder
+ - depguard
+ - dogsled
+ - dupl
+ - dupword
+ - durationcheck
+ - errchkjson
+ - errorlint
+ - execinquery
+ - exhaustive
+ - exhaustivestruct
+ - exhaustruct
+ - exportloopref
+ - forbidigo
+ - forcetypeassert
+ - funlen
+ - gci
+ - ginkgolinter
+ - gocheckcompilerdirectives
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - goconst
+ - gocritic
+ - gocyclo
+ - godot
+ - godox
+ - goerr113
+ - goheader
+ - goimports
+ - golint
+ - gomnd
+ - gomoddirectives
+ - gomodguard
+ - goprintffuncname
+ - gosec
+ - gosmopolitan
+ - govet
+ - grouper
+ - ifshort
+ - importas
+ - ineffassign
+ - interfacebloat
+ - interfacer
+ - ireturn
+ - lll
+ - loggercheck
+ - maintidx
+ - makezero
+ - maligned
+ - mirror
+ - musttag
+ - nakedret
+ - nestif
+ - nilerr
+ - nilnil
+ - nlreturn
+ - noctx
+ - nolintlint
+ - nonamedreturns
+ - nosnakecase
+ - nosprintfhostport
+ - paralleltest
+ - prealloc
+ - predeclared
+ - promlinter
+ - reassign
+ - revive
+ - rowserrcheck
+ - scopelint
+ - sqlclosecheck
+ - staticcheck
+ - structcheck
+ - stylecheck
+ - tagalign
+ - tagliatelle
+ - tenv
+ - testableexamples
+ - testpackage
+ - thelper
+ - tparallel
+ - typecheck
+ - unconvert
+ - unparam
+ - unused
+ - usestdlibvars
+ - varcheck
+ - varnamelen
+ - wastedassign
+ - whitespace
+ - wrapcheck
+ - wsl
+ - zerologlint
\ No newline at end of file
diff --git a/v2/.prettierignore b/v2/.prettierignore
new file mode 100644
index 000000000..94c6af38e
--- /dev/null
+++ b/v2/.prettierignore
@@ -0,0 +1 @@
+website
\ No newline at end of file
diff --git a/v2/.prettierrc.yml b/v2/.prettierrc.yml
new file mode 100644
index 000000000..685d8b6e7
--- /dev/null
+++ b/v2/.prettierrc.yml
@@ -0,0 +1,6 @@
+overrides:
+ - files:
+ - "**/*.md"
+ options:
+ printWidth: 80
+ proseWrap: always
diff --git a/v2/Taskfile.yaml b/v2/Taskfile.yaml
new file mode 100644
index 000000000..d1893732b
--- /dev/null
+++ b/v2/Taskfile.yaml
@@ -0,0 +1,28 @@
+# https://taskfile.dev
+
+version: "3"
+
+tasks:
+ download:
+ summary: Run go mod tidy
+ cmds:
+ - go mod tidy
+
+ lint:
+ summary: Run golangci-lint
+ cmds:
+ - golangci-lint run ./... --timeout=3m -v
+
+ release:
+ summary: Release a new version of Task. Call with `task v2:release -- `
+ dir: tools/release
+ cmds:
+ - go run release.go {{.CLI_ARGS}}
+
+ format:md:
+ cmds:
+ - npx prettier --write "**/*.md"
+
+ format:
+ cmds:
+ - task: format:md
diff --git a/v2/cmd/wails/build.go b/v2/cmd/wails/build.go
index 5d284e9a2..39ad00d2f 100644
--- a/v2/cmd/wails/build.go
+++ b/v2/cmd/wails/build.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "github.com/wailsapp/wails/v2/pkg/commands/buildtags"
"os"
"runtime"
"strings"
@@ -18,7 +19,6 @@ import (
)
func buildApplication(f *flags.Build) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
@@ -50,6 +50,23 @@ func buildApplication(f *flags.Build) error {
return err
}
+ // Set obfuscation from project file
+ if projectOptions.Obfuscated {
+ f.Obfuscated = projectOptions.Obfuscated
+ }
+
+ // Set garble args from project file
+ if projectOptions.GarbleArgs != "" {
+ f.GarbleArgs = projectOptions.GarbleArgs
+ }
+
+ projectTags, err := buildtags.Parse(projectOptions.BuildTags)
+ if err != nil {
+ return err
+ }
+ userTags := f.GetTags()
+ compiledTags := append(projectTags, userTags...)
+
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
@@ -57,6 +74,7 @@ func buildApplication(f *flags.Build) error {
OutputFile: f.OutputFilename,
CleanBinDirectory: f.Clean,
Mode: f.GetBuildMode(),
+ Devtools: f.Debug || f.Devtools,
Pack: !f.NoPackage,
LDFlags: f.LdFlags,
Compiler: f.Compiler,
@@ -66,7 +84,7 @@ func buildApplication(f *flags.Build) error {
IgnoreFrontend: f.SkipFrontend,
Compress: f.Upx,
CompressFlags: f.UpxFlags,
- UserTags: f.GetTags(),
+ UserTags: compiledTags,
WebView2Strategy: f.GetWebView2Strategy(),
TrimPath: f.TrimPath,
RaceDetector: f.RaceDetector,
@@ -75,6 +93,7 @@ func buildApplication(f *flags.Build) error {
GarbleArgs: f.GarbleArgs,
SkipBindings: f.SkipBindings,
ProjectData: projectOptions,
+ SkipEmbedCreate: f.SkipEmbedCreate,
}
tableData := pterm.TableData{
@@ -82,6 +101,7 @@ func buildApplication(f *flags.Build) error {
{"Compiler", f.GetCompilerPath()},
{"Skip Bindings", bool2Str(f.SkipBindings)},
{"Build Mode", f.GetBuildModeAsString()},
+ {"Devtools", bool2Str(buildOptions.Devtools)},
{"Frontend Directory", projectOptions.GetFrontendDir()},
{"Obfuscated", bool2Str(f.Obfuscated)},
}
@@ -94,7 +114,7 @@ func buildApplication(f *flags.Build) error {
{"Package", bool2Str(!f.NoPackage)},
{"Clean Bin Dir", bool2Str(f.Clean)},
{"LDFlags", f.LdFlags},
- {"Tags", "[" + strings.Join(f.GetTags(), ",") + "]"},
+ {"Tags", "[" + strings.Join(compiledTags, ",") + "]"},
{"Race Detector", bool2Str(f.RaceDetector)},
}...)
if len(buildOptions.OutputFile) > 0 && f.GetTargets().Length() == 1 {
@@ -253,5 +273,4 @@ func buildApplication(f *flags.Build) error {
}
return nil
-
}
diff --git a/v2/cmd/wails/dev.go b/v2/cmd/wails/dev.go
index dbb2cf5d8..30213a68e 100644
--- a/v2/cmd/wails/dev.go
+++ b/v2/cmd/wails/dev.go
@@ -1,16 +1,16 @@
package main
import (
+ "os"
+
"github.com/pterm/pterm"
"github.com/wailsapp/wails/v2/cmd/wails/flags"
"github.com/wailsapp/wails/v2/cmd/wails/internal/dev"
"github.com/wailsapp/wails/v2/internal/colour"
"github.com/wailsapp/wails/v2/pkg/clilogger"
- "os"
)
func devApplication(f *flags.Dev) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
@@ -34,5 +34,4 @@ func devApplication(f *flags.Dev) error {
}
return dev.Application(f, logger)
-
}
diff --git a/v2/cmd/wails/doctor.go b/v2/cmd/wails/doctor.go
index 3c8a2d712..7f453133d 100644
--- a/v2/cmd/wails/doctor.go
+++ b/v2/cmd/wails/doctor.go
@@ -1,11 +1,17 @@
package main
import (
+ "fmt"
"runtime"
"runtime/debug"
+ "strconv"
"strings"
+ "github.com/wailsapp/wails/v2/internal/shell"
+
"github.com/pterm/pterm"
+
+ "github.com/jaypipes/ghw"
"github.com/wailsapp/wails/v2/cmd/wails/flags"
"github.com/wailsapp/wails/v2/internal/colour"
"github.com/wailsapp/wails/v2/internal/system"
@@ -13,43 +19,33 @@ import (
)
func diagnoseEnvironment(f *flags.Doctor) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
}
- app.PrintBanner()
+ pterm.DefaultSection = *pterm.DefaultSection.
+ WithBottomPadding(0).
+ WithStyle(pterm.NewStyle(pterm.FgBlue, pterm.Bold))
- pterm.Print("Scanning system - Please wait (this may take a long time)...")
+ pterm.Println() // Spacer
+ pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Println("Wails Doctor")
+ pterm.Println() // Spacer
+
+ spinner, _ := pterm.DefaultSpinner.WithRemoveWhenDone().Start("Scanning system - Please wait (this may take a long time)...")
// Get system info
info, err := system.GetInfo()
if err != nil {
- pterm.Println("Failed.")
- return err
- }
- pterm.Println("Done.")
-
- pterm.DefaultSection.Println("System")
-
- systemTabledata := [][]string{
- {"OS", info.OS.Name},
- {"Version", info.OS.Version},
- {"ID", info.OS.ID},
- {"Go Version", runtime.Version()},
- {"Platform", runtime.GOOS},
- {"Architecture", runtime.GOARCH},
- }
-
- err = pterm.DefaultTable.WithData(systemTabledata).Render()
- if err != nil {
+ spinner.Fail()
+ pterm.Error.Println("Failed to get system information")
return err
}
+ spinner.Success()
pterm.DefaultSection.Println("Wails")
- wailsTableData := [][]string{
+ wailsTableData := pterm.TableData{
{"Version", app.Version()},
}
@@ -77,41 +73,138 @@ func diagnoseEnvironment(f *flags.Doctor) error {
return err
}
+ pterm.DefaultSection.Println("System")
+
+ systemTabledata := pterm.TableData{
+ {pterm.Bold.Sprint("OS"), info.OS.Name},
+ {pterm.Bold.Sprint("Version"), info.OS.Version},
+ {pterm.Bold.Sprint("ID"), info.OS.ID},
+ {pterm.Bold.Sprint("Branding"), info.OS.Branding},
+ {pterm.Bold.Sprint("Go Version"), runtime.Version()},
+ {pterm.Bold.Sprint("Platform"), runtime.GOOS},
+ {pterm.Bold.Sprint("Architecture"), runtime.GOARCH},
+ }
+
+ // Probe CPU
+ cpus, _ := ghw.CPU()
+ if cpus != nil {
+ prefix := "CPU"
+ for idx, cpu := range cpus.Processors {
+ if len(cpus.Processors) > 1 {
+ prefix = "CPU " + strconv.Itoa(idx+1)
+ }
+ systemTabledata = append(systemTabledata, []string{prefix, cpu.Model})
+ }
+ } else {
+ cpuInfo := "Unknown"
+ if runtime.GOOS == "darwin" {
+ // Try to get CPU info from sysctl
+ if stdout, _, err := shell.RunCommand("", "sysctl", "-n", "machdep.cpu.brand_string"); err == nil {
+ cpuInfo = strings.TrimSpace(stdout)
+ }
+ }
+ systemTabledata = append(systemTabledata, []string{"CPU", cpuInfo})
+ }
+
+ // Probe GPU
+ gpu, _ := ghw.GPU(ghw.WithDisableWarnings())
+ if gpu != nil {
+ prefix := "GPU"
+ for idx, card := range gpu.GraphicsCards {
+ if len(gpu.GraphicsCards) > 1 {
+ prefix = "GPU " + strconv.Itoa(idx+1) + " "
+ }
+ if card.DeviceInfo == nil {
+ systemTabledata = append(systemTabledata, []string{prefix, "Unknown"})
+ continue
+ }
+ details := fmt.Sprintf("%s (%s) - Driver: %s", card.DeviceInfo.Product.Name, card.DeviceInfo.Vendor.Name, card.DeviceInfo.Driver)
+ systemTabledata = append(systemTabledata, []string{prefix, details})
+ }
+ } else {
+ gpuInfo := "Unknown"
+ if runtime.GOOS == "darwin" {
+ // Try to get GPU info from system_profiler
+ if stdout, _, err := shell.RunCommand("", "system_profiler", "SPDisplaysDataType"); err == nil {
+ var (
+ startCapturing bool
+ gpuInfoDetails []string
+ )
+ for _, line := range strings.Split(stdout, "\n") {
+ if strings.Contains(line, "Chipset Model") {
+ startCapturing = true
+ }
+ if startCapturing {
+ gpuInfoDetails = append(gpuInfoDetails, strings.TrimSpace(line))
+ }
+ if strings.Contains(line, "Metal Support") {
+ break
+ }
+ }
+ if len(gpuInfoDetails) > 0 {
+ gpuInfo = strings.Join(gpuInfoDetails, " ")
+ }
+ }
+ }
+ systemTabledata = append(systemTabledata, []string{"GPU", gpuInfo})
+ }
+
+ memory, _ := ghw.Memory()
+ if memory != nil {
+ systemTabledata = append(systemTabledata, []string{"Memory", strconv.Itoa(int(memory.TotalPhysicalBytes/1024/1024/1024)) + "GB"})
+ } else {
+ memInfo := "Unknown"
+ if runtime.GOOS == "darwin" {
+ // Try to get Memory info from sysctl
+ if stdout, _, err := shell.RunCommand("", "sysctl", "-n", "hw.memsize"); err == nil {
+ if memSize, err := strconv.Atoi(strings.TrimSpace(stdout)); err == nil {
+ memInfo = strconv.Itoa(memSize/1024/1024/1024) + "GB"
+ }
+ }
+ }
+ systemTabledata = append(systemTabledata, []string{"Memory", memInfo})
+ }
+
+ err = pterm.DefaultTable.WithBoxed().WithData(systemTabledata).Render()
+ if err != nil {
+ return err
+ }
+
pterm.DefaultSection.Println("Dependencies")
// Output Dependencies Status
- var dependenciesMissing = []string{}
- var externalPackages = []*packagemanager.Dependency{}
- var dependenciesAvailableRequired = 0
- var dependenciesAvailableOptional = 0
+ var dependenciesMissing []string
+ var externalPackages []*packagemanager.Dependency
+ dependenciesAvailableRequired := 0
+ dependenciesAvailableOptional := 0
- dependenciesTableData := [][]string{
+ dependenciesTableData := pterm.TableData{
{"Dependency", "Package Name", "Status", "Version"},
}
hasOptionalDependencies := false
// Loop over dependencies
for _, dependency := range info.Dependencies {
-
name := dependency.Name
+
if dependency.Optional {
- name = "*" + name
+ name = pterm.Gray("*") + name
hasOptionalDependencies = true
}
+
packageName := "Unknown"
- status := "Not Found"
+ status := pterm.LightRed("Not Found")
// If we found the package
if dependency.PackageName != "" {
-
packageName = dependency.PackageName
// If it's installed, update the status
if dependency.Installed {
- status = "Installed"
+ status = pterm.LightGreen("Installed")
} else {
// Generate meaningful status text
- status = "Available"
+ status = pterm.LightMagenta("Available")
if dependency.Optional {
dependenciesAvailableOptional++
@@ -132,22 +225,19 @@ func diagnoseEnvironment(f *flags.Doctor) error {
dependenciesTableData = append(dependenciesTableData, []string{name, packageName, status, dependency.Version})
}
- err = pterm.DefaultTable.WithHasHeader(true).WithData(dependenciesTableData).Render()
+ dependenciesTableString, _ := pterm.DefaultTable.WithHasHeader(true).WithData(dependenciesTableData).Srender()
+ dependenciesBox := pterm.DefaultBox.WithTitleBottomCenter()
if hasOptionalDependencies {
- pterm.Println("* - Optional Dependency")
+ dependenciesBox = dependenciesBox.WithTitle(pterm.Gray("*") + " - Optional Dependency")
}
+ dependenciesBox.Println(dependenciesTableString)
+
pterm.DefaultSection.Println("Diagnosis")
// Generate an appropriate diagnosis
- if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 {
- pterm.Println("Your system is ready for Wails development!")
- } else {
- pterm.Println("Your system has missing dependencies!")
- }
-
if dependenciesAvailableRequired != 0 {
pterm.Println("Required package(s) installation details: \n" + info.Dependencies.InstallAllRequiredCommand())
}
@@ -156,11 +246,17 @@ func diagnoseEnvironment(f *flags.Doctor) error {
pterm.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand())
}
+ if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 {
+ pterm.Success.Println("Your system is ready for Wails development!")
+ } else {
+ pterm.Warning.Println("Your system has missing dependencies!")
+ }
+
if len(dependenciesMissing) != 0 {
pterm.Println("Fatal:")
pterm.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
- pterm.Println("Please read this article on how to resolve this: https://wails.io/guides/resolving-missing-packages")
}
+ pterm.Println() // Spacer for sponsor message
return nil
}
diff --git a/v2/cmd/wails/flags/build.go b/v2/cmd/wails/flags/build.go
index d36ceef6a..db05c9035 100644
--- a/v2/cmd/wails/flags/build.go
+++ b/v2/cmd/wails/flags/build.go
@@ -24,8 +24,7 @@ type Build struct {
Common
BuildCommon
- NoPackage bool `name:"noPackage" description:"Skips platform specific packaging"`
- SkipModTidy bool `name:"m" description:"Skip mod tidy before compile"`
+ NoPackage bool `description:"Skips platform specific packaging"`
Upx bool `description:"Compress final binary with UPX (if installed)"`
UpxFlags string `description:"Flags to pass to upx"`
Platform string `description:"Platform to target. Comma separate multiple platforms"`
@@ -35,6 +34,7 @@ type Build struct {
ForceBuild bool `name:"f" description:"Force build of application"`
UpdateWailsVersionGoMod bool `name:"u" description:"Updates go.mod to use the same Wails version as the CLI"`
Debug bool `description:"Builds the application in debug mode"`
+ Devtools bool `description:"Enable Devtools in productions, Already enabled in debug mode (-debug)"`
NSIS bool `description:"Generate NSIS installer for Windows"`
TrimPath bool `description:"Remove all file system paths from the resulting executable"`
WindowsConsole bool `description:"Keep the console when building for Windows"`
diff --git a/v2/cmd/wails/flags/buildcommon.go b/v2/cmd/wails/flags/buildcommon.go
index dcad33abf..a22f7a502 100644
--- a/v2/cmd/wails/flags/buildcommon.go
+++ b/v2/cmd/wails/flags/buildcommon.go
@@ -1,14 +1,16 @@
package flags
type BuildCommon struct {
- LdFlags string `description:"Additional ldflags to pass to the compiler"`
- Compiler string `description:"Use a different go compiler to build, eg go1.15beta1"`
- SkipBindings bool `description:"Skips generation of bindings"`
- RaceDetector bool `name:"race" description:"Build with Go's race detector"`
- SkipFrontend bool `name:"s" description:"Skips building the frontend"`
- Verbosity int `name:"v" description:"Verbosity level (0 = quiet, 1 = normal, 2 = verbose)"`
- Tags string `description:"Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated"`
- NoSyncGoMod bool `description:"Don't sync go.mod"`
+ LdFlags string `description:"Additional ldflags to pass to the compiler"`
+ Compiler string `description:"Use a different go compiler to build, eg go1.15beta1"`
+ SkipBindings bool `description:"Skips generation of bindings"`
+ RaceDetector bool `name:"race" description:"Build with Go's race detector"`
+ SkipFrontend bool `name:"s" description:"Skips building the frontend"`
+ Verbosity int `name:"v" description:"Verbosity level (0 = quiet, 1 = normal, 2 = verbose)"`
+ Tags string `description:"Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated"`
+ NoSyncGoMod bool `description:"Don't sync go.mod"`
+ SkipModTidy bool `name:"m" description:"Skip mod tidy before compile"`
+ SkipEmbedCreate bool `description:"Skips creation of embed files"`
}
func (c BuildCommon) Default() BuildCommon {
diff --git a/v2/cmd/wails/flags/dev.go b/v2/cmd/wails/flags/dev.go
index d6e5d361e..d31d8bc87 100644
--- a/v2/cmd/wails/flags/dev.go
+++ b/v2/cmd/wails/flags/dev.go
@@ -2,14 +2,15 @@ package flags
import (
"fmt"
- "github.com/samber/lo"
- "github.com/wailsapp/wails/v2/internal/project"
- "github.com/wailsapp/wails/v2/pkg/commands/build"
"net"
"net/url"
"os"
"path/filepath"
"runtime"
+
+ "github.com/samber/lo"
+ "github.com/wailsapp/wails/v2/internal/project"
+ "github.com/wailsapp/wails/v2/pkg/commands/build"
)
type Dev struct {
@@ -21,6 +22,7 @@ type Dev struct {
Browser bool `flag:"browser" description:"Open the application in a browser"`
NoReload bool `flag:"noreload" description:"Disable reload on asset change"`
NoColour bool `flag:"nocolor" description:"Disable colour in output"`
+ NoGoRebuild bool `flag:"nogorebuild" description:"Disable automatic rebuilding on backend file changes/additions"`
WailsJSDir string `flag:"wailsjsdir" description:"Directory to generate the Wails JS modules"`
LogLevel string `flag:"loglevel" description:"LogLevel to use - Trace, Debug, Info, Warning, Error)"`
ForceBuild bool `flag:"f" description:"Force build of application"`
@@ -29,6 +31,7 @@ type Dev struct {
AppArgs string `flag:"appargs" description:"arguments to pass to the underlying app (quoted and space separated)"`
Save bool `flag:"save" description:"Save the given flags as defaults"`
FrontendDevServerURL string `flag:"frontenddevserverurl" description:"The url of the external frontend dev server to use"`
+ ViteServerTimeout int `flag:"viteservertimeout" description:"The timeout in seconds for Vite server detection (default: 10)"`
// Internal state
devServerURL *url.URL
@@ -39,13 +42,13 @@ func (*Dev) Default() *Dev {
result := &Dev{
Extensions: "go",
Debounce: 100,
+ LogLevel: "Info",
}
result.BuildCommon = result.BuildCommon.Default()
return result
}
func (d *Dev) Process() error {
-
var err error
err = d.loadAndMergeProjectConfig()
if err != nil {
@@ -103,6 +106,13 @@ func (d *Dev) loadAndMergeProjectConfig() error {
d.AppArgs, _ = lo.Coalesce(d.AppArgs, d.projectConfig.AppArgs)
+ if d.ViteServerTimeout == 0 && d.projectConfig.ViteServerTimeout != 0 {
+ d.ViteServerTimeout = d.projectConfig.ViteServerTimeout
+ } else if d.ViteServerTimeout == 0 {
+ d.ViteServerTimeout = 10 // Default timeout
+ }
+ d.projectConfig.ViteServerTimeout = d.ViteServerTimeout
+
if d.Save {
err = d.projectConfig.Save()
if err != nil {
@@ -111,25 +121,28 @@ func (d *Dev) loadAndMergeProjectConfig() error {
}
return nil
-
}
// GenerateBuildOptions creates a build.Options using the flags
func (d *Dev) GenerateBuildOptions() *build.Options {
result := &build.Options{
- OutputType: "dev",
- Mode: build.Dev,
- Arch: runtime.GOARCH,
- Pack: true,
- Platform: runtime.GOOS,
- LDFlags: d.LdFlags,
- Compiler: d.Compiler,
- ForceBuild: d.ForceBuild,
- IgnoreFrontend: d.SkipFrontend,
- Verbosity: d.Verbosity,
- WailsJSDir: d.WailsJSDir,
- RaceDetector: d.RaceDetector,
- ProjectData: d.projectConfig,
+ OutputType: "dev",
+ Mode: build.Dev,
+ Devtools: true,
+ Arch: runtime.GOARCH,
+ Pack: true,
+ Platform: runtime.GOOS,
+ LDFlags: d.LdFlags,
+ Compiler: d.Compiler,
+ ForceBuild: d.ForceBuild,
+ IgnoreFrontend: d.SkipFrontend,
+ SkipBindings: d.SkipBindings,
+ SkipModTidy: d.SkipModTidy,
+ Verbosity: d.Verbosity,
+ WailsJSDir: d.WailsJSDir,
+ RaceDetector: d.RaceDetector,
+ ProjectData: d.projectConfig,
+ SkipEmbedCreate: d.SkipEmbedCreate,
}
return result
diff --git a/v2/cmd/wails/flags/generate.go b/v2/cmd/wails/flags/generate.go
index 9adf78aa4..b14d67017 100644
--- a/v2/cmd/wails/flags/generate.go
+++ b/v2/cmd/wails/flags/generate.go
@@ -2,6 +2,7 @@ package flags
type GenerateModule struct {
Common
+ Compiler string `description:"Use a different go compiler to build, eg go1.15beta1"`
Tags string `description:"Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated"`
Verbosity int `name:"v" description:"Verbosity level (0 = quiet, 1 = normal, 2 = verbose)"`
}
@@ -12,3 +13,9 @@ type GenerateTemplate struct {
Frontend string `description:"Frontend to use for the template"`
Quiet bool `description:"Suppress output"`
}
+
+func (c *GenerateModule) Default() *GenerateModule {
+ return &GenerateModule{
+ Compiler: "go",
+ }
+}
diff --git a/v2/cmd/wails/flags/init.go b/v2/cmd/wails/flags/init.go
index 6e642ec9a..16d56a207 100644
--- a/v2/cmd/wails/flags/init.go
+++ b/v2/cmd/wails/flags/init.go
@@ -14,7 +14,6 @@ type Init struct {
}
func (i *Init) Default() *Init {
-
result := &Init{
TemplateName: "vanilla",
}
diff --git a/v2/cmd/wails/generate.go b/v2/cmd/wails/generate.go
index a7b059ecf..15a6b33d8 100644
--- a/v2/cmd/wails/generate.go
+++ b/v2/cmd/wails/generate.go
@@ -2,6 +2,9 @@ package main
import (
"fmt"
+ "os"
+ "path/filepath"
+
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"github.com/pterm/pterm"
@@ -14,12 +17,9 @@ import (
"github.com/wailsapp/wails/v2/pkg/clilogger"
"github.com/wailsapp/wails/v2/pkg/commands/bindings"
"github.com/wailsapp/wails/v2/pkg/commands/buildtags"
- "os"
- "path/filepath"
)
func generateModule(f *flags.GenerateModule) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
@@ -43,10 +43,16 @@ func generateModule(f *flags.GenerateModule) error {
return err
}
+ if projectConfig.Bindings.TsGeneration.OutputType == "" {
+ projectConfig.Bindings.TsGeneration.OutputType = "classes"
+ }
+
_, err = bindings.GenerateBindings(bindings.Options{
- Tags: buildTags,
- TsPrefix: projectConfig.Bindings.TsGeneration.Prefix,
- TsSuffix: projectConfig.Bindings.TsGeneration.Suffix,
+ Compiler: f.Compiler,
+ Tags: buildTags,
+ TsPrefix: projectConfig.Bindings.TsGeneration.Prefix,
+ TsSuffix: projectConfig.Bindings.TsGeneration.Suffix,
+ TsOutputType: projectConfig.Bindings.TsGeneration.OutputType,
})
if err != nil {
return err
@@ -55,7 +61,6 @@ func generateModule(f *flags.GenerateModule) error {
}
func generateTemplate(f *flags.GenerateTemplate) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
@@ -77,7 +82,7 @@ func generateTemplate(f *flags.GenerateTemplate) error {
}
templateDir := filepath.Join(cwd, f.Name)
if !fs.DirExists(templateDir) {
- err := os.MkdirAll(templateDir, 0755)
+ err := os.MkdirAll(templateDir, 0o755)
if err != nil {
return err
}
@@ -200,7 +205,7 @@ func processPackageJSON(frontendDir string) error {
json, _ = sjson.SetBytes(json, "name", "{{.ProjectName}}")
json, _ = sjson.SetBytes(json, "author", "{{.AuthorName}}")
- err = os.WriteFile(packageJSON, json, 0644)
+ err = os.WriteFile(packageJSON, json, 0o644)
if err != nil {
return err
}
@@ -231,7 +236,7 @@ func processPackageLockJSON(frontendDir string) error {
printBulletPoint("Updating package-lock.json data...")
json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
- err = os.WriteFile(filename, []byte(json), 0644)
+ err = os.WriteFile(filename, []byte(json), 0o644)
if err != nil {
return err
}
diff --git a/v2/cmd/wails/init.go b/v2/cmd/wails/init.go
index f9a9c6b3f..f79e37ffc 100644
--- a/v2/cmd/wails/init.go
+++ b/v2/cmd/wails/init.go
@@ -3,6 +3,12 @@ package main
import (
"bufio"
"fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "time"
+
"github.com/flytam/filenamify"
"github.com/leaanthony/slicer"
"github.com/pkg/errors"
@@ -13,15 +19,9 @@ import (
"github.com/wailsapp/wails/v2/pkg/clilogger"
"github.com/wailsapp/wails/v2/pkg/git"
"github.com/wailsapp/wails/v2/pkg/templates"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- "time"
)
func initProject(f *flags.Init) error {
-
if f.NoColour {
pterm.DisableColor()
colour.ColourEnabled = false
@@ -125,6 +125,12 @@ func initProject(f *flags.Init) error {
return err
}
+ // Change the module name to project name
+ err = updateModuleNameToProjectName(options, quiet)
+ if err != nil {
+ return err
+ }
+
if !f.CIMode {
// Run `go mod tidy` to ensure `go.sum` is up to date
cmd := exec.Command("go", "mod", "tidy")
@@ -215,7 +221,7 @@ func initGit(options *templates.Options) error {
"frontend/dist",
"frontend/node_modules",
}
- err = os.WriteFile(filepath.Join(options.TargetDir, ".gitignore"), []byte(strings.Join(ignore, "\n")), 0644)
+ err = os.WriteFile(filepath.Join(options.TargetDir, ".gitignore"), []byte(strings.Join(ignore, "\n")), 0o644)
if err != nil {
return errors.Wrap(err, "Unable to create gitignore")
}
@@ -271,8 +277,19 @@ func updateReplaceLine(targetPath string) {
}
}
- err = os.WriteFile("go.mod", []byte(strings.Join(lines, "\n")), 0644)
+ err = os.WriteFile("go.mod", []byte(strings.Join(lines, "\n")), 0o644)
if err != nil {
fatal(err.Error())
}
}
+
+func updateModuleNameToProjectName(options *templates.Options, quiet bool) error {
+ cmd := exec.Command("go", "mod", "edit", "-module", options.ProjectName)
+ cmd.Dir = options.TargetDir
+ cmd.Stderr = os.Stderr
+ if !quiet {
+ cmd.Stdout = os.Stdout
+ }
+
+ return cmd.Run()
+}
diff --git a/v2/cmd/wails/internal/dev/dev.go b/v2/cmd/wails/internal/dev/dev.go
index c330470e1..9495b5bf2 100644
--- a/v2/cmd/wails/internal/dev/dev.go
+++ b/v2/cmd/wails/internal/dev/dev.go
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
+ "log"
"net/http"
"net/url"
"os"
@@ -22,6 +23,7 @@ import (
"github.com/wailsapp/wails/v2/cmd/wails/flags"
"github.com/wailsapp/wails/v2/cmd/wails/internal/gomod"
"github.com/wailsapp/wails/v2/cmd/wails/internal/logutils"
+ "golang.org/x/mod/semver"
"github.com/wailsapp/wails/v2/pkg/commands/buildtags"
@@ -36,6 +38,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/commands/build"
)
+const (
+ viteMinVersion = "v3.0.0"
+)
+
func sliceToMap(input []string) map[string]struct{} {
result := map[string]struct{}{}
for _, value := range input {
@@ -44,34 +50,8 @@ func sliceToMap(input []string) map[string]struct{} {
return result
}
-type devFlags struct {
- ldflags string
- compilerCommand string
- assetDir string
- extensions string
- reloadDirs string
- openBrowser bool
- noReload bool
- skipBindings bool
- wailsjsdir string
- tags string
- verbosity int
- loglevel string
- forceBuild bool
- debounceMS int
- devServer string
- appargs string
- saveConfig bool
- raceDetector bool
-
- frontendDevServerURL string
- skipFrontend bool
- noColour bool
-}
-
// Application runs the application in dev mode
func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
-
cwd := lo.Must(os.Getwd())
// Update go.mod to use current wails version
@@ -80,10 +60,12 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
return err
}
- // Run go mod tidy to ensure we're up-to-date
- err = runCommand(cwd, false, "go", "mod", "tidy")
- if err != nil {
- return err
+ if !f.SkipModTidy {
+ // Run go mod tidy to ensure we're up-to-date
+ err = runCommand(cwd, false, f.Compiler, "mod", "tidy")
+ if err != nil {
+ return err
+ }
}
buildOptions := f.GenerateBuildOptions()
@@ -94,13 +76,18 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
return err
}
- buildOptions.UserTags = userTags
-
projectConfig := f.ProjectConfig()
+ projectTags, err := buildtags.Parse(projectConfig.BuildTags)
+ if err != nil {
+ return err
+ }
+ compiledTags := append(projectTags, userTags...)
+ buildOptions.UserTags = compiledTags
+
// Setup signal handler
quitChannel := make(chan os.Signal, 1)
- signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
+ signal.Notify(quitChannel, os.Interrupt, syscall.SIGTERM)
exitCodeChannel := make(chan int, 1)
// Build the frontend if requested, but ignore building the application itself.
@@ -113,10 +100,11 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
buildOptions.IgnoreApplication = false
}
+ legacyUseDevServerInsteadofCustomScheme := false
// frontend:dev:watcher command.
frontendDevAutoDiscovery := projectConfig.IsFrontendDevServerURLAutoDiscovery()
if command := projectConfig.DevWatcherCommand; command != "" {
- closer, devServerURL, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
+ closer, devServerURL, devServerViteVersion, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery, projectConfig.ViteServerTimeout)
if err != nil {
return err
}
@@ -125,6 +113,12 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
f.FrontendDevServerURL = devServerURL
}
defer closer()
+
+ if devServerViteVersion != "" && semver.Compare(devServerViteVersion, viteMinVersion) < 0 {
+ logutils.LogRed("Please upgrade your Vite Server to at least '%s' future Wails versions will require at least Vite '%s'", viteMinVersion, viteMinVersion)
+ time.Sleep(3 * time.Second)
+ legacyUseDevServerInsteadofCustomScheme = true
+ }
} else if frontendDevAutoDiscovery {
return fmt.Errorf("unable to auto discover frontend:dev:serverUrl without a frontend:dev:watcher command, please either set frontend:dev:watcher or remove the auto discovery from frontend:dev:serverUrl")
}
@@ -132,7 +126,7 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
// Do initial build but only for the application.
logger.Println("Building application for development...")
buildOptions.IgnoreFrontend = true
- debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, f, exitCodeChannel)
+ debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, f, exitCodeChannel, legacyUseDevServerInsteadofCustomScheme)
buildOptions.IgnoreFrontend = ignoreFrontend || f.FrontendDevServerURL != ""
if err != nil {
return err
@@ -151,20 +145,6 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
}
}
- // create the project files watcher
- watcher, err := initialiseWatcher(cwd)
- if err != nil {
- return err
- }
-
- defer func(watcher *fsnotify.Watcher) {
- err := watcher.Close()
- if err != nil {
- logger.Fatal(err.Error())
- }
- }(watcher)
-
- logutils.LogGreen("Watching (sub)/directory: %s", cwd)
logutils.LogGreen("Using DevServer URL: %s", f.DevServerURL())
if f.FrontendDevServerURL != "" {
logutils.LogGreen("Using Frontend DevServer URL: %s", f.FrontendDevServerURL)
@@ -178,7 +158,10 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
}()
// Watch for changes and trigger restartApp()
- debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, f, watcher, exitCodeChannel, quitChannel, f.DevServerURL())
+ debugBinaryProcess, err = doWatcherLoop(cwd, projectConfig.ReloadDirectories, buildOptions, debugBinaryProcess, f, exitCodeChannel, quitChannel, f.DevServerURL(), legacyUseDevServerInsteadofCustomScheme)
+ if err != nil {
+ return err
+ }
// Kill the current program if running and remove dev binary
if err := killProcessAndCleanupBinary(debugBinaryProcess, appBinary); err != nil {
@@ -227,7 +210,7 @@ func runCommand(dir string, exitOnError bool, command string, args ...string) er
}
// runFrontendDevWatcherCommand will run the `frontend:dev:watcher` command if it was given, ex- `npm run dev`
-func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
+func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool, viteServerTimeout int) (func(), string, string, error) {
ctx, cancel := context.WithCancel(context.Background())
scanner := NewStdoutScanner()
cmdSlice := strings.Split(devCommand, " ")
@@ -239,7 +222,7 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
if err := cmd.Start(); err != nil {
cancel()
- return nil, "", fmt.Errorf("unable to start frontend DevWatcher: %w", err)
+ return nil, "", "", fmt.Errorf("unable to start frontend DevWatcher: %w", err)
}
var viteServerURL string
@@ -247,20 +230,29 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
select {
case serverURL := <-scanner.ViteServerURLChan:
viteServerURL = serverURL
- case <-time.After(time.Second * 10):
+ case <-time.After(time.Second * time.Duration(viteServerTimeout)):
cancel()
- return nil, "", errors.New("failed to find Vite server URL")
+ return nil, "", "", fmt.Errorf("failed to find Vite server URL: Timed out waiting for Vite to output a URL after %d seconds", viteServerTimeout)
}
}
+ viteVersion := ""
+ select {
+ case version := <-scanner.ViteServerVersionC:
+ viteVersion = version
+
+ case <-time.After(time.Second * 5):
+ // That's fine, then most probably it was not vite that was running
+ }
+
logutils.LogGreen("Running frontend DevWatcher command: '%s'", devCommand)
var wg sync.WaitGroup
wg.Add(1)
const (
stateRunning int32 = 0
- stateCanceling = 1
- stateStopped = 2
+ stateCanceling int32 = 1
+ stateStopped int32 = 2
)
state := stateRunning
go func() {
@@ -280,12 +272,11 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
}
cancel()
wg.Wait()
- }, viteServerURL, nil
+ }, viteServerURL, viteVersion, nil
}
// restartApp does the actual rebuilding of the application when files change
-func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int) (*process.Process, string, error) {
-
+func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int, legacyUseDevServerInsteadofCustomScheme bool) (*process.Process, string, error) {
appBinary, err := build.Build(buildOptions)
println()
if err != nil {
@@ -312,7 +303,6 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
// parse appargs if any
args, err := shlex.Split(f.AppArgs)
-
if err != nil {
buildOptions.Logger.Fatal("Unable to parse appargs: %s", err.Error())
}
@@ -341,9 +331,25 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
}
// doWatcherLoop is the main watch loop that runs while dev is active
-func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL) *process.Process {
+func doWatcherLoop(cwd string, reloadDirs string, buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL, legacyUseDevServerInsteadofCustomScheme bool) (*process.Process, error) {
+ // create the project files watcher
+ watcher, err := initialiseWatcher(cwd, reloadDirs)
+ if err != nil {
+ logutils.LogRed("Unable to create filesystem watcher. Reloads will not occur.")
+ return nil, err
+ }
+
+ defer func(watcher *fsnotify.Watcher) {
+ err := watcher.Close()
+ if err != nil {
+ log.Fatal(err.Error())
+ }
+ }(watcher)
+
+ logutils.LogGreen("Watching (sub)/directory: %s", cwd)
+
// Main Loop
- var extensionsThatTriggerARebuild = sliceToMap(strings.Split(f.Extensions, ","))
+ extensionsThatTriggerARebuild := sliceToMap(strings.Split(f.Extensions, ","))
var dirsThatTriggerAReload []string
for _, dir := range strings.Split(f.ReloadDirs, ",") {
if dir == "" {
@@ -355,6 +361,12 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
continue
}
dirsThatTriggerAReload = append(dirsThatTriggerAReload, thePath)
+ err = watcher.Add(thePath)
+ if err != nil {
+ logutils.LogRed("Unable to watch path: %s due to error %v", thePath, err)
+ } else {
+ logutils.LogGreen("Watching (sub)/directory: %s", thePath)
+ }
}
quit := false
@@ -370,7 +382,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
assetDirURL := joinPath(devServerURL, "/wails/assetdir")
reloadURL := joinPath(devServerURL, "/wails/reload")
- for quit == false {
+ for !quit {
// reload := false
select {
case exitCode := <-exitCodeChannel:
@@ -445,16 +457,21 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
case <-timer.C:
if rebuild {
rebuild = false
- logutils.LogGreen("[Rebuild triggered] files updated")
- // Try and build the app
- newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, f, exitCodeChannel)
- if err != nil {
- logutils.LogRed("Error during build: %s", err.Error())
- continue
- }
- // If we have a new process, saveConfig it
- if newBinaryProcess != nil {
- debugBinaryProcess = newBinaryProcess
+ if f.NoGoRebuild {
+ logutils.LogGreen("[Rebuild triggered] skipping due to flag -nogorebuild")
+ } else {
+ logutils.LogGreen("[Rebuild triggered] files updated")
+ // Try and build the app
+
+ newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, f, exitCodeChannel, legacyUseDevServerInsteadofCustomScheme)
+ if err != nil {
+ logutils.LogRed("Error during build: %s", err.Error())
+ continue
+ }
+ // If we have a new process, saveConfig it
+ if newBinaryProcess != nil {
+ debugBinaryProcess = newBinaryProcess
+ }
}
}
@@ -498,7 +515,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
quit = true
}
}
- return debugBinaryProcess
+ return debugBinaryProcess, nil
}
func joinPath(url *url.URL, subPath string) string {
diff --git a/v2/cmd/wails/internal/dev/stdout_scanner.go b/v2/cmd/wails/internal/dev/stdout_scanner.go
index d84e4785e..dad4e72cf 100644
--- a/v2/cmd/wails/internal/dev/stdout_scanner.go
+++ b/v2/cmd/wails/internal/dev/stdout_scanner.go
@@ -2,30 +2,47 @@ package dev
import (
"bufio"
+ "fmt"
"net/url"
"os"
"strings"
"github.com/acarl005/stripansi"
"github.com/wailsapp/wails/v2/cmd/wails/internal/logutils"
+ "golang.org/x/mod/semver"
)
// stdoutScanner acts as a stdout target that will scan the incoming
// data to find out the vite server url
type stdoutScanner struct {
- ViteServerURLChan chan string
+ ViteServerURLChan chan string
+ ViteServerVersionC chan string
+ versionDetected bool
}
// NewStdoutScanner creates a new stdoutScanner
func NewStdoutScanner() *stdoutScanner {
return &stdoutScanner{
- ViteServerURLChan: make(chan string, 2),
+ ViteServerURLChan: make(chan string, 2),
+ ViteServerVersionC: make(chan string, 2),
}
}
// Write bytes to the scanner. Will copy the bytes to stdout
func (s *stdoutScanner) Write(data []byte) (n int, err error) {
input := stripansi.Strip(string(data))
+ if !s.versionDetected {
+ v, err := detectViteVersion(input)
+ if v != "" || err != nil {
+ if err != nil {
+ logutils.LogRed("ViteStdoutScanner: %s", err)
+ v = "v0.0.0"
+ }
+ s.ViteServerVersionC <- v
+ s.versionDetected = true
+ }
+ }
+
match := strings.Index(input, "Local:")
if match != -1 {
sc := bufio.NewScanner(strings.NewReader(input))
@@ -47,3 +64,21 @@ func (s *stdoutScanner) Write(data []byte) (n int, err error) {
}
return os.Stdout.Write(data)
}
+
+func detectViteVersion(line string) (string, error) {
+ s := strings.Split(strings.TrimSpace(line), " ")
+ if strings.ToLower(s[0]) != "vite" {
+ return "", nil
+ }
+
+ if len(line) < 2 {
+ return "", fmt.Errorf("unable to parse vite version")
+ }
+
+ v := s[1]
+ if !semver.IsValid(v) {
+ return "", fmt.Errorf("%s is not a valid vite version string", v)
+ }
+
+ return v, nil
+}
diff --git a/v2/cmd/wails/internal/dev/watcher.go b/v2/cmd/wails/internal/dev/watcher.go
index 19caf0df8..e1161f87c 100644
--- a/v2/cmd/wails/internal/dev/watcher.go
+++ b/v2/cmd/wails/internal/dev/watcher.go
@@ -4,6 +4,7 @@ import (
"bufio"
"os"
"path/filepath"
+ "strings"
"github.com/wailsapp/wails/v2/internal/fs"
@@ -17,8 +18,7 @@ type Watcher interface {
}
// initialiseWatcher creates the project directory watcher that will trigger recompile
-func initialiseWatcher(cwd string) (*fsnotify.Watcher, error) {
-
+func initialiseWatcher(cwd, reloadDirs string) (*fsnotify.Watcher, error) {
// Ignore dot files, node_modules and build directories by default
ignoreDirs := getIgnoreDirs(cwd)
@@ -28,31 +28,42 @@ func initialiseWatcher(cwd string) (*fsnotify.Watcher, error) {
return nil, err
}
+ customDirs := dirs.AsSlice()
+ seperatedDirs := strings.Split(reloadDirs, ",")
+ for _, dir := range seperatedDirs {
+ customSub, err := fs.GetSubdirectories(filepath.Join(cwd, dir))
+ if err != nil {
+ return nil, err
+ }
+ customDirs = append(customDirs, customSub.AsSlice()...)
+ }
+
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
- for _, dir := range processDirectories(dirs.AsSlice(), ignoreDirs) {
+ for _, dir := range processDirectories(customDirs, ignoreDirs) {
err := watcher.Add(dir)
if err != nil {
return nil, err
}
- println("watching: " + dir)
}
return watcher, nil
}
func getIgnoreDirs(cwd string) []string {
ignoreDirs := []string{filepath.Join(cwd, "build/*"), ".*", "node_modules"}
-
+ baseDir := filepath.Base(cwd)
// Read .gitignore into ignoreDirs
f, err := os.Open(filepath.Join(cwd, ".gitignore"))
if err == nil {
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
- ignoreDirs = append(ignoreDirs, line)
+ if line != baseDir {
+ ignoreDirs = append(ignoreDirs, line)
+ }
}
}
diff --git a/v2/cmd/wails/internal/gomod/gomod.go b/v2/cmd/wails/internal/gomod/gomod.go
index 52e56344b..5da14a5ff 100644
--- a/v2/cmd/wails/internal/gomod/gomod.go
+++ b/v2/cmd/wails/internal/gomod/gomod.go
@@ -56,7 +56,7 @@ func SyncGoMod(logger *clilogger.CLILogger, updateWailsVersion bool) error {
}
if updated {
- return os.WriteFile(gomodFilename, gomodData, 0755)
+ return os.WriteFile(gomodFilename, gomodData, 0o755)
}
return nil
diff --git a/v2/cmd/wails/internal/version.txt b/v2/cmd/wails/internal/version.txt
index d07897c40..805579f30 100644
--- a/v2/cmd/wails/internal/version.txt
+++ b/v2/cmd/wails/internal/version.txt
@@ -1 +1 @@
-v2.3.1
\ No newline at end of file
+v2.11.0
\ No newline at end of file
diff --git a/v2/cmd/wails/main.go b/v2/cmd/wails/main.go
index 7a09559e9..ccf1576e9 100644
--- a/v2/cmd/wails/main.go
+++ b/v2/cmd/wails/main.go
@@ -41,7 +41,7 @@ func printBulletPoint(text string, args ...any) {
fatal(err.Error())
}
t = strings.Trim(t, "\n\r")
- pterm.Printf(t, args...)
+ pterm.Printfln(t, args...)
}
func printFooter() {
@@ -66,7 +66,6 @@ func bool2Str(b bool) string {
var app *clir.Cli
func main() {
-
var err error
app = clir.NewCli("Wails", "Go/HTML Appkit", internal.Version)
diff --git a/v2/cmd/wails/update.go b/v2/cmd/wails/update.go
index ac0e7375a..9f8b6e604 100644
--- a/v2/cmd/wails/update.go
+++ b/v2/cmd/wails/update.go
@@ -15,7 +15,6 @@ import (
// AddSubcommand adds the `init` command for the Wails application
func update(f *flags.Update) error {
-
if f.NoColour {
colour.ColourEnabled = false
pterm.DisableColor()
@@ -73,8 +72,7 @@ func update(f *flags.Update) error {
}
func updateToVersion(targetVersion *github.SemanticVersion, force bool, currentVersion string) error {
-
- var targetVersionString = "v" + targetVersion.String()
+ targetVersionString := "v" + targetVersion.String()
if targetVersionString == currentVersion {
pterm.Println("\nLooks like you're up to date!")
diff --git a/v2/examples/customlayout/build/windows/installer/project.nsi b/v2/examples/customlayout/build/windows/installer/project.nsi
index 3b1588e0c..2ccc0f3f3 100644
--- a/v2/examples/customlayout/build/windows/installer/project.nsi
+++ b/v2/examples/customlayout/build/windows/installer/project.nsi
@@ -45,6 +45,9 @@ VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
+# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
+ManifestDPIAware true
+
!include "MUI.nsh"
!define MUI_ICON "..\icon.ico"
diff --git a/v2/examples/customlayout/go.mod b/v2/examples/customlayout/go.mod
index 97defaeb1..e1a17304e 100644
--- a/v2/examples/customlayout/go.mod
+++ b/v2/examples/customlayout/go.mod
@@ -1,34 +1,39 @@
module changeme
-go 1.18
+go 1.22.0
+
+toolchain go1.24.1
require github.com/wailsapp/wails/v2 v2.1.0
require (
github.com/bep/debounce v1.2.1 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/google/uuid v1.1.2 // indirect
- github.com/imdario/mergo v0.3.12 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
+ github.com/google/uuid v1.6.0 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
- github.com/labstack/echo/v4 v4.9.0 // indirect
- github.com/labstack/gommon v0.3.1 // indirect
- github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/gosod v1.0.3 // indirect
- github.com/leaanthony/slicer v1.5.0 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/labstack/echo/v4 v4.13.3 // indirect
+ github.com/labstack/gommon v0.4.2 // indirect
+ github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
+ github.com/leaanthony/gosod v1.0.4 // indirect
+ github.com/leaanthony/slicer v1.6.0 // indirect
+ github.com/leaanthony/u v1.1.1 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/samber/lo v1.27.1 // indirect
- github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/samber/lo v1.49.1 // indirect
+ github.com/tkrajina/go-reflector v0.5.8 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
+ github.com/valyala/fasttemplate v1.2.2 // indirect
+ github.com/wailsapp/go-webview2 v1.0.22 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
- golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
- golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
- golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
- golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
- golang.org/x/text v0.3.7 // indirect
+ golang.org/x/crypto v0.33.0 // indirect
+ golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
+ golang.org/x/net v0.35.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
)
replace github.com/wailsapp/wails/v2 v2.1.0 => ../..
diff --git a/v2/examples/customlayout/go.sum b/v2/examples/customlayout/go.sum
index 13bb6bbe1..f1995affb 100644
--- a/v2/examples/customlayout/go.sum
+++ b/v2/examples/customlayout/go.sum
@@ -5,57 +5,85 @@ 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/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-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/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
-github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
-github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
+github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
+github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
+github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
-github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
+github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
+github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
+github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
+github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
+github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
+github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI=
+github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
+github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
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/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
-github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
+github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
+github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
-github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
-github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
-github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
+github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w=
+github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
+github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
+github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -64,16 +92,20 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/v2/examples/customlayout/myfrontend/package.json b/v2/examples/customlayout/myfrontend/package.json
index 4ac881798..a1b6f8e1a 100644
--- a/v2/examples/customlayout/myfrontend/package.json
+++ b/v2/examples/customlayout/myfrontend/package.json
@@ -8,6 +8,6 @@
"preview": "vite preview"
},
"devDependencies": {
- "vite": "^2.9.9"
+ "vite": "^3.0.7"
}
}
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/.gitignore b/v2/examples/dragdrop-test/.gitignore
new file mode 100644
index 000000000..a11bbf414
--- /dev/null
+++ b/v2/examples/dragdrop-test/.gitignore
@@ -0,0 +1,4 @@
+build/bin
+node_modules
+frontend/dist
+frontend/wailsjs
diff --git a/v2/examples/dragdrop-test/README.md b/v2/examples/dragdrop-test/README.md
new file mode 100644
index 000000000..397b08b92
--- /dev/null
+++ b/v2/examples/dragdrop-test/README.md
@@ -0,0 +1,19 @@
+# README
+
+## About
+
+This is the official Wails Vanilla template.
+
+You can configure the project by editing `wails.json`. More information about the project settings can be found
+here: https://wails.io/docs/reference/project-config
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. This will run a Vite development
+server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser
+and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect
+to this in your browser, and you can call your Go code from devtools.
+
+## Building
+
+To build a redistributable, production mode package, use `wails build`.
diff --git a/v2/examples/dragdrop-test/app.go b/v2/examples/dragdrop-test/app.go
new file mode 100644
index 000000000..af53038a1
--- /dev/null
+++ b/v2/examples/dragdrop-test/app.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called when the app starts. The context is saved
+// so we can call the runtime methods
+func (a *App) startup(ctx context.Context) {
+ a.ctx = ctx
+}
+
+// Greet returns a greeting for the given name
+func (a *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s, It's show time!", name)
+}
diff --git a/v2/examples/dragdrop-test/build/README.md b/v2/examples/dragdrop-test/build/README.md
new file mode 100644
index 000000000..1ae2f677f
--- /dev/null
+++ b/v2/examples/dragdrop-test/build/README.md
@@ -0,0 +1,35 @@
+# Build Directory
+
+The build directory is used to house all the build files and assets for your application.
+
+The structure is:
+
+* bin - Output directory
+* darwin - macOS specific files
+* windows - Windows specific files
+
+## Mac
+
+The `darwin` directory holds files specific to Mac builds.
+These may be customised and used as part of the build. To return these files to the default state, simply delete them
+and
+build with `wails build`.
+
+The directory contains the following files:
+
+- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`.
+- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`.
+
+## Windows
+
+The `windows` directory contains the manifest and rc files used when building with `wails build`.
+These may be customised for your application. To return these files to the default state, simply delete them and
+build with `wails build`.
+
+- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to
+ use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file
+ will be created using the `appicon.png` file in the build directory.
+- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`.
+- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer,
+ as well as the application itself (right click the exe -> properties -> details)
+- `wails.exe.manifest` - The main application manifest file.
\ No newline at end of file
diff --git a/v2/examples/systray/build/appicon.png b/v2/examples/dragdrop-test/build/appicon.png
similarity index 100%
rename from v2/examples/systray/build/appicon.png
rename to v2/examples/dragdrop-test/build/appicon.png
diff --git a/v2/examples/dragdrop-test/build/darwin/Info.dev.plist b/v2/examples/dragdrop-test/build/darwin/Info.dev.plist
new file mode 100644
index 000000000..14121ef7c
--- /dev/null
+++ b/v2/examples/dragdrop-test/build/darwin/Info.dev.plist
@@ -0,0 +1,68 @@
+
+
+
+ CFBundlePackageType
+ APPL
+ CFBundleName
+ {{.Info.ProductName}}
+ CFBundleExecutable
+ {{.OutputFilename}}
+ CFBundleIdentifier
+ com.wails.{{.Name}}
+ CFBundleVersion
+ {{.Info.ProductVersion}}
+ CFBundleGetInfoString
+ {{.Info.Comments}}
+ CFBundleShortVersionString
+ {{.Info.ProductVersion}}
+ CFBundleIconFile
+ iconfile
+ LSMinimumSystemVersion
+ 10.13.0
+ NSHighResolutionCapable
+ true
+ NSHumanReadableCopyright
+ {{.Info.Copyright}}
+ {{if .Info.FileAssociations}}
+ CFBundleDocumentTypes
+
+ {{range .Info.FileAssociations}}
+
+ CFBundleTypeExtensions
+
+ {{.Ext}}
+
+ CFBundleTypeName
+ {{.Name}}
+ CFBundleTypeRole
+ {{.Role}}
+ CFBundleTypeIconFile
+ {{.IconName}}
+
+ {{end}}
+
+ {{end}}
+ {{if .Info.Protocols}}
+ CFBundleURLTypes
+
+ {{range .Info.Protocols}}
+
+ CFBundleURLName
+ com.wails.{{.Scheme}}
+ CFBundleURLSchemes
+
+ {{.Scheme}}
+
+ CFBundleTypeRole
+ {{.Role}}
+
+ {{end}}
+
+ {{end}}
+ NSAppTransportSecurity
+
+ NSAllowsLocalNetworking
+
+
+
+
diff --git a/v2/examples/dragdrop-test/build/darwin/Info.plist b/v2/examples/dragdrop-test/build/darwin/Info.plist
new file mode 100644
index 000000000..d17a7475c
--- /dev/null
+++ b/v2/examples/dragdrop-test/build/darwin/Info.plist
@@ -0,0 +1,63 @@
+
+
+
+ CFBundlePackageType
+ APPL
+ CFBundleName
+ {{.Info.ProductName}}
+ CFBundleExecutable
+ {{.OutputFilename}}
+ CFBundleIdentifier
+ com.wails.{{.Name}}
+ CFBundleVersion
+ {{.Info.ProductVersion}}
+ CFBundleGetInfoString
+ {{.Info.Comments}}
+ CFBundleShortVersionString
+ {{.Info.ProductVersion}}
+ CFBundleIconFile
+ iconfile
+ LSMinimumSystemVersion
+ 10.13.0
+ NSHighResolutionCapable
+ true
+ NSHumanReadableCopyright
+ {{.Info.Copyright}}
+ {{if .Info.FileAssociations}}
+ CFBundleDocumentTypes
+
+ {{range .Info.FileAssociations}}
+
+ CFBundleTypeExtensions
+
+ {{.Ext}}
+
+ CFBundleTypeName
+ {{.Name}}
+ CFBundleTypeRole
+ {{.Role}}
+ CFBundleTypeIconFile
+ {{.IconName}}
+
+ {{end}}
+
+ {{end}}
+ {{if .Info.Protocols}}
+ CFBundleURLTypes
+
+ {{range .Info.Protocols}}
+
+ CFBundleURLName
+ com.wails.{{.Scheme}}
+ CFBundleURLSchemes
+
+ {{.Scheme}}
+
+ CFBundleTypeRole
+ {{.Role}}
+
+ {{end}}
+
+ {{end}}
+
+
diff --git a/v2/examples/systray/build/windows/icon.ico b/v2/examples/dragdrop-test/build/windows/icon.ico
similarity index 100%
rename from v2/examples/systray/build/windows/icon.ico
rename to v2/examples/dragdrop-test/build/windows/icon.ico
diff --git a/v2/examples/dragdrop-test/build/windows/info.json b/v2/examples/dragdrop-test/build/windows/info.json
new file mode 100644
index 000000000..9727946b7
--- /dev/null
+++ b/v2/examples/dragdrop-test/build/windows/info.json
@@ -0,0 +1,15 @@
+{
+ "fixed": {
+ "file_version": "{{.Info.ProductVersion}}"
+ },
+ "info": {
+ "0000": {
+ "ProductVersion": "{{.Info.ProductVersion}}",
+ "CompanyName": "{{.Info.CompanyName}}",
+ "FileDescription": "{{.Info.ProductName}}",
+ "LegalCopyright": "{{.Info.Copyright}}",
+ "ProductName": "{{.Info.ProductName}}",
+ "Comments": "{{.Info.Comments}}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/v2/examples/systray/build/windows/installer/project.nsi b/v2/examples/dragdrop-test/build/windows/installer/project.nsi
similarity index 89%
rename from v2/examples/systray/build/windows/installer/project.nsi
rename to v2/examples/dragdrop-test/build/windows/installer/project.nsi
index 3b1588e0c..654ae2e49 100644
--- a/v2/examples/systray/build/windows/installer/project.nsi
+++ b/v2/examples/dragdrop-test/build/windows/installer/project.nsi
@@ -3,10 +3,10 @@ Unicode true
####
## Please note: Template replacements don't work in this file. They are provided with default defines like
## mentioned underneath.
-## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
-## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
+## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
+## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
## from outside of Wails for debugging and development of the installer.
-##
+##
## For development first make a wails nsis build to populate the "wails_tools.nsh":
## > wails build --target windows/amd64 --nsis
## Then you can call makensis on this file with specifying the path to your binary:
@@ -17,7 +17,7 @@ Unicode true
## For a installer with both architectures:
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
####
-## The following information is taken from the ProjectInfo file, but they can be overwritten here.
+## The following information is taken from the ProjectInfo file, but they can be overwritten here.
####
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
@@ -45,6 +45,9 @@ VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
+# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
+ManifestDPIAware true
+
!include "MUI.nsh"
!define MUI_ICON "..\icon.ico"
@@ -77,19 +80,26 @@ Function .onInit
FunctionEnd
Section
+ !insertmacro wails.setShellContext
+
!insertmacro wails.webview2runtime
SetOutPath $INSTDIR
-
+
!insertmacro wails.files
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
+ !insertmacro wails.associateFiles
+ !insertmacro wails.associateCustomProtocols
+
!insertmacro wails.writeUninstaller
SectionEnd
-Section "uninstall"
+Section "uninstall"
+ !insertmacro wails.setShellContext
+
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
RMDir /r $INSTDIR
@@ -97,5 +107,8 @@ Section "uninstall"
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
+ !insertmacro wails.unassociateFiles
+ !insertmacro wails.unassociateCustomProtocols
+
!insertmacro wails.deleteUninstaller
SectionEnd
diff --git a/v2/examples/dragdrop-test/build/windows/installer/wails_tools.nsh b/v2/examples/dragdrop-test/build/windows/installer/wails_tools.nsh
new file mode 100644
index 000000000..f9c0f8852
--- /dev/null
+++ b/v2/examples/dragdrop-test/build/windows/installer/wails_tools.nsh
@@ -0,0 +1,249 @@
+# DO NOT EDIT - Generated automatically by `wails build`
+
+!include "x64.nsh"
+!include "WinVer.nsh"
+!include "FileFunc.nsh"
+
+!ifndef INFO_PROJECTNAME
+ !define INFO_PROJECTNAME "{{.Name}}"
+!endif
+!ifndef INFO_COMPANYNAME
+ !define INFO_COMPANYNAME "{{.Info.CompanyName}}"
+!endif
+!ifndef INFO_PRODUCTNAME
+ !define INFO_PRODUCTNAME "{{.Info.ProductName}}"
+!endif
+!ifndef INFO_PRODUCTVERSION
+ !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
+!endif
+!ifndef INFO_COPYRIGHT
+ !define INFO_COPYRIGHT "{{.Info.Copyright}}"
+!endif
+!ifndef PRODUCT_EXECUTABLE
+ !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
+!endif
+!ifndef UNINST_KEY_NAME
+ !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
+!endif
+!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
+
+!ifndef REQUEST_EXECUTION_LEVEL
+ !define REQUEST_EXECUTION_LEVEL "admin"
+!endif
+
+RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
+
+!ifdef ARG_WAILS_AMD64_BINARY
+ !define SUPPORTS_AMD64
+!endif
+
+!ifdef ARG_WAILS_ARM64_BINARY
+ !define SUPPORTS_ARM64
+!endif
+
+!ifdef SUPPORTS_AMD64
+ !ifdef SUPPORTS_ARM64
+ !define ARCH "amd64_arm64"
+ !else
+ !define ARCH "amd64"
+ !endif
+!else
+ !ifdef SUPPORTS_ARM64
+ !define ARCH "arm64"
+ !else
+ !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
+ !endif
+!endif
+
+!macro wails.checkArchitecture
+ !ifndef WAILS_WIN10_REQUIRED
+ !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
+ !endif
+
+ !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
+ !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
+ !endif
+
+ ${If} ${AtLeastWin10}
+ !ifdef SUPPORTS_AMD64
+ ${if} ${IsNativeAMD64}
+ Goto ok
+ ${EndIf}
+ !endif
+
+ !ifdef SUPPORTS_ARM64
+ ${if} ${IsNativeARM64}
+ Goto ok
+ ${EndIf}
+ !endif
+
+ IfSilent silentArch notSilentArch
+ silentArch:
+ SetErrorLevel 65
+ Abort
+ notSilentArch:
+ MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
+ Quit
+ ${else}
+ IfSilent silentWin notSilentWin
+ silentWin:
+ SetErrorLevel 64
+ Abort
+ notSilentWin:
+ MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
+ Quit
+ ${EndIf}
+
+ ok:
+!macroend
+
+!macro wails.files
+ !ifdef SUPPORTS_AMD64
+ ${if} ${IsNativeAMD64}
+ File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
+ ${EndIf}
+ !endif
+
+ !ifdef SUPPORTS_ARM64
+ ${if} ${IsNativeARM64}
+ File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
+ ${EndIf}
+ !endif
+!macroend
+
+!macro wails.writeUninstaller
+ WriteUninstaller "$INSTDIR\uninstall.exe"
+
+ SetRegView 64
+ WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
+ WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
+ WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
+ WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
+ WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
+ WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
+
+ ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
+ IntFmt $0 "0x%08X" $0
+ WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
+!macroend
+
+!macro wails.deleteUninstaller
+ Delete "$INSTDIR\uninstall.exe"
+
+ SetRegView 64
+ DeleteRegKey HKLM "${UNINST_KEY}"
+!macroend
+
+!macro wails.setShellContext
+ ${If} ${REQUEST_EXECUTION_LEVEL} == "admin"
+ SetShellVarContext all
+ ${else}
+ SetShellVarContext current
+ ${EndIf}
+!macroend
+
+# Install webview2 by launching the bootstrapper
+# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
+!macro wails.webview2runtime
+ !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
+ !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
+ !endif
+
+ SetRegView 64
+ # If the admin key exists and is not empty then webview2 is already installed
+ ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
+ ${If} $0 != ""
+ Goto ok
+ ${EndIf}
+
+ ${If} ${REQUEST_EXECUTION_LEVEL} == "user"
+ # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
+ ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
+ ${If} $0 != ""
+ Goto ok
+ ${EndIf}
+ ${EndIf}
+
+ SetDetailsPrint both
+ DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
+ SetDetailsPrint listonly
+
+ InitPluginsDir
+ CreateDirectory "$pluginsdir\webview2bootstrapper"
+ SetOutPath "$pluginsdir\webview2bootstrapper"
+ File "tmp\MicrosoftEdgeWebview2Setup.exe"
+ ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
+
+ SetDetailsPrint both
+ ok:
+!macroend
+
+# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
+!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_UNASSOCIATE EXT FILECLASS
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
+
+ DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
+!macroend
+
+!macro wails.associateFiles
+ ; Create file associations
+ {{range .Info.FileAssociations}}
+ !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
+
+ File "..\{{.IconName}}.ico"
+ {{end}}
+!macroend
+
+!macro wails.unassociateFiles
+ ; Delete app associations
+ {{range .Info.FileAssociations}}
+ !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
+
+ Delete "$INSTDIR\{{.IconName}}.ico"
+ {{end}}
+!macroend
+
+!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
+ DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
+!macroend
+
+!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
+ DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
+!macroend
+
+!macro wails.associateCustomProtocols
+ ; Create custom protocols associations
+ {{range .Info.Protocols}}
+ !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
+
+ {{end}}
+!macroend
+
+!macro wails.unassociateCustomProtocols
+ ; Delete app custom protocol associations
+ {{range .Info.Protocols}}
+ !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}"
+ {{end}}
+!macroend
diff --git a/v2/examples/systray/build/windows/wails.exe.manifest b/v2/examples/dragdrop-test/build/windows/wails.exe.manifest
similarity index 100%
rename from v2/examples/systray/build/windows/wails.exe.manifest
rename to v2/examples/dragdrop-test/build/windows/wails.exe.manifest
diff --git a/v2/examples/dragdrop-test/frontend/index.html b/v2/examples/dragdrop-test/frontend/index.html
new file mode 100644
index 000000000..4010f1be6
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ dragdrop-test
+
+
+
+
+
+
diff --git a/v2/examples/dragdrop-test/frontend/package-lock.json b/v2/examples/dragdrop-test/frontend/package-lock.json
new file mode 100644
index 000000000..8eed5313c
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/package-lock.json
@@ -0,0 +1,653 @@
+{
+ "name": "frontend",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "frontend",
+ "version": "0.0.0",
+ "devDependencies": {
+ "vite": "^3.0.7"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "2.79.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
+ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/vite": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz",
+ "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.15.9",
+ "postcss": "^8.4.18",
+ "resolve": "^1.22.1",
+ "rollup": "^2.79.1"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/v2/examples/dragdrop-test/frontend/package.json b/v2/examples/dragdrop-test/frontend/package.json
new file mode 100644
index 000000000..a1b6f8e1a
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "frontend",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "vite": "^3.0.7"
+ }
+}
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/frontend/src/app.css b/v2/examples/dragdrop-test/frontend/src/app.css
new file mode 100644
index 000000000..1d3b595bc
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/src/app.css
@@ -0,0 +1,229 @@
+/* #app styles are in style.css to avoid conflicts */
+
+.compact-container {
+ display: flex;
+ gap: 15px;
+ margin: 15px 0;
+ justify-content: center;
+ align-items: flex-start;
+}
+
+.drag-source {
+ background: white;
+ border: 2px solid #5c6bc0;
+ padding: 12px;
+ min-width: 140px;
+ border-radius: 6px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+
+.drag-source h4 {
+ color: #3949ab;
+ margin: 0 0 8px 0;
+ font-size: 14px;
+}
+
+.draggable {
+ background: #f5f5f5;
+ color: #1a1a1a;
+ padding: 8px;
+ margin: 6px 0;
+ border-radius: 4px;
+ cursor: move;
+ text-align: center;
+ transition: all 0.3s ease;
+ font-weight: 600;
+ font-size: 14px;
+ border: 2px solid #c5cae9;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+
+.draggable:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+ background: #e8eaf6;
+ border-color: #7986cb;
+}
+
+.draggable.dragging {
+ opacity: 0.5;
+ transform: scale(0.95);
+ background: #c5cae9;
+}
+
+.drop-zone {
+ background: #f8f9fa;
+ border: 2px dashed #9e9e9e;
+ padding: 12px;
+ min-width: 180px;
+ min-height: 120px;
+ border-radius: 6px;
+ transition: all 0.3s ease;
+}
+
+.drop-zone h4 {
+ color: #5c6bc0;
+ margin: 0 0 8px 0;
+ font-size: 14px;
+}
+
+.drop-zone.drag-over {
+ background: #e3f2fd;
+ border-color: #2196F3;
+ transform: scale(1.02);
+ box-shadow: 0 4px 12px rgba(33, 150, 243, 0.2);
+}
+
+.file-drop-zone {
+ background: #fff8e1;
+ border: 2px dashed #ffc107;
+ padding: 12px;
+ min-width: 180px;
+ min-height: 120px;
+ border-radius: 6px;
+ transition: all 0.3s ease;
+}
+
+.file-drop-zone h4 {
+ color: #f57c00;
+ margin: 0 0 8px 0;
+ font-size: 14px;
+}
+
+.file-drop-zone.drag-over {
+ background: #fff3cd;
+ border-color: #ff9800;
+ transform: scale(1.02);
+ box-shadow: 0 4px 12px rgba(255, 152, 0, 0.2);
+}
+
+.dropped-item {
+ background: linear-gradient(135deg, #42a5f5 0%, #66bb6a 100%);
+ color: white;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ border-radius: 4px;
+ text-align: center;
+ animation: slideIn 0.3s ease;
+ display: inline-block;
+ font-weight: 500;
+ font-size: 13px;
+}
+
+.dropped-file {
+ background: #fff;
+ border: 2px solid #ff9800;
+ color: #333;
+ padding: 6px 8px;
+ margin: 4px 0;
+ border-radius: 4px;
+ text-align: left;
+ animation: slideIn 0.3s ease;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ font-size: 13px;
+}
+
+#dropMessage, #fileDropMessage {
+ font-size: 12px;
+ color: #666;
+ margin: 4px 0;
+}
+
+@keyframes slideIn {
+ from {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.status {
+ margin: 15px auto;
+ max-width: 1000px;
+ padding: 12px;
+ background: #2c3e50;
+ border-radius: 6px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+
+.status h4 {
+ color: white;
+ margin: 0 0 8px 0;
+ font-size: 14px;
+}
+
+#eventLog {
+ background: #1a1a1a;
+ padding: 10px;
+ border-radius: 4px;
+ max-height: 200px;
+ overflow-y: auto;
+ font-family: 'Courier New', monospace;
+ text-align: left;
+ font-size: 12px;
+}
+
+.log-entry {
+ padding: 4px 8px;
+ font-size: 13px;
+ margin: 2px 0;
+ border-radius: 3px;
+}
+
+.log-entry.drag-start {
+ color: #81c784;
+ background: rgba(129, 199, 132, 0.1);
+}
+
+.log-entry.drag-over {
+ color: #64b5f6;
+ background: rgba(100, 181, 246, 0.1);
+}
+
+.log-entry.drag-enter {
+ color: #ffb74d;
+ background: rgba(255, 183, 77, 0.1);
+}
+
+.log-entry.drag-leave {
+ color: #ba68c8;
+ background: rgba(186, 104, 200, 0.1);
+}
+
+.log-entry.drop {
+ color: #e57373;
+ background: rgba(229, 115, 115, 0.1);
+ font-weight: bold;
+}
+
+.log-entry.drag-end {
+ color: #90a4ae;
+ background: rgba(144, 164, 174, 0.1);
+}
+
+.log-entry.file-drop {
+ color: #ffc107;
+ background: rgba(255, 193, 7, 0.1);
+ font-weight: bold;
+}
+
+.log-entry.page-loaded {
+ color: #4caf50;
+ background: rgba(76, 175, 80, 0.1);
+}
+
+.log-entry.wails-status {
+ color: #00bcd4;
+ background: rgba(0, 188, 212, 0.1);
+}
+
+h1 {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ font-size: 1.8em;
+ margin: 10px 0 8px 0;
+}
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/frontend/src/assets/fonts/OFL.txt b/v2/examples/dragdrop-test/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/src/assets/fonts/OFL.txt
@@ -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.
diff --git a/v2/examples/dragdrop-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/examples/dragdrop-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/examples/dragdrop-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/examples/dragdrop-test/frontend/src/assets/images/logo-universal.png b/v2/examples/dragdrop-test/frontend/src/assets/images/logo-universal.png
new file mode 100644
index 000000000..d63303bfa
Binary files /dev/null and b/v2/examples/dragdrop-test/frontend/src/assets/images/logo-universal.png differ
diff --git a/v2/examples/dragdrop-test/frontend/src/main.js b/v2/examples/dragdrop-test/frontend/src/main.js
new file mode 100644
index 000000000..60d76ac0f
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/src/main.js
@@ -0,0 +1,231 @@
+import './style.css';
+import './app.css';
+
+// CRITICAL: Register global handlers IMMEDIATELY to prevent file drops from opening new windows
+// This must be done as early as possible, before any other code runs
+(function() {
+ // Helper function to check if drag event contains files
+ function isFileDrop(e) {
+ return e.dataTransfer && e.dataTransfer.types &&
+ (e.dataTransfer.types.includes('Files') ||
+ Array.from(e.dataTransfer.types).includes('Files'));
+ }
+
+ // Global dragover handler - MUST prevent default for file drops
+ window.addEventListener('dragover', function(e) {
+ if (isFileDrop(e)) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ }, true); // Use capture phase to handle before any other handlers
+
+ // Global drop handler - MUST prevent default for file drops
+ window.addEventListener('drop', function(e) {
+ if (isFileDrop(e)) {
+ e.preventDefault();
+ console.log('Global handler prevented file drop navigation');
+ }
+ }, true); // Use capture phase to handle before any other handlers
+
+ // Global dragleave handler
+ window.addEventListener('dragleave', function(e) {
+ if (isFileDrop(e)) {
+ e.preventDefault();
+ }
+ }, true); // Use capture phase
+
+ console.log('Global file drop prevention handlers registered');
+})();
+
+document.querySelector('#app').innerHTML = `
+ Wails Drag & Drop Test
+
+
+
+
HTML5 Source
+
Item 1
+
Item 2
+
Item 3
+
+
+
+
HTML5 Drop
+
Drop here
+
+
+
+
File Drop
+
Drop files here
+
+
+
+
+`;
+
+// Get all draggable items and drop zones
+const draggables = document.querySelectorAll('.draggable');
+const dropZone = document.getElementById('dropZone');
+const fileDropZone = document.getElementById('fileDropZone');
+const eventLog = document.getElementById('eventLog');
+const dropMessage = document.getElementById('dropMessage');
+const fileDropMessage = document.getElementById('fileDropMessage');
+
+let draggedItem = null;
+let eventCounter = 0;
+
+// Function to log events
+function logEvent(eventName, details = '') {
+ eventCounter++;
+ const timestamp = new Date().toLocaleTimeString();
+ const logEntry = document.createElement('div');
+ logEntry.className = `log-entry ${eventName.replace(' ', '-').toLowerCase()}`;
+ logEntry.textContent = `[${timestamp}] ${eventCounter}. ${eventName} ${details}`;
+ eventLog.insertBefore(logEntry, eventLog.firstChild);
+
+ // Keep only last 20 events
+ while (eventLog.children.length > 20) {
+ eventLog.removeChild(eventLog.lastChild);
+ }
+
+ console.log(`Event: ${eventName} ${details}`);
+}
+
+// Add event listeners to draggable items
+draggables.forEach(item => {
+ // Drag start
+ item.addEventListener('dragstart', (e) => {
+ draggedItem = e.target;
+ e.target.classList.add('dragging');
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', e.target.dataset.item);
+ logEvent('drag-start', `- Started dragging: ${e.target.dataset.item}`);
+ });
+
+ // Drag end
+ item.addEventListener('dragend', (e) => {
+ e.target.classList.remove('dragging');
+ logEvent('drag-end', `- Ended dragging: ${e.target.dataset.item}`);
+ });
+});
+
+// Add event listeners to HTML drop zone
+dropZone.addEventListener('dragenter', (e) => {
+ e.preventDefault();
+ dropZone.classList.add('drag-over');
+ logEvent('drag-enter', '- Entered HTML drop zone');
+});
+
+dropZone.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ // Don't log every dragover to avoid spam
+});
+
+dropZone.addEventListener('dragleave', (e) => {
+ if (e.target === dropZone) {
+ dropZone.classList.remove('drag-over');
+ logEvent('drag-leave', '- Left HTML drop zone');
+ }
+});
+
+dropZone.addEventListener('drop', (e) => {
+ e.preventDefault();
+ dropZone.classList.remove('drag-over');
+
+ const data = e.dataTransfer.getData('text/plain');
+ logEvent('drop', `- Dropped in HTML zone: ${data}`);
+
+ if (draggedItem) {
+ // Create a copy of the dragged item
+ const droppedElement = document.createElement('div');
+ droppedElement.className = 'dropped-item';
+ droppedElement.textContent = data;
+
+ // Remove the placeholder message if it exists
+ if (dropMessage) {
+ dropMessage.style.display = 'none';
+ }
+
+ dropZone.appendChild(droppedElement);
+ }
+
+ draggedItem = null;
+});
+
+// Add event listeners to file drop zone
+fileDropZone.addEventListener('dragenter', (e) => {
+ e.preventDefault();
+ fileDropZone.classList.add('drag-over');
+ logEvent('drag-enter', '- Entered file drop zone');
+});
+
+fileDropZone.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+});
+
+fileDropZone.addEventListener('dragleave', (e) => {
+ if (e.target === fileDropZone) {
+ fileDropZone.classList.remove('drag-over');
+ logEvent('drag-leave', '- Left file drop zone');
+ }
+});
+
+fileDropZone.addEventListener('drop', (e) => {
+ e.preventDefault();
+ fileDropZone.classList.remove('drag-over');
+
+ const files = [...e.dataTransfer.files];
+ if (files.length > 0) {
+ logEvent('file-drop', `- Dropped ${files.length} file(s)`);
+
+ // Hide the placeholder message
+ if (fileDropMessage) {
+ fileDropMessage.style.display = 'none';
+ }
+
+ // Display dropped files
+ files.forEach(file => {
+ const fileElement = document.createElement('div');
+ fileElement.className = 'dropped-file';
+
+ // Format file size
+ let size = file.size;
+ let unit = 'bytes';
+ if (size > 1024 * 1024) {
+ size = (size / (1024 * 1024)).toFixed(2);
+ unit = 'MB';
+ } else if (size > 1024) {
+ size = (size / 1024).toFixed(2);
+ unit = 'KB';
+ }
+
+ fileElement.textContent = `📄 ${file.name} (${size} ${unit})`;
+ fileDropZone.appendChild(fileElement);
+ });
+ }
+});
+
+// Log when page loads
+window.addEventListener('DOMContentLoaded', () => {
+ logEvent('page-loaded', '- Wails drag-and-drop test page ready');
+ console.log('Wails Drag and Drop test application loaded');
+
+ // Check if Wails drag and drop is enabled
+ if (window.wails && window.wails.flags) {
+ logEvent('wails-status', `- Wails DnD enabled: ${window.wails.flags.enableWailsDragAndDrop}`);
+ }
+
+ // IMPORTANT: Register Wails drag-and-drop handlers to prevent browser navigation
+ // This will ensure external files don't open in new windows when dropped anywhere
+ if (window.runtime && window.runtime.OnFileDrop) {
+ window.runtime.OnFileDrop((x, y, paths) => {
+ logEvent('wails-file-drop', `- Wails received ${paths.length} file(s) at (${x}, ${y})`);
+ console.log('Wails OnFileDrop:', paths);
+ }, false); // false = don't require drop target, handle all file drops
+ logEvent('wails-setup', '- Wails OnFileDrop handlers registered');
+ }
+});
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/frontend/src/style.css b/v2/examples/dragdrop-test/frontend/src/style.css
new file mode 100644
index 000000000..f5d071597
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/src/style.css
@@ -0,0 +1,33 @@
+html {
+ background-color: rgba(27, 38, 54, 1);
+ text-align: center;
+ color: white;
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ margin: 0;
+ color: white;
+ font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
+ "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ height: 100%;
+ overflow: hidden;
+}
+
+@font-face {
+ font-family: "Nunito";
+ font-style: normal;
+ font-weight: 400;
+ src: local(""),
+ url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
+}
+
+#app {
+ height: 100vh;
+ text-align: center;
+ overflow: hidden;
+ box-sizing: border-box;
+ padding: 10px;
+}
diff --git a/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.d.ts b/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.d.ts
new file mode 100644
index 000000000..02a3bb988
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.d.ts
@@ -0,0 +1,4 @@
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function Greet(arg1:string):Promise;
diff --git a/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.js b/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.js
new file mode 100644
index 000000000..c71ae77cb
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/wailsjs/go/main/App.js
@@ -0,0 +1,7 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function Greet(arg1) {
+ return window['go']['main']['App']['Greet'](arg1);
+}
diff --git a/v2/examples/dragdrop-test/frontend/wailsjs/runtime/package.json b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/package.json
new file mode 100644
index 000000000..1e7c8a5d7
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@wailsapp/runtime",
+ "version": "2.0.0",
+ "description": "Wails Javascript runtime library",
+ "main": "runtime.js",
+ "types": "runtime.d.ts",
+ "scripts": {
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/wailsapp/wails.git"
+ },
+ "keywords": [
+ "Wails",
+ "Javascript",
+ "Go"
+ ],
+ "author": "Lea Anthony ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/wailsapp/wails/issues"
+ },
+ "homepage": "https://github.com/wailsapp/wails#readme"
+}
diff --git a/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.d.ts b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.d.ts
new file mode 100644
index 000000000..4445dac21
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.d.ts
@@ -0,0 +1,249 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export interface Position {
+ x: number;
+ y: number;
+}
+
+export interface Size {
+ w: number;
+ h: number;
+}
+
+export interface Screen {
+ isCurrent: boolean;
+ isPrimary: boolean;
+ width : number
+ height : number
+}
+
+// Environment information such as platform, buildtype, ...
+export interface EnvironmentInfo {
+ buildType: string;
+ platform: string;
+ arch: string;
+}
+
+// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
+// emits the given event. Optional data may be passed with the event.
+// This will trigger any event listeners.
+export function EventsEmit(eventName: string, ...data: any): void;
+
+// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
+export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
+// sets up a listener for the given event name, but will only trigger a given number times.
+export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
+
+// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
+// sets up a listener for the given event name, but will only trigger once.
+export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
+// unregisters the listener for the given event name.
+export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
+
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all listeners.
+export function EventsOffAll(): void;
+
+// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
+// logs the given message as a raw message
+export function LogPrint(message: string): void;
+
+// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
+// logs the given message at the `trace` log level.
+export function LogTrace(message: string): void;
+
+// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
+// logs the given message at the `debug` log level.
+export function LogDebug(message: string): void;
+
+// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
+// logs the given message at the `error` log level.
+export function LogError(message: string): void;
+
+// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
+// logs the given message at the `fatal` log level.
+// The application will quit after calling this method.
+export function LogFatal(message: string): void;
+
+// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
+// logs the given message at the `info` log level.
+export function LogInfo(message: string): void;
+
+// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
+// logs the given message at the `warning` log level.
+export function LogWarning(message: string): void;
+
+// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
+// Forces a reload by the main application as well as connected browsers.
+export function WindowReload(): void;
+
+// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
+// Reloads the application frontend.
+export function WindowReloadApp(): void;
+
+// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
+// Sets the window AlwaysOnTop or not on top.
+export function WindowSetAlwaysOnTop(b: boolean): void;
+
+// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
+// *Windows only*
+// Sets window theme to system default (dark/light).
+export function WindowSetSystemDefaultTheme(): void;
+
+// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
+// *Windows only*
+// Sets window to light theme.
+export function WindowSetLightTheme(): void;
+
+// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
+// *Windows only*
+// Sets window to dark theme.
+export function WindowSetDarkTheme(): void;
+
+// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
+// Centers the window on the monitor the window is currently on.
+export function WindowCenter(): void;
+
+// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
+// Sets the text in the window title bar.
+export function WindowSetTitle(title: string): void;
+
+// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
+// Makes the window full screen.
+export function WindowFullscreen(): void;
+
+// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
+// Restores the previous window dimensions and position prior to full screen.
+export function WindowUnfullscreen(): void;
+
+// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
+// Returns the state of the window, i.e. whether the window is in full screen mode or not.
+export function WindowIsFullscreen(): Promise;
+
+// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
+// Sets the width and height of the window.
+export function WindowSetSize(width: number, height: number): void;
+
+// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
+// Gets the width and height of the window.
+export function WindowGetSize(): Promise;
+
+// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
+// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMaxSize(width: number, height: number): void;
+
+// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
+// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMinSize(width: number, height: number): void;
+
+// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
+// Sets the window position relative to the monitor the window is currently on.
+export function WindowSetPosition(x: number, y: number): void;
+
+// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
+// Gets the window position relative to the monitor the window is currently on.
+export function WindowGetPosition(): Promise;
+
+// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
+// Hides the window.
+export function WindowHide(): void;
+
+// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
+// Shows the window, if it is currently hidden.
+export function WindowShow(): void;
+
+// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
+// Maximises the window to fill the screen.
+export function WindowMaximise(): void;
+
+// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
+// Toggles between Maximised and UnMaximised.
+export function WindowToggleMaximise(): void;
+
+// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
+// Restores the window to the dimensions and position prior to maximising.
+export function WindowUnmaximise(): void;
+
+// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
+// Returns the state of the window, i.e. whether the window is maximised or not.
+export function WindowIsMaximised(): Promise;
+
+// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
+// Minimises the window.
+export function WindowMinimise(): void;
+
+// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
+// Restores the window to the dimensions and position prior to minimising.
+export function WindowUnminimise(): void;
+
+// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
+// Returns the state of the window, i.e. whether the window is minimised or not.
+export function WindowIsMinimised(): Promise;
+
+// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
+// Returns the state of the window, i.e. whether the window is normal or not.
+export function WindowIsNormal(): Promise;
+
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
+// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
+
+// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
+// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
+export function ScreenGetAll(): Promise;
+
+// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
+// Opens the given URL in the system browser.
+export function BrowserOpenURL(url: string): void;
+
+// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
+// Returns information about the environment
+export function Environment(): Promise;
+
+// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
+// Quits the application.
+export function Quit(): void;
+
+// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
+// Hides the application.
+export function Hide(): void;
+
+// [Show](https://wails.io/docs/reference/runtime/intro#show)
+// Shows the application.
+export function Show(): void;
+
+// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
+// Returns the current text stored on clipboard
+export function ClipboardGetText(): Promise;
+
+// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
+// Sets a text on the clipboard
+export function ClipboardSetText(text: string): Promise;
+
+// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
+// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
+
+// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
+// OnFileDropOff removes the drag and drop listeners and handlers.
+export function OnFileDropOff() :void
+
+// Check if the file path resolver is available
+export function CanResolveFilePaths(): boolean;
+
+// Resolves file paths for an array of files
+export function ResolveFilePaths(files: File[]): void
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.js b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.js
new file mode 100644
index 000000000..7cb89d750
--- /dev/null
+++ b/v2/examples/dragdrop-test/frontend/wailsjs/runtime/runtime.js
@@ -0,0 +1,242 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export function LogPrint(message) {
+ window.runtime.LogPrint(message);
+}
+
+export function LogTrace(message) {
+ window.runtime.LogTrace(message);
+}
+
+export function LogDebug(message) {
+ window.runtime.LogDebug(message);
+}
+
+export function LogInfo(message) {
+ window.runtime.LogInfo(message);
+}
+
+export function LogWarning(message) {
+ window.runtime.LogWarning(message);
+}
+
+export function LogError(message) {
+ window.runtime.LogError(message);
+}
+
+export function LogFatal(message) {
+ window.runtime.LogFatal(message);
+}
+
+export function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
+}
+
+export function EventsOn(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, -1);
+}
+
+export function EventsOff(eventName, ...additionalEventNames) {
+ return window.runtime.EventsOff(eventName, ...additionalEventNames);
+}
+
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
+export function EventsOnce(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, 1);
+}
+
+export function EventsEmit(eventName) {
+ let args = [eventName].slice.call(arguments);
+ return window.runtime.EventsEmit.apply(null, args);
+}
+
+export function WindowReload() {
+ window.runtime.WindowReload();
+}
+
+export function WindowReloadApp() {
+ window.runtime.WindowReloadApp();
+}
+
+export function WindowSetAlwaysOnTop(b) {
+ window.runtime.WindowSetAlwaysOnTop(b);
+}
+
+export function WindowSetSystemDefaultTheme() {
+ window.runtime.WindowSetSystemDefaultTheme();
+}
+
+export function WindowSetLightTheme() {
+ window.runtime.WindowSetLightTheme();
+}
+
+export function WindowSetDarkTheme() {
+ window.runtime.WindowSetDarkTheme();
+}
+
+export function WindowCenter() {
+ window.runtime.WindowCenter();
+}
+
+export function WindowSetTitle(title) {
+ window.runtime.WindowSetTitle(title);
+}
+
+export function WindowFullscreen() {
+ window.runtime.WindowFullscreen();
+}
+
+export function WindowUnfullscreen() {
+ window.runtime.WindowUnfullscreen();
+}
+
+export function WindowIsFullscreen() {
+ return window.runtime.WindowIsFullscreen();
+}
+
+export function WindowGetSize() {
+ return window.runtime.WindowGetSize();
+}
+
+export function WindowSetSize(width, height) {
+ window.runtime.WindowSetSize(width, height);
+}
+
+export function WindowSetMaxSize(width, height) {
+ window.runtime.WindowSetMaxSize(width, height);
+}
+
+export function WindowSetMinSize(width, height) {
+ window.runtime.WindowSetMinSize(width, height);
+}
+
+export function WindowSetPosition(x, y) {
+ window.runtime.WindowSetPosition(x, y);
+}
+
+export function WindowGetPosition() {
+ return window.runtime.WindowGetPosition();
+}
+
+export function WindowHide() {
+ window.runtime.WindowHide();
+}
+
+export function WindowShow() {
+ window.runtime.WindowShow();
+}
+
+export function WindowMaximise() {
+ window.runtime.WindowMaximise();
+}
+
+export function WindowToggleMaximise() {
+ window.runtime.WindowToggleMaximise();
+}
+
+export function WindowUnmaximise() {
+ window.runtime.WindowUnmaximise();
+}
+
+export function WindowIsMaximised() {
+ return window.runtime.WindowIsMaximised();
+}
+
+export function WindowMinimise() {
+ window.runtime.WindowMinimise();
+}
+
+export function WindowUnminimise() {
+ window.runtime.WindowUnminimise();
+}
+
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
+}
+
+export function ScreenGetAll() {
+ return window.runtime.ScreenGetAll();
+}
+
+export function WindowIsMinimised() {
+ return window.runtime.WindowIsMinimised();
+}
+
+export function WindowIsNormal() {
+ return window.runtime.WindowIsNormal();
+}
+
+export function BrowserOpenURL(url) {
+ window.runtime.BrowserOpenURL(url);
+}
+
+export function Environment() {
+ return window.runtime.Environment();
+}
+
+export function Quit() {
+ window.runtime.Quit();
+}
+
+export function Hide() {
+ window.runtime.Hide();
+}
+
+export function Show() {
+ window.runtime.Show();
+}
+
+export function ClipboardGetText() {
+ return window.runtime.ClipboardGetText();
+}
+
+export function ClipboardSetText(text) {
+ return window.runtime.ClipboardSetText(text);
+}
+
+/**
+ * Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ *
+ * @export
+ * @callback OnFileDropCallback
+ * @param {number} x - x coordinate of the drop
+ * @param {number} y - y coordinate of the drop
+ * @param {string[]} paths - A list of file paths.
+ */
+
+/**
+ * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+ *
+ * @export
+ * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
+ */
+export function OnFileDrop(callback, useDropTarget) {
+ return window.runtime.OnFileDrop(callback, useDropTarget);
+}
+
+/**
+ * OnFileDropOff removes the drag and drop listeners and handlers.
+ */
+export function OnFileDropOff() {
+ return window.runtime.OnFileDropOff();
+}
+
+export function CanResolveFilePaths() {
+ return window.runtime.CanResolveFilePaths();
+}
+
+export function ResolveFilePaths(files) {
+ return window.runtime.ResolveFilePaths(files);
+}
\ No newline at end of file
diff --git a/v2/examples/dragdrop-test/go.mod b/v2/examples/dragdrop-test/go.mod
new file mode 100644
index 000000000..be13aac19
--- /dev/null
+++ b/v2/examples/dragdrop-test/go.mod
@@ -0,0 +1,37 @@
+module dragdrop-test
+
+go 1.23
+
+require github.com/wailsapp/wails/v2 v2.10.1
+
+require (
+ github.com/bep/debounce v1.2.1 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/websocket v1.5.3 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/labstack/echo/v4 v4.13.3 // indirect
+ github.com/labstack/gommon v0.4.2 // indirect
+ github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
+ github.com/leaanthony/gosod v1.0.4 // indirect
+ github.com/leaanthony/slicer v1.6.0 // indirect
+ github.com/leaanthony/u v1.1.1 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/samber/lo v1.49.1 // indirect
+ github.com/tkrajina/go-reflector v0.5.8 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasttemplate v1.2.2 // indirect
+ github.com/wailsapp/go-webview2 v1.0.22 // indirect
+ github.com/wailsapp/mimetype v1.4.1 // indirect
+ golang.org/x/crypto v0.33.0 // indirect
+ golang.org/x/net v0.35.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
+)
+
+replace github.com/wailsapp/wails/v2 => E:/releases/wails/v2
diff --git a/v2/examples/dragdrop-test/go.sum b/v2/examples/dragdrop-test/go.sum
new file mode 100644
index 000000000..10d4a9b18
--- /dev/null
+++ b/v2/examples/dragdrop-test/go.sum
@@ -0,0 +1,79 @@
+github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
+github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
+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/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
+github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
+github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
+github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
+github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
+github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
+github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI=
+github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw=
+github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
+github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
+github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
+github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
+github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
+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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
+github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
+github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6NZijQ58=
+github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
+github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
+github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
+golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
+golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
+golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/v2/examples/dragdrop-test/main.go b/v2/examples/dragdrop-test/main.go
new file mode 100644
index 000000000..64a0c2734
--- /dev/null
+++ b/v2/examples/dragdrop-test/main.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "embed"
+
+ "github.com/wailsapp/wails/v2"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
+)
+
+//go:embed all:frontend/dist
+var assets embed.FS
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "Wails Drag & Drop Test",
+ Width: 800,
+ Height: 600,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
+ Bind: []interface{}{
+ app,
+ },
+ })
+
+ if err != nil {
+ println("Error:", err.Error())
+ }
+}
diff --git a/v2/examples/dragdrop-test/wails.json b/v2/examples/dragdrop-test/wails.json
new file mode 100644
index 000000000..7970ea4ca
--- /dev/null
+++ b/v2/examples/dragdrop-test/wails.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://wails.io/schemas/config.v2.json",
+ "name": "dragdrop-test",
+ "outputfilename": "dragdrop-test",
+ "frontend:install": "npm install",
+ "frontend:build": "npm run build",
+ "frontend:dev:watcher": "npm run dev",
+ "frontend:dev:serverUrl": "auto",
+ "author": {
+ "name": "Lea Anthony",
+ "email": "lea.anthony@gmail.com"
+ }
+}
diff --git a/v2/examples/panic-recovery-test/README.md b/v2/examples/panic-recovery-test/README.md
new file mode 100644
index 000000000..c0a6a7e5a
--- /dev/null
+++ b/v2/examples/panic-recovery-test/README.md
@@ -0,0 +1,76 @@
+# Panic Recovery Test
+
+This example demonstrates the Linux signal handler issue (#3965) and verifies the fix using `runtime.ResetSignalHandlers()`.
+
+## The Problem
+
+On Linux, WebKit installs signal handlers without the `SA_ONSTACK` flag, which prevents Go from recovering panics caused by nil pointer dereferences (SIGSEGV). Without the fix, the application crashes with:
+
+```
+signal 11 received but handler not on signal stack
+fatal error: non-Go code set up signal handler without SA_ONSTACK flag
+```
+
+## The Solution
+
+Call `runtime.ResetSignalHandlers()` immediately before code that might panic:
+
+```go
+import "github.com/wailsapp/wails/v2/pkg/runtime"
+
+go func() {
+ defer func() {
+ if err := recover(); err != nil {
+ log.Printf("Recovered: %v", err)
+ }
+ }()
+ runtime.ResetSignalHandlers()
+ // Code that might panic...
+}()
+```
+
+## How to Reproduce
+
+### Prerequisites
+
+- Linux with WebKit2GTK 4.1 installed
+- Go 1.21+
+- Wails CLI
+
+### Steps
+
+1. Build the example:
+ ```bash
+ cd v2/examples/panic-recovery-test
+ wails build -tags webkit2_41
+ ```
+
+2. Run the application:
+ ```bash
+ ./build/bin/panic-recovery-test
+ ```
+
+3. Wait ~10 seconds (the app auto-calls `Greet` after 5s, then waits another 5s before the nil pointer dereference)
+
+### Expected Result (with fix)
+
+The panic is recovered and you see:
+```
+------------------------------"invalid memory address or nil pointer dereference"
+```
+
+The application continues running.
+
+### Without the fix
+
+Comment out the `runtime.ResetSignalHandlers()` call in `app.go` and rebuild. The application will crash with a fatal signal 11 error.
+
+## Files
+
+- `app.go` - Contains the `Greet` function that demonstrates panic recovery
+- `frontend/src/main.js` - Auto-calls `Greet` after 5 seconds to trigger the test
+
+## Related
+
+- Issue: https://github.com/wailsapp/wails/issues/3965
+- Original fix PR: https://github.com/wailsapp/wails/pull/2152
diff --git a/v2/examples/panic-recovery-test/app.go b/v2/examples/panic-recovery-test/app.go
new file mode 100644
index 000000000..ceb46e8d5
--- /dev/null
+++ b/v2/examples/panic-recovery-test/app.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called when the app starts. The context is saved
+// so we can call the runtime methods
+func (a *App) startup(ctx context.Context) {
+ a.ctx = ctx
+}
+
+// Greet returns a greeting for the given name
+func (a *App) Greet(name string) string {
+ go func() {
+ defer func() {
+ if err := recover(); err != nil {
+ fmt.Printf("------------------------------%#v\n", err)
+ }
+ }()
+ time.Sleep(5 * time.Second)
+ // Fix signal handlers right before potential panic using the Wails runtime
+ runtime.ResetSignalHandlers()
+ // Nil pointer dereference - causes SIGSEGV
+ var t *time.Time
+ fmt.Println(t.Unix())
+ }()
+
+ return fmt.Sprintf("Hello %s, It's show time!", name)
+}
diff --git a/v2/examples/panic-recovery-test/frontend/index.html b/v2/examples/panic-recovery-test/frontend/index.html
new file mode 100644
index 000000000..d7aa4e942
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ panic-test
+
+
+
+
+
+
diff --git a/v2/examples/panic-recovery-test/frontend/package.json b/v2/examples/panic-recovery-test/frontend/package.json
new file mode 100644
index 000000000..a1b6f8e1a
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "frontend",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "vite": "^3.0.7"
+ }
+}
\ No newline at end of file
diff --git a/v2/examples/panic-recovery-test/frontend/src/app.css b/v2/examples/panic-recovery-test/frontend/src/app.css
new file mode 100644
index 000000000..59d06f692
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/src/app.css
@@ -0,0 +1,54 @@
+#logo {
+ display: block;
+ width: 50%;
+ height: 50%;
+ margin: auto;
+ padding: 10% 0 0;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ background-origin: content-box;
+}
+
+.result {
+ height: 20px;
+ line-height: 20px;
+ margin: 1.5rem auto;
+}
+
+.input-box .btn {
+ width: 60px;
+ height: 30px;
+ line-height: 30px;
+ border-radius: 3px;
+ border: none;
+ margin: 0 0 0 20px;
+ padding: 0 8px;
+ cursor: pointer;
+}
+
+.input-box .btn:hover {
+ background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
+ color: #333333;
+}
+
+.input-box .input {
+ border: none;
+ border-radius: 3px;
+ outline: none;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ background-color: rgba(240, 240, 240, 1);
+ -webkit-font-smoothing: antialiased;
+}
+
+.input-box .input:hover {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
+
+.input-box .input:focus {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
\ No newline at end of file
diff --git a/v2/examples/panic-recovery-test/frontend/src/assets/fonts/OFL.txt b/v2/examples/panic-recovery-test/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/src/assets/fonts/OFL.txt
@@ -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.
diff --git a/v2/examples/panic-recovery-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/examples/panic-recovery-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/examples/panic-recovery-test/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/examples/panic-recovery-test/frontend/src/assets/images/logo-universal.png b/v2/examples/panic-recovery-test/frontend/src/assets/images/logo-universal.png
new file mode 100644
index 000000000..d63303bfa
Binary files /dev/null and b/v2/examples/panic-recovery-test/frontend/src/assets/images/logo-universal.png differ
diff --git a/v2/examples/panic-recovery-test/frontend/src/main.js b/v2/examples/panic-recovery-test/frontend/src/main.js
new file mode 100644
index 000000000..ea5e74fc6
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/src/main.js
@@ -0,0 +1,55 @@
+import './style.css';
+import './app.css';
+
+import logo from './assets/images/logo-universal.png';
+import {Greet} from '../wailsjs/go/main/App';
+
+document.querySelector('#app').innerHTML = `
+
+ Please enter your name below 👇
+
+
+ Greet
+
+
+`;
+document.getElementById('logo').src = logo;
+
+let nameElement = document.getElementById("name");
+nameElement.focus();
+let resultElement = document.getElementById("result");
+
+// Setup the greet function
+window.greet = function () {
+ // Get name
+ let name = nameElement.value;
+
+ // Check if the input is empty
+ if (name === "") return;
+
+ // Call App.Greet(name)
+ try {
+ Greet(name)
+ .then((result) => {
+ // Update result with data back from App.Greet()
+ resultElement.innerText = result;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ } catch (err) {
+ console.error(err);
+ }
+};
+
+// Auto-call Greet after 5 seconds to trigger the panic test
+setTimeout(() => {
+ console.log("Auto-calling Greet to trigger panic test...");
+ Greet("PanicTest")
+ .then((result) => {
+ resultElement.innerText = result + " (auto-called - panic will occur in 5s)";
+ })
+ .catch((err) => {
+ console.error("Error:", err);
+ });
+}, 5000);
diff --git a/v2/examples/panic-recovery-test/frontend/src/style.css b/v2/examples/panic-recovery-test/frontend/src/style.css
new file mode 100644
index 000000000..3940d6c63
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/src/style.css
@@ -0,0 +1,26 @@
+html {
+ background-color: rgba(27, 38, 54, 1);
+ text-align: center;
+ color: white;
+}
+
+body {
+ margin: 0;
+ color: white;
+ font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
+ "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+}
+
+@font-face {
+ font-family: "Nunito";
+ font-style: normal;
+ font-weight: 400;
+ src: local(""),
+ url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
+}
+
+#app {
+ height: 100vh;
+ text-align: center;
+}
diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts
new file mode 100755
index 000000000..02a3bb988
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts
@@ -0,0 +1,4 @@
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function Greet(arg1:string):Promise;
diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js
new file mode 100755
index 000000000..c71ae77cb
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js
@@ -0,0 +1,7 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function Greet(arg1) {
+ return window['go']['main']['App']['Greet'](arg1);
+}
diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json
new file mode 100644
index 000000000..1e7c8a5d7
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@wailsapp/runtime",
+ "version": "2.0.0",
+ "description": "Wails Javascript runtime library",
+ "main": "runtime.js",
+ "types": "runtime.d.ts",
+ "scripts": {
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/wailsapp/wails.git"
+ },
+ "keywords": [
+ "Wails",
+ "Javascript",
+ "Go"
+ ],
+ "author": "Lea Anthony ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/wailsapp/wails/issues"
+ },
+ "homepage": "https://github.com/wailsapp/wails#readme"
+}
diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts
new file mode 100644
index 000000000..4445dac21
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts
@@ -0,0 +1,249 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export interface Position {
+ x: number;
+ y: number;
+}
+
+export interface Size {
+ w: number;
+ h: number;
+}
+
+export interface Screen {
+ isCurrent: boolean;
+ isPrimary: boolean;
+ width : number
+ height : number
+}
+
+// Environment information such as platform, buildtype, ...
+export interface EnvironmentInfo {
+ buildType: string;
+ platform: string;
+ arch: string;
+}
+
+// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
+// emits the given event. Optional data may be passed with the event.
+// This will trigger any event listeners.
+export function EventsEmit(eventName: string, ...data: any): void;
+
+// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
+export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
+// sets up a listener for the given event name, but will only trigger a given number times.
+export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
+
+// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
+// sets up a listener for the given event name, but will only trigger once.
+export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
+// unregisters the listener for the given event name.
+export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
+
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all listeners.
+export function EventsOffAll(): void;
+
+// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
+// logs the given message as a raw message
+export function LogPrint(message: string): void;
+
+// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
+// logs the given message at the `trace` log level.
+export function LogTrace(message: string): void;
+
+// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
+// logs the given message at the `debug` log level.
+export function LogDebug(message: string): void;
+
+// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
+// logs the given message at the `error` log level.
+export function LogError(message: string): void;
+
+// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
+// logs the given message at the `fatal` log level.
+// The application will quit after calling this method.
+export function LogFatal(message: string): void;
+
+// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
+// logs the given message at the `info` log level.
+export function LogInfo(message: string): void;
+
+// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
+// logs the given message at the `warning` log level.
+export function LogWarning(message: string): void;
+
+// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
+// Forces a reload by the main application as well as connected browsers.
+export function WindowReload(): void;
+
+// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
+// Reloads the application frontend.
+export function WindowReloadApp(): void;
+
+// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
+// Sets the window AlwaysOnTop or not on top.
+export function WindowSetAlwaysOnTop(b: boolean): void;
+
+// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
+// *Windows only*
+// Sets window theme to system default (dark/light).
+export function WindowSetSystemDefaultTheme(): void;
+
+// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
+// *Windows only*
+// Sets window to light theme.
+export function WindowSetLightTheme(): void;
+
+// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
+// *Windows only*
+// Sets window to dark theme.
+export function WindowSetDarkTheme(): void;
+
+// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
+// Centers the window on the monitor the window is currently on.
+export function WindowCenter(): void;
+
+// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
+// Sets the text in the window title bar.
+export function WindowSetTitle(title: string): void;
+
+// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
+// Makes the window full screen.
+export function WindowFullscreen(): void;
+
+// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
+// Restores the previous window dimensions and position prior to full screen.
+export function WindowUnfullscreen(): void;
+
+// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
+// Returns the state of the window, i.e. whether the window is in full screen mode or not.
+export function WindowIsFullscreen(): Promise;
+
+// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
+// Sets the width and height of the window.
+export function WindowSetSize(width: number, height: number): void;
+
+// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
+// Gets the width and height of the window.
+export function WindowGetSize(): Promise;
+
+// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
+// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMaxSize(width: number, height: number): void;
+
+// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
+// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMinSize(width: number, height: number): void;
+
+// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
+// Sets the window position relative to the monitor the window is currently on.
+export function WindowSetPosition(x: number, y: number): void;
+
+// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
+// Gets the window position relative to the monitor the window is currently on.
+export function WindowGetPosition(): Promise;
+
+// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
+// Hides the window.
+export function WindowHide(): void;
+
+// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
+// Shows the window, if it is currently hidden.
+export function WindowShow(): void;
+
+// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
+// Maximises the window to fill the screen.
+export function WindowMaximise(): void;
+
+// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
+// Toggles between Maximised and UnMaximised.
+export function WindowToggleMaximise(): void;
+
+// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
+// Restores the window to the dimensions and position prior to maximising.
+export function WindowUnmaximise(): void;
+
+// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
+// Returns the state of the window, i.e. whether the window is maximised or not.
+export function WindowIsMaximised(): Promise;
+
+// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
+// Minimises the window.
+export function WindowMinimise(): void;
+
+// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
+// Restores the window to the dimensions and position prior to minimising.
+export function WindowUnminimise(): void;
+
+// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
+// Returns the state of the window, i.e. whether the window is minimised or not.
+export function WindowIsMinimised(): Promise;
+
+// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
+// Returns the state of the window, i.e. whether the window is normal or not.
+export function WindowIsNormal(): Promise;
+
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
+// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
+
+// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
+// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
+export function ScreenGetAll(): Promise;
+
+// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
+// Opens the given URL in the system browser.
+export function BrowserOpenURL(url: string): void;
+
+// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
+// Returns information about the environment
+export function Environment(): Promise;
+
+// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
+// Quits the application.
+export function Quit(): void;
+
+// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
+// Hides the application.
+export function Hide(): void;
+
+// [Show](https://wails.io/docs/reference/runtime/intro#show)
+// Shows the application.
+export function Show(): void;
+
+// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
+// Returns the current text stored on clipboard
+export function ClipboardGetText(): Promise;
+
+// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
+// Sets a text on the clipboard
+export function ClipboardSetText(text: string): Promise;
+
+// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
+// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
+
+// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
+// OnFileDropOff removes the drag and drop listeners and handlers.
+export function OnFileDropOff() :void
+
+// Check if the file path resolver is available
+export function CanResolveFilePaths(): boolean;
+
+// Resolves file paths for an array of files
+export function ResolveFilePaths(files: File[]): void
\ No newline at end of file
diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js
new file mode 100644
index 000000000..7cb89d750
--- /dev/null
+++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js
@@ -0,0 +1,242 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export function LogPrint(message) {
+ window.runtime.LogPrint(message);
+}
+
+export function LogTrace(message) {
+ window.runtime.LogTrace(message);
+}
+
+export function LogDebug(message) {
+ window.runtime.LogDebug(message);
+}
+
+export function LogInfo(message) {
+ window.runtime.LogInfo(message);
+}
+
+export function LogWarning(message) {
+ window.runtime.LogWarning(message);
+}
+
+export function LogError(message) {
+ window.runtime.LogError(message);
+}
+
+export function LogFatal(message) {
+ window.runtime.LogFatal(message);
+}
+
+export function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
+}
+
+export function EventsOn(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, -1);
+}
+
+export function EventsOff(eventName, ...additionalEventNames) {
+ return window.runtime.EventsOff(eventName, ...additionalEventNames);
+}
+
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
+export function EventsOnce(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, 1);
+}
+
+export function EventsEmit(eventName) {
+ let args = [eventName].slice.call(arguments);
+ return window.runtime.EventsEmit.apply(null, args);
+}
+
+export function WindowReload() {
+ window.runtime.WindowReload();
+}
+
+export function WindowReloadApp() {
+ window.runtime.WindowReloadApp();
+}
+
+export function WindowSetAlwaysOnTop(b) {
+ window.runtime.WindowSetAlwaysOnTop(b);
+}
+
+export function WindowSetSystemDefaultTheme() {
+ window.runtime.WindowSetSystemDefaultTheme();
+}
+
+export function WindowSetLightTheme() {
+ window.runtime.WindowSetLightTheme();
+}
+
+export function WindowSetDarkTheme() {
+ window.runtime.WindowSetDarkTheme();
+}
+
+export function WindowCenter() {
+ window.runtime.WindowCenter();
+}
+
+export function WindowSetTitle(title) {
+ window.runtime.WindowSetTitle(title);
+}
+
+export function WindowFullscreen() {
+ window.runtime.WindowFullscreen();
+}
+
+export function WindowUnfullscreen() {
+ window.runtime.WindowUnfullscreen();
+}
+
+export function WindowIsFullscreen() {
+ return window.runtime.WindowIsFullscreen();
+}
+
+export function WindowGetSize() {
+ return window.runtime.WindowGetSize();
+}
+
+export function WindowSetSize(width, height) {
+ window.runtime.WindowSetSize(width, height);
+}
+
+export function WindowSetMaxSize(width, height) {
+ window.runtime.WindowSetMaxSize(width, height);
+}
+
+export function WindowSetMinSize(width, height) {
+ window.runtime.WindowSetMinSize(width, height);
+}
+
+export function WindowSetPosition(x, y) {
+ window.runtime.WindowSetPosition(x, y);
+}
+
+export function WindowGetPosition() {
+ return window.runtime.WindowGetPosition();
+}
+
+export function WindowHide() {
+ window.runtime.WindowHide();
+}
+
+export function WindowShow() {
+ window.runtime.WindowShow();
+}
+
+export function WindowMaximise() {
+ window.runtime.WindowMaximise();
+}
+
+export function WindowToggleMaximise() {
+ window.runtime.WindowToggleMaximise();
+}
+
+export function WindowUnmaximise() {
+ window.runtime.WindowUnmaximise();
+}
+
+export function WindowIsMaximised() {
+ return window.runtime.WindowIsMaximised();
+}
+
+export function WindowMinimise() {
+ window.runtime.WindowMinimise();
+}
+
+export function WindowUnminimise() {
+ window.runtime.WindowUnminimise();
+}
+
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
+}
+
+export function ScreenGetAll() {
+ return window.runtime.ScreenGetAll();
+}
+
+export function WindowIsMinimised() {
+ return window.runtime.WindowIsMinimised();
+}
+
+export function WindowIsNormal() {
+ return window.runtime.WindowIsNormal();
+}
+
+export function BrowserOpenURL(url) {
+ window.runtime.BrowserOpenURL(url);
+}
+
+export function Environment() {
+ return window.runtime.Environment();
+}
+
+export function Quit() {
+ window.runtime.Quit();
+}
+
+export function Hide() {
+ window.runtime.Hide();
+}
+
+export function Show() {
+ window.runtime.Show();
+}
+
+export function ClipboardGetText() {
+ return window.runtime.ClipboardGetText();
+}
+
+export function ClipboardSetText(text) {
+ return window.runtime.ClipboardSetText(text);
+}
+
+/**
+ * Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ *
+ * @export
+ * @callback OnFileDropCallback
+ * @param {number} x - x coordinate of the drop
+ * @param {number} y - y coordinate of the drop
+ * @param {string[]} paths - A list of file paths.
+ */
+
+/**
+ * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+ *
+ * @export
+ * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
+ */
+export function OnFileDrop(callback, useDropTarget) {
+ return window.runtime.OnFileDrop(callback, useDropTarget);
+}
+
+/**
+ * OnFileDropOff removes the drag and drop listeners and handlers.
+ */
+export function OnFileDropOff() {
+ return window.runtime.OnFileDropOff();
+}
+
+export function CanResolveFilePaths() {
+ return window.runtime.CanResolveFilePaths();
+}
+
+export function ResolveFilePaths(files) {
+ return window.runtime.ResolveFilePaths(files);
+}
\ No newline at end of file
diff --git a/v2/examples/panic-recovery-test/go.mod b/v2/examples/panic-recovery-test/go.mod
new file mode 100644
index 000000000..026042cbf
--- /dev/null
+++ b/v2/examples/panic-recovery-test/go.mod
@@ -0,0 +1,5 @@
+module panic-recovery-test
+
+go 1.21
+
+require github.com/wailsapp/wails/v2 v2.11.0
diff --git a/v2/examples/panic-recovery-test/main.go b/v2/examples/panic-recovery-test/main.go
new file mode 100644
index 000000000..f6a38e86c
--- /dev/null
+++ b/v2/examples/panic-recovery-test/main.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "embed"
+
+ "github.com/wailsapp/wails/v2"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
+)
+
+//go:embed all:frontend/dist
+var assets embed.FS
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "panic-test",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
+ Bind: []interface{}{
+ app,
+ },
+ })
+
+ if err != nil {
+ println("Error:", err.Error())
+ }
+}
diff --git a/v2/examples/panic-recovery-test/wails.json b/v2/examples/panic-recovery-test/wails.json
new file mode 100644
index 000000000..56770f091
--- /dev/null
+++ b/v2/examples/panic-recovery-test/wails.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://wails.io/schemas/config.v2.json",
+ "name": "panic-recovery-test",
+ "outputfilename": "panic-recovery-test",
+ "frontend:install": "npm install",
+ "frontend:build": "npm run build",
+ "frontend:dev:watcher": "npm run dev",
+ "frontend:dev:serverUrl": "auto",
+ "author": {
+ "name": "Lea Anthony",
+ "email": "lea.anthony@gmail.com"
+ }
+}
diff --git a/v2/examples/systray/.gitignore b/v2/examples/systray/.gitignore
deleted file mode 100644
index 9fc08b5e3..000000000
--- a/v2/examples/systray/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-build/bin
-node_modules
-frontend/wailsjs
diff --git a/v2/examples/systray/README.md b/v2/examples/systray/README.md
deleted file mode 100644
index c99dfcb95..000000000
--- a/v2/examples/systray/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# System Tray
-
-This example shows how to create a system tray using an experimental programmatic API.
-
-## Running
-
-As this example outputs text to the console, it is recommended to build using `wails build -debug`.
-
-## Supported Platforms
-
-- [x] Windows
-- [ ] macOS
-- [ ] Linux
-
-
-
-
diff --git a/v2/examples/systray/build/darwin/Info.plist b/v2/examples/systray/build/darwin/Info.plist
deleted file mode 100644
index e7819a7e8..000000000
--- a/v2/examples/systray/build/darwin/Info.plist
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- CFBundlePackageType
- APPL
- CFBundleName
- {{.Info.ProductName}}
- CFBundleExecutable
- {{.Name}}
- CFBundleIdentifier
- com.wails.{{.Name}}
- CFBundleVersion
- {{.Info.ProductVersion}}
- CFBundleGetInfoString
- {{.Info.Comments}}
- CFBundleShortVersionString
- {{.Info.ProductVersion}}
- CFBundleIconFile
- iconfile
- LSMinimumSystemVersion
- 10.13.0
- NSHighResolutionCapable
- true
- NSHumanReadableCopyright
- {{.Info.Copyright}}
-
-
\ No newline at end of file
diff --git a/v2/examples/systray/build/windows/info.json b/v2/examples/systray/build/windows/info.json
deleted file mode 100644
index c23c173c9..000000000
--- a/v2/examples/systray/build/windows/info.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "fixed": {
- "file_version": "{{.Info.ProductVersion}}"
- },
- "info": {
- "0000": {
- "ProductVersion": "{{.Info.ProductVersion}}",
- "CompanyName": "{{.Info.CompanyName}}",
- "FileDescription": "{{.Info.ProductName}}",
- "LegalCopyright": "{{.Info.Copyright}}",
- "ProductName": "{{.Info.ProductName}}",
- "Comments": "{{.Info.Comments}}"
- }
- }
-}
\ No newline at end of file
diff --git a/v2/examples/systray/build/windows/installer/wails_tools.nsh b/v2/examples/systray/build/windows/installer/wails_tools.nsh
deleted file mode 100644
index 66dc209a3..000000000
--- a/v2/examples/systray/build/windows/installer/wails_tools.nsh
+++ /dev/null
@@ -1,171 +0,0 @@
-# DO NOT EDIT - Generated automatically by `wails build`
-
-!include "x64.nsh"
-!include "WinVer.nsh"
-!include "FileFunc.nsh"
-
-!ifndef INFO_PROJECTNAME
- !define INFO_PROJECTNAME "{{.Name}}"
-!endif
-!ifndef INFO_COMPANYNAME
- !define INFO_COMPANYNAME "{{.Info.CompanyName}}"
-!endif
-!ifndef INFO_PRODUCTNAME
- !define INFO_PRODUCTNAME "{{.Info.ProductName}}"
-!endif
-!ifndef INFO_PRODUCTVERSION
- !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
-!endif
-!ifndef INFO_COPYRIGHT
- !define INFO_COPYRIGHT "{{.Info.Copyright}}"
-!endif
-!ifndef PRODUCT_EXECUTABLE
- !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
-!endif
-!ifndef UNINST_KEY_NAME
- !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
-!endif
-!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
-
-!ifndef REQUEST_EXECUTION_LEVEL
- !define REQUEST_EXECUTION_LEVEL "admin"
-!endif
-
-RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
-
-!ifdef ARG_WAILS_AMD64_BINARY
- !define SUPPORTS_AMD64
-!endif
-
-!ifdef ARG_WAILS_ARM64_BINARY
- !define SUPPORTS_ARM64
-!endif
-
-!ifdef SUPPORTS_AMD64
- !ifdef SUPPORTS_ARM64
- !define ARCH "amd64_arm64"
- !else
- !define ARCH "amd64"
- !endif
-!else
- !ifdef SUPPORTS_ARM64
- !define ARCH "arm64"
- !else
- !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
- !endif
-!endif
-
-!macro wails.checkArchitecture
- !ifndef WAILS_WIN10_REQUIRED
- !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
- !endif
-
- !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
- !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
- !endif
-
- ${If} ${AtLeastWin10}
- !ifdef SUPPORTS_AMD64
- ${if} ${IsNativeAMD64}
- Goto ok
- ${EndIf}
- !endif
-
- !ifdef SUPPORTS_ARM64
- ${if} ${IsNativeARM64}
- Goto ok
- ${EndIf}
- !endif
-
- IfSilent silentArch notSilentArch
- silentArch:
- SetErrorLevel 65
- Abort
- notSilentArch:
- MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
- Quit
- ${else}
- IfSilent silentWin notSilentWin
- silentWin:
- SetErrorLevel 64
- Abort
- notSilentWin:
- MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
- Quit
- ${EndIf}
-
- ok:
-!macroend
-
-!macro wails.files
- !ifdef SUPPORTS_AMD64
- ${if} ${IsNativeAMD64}
- File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
- ${EndIf}
- !endif
-
- !ifdef SUPPORTS_ARM64
- ${if} ${IsNativeARM64}
- File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
- ${EndIf}
- !endif
-!macroend
-
-!macro wails.writeUninstaller
- WriteUninstaller "$INSTDIR\uninstall.exe"
-
- SetRegView 64
- WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
- WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
- WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
-
- ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
- IntFmt $0 "0x%08X" $0
- WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
-!macroend
-
-!macro wails.deleteUninstaller
- Delete "$INSTDIR\uninstall.exe"
-
- SetRegView 64
- DeleteRegKey HKLM "${UNINST_KEY}"
-!macroend
-
-# Install webview2 by launching the bootstrapper
-# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
-!macro wails.webview2runtime
- !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
- !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
- !endif
-
- SetRegView 64
- # If the admin key exists and is not empty then webview2 is already installed
- ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${If} $0 != ""
- Goto ok
- ${EndIf}
-
- ${If} ${REQUEST_EXECUTION_LEVEL} == "user"
- # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
- ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${If} $0 != ""
- Goto ok
- ${EndIf}
- ${EndIf}
-
- SetDetailsPrint both
- DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
- SetDetailsPrint listonly
-
- InitPluginsDir
- CreateDirectory "$pluginsdir\webview2bootstrapper"
- SetOutPath "$pluginsdir\webview2bootstrapper"
- File "tmp\MicrosoftEdgeWebview2Setup.exe"
- ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
-
- SetDetailsPrint both
- ok:
-!macroend
\ No newline at end of file
diff --git a/v2/examples/systray/frontend/dist/gitkeep b/v2/examples/systray/frontend/dist/gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/v2/examples/systray/frontend/index.html b/v2/examples/systray/frontend/index.html
deleted file mode 100644
index 5451f1e30..000000000
--- a/v2/examples/systray/frontend/index.html
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
- Systray Example
-
-
-
-
-
-
diff --git a/v2/examples/systray/frontend/package-lock.json b/v2/examples/systray/frontend/package-lock.json
deleted file mode 100644
index 1f1e962f0..000000000
--- a/v2/examples/systray/frontend/package-lock.json
+++ /dev/null
@@ -1,852 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "frontend",
- "version": "0.0.0",
- "devDependencies": {
- "vite": "^2.9.9"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
- "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz",
- "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/linux-loong64": "0.14.54",
- "esbuild-android-64": "0.14.54",
- "esbuild-android-arm64": "0.14.54",
- "esbuild-darwin-64": "0.14.54",
- "esbuild-darwin-arm64": "0.14.54",
- "esbuild-freebsd-64": "0.14.54",
- "esbuild-freebsd-arm64": "0.14.54",
- "esbuild-linux-32": "0.14.54",
- "esbuild-linux-64": "0.14.54",
- "esbuild-linux-arm": "0.14.54",
- "esbuild-linux-arm64": "0.14.54",
- "esbuild-linux-mips64le": "0.14.54",
- "esbuild-linux-ppc64le": "0.14.54",
- "esbuild-linux-riscv64": "0.14.54",
- "esbuild-linux-s390x": "0.14.54",
- "esbuild-netbsd-64": "0.14.54",
- "esbuild-openbsd-64": "0.14.54",
- "esbuild-sunos-64": "0.14.54",
- "esbuild-windows-32": "0.14.54",
- "esbuild-windows-64": "0.14.54",
- "esbuild-windows-arm64": "0.14.54"
- }
- },
- "node_modules/esbuild-android-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
- "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-android-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
- "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
- "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
- "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
- "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
- "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-32": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
- "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
- "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
- "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
- "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-mips64le": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
- "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-ppc64le": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
- "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-riscv64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
- "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-s390x": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
- "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-netbsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
- "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-openbsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
- "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-sunos-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
- "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-32": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
- "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
- "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
- "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
- "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
- "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
- "dev": true,
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/postcss": {
- "version": "8.4.16",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
- "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.4",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.9.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/rollup": {
- "version": "2.77.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz",
- "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/vite": {
- "version": "2.9.15",
- "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz",
- "integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.14.27",
- "postcss": "^8.4.13",
- "resolve": "^1.22.0",
- "rollup": ">=2.59.0 <2.78.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": ">=12.2.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "less": "*",
- "sass": "*",
- "stylus": "*"
- },
- "peerDependenciesMeta": {
- "less": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- }
- }
- }
- },
- "dependencies": {
- "@esbuild/linux-loong64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
- "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
- "dev": true,
- "optional": true
- },
- "esbuild": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz",
- "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
- "dev": true,
- "requires": {
- "@esbuild/linux-loong64": "0.14.54",
- "esbuild-android-64": "0.14.54",
- "esbuild-android-arm64": "0.14.54",
- "esbuild-darwin-64": "0.14.54",
- "esbuild-darwin-arm64": "0.14.54",
- "esbuild-freebsd-64": "0.14.54",
- "esbuild-freebsd-arm64": "0.14.54",
- "esbuild-linux-32": "0.14.54",
- "esbuild-linux-64": "0.14.54",
- "esbuild-linux-arm": "0.14.54",
- "esbuild-linux-arm64": "0.14.54",
- "esbuild-linux-mips64le": "0.14.54",
- "esbuild-linux-ppc64le": "0.14.54",
- "esbuild-linux-riscv64": "0.14.54",
- "esbuild-linux-s390x": "0.14.54",
- "esbuild-netbsd-64": "0.14.54",
- "esbuild-openbsd-64": "0.14.54",
- "esbuild-sunos-64": "0.14.54",
- "esbuild-windows-32": "0.14.54",
- "esbuild-windows-64": "0.14.54",
- "esbuild-windows-arm64": "0.14.54"
- }
- },
- "esbuild-android-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
- "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
- "dev": true,
- "optional": true
- },
- "esbuild-android-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
- "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
- "dev": true,
- "optional": true
- },
- "esbuild-darwin-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
- "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
- "dev": true,
- "optional": true
- },
- "esbuild-darwin-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
- "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
- "dev": true,
- "optional": true
- },
- "esbuild-freebsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
- "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
- "dev": true,
- "optional": true
- },
- "esbuild-freebsd-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
- "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-32": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
- "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
- "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-arm": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
- "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
- "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-mips64le": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
- "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-ppc64le": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
- "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-riscv64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
- "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
- "dev": true,
- "optional": true
- },
- "esbuild-linux-s390x": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
- "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
- "dev": true,
- "optional": true
- },
- "esbuild-netbsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
- "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
- "dev": true,
- "optional": true
- },
- "esbuild-openbsd-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
- "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
- "dev": true,
- "optional": true
- },
- "esbuild-sunos-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
- "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
- "dev": true,
- "optional": true
- },
- "esbuild-windows-32": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
- "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
- "dev": true,
- "optional": true
- },
- "esbuild-windows-64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
- "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
- "dev": true,
- "optional": true
- },
- "esbuild-windows-arm64": {
- "version": "0.14.54",
- "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
- "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
- "dev": true,
- "optional": true
- },
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "optional": true
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "is-core-module": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
- "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "nanoid": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
- "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
- "dev": true
- },
- "path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "postcss": {
- "version": "8.4.16",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
- "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
- "dev": true,
- "requires": {
- "nanoid": "^3.3.4",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- }
- },
- "resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
- "requires": {
- "is-core-module": "^2.9.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- }
- },
- "rollup": {
- "version": "2.77.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz",
- "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
- "dev": true,
- "requires": {
- "fsevents": "~2.3.2"
- }
- },
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true
- },
- "supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true
- },
- "vite": {
- "version": "2.9.15",
- "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz",
- "integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==",
- "dev": true,
- "requires": {
- "esbuild": "^0.14.27",
- "fsevents": "~2.3.2",
- "postcss": "^8.4.13",
- "resolve": "^1.22.0",
- "rollup": ">=2.59.0 <2.78.0"
- }
- }
- }
-}
diff --git a/v2/examples/systray/frontend/package.json b/v2/examples/systray/frontend/package.json
deleted file mode 100644
index 4ac881798..000000000
--- a/v2/examples/systray/frontend/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "preview": "vite preview"
- },
- "devDependencies": {
- "vite": "^2.9.9"
- }
-}
\ No newline at end of file
diff --git a/v2/examples/systray/go.mod b/v2/examples/systray/go.mod
deleted file mode 100644
index f624d426f..000000000
--- a/v2/examples/systray/go.mod
+++ /dev/null
@@ -1,34 +0,0 @@
-module github.com/wailsapp/examples/systray
-
-go 1.18
-
-require github.com/wailsapp/wails/v2 v2.2.0
-
-require (
- github.com/bep/debounce v1.2.1 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/google/uuid v1.1.2 // indirect
- github.com/imdario/mergo v0.3.12 // indirect
- github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
- github.com/labstack/echo/v4 v4.9.0 // indirect
- github.com/labstack/gommon v0.3.1 // indirect
- github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/gosod v1.0.3 // indirect
- github.com/leaanthony/slicer v1.5.0 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
- github.com/pkg/errors v0.9.1 // indirect
- github.com/samber/lo v1.27.1 // indirect
- github.com/tkrajina/go-reflector v0.5.5 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
- github.com/wailsapp/mimetype v1.4.1 // indirect
- golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
- golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
- golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
- golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
- golang.org/x/text v0.3.7 // indirect
-)
-
-replace github.com/wailsapp/wails/v2 v2.2.0 => ../..
diff --git a/v2/examples/systray/go.sum b/v2/examples/systray/go.sum
deleted file mode 100644
index 9f577485c..000000000
--- a/v2/examples/systray/go.sum
+++ /dev/null
@@ -1,79 +0,0 @@
-github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
-github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
-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/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
-github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-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/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
-github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
-github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
-github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
-github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
-github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
-github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
-github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
-github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
-github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
-github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
-github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
-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/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
-github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
-github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
-github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
-github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
-github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/v2/examples/systray/iconDarkMode.png b/v2/examples/systray/iconDarkMode.png
deleted file mode 100644
index 8d72ee490..000000000
Binary files a/v2/examples/systray/iconDarkMode.png and /dev/null differ
diff --git a/v2/examples/systray/iconLightMode.png b/v2/examples/systray/iconLightMode.png
deleted file mode 100644
index e8d341875..000000000
Binary files a/v2/examples/systray/iconLightMode.png and /dev/null differ
diff --git a/v2/examples/systray/main.go b/v2/examples/systray/main.go
deleted file mode 100644
index d675ec4d1..000000000
--- a/v2/examples/systray/main.go
+++ /dev/null
@@ -1,216 +0,0 @@
-package main
-
-import (
- "context"
- "embed"
- "fmt"
- "github.com/wailsapp/wails/v2/pkg/application"
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
- "github.com/wailsapp/wails/v2/pkg/options/windows"
- "github.com/wailsapp/wails/v2/pkg/runtime"
- "time"
-)
-
-//go:embed all:frontend/dist
-var assets embed.FS
-
-//go:embed iconLightMode.png
-var lightModeIcon []byte
-
-//go:embed iconDarkMode.png
-var darkModeIcon []byte
-
-func main() {
-
- var runtimeContext context.Context
-
- // Create a new Wails application using the current options
- mainApp := application.NewWithOptions(&options.App{
- Assets: assets,
- StartHidden: true,
- HideWindowOnClose: true,
- OnStartup: func(ctx context.Context) {
- runtimeContext = ctx
- },
- Windows: &windows.Options{
- BackdropType: windows.Acrylic,
- WindowIsTranslucent: true,
- WebviewIsTransparent: true,
- DisableWindowIcon: true,
- },
- })
-
- // ------------------------------------
- // Create a systray for the application
- // Currently we only support PNG for icons
-
- var systray *application.SystemTray
- var showWindow = func() {
- // Show the window
- // In a future version of this API, it will be possible to
- // create windows programmatically and be able to show/hide
- // them from the systray with something like:
- //
- // myWindow := mainApp.NewWindow(...)
- // mainApp.NewSystemTray(&options.SystemTray{
- // OnLeftClick: func() {
- // myWindow.SetVisibility(!myWindow.IsVisible())
- // }
- // })
- runtime.Show(runtimeContext)
- }
- systray = mainApp.NewSystemTray(&options.SystemTray{
- // This is the icon used when the system in using light mode
- LightModeIcon: &options.SystemTrayIcon{
- Data: lightModeIcon,
- },
- // This is the icon used when the system in using dark mode
- DarkModeIcon: &options.SystemTrayIcon{
- Data: darkModeIcon,
- },
- Tooltip: "Systray Example",
- OnLeftClick: showWindow,
- OnMenuClose: func() {
- // Add the left click call after 500ms
- // We do this because the left click fires right
- // after the menu closes, and we don't want to show
- // the window on menu close.
- go func() {
- time.Sleep(500 * time.Millisecond)
- systray.OnLeftClick(showWindow)
- }()
- },
- OnMenuOpen: func() {
- // Remove the left click callback
- systray.OnLeftClick(func() {})
- },
- })
-
- // ---------------------------------------------------
- // Menu items are created in the order they are added.
- // This is a contrived example to show what can be done
- // with menus.
-
- // This is a menuitem we will show/hide at runtime
- visibleNotVisible := menu.Label("visible?").Show()
-
- counter := 0
- icons := [][]byte{lightModeIcon, darkModeIcon}
- iconCounter := 0
-
- disabledEnabledMenu := menu.Label("disabled").Disable().OnClick(func(c *menu.CallbackData) {
- println("Disabled item clicked!")
- })
-
- // This checkbox menuitem will print the current checked state to the console when clicked.
- // When a checkbox item is clicked, the state of the `Checked` variable is toggled.
- // The UI automatically reflects the current state, even if this item is used multiple times.
- mycheckbox := menu.Label("checked").SetChecked(true).OnClick(func(c *menu.CallbackData) {
- println("My checked state is: ", c.MenuItem.Checked)
- })
-
- // This radio callback will be used by all the radio items.
- // The CallbackData has a pointer back to the menuitem, so we can determine
- // which item was selected
- radioCallback := func(data *menu.CallbackData) {
- println("Radio item clicked:", data.MenuItem.Label)
- }
-
- // We create 3 radio items , with the first being selected. They all share a callback.
- radio1 := menu.Radio("Radio 1", true, nil, radioCallback)
- radio2 := menu.Radio("Radio 2", false, nil, radioCallback)
- radio3 := menu.Radio("Radio 3", false, nil, radioCallback)
-
- // Now we set the menu of the systray.
- // This would likely be created in a different function/file
- systray.SetMenu(menu.NewMenuFromItems(
-
- visibleNotVisible,
- // This menu item changes its label when clicked.
- menu.Label("Click Me!").OnClick(func(c *menu.CallbackData) {
- counter++
- c.MenuItem.SetLabel(fmt.Sprintf("Clicked %d times", counter))
- systray.Update()
- }),
-
- // We add a checkbox
- menu.Separator(),
- mycheckbox,
-
- // Next we create 2 radio groups containing the same menu items.
- // It is perfectly fine to reuse radio item groups - the state and UI will
- // stay in sync. Warning: Using the same radio item in different groups will
- // lead to unspecified behaviour!
- menu.Separator(),
- radio1,
- radio2,
- radio3,
-
- menu.Separator(),
- mycheckbox,
-
- menu.Label("Toggle items!").OnClick(func(c *menu.CallbackData) {
-
- iconCounter++
-
- // Swap light and dark mode icons
- systray.SetIcons(&options.SystemTrayIcon{
- Data: icons[iconCounter%2],
- }, &options.SystemTrayIcon{
- Data: icons[(iconCounter+1)%2],
- })
-
- // Do some toggling
- if iconCounter%2 == 0 {
- visibleNotVisible.Show()
- disabledEnabledMenu.Disable()
- } else {
- visibleNotVisible.Hide()
- disabledEnabledMenu.Enable()
- }
-
- // Update the menu
- err := systray.Update()
- if err != nil {
- panic(err)
- }
- }),
-
- // We create a checkbox item that is initially unchecked.
- menu.Label("unchecked").SetChecked(false).OnClick(func(c *menu.CallbackData) {
- println("My checked state is: ", c.MenuItem.Checked)
- systray.SetTooltip("My updated tooltip!")
- }),
-
- // This menu item will toggle between enabled and disabled each time the "Toggle items!" menu
- // option is selected
- disabledEnabledMenu,
-
- // We now add a submenu, reusing the checkbox item and submenu we created earlier
- menu.SubMenu("submenu", menu.NewMenuFromItems(
- mycheckbox,
- menu.Label("submenu item").OnClick(func(data *menu.CallbackData) {
- println("submenu item clicked")
- }),
- menu.Separator(),
- radio1,
- radio2,
- radio3,
- )),
- menu.Separator(),
- menu.Label("quit").OnClick(func(_ *menu.CallbackData) {
- println("Quitting application")
- mainApp.Quit()
- }),
- ))
-
- println("Check out the system tray!")
-
- // Now we run the application
- err := mainApp.Run()
-
- if err != nil {
- println("Error:", err.Error())
- }
-}
diff --git a/v2/examples/systray/wails.json b/v2/examples/systray/wails.json
deleted file mode 100644
index f532e0088..000000000
--- a/v2/examples/systray/wails.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "systray",
- "outputfilename": "systray",
- "frontend:install": "npm install",
- "frontend:build": "npm run build",
- "frontend:dev:watcher": "npm run dev",
- "frontend:dev:serverUrl": "auto",
- "author": {
- "name": "Lea Anthony",
- "email": "lea.anthony@gmail.com"
- }
-}
diff --git a/v2/go.mod b/v2/go.mod
index 7f6b7cc08..2eb753ee2 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -1,98 +1,112 @@
module github.com/wailsapp/wails/v2
-go 1.18
+go 1.22.0
require (
github.com/Masterminds/semver v1.5.0
- github.com/flytam/filenamify v1.0.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/google/shlex v0.0.0-20191202100458-e7afc7fbc510
- github.com/google/uuid v1.1.2
- github.com/imdario/mergo v0.3.12
- github.com/jackmordaunt/icns v1.0.0
- github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e
- github.com/labstack/echo/v4 v4.9.0
- github.com/leaanthony/clir v1.3.0
- github.com/leaanthony/debme v1.2.1
- github.com/leaanthony/go-ansi-parser v1.0.1
- github.com/leaanthony/gosod v1.0.3
- github.com/leaanthony/slicer v1.5.0
- github.com/leaanthony/winicon v1.0.0
- github.com/matryer/is v1.4.0
- github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
- github.com/pkg/errors v0.9.1
- github.com/tc-hib/winres v0.1.5
- github.com/tidwall/sjson v1.1.7
- github.com/tkrajina/go-reflector v0.5.5
- github.com/wailsapp/mimetype v1.4.1
- github.com/wzshiming/ctc v1.2.3
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
- golang.org/x/net v0.0.0-20220722155237-a158d28d115b
- golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
-)
-
-require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/bep/debounce v1.2.1
- github.com/bitfield/script v0.19.0
- github.com/charmbracelet/glamour v0.5.0
- github.com/go-ole/go-ole v1.2.6
- github.com/labstack/gommon v0.3.1
- github.com/pterm/pterm v0.12.49
+ github.com/bitfield/script v0.24.0
+ github.com/charmbracelet/glamour v0.8.0
+ github.com/flytam/filenamify v1.2.0
+ github.com/fsnotify/fsnotify v1.9.0
+ github.com/go-git/go-git/v5 v5.13.2
+ github.com/go-ole/go-ole v1.3.0
+ github.com/godbus/dbus/v5 v5.1.0
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
+ github.com/google/uuid v1.6.0
+ github.com/gorilla/websocket v1.5.3
+ github.com/jackmordaunt/icns v1.0.0
+ github.com/jaypipes/ghw v0.21.3
+ github.com/labstack/echo/v4 v4.13.3
+ github.com/labstack/gommon v0.4.2
+ github.com/leaanthony/clir v1.3.0
+ github.com/leaanthony/debme v1.2.1
+ github.com/leaanthony/go-ansi-parser v1.6.1
+ github.com/leaanthony/gosod v1.0.4
+ github.com/leaanthony/slicer v1.6.0
+ github.com/leaanthony/u v1.1.1
+ github.com/leaanthony/winicon v1.0.0
+ github.com/matryer/is v1.4.1
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
+ github.com/pkg/errors v0.9.1
+ github.com/pterm/pterm v0.12.80
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
- github.com/samber/lo v1.27.1
- github.com/stretchr/testify v1.8.0
- golang.org/x/tools v0.1.12
+ github.com/samber/lo v1.49.1
+ github.com/stretchr/testify v1.10.0
+ github.com/tc-hib/winres v0.3.1
+ github.com/tidwall/sjson v1.2.5
+ github.com/tkrajina/go-reflector v0.5.8
+ github.com/wailsapp/go-webview2 v1.0.22
+ github.com/wailsapp/mimetype v1.4.1
+ github.com/wzshiming/ctc v1.2.3
+ golang.org/x/mod v0.23.0
+ golang.org/x/net v0.35.0
+ golang.org/x/sys v0.30.0
+ golang.org/x/tools v0.30.0
)
require (
- atomicgo.dev/cursor v0.1.1 // indirect
- atomicgo.dev/keyboard v0.2.8 // indirect
- bitbucket.org/creachadair/shell v0.0.7 // indirect
- github.com/Microsoft/go-winio v0.4.16 // indirect
- github.com/alecthomas/chroma v0.10.0 // indirect
+ atomicgo.dev/cursor v0.2.0 // indirect
+ atomicgo.dev/keyboard v0.2.9 // indirect
+ atomicgo.dev/schedule v0.1.0 // indirect
+ dario.cat/mergo v1.0.0 // indirect
+ github.com/Microsoft/go-winio v0.6.1 // indirect
+ github.com/ProtonMail/go-crypto v1.1.5 // indirect
+ github.com/alecthomas/chroma/v2 v2.14.0 // indirect
+ github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
+ github.com/charmbracelet/lipgloss v0.12.1 // indirect
+ github.com/charmbracelet/x/ansi v0.1.4 // indirect
+ github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/console v1.0.3 // indirect
+ github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/dlclark/regexp2 v1.4.0 // indirect
- github.com/emirpasic/gods v1.12.0 // indirect
- github.com/go-git/gcfg v1.5.0 // indirect
- github.com/gookit/color v1.5.2 // indirect
- github.com/gorilla/css v1.0.0 // indirect
+ github.com/dlclark/regexp2 v1.11.0 // indirect
+ github.com/emirpasic/gods v1.18.1 // indirect
+ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
+ github.com/go-git/go-billy/v5 v5.6.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/gookit/color v1.5.4 // indirect
+ github.com/gorilla/css v1.0.1 // indirect
+ github.com/itchyny/gojq v0.12.13 // indirect
+ github.com/itchyny/timefmt-go v0.1.5 // indirect
+ github.com/jaypipes/pcidb v1.1.1 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
- github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
- github.com/kr/pretty v0.3.0 // indirect
- github.com/lithammer/fuzzysearch v1.1.5 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/kevinburke/ssh_config v1.2.0 // indirect
+ github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/mattn/go-runewidth v0.0.13 // indirect
- github.com/microcosm-cc/bluemonday v1.0.17 // indirect
- github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-runewidth v0.0.16 // indirect
+ github.com/microcosm-cc/bluemonday v1.0.27 // indirect
github.com/muesli/reflow v0.3.0 // indirect
- github.com/muesli/termenv v0.9.0 // indirect
+ github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
- github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/rivo/uniseg v0.2.0 // indirect
- github.com/sergi/go-diff v1.2.0 // indirect
- github.com/tidwall/gjson v1.8.0 // indirect
- github.com/tidwall/match v1.0.3 // indirect
- github.com/tidwall/pretty v1.1.0 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
+ github.com/skeema/knownhosts v1.3.0 // indirect
+ github.com/tidwall/gjson v1.14.2 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
+ github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect
- github.com/xanzy/ssh-agent v0.3.0 // indirect
- github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
- github.com/yuin/goldmark v1.4.13 // indirect
- github.com/yuin/goldmark-emoji v1.0.1 // indirect
- golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
- golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
- golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect
- golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
- golang.org/x/text v0.3.7 // indirect
+ github.com/xanzy/ssh-agent v0.3.3 // indirect
+ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
+ github.com/yuin/goldmark v1.7.4 // indirect
+ github.com/yuin/goldmark-emoji v1.0.3 // indirect
+ github.com/yusufpapurcu/wmi v1.2.4 // indirect
+ golang.org/x/crypto v0.33.0 // indirect
+ golang.org/x/image v0.12.0 // indirect
+ golang.org/x/sync v0.11.0 // indirect
+ golang.org/x/term v0.29.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+ howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect
+ mvdan.cc/sh/v3 v3.7.0 // indirect
)
diff --git a/v2/go.sum b/v2/go.sum
index c434fd7af..f6df3507e 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -1,9 +1,13 @@
-atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4=
-atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
-atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4=
-atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
-bitbucket.org/creachadair/shell v0.0.7 h1:Z96pB6DkSb7F3Y3BBnJeOZH2gazyMTWlvecSD4vDqfk=
-bitbucket.org/creachadair/shell v0.0.7/go.mod h1:oqtXSSvSYr4624lnnabXHaBsYW6RD80caLi2b3hJk0U=
+atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=
+atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ=
+atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw=
+atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
+atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
+atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
+atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
+atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
@@ -11,146 +15,179 @@ github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSr
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
-github.com/MarvinJWendt/testza v0.4.3 h1:u2XaM4IqGp9dsdUmML8/Z791fu4yjQYzOiufOtJwTII=
+github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
+github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
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/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
+github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
-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/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
-github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
-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/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
+github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
+github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
+github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
+github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
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/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
+github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
+github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
-github.com/bitfield/script v0.19.0 h1:W24f+FQuPab9gXcW8bhcbo5qO8AtrXyu3XOnR4zhHN0=
-github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kgja+WMmIY=
-github.com/charmbracelet/glamour v0.5.0 h1:wu15ykPdB7X6chxugG/NNfDUbyyrCLV9XBalj5wdu3g=
-github.com/charmbracelet/glamour v0.5.0/go.mod h1:9ZRtG19AUIzcTm7FGLGbq3D5WKQ5UyZBbQsMQN0XIqc=
+github.com/bitfield/script v0.24.0 h1:ic0Tbx+2AgRtkGGIcUyr+Un60vu4WXvqFrCSumf+T7M=
+github.com/bitfield/script v0.24.0/go.mod h1:fv+6x4OzVsRs6qAlc7wiGq8fq1b5orhtQdtW0dwjUHI=
+github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs=
+github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw=
+github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs=
+github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8=
+github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM=
+github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
+github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4 h1:6KzMkQeAF56rggw2NZu1L+TH7j9+DM1/2Kmh7KUxg1I=
+github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
+github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
+github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
+github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
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/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
-github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
-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/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/flytam/filenamify v1.0.0 h1:ewx6BY2dj7U6h2zGPJmt33q/BjkSf/YsY/woQvnUNIs=
-github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8=
-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/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.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
+github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/flytam/filenamify v1.2.0 h1:7RiSqXYR4cJftDQ5NuvljKMfd/ubKnW/j9C6iekChgI=
+github.com/flytam/filenamify v1.2.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8=
+github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
+github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
+github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
+github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
+github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
+github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
+github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
+github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
-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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
-github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
-github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
-github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
-github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
-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/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
+github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
+github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
+github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
+github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
+github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU=
+github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4=
+github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
+github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
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/jaypipes/ghw v0.21.3 h1:v5mUHM+RN854Vqmk49Uh213jyUA4+8uqaRajlYESsh8=
+github.com/jaypipes/ghw v0.21.3/go.mod h1:GPrvwbtPoxYUenr74+nAnWbardIZq600vJDD5HnPsPE=
+github.com/jaypipes/pcidb v1.1.1 h1:QmPhpsbmmnCwZmHeYAATxEaoRuiMAJusKYkUncMC0ro=
+github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6hH0G7g8=
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/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
-github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
-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/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
-github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
+github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
-github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
+github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0=
github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
-github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
-github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
-github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
+github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
+github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
+github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI=
+github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
+github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
+github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
+github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
+github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
-github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
-github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
+github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
+github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
-github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
-github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
+github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
-github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/microcosm-cc/bluemonday v1.0.17 h1:Z1a//hgsQ4yjC+8zEkV8IWySkXnsxmdSY642CTFQb5Y=
-github.com/microcosm-cc/bluemonday v1.0.17/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM=
-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/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
+github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
-github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8=
-github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw=
+github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
+github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
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.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
-github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
+github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
+github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
+github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
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=
@@ -162,133 +199,153 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
-github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg=
-github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg=
+github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg=
+github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
-github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
-github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
+github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
+github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/tc-hib/winres v0.1.5 h1:2dA5yfjdoEA3UyRaOC92HNMt3jap66pLzoW4MjpC/0M=
-github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
-github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
-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/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
-github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4=
+github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
+github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo=
+github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
+github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
+github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
+github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6NZijQ58=
+github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
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/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
-github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
+github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
+github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
-github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
-golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
+github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
+github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
+github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
+github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4=
+github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
+golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI=
-golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
+golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
+golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
+golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
+golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-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-20191026070338-33540a1f6037/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-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
+golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
+golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
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.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 h1:eeH1AIcPvSc0Z25ThsYF+Xoqbn0CI/YnXVYoTLFdGQw=
+howett.net/plist v1.0.2-0.20250314012144-ee69052608d9/go.mod h1:fyFX5Hj5tP1Mpk8obqA9MZgXT416Q5711SDT7dQLTLk=
+mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
+mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
diff --git a/v2/internal/app/app.go b/v2/internal/app/app.go
index f2821aaba..0cd6bf614 100644
--- a/v2/internal/app/app.go
+++ b/v2/internal/app/app.go
@@ -2,6 +2,7 @@ package app
import (
"context"
+
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/menumanager"
@@ -20,6 +21,9 @@ type App struct {
// Indicates if the app is in debug mode
debug bool
+ // Indicates if the devtools is enabled
+ devtoolsEnabled bool
+
// OnStartup/OnShutdown
startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context)
diff --git a/v2/internal/app/app_bindings.go b/v2/internal/app/app_bindings.go
index d079790aa..be031819c 100644
--- a/v2/internal/app/app_bindings.go
+++ b/v2/internal/app/app_bindings.go
@@ -31,6 +31,7 @@ func (a *App) Run() error {
var tsPrefixFlag *string
var tsPostfixFlag *string
+ var tsOutputTypeFlag *string
tsPrefix := os.Getenv("tsprefix")
if tsPrefix == "" {
@@ -42,6 +43,11 @@ func (a *App) Run() error {
tsPostfixFlag = bindingFlags.String("tssuffix", "", "Suffix for generated typescript entities")
}
+ tsOutputType := os.Getenv("tsoutputtype")
+ if tsOutputType == "" {
+ tsOutputTypeFlag = bindingFlags.String("tsoutputtype", "", "Output type for generated typescript entities (classes|interfaces)")
+ }
+
_ = bindingFlags.Parse(os.Args[1:])
if tsPrefixFlag != nil {
tsPrefix = *tsPrefixFlag
@@ -49,11 +55,15 @@ func (a *App) Run() error {
if tsPostfixFlag != nil {
tsSuffix = *tsPostfixFlag
}
+ if tsOutputTypeFlag != nil {
+ tsOutputType = *tsOutputTypeFlag
+ }
- appBindings := binding.NewBindings(a.logger, a.options.Bind, bindingExemptions, IsObfuscated())
+ appBindings := binding.NewBindings(a.logger, a.options.Bind, bindingExemptions, IsObfuscated(), a.options.EnumBind)
appBindings.SetTsPrefix(tsPrefix)
appBindings.SetTsSuffix(tsSuffix)
+ appBindings.SetOutputType(tsOutputType)
err := generateBindings(appBindings)
if err != nil {
diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go
index 32c27fa2e..6de845f96 100644
--- a/v2/internal/app/app_dev.go
+++ b/v2/internal/app/app_dev.go
@@ -8,9 +8,11 @@ import (
"flag"
"fmt"
iofs "io/fs"
+ "net"
"net/url"
"os"
"path/filepath"
+ "time"
"github.com/wailsapp/wails/v2/pkg/assetserver"
@@ -40,9 +42,16 @@ func (a *App) Run() error {
func CreateApp(appoptions *options.App) (*App, error) {
var err error
- ctx := context.WithValue(context.Background(), "debug", true)
+ ctx := context.Background()
+ ctx = context.WithValue(ctx, "debug", true)
+ ctx = context.WithValue(ctx, "devtoolsEnabled", true)
+
+ // Set up logger if the appoptions.LogLevel is an invalid value, set it to the default log level
+ appoptions.LogLevel, err = pkglogger.StringToLogLevel(appoptions.LogLevel.String())
+ if err != nil {
+ return nil, err
+ }
- // Set up logger
myLogger := logger.New(appoptions.Logger)
myLogger.SetLogLevel(appoptions.LogLevel)
@@ -70,9 +79,11 @@ func CreateApp(appoptions *options.App) (*App, error) {
}
loglevel := os.Getenv("loglevel")
- if loglevel == "" {
- loglevelFlag = devFlags.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
+ appLogLevel := appoptions.LogLevel.String()
+ if loglevel != "" {
+ appLogLevel = loglevel
}
+ loglevelFlag = devFlags.String("loglevel", appLogLevel, "Loglevel to use - Trace, Debug, Info, Warning, Error")
// If we weren't given the assetdir in the environment variables
if assetdir == "" {
@@ -104,17 +115,33 @@ func CreateApp(appoptions *options.App) (*App, error) {
}
if frontendDevServerURL != "" {
- if devServer == "" {
- return nil, fmt.Errorf("Unable to use FrontendDevServerUrl without a DevServer address")
+ _, port, err := net.SplitHostPort(devServer)
+ if err != nil {
+ return nil, fmt.Errorf("unable to determine port of DevServer: %s", err)
}
- startURL, err := url.Parse("http://" + devServer)
+ ctx = context.WithValue(ctx, "assetserverport", port)
+
+ ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)
+
+ externalURL, err := url.Parse(frontendDevServerURL)
if err != nil {
return nil, err
}
- ctx = context.WithValue(ctx, "starturl", startURL)
- ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)
+ if externalURL.Host == "" {
+ return nil, fmt.Errorf("Invalid frontend:dev:serverUrl missing protocol scheme?")
+ }
+
+ waitCb := func() { myLogger.Debug("Waiting for frontend DevServer '%s' to be ready", externalURL) }
+ if !checkPortIsOpen(externalURL.Host, time.Minute, waitCb) {
+ myLogger.Error("Timeout waiting for frontend DevServer")
+ }
+
+ handler := assetserver.NewExternalAssetsHandler(myLogger, assetConfig, externalURL)
+ assetConfig.Assets = nil
+ assetConfig.Handler = handler
+ assetConfig.Middleware = nil
myLogger.Info("Serving assets from frontend DevServer URL: %s", frontendDevServerURL)
} else {
@@ -154,7 +181,10 @@ func CreateApp(appoptions *options.App) (*App, error) {
if err != nil {
return nil, err
}
- myLogger.SetLogLevel(level)
+ // Only set the log level if it's different from the appoptions.LogLevel
+ if level != appoptions.LogLevel {
+ myLogger.SetLogLevel(level)
+ }
}
// Attach logger to context
@@ -189,11 +219,11 @@ func CreateApp(appoptions *options.App) (*App, error) {
appoptions.OnDomReady,
appoptions.OnBeforeClose,
}
- appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions, false)
+ appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions, false, appoptions.EnumBind)
eventHandler := runtime.NewEvents(myLogger)
ctx = context.WithValue(ctx, "events", eventHandler)
- messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter, appoptions.DisablePanicRecovery)
// Create the frontends and register to event handler
desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
@@ -210,6 +240,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown,
debug: true,
+ devtoolsEnabled: true,
}
result.options = appoptions
@@ -246,3 +277,22 @@ func tryInferAssetDirFromFS(assets iofs.FS) (string, error) {
return path, nil
}
+
+func checkPortIsOpen(host string, timeout time.Duration, waitCB func()) (ret bool) {
+ if timeout == 0 {
+ timeout = time.Minute
+ }
+
+ deadline := time.Now().Add(timeout)
+ for time.Now().Before(deadline) {
+ conn, _ := net.DialTimeout("tcp", host, 2*time.Second)
+ if conn != nil {
+ conn.Close()
+ return true
+ }
+
+ waitCB()
+ time.Sleep(1 * time.Second)
+ }
+ return false
+}
diff --git a/v2/internal/app/app_devtools.go b/v2/internal/app/app_devtools.go
new file mode 100644
index 000000000..60b221094
--- /dev/null
+++ b/v2/internal/app/app_devtools.go
@@ -0,0 +1,8 @@
+//go:build devtools
+
+package app
+
+// Note: devtools flag is also added in debug builds
+func IsDevtoolsEnabled() bool {
+ return true
+}
diff --git a/v2/internal/app/app_devtools_not.go b/v2/internal/app/app_devtools_not.go
new file mode 100644
index 000000000..912672048
--- /dev/null
+++ b/v2/internal/app/app_devtools_not.go
@@ -0,0 +1,9 @@
+//go:build !devtools
+
+package app
+
+// IsDevtoolsEnabled returns true if devtools should be enabled
+// Note: devtools flag is also added in debug builds
+func IsDevtoolsEnabled() bool {
+ return false
+}
diff --git a/v2/internal/app/app_production.go b/v2/internal/app/app_production.go
index afb67bdb3..9eb0e5a66 100644
--- a/v2/internal/app/app_production.go
+++ b/v2/internal/app/app_production.go
@@ -34,7 +34,9 @@ func CreateApp(appoptions *options.App) (*App, error) {
options.MergeDefaults(appoptions)
debug := IsDebug()
+ devtoolsEnabled := IsDevtoolsEnabled()
ctx = context.WithValue(ctx, "debug", debug)
+ ctx = context.WithValue(ctx, "devtoolsEnabled", devtoolsEnabled)
// Set up logger
myLogger := logger.New(appoptions.Logger)
@@ -70,7 +72,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
appoptions.OnDomReady,
appoptions.OnBeforeClose,
}
- appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions, IsObfuscated())
+ appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions, IsObfuscated(), appoptions.EnumBind)
eventHandler := runtime.NewEvents(myLogger)
ctx = context.WithValue(ctx, "events", eventHandler)
// Attach logger to context
@@ -80,7 +82,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
ctx = context.WithValue(ctx, "buildtype", "production")
}
- messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter, appoptions.DisablePanicRecovery)
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
eventHandler.AddFrontend(appFrontend)
@@ -93,6 +95,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown,
debug: debug,
+ devtoolsEnabled: devtoolsEnabled,
options: appoptions,
}
diff --git a/v2/internal/binding/binding.go b/v2/internal/binding/binding.go
old mode 100755
new mode 100644
index 75b821f29..b7bf07ae0
--- a/v2/internal/binding/binding.go
+++ b/v2/internal/binding/binding.go
@@ -14,6 +14,7 @@ import (
"github.com/wailsapp/wails/v2/internal/typescriptify"
"github.com/leaanthony/slicer"
+
"github.com/wailsapp/wails/v2/internal/logger"
)
@@ -23,17 +24,20 @@ type Bindings struct {
exemptions slicer.StringSlicer
structsToGenerateTS map[string]map[string]interface{}
+ enumsToGenerateTS map[string]map[string]interface{}
tsPrefix string
tsSuffix string
+ tsInterface bool
obfuscate bool
}
// NewBindings returns a new Bindings object
-func NewBindings(logger *logger.Logger, structPointersToBind []interface{}, exemptions []interface{}, obfuscate bool) *Bindings {
+func NewBindings(logger *logger.Logger, structPointersToBind []interface{}, exemptions []interface{}, obfuscate bool, enumsToBind []interface{}) *Bindings {
result := &Bindings{
db: newDB(),
logger: logger.CustomLogger("Bindings"),
structsToGenerateTS: make(map[string]map[string]interface{}),
+ enumsToGenerateTS: make(map[string]map[string]interface{}),
obfuscate: obfuscate,
}
@@ -47,6 +51,10 @@ func NewBindings(logger *logger.Logger, structPointersToBind []interface{}, exem
result.exemptions.Add(name)
}
+ for _, enum := range enumsToBind {
+ result.AddEnumToGenerateTS(enum)
+ }
+
// Add the structs to bind
for _, ptr := range structPointersToBind {
err := result.Add(ptr)
@@ -60,20 +68,13 @@ func NewBindings(logger *logger.Logger, structPointersToBind []interface{}, exem
// Add the given struct methods to the Bindings
func (b *Bindings) Add(structPtr interface{}) error {
-
methods, err := b.getMethods(structPtr)
if err != nil {
return fmt.Errorf("cannot bind value to app: %s", err.Error())
}
for _, method := range methods {
- splitName := strings.Split(method.Name, ".")
- packageName := splitName[0]
- structName := splitName[1]
- methodName := splitName[2]
-
- // Add it as a regular method
- b.db.AddMethod(packageName, structName, methodName, method)
+ b.db.AddMethod(method.Path.Package, method.Path.Struct, method.Path.Name, method)
}
return nil
}
@@ -89,16 +90,21 @@ func (b *Bindings) ToJSON() (string, error) {
func (b *Bindings) GenerateModels() ([]byte, error) {
models := map[string]string{}
var seen slicer.StringSlicer
+ var seenEnumsPackages slicer.StringSlicer
allStructNames := b.getAllStructNames()
allStructNames.Sort()
+ allEnumNames := b.getAllEnumNames()
+ allEnumNames.Sort()
for packageName, structsToGenerate := range b.structsToGenerateTS {
thisPackageCode := ""
w := typescriptify.New()
w.WithPrefix(b.tsPrefix)
w.WithSuffix(b.tsSuffix)
+ w.WithInterface(b.tsInterface)
w.Namespace = packageName
w.WithBackupDir("")
w.KnownStructs = allStructNames
+ w.KnownEnums = allEnumNames
// sort the structs
var structNames []string
for structName := range structsToGenerate {
@@ -113,6 +119,28 @@ func (b *Bindings) GenerateModels() ([]byte, error) {
structInterface := structsToGenerate[structName]
w.Add(structInterface)
}
+
+ // if we have enums for this package, add them as well
+ var enums, enumsExist = b.enumsToGenerateTS[packageName]
+ if enumsExist {
+ // Sort the enum names first to make the output deterministic
+ sortedEnumNames := make([]string, 0, len(enums))
+ for enumName := range enums {
+ sortedEnumNames = append(sortedEnumNames, enumName)
+ }
+ sort.Strings(sortedEnumNames)
+
+ for _, enumName := range sortedEnumNames {
+ enum := enums[enumName]
+ fqemumname := packageName + "." + enumName
+ if seen.Contains(fqemumname) {
+ continue
+ }
+ w.AddEnum(enum)
+ }
+ seenEnumsPackages.Add(packageName)
+ }
+
str, err := w.Convert(nil)
if err != nil {
return nil, err
@@ -122,8 +150,37 @@ func (b *Bindings) GenerateModels() ([]byte, error) {
models[packageName] = thisPackageCode
}
+ // Add outstanding enums to the models that were not in packages with structs
+ for packageName, enumsToGenerate := range b.enumsToGenerateTS {
+ if seenEnumsPackages.Contains(packageName) {
+ continue
+ }
+
+ thisPackageCode := ""
+ w := typescriptify.New()
+ w.WithPrefix(b.tsPrefix)
+ w.WithSuffix(b.tsSuffix)
+ w.WithInterface(b.tsInterface)
+ w.Namespace = packageName
+ w.WithBackupDir("")
+
+ for enumName, enum := range enumsToGenerate {
+ fqemumname := packageName + "." + enumName
+ if seen.Contains(fqemumname) {
+ continue
+ }
+ w.AddEnum(enum)
+ }
+ str, err := w.Convert(nil)
+ if err != nil {
+ return nil, err
+ }
+ thisPackageCode += str
+ models[packageName] = thisPackageCode
+ }
+
// Sort the package names first to make the output deterministic
- sortedPackageNames := make([]string, 0)
+ sortedPackageNames := make([]string, 0, len(models))
for packageName := range models {
sortedPackageNames = append(sortedPackageNames, packageName)
}
@@ -146,7 +203,6 @@ func (b *Bindings) GenerateModels() ([]byte, error) {
}
func (b *Bindings) WriteModels(modelsDir string) error {
-
modelsData, err := b.GenerateModels()
if err != nil {
return err
@@ -157,7 +213,7 @@ func (b *Bindings) WriteModels(modelsDir string) error {
}
filename := filepath.Join(modelsDir, "models.ts")
- err = os.WriteFile(filename, modelsData, 0755)
+ err = os.WriteFile(filename, modelsData, 0o755)
if err != nil {
return err
}
@@ -165,6 +221,39 @@ func (b *Bindings) WriteModels(modelsDir string) error {
return nil
}
+func (b *Bindings) AddEnumToGenerateTS(e interface{}) {
+ enumType := reflect.TypeOf(e)
+
+ var packageName string
+ var enumName string
+ // enums should be represented as array of all possible values
+ if hasElements(enumType) {
+ enum := enumType.Elem()
+ // simple enum represented by struct with Value/TSName fields
+ if enum.Kind() == reflect.Struct {
+ _, tsNamePresented := enum.FieldByName("TSName")
+ enumT, valuePresented := enum.FieldByName("Value")
+ if tsNamePresented && valuePresented {
+ packageName = getPackageName(enumT.Type.String())
+ enumName = enumT.Type.Name()
+ } else {
+ return
+ }
+ // otherwise expecting implementation with TSName() https://github.com/tkrajina/typescriptify-golang-structs#enums-with-tsname
+ } else {
+ packageName = getPackageName(enumType.Elem().String())
+ enumName = enumType.Elem().Name()
+ }
+ if b.enumsToGenerateTS[packageName] == nil {
+ b.enumsToGenerateTS[packageName] = make(map[string]interface{})
+ }
+ if b.enumsToGenerateTS[packageName][enumName] != nil {
+ return
+ }
+ b.enumsToGenerateTS[packageName][enumName] = e
+ }
+}
+
func (b *Bindings) AddStructToGenerateTS(packageName string, structName string, s interface{}) {
if b.structsToGenerateTS[packageName] == nil {
b.structsToGenerateTS[packageName] = make(map[string]interface{})
@@ -176,22 +265,19 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string,
// Iterate this struct and add any struct field references
structType := reflect.TypeOf(s)
- if hasElements(structType) {
+ for hasElements(structType) {
structType = structType.Elem()
}
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
- if field.Anonymous {
+ if field.Anonymous || !field.IsExported() {
continue
}
kind := field.Type.Kind()
if kind == reflect.Struct {
- if !field.IsExported() {
- continue
- }
fqname := field.Type.String()
- sNameSplit := strings.Split(fqname, ".")
+ sNameSplit := strings.SplitN(fqname, ".", 2)
if len(sNameSplit) < 2 {
continue
}
@@ -202,22 +288,24 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string,
s := reflect.Indirect(a).Interface()
b.AddStructToGenerateTS(pName, sName, s)
}
- } else if hasElements(field.Type) && field.Type.Elem().Kind() == reflect.Struct {
- if !field.IsExported() {
- continue
+ } else {
+ fType := field.Type
+ for hasElements(fType) {
+ fType = fType.Elem()
}
- fqname := field.Type.Elem().String()
- sNameSplit := strings.Split(fqname, ".")
- if len(sNameSplit) < 2 {
- continue
- }
- sName := sNameSplit[1]
- pName := getPackageName(fqname)
- typ := field.Type.Elem()
- a := reflect.New(typ)
- if b.hasExportedJSONFields(typ) {
- s := reflect.Indirect(a).Interface()
- b.AddStructToGenerateTS(pName, sName, s)
+ if fType.Kind() == reflect.Struct {
+ fqname := fType.String()
+ sNameSplit := strings.SplitN(fqname, ".", 2)
+ if len(sNameSplit) < 2 {
+ continue
+ }
+ sName := sNameSplit[1]
+ pName := getPackageName(fqname)
+ a := reflect.New(fType)
+ if b.hasExportedJSONFields(fType) {
+ s := reflect.Indirect(a).Interface()
+ b.AddStructToGenerateTS(pName, sName, s)
+ }
}
}
}
@@ -233,6 +321,13 @@ func (b *Bindings) SetTsSuffix(postfix string) *Bindings {
return b
}
+func (b *Bindings) SetOutputType(outputType string) *Bindings {
+ if outputType == "interfaces" {
+ b.tsInterface = true
+ }
+ return b
+}
+
func (b *Bindings) getAllStructNames() *slicer.StringSlicer {
var result slicer.StringSlicer
for packageName, structsToGenerate := range b.structsToGenerateTS {
@@ -243,11 +338,32 @@ func (b *Bindings) getAllStructNames() *slicer.StringSlicer {
return &result
}
+func (b *Bindings) getAllEnumNames() *slicer.StringSlicer {
+ var result slicer.StringSlicer
+ for packageName, enumsToGenerate := range b.enumsToGenerateTS {
+ for enumName := range enumsToGenerate {
+ result.Add(packageName + "." + enumName)
+ }
+ }
+ return &result
+}
+
func (b *Bindings) hasExportedJSONFields(typeOf reflect.Type) bool {
for i := 0; i < typeOf.NumField(); i++ {
jsonFieldName := ""
f := typeOf.Field(i)
- jsonTag := f.Tag.Get("json")
+ // function, complex, and channel types cannot be json-encoded
+ if f.Type.Kind() == reflect.Chan ||
+ f.Type.Kind() == reflect.Func ||
+ f.Type.Kind() == reflect.UnsafePointer ||
+ f.Type.Kind() == reflect.Complex128 ||
+ f.Type.Kind() == reflect.Complex64 {
+ continue
+ }
+ jsonTag, hasTag := f.Tag.Lookup("json")
+ if !hasTag && f.IsExported() {
+ return true
+ }
if len(jsonTag) == 0 {
continue
}
diff --git a/v2/internal/binding/binding_test/binding_anonymous_sub_struct_multi_level_test.go b/v2/internal/binding/binding_test/binding_anonymous_sub_struct_multi_level_test.go
index 3c888ab27..29777481b 100644
--- a/v2/internal/binding/binding_test/binding_anonymous_sub_struct_multi_level_test.go
+++ b/v2/internal/binding/binding_test/binding_anonymous_sub_struct_multi_level_test.go
@@ -45,7 +45,7 @@ export namespace binding_test {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_anonymous_sub_struct_test.go b/v2/internal/binding/binding_test/binding_anonymous_sub_struct_test.go
index 53617efac..11afe4f0d 100644
--- a/v2/internal/binding/binding_test/binding_anonymous_sub_struct_test.go
+++ b/v2/internal/binding/binding_test/binding_anonymous_sub_struct_test.go
@@ -39,7 +39,7 @@ export namespace binding_test {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_conflicting_package_name_test.go b/v2/internal/binding/binding_test/binding_conflicting_package_name_test.go
index 2309d6daf..b37334ec3 100644
--- a/v2/internal/binding/binding_test/binding_conflicting_package_name_test.go
+++ b/v2/internal/binding/binding_test/binding_conflicting_package_name_test.go
@@ -42,7 +42,7 @@ func TestConflictingPackageName(t *testing.T) {
// setup
testLogger := &logger.Logger{}
- b := binding.NewBindings(testLogger, []interface{}{&HandlerTest{}}, []interface{}{}, false)
+ b := binding.NewBindings(testLogger, []interface{}{&HandlerTest{}}, []interface{}{}, false, []interface{}{})
// then
err := b.GenerateGoBindings(generationDir)
diff --git a/v2/internal/binding/binding_test/binding_deepelements_test.go b/v2/internal/binding/binding_test/binding_deepelements_test.go
new file mode 100644
index 000000000..034687474
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_deepelements_test.go
@@ -0,0 +1,126 @@
+package binding_test
+
+// Issues 2303, 3442, 3709
+
+type DeepMessage struct {
+ Msg string
+}
+
+type DeepElements struct {
+ Single []int
+ Double [][]string
+ FourDouble [4][]float64
+ DoubleFour [][4]int64
+ Triple [][][]int
+
+ SingleMap map[string]int
+ SliceMap map[string][]int
+ DoubleSliceMap map[string][][]int
+
+ ArrayMap map[string][4]int
+ DoubleArrayMap1 map[string][4][]int
+ DoubleArrayMap2 map[string][][4]int
+ DoubleArrayMap3 map[string][4][4]int
+
+ OneStructs []*DeepMessage
+ TwoStructs [3][]*DeepMessage
+ ThreeStructs [][][]DeepMessage
+ MapStructs map[string][]*DeepMessage
+ MapTwoStructs map[string][4][]DeepMessage
+ MapThreeStructs map[string][][7][]*DeepMessage
+}
+
+func (x DeepElements) Get() DeepElements {
+ return x
+}
+
+var DeepElementsTest = BindingTest{
+ name: "DeepElements",
+ structs: []interface{}{
+ &DeepElements{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+
+ export class DeepMessage {
+ Msg: string;
+
+ static createFrom(source: any = {}) {
+ return new DeepMessage(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Msg = source["Msg"];
+ }
+ }
+ export class DeepElements {
+ Single: number[];
+ Double: string[][];
+ FourDouble: number[][];
+ DoubleFour: number[][];
+ Triple: number[][][];
+ SingleMap: Record;
+ SliceMap: Record>;
+ DoubleSliceMap: Record>>;
+ ArrayMap: Record>;
+ DoubleArrayMap1: Record>>;
+ DoubleArrayMap2: Record>>;
+ DoubleArrayMap3: Record>>;
+ OneStructs: DeepMessage[];
+ TwoStructs: DeepMessage[][];
+ ThreeStructs: DeepMessage[][][];
+ MapStructs: Record>;
+ MapTwoStructs: Record>>;
+ MapThreeStructs: Record>>>;
+
+ static createFrom(source: any = {}) {
+ return new DeepElements(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Single = source["Single"];
+ this.Double = source["Double"];
+ this.FourDouble = source["FourDouble"];
+ this.DoubleFour = source["DoubleFour"];
+ this.Triple = source["Triple"];
+ this.SingleMap = source["SingleMap"];
+ this.SliceMap = source["SliceMap"];
+ this.DoubleSliceMap = source["DoubleSliceMap"];
+ this.ArrayMap = source["ArrayMap"];
+ this.DoubleArrayMap1 = source["DoubleArrayMap1"];
+ this.DoubleArrayMap2 = source["DoubleArrayMap2"];
+ this.DoubleArrayMap3 = source["DoubleArrayMap3"];
+ this.OneStructs = this.convertValues(source["OneStructs"], DeepMessage);
+ this.TwoStructs = this.convertValues(source["TwoStructs"], DeepMessage);
+ this.ThreeStructs = this.convertValues(source["ThreeStructs"], DeepMessage);
+ this.MapStructs = this.convertValues(source["MapStructs"], Array, true);
+ this.MapTwoStructs = this.convertValues(source["MapTwoStructs"], Array>, true);
+ this.MapThreeStructs = this.convertValues(source["MapThreeStructs"], Array>>, true);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+
+ }
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_emptystruct_test.go b/v2/internal/binding/binding_test/binding_emptystruct_test.go
index c36603e64..ffb85e865 100644
--- a/v2/internal/binding/binding_test/binding_emptystruct_test.go
+++ b/v2/internal/binding/binding_test/binding_emptystruct_test.go
@@ -34,7 +34,7 @@ export namespace binding_test {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_enum_ordering_test.go b/v2/internal/binding/binding_test/binding_enum_ordering_test.go
new file mode 100644
index 000000000..0939535ec
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_enum_ordering_test.go
@@ -0,0 +1,271 @@
+package binding_test
+
+// Test for PR #4664: Fix generated enums ordering
+// This test ensures that enum output is deterministic regardless of map iteration order
+
+// ZFirstEnum - named with Z prefix to test alphabetical sorting
+type ZFirstEnum int
+
+const (
+ ZFirstEnumValue1 ZFirstEnum = iota
+ ZFirstEnumValue2
+)
+
+var AllZFirstEnumValues = []struct {
+ Value ZFirstEnum
+ TSName string
+}{
+ {ZFirstEnumValue1, "ZValue1"},
+ {ZFirstEnumValue2, "ZValue2"},
+}
+
+// ASecondEnum - named with A prefix to test alphabetical sorting
+type ASecondEnum int
+
+const (
+ ASecondEnumValue1 ASecondEnum = iota
+ ASecondEnumValue2
+)
+
+var AllASecondEnumValues = []struct {
+ Value ASecondEnum
+ TSName string
+}{
+ {ASecondEnumValue1, "AValue1"},
+ {ASecondEnumValue2, "AValue2"},
+}
+
+// MMiddleEnum - named with M prefix to test alphabetical sorting
+type MMiddleEnum int
+
+const (
+ MMiddleEnumValue1 MMiddleEnum = iota
+ MMiddleEnumValue2
+)
+
+var AllMMiddleEnumValues = []struct {
+ Value MMiddleEnum
+ TSName string
+}{
+ {MMiddleEnumValue1, "MValue1"},
+ {MMiddleEnumValue2, "MValue2"},
+}
+
+type EntityWithMultipleEnums struct {
+ Name string `json:"name"`
+ EnumZ ZFirstEnum `json:"enumZ"`
+ EnumA ASecondEnum `json:"enumA"`
+ EnumM MMiddleEnum `json:"enumM"`
+}
+
+func (e EntityWithMultipleEnums) Get() EntityWithMultipleEnums {
+ return e
+}
+
+// EnumOrderingTest tests that multiple enums in the same package are output
+// in alphabetical order by enum name. Before PR #4664, the order was
+// non-deterministic due to Go map iteration order.
+var EnumOrderingTest = BindingTest{
+ name: "EnumOrderingTest",
+ structs: []interface{}{
+ &EntityWithMultipleEnums{},
+ },
+ enums: []interface{}{
+ // Intentionally add enums in non-alphabetical order
+ AllZFirstEnumValues,
+ AllASecondEnumValues,
+ AllMMiddleEnumValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "",
+ TsSuffix: "",
+ },
+ // Expected output should have enums in alphabetical order: ASecondEnum, MMiddleEnum, ZFirstEnum
+ want: `export namespace binding_test {
+
+ export enum ASecondEnum {
+ AValue1 = 0,
+ AValue2 = 1,
+ }
+ export enum MMiddleEnum {
+ MValue1 = 0,
+ MValue2 = 1,
+ }
+ export enum ZFirstEnum {
+ ZValue1 = 0,
+ ZValue2 = 1,
+ }
+ export class EntityWithMultipleEnums {
+ name: string;
+ enumZ: ZFirstEnum;
+ enumA: ASecondEnum;
+ enumM: MMiddleEnum;
+
+ static createFrom(source: any = {}) {
+ return new EntityWithMultipleEnums(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enumZ = source["enumZ"];
+ this.enumA = source["enumA"];
+ this.enumM = source["enumM"];
+ }
+ }
+
+}
+`,
+}
+
+// EnumElementOrderingEnum tests sorting of enum elements by TSName
+type EnumElementOrderingEnum string
+
+const (
+ EnumElementZ EnumElementOrderingEnum = "z_value"
+ EnumElementA EnumElementOrderingEnum = "a_value"
+ EnumElementM EnumElementOrderingEnum = "m_value"
+)
+
+// AllEnumElementOrderingValues intentionally lists values out of alphabetical order
+// to test that AddEnum sorts them
+var AllEnumElementOrderingValues = []struct {
+ Value EnumElementOrderingEnum
+ TSName string
+}{
+ {EnumElementZ, "Zebra"},
+ {EnumElementA, "Apple"},
+ {EnumElementM, "Mango"},
+}
+
+type EntityWithUnorderedEnumElements struct {
+ Name string `json:"name"`
+ Enum EnumElementOrderingEnum `json:"enum"`
+}
+
+func (e EntityWithUnorderedEnumElements) Get() EntityWithUnorderedEnumElements {
+ return e
+}
+
+// EnumElementOrderingTest tests that enum elements are sorted alphabetically
+// by their TSName within an enum. Before PR #4664, elements appeared in the
+// order they were added, which could be arbitrary.
+var EnumElementOrderingTest = BindingTest{
+ name: "EnumElementOrderingTest",
+ structs: []interface{}{
+ &EntityWithUnorderedEnumElements{},
+ },
+ enums: []interface{}{
+ AllEnumElementOrderingValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "",
+ TsSuffix: "",
+ },
+ // Expected output should have enum elements sorted: Apple, Mango, Zebra
+ want: `export namespace binding_test {
+
+ export enum EnumElementOrderingEnum {
+ Apple = "a_value",
+ Mango = "m_value",
+ Zebra = "z_value",
+ }
+ export class EntityWithUnorderedEnumElements {
+ name: string;
+ enum: EnumElementOrderingEnum;
+
+ static createFrom(source: any = {}) {
+ return new EntityWithUnorderedEnumElements(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enum = source["enum"];
+ }
+ }
+
+}
+`,
+}
+
+// TSNameEnumElementOrdering tests sorting with TSName() method enum
+type TSNameEnumElementOrdering string
+
+const (
+ TSNameEnumZ TSNameEnumElementOrdering = "z_value"
+ TSNameEnumA TSNameEnumElementOrdering = "a_value"
+ TSNameEnumM TSNameEnumElementOrdering = "m_value"
+)
+
+func (v TSNameEnumElementOrdering) TSName() string {
+ switch v {
+ case TSNameEnumZ:
+ return "Zebra"
+ case TSNameEnumA:
+ return "Apple"
+ case TSNameEnumM:
+ return "Mango"
+ default:
+ return "Unknown"
+ }
+}
+
+// AllTSNameEnumValues intentionally out of order
+var AllTSNameEnumValues = []TSNameEnumElementOrdering{TSNameEnumZ, TSNameEnumA, TSNameEnumM}
+
+type EntityWithTSNameEnumOrdering struct {
+ Name string `json:"name"`
+ Enum TSNameEnumElementOrdering `json:"enum"`
+}
+
+func (e EntityWithTSNameEnumOrdering) Get() EntityWithTSNameEnumOrdering {
+ return e
+}
+
+// TSNameEnumElementOrderingTest tests that enums using TSName() method
+// also have their elements sorted alphabetically by the TSName.
+var TSNameEnumElementOrderingTest = BindingTest{
+ name: "TSNameEnumElementOrderingTest",
+ structs: []interface{}{
+ &EntityWithTSNameEnumOrdering{},
+ },
+ enums: []interface{}{
+ AllTSNameEnumValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "",
+ TsSuffix: "",
+ },
+ // Expected output should have enum elements sorted: Apple, Mango, Zebra
+ want: `export namespace binding_test {
+
+ export enum TSNameEnumElementOrdering {
+ Apple = "a_value",
+ Mango = "m_value",
+ Zebra = "z_value",
+ }
+ export class EntityWithTSNameEnumOrdering {
+ name: string;
+ enum: TSNameEnumElementOrdering;
+
+ static createFrom(source: any = {}) {
+ return new EntityWithTSNameEnumOrdering(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enum = source["enum"];
+ }
+ }
+
+}
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_generics_test.go b/v2/internal/binding/binding_test/binding_generics_test.go
new file mode 100644
index 000000000..920bd2a7a
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_generics_test.go
@@ -0,0 +1,154 @@
+package binding_test
+
+import "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import/float_package"
+
+// Issues 3900, 3371, 2323 (no TS generics though)
+
+type ListData[T interface{}] struct {
+ Total int64 `json:"Total"`
+ TotalPage int64 `json:"TotalPage"`
+ PageNum int `json:"PageNum"`
+ List []T `json:"List,omitempty"`
+}
+
+func (x ListData[T]) Get() ListData[T] {
+ return x
+}
+
+var Generics1Test = BindingTest{
+ name: "Generics1",
+ structs: []interface{}{
+ &ListData[string]{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+
+ export class ListData_string_ {
+ Total: number;
+ TotalPage: number;
+ PageNum: number;
+ List?: string[];
+
+ static createFrom(source: any = {}) {
+ return new ListData_string_(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Total = source["Total"];
+ this.TotalPage = source["TotalPage"];
+ this.PageNum = source["PageNum"];
+ this.List = source["List"];
+ }
+ }
+
+ }
+`,
+}
+
+var Generics2Test = BindingTest{
+ name: "Generics2",
+ structs: []interface{}{
+ &ListData[float_package.SomeStruct]{},
+ &ListData[*float_package.SomeStruct]{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+
+ export class ListData__github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_ {
+ Total: number;
+ TotalPage: number;
+ PageNum: number;
+ List?: float_package.SomeStruct[];
+
+ static createFrom(source: any = {}) {
+ return new ListData__github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Total = source["Total"];
+ this.TotalPage = source["TotalPage"];
+ this.PageNum = source["PageNum"];
+ this.List = this.convertValues(source["List"], float_package.SomeStruct);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+ export class ListData_github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_ {
+ Total: number;
+ TotalPage: number;
+ PageNum: number;
+ List?: float_package.SomeStruct[];
+
+ static createFrom(source: any = {}) {
+ return new ListData_github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Total = source["Total"];
+ this.TotalPage = source["TotalPage"];
+ this.PageNum = source["PageNum"];
+ this.List = this.convertValues(source["List"], float_package.SomeStruct);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+
+ }
+
+ export namespace float_package {
+
+ export class SomeStruct {
+ string: string;
+
+ static createFrom(source: any = {}) {
+ return new SomeStruct(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.string = source["string"];
+ }
+ }
+
+ }
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_ignored_test.go b/v2/internal/binding/binding_test/binding_ignored_test.go
new file mode 100644
index 000000000..aeb6a9c3f
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_ignored_test.go
@@ -0,0 +1,47 @@
+package binding_test
+
+import (
+ "unsafe"
+)
+
+// Issues 3755, 3809
+
+type Ignored struct {
+ Valid bool
+ Total func() int `json:"Total"`
+ UnsafeP unsafe.Pointer
+ Complex64 complex64 `json:"Complex"`
+ Complex128 complex128
+ StringChan chan string
+}
+
+func (x Ignored) Get() Ignored {
+ return x
+}
+
+var IgnoredTest = BindingTest{
+ name: "Ignored",
+ structs: []interface{}{
+ &Ignored{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+
+ export class Ignored {
+ Valid: boolean;
+
+ static createFrom(source: any = {}) {
+ return new Ignored(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Valid = source["Valid"];
+ }
+ }
+
+ }
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_importedenum_test.go b/v2/internal/binding/binding_test/binding_importedenum_test.go
new file mode 100644
index 000000000..5b5b4419e
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_importedenum_test.go
@@ -0,0 +1,50 @@
+package binding_test
+
+import "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import"
+
+type ImportedEnumStruct struct {
+ EnumValue binding_test_import.ImportedEnum `json:"EnumValue"`
+}
+
+func (s ImportedEnumStruct) Get() ImportedEnumStruct {
+ return s
+}
+
+var ImportedEnumTest = BindingTest{
+ name: "ImportedEnum",
+ structs: []interface{}{
+ &ImportedEnumStruct{},
+ },
+ enums: []interface{}{
+ binding_test_import.AllImportedEnumValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `export namespace binding_test {
+
+ export class ImportedEnumStruct {
+ EnumValue: binding_test_import.ImportedEnum;
+
+ static createFrom(source: any = {}) {
+ return new ImportedEnumStruct(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.EnumValue = source["EnumValue"];
+ }
+ }
+
+ }
+
+ export namespace binding_test_import {
+
+ export enum ImportedEnum {
+ Value1 = "value1",
+ Value2 = "value2",
+ Value3 = "value3",
+ }
+
+ }
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_importedmap_test.go b/v2/internal/binding/binding_test/binding_importedmap_test.go
index 54fb261a8..4a4b2996c 100644
--- a/v2/internal/binding/binding_test/binding_importedmap_test.go
+++ b/v2/internal/binding/binding_test/binding_importedmap_test.go
@@ -32,7 +32,7 @@ export namespace binding_test {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
@@ -50,7 +50,7 @@ export namespace binding_test {
export namespace binding_test_import {
export class AMapWrapper {
- AMap: {[key: string]: binding_test_nestedimport.A};
+ AMap: Record;
static createFrom(source: any = {}) {
return new AMapWrapper(source);
}
@@ -62,7 +62,7 @@ export namespace binding_test_import {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_importedslice_test.go b/v2/internal/binding/binding_test/binding_importedslice_test.go
index b4a63689c..5abf55b43 100644
--- a/v2/internal/binding/binding_test/binding_importedslice_test.go
+++ b/v2/internal/binding/binding_test/binding_importedslice_test.go
@@ -32,7 +32,7 @@ export namespace binding_test {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
@@ -62,7 +62,7 @@ export namespace binding_test_import {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_importedstruct_test.go b/v2/internal/binding/binding_test/binding_importedstruct_test.go
index 1629be9fa..1e94453c2 100644
--- a/v2/internal/binding/binding_test/binding_importedstruct_test.go
+++ b/v2/internal/binding/binding_test/binding_importedstruct_test.go
@@ -33,7 +33,7 @@ export namespace binding_test {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
@@ -63,7 +63,7 @@ export namespace binding_test_import {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_nestedfield_test.go b/v2/internal/binding/binding_test/binding_nestedfield_test.go
index c2e4fcf9f..66dd11cbf 100644
--- a/v2/internal/binding/binding_test/binding_nestedfield_test.go
+++ b/v2/internal/binding/binding_test/binding_nestedfield_test.go
@@ -44,7 +44,7 @@ export namespace binding_test {
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
diff --git a/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go b/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go
index 37a61dd29..9efee710f 100644
--- a/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go
+++ b/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go
@@ -18,7 +18,7 @@ var NonStringMapKeyTest = BindingTest{
want: `
export namespace binding_test {
export class NonStringMapKey {
- numberMap: {[key: number]: any};
+ numberMap: Record;
static createFrom(source: any = {}) {
return new NonStringMapKey(source);
}
diff --git a/v2/internal/binding/binding_test/binding_notags_test.go b/v2/internal/binding/binding_test/binding_notags_test.go
new file mode 100644
index 000000000..d4d9997e0
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_notags_test.go
@@ -0,0 +1,60 @@
+package binding_test
+
+type NoFieldTags struct {
+ Name string
+ Address string
+ Zip *string
+ Spouse *NoFieldTags
+ NoFunc func() string
+}
+
+func (n NoFieldTags) Get() NoFieldTags {
+ return n
+}
+
+var NoFieldTagsTest = BindingTest{
+ name: "NoFieldTags",
+ structs: []interface{}{
+ &NoFieldTags{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+ export class NoFieldTags {
+ Name: string;
+ Address: string;
+ Zip?: string;
+ Spouse?: NoFieldTags;
+ static createFrom(source: any = {}) {
+ return new NoFieldTags(source);
+ }
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Name = source["Name"];
+ this.Address = source["Address"];
+ this.Zip = source["Zip"];
+ this.Spouse = this.convertValues(source["Spouse"], NoFieldTags);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+}
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_returned_promises_test.go b/v2/internal/binding/binding_test/binding_returned_promises_test.go
index 35c22569c..94941d0a3 100644
--- a/v2/internal/binding/binding_test/binding_returned_promises_test.go
+++ b/v2/internal/binding/binding_test/binding_returned_promises_test.go
@@ -11,6 +11,7 @@ import (
const expectedPromiseBindings = `// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
+import {binding_test} from '../models';
export function ErrorReturn(arg1:number):Promise;
@@ -18,16 +19,37 @@ export function NoReturn(arg1:string):Promise;
export function SingleReturn(arg1:any):Promise;
+export function SingleReturnStruct(arg1:any):Promise;
+
+export function SingleReturnStructPointer(arg1:any):Promise;
+
+export function SingleReturnStructPointerSlice(arg1:any):Promise>;
+
+export function SingleReturnStructSlice(arg1:any):Promise>;
+
export function SingleReturnWithError(arg1:number):Promise;
export function TwoReturn(arg1:any):Promise;
`
type PromisesTest struct{}
+type PromisesTestReturnStruct struct{}
-func (h *PromisesTest) NoReturn(_ string) {}
-func (h *PromisesTest) ErrorReturn(_ int) error { return nil }
-func (h *PromisesTest) SingleReturn(_ interface{}) int { return 0 }
+func (h *PromisesTest) NoReturn(_ string) {}
+func (h *PromisesTest) ErrorReturn(_ int) error { return nil }
+func (h *PromisesTest) SingleReturn(_ interface{}) int { return 0 }
+func (h *PromisesTest) SingleReturnStructPointer(_ interface{}) *PromisesTestReturnStruct {
+ return &PromisesTestReturnStruct{}
+}
+func (h *PromisesTest) SingleReturnStruct(_ interface{}) PromisesTestReturnStruct {
+ return PromisesTestReturnStruct{}
+}
+func (h *PromisesTest) SingleReturnStructSlice(_ interface{}) []PromisesTestReturnStruct {
+ return []PromisesTestReturnStruct{}
+}
+func (h *PromisesTest) SingleReturnStructPointerSlice(_ interface{}) []*PromisesTestReturnStruct {
+ return []*PromisesTestReturnStruct{}
+}
func (h *PromisesTest) SingleReturnWithError(_ int) (string, error) { return "", nil }
func (h *PromisesTest) TwoReturn(_ interface{}) (string, int) { return "", 0 }
@@ -37,7 +59,7 @@ func TestPromises(t *testing.T) {
// setup
testLogger := &logger.Logger{}
- b := binding.NewBindings(testLogger, []interface{}{&PromisesTest{}}, []interface{}{}, false)
+ b := binding.NewBindings(testLogger, []interface{}{&PromisesTest{}}, []interface{}{}, false, []interface{}{})
// then
err := b.GenerateGoBindings(generationDir)
diff --git a/v2/internal/binding/binding_test/binding_structwithoutfields_test.go b/v2/internal/binding/binding_test/binding_structwithoutfields_test.go
new file mode 100644
index 000000000..4b2289b98
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_structwithoutfields_test.go
@@ -0,0 +1,34 @@
+package binding_test
+
+type WithoutFields struct {
+}
+
+func (s WithoutFields) Get() WithoutFields {
+ return s
+}
+
+var WithoutFieldsTest = BindingTest{
+ name: "StructWithoutFields",
+ structs: []interface{}{
+ &WithoutFields{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+
+ export class WithoutFields {
+
+
+ static createFrom(source: any = {}) {
+ return new WithoutFields(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+
+ }
+ }
+
+}`,
+}
diff --git a/v2/internal/binding/binding_test/binding_test.go b/v2/internal/binding/binding_test/binding_test.go
index 0b143db17..41f0618ce 100644
--- a/v2/internal/binding/binding_test/binding_test.go
+++ b/v2/internal/binding/binding_test/binding_test.go
@@ -13,6 +13,7 @@ import (
type BindingTest struct {
name string
structs []interface{}
+ enums []interface{}
exemptions []interface{}
want string
shouldError bool
@@ -20,8 +21,9 @@ type BindingTest struct {
}
type TsGenerationOptionsTest struct {
- TsPrefix string
- TsSuffix string
+ TsPrefix string
+ TsSuffix string
+ TsOutputType string
}
func TestBindings_GenerateModels(t *testing.T) {
@@ -31,28 +33,45 @@ func TestBindings_GenerateModels(t *testing.T) {
ImportedStructTest,
ImportedSliceTest,
ImportedMapTest,
+ ImportedEnumTest,
NestedFieldTest,
NonStringMapKeyTest,
SingleFieldTest,
MultistructTest,
EmptyStructTest,
GeneratedJsEntityTest,
+ GeneratedJsEntityWithIntEnumTest,
+ GeneratedJsEntityWithStringEnumTest,
+ GeneratedJsEntityWithEnumTsName,
+ GeneratedJsEntityWithNestedStructInterfacesTest,
AnonymousSubStructTest,
AnonymousSubStructMultiLevelTest,
+ GeneratedJsEntityWithNestedStructTest,
+ EntityWithDiffNamespacesTest,
+ SpecialCharacterFieldTest,
+ WithoutFieldsTest,
+ NoFieldTagsTest,
+ Generics1Test,
+ Generics2Test,
+ IgnoredTest,
+ DeepElementsTest,
+ // PR #4664: Enum ordering tests
+ EnumOrderingTest,
+ EnumElementOrderingTest,
+ TSNameEnumElementOrderingTest,
}
testLogger := &logger.Logger{}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- b := binding.NewBindings(testLogger, tt.structs, tt.exemptions, false)
+ b := binding.NewBindings(testLogger, tt.structs, tt.exemptions, false, tt.enums)
for _, s := range tt.structs {
err := b.Add(s)
require.NoError(t, err)
}
b.SetTsPrefix(tt.TsPrefix)
-
- // TODO - rename this to SetTsSuffix
b.SetTsSuffix(tt.TsSuffix)
+ b.SetOutputType(tt.TsOutputType)
got, err := b.GenerateModels()
if (err != nil) != tt.shouldError {
t.Errorf("GenerateModels() error = %v, shouldError %v", err, tt.shouldError)
diff --git a/v2/internal/binding/binding_test/binding_test_import/binding_test_import.go b/v2/internal/binding/binding_test/binding_test_import/binding_test_import.go
index 6b99d43be..e7080c694 100644
--- a/v2/internal/binding/binding_test/binding_test_import/binding_test_import.go
+++ b/v2/internal/binding/binding_test/binding_test_import/binding_test_import.go
@@ -13,3 +13,20 @@ type ASliceWrapper struct {
type AMapWrapper struct {
AMap map[string]binding_test_nestedimport.A `json:"AMap"`
}
+
+type ImportedEnum string
+
+const (
+ ImportedEnumValue1 ImportedEnum = "value1"
+ ImportedEnumValue2 ImportedEnum = "value2"
+ ImportedEnumValue3 ImportedEnum = "value3"
+)
+
+var AllImportedEnumValues = []struct {
+ Value ImportedEnum
+ TSName string
+}{
+ {ImportedEnumValue1, "Value1"},
+ {ImportedEnumValue2, "Value2"},
+ {ImportedEnumValue3, "Value3"},
+}
diff --git a/v2/internal/binding/binding_test/binding_tsgeneration_test.go b/v2/internal/binding/binding_test/binding_tsgeneration_test.go
index b808ad9c6..850bc778a 100644
--- a/v2/internal/binding/binding_test/binding_tsgeneration_test.go
+++ b/v2/internal/binding/binding_test/binding_tsgeneration_test.go
@@ -1,5 +1,9 @@
package binding_test
+import (
+ "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import"
+)
+
type GeneratedJsEntity struct {
Name string `json:"name"`
}
@@ -9,7 +13,7 @@ func (s GeneratedJsEntity) Get() GeneratedJsEntity {
}
var GeneratedJsEntityTest = BindingTest{
- name: "GeneratedJsEntityTest ",
+ name: "GeneratedJsEntityTest",
structs: []interface{}{
&GeneratedJsEntity{},
},
@@ -39,3 +43,467 @@ export namespace binding_test {
`,
}
+
+type ParentEntity struct {
+ Name string `json:"name"`
+ Ref ChildEntity `json:"ref"`
+ ParentProp string `json:"parentProp"`
+}
+
+func (p ParentEntity) Get() ParentEntity {
+ return p
+}
+
+type ChildEntity struct {
+ Name string `json:"name"`
+ ChildProp int `json:"childProp"`
+}
+
+var GeneratedJsEntityWithNestedStructTest = BindingTest{
+ name: "GeneratedJsEntityWithNestedStructTest",
+ structs: []interface{}{
+ &ParentEntity{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ },
+ want: `
+export namespace binding_test {
+
+ export class MY_PREFIX_ChildEntity_MY_SUFFIX {
+ name: string;
+ childProp: number;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_ChildEntity_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.childProp = source["childProp"];
+ }
+ }
+ export class MY_PREFIX_ParentEntity_MY_SUFFIX {
+ name: string;
+ ref: MY_PREFIX_ChildEntity_MY_SUFFIX;
+ parentProp: string;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_ParentEntity_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.ref = this.convertValues(source["ref"], MY_PREFIX_ChildEntity_MY_SUFFIX);
+ this.parentProp = source["parentProp"];
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+
+ }
+`,
+}
+
+type ParentPackageEntity struct {
+ Name string `json:"name"`
+ Ref ChildPackageEntity `json:"ref"`
+}
+
+func (p ParentPackageEntity) Get() ParentPackageEntity {
+ return p
+}
+
+type ChildPackageEntity struct {
+ Name string `json:"name"`
+ ImportedPackage binding_test_import.AWrapper `json:"importedPackage"`
+}
+
+var EntityWithDiffNamespacesTest = BindingTest{
+ name: "EntityWithDiffNamespaces ",
+ structs: []interface{}{
+ &ParentPackageEntity{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ },
+ want: `
+export namespace binding_test {
+
+ export class MY_PREFIX_ChildPackageEntity_MY_SUFFIX {
+ name: string;
+ importedPackage: binding_test_import.MY_PREFIX_AWrapper_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_ChildPackageEntity_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.importedPackage = this.convertValues(source["importedPackage"], binding_test_import.MY_PREFIX_AWrapper_MY_SUFFIX);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+ export class MY_PREFIX_ParentPackageEntity_MY_SUFFIX {
+ name: string;
+ ref: MY_PREFIX_ChildPackageEntity_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_ParentPackageEntity_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.ref = this.convertValues(source["ref"], MY_PREFIX_ChildPackageEntity_MY_SUFFIX);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+
+ }
+
+ export namespace binding_test_import {
+
+ export class MY_PREFIX_AWrapper_MY_SUFFIX {
+ AWrapper: binding_test_nestedimport.MY_PREFIX_A_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_AWrapper_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.AWrapper = this.convertValues(source["AWrapper"], binding_test_nestedimport.MY_PREFIX_A_MY_SUFFIX);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice && a.map) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
+
+ }
+
+ export namespace binding_test_nestedimport {
+
+ export class MY_PREFIX_A_MY_SUFFIX {
+ A: string;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_A_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.A = source["A"];
+ }
+ }
+
+ }
+
+`,
+}
+
+type IntEnum int
+
+const (
+ IntEnumValue1 IntEnum = iota
+ IntEnumValue2
+ IntEnumValue3
+)
+
+var AllIntEnumValues = []struct {
+ Value IntEnum
+ TSName string
+}{
+ {IntEnumValue1, "Value1"},
+ {IntEnumValue2, "Value2"},
+ {IntEnumValue3, "Value3"},
+}
+
+type EntityWithIntEnum struct {
+ Name string `json:"name"`
+ Enum IntEnum `json:"enum"`
+}
+
+func (e EntityWithIntEnum) Get() EntityWithIntEnum {
+ return e
+}
+
+var GeneratedJsEntityWithIntEnumTest = BindingTest{
+ name: "GeneratedJsEntityWithIntEnumTest",
+ structs: []interface{}{
+ &EntityWithIntEnum{},
+ },
+ enums: []interface{}{
+ AllIntEnumValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ },
+ want: `export namespace binding_test {
+
+ export enum MY_PREFIX_IntEnum_MY_SUFFIX {
+ Value1 = 0,
+ Value2 = 1,
+ Value3 = 2,
+ }
+ export class MY_PREFIX_EntityWithIntEnum_MY_SUFFIX {
+ name: string;
+ enum: MY_PREFIX_IntEnum_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_EntityWithIntEnum_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enum = source["enum"];
+ }
+ }
+
+ }
+`,
+}
+
+type StringEnum string
+
+const (
+ StringEnumValue1 StringEnum = "value1"
+ StringEnumValue2 StringEnum = "value2"
+ StringEnumValue3 StringEnum = "value3"
+)
+
+var AllStringEnumValues = []struct {
+ Value StringEnum
+ TSName string
+}{
+ {StringEnumValue1, "Value1"},
+ {StringEnumValue2, "Value2"},
+ {StringEnumValue3, "Value3"},
+}
+
+type EntityWithStringEnum struct {
+ Name string `json:"name"`
+ Enum StringEnum `json:"enum"`
+}
+
+func (e EntityWithStringEnum) Get() EntityWithStringEnum {
+ return e
+}
+
+var GeneratedJsEntityWithStringEnumTest = BindingTest{
+ name: "GeneratedJsEntityWithStringEnumTest",
+ structs: []interface{}{
+ &EntityWithStringEnum{},
+ },
+ enums: []interface{}{
+ AllStringEnumValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ },
+ want: `export namespace binding_test {
+
+ export enum MY_PREFIX_StringEnum_MY_SUFFIX {
+ Value1 = "value1",
+ Value2 = "value2",
+ Value3 = "value3",
+ }
+ export class MY_PREFIX_EntityWithStringEnum_MY_SUFFIX {
+ name: string;
+ enum: MY_PREFIX_StringEnum_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_EntityWithStringEnum_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enum = source["enum"];
+ }
+ }
+
+ }
+`,
+}
+
+type EnumWithTsName string
+
+const (
+ EnumWithTsName1 EnumWithTsName = "value1"
+ EnumWithTsName2 EnumWithTsName = "value2"
+ EnumWithTsName3 EnumWithTsName = "value3"
+)
+
+var AllEnumWithTsNameValues = []EnumWithTsName{EnumWithTsName1, EnumWithTsName2, EnumWithTsName3}
+
+func (v EnumWithTsName) TSName() string {
+ switch v {
+ case EnumWithTsName1:
+ return "TsName1"
+ case EnumWithTsName2:
+ return "TsName2"
+ case EnumWithTsName3:
+ return "TsName3"
+ default:
+ return "???"
+ }
+}
+
+type EntityWithEnumTsName struct {
+ Name string `json:"name"`
+ Enum EnumWithTsName `json:"enum"`
+}
+
+func (e EntityWithEnumTsName) Get() EntityWithEnumTsName {
+ return e
+}
+
+var GeneratedJsEntityWithEnumTsName = BindingTest{
+ name: "GeneratedJsEntityWithEnumTsName",
+ structs: []interface{}{
+ &EntityWithEnumTsName{},
+ },
+ enums: []interface{}{
+ AllEnumWithTsNameValues,
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ },
+ want: `export namespace binding_test {
+
+ export enum MY_PREFIX_EnumWithTsName_MY_SUFFIX {
+ TsName1 = "value1",
+ TsName2 = "value2",
+ TsName3 = "value3",
+ }
+ export class MY_PREFIX_EntityWithEnumTsName_MY_SUFFIX {
+ name: string;
+ enum: MY_PREFIX_EnumWithTsName_MY_SUFFIX;
+
+ static createFrom(source: any = {}) {
+ return new MY_PREFIX_EntityWithEnumTsName_MY_SUFFIX(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.enum = source["enum"];
+ }
+ }
+
+ }
+`,
+}
+
+var GeneratedJsEntityWithNestedStructInterfacesTest = BindingTest{
+ name: "GeneratedJsEntityWithNestedStructInterfacesTest",
+ structs: []interface{}{
+ &ParentEntity{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ TsGenerationOptionsTest: TsGenerationOptionsTest{
+ TsPrefix: "MY_PREFIX_",
+ TsSuffix: "_MY_SUFFIX",
+ TsOutputType: "interfaces",
+ },
+ want: `export namespace binding_test {
+
+ export interface MY_PREFIX_ChildEntity_MY_SUFFIX {
+ name: string;
+ childProp: number;
+ }
+ export interface MY_PREFIX_ParentEntity_MY_SUFFIX {
+ name: string;
+ ref: MY_PREFIX_ChildEntity_MY_SUFFIX;
+ parentProp: string;
+ }
+
+ }
+`,
+}
diff --git a/v2/internal/binding/binding_test/binding_type_alias_test.go b/v2/internal/binding/binding_test/binding_type_alias_test.go
new file mode 100644
index 000000000..90b009c5f
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_type_alias_test.go
@@ -0,0 +1,64 @@
+package binding_test
+
+import (
+ "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import/int_package"
+ "io/fs"
+ "os"
+ "testing"
+
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+const expectedTypeAliasBindings = `// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+import {binding_test} from '../models';
+import {int_package} from '../models';
+
+export function Map():Promise>;
+
+export function MapAlias():Promise;
+
+export function MapWithImportedStructValue():Promise>;
+
+export function Slice():Promise>;
+
+export function SliceImportedStruct():Promise>;
+`
+
+type AliasTest struct{}
+type MapAlias map[string]string
+
+func (h *AliasTest) Map() map[string]string { return nil }
+func (h *AliasTest) MapAlias() MapAlias { return nil }
+func (h *AliasTest) MapWithImportedStructValue() map[string]int_package.SomeStruct { return nil }
+func (h *AliasTest) Slice() []string { return nil }
+func (h *AliasTest) SliceImportedStruct() []int_package.SomeStruct { return nil }
+
+func TestAliases(t *testing.T) {
+ // given
+ generationDir := t.TempDir()
+
+ // setup
+ testLogger := &logger.Logger{}
+ b := binding.NewBindings(testLogger, []interface{}{&AliasTest{}}, []interface{}{}, false, []interface{}{})
+
+ // then
+ err := b.GenerateGoBindings(generationDir)
+ if err != nil {
+ t.Fatalf("could not generate the Go bindings: %v", err)
+ }
+
+ // then
+ rawGeneratedBindings, err := fs.ReadFile(os.DirFS(generationDir), "binding_test/AliasTest.d.ts")
+ if err != nil {
+ t.Fatalf("could not read the generated bindings: %v", err)
+ }
+
+ // then
+ generatedBindings := string(rawGeneratedBindings)
+ if generatedBindings != expectedTypeAliasBindings {
+ t.Fatalf("the generated bindings does not match the expected ones.\nWanted:\n%s\n\nGot:\n%s", expectedTypeAliasBindings,
+ generatedBindings)
+ }
+}
diff --git a/v2/internal/binding/binding_test/binding_variablespecialcharacter_test.go b/v2/internal/binding/binding_test/binding_variablespecialcharacter_test.go
new file mode 100644
index 000000000..7dbe72350
--- /dev/null
+++ b/v2/internal/binding/binding_test/binding_variablespecialcharacter_test.go
@@ -0,0 +1,32 @@
+package binding_test
+
+type SpecialCharacterField struct {
+ ID string `json:"@ID,omitempty"`
+}
+
+func (s SpecialCharacterField) Get() SpecialCharacterField {
+ return s
+}
+
+var SpecialCharacterFieldTest = BindingTest{
+ name: "SpecialCharacterField",
+ structs: []interface{}{
+ &SpecialCharacterField{},
+ },
+ exemptions: nil,
+ shouldError: false,
+ want: `
+export namespace binding_test {
+ export class SpecialCharacterField {
+ "@ID"?: string;
+ static createFrom(source: any = {}) {
+ return new SpecialCharacterField(source);
+ }
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this["@ID"] = source["@ID"];
+ }
+ }
+}
+`,
+}
diff --git a/v2/internal/binding/boundMethod.go b/v2/internal/binding/boundMethod.go
index f6ffdb600..e697041b0 100644
--- a/v2/internal/binding/boundMethod.go
+++ b/v2/internal/binding/boundMethod.go
@@ -6,14 +6,24 @@ import (
"reflect"
)
+type BoundedMethodPath struct {
+ Package string
+ Struct string
+ Name string
+}
+
+func (p *BoundedMethodPath) FullName() string {
+ return fmt.Sprintf("%s.%s.%s", p.Package, p.Struct, p.Name)
+}
+
// BoundMethod defines all the data related to a Go method that is
// bound to the Wails application
type BoundMethod struct {
- Name string `json:"name"`
- Inputs []*Parameter `json:"inputs,omitempty"`
- Outputs []*Parameter `json:"outputs,omitempty"`
- Comments string `json:"comments,omitempty"`
- Method reflect.Value `json:"-"`
+ Path *BoundedMethodPath `json:"path"`
+ Inputs []*Parameter `json:"inputs,omitempty"`
+ Outputs []*Parameter `json:"outputs,omitempty"`
+ Comments string `json:"comments,omitempty"`
+ Method reflect.Value `json:"-"`
}
// InputCount returns the number of inputs this bound method has
@@ -28,10 +38,9 @@ func (b *BoundMethod) OutputCount() int {
// ParseArgs method converts the input json into the types expected by the method
func (b *BoundMethod) ParseArgs(args []json.RawMessage) ([]interface{}, error) {
-
result := make([]interface{}, b.InputCount())
if len(args) != b.InputCount() {
- return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Name, b.InputCount())
+ return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Path.FullName(), b.InputCount())
}
for index, arg := range args {
typ := b.Inputs[index].reflectType
@@ -55,7 +64,7 @@ func (b *BoundMethod) Call(args []interface{}) (interface{}, error) {
expectedInputLength := len(b.Inputs)
actualInputLength := len(args)
if expectedInputLength != actualInputLength {
- return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Name, expectedInputLength, actualInputLength)
+ return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Path.FullName(), expectedInputLength, actualInputLength)
}
/** Convert inputs to reflect values **/
diff --git a/v2/internal/binding/db.go b/v2/internal/binding/db.go
index f22798680..f7b793839 100644
--- a/v2/internal/binding/db.go
+++ b/v2/internal/binding/db.go
@@ -2,7 +2,6 @@ package binding
import (
"encoding/json"
- "sort"
"sync"
"unsafe"
)
@@ -17,24 +16,28 @@ type DB struct {
methodMap map[string]*BoundMethod
// This uses ids to reference bound methods at runtime
- obfuscatedMethodMap map[int]*BoundMethod
+ obfuscatedMethodArray []*ObfuscatedMethod
// Lock to ensure sync access to the data
lock sync.RWMutex
}
+type ObfuscatedMethod struct {
+ method *BoundMethod
+ methodName string
+}
+
func newDB() *DB {
return &DB{
- store: make(map[string]map[string]map[string]*BoundMethod),
- methodMap: make(map[string]*BoundMethod),
- obfuscatedMethodMap: make(map[int]*BoundMethod),
+ store: make(map[string]map[string]map[string]*BoundMethod),
+ methodMap: make(map[string]*BoundMethod),
+ obfuscatedMethodArray: []*ObfuscatedMethod{},
}
}
// GetMethodFromStore returns the method for the given package/struct/method names
// nil is returned if any one of those does not exist
func (d *DB) GetMethodFromStore(packageName string, structName string, methodName string) *BoundMethod {
-
// Lock the db whilst processing and unlock on return
d.lock.RLock()
defer d.lock.RUnlock()
@@ -53,7 +56,6 @@ func (d *DB) GetMethodFromStore(packageName string, structName string, methodNam
// GetMethod returns the method for the given qualified method name
// qualifiedMethodName is "packagename.structname.methodname"
func (d *DB) GetMethod(qualifiedMethodName string) *BoundMethod {
-
// Lock the db whilst processing and unlock on return
d.lock.RLock()
defer d.lock.RUnlock()
@@ -67,12 +69,15 @@ func (d *DB) GetObfuscatedMethod(id int) *BoundMethod {
d.lock.RLock()
defer d.lock.RUnlock()
- return d.obfuscatedMethodMap[id]
+ if len(d.obfuscatedMethodArray) <= id {
+ return nil
+ }
+
+ return d.obfuscatedMethodArray[id].method
}
// AddMethod adds the given method definition to the db using the given qualified path: packageName.structName.methodName
func (d *DB) AddMethod(packageName string, structName string, methodName string, methodDefinition *BoundMethod) {
-
// Lock the db whilst processing and unlock on return
d.lock.Lock()
defer d.lock.Unlock()
@@ -99,12 +104,11 @@ func (d *DB) AddMethod(packageName string, structName string, methodName string,
// Store in the methodMap
key := packageName + "." + structName + "." + methodName
d.methodMap[key] = methodDefinition
-
+ d.obfuscatedMethodArray = append(d.obfuscatedMethodArray, &ObfuscatedMethod{method: methodDefinition, methodName: key})
}
// ToJSON converts the method map to JSON
func (d *DB) ToJSON() (string, error) {
-
// Lock the db whilst processing and unlock on return
d.lock.RLock()
defer d.lock.RUnlock()
@@ -120,20 +124,11 @@ func (d *DB) ToJSON() (string, error) {
// UpdateObfuscatedCallMap sets up the secure call mappings
func (d *DB) UpdateObfuscatedCallMap() map[string]int {
+ mappings := make(map[string]int)
- var mappings = make(map[string]int)
-
- // Iterate map keys and sort them
- keys := make([]string, 0, len(d.methodMap))
- for k := range d.methodMap {
- keys = append(keys, k)
+ for id, k := range d.obfuscatedMethodArray {
+ mappings[k.methodName] = id
}
- sort.Strings(keys)
- // Iterate sorted keys and add to obfuscated method map
- for id, k := range keys {
- mappings[k] = id
- d.obfuscatedMethodMap[id] = d.methodMap[k]
- }
return mappings
}
diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go
index 8109a73af..77edc983d 100644
--- a/v2/internal/binding/generate.go
+++ b/v2/internal/binding/generate.go
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "regexp"
"sort"
"strings"
@@ -14,6 +15,24 @@ import (
"github.com/leaanthony/slicer"
)
+var (
+ mapRegex *regexp.Regexp
+ keyPackageIndex int
+ keyTypeIndex int
+ valueArrayIndex int
+ valuePackageIndex int
+ valueTypeIndex int
+)
+
+func init() {
+ mapRegex = regexp.MustCompile(`(?:map\[(?:(?P\w+)\.)?(?P\w+)])?(?P\[])?(?:\*?(?P\w+)\.)?(?P.+)`)
+ keyPackageIndex = mapRegex.SubexpIndex("keyPackage")
+ keyTypeIndex = mapRegex.SubexpIndex("keyType")
+ valueArrayIndex = mapRegex.SubexpIndex("valueArray")
+ valuePackageIndex = mapRegex.SubexpIndex("valuePackage")
+ valueTypeIndex = mapRegex.SubexpIndex("valueType")
+}
+
func (b *Bindings) GenerateGoBindings(baseDir string) error {
store := b.db.store
var obfuscatedBindings map[string]int
@@ -64,9 +83,7 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
} else {
jsoutput.WriteString(fmt.Sprintf(" return window['go']['%s']['%s']['%s'](%s);", packageName, structName, methodName, argsString))
}
- jsoutput.WriteString("\n")
- jsoutput.WriteString(fmt.Sprintf("}"))
- jsoutput.WriteString("\n")
+ jsoutput.WriteString("\n}\n")
// Generate TS
tsBody.WriteString(fmt.Sprintf("\nexport function %s(", methodName))
@@ -74,7 +91,8 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
args.Clear()
for count, input := range methodDetails.Inputs {
arg := fmt.Sprintf("arg%d", count+1)
- args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName, &importNamespaces))
+ entityName := entityFullReturnType(input.TypeName, b.tsPrefix, b.tsSuffix, &importNamespaces)
+ args.Add(arg + ":" + goTypeToTypescriptType(entityName, &importNamespaces))
}
tsBody.WriteString(args.Join(",") + "):")
// now build Typescript return types
@@ -109,12 +127,12 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
tsContent.WriteString(tsBody.String())
jsfilename := filepath.Join(packageDir, structName+".js")
- err = os.WriteFile(jsfilename, jsoutput.Bytes(), 0755)
+ err = os.WriteFile(jsfilename, jsoutput.Bytes(), 0o755)
if err != nil {
return err
}
tsfilename := filepath.Join(packageDir, structName+".d.ts")
- err = os.WriteFile(tsfilename, tsContent.Bytes(), 0755)
+ err = os.WriteFile(tsfilename, tsContent.Bytes(), 0o755)
if err != nil {
return err
}
@@ -127,56 +145,96 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
return nil
}
-func goTypeToJSDocType(input string, importNamespaces *slicer.StringSlicer) string {
- // Verifying this first to ensure we are not converting a type
- // coming from a package that has a name matching a golang type, such as:
- // - interactor -> int
- // - mapper -> map
- if strings.ContainsRune(input, '.') {
- namespace := getPackageName(input)
- importNamespaces.Add(namespace)
- return namespace + "." + strings.Split(input, ".")[1]
+func fullyQualifiedName(packageName string, typeName string) string {
+ if len(packageName) > 0 {
+ return packageName + "." + typeName
}
switch true {
- case input == "interface {}" || input == "interface{}":
+ case len(typeName) == 0:
+ return ""
+ case typeName == "interface{}" || typeName == "interface {}":
return "any"
- case input == "string":
+ case typeName == "string":
return "string"
- case input == "error":
+ case typeName == "error":
return "Error"
case
- strings.HasPrefix(input, "int"),
- strings.HasPrefix(input, "uint"),
- strings.HasPrefix(input, "float"):
+ strings.HasPrefix(typeName, "int"),
+ strings.HasPrefix(typeName, "uint"),
+ strings.HasPrefix(typeName, "float"):
return "number"
- case input == "bool":
+ case typeName == "bool":
return "boolean"
- case input == "[]byte":
- return "string"
- case strings.HasPrefix(input, "map"):
- temp := strings.TrimPrefix(input, "map[")
- // Split the string into the key and value types
- tempSplit := strings.SplitN(temp, "]", 2)
- if len(tempSplit) < 2 {
- panic("Invalid map type provided: " + input)
- }
- keyType := tempSplit[0]
- valueType := tempSplit[1]
- return fmt.Sprintf("{[key: %s]: %s}", goTypeToJSDocType(keyType, importNamespaces), goTypeToJSDocType(valueType, importNamespaces))
- case strings.HasPrefix(input, "[]"):
- arrayType := goTypeToJSDocType(input[2:], importNamespaces)
- return "Array<" + arrayType + ">"
default:
return "any"
}
}
-func goTypeToTypescriptType(input string, importNamespaces *slicer.StringSlicer) string {
- if strings.HasPrefix(input, "[]") {
- arrayType := goTypeToJSDocType(input[2:], importNamespaces)
- return "Array<" + arrayType + ">"
+var (
+ jsVariableUnsafeChars = regexp.MustCompile(`[^A-Za-z0-9_]`)
+)
+
+func arrayifyValue(valueArray string, valueType string) string {
+ valueType = strings.ReplaceAll(valueType, "*", "")
+ gidx := strings.IndexRune(valueType, '[')
+ if gidx > 0 { // its a generic type
+ rem := strings.SplitN(valueType, "[", 2)
+ valueType = rem[0] + "_" + jsVariableUnsafeChars.ReplaceAllLiteralString(rem[1], "_")
}
+
+ if len(valueArray) == 0 {
+ return valueType
+ }
+
+ return "Array<" + valueType + ">"
+}
+
+func goTypeToJSDocType(input string, importNamespaces *slicer.StringSlicer) string {
+ matches := mapRegex.FindStringSubmatch(input)
+ keyPackage := matches[keyPackageIndex]
+ keyType := matches[keyTypeIndex]
+ valueArray := matches[valueArrayIndex]
+ valuePackage := matches[valuePackageIndex]
+ valueType := matches[valueTypeIndex]
+ // fmt.Printf("input=%s, keyPackage=%s, keyType=%s, valueArray=%s, valuePackage=%s, valueType=%s\n",
+ // input,
+ // keyPackage,
+ // keyType,
+ // valueArray,
+ // valuePackage,
+ // valueType)
+
+ // byte array is special case
+ if valueArray == "[]" && valueType == "byte" {
+ return "string"
+ }
+
+ // if any packages, make sure they're saved
+ if len(keyPackage) > 0 {
+ importNamespaces.Add(keyPackage)
+ }
+
+ if len(valuePackage) > 0 {
+ importNamespaces.Add(valuePackage)
+ }
+
+ key := fullyQualifiedName(keyPackage, keyType)
+ var value string
+ if strings.HasPrefix(valueType, "map") {
+ value = goTypeToJSDocType(valueType, importNamespaces)
+ } else {
+ value = fullyQualifiedName(valuePackage, valueType)
+ }
+
+ if len(key) > 0 {
+ return fmt.Sprintf("Record<%s, %s>", key, arrayifyValue(valueArray, value))
+ }
+
+ return arrayifyValue(valueArray, value)
+}
+
+func goTypeToTypescriptType(input string, importNamespaces *slicer.StringSlicer) string {
return goTypeToJSDocType(input, importNamespaces)
}
diff --git a/v2/internal/binding/generate_test.go b/v2/internal/binding/generate_test.go
index 565fba31c..26d7c70df 100644
--- a/v2/internal/binding/generate_test.go
+++ b/v2/internal/binding/generate_test.go
@@ -25,7 +25,7 @@ type B struct {
func TestNestedStruct(t *testing.T) {
bind := &BindForTest{}
- testBindings := NewBindings(logger.New(nil), []interface{}{bind}, []interface{}{}, false)
+ testBindings := NewBindings(logger.New(nil), []interface{}{bind}, []interface{}{}, false, []interface{}{})
namesStrSlicer := testBindings.getAllStructNames()
names := []string{}
@@ -116,18 +116,28 @@ func Test_goTypeToJSDocType(t *testing.T) {
{
name: "map",
input: "map[string]float64",
- want: "{[key: string]: number}",
+ want: "Record",
},
{
name: "map",
input: "map[string]map[string]float64",
- want: "{[key: string]: {[key: string]: number}}",
+ want: "Record>",
},
{
name: "types",
input: "main.SomeType",
want: "main.SomeType",
},
+ {
+ name: "primitive_generic",
+ input: "main.ListData[string]",
+ want: "main.ListData_string_",
+ },
+ {
+ name: "stdlib_generic",
+ input: "main.ListData[*net/http.Request]",
+ want: "main.ListData_net_http_Request_",
+ },
}
var importNamespaces slicer.StringSlicer
for _, tt := range tests {
diff --git a/v2/internal/binding/reflect.go b/v2/internal/binding/reflect.go
old mode 100755
new mode 100644
index 66a9cf7bd..c254d0f0a
--- a/v2/internal/binding/reflect.go
+++ b/v2/internal/binding/reflect.go
@@ -19,13 +19,32 @@ func isFunction(value interface{}) bool {
return reflect.ValueOf(value).Kind() == reflect.Func
}
-// isStructPtr returns true if the value given is a struct
+// isStruct returns true if the value given is a struct
func isStruct(value interface{}) bool {
return reflect.ValueOf(value).Kind() == reflect.Struct
}
-func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
+func normalizeStructName(name string) string {
+ return strings.ReplaceAll(
+ strings.ReplaceAll(
+ strings.ReplaceAll(
+ strings.ReplaceAll(
+ name,
+ ",",
+ "-",
+ ),
+ "*",
+ "",
+ ),
+ "]",
+ "__",
+ ),
+ "[",
+ "__",
+ )
+}
+func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
// Create result placeholder
var result []*BoundMethod
@@ -48,14 +67,14 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
// Process Struct
structType := reflect.TypeOf(value)
structValue := reflect.ValueOf(value)
- structTypeString := structType.String()
- baseName := structTypeString[1:]
+ structName := structType.Elem().Name()
+ structNameNormalized := normalizeStructName(structName)
+ pkgPath := strings.TrimSuffix(structType.Elem().String(), fmt.Sprintf(".%s", structName))
// Process Methods
for i := 0; i < structType.NumMethod(); i++ {
methodDef := structType.Method(i)
methodName := methodDef.Name
- fullMethodName := baseName + "." + methodName
method := structValue.MethodByName(methodName)
methodReflectName := runtime.FuncForPC(methodDef.Func.Pointer()).Name()
@@ -65,7 +84,11 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
// Create new method
boundMethod := &BoundMethod{
- Name: fullMethodName,
+ Path: &BoundedMethodPath{
+ Package: pkgPath,
+ Struct: structNameNormalized,
+ Name: methodName,
+ },
Inputs: nil,
Outputs: nil,
Comments: "",
@@ -167,9 +190,8 @@ func getPackageName(in string) string {
}
func getSplitReturn(in string) (string, string) {
- result := strings.Split(in, ".")
+ result := strings.SplitN(in, ".", 2)
return result[0], result[1]
-
}
func hasElements(typ reflect.Type) bool {
diff --git a/v2/internal/frontend/calls.go b/v2/internal/frontend/calls.go
index 3983c24bf..5401106bc 100644
--- a/v2/internal/frontend/calls.go
+++ b/v2/internal/frontend/calls.go
@@ -1,5 +1,5 @@
package frontend
type Calls interface {
- Callback(string)
+ Callback(message string)
}
diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.h b/v2/internal/frontend/desktop/darwin/AppDelegate.h
index e2dd841c9..a8d10f647 100644
--- a/v2/internal/frontend/desktop/darwin/AppDelegate.h
+++ b/v2/internal/frontend/desktop/darwin/AppDelegate.h
@@ -11,13 +11,23 @@
#import
#import "WailsContext.h"
-@interface AppDelegate : NSResponder
+@interface AppDelegate : NSResponder
@property bool alwaysOnTop;
@property bool startHidden;
+@property (retain) NSString* singleInstanceUniqueId;
+@property bool singleInstanceLockEnabled;
@property bool startFullscreen;
@property (retain) WailsWindow* mainWindow;
@end
+extern void HandleOpenFile(char *);
+
+extern void HandleSecondInstanceData(char * message);
+
+void SendDataToFirstInstance(char * singleInstanceUniqueId, char * text);
+
+char* GetMacOsNativeTempDir();
+
#endif /* AppDelegate_h */
diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.m b/v2/internal/frontend/desktop/darwin/AppDelegate.m
index 6d46deae4..a73ec3ec3 100644
--- a/v2/internal/frontend/desktop/darwin/AppDelegate.m
+++ b/v2/internal/frontend/desktop/darwin/AppDelegate.m
@@ -9,15 +9,41 @@
#import
#import "AppDelegate.h"
+#import "CustomProtocol.h"
+#import "message.h"
@implementation AppDelegate
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
- return NO;
+-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
+{
+ const char* utf8FileName = filename.UTF8String;
+ HandleOpenFile((char*)utf8FileName);
+ return YES;
}
+
+- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> * _Nullable))restorationHandler {
+ if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
+ NSURL *url = userActivity.webpageURL;
+ if (url) {
+ HandleOpenURL((char*)[[url absoluteString] UTF8String]);
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
+ return NO;
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+ processMessage("Q");
+ return NSTerminateCancel;
+}
+
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
if (self.alwaysOnTop) {
- [self.mainWindow setLevel:NSStatusWindowLevel];
+ [self.mainWindow setLevel:NSFloatingWindowLevel];
}
if ( !self.startHidden ) {
[self.mainWindow makeKeyAndOrderFront:self];
@@ -32,6 +58,37 @@
[self.mainWindow setCollectionBehavior:behaviour];
[self.mainWindow toggleFullScreen:nil];
}
+
+ if ( self.singleInstanceLockEnabled ) {
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(handleSecondInstanceNotification:) name:self.singleInstanceUniqueId object:nil];
+ }
+}
+
+void SendDataToFirstInstance(char * singleInstanceUniqueId, char * message) {
+ // we pass message in object because otherwise sandboxing will prevent us from sending it https://developer.apple.com/forums/thread/129437
+ NSString * myString = [NSString stringWithUTF8String:message];
+ [[NSDistributedNotificationCenter defaultCenter]
+ postNotificationName:[NSString stringWithUTF8String:singleInstanceUniqueId]
+ object:(__bridge const void *)(myString)
+ userInfo:nil
+ deliverImmediately:YES];
+}
+
+char* GetMacOsNativeTempDir() {
+ NSString *tempDir = NSTemporaryDirectory();
+ char *copy = strdup([tempDir UTF8String]);
+
+ return copy;
+}
+
+- (void)handleSecondInstanceNotification:(NSNotification *)note;
+{
+ if (note.object != nil) {
+ NSString * message = (__bridge NSString *)note.object;
+ const char* utf8Message = message.UTF8String;
+ HandleSecondInstanceData((char*)utf8Message);
+ }
}
- (void)dealloc {
diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h
index e418168e6..4d8bbd37b 100644
--- a/v2/internal/frontend/desktop/darwin/Application.h
+++ b/v2/internal/frontend/desktop/darwin/Application.h
@@ -17,7 +17,7 @@
#define WindowStartsMinimised 2
#define WindowStartsFullscreen 3
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled);
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop);
void Run(void*, const char* url);
void SetTitle(void* ctx, const char *title);
@@ -41,6 +41,7 @@ void ShowApplication(void* ctx);
void SetBackgroundColour(void* ctx, int r, int g, int b, int a);
void ExecJS(void* ctx, const char*);
void Quit(void*);
+void WindowPrint(void* ctx);
const char* GetSize(void *ctx);
const char* GetPosition(void *ctx);
diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m
index ab951714d..38d349c2c 100644
--- a/v2/internal/frontend/desktop/darwin/Application.m
+++ b/v2/internal/frontend/desktop/darwin/Application.m
@@ -10,25 +10,32 @@
#import "WailsContext.h"
#import "Application.h"
#import "AppDelegate.h"
+#import "WindowDelegate.h"
#import "WailsMenu.h"
#import "WailsMenuItem.h"
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) {
-
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop) {
+
[NSApplication sharedApplication];
WailsContext *result = [WailsContext new];
- result.debug = debug;
-
+ result.devtoolsEnabled = devtoolsEnabled;
+ result.defaultContextMenuEnabled = defaultContextMenuEnabled;
+
if ( windowStartState == WindowStartsFullscreen ) {
fullscreen = 1;
}
- [result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight :fraudulentWebsiteWarningEnabled];
+ [result CreateWindow:width :height :frameless :resizable :zoomable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight :fraudulentWebsiteWarningEnabled :preferences :enableDragAndDrop :disableWebViewDragAndDrop];
[result SetTitle:safeInit(title)];
[result Center];
-
+
+ if (contentProtection == 1 &&
+ [result.mainWindow respondsToSelector:@selector(setSharingType:)]) {
+ [result.mainWindow setSharingType:NSWindowSharingNone];
+ }
+
switch( windowStartState ) {
case WindowStartsMaximised:
[result.mainWindow zoom:nil];
@@ -41,14 +48,19 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
if ( startsHidden == 1 ) {
result.startHidden = true;
}
-
+
if ( fullscreen == 1 ) {
result.startFullscreen = true;
}
-
+
+ if ( singleInstanceLockEnabled == 1 ) {
+ result.singleInstanceLockEnabled = true;
+ result.singleInstanceUniqueId = safeInit(singleInstanceUniqueId);
+ }
+
result.alwaysOnTop = alwaysOnTop;
result.hideOnClose = hideWindowOnClose;
-
+
return result;
}
@@ -179,7 +191,7 @@ const char* GetPosition(void *inctx) {
NSString *result = [NSString stringWithFormat:@"%d,%d",x,y];
return [result UTF8String];
}
-
+
const bool IsFullScreen(void *inctx) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
return [ctx IsFullScreen];
@@ -247,7 +259,7 @@ NSString* safeInit(const char* input) {
void MessageDialog(void *inctx, const char* dialogType, const char* title, const char* message, const char* button1, const char* button2, const char* button3, const char* button4, const char* defaultButton, const char* cancelButton, void* iconData, int iconDataLength) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
-
+
NSString *_dialogType = safeInit(dialogType);
NSString *_title = safeInit(title);
NSString *_message = safeInit(message);
@@ -257,33 +269,33 @@ void MessageDialog(void *inctx, const char* dialogType, const char* title, const
NSString *_button4 = safeInit(button4);
NSString *_defaultButton = safeInit(defaultButton);
NSString *_cancelButton = safeInit(cancelButton);
-
+
ON_MAIN_THREAD(
[ctx MessageDialog:_dialogType :_title :_message :_button1 :_button2 :_button3 :_button4 :_defaultButton :_cancelButton :iconData :iconDataLength];
)
}
void OpenFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int allowDirectories, int allowFiles, int canCreateDirectories, int treatPackagesAsDirectories, int resolveAliases, int showHiddenFiles, int allowMultipleSelection, const char* filters) {
-
+
WailsContext *ctx = (__bridge WailsContext*) inctx;
NSString *_title = safeInit(title);
NSString *_defaultFilename = safeInit(defaultFilename);
NSString *_defaultDirectory = safeInit(defaultDirectory);
NSString *_filters = safeInit(filters);
-
+
ON_MAIN_THREAD(
[ctx OpenFileDialog:_title :_defaultFilename :_defaultDirectory :allowDirectories :allowFiles :canCreateDirectories :treatPackagesAsDirectories :resolveAliases :showHiddenFiles :allowMultipleSelection :_filters];
)
}
void SaveFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int canCreateDirectories, int treatPackagesAsDirectories, int showHiddenFiles, const char* filters) {
-
+
WailsContext *ctx = (__bridge WailsContext*) inctx;
NSString *_title = safeInit(title);
NSString *_defaultFilename = safeInit(defaultFilename);
NSString *_defaultDirectory = safeInit(defaultDirectory);
NSString *_filters = safeInit(filters);
-
+
ON_MAIN_THREAD(
[ctx SaveFileDialog:_title :_defaultFilename :_defaultDirectory :canCreateDirectories :treatPackagesAsDirectories :showHiddenFiles :_filters];
)
@@ -365,6 +377,8 @@ void Run(void *inctx, const char* url) {
delegate.mainWindow = ctx.mainWindow;
delegate.alwaysOnTop = ctx.alwaysOnTop;
delegate.startHidden = ctx.startHidden;
+ delegate.singleInstanceLockEnabled = ctx.singleInstanceLockEnabled;
+ delegate.singleInstanceUniqueId = ctx.singleInstanceUniqueId;
delegate.startFullscreen = ctx.startFullscreen;
NSString *_url = safeInit(url);
@@ -383,3 +397,37 @@ void ReleaseContext(void *inctx) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
[ctx release];
}
+
+// Credit: https://stackoverflow.com/q/33319295
+void WindowPrint(void *inctx) {
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
+ if (@available(macOS 11.0, *)) {
+ ON_MAIN_THREAD(
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ WKWebView* webView = ctx.webview;
+
+ // I think this should be exposed as a config
+ // It directly affects the printed output/PDF
+ NSPrintInfo *pInfo = [NSPrintInfo sharedPrintInfo];
+ pInfo.horizontalPagination = NSPrintingPaginationModeAutomatic;
+ pInfo.verticalPagination = NSPrintingPaginationModeAutomatic;
+ pInfo.verticallyCentered = YES;
+ pInfo.horizontallyCentered = YES;
+ pInfo.orientation = NSPaperOrientationLandscape;
+ pInfo.leftMargin = 0;
+ pInfo.rightMargin = 0;
+ pInfo.topMargin = 0;
+ pInfo.bottomMargin = 0;
+
+ NSPrintOperation *po = [webView printOperationWithPrintInfo:pInfo];
+ po.showsPrintPanel = YES;
+ po.showsProgressPanel = YES;
+
+ po.view.frame = webView.bounds;
+
+ [po runOperationModalForWindow:ctx.mainWindow delegate:ctx.mainWindow.delegate didRunSelector:nil contextInfo:nil];
+ )
+ }
+#endif
+}
diff --git a/v2/internal/frontend/desktop/darwin/CustomProtocol.h b/v2/internal/frontend/desktop/darwin/CustomProtocol.h
new file mode 100644
index 000000000..0698a4d45
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/CustomProtocol.h
@@ -0,0 +1,14 @@
+#ifndef CustomProtocol_h
+#define CustomProtocol_h
+
+#import
+
+extern void HandleOpenURL(char*);
+
+@interface CustomProtocolSchemeHandler : NSObject
++ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
+@end
+
+void StartCustomProtocolHandler(void);
+
+#endif /* CustomProtocol_h */
diff --git a/v2/internal/frontend/desktop/darwin/CustomProtocol.m b/v2/internal/frontend/desktop/darwin/CustomProtocol.m
new file mode 100644
index 000000000..ebc61aa00
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/CustomProtocol.m
@@ -0,0 +1,20 @@
+#include "CustomProtocol.h"
+
+@implementation CustomProtocolSchemeHandler
++ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+ [event paramDescriptorForKeyword:keyDirectObject];
+
+ NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+
+ HandleOpenURL((char*)[[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]);
+}
+@end
+
+void StartCustomProtocolHandler(void) {
+ NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
+
+ [appleEventManager setEventHandler:[CustomProtocolSchemeHandler class]
+ andSelector:@selector(handleGetURLEvent:withReplyEvent:)
+ forEventClass:kInternetEventClass
+ andEventID: kAEGetURL];
+}
diff --git a/v2/internal/frontend/desktop/darwin/Role.h b/v2/internal/frontend/desktop/darwin/Role.h
index 20e670689..6b8877a09 100644
--- a/v2/internal/frontend/desktop/darwin/Role.h
+++ b/v2/internal/frontend/desktop/darwin/Role.h
@@ -12,5 +12,6 @@ typedef int Role;
static const Role AppMenu = 1;
static const Role EditMenu = 2;
+static const Role WindowMenu = 3;
#endif /* Role_h */
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.h b/v2/internal/frontend/desktop/darwin/WailsContext.h
index 1e48b2182..2ec6d8707 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.h
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.h
@@ -10,6 +10,7 @@
#import
#import
+#import "WailsWebView.h"
#if __has_include()
#define USE_NEW_FILTERS
@@ -32,7 +33,7 @@
@interface WailsContext : NSObject
@property (retain) WailsWindow* mainWindow;
-@property (retain) WKWebView* webview;
+@property (retain) WailsWebView* webview;
@property (nonatomic, assign) id appdelegate;
@property bool hideOnClose;
@@ -40,11 +41,15 @@
@property bool startHidden;
@property bool startFullscreen;
+@property bool singleInstanceLockEnabled;
+@property (retain) NSString* singleInstanceUniqueId;
+
@property (retain) NSEvent* mouseEvent;
@property bool alwaysOnTop;
-@property bool debug;
+@property bool devtoolsEnabled;
+@property bool defaultContextMenuEnabled;
@property (retain) WKUserContentController* userContentController;
@@ -54,7 +59,13 @@
@property (retain) NSString* aboutTitle;
@property (retain) NSString* aboutDescription;
-- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled;
+struct Preferences {
+ bool *tabFocusesLinks;
+ bool *textInteractionEnabled;
+ bool *fullscreenEnabled;
+};
+
+- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)zoomable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences :(bool)enableDragAndDrop :(bool)disableWebViewDragAndDrop;
- (void) SetSize:(int)width :(int)height;
- (void) SetPosition:(int)x :(int) y;
- (void) SetMinSize:(int)minWidth :(int)minHeight;
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m
index 29fa99317..7c9660d54 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.m
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.m
@@ -1,4 +1,3 @@
-//go:build darwin
//
// WailsContext.m
// test
@@ -11,6 +10,7 @@
#import "WailsContext.h"
#import "WailsAlert.h"
#import "WailsMenu.h"
+#import "WailsWebView.h"
#import "WindowDelegate.h"
#import "message.h"
#import "Role.h"
@@ -39,9 +39,9 @@ typedef void (^schemeTaskCaller)(id);
@implementation WailsContext
- (void) SetSize:(int)width :(int)height {
-
+
if (self.shuttingDown) return;
-
+
NSRect frame = [self.mainWindow frame];
frame.origin.y += frame.size.height - height;
frame.size.width = width;
@@ -50,22 +50,22 @@ typedef void (^schemeTaskCaller)(id);
}
- (void) SetPosition:(int)x :(int)y {
-
+
if (self.shuttingDown) return;
-
+
NSScreen* screen = [self getCurrentScreen];
NSRect windowFrame = [self.mainWindow frame];
- NSRect screenFrame = [screen frame];
+ NSRect screenFrame = [screen visibleFrame];
windowFrame.origin.x = screenFrame.origin.x + (float)x;
windowFrame.origin.y = (screenFrame.origin.y + screenFrame.size.height) - windowFrame.size.height - (float)y;
-
+
[self.mainWindow setFrame:windowFrame display:TRUE animate:FALSE];
}
- (void) SetMinSize:(int)minWidth :(int)minHeight {
-
+
if (self.shuttingDown) return;
-
+
NSSize size = { minWidth, minHeight };
self.mainWindow.userMinSize = size;
[self.mainWindow setMinSize:size];
@@ -74,14 +74,14 @@ typedef void (^schemeTaskCaller)(id);
- (void) SetMaxSize:(int)maxWidth :(int)maxHeight {
-
+
if (self.shuttingDown) return;
-
+
NSSize size = { FLT_MAX, FLT_MAX };
-
+
size.width = maxWidth > 0 ? maxWidth : FLT_MAX;
size.height = maxHeight > 0 ? maxHeight : FLT_MAX;
-
+
self.mainWindow.userMaxSize = size;
[self.mainWindow setMaxSize:size];
[self adjustWindowSize];
@@ -89,18 +89,18 @@ typedef void (^schemeTaskCaller)(id);
- (void) adjustWindowSize {
-
+
if (self.shuttingDown) return;
-
+
NSRect currentFrame = [self.mainWindow frame];
-
+
if ( currentFrame.size.width > self.mainWindow.userMaxSize.width ) currentFrame.size.width = self.mainWindow.userMaxSize.width;
if ( currentFrame.size.width < self.mainWindow.userMinSize.width ) currentFrame.size.width = self.mainWindow.userMinSize.width;
if ( currentFrame.size.height > self.mainWindow.userMaxSize.height ) currentFrame.size.height = self.mainWindow.userMaxSize.height;
if ( currentFrame.size.height < self.mainWindow.userMinSize.height ) currentFrame.size.height = self.mainWindow.userMinSize.height;
[self.mainWindow setFrame:currentFrame display:YES animate:FALSE];
-
+
}
- (void) dealloc {
@@ -136,16 +136,16 @@ typedef void (^schemeTaskCaller)(id);
return NO;
}
-- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled {
+- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)zoomable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences :(bool)enableDragAndDrop :(bool)disableWebViewDragAndDrop {
NSWindowStyleMask styleMask = 0;
-
+
if( !frameless ) {
if (!hideTitleBar) {
styleMask |= NSWindowStyleMaskTitled;
}
styleMask |= NSWindowStyleMaskClosable;
}
-
+
styleMask |= NSWindowStyleMaskMiniaturizable;
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
@@ -155,23 +155,22 @@ typedef void (^schemeTaskCaller)(id);
if (resizable) {
styleMask |= NSWindowStyleMaskResizable;
}
-
+
self.mainWindow = [[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
-
if (!frameless && useToolbar) {
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
[toolbar autorelease];
[toolbar setShowsBaselineSeparator:!hideToolbarSeparator];
[self.mainWindow setToolbar:toolbar];
-
+
}
-
+
[self.mainWindow setTitleVisibility:hideTitle];
[self.mainWindow setTitlebarAppearsTransparent:titlebarAppearsTransparent];
-
+
// [self.mainWindow canBecomeKeyWindow];
-
+
id contentView = [self.mainWindow contentView];
if (windowIsTranslucent) {
NSVisualEffectView *effectView = [NSVisualEffectView alloc];
@@ -182,12 +181,17 @@ typedef void (^schemeTaskCaller)(id);
[effectView setState:NSVisualEffectStateActive];
[contentView addSubview:effectView positioned:NSWindowBelow relativeTo:nil];
}
-
+
if (appearance != nil) {
NSAppearance *nsAppearance = [NSAppearance appearanceNamed:appearance];
[self.mainWindow setAppearance:nsAppearance];
}
-
+
+ if (!zoomable && resizable) {
+ NSButton *button = [self.mainWindow standardWindowButton:NSWindowZoomButton];
+ [button setEnabled: NO];
+ }
+
NSSize minSize = { minWidth, minHeight };
NSSize maxSize = { maxWidth, maxHeight };
@@ -199,62 +203,93 @@ typedef void (^schemeTaskCaller)(id);
}
self.mainWindow.userMaxSize = maxSize;
self.mainWindow.userMinSize = minSize;
-
+
if( !fullscreen ) {
[self.mainWindow applyWindowConstraints];
}
-
+
WindowDelegate *windowDelegate = [WindowDelegate new];
windowDelegate.hideOnClose = hideWindowOnClose;
windowDelegate.ctx = self;
[self.mainWindow setDelegate:windowDelegate];
-
+
// Webview stuff here!
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
- config.suppressesIncrementalRendering = true;
+ // Disable suppressesIncrementalRendering on macOS 26+ to prevent WebView crashes
+ // during rapid UI updates. See: https://github.com/wailsapp/wails/issues/4592
+ if (@available(macOS 26.0, *)) {
+ config.suppressesIncrementalRendering = false;
+ } else {
+ config.suppressesIncrementalRendering = true;
+ }
config.applicationNameForUserAgent = @"wails.io";
[config setURLSchemeHandler:self forURLScheme:@"wails"];
-
-// [config.preferences setValue:[NSNumber numberWithBool:true] forKey:@"developerExtrasEnabled"];
+ if (preferences.tabFocusesLinks != NULL) {
+ config.preferences.tabFocusesLinks = *preferences.tabFocusesLinks;
+ }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110300
+ if (@available(macOS 11.3, *)) {
+ if (preferences.textInteractionEnabled != NULL) {
+ config.preferences.textInteractionEnabled = *preferences.textInteractionEnabled;
+ }
+ }
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120300
+ if (@available(macOS 12.3, *)) {
+ if (preferences.fullscreenEnabled != NULL) {
+ config.preferences.elementFullscreenEnabled = *preferences.fullscreenEnabled;
+ }
+ }
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
if (@available(macOS 10.15, *)) {
config.preferences.fraudulentWebsiteWarningEnabled = fraudulentWebsiteWarningEnabled;
}
+#endif
WKUserContentController* userContentController = [WKUserContentController new];
[userContentController addScriptMessageHandler:self name:@"external"];
config.userContentController = userContentController;
self.userContentController = userContentController;
- if (self.debug) {
+
+ if (self.devtoolsEnabled) {
[config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
- } else {
+ }
+
+ if (!self.defaultContextMenuEnabled) {
// Disable default context menus
WKUserScript *initScript = [WKUserScript new];
- [initScript initWithSource:@"window.wails.flags.disableWailsDefaultContextMenu = true;"
+ [initScript initWithSource:@"window.wails.flags.disableDefaultContextMenu = true;"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:false];
[userContentController addUserScript:initScript];
-
}
-
- self.webview = [WKWebView alloc];
+
+ self.webview = [WailsWebView alloc];
+ self.webview.enableDragAndDrop = enableDragAndDrop;
+ self.webview.disableWebViewDragAndDrop = disableWebViewDragAndDrop;
+
CGRect init = { 0,0,0,0 };
[self.webview initWithFrame:init configuration:config];
[contentView addSubview:self.webview];
[self.webview setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
CGRect contentViewBounds = [contentView bounds];
[self.webview setFrame:contentViewBounds];
-
+
if (webviewIsTransparent) {
[self.webview setValue:[NSNumber numberWithBool:!webviewIsTransparent] forKey:@"drawsBackground"];
}
-
+
[self.webview setNavigationDelegate:self];
self.webview.UIDelegate = self;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:FALSE forKey:@"NSAutomaticQuoteSubstitutionEnabled"];
-
+
// Mouse monitors
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
id window = [event window];
@@ -263,7 +298,7 @@ typedef void (^schemeTaskCaller)(id);
}
return event;
}];
-
+
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
id window = [event window];
if (window == self.mainWindow) {
@@ -272,9 +307,9 @@ typedef void (^schemeTaskCaller)(id);
}
return event;
}];
-
+
self.applicationMenu = [NSMenu new];
-
+
}
- (NSMenuItem*) newMenuItem :(NSString*)title :(SEL)selector :(NSString*)key :(NSEventModifierFlags)flags {
@@ -310,9 +345,9 @@ typedef void (^schemeTaskCaller)(id);
float green = g/255.0;
float blue = b/255.0;
float alpha = a/255.0;
-
+
id colour = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha ];
-
+
[self.mainWindow setBackgroundColor:colour];
}
@@ -394,7 +429,7 @@ typedef void (^schemeTaskCaller)(id);
- (void) SetAlwaysOnTop:(int)onTop {
if (onTop) {
- [self.mainWindow setLevel:NSStatusWindowLevel];
+ [self.mainWindow setLevel:NSFloatingWindowLevel];
} else {
[self.mainWindow setLevel:NSNormalWindowLevel];
}
@@ -408,16 +443,17 @@ typedef void (^schemeTaskCaller)(id);
[self.webview evaluateJavaScript:script completionHandler:nil];
}
-- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters
+- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray * URLs))completionHandler {
-
+
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
if (@available(macOS 10.14, *)) {
openPanel.canChooseDirectories = parameters.allowsDirectories;
}
-
- [openPanel
+#endif
+ [openPanel
beginSheetModalForWindow:webView.window
completionHandler:^(NSInteger result) {
if (result == NSModalResponseOK)
@@ -447,8 +483,17 @@ typedef void (^schemeTaskCaller)(id);
}
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
+ // Get the origin from the message's frame
+ NSString *origin = nil;
+ if (message.frameInfo && message.frameInfo.request && message.frameInfo.request.URL) {
+ NSURL *url = message.frameInfo.request.URL;
+ if (url.scheme && url.host) {
+ origin = [url absoluteString];
+ }
+ }
+
NSString *m = message.body;
-
+
// Check for drag
if ( [m isEqualToString:@"drag"] ) {
if( [self IsFullScreen] ) {
@@ -459,18 +504,18 @@ typedef void (^schemeTaskCaller)(id);
}
return;
}
-
- const char *_m = [m UTF8String];
-
- processMessage(_m);
-}
+ const char *_m = [m UTF8String];
+ const char *_origin = [origin UTF8String];
+
+ processBindingMessage(_m, _origin, message.frameInfo.isMainFrame);
+}
/***** Dialogs ******/
-(void) MessageDialog :(NSString*)dialogType :(NSString*)title :(NSString*)message :(NSString*)button1 :(NSString*)button2 :(NSString*)button3 :(NSString*)button4 :(NSString*)defaultButton :(NSString*)cancelButton :(void*)iconData :(int)iconDataLength {
WailsAlert *alert = [WailsAlert new];
-
+
int style = NSAlertStyleInformational;
if (dialogType != nil ) {
if( [dialogType isEqualToString:@"warning"] ) {
@@ -487,12 +532,12 @@ typedef void (^schemeTaskCaller)(id);
if( message != nil ) {
[alert setInformativeText:message];
}
-
+
[alert addButton:button1 :defaultButton :cancelButton];
[alert addButton:button2 :defaultButton :cancelButton];
[alert addButton:button3 :defaultButton :cancelButton];
[alert addButton:button4 :defaultButton :cancelButton];
-
+
NSImage *icon = nil;
if (iconData != nil) {
NSData *imageData = [NSData dataWithBytes:iconData length:iconDataLength];
@@ -521,8 +566,8 @@ typedef void (^schemeTaskCaller)(id);
}
-(void) OpenFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)allowDirectories :(bool)allowFiles :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)resolveAliases :(bool)showHiddenFiles :(bool)allowMultipleSelection :(NSString*)filters {
-
-
+
+
// Create the dialog
NSOpenPanel *dialog = [NSOpenPanel openPanel];
@@ -540,14 +585,18 @@ typedef void (^schemeTaskCaller)(id);
#ifdef USE_NEW_FILTERS
NSMutableArray *contentTypes = [[NSMutableArray new] autorelease];
for (NSString *filter in filterList) {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
if (@available(macOS 11.0, *)) {
UTType *t = [UTType typeWithFilenameExtension:filter];
[contentTypes addObject:t];
}
+#endif
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
if (@available(macOS 11.0, *)) {
[dialog setAllowedContentTypes:contentTypes];
}
+#endif
#else
[dialog setAllowedFileTypes:filterList];
#endif
@@ -558,11 +607,10 @@ typedef void (^schemeTaskCaller)(id);
if( defaultFilename != nil ) {
[dialog setNameFieldStringValue:defaultFilename];
}
-
- [dialog setAllowsMultipleSelection: allowMultipleSelection];
- [dialog setShowsHiddenFiles: showHiddenFiles];
+ [dialog setAllowsMultipleSelection: allowMultipleSelection];
}
+ [dialog setShowsHiddenFiles: showHiddenFiles];
// Default Directory
if( defaultDirectory != nil ) {
@@ -594,19 +642,19 @@ typedef void (^schemeTaskCaller)(id);
[nsjson release];
[arr release];
}];
-
+
}
-(void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters; {
-
-
+
+
// Create the dialog
NSSavePanel *dialog = [NSSavePanel savePanel];
// Do not hide extension
[dialog setExtensionHidden:false];
-
+
// Valid but appears to do nothing.... :/
if( title != nil ) {
[dialog setTitle:title];
@@ -620,17 +668,21 @@ typedef void (^schemeTaskCaller)(id);
#ifdef USE_NEW_FILTERS
NSMutableArray *contentTypes = [[NSMutableArray new] autorelease];
for (NSString *filter in filterList) {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
if (@available(macOS 11.0, *)) {
UTType *t = [UTType typeWithFilenameExtension:filter];
[contentTypes addObject:t];
}
+#endif
}
if( contentTypes.count == 0) {
[dialog setAllowsOtherFileTypes:true];
} else {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
if (@available(macOS 11.0, *)) {
[dialog setAllowedContentTypes:contentTypes];
}
+#endif
}
#else
@@ -643,7 +695,7 @@ typedef void (^schemeTaskCaller)(id);
if( defaultFilename != nil ) {
[dialog setNameFieldStringValue:defaultFilename];
}
-
+
// Default Directory
if( defaultDirectory != nil ) {
NSURL *url = [NSURL fileURLWithPath:defaultDirectory];
@@ -668,19 +720,19 @@ typedef void (^schemeTaskCaller)(id);
}
processSaveFileDialogResponse("");
}];
-
+
}
- (void) SetAbout :(NSString*)title :(NSString*)description :(void*)imagedata :(int)datalen {
self.aboutTitle = title;
self.aboutDescription = description;
-
+
NSData *imageData = [NSData dataWithBytes:imagedata length:datalen];
self.aboutImage = [[NSImage alloc] initWithData:imageData];
}
-(void) About {
-
+
WailsAlert *alert = [WailsAlert new];
[alert setAlertStyle:NSAlertStyleInformational];
if( self.aboutTitle != nil ) {
@@ -689,8 +741,8 @@ typedef void (^schemeTaskCaller)(id);
if( self.aboutDescription != nil ) {
[alert setInformativeText:self.aboutDescription];
}
-
-
+
+
[alert.window setLevel:NSFloatingWindowLevel];
if ( self.aboutImage != nil) {
[alert setIcon:self.aboutImage];
diff --git a/v2/internal/frontend/desktop/darwin/WailsMenu.m b/v2/internal/frontend/desktop/darwin/WailsMenu.m
index 033140d91..66e5dd399 100644
--- a/v2/internal/frontend/desktop/darwin/WailsMenu.m
+++ b/v2/internal/frontend/desktop/darwin/WailsMenu.m
@@ -68,12 +68,20 @@
appName = [[NSProcessInfo processInfo] processName];
}
WailsMenu *appMenu = [[[WailsMenu new] initWithNSTitle:appName] autorelease];
+
+ if (ctx.aboutTitle != nil) {
+ [appMenu addItem:[self newMenuItemWithContext :ctx :[@"About " stringByAppendingString:appName] :@selector(About) :nil :0]];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ }
+
+ [appMenu addItem:[self newMenuItem:[@"Hide " stringByAppendingString:appName] :@selector(hide:) :@"h" :NSEventModifierFlagCommand]];
+ [appMenu addItem:[self newMenuItem:@"Hide Others" :@selector(hideOtherApplications:) :@"h" :(NSEventModifierFlagOption | NSEventModifierFlagCommand)]];
+ [appMenu addItem:[self newMenuItem:@"Show All" :@selector(unhideAllApplications:) :@""]];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+
id quitTitle = [@"Quit " stringByAppendingString:appName];
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
quitMenuItem.target = ctx;
- if (ctx.aboutTitle != nil) {
- [appMenu addItem:[self newMenuItemWithContext :ctx :[@"About " stringByAppendingString:appName] :@selector(About) :nil :0]];
- }
[appMenu addItem:quitMenuItem];
[self appendSubmenu:appMenu];
break;
@@ -81,8 +89,8 @@
case EditMenu:
{
WailsMenu *editMenu = [[[WailsMenu new] initWithNSTitle:@"Edit"] autorelease];
- [editMenu addItem:[self newMenuItem:@"Undo" :@selector(undoActionName) :@"z" :NSEventModifierFlagCommand]];
- [editMenu addItem:[self newMenuItem:@"Redo" :@selector(redoActionName) :@"z" :(NSEventModifierFlagShift | NSEventModifierFlagCommand)]];
+ [editMenu addItem:[self newMenuItem:@"Undo" :@selector(undo:) :@"z" :NSEventModifierFlagCommand]];
+ [editMenu addItem:[self newMenuItem:@"Redo" :@selector(redo:) :@"z" :(NSEventModifierFlagShift | NSEventModifierFlagCommand)]];
[editMenu addItem:[NSMenuItem separatorItem]];
[editMenu addItem:[self newMenuItem:@"Cut" :@selector(cut:) :@"x" :NSEventModifierFlagCommand]];
[editMenu addItem:[self newMenuItem:@"Copy" :@selector(copy:) :@"c" :NSEventModifierFlagCommand]];
@@ -100,6 +108,17 @@
[editMenu appendSubmenu:speechMenu];
[self appendSubmenu:editMenu];
+ break;
+ }
+ case WindowMenu:
+ {
+ WailsMenu *windowMenu = [[[WailsMenu new] initWithNSTitle:@"Window"] autorelease];
+ [windowMenu addItem:[self newMenuItem:@"Minimize" :@selector(performMiniaturize:) :@"m" :NSEventModifierFlagCommand]];
+ [windowMenu addItem:[self newMenuItem:@"Zoom" :@selector(performZoom:) :@""]];
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [windowMenu addItem:[self newMenuItem:@"Full Screen" :@selector(enterFullScreenMode:) :@"f" :(NSEventModifierFlagControl | NSEventModifierFlagCommand)]];
+ [self appendSubmenu:windowMenu];
+
break;
}
}
diff --git a/v2/internal/frontend/desktop/darwin/WailsWebView.h b/v2/internal/frontend/desktop/darwin/WailsWebView.h
new file mode 100644
index 000000000..b6f746cf2
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsWebView.h
@@ -0,0 +1,14 @@
+#ifndef WailsWebView_h
+#define WailsWebView_h
+
+#import
+#import
+
+// We will override WKWebView, so we can detect file drop in obj-c
+// and grab their file path, to then inject into JS
+@interface WailsWebView : WKWebView
+@property bool disableWebViewDragAndDrop;
+@property bool enableDragAndDrop;
+@end
+
+#endif /* WailsWebView_h */
diff --git a/v2/internal/frontend/desktop/darwin/WailsWebView.m b/v2/internal/frontend/desktop/darwin/WailsWebView.m
new file mode 100644
index 000000000..de23ac794
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsWebView.m
@@ -0,0 +1,122 @@
+#import "WailsWebView.h"
+#import "message.h"
+
+
+@implementation WailsWebView
+@synthesize disableWebViewDragAndDrop;
+@synthesize enableDragAndDrop;
+
+- (BOOL)prepareForDragOperation:(id)sender
+{
+ if ( !enableDragAndDrop ) {
+ return [super prepareForDragOperation: sender];
+ }
+
+ if ( disableWebViewDragAndDrop ) {
+ return YES;
+ }
+
+ return [super prepareForDragOperation: sender];
+}
+
+- (BOOL)performDragOperation:(id )sender
+{
+ if ( !enableDragAndDrop ) {
+ return [super performDragOperation: sender];
+ }
+
+ NSPasteboard *pboard = [sender draggingPasteboard];
+
+ // if no types, then we'll just let the WKWebView handle the drag-n-drop as normal
+ NSArray * types = [pboard types];
+ if( !types )
+ return [super performDragOperation: sender];
+
+ // getting all NSURL types
+ NSArray *url_class = @[[NSURL class]];
+ NSDictionary *options = @{};
+ NSArray *files = [pboard readObjectsForClasses:url_class options:options];
+
+ // collecting all file paths
+ NSMutableArray *files_strs = [[NSMutableArray alloc] init];
+ for (NSURL *url in files)
+ {
+ const char *fs_path = [url fileSystemRepresentation]; //Will be UTF-8 encoded
+ NSString *fs_path_str = [[NSString alloc] initWithCString:fs_path encoding:NSUTF8StringEncoding];
+ [files_strs addObject:fs_path_str];
+// NSLog( @"performDragOperation: file path: %s", fs_path );
+ }
+
+ NSString *joined=[files_strs componentsJoinedByString:@"\n"];
+
+ // Release the array of file paths
+ [files_strs release];
+
+ int dragXLocation = [sender draggingLocation].x - [self frame].origin.x;
+ int dragYLocation = [self frame].size.height - [sender draggingLocation].y; // Y coordinate is inverted, so we need to subtract from the height
+
+// NSLog( @"draggingUpdated: X coord: %d", dragXLocation );
+// NSLog( @"draggingUpdated: Y coord: %d", dragYLocation );
+
+ NSString *message = [NSString stringWithFormat:@"DD:%d:%d:%@", dragXLocation, dragYLocation, joined];
+
+ const char* res = message.UTF8String;
+
+ processMessage(res);
+
+ if ( disableWebViewDragAndDrop ) {
+ return YES;
+ }
+
+ return [super performDragOperation: sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id )sender {
+ if ( !enableDragAndDrop ) {
+ return [super draggingUpdated: sender];
+ }
+
+ NSPasteboard *pboard = [sender draggingPasteboard];
+
+ // if no types, then we'll just let the WKWebView handle the drag-n-drop as normal
+ NSArray * types = [pboard types];
+ if( !types ) {
+ return [super draggingUpdated: sender];
+ }
+
+ if ( disableWebViewDragAndDrop ) {
+ // we should call supper as otherwise events will not pass
+ [super draggingUpdated: sender];
+
+ // pass NSDragOperationGeneric = 4 to show regular hover for drag and drop. As we want to ignore webkit behaviours that depends on webpage
+ return 4;
+ }
+
+ return [super draggingUpdated: sender];
+}
+
+- (NSDragOperation)draggingEntered:(id )sender {
+ if ( !enableDragAndDrop ) {
+ return [super draggingEntered: sender];
+ }
+
+ NSPasteboard *pboard = [sender draggingPasteboard];
+
+ // if no types, then we'll just let the WKWebView handle the drag-n-drop as normal
+ NSArray * types = [pboard types];
+ if( !types ) {
+ return [super draggingEntered: sender];
+ }
+
+ if ( disableWebViewDragAndDrop ) {
+ // we should call supper as otherwise events will not pass
+ [super draggingEntered: sender];
+
+ // pass NSDragOperationGeneric = 4 to show regular hover for drag and drop. As we want to ignore webkit behaviours that depends on webpage
+ return 4;
+ }
+
+ return [super draggingEntered: sender];
+}
+
+@end
diff --git a/v2/internal/frontend/desktop/darwin/browser.go b/v2/internal/frontend/desktop/darwin/browser.go
index 417501c8e..c865ab6d9 100644
--- a/v2/internal/frontend/desktop/darwin/browser.go
+++ b/v2/internal/frontend/desktop/darwin/browser.go
@@ -4,11 +4,21 @@
package darwin
import (
+ "fmt"
"github.com/pkg/browser"
+ "github.com/wailsapp/wails/v2/internal/frontend/utils"
)
// BrowserOpenURL Use the default browser to open the url
-func (f *Frontend) BrowserOpenURL(url string) {
+func (f *Frontend) BrowserOpenURL(rawURL string) {
+ url, err := utils.ValidateAndSanitizeURL(rawURL)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error()))
+ return
+ }
+
// Specific method implementation
- _ = browser.OpenURL(url)
+ if err := browser.OpenURL(url); err != nil {
+ f.logger.Error("Unable to open default system browser")
+ }
}
diff --git a/v2/internal/frontend/desktop/darwin/callbacks.go b/v2/internal/frontend/desktop/darwin/callbacks.go
index 7d930a2f9..ab0d18e47 100644
--- a/v2/internal/frontend/desktop/darwin/callbacks.go
+++ b/v2/internal/frontend/desktop/darwin/callbacks.go
@@ -12,6 +12,7 @@ package darwin
#include
*/
import "C"
+
import (
"errors"
"strconv"
@@ -20,7 +21,6 @@ import (
)
func (f *Frontend) handleCallback(menuItemID uint) error {
-
menuItem := getMenuItemForID(menuItemID)
if menuItem == nil {
return errors.New("unknown menuItem ID: " + strconv.Itoa(int(menuItemID)))
diff --git a/v2/internal/frontend/desktop/darwin/clipboard.go b/v2/internal/frontend/desktop/darwin/clipboard.go
index eea6c79ae..c40ba8771 100644
--- a/v2/internal/frontend/desktop/darwin/clipboard.go
+++ b/v2/internal/frontend/desktop/darwin/clipboard.go
@@ -16,7 +16,6 @@ func (f *Frontend) ClipboardGetText() (string, error) {
}
func (f *Frontend) ClipboardSetText(text string) error {
-
copyCmd := exec.Command("pbcopy")
in, err := copyCmd.StdinPipe()
if err != nil {
diff --git a/v2/internal/frontend/desktop/darwin/dialog.go b/v2/internal/frontend/desktop/darwin/dialog.go
index c6be559cb..66bb2f13a 100644
--- a/v2/internal/frontend/desktop/darwin/dialog.go
+++ b/v2/internal/frontend/desktop/darwin/dialog.go
@@ -11,6 +11,7 @@ package darwin
#import "WailsContext.h"
*/
import "C"
+
import (
"encoding/json"
"fmt"
@@ -23,10 +24,12 @@ import (
)
// Obj-C dialog methods send the response to this channel
-var messageDialogResponse = make(chan int)
-var openFileDialogResponse = make(chan string)
-var saveFileDialogResponse = make(chan string)
-var dialogLock sync.Mutex
+var (
+ messageDialogResponse = make(chan int)
+ openFileDialogResponse = make(chan string)
+ saveFileDialogResponse = make(chan string)
+ dialogLock sync.Mutex
+)
// OpenDirectoryDialog prompts the user to select a directory
func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (string, error) {
@@ -74,7 +77,7 @@ func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool
filters := filterStrings.Join(";")
C.OpenFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, allowDirectories, allowFiles, canCreateDirectories, treatPackagesAsDirectories, resolveAliases, showHiddenFiles, allowMultipleFileSelection, c.String(filters))
- var result = <-openFileDialogResponse
+ result := <-openFileDialogResponse
var parsedResults []string
err := json.Unmarshal([]byte(result), &parsedResults)
@@ -130,7 +133,7 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e
filters := filterStrings.Join(";")
C.SaveFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, canCreateDirectories, treatPackagesAsDirectories, showHiddenFiles, c.String(filters))
- var result = <-saveFileDialogResponse
+ result := <-saveFileDialogResponse
return result, nil
}
@@ -165,7 +168,7 @@ func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string,
C.MessageDialog(f.mainWindow.context, dialogType, title, message, buttons[0], buttons[1], buttons[2], buttons[3], defaultButton, cancelButton, iconData, iconDataLength)
- var result = <-messageDialogResponse
+ result := <-messageDialogResponse
selectedC := buttons[result]
var selected string
diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go
index 7295e0ee6..6566445d5 100644
--- a/v2/internal/frontend/desktop/darwin/frontend.go
+++ b/v2/internal/frontend/desktop/darwin/frontend.go
@@ -8,19 +8,22 @@ package darwin
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
#import
#import "Application.h"
+#import "CustomProtocol.h"
#import "WailsContext.h"
#include
*/
import "C"
+
import (
"context"
"encoding/json"
"fmt"
"html/template"
"log"
+ "net"
"net/url"
- "strconv"
+ "os"
"unsafe"
"github.com/wailsapp/wails/v2/pkg/assetserver"
@@ -28,6 +31,7 @@ import (
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/originvalidator"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
@@ -35,18 +39,33 @@ import (
const startURL = "wails://wails/"
-var messageBuffer = make(chan string, 100)
-var requestBuffer = make(chan webview.Request, 100)
-var callbackBuffer = make(chan uint, 10)
+type bindingsMessage struct {
+ message string
+ source string
+ isMainFrame bool
+}
+
+var (
+ messageBuffer = make(chan string, 100)
+ bindingsMessageBuffer = make(chan *bindingsMessage, 100)
+ requestBuffer = make(chan webview.Request, 100)
+ callbackBuffer = make(chan uint, 10)
+ openFilepathBuffer = make(chan string, 100)
+ openUrlBuffer = make(chan string, 100)
+ secondInstanceBuffer = make(chan options.SecondInstanceData, 1)
+)
type Frontend struct {
-
// Context
ctx context.Context
frontendOptions *options.App
logger *logger.Logger
debug bool
+ devtoolsEnabled bool
+
+ // Keep single instance lock file, so that it will not be GC and lock will exist while app is running
+ singleInstanceLockFile *os.File
// Assets
assets *assetserver.AssetServer
@@ -56,6 +75,8 @@ type Frontend struct {
mainWindow *Window
bindings *binding.Bindings
dispatcher frontend.Dispatcher
+
+ originValidator *originvalidator.OriginValidator
}
func (f *Frontend) RunMainLoop() {
@@ -75,10 +96,20 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
ctx: ctx,
}
result.startURL, _ = url.Parse(startURL)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
+
+ // this should be initialized as early as possible to handle first instance launch
+ C.StartCustomProtocolHandler()
if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil {
result.startURL = _starturl
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
} else {
+ if port, _ := ctx.Value("assetserverport").(string); port != "" {
+ result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
+ }
+
var bindings string
var err error
if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated {
@@ -101,22 +132,72 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
}
go result.startMessageProcessor()
+ go result.startBindingsMessageProcessor()
go result.startCallbackProcessor()
+ go result.startFileOpenProcessor()
+ go result.startUrlOpenProcessor()
+ go result.startSecondInstanceProcessor()
return result
}
+func (f *Frontend) startFileOpenProcessor() {
+ for filePath := range openFilepathBuffer {
+ f.ProcessOpenFileEvent(filePath)
+ }
+}
+
+func (f *Frontend) startUrlOpenProcessor() {
+ for url := range openUrlBuffer {
+ f.ProcessOpenUrlEvent(url)
+ }
+}
+
+func (f *Frontend) startSecondInstanceProcessor() {
+ for secondInstanceData := range secondInstanceBuffer {
+ if f.frontendOptions.SingleInstanceLock != nil &&
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch != nil {
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch(secondInstanceData)
+ }
+ }
+}
+
func (f *Frontend) startMessageProcessor() {
for message := range messageBuffer {
f.processMessage(message)
}
}
+
+func (f *Frontend) startBindingsMessageProcessor() {
+ for msg := range bindingsMessageBuffer {
+ // Apple webkit doesn't provide origin of main frame. So we can't verify in case of iFrame that top level origin is allowed.
+ if !msg.isMainFrame {
+ f.logger.Error("Blocked request from not main frame")
+ continue
+ }
+
+ origin, err := f.originValidator.GetOriginFromURL(msg.source)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("failed to get origin for URL %q: %v", msg.source, err))
+ continue
+ }
+
+ allowed := f.originValidator.IsOriginAllowed(origin)
+ if !allowed {
+ f.logger.Error("Blocked request from unauthorized origin: %s", origin)
+ continue
+ }
+
+ f.processMessage(msg.message)
+ }
+}
+
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.assets.ServeWebViewRequest(request)
- request.Release()
}
}
+
func (f *Frontend) startCallbackProcessor() {
for callback := range callbackBuffer {
err := f.handleCallback(callback)
@@ -135,25 +216,32 @@ func (f *Frontend) WindowReloadApp() {
}
func (f *Frontend) WindowSetSystemDefaultTheme() {
- return
}
func (f *Frontend) WindowSetLightTheme() {
- return
}
func (f *Frontend) WindowSetDarkTheme() {
- return
}
func (f *Frontend) Run(ctx context.Context) error {
f.ctx = ctx
- var _debug = ctx.Value("debug")
+
+ if f.frontendOptions.SingleInstanceLock != nil {
+ f.singleInstanceLockFile = SetupSingleInstance(f.frontendOptions.SingleInstanceLock.UniqueId)
+ }
+
+ _debug := ctx.Value("debug")
+ _devtoolsEnabled := ctx.Value("devtoolsEnabled")
+
if _debug != nil {
f.debug = _debug.(bool)
}
+ if _devtoolsEnabled != nil {
+ f.devtoolsEnabled = _devtoolsEnabled.(bool)
+ }
- mainWindow := NewWindow(f.frontendOptions, f.debug)
+ mainWindow := NewWindow(f.frontendOptions, f.debug, f.devtoolsEnabled)
f.mainWindow = mainWindow
f.mainWindow.Center()
@@ -169,6 +257,7 @@ func (f *Frontend) Run(ctx context.Context) error {
func (f *Frontend) WindowCenter() {
f.mainWindow.Center()
}
+
func (f *Frontend) WindowSetAlwaysOnTop(onTop bool) {
f.mainWindow.SetAlwaysOnTop(onTop)
}
@@ -176,6 +265,7 @@ func (f *Frontend) WindowSetAlwaysOnTop(onTop bool) {
func (f *Frontend) WindowSetPosition(x, y int) {
f.mainWindow.SetPosition(x, y)
}
+
func (f *Frontend) WindowGetPosition() (int, int) {
return f.mainWindow.GetPosition()
}
@@ -207,6 +297,7 @@ func (f *Frontend) WindowShow() {
func (f *Frontend) WindowHide() {
f.mainWindow.Hide()
}
+
func (f *Frontend) Show() {
f.mainWindow.ShowApplication()
}
@@ -214,18 +305,23 @@ func (f *Frontend) Show() {
func (f *Frontend) Hide() {
f.mainWindow.HideApplication()
}
+
func (f *Frontend) WindowMaximise() {
f.mainWindow.Maximise()
}
+
func (f *Frontend) WindowToggleMaximise() {
f.mainWindow.ToggleMaximise()
}
+
func (f *Frontend) WindowUnmaximise() {
f.mainWindow.UnMaximise()
}
+
func (f *Frontend) WindowMinimise() {
f.mainWindow.Minimise()
}
+
func (f *Frontend) WindowUnminimise() {
f.mainWindow.UnMinimise()
}
@@ -233,6 +329,7 @@ func (f *Frontend) WindowUnminimise() {
func (f *Frontend) WindowSetMinSize(width int, height int) {
f.mainWindow.SetMinSize(width, height)
}
+
func (f *Frontend) WindowSetMaxSize(width int, height int) {
f.mainWindow.SetMaxSize(width, height)
}
@@ -276,6 +373,10 @@ func (f *Frontend) Quit() {
f.mainWindow.Quit()
}
+func (f *Frontend) WindowPrint() {
+ f.mainWindow.Print()
+}
+
type EventNotify struct {
Name string `json:"name"`
Data []interface{} `json:"data"`
@@ -295,7 +396,6 @@ func (f *Frontend) Notify(name string, data ...interface{}) {
}
func (f *Frontend) processMessage(message string) {
-
if message == "DomReady" {
if f.frontendOptions.OnDomReady != nil {
f.frontendOptions.OnDomReady(f.ctx)
@@ -306,6 +406,16 @@ func (f *Frontend) processMessage(message string) {
if message == "runtime:ready" {
cmd := fmt.Sprintf("window.wails.setCSSDragProperties('%s', '%s');", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
f.ExecJS(cmd)
+
+ if f.frontendOptions.DragAndDrop != nil && f.frontendOptions.DragAndDrop.EnableFileDrop {
+ f.ExecJS("window.wails.flags.enableWailsDragAndDrop = true;")
+ }
+
+ return
+ }
+
+ if message == "wails:openInspector" {
+ showInspector(f.mainWindow.context)
return
}
@@ -333,11 +443,26 @@ func (f *Frontend) processMessage(message string) {
f.logger.Info("Unknown message returned from dispatcher: %+v", result)
}
}()
+}
+func (f *Frontend) ProcessOpenFileEvent(filePath string) {
+ if f.frontendOptions.Mac != nil && f.frontendOptions.Mac.OnFileOpen != nil {
+ f.frontendOptions.Mac.OnFileOpen(filePath)
+ }
+}
+
+func (f *Frontend) ProcessOpenUrlEvent(url string) {
+ if f.frontendOptions.Mac != nil && f.frontendOptions.Mac.OnUrlOpen != nil {
+ f.frontendOptions.Mac.OnUrlOpen(url)
+ }
}
func (f *Frontend) Callback(message string) {
- f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
+ escaped, err := json.Marshal(message)
+ if err != nil {
+ panic(err)
+ }
+ f.ExecJS(`window.wails.Callback(` + string(escaped) + `);`)
}
func (f *Frontend) ExecJS(js string) {
@@ -366,12 +491,35 @@ func processMessage(message *C.char) {
messageBuffer <- goMessage
}
+//export processBindingMessage
+func processBindingMessage(message *C.char, source *C.char, fromMainFrame bool) {
+ goMessage := C.GoString(message)
+ goSource := C.GoString(source)
+ bindingsMessageBuffer <- &bindingsMessage{
+ message: goMessage,
+ source: goSource,
+ isMainFrame: fromMainFrame,
+ }
+}
+
//export processCallback
func processCallback(callbackID uint) {
callbackBuffer <- callbackID
}
//export processURLRequest
-func processURLRequest(ctx unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
+func processURLRequest(_ unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
requestBuffer <- webview.NewRequest(wkURLSchemeTask)
}
+
+//export HandleOpenFile
+func HandleOpenFile(filePath *C.char) {
+ goFilepath := C.GoString(filePath)
+ openFilepathBuffer <- goFilepath
+}
+
+//export HandleOpenURL
+func HandleOpenURL(url *C.char) {
+ goUrl := C.GoString(url)
+ openUrlBuffer <- goUrl
+}
diff --git a/v2/internal/frontend/desktop/darwin/inspector.go b/v2/internal/frontend/desktop/darwin/inspector.go
index 3021c5c16..dc3f08969 100644
--- a/v2/internal/frontend/desktop/darwin/inspector.go
+++ b/v2/internal/frontend/desktop/darwin/inspector.go
@@ -1,4 +1,4 @@
-//go:build darwin && !(dev || debug)
+//go:build darwin && !(dev || debug || devtools)
package darwin
@@ -6,6 +6,5 @@ import (
"unsafe"
)
-func showInspector(context unsafe.Pointer) {
-
+func showInspector(_ unsafe.Pointer) {
}
diff --git a/v2/internal/frontend/desktop/darwin/inspector_dev.go b/v2/internal/frontend/desktop/darwin/inspector_dev.go
index 4e63e23e3..e79b9c3e7 100644
--- a/v2/internal/frontend/desktop/darwin/inspector_dev.go
+++ b/v2/internal/frontend/desktop/darwin/inspector_dev.go
@@ -1,4 +1,4 @@
-//go:build darwin && (dev || debug)
+//go:build darwin && (dev || debug || devtools)
package darwin
@@ -11,6 +11,8 @@ package darwin
#import
#import "WailsContext.h"
+extern void processMessage(const char *message);
+
@interface _WKInspector : NSObject
- (void)show;
- (void)detach;
@@ -21,14 +23,45 @@ package darwin
@end
void showInspector(void *inctx) {
- WailsContext *ctx = (__bridge WailsContext*) inctx;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+ ON_MAIN_THREAD(
+ if (@available(macOS 12.0, *)) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
- [ctx.webview._inspector show];
- dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
- dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
- // Detach must be deferred a little bit and is ignored directly after a show.
- [ctx.webview._inspector detach];
- });
+ @try {
+ [ctx.webview._inspector show];
+ } @catch (NSException *exception) {
+ NSLog(@"Opening the inspector failed: %@", exception.reason);
+ return;
+ }
+
+ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
+ dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
+ // Detach must be deferred a little bit and is ignored directly after a show.
+ @try {
+ [ctx.webview._inspector detach];
+ } @catch (NSException *exception) {
+ NSLog(@"Detaching the inspector failed: %@", exception.reason);
+ }
+ });
+ } else {
+ NSLog(@"Opening the inspector needs at least MacOS 12");
+ }
+ );
+#endif
+}
+
+void setupF12hotkey() {
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
+ if (event.keyCode == 111 &&
+ event.modifierFlags & NSEventModifierFlagFunction &&
+ event.modifierFlags & NSEventModifierFlagCommand &&
+ event.modifierFlags & NSEventModifierFlagShift) {
+ processMessage("wails:openInspector");
+ return nil;
+ }
+ return event;
+ }];
}
*/
import "C"
@@ -36,6 +69,10 @@ import (
"unsafe"
)
+func init() {
+ C.setupF12hotkey()
+}
+
func showInspector(context unsafe.Pointer) {
C.showInspector(context)
}
diff --git a/v2/internal/frontend/desktop/darwin/main.m b/v2/internal/frontend/desktop/darwin/main.m
index d2f39bccb..75a84dc76 100644
--- a/v2/internal/frontend/desktop/darwin/main.m
+++ b/v2/internal/frontend/desktop/darwin/main.m
@@ -203,6 +203,7 @@ int main(int argc, const char * argv[]) {
// insert code here...
int frameless = 0;
int resizable = 1;
+ int zoomable = 0;
int fullscreen = 1;
int fullSizeContent = 1;
int hideTitleBar = 0;
@@ -215,10 +216,11 @@ int main(int argc, const char * argv[]) {
int hideWindowOnClose = 0;
const char* appearance = "NSAppearanceNameDarkAqua";
int windowIsTranslucent = 1;
- int debug = 1;
+ int devtoolsEnabled = 1;
+ int defaultContextMenuEnabled = 1;
int windowStartState = 0;
int startsHidden = 0;
- WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState,
+ WailsContext *result = Create("OI OI!",400,400, frameless, resizable, zoomable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled, windowStartState,
startsHidden, 400, 400, 600, 600, false);
SetBackgroundColour(result, 255, 0, 0, 255);
void *m = NewMenu("");
diff --git a/v2/internal/frontend/desktop/darwin/menu.go b/v2/internal/frontend/desktop/darwin/menu.go
index 8afb63fb9..24dbe3201 100644
--- a/v2/internal/frontend/desktop/darwin/menu.go
+++ b/v2/internal/frontend/desktop/darwin/menu.go
@@ -13,6 +13,7 @@ package darwin
#include
*/
import "C"
+
import (
"unsafe"
@@ -122,7 +123,6 @@ func processMenuItem(parent *NSMenu, menuItem *menu.MenuItem) *MenuItem {
}
return parent.AddMenuItem(menuItem)
-
}
func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
@@ -130,6 +130,5 @@ func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
}
func (f *Frontend) MenuUpdateApplicationMenu() {
- f.MenuSetApplicationMenu(f.frontendOptions.Menu)
f.mainWindow.UpdateApplicationMenu()
}
diff --git a/v2/internal/frontend/desktop/darwin/menuitem.go b/v2/internal/frontend/desktop/darwin/menuitem.go
index 00ad57aa3..64aab84a9 100644
--- a/v2/internal/frontend/desktop/darwin/menuitem.go
+++ b/v2/internal/frontend/desktop/darwin/menuitem.go
@@ -13,16 +13,19 @@ package darwin
#include
*/
import "C"
+
import (
"log"
"math"
"sync"
)
-var menuItemToID = make(map[*MenuItem]uint)
-var idToMenuItem = make(map[uint]*MenuItem)
-var menuItemLock sync.Mutex
-var menuItemIDCounter uint = 0
+var (
+ menuItemToID = make(map[*MenuItem]uint)
+ idToMenuItem = make(map[uint]*MenuItem)
+ menuItemLock sync.Mutex
+ menuItemIDCounter uint = 0
+)
func createMenuItemID(item *MenuItem) uint {
menuItemLock.Lock()
diff --git a/v2/internal/frontend/desktop/darwin/message.h b/v2/internal/frontend/desktop/darwin/message.h
index 66110841d..86506f868 100644
--- a/v2/internal/frontend/desktop/darwin/message.h
+++ b/v2/internal/frontend/desktop/darwin/message.h
@@ -15,6 +15,7 @@ extern "C"
#endif
void processMessage(const char *);
+void processBindingMessage(const char *, const char *, bool);
void processURLRequest(void *, void*);
void processMessageDialogResponse(int);
void processOpenFileDialogResponse(const char*);
diff --git a/v2/internal/frontend/desktop/darwin/screen.go b/v2/internal/frontend/desktop/darwin/screen.go
index 7b552065a..bd64a31f9 100644
--- a/v2/internal/frontend/desktop/darwin/screen.go
+++ b/v2/internal/frontend/desktop/darwin/screen.go
@@ -18,6 +18,8 @@ typedef struct Screen {
int isPrimary;
int height;
int width;
+ int pHeight;
+ int pWidth;
} Screen;
@@ -48,14 +50,43 @@ Screen GetNthScreen(int nth, void *inctx){
returnScreen.isPrimary = nth==0;
returnScreen.height = (int) nthScreen.frame.size.height;
returnScreen.width = (int) nthScreen.frame.size.width;
+
+ returnScreen.pWidth = 0;
+ returnScreen.pHeight = 0;
+
+ // https://stackoverflow.com/questions/13859109/how-to-programmatically-determine-native-pixel-resolution-of-retina-macbook-pro
+ CGDirectDisplayID sid = ((NSNumber *)[nthScreen.deviceDescription
+ objectForKey:@"NSScreenNumber"]).unsignedIntegerValue;
+
+ CFArrayRef ms = CGDisplayCopyAllDisplayModes(sid, NULL);
+ CFIndex n = CFArrayGetCount(ms);
+ for (int i = 0; i < n; i++) {
+ CGDisplayModeRef m = (CGDisplayModeRef) CFArrayGetValueAtIndex(ms, i);
+ if (CGDisplayModeGetIOFlags(m) & kDisplayModeNativeFlag) {
+ // This corresponds with "System Settings" -> General -> About -> Displays
+ returnScreen.pWidth = CGDisplayModeGetPixelWidth(m);
+ returnScreen.pHeight = CGDisplayModeGetPixelHeight(m);
+ break;
+ }
+ }
+ CFRelease(ms);
+
+ if (returnScreen.pWidth == 0 || returnScreen.pHeight == 0) {
+ // If there was no native resolution take a best fit approach and use the backing pixel size.
+ NSRect pSize = [nthScreen convertRectToBacking:nthScreen.frame];
+ returnScreen.pHeight = (int) pSize.size.height;
+ returnScreen.pWidth = (int) pSize.size.width;
+ }
return returnScreen;
}
*/
import "C"
+
import (
- "github.com/wailsapp/wails/v2/internal/frontend"
"unsafe"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
)
func GetAllScreens(wailsContext unsafe.Pointer) ([]frontend.Screen, error) {
@@ -65,11 +96,21 @@ func GetAllScreens(wailsContext unsafe.Pointer) ([]frontend.Screen, error) {
for screeNum := 0; screeNum < numScreens; screeNum++ {
screenNumC := C.int(screeNum)
cScreen := C.GetNthScreen(screenNumC, wailsContext)
+
screen := frontend.Screen{
Height: int(cScreen.height),
Width: int(cScreen.width),
IsCurrent: cScreen.isCurrent == C.int(1),
IsPrimary: cScreen.isPrimary == C.int(1),
+
+ Size: frontend.ScreenSize{
+ Height: int(cScreen.height),
+ Width: int(cScreen.width),
+ },
+ PhysicalSize: frontend.ScreenSize{
+ Height: int(cScreen.pHeight),
+ Width: int(cScreen.pWidth),
+ },
}
screens = append(screens, screen)
}
diff --git a/v2/internal/frontend/desktop/darwin/single_instance.go b/v2/internal/frontend/desktop/darwin/single_instance.go
new file mode 100644
index 000000000..27b34045b
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/single_instance.go
@@ -0,0 +1,95 @@
+//go:build darwin
+// +build darwin
+
+package darwin
+
+/*
+#cgo CFLAGS: -x objective-c
+#cgo LDFLAGS: -framework Foundation -framework Cocoa
+#import "AppDelegate.h"
+
+*/
+import "C"
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func SetupSingleInstance(uniqueID string) *os.File {
+ lockFilePath := getTempDir()
+ lockFileName := uniqueID + ".lock"
+ file, err := createLockFile(lockFilePath + "/" + lockFileName)
+ // if lockFile exist – send notification to second instance
+ if err != nil {
+ c := NewCalloc()
+ defer c.Free()
+ singleInstanceUniqueId := c.String(uniqueID)
+
+ data, err := options.NewSecondInstanceData()
+ if err != nil {
+ return nil
+ }
+
+ serialized, err := json.Marshal(data)
+ if err != nil {
+ return nil
+ }
+
+ C.SendDataToFirstInstance(singleInstanceUniqueId, c.String(string(serialized)))
+
+ os.Exit(0)
+ }
+
+ return file
+}
+
+//export HandleSecondInstanceData
+func HandleSecondInstanceData(secondInstanceMessage *C.char) {
+ message := C.GoString(secondInstanceMessage)
+
+ var secondInstanceData options.SecondInstanceData
+
+ err := json.Unmarshal([]byte(message), &secondInstanceData)
+ if err == nil {
+ secondInstanceBuffer <- secondInstanceData
+ }
+}
+
+// createLockFile tries to create a file with given name and acquire an
+// exclusive lock on it. If the file already exists AND is still locked, it will
+// fail.
+func createLockFile(filename string) (*os.File, error) {
+ file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0o600)
+ if err != nil {
+ fmt.Printf("Failed to open lockfile %s: %s", filename, err)
+ return nil, err
+ }
+
+ err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
+ if err != nil {
+ // Flock failed for some other reason than other instance already lock it. Print it in logs for possible debugging.
+ if !strings.Contains(err.Error(), "resource temporarily unavailable") {
+ fmt.Printf("Failed to lock lockfile %s: %s", filename, err)
+ }
+ file.Close()
+ return nil, err
+ }
+
+ return file, nil
+}
+
+// If app is sandboxed, golang os.TempDir() will return path that will not be accessible. So use native macOS temp dir function.
+func getTempDir() string {
+ cstring := C.GetMacOsNativeTempDir()
+ path := C.GoString(cstring)
+ C.free(unsafe.Pointer(cstring))
+
+ return path
+}
diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go
index 8b4c77799..87d4213d9 100644
--- a/v2/internal/frontend/desktop/darwin/window.go
+++ b/v2/internal/frontend/desktop/darwin/window.go
@@ -13,6 +13,7 @@ package darwin
#include
*/
import "C"
+
import (
"log"
"runtime"
@@ -31,6 +32,8 @@ func init() {
type Window struct {
context unsafe.Pointer
+
+ applicationMenu *menu.Menu
}
func bool2Cint(value bool) C.int {
@@ -40,8 +43,12 @@ func bool2Cint(value bool) C.int {
return C.int(0)
}
-func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
+func bool2CboolPtr(value bool) *C.bool {
+ v := C.bool(value)
+ return &v
+}
+func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window {
c := NewCalloc()
defer c.Free()
@@ -51,11 +58,14 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
startsHidden := bool2Cint(frontendOptions.StartHidden)
- debug := bool2Cint(debugMode)
+ devtoolsEnabled := bool2Cint(devtools)
+ defaultContextMenuEnabled := bool2Cint(debug || frontendOptions.EnableDefaultContextMenu)
+ singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil)
- var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
- var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
+ var fullSizeContent, hideTitleBar, zoomable, hideTitle, useToolbar, webviewIsTransparent C.int
+ var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent, contentProtection C.int
var appearance, title *C.char
+ var preferences C.struct_Preferences
width := C.int(frontendOptions.Width)
height := C.int(frontendOptions.Height)
@@ -67,8 +77,17 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
title = c.String(frontendOptions.Title)
+ singleInstanceUniqueIdStr := ""
+ if frontendOptions.SingleInstanceLock != nil {
+ singleInstanceUniqueIdStr = frontendOptions.SingleInstanceLock.UniqueId
+ }
+ singleInstanceUniqueId := c.String(singleInstanceUniqueIdStr)
+
enableFraudulentWebsiteWarnings := C.bool(frontendOptions.EnableFraudulentWebsiteDetection)
+ enableDragAndDrop := C.bool(frontendOptions.DragAndDrop != nil && frontendOptions.DragAndDrop.EnableFileDrop)
+ disableWebViewDragAndDrop := C.bool(frontendOptions.DragAndDrop != nil && frontendOptions.DragAndDrop.DisableWebViewDrop)
+
if frontendOptions.Mac != nil {
mac := frontendOptions.Mac
if mac.TitleBar != nil {
@@ -79,15 +98,35 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
titlebarAppearsTransparent = bool2Cint(mac.TitleBar.TitlebarAppearsTransparent)
hideToolbarSeparator = bool2Cint(mac.TitleBar.HideToolbarSeparator)
}
+
+ if mac.Preferences != nil {
+ if mac.Preferences.TabFocusesLinks.IsSet() {
+ preferences.tabFocusesLinks = bool2CboolPtr(mac.Preferences.TabFocusesLinks.Get())
+ }
+
+ if mac.Preferences.TextInteractionEnabled.IsSet() {
+ preferences.textInteractionEnabled = bool2CboolPtr(mac.Preferences.TextInteractionEnabled.Get())
+ }
+
+ if mac.Preferences.FullscreenEnabled.IsSet() {
+ preferences.fullscreenEnabled = bool2CboolPtr(mac.Preferences.FullscreenEnabled.Get())
+ }
+ }
+
+ zoomable = bool2Cint(!frontendOptions.Mac.DisableZoom)
+
windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent)
webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent)
+ contentProtection = bool2Cint(mac.ContentProtection)
appearance = c.String(string(mac.Appearance))
}
- var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
+ var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, zoomable, fullscreen, fullSizeContent,
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
- alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden,
- minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings)
+ alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, contentProtection, devtoolsEnabled, defaultContextMenuEnabled,
+ windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings,
+ preferences, singleInstanceEnabled, singleInstanceUniqueId, enableDragAndDrop, disableWebViewDragAndDrop,
+ )
// Create menu
result := &Window{
@@ -114,7 +153,7 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
result.SetApplicationMenu(frontendOptions.Menu)
}
- if debugMode && frontendOptions.Debug.OpenInspectorOnStartup {
+ if debug && frontendOptions.Debug.OpenInspectorOnStartup {
showInspector(result.context)
}
return result
@@ -165,6 +204,7 @@ func (w *Window) SetTitle(title string) {
func (w *Window) Maximise() {
C.Maximise(w.context)
}
+
func (w *Window) ToggleMaximise() {
C.ToggleMaximise(w.context)
}
@@ -220,6 +260,7 @@ func (w *Window) Show() {
func (w *Window) Hide() {
C.Hide(w.context)
}
+
func (w *Window) ShowApplication() {
C.ShowApplication(w.context)
}
@@ -254,11 +295,19 @@ func (w *Window) Size() (int, int) {
}
func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
- mainMenu := NewNSMenu(w.context, "")
- processMenu(mainMenu, inMenu)
- C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
+ w.applicationMenu = inMenu
+ w.UpdateApplicationMenu()
}
func (w *Window) UpdateApplicationMenu() {
+ mainMenu := NewNSMenu(w.context, "")
+ if w.applicationMenu != nil {
+ processMenu(mainMenu, w.applicationMenu)
+ }
+ C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
C.UpdateApplicationMenu(w.context)
}
+
+func (w Window) Print() {
+ C.WindowPrint(w.context)
+}
diff --git a/v2/internal/frontend/desktop/linux/browser.go b/v2/internal/frontend/desktop/linux/browser.go
index 47bf0ba5d..962e3b28a 100644
--- a/v2/internal/frontend/desktop/linux/browser.go
+++ b/v2/internal/frontend/desktop/linux/browser.go
@@ -3,10 +3,21 @@
package linux
-import "github.com/pkg/browser"
+import (
+ "fmt"
+ "github.com/pkg/browser"
+ "github.com/wailsapp/wails/v2/internal/frontend/utils"
+)
// BrowserOpenURL Use the default browser to open the url
-func (f *Frontend) BrowserOpenURL(url string) {
+func (f *Frontend) BrowserOpenURL(rawURL string) {
+ url, err := utils.ValidateAndSanitizeURL(rawURL)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error()))
+ return
+ }
// Specific method implementation
- _ = browser.OpenURL(url)
+ if err := browser.OpenURL(url); err != nil {
+ f.logger.Error("Unable to open default system browser")
+ }
}
diff --git a/v2/internal/frontend/desktop/linux/clipboard.go b/v2/internal/frontend/desktop/linux/clipboard.go
index 88b8c713f..a2a46dacc 100644
--- a/v2/internal/frontend/desktop/linux/clipboard.go
+++ b/v2/internal/frontend/desktop/linux/clipboard.go
@@ -4,7 +4,9 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go
index 07d270f13..2942a112e 100644
--- a/v2/internal/frontend/desktop/linux/frontend.go
+++ b/v2/internal/frontend/desktop/linux/frontend.go
@@ -4,7 +4,9 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
@@ -71,33 +73,50 @@ static void install_signal_handlers()
#endif
}
+static gboolean install_signal_handlers_idle(gpointer data) {
+ (void)data;
+ install_signal_handlers();
+ return G_SOURCE_REMOVE;
+}
+
+static void fix_signal_handlers_after_gtk_init() {
+ g_idle_add(install_signal_handlers_idle, NULL);
+}
+
*/
import "C"
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"log"
- "net/http"
+ "net"
"net/url"
"os"
"runtime"
- "strconv"
"strings"
+ "sync"
"text/template"
"unsafe"
"github.com/wailsapp/wails/v2/pkg/assetserver"
+ "github.com/wailsapp/wails/v2/pkg/assetserver/webview"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/originvalidator"
wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
+var initOnce = sync.Once{}
+
const startURL = "wails://wails/"
+var secondInstanceBuffer = make(chan options.SecondInstanceData, 1)
+
type Frontend struct {
// Context
@@ -106,6 +125,7 @@ type Frontend struct {
frontendOptions *options.App
logger *logger.Logger
debug bool
+ devtoolsEnabled bool
// Assets
assets *assetserver.AssetServer
@@ -115,6 +135,8 @@ type Frontend struct {
mainWindow *Window
bindings *binding.Bindings
dispatcher frontend.Dispatcher
+
+ originValidator *originvalidator.OriginValidator
}
func (f *Frontend) RunMainLoop() {
@@ -125,18 +147,19 @@ func (f *Frontend) WindowClose() {
f.mainWindow.Destroy()
}
-func init() {
- runtime.LockOSThread()
-
- // Set GDK_BACKEND=x11 if currently unset and XDG_SESSION_TYPE is unset, unspecified or x11 to prevent warnings
- if os.Getenv("GDK_BACKEND") == "" && (os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "unspecified" || os.Getenv("XDG_SESSION_TYPE") == "x11") {
- _ = os.Setenv("GDK_BACKEND", "x11")
- }
-
- C.gtk_init(nil, nil)
-}
-
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
+ initOnce.Do(func() {
+ runtime.LockOSThread()
+
+ // Set GDK_BACKEND=x11 if currently unset and XDG_SESSION_TYPE is unset, unspecified or x11 to prevent warnings
+ if os.Getenv("GDK_BACKEND") == "" && (os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "unspecified" || os.Getenv("XDG_SESSION_TYPE") == "x11") {
+ _ = os.Setenv("GDK_BACKEND", "x11")
+ }
+
+ if ok := C.gtk_init_check(nil, nil); ok != 1 {
+ panic(errors.New("failed to init GTK"))
+ }
+ })
result := &Frontend{
frontendOptions: appoptions,
@@ -146,10 +169,17 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
ctx: ctx,
}
result.startURL, _ = url.Parse(startURL)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil {
result.startURL = _starturl
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
} else {
+ if port, _ := ctx.Value("assetserverport").(string); port != "" {
+ result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
+ }
+
var bindings string
var err error
if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated {
@@ -166,21 +196,33 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
}
result.assets = assets
- // Start 10 processors to handle requests in parallel
- for i := 0; i < 10; i++ {
- go result.startRequestProcessor()
- }
+ go result.startRequestProcessor()
}
go result.startMessageProcessor()
+ go result.startBindingsMessageProcessor()
var _debug = ctx.Value("debug")
+ var _devtoolsEnabled = ctx.Value("devtoolsEnabled")
+
if _debug != nil {
result.debug = _debug.(bool)
}
- result.mainWindow = NewWindow(appoptions, result.debug)
+ if _devtoolsEnabled != nil {
+ result.devtoolsEnabled = _devtoolsEnabled.(bool)
+ }
- C.install_signal_handlers()
+ result.mainWindow = NewWindow(appoptions, result.debug, result.devtoolsEnabled)
+
+ C.fix_signal_handlers_after_gtk_init()
+
+ if appoptions.Linux != nil && appoptions.Linux.ProgramName != "" {
+ prgname := C.CString(appoptions.Linux.ProgramName)
+ C.g_set_prgname(prgname)
+ C.free(unsafe.Pointer(prgname))
+ }
+
+ go result.startSecondInstanceProcessor()
return result
}
@@ -191,6 +233,24 @@ func (f *Frontend) startMessageProcessor() {
}
}
+func (f *Frontend) startBindingsMessageProcessor() {
+ for msg := range bindingsMessageBuffer {
+ origin, err := f.originValidator.GetOriginFromURL(msg.source)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("failed to get origin for URL %q: %v", msg.source, err))
+ continue
+ }
+
+ allowed := f.originValidator.IsOriginAllowed(origin)
+ if !allowed {
+ f.logger.Error("Blocked request from unauthorized origin: %s", origin)
+ continue
+ }
+
+ f.processMessage(msg.message)
+ }
+}
+
func (f *Frontend) WindowReload() {
f.ExecJS("runtime.WindowReload();")
}
@@ -216,6 +276,10 @@ func (f *Frontend) Run(ctx context.Context) error {
}
}()
+ if f.frontendOptions.SingleInstanceLock != nil {
+ SetupSingleInstance(f.frontendOptions.SingleInstanceLock.UniqueId)
+ }
+
f.mainWindow.Run(f.startURL.String())
return nil
@@ -343,6 +407,10 @@ func (f *Frontend) Quit() {
f.mainWindow.Quit()
}
+func (f *Frontend) WindowPrint() {
+ f.ExecJS("window.print();")
+}
+
type EventNotify struct {
Name string `json:"name"`
Data []interface{} `json:"data"`
@@ -387,6 +455,11 @@ func (f *Frontend) processMessage(message string) {
return
}
+ if message == "wails:showInspector" {
+ f.mainWindow.ShowInspector()
+ return
+ }
+
if strings.HasPrefix(message, "resize:") {
if !f.mainWindow.IsFullScreen() {
sl := strings.Split(message, ":")
@@ -406,12 +479,24 @@ func (f *Frontend) processMessage(message string) {
if message == "runtime:ready" {
cmd := fmt.Sprintf(
"window.wails.setCSSDragProperties('%s', '%s');\n"+
- "window.wails.flags.deferDragToMouseMove = true;", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
+ "window.wails.setCSSDropProperties('%s', '%s');\n"+
+ "window.wails.flags.deferDragToMouseMove = true;",
+ f.frontendOptions.CSSDragProperty,
+ f.frontendOptions.CSSDragValue,
+ f.frontendOptions.DragAndDrop.CSSDropProperty,
+ f.frontendOptions.DragAndDrop.CSSDropValue,
+ )
+
f.ExecJS(cmd)
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
f.ExecJS("window.wails.flags.enableResize = true;")
}
+
+ if f.frontendOptions.DragAndDrop.EnableFileDrop {
+ f.ExecJS("window.wails.flags.enableWailsDragAndDrop = true;")
+ }
+
return
}
@@ -437,7 +522,11 @@ func (f *Frontend) processMessage(message string) {
}
func (f *Frontend) Callback(message string) {
- f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
+ escaped, err := json.Marshal(message)
+ if err != nil {
+ panic(err)
+ }
+ f.ExecJS(`window.wails.Callback(` + string(escaped) + `);`)
}
func (f *Frontend) startDrag() {
@@ -453,7 +542,13 @@ func (f *Frontend) ExecJS(js string) {
f.mainWindow.ExecJS(js)
}
+type bindingsMessage struct {
+ message string
+ source string
+}
+
var messageBuffer = make(chan string, 100)
+var bindingsMessageBuffer = make(chan *bindingsMessage, 100)
//export processMessage
func processMessage(message *C.char) {
@@ -461,50 +556,34 @@ func processMessage(message *C.char) {
messageBuffer <- goMessage
}
-var requestBuffer = make(chan unsafe.Pointer, 100)
+//export processBindingMessage
+func processBindingMessage(message *C.char, source *C.char) {
+ goMessage := C.GoString(message)
+ goSource := C.GoString(source)
+ bindingsMessageBuffer <- &bindingsMessage{
+ message: goMessage,
+ source: goSource,
+ }
+}
+
+var requestBuffer = make(chan webview.Request, 100)
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
- f.processRequest(request)
- C.g_object_unref(C.gpointer(request))
+ f.assets.ServeWebViewRequest(request)
}
}
//export processURLRequest
func processURLRequest(request unsafe.Pointer) {
- // Increment reference counter to allow async processing, will be decremented after the processing
- // has been finished by a worker.
- C.g_object_ref(C.gpointer(request))
- requestBuffer <- request
+ requestBuffer <- webview.NewRequest(request)
}
-func (f *Frontend) processRequest(request unsafe.Pointer) {
- req := (*C.WebKitURISchemeRequest)(request)
- uri := C.webkit_uri_scheme_request_get_uri(req)
- goURI := C.GoString(uri)
-
- rw := &webKitResponseWriter{req: req}
- defer rw.Close()
-
- f.assets.ProcessHTTPRequestLegacy(
- rw,
- func() (*http.Request, error) {
- method := webkit_uri_scheme_request_get_http_method(req)
- r, err := http.NewRequest(method, goURI, nil)
- if err != nil {
- return nil, err
- }
- r.Header = webkit_uri_scheme_request_get_http_headers(req)
-
- if r.URL.Host != f.startURL.Host {
- if r.Body != nil {
- r.Body.Close()
- }
-
- return nil, fmt.Errorf("Expected host '%s' in request, but was '%s'", f.startURL.Host, r.URL.Host)
- }
-
- return r, nil
- })
-
+func (f *Frontend) startSecondInstanceProcessor() {
+ for secondInstanceData := range secondInstanceBuffer {
+ if f.frontendOptions.SingleInstanceLock != nil &&
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch != nil {
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch(secondInstanceData)
+ }
+ }
}
diff --git a/v2/internal/frontend/desktop/linux/gtk.go b/v2/internal/frontend/desktop/linux/gtk.go
index f4bc531b3..67a38c7a0 100644
--- a/v2/internal/frontend/desktop/linux/gtk.go
+++ b/v2/internal/frontend/desktop/linux/gtk.go
@@ -4,7 +4,9 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include "gtk/gtk.h"
diff --git a/v2/internal/frontend/desktop/linux/keys.go b/v2/internal/frontend/desktop/linux/keys.go
index 36486ea7b..e5a127dbd 100644
--- a/v2/internal/frontend/desktop/linux/keys.go
+++ b/v2/internal/frontend/desktop/linux/keys.go
@@ -4,7 +4,10 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
+
#include "gtk/gtk.h"
@@ -81,7 +84,8 @@ func parseKey(key string) C.guint {
return result
}
// Check for unknown namedkeys
- if len(key) > 1 {
+ // Check if we only have a single character
+ if len(key) != 1 {
return C.guint(0)
}
keyval := rune(key[0])
diff --git a/v2/internal/frontend/desktop/linux/menu.go b/v2/internal/frontend/desktop/linux/menu.go
index bc3d2740b..a61d190bd 100644
--- a/v2/internal/frontend/desktop/linux/menu.go
+++ b/v2/internal/frontend/desktop/linux/menu.go
@@ -4,7 +4,9 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include "gtk/gtk.h"
@@ -32,8 +34,11 @@ void addAccelerator(GtkWidget* menuItem, GtkAccelGroup* group, guint key, GdkMod
}
*/
import "C"
-import "github.com/wailsapp/wails/v2/pkg/menu"
-import "unsafe"
+import (
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/pkg/menu"
+)
var menuIdCounter int
var menuItemToId map[*menu.MenuItem]int
@@ -79,8 +84,10 @@ func (w *Window) SetApplicationMenu(inmenu *menu.Menu) {
func processMenu(window *Window, menu *menu.Menu) {
for _, menuItem := range menu.Items {
- submenu := processSubmenu(menuItem, window.accels)
- C.gtk_menu_shell_append(C.toGtkMenuShell(unsafe.Pointer(window.menubar)), submenu)
+ if menuItem.SubMenu != nil {
+ submenu := processSubmenu(menuItem, window.accels)
+ C.gtk_menu_shell_append(C.toGtkMenuShell(unsafe.Pointer(window.menubar)), submenu)
+ }
}
}
diff --git a/v2/internal/frontend/desktop/linux/screen.go b/v2/internal/frontend/desktop/linux/screen.go
index bd186363b..0a0507425 100644
--- a/v2/internal/frontend/desktop/linux/screen.go
+++ b/v2/internal/frontend/desktop/linux/screen.go
@@ -4,7 +4,10 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
+
#cgo CFLAGS: -w
#include
#include "webkit2/webkit2.h"
@@ -16,6 +19,7 @@ typedef struct Screen {
int isPrimary;
int height;
int width;
+ int scale;
} Screen;
int GetNMonitors(GtkWindow *window){
@@ -36,14 +40,16 @@ Screen GetNThMonitor(int monitor_num, GtkWindow *window){
screen.isPrimary = gdk_monitor_is_primary(monitor);
screen.height = geometry.height;
screen.width = geometry.width;
+ screen.scale = gdk_monitor_get_scale_factor(monitor);
return screen;
}
*/
import "C"
import (
+ "sync"
+
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/frontend"
- "sync"
)
type Screen = frontend.Screen
@@ -59,11 +65,21 @@ func GetAllScreens(window *C.GtkWindow) ([]Screen, error) {
numMonitors := C.GetNMonitors(window)
for i := 0; i < int(numMonitors); i++ {
cMonitor := C.GetNThMonitor(C.int(i), window)
+
screen := Screen{
IsCurrent: cMonitor.isCurrent == 1,
IsPrimary: cMonitor.isPrimary == 1,
Width: int(cMonitor.width),
Height: int(cMonitor.height),
+
+ Size: frontend.ScreenSize{
+ Width: int(cMonitor.width),
+ Height: int(cMonitor.height),
+ },
+ PhysicalSize: frontend.ScreenSize{
+ Width: int(cMonitor.width * cMonitor.scale),
+ Height: int(cMonitor.height * cMonitor.scale),
+ },
}
screens = append(screens, screen)
}
diff --git a/v2/internal/frontend/desktop/linux/single_instance.go b/v2/internal/frontend/desktop/linux/single_instance.go
new file mode 100644
index 000000000..0317dee49
--- /dev/null
+++ b/v2/internal/frontend/desktop/linux/single_instance.go
@@ -0,0 +1,77 @@
+//go:build linux
+// +build linux
+
+package linux
+
+import (
+ "encoding/json"
+ "github.com/godbus/dbus/v5"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "log"
+ "os"
+ "strings"
+)
+
+type dbusHandler func(string)
+
+func (f dbusHandler) SendMessage(message string) *dbus.Error {
+ f(message)
+ return nil
+}
+
+func SetupSingleInstance(uniqueID string) {
+ id := "wails_app_" + strings.ReplaceAll(strings.ReplaceAll(uniqueID, "-", "_"), ".", "_")
+
+ dbusName := "org." + id + ".SingleInstance"
+ dbusPath := "/org/" + id + "/SingleInstance"
+
+ conn, err := dbus.ConnectSessionBus()
+ // if we will reach any error during establishing connection or sending message we will just continue.
+ // It should not be the case that such thing will happen actually, but just in case.
+ if err != nil {
+ return
+ }
+
+ f := dbusHandler(func(message string) {
+ var secondInstanceData options.SecondInstanceData
+
+ err := json.Unmarshal([]byte(message), &secondInstanceData)
+ if err == nil {
+ secondInstanceBuffer <- secondInstanceData
+ }
+ })
+
+ err = conn.Export(f, dbus.ObjectPath(dbusPath), dbusName)
+ if err != nil {
+ return
+ }
+
+ reply, err := conn.RequestName(dbusName, dbus.NameFlagDoNotQueue)
+ if err != nil {
+ return
+ }
+
+ // if name already taken, try to send args to existing instance, if no success just launch new instance
+ if reply == dbus.RequestNameReplyExists {
+ data := options.SecondInstanceData{
+ Args: os.Args[1:],
+ }
+ data.WorkingDirectory, err = os.Getwd()
+ if err != nil {
+ log.Printf("Failed to get working directory: %v", err)
+ return
+ }
+
+ serialized, err := json.Marshal(data)
+ if err != nil {
+ log.Printf("Failed to marshal data: %v", err)
+ return
+ }
+
+ err = conn.Object(dbusName, dbus.ObjectPath(dbusPath)).Call(dbusName+".SendMessage", 0, string(serialized)).Store()
+ if err != nil {
+ return
+ }
+ os.Exit(1)
+ }
+}
diff --git a/v2/internal/frontend/desktop/linux/webkit2.go b/v2/internal/frontend/desktop/linux/webkit2.go
index 9d64104c4..06e0c7824 100644
--- a/v2/internal/frontend/desktop/linux/webkit2.go
+++ b/v2/internal/frontend/desktop/linux/webkit2.go
@@ -3,7 +3,8 @@
package linux
/*
-#cgo linux pkg-config: webkit2gtk-4.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include "webkit2/webkit2.h"
*/
import "C"
@@ -12,10 +13,12 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/linux"
+
+ "github.com/wailsapp/wails/v2/pkg/assetserver/webview"
)
func validateWebKit2Version(options *options.App) {
- if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webkit2MinMinorVersion {
+ if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webview.Webkit2MinMinorVersion {
return
}
@@ -24,6 +27,6 @@ func validateWebKit2Version(options *options.App) {
msg = options.Linux.Messages
}
- v := fmt.Sprintf("2.%d.0", webkit2MinMinorVersion)
+ v := fmt.Sprintf("2.%d.0", webview.Webkit2MinMinorVersion)
showModalDialogAndExit("WebKit2GTK", fmt.Sprintf(msg.WebKit2GTKMinRequired, v))
}
diff --git a/v2/internal/frontend/desktop/linux/webkit2_36.go b/v2/internal/frontend/desktop/linux/webkit2_36.go
deleted file mode 100644
index 0c0c382e6..000000000
--- a/v2/internal/frontend/desktop/linux/webkit2_36.go
+++ /dev/null
@@ -1,73 +0,0 @@
-//go:build linux && webkit2_36
-
-package linux
-
-/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
-
-#include "gtk/gtk.h"
-#include "webkit2/webkit2.h"
-#include "libsoup/soup.h"
-*/
-import "C"
-
-import (
- "net/http"
- "strings"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/pkg/assetserver"
-)
-
-const webkit2MinMinorVersion = 36
-
-func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
- method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
- return strings.ToUpper(method)
-}
-
-func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header {
- hdrs := C.webkit_uri_scheme_request_get_http_headers(req)
-
- var iter C.SoupMessageHeadersIter
- C.soup_message_headers_iter_init(&iter, hdrs)
-
- var name *C.char
- var value *C.char
-
- h := http.Header{}
- for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 {
- h.Add(C.GoString(name), C.GoString(value))
- }
-
- return h
-}
-
-func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
- resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength))
- defer C.g_object_unref(C.gpointer(resp))
-
- cReason := C.CString(http.StatusText(code))
- C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
- C.free(unsafe.Pointer(cReason))
-
- cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
- C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
- C.free(unsafe.Pointer(cMimeType))
-
- hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE)
- for name, values := range header {
- cName := C.CString(name)
- for _, value := range values {
- cValue := C.CString(value)
- C.soup_message_headers_append(hdrs, cName, cValue)
- C.free(unsafe.Pointer(cValue))
- }
- C.free(unsafe.Pointer(cName))
- }
-
- C.webkit_uri_scheme_response_set_http_headers(resp, hdrs)
-
- C.webkit_uri_scheme_request_finish_with_response(req, resp)
- return nil
-}
diff --git a/v2/internal/frontend/desktop/linux/webkit2_legacy.go b/v2/internal/frontend/desktop/linux/webkit2_legacy.go
deleted file mode 100644
index 9d5158f4e..000000000
--- a/v2/internal/frontend/desktop/linux/webkit2_legacy.go
+++ /dev/null
@@ -1,40 +0,0 @@
-//go:build linux && !webkit2_36
-
-package linux
-
-/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
-
-#include "gtk/gtk.h"
-#include "webkit2/webkit2.h"
-*/
-import "C"
-
-import (
- "fmt"
- "net/http"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/pkg/assetserver"
-)
-
-const webkit2MinMinorVersion = 0
-
-func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string {
- return http.MethodGet
-}
-
-func webkit_uri_scheme_request_get_http_headers(_ *C.WebKitURISchemeRequest) http.Header {
- return http.Header{}
-}
-
-func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
- if code != http.StatusOK {
- return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
- }
-
- cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
- C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType)
- C.free(unsafe.Pointer(cMimeType))
- return nil
-}
diff --git a/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go b/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go
deleted file mode 100644
index ca3fa65c7..000000000
--- a/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go
+++ /dev/null
@@ -1,118 +0,0 @@
-//go:build linux
-// +build linux
-
-package linux
-
-/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
-
-#include "gtk/gtk.h"
-#include "webkit2/webkit2.h"
-#include "gio/gunixinputstream.h"
-
-*/
-import "C"
-import (
- "fmt"
- "io"
- "net/http"
- "os"
- "strconv"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/pkg/assetserver"
-)
-
-type webKitResponseWriter struct {
- req *C.WebKitURISchemeRequest
-
- header http.Header
- wroteHeader bool
-
- w io.WriteCloser
- wErr error
-}
-
-func (rw *webKitResponseWriter) Header() http.Header {
- if rw.header == nil {
- rw.header = http.Header{}
- }
- return rw.header
-}
-
-func (rw *webKitResponseWriter) Write(buf []byte) (int, error) {
- rw.WriteHeader(http.StatusOK)
- if rw.wErr != nil {
- return 0, rw.wErr
- }
- return rw.w.Write(buf)
-}
-
-func (rw *webKitResponseWriter) WriteHeader(code int) {
- if rw.wroteHeader {
- return
- }
- rw.wroteHeader = true
-
- contentLength := int64(-1)
- if sLen := rw.Header().Get(assetserver.HeaderContentLength); sLen != "" {
- if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 {
- contentLength = pLen
- }
- }
-
- // We can't use os.Pipe here, because that returns files with a finalizer for closing the FD. But the control over the
- // read FD is given to the InputStream and will be closed there.
- // Furthermore we especially don't want to have the FD_CLOEXEC
- rFD, w, err := pipe()
- if err != nil {
- rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to open pipe: %s", err))
- return
- }
- rw.w = w
-
- stream := C.g_unix_input_stream_new(C.int(rFD), gtkBool(true))
- defer C.g_object_unref(C.gpointer(stream))
-
- if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil {
- rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err))
- return
- }
-}
-
-func (rw *webKitResponseWriter) Close() {
- if rw.w != nil {
- rw.w.Close()
- }
-}
-
-func (rw *webKitResponseWriter) finishWithError(code int, err error) {
- if rw.w != nil {
- rw.w.Close()
- rw.w = &nopCloser{io.Discard}
- }
- rw.wErr = err
-
- msg := C.CString(err.Error())
- gerr := C.g_error_new_literal(C.g_quark_from_string(msg), C.int(code), msg)
- C.webkit_uri_scheme_request_finish_error(rw.req, gerr)
- C.g_error_free(gerr)
- C.free(unsafe.Pointer(msg))
-}
-
-type nopCloser struct {
- io.Writer
-}
-
-func (nopCloser) Close() error { return nil }
-
-func pipe() (r int, w *os.File, err error) {
- var p [2]int
- e := syscall.Pipe2(p[0:], 0)
- if e != nil {
- return 0, nil, fmt.Errorf("pipe2: %s", e)
- }
-
- return p[0], os.NewFile(uintptr(p[1]), "|1"), nil
-}
diff --git a/v2/internal/frontend/desktop/linux/window.c b/v2/internal/frontend/desktop/linux/window.c
index 1e7d5aa73..5441db022 100644
--- a/v2/internal/frontend/desktop/linux/window.c
+++ b/v2/internal/frontend/desktop/linux/window.c
@@ -4,6 +4,8 @@
#include
#include
#include
+#include
+#include
#include "window.h"
// These are the x,y,time & button of the last mouse down event
@@ -12,6 +14,9 @@ static float xroot = 0.0f;
static float yroot = 0.0f;
static int dragTime = -1;
static uint mouseButton = 0;
+static int wmIsWayland = -1;
+static int decoratorWidth = -1;
+static int decoratorHeight = -1;
// casts
void ExecuteOnMainThread(void *f, gpointer jscallback)
@@ -40,11 +45,17 @@ GtkBox *GTKBOX(void *pointer)
}
extern void processMessage(char *);
+extern void processBindingMessage(char *, char *);
static void sendMessageToBackend(WebKitUserContentManager *contentManager,
WebKitJavascriptResult *result,
void *data)
{
+ // Retrieve webview from content manager
+ WebKitWebView *webview = WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(contentManager), "webview"));
+ const char *current_uri = webview ? webkit_web_view_get_uri(webview) : NULL;
+ char *uri = current_uri ? g_strdup(current_uri) : NULL;
+
#if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22
JSCValue *value = webkit_javascript_result_get_js_value(result);
char *message = jsc_value_to_string(value);
@@ -57,8 +68,11 @@ static void sendMessageToBackend(WebKitUserContentManager *contentManager,
JSStringGetUTF8CString(js, message, messageSize);
JSStringRelease(js);
#endif
- processMessage(message);
+ processBindingMessage(message, uri);
g_free(message);
+ if (uri) {
+ g_free(uri);
+ }
}
static bool isNULLRectangle(GdkRectangle input)
@@ -66,6 +80,29 @@ static bool isNULLRectangle(GdkRectangle input)
return input.x == -1 && input.y == -1 && input.width == -1 && input.height == -1;
}
+static gboolean onWayland()
+{
+ switch (wmIsWayland)
+ {
+ case -1:
+ {
+ char *gdkBackend = getenv("XDG_SESSION_TYPE");
+ if(gdkBackend != NULL && strcmp(gdkBackend, "wayland") == 0)
+ {
+ wmIsWayland = 1;
+ return TRUE;
+ }
+
+ wmIsWayland = 0;
+ return FALSE;
+ }
+ case 1:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
static GdkMonitor *getCurrentMonitor(GtkWindow *window)
{
// Get the monitor that the window is currently on
@@ -139,11 +176,50 @@ void SetWindowTransparency(GtkWidget *widget)
}
}
+static GtkCssProvider *windowCssProvider = NULL;
+
void SetBackgroundColour(void *data)
{
+ // set webview's background color
RGBAOptions *options = (RGBAOptions *)data;
+
GdkRGBA colour = {options->r / 255.0, options->g / 255.0, options->b / 255.0, options->a / 255.0};
+ if (options->windowIsTranslucent != NULL && options->windowIsTranslucent == TRUE)
+ {
+ colour.alpha = 0.0;
+ }
webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(options->webview), &colour);
+
+ // set window's background color
+ // Get the name of the current locale
+ char *old_locale, *saved_locale;
+ old_locale = setlocale(LC_ALL, NULL);
+
+ // Copy the name so it won’t be clobbered by setlocale.
+ saved_locale = strdup(old_locale);
+ if (saved_locale == NULL)
+ return;
+
+ //Now change the locale to english for so printf always converts floats with a dot decimal separator
+ setlocale(LC_ALL, "en_US.UTF-8");
+ gchar *str = g_strdup_printf("#webview-box {background-color: rgba(%d, %d, %d, %1.1f);}", options->r, options->g, options->b, options->a / 255.0);
+
+ //Restore the original locale.
+ setlocale(LC_ALL, saved_locale);
+ free(saved_locale);
+
+ if (windowCssProvider == NULL)
+ {
+ windowCssProvider = gtk_css_provider_new();
+ gtk_style_context_add_provider(
+ gtk_widget_get_style_context(GTK_WIDGET(options->webviewBox)),
+ GTK_STYLE_PROVIDER(windowCssProvider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ g_object_unref(windowCssProvider);
+ }
+
+ gtk_css_provider_load_from_data(windowCssProvider, str, -1, NULL);
+ g_free(str);
}
static gboolean setTitle(gpointer data)
@@ -197,15 +273,38 @@ void SetMinMaxSize(GtkWindow *window, int min_width, int min_height, int max_wid
{
return;
}
+
int flags = GDK_HINT_MAX_SIZE | GDK_HINT_MIN_SIZE;
+
size.max_height = (max_height == 0 ? monitorSize.height : max_height);
size.max_width = (max_width == 0 ? monitorSize.width : max_width);
size.min_height = min_height;
size.min_width = min_width;
+
+ // On Wayland window manager get the decorators and calculate the differences from the windows' size.
+ if(onWayland())
+ {
+ if(decoratorWidth == -1 && decoratorHeight == -1)
+ {
+ int windowWidth, windowHeight;
+ gtk_window_get_size(window, &windowWidth, &windowHeight);
+
+ GtkAllocation windowAllocation;
+ gtk_widget_get_allocation(GTK_WIDGET(window), &windowAllocation);
+
+ decoratorWidth = (windowAllocation.width-windowWidth);
+ decoratorHeight = (windowAllocation.height-windowHeight);
+ }
+
+ // Add the decorator difference to the window so fullscreen and maximise can fill the window.
+ size.max_height = decoratorHeight+size.max_height;
+ size.max_width = decoratorWidth+size.max_width;
+ }
+
gtk_window_set_geometry_hints(window, NULL, &size, flags);
}
-// function to disable the context menu but propogate the event
+// function to disable the context menu but propagate the event
static gboolean disableContextMenu(GtkWidget *widget, WebKitContextMenu *context_menu, GdkEvent *event, WebKitHitTestResult *hit_test_result, gpointer data)
{
// return true to disable the context menu
@@ -214,7 +313,7 @@ static gboolean disableContextMenu(GtkWidget *widget, WebKitContextMenu *context
void DisableContextMenu(void *webview)
{
- // Disable the context menu but propogate the event
+ // Disable the context menu but propagate the event
g_signal_connect(WEBKIT_WEB_VIEW(webview), "context-menu", G_CALLBACK(disableContextMenu), NULL);
}
@@ -389,14 +488,95 @@ gboolean close_button_pressed(GtkWidget *widget, GdkEvent *event, void *data)
return TRUE;
}
+char *droppedFiles = NULL;
+
+static void onDragDataReceived(GtkWidget *self, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, gpointer data)
+{
+ if(selection_data == NULL || (gtk_selection_data_get_length(selection_data) <= 0) || target_type != 2)
+ {
+ return;
+ }
+
+ if(droppedFiles != NULL) {
+ free(droppedFiles);
+ droppedFiles = NULL;
+ }
+
+ gchar **filenames = NULL;
+ filenames = g_uri_list_extract_uris((const gchar *)gtk_selection_data_get_data(selection_data));
+ if (filenames == NULL) // If unable to retrieve filenames:
+ {
+ g_strfreev(filenames);
+ return;
+ }
+
+ droppedFiles = calloc((size_t)gtk_selection_data_get_length(selection_data), 1);
+
+ int iter = 0;
+ while(filenames[iter] != NULL) // The last URI list element is NULL.
+ {
+ if(iter != 0)
+ {
+ strncat(droppedFiles, "\n", 1);
+ }
+ char *filename = g_filename_from_uri(filenames[iter], NULL, NULL);
+ if (filename == NULL)
+ {
+ break;
+ }
+ strncat(droppedFiles, filename, strlen(filename));
+
+ free(filename);
+ iter++;
+ }
+
+ g_strfreev(filenames);
+}
+
+static gboolean onDragDrop(GtkWidget* self, GdkDragContext* context, gint x, gint y, guint time, gpointer user_data)
+{
+ if(droppedFiles == NULL)
+ {
+ return FALSE;
+ }
+
+ size_t resLen = strlen(droppedFiles)+(sizeof(gint)*2)+6;
+ char *res = calloc(resLen, 1);
+
+ snprintf(res, resLen, "DD:%d:%d:%s", x, y, droppedFiles);
+
+ if(droppedFiles != NULL) {
+ free(droppedFiles);
+ droppedFiles = NULL;
+ }
+
+ processMessage(res);
+ return FALSE;
+}
+
// WebView
-GtkWidget *SetupWebview(void *contentManager, GtkWindow *window, int hideWindowOnClose, int gpuPolicy)
+GtkWidget *SetupWebview(void *contentManager, GtkWindow *window, int hideWindowOnClose, int gpuPolicy, int disableWebViewDragAndDrop, int enableDragAndDrop)
{
GtkWidget *webview = webkit_web_view_new_with_user_content_manager((WebKitUserContentManager *)contentManager);
+
+ // Store webview reference in the content manager
+ g_object_set_data(G_OBJECT((WebKitUserContentManager *)contentManager), "webview", webview);
// gtk_container_add(GTK_CONTAINER(window), webview);
WebKitWebContext *context = webkit_web_context_get_default();
webkit_web_context_register_uri_scheme(context, "wails", (WebKitURISchemeRequestCallback)processURLRequest, NULL, NULL);
g_signal_connect(G_OBJECT(webview), "load-changed", G_CALLBACK(webviewLoadChanged), NULL);
+
+ if(disableWebViewDragAndDrop)
+ {
+ gtk_drag_dest_unset(webview);
+ }
+
+ if(enableDragAndDrop)
+ {
+ g_signal_connect(G_OBJECT(webview), "drag-data-received", G_CALLBACK(onDragDataReceived), NULL);
+ g_signal_connect(G_OBJECT(webview), "drag-drop", G_CALLBACK(onDragDrop), NULL);
+ }
+
if (hideWindowOnClose)
{
g_signal_connect(GTK_WIDGET(window), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
@@ -434,8 +614,7 @@ void DevtoolsEnabled(void *webview, int enabled, bool showInspector)
if (genabled && showInspector)
{
- WebKitWebInspector *inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview));
- webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector));
+ ShowInspector(webview);
}
}
@@ -692,3 +871,21 @@ GtkFileFilter *newFileFilter()
g_object_ref(result);
return result;
}
+
+void ShowInspector(void *webview) {
+ WebKitWebInspector *inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview));
+ webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector));
+}
+
+void sendShowInspectorMessage() {
+ processMessage("wails:showInspector");
+}
+
+void InstallF12Hotkey(void *window)
+{
+ // When the user presses Ctrl+Shift+F12, call ShowInspector
+ GtkAccelGroup *accel_group = gtk_accel_group_new();
+ gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+ GClosure *closure = g_cclosure_new(G_CALLBACK(sendShowInspectorMessage), window, NULL);
+ gtk_accel_group_connect(accel_group, GDK_KEY_F12, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE, closure);
+}
diff --git a/v2/internal/frontend/desktop/linux/window.go b/v2/internal/frontend/desktop/linux/window.go
index f1700908c..0bf5ac51d 100644
--- a/v2/internal/frontend/desktop/linux/window.go
+++ b/v2/internal/frontend/desktop/linux/window.go
@@ -4,7 +4,9 @@
package linux
/*
-#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
#include
#include
@@ -25,6 +27,7 @@ import (
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/linux"
)
func gtkBool(input bool) C.gboolean {
@@ -37,11 +40,13 @@ func gtkBool(input bool) C.gboolean {
type Window struct {
appoptions *options.App
debug bool
+ devtoolsEnabled bool
gtkWindow unsafe.Pointer
contentManager unsafe.Pointer
webview unsafe.Pointer
applicationMenu *menu.Menu
menubar *C.GtkWidget
+ webviewBox *C.GtkWidget
vbox *C.GtkWidget
accels *C.GtkAccelGroup
minWidth, minHeight, maxWidth, maxHeight int
@@ -54,22 +59,28 @@ func bool2Cint(value bool) C.int {
return C.int(0)
}
-func NewWindow(appoptions *options.App, debug bool) *Window {
+func NewWindow(appoptions *options.App, debug bool, devtoolsEnabled bool) *Window {
validateWebKit2Version(appoptions)
result := &Window{
- appoptions: appoptions,
- debug: debug,
- minHeight: appoptions.MinHeight,
- minWidth: appoptions.MinWidth,
- maxHeight: appoptions.MaxHeight,
- maxWidth: appoptions.MaxWidth,
+ appoptions: appoptions,
+ debug: debug,
+ devtoolsEnabled: devtoolsEnabled,
+ minHeight: appoptions.MinHeight,
+ minWidth: appoptions.MinWidth,
+ maxHeight: appoptions.MaxHeight,
+ maxWidth: appoptions.MaxWidth,
}
gtkWindow := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
C.g_object_ref_sink(C.gpointer(gtkWindow))
result.gtkWindow = unsafe.Pointer(gtkWindow)
+ webviewName := C.CString("webview-box")
+ defer C.free(unsafe.Pointer(webviewName))
+ result.webviewBox = C.gtk_box_new(C.GTK_ORIENTATION_VERTICAL, 0)
+ C.gtk_widget_set_name(result.webviewBox, webviewName)
+
result.vbox = C.gtk_box_new(C.GTK_ORIENTATION_VERTICAL, 0)
C.gtk_container_add(result.asGTKContainer(), result.vbox)
@@ -82,6 +93,9 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
var webviewGpuPolicy int
if appoptions.Linux != nil {
webviewGpuPolicy = int(appoptions.Linux.WebviewGpuPolicy)
+ } else {
+ // workaround for https://github.com/wailsapp/wails/issues/2977
+ webviewGpuPolicy = int(linux.WebviewGpuPolicyNever)
}
webview := C.SetupWebview(
@@ -89,15 +103,21 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
result.asGTKWindow(),
bool2Cint(appoptions.HideWindowOnClose),
C.int(webviewGpuPolicy),
+ bool2Cint(appoptions.DragAndDrop != nil && appoptions.DragAndDrop.DisableWebViewDrop),
+ bool2Cint(appoptions.DragAndDrop != nil && appoptions.DragAndDrop.EnableFileDrop),
)
result.webview = unsafe.Pointer(webview)
buttonPressedName := C.CString("button-press-event")
defer C.free(unsafe.Pointer(buttonPressedName))
C.ConnectButtons(unsafe.Pointer(webview))
- if debug {
- C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(appoptions.Debug.OpenInspectorOnStartup))
- } else {
+ if devtoolsEnabled {
+ C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(debug && appoptions.Debug.OpenInspectorOnStartup))
+ // Install Ctrl-Shift-F12 hotkey to call ShowInspector
+ C.InstallF12Hotkey(unsafe.Pointer(gtkWindow))
+ }
+
+ if !(debug || appoptions.EnableDefaultContextMenu) {
C.DisableContextMenu(unsafe.Pointer(webview))
}
@@ -108,7 +128,7 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
// Setup window
result.SetKeepAbove(appoptions.AlwaysOnTop)
result.SetResizable(!appoptions.DisableResize)
- result.SetSize(appoptions.Width, appoptions.Height)
+ result.SetDefaultSize(appoptions.Width, appoptions.Height)
result.SetDecorated(!appoptions.Frameless)
result.SetTitle(appoptions.Title)
result.SetMinSize(appoptions.MinWidth, appoptions.MinHeight)
@@ -171,7 +191,9 @@ func (w *Window) Center() {
}
func (w *Window) SetPosition(x int, y int) {
- C.SetPosition(unsafe.Pointer(w.asGTKWindow()), C.int(x), C.int(y))
+ invokeOnMainThread(func() {
+ C.SetPosition(unsafe.Pointer(w.asGTKWindow()), C.int(x), C.int(y))
+ })
}
func (w *Window) Size() (int, int) {
@@ -261,12 +283,18 @@ func (w *Window) IsNormal() bool {
}
func (w *Window) SetBackgroundColour(r uint8, g uint8, b uint8, a uint8) {
+ windowIsTranslucent := false
+ if w.appoptions.Linux != nil && w.appoptions.Linux.WindowIsTranslucent {
+ windowIsTranslucent = true
+ }
data := C.RGBAOptions{
- r: C.uchar(r),
- g: C.uchar(g),
- b: C.uchar(b),
- a: C.uchar(a),
- webview: w.webview,
+ r: C.uchar(r),
+ g: C.uchar(g),
+ b: C.uchar(b),
+ a: C.uchar(a),
+ webview: w.webview,
+ webviewBox: unsafe.Pointer(w.webviewBox),
+ windowIsTranslucent: gtkBool(windowIsTranslucent),
}
invokeOnMainThread(func() { C.SetBackgroundColour(unsafe.Pointer(&data)) })
@@ -283,10 +311,15 @@ func (w *Window) Run(url string) {
if w.menubar != nil {
C.gtk_box_pack_start(C.GTKBOX(unsafe.Pointer(w.vbox)), w.menubar, 0, 0, 0)
}
- C.gtk_box_pack_start(C.GTKBOX(unsafe.Pointer(w.vbox)), C.GTKWIDGET(w.webview), 1, 1, 0)
+
+ C.gtk_box_pack_start(C.GTKBOX(unsafe.Pointer(w.webviewBox)), C.GTKWIDGET(w.webview), 1, 1, 0)
+ C.gtk_box_pack_start(C.GTKBOX(unsafe.Pointer(w.vbox)), w.webviewBox, 1, 1, 0)
_url := C.CString(url)
C.LoadIndex(w.webview, _url)
defer C.free(unsafe.Pointer(_url))
+ if w.appoptions.StartHidden {
+ w.Hide()
+ }
C.gtk_widget_show_all(w.asGTKWidget())
w.Center()
switch w.appoptions.WindowStartState {
@@ -297,7 +330,6 @@ func (w *Window) Run(url string) {
case options.Maximised:
w.Maximise()
}
-
}
func (w *Window) SetKeepAbove(top bool) {
@@ -308,6 +340,10 @@ func (w *Window) SetResizable(resizable bool) {
C.gtk_window_set_resizable(w.asGTKWindow(), gtkBool(resizable))
}
+func (w *Window) SetDefaultSize(width int, height int) {
+ C.gtk_window_set_default_size(w.asGTKWindow(), C.int(width), C.int(height))
+}
+
func (w *Window) SetSize(width int, height int) {
C.gtk_window_resize(w.asGTKWindow(), C.gint(width), C.gint(height))
}
@@ -422,6 +458,10 @@ func (w *Window) ToggleMaximise() {
}
}
+func (w *Window) ShowInspector() {
+ invokeOnMainThread(func() { C.ShowInspector(w.webview) })
+}
+
// showModalDialogAndExit shows a modal dialog and exits the app.
func showModalDialogAndExit(title, message string) {
go func() {
diff --git a/v2/internal/frontend/desktop/linux/window.h b/v2/internal/frontend/desktop/linux/window.h
index f02542feb..04410959a 100644
--- a/v2/internal/frontend/desktop/linux/window.h
+++ b/v2/internal/frontend/desktop/linux/window.h
@@ -55,6 +55,8 @@ typedef struct RGBAOptions
uint8_t b;
uint8_t a;
void *webview;
+ void *webviewBox;
+ gboolean windowIsTranslucent;
} RGBAOptions;
typedef struct SetTitleArgs
@@ -104,7 +106,7 @@ gboolean Fullscreen(gpointer data);
gboolean UnFullscreen(gpointer data);
// WebView
-GtkWidget *SetupWebview(void *contentManager, GtkWindow *window, int hideWindowOnClose, int gpuPolicy);
+GtkWidget *SetupWebview(void *contentManager, GtkWindow *window, int hideWindowOnClose, int gpuPolicy, int disableWebViewDragAndDrop, int enableDragAndDrop);
void LoadIndex(void *webview, char *url);
void DevtoolsEnabled(void *webview, int enabled, bool showInspector);
void ExecuteJS(void *data);
@@ -118,4 +120,9 @@ void MessageDialog(void *data);
GtkFileFilter **AllocFileFilterArray(size_t ln);
void Opendialog(void *data);
+// Inspector
+void sendShowInspectorMessage();
+void ShowInspector(void *webview);
+void InstallF12Hotkey(void *window);
+
#endif /* window_h */
diff --git a/v2/internal/frontend/desktop/windows/browser.go b/v2/internal/frontend/desktop/windows/browser.go
index f23b04dbe..13d037b14 100644
--- a/v2/internal/frontend/desktop/windows/browser.go
+++ b/v2/internal/frontend/desktop/windows/browser.go
@@ -4,11 +4,40 @@
package windows
import (
+ "fmt"
"github.com/pkg/browser"
+ "github.com/wailsapp/wails/v2/internal/frontend/utils"
+ "golang.org/x/sys/windows"
)
-// BrowserOpenURL Use the default browser to open the url
-func (f *Frontend) BrowserOpenURL(url string) {
- // Specific method implementation
- _ = browser.OpenURL(url)
+var fallbackBrowserPaths = []string{
+ `\Program Files (x86)\Microsoft\Edge\Application\msedge.exe`,
+ `\Program Files\Google\Chrome\Application\chrome.exe`,
+ `\Program Files (x86)\Google\Chrome\Application\chrome.exe`,
+ `\Program Files\Mozilla Firefox\firefox.exe`,
+}
+
+// BrowserOpenURL Use the default browser to open the url
+func (f *Frontend) BrowserOpenURL(rawURL string) {
+ url, err := utils.ValidateAndSanitizeURL(rawURL)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error()))
+ return
+ }
+
+ // Specific method implementation
+ err = browser.OpenURL(url)
+ if err == nil {
+ return
+ }
+ for _, fallback := range fallbackBrowserPaths {
+ if err := openBrowser(fallback, url); err == nil {
+ return
+ }
+ }
+ f.logger.Error("Unable to open default system browser")
+}
+
+func openBrowser(path, url string) error {
+ return windows.ShellExecute(0, nil, windows.StringToUTF16Ptr(path), windows.StringToUTF16Ptr(url), nil, windows.SW_SHOWNORMAL)
}
diff --git a/v2/internal/frontend/desktop/windows/dialog.go b/v2/internal/frontend/desktop/windows/dialog.go
index ab41df332..573325886 100644
--- a/v2/internal/frontend/desktop/windows/dialog.go
+++ b/v2/internal/frontend/desktop/windows/dialog.go
@@ -4,13 +4,14 @@
package windows
import (
+ "path/filepath"
+ "strings"
+ "syscall"
+
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
"golang.org/x/sys/windows"
- "path/filepath"
- "strings"
- "syscall"
)
func (f *Frontend) getHandleForDialog() w32.HWND {
@@ -40,27 +41,20 @@ func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (stri
Role: "PickFolder",
Folder: defaultFolder,
}
- thisDialog, err := cfd.NewSelectFolderDialog(config)
- if err != nil {
+
+ result, err := f.showCfdDialog(
+ func() (cfd.Dialog, error) {
+ return cfd.NewSelectFolderDialog(config)
+ }, false)
+
+ if err != nil && err != cfd.ErrCancelled {
return "", err
}
- thisDialog.SetParentWindowHandle(f.getHandleForDialog())
- defer func(thisDialog cfd.SelectFolderDialog) {
- err := thisDialog.Release()
- if err != nil {
- println("ERROR: Unable to release dialog:", err.Error())
- }
- }(thisDialog)
- result, err := thisDialog.ShowAndGetResult()
- if err != nil && err != cfd.ErrorCancelled {
- return "", err
- }
- return result, nil
+ return result.(string), nil
}
// OpenFileDialog prompts the user to select a file
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
-
defaultFolder, err := getDefaultFolder(options.DefaultDirectory)
if err != nil {
return "", err
@@ -72,22 +66,16 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
FileName: options.DefaultFilename,
Title: options.Title,
}
- thisdialog, err := cfd.NewOpenFileDialog(config)
- if err != nil {
+
+ result, err := f.showCfdDialog(
+ func() (cfd.Dialog, error) {
+ return cfd.NewOpenFileDialog(config)
+ }, false)
+
+ if err != nil && err != cfd.ErrCancelled {
return "", err
}
- thisdialog.SetParentWindowHandle(f.getHandleForDialog())
- defer func(thisdialog cfd.OpenFileDialog) {
- err := thisdialog.Release()
- if err != nil {
- println("ERROR: Unable to release dialog:", err.Error())
- }
- }(thisdialog)
- result, err := thisdialog.ShowAndGetResult()
- if err != nil && err != cfd.ErrorCancelled {
- return "", err
- }
- return result, nil
+ return result.(string), nil
}
// OpenMultipleFilesDialog prompts the user to select a file
@@ -105,22 +93,16 @@ func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) (
FileName: options.DefaultFilename,
Folder: defaultFolder,
}
- thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
- if err != nil {
+
+ result, err := f.showCfdDialog(
+ func() (cfd.Dialog, error) {
+ return cfd.NewOpenMultipleFilesDialog(config)
+ }, true)
+
+ if err != nil && err != cfd.ErrCancelled {
return nil, err
}
- thisdialog.SetParentWindowHandle(f.getHandleForDialog())
- defer func(thisdialog cfd.OpenMultipleFilesDialog) {
- err := thisdialog.Release()
- if err != nil {
- println("ERROR: Unable to release dialog:", err.Error())
- }
- }(thisdialog)
- result, err := thisdialog.ShowAndGetResults()
- if err != nil && err != cfd.ErrorCancelled {
- return nil, err
- }
- return result, nil
+ return result.([]string), nil
}
// SaveFileDialog prompts the user to select a file
@@ -131,26 +113,48 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e
return "", err
}
- saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
+ config := cfd.DialogConfig{
Title: options.Title,
Role: "SaveFile",
FileFilters: convertFilters(options.Filters),
FileName: options.DefaultFilename,
Folder: defaultFolder,
+ }
+
+ if len(options.Filters) > 0 {
+ config.DefaultExtension = strings.TrimPrefix(strings.Split(options.Filters[0].Pattern, ";")[0], "*")
+ }
+
+ result, err := f.showCfdDialog(
+ func() (cfd.Dialog, error) {
+ return cfd.NewSaveFileDialog(config)
+ }, false)
+
+ if err != nil && err != cfd.ErrCancelled {
+ return "", err
+ }
+ return result.(string), nil
+}
+
+func (f *Frontend) showCfdDialog(newDlg func() (cfd.Dialog, error), isMultiSelect bool) (any, error) {
+ return invokeSync(f.mainWindow, func() (any, error) {
+ dlg, err := newDlg()
+ if err != nil {
+ return nil, err
+ }
+ defer func() {
+ err := dlg.Release()
+ if err != nil {
+ println("ERROR: Unable to release dialog:", err.Error())
+ }
+ }()
+
+ dlg.SetParentWindowHandle(f.getHandleForDialog())
+ if multi, _ := dlg.(cfd.OpenMultipleFilesDialog); multi != nil && isMultiSelect {
+ return multi.ShowAndGetResults()
+ }
+ return dlg.ShowAndGetResult()
})
- if err != nil {
- return "", err
- }
- saveDialog.SetParentWindowHandle(f.getHandleForDialog())
- err = saveDialog.Show()
- if err != nil {
- return "", err
- }
- result, err := saveDialog.GetResult()
- if err != nil && err != cfd.ErrorCancelled {
- return "", err
- }
- return result, nil
}
func calculateMessageDialogFlags(options frontend.MessageDialogOptions) uint32 {
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
index bf1c7d7c5..5df13ed98 100644
--- a/v2/internal/frontend/desktop/windows/frontend.go
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -7,35 +7,40 @@ import (
"context"
"encoding/json"
"fmt"
- "io"
"log"
- "net/http"
- "net/http/httptest"
+ "net"
"net/url"
+ "os"
"runtime"
- "strconv"
"strings"
"sync"
"text/template"
"time"
+ "unsafe"
"github.com/bep/debounce"
+ "github.com/wailsapp/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
+ "github.com/wailsapp/wails/v2/internal/frontend/originvalidator"
wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
+ w32consts "github.com/wailsapp/wails/v2/internal/platform/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/pkg/assetserver"
+ "github.com/wailsapp/wails/v2/pkg/assetserver/webview"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
+ w "golang.org/x/sys/windows"
)
const startURL = "http://wails.localhost/"
+var secondInstanceBuffer = make(chan options.SecondInstanceData, 1)
+
type Screen = frontend.Screen
type Frontend struct {
@@ -47,6 +52,7 @@ type Frontend struct {
logger *logger.Logger
chromium *edge.Chromium
debug bool
+ devtoolsEnabled bool
// Assets
assets *assetserver.AssetServer
@@ -59,6 +65,8 @@ type Frontend struct {
hasStarted bool
+ originValidator *originvalidator.OriginValidator
+
// Windows build number
versionInfo *operatingsystem.WindowsVersionInfo
resizeDebouncer func(f func())
@@ -69,6 +77,13 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
// Get Windows build number
versionInfo, _ := operatingsystem.GetWindowsVersionInfo()
+ // Apply DLL search path settings if specified
+ if appoptions.Windows != nil && appoptions.Windows.DLLSearchPaths != 0 {
+ w.SetDefaultDllDirectories(appoptions.Windows.DLLSearchPaths)
+ }
+ // Now initialize packages that load DLLs
+ w32.Init()
+ w32consts.Init()
result := &Frontend{
frontendOptions: appoptions,
logger: myLogger,
@@ -86,12 +101,19 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
// We currently can't use wails://wails/ as other platforms do, therefore we map the assets sever onto the following url.
result.startURL, _ = url.Parse(startURL)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil {
result.startURL = _starturl
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
return result
}
+ if port, _ := ctx.Value("assetserverport").(string); port != "" {
+ result.startURL.Host = net.JoinHostPort(result.startURL.Host, port)
+ result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins)
+ }
+
var bindings string
var err error
if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated {
@@ -109,6 +131,8 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
}
result.assets = assets
+ go result.startSecondInstanceProcessor()
+
return result
}
@@ -133,13 +157,22 @@ func (f *Frontend) Run(ctx context.Context) error {
f.chromium = edge.NewChromium()
+ if f.frontendOptions.SingleInstanceLock != nil {
+ SetupSingleInstance(f.frontendOptions.SingleInstanceLock.UniqueId)
+ }
+
mainWindow := NewWindow(nil, f.frontendOptions, f.versionInfo, f.chromium)
f.mainWindow = mainWindow
var _debug = ctx.Value("debug")
+ var _devtoolsEnabled = ctx.Value("devtoolsEnabled")
+
if _debug != nil {
f.debug = _debug.(bool)
}
+ if _devtoolsEnabled != nil {
+ f.devtoolsEnabled = _devtoolsEnabled.(bool)
+ }
f.WindowCenter()
f.setupChromium()
@@ -152,10 +185,21 @@ func (f *Frontend) Run(ctx context.Context) error {
// depends on the content in the WebView, see https://github.com/wailsapp/wails/issues/1319
event, _ := arg.Data.(*winc.SizeEventData)
if event != nil && event.Type == w32.SIZE_MINIMIZED {
+ // Set minimizing flag to prevent unnecessary redraws during minimize/restore for frameless windows
+ // 设置最小化标志以防止无边框窗口在最小化/恢复过程中的不必要重绘
+ // This fixes window flickering when minimizing/restoring frameless windows
+ // 这修复了无边框窗口在最小化/恢复时的闪烁问题
+ // Reference: https://github.com/wailsapp/wails/issues/3951
+ f.mainWindow.isMinimizing = true
return
}
}
+ // Clear minimizing flag for all non-minimize size events
+ // 对于所有非最小化的尺寸变化事件,清除最小化标志
+ // Reference: https://github.com/wailsapp/wails/issues/3951
+ f.mainWindow.isMinimizing = false
+
if f.resizeDebouncer != nil {
f.resizeDebouncer(func() {
f.mainWindow.Invoke(func() {
@@ -202,6 +246,7 @@ func (f *Frontend) WindowCenter() {
func (f *Frontend) WindowSetAlwaysOnTop(b bool) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetAlwaysOnTop(b)
}
@@ -414,6 +459,10 @@ func (f *Frontend) Quit() {
f.mainWindow.Invoke(winc.Exit)
}
+func (f *Frontend) WindowPrint() {
+ f.ExecJS("window.print();")
+}
+
func (f *Frontend) setupChromium() {
chromium := f.chromium
@@ -429,6 +478,9 @@ func (f *Frontend) setupChromium() {
if opts.WebviewGpuIsDisabled {
chromium.AdditionalBrowserArgs = append(chromium.AdditionalBrowserArgs, "--disable-gpu")
}
+ if opts.WebviewDisableRendererCodeIntegrity {
+ disableFeatues = append(disableFeatues, "RendererCodeIntegrity")
+ }
}
if len(disableFeatues) > 0 {
@@ -436,25 +488,83 @@ func (f *Frontend) setupChromium() {
chromium.AdditionalBrowserArgs = append(chromium.AdditionalBrowserArgs, arg)
}
+ if f.frontendOptions.DragAndDrop != nil && f.frontendOptions.DragAndDrop.DisableWebViewDrop {
+ if err := chromium.AllowExternalDrag(false); err != nil {
+ f.logger.Warning("WebView failed to set AllowExternalDrag to false!")
+ }
+ }
+
chromium.MessageCallback = f.processMessage
+ chromium.MessageWithAdditionalObjectsCallback = f.processMessageWithAdditionalObjects
chromium.WebResourceRequestedCallback = f.processRequest
chromium.NavigationCompletedCallback = f.navigationCompleted
chromium.AcceleratorKeyCallback = func(vkey uint) bool {
+ if vkey == w32.VK_F12 && f.devtoolsEnabled {
+ var keyState [256]byte
+ if w32.GetKeyboardState(keyState[:]) {
+ // Check if CTRL is pressed
+ if keyState[w32.VK_CONTROL]&0x80 != 0 && keyState[w32.VK_SHIFT]&0x80 != 0 {
+ chromium.OpenDevToolsWindow()
+ return true
+ }
+ } else {
+ f.logger.Error("Call to GetKeyboardState failed")
+ }
+ }
w32.PostMessage(f.mainWindow.Handle(), w32.WM_KEYDOWN, uintptr(vkey), 0)
return false
}
+ chromium.ProcessFailedCallback = func(sender *edge.ICoreWebView2, args *edge.ICoreWebView2ProcessFailedEventArgs) {
+ kind, err := args.GetProcessFailedKind()
+ if err != nil {
+ f.logger.Error("GetProcessFailedKind: %s", err)
+ return
+ }
+
+ f.logger.Error("WebVie2wProcess failed with kind %d", kind)
+ switch kind {
+ case edge.COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED:
+ // => The app has to recreate a new WebView to recover from this failure.
+ messages := windows.DefaultMessages()
+ if f.frontendOptions.Windows != nil && f.frontendOptions.Windows.Messages != nil {
+ messages = f.frontendOptions.Windows.Messages
+ }
+ winc.Errorf(f.mainWindow, messages.WebView2ProcessCrash)
+ os.Exit(-1)
+ case edge.COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED,
+ edge.COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED:
+ // => A new render process is created automatically and navigated to an error page.
+ // => Make sure that the error page is shown.
+ if !f.hasStarted {
+ // NavgiationCompleted didn't come in, make sure the chromium is shown
+ chromium.Show()
+ }
+ if !f.mainWindow.hasBeenShown {
+ // The window has never been shown, make sure to show it
+ f.ShowWindow()
+ }
+ }
+ }
chromium.Embed(f.mainWindow.Handle())
+
+ if chromium.HasCapability(edge.SwipeNavigation) {
+ swipeGesturesEnabled := f.frontendOptions.Windows != nil && f.frontendOptions.Windows.EnableSwipeGestures
+ err := chromium.PutIsSwipeNavigationEnabled(swipeGesturesEnabled)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
chromium.Resize()
settings, err := chromium.GetSettings()
if err != nil {
log.Fatal(err)
}
- err = settings.PutAreDefaultContextMenusEnabled(f.debug)
+ err = settings.PutAreDefaultContextMenusEnabled(f.debug || f.frontendOptions.EnableDefaultContextMenu)
if err != nil {
log.Fatal(err)
}
- err = settings.PutAreDevToolsEnabled(f.debug)
+ err = settings.PutAreDevToolsEnabled(f.devtoolsEnabled)
if err != nil {
log.Fatal(err)
}
@@ -467,6 +577,10 @@ func (f *Frontend) setupChromium() {
if err != nil {
log.Fatal(err)
}
+ err = settings.PutIsPinchZoomEnabled(!opts.DisablePinchZoom)
+ if err != nil {
+ log.Fatal(err)
+ }
}
err = settings.PutIsStatusBarEnabled(false)
@@ -477,10 +591,6 @@ func (f *Frontend) setupChromium() {
if err != nil {
log.Fatal(err)
}
- err = settings.PutIsSwipeNavigationEnabled(false)
- if err != nil {
- log.Fatal(err)
- }
if f.debug && f.frontendOptions.Debug.OpenInspectorOnStartup {
chromium.OpenDevToolsWindow()
@@ -547,28 +657,31 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
return
}
- rw := httptest.NewRecorder()
- f.assets.ProcessHTTPRequestLegacy(rw, coreWebview2RequestToHttpRequest(req))
+ webviewRequest, err := webview.NewRequest(
+ f.chromium.Environment(),
+ args,
+ func(fn func()) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ if f.mainWindow.InvokeRequired() {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ f.mainWindow.Invoke(func() {
+ fn()
+ wg.Done()
+ })
+ wg.Wait()
+ } else {
+ fn()
+ }
+ })
- headers := []string{}
- for k, v := range rw.Header() {
- headers = append(headers, fmt.Sprintf("%s: %s", k, strings.Join(v, ",")))
- }
-
- env := f.chromium.Environment()
- response, err := env.CreateWebResourceResponse(rw.Body.Bytes(), rw.Code, http.StatusText(rw.Code), strings.Join(headers, "\n"))
if err != nil {
- f.logger.Error("CreateWebResourceResponse Error: %s", err)
+ f.logger.Error("%s: NewRequest failed: %s", uri, err)
return
}
- defer response.Release()
- // Send response back
- err = args.PutResponse(response)
- if err != nil {
- f.logger.Error("PutResponse Error: %s", err)
- return
- }
+ f.assets.ServeWebViewRequest(webviewRequest)
}
var edgeMap = map[string]uintptr{
@@ -582,7 +695,24 @@ var edgeMap = map[string]uintptr{
"nw-resize": w32.HTTOPLEFT,
}
-func (f *Frontend) processMessage(message string) {
+func (f *Frontend) processMessage(message string, sender *edge.ICoreWebView2, args *edge.ICoreWebView2WebMessageReceivedEventArgs) {
+ topSource, err := sender.GetSource()
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Unable to get source from sender: %s", err.Error()))
+ return
+ }
+
+ senderSource, err := args.GetSource()
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Unable to get source from args: %s", err.Error()))
+ return
+ }
+
+ // verify both topSource and sender are allowed origins
+ if !f.validBindingOrigin(topSource) || !f.validBindingOrigin(senderSource) {
+ return
+ }
+
if message == "drag" {
if !f.mainWindow.IsFullScreen() {
err := f.startDrag()
@@ -594,7 +724,15 @@ func (f *Frontend) processMessage(message string) {
}
if message == "runtime:ready" {
- cmd := fmt.Sprintf("window.wails.setCSSDragProperties('%s', '%s');", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
+ cmd := fmt.Sprintf(
+ "window.wails.setCSSDragProperties('%s', '%s');\n"+
+ "window.wails.setCSSDropProperties('%s', '%s');",
+ f.frontendOptions.CSSDragProperty,
+ f.frontendOptions.CSSDragValue,
+ f.frontendOptions.DragAndDrop.CSSDropProperty,
+ f.frontendOptions.DragAndDrop.CSSDropValue,
+ )
+
f.ExecJS(cmd)
return
}
@@ -615,30 +753,126 @@ func (f *Frontend) processMessage(message string) {
return
}
- go func() {
- result, err := f.dispatcher.ProcessMessage(message, f)
- if err != nil {
- f.logger.Error(err.Error())
- f.Callback(result)
+ go f.dispatchMessage(message)
+}
+
+func (f *Frontend) processMessageWithAdditionalObjects(message string, sender *edge.ICoreWebView2, args *edge.ICoreWebView2WebMessageReceivedEventArgs) {
+ topSource, err := sender.GetSource()
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Unable to get source from sender: %s", err.Error()))
+ return
+ }
+
+ senderSource, err := args.GetSource()
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Unable to get source from args: %s", err.Error()))
+ return
+ }
+
+ // verify both topSource and sender are allowed origins
+ if !f.validBindingOrigin(topSource) || !f.validBindingOrigin(senderSource) {
+ return
+ }
+
+ if strings.HasPrefix(message, "file:drop") {
+ if !f.frontendOptions.DragAndDrop.EnableFileDrop {
return
}
- if result == "" {
+ objs, err := args.GetAdditionalObjects()
+ if err != nil {
+ f.logger.Error(err.Error())
return
}
- switch result[0] {
- case 'c':
- // Callback from a method call
- f.Callback(result[1:])
- default:
- f.logger.Info("Unknown message returned from dispatcher: %+v", result)
+ defer objs.Release()
+
+ count, err := objs.GetCount()
+ if err != nil {
+ f.logger.Error(err.Error())
+ return
}
- }()
+
+ files := make([]string, count)
+ for i := uint32(0); i < count; i++ {
+ _file, err := objs.GetValueAtIndex(i)
+ if err != nil {
+ f.logger.Error("cannot get value at %d : %s", i, err.Error())
+ return
+ }
+
+ if _file == nil {
+ f.logger.Warning("object at %d is not a file", i)
+ continue
+ }
+
+ file := (*edge.ICoreWebView2File)(unsafe.Pointer(_file))
+ defer file.Release()
+
+ filepath, err := file.GetPath()
+ if err != nil {
+ f.logger.Error("cannot get path for object at %d : %s", i, err.Error())
+ return
+ }
+
+ files[i] = filepath
+ }
+
+ var (
+ x = "0"
+ y = "0"
+ )
+ coords := strings.SplitN(message[10:], ":", 2)
+ if len(coords) == 2 {
+ x = coords[0]
+ y = coords[1]
+ }
+
+ go f.dispatchMessage(fmt.Sprintf("DD:%s:%s:%s", x, y, strings.Join(files, "\n")))
+ return
+ }
+}
+
+func (f *Frontend) validBindingOrigin(source string) bool {
+ origin, err := f.originValidator.GetOriginFromURL(source)
+ if err != nil {
+ f.logger.Error(fmt.Sprintf("Error parsing source URL %s: %v", source, err.Error()))
+ return false
+ }
+ allowed := f.originValidator.IsOriginAllowed(origin)
+ if !allowed {
+ f.logger.Error("Blocked request from unauthorized origin: %s", origin)
+ return false
+ }
+ return true
+}
+
+func (f *Frontend) dispatchMessage(message string) {
+ result, err := f.dispatcher.ProcessMessage(message, f)
+ if err != nil {
+ f.logger.Error(err.Error())
+ f.Callback(result)
+ return
+ }
+ if result == "" {
+ return
+ }
+
+ switch result[0] {
+ case 'c':
+ // Callback from a method call
+ f.Callback(result[1:])
+ default:
+ f.logger.Info("Unknown message returned from dispatcher: %+v", result)
+ }
}
func (f *Frontend) Callback(message string) {
+ escaped, err := json.Marshal(message)
+ if err != nil {
+ panic(err)
+ }
f.mainWindow.Invoke(func() {
- f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`)
+ f.chromium.Eval(`window.wails.Callback(` + string(escaped) + `);`)
})
}
@@ -675,6 +909,10 @@ func (f *Frontend) navigationCompleted(sender *edge.ICoreWebView2, args *edge.IC
f.ExecJS("window.wails.flags.enableResize = true;")
}
+ if f.frontendOptions.DragAndDrop != nil && f.frontendOptions.DragAndDrop.EnableFileDrop {
+ f.ExecJS("window.wails.flags.enableWailsDragAndDrop = true;")
+ }
+
if f.hasStarted {
return
}
@@ -756,86 +994,11 @@ func (f *Frontend) onFocus(arg *winc.Event) {
f.chromium.Focus()
}
-func coreWebview2RequestToHttpRequest(coreReq *edge.ICoreWebView2WebResourceRequest) func() (*http.Request, error) {
- return func() (r *http.Request, err error) {
- header := http.Header{}
- headers, err := coreReq.GetHeaders()
- if err != nil {
- return nil, fmt.Errorf("GetHeaders Error: %s", err)
+func (f *Frontend) startSecondInstanceProcessor() {
+ for secondInstanceData := range secondInstanceBuffer {
+ if f.frontendOptions.SingleInstanceLock != nil &&
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch != nil {
+ f.frontendOptions.SingleInstanceLock.OnSecondInstanceLaunch(secondInstanceData)
}
- defer headers.Release()
-
- headersIt, err := headers.GetIterator()
- if err != nil {
- return nil, fmt.Errorf("GetIterator Error: %s", err)
- }
- defer headersIt.Release()
-
- for {
- has, err := headersIt.HasCurrentHeader()
- if err != nil {
- return nil, fmt.Errorf("HasCurrentHeader Error: %s", err)
- }
- if !has {
- break
- }
-
- name, value, err := headersIt.GetCurrentHeader()
- if err != nil {
- return nil, fmt.Errorf("GetCurrentHeader Error: %s", err)
- }
-
- header.Set(name, value)
- if _, err := headersIt.MoveNext(); err != nil {
- return nil, fmt.Errorf("MoveNext Error: %s", err)
- }
- }
-
- method, err := coreReq.GetMethod()
- if err != nil {
- return nil, fmt.Errorf("GetMethod Error: %s", err)
- }
-
- uri, err := coreReq.GetUri()
- if err != nil {
- return nil, fmt.Errorf("GetUri Error: %s", err)
- }
-
- var body io.ReadCloser
- if content, err := coreReq.GetContent(); err != nil {
- return nil, fmt.Errorf("GetContent Error: %s", err)
- } else if content != nil {
- body = &iStreamReleaseCloser{stream: content}
- }
-
- req, err := http.NewRequest(method, uri, body)
- if err != nil {
- if body != nil {
- body.Close()
- }
- return nil, err
- }
- req.Header = header
- return req, nil
}
}
-
-type iStreamReleaseCloser struct {
- stream *edge.IStream
- closed bool
-}
-
-func (i *iStreamReleaseCloser) Read(p []byte) (int, error) {
- if i.closed {
- return 0, io.ErrClosedPipe
- }
- return i.stream.Read(p)
-}
-
-func (i *iStreamReleaseCloser) Close() error {
- if i.closed {
- return nil
- }
- i.closed = true
- return i.stream.Release()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/LICENSE b/v2/internal/frontend/desktop/windows/go-webview2/LICENSE
deleted file mode 100644
index ef2a0f485..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-MIT License
-
-Copyright (c) 2020 John Chadwick
-Some portions Copyright (c) 2017 Serge Zaitsev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/README.md b/v2/internal/frontend/desktop/windows/go-webview2/README.md
deleted file mode 100644
index 7379b3025..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# go-webview2
-
-This is a proof of concept for embedding Webview2 into Go without CGo. It is based
-on [webview/webview](https://github.com/webview/webview) and provides a compatible API.
-
-## Notice
-
-Because this version doesn't currently have an EdgeHTML fallback, it will not work unless you have a Webview2 runtime
-installed. In addition, it requires the Webview2Loader DLL in order to function. Adding an EdgeHTML fallback should be
-technically possible but will likely require much worse hacks since the API is not strictly COM to my knowledge.
-
-## Demo
-
-For now, you'll need to install the Webview2 runtime, as it does not ship with Windows.
-
-[WebView2 runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
-
-After that, you should be able to run go-webview2 directly:
-
-```
-go run go-webview2/cmd/demo
-```
-
-This will use go-winloader to load an embedded copy of WebView2Loader.dll.
-
-If this does not work, please try running from a directory that has an appropriate copy of `WebView2Loader.dll` for your
-GOARCH. If _that_ worked, *please* file a bug so we can figure out what's wrong with go-winloader :)
\ No newline at end of file
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go b/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go
deleted file mode 100644
index 2b564173f..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go
+++ /dev/null
@@ -1,157 +0,0 @@
-//go:build windows
-
-package w32
-
-import (
- "syscall"
- "unicode/utf16"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- ole32 = windows.NewLazySystemDLL("ole32")
- Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx")
-
- kernel32 = windows.NewLazySystemDLL("kernel32")
- Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId")
-
- shlwapi = windows.NewLazySystemDLL("shlwapi")
- shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream")
-
- user32 = windows.NewLazySystemDLL("user32")
- User32LoadImageW = user32.NewProc("LoadImageW")
- User32GetSystemMetrics = user32.NewProc("GetSystemMetrics")
- User32RegisterClassExW = user32.NewProc("RegisterClassExW")
- User32CreateWindowExW = user32.NewProc("CreateWindowExW")
- User32DestroyWindow = user32.NewProc("DestroyWindow")
- User32ShowWindow = user32.NewProc("ShowWindow")
- User32UpdateWindow = user32.NewProc("UpdateWindow")
- User32SetFocus = user32.NewProc("SetFocus")
- User32GetMessageW = user32.NewProc("GetMessageW")
- User32TranslateMessage = user32.NewProc("TranslateMessage")
- User32DispatchMessageW = user32.NewProc("DispatchMessageW")
- User32DefWindowProcW = user32.NewProc("DefWindowProcW")
- User32GetClientRect = user32.NewProc("GetClientRect")
- User32PostQuitMessage = user32.NewProc("PostQuitMessage")
- User32SetWindowTextW = user32.NewProc("SetWindowTextW")
- User32PostThreadMessageW = user32.NewProc("PostThreadMessageW")
- User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW")
- User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW")
- User32AdjustWindowRect = user32.NewProc("AdjustWindowRect")
- User32SetWindowPos = user32.NewProc("SetWindowPos")
-)
-
-const (
- SystemMetricsCxIcon = 11
- SystemMetricsCyIcon = 12
-)
-
-const (
- SWShow = 5
-)
-
-const (
- SWPNoZOrder = 0x0004
- SWPNoActivate = 0x0010
- SWPNoMove = 0x0002
- SWPFrameChanged = 0x0020
-)
-
-const (
- WMDestroy = 0x0002
- WMMove = 0x0003
- WMSize = 0x0005
- WMClose = 0x0010
- WMQuit = 0x0012
- WMGetMinMaxInfo = 0x0024
- WMNCLButtonDown = 0x00A1
- WMMoving = 0x0216
- WMApp = 0x8000
-)
-
-const (
- GWLStyle = -16
-)
-
-const (
- WSOverlapped = 0x00000000
- WSMaximizeBox = 0x00020000
- WSThickFrame = 0x00040000
- WSCaption = 0x00C00000
- WSSysMenu = 0x00080000
- WSMinimizeBox = 0x00020000
- WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox)
-)
-
-type WndClassExW struct {
- CbSize uint32
- Style uint32
- LpfnWndProc uintptr
- CnClsExtra int32
- CbWndExtra int32
- HInstance windows.Handle
- HIcon windows.Handle
- HCursor windows.Handle
- HbrBackground windows.Handle
- LpszMenuName *uint16
- LpszClassName *uint16
- HIconSm windows.Handle
-}
-
-type Rect struct {
- Left int32
- Top int32
- Right int32
- Bottom int32
-}
-
-type MinMaxInfo struct {
- PtReserved Point
- PtMaxSize Point
- PtMaxPosition Point
- PtMinTrackSize Point
- PtMaxTrackSize Point
-}
-
-type Point struct {
- X, Y int32
-}
-
-type Msg struct {
- Hwnd syscall.Handle
- Message uint32
- WParam uintptr
- LParam uintptr
- Time uint32
- Pt Point
- LPrivate uint32
-}
-
-func Utf16PtrToString(p *uint16) string {
- if p == nil {
- return ""
- }
- // Find NUL terminator.
- end := unsafe.Pointer(p)
- n := 0
- for *(*uint16)(end) != 0 {
- end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
- n++
- }
- s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
- return string(utf16.Decode(s))
-}
-
-func SHCreateMemStream(data []byte) (uintptr, error) {
- ret, _, err := shlwapiSHCreateMemStream.Call(
- uintptr(unsafe.Pointer(&data[0])),
- uintptr(len(data)),
- )
- if ret == 0 {
- return 0, err
- }
-
- return ret, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go
deleted file mode 100644
index ccf04243f..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go
+++ /dev/null
@@ -1,239 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "fmt"
- "runtime"
- "sync"
- "sync/atomic"
-)
-
-var (
- comIfcePointersL sync.RWMutex
- comIfcePointers = map[uintptr]*comObject{} // Map from ComInterfacePointer to the Go ComObject
-)
-
-// Resolve the GoInterface of the specified ComInterfacePointer
-func Resolve[T IUnknown](ifceP uintptr) T {
- comIfcePointersL.RLock()
- comObj := comIfcePointers[ifceP]
- comIfcePointersL.RUnlock()
-
- var n T
- if comObj != nil {
- t := comObj.resolve(ifceP)
- if t != nil {
- n = t.(T)
- }
- }
-
- return n
-}
-
-// New returns a new ComObject which implements the specified Com Interface, com calls will be redirected
-// to the specified go interface.
-func New[T IUnknown](obj T) *ComObject[T] {
- cObj := new(
- ifceDef[T]{obj},
- )
- return newComObject[T](cObj)
-}
-
-// New2 returns a new ComObject which implements the two specified Com Interfaces, com calls will be redirected
-// to those interfaces accordingly.
-// This is needed if a ComObject should implement two interfaces that are not descendants of each other,
-// then you get multiple inheritance.
-func New2[T IUnknown, T2 IUnknown](obj T, obj2 T2) *ComObject[T] {
- cObj := new(
- ifceDef[T]{obj},
- ifceDef[T2]{obj2},
- )
- return newComObject[T](cObj)
-}
-
-// new returns a new ComObject which implements multiple specified Com Interfaces, com calls will be redirected
-// to the specified go interfaces accordingly.
-// This is needed if a ComObject should implement multiple interfaces that are not descendants of each other,
-// then you get multiple inheritance.
-func new(impls ...ifceImpl) *comObject {
- impls = append([]ifceImpl{ifceDef[IUnknown]{}}, impls...)
-
- cObj := &comObject{
- refCount: 1,
- ifces: map[string]int{},
- ifcesImpl: make([]comInterfaceDesc, len(impls)),
- }
-
- for i, ifceDef := range impls {
- vtable, err := ifceDef.ifce()
- if err != nil {
- panic(err)
- }
-
- needsImplement := false
- for table := vtable; table != nil; table = table.Parent {
- guid := table.ComGUID
- if i, found := cObj.ifces[guid]; found {
- // This Interface is already implemented
- if guid == iUnknownGUID {
- // IUnknown is a special interface and never has an user specific implementation
- } else if cObj.ifcesImpl[i].impl != ifceDef.impl() {
- panic(fmt.Sprintf("Interface '%s' is already implemented by another object", table.Name))
- }
-
- break
- }
-
- needsImplement = true
- cObj.ifces[guid] = i
- }
-
- if !needsImplement {
- continue
- }
-
- ifceP, ifcePSlice := allocUintptrObject(1)
- ifcePSlice[0] = vtable.ComVTable
- cObj.ifcesImpl[i] = comInterfaceDesc{ifceP, ifceDef.impl()}
- }
-
- comIfcePointersL.Lock()
- for _, ifceImpl := range cObj.ifcesImpl {
- comIfcePointers[ifceImpl.ref] = cObj
- }
- comIfcePointersL.Unlock()
-
- return cObj
-}
-
-func newComObject[T IUnknown](comObj *comObject) *ComObject[T] {
- c := &ComObject[T]{obj: comObj}
- // Make sure to async release since release needs locks and might block the finalizer goroutine for a longer period
- runtime.SetFinalizer(c, func(obj *ComObject[T]) { obj.close(true) })
- return c
-}
-
-// ComObject describes an exported go instance to be used as a ComObject which implements
-// the specified Interface.
-type ComObject[T IUnknown] struct {
- obj *comObject
- closed int32
-}
-
-// Ref returns the native uintptr that points to the ComObject that is an interface pointer to T.
-// This can be used in native calls. If the object has been closed this function will panic.
-func (o *ComObject[T]) Ref() uintptr {
- if atomic.LoadInt32(&o.closed) != 0 {
- panic("ComObject has been released")
- }
- return o.obj.queryInterface(guidOf[T](), false)
-}
-
-// Close releases the native com object from the go side. It will only be destroyed if the ref counter
-// reaches zero.
-// After closing `Ref()` will panic.
-func (o *ComObject[T]) Close() error {
- o.close(false)
- return nil
-}
-
-// close releases the native com object from the go side. It will only be destroyed if the ref counter
-// reaches zero.
-// After closing `Ref()` will panic.
-func (o *ComObject[T]) close(asyncRelease bool) {
- if atomic.CompareAndSwapInt32(&o.closed, 0, 1) {
- runtime.SetFinalizer(o, nil)
- if asyncRelease {
- go o.obj.release()
- } else {
- o.obj.release()
- }
- }
-}
-
-type comInterfaceDesc struct {
- ref uintptr // The native Com InterfacePointer
- impl any // The golang target object
-}
-
-type comObject struct {
- l sync.Mutex
-
- refCount int32
- ifces map[string]int // Map of ComInterfaceGUID to Interface Slots
- ifcesImpl []comInterfaceDesc // Slots with InterfaceDescriptors
-}
-
-func (c *comObject) queryInterface(ifceGUID string, withAddRef bool) uintptr {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on released com object")
- }
-
- i, found := c.ifces[ifceGUID]
- if !found {
- return 0
- }
-
- if withAddRef {
- c.refCount++
- }
- return c.ifcesImpl[i].ref
-}
-
-func (c *comObject) resolve(ifceP uintptr) any {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- for _, ifce := range c.ifcesImpl {
- if ifce.ref != ifceP {
- continue
- }
-
- return ifce.impl
- }
- return nil
-}
-
-func (c *comObject) addRef() int32 {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- c.refCount++
- return c.refCount
-}
-
-func (c *comObject) release() int32 {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- if c.refCount--; c.refCount == 0 {
- comIfcePointersL.Lock()
- for _, ref := range c.ifcesImpl {
- delete(comIfcePointers, ref.ref)
- }
- comIfcePointersL.Unlock()
-
- for _, impl := range c.ifcesImpl {
- ref := impl.ref
- if ref == 0 {
- continue
- }
-
- globalFree(ref)
- }
- }
-
- return c.refCount
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go
deleted file mode 100644
index 90d7247fe..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "golang.org/x/sys/windows"
-)
-
-const iUnknownGUID = "{00000000-0000-0000-C000-000000000046}"
-
-func init() {
- registerVTableInternal[IUnknown, IUnknown](
- iUnknownGUID,
- true,
- iUnknownQueryInterface,
- iUnknownAddRef,
- iUnknownRelease,
- )
-}
-
-type IUnknown interface{}
-
-func iUnknownQueryInterface(this uintptr, refiid *windows.GUID, ppvObject *uintptr) uintptr {
- if refiid == nil || ppvObject == nil {
- return uintptr(windows.E_INVALIDARG)
- }
-
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- ref := obj.queryInterface(refiid.String(), true)
- if ref != 0 {
- *ppvObject = ref
- return windows.NO_ERROR
- }
-
- *ppvObject = 0
- return uintptr(windows.E_NOINTERFACE)
-}
-
-func iUnknownAddRef(this uintptr) uintptr {
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- return uintptr(obj.addRef())
-}
-
-func iUnknownRelease(this uintptr) uintptr {
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- return uintptr(obj.release())
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go
deleted file mode 100644
index 4c748d461..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go
+++ /dev/null
@@ -1,74 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-// IUnknownFromPointer cast a generic pointer into a IUnknownImpl pointer
-func IUnknownFromPointer(ref unsafe.Pointer) *IUnknownImpl {
- return (*IUnknownImpl)(ref)
-}
-
-// IUnknownFromPointer cast native pointer into a IUnknownImpl pointer
-func IUnknownFromUintptr(ref uintptr) *IUnknownImpl {
- return IUnknownFromPointer(unsafe.Pointer(ref))
-}
-
-type IUnknownVtbl struct {
- queryInterface uintptr
- addRef uintptr
- release uintptr
-}
-
-func (i *IUnknownVtbl) QueryInterface(this unsafe.Pointer, refiid *windows.GUID, ppvObject **IUnknownImpl) error {
- r, _, _ := syscall.SyscallN(
- i.queryInterface,
- uintptr(this),
- uintptr(unsafe.Pointer(refiid)),
- uintptr(unsafe.Pointer(ppvObject)),
- )
-
- if r != uintptr(windows.S_OK) {
- return syscall.Errno(r)
- }
-
- return nil
-}
-
-func (i *IUnknownVtbl) AddRef(this unsafe.Pointer) uint32 {
- r, _, _ := syscall.SyscallN(
- i.addRef,
- uintptr(this),
- )
- return uint32(r)
-}
-
-func (i *IUnknownVtbl) Release(this unsafe.Pointer) uint32 {
- r, _, _ := syscall.SyscallN(
- i.release,
- uintptr(this),
- )
-
- return uint32(r)
-}
-
-type IUnknownImpl struct {
- vtbl *IUnknownVtbl
-}
-
-func (i *IUnknownImpl) QueryInterface(refiid *windows.GUID, ppvObject **IUnknownImpl) error {
- return i.vtbl.QueryInterface(unsafe.Pointer(i), refiid, ppvObject)
-}
-
-func (i *IUnknownImpl) AddRef() uint32 {
- return i.vtbl.AddRef(unsafe.Pointer(i))
-}
-
-func (i *IUnknownImpl) Release() uint32 {
- return i.vtbl.Release(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go
deleted file mode 100644
index 17b7f500e..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go
+++ /dev/null
@@ -1,39 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
- procGlobalFree = modkernel32.NewProc("GlobalFree")
-
- uintptrSize = unsafe.Sizeof(uintptr(0))
-)
-
-func allocUintptrObject(size int) (uintptr, []uintptr) {
- v := globalAlloc(uintptr(size) * uintptrSize)
- slice := unsafe.Slice((*uintptr)(unsafe.Pointer(v)), size)
- return v, slice
-}
-
-func globalAlloc(dwBytes uintptr) uintptr {
- ret, _, _ := procGlobalAlloc.Call(uintptr(0), dwBytes)
- if ret == 0 {
- panic("globalAlloc failed")
- }
-
- return ret
-}
-
-func globalFree(data uintptr) {
- ret, _, _ := procGlobalFree.Call(data)
- if ret != 0 {
- panic("globalFree failed")
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go
deleted file mode 100644
index b099a7848..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go
+++ /dev/null
@@ -1,147 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "fmt"
- "reflect"
- "sync"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- vTablesL sync.Mutex
- vTables = make(map[string]*vTable)
-)
-
-// RegisterVTable registers the vtable trampoline methods for the specified ComInterface
-// TBase is the base interface of T, and must be another ComInterface which roots in IUnknown or IUnknown itself.
-// The first paramter of the fn is always the uintptr of the ComObject and the GoObject can be resolved with Resolve().
-// After having resolved the GoObject the call must be redirected to the GoObject.
-// Typically a trampoline FN looks like this.
-//
-// func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this uintptr, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
-// return combridge.Resolve[_ICoreWebView2NavigationCompletedEventHandler](this).NavigationCompleted(sender, args)
-// }
-//
-// The order of registration must be in the correct order as specified in the IDL of the interface.
-func RegisterVTable[TParent, T IUnknown](guid string, fns ...interface{}) {
- registerVTableInternal[TParent, T](guid, false, fns...)
-}
-
-type vTable struct {
- Parent *vTable
-
- Name string
- ComGUID string
- ComVTable uintptr
- ComProcs []uintptr
-}
-
-func registerVTableInternal[TParent, T IUnknown](guid string, isInternal bool, fns ...interface{}) {
- vTablesL.Lock()
- defer vTablesL.Unlock()
-
- t, tName := typeInterfaceToString[T]()
- tParent, tParentName := typeInterfaceToString[TParent]()
- if !t.Implements(tParent) {
- panic(fmt.Errorf("RegisterVTable '%s': '%s' must implement '%s'", tName, tName, tParentName))
- }
-
- if !isInternal {
- if t == reflect.TypeOf((*IUnknown)(nil)).Elem() {
- panic(fmt.Errorf("RegisterVTable '%s' IUnknown can't be registered", tName))
- }
-
- if t == tParent {
- panic(fmt.Errorf("RegisterVTable '%s': T and TParent can't be the same type", tName))
- }
- }
-
- var parent *vTable
- var parentProcs []uintptr
- var parentProcsCount int
- if t != tParent {
- parent = vTables[tParentName]
- if parent == nil {
- panic(fmt.Errorf("RegisterVTable '%s': Parent VTable '%s' not registered", tName, tParentName))
- }
-
- parentProcs = parent.ComProcs
- parentProcsCount = len(parentProcs)
- }
-
- comGuid, err := windows.GUIDFromString(guid)
- if err != nil {
- panic(fmt.Errorf("RegisterVTable '%s': invalid guid: %s", tName, err))
- }
-
- vTable := &vTable{
- Parent: parent,
- Name: tName,
- ComGUID: comGuid.String(),
- }
- vTable.ComVTable, vTable.ComProcs = allocUintptrObject(parentProcsCount + len(fns))
-
- for i, proc := range parentProcs {
- vTable.ComProcs[i] = proc
- }
-
- for i, fn := range fns {
- vTable.ComProcs[parentProcsCount+i] = windows.NewCallback(fn)
- }
-
- vTables[tName] = vTable
-}
-
-func typeInterfaceToString[T any]() (reflect.Type, string) {
- t := reflect.TypeOf((*T)(nil))
- if t.Kind() != reflect.Pointer {
- panic("must be a (*yourInterfaceType)(nil)")
- }
- t = t.Elem()
- return t, t.PkgPath() + "/" + t.Name()
-}
-
-func typeInterfaceToStringOnly[T any]() string {
- _, nane := typeInterfaceToString[T]()
- return nane
-}
-
-func guidOf[T any]() string {
- vtable := vTableOf[T]()
- if vtable == nil {
- return ""
- }
- return vtable.ComGUID
-}
-
-func vTableOf[T any]() *vTable {
- name := typeInterfaceToStringOnly[T]()
- vTablesL.Lock()
- defer vTablesL.Unlock()
-
- return vTables[name]
-}
-
-type ifceImpl interface {
- impl() any
- ifce() (*vTable, error)
-}
-
-type ifceDef[T any] struct {
- objImpl any
-}
-
-func (i ifceDef[T]) impl() any {
- return i.objImpl
-}
-
-func (i ifceDef[T]) ifce() (*vTable, error) {
- vtable := vTableOf[T]()
- if vtable == nil {
- return nil, fmt.Errorf("Unable to find vTable for %s", typeInterfaceToStringOnly[T]())
- }
- return vtable, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go
deleted file mode 100644
index 429ecef24..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_COLOR struct {
- A uint8
- R uint8
- G uint8
- B uint8
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go
deleted file mode 100644
index ed106ed44..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND uint32
-
-const (
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = iota
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go
deleted file mode 100644
index 607147535..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go
+++ /dev/null
@@ -1,12 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_KEY_EVENT_KIND uint32
-
-const (
- COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0
- COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1
- COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2
- COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go
deleted file mode 100644
index c1679cc37..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_MOVE_FOCUS_REASON uint32
-
-const (
- COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0
- COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = 1
- COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = 2
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go
deleted file mode 100644
index dd8834255..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go
+++ /dev/null
@@ -1,12 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct {
- RepeatCount uint32
- ScanCode uint32
- IsExtendedKey bool
- IsMenuKeyDown bool
- WasKeyDown bool
- IsKeyReleased bool
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go
deleted file mode 100644
index 2e9261d0e..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go
+++ /dev/null
@@ -1,25 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_WEB_RESOURCE_CONTEXT uint32
-
-const (
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = 1
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = 2
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = 3
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = 4
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = 5
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = 6
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = 7
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = 8
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = 9
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = 10
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = 11
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = 12
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = 13
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = 14
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = 15
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = 16
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go
deleted file mode 100644
index 2a3a9c823..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go
+++ /dev/null
@@ -1,79 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct {
- _IUnknownVtbl
- GetKeyEventKind ComProc
- GetVirtualKey ComProc
- GetKeyEventLParam ComProc
- GetPhysicalKeyStatus ComProc
- GetHandled ComProc
- PutHandled ComProc
-}
-
-type ICoreWebView2AcceleratorKeyPressedEventArgs struct {
- vtbl *_ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) {
- var err error
- var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND
- _, _, err = i.vtbl.GetKeyEventKind.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&keyEventKind)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return keyEventKind, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) {
- var err error
- var virtualKey uint
- _, _, err = i.vtbl.GetVirtualKey.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&virtualKey)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return virtualKey, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetPhysicalKeyStatus() (COREWEBVIEW2_PHYSICAL_KEY_STATUS, error) {
- var err error
- var physicalKeyStatus COREWEBVIEW2_PHYSICAL_KEY_STATUS
- _, _, err = i.vtbl.GetPhysicalKeyStatus.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&physicalKeyStatus)),
- )
- if err != windows.ERROR_SUCCESS {
- return COREWEBVIEW2_PHYSICAL_KEY_STATUS{}, err
- }
- return physicalKeyStatus, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutHandled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(handled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go
deleted file mode 100644
index 2c276560b..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type ICoreWebView2AcceleratorKeyPressedEventHandler struct {
- vtbl *_ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl
- impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface(this *ICoreWebView2AcceleratorKeyPressedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke(this *ICoreWebView2AcceleratorKeyPressedEventHandler, sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
- return this.impl.AcceleratorKeyPressed(sender, args)
-}
-
-type _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl interface {
- _IUnknownImpl
- AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr
-}
-
-var _ICoreWebView2AcceleratorKeyPressedEventHandlerFn = _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke),
-}
-
-func newICoreWebView2AcceleratorKeyPressedEventHandler(impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl) *ICoreWebView2AcceleratorKeyPressedEventHandler {
- return &ICoreWebView2AcceleratorKeyPressedEventHandler{
- vtbl: &_ICoreWebView2AcceleratorKeyPressedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go
deleted file mode 100644
index c95a00ade..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go
+++ /dev/null
@@ -1,160 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "math"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2ControllerVtbl struct {
- _IUnknownVtbl
- GetIsVisible ComProc
- PutIsVisible ComProc
- GetBounds ComProc
- PutBounds ComProc
- GetZoomFactor ComProc
- PutZoomFactor ComProc
- AddZoomFactorChanged ComProc
- RemoveZoomFactorChanged ComProc
- SetBoundsAndZoomFactor ComProc
- MoveFocus ComProc
- AddMoveFocusRequested ComProc
- RemoveMoveFocusRequested ComProc
- AddGotFocus ComProc
- RemoveGotFocus ComProc
- AddLostFocus ComProc
- RemoveLostFocus ComProc
- AddAcceleratorKeyPressed ComProc
- RemoveAcceleratorKeyPressed ComProc
- GetParentWindow ComProc
- PutParentWindow ComProc
- NotifyParentWindowPositionChanged ComProc
- Close ComProc
- GetCoreWebView2 ComProc
-}
-
-type ICoreWebView2Controller struct {
- vtbl *_ICoreWebView2ControllerVtbl
-}
-
-func (i *ICoreWebView2Controller) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Controller) GetBounds() (*w32.Rect, error) {
- var err error
- var bounds w32.Rect
- _, _, err = i.vtbl.GetBounds.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&bounds)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return &bounds, nil
-}
-
-func (i *ICoreWebView2Controller) PutBounds(bounds w32.Rect) error {
- var err error
-
- _, _, err = i.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&bounds)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) MoveFocus(reason COREWEBVIEW2_MOVE_FOCUS_REASON) error {
- var err error
-
- _, _, err = i.vtbl.MoveFocus.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(reason),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) AddAcceleratorKeyPressed(eventHandler *ICoreWebView2AcceleratorKeyPressedEventHandler, token *_EventRegistrationToken) error {
- var err error
- _, _, err = i.vtbl.AddAcceleratorKeyPressed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(eventHandler)),
- uintptr(unsafe.Pointer(&token)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsVisible.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isVisible)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 {
-
- var result *ICoreWebView2Controller2
-
- iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}")
- i.vtbl.QueryInterface.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(iidICoreWebView2Controller2)),
- uintptr(unsafe.Pointer(&result)))
-
- return result
-}
-
-func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error {
- var err error
- _, _, err = i.vtbl.NotifyParentWindowPositionChanged.Call(
- uintptr(unsafe.Pointer(i)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error {
- var err error
- _, _, err = i.vtbl.PutZoomFactor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(math.Float64bits(zoomFactor)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) GetZoomFactor() (float64, error) {
- var err error
- var zoomFactorUint64 uint64
- _, _, err = i.vtbl.GetZoomFactor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&zoomFactorUint64)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0.0, err
- }
- return math.Float64frombits(zoomFactorUint64), nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go
deleted file mode 100644
index eff315a91..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go
+++ /dev/null
@@ -1,75 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2Controller2Vtbl struct {
- _IUnknownVtbl
- GetIsVisible ComProc
- PutIsVisible ComProc
- GetBounds ComProc
- PutBounds ComProc
- GetZoomFactor ComProc
- PutZoomFactor ComProc
- AddZoomFactorChanged ComProc
- RemoveZoomFactorChanged ComProc
- SetBoundsAndZoomFactor ComProc
- MoveFocus ComProc
- AddMoveFocusRequested ComProc
- RemoveMoveFocusRequested ComProc
- AddGotFocus ComProc
- RemoveGotFocus ComProc
- AddLostFocus ComProc
- RemoveLostFocus ComProc
- AddAcceleratorKeyPressed ComProc
- RemoveAcceleratorKeyPressed ComProc
- GetParentWindow ComProc
- PutParentWindow ComProc
- NotifyParentWindowPositionChanged ComProc
- Close ComProc
- GetCoreWebView2 ComProc
- GetDefaultBackgroundColor ComProc
- PutDefaultBackgroundColor ComProc
-}
-
-type ICoreWebView2Controller2 struct {
- vtbl *_ICoreWebView2Controller2Vtbl
-}
-
-func (i *ICoreWebView2Controller2) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Controller2) GetDefaultBackgroundColor() (*COREWEBVIEW2_COLOR, error) {
- var err error
- var backgroundColor *COREWEBVIEW2_COLOR
- _, _, err = i.vtbl.GetDefaultBackgroundColor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&backgroundColor)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return backgroundColor, nil
-}
-
-func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(backgroundColor COREWEBVIEW2_COLOR) error {
- var err error
-
- // Cast to a uint32 as that's what the call is expecting
- col := *(*uint32)(unsafe.Pointer(&backgroundColor))
-
- _, _, err = i.vtbl.PutDefaultBackgroundColor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(col),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go
deleted file mode 100644
index c0e4d13b7..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2CreateCoreWebView2ControllerCompletedHandler struct {
- vtbl *_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl
- impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl
-}
-
-func (i *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, errorCode uintptr, createdController *ICoreWebView2Controller) uintptr {
- return this.impl.CreateCoreWebView2ControllerCompleted(errorCode, createdController)
-}
-
-type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl interface {
- _IUnknownImpl
- CreateCoreWebView2ControllerCompleted(errorCode uintptr, createdController *ICoreWebView2Controller) uintptr
-}
-
-var _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn = _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke),
-}
-
-func newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler {
- return &iCoreWebView2CreateCoreWebView2ControllerCompletedHandler{
- vtbl: &_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go
deleted file mode 100644
index 0c9eacb46..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go
+++ /dev/null
@@ -1,78 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2HttpHeadersCollectionIteratorVtbl struct {
- _IUnknownVtbl
- GetCurrentHeader ComProc
- GetHasCurrentHeader ComProc
- MoveNext ComProc
-}
-
-type ICoreWebView2HttpHeadersCollectionIterator struct {
- vtbl *_ICoreWebView2HttpHeadersCollectionIteratorVtbl
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) HasCurrentHeader() (bool, error) {
- var hasHeader int32
- res, _, err := i.vtbl.GetHasCurrentHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&hasHeader)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- if windows.Handle(res) != windows.S_OK {
- return false, syscall.Errno(res)
- }
- return hasHeader != 0, nil
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, string, error) {
- // Create *uint16 to hold result
- var _name *uint16
- var _value *uint16
- res, _, err := i.vtbl.GetCurrentHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_name)),
- uintptr(unsafe.Pointer(&_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", "", syscall.Errno(res)
- }
- // Get result and cleanup
- name := windows.UTF16PtrToString(_name)
- windows.CoTaskMemFree(unsafe.Pointer(_name))
- value := windows.UTF16PtrToString(_value)
- windows.CoTaskMemFree(unsafe.Pointer(_value))
- return name, value, nil
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) MoveNext() (bool, error) {
- var next int32
- res, _, err := i.vtbl.MoveNext.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&next)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- if windows.Handle(res) != windows.S_OK {
- return false, syscall.Errno(res)
- }
- return next != 0, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go
deleted file mode 100644
index 5a147b299..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go
+++ /dev/null
@@ -1,101 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- ERROR_ELEMENT_NOT_FOUND syscall.Errno = 0x80070490
-)
-
-type _ICoreWebView2HttpRequestHeadersVtbl struct {
- _IUnknownVtbl
- GetHeader ComProc
- GetHeaders ComProc
- Contains ComProc
- SetHeader ComProc
- RemoveHeader ComProc
- GetIterator ComProc
-}
-
-type ICoreWebView2HttpRequestHeaders struct {
- vtbl *_ICoreWebView2HttpRequestHeadersVtbl
-}
-
-func (i *ICoreWebView2HttpRequestHeaders) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-// GetHeader returns the value of the specified header. If the header is not found
-// ERROR_ELEMENT_NOT_FOUND is returned as error.
-func (i *ICoreWebView2HttpRequestHeaders) GetHeader(name string) (string, error) {
- _name, err := windows.UTF16PtrFromString(name)
- if err != nil {
- return "", nil
- }
-
- var _value *uint16
- res, _, err := i.vtbl.GetHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_name)),
- uintptr(unsafe.Pointer(&_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", syscall.Errno(res)
- }
-
- value := windows.UTF16PtrToString(_value)
- windows.CoTaskMemFree(unsafe.Pointer(_value))
- return value, nil
-}
-
-// SetHeader sets the specified header to the value.
-func (i *ICoreWebView2HttpRequestHeaders) SetHeader(name, value string) error {
- _name, err := windows.UTF16PtrFromString(name)
- if err != nil {
- return nil
- }
-
- _value, err := windows.UTF16PtrFromString(value)
- if err != nil {
- return nil
- }
-
- res, _, err := i.vtbl.SetHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_name)),
- uintptr(unsafe.Pointer(_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- if windows.Handle(res) != windows.S_OK {
- return syscall.Errno(res)
- }
- return nil
-}
-
-// GetIterator returns an iterator over the collection of request headers. Make sure to call
-// Release on the returned Object after finished using it.
-func (i *ICoreWebView2HttpRequestHeaders) GetIterator() (*ICoreWebView2HttpHeadersCollectionIterator, error) {
- var headers *ICoreWebView2HttpHeadersCollectionIterator
- res, _, err := i.vtbl.GetIterator.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&headers)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return headers, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go
deleted file mode 100644
index c3998e0a2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go
+++ /dev/null
@@ -1,18 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2NavigationCompletedEventArgsVtbl struct {
- _IUnknownVtbl
- GetIsSuccess ComProc
- GetWebErrorStatus ComProc
- GetNavigationId ComProc
-}
-
-type ICoreWebView2NavigationCompletedEventArgs struct {
- vtbl *_ICoreWebView2NavigationCompletedEventArgsVtbl
-}
-
-func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go
deleted file mode 100644
index 456da5074..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2NavigationCompletedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type ICoreWebView2NavigationCompletedEventHandler struct {
- vtbl *_ICoreWebView2NavigationCompletedEventHandlerVtbl
- impl _ICoreWebView2NavigationCompletedEventHandlerImpl
-}
-
-func (i *ICoreWebView2NavigationCompletedEventHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationCompletedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this *ICoreWebView2NavigationCompletedEventHandler, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
- return this.impl.NavigationCompleted(sender, args)
-}
-
-type _ICoreWebView2NavigationCompletedEventHandlerImpl interface {
- _IUnknownImpl
- NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr
-}
-
-var _ICoreWebView2NavigationCompletedEventHandlerFn = _ICoreWebView2NavigationCompletedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerInvoke),
-}
-
-func newICoreWebView2NavigationCompletedEventHandler(impl _ICoreWebView2NavigationCompletedEventHandlerImpl) *ICoreWebView2NavigationCompletedEventHandler {
- return &ICoreWebView2NavigationCompletedEventHandler{
- vtbl: &_ICoreWebView2NavigationCompletedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go
deleted file mode 100644
index a4ba613d2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go
+++ /dev/null
@@ -1,271 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2SettingsVtbl struct {
- _IUnknownVtbl
- GetIsScriptEnabled ComProc
- PutIsScriptEnabled ComProc
- GetIsWebMessageEnabled ComProc
- PutIsWebMessageEnabled ComProc
- GetAreDefaultScriptDialogsEnabled ComProc
- PutAreDefaultScriptDialogsEnabled ComProc
- GetIsStatusBarEnabled ComProc
- PutIsStatusBarEnabled ComProc
- GetAreDevToolsEnabled ComProc
- PutAreDevToolsEnabled ComProc
- GetAreDefaultContextMenusEnabled ComProc
- PutAreDefaultContextMenusEnabled ComProc
- GetAreHostObjectsAllowed ComProc
- PutAreHostObjectsAllowed ComProc
- GetIsZoomControlEnabled ComProc
- PutIsZoomControlEnabled ComProc
- GetIsBuiltInErrorPageEnabled ComProc
- PutIsBuiltInErrorPageEnabled ComProc
-}
-
-type ICoreWebView2Settings struct {
- vtbl *_ICoreWebView2SettingsVtbl
-}
-
-func (i *ICoreWebView2Settings) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) {
- var err error
- var isScriptEnabled bool
- _, _, err = i.vtbl.GetIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isScriptEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsWebMessageEnabled() (bool, error) {
- var err error
- var isWebMessageEnabled bool
- _, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isWebMessageEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
- var err error
- var areDefaultScriptDialogsEnabled bool
- _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDefaultScriptDialogsEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsStatusBarEnabled() (bool, error) {
- var err error
- var isStatusBarEnabled bool
- _, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isStatusBarEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDevToolsEnabled() (bool, error) {
- var err error
- var areDevToolsEnabled bool
- _, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDevToolsEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDefaultContextMenusEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreHostObjectsAllowed() (bool, error) {
- var err error
- var allowed bool
- _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return allowed, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsZoomControlEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsBuiltInErrorPageEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go
deleted file mode 100644
index fe7f2cfa2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go
+++ /dev/null
@@ -1,102 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2WebResourceRequestVtbl struct {
- _IUnknownVtbl
- GetUri ComProc
- PutUri ComProc
- GetMethod ComProc
- PutMethod ComProc
- GetContent ComProc
- PutContent ComProc
- GetHeaders ComProc
-}
-
-type ICoreWebView2WebResourceRequest struct {
- vtbl *_ICoreWebView2WebResourceRequestVtbl
-}
-
-func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceRequest) GetMethod() (string, error) {
- // Create *uint16 to hold result
- var _method *uint16
- res, _, err := i.vtbl.GetMethod.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_method)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", syscall.Errno(res)
- }
- // Get result and cleanup
- uri := windows.UTF16PtrToString(_method)
- windows.CoTaskMemFree(unsafe.Pointer(_method))
- return uri, nil
-}
-
-func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) {
- var err error
- // Create *uint16 to hold result
- var _uri *uint16
- _, _, err = i.vtbl.GetUri.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_uri)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- } // Get result and cleanup
- uri := windows.UTF16PtrToString(_uri)
- windows.CoTaskMemFree(unsafe.Pointer(_uri))
- return uri, nil
-}
-
-// GetContent returns the body of the request. Returns nil if there's no body. Make sure to call
-// Release on the returned IStream after finished using it.
-func (i *ICoreWebView2WebResourceRequest) GetContent() (*IStream, error) {
- var stream *IStream
- res, _, err := i.vtbl.GetContent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&stream)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return stream, nil
-}
-
-// GetHeaders returns the mutable HTTP request headers. Make sure to call
-// Release on the returned Object after finished using it.
-func (i *ICoreWebView2WebResourceRequest) GetHeaders() (*ICoreWebView2HttpRequestHeaders, error) {
- var headers *ICoreWebView2HttpRequestHeaders
- res, _, err := i.vtbl.GetHeaders.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&headers)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return headers, nil
-}
-
-func (i *ICoreWebView2WebResourceRequest) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go
deleted file mode 100644
index 614594e87..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go
+++ /dev/null
@@ -1,52 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2WebResourceRequestedEventArgsVtbl struct {
- _IUnknownVtbl
- GetRequest ComProc
- GetResponse ComProc
- PutResponse ComProc
- GetDeferral ComProc
- GetResourceContext ComProc
-}
-
-type ICoreWebView2WebResourceRequestedEventArgs struct {
- vtbl *_ICoreWebView2WebResourceRequestedEventArgsVtbl
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) PutResponse(response *ICoreWebView2WebResourceResponse) error {
- var err error
-
- _, _, err = i.vtbl.PutResponse.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(response)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) {
- var err error
- var request *ICoreWebView2WebResourceRequest
- _, _, err = i.vtbl.GetRequest.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&request)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return request, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go
deleted file mode 100644
index d0860c3be..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go
+++ /dev/null
@@ -1,50 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2WebResourceRequestedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2WebResourceRequestedEventHandler struct {
- vtbl *_ICoreWebView2WebResourceRequestedEventHandlerVtbl
- impl _ICoreWebView2WebResourceRequestedEventHandlerImpl
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebResourceRequestedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerInvoke(this *iCoreWebView2WebResourceRequestedEventHandler, sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
- return this.impl.WebResourceRequested(sender, args)
-}
-
-type _ICoreWebView2WebResourceRequestedEventHandlerImpl interface {
- _IUnknownImpl
- WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr
-}
-
-var _ICoreWebView2WebResourceRequestedEventHandlerFn = _ICoreWebView2WebResourceRequestedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerInvoke),
-}
-
-func newICoreWebView2WebResourceRequestedEventHandler(impl _ICoreWebView2WebResourceRequestedEventHandlerImpl) *iCoreWebView2WebResourceRequestedEventHandler {
- return &iCoreWebView2WebResourceRequestedEventHandler{
- vtbl: &_ICoreWebView2WebResourceRequestedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go
deleted file mode 100644
index dd02e6089..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go
+++ /dev/null
@@ -1,28 +0,0 @@
-//go:build windows
-
-package edge
-
-import "unsafe"
-
-type _ICoreWebView2WebResourceResponseVtbl struct {
- _IUnknownVtbl
- GetContent ComProc
- PutContent ComProc
- GetHeaders ComProc
- GetStatusCode ComProc
- PutStatusCode ComProc
- GetReasonPhrase ComProc
- PutReasonPhrase ComProc
-}
-
-type ICoreWebView2WebResourceResponse struct {
- vtbl *_ICoreWebView2WebResourceResponseVtbl
-}
-
-func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceResponse) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go
deleted file mode 100644
index 85a4f71fa..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go
+++ /dev/null
@@ -1,18 +0,0 @@
-//go:build windows
-
-package edge
-
-type iCoreWebView2_2Vtbl struct {
- iCoreWebView2Vtbl
- AddWebResourceResponseReceived ComProc
- RemoveWebResourceResponseReceived ComProc
- NavigateWithWebResourceRequest ComProc
- AddDomContentLoaded ComProc
- RemoveDomContentLoaded ComProc
- GetCookieManager ComProc
- GetEnvironment ComProc
-}
-
-type ICoreWebView2_2 struct {
- vtbl *iCoreWebView2_2Vtbl
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go
deleted file mode 100644
index 58424bd6a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go
+++ /dev/null
@@ -1,62 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type iCoreWebView2_3Vtbl struct {
- iCoreWebView2_2Vtbl
- TrySuspend ComProc
- Resume ComProc
- GetIsSuspended ComProc
- SetVirtualHostNameToFolderMapping ComProc
- ClearVirtualHostNameToFolderMapping ComProc
-}
-
-type ICoreWebView2_3 struct {
- vtbl *iCoreWebView2_3Vtbl
-}
-
-func (i *ICoreWebView2_3) SetVirtualHostNameToFolderMapping(hostName, folderPath string, accessKind COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND) error {
- _hostName, err := windows.UTF16PtrFromString(hostName)
- if err != nil {
- return err
- }
-
- _folderPath, err := windows.UTF16PtrFromString(folderPath)
- if err != nil {
- return err
- }
-
- _, _, err = i.vtbl.SetVirtualHostNameToFolderMapping.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_hostName)),
- uintptr(unsafe.Pointer(_folderPath)),
- uintptr(accessKind),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
-
- return nil
-}
-
-func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 {
- var result *ICoreWebView2_3
-
- iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}")
- _, _, _ = i.vtbl.QueryInterface.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(iidICoreWebView2_3)),
- uintptr(unsafe.Pointer(&result)))
-
- return result
-}
-
-func (e *Chromium) GetICoreWebView2_3() *ICoreWebView2_3 {
- return e.webview.GetICoreWebView2_3()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
deleted file mode 100644
index 6c6b16d74..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
+++ /dev/null
@@ -1,397 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-// ICoreWebviewSettings is the merged settings class
-
-type _ICoreWebViewSettingsVtbl struct {
- _IUnknownVtbl
- GetIsScriptEnabled ComProc
- PutIsScriptEnabled ComProc
- GetIsWebMessageEnabled ComProc
- PutIsWebMessageEnabled ComProc
- GetAreDefaultScriptDialogsEnabled ComProc
- PutAreDefaultScriptDialogsEnabled ComProc
- GetIsStatusBarEnabled ComProc
- PutIsStatusBarEnabled ComProc
- GetAreDevToolsEnabled ComProc
- PutAreDevToolsEnabled ComProc
- GetAreDefaultContextMenusEnabled ComProc
- PutAreDefaultContextMenusEnabled ComProc
- GetAreHostObjectsAllowed ComProc
- PutAreHostObjectsAllowed ComProc
- GetIsZoomControlEnabled ComProc
- PutIsZoomControlEnabled ComProc
- GetIsBuiltInErrorPageEnabled ComProc
- PutIsBuiltInErrorPageEnabled ComProc
- GetUserAgent ComProc // ICoreWebView2Settings2: SDK 1.0.864.35
- PutUserAgent ComProc
- GetAreBrowserAcceleratorKeysEnabled ComProc // ICoreWebView2Settings3: SDK 1.0.864.35
- PutAreBrowserAcceleratorKeysEnabled ComProc
- GetIsPasswordAutosaveEnabled ComProc // ICoreWebView2Settings4: SDK 1.0.902.49
- PutIsPasswordAutosaveEnabled ComProc
- GetIsGeneralAutofillEnabled ComProc
- PutIsGeneralAutofillEnabled ComProc
- GetIsPinchZoomEnabled ComProc // ICoreWebView2Settings5: SDK 1.0.902.49
- PutIsPinchZoomEnabled ComProc
- GetIsSwipeNavigationEnabled ComProc // ICoreWebView2Settings6: SDK 1.0.992.28
- PutIsSwipeNavigationEnabled ComProc
-}
-
-type ICoreWebViewSettings struct {
- vtbl *_ICoreWebViewSettingsVtbl
-}
-
-func (i *ICoreWebViewSettings) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebViewSettings) GetIsScriptEnabled() (bool, error) {
- var err error
- var isScriptEnabled bool
- _, _, err = i.vtbl.GetIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isScriptEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsScriptEnabled(isScriptEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsWebMessageEnabled() (bool, error) {
- var err error
- var isWebMessageEnabled bool
- _, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isWebMessageEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
- var err error
- var areDefaultScriptDialogsEnabled bool
- _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDefaultScriptDialogsEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsStatusBarEnabled() (bool, error) {
- var err error
- var isStatusBarEnabled bool
- _, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isStatusBarEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDevToolsEnabled() (bool, error) {
- var err error
- var areDevToolsEnabled bool
- _, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDevToolsEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDefaultContextMenusEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDefaultContextMenusEnabled(enabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreHostObjectsAllowed() (bool, error) {
- var err error
- var allowed bool
- _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return allowed, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreHostObjectsAllowed(allowed bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsZoomControlEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsZoomControlEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsBuiltInErrorPageEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetUserAgent() (string, error) {
- var err error
- // Create *uint16 to hold result
- var _userAgent *uint16
- _, _, err = i.vtbl.GetUserAgent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_userAgent)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- } // Get result and cleanup
- userAgent := windows.UTF16PtrToString(_userAgent)
- windows.CoTaskMemFree(unsafe.Pointer(_userAgent))
- return userAgent, nil
-}
-
-func (i *ICoreWebViewSettings) PutUserAgent(userAgent string) error {
- var err error
- // Convert string 'userAgent' to *uint16
- _userAgent, err := windows.UTF16PtrFromString(userAgent)
- if err != nil {
- return err
- }
-
- _, _, err = i.vtbl.PutUserAgent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_userAgent)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreBrowserAcceleratorKeysEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreBrowserAcceleratorKeysEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreBrowserAcceleratorKeysEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreBrowserAcceleratorKeysEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsPinchZoomEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsPinchZoomEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsPinchZoomEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsPinchZoomEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsSwipeNavigationEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsSwipeNavigationEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsSwipeNavigationEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsSwipeNavigationEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go
deleted file mode 100644
index 9e29ca4f0..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "io"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _IStreamVtbl struct {
- _IUnknownVtbl
- Read ComProc
- Write ComProc
-}
-
-type IStream struct {
- vtbl *_IStreamVtbl
-}
-
-func (i *IStream) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-func (i *IStream) Read(p []byte) (int, error) {
- bufLen := len(p)
- if bufLen == 0 {
- return 0, nil
- }
-
- var n int
- res, _, err := i.vtbl.Read.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&p[0])),
- uintptr(bufLen),
- uintptr(unsafe.Pointer(&n)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
-
- switch windows.Handle(res) {
- case windows.S_OK:
- // The buffer has been completely filled
- return n, nil
- case windows.S_FALSE:
- // The buffer has been filled with less than len data and the stream is EOF
- return n, io.EOF
- default:
- return 0, syscall.Errno(res)
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
deleted file mode 100644
index 219aca35c..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
+++ /dev/null
@@ -1,404 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "errors"
- "log"
- "os"
- "path/filepath"
- "strings"
- "sync/atomic"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "golang.org/x/sys/windows"
-)
-
-type Rect = w32.Rect
-
-type Chromium struct {
- hwnd uintptr
- controller *ICoreWebView2Controller
- webview *ICoreWebView2
- inited uintptr
- envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
- controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler
- webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler
- permissionRequested *iCoreWebView2PermissionRequestedEventHandler
- webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler
- acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler
- navigationCompleted *ICoreWebView2NavigationCompletedEventHandler
-
- environment *ICoreWebView2Environment
-
- padding Rect
-
- // Settings
- Debug bool
- DataPath string
- BrowserPath string
- AdditionalBrowserArgs []string
-
- // permissions
- permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
- globalPermission *CoreWebView2PermissionState
-
- // Callbacks
- MessageCallback func(string)
- WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs)
- NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs)
- AcceleratorKeyCallback func(uint) bool
-}
-
-func NewChromium() *Chromium {
- e := &Chromium{}
- /*
- All these handlers are passed to native code through syscalls with 'uintptr(unsafe.Pointer(handler))' and we know
- that a pointer to those will be kept in the native code. Furthermore these handlers als contain pointer to other Go
- structs like the vtable.
- This violates the unsafe.Pointer rule '(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.' because
- theres no guarantee that Go doesn't move these objects.
- AFAIK currently the Go runtime doesn't move HEAP objects, so we should be safe with these handlers. But they don't
- guarantee it, because in the future Go might use a compacting GC.
- There's a proposal to add a runtime.Pin function, to prevent moving pinned objects, which would allow to easily fix
- this issue by just pinning the handlers. The https://go-review.googlesource.com/c/go/+/367296/ should land in Go 1.19.
- */
- e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e)
- e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e)
- e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e)
- e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e)
- e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e)
- e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e)
- e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e)
- e.permissions = make(map[CoreWebView2PermissionKind]CoreWebView2PermissionState)
-
- return e
-}
-
-func (e *Chromium) Embed(hwnd uintptr) bool {
- e.hwnd = hwnd
-
- dataPath := e.DataPath
- if dataPath == "" {
- currentExePath := make([]uint16, windows.MAX_PATH)
- _, err := windows.GetModuleFileName(windows.Handle(0), ¤tExePath[0], windows.MAX_PATH)
- if err != nil {
- // What to do here?
- return false
- }
- currentExeName := filepath.Base(windows.UTF16ToString(currentExePath))
- dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
- }
-
- if e.BrowserPath != "" {
- if _, err := os.Stat(e.BrowserPath); errors.Is(err, os.ErrNotExist) {
- log.Printf("Browser path %s does not exist", e.BrowserPath)
- return false
- }
- }
-
- browserArgs := strings.Join(e.AdditionalBrowserArgs, " ")
- if err := createCoreWebView2EnvironmentWithOptions(e.BrowserPath, dataPath, e.envCompleted, browserArgs); err != nil {
- log.Printf("Error calling Webview2Loader: %v", err)
- return false
- }
-
- var msg w32.Msg
- for {
- if atomic.LoadUintptr(&e.inited) != 0 {
- break
- }
- r, _, _ := w32.User32GetMessageW.Call(
- uintptr(unsafe.Pointer(&msg)),
- 0,
- 0,
- 0,
- )
- if r == 0 {
- break
- }
- w32.User32TranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
- w32.User32DispatchMessageW.Call(uintptr(unsafe.Pointer(&msg)))
- }
- e.Init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}")
- return true
-}
-
-func (e *Chromium) SetPadding(padding Rect) {
- if e.padding.Top == padding.Top && e.padding.Bottom == padding.Bottom &&
- e.padding.Left == padding.Left && e.padding.Right == padding.Right {
-
- return
- }
-
- e.padding = padding
- e.Resize()
-}
-
-func (e *Chromium) Resize() {
- if e.hwnd == 0 {
- return
- }
-
- var bounds w32.Rect
- w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds)))
-
- bounds.Top += e.padding.Top
- bounds.Bottom -= e.padding.Bottom
- bounds.Left += e.padding.Left
- bounds.Right -= e.padding.Right
-
- e.SetSize(bounds)
-}
-
-func (e *Chromium) Navigate(url string) {
- e.webview.vtbl.Navigate.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))),
- )
-}
-
-func (e *Chromium) Init(script string) {
- e.webview.vtbl.AddScriptToExecuteOnDocumentCreated.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(script))),
- 0,
- )
-}
-
-func (e *Chromium) Eval(script string) {
-
- _script, err := windows.UTF16PtrFromString(script)
- if err != nil {
- log.Fatal(err)
- }
-
- e.webview.vtbl.ExecuteScript.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(_script)),
- 0,
- )
-}
-
-func (e *Chromium) Show() error {
- return e.controller.PutIsVisible(true)
-}
-
-func (e *Chromium) Hide() error {
- return e.controller.PutIsVisible(false)
-}
-
-func (e *Chromium) QueryInterface(_, _ uintptr) uintptr {
- return 0
-}
-
-func (e *Chromium) AddRef() uintptr {
- return 1
-}
-
-func (e *Chromium) Release() uintptr {
- return 1
-}
-
-func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr {
- if int32(res) < 0 {
- log.Fatalf("Creating environment failed with %08x: %s", res, syscall.Errno(res))
- }
- env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env)))
- e.environment = env
-
- env.vtbl.CreateCoreWebView2Controller.Call(
- uintptr(unsafe.Pointer(env)),
- e.hwnd,
- uintptr(unsafe.Pointer(e.controllerCompleted)),
- )
- return 0
-}
-
-func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller *ICoreWebView2Controller) uintptr {
- if int32(res) < 0 {
- log.Fatalf("Creating controller failed with %08x: %s", res, syscall.Errno(res))
- }
- controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller)))
- e.controller = controller
-
- var token _EventRegistrationToken
- controller.vtbl.GetCoreWebView2.Call(
- uintptr(unsafe.Pointer(controller)),
- uintptr(unsafe.Pointer(&e.webview)),
- )
- e.webview.vtbl.AddRef.Call(
- uintptr(unsafe.Pointer(e.webview)),
- )
- e.webview.vtbl.AddWebMessageReceived.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.webMessageReceived)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddPermissionRequested.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.permissionRequested)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddWebResourceRequested.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.webResourceRequested)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddNavigationCompleted.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.navigationCompleted)),
- uintptr(unsafe.Pointer(&token)),
- )
-
- e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token)
-
- atomic.StoreUintptr(&e.inited, 1)
-
- return 0
-}
-
-func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
- var message *uint16
- args.vtbl.TryGetWebMessageAsString.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(unsafe.Pointer(&message)),
- )
- if e.MessageCallback != nil {
- e.MessageCallback(w32.Utf16PtrToString(message))
- }
- sender.vtbl.PostWebMessageAsString.Call(
- uintptr(unsafe.Pointer(sender)),
- uintptr(unsafe.Pointer(message)),
- )
- windows.CoTaskMemFree(unsafe.Pointer(message))
- return 0
-}
-
-func (e *Chromium) SetPermission(kind CoreWebView2PermissionKind, state CoreWebView2PermissionState) {
- e.permissions[kind] = state
-}
-
-func (e *Chromium) SetGlobalPermission(state CoreWebView2PermissionState) {
- e.globalPermission = &state
-}
-
-func (e *Chromium) PermissionRequested(_ *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
- var kind CoreWebView2PermissionKind
- args.vtbl.GetPermissionKind.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(kind),
- )
- var result CoreWebView2PermissionState
- if e.globalPermission != nil {
- result = *e.globalPermission
- } else {
- var ok bool
- result, ok = e.permissions[kind]
- if !ok {
- result = CoreWebView2PermissionStateDefault
- }
- }
- args.vtbl.PutState.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(result),
- )
- return 0
-}
-
-func (e *Chromium) WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
- req, err := args.GetRequest()
- if err != nil {
- log.Fatal(err)
- }
- defer req.Release()
-
- if e.WebResourceRequestedCallback != nil {
- e.WebResourceRequestedCallback(req, args)
- }
- return 0
-}
-
-func (e *Chromium) AddWebResourceRequestedFilter(filter string, ctx COREWEBVIEW2_WEB_RESOURCE_CONTEXT) {
- err := e.webview.AddWebResourceRequestedFilter(filter, ctx)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) Environment() *ICoreWebView2Environment {
- return e.environment
-}
-
-// AcceleratorKeyPressed is called when an accelerator key is pressed.
-// If the AcceleratorKeyCallback method has been set, it will defer handling of the keypress
-// to the callback. That callback returns a bool indicating if the event was handled.
-func (e *Chromium) AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
- if e.AcceleratorKeyCallback == nil {
- return 0
- }
- eventKind, _ := args.GetKeyEventKind()
- if eventKind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN ||
- eventKind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN {
- virtualKey, _ := args.GetVirtualKey()
- status, _ := args.GetPhysicalKeyStatus()
- if !status.WasKeyDown {
- args.PutHandled(e.AcceleratorKeyCallback(virtualKey))
- return 0
- }
- }
- args.PutHandled(false)
- return 0
-}
-
-func (e *Chromium) GetSettings() (*ICoreWebViewSettings, error) {
- return e.webview.GetSettings()
-}
-
-func (e *Chromium) GetController() *ICoreWebView2Controller {
- return e.controller
-}
-
-func boolToInt(input bool) int {
- if input {
- return 1
- }
- return 0
-}
-
-func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
- if e.NavigationCompletedCallback != nil {
- e.NavigationCompletedCallback(sender, args)
- }
- return 0
-}
-
-func (e *Chromium) NotifyParentWindowPositionChanged() error {
- //It looks like the wndproc function is called before the controller initialization is complete.
- //Because of this the controller is nil
- if e.controller == nil {
- return nil
- }
- return e.controller.NotifyParentWindowPositionChanged()
-}
-
-func (e *Chromium) Focus() {
- err := e.controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) PutZoomFactor(zoomFactor float64) {
- err := e.controller.PutZoomFactor(zoomFactor)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) OpenDevToolsWindow() {
- e.webview.OpenDevToolsWindow()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go
deleted file mode 100644
index 00f6f42fb..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "unsafe"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- uintptr(bounds.Left),
- uintptr(bounds.Top),
- uintptr(bounds.Right),
- uintptr(bounds.Bottom),
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go
deleted file mode 100644
index 858b93f17..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go
+++ /dev/null
@@ -1,20 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "unsafe"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- uintptr(unsafe.Pointer(&bounds)),
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go
deleted file mode 100644
index b237792e4..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- words := (*[2]uintptr)(unsafe.Pointer(&bounds))
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- words[0],
- words[1],
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go
deleted file mode 100644
index b8d819754..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go
+++ /dev/null
@@ -1,482 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "log"
- "runtime"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
-
- "golang.org/x/sys/windows"
-)
-
-func init() {
- runtime.LockOSThread()
-
- r, _, _ := w32.Ole32CoInitializeEx.Call(0, 2)
- if int(r) < 0 {
- log.Printf("Warning: CoInitializeEx call failed: E=%08x", r)
- }
-}
-
-type _EventRegistrationToken struct {
- value int64
-}
-
-type CoreWebView2PermissionKind uint32
-
-const (
- CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota
- CoreWebView2PermissionKindMicrophone
- CoreWebView2PermissionKindCamera
- CoreWebView2PermissionKindGeolocation
- CoreWebView2PermissionKindNotifications
- CoreWebView2PermissionKindOtherSensors
- CoreWebView2PermissionKindClipboardRead
-)
-
-type CoreWebView2PermissionState uint32
-
-const (
- CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota
- CoreWebView2PermissionStateAllow
- CoreWebView2PermissionStateDeny
-)
-
-// ComProc stores a COM procedure.
-type ComProc uintptr
-
-// NewComProc creates a new COM proc from a Go function.
-func NewComProc(fn interface{}) ComProc {
- return ComProc(windows.NewCallback(fn))
-}
-
-// Call calls a COM procedure.
-//
-//go:uintptrescapes
-func (p ComProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
- // The magic uintptrescapes comment is needed to prevent moving uintptr(unsafe.Pointer(p)) so calls to .Call() also
- // satisfy the unsafe.Pointer rule "(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall."
- // Otherwise it might be that pointers get moved, especially pointer onto the Go stack which might grow dynamically.
- // See https://pkg.go.dev/unsafe#Pointer and https://github.com/golang/go/issues/34474
- switch len(a) {
- case 0:
- return syscall.Syscall(uintptr(p), 0, 0, 0, 0)
- case 1:
- return syscall.Syscall(uintptr(p), 1, a[0], 0, 0)
- case 2:
- return syscall.Syscall(uintptr(p), 2, a[0], a[1], 0)
- case 3:
- return syscall.Syscall(uintptr(p), 3, a[0], a[1], a[2])
- case 4:
- return syscall.Syscall6(uintptr(p), 4, a[0], a[1], a[2], a[3], 0, 0)
- case 5:
- return syscall.Syscall6(uintptr(p), 5, a[0], a[1], a[2], a[3], a[4], 0)
- case 6:
- return syscall.Syscall6(uintptr(p), 6, a[0], a[1], a[2], a[3], a[4], a[5])
- case 7:
- return syscall.Syscall9(uintptr(p), 7, a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
- case 8:
- return syscall.Syscall9(uintptr(p), 8, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
- case 9:
- return syscall.Syscall9(uintptr(p), 9, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
- case 10:
- return syscall.Syscall12(uintptr(p), 10, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
- case 11:
- return syscall.Syscall12(uintptr(p), 11, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
- case 12:
- return syscall.Syscall12(uintptr(p), 12, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
- case 13:
- return syscall.Syscall15(uintptr(p), 13, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
- case 14:
- return syscall.Syscall15(uintptr(p), 14, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
- case 15:
- return syscall.Syscall15(uintptr(p), 15, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
- default:
- panic("too many arguments")
- }
-}
-
-// IUnknown
-
-type _IUnknownVtbl struct {
- QueryInterface ComProc
- AddRef ComProc
- Release ComProc
-}
-
-func (i *_IUnknownVtbl) CallRelease(this unsafe.Pointer) error {
- _, _, err := i.Release.Call(
- uintptr(this),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-type _IUnknownImpl interface {
- QueryInterface(refiid, object uintptr) uintptr
- AddRef() uintptr
- Release() uintptr
-}
-
-// ICoreWebView2
-
-type iCoreWebView2Vtbl struct {
- _IUnknownVtbl
- GetSettings ComProc
- GetSource ComProc
- Navigate ComProc
- NavigateToString ComProc
- AddNavigationStarting ComProc
- RemoveNavigationStarting ComProc
- AddContentLoading ComProc
- RemoveContentLoading ComProc
- AddSourceChanged ComProc
- RemoveSourceChanged ComProc
- AddHistoryChanged ComProc
- RemoveHistoryChanged ComProc
- AddNavigationCompleted ComProc
- RemoveNavigationCompleted ComProc
- AddFrameNavigationStarting ComProc
- RemoveFrameNavigationStarting ComProc
- AddFrameNavigationCompleted ComProc
- RemoveFrameNavigationCompleted ComProc
- AddScriptDialogOpening ComProc
- RemoveScriptDialogOpening ComProc
- AddPermissionRequested ComProc
- RemovePermissionRequested ComProc
- AddProcessFailed ComProc
- RemoveProcessFailed ComProc
- AddScriptToExecuteOnDocumentCreated ComProc
- RemoveScriptToExecuteOnDocumentCreated ComProc
- ExecuteScript ComProc
- CapturePreview ComProc
- Reload ComProc
- PostWebMessageAsJSON ComProc
- PostWebMessageAsString ComProc
- AddWebMessageReceived ComProc
- RemoveWebMessageReceived ComProc
- CallDevToolsProtocolMethod ComProc
- GetBrowserProcessID ComProc
- GetCanGoBack ComProc
- GetCanGoForward ComProc
- GoBack ComProc
- GoForward ComProc
- GetDevToolsProtocolEventReceiver ComProc
- Stop ComProc
- AddNewWindowRequested ComProc
- RemoveNewWindowRequested ComProc
- AddDocumentTitleChanged ComProc
- RemoveDocumentTitleChanged ComProc
- GetDocumentTitle ComProc
- AddHostObjectToScript ComProc
- RemoveHostObjectFromScript ComProc
- OpenDevToolsWindow ComProc
- AddContainsFullScreenElementChanged ComProc
- RemoveContainsFullScreenElementChanged ComProc
- GetContainsFullScreenElement ComProc
- AddWebResourceRequested ComProc
- RemoveWebResourceRequested ComProc
- AddWebResourceRequestedFilter ComProc
- RemoveWebResourceRequestedFilter ComProc
- AddWindowCloseRequested ComProc
- RemoveWindowCloseRequested ComProc
-}
-
-type ICoreWebView2 struct {
- vtbl *iCoreWebView2Vtbl
-}
-
-func (i *ICoreWebView2) GetSettings() (*ICoreWebViewSettings, error) {
- var err error
- var settings *ICoreWebViewSettings
- _, _, err = i.vtbl.GetSettings.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&settings)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return settings, nil
-}
-
-// ICoreWebView2Environment
-
-type iCoreWebView2EnvironmentVtbl struct {
- _IUnknownVtbl
- CreateCoreWebView2Controller ComProc
- CreateWebResourceResponse ComProc
- GetBrowserVersionString ComProc
- AddNewBrowserVersionAvailable ComProc
- RemoveNewBrowserVersionAvailable ComProc
-}
-
-type ICoreWebView2Environment struct {
- vtbl *iCoreWebView2EnvironmentVtbl
-}
-
-// CreateWebResourceResponse creates a new ICoreWebView2WebResourceResponse, it must be released after finishing using it.
-func (e *ICoreWebView2Environment) CreateWebResourceResponse(content []byte, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) {
- var err error
- var stream uintptr
-
- if len(content) > 0 {
- // Create stream for response
- stream, err = w32.SHCreateMemStream(content)
- if err != nil {
- return nil, err
- }
-
- // Release the IStream after we are finished, CreateWebResourceResponse Call will increase the reference
- // count on IStream and therefore it won't be freed until the reference count of the response is 0.
- defer (*IStream)(unsafe.Pointer(stream)).Release()
- }
-
- // Convert string 'uri' to *uint16
- _reason, err := windows.UTF16PtrFromString(reasonPhrase)
- if err != nil {
- return nil, err
- }
- // Convert string 'uri' to *uint16
- _headers, err := windows.UTF16PtrFromString(headers)
- if err != nil {
- return nil, err
- }
- var response *ICoreWebView2WebResourceResponse
- _, _, err = e.vtbl.CreateWebResourceResponse.Call(
- uintptr(unsafe.Pointer(e)),
- stream,
- uintptr(statusCode),
- uintptr(unsafe.Pointer(_reason)),
- uintptr(unsafe.Pointer(_headers)),
- uintptr(unsafe.Pointer(&response)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return response, nil
-
-}
-
-// ICoreWebView2WebMessageReceivedEventArgs
-
-type iCoreWebView2WebMessageReceivedEventArgsVtbl struct {
- _IUnknownVtbl
- GetSource ComProc
- GetWebMessageAsJSON ComProc
- TryGetWebMessageAsString ComProc
-}
-
-type iCoreWebView2WebMessageReceivedEventArgs struct {
- vtbl *iCoreWebView2WebMessageReceivedEventArgsVtbl
-}
-
-// ICoreWebView2PermissionRequestedEventArgs
-
-type iCoreWebView2PermissionRequestedEventArgsVtbl struct {
- _IUnknownVtbl
- GetURI ComProc
- GetPermissionKind ComProc
- GetIsUserInitiated ComProc
- GetState ComProc
- PutState ComProc
- GetDeferral ComProc
-}
-
-type iCoreWebView2PermissionRequestedEventArgs struct {
- vtbl *iCoreWebView2PermissionRequestedEventArgsVtbl
-}
-
-// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl interface {
- _IUnknownImpl
- EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler struct {
- vtbl *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl
- impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, res uintptr, env *ICoreWebView2Environment) uintptr {
- return this.impl.EnvironmentCompleted(res, env)
-}
-
-var iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn = iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke),
-}
-
-func newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler {
- return &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{
- vtbl: &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn,
- impl: impl,
- }
-}
-
-// ICoreWebView2WebMessageReceivedEventHandler
-
-type iCoreWebView2WebMessageReceivedEventHandlerImpl interface {
- _IUnknownImpl
- MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr
-}
-
-type iCoreWebView2WebMessageReceivedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2WebMessageReceivedEventHandler struct {
- vtbl *iCoreWebView2WebMessageReceivedEventHandlerVtbl
- impl iCoreWebView2WebMessageReceivedEventHandlerImpl
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebMessageReceivedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerInvoke(this *iCoreWebView2WebMessageReceivedEventHandler, sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
- return this.impl.MessageReceived(sender, args)
-}
-
-var iCoreWebView2WebMessageReceivedEventHandlerFn = iCoreWebView2WebMessageReceivedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerInvoke),
-}
-
-func newICoreWebView2WebMessageReceivedEventHandler(impl iCoreWebView2WebMessageReceivedEventHandlerImpl) *iCoreWebView2WebMessageReceivedEventHandler {
- return &iCoreWebView2WebMessageReceivedEventHandler{
- vtbl: &iCoreWebView2WebMessageReceivedEventHandlerFn,
- impl: impl,
- }
-}
-
-// ICoreWebView2PermissionRequestedEventHandler
-
-type iCoreWebView2PermissionRequestedEventHandlerImpl interface {
- _IUnknownImpl
- PermissionRequested(sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr
-}
-
-type iCoreWebView2PermissionRequestedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2PermissionRequestedEventHandler struct {
- vtbl *iCoreWebView2PermissionRequestedEventHandlerVtbl
- impl iCoreWebView2PermissionRequestedEventHandlerImpl
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2PermissionRequestedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerInvoke(this *iCoreWebView2PermissionRequestedEventHandler, sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
- return this.impl.PermissionRequested(sender, args)
-}
-
-var iCoreWebView2PermissionRequestedEventHandlerFn = iCoreWebView2PermissionRequestedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerInvoke),
-}
-
-func newICoreWebView2PermissionRequestedEventHandler(impl iCoreWebView2PermissionRequestedEventHandlerImpl) *iCoreWebView2PermissionRequestedEventHandler {
- return &iCoreWebView2PermissionRequestedEventHandler{
- vtbl: &iCoreWebView2PermissionRequestedEventHandlerFn,
- impl: impl,
- }
-}
-
-func (i *ICoreWebView2) AddWebResourceRequestedFilter(uri string, resourceContext COREWEBVIEW2_WEB_RESOURCE_CONTEXT) error {
- var err error
- // Convert string 'uri' to *uint16
- _uri, err := windows.UTF16PtrFromString(uri)
- if err != nil {
- return err
- }
- _, _, err = i.vtbl.AddWebResourceRequestedFilter.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_uri)),
- uintptr(resourceContext),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error {
- var err error
- _, _, err = i.vtbl.AddNavigationCompleted.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(eventHandler)),
- uintptr(unsafe.Pointer(&token)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2) OpenDevToolsWindow() error {
- var err error
- _, _, err = i.vtbl.OpenDevToolsWindow.Call(
- uintptr(unsafe.Pointer(i)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go
deleted file mode 100644
index a3b7374ca..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go
+++ /dev/null
@@ -1,29 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package edge
-
-import (
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
-)
-
-func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
- e := &environmentCreatedHandler{environmentCompletedHandle}
- return webviewloader.CreateCoreWebView2EnvironmentWithOptions(
- e,
- webviewloader.WithBrowserExecutableFolder(browserExecutableFolder),
- webviewloader.WithUserDataFolder(userDataFolder),
- webviewloader.WithAdditionalBrowserArguments(additionalBrowserArgs),
- )
-}
-
-type environmentCreatedHandler struct {
- originalHandler *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode webviewloader.HRESULT, createdEnvironment *webviewloader.ICoreWebView2Environment) webviewloader.HRESULT {
- env := (*ICoreWebView2Environment)(unsafe.Pointer(createdEnvironment))
- res := r.originalHandler.impl.EnvironmentCompleted(uintptr(errorCode), env)
- return webviewloader.HRESULT(res)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go
deleted file mode 100644
index 9b4f02bfd..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//go:build windows && native_webview2loader
-
-package edge
-
-import (
- "fmt"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
-
- "golang.org/x/sys/windows"
-)
-
-func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
- browserPathPtr, err := windows.UTF16PtrFromString(browserExecutableFolder)
- if err != nil {
- return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", browserExecutableFolder, err)
- }
-
- userPathPtr, err := windows.UTF16PtrFromString(userDataFolder)
- if err != nil {
- return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", userDataFolder, err)
- }
-
- hr, err := webviewloader.CreateCoreWebView2EnvironmentWithOptions(
- browserPathPtr,
- userPathPtr,
- uintptr(unsafe.Pointer(environmentCompletedHandle)),
- additionalBrowserArgs,
- )
-
- if hr != 0 {
- if err == nil || err == windows.ERROR_SUCCESS {
- err = syscall.Errno(hr)
- }
- return err
- }
-
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go
deleted file mode 100644
index 007e60586..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go
+++ /dev/null
@@ -1,225 +0,0 @@
-//go:build windows
-
-package edge
-
-// This code has been adapted from: https://github.com/go-ole/go-ole
-
-/*
-
-The MIT License (MIT)
-
-Copyright © 2013-2017 Yasuhiro Matsumoto,
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the “Software”), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-
-const hextable = "0123456789ABCDEF"
-const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
-
-// GUID is Windows API specific GUID type.
-//
-// This exists to match Windows GUID type for direct passing for COM.
-// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
-type GUID struct {
- Data1 uint32
- Data2 uint16
- Data3 uint16
- Data4 [8]byte
-}
-
-// NewGUID converts the given string into a globally unique identifier that is
-// compliant with the Windows API.
-//
-// The supplied string may be in any of these formats:
-//
-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
-// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
-//
-// The conversion of the supplied string is not case-sensitive.
-func NewGUID(guid string) *GUID {
- d := []byte(guid)
- var d1, d2, d3, d4a, d4b []byte
-
- switch len(d) {
- case 38:
- if d[0] != '{' || d[37] != '}' {
- return nil
- }
- d = d[1:37]
- fallthrough
- case 36:
- if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
- return nil
- }
- d1 = d[0:8]
- d2 = d[9:13]
- d3 = d[14:18]
- d4a = d[19:23]
- d4b = d[24:36]
- case 32:
- d1 = d[0:8]
- d2 = d[8:12]
- d3 = d[12:16]
- d4a = d[16:20]
- d4b = d[20:32]
- default:
- return nil
- }
-
- var g GUID
- var ok1, ok2, ok3, ok4 bool
- g.Data1, ok1 = decodeHexUint32(d1)
- g.Data2, ok2 = decodeHexUint16(d2)
- g.Data3, ok3 = decodeHexUint16(d3)
- g.Data4, ok4 = decodeHexByte64(d4a, d4b)
- if ok1 && ok2 && ok3 && ok4 {
- return &g
- }
- return nil
-}
-
-func decodeHexUint32(src []byte) (value uint32, ok bool) {
- var b1, b2, b3, b4 byte
- var ok1, ok2, ok3, ok4 bool
- b1, ok1 = decodeHexByte(src[0], src[1])
- b2, ok2 = decodeHexByte(src[2], src[3])
- b3, ok3 = decodeHexByte(src[4], src[5])
- b4, ok4 = decodeHexByte(src[6], src[7])
- value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
- ok = ok1 && ok2 && ok3 && ok4
- return
-}
-
-func decodeHexUint16(src []byte) (value uint16, ok bool) {
- var b1, b2 byte
- var ok1, ok2 bool
- b1, ok1 = decodeHexByte(src[0], src[1])
- b2, ok2 = decodeHexByte(src[2], src[3])
- value = (uint16(b1) << 8) | uint16(b2)
- ok = ok1 && ok2
- return
-}
-
-func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
- var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
- value[0], ok1 = decodeHexByte(s1[0], s1[1])
- value[1], ok2 = decodeHexByte(s1[2], s1[3])
- value[2], ok3 = decodeHexByte(s2[0], s2[1])
- value[3], ok4 = decodeHexByte(s2[2], s2[3])
- value[4], ok5 = decodeHexByte(s2[4], s2[5])
- value[5], ok6 = decodeHexByte(s2[6], s2[7])
- value[6], ok7 = decodeHexByte(s2[8], s2[9])
- value[7], ok8 = decodeHexByte(s2[10], s2[11])
- ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
- return
-}
-
-func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
- var n1, n2 byte
- var ok1, ok2 bool
- n1, ok1 = decodeHexChar(c1)
- n2, ok2 = decodeHexChar(c2)
- value = (n1 << 4) | n2
- ok = ok1 && ok2
- return
-}
-
-func decodeHexChar(c byte) (byte, bool) {
- switch {
- case '0' <= c && c <= '9':
- return c - '0', true
- case 'a' <= c && c <= 'f':
- return c - 'a' + 10, true
- case 'A' <= c && c <= 'F':
- return c - 'A' + 10, true
- }
-
- return 0, false
-}
-
-// String converts the GUID to string form. It will adhere to this pattern:
-//
-// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
-//
-// If the GUID is nil, the string representation of an empty GUID is returned:
-//
-// {00000000-0000-0000-0000-000000000000}
-func (guid *GUID) String() string {
- if guid == nil {
- return emptyGUID
- }
-
- var c [38]byte
- c[0] = '{'
- putUint32Hex(c[1:9], guid.Data1)
- c[9] = '-'
- putUint16Hex(c[10:14], guid.Data2)
- c[14] = '-'
- putUint16Hex(c[15:19], guid.Data3)
- c[19] = '-'
- putByteHex(c[20:24], guid.Data4[0:2])
- c[24] = '-'
- putByteHex(c[25:37], guid.Data4[2:8])
- c[37] = '}'
- return string(c[:])
-}
-
-func putUint32Hex(b []byte, v uint32) {
- b[0] = hextable[byte(v>>24)>>4]
- b[1] = hextable[byte(v>>24)&0x0f]
- b[2] = hextable[byte(v>>16)>>4]
- b[3] = hextable[byte(v>>16)&0x0f]
- b[4] = hextable[byte(v>>8)>>4]
- b[5] = hextable[byte(v>>8)&0x0f]
- b[6] = hextable[byte(v)>>4]
- b[7] = hextable[byte(v)&0x0f]
-}
-
-func putUint16Hex(b []byte, v uint16) {
- b[0] = hextable[byte(v>>8)>>4]
- b[1] = hextable[byte(v>>8)&0x0f]
- b[2] = hextable[byte(v)>>4]
- b[3] = hextable[byte(v)&0x0f]
-}
-
-func putByteHex(dst, src []byte) {
- for i := 0; i < len(src); i++ {
- dst[i*2] = hextable[src[i]>>4]
- dst[i*2+1] = hextable[src[i]&0x0f]
- }
-}
-
-// IsEqualGUID compares two GUID.
-//
-// Not constant time comparison.
-func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
- return guid1.Data1 == guid2.Data1 &&
- guid1.Data2 == guid2.Data2 &&
- guid1.Data3 == guid2.Data3 &&
- guid1.Data4[0] == guid2.Data4[0] &&
- guid1.Data4[1] == guid2.Data4[1] &&
- guid1.Data4[2] == guid2.Data4[2] &&
- guid1.Data4[3] == guid2.Data4[3] &&
- guid1.Data4[4] == guid2.Data4[4] &&
- guid1.Data4[5] == guid2.Data4[5] &&
- guid1.Data4[6] == guid2.Data4[6] &&
- guid1.Data4[7] == guid2.Data4[7]
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE
deleted file mode 100644
index af1894c87..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-ISC License (ISC)
-
-Copyright (c) 2020 John Chadwick
-Copyright (c) 2022 Wails Project Developers
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md
deleted file mode 100644
index f3e020ec4..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Webviewloader
-
-Webviewloader is a port of [OpenWebView2Loader](https://github.com/jchv/OpenWebView2Loader) to Go.
-
-It is intended to be feature-complete with the original WebView2Loader distributed with
-the WebView2 NuGet package, but some features are intentionally not implemented.
-
-## Status
-
-- [x] CompareBrowserVersions
-- [x] CreateCoreWebView2Environment
-- [x] CreateCoreWebView2EnvironmentWithOptions
-- [x] GetAvailableCoreWebView2BrowserVersionString
-
-## Not implemented features
-
-- Registry Overrides of Parameters
-- Env Variable Overrides of Parameters
-- Does not incorporate `GetCurrentPackageInfo` to search for an installed runtime
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll
deleted file mode 100644
index cd1c694b8..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go
deleted file mode 100644
index 1c586d2c6..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go
+++ /dev/null
@@ -1,159 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "fmt"
- "path/filepath"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
- "golang.org/x/sys/windows"
-)
-
-func init() {
- fmt.Println("DEB | Using go webview2loader")
-}
-
-type webView2RunTimeType int32
-
-const (
- webView2RunTimeTypeInstalled webView2RunTimeType = 0x00
- webView2RunTimeTypeRedistributable webView2RunTimeType = 0x01
-)
-
-// CreateCoreWebView2Environment creates an evergreen WebView2 Environment using the installed WebView2 Runtime version.
-//
-// This is equivalent to running CreateCoreWebView2EnvironmentWithOptions without any options.
-// For more information, see CreateCoreWebView2EnvironmentWithOptions.
-func CreateCoreWebView2Environment(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
- return CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler)
-}
-
-// CreateCoreWebView2EnvironmentWithOptions creates an environment with a custom version of WebView2 Runtime,
-// user data folder, and with or without additional options.
-//
-// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?#createcorewebview2environmentwithoptions
-func CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, opts ...option) error {
- var params environmentOptions
- for _, opt := range opts {
- opt(¶ms)
- }
-
- var err error
- var dllPath string
- var runtimeType webView2RunTimeType
- if browserExecutableFolder := params.browserExecutableFolder; browserExecutableFolder != "" {
- runtimeType = webView2RunTimeTypeRedistributable
- dllPath, err = findEmbeddedClientDll(browserExecutableFolder)
- } else {
- runtimeType = webView2RunTimeTypeInstalled
- dllPath, _, err = findInstalledClientDll(params.preferCanary)
- }
-
- if err != nil {
- return err
- }
-
- return createWebViewEnvironmentWithClientDll(dllPath, runtimeType, params.userDataFolder,
- ¶ms, environmentCompletedHandler)
-}
-
-func createWebViewEnvironmentWithClientDll(lpLibFileName string, runtimeType webView2RunTimeType, userDataFolder string,
- envOptions *environmentOptions, envCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
-
- if !filepath.IsAbs(lpLibFileName) {
- return fmt.Errorf("lpLibFileName must be absolute")
- }
-
- dll, err := windows.LoadDLL(lpLibFileName)
- if err != nil {
- return fmt.Errorf("Loading DLL failed: %w", err)
- }
-
- defer func() {
- canUnloadProc, err := dll.FindProc("DllCanUnloadNow")
- if err != nil {
- return
- }
-
- if r1, _, _ := canUnloadProc.Call(); r1 != windows.NO_ERROR {
- return
- }
-
- dll.Release()
- }()
-
- createProc, err := dll.FindProc("CreateWebViewEnvironmentWithOptionsInternal")
- if err != nil {
- return fmt.Errorf("Unable to find CreateWebViewEnvironmentWithOptionsInternal entrypoint: %w", err)
- }
-
- userDataPtr, err := windows.UTF16PtrFromString(userDataFolder)
- if err != nil {
- return err
- }
-
- envOptionsCom := combridge.New2[iCoreWebView2EnvironmentOptions, iCoreWebView2EnvironmentOptions2](
- envOptions, envOptions)
-
- defer envOptionsCom.Close()
-
- envCompletedHandler = &environmentCreatedHandler{envCompletedHandler}
- envCompletedCom := combridge.New[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](envCompletedHandler)
- defer envCompletedCom.Close()
-
- const unknown = 1
- hr, _, err := createProc.Call(
- uintptr(unknown),
- uintptr(runtimeType),
- uintptr(unsafe.Pointer(userDataPtr)),
- uintptr(envOptionsCom.Ref()),
- uintptr(envCompletedCom.Ref()))
-
- if hr != 0 {
- if err == nil || err == windows.ERROR_SUCCESS {
- err = syscall.Errno(hr)
- }
- return err
- }
-
- return nil
-}
-
-type environmentCreatedHandler struct {
- originalHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT {
- // The OpenWebview2Loader has some retry logic and retries once, didn't encounter any case when this would have been
- // needed during the development: https://github.com/jchv/OpenWebView2Loader/blob/master/Source/WebView2Loader.cpp#L202
-
- if createdEnvironment != nil {
- // May or may not be necessary, but the official WebView2Loader seems to do it.
- iidICoreWebView2Environment := windows.GUID{
- Data1: 0xb96d755e,
- Data2: 0x0319,
- Data3: 0x4e92,
- Data4: [8]byte{0xa2, 0x96, 0x23, 0x43, 0x6f, 0x46, 0xa1, 0xfc},
- }
-
- if err := createdEnvironment.QueryInterface(&iidICoreWebView2Environment, &createdEnvironment); err != nil {
- createdEnvironment = nil
- errNo, ok := err.(syscall.Errno)
- if !ok {
- errNo = syscall.Errno(windows.E_FAIL)
- }
- errorCode = HRESULT(errNo)
- }
- }
-
- r.originalHandler.EnvironmentCompleted(errorCode, createdEnvironment)
-
- if createdEnvironment != nil {
- createdEnvironment.Release()
- }
-
- return HRESULT(windows.S_OK)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go
deleted file mode 100644
index 223c77e85..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go
+++ /dev/null
@@ -1,42 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
-)
-
-// HRESULT
-//
-// See https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
-type HRESULT int32
-
-// ICoreWebView2Environment Represents the WebView2 Environment
-//
-// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment
-type ICoreWebView2Environment = combridge.IUnknownImpl
-
-// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler receives the WebView2Environment created using CreateCoreWebView2Environment.
-type ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
- // EnvironmentCompleted is invoked to receive the created WebView2Environment
- //
- // See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2createcorewebview2environmentcompletedhandler?#invoke
- EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
- combridge.IUnknown
- ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func init() {
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](
- "{4e8a3389-c9d8-4bd2-b6b5-124fee6cc14d}",
- _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke,
- )
-}
-
-func _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this uintptr, errorCode HRESULT, env *combridge.IUnknownImpl) uintptr {
- res := combridge.Resolve[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](this).EnvironmentCompleted(errorCode, env)
- return uintptr(res)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go
deleted file mode 100644
index 4bae6064a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go
+++ /dev/null
@@ -1,276 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "unicode/utf16"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
- "golang.org/x/sys/windows"
-)
-
-// WithBrowserExecutableFolder to specify whether WebView2 controls use a fixed or installed version
-// of the WebView2 Runtime that exists on a user machine.
-//
-// To use a fixed version of the WebView2 Runtime,
-// pass the folder path that contains the fixed version of the WebView2 Runtime.
-// BrowserExecutableFolder supports both relative (to the application's executable) and absolute files paths.
-// To create WebView2 controls that use the installed version of the WebView2 Runtime that exists on user
-// machines, pass a empty string to WithBrowserExecutableFolder. In this scenario, the API tries to find a
-// compatible version of the WebView2 Runtime that is installed on the user machine (first at the machine level,
-// and then per user) using the selected channel preference. The path of fixed version of the WebView2 Runtime
-// should not contain \Edge\Application\. When such a path is used, the API fails with HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
-func WithBrowserExecutableFolder(folder string) option {
- return func(wvep *environmentOptions) {
- wvep.browserExecutableFolder = folder
- }
-}
-
-// WithUserDataFolder specifies to user data folder location for WebView2
-//
-// You may specify the userDataFolder to change the default user data folder location for WebView2.
-// The path is either an absolute file path or a relative file path that is interpreted as relative
-// to the compiled code for the current process.
-// Dhe default user data ({Executable File Name}.WebView2) folder is created in the same directory
-// next to the compiled code for the app. WebView2 creation fails if the compiled code is running
-// in a directory in which the process does not have permission to create a new directory.
-// The app is responsible to clean up the associated user data folder when it is done.
-func WithUserDataFolder(folder string) option {
- return func(wvep *environmentOptions) {
- wvep.userDataFolder = folder
- }
-}
-
-// WithAdditionalBrowserArguments changes the behavior of the WebView.
-//
-// The arguments are passed to the
-// browser process as part of the command. For more information about
-// using command-line switches with Chromium browser processes, navigate to
-// [Run Chromium with Flags][ChromiumDevelopersHowTosRunWithFlags].
-// The value appended to a switch is appended to the browser process, for
-// example, in `--edge-webview-switches=xxx` the value is `xxx`. If you
-// specify a switch that is important to WebView functionality, it is
-// ignored, for example, `--user-data-dir`. Specific features are disabled
-// internally and blocked from being enabled. If a switch is specified
-// multiple times, only the last instance is used.
-//
-// \> [!NOTE]\n\> A merge of the different values of the same switch is not attempted,
-// except for disabled and enabled features. The features specified by
-// `--enable-features` and `--disable-features` are merged with simple
-// logic.\n\> * The features is the union of the specified features
-// and built-in features. If a feature is disabled, it is removed from the
-// enabled features list.
-//
-// If you specify command-line switches and use the
-// `additionalBrowserArguments` parameter, the `--edge-webview-switches`
-// value takes precedence and is processed last. If a switch fails to
-// parse, the switch is ignored. The default state for the operation is
-// to run the browser process with no extra flags.
-//
-// [ChromiumDevelopersHowTosRunWithFlags]: https://www.chromium.org/developers/how-tos/run-chromium-with-flags "Run Chromium with flags | The Chromium Projects"
-func WithAdditionalBrowserArguments(args string) option {
- return func(wvep *environmentOptions) {
- wvep.additionalBrowserArguments = args
- }
-}
-
-// WithLanguage sets the default display language for WebView.
-//
-// It applies to browser UI such as
-// context menu and dialogs. It also applies to the `accept-languages` HTTP
-// header that WebView sends to websites. It is in the format of
-//
-// `language[-country]` where `language` is the 2-letter code from
-// [ISO 639][ISO639LanguageCodesHtml]
-// and `country` is the
-// 2-letter code from
-// [ISO 3166][ISOStandard72482Html].
-//
-// [ISO639LanguageCodesHtml]: https://www.iso.org/iso-639-language-codes.html "ISO 639 | ISO"
-// [ISOStandard72482Html]: https://www.iso.org/standard/72482.html "ISO 3166-1:2020 | ISO"
-func WithLanguage(lang string) option {
- return func(wvep *environmentOptions) {
- wvep.language = lang
- }
-}
-
-// WithTargetCompatibleBrowserVersion secifies the version of the WebView2 Runtime binaries required to be
-// compatible with your app.
-//
-// This defaults to the WebView2 Runtime version
-// that corresponds with the version of the SDK the app is using. The
-// format of this value is the same as the format of the
-// `BrowserVersionString` property and other `BrowserVersion` values. Only
-// the version part of the `BrowserVersion` value is respected. The channel
-// suffix, if it exists, is ignored. The version of the WebView2 Runtime
-// binaries actually used may be different from the specified
-// `TargetCompatibleBrowserVersion`. The binaries are only guaranteed to be
-// compatible. Verify the actual version on the `BrowserVersionString`
-// property on the `ICoreWebView2Environment`.
-func WithTargetCompatibleBrowserVersion(version string) option {
- return func(wvep *environmentOptions) {
- wvep.targetCompatibleBrowserVersion = version
- }
-}
-
-// WithAllowSingleSignOnUsingOSPrimaryAccount is used to enable
-// single sign on with Azure Active Directory (AAD) and personal Microsoft
-// Account (MSA) resources inside WebView. All AAD accounts, connected to
-// Windows and shared for all apps, are supported. For MSA, SSO is only enabled
-// for the account associated for Windows account login, if any.
-// Default is disabled. Universal Windows Platform apps must also declare
-// `enterpriseCloudSSO`
-// [Restricted capabilities][WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]
-// for the single sign on (SSO) to work.
-//
-// [WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]: /windows/uwp/packaging/app-capability-declarations\#restricted-capabilities "Restricted capabilities - App capability declarations | Microsoft Docs"
-func WithAllowSingleSignOnUsingOSPrimaryAccount(allow bool) option {
- return func(wvep *environmentOptions) {
- wvep.allowSingleSignOnUsingOSPrimaryAccount = allow
- }
-}
-
-// WithExclusiveUserDataFolderAccess specifies that the WebView environment
-// obtains exclusive access to the user data folder.
-//
-// If the user data folder is already being used by another WebView environment with a
-// different value for `ExclusiveUserDataFolderAccess` property, the creation of a WebView2Controller
-// using the environment object will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
-// When set as TRUE, no other WebView can be created from other processes using WebView2Environment
-// objects with the same UserDataFolder. This prevents other processes from creating WebViews
-// which share the same browser process instance, since sharing is performed among
-// WebViews that have the same UserDataFolder. When another process tries to create a
-// WebView2Controller from an WebView2Environment object created with the same user data folder,
-// it will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
-func WithExclusiveUserDataFolderAccess(exclusive bool) option {
- return func(wvep *environmentOptions) {
- wvep.exclusiveUserDataFolderAccess = exclusive
- }
-}
-
-type option func(*environmentOptions)
-
-var _ iCoreWebView2EnvironmentOptions = &environmentOptions{}
-var _ iCoreWebView2EnvironmentOptions2 = &environmentOptions{}
-
-type environmentOptions struct {
- browserExecutableFolder string
- userDataFolder string
- preferCanary bool
-
- additionalBrowserArguments string
- language string
- targetCompatibleBrowserVersion string
- allowSingleSignOnUsingOSPrimaryAccount bool
- exclusiveUserDataFolderAccess bool
-}
-
-func (o *environmentOptions) AdditionalBrowserArguments() string {
- return o.additionalBrowserArguments
-}
-
-func (o *environmentOptions) Language() string {
- return o.language
-}
-
-func (o *environmentOptions) TargetCompatibleBrowserVersion() string {
- v := o.targetCompatibleBrowserVersion
- if v == "" {
- v = kMinimumCompatibleVersion
- }
- return v
-}
-
-func (o *environmentOptions) AllowSingleSignOnUsingOSPrimaryAccount() bool {
- return o.allowSingleSignOnUsingOSPrimaryAccount
-}
-
-func (o *environmentOptions) ExclusiveUserDataFolderAccess() bool {
- return o.exclusiveUserDataFolderAccess
-}
-
-type iCoreWebView2EnvironmentOptions interface {
- combridge.IUnknown
-
- AdditionalBrowserArguments() string
- Language() string
- TargetCompatibleBrowserVersion() string
- AllowSingleSignOnUsingOSPrimaryAccount() bool
-}
-
-type iCoreWebView2EnvironmentOptions2 interface {
- combridge.IUnknown
-
- ExclusiveUserDataFolderAccess() bool
-}
-
-func init() {
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions](
- "{2fde08a8-1e9a-4766-8c05-95a9ceb9d1c5}",
- _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentOptionsLanguage,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount,
- _iCoreWebView2EnvironmentOptionsNOP,
- )
-
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions2](
- "{ff85c98a-1ba7-4a6b-90c8-2b752c89e9e2}",
- _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess,
- _iCoreWebView2EnvironmentOptionsNOP,
- )
-}
-func _iCoreWebView2EnvironmentOptionsNOP(this uintptr) uintptr {
- return uintptr(windows.S_FALSE)
-}
-
-func _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments(this uintptr, value **uint16) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AdditionalBrowserArguments()
- *value = stringToOleString(v)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptionsLanguage(this uintptr, value **uint16) uintptr {
- args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).Language()
- *value = stringToOleString(args)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion(this uintptr, value **uint16) uintptr {
- args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).TargetCompatibleBrowserVersion()
- *value = stringToOleString(args)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount(this uintptr, value *int32) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AllowSingleSignOnUsingOSPrimaryAccount()
- *value = boolToInt(v)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess(this uintptr, value *int32) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions2](this).ExclusiveUserDataFolderAccess()
- *value = boolToInt(v)
- return uintptr(windows.S_OK)
-}
-
-func stringToOleString(v string) *uint16 {
- wstr := utf16.Encode([]rune(v + "\x00"))
- lwstr := len(wstr)
- ptr := (*uint16)(coTaskMemAlloc(2 * lwstr))
-
- copy(unsafe.Slice(ptr, lwstr), wstr)
-
- return ptr
-}
-
-func boolToInt(v bool) int32 {
- if v {
- return 1
- }
- return 0
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go
deleted file mode 100644
index da9472ff1..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go
+++ /dev/null
@@ -1,74 +0,0 @@
-//go:build windows
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "os"
- "path/filepath"
- "runtime"
-
- "golang.org/x/sys/windows/registry"
-)
-
-var (
- errNoClientDLLFound = errors.New("no webview2 found")
-)
-
-func findEmbeddedBrowserVersion(filename string) (string, error) {
- block, err := getFileVersionInfo(filename)
- if err != nil {
- return "", err
- }
-
- info, err := verQueryValueString(block, "\\StringFileInfo\\040904B0\\ProductVersion")
- if err != nil {
- return "", err
- }
-
- return info, nil
-}
-
-func findEmbeddedClientDll(embeddedEdgeSubFolder string) (outClientPath string, err error) {
- if !filepath.IsAbs(embeddedEdgeSubFolder) {
- exe, err := os.Executable()
- if err != nil {
- return "", err
- }
-
- embeddedEdgeSubFolder = filepath.Join(filepath.Dir(exe), embeddedEdgeSubFolder)
- }
-
- return findClientDllInFolder(embeddedEdgeSubFolder)
-}
-
-func findClientDllInFolder(folder string) (string, error) {
- arch := ""
- switch runtime.GOARCH {
- case "arm64":
- arch = "arm64"
- case "amd64":
- arch = "x64"
- case "386":
- arch = "x86"
- default:
- return "", fmt.Errorf("Unsupported architecture")
- }
-
- dllPath := filepath.Join(folder, "EBWebView", arch, "EmbeddedBrowserWebView.dll")
- if _, err := os.Stat(dllPath); err != nil {
- return "", mapFindErr(err)
- }
- return dllPath, nil
-}
-
-func mapFindErr(err error) error {
- if errors.Is(err, registry.ErrNotExist) {
- return errNoClientDLLFound
- }
- if errors.Is(err, os.ErrNotExist) {
- return errNoClientDLLFound
- }
- return err
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go
deleted file mode 100644
index 7ee171b2a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go
+++ /dev/null
@@ -1,94 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "path/filepath"
-
- "golang.org/x/sys/windows/registry"
-)
-
-const (
- kNumChannels = 4
- kInstallKeyPath = "Software\\Microsoft\\EdgeUpdate\\ClientState\\"
- kMinimumCompatibleVersion = "86.0.616.0"
-)
-
-var (
- kChannelName = [kNumChannels]string{
- "", "beta", "dev", "canary", // "internal"
- }
-
- kChannelUuid = [kNumChannels]string{
- "{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}",
- "{2CD8A007-E189-409D-A2C8-9AF4EF3C72AA}",
- "{0D50BFEC-CD6A-4F9A-964C-C7416E3ACB10}",
- "{65C35B14-6C1D-4122-AC46-7148CC9D6497}",
- //"{BE59E8FD-089A-411B-A3B0-051D9E417818}",
- }
-
- minimumCompatibleVersion, _ = parseVersion(kMinimumCompatibleVersion)
-)
-
-func findInstalledClientDll(preferCanary bool) (clientPath string, version *version, err error) {
- for i := 0; i < kNumChannels; i++ {
- channel := i
- if preferCanary {
- channel = (kNumChannels - 1) - i
- }
-
- key := kInstallKeyPath + kChannelUuid[channel]
- for _, checkSystem := range []bool{true, false} {
- clientPath, version, err := findInstalledClientDllForChannel(key, checkSystem)
- if err == errNoClientDLLFound {
- continue
- }
- if err != nil {
- return "", nil, err
- }
-
- version.channel = kChannelName[channel]
- return clientPath, version, nil
- }
- }
- return "", nil, errNoClientDLLFound
-}
-
-func findInstalledClientDllForChannel(subKey string, system bool) (clientPath string, clientVersion *version, err error) {
- key := registry.LOCAL_MACHINE
- if !system {
- key = registry.CURRENT_USER
- }
-
- regKey, err := registry.OpenKey(key, subKey, registry.READ|registry.WOW64_32KEY)
- if err != nil {
- return "", nil, mapFindErr(err)
- }
- defer regKey.Close()
-
- embeddedEdgeSubFolder, _, err := regKey.GetStringValue("EBWebView")
- if err != nil {
- return "", nil, mapFindErr(err)
- }
-
- if embeddedEdgeSubFolder == "" {
- return "", nil, errNoClientDLLFound
- }
-
- versionString := filepath.Base(embeddedEdgeSubFolder)
- version, err := parseVersion(versionString)
- if err != nil {
- return "", nil, errNoClientDLLFound
- }
-
- if version.compare(minimumCompatibleVersion) < 0 {
- return "", nil, errNoClientDLLFound
- }
-
- dllPath, err := findEmbeddedClientDll(embeddedEdgeSubFolder)
- if err != nil {
- return "", nil, mapFindErr(err)
- }
-
- return dllPath, &version, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go
deleted file mode 100644
index 3e02fe985..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go
+++ /dev/null
@@ -1,173 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "os"
- "sync"
- "unsafe"
-
- "github.com/jchv/go-winloader"
-
- "golang.org/x/sys/windows"
-)
-
-func init() {
- preventEnvAndRegistryOverrides(nil, nil, "")
-}
-
-var (
- memOnce sync.Once
- memModule winloader.Module
- memCreate winloader.Proc
- memCompareBrowserVersions winloader.Proc
- memGetAvailableCoreWebView2BrowserVersionString winloader.Proc
- memErr error
-)
-
-const (
- // https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20
- E_FILENOTFOUND = 0x80070002
-)
-
-// CompareBrowserVersions will compare the 2 given versions and return:
-//
-// Less than zero: v1 < v2
-// zero: v1 == v2
-// Greater than zero: v1 > v2
-func CompareBrowserVersions(v1 string, v2 string) (int, error) {
- _v1, err := windows.UTF16PtrFromString(v1)
- if err != nil {
- return 0, err
- }
- _v2, err := windows.UTF16PtrFromString(v2)
- if err != nil {
- return 0, err
- }
-
- err = loadFromMemory()
- if err != nil {
- return 0, err
- }
-
- var result int32
- _, _, err = memCompareBrowserVersions.Call(
- uint64(uintptr(unsafe.Pointer(_v1))),
- uint64(uintptr(unsafe.Pointer(_v2))),
- uint64(uintptr(unsafe.Pointer(&result))))
-
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return int(result), nil
-}
-
-// GetAvailableCoreWebView2BrowserVersionString returns version of the webview2 runtime.
-// If path is empty, it will try to find installed webview2 is the system.
-// If there is no version installed, a blank string is returned.
-func GetAvailableCoreWebView2BrowserVersionString(path string) (string, error) {
- if path != "" {
- // The default implementation fails if CGO and a fixed browser path is used. It's caused by the go-winloader
- // which loads the native DLL from memory.
- // Use the new GoWebView2Loader in this case, in the future we will make GoWebView2Loader
- // feature-complete and remove the use of the native DLL and go-winloader.
- version, err := goGetAvailableCoreWebView2BrowserVersionString(path)
- if errors.Is(err, errNoClientDLLFound) {
- // WebView2 is not found
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return version, nil
- }
-
- err := loadFromMemory()
- if err != nil {
- return "", err
- }
-
- var browserPath *uint16 = nil
- if path != "" {
- browserPath, err = windows.UTF16PtrFromString(path)
- if err != nil {
- return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err)
- }
- }
-
- preventEnvAndRegistryOverrides(browserPath, nil, "")
- var result *uint16
- res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
- uint64(uintptr(unsafe.Pointer(browserPath))),
- uint64(uintptr(unsafe.Pointer(&result))))
-
- if res != 0 {
- if res == E_FILENOTFOUND {
- // WebView2 is not installed
- return "", nil
- }
-
- return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err)
- }
-
- version := windows.UTF16PtrToString(result)
- windows.CoTaskMemFree(unsafe.Pointer(result))
- return version, nil
-}
-
-// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and
-// call the CreateCoreWebView2EnvironmentWithOptions routine.
-func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentCompletedHandle uintptr, additionalBrowserArgs string) (uintptr, error) {
- err := loadFromMemory()
- if err != nil {
- return 0, err
- }
-
- preventEnvAndRegistryOverrides(browserExecutableFolder, userDataFolder, additionalBrowserArgs)
- res, _, _ := memCreate.Call(
- uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
- uint64(uintptr(unsafe.Pointer(userDataFolder))),
- 0,
- uint64(environmentCompletedHandle),
- )
- return uintptr(res), nil
-}
-
-func loadFromMemory() error {
- var err error
- // DLL is not available natively. Try loading embedded copy.
- memOnce.Do(func() {
- memModule, memErr = winloader.LoadFromMemory(WebView2Loader)
- if memErr != nil {
- err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr)
- return
- }
- memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions")
- memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions")
- memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString")
- })
- return err
-}
-
-func preventEnvAndRegistryOverrides(browserFolder, userDataFolder *uint16, additionalBrowserArgs string) {
- // Setting these env variables to empty string also prevents registry overrides because webview2loader
- // checks for existence and not for empty value
- os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
-
- // Set these overrides to the values or empty to prevent registry and external env overrides
- os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", additionalBrowserArgs)
- os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
- os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", windows.UTF16PtrToString(browserFolder))
- os.Setenv("WEBVIEW2_USER_DATA_FOLDER", windows.UTF16PtrToString(userDataFolder))
-}
-
-func goGetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
- clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
- if err != nil {
- return "", err
- }
-
- return findEmbeddedBrowserVersion(clientPath)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go
deleted file mode 100644
index e4ff44ff3..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed x86/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go
deleted file mode 100644
index 27423ae8a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed x64/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go
deleted file mode 100644
index bba6a88cb..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed arm64/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go
deleted file mode 100644
index 24d0856a5..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go
+++ /dev/null
@@ -1,143 +0,0 @@
-//go:build windows
-
-package webviewloader
-
-import (
- "fmt"
- "syscall"
- "unicode/utf16"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
- procGlobalFree = modkernel32.NewProc("GlobalFree")
-
- modversion = windows.NewLazySystemDLL("version.dll")
- procGetFileVersionInfoSize = modversion.NewProc("GetFileVersionInfoSizeW")
- procGetFileVersionInfo = modversion.NewProc("GetFileVersionInfoW")
- procVerQueryValue = modversion.NewProc("VerQueryValueW")
-
- modole32 = windows.NewLazySystemDLL("ole32.dll")
- procCoTaskMemAlloc = modole32.NewProc("CoTaskMemAlloc")
-)
-
-func getFileVersionInfo(path string) ([]byte, error) {
- lptstrFilename, err := syscall.UTF16PtrFromString(path)
- if err != nil {
- return nil, err
- }
-
- size, _, err := procGetFileVersionInfoSize.Call(
- uintptr(unsafe.Pointer(lptstrFilename)),
- 0,
- )
-
- err = maskErrorSuccess(err)
- if size == 0 && err == nil {
- err = fmt.Errorf("GetFileVersionInfoSize failed")
- }
-
- if err != nil {
- return nil, err
- }
-
- data := make([]byte, size)
- ret, _, err := procGetFileVersionInfo.Call(
- uintptr(unsafe.Pointer(lptstrFilename)),
- 0,
- uintptr(size),
- uintptr(unsafe.Pointer(&data[0])),
- )
-
- err = maskErrorSuccess(err)
- if ret == 0 && err == nil {
- err = fmt.Errorf("GetFileVersionInfo failed")
- }
-
- if err != nil {
- return nil, err
- }
- return data, nil
-}
-
-func verQueryValueString(block []byte, subBlock string) (string, error) {
- // Allocate memory from native side to make sure the block doesn't get moved
- // because we get a pointer into that memory block from the native verQueryValue
- // call back.
- pBlock := globalAlloc(0, uint32(len(block)))
- defer globalFree(unsafe.Pointer(pBlock))
-
- // Copy the memory region into native side memory
- copy(unsafe.Slice((*byte)(pBlock), len(block)), block)
-
- lpSubBlock, err := syscall.UTF16PtrFromString(subBlock)
- if err != nil {
- return "", err
- }
-
- var lplpBuffer unsafe.Pointer
- var puLen uint
- ret, _, err := procVerQueryValue.Call(
- uintptr(pBlock),
- uintptr(unsafe.Pointer(lpSubBlock)),
- uintptr(unsafe.Pointer(&lplpBuffer)),
- uintptr(unsafe.Pointer(&puLen)),
- )
-
- err = maskErrorSuccess(err)
- if ret == 0 && err == nil {
- err = fmt.Errorf("VerQueryValue failed")
- }
-
- if err != nil {
- return "", err
- }
-
- if puLen <= 1 {
- return "", nil
- }
- puLen -= 1 // Remove Null-Terminator
-
- wchar := unsafe.Slice((*uint16)(lplpBuffer), puLen)
- return string(utf16.Decode(wchar)), nil
-}
-
-func globalAlloc(uFlags uint, dwBytes uint32) unsafe.Pointer {
- ret, _, _ := procGlobalAlloc.Call(
- uintptr(uFlags),
- uintptr(dwBytes))
-
- if ret == 0 {
- panic("globalAlloc failed")
- }
-
- return unsafe.Pointer(ret)
-}
-
-func globalFree(data unsafe.Pointer) {
- ret, _, _ := procGlobalFree.Call(uintptr(data))
- if ret != 0 {
- panic("globalFree failed")
- }
-}
-
-func maskErrorSuccess(err error) error {
- if err == windows.ERROR_SUCCESS {
- return nil
- }
- return err
-}
-
-func coTaskMemAlloc(size int) unsafe.Pointer {
- ret, _, _ := procCoTaskMemAlloc.Call(
- uintptr(size))
-
- if ret == 0 {
- panic("coTaskMemAlloc failed")
- }
- return unsafe.Pointer(ret)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go
deleted file mode 100644
index cf278d950..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go
+++ /dev/null
@@ -1,147 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "strconv"
- "strings"
-)
-
-// CompareBrowserVersions will compare the 2 given versions and return:
-//
-// -1 = v1 < v2
-// 0 = v1 == v2
-// 1 = v1 > v2
-func CompareBrowserVersions(v1 string, v2 string) (int, error) {
- v, err := parseVersion(v1)
- if err != nil {
- return 0, fmt.Errorf("v1 invalid: %w", err)
- }
-
- w, err := parseVersion(v2)
- if err != nil {
- return 0, fmt.Errorf("v2 invalid: %w", err)
- }
-
- return v.compare(w), nil
-}
-
-// GetAvailableCoreWebView2BrowserVersionString get the browser version info including channel name
-// if it is the WebView2 Runtime.
-// Channel names are Beta, Dev, and Canary.
-func GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
- if browserExecutableFolder != "" {
- clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
- if errors.Is(err, errNoClientDLLFound) {
- // WebView2 is not found
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return findEmbeddedBrowserVersion(clientPath)
- }
-
- _, version, err := findInstalledClientDll(false)
- if errors.Is(err, errNoClientDLLFound) {
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return version.String(), nil
-}
-
-type version struct {
- major int
- minor int
- patch int
- build int
-
- channel string
-}
-
-func (v version) String() string {
- vv := fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.patch, v.build)
- if v.channel != "" {
- vv += " " + v.channel
- }
-
- return vv
-}
-
-func (v version) compare(o version) int {
- if c := compareInt(v.major, o.major); c != 0 {
- return c
- }
- if c := compareInt(v.minor, o.minor); c != 0 {
- return c
- }
- if c := compareInt(v.patch, o.patch); c != 0 {
- return c
- }
- return compareInt(v.build, o.build)
-}
-
-func parseVersion(v string) (version, error) {
- var p version
-
- // Split away channel information...
- if i := strings.Index(v, " "); i > 0 {
- p.channel = v[i+1:]
- v = v[:i]
- }
-
- vv := strings.Split(v, ".")
- if len(vv) > 4 {
- return p, fmt.Errorf("too many version parts")
- }
-
- var err error
- vv, p.major, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad major version: %w", err)
- }
-
- vv, p.minor, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad minor version: %w", err)
- }
-
- vv, p.patch, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad patch version: %w", err)
- }
-
- _, p.build, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad build version: %w", err)
- }
-
- return p, nil
-}
-
-func parseInt(v []string) ([]string, int, error) {
- if len(v) == 0 {
- return nil, 0, nil
- }
-
- p, err := strconv.ParseInt(v[0], 10, 32)
- if err != nil {
- return nil, 0, err
- }
- return v[1:], int(p), nil
-}
-
-func compareInt(v1, v2 int) int {
- if v1 == v2 {
- return 0
- }
- if v1 < v2 {
- return -1
- } else {
- return +1
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll
deleted file mode 100644
index ab15cffb4..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll
deleted file mode 100644
index 8609d58ee..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/screen.go b/v2/internal/frontend/desktop/windows/screen.go
index e9e9cd603..f6e12bcce 100644
--- a/v2/internal/frontend/desktop/windows/screen.go
+++ b/v2/internal/frontend/desktop/windows/screen.go
@@ -5,10 +5,12 @@ package windows
import (
"fmt"
- "github.com/pkg/errors"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"syscall"
"unsafe"
+
+ "github.com/pkg/errors"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
)
func MonitorsEqual(first w32.MONITORINFO, second w32.MONITORINFO) bool {
@@ -66,13 +68,26 @@ func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT,
return w32.TRUE
}
- height := lprcMonitor.Right - lprcMonitor.Left
- width := lprcMonitor.Bottom - lprcMonitor.Top
+ width := lprcMonitor.Right - lprcMonitor.Left
+ height := lprcMonitor.Bottom - lprcMonitor.Top
ourMonitorData.IsPrimary = monInfo.DwFlags&w32.MONITORINFOF_PRIMARY == 1
- ourMonitorData.Height = int(width)
- ourMonitorData.Width = int(height)
+ ourMonitorData.Height = int(height)
+ ourMonitorData.Width = int(width)
ourMonitorData.IsCurrent = MonitorsEqual(*currentMonInfo, *monInfo)
+ ourMonitorData.PhysicalSize.Width = int(width)
+ ourMonitorData.PhysicalSize.Height = int(height)
+
+ var dpiX, dpiY uint
+ w32.GetDPIForMonitor(hMonitor, w32.MDT_EFFECTIVE_DPI, &dpiX, &dpiY)
+ if dpiX == 0 || dpiY == 0 {
+ screenContainer.errors = append(screenContainer.errors, fmt.Errorf("unable to get DPI for screen"))
+ screenContainer.monitors = append(screenContainer.monitors, Screen{})
+ return w32.TRUE
+ }
+ ourMonitorData.Size.Width = winc.ScaleToDefaultDPI(ourMonitorData.PhysicalSize.Width, dpiX)
+ ourMonitorData.Size.Height = winc.ScaleToDefaultDPI(ourMonitorData.PhysicalSize.Height, dpiY)
+
// the reason we need a container is that we have don't know how many times this function will be called
// this "append" call could potentially do an allocation and rewrite the pointer to monitors. So we save the pointer in screenContainer.monitors
// and retrieve the values after all EnumProc calls
diff --git a/v2/internal/frontend/desktop/windows/single_instance.go b/v2/internal/frontend/desktop/windows/single_instance.go
new file mode 100644
index 000000000..a02b7edb9
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/single_instance.go
@@ -0,0 +1,136 @@
+//go:build windows
+
+package windows
+
+import (
+ "encoding/json"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "golang.org/x/sys/windows"
+ "log"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+type COPYDATASTRUCT struct {
+ dwData uintptr
+ cbData uint32
+ lpData uintptr
+}
+
+// WMCOPYDATA_SINGLE_INSTANCE_DATA we define our own type for WM_COPYDATA message
+const WMCOPYDATA_SINGLE_INSTANCE_DATA = 1542
+
+func SendMessage(hwnd w32.HWND, data string) {
+ arrUtf16, _ := syscall.UTF16FromString(data)
+
+ pCopyData := new(COPYDATASTRUCT)
+ pCopyData.dwData = WMCOPYDATA_SINGLE_INSTANCE_DATA
+ pCopyData.cbData = uint32(len(arrUtf16)*2 + 1)
+ pCopyData.lpData = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(data)))
+
+ w32.SendMessage(hwnd, w32.WM_COPYDATA, 0, uintptr(unsafe.Pointer(pCopyData)))
+}
+
+// SetupSingleInstance single instance Windows app
+func SetupSingleInstance(uniqueId string) {
+ id := "wails-app-" + uniqueId
+
+ className := id + "-sic"
+ windowName := id + "-siw"
+ mutexName := id + "sim"
+
+ _, err := windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(mutexName))
+
+ if err != nil {
+ if err == windows.ERROR_ALREADY_EXISTS {
+ // app is already running
+ hwnd := w32.FindWindowW(windows.StringToUTF16Ptr(className), windows.StringToUTF16Ptr(windowName))
+
+ if hwnd != 0 {
+ data := options.SecondInstanceData{
+ Args: os.Args[1:],
+ }
+ data.WorkingDirectory, err = os.Getwd()
+ if err != nil {
+ log.Printf("Failed to get working directory: %v", err)
+ return
+ }
+ serialized, err := json.Marshal(data)
+ if err != nil {
+ log.Printf("Failed to marshal data: %v", err)
+ return
+ }
+
+ SendMessage(hwnd, string(serialized))
+ // exit second instance of app after sending message
+ os.Exit(0)
+ }
+ // if we got any other unknown error we will just start new application instance
+ }
+ } else {
+ createEventTargetWindow(className, windowName)
+ }
+}
+
+func createEventTargetWindow(className string, windowName string) w32.HWND {
+ // callback handler in the event target window
+ wndProc := func(
+ hwnd w32.HWND, msg uint32, wparam w32.WPARAM, lparam w32.LPARAM,
+ ) w32.LRESULT {
+ if msg == w32.WM_COPYDATA {
+ ldata := (*COPYDATASTRUCT)(unsafe.Pointer(lparam))
+
+ if ldata.dwData == WMCOPYDATA_SINGLE_INSTANCE_DATA {
+ serialized := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ldata.lpData)))
+
+ var secondInstanceData options.SecondInstanceData
+
+ err := json.Unmarshal([]byte(serialized), &secondInstanceData)
+
+ if err == nil {
+ secondInstanceBuffer <- secondInstanceData
+ }
+ }
+
+ return w32.LRESULT(0)
+ }
+
+ return w32.DefWindowProc(hwnd, msg, wparam, lparam)
+ }
+
+ var class w32.WNDCLASSEX
+ class.Size = uint32(unsafe.Sizeof(class))
+ class.Style = 0
+ class.WndProc = syscall.NewCallback(wndProc)
+ class.ClsExtra = 0
+ class.WndExtra = 0
+ class.Instance = w32.GetModuleHandle("")
+ class.Icon = 0
+ class.Cursor = 0
+ class.Background = 0
+ class.MenuName = nil
+ class.ClassName = windows.StringToUTF16Ptr(className)
+ class.IconSm = 0
+
+ w32.RegisterClassEx(&class)
+
+ // create event window that will not be visible for user
+ hwnd := w32.CreateWindowEx(
+ 0,
+ windows.StringToUTF16Ptr(className),
+ windows.StringToUTF16Ptr(windowName),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ w32.HWND_MESSAGE,
+ 0,
+ w32.GetModuleHandle(""),
+ nil,
+ )
+
+ return hwnd
+}
diff --git a/v2/internal/frontend/desktop/windows/winc/app.go b/v2/internal/frontend/desktop/windows/winc/app.go
index 52b30f591..973880444 100644
--- a/v2/internal/frontend/desktop/windows/winc/app.go
+++ b/v2/internal/frontend/desktop/windows/winc/app.go
@@ -37,7 +37,7 @@ func init() {
w32.InitCommonControlsEx(&initCtrls)
}
-// SetAppIconID sets recource icon ID for the apps windows.
+// SetAppIcon sets resource icon ID for the apps windows.
func SetAppIcon(appIconID int) {
AppIconID = appIconID
}
diff --git a/v2/internal/frontend/desktop/windows/winc/combobox.go b/v2/internal/frontend/desktop/windows/winc/combobox.go
index 3b4348acb..380ea88d8 100644
--- a/v2/internal/frontend/desktop/windows/winc/combobox.go
+++ b/v2/internal/frontend/desktop/windows/winc/combobox.go
@@ -54,7 +54,7 @@ func (cb *ComboBox) OnSelectedChange() *EventManager {
return &cb.onSelectedChange
}
-// Message processer
+// Message processor
func (cb *ComboBox) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
switch msg {
case w32.WM_COMMAND:
diff --git a/v2/internal/frontend/desktop/windows/winc/controlbase.go b/v2/internal/frontend/desktop/windows/winc/controlbase.go
index 8dd116780..cdb29518c 100644
--- a/v2/internal/frontend/desktop/windows/winc/controlbase.go
+++ b/v2/internal/frontend/desktop/windows/winc/controlbase.go
@@ -65,7 +65,7 @@ type ControlBase struct {
dispatchq []func()
}
-// initControl is called by controls: edit, button, treeview, listview, and so on.
+// InitControl is called by controls: edit, button, treeview, listview, and so on.
func (cba *ControlBase) InitControl(className string, parent Controller, exstyle, style uint) {
cba.hwnd = CreateWindow(className, parent, exstyle, style)
if cba.hwnd == 0 {
@@ -170,6 +170,14 @@ func (cba *ControlBase) SetTranslucentBackground() {
w32.SetWindowCompositionAttribute(cba.hwnd, &data)
}
+func (cba *ControlBase) SetContentProtection(enable bool) {
+ if enable {
+ w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_EXCLUDEFROMCAPTURE)
+ } else {
+ w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_NONE)
+ }
+}
+
func min(a, b int) int {
if a < b {
return a
@@ -250,6 +258,7 @@ func (cba *ControlBase) Size() (width, height int) {
rect := w32.GetWindowRect(cba.hwnd)
width = int(rect.Right - rect.Left)
height = int(rect.Bottom - rect.Top)
+ width, height = cba.scaleToDefaultDPI(width, height)
return
}
@@ -333,7 +342,23 @@ func (cba *ControlBase) ClientHeight() int {
}
func (cba *ControlBase) Show() {
- w32.ShowWindow(cba.hwnd, w32.SW_SHOWDEFAULT)
+ // WindowPos is used with HWND_TOPMOST to guarantee bring our app on top
+ // force set our main window on top
+ w32.SetWindowPos(
+ cba.hwnd,
+ w32.HWND_TOPMOST,
+ 0, 0, 0, 0,
+ w32.SWP_SHOWWINDOW|w32.SWP_NOSIZE|w32.SWP_NOMOVE,
+ )
+ // remove topmost to allow normal windows manipulations
+ w32.SetWindowPos(
+ cba.hwnd,
+ w32.HWND_NOTOPMOST,
+ 0, 0, 0, 0,
+ w32.SWP_SHOWWINDOW|w32.SWP_NOSIZE|w32.SWP_NOMOVE,
+ )
+ // put main window on tops foreground
+ w32.SetForegroundWindow(cba.hwnd)
}
func (cba *ControlBase) Hide() {
@@ -498,6 +523,14 @@ func (cba *ControlBase) scaleWithWindowDPI(width, height int) (int, int) {
return scaledWidth, scaledHeight
}
+func (cba *ControlBase) scaleToDefaultDPI(width, height int) (int, int) {
+ dpix, dpiy := cba.GetWindowDPI()
+ scaledWidth := ScaleToDefaultDPI(width, dpix)
+ scaledHeight := ScaleToDefaultDPI(height, dpiy)
+
+ return scaledWidth, scaledHeight
+}
+
func (cba *ControlBase) tryInvokeOnCurrentGoRoutine(f func()) bool {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
diff --git a/v2/internal/frontend/desktop/windows/winc/form.go b/v2/internal/frontend/desktop/windows/winc/form.go
index 9b9cadb2c..c9acf7278 100644
--- a/v2/internal/frontend/desktop/windows/winc/form.go
+++ b/v2/internal/frontend/desktop/windows/winc/form.go
@@ -136,7 +136,16 @@ func (fm *Form) Minimise() {
}
func (fm *Form) Restore() {
- w32.ShowWindow(fm.hwnd, w32.SW_RESTORE)
+ // SC_RESTORE param for WM_SYSCOMMAND to restore app if it is minimized
+ const SC_RESTORE = 0xF120
+ // restore the minimized window, if it is
+ w32.SendMessage(
+ fm.hwnd,
+ w32.WM_SYSCOMMAND,
+ SC_RESTORE,
+ 0,
+ )
+ w32.ShowWindow(fm.hwnd, w32.SW_SHOW)
}
// Public methods
diff --git a/v2/internal/frontend/desktop/windows/winc/layout.go b/v2/internal/frontend/desktop/windows/winc/layout.go
index da9895205..7962dc726 100644
--- a/v2/internal/frontend/desktop/windows/winc/layout.go
+++ b/v2/internal/frontend/desktop/windows/winc/layout.go
@@ -65,7 +65,7 @@ type SimpleDock struct {
loadedState bool
}
-// DockState gets saved and loaded from json
+// CtlState gets saved and loaded from json
type CtlState struct {
X, Y, Width, Height int
}
diff --git a/v2/internal/frontend/desktop/windows/winc/listview.go b/v2/internal/frontend/desktop/windows/winc/listview.go
index c98fc4c62..8edfd1c11 100644
--- a/v2/internal/frontend/desktop/windows/winc/listview.go
+++ b/v2/internal/frontend/desktop/windows/winc/listview.go
@@ -438,7 +438,7 @@ func (lv *ListView) OnEndScroll() *EventManager {
return &lv.onEndScroll
}
-// Message processer
+// Message processor
func (lv *ListView) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
switch msg {
/*case w32.WM_ERASEBKGND:
diff --git a/v2/internal/frontend/desktop/windows/winc/treeview.go b/v2/internal/frontend/desktop/windows/winc/treeview.go
index 9118f3d05..2cdc0e936 100644
--- a/v2/internal/frontend/desktop/windows/winc/treeview.go
+++ b/v2/internal/frontend/desktop/windows/winc/treeview.go
@@ -248,7 +248,7 @@ func (tv *TreeView) OnViewChange() *EventManager {
return &tv.onViewChange
}
-// Message processer
+// Message processor
func (tv *TreeView) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
switch msg {
case w32.WM_NOTIFY:
diff --git a/v2/internal/frontend/desktop/windows/winc/utils.go b/v2/internal/frontend/desktop/windows/winc/utils.go
index 00926c70b..c2d91a8c3 100644
--- a/v2/internal/frontend/desktop/windows/winc/utils.go
+++ b/v2/internal/frontend/desktop/windows/winc/utils.go
@@ -149,3 +149,8 @@ func ScreenToClientRect(hwnd w32.HWND, rect *w32.RECT) *Rect {
func ScaleWithDPI(pixels int, dpi uint) int {
return (pixels * int(dpi)) / 96
}
+
+// ScaleToDefaultDPI scales the pixels from scaled DPI-Space to default DPI-Space (96).
+func ScaleToDefaultDPI(pixels int, dpi uint) int {
+ return (pixels * 96) / int(dpi)
+}
diff --git a/v2/internal/frontend/desktop/windows/winc/w32/user32.go b/v2/internal/frontend/desktop/windows/winc/w32/user32.go
index 17e0d9991..707701f5e 100644
--- a/v2/internal/frontend/desktop/windows/winc/w32/user32.go
+++ b/v2/internal/frontend/desktop/windows/winc/w32/user32.go
@@ -24,6 +24,7 @@ var (
procShowWindowAsync = moduser32.NewProc("ShowWindowAsync")
procUpdateWindow = moduser32.NewProc("UpdateWindow")
procCreateWindowEx = moduser32.NewProc("CreateWindowExW")
+ procFindWindowW = moduser32.NewProc("FindWindowW")
procAdjustWindowRect = moduser32.NewProc("AdjustWindowRect")
procAdjustWindowRectEx = moduser32.NewProc("AdjustWindowRectEx")
procDestroyWindow = moduser32.NewProc("DestroyWindow")
@@ -263,6 +264,14 @@ func CreateWindowEx(exStyle uint, className, windowName *uint16,
return HWND(ret)
}
+func FindWindowW(className, windowName *uint16) HWND {
+ ret, _, _ := procFindWindowW.Call(
+ uintptr(unsafe.Pointer(className)),
+ uintptr(unsafe.Pointer(windowName)))
+
+ return HWND(ret)
+}
+
func AdjustWindowRectEx(rect *RECT, style uint, menu bool, exStyle uint) bool {
ret, _, _ := procAdjustWindowRectEx.Call(
uintptr(unsafe.Pointer(rect)),
@@ -630,7 +639,7 @@ func GetSysColorBrush(nIndex int) HBRUSH {
return HBRUSH(ret)
*/
- ret, _, _ := syscall.Syscall(getSysColorBrush, 1,
+ ret, _, _ := syscall.SyscallN(getSysColorBrush,
uintptr(nIndex),
0,
0)
@@ -783,11 +792,9 @@ func CreateMenu() HMENU {
}
func SetMenu(hWnd HWND, hMenu HMENU) bool {
- ret, _, _ := syscall.Syscall(setMenu, 2,
+ ret, _, _ := syscall.SyscallN(setMenu,
uintptr(hWnd),
- uintptr(hMenu),
- 0)
-
+ uintptr(hMenu))
return ret != 0
}
@@ -825,11 +832,7 @@ func TrackPopupMenuEx(hMenu HMENU, fuFlags uint32, x, y int32, hWnd HWND, lptpm
}
func DrawMenuBar(hWnd HWND) bool {
- ret, _, _ := syscall.Syscall(drawMenuBar, 1,
- uintptr(hWnd),
- 0,
- 0)
-
+ ret, _, _ := syscall.SyscallN(drawMenuBar, hWnd)
return ret != 0
}
@@ -1023,9 +1026,11 @@ func EndPaint(hwnd HWND, paint *PAINTSTRUCT) {
uintptr(unsafe.Pointer(paint)))
}
-func GetKeyboardState(lpKeyState *[]byte) bool {
- ret, _, _ := procGetKeyboardState.Call(
- uintptr(unsafe.Pointer(&(*lpKeyState)[0])))
+func GetKeyboardState(keyState []byte) bool {
+ if len(keyState) != 256 {
+ panic("keyState slice must have a size of 256 bytes")
+ }
+ ret, _, _ := procGetKeyboardState.Call(uintptr(unsafe.Pointer(&keyState[0])))
return ret != 0
}
@@ -1220,11 +1225,8 @@ func CallNextHookEx(hhk HHOOK, nCode int, wParam WPARAM, lParam LPARAM) LRESULT
}
func GetKeyState(nVirtKey int32) int16 {
- ret, _, _ := syscall.Syscall(getKeyState, 1,
- uintptr(nVirtKey),
- 0,
- 0)
-
+ ret, _, _ := syscall.SyscallN(getKeyState,
+ uintptr(nVirtKey))
return int16(ret)
}
@@ -1238,17 +1240,15 @@ func DestroyMenu(hMenu HMENU) bool {
}
func GetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool {
- ret, _, _ := syscall.Syscall(getWindowPlacement, 2,
- uintptr(hWnd),
- uintptr(unsafe.Pointer(lpwndpl)),
- 0)
-
+ ret, _, _ := syscall.SyscallN(getWindowPlacement,
+ hWnd,
+ uintptr(unsafe.Pointer(lpwndpl)))
return ret != 0
}
func SetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool {
- ret, _, _ := syscall.Syscall(setWindowPlacement, 2,
- uintptr(hWnd),
+ ret, _, _ := syscall.SyscallN(setWindowPlacement,
+ hWnd,
uintptr(unsafe.Pointer(lpwndpl)),
0)
@@ -1268,7 +1268,7 @@ func SetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO, fRedraw bool) int32
}
func GetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO) bool {
- ret, _, _ := syscall.Syscall(getScrollInfo, 3,
+ ret, _, _ := syscall.SyscallN(getScrollInfo,
hwnd,
uintptr(fnBar),
uintptr(unsafe.Pointer(lpsi)))
diff --git a/v2/internal/frontend/desktop/windows/winc/w32/utils.go b/v2/internal/frontend/desktop/windows/winc/w32/utils.go
index 8a72d4846..4568b4849 100644
--- a/v2/internal/frontend/desktop/windows/winc/w32/utils.go
+++ b/v2/internal/frontend/desktop/windows/winc/w32/utils.go
@@ -75,7 +75,7 @@ func UTF16PtrToString(cstr *uint16) string {
}
func ComAddRef(unknown *IUnknown) int32 {
- ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1,
+ ret, _, _ := syscall.SyscallN(unknown.lpVtbl.pAddRef,
uintptr(unsafe.Pointer(unknown)),
0,
0)
@@ -83,7 +83,7 @@ func ComAddRef(unknown *IUnknown) int32 {
}
func ComRelease(unknown *IUnknown) int32 {
- ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1,
+ ret, _, _ := syscall.SyscallN(unknown.lpVtbl.pRelease,
uintptr(unsafe.Pointer(unknown)),
0,
0)
@@ -92,7 +92,7 @@ func ComRelease(unknown *IUnknown) int32 {
func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
var disp *IDispatch
- hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3,
+ hr, _, _ := syscall.SyscallN(unknown.lpVtbl.pQueryInterface,
uintptr(unsafe.Pointer(unknown)),
uintptr(unsafe.Pointer(id)),
uintptr(unsafe.Pointer(&disp)))
diff --git a/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go
index 51ec0035f..8a14f0cb7 100644
--- a/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go
+++ b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go
@@ -69,7 +69,7 @@ var (
setWindowTheme uintptr
)
-func init() {
+func Init() {
// Library
libuxtheme = MustLoadLibrary("uxtheme.dll")
@@ -83,7 +83,7 @@ func init() {
}
func CloseThemeData(hTheme HTHEME) HRESULT {
- ret, _, _ := syscall.Syscall(closeThemeData, 1,
+ ret, _, _ := syscall.SyscallN(closeThemeData,
uintptr(hTheme),
0,
0)
@@ -134,7 +134,7 @@ func GetThemeTextExtent(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText
}
func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME {
- ret, _, _ := syscall.Syscall(openThemeData, 2,
+ ret, _, _ := syscall.SyscallN(openThemeData,
uintptr(hwnd),
uintptr(unsafe.Pointer(pszClassList)),
0)
@@ -143,7 +143,7 @@ func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME {
}
func SetWindowTheme(hwnd HWND, pszSubAppName, pszSubIdList *uint16) HRESULT {
- ret, _, _ := syscall.Syscall(setWindowTheme, 3,
+ ret, _, _ := syscall.SyscallN(setWindowTheme,
uintptr(hwnd),
uintptr(unsafe.Pointer(pszSubAppName)),
uintptr(unsafe.Pointer(pszSubIdList)))
diff --git a/v2/internal/frontend/desktop/windows/winc/w32/wda.go b/v2/internal/frontend/desktop/windows/winc/w32/wda.go
new file mode 100644
index 000000000..3925f2805
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/winc/w32/wda.go
@@ -0,0 +1,47 @@
+//go:build windows
+
+package w32
+
+import (
+ "syscall"
+
+ "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
+)
+
+var user32 = syscall.NewLazyDLL("user32.dll")
+var procSetWindowDisplayAffinity = user32.NewProc("SetWindowDisplayAffinity")
+var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo()
+
+const (
+ WDA_NONE = 0x00000000
+ WDA_MONITOR = 0x00000001
+ WDA_EXCLUDEFROMCAPTURE = 0x00000011 // windows 10 2004+
+)
+
+func isWindowsVersionAtLeast(major, minor, build int) bool {
+ if windowsVersion.Major > major {
+ return true
+ }
+ if windowsVersion.Major < major {
+ return false
+ }
+ if windowsVersion.Minor > minor {
+ return true
+ }
+ if windowsVersion.Minor < minor {
+ return false
+ }
+ return windowsVersion.Build >= build
+}
+
+func SetWindowDisplayAffinity(hwnd uintptr, affinity uint32) bool {
+ if affinity == WDA_EXCLUDEFROMCAPTURE && !isWindowsVersionAtLeast(10, 0, 19041) {
+ // for older windows versions, use WDA_MONITOR
+ affinity = WDA_MONITOR
+ }
+ ret, _, _ := procSetWindowDisplayAffinity.Call(
+ hwnd,
+ uintptr(affinity),
+ )
+ return ret != 0
+}
diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go
index 9080009a9..b04d61814 100644
--- a/v2/internal/frontend/desktop/windows/window.go
+++ b/v2/internal/frontend/desktop/windows/window.go
@@ -3,9 +3,10 @@
package windows
import (
+ "sync"
"unsafe"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
+ "github.com/wailsapp/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
@@ -37,6 +38,13 @@ type Window struct {
OnResume func()
chromium *edge.Chromium
+
+ // isMinimizing indicates whether the window is currently being minimized
+ // 标识窗口是否处于最小化状态,用于解决最小化/恢复时的闪屏问题
+ // This flag is used to prevent unnecessary redraws during minimize/restore transitions for frameless windows
+ // 此标志用于防止无边框窗口在最小化/恢复过程中的不必要重绘
+ // Reference: https://github.com/wailsapp/wails/issues/3951
+ isMinimizing bool
}
func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *operatingsystem.WindowsVersionInfo, chromium *edge.Chromium) *Window {
@@ -70,8 +78,13 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
var dwStyle = w32.WS_OVERLAPPEDWINDOW
- winc.RegClassOnlyOnce("wailsWindow")
- handle := winc.CreateWindow("wailsWindow", parent, uint(exStyle), uint(dwStyle))
+ windowClassName := "wailsWindow"
+ if windowsOptions != nil && windowsOptions.WindowClassName != "" {
+ windowClassName = windowsOptions.WindowClassName
+ }
+
+ winc.RegClassOnlyOnce(windowClassName)
+ handle := winc.CreateWindow(windowClassName, parent, uint(exStyle), uint(dwStyle))
result.SetHandle(handle)
winc.RegMsgHandler(result)
result.SetParent(parent)
@@ -118,6 +131,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
}
}
+ if windowsOptions.ContentProtection {
+ w32.SetWindowDisplayAffinity(result.Handle(), w32.WDA_EXCLUDEFROMCAPTURE)
+ }
+
if windowsOptions.DisableWindowIcon {
result.DisableIcon()
}
@@ -251,7 +268,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
if w.Form.IsFullScreen() {
// In Full-Screen mode we don't need to adjust anything
- w.chromium.SetPadding(edge.Rect{})
+ w.SetPadding(edge.Rect{})
} else if w.IsMaximised() {
// If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise
// some content goes beyond the visible part of the monitor.
@@ -282,7 +299,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
}
}
}
- w.chromium.SetPadding(edge.Rect{})
+ w.SetPadding(edge.Rect{})
} else {
// This is needed to workaround the resize flickering in frameless mode with WindowDecorations
// See: https://stackoverflow.com/a/6558508
@@ -291,7 +308,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
// Increasing the bottom also worksaround the flickering but we would loose 1px of the WebView content
// therefore let's pad the content with 1px at the bottom.
rgrc.Bottom += 1
- w.chromium.SetPadding(edge.Rect{Bottom: 1})
+ w.SetPadding(edge.Rect{Bottom: 1})
}
return 0
}
@@ -323,3 +340,28 @@ func (w *Window) SetTheme(theme winoptions.Theme) {
w.UpdateTheme()
})
}
+
+func invokeSync[T any](cba *Window, fn func() (T, error)) (res T, err error) {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ cba.Invoke(func() {
+ res, err = fn()
+ wg.Done()
+ })
+ wg.Wait()
+ return res, err
+}
+
+// SetPadding is a filter that wraps chromium.SetPadding to prevent unnecessary redraws during minimize/restore
+// 包装了chromium.SetPadding的过滤器,用于防止窗口最小化/恢复过程中的不必要重绘
+// This fixes window flickering when minimizing/restoring frameless windows
+// 这修复了无边框窗口在最小化/恢复时的闪烁问题
+// Reference: https://github.com/wailsapp/wails/issues/3951
+func (w *Window) SetPadding(padding edge.Rect) {
+ // Skip SetPadding if window is being minimized to prevent flickering
+ // 如果窗口正在最小化,跳过设置padding以防止闪烁
+ if w.isMinimizing {
+ return
+ }
+ w.chromium.SetPadding(padding)
+}
diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go
index 8d5003c60..8a130890d 100644
--- a/v2/internal/frontend/devserver/devserver.go
+++ b/v2/internal/frontend/devserver/devserver.go
@@ -10,29 +10,33 @@ import (
"encoding/json"
"fmt"
"log"
- "net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"sync"
- "time"
"github.com/wailsapp/wails/v2/pkg/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/menumanager"
"github.com/wailsapp/wails/v2/pkg/options"
- "golang.org/x/net/websocket"
)
type Screen = frontend.Screen
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ CheckOrigin: func(r *http.Request) bool { return true },
+}
+
type DevWebServer struct {
server *echo.Echo
ctx context.Context
@@ -62,9 +66,12 @@ func (d *DevWebServer) Run(ctx context.Context) error {
return err
}
- var assetHandler http.Handler
+ var myLogger assetserver.Logger
+ if _logger := ctx.Value("logger"); _logger != nil {
+ myLogger = _logger.(*logger.Logger)
+ }
+
var wsHandler http.Handler
- var myLogger *logger.Logger
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
if _fronendDevServerURL == "" {
@@ -73,49 +80,40 @@ func (d *DevWebServer) Run(ctx context.Context) error {
return c.String(http.StatusOK, assetdir)
})
- if _logger := ctx.Value("logger"); _logger != nil {
- myLogger = _logger.(*logger.Logger)
- }
- var err error
- assetHandler, err = assetserver.NewAssetHandler(assetServerConfig, myLogger)
- if err != nil {
- log.Fatal(err)
- }
} else {
externalURL, err := url.Parse(_fronendDevServerURL)
if err != nil {
return err
}
- if externalURL.Host == "" {
- return fmt.Errorf("Invalid frontend:dev:serverUrl missing protocol scheme?")
- }
-
- waitCb := func() { d.LogDebug("Waiting for frontend DevServer '%s' to be ready", externalURL) }
- if !checkPortIsOpen(externalURL.Host, time.Minute, waitCb) {
- d.logger.Error("Timeout waiting for frontend DevServer")
- }
-
- assetHandler = newExternalDevServerAssetHandler(d.logger, externalURL, assetServerConfig)
// WebSockets aren't currently supported in prod mode, so a WebSocket connection is the result of the
// FrontendDevServer e.g. Vite to support auto reloads.
// Therefore we direct WebSockets directly to the FrontendDevServer instead of returning a NotImplementedStatus.
wsHandler = httputil.NewSingleHostReverseProxy(externalURL)
}
+ assetHandler, err := assetserver.NewAssetHandler(assetServerConfig, myLogger)
+ if err != nil {
+ log.Fatal(err)
+ }
+
// Setup internal dev server
bindingsJSON, err := d.appBindings.ToJSON()
if err != nil {
log.Fatal(err)
}
- assetServer, err := assetserver.NewDevAssetServer(assetHandler, wsHandler, bindingsJSON, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle)
+ assetServer, err := assetserver.NewDevAssetServer(assetHandler, bindingsJSON, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle)
if err != nil {
log.Fatal(err)
}
d.server.Any("/*", func(c echo.Context) error {
- assetServer.ServeHTTP(c.Response(), c.Request())
+ if c.IsWebSocket() {
+ wsHandler.ServeHTTP(c.Response(), c.Request())
+ } else {
+ assetServer.ServeHTTP(c.Response(), c.Request())
+ }
return nil
})
@@ -163,51 +161,64 @@ func (d *DevWebServer) handleReloadApp(c echo.Context) error {
}
func (d *DevWebServer) handleIPCWebSocket(c echo.Context) error {
- websocket.Handler(func(c *websocket.Conn) {
- d.LogDebug(fmt.Sprintf("Websocket client %p connected", c))
+ conn, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
+ if err != nil {
+ d.logger.Error("WebSocket upgrade failed %v", err)
+ return err
+ }
+ d.LogDebug(fmt.Sprintf("WebSocket client %p connected", conn))
+
+ d.socketMutex.Lock()
+ d.websocketClients[conn] = &sync.Mutex{}
+ locker := d.websocketClients[conn]
+ d.socketMutex.Unlock()
+
+ var wg sync.WaitGroup
+
+ defer func() {
+ wg.Wait()
d.socketMutex.Lock()
- d.websocketClients[c] = &sync.Mutex{}
- locker := d.websocketClients[c]
+ delete(d.websocketClients, conn)
d.socketMutex.Unlock()
+ d.LogDebug(fmt.Sprintf("WebSocket client %p disconnected", conn))
+ conn.Close()
+ }()
- defer func() {
- d.socketMutex.Lock()
- delete(d.websocketClients, c)
- d.socketMutex.Unlock()
- d.LogDebug(fmt.Sprintf("Websocket client %p disconnected", c))
- }()
+ for {
+ _, msgBytes, err := conn.ReadMessage()
+ if err != nil {
+ break
+ }
- var msg string
- defer c.Close()
- for {
- if err := websocket.Message.Receive(c, &msg); err != nil {
- break
- }
- // We do not support drag in browsers
- if msg == "drag" {
- continue
+ msg := string(msgBytes)
+ wg.Add(1)
+
+ go func(m string) {
+ defer wg.Done()
+
+ if m == "drag" {
+ return
}
- // Notify the other browsers of "EventEmit"
- if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") {
- d.notifyExcludingSender([]byte(msg), c)
+ if len(m) > 2 && strings.HasPrefix(m, "EE") {
+ d.notifyExcludingSender([]byte(m), conn)
}
- // Send the message to dispatch to the frontend
- result, err := d.dispatcher.ProcessMessage(string(msg), d)
+ result, err := d.dispatcher.ProcessMessage(m, d)
if err != nil {
d.logger.Error(err.Error())
}
+
if result != "" {
locker.Lock()
- if err = websocket.Message.Send(c, result); err != nil {
- locker.Unlock()
- break
+ defer locker.Unlock()
+ if err := conn.WriteMessage(websocket.TextMessage, []byte(result)); err != nil {
+ d.logger.Error("Websocket write message failed %v", err)
}
- locker.Unlock()
}
- }
- }).ServeHTTP(c.Response(), c.Request())
+ }(msg)
+ }
+
return nil
}
@@ -230,7 +241,7 @@ func (d *DevWebServer) broadcast(message string) {
return
}
locker.Lock()
- err := websocket.Message.Send(client, message)
+ err := client.WriteMessage(websocket.TextMessage, []byte(message))
if err != nil {
locker.Unlock()
d.logger.Error(err.Error())
@@ -264,7 +275,7 @@ func (d *DevWebServer) broadcastExcludingSender(message string, sender *websocke
return
}
locker.Lock()
- err := websocket.Message.Send(client, message)
+ err := client.WriteMessage(websocket.TextMessage, []byte(message))
if err != nil {
locker.Unlock()
d.logger.Error(err.Error())
@@ -306,22 +317,3 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
result.server.HidePort = true
return result
}
-
-func checkPortIsOpen(host string, timeout time.Duration, waitCB func()) (ret bool) {
- if timeout == 0 {
- timeout = time.Minute
- }
-
- deadline := time.Now().Add(timeout)
- for time.Now().Before(deadline) {
- conn, _ := net.DialTimeout("tcp", host, 2*time.Second)
- if conn != nil {
- conn.Close()
- return true
- }
-
- waitCB()
- time.Sleep(1 * time.Second)
- }
- return false
-}
diff --git a/v2/internal/frontend/devserver/external.go b/v2/internal/frontend/devserver/external.go
deleted file mode 100644
index fd717e723..000000000
--- a/v2/internal/frontend/devserver/external.go
+++ /dev/null
@@ -1,83 +0,0 @@
-//go:build dev
-// +build dev
-
-package devserver
-
-import (
- "errors"
- "fmt"
- "net/http"
- "net/http/httputil"
- "net/url"
-
- "github.com/wailsapp/wails/v2/internal/logger"
- "github.com/wailsapp/wails/v2/pkg/options/assetserver"
-)
-
-func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, options assetserver.Options) http.Handler {
- handler := newExternalAssetsHandler(logger, url, options.Handler)
-
- if middleware := options.Middleware; middleware != nil {
- handler = middleware(handler)
- }
-
- return handler
-}
-
-func newExternalAssetsHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
- errSkipProxy := fmt.Errorf("skip proxying")
-
- proxy := httputil.NewSingleHostReverseProxy(url)
- baseDirector := proxy.Director
- proxy.Director = func(r *http.Request) {
- baseDirector(r)
- if logger != nil {
- logger.Debug("[ExternalAssetHandler] Loading '%s'", r.URL)
- }
- }
-
- proxy.ModifyResponse = func(res *http.Response) error {
- if handler == nil {
- return nil
- }
-
- if res.StatusCode == http.StatusSwitchingProtocols {
- return nil
- }
-
- if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed {
- return errSkipProxy
- }
-
- return nil
- }
-
- proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
- if handler != nil && errors.Is(err, errSkipProxy) {
- if logger != nil {
- logger.Debug("[ExternalAssetHandler] Loading '%s' failed, using AssetHandler", r.URL)
- }
- handler.ServeHTTP(rw, r)
- } else {
- if logger != nil {
- logger.Error("[ExternalAssetHandler] Proxy error: %v", err)
- }
- rw.WriteHeader(http.StatusBadGateway)
- }
- }
-
- return http.HandlerFunc(
- func(rw http.ResponseWriter, req *http.Request) {
- if req.Method == http.MethodGet {
- proxy.ServeHTTP(rw, req)
- return
- }
-
- if handler != nil {
- handler.ServeHTTP(rw, req)
- return
- }
-
- rw.WriteHeader(http.StatusMethodNotAllowed)
- })
-}
diff --git a/v2/internal/frontend/dispatcher/calls.go b/v2/internal/frontend/dispatcher/calls.go
index ef19c6030..ba1062913 100644
--- a/v2/internal/frontend/dispatcher/calls.go
+++ b/v2/internal/frontend/dispatcher/calls.go
@@ -3,8 +3,9 @@ package dispatcher
import (
"encoding/json"
"fmt"
- "github.com/wailsapp/wails/v2/internal/frontend"
"strings"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
)
type callMessage struct {
@@ -14,7 +15,6 @@ type callMessage struct {
}
func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend) (string, error) {
-
var payload callMessage
err := json.Unmarshal([]byte(message[1:]), &payload)
if err != nil {
@@ -49,7 +49,12 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
CallbackID: payload.CallbackID,
}
if err != nil {
- callbackMessage.Err = err.Error()
+ // Use the error formatter if one was provided
+ if d.errfmt != nil {
+ callbackMessage.Err = d.errfmt(err)
+ } else {
+ callbackMessage.Err = err.Error()
+ }
} else {
callbackMessage.Result = result
}
@@ -66,7 +71,7 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
// CallbackMessage defines a message that contains the result of a call
type CallbackMessage struct {
Result interface{} `json:"result"`
- Err string `json:"error"`
+ Err any `json:"error"`
CallbackID string `json:"callbackid"`
}
diff --git a/v2/internal/frontend/dispatcher/dispatcher.go b/v2/internal/frontend/dispatcher/dispatcher.go
index 44a8886e5..24a43cfef 100644
--- a/v2/internal/frontend/dispatcher/dispatcher.go
+++ b/v2/internal/frontend/dispatcher/dispatcher.go
@@ -2,32 +2,52 @@ package dispatcher
import (
"context"
-
+ "fmt"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
)
type Dispatcher struct {
- log *logger.Logger
- bindings *binding.Bindings
- events frontend.Events
- bindingsDB *binding.DB
- ctx context.Context
+ log *logger.Logger
+ bindings *binding.Bindings
+ events frontend.Events
+ bindingsDB *binding.DB
+ ctx context.Context
+ errfmt options.ErrorFormatter
+ disablePanicRecovery bool
}
-func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events) *Dispatcher {
+func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events, errfmt options.ErrorFormatter, disablePanicRecovery bool) *Dispatcher {
return &Dispatcher{
- log: log,
- bindings: bindings,
- events: events,
- bindingsDB: bindings.DB(),
- ctx: ctx,
+ log: log,
+ bindings: bindings,
+ events: events,
+ bindingsDB: bindings.DB(),
+ ctx: ctx,
+ errfmt: errfmt,
+ disablePanicRecovery: disablePanicRecovery,
}
}
-func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (string, error) {
+func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (_ string, err error) {
+ if !d.disablePanicRecovery {
+ defer func() {
+ if e := recover(); e != nil {
+ if errPanic, ok := e.(error); ok {
+ err = errPanic
+ } else {
+ err = fmt.Errorf("%v", e)
+ }
+ }
+ if err != nil {
+ d.log.Error("process message error: %s -> %s", message, err)
+ }
+ }()
+ }
+
if message == "" {
return "", errors.New("No message to process")
}
@@ -44,6 +64,8 @@ func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (s
return d.processWindowMessage(message, sender)
case 'B':
return d.processBrowserMessage(message, sender)
+ case 'D':
+ return d.processDragAndDropMessage(message)
case 'Q':
sender.Quit()
return "", nil
diff --git a/v2/internal/frontend/dispatcher/draganddrop.go b/v2/internal/frontend/dispatcher/draganddrop.go
new file mode 100644
index 000000000..8266ec712
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/draganddrop.go
@@ -0,0 +1,38 @@
+package dispatcher
+
+import (
+ "errors"
+ "strconv"
+ "strings"
+)
+
+func (d *Dispatcher) processDragAndDropMessage(message string) (string, error) {
+ switch message[1] {
+ case 'D':
+ msg := strings.SplitN(message[3:], ":", 3)
+ if len(msg) != 3 {
+ return "", errors.New("Invalid drag and drop Message: " + message)
+ }
+
+ x, err := strconv.Atoi(msg[0])
+ if err != nil {
+ return "", errors.New("Invalid x coordinate in drag and drop Message: " + message)
+ }
+
+ y, err := strconv.Atoi(msg[1])
+ if err != nil {
+ return "", errors.New("Invalid y coordinate in drag and drop Message: " + message)
+ }
+
+ paths := strings.Split(msg[2], "\n")
+ if len(paths) < 1 {
+ return "", errors.New("Invalid drag and drop Message: " + message)
+ }
+
+ d.events.Emit("wails:file-drop", x, y, paths)
+ default:
+ return "", errors.New("Invalid drag and drop Message: " + message)
+ }
+
+ return "", nil
+}
diff --git a/v2/internal/frontend/dispatcher/events.go b/v2/internal/frontend/dispatcher/events.go
index 11680651b..12fe7b89e 100644
--- a/v2/internal/frontend/dispatcher/events.go
+++ b/v2/internal/frontend/dispatcher/events.go
@@ -3,6 +3,7 @@ package dispatcher
import (
"encoding/json"
"errors"
+
"github.com/wailsapp/wails/v2/internal/frontend"
)
diff --git a/v2/internal/frontend/dispatcher/securecalls.go b/v2/internal/frontend/dispatcher/securecalls.go
index 40accaa26..8cdcdfb85 100644
--- a/v2/internal/frontend/dispatcher/securecalls.go
+++ b/v2/internal/frontend/dispatcher/securecalls.go
@@ -3,6 +3,7 @@ package dispatcher
import (
"encoding/json"
"fmt"
+
"github.com/wailsapp/wails/v2/internal/frontend"
)
@@ -13,7 +14,6 @@ type secureCallMessage struct {
}
func (d *Dispatcher) processSecureCallMessage(message string, sender frontend.Frontend) (string, error) {
-
var payload secureCallMessage
err := json.Unmarshal([]byte(message[1:]), &payload)
if err != nil {
diff --git a/v2/internal/frontend/dispatcher/systemcalls.go b/v2/internal/frontend/dispatcher/systemcalls.go
index b810d9bea..b090a416e 100644
--- a/v2/internal/frontend/dispatcher/systemcalls.go
+++ b/v2/internal/frontend/dispatcher/systemcalls.go
@@ -4,9 +4,10 @@ import (
"encoding/json"
"errors"
"fmt"
- "github.com/wailsapp/wails/v2/pkg/runtime"
"strings"
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+
"github.com/wailsapp/wails/v2/internal/frontend"
)
@@ -23,7 +24,6 @@ type size struct {
}
func (d *Dispatcher) processSystemCall(payload callMessage, sender frontend.Frontend) (interface{}, error) {
-
// Strip prefix
name := strings.TrimPrefix(payload.Name, systemCallPrefix)
@@ -64,5 +64,4 @@ func (d *Dispatcher) processSystemCall(payload callMessage, sender frontend.Fron
default:
return nil, fmt.Errorf("unknown systemcall message: %s", payload.Name)
}
-
}
diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go
index 79ee254c2..6b2ccbcae 100644
--- a/v2/internal/frontend/frontend.go
+++ b/v2/internal/frontend/frontend.go
@@ -48,8 +48,21 @@ const (
type Screen struct {
IsCurrent bool `json:"isCurrent"`
IsPrimary bool `json:"isPrimary"`
- Width int `json:"width"`
- Height int `json:"height"`
+
+ // Deprecated: Please use Size and PhysicalSize
+ Width int `json:"width"`
+ // Deprecated: Please use Size and PhysicalSize
+ Height int `json:"height"`
+
+ // Size is the size of the screen in logical pixel space, used when setting sizes in Wails
+ Size ScreenSize `json:"size"`
+ // PhysicalSize is the physical size of the screen in pixels
+ PhysicalSize ScreenSize `json:"physicalSize"`
+}
+
+type ScreenSize struct {
+ Width int `json:"width"`
+ Height int `json:"height"`
}
// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
@@ -64,7 +77,7 @@ type MessageDialogOptions struct {
}
type Frontend interface {
- Run(context.Context) error
+ Run(ctx context.Context) error
RunMainLoop()
ExecJS(js string)
Hide()
@@ -108,8 +121,9 @@ type Frontend interface {
WindowIsNormal() bool
WindowIsFullscreen() bool
WindowClose()
+ WindowPrint()
- //Screen
+ // Screen
ScreenGetAll() ([]Screen, error)
// Menus
diff --git a/v2/internal/frontend/originvalidator/originValidator.go b/v2/internal/frontend/originvalidator/originValidator.go
new file mode 100644
index 000000000..fd416f945
--- /dev/null
+++ b/v2/internal/frontend/originvalidator/originValidator.go
@@ -0,0 +1,116 @@
+package originvalidator
+
+import (
+ "fmt"
+ "net/url"
+ "regexp"
+ "strings"
+)
+
+type OriginValidator struct {
+ allowedOrigins []string
+}
+
+// NewOriginValidator creates a new validator from a comma-separated string of allowed origins
+func NewOriginValidator(startUrl *url.URL, allowedOriginsString string) *OriginValidator {
+ allowedOrigins := startUrl.Scheme + "://" + startUrl.Host
+ if allowedOriginsString != "" {
+ allowedOrigins += "," + allowedOriginsString
+ }
+ validator := &OriginValidator{}
+ validator.parseAllowedOrigins(allowedOrigins)
+ return validator
+}
+
+// parseAllowedOrigins parses the comma-separated origins string
+func (v *OriginValidator) parseAllowedOrigins(originsString string) {
+ if originsString == "" {
+ v.allowedOrigins = []string{}
+ return
+ }
+
+ origins := strings.Split(originsString, ",")
+ var trimmedOrigins []string
+
+ for _, origin := range origins {
+ trimmed := strings.TrimSuffix(strings.TrimSpace(origin), "/")
+ if trimmed != "" {
+ trimmedOrigins = append(trimmedOrigins, trimmed)
+ }
+ }
+
+ v.allowedOrigins = trimmedOrigins
+}
+
+// IsOriginAllowed checks if the given origin is allowed
+func (v *OriginValidator) IsOriginAllowed(origin string) bool {
+ if origin == "" {
+ return false
+ }
+
+ for _, allowedOrigin := range v.allowedOrigins {
+ if v.matchesOriginPattern(allowedOrigin, origin) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// matchesOriginPattern checks if origin matches the pattern (supports wildcards)
+func (v *OriginValidator) matchesOriginPattern(pattern, origin string) bool {
+ // Exact match
+ if pattern == origin {
+ return true
+ }
+
+ // Wildcard pattern matching
+ if strings.Contains(pattern, "*") {
+ regexPattern := v.wildcardPatternToRegex(pattern)
+ matched, err := regexp.MatchString(regexPattern, origin)
+ if err != nil {
+ return false
+ }
+ return matched
+ }
+
+ return false
+}
+
+// wildcardPatternToRegex converts wildcard pattern to regex
+func (v *OriginValidator) wildcardPatternToRegex(wildcardPattern string) string {
+ // Escape special regex characters except *
+ specialChars := []string{"\\", ".", "+", "?", "^", "$", "{", "}", "(", ")", "|", "[", "]"}
+
+ escaped := wildcardPattern
+ for _, specialChar := range specialChars {
+ escaped = strings.ReplaceAll(escaped, specialChar, "\\"+specialChar)
+ }
+
+ // Replace * with .* (matches any characters)
+ escaped = strings.ReplaceAll(escaped, "*", ".*")
+
+ // Anchor the pattern to match the entire string
+ return "^" + escaped + "$"
+}
+
+// GetOriginFromURL extracts origin from URL string
+func (v *OriginValidator) GetOriginFromURL(urlString string) (string, error) {
+ if urlString == "" {
+ return "", fmt.Errorf("empty URL")
+ }
+
+ parsedURL, err := url.Parse(urlString)
+ if err != nil {
+ return "", fmt.Errorf("invalid URL: %v", err)
+ }
+
+ if parsedURL.Scheme == "" || parsedURL.Host == "" {
+ return "", fmt.Errorf("URL missing scheme or host")
+ }
+
+ // Build origin (scheme + host)
+ origin := parsedURL.Scheme + "://" + parsedURL.Host
+
+ return origin, nil
+}
diff --git a/v2/internal/frontend/runtime/desktop/contextmenu.js b/v2/internal/frontend/runtime/desktop/contextmenu.js
new file mode 100644
index 000000000..b9c397546
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/contextmenu.js
@@ -0,0 +1,50 @@
+/*
+--default-contextmenu: auto; (default) will show the default context menu if contentEditable is true OR text has been selected OR element is input or textarea
+--default-contextmenu: show; will always show the default context menu
+--default-contextmenu: hide; will always hide the default context menu
+
+This rule is inherited like normal CSS rules, so nesting works as expected
+*/
+export function processDefaultContextMenu(event) {
+ // Process default context menu
+ const element = event.target;
+ const computedStyle = window.getComputedStyle(element);
+ const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
+ switch (defaultContextMenuAction) {
+ case "show":
+ return;
+ case "hide":
+ event.preventDefault();
+ return;
+ default:
+ // Check if contentEditable is true
+ if (element.isContentEditable) {
+ return;
+ }
+
+ // Check if text has been selected and action is on the selected elements
+ const selection = window.getSelection();
+ const hasSelection = (selection.toString().length > 0)
+ if (hasSelection) {
+ for (let i = 0; i < selection.rangeCount; i++) {
+ const range = selection.getRangeAt(i);
+ const rects = range.getClientRects();
+ for (let j = 0; j < rects.length; j++) {
+ const rect = rects[j];
+ if (document.elementFromPoint(rect.left, rect.top) === element) {
+ return;
+ }
+ }
+ }
+ }
+ // Check if tagname is input or textarea
+ if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
+ if (hasSelection || (!element.readOnly && !element.disabled)) {
+ return;
+ }
+ }
+
+ // hide default context menu
+ event.preventDefault();
+ }
+}
diff --git a/v2/internal/frontend/runtime/desktop/draganddrop.js b/v2/internal/frontend/runtime/desktop/draganddrop.js
new file mode 100644
index 000000000..e470e4823
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/draganddrop.js
@@ -0,0 +1,276 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 9 */
+
+import {EventsOn, EventsOff} from "./events";
+
+const flags = {
+ registered: false,
+ defaultUseDropTarget: true,
+ useDropTarget: true,
+ nextDeactivate: null,
+ nextDeactivateTimeout: null,
+};
+
+const DROP_TARGET_ACTIVE = "wails-drop-target-active";
+
+/**
+ * checkStyleDropTarget checks if the style has the drop target attribute
+ *
+ * @param {CSSStyleDeclaration} style
+ * @returns
+ */
+function checkStyleDropTarget(style) {
+ const cssDropValue = style.getPropertyValue(window.wails.flags.cssDropProperty).trim();
+ if (cssDropValue) {
+ if (cssDropValue === window.wails.flags.cssDropValue) {
+ return true;
+ }
+ // if the element has the drop target attribute, but
+ // the value is not correct, terminate finding process.
+ // This can be useful to block some child elements from being drop targets.
+ return false;
+ }
+ return false;
+}
+
+/**
+ * onDragOver is called when the dragover event is emitted.
+ * @param {DragEvent} e
+ * @returns
+ */
+function onDragOver(e) {
+ // Check if this is an external file drop or internal HTML drag
+ // External file drops will have "Files" in the types array
+ // Internal HTML drags typically have "text/plain", "text/html" or custom types
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+
+ // Only handle external file drops, let internal HTML5 drag-and-drop work normally
+ if (!isFileDrop) {
+ return;
+ }
+
+ // ALWAYS prevent default for file drops to stop browser navigation
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+
+ if (!flags.useDropTarget) {
+ return;
+ }
+
+ const element = e.target;
+
+ // Trigger debounce function to deactivate drop targets
+ if(flags.nextDeactivate) flags.nextDeactivate();
+
+ // if the element is null or element is not child of drop target element
+ if (!element || !checkStyleDropTarget(getComputedStyle(element))) {
+ return;
+ }
+
+ let currentElement = element;
+ while (currentElement) {
+ // check if currentElement is drop target element
+ if (checkStyleDropTarget(getComputedStyle(currentElement))) {
+ currentElement.classList.add(DROP_TARGET_ACTIVE);
+ }
+ currentElement = currentElement.parentElement;
+ }
+}
+
+/**
+ * onDragLeave is called when the dragleave event is emitted.
+ * @param {DragEvent} e
+ * @returns
+ */
+function onDragLeave(e) {
+ // Check if this is an external file drop or internal HTML drag
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+
+ // Only handle external file drops, let internal HTML5 drag-and-drop work normally
+ if (!isFileDrop) {
+ return;
+ }
+
+ // ALWAYS prevent default for file drops to stop browser navigation
+ e.preventDefault();
+
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+
+ if (!flags.useDropTarget) {
+ return;
+ }
+
+ // Find the close drop target element
+ if (!e.target || !checkStyleDropTarget(getComputedStyle(e.target))) {
+ return null;
+ }
+
+ // Trigger debounce function to deactivate drop targets
+ if(flags.nextDeactivate) flags.nextDeactivate();
+
+ // Use debounce technique to tacle dragleave events on overlapping elements and drop target elements
+ flags.nextDeactivate = () => {
+ // Deactivate all drop targets, new drop target will be activated on next dragover event
+ Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach(el => el.classList.remove(DROP_TARGET_ACTIVE));
+ // Reset nextDeactivate
+ flags.nextDeactivate = null;
+ // Clear timeout
+ if (flags.nextDeactivateTimeout) {
+ clearTimeout(flags.nextDeactivateTimeout);
+ flags.nextDeactivateTimeout = null;
+ }
+ }
+
+ // Set timeout to deactivate drop targets if not triggered by next drag event
+ flags.nextDeactivateTimeout = setTimeout(() => {
+ if(flags.nextDeactivate) flags.nextDeactivate();
+ }, 50);
+}
+
+/**
+ * onDrop is called when the drop event is emitted.
+ * @param {DragEvent} e
+ * @returns
+ */
+function onDrop(e) {
+ // Check if this is an external file drop or internal HTML drag
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+
+ // Only handle external file drops, let internal HTML5 drag-and-drop work normally
+ if (!isFileDrop) {
+ return;
+ }
+
+ // ALWAYS prevent default for file drops to stop browser navigation
+ e.preventDefault();
+
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+
+ if (CanResolveFilePaths()) {
+ // process files
+ let files = [];
+ if (e.dataTransfer.items) {
+ files = [...e.dataTransfer.items].map((item, i) => {
+ if (item.kind === 'file') {
+ return item.getAsFile();
+ }
+ });
+ } else {
+ files = [...e.dataTransfer.files];
+ }
+ window.runtime.ResolveFilePaths(e.x, e.y, files);
+ }
+
+ if (!flags.useDropTarget) {
+ return;
+ }
+
+ // Trigger debounce function to deactivate drop targets
+ if(flags.nextDeactivate) flags.nextDeactivate();
+
+ // Deactivate all drop targets
+ Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach(el => el.classList.remove(DROP_TARGET_ACTIVE));
+}
+
+/**
+ * postMessageWithAdditionalObjects checks the browser's capability of sending postMessageWithAdditionalObjects
+ *
+ * @returns {boolean}
+ * @constructor
+ */
+export function CanResolveFilePaths() {
+ return window.chrome?.webview?.postMessageWithAdditionalObjects != null;
+}
+
+/**
+ * ResolveFilePaths sends drop events to the GO side to resolve file paths on windows.
+ *
+ * @param {number} x
+ * @param {number} y
+ * @param {any[]} files
+ * @constructor
+ */
+export function ResolveFilePaths(x, y, files) {
+ // Only for windows webview2 >= 1.0.1774.30
+ // https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2webmessagereceivedeventargs2?view=webview2-1.0.1823.32#applies-to
+ if (window.chrome?.webview?.postMessageWithAdditionalObjects) {
+ chrome.webview.postMessageWithAdditionalObjects(`file:drop:${x}:${y}`, files);
+ }
+}
+
+/**
+ * Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ *
+ * @export
+ * @callback OnFileDropCallback
+ * @param {number} x - x coordinate of the drop
+ * @param {number} y - y coordinate of the drop
+ * @param {string[]} paths - A list of file paths.
+ */
+
+/**
+ * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+ *
+ * @export
+ * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
+ */
+export function OnFileDrop(callback, useDropTarget) {
+ if (typeof callback !== "function") {
+ console.error("DragAndDropCallback is not a function");
+ return;
+ }
+
+ if (flags.registered) {
+ return;
+ }
+ flags.registered = true;
+
+ const uDTPT = typeof useDropTarget;
+ flags.useDropTarget = uDTPT === "undefined" || uDTPT !== "boolean" ? flags.defaultUseDropTarget : useDropTarget;
+ window.addEventListener('dragover', onDragOver);
+ window.addEventListener('dragleave', onDragLeave);
+ window.addEventListener('drop', onDrop);
+
+ let cb = callback;
+ if (flags.useDropTarget) {
+ cb = function (x, y, paths) {
+ const element = document.elementFromPoint(x, y)
+ // if the element is null or element is not child of drop target element, return null
+ if (!element || !checkStyleDropTarget(getComputedStyle(element))) {
+ return null;
+ }
+ callback(x, y, paths);
+ }
+ }
+
+ EventsOn("wails:file-drop", cb);
+}
+
+/**
+ * OnFileDropOff removes the drag and drop listeners and handlers.
+ */
+export function OnFileDropOff() {
+ window.removeEventListener('dragover', onDragOver);
+ window.removeEventListener('dragleave', onDragLeave);
+ window.removeEventListener('drop', onDrop);
+ EventsOff("wails:file-drop");
+ flags.registered = false;
+}
diff --git a/v2/internal/frontend/runtime/desktop/events.js b/v2/internal/frontend/runtime/desktop/events.js
index 0ee9b2dd3..e665a8aff 100644
--- a/v2/internal/frontend/runtime/desktop/events.js
+++ b/v2/internal/frontend/runtime/desktop/events.js
@@ -90,17 +90,17 @@ function notifyListeners(eventData) {
// Get the event name
let eventName = eventData.name;
- // Check if we have any listeners for this event
- if (eventListeners[eventName]) {
+ // Keep a list of listener indexes to destroy
+ const newEventListenerList = eventListeners[eventName]?.slice() || [];
- // Keep a list of listener indexes to destroy
- const newEventListenerList = eventListeners[eventName].slice();
+ // Check if we have any listeners for this event
+ if (newEventListenerList.length) {
// Iterate listeners
- for (let count = 0; count < eventListeners[eventName].length; count += 1) {
+ for (let count = newEventListenerList.length - 1; count >= 0; count -= 1) {
// Get next listener
- const listener = eventListeners[eventName][count];
+ const listener = newEventListenerList[count];
let data = eventData.data;
@@ -190,9 +190,9 @@ export function EventsOff(eventName, ...additionalEventNames) {
*/
export function EventsOffAll() {
const eventNames = Object.keys(eventListeners);
- for (let i = 0; i !== eventNames.length; i++) {
- removeListener(eventNames[i]);
- }
+ eventNames.forEach(eventName => {
+ removeListener(eventName)
+ })
}
/**
@@ -202,6 +202,8 @@ export function EventsOff(eventName, ...additionalEventNames) {
*/
function listenerOff(listener) {
const eventName = listener.eventName;
+ if (eventListeners[eventName] === undefined) return;
+
// Remove local listener
eventListeners[eventName] = eventListeners[eventName].filter(l => l !== listener);
diff --git a/v2/internal/frontend/runtime/desktop/main.js b/v2/internal/frontend/runtime/desktop/main.js
index 714c188b2..3fda7ef36 100644
--- a/v2/internal/frontend/runtime/desktop/main.js
+++ b/v2/internal/frontend/runtime/desktop/main.js
@@ -9,14 +9,24 @@ The electron alternative for Go
*/
/* jshint esversion: 9 */
import * as Log from './log';
-import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events';
-import {Call, Callback, callbacks} from './calls';
-import {SetBindings} from "./bindings";
+import {
+ eventListeners,
+ EventsEmit,
+ EventsNotify,
+ EventsOff,
+ EventsOffAll,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+} from "./events";
+import { Call, Callback, callbacks } from './calls';
+import { SetBindings } from "./bindings";
import * as Window from "./window";
import * as Screen from "./screen";
import * as Browser from "./browser";
import * as Clipboard from "./clipboard";
-
+import * as DragAndDrop from "./draganddrop";
+import * as ContextMenu from "./contextmenu";
export function Quit() {
window.WailsInvoke('Q');
@@ -41,11 +51,13 @@ window.runtime = {
...Browser,
...Screen,
...Clipboard,
+ ...DragAndDrop,
EventsOn,
EventsOnce,
EventsOnMultiple,
EventsEmit,
EventsOff,
+ EventsOffAll,
Environment,
Show,
Hide,
@@ -61,14 +73,17 @@ window.wails = {
callbacks,
flags: {
disableScrollbarDrag: false,
- disableWailsDefaultContextMenu: false,
+ disableDefaultContextMenu: false,
enableResize: false,
defaultCursor: null,
borderThickness: 6,
shouldDrag: false,
- deferDragToMouseMove: false,
+ deferDragToMouseMove: true,
cssDragProperty: "--wails-draggable",
cssDragValue: "drag",
+ cssDropProperty: "--wails-drop-target",
+ cssDropValue: "drop",
+ enableWailsDragAndDrop: false,
}
};
@@ -78,19 +93,17 @@ if (window.wailsbindings) {
delete window.wails.SetBindings;
}
-// This is evaluated at build time in package.json
-// const dev = 0;
-// const production = 1;
-if (ENV === 1) {
+// (bool) This is evaluated at build time in package.json
+if (!DEBUG) {
delete window.wailsbindings;
}
-let dragTest = function (e) {
+let dragTest = function(e) {
var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);
if (val) {
- val = val.trim();
+ val = val.trim();
}
-
+
if (val !== window.wails.flags.cssDragValue) {
return false;
}
@@ -108,13 +121,17 @@ let dragTest = function (e) {
return true;
};
-window.wails.setCSSDragProperties = function (property, value) {
+window.wails.setCSSDragProperties = function(property, value) {
window.wails.flags.cssDragProperty = property;
window.wails.flags.cssDragValue = value;
}
-window.addEventListener('mousedown', (e) => {
+window.wails.setCSSDropProperties = function(property, value) {
+ window.wails.flags.cssDropProperty = property;
+ window.wails.flags.cssDropValue = value;
+}
+window.addEventListener('mousedown', (e) => {
// Check for resizing
if (window.wails.flags.resizeEdge) {
window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
@@ -130,7 +147,7 @@ window.addEventListener('mousedown', (e) => {
}
}
if (window.wails.flags.deferDragToMouseMove) {
- window.wails.flags.shouldDrag = true;
+ window.wails.flags.shouldDrag = true;
} else {
e.preventDefault()
window.WailsInvoke("drag");
@@ -150,12 +167,11 @@ function setResize(cursor) {
window.wails.flags.resizeEdge = cursor;
}
-window.addEventListener('mousemove', function (e) {
+window.addEventListener('mousemove', function(e) {
if (window.wails.flags.shouldDrag) {
+ window.wails.flags.shouldDrag = false;
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
- if(mousePressed <= 0) {
- window.wails.flags.shouldDrag = false;
- } else {
+ if (mousePressed > 0) {
window.WailsInvoke("drag");
return;
}
@@ -189,9 +205,14 @@ window.addEventListener('mousemove', function (e) {
});
// Setup context menu hook
-window.addEventListener('contextmenu', function (e) {
- if (window.wails.flags.disableWailsDefaultContextMenu) {
+window.addEventListener('contextmenu', function(e) {
+ // always show the contextmenu in debug & dev
+ if (DEBUG) return;
+
+ if (window.wails.flags.disableDefaultContextMenu) {
e.preventDefault();
+ } else {
+ ContextMenu.processDefaultContextMenu(e);
}
});
diff --git a/v2/internal/frontend/runtime/dev/main.js b/v2/internal/frontend/runtime/dev/main.js
index e6e05be54..c7f31b0f2 100644
--- a/v2/internal/frontend/runtime/dev/main.js
+++ b/v2/internal/frontend/runtime/dev/main.js
@@ -80,7 +80,7 @@ function handleDisconnect() {
function _connect() {
if (websocket == null) {
- websocket = new WebSocket('ws://' + window.location.host + '/wails/ipc');
+ websocket = new WebSocket((window.location.protocol.startsWith("https") ? "wss://" : "ws://") + window.location.host + "/wails/ipc");
websocket.onopen = handleConnect;
websocket.onerror = function (e) {
e.stopImmediatePropagation();
diff --git a/v2/internal/frontend/runtime/events.go b/v2/internal/frontend/runtime/events.go
index 2725817ce..1f2e0a6e4 100644
--- a/v2/internal/frontend/runtime/events.go
+++ b/v2/internal/frontend/runtime/events.go
@@ -69,6 +69,7 @@ func (e *Events) OffAll() {
for eventName := range e.listeners {
delete(e.listeners, eventName)
}
+ e.notifyLock.Unlock()
}
// NewEvents creates a new log subsystem
@@ -115,6 +116,8 @@ func (e *Events) unRegisterListener(eventName string) {
// Notify backend for the given event name
func (e *Events) notifyBackend(eventName string, data ...interface{}) {
+ e.notifyLock.Lock()
+ defer e.notifyLock.Unlock()
// Get list of event listeners
listeners := e.listeners[eventName]
@@ -123,9 +126,6 @@ func (e *Events) notifyBackend(eventName string, data ...interface{}) {
return
}
- // Lock the listeners
- e.notifyLock.Lock()
-
// We have a dirty flag to indicate that there are items to delete
itemsToDelete := false
@@ -143,7 +143,7 @@ func (e *Events) notifyBackend(eventName string, data ...interface{}) {
}
// Do we have items to delete?
- if itemsToDelete == true {
+ if itemsToDelete {
// Create a new Listeners slice
var newListeners []*eventListener
@@ -163,9 +163,6 @@ func (e *Events) notifyBackend(eventName string, data ...interface{}) {
delete(e.listeners, eventName)
}
}
-
- // Unlock
- e.notifyLock.Unlock()
}
func (e *Events) AddFrontend(appFrontend frontend.Frontend) {
diff --git a/v2/internal/frontend/runtime/ipc_websocket.js b/v2/internal/frontend/runtime/ipc_websocket.js
index d5dca66af..1ca048df1 100644
--- a/v2/internal/frontend/runtime/ipc_websocket.js
+++ b/v2/internal/frontend/runtime/ipc_websocket.js
@@ -1,10 +1,10 @@
-(()=>{function D(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function p(){}var A=t=>t;function N(t){return t()}function it(){return Object.create(null)}function b(t){t.forEach(N)}function w(t){return typeof t=="function"}function L(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function ot(t){return Object.keys(t).length===0}function rt(t,...e){if(t==null)return p;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function st(t,e,n){t.$$.on_destroy.push(rt(e,n))}var ct=typeof window!="undefined",Ot=ct?()=>window.performance.now():()=>Date.now(),P=ct?t=>requestAnimationFrame(t):p;var x=new Set;function lt(t){x.forEach(e=>{e.c(t)||(x.delete(e),e.f())}),x.size!==0&&P(lt)}function Dt(t){let e;return x.size===0&&P(lt),{promise:new Promise(n=>{x.add(e={c:t,f:n})}),abort(){x.delete(e)}}}var ut=!1;function At(){ut=!0}function Lt(){ut=!1}function Bt(t,e){t.appendChild(e)}function at(t,e,n){let i=R(t);if(!i.getElementById(e)){let o=B("style");o.id=e,o.textContent=n,ft(i,o)}}function R(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e&&e.host?e:t.ownerDocument}function Tt(t){let e=B("style");return ft(R(t),e),e.sheet}function ft(t,e){return Bt(t.head||t,e),e.sheet}function W(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode.removeChild(t)}function B(t){return document.createElement(t)}function Jt(t){return document.createTextNode(t)}function dt(){return Jt("")}function ht(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function zt(t){return Array.from(t.childNodes)}function Ht(t,e,{bubbles:n=!1,cancelable:i=!1}={}){let o=document.createEvent("CustomEvent");return o.initCustomEvent(t,n,i,e),o}var T=new Map,J=0;function Gt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function qt(t,e){let n={stylesheet:Tt(e),rules:{}};return T.set(t,n),n}function _t(t,e,n,i,o,c,s,l=0){let f=16.666/i,r=`{
+(()=>{function D(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function _(){}var A=t=>t;function N(t){return t()}function it(){return Object.create(null)}function b(t){t.forEach(N)}function w(t){return typeof t=="function"}function L(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function ot(t){return Object.keys(t).length===0}function rt(t,...e){if(t==null)return _;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function st(t,e,n){t.$$.on_destroy.push(rt(e,n))}var ct=typeof window!="undefined",Ot=ct?()=>window.performance.now():()=>Date.now(),P=ct?t=>requestAnimationFrame(t):_;var x=new Set;function lt(t){x.forEach(e=>{e.c(t)||(x.delete(e),e.f())}),x.size!==0&&P(lt)}function Dt(t){let e;return x.size===0&&P(lt),{promise:new Promise(n=>{x.add(e={c:t,f:n})}),abort(){x.delete(e)}}}var ut=!1;function At(){ut=!0}function Lt(){ut=!1}function Bt(t,e){t.appendChild(e)}function at(t,e,n){let i=R(t);if(!i.getElementById(e)){let o=B("style");o.id=e,o.textContent=n,ft(i,o)}}function R(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e&&e.host?e:t.ownerDocument}function Tt(t){let e=B("style");return ft(R(t),e),e.sheet}function ft(t,e){return Bt(t.head||t,e),e.sheet}function W(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode.removeChild(t)}function B(t){return document.createElement(t)}function Jt(t){return document.createTextNode(t)}function dt(){return Jt("")}function ht(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function zt(t){return Array.from(t.childNodes)}function Ht(t,e,{bubbles:n=!1,cancelable:i=!1}={}){let o=document.createEvent("CustomEvent");return o.initCustomEvent(t,n,i,e),o}var T=new Map,J=0;function Gt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function qt(t,e){let n={stylesheet:Tt(e),rules:{}};return T.set(t,n),n}function pt(t,e,n,i,o,c,s,l=0){let f=16.666/i,r=`{
`;for(let g=0;g<=1;g+=f){let F=e+(n-e)*c(g);r+=g*100+`%{${s(F,1-F)}}
`}let y=r+`100% {${s(n,1-n)}}
-}`,a=`__svelte_${Gt(y)}_${l}`,u=R(t),{stylesheet:h,rules:_}=T.get(u)||qt(u,t);_[a]||(_[a]=!0,h.insertRule(`@keyframes ${a} ${y}`,h.cssRules.length));let v=t.style.animation||"";return t.style.animation=`${v?`${v}, `:""}${a} ${i}ms linear ${o}ms 1 both`,J+=1,a}function Kt(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),J-=o,J||Nt())}function Nt(){P(()=>{J||(T.forEach(t=>{let{ownerNode:e}=t.stylesheet;e&&S(e)}),T.clear())})}var V;function C(t){V=t}var k=[];var pt=[],z=[],mt=[],Pt=Promise.resolve(),U=!1;function Rt(){U||(U=!0,Pt.then(yt))}function $(t){z.push(t)}var X=new Set,H=0;function yt(){let t=V;do{for(;H{E=null})),E}function Z(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var G=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(G.delete(t),t.i(e))}function Q(t,e,n,i){if(t&&t.o){if(G.has(t))return;G.add(t),m.c.push(()=>{G.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}var Ut={duration:0};function Y(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,f=null;function r(){f&&Kt(t,f)}function y(u,h){let _=u.b-c;return h*=Math.abs(_),{a:c,b:u.b,d:_,duration:h,start:u.start,end:u.start+h,group:u.group}}function a(u){let{delay:h=0,duration:_=300,easing:v=A,tick:g=p,css:F}=o||Ut,K={start:Ot()+h,b:u};u||(K.group=m,m.r+=1),s||l?l=K:(F&&(r(),f=_t(t,c,u,_,h,v,F)),u&&g(0,1),s=y(K,_),$(()=>Z(t,u,"start")),Dt(O=>{if(l&&O>l.start&&(s=y(l,_),l=null,Z(t,s.b,"start"),F&&(r(),f=_t(t,c,s.b,s.duration,0,v,o.css))),s){if(O>=s.end)g(c=s.b,1-c),Z(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(O>=s.start){let jt=O-s.start;c=s.a+s.d*v(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){w(o)?Vt().then(()=>{o=o(),a(u)}):a(u)},end(){r(),s=l=null}}}var le=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var ue=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Xt(t,e,n,i){let{fragment:o,after_update:c}=t.$$;o&&o.m(e,n),i||$(()=>{let s=t.$$.on_mount.map(N).filter(w);t.$$.on_destroy?t.$$.on_destroy.push(...s):b(s),t.$$.on_mount=[]}),c.forEach($)}function wt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Zt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let _=h.length?h[0]:u;return r.ctx&&o(r.ctx[a],r.ctx[a]=_)&&(!r.skip_bound&&r.bound[a]&&r.bound[a](_),y&&Zt(t,a)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){At();let a=zt(e.target);r.fragment&&r.fragment.l(a),a.forEach(S)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Xt(t,e.target,e.anchor,e.customElement),Lt(),yt()}C(f)}var Qt;typeof HTMLElement=="function"&&(Qt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(N).filter(w);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){wt(this,1),this.$destroy=p}$on(t,e){if(!w(e))return p;let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!ot(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var tt=class{$destroy(){wt(this,1),this.$destroy=p}$on(e,n){if(!w(n))return p;let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!ot(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=p){let n,i=new Set;function o(l){if(L(t,l)&&(t=l,n)){let f=!M.length;for(let r of i)r[1](),M.push(r,t);if(f){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var q=Ft(!1);function xt(){q.set(!0)}function $t(){q.set(!1)}function et(t,{delay:e=0,duration:n=400,easing:i=A}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Yt(t){at(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999
- }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,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);background-repeat:no-repeat;background-position:center
- }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em
- }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function Mt(t){let e,n,i;return{c(){e=B("div"),e.innerHTML='',ht(e,"class","wails-reconnect-overlay svelte-181h7z")},m(o,c){W(o,e,c),i=!0},i(o){i||($(()=>{n||(n=Y(e,et,{duration:300},!0)),n.run(1)}),i=!0)},o(o){n||(n=Y(e,et,{duration:300},!1)),n.run(0),i=!1},d(o){o&&S(e),o&&n&&n.end()}}}function te(t){let e,n,i=t[0]&&Mt(t);return{c(){i&&i.c(),e=dt()},m(o,c){i&&i.m(o,c),W(o,e,c),n=!0},p(o,[c]){o[0]?i?c&1&&I(i,1):(i=Mt(o),i.c(),I(i,1),i.m(e.parentNode,e)):i&&(gt(),Q(i,1,1,()=>{i=null}),bt())},i(o){n||(I(i),n=!0)},o(o){Q(i),n=!1},d(o){i&&i.d(o),o&&S(e)}}}function ee(t,e,n){let i;return st(t,q,o=>n(0,i=o)),[i]}var St=class extends tt{constructor(e){super();vt(this,e,ee,te,L,{},Yt)}},Ct=St;var ne={},nt=null,j=[];window.WailsInvoke=t=>{if(!nt){console.log("Queueing: "+t),j.push(t);return}nt(t)};window.addEventListener("DOMContentLoaded",()=>{ne.overlay=new Ct({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,kt;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};It();function ie(){nt=t=>{d.send(t)};for(let t=0;tc.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),J-=o,J||Nt())}function Nt(){P(()=>{J||(T.forEach(t=>{let{ownerNode:e}=t.stylesheet;e&&S(e)}),T.clear())})}var V;function C(t){V=t}var k=[];var _t=[],z=[],mt=[],Pt=Promise.resolve(),U=!1;function Rt(){U||(U=!0,Pt.then(yt))}function $(t){z.push(t)}var X=new Set,H=0;function yt(){let t=V;do{for(;H{E=null})),E}function Z(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var G=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(G.delete(t),t.i(e))}function Q(t,e,n,i){if(t&&t.o){if(G.has(t))return;G.add(t),m.c.push(()=>{G.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}var Ut={duration:0};function Y(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,f=null;function r(){f&&Kt(t,f)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function a(u){let{delay:h=0,duration:p=300,easing:v=A,tick:g=_,css:F}=o||Ut,K={start:Ot()+h,b:u};u||(K.group=m,m.r+=1),s||l?l=K:(F&&(r(),f=pt(t,c,u,p,h,v,F)),u&&g(0,1),s=y(K,p),$(()=>Z(t,u,"start")),Dt(O=>{if(l&&O>l.start&&(s=y(l,p),l=null,Z(t,s.b,"start"),F&&(r(),f=pt(t,c,s.b,s.duration,0,v,o.css))),s){if(O>=s.end)g(c=s.b,1-c),Z(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(O>=s.start){let jt=O-s.start;c=s.a+s.d*v(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){w(o)?Vt().then(()=>{o=o(),a(u)}):a(u)},end(){r(),s=l=null}}}var le=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var ue=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Xt(t,e,n,i){let{fragment:o,after_update:c}=t.$$;o&&o.m(e,n),i||$(()=>{let s=t.$$.on_mount.map(N).filter(w);t.$$.on_destroy?t.$$.on_destroy.push(...s):b(s),t.$$.on_mount=[]}),c.forEach($)}function wt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Zt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return r.ctx&&o(r.ctx[a],r.ctx[a]=p)&&(!r.skip_bound&&r.bound[a]&&r.bound[a](p),y&&Zt(t,a)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){At();let a=zt(e.target);r.fragment&&r.fragment.l(a),a.forEach(S)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Xt(t,e.target,e.anchor,e.customElement),Lt(),yt()}C(f)}var Qt;typeof HTMLElement=="function"&&(Qt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(N).filter(w);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){wt(this,1),this.$destroy=_}$on(t,e){if(!w(e))return _;let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!ot(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var tt=class{$destroy(){wt(this,1),this.$destroy=_}$on(e,n){if(!w(n))return _;let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!ot(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=_){let n,i=new Set;function o(l){if(L(t,l)&&(t=l,n)){let f=!M.length;for(let r of i)r[1](),M.push(r,t);if(f){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var q=Ft(!1);function xt(){q.set(!0)}function $t(){q.set(!1)}function et(t,{delay:e=0,duration:n=400,easing:i=A}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Yt(t){at(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999\r
+ }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,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);background-repeat:no-repeat;background-position:center\r
+ }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em\r
+ }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function Mt(t){let e,n,i;return{c(){e=B("div"),e.innerHTML='',ht(e,"class","wails-reconnect-overlay svelte-181h7z")},m(o,c){W(o,e,c),i=!0},i(o){i||($(()=>{n||(n=Y(e,et,{duration:300},!0)),n.run(1)}),i=!0)},o(o){n||(n=Y(e,et,{duration:300},!1)),n.run(0),i=!1},d(o){o&&S(e),o&&n&&n.end()}}}function te(t){let e,n,i=t[0]&&Mt(t);return{c(){i&&i.c(),e=dt()},m(o,c){i&&i.m(o,c),W(o,e,c),n=!0},p(o,[c]){o[0]?i?c&1&&I(i,1):(i=Mt(o),i.c(),I(i,1),i.m(e.parentNode,e)):i&&(gt(),Q(i,1,1,()=>{i=null}),bt())},i(o){n||(I(i),n=!0)},o(o){Q(i),n=!1},d(o){i&&i.d(o),o&&S(e)}}}function ee(t,e,n){let i;return st(t,q,o=>n(0,i=o)),[i]}var St=class extends tt{constructor(e){super();vt(this,e,ee,te,L,{},Yt)}},Ct=St;var ne={},nt=null,j=[];window.WailsInvoke=t=>{if(!nt){console.log("Queueing: "+t),j.push(t);return}nt(t)};window.addEventListener("DOMContentLoaded",()=>{ne.overlay=new Ct({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,kt;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};It();function ie(){nt=t=>{d.send(t)};for(let t=0;t= 14",
"less": "*",
"sass": "*",
"stylus": "*",
+ "sugarss": "*",
"terser": "^5.4.0"
},
"peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
"less": {
"optional": true
},
@@ -1890,6 +1905,9 @@
"stylus": {
"optional": true
},
+ "sugarss": {
+ "optional": true
+ },
"terser": {
"optional": true
}
@@ -2518,9 +2536,9 @@
}
},
"fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"optional": true
},
@@ -2829,9 +2847,9 @@
"dev": true
},
"nanoid": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
- "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true
},
"nice-try": {
@@ -2964,12 +2982,12 @@
"dev": true
},
"postcss": {
- "version": "8.4.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
- "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"requires": {
- "nanoid": "^3.3.4",
+ "nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@@ -3036,9 +3054,9 @@
}
},
"rollup": {
- "version": "2.78.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz",
- "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==",
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
"dev": true,
"requires": {
"fsevents": "~2.3.2"
@@ -3057,9 +3075,9 @@
"dev": true
},
"semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
},
"shebang-command": {
@@ -3320,16 +3338,16 @@
}
},
"vite": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz",
- "integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==",
+ "version": "3.2.10",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.10.tgz",
+ "integrity": "sha512-Dx3olBo/ODNiMVk/cA5Yft9Ws+snLOXrhLtrI3F4XLt4syz2Yg8fayZMWScPKoz12v5BUv7VEmQHnsfpY80fYw==",
"dev": true,
"requires": {
"esbuild": "^0.15.9",
"fsevents": "~2.3.2",
- "postcss": "^8.4.16",
+ "postcss": "^8.4.18",
"resolve": "^1.22.1",
- "rollup": "~2.78.0"
+ "rollup": "^2.79.1"
}
},
"vitest": {
diff --git a/v2/internal/frontend/runtime/package.json b/v2/internal/frontend/runtime/package.json
index aa6c3aad5..09ff4d50f 100644
--- a/v2/internal/frontend/runtime/package.json
+++ b/v2/internal/frontend/runtime/package.json
@@ -7,8 +7,8 @@
"build": "run-p build:*",
"build:ipc-desktop": "npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js",
"build:ipc-dev": "cd dev && npm install && npm run build",
- "build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
- "build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
+ "build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:DEBUG=false",
+ "build:runtime-desktop-debug": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_desktop.js --define:DEBUG=true",
"test": "vitest"
},
"author": "Lea Anthony ",
diff --git a/v2/internal/frontend/runtime/runtime_debug_desktop.go b/v2/internal/frontend/runtime/runtime_debug_desktop.go
new file mode 100644
index 000000000..8dff343c0
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_debug_desktop.go
@@ -0,0 +1,8 @@
+//go:build debug || !production
+
+package runtime
+
+import _ "embed"
+
+//go:embed runtime_debug_desktop.js
+var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_debug_desktop.js b/v2/internal/frontend/runtime/runtime_debug_desktop.js
new file mode 100644
index 000000000..a5f6068e9
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_debug_desktop.js
@@ -0,0 +1,792 @@
+(() => {
+ var __defProp = Object.defineProperty;
+ var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+ };
+
+ // desktop/log.js
+ var log_exports = {};
+ __export(log_exports, {
+ LogDebug: () => LogDebug,
+ LogError: () => LogError,
+ LogFatal: () => LogFatal,
+ LogInfo: () => LogInfo,
+ LogLevel: () => LogLevel,
+ LogPrint: () => LogPrint,
+ LogTrace: () => LogTrace,
+ LogWarning: () => LogWarning,
+ SetLogLevel: () => SetLogLevel
+ });
+ function sendLogMessage(level, message) {
+ window.WailsInvoke("L" + level + message);
+ }
+ function LogTrace(message) {
+ sendLogMessage("T", message);
+ }
+ function LogPrint(message) {
+ sendLogMessage("P", message);
+ }
+ function LogDebug(message) {
+ sendLogMessage("D", message);
+ }
+ function LogInfo(message) {
+ sendLogMessage("I", message);
+ }
+ function LogWarning(message) {
+ sendLogMessage("W", message);
+ }
+ function LogError(message) {
+ sendLogMessage("E", message);
+ }
+ function LogFatal(message) {
+ sendLogMessage("F", message);
+ }
+ function SetLogLevel(loglevel) {
+ sendLogMessage("S", loglevel);
+ }
+ var LogLevel = {
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARNING: 4,
+ ERROR: 5
+ };
+
+ // desktop/events.js
+ var Listener = class {
+ constructor(eventName, callback, maxCallbacks) {
+ this.eventName = eventName;
+ this.maxCallbacks = maxCallbacks || -1;
+ this.Callback = (data) => {
+ callback.apply(null, data);
+ if (this.maxCallbacks === -1) {
+ return false;
+ }
+ this.maxCallbacks -= 1;
+ return this.maxCallbacks === 0;
+ };
+ }
+ };
+ var eventListeners = {};
+ function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ eventListeners[eventName] = eventListeners[eventName] || [];
+ const thisListener = new Listener(eventName, callback, maxCallbacks);
+ eventListeners[eventName].push(thisListener);
+ return () => listenerOff(thisListener);
+ }
+ function EventsOn(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, -1);
+ }
+ function EventsOnce(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, 1);
+ }
+ function notifyListeners(eventData) {
+ let eventName = eventData.name;
+ const newEventListenerList = eventListeners[eventName]?.slice() || [];
+ if (newEventListenerList.length) {
+ for (let count = newEventListenerList.length - 1; count >= 0; count -= 1) {
+ const listener = newEventListenerList[count];
+ let data = eventData.data;
+ const destroy = listener.Callback(data);
+ if (destroy) {
+ newEventListenerList.splice(count, 1);
+ }
+ }
+ if (newEventListenerList.length === 0) {
+ removeListener(eventName);
+ } else {
+ eventListeners[eventName] = newEventListenerList;
+ }
+ }
+ }
+ function EventsNotify(notifyMessage) {
+ let message;
+ try {
+ message = JSON.parse(notifyMessage);
+ } catch (e) {
+ const error = "Invalid JSON passed to Notify: " + notifyMessage;
+ throw new Error(error);
+ }
+ notifyListeners(message);
+ }
+ function EventsEmit(eventName) {
+ const payload = {
+ name: eventName,
+ data: [].slice.apply(arguments).slice(1)
+ };
+ notifyListeners(payload);
+ window.WailsInvoke("EE" + JSON.stringify(payload));
+ }
+ function removeListener(eventName) {
+ delete eventListeners[eventName];
+ window.WailsInvoke("EX" + eventName);
+ }
+ function EventsOff(eventName, ...additionalEventNames) {
+ removeListener(eventName);
+ if (additionalEventNames.length > 0) {
+ additionalEventNames.forEach((eventName2) => {
+ removeListener(eventName2);
+ });
+ }
+ }
+ function EventsOffAll() {
+ const eventNames = Object.keys(eventListeners);
+ eventNames.forEach((eventName) => {
+ removeListener(eventName);
+ });
+ }
+ function listenerOff(listener) {
+ const eventName = listener.eventName;
+ if (eventListeners[eventName] === void 0)
+ return;
+ eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener);
+ if (eventListeners[eventName].length === 0) {
+ removeListener(eventName);
+ }
+ }
+
+ // desktop/calls.js
+ var callbacks = {};
+ function cryptoRandom() {
+ var array = new Uint32Array(1);
+ return window.crypto.getRandomValues(array)[0];
+ }
+ function basicRandom() {
+ return Math.random() * 9007199254740991;
+ }
+ var randomFunc;
+ if (window.crypto) {
+ randomFunc = cryptoRandom;
+ } else {
+ randomFunc = basicRandom;
+ }
+ function Call(name, args, timeout) {
+ if (timeout == null) {
+ timeout = 0;
+ }
+ return new Promise(function(resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = name + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function() {
+ reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
+ const payload = {
+ name,
+ args,
+ callbackID
+ };
+ window.WailsInvoke("C" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+ window.ObfuscatedCall = (id, args, timeout) => {
+ if (timeout == null) {
+ timeout = 0;
+ }
+ return new Promise(function(resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = id + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function() {
+ reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
+ const payload = {
+ id,
+ args,
+ callbackID
+ };
+ window.WailsInvoke("c" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ };
+ function Callback(incomingMessage) {
+ let message;
+ try {
+ message = JSON.parse(incomingMessage);
+ } catch (e) {
+ const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
+ runtime.LogDebug(error);
+ throw new Error(error);
+ }
+ let callbackID = message.callbackid;
+ let callbackData = callbacks[callbackID];
+ if (!callbackData) {
+ const error = `Callback '${callbackID}' not registered!!!`;
+ console.error(error);
+ throw new Error(error);
+ }
+ clearTimeout(callbackData.timeoutHandle);
+ delete callbacks[callbackID];
+ if (message.error) {
+ callbackData.reject(message.error);
+ } else {
+ callbackData.resolve(message.result);
+ }
+ }
+
+ // desktop/bindings.js
+ window.go = {};
+ function SetBindings(bindingsMap) {
+ try {
+ bindingsMap = JSON.parse(bindingsMap);
+ } catch (e) {
+ console.error(e);
+ }
+ window.go = window.go || {};
+ Object.keys(bindingsMap).forEach((packageName) => {
+ window.go[packageName] = window.go[packageName] || {};
+ Object.keys(bindingsMap[packageName]).forEach((structName) => {
+ window.go[packageName][structName] = window.go[packageName][structName] || {};
+ Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
+ window.go[packageName][structName][methodName] = function() {
+ let timeout = 0;
+ function dynamic() {
+ const args = [].slice.call(arguments);
+ return Call([packageName, structName, methodName].join("."), args, timeout);
+ }
+ dynamic.setTimeout = function(newTimeout) {
+ timeout = newTimeout;
+ };
+ dynamic.getTimeout = function() {
+ return timeout;
+ };
+ return dynamic;
+ }();
+ });
+ });
+ });
+ }
+
+ // desktop/window.js
+ var window_exports = {};
+ __export(window_exports, {
+ WindowCenter: () => WindowCenter,
+ WindowFullscreen: () => WindowFullscreen,
+ WindowGetPosition: () => WindowGetPosition,
+ WindowGetSize: () => WindowGetSize,
+ WindowHide: () => WindowHide,
+ WindowIsFullscreen: () => WindowIsFullscreen,
+ WindowIsMaximised: () => WindowIsMaximised,
+ WindowIsMinimised: () => WindowIsMinimised,
+ WindowIsNormal: () => WindowIsNormal,
+ WindowMaximise: () => WindowMaximise,
+ WindowMinimise: () => WindowMinimise,
+ WindowReload: () => WindowReload,
+ WindowReloadApp: () => WindowReloadApp,
+ WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop,
+ WindowSetBackgroundColour: () => WindowSetBackgroundColour,
+ WindowSetDarkTheme: () => WindowSetDarkTheme,
+ WindowSetLightTheme: () => WindowSetLightTheme,
+ WindowSetMaxSize: () => WindowSetMaxSize,
+ WindowSetMinSize: () => WindowSetMinSize,
+ WindowSetPosition: () => WindowSetPosition,
+ WindowSetSize: () => WindowSetSize,
+ WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme,
+ WindowSetTitle: () => WindowSetTitle,
+ WindowShow: () => WindowShow,
+ WindowToggleMaximise: () => WindowToggleMaximise,
+ WindowUnfullscreen: () => WindowUnfullscreen,
+ WindowUnmaximise: () => WindowUnmaximise,
+ WindowUnminimise: () => WindowUnminimise
+ });
+ function WindowReload() {
+ window.location.reload();
+ }
+ function WindowReloadApp() {
+ window.WailsInvoke("WR");
+ }
+ function WindowSetSystemDefaultTheme() {
+ window.WailsInvoke("WASDT");
+ }
+ function WindowSetLightTheme() {
+ window.WailsInvoke("WALT");
+ }
+ function WindowSetDarkTheme() {
+ window.WailsInvoke("WADT");
+ }
+ function WindowCenter() {
+ window.WailsInvoke("Wc");
+ }
+ function WindowSetTitle(title) {
+ window.WailsInvoke("WT" + title);
+ }
+ function WindowFullscreen() {
+ window.WailsInvoke("WF");
+ }
+ function WindowUnfullscreen() {
+ window.WailsInvoke("Wf");
+ }
+ function WindowIsFullscreen() {
+ return Call(":wails:WindowIsFullscreen");
+ }
+ function WindowSetSize(width, height) {
+ window.WailsInvoke("Ws:" + width + ":" + height);
+ }
+ function WindowGetSize() {
+ return Call(":wails:WindowGetSize");
+ }
+ function WindowSetMaxSize(width, height) {
+ window.WailsInvoke("WZ:" + width + ":" + height);
+ }
+ function WindowSetMinSize(width, height) {
+ window.WailsInvoke("Wz:" + width + ":" + height);
+ }
+ function WindowSetAlwaysOnTop(b) {
+ window.WailsInvoke("WATP:" + (b ? "1" : "0"));
+ }
+ function WindowSetPosition(x, y) {
+ window.WailsInvoke("Wp:" + x + ":" + y);
+ }
+ function WindowGetPosition() {
+ return Call(":wails:WindowGetPos");
+ }
+ function WindowHide() {
+ window.WailsInvoke("WH");
+ }
+ function WindowShow() {
+ window.WailsInvoke("WS");
+ }
+ function WindowMaximise() {
+ window.WailsInvoke("WM");
+ }
+ function WindowToggleMaximise() {
+ window.WailsInvoke("Wt");
+ }
+ function WindowUnmaximise() {
+ window.WailsInvoke("WU");
+ }
+ function WindowIsMaximised() {
+ return Call(":wails:WindowIsMaximised");
+ }
+ function WindowMinimise() {
+ window.WailsInvoke("Wm");
+ }
+ function WindowUnminimise() {
+ window.WailsInvoke("Wu");
+ }
+ function WindowIsMinimised() {
+ return Call(":wails:WindowIsMinimised");
+ }
+ function WindowIsNormal() {
+ return Call(":wails:WindowIsNormal");
+ }
+ function WindowSetBackgroundColour(R, G, B, A) {
+ let rgba = JSON.stringify({ r: R || 0, g: G || 0, b: B || 0, a: A || 255 });
+ window.WailsInvoke("Wr:" + rgba);
+ }
+
+ // desktop/screen.js
+ var screen_exports = {};
+ __export(screen_exports, {
+ ScreenGetAll: () => ScreenGetAll
+ });
+ function ScreenGetAll() {
+ return Call(":wails:ScreenGetAll");
+ }
+
+ // desktop/browser.js
+ var browser_exports = {};
+ __export(browser_exports, {
+ BrowserOpenURL: () => BrowserOpenURL
+ });
+ function BrowserOpenURL(url) {
+ window.WailsInvoke("BO:" + url);
+ }
+
+ // desktop/clipboard.js
+ var clipboard_exports = {};
+ __export(clipboard_exports, {
+ ClipboardGetText: () => ClipboardGetText,
+ ClipboardSetText: () => ClipboardSetText
+ });
+ function ClipboardSetText(text) {
+ return Call(":wails:ClipboardSetText", [text]);
+ }
+ function ClipboardGetText() {
+ return Call(":wails:ClipboardGetText");
+ }
+
+ // desktop/draganddrop.js
+ var draganddrop_exports = {};
+ __export(draganddrop_exports, {
+ CanResolveFilePaths: () => CanResolveFilePaths,
+ OnFileDrop: () => OnFileDrop,
+ OnFileDropOff: () => OnFileDropOff,
+ ResolveFilePaths: () => ResolveFilePaths
+ });
+ var flags = {
+ registered: false,
+ defaultUseDropTarget: true,
+ useDropTarget: true,
+ nextDeactivate: null,
+ nextDeactivateTimeout: null
+ };
+ var DROP_TARGET_ACTIVE = "wails-drop-target-active";
+ function checkStyleDropTarget(style) {
+ const cssDropValue = style.getPropertyValue(window.wails.flags.cssDropProperty).trim();
+ if (cssDropValue) {
+ if (cssDropValue === window.wails.flags.cssDropValue) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+ function onDragOver(e) {
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+ if (!isFileDrop) {
+ return;
+ }
+ e.preventDefault();
+ e.dataTransfer.dropEffect = "copy";
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+ if (!flags.useDropTarget) {
+ return;
+ }
+ const element = e.target;
+ if (flags.nextDeactivate)
+ flags.nextDeactivate();
+ if (!element || !checkStyleDropTarget(getComputedStyle(element))) {
+ return;
+ }
+ let currentElement = element;
+ while (currentElement) {
+ if (checkStyleDropTarget(getComputedStyle(currentElement))) {
+ currentElement.classList.add(DROP_TARGET_ACTIVE);
+ }
+ currentElement = currentElement.parentElement;
+ }
+ }
+ function onDragLeave(e) {
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+ if (!isFileDrop) {
+ return;
+ }
+ e.preventDefault();
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+ if (!flags.useDropTarget) {
+ return;
+ }
+ if (!e.target || !checkStyleDropTarget(getComputedStyle(e.target))) {
+ return null;
+ }
+ if (flags.nextDeactivate)
+ flags.nextDeactivate();
+ flags.nextDeactivate = () => {
+ Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach((el) => el.classList.remove(DROP_TARGET_ACTIVE));
+ flags.nextDeactivate = null;
+ if (flags.nextDeactivateTimeout) {
+ clearTimeout(flags.nextDeactivateTimeout);
+ flags.nextDeactivateTimeout = null;
+ }
+ };
+ flags.nextDeactivateTimeout = setTimeout(() => {
+ if (flags.nextDeactivate)
+ flags.nextDeactivate();
+ }, 50);
+ }
+ function onDrop(e) {
+ const isFileDrop = e.dataTransfer.types.includes("Files");
+ if (!isFileDrop) {
+ return;
+ }
+ e.preventDefault();
+ if (!window.wails.flags.enableWailsDragAndDrop) {
+ return;
+ }
+ if (CanResolveFilePaths()) {
+ let files = [];
+ if (e.dataTransfer.items) {
+ files = [...e.dataTransfer.items].map((item, i) => {
+ if (item.kind === "file") {
+ return item.getAsFile();
+ }
+ });
+ } else {
+ files = [...e.dataTransfer.files];
+ }
+ window.runtime.ResolveFilePaths(e.x, e.y, files);
+ }
+ if (!flags.useDropTarget) {
+ return;
+ }
+ if (flags.nextDeactivate)
+ flags.nextDeactivate();
+ Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach((el) => el.classList.remove(DROP_TARGET_ACTIVE));
+ }
+ function CanResolveFilePaths() {
+ return window.chrome?.webview?.postMessageWithAdditionalObjects != null;
+ }
+ function ResolveFilePaths(x, y, files) {
+ if (window.chrome?.webview?.postMessageWithAdditionalObjects) {
+ chrome.webview.postMessageWithAdditionalObjects(`file:drop:${x}:${y}`, files);
+ }
+ }
+ function OnFileDrop(callback, useDropTarget) {
+ if (typeof callback !== "function") {
+ console.error("DragAndDropCallback is not a function");
+ return;
+ }
+ if (flags.registered) {
+ return;
+ }
+ flags.registered = true;
+ const uDTPT = typeof useDropTarget;
+ flags.useDropTarget = uDTPT === "undefined" || uDTPT !== "boolean" ? flags.defaultUseDropTarget : useDropTarget;
+ window.addEventListener("dragover", onDragOver);
+ window.addEventListener("dragleave", onDragLeave);
+ window.addEventListener("drop", onDrop);
+ let cb = callback;
+ if (flags.useDropTarget) {
+ cb = function(x, y, paths) {
+ const element = document.elementFromPoint(x, y);
+ if (!element || !checkStyleDropTarget(getComputedStyle(element))) {
+ return null;
+ }
+ callback(x, y, paths);
+ };
+ }
+ EventsOn("wails:file-drop", cb);
+ }
+ function OnFileDropOff() {
+ window.removeEventListener("dragover", onDragOver);
+ window.removeEventListener("dragleave", onDragLeave);
+ window.removeEventListener("drop", onDrop);
+ EventsOff("wails:file-drop");
+ flags.registered = false;
+ }
+
+ // desktop/contextmenu.js
+ function processDefaultContextMenu(event) {
+ const element = event.target;
+ const computedStyle = window.getComputedStyle(element);
+ const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
+ switch (defaultContextMenuAction) {
+ case "show":
+ return;
+ case "hide":
+ event.preventDefault();
+ return;
+ default:
+ if (element.isContentEditable) {
+ return;
+ }
+ const selection = window.getSelection();
+ const hasSelection = selection.toString().length > 0;
+ if (hasSelection) {
+ for (let i = 0; i < selection.rangeCount; i++) {
+ const range = selection.getRangeAt(i);
+ const rects = range.getClientRects();
+ for (let j = 0; j < rects.length; j++) {
+ const rect = rects[j];
+ if (document.elementFromPoint(rect.left, rect.top) === element) {
+ return;
+ }
+ }
+ }
+ }
+ if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
+ if (hasSelection || !element.readOnly && !element.disabled) {
+ return;
+ }
+ }
+ event.preventDefault();
+ }
+ }
+
+ // desktop/main.js
+ function Quit() {
+ window.WailsInvoke("Q");
+ }
+ function Show() {
+ window.WailsInvoke("S");
+ }
+ function Hide() {
+ window.WailsInvoke("H");
+ }
+ function Environment() {
+ return Call(":wails:Environment");
+ }
+ window.runtime = {
+ ...log_exports,
+ ...window_exports,
+ ...browser_exports,
+ ...screen_exports,
+ ...clipboard_exports,
+ ...draganddrop_exports,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+ EventsEmit,
+ EventsOff,
+ EventsOffAll,
+ Environment,
+ Show,
+ Hide,
+ Quit
+ };
+ window.wails = {
+ Callback,
+ EventsNotify,
+ SetBindings,
+ eventListeners,
+ callbacks,
+ flags: {
+ disableScrollbarDrag: false,
+ disableDefaultContextMenu: false,
+ enableResize: false,
+ defaultCursor: null,
+ borderThickness: 6,
+ shouldDrag: false,
+ deferDragToMouseMove: true,
+ cssDragProperty: "--wails-draggable",
+ cssDragValue: "drag",
+ cssDropProperty: "--wails-drop-target",
+ cssDropValue: "drop",
+ enableWailsDragAndDrop: false
+ }
+ };
+ if (window.wailsbindings) {
+ window.wails.SetBindings(window.wailsbindings);
+ delete window.wails.SetBindings;
+ }
+ if (false) {
+ delete window.wailsbindings;
+ }
+ var dragTest = function(e) {
+ var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);
+ if (val) {
+ val = val.trim();
+ }
+ if (val !== window.wails.flags.cssDragValue) {
+ return false;
+ }
+ if (e.buttons !== 1) {
+ return false;
+ }
+ if (e.detail !== 1) {
+ return false;
+ }
+ return true;
+ };
+ window.wails.setCSSDragProperties = function(property, value) {
+ window.wails.flags.cssDragProperty = property;
+ window.wails.flags.cssDragValue = value;
+ };
+ window.wails.setCSSDropProperties = function(property, value) {
+ window.wails.flags.cssDropProperty = property;
+ window.wails.flags.cssDropValue = value;
+ };
+ window.addEventListener("mousedown", (e) => {
+ if (window.wails.flags.resizeEdge) {
+ window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
+ e.preventDefault();
+ return;
+ }
+ if (dragTest(e)) {
+ if (window.wails.flags.disableScrollbarDrag) {
+ if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
+ return;
+ }
+ }
+ if (window.wails.flags.deferDragToMouseMove) {
+ window.wails.flags.shouldDrag = true;
+ } else {
+ e.preventDefault();
+ window.WailsInvoke("drag");
+ }
+ return;
+ } else {
+ window.wails.flags.shouldDrag = false;
+ }
+ });
+ window.addEventListener("mouseup", () => {
+ window.wails.flags.shouldDrag = false;
+ });
+ function setResize(cursor) {
+ document.documentElement.style.cursor = cursor || window.wails.flags.defaultCursor;
+ window.wails.flags.resizeEdge = cursor;
+ }
+ window.addEventListener("mousemove", function(e) {
+ if (window.wails.flags.shouldDrag) {
+ window.wails.flags.shouldDrag = false;
+ let mousePressed = e.buttons !== void 0 ? e.buttons : e.which;
+ if (mousePressed > 0) {
+ window.WailsInvoke("drag");
+ return;
+ }
+ }
+ if (!window.wails.flags.enableResize) {
+ return;
+ }
+ if (window.wails.flags.defaultCursor == null) {
+ window.wails.flags.defaultCursor = document.documentElement.style.cursor;
+ }
+ if (window.outerWidth - e.clientX < window.wails.flags.borderThickness && window.outerHeight - e.clientY < window.wails.flags.borderThickness) {
+ document.documentElement.style.cursor = "se-resize";
+ }
+ let rightBorder = window.outerWidth - e.clientX < window.wails.flags.borderThickness;
+ let leftBorder = e.clientX < window.wails.flags.borderThickness;
+ let topBorder = e.clientY < window.wails.flags.borderThickness;
+ let bottomBorder = window.outerHeight - e.clientY < window.wails.flags.borderThickness;
+ if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && window.wails.flags.resizeEdge !== void 0) {
+ setResize();
+ } else if (rightBorder && bottomBorder)
+ setResize("se-resize");
+ else if (leftBorder && bottomBorder)
+ setResize("sw-resize");
+ else if (leftBorder && topBorder)
+ setResize("nw-resize");
+ else if (topBorder && rightBorder)
+ setResize("ne-resize");
+ else if (leftBorder)
+ setResize("w-resize");
+ else if (topBorder)
+ setResize("n-resize");
+ else if (bottomBorder)
+ setResize("s-resize");
+ else if (rightBorder)
+ setResize("e-resize");
+ });
+ window.addEventListener("contextmenu", function(e) {
+ if (true)
+ return;
+ if (window.wails.flags.disableDefaultContextMenu) {
+ e.preventDefault();
+ } else {
+ processDefaultContextMenu(e);
+ }
+ });
+ window.WailsInvoke("runtime:ready");
+})();
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL2RyYWdhbmRkcm9wLmpzIiwgImRlc2t0b3AvY29udGV4dG1lbnUuanMiLCAiZGVza3RvcC9tYWluLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG4vKipcclxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGxldmVsXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5mdW5jdGlvbiBzZW5kTG9nTWVzc2FnZShsZXZlbCwgbWVzc2FnZSkge1xyXG5cclxuXHQvLyBMb2cgTWVzc2FnZSBmb3JtYXQ6XHJcblx0Ly8gbFt0eXBlXVttZXNzYWdlXVxyXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiB0cmFjZSBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnVCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1ByaW50KG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnUCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0RlYnVnKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBpbmZvIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0knLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gd2FybmluZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1dhcm5pbmcobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdXJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nRXJyb3IobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGZhdGFsIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdGJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSBMb2cgbGV2ZWwgdG8gdGhlIGdpdmVuIGxvZyBsZXZlbFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb2dsZXZlbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldExvZ0xldmVsKGxvZ2xldmVsKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1MnLCBsb2dsZXZlbCk7XHJcbn1cclxuXHJcbi8vIExvZyBsZXZlbHNcclxuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xyXG5cdFRSQUNFOiAxLFxyXG5cdERFQlVHOiAyLFxyXG5cdElORk86IDMsXHJcblx0V0FSTklORzogNCxcclxuXHRFUlJPUjogNSxcclxufTtcclxuIiwgIi8qXHJcbiBfICAgICAgIF9fICAgICAgXyBfX1xyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcclxuXHJcbi8qKlxyXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcclxuICpcclxuICogQGNsYXNzIExpc3RlbmVyXHJcbiAqL1xyXG5jbGFzcyBMaXN0ZW5lciB7XHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xyXG4gICAgICogQG1lbWJlcm9mIExpc3RlbmVyXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xyXG4gICAgICAgIC8vIERlZmF1bHQgb2YgLTEgbWVhbnMgaW5maW5pdGVcclxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcclxuICAgICAgICAvLyBDYWxsYmFjayBpbnZva2VzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBnaXZlbiBkYXRhXHJcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoaXMgbGlzdGVuZXIgc2hvdWxkIGJlIGRlc3Ryb3llZFxyXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgLy8gSWYgbWF4Q2FsbGJhY2tzIGlzIGluZmluaXRlLCByZXR1cm4gZmFsc2UgKGRvIG5vdCBkZXN0cm95KVxyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxyXG4gICAgICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge307XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGBtYXhDYWxsYmFja3NgIHRpbWVzIGJlZm9yZSBiZWluZyBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XHJcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKTtcclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xyXG4gICAgcmV0dXJuICgpID0+IGxpc3RlbmVyT2ZmKHRoaXNMaXN0ZW5lcik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgZXZlcnkgdGltZSB0aGUgZXZlbnQgaXMgZW1pdHRlZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XHJcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgb25jZSB0aGVuIGRlc3Ryb3llZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcclxuICAgIHJldHVybiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXHJcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XHJcblxyXG4gICAgLy8gS2VlcCBhIGxpc3Qgb2YgbGlzdGVuZXIgaW5kZXhlcyB0byBkZXN0cm95XHJcbiAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0/LnNsaWNlKCkgfHwgW107XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XHJcbiAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoKSB7XHJcblxyXG4gICAgICAgIC8vIEl0ZXJhdGUgbGlzdGVuZXJzXHJcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSBuZXdFdmVudExpc3RlbmVyTGlzdC5sZW5ndGggLSAxOyBjb3VudCA+PSAwOyBjb3VudCAtPSAxKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgbmV4dCBsaXN0ZW5lclxyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0W2NvdW50XTtcclxuXHJcbiAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnREYXRhLmRhdGE7XHJcblxyXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcclxuICAgICAgICAgICAgY29uc3QgZGVzdHJveSA9IGxpc3RlbmVyLkNhbGxiYWNrKGRhdGEpO1xyXG4gICAgICAgICAgICBpZiAoZGVzdHJveSkge1xyXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcclxuICAgICAgICAgICAgICAgIG5ld0V2ZW50TGlzdGVuZXJMaXN0LnNwbGljZShjb3VudCwgMSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFVwZGF0ZSBjYWxsYmFja3Mgd2l0aCBuZXcgbGlzdCBvZiBsaXN0ZW5lcnNcclxuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcclxuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcclxuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXHJcbiAgICBsZXQgbWVzc2FnZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XHJcbiAgICB9XHJcbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcclxuXHJcbiAgICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcclxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXHJcbiAgICBub3RpZnlMaXN0ZW5lcnMocGF5bG9hZCk7XHJcblxyXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFRScgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSkge1xyXG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xyXG4gICAgZGVsZXRlIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV07XHJcblxyXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFWCcgKyBldmVudE5hbWUpO1xyXG59XHJcblxyXG4vKipcclxuICogT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT24sXHJcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XHJcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXHJcblxyXG4gICAgaWYgKGFkZGl0aW9uYWxFdmVudE5hbWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XHJcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogT2ZmIHVucmVnaXN0ZXJzIGFsbCBldmVudCBsaXN0ZW5lcnMgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT25cclxuICovXHJcbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xyXG4gICAgY29uc3QgZXZlbnROYW1lcyA9IE9iamVjdC5rZXlzKGV2ZW50TGlzdGVuZXJzKTtcclxuICAgIGV2ZW50TmFtZXMuZm9yRWFjaChldmVudE5hbWUgPT4ge1xyXG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcclxuICAgIH0pXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBsaXN0ZW5lck9mZiB1bnJlZ2lzdGVycyBhIGxpc3RlbmVyIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIEV2ZW50c09uXHJcbiAqXHJcbiAqIEBwYXJhbSB7TGlzdGVuZXJ9IGxpc3RlbmVyXHJcbiAqL1xyXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcclxuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcclxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuXHJcbiAgICAvLyBSZW1vdmUgbG9jYWwgbGlzdGVuZXJcclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmZpbHRlcihsID0+IGwgIT09IGxpc3RlbmVyKTtcclxuXHJcbiAgICAvLyBDbGVhbiB1cCBpZiB0aGVyZSBhcmUgbm8gZXZlbnQgbGlzdGVuZXJzIGxlZnRcclxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XHJcbiAgICB9XHJcbn1cclxuIiwgIi8qXHJcbiBfICAgICAgIF9fICAgICAgXyBfX1xyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXHJcbiAqXHJcbiAqIEByZXR1cm5zIG51bWJlclxyXG4gKi9cclxuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xyXG5cdHZhciBhcnJheSA9IG5ldyBVaW50MzJBcnJheSgxKTtcclxuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cclxuICogSSBsaWtlcyB0byBjYWxsIGl0IExPTFJhbmRvbVxyXG4gKlxyXG4gKiBAcmV0dXJucyBudW1iZXJcclxuICovXHJcbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xyXG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcclxufVxyXG5cclxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XHJcbnZhciByYW5kb21GdW5jO1xyXG5pZiAod2luZG93LmNyeXB0bykge1xyXG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XHJcbn0gZWxzZSB7XHJcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGwgc2VuZHMgYSBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kIHRvIGNhbGwgdGhlIGJpbmRpbmcgd2l0aCB0aGVcclxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxyXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxyXG4gKiBvciByZWplY3RlZCBpZiBhbiBlcnJvciBpcyBwYXNzZWQgYmFjay5cclxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxyXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcclxuICogQHBhcmFtIHthbnk9fSBhcmdzXHJcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xyXG5cclxuXHQvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcclxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XHJcblx0XHR0aW1lb3V0ID0gMDtcclxuXHR9XHJcblxyXG5cdC8vIENyZWF0ZSBhIHByb21pc2VcclxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG5cclxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXHJcblx0XHR2YXIgY2FsbGJhY2tJRDtcclxuXHRcdGRvIHtcclxuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XHJcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xyXG5cdFx0Ly8gU2V0IHRpbWVvdXRcclxuXHRcdGlmICh0aW1lb3V0ID4gMCkge1xyXG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XHJcblx0XHRcdH0sIHRpbWVvdXQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFN0b3JlIGNhbGxiYWNrXHJcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XHJcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXHJcblx0XHRcdHJlamVjdDogcmVqZWN0LFxyXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXHJcblx0XHR9O1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0bmFtZSxcclxuXHRcdFx0XHRhcmdzLFxyXG5cdFx0XHRcdGNhbGxiYWNrSUQsXHJcblx0XHRcdH07XHJcblxyXG4gICAgICAgICAgICAvLyBNYWtlIHRoZSBjYWxsXHJcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnQycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxufVxyXG5cclxud2luZG93Lk9iZnVzY2F0ZWRDYWxsID0gKGlkLCBhcmdzLCB0aW1lb3V0KSA9PiB7XHJcblxyXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XHJcbiAgICBpZiAodGltZW91dCA9PSBudWxsKSB7XHJcbiAgICAgICAgdGltZW91dCA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ3JlYXRlIGEgcHJvbWlzZVxyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcclxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcclxuICAgICAgICBkbyB7XHJcbiAgICAgICAgICAgIGNhbGxiYWNrSUQgPSBpZCArICctJyArIHJhbmRvbUZ1bmMoKTtcclxuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuICAgICAgICB2YXIgdGltZW91dEhhbmRsZTtcclxuICAgICAgICAvLyBTZXQgdGltZW91dFxyXG4gICAgICAgIGlmICh0aW1lb3V0ID4gMCkge1xyXG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xyXG4gICAgICAgICAgICB9LCB0aW1lb3V0KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFN0b3JlIGNhbGxiYWNrXHJcbiAgICAgICAgY2FsbGJhY2tzW2NhbGxiYWNrSURdID0ge1xyXG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxyXG4gICAgICAgICAgICByZWplY3Q6IHJlamVjdCxcclxuICAgICAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0aWQsXHJcblx0XHRcdFx0YXJncyxcclxuXHRcdFx0XHRjYWxsYmFja0lELFxyXG5cdFx0XHR9O1xyXG5cclxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxyXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ2MnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbn07XHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGxlZCBieSB0aGUgYmFja2VuZCB0byByZXR1cm4gZGF0YSB0byBhIHByZXZpb3VzbHkgY2FsbGVkXHJcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsYmFjayhpbmNvbWluZ01lc3NhZ2UpIHtcclxuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxyXG5cdGxldCBtZXNzYWdlO1xyXG5cdHRyeSB7XHJcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xyXG5cdH0gY2F0Y2ggKGUpIHtcclxuXHRcdGNvbnN0IGVycm9yID0gYEludmFsaWQgSlNPTiBwYXNzZWQgdG8gY2FsbGJhY2s6ICR7ZS5tZXNzYWdlfS4gTWVzc2FnZTogJHtpbmNvbWluZ01lc3NhZ2V9YDtcclxuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xyXG5cdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yKTtcclxuXHR9XHJcblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XHJcblx0bGV0IGNhbGxiYWNrRGF0YSA9IGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcclxuXHRpZiAoIWNhbGxiYWNrRGF0YSkge1xyXG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcclxuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xyXG5cdH1cclxuXHRjbGVhclRpbWVvdXQoY2FsbGJhY2tEYXRhLnRpbWVvdXRIYW5kbGUpO1xyXG5cclxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xyXG5cclxuXHRpZiAobWVzc2FnZS5lcnJvcikge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlc29sdmUobWVzc2FnZS5yZXN1bHQpO1xyXG5cdH1cclxufVxyXG4iLCAiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcclxuXHJcbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcclxud2luZG93LmdvID0ge307XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcclxuXHR0cnkge1xyXG5cdFx0YmluZGluZ3NNYXAgPSBKU09OLnBhcnNlKGJpbmRpbmdzTWFwKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKGUpO1xyXG5cdH1cclxuXHJcblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXHJcblx0d2luZG93LmdvID0gd2luZG93LmdvIHx8IHt9O1xyXG5cclxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcclxuXHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcCkuZm9yRWFjaCgocGFja2FnZU5hbWUpID0+IHtcclxuXHJcblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3RcclxuXHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdIHx8IHt9O1xyXG5cclxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXHJcblx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV0pLmZvckVhY2goKHN0cnVjdE5hbWUpID0+IHtcclxuXHJcblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxyXG5cdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcclxuXHJcblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdFx0XHRcdC8vIE5vIHRpbWVvdXQgYnkgZGVmYXVsdFxyXG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xyXG5cclxuXHRcdFx0XHRcdC8vIEFjdHVhbCBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIENhbGwoW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXS5qb2luKCcuJyksIGFyZ3MsIHRpbWVvdXQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IHNldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcclxuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XHJcblx0XHRcdFx0XHR9O1xyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5nZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcclxuXHRcdFx0XHRcdH07XHJcblxyXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XHJcblx0XHRcdFx0fSgpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH0pO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcclxuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1InKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFN5c3RlbURlZmF1bHRUaGVtZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FTRFQnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldExpZ2h0VGhlbWUoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FEVCcpO1xyXG59XHJcblxyXG4vKipcclxuICogUGxhY2UgdGhlIHdpbmRvdyBpbiB0aGUgY2VudGVyIG9mIHRoZSBzY3JlZW5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2MnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHdpbmRvdyB0aXRsZVxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFRpdGxlKHRpdGxlKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dUJyArIHRpdGxlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93RnVsbHNjcmVlbigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0YnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VuZnVsbHNjcmVlbigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2YnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNGdWxsc2NyZWVuKCkge1xyXG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XHJcblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRTaXplXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXQgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcclxufVxyXG5cclxuXHJcblxyXG4vKipcclxuICogU2V0IHRoZSB3aW5kb3cgQWx3YXlzT25Ub3Agb3Igbm90IG9uIHRvcFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xyXG5cclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FUUDonICsgKGIgPyAnMScgOiAnMCcpKTtcclxufVxyXG5cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcDonICsgeCArICc6JyArIHkpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhpZGUgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SGlkZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNob3cgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2hvdygpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01heGltaXNlKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dUb2dnbGVNYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5tYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc01heGltaXNlZCgpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogTWluaW1pc2UgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBVbm1pbmltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBtaW5pbWlzZWQgb3Igbm90LlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc01pbmltaXNlZFwiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG5vcm1hbCBvciBub3QuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc05vcm1hbCgpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTm9ybWFsXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxyXG4gKiBAcGFyYW0ge251bWJlcn0gRyBHcmVlblxyXG4gKiBAcGFyYW0ge251bWJlcn0gQiBCbHVlXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QmFja2dyb3VuZENvbG91cihSLCBHLCBCLCBBKSB7XHJcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcjonICsgcmdiYSk7XHJcbn1cclxuXHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xyXG5cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXHJcbiAqIEBleHBvcnRcclxuICogQHR5cGVkZWYge2ltcG9ydCgnLi4vd3JhcHBlci9ydW50aW1lJykuU2NyZWVufSBTY3JlZW5cclxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW5HZXRBbGwoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcclxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBCcm93c2VyT3BlblVSTCh1cmwpIHtcclxuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcclxuXHJcbi8qKlxyXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkU2V0VGV4dCh0ZXh0KSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRTZXRUZXh0XCIsIFt0ZXh0XSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXQgdGhlIHRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTx7c3RyaW5nfT59IFRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXHJcblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENsaXBib2FyZEdldFRleHQoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRHZXRUZXh0XCIpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7RXZlbnRzT24sIEV2ZW50c09mZn0gZnJvbSBcIi4vZXZlbnRzXCI7XHJcblxyXG5jb25zdCBmbGFncyA9IHtcclxuICAgIHJlZ2lzdGVyZWQ6IGZhbHNlLFxyXG4gICAgZGVmYXVsdFVzZURyb3BUYXJnZXQ6IHRydWUsXHJcbiAgICB1c2VEcm9wVGFyZ2V0OiB0cnVlLFxyXG4gICAgbmV4dERlYWN0aXZhdGU6IG51bGwsXHJcbiAgICBuZXh0RGVhY3RpdmF0ZVRpbWVvdXQ6IG51bGwsXHJcbn07XHJcblxyXG5jb25zdCBEUk9QX1RBUkdFVF9BQ1RJVkUgPSBcIndhaWxzLWRyb3AtdGFyZ2V0LWFjdGl2ZVwiO1xyXG5cclxuLyoqXHJcbiAqIGNoZWNrU3R5bGVEcm9wVGFyZ2V0IGNoZWNrcyBpZiB0aGUgc3R5bGUgaGFzIHRoZSBkcm9wIHRhcmdldCBhdHRyaWJ1dGVcclxuICogXHJcbiAqIEBwYXJhbSB7Q1NTU3R5bGVEZWNsYXJhdGlvbn0gc3R5bGUgXHJcbiAqIEByZXR1cm5zIFxyXG4gKi9cclxuZnVuY3Rpb24gY2hlY2tTdHlsZURyb3BUYXJnZXQoc3R5bGUpIHtcclxuICAgIGNvbnN0IGNzc0Ryb3BWYWx1ZSA9IHN0eWxlLmdldFByb3BlcnR5VmFsdWUod2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BQcm9wZXJ0eSkudHJpbSgpO1xyXG4gICAgaWYgKGNzc0Ryb3BWYWx1ZSkge1xyXG4gICAgICAgIGlmIChjc3NEcm9wVmFsdWUgPT09IHdpbmRvdy53YWlscy5mbGFncy5jc3NEcm9wVmFsdWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGlmIHRoZSBlbGVtZW50IGhhcyB0aGUgZHJvcCB0YXJnZXQgYXR0cmlidXRlLCBidXQgXHJcbiAgICAgICAgLy8gdGhlIHZhbHVlIGlzIG5vdCBjb3JyZWN0LCB0ZXJtaW5hdGUgZmluZGluZyBwcm9jZXNzLlxyXG4gICAgICAgIC8vIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBibG9jayBzb21lIGNoaWxkIGVsZW1lbnRzIGZyb20gYmVpbmcgZHJvcCB0YXJnZXRzLlxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIG9uRHJhZ092ZXIgaXMgY2FsbGVkIHdoZW4gdGhlIGRyYWdvdmVyIGV2ZW50IGlzIGVtaXR0ZWQuXHJcbiAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5mdW5jdGlvbiBvbkRyYWdPdmVyKGUpIHtcclxuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYW4gZXh0ZXJuYWwgZmlsZSBkcm9wIG9yIGludGVybmFsIEhUTUwgZHJhZ1xyXG4gICAgLy8gRXh0ZXJuYWwgZmlsZSBkcm9wcyB3aWxsIGhhdmUgXCJGaWxlc1wiIGluIHRoZSB0eXBlcyBhcnJheVxyXG4gICAgLy8gSW50ZXJuYWwgSFRNTCBkcmFncyB0eXBpY2FsbHkgaGF2ZSBcInRleHQvcGxhaW5cIiwgXCJ0ZXh0L2h0bWxcIiBvciBjdXN0b20gdHlwZXNcclxuICAgIGNvbnN0IGlzRmlsZURyb3AgPSBlLmRhdGFUcmFuc2Zlci50eXBlcy5pbmNsdWRlcyhcIkZpbGVzXCIpO1xyXG5cclxuICAgIC8vIE9ubHkgaGFuZGxlIGV4dGVybmFsIGZpbGUgZHJvcHMsIGxldCBpbnRlcm5hbCBIVE1MNSBkcmFnLWFuZC1kcm9wIHdvcmsgbm9ybWFsbHlcclxuICAgIGlmICghaXNGaWxlRHJvcCkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBTFdBWVMgcHJldmVudCBkZWZhdWx0IGZvciBmaWxlIGRyb3BzIHRvIHN0b3AgYnJvd3NlciBuYXZpZ2F0aW9uXHJcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBlLmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ2NvcHknO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVsZW1lbnQgPSBlLnRhcmdldDtcclxuXHJcbiAgICAvLyBUcmlnZ2VyIGRlYm91bmNlIGZ1bmN0aW9uIHRvIGRlYWN0aXZhdGUgZHJvcCB0YXJnZXRzXHJcbiAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcclxuXHJcbiAgICAvLyBpZiB0aGUgZWxlbWVudCBpcyBudWxsIG9yIGVsZW1lbnQgaXMgbm90IGNoaWxkIG9mIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgIGlmICghZWxlbWVudCB8fCAhY2hlY2tTdHlsZURyb3BUYXJnZXQoZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KSkpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGN1cnJlbnRFbGVtZW50ID0gZWxlbWVudDtcclxuICAgIHdoaWxlIChjdXJyZW50RWxlbWVudCkge1xyXG4gICAgICAgIC8vIGNoZWNrIGlmIGN1cnJlbnRFbGVtZW50IGlzIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgICAgICBpZiAoY2hlY2tTdHlsZURyb3BUYXJnZXQoZ2V0Q29tcHV0ZWRTdHlsZShjdXJyZW50RWxlbWVudCkpKSB7XHJcbiAgICAgICAgICAgIGN1cnJlbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoRFJPUF9UQVJHRVRfQUNUSVZFKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogb25EcmFnTGVhdmUgaXMgY2FsbGVkIHdoZW4gdGhlIGRyYWdsZWF2ZSBldmVudCBpcyBlbWl0dGVkLlxyXG4gKiBAcGFyYW0ge0RyYWdFdmVudH0gZVxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZnVuY3Rpb24gb25EcmFnTGVhdmUoZSkge1xyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiBleHRlcm5hbCBmaWxlIGRyb3Agb3IgaW50ZXJuYWwgSFRNTCBkcmFnXHJcbiAgICBjb25zdCBpc0ZpbGVEcm9wID0gZS5kYXRhVHJhbnNmZXIudHlwZXMuaW5jbHVkZXMoXCJGaWxlc1wiKTtcclxuXHJcbiAgICAvLyBPbmx5IGhhbmRsZSBleHRlcm5hbCBmaWxlIGRyb3BzLCBsZXQgaW50ZXJuYWwgSFRNTDUgZHJhZy1hbmQtZHJvcCB3b3JrIG5vcm1hbGx5XHJcbiAgICBpZiAoIWlzRmlsZURyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQUxXQVlTIHByZXZlbnQgZGVmYXVsdCBmb3IgZmlsZSBkcm9wcyB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEZpbmQgdGhlIGNsb3NlIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgIGlmICghZS50YXJnZXQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZS50YXJnZXQpKSkge1xyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRyaWdnZXIgZGVib3VuY2UgZnVuY3Rpb24gdG8gZGVhY3RpdmF0ZSBkcm9wIHRhcmdldHNcclxuICAgIGlmKGZsYWdzLm5leHREZWFjdGl2YXRlKSBmbGFncy5uZXh0RGVhY3RpdmF0ZSgpO1xyXG4gICAgXHJcbiAgICAvLyBVc2UgZGVib3VuY2UgdGVjaG5pcXVlIHRvIHRhY2xlIGRyYWdsZWF2ZSBldmVudHMgb24gb3ZlcmxhcHBpbmcgZWxlbWVudHMgYW5kIGRyb3AgdGFyZ2V0IGVsZW1lbnRzXHJcbiAgICBmbGFncy5uZXh0RGVhY3RpdmF0ZSA9ICgpID0+IHtcclxuICAgICAgICAvLyBEZWFjdGl2YXRlIGFsbCBkcm9wIHRhcmdldHMsIG5ldyBkcm9wIHRhcmdldCB3aWxsIGJlIGFjdGl2YXRlZCBvbiBuZXh0IGRyYWdvdmVyIGV2ZW50XHJcbiAgICAgICAgQXJyYXkuZnJvbShkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKERST1BfVEFSR0VUX0FDVElWRSkpLmZvckVhY2goZWwgPT4gZWwuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkUpKTtcclxuICAgICAgICAvLyBSZXNldCBuZXh0RGVhY3RpdmF0ZVxyXG4gICAgICAgIGZsYWdzLm5leHREZWFjdGl2YXRlID0gbnVsbDtcclxuICAgICAgICAvLyBDbGVhciB0aW1lb3V0XHJcbiAgICAgICAgaWYgKGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0KTtcclxuICAgICAgICAgICAgZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0ID0gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gU2V0IHRpbWVvdXQgdG8gZGVhY3RpdmF0ZSBkcm9wIHRhcmdldHMgaWYgbm90IHRyaWdnZXJlZCBieSBuZXh0IGRyYWcgZXZlbnRcclxuICAgIGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIGlmKGZsYWdzLm5leHREZWFjdGl2YXRlKSBmbGFncy5uZXh0RGVhY3RpdmF0ZSgpO1xyXG4gICAgfSwgNTApO1xyXG59XHJcblxyXG4vKipcclxuICogb25Ecm9wIGlzIGNhbGxlZCB3aGVuIHRoZSBkcm9wIGV2ZW50IGlzIGVtaXR0ZWQuXHJcbiAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5mdW5jdGlvbiBvbkRyb3AoZSkge1xyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiBleHRlcm5hbCBmaWxlIGRyb3Agb3IgaW50ZXJuYWwgSFRNTCBkcmFnXHJcbiAgICBjb25zdCBpc0ZpbGVEcm9wID0gZS5kYXRhVHJhbnNmZXIudHlwZXMuaW5jbHVkZXMoXCJGaWxlc1wiKTtcclxuXHJcbiAgICAvLyBPbmx5IGhhbmRsZSBleHRlcm5hbCBmaWxlIGRyb3BzLCBsZXQgaW50ZXJuYWwgSFRNTDUgZHJhZy1hbmQtZHJvcCB3b3JrIG5vcm1hbGx5XHJcbiAgICBpZiAoIWlzRmlsZURyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQUxXQVlTIHByZXZlbnQgZGVmYXVsdCBmb3IgZmlsZSBkcm9wcyB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKENhblJlc29sdmVGaWxlUGF0aHMoKSkge1xyXG4gICAgICAgIC8vIHByb2Nlc3MgZmlsZXNcclxuICAgICAgICBsZXQgZmlsZXMgPSBbXTtcclxuICAgICAgICBpZiAoZS5kYXRhVHJhbnNmZXIuaXRlbXMpIHtcclxuICAgICAgICAgICAgZmlsZXMgPSBbLi4uZS5kYXRhVHJhbnNmZXIuaXRlbXNdLm1hcCgoaXRlbSwgaSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0ua2luZCA9PT0gJ2ZpbGUnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0QXNGaWxlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGZpbGVzID0gWy4uLmUuZGF0YVRyYW5zZmVyLmZpbGVzXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgd2luZG93LnJ1bnRpbWUuUmVzb2x2ZUZpbGVQYXRocyhlLngsIGUueSwgZmlsZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghZmxhZ3MudXNlRHJvcFRhcmdldCkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBUcmlnZ2VyIGRlYm91bmNlIGZ1bmN0aW9uIHRvIGRlYWN0aXZhdGUgZHJvcCB0YXJnZXRzXHJcbiAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcclxuXHJcbiAgICAvLyBEZWFjdGl2YXRlIGFsbCBkcm9wIHRhcmdldHNcclxuICAgIEFycmF5LmZyb20oZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShEUk9QX1RBUkdFVF9BQ1RJVkUpKS5mb3JFYWNoKGVsID0+IGVsLmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFKSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBwb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyBjaGVja3MgdGhlIGJyb3dzZXIncyBjYXBhYmlsaXR5IG9mIHNlbmRpbmcgcG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHNcclxuICpcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqIEBjb25zdHJ1Y3RvclxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhblJlc29sdmVGaWxlUGF0aHMoKSB7XHJcbiAgICByZXR1cm4gd2luZG93LmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMgIT0gbnVsbDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlc29sdmVGaWxlUGF0aHMgc2VuZHMgZHJvcCBldmVudHMgdG8gdGhlIEdPIHNpZGUgdG8gcmVzb2x2ZSBmaWxlIHBhdGhzIG9uIHdpbmRvd3MuXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XHJcbiAqIEBwYXJhbSB7YW55W119IGZpbGVzXHJcbiAqIEBjb25zdHJ1Y3RvclxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFJlc29sdmVGaWxlUGF0aHMoeCwgeSwgZmlsZXMpIHtcclxuICAgIC8vIE9ubHkgZm9yIHdpbmRvd3Mgd2VidmlldzIgPj0gMS4wLjE3NzQuMzBcclxuICAgIC8vIGh0dHBzOi8vbGVhcm4ubWljcm9zb2Z0LmNvbS9lbi11cy9taWNyb3NvZnQtZWRnZS93ZWJ2aWV3Mi9yZWZlcmVuY2Uvd2luMzIvaWNvcmV3ZWJ2aWV3MndlYm1lc3NhZ2VyZWNlaXZlZGV2ZW50YXJnczI/dmlldz13ZWJ2aWV3Mi0xLjAuMTgyMy4zMiNhcHBsaWVzLXRvXHJcbiAgICBpZiAod2luZG93LmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMpIHtcclxuICAgICAgICBjaHJvbWUud2Vidmlldy5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyhgZmlsZTpkcm9wOiR7eH06JHt5fWAsIGZpbGVzKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIENhbGxiYWNrIGZvciBPbkZpbGVEcm9wIHJldHVybnMgYSBzbGljZSBvZiBmaWxlIHBhdGggc3RyaW5ncyB3aGVuIGEgZHJvcCBpcyBmaW5pc2hlZC5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAY2FsbGJhY2sgT25GaWxlRHJvcENhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IC0geCBjb29yZGluYXRlIG9mIHRoZSBkcm9wXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0geSBjb29yZGluYXRlIG9mIHRoZSBkcm9wXHJcbiAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhzIC0gQSBsaXN0IG9mIGZpbGUgcGF0aHMuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIE9uRmlsZURyb3AgbGlzdGVucyB0byBkcmFnIGFuZCBkcm9wIGV2ZW50cyBhbmQgY2FsbHMgdGhlIGNhbGxiYWNrIHdpdGggdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBkcm9wIGFuZCBhbiBhcnJheSBvZiBwYXRoIHN0cmluZ3MuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtPbkZpbGVEcm9wQ2FsbGJhY2t9IGNhbGxiYWNrIC0gQ2FsbGJhY2sgZm9yIE9uRmlsZURyb3AgcmV0dXJucyBhIHNsaWNlIG9mIGZpbGUgcGF0aCBzdHJpbmdzIHdoZW4gYSBkcm9wIGlzIGZpbmlzaGVkLlxyXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1c2VEcm9wVGFyZ2V0PXRydWVdIC0gT25seSBjYWxsIHRoZSBjYWxsYmFjayB3aGVuIHRoZSBkcm9wIGZpbmlzaGVkIG9uIGFuIGVsZW1lbnQgdGhhdCBoYXMgdGhlIGRyb3AgdGFyZ2V0IHN0eWxlLiAoLS13YWlscy1kcm9wLXRhcmdldClcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPbkZpbGVEcm9wKGNhbGxiYWNrLCB1c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKFwiRHJhZ0FuZERyb3BDYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvblwiKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGZsYWdzLnJlZ2lzdGVyZWQpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBmbGFncy5yZWdpc3RlcmVkID0gdHJ1ZTtcclxuXHJcbiAgICBjb25zdCB1RFRQVCA9IHR5cGVvZiB1c2VEcm9wVGFyZ2V0O1xyXG4gICAgZmxhZ3MudXNlRHJvcFRhcmdldCA9IHVEVFBUID09PSBcInVuZGVmaW5lZFwiIHx8IHVEVFBUICE9PSBcImJvb2xlYW5cIiA/IGZsYWdzLmRlZmF1bHRVc2VEcm9wVGFyZ2V0IDogdXNlRHJvcFRhcmdldDtcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcmFnb3ZlcicsIG9uRHJhZ092ZXIpO1xyXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdsZWF2ZScsIG9uRHJhZ0xlYXZlKTtcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgb25Ecm9wKTtcclxuXHJcbiAgICBsZXQgY2IgPSBjYWxsYmFjaztcclxuICAgIGlmIChmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgY2IgPSBmdW5jdGlvbiAoeCwgeSwgcGF0aHMpIHtcclxuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoeCwgeSlcclxuICAgICAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgaXMgbnVsbCBvciBlbGVtZW50IGlzIG5vdCBjaGlsZCBvZiBkcm9wIHRhcmdldCBlbGVtZW50LCByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgICBpZiAoIWVsZW1lbnQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYWxsYmFjayh4LCB5LCBwYXRocyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIEV2ZW50c09uKFwid2FpbHM6ZmlsZS1kcm9wXCIsIGNiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE9uRmlsZURyb3BPZmYgcmVtb3ZlcyB0aGUgZHJhZyBhbmQgZHJvcCBsaXN0ZW5lcnMgYW5kIGhhbmRsZXJzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE9uRmlsZURyb3BPZmYoKSB7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ292ZXInLCBvbkRyYWdPdmVyKTtcclxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBvbkRyYWdMZWF2ZSk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJvcCcsIG9uRHJvcCk7XHJcbiAgICBFdmVudHNPZmYoXCJ3YWlsczpmaWxlLWRyb3BcIik7XHJcbiAgICBmbGFncy5yZWdpc3RlcmVkID0gZmFsc2U7XHJcbn1cclxuIiwgIi8qXHJcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogYXV0bzsgKGRlZmF1bHQpIHdpbGwgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnUgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWUgT1IgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBPUiBlbGVtZW50IGlzIGlucHV0IG9yIHRleHRhcmVhXHJcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogc2hvdzsgd2lsbCBhbHdheXMgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcclxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG5cclxuVGhpcyBydWxlIGlzIGluaGVyaXRlZCBsaWtlIG5vcm1hbCBDU1MgcnVsZXMsIHNvIG5lc3Rpbmcgd29ya3MgYXMgZXhwZWN0ZWRcclxuKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcclxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcclxuICAgIGNvbnN0IGVsZW1lbnQgPSBldmVudC50YXJnZXQ7XHJcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XHJcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xyXG4gICAgc3dpdGNoIChkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24pIHtcclxuICAgICAgICBjYXNlIFwic2hvd1wiOlxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgY2FzZSBcImhpZGVcIjpcclxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXHJcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgYW5kIGFjdGlvbiBpcyBvbiB0aGUgc2VsZWN0ZWQgZWxlbWVudHNcclxuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgaWYgKGhhc1NlbGVjdGlvbikge1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0cyA9IHJhbmdlLmdldENsaWVudFJlY3RzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHJlY3QubGVmdCwgcmVjdC50b3ApID09PSBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGFnbmFtZSBpcyBpbnB1dCBvciB0ZXh0YXJlYVxyXG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIklOUFVUXCIgfHwgZWxlbWVudC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCIpIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgfVxyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0ICogYXMgTG9nIGZyb20gJy4vbG9nJztcclxuaW1wb3J0IHtcclxuICBldmVudExpc3RlbmVycyxcclxuICBFdmVudHNFbWl0LFxyXG4gIEV2ZW50c05vdGlmeSxcclxuICBFdmVudHNPZmYsXHJcbiAgRXZlbnRzT2ZmQWxsLFxyXG4gIEV2ZW50c09uLFxyXG4gIEV2ZW50c09uY2UsXHJcbiAgRXZlbnRzT25NdWx0aXBsZSxcclxufSBmcm9tIFwiLi9ldmVudHNcIjtcclxuaW1wb3J0IHsgQ2FsbCwgQ2FsbGJhY2ssIGNhbGxiYWNrcyB9IGZyb20gJy4vY2FsbHMnO1xyXG5pbXBvcnQgeyBTZXRCaW5kaW5ncyB9IGZyb20gXCIuL2JpbmRpbmdzXCI7XHJcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi93aW5kb3dcIjtcclxuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xyXG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcclxuaW1wb3J0ICogYXMgQ2xpcGJvYXJkIGZyb20gXCIuL2NsaXBib2FyZFwiO1xyXG5pbXBvcnQgKiBhcyBEcmFnQW5kRHJvcCBmcm9tIFwiLi9kcmFnYW5kZHJvcFwiO1xyXG5pbXBvcnQgKiBhcyBDb250ZXh0TWVudSBmcm9tIFwiLi9jb250ZXh0bWVudVwiO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1MnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0gnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xyXG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XHJcbn1cclxuXHJcbi8vIFRoZSBKUyBydW50aW1lXHJcbndpbmRvdy5ydW50aW1lID0ge1xyXG4gICAgLi4uTG9nLFxyXG4gICAgLi4uV2luZG93LFxyXG4gICAgLi4uQnJvd3NlcixcclxuICAgIC4uLlNjcmVlbixcclxuICAgIC4uLkNsaXBib2FyZCxcclxuICAgIC4uLkRyYWdBbmREcm9wLFxyXG4gICAgRXZlbnRzT24sXHJcbiAgICBFdmVudHNPbmNlLFxyXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcclxuICAgIEV2ZW50c0VtaXQsXHJcbiAgICBFdmVudHNPZmYsXHJcbiAgICBFdmVudHNPZmZBbGwsXHJcbiAgICBFbnZpcm9ubWVudCxcclxuICAgIFNob3csXHJcbiAgICBIaWRlLFxyXG4gICAgUXVpdFxyXG59O1xyXG5cclxuLy8gSW50ZXJuYWwgd2FpbHMgZW5kcG9pbnRzXHJcbndpbmRvdy53YWlscyA9IHtcclxuICAgIENhbGxiYWNrLFxyXG4gICAgRXZlbnRzTm90aWZ5LFxyXG4gICAgU2V0QmluZGluZ3MsXHJcbiAgICBldmVudExpc3RlbmVycyxcclxuICAgIGNhbGxiYWNrcyxcclxuICAgIGZsYWdzOiB7XHJcbiAgICAgICAgZGlzYWJsZVNjcm9sbGJhckRyYWc6IGZhbHNlLFxyXG4gICAgICAgIGRpc2FibGVEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxyXG4gICAgICAgIGVuYWJsZVJlc2l6ZTogZmFsc2UsXHJcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcclxuICAgICAgICBib3JkZXJUaGlja25lc3M6IDYsXHJcbiAgICAgICAgc2hvdWxkRHJhZzogZmFsc2UsXHJcbiAgICAgICAgZGVmZXJEcmFnVG9Nb3VzZU1vdmU6IHRydWUsXHJcbiAgICAgICAgY3NzRHJhZ1Byb3BlcnR5OiBcIi0td2FpbHMtZHJhZ2dhYmxlXCIsXHJcbiAgICAgICAgY3NzRHJhZ1ZhbHVlOiBcImRyYWdcIixcclxuICAgICAgICBjc3NEcm9wUHJvcGVydHk6IFwiLS13YWlscy1kcm9wLXRhcmdldFwiLFxyXG4gICAgICAgIGNzc0Ryb3BWYWx1ZTogXCJkcm9wXCIsXHJcbiAgICAgICAgZW5hYmxlV2FpbHNEcmFnQW5kRHJvcDogZmFsc2UsXHJcbiAgICB9XHJcbn07XHJcblxyXG4vLyBTZXQgdGhlIGJpbmRpbmdzXHJcbmlmICh3aW5kb3cud2FpbHNiaW5kaW5ncykge1xyXG4gICAgd2luZG93LndhaWxzLlNldEJpbmRpbmdzKHdpbmRvdy53YWlsc2JpbmRpbmdzKTtcclxuICAgIGRlbGV0ZSB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3M7XHJcbn1cclxuXHJcbi8vIChib29sKSBUaGlzIGlzIGV2YWx1YXRlZCBhdCBidWlsZCB0aW1lIGluIHBhY2thZ2UuanNvblxyXG5pZiAoIURFQlVHKSB7XHJcbiAgICBkZWxldGUgd2luZG93LndhaWxzYmluZGluZ3M7XHJcbn1cclxuXHJcbmxldCBkcmFnVGVzdCA9IGZ1bmN0aW9uKGUpIHtcclxuICAgIHZhciB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5KTtcclxuICAgIGlmICh2YWwpIHtcclxuICAgICAgICB2YWwgPSB2YWwudHJpbSgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh2YWwgIT09IHdpbmRvdy53YWlscy5mbGFncy5jc3NEcmFnVmFsdWUpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGUuYnV0dG9ucyAhPT0gMSkge1xyXG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBub3QgdGhlIHByaW1hcnkgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWQuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlLmRldGFpbCAhPT0gMSkge1xyXG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBtb3JlIHRoYW4gb25jZSBoYXMgYmVlbiBjbGlja2VkLCBlLmcuIHdoZW4gZG91YmxlIGNsaWNraW5nXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG59O1xyXG5cclxud2luZG93LndhaWxzLnNldENTU0RyYWdQcm9wZXJ0aWVzID0gZnVuY3Rpb24ocHJvcGVydHksIHZhbHVlKSB7XHJcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5ID0gcHJvcGVydHk7XHJcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlID0gdmFsdWU7XHJcbn1cclxuXHJcbndpbmRvdy53YWlscy5zZXRDU1NEcm9wUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BlcnR5LCB2YWx1ZSkge1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BQcm9wZXJ0eSA9IHByb3BlcnR5O1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BWYWx1ZSA9IHZhbHVlO1xyXG59XHJcblxyXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcclxuICAgIC8vIENoZWNrIGZvciByZXNpemluZ1xyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKSB7XHJcbiAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwicmVzaXplOlwiICsgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpO1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRyYWdUZXN0KGUpKSB7XHJcbiAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlU2Nyb2xsYmFyRHJhZykge1xyXG4gICAgICAgICAgICAvLyBUaGlzIGNoZWNrcyBmb3IgY2xpY2tzIG9uIHRoZSBzY3JvbGwgYmFyXHJcbiAgICAgICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRlZmVyRHJhZ1RvTW91c2VNb3ZlKSB7XHJcbiAgICAgICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gdHJ1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcclxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgKCkgPT4ge1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcclxufSk7XHJcblxyXG5mdW5jdGlvbiBzZXRSZXNpemUoY3Vyc29yKSB7XHJcbiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gY3Vyc29yIHx8IHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yO1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgPSBjdXJzb3I7XHJcbn1cclxuXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XHJcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcpIHtcclxuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xyXG4gICAgICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XHJcbiAgICAgICAgaWYgKG1vdXNlUHJlc3NlZCA+IDApIHtcclxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVJlc2l6ZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvciA9PSBudWxsKSB7XHJcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yO1xyXG4gICAgfVxyXG4gICAgaWYgKHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcyAmJiB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzKSB7XHJcbiAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IFwic2UtcmVzaXplXCI7XHJcbiAgICB9XHJcbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XHJcbiAgICBsZXQgbGVmdEJvcmRlciA9IGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XHJcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcclxuICAgIGxldCBib3R0b21Cb3JkZXIgPSB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xyXG5cclxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XHJcbiAgICBpZiAoIWxlZnRCb3JkZXIgJiYgIXJpZ2h0Qm9yZGVyICYmICF0b3BCb3JkZXIgJiYgIWJvdHRvbUJvcmRlciAmJiB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgc2V0UmVzaXplKCk7XHJcbiAgICB9IGVsc2UgaWYgKHJpZ2h0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAobGVmdEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgdG9wQm9yZGVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIgJiYgcmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XHJcblxyXG59KTtcclxuXHJcbi8vIFNldHVwIGNvbnRleHQgbWVudSBob29rXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGZ1bmN0aW9uKGUpIHtcclxuICAgIC8vIGFsd2F5cyBzaG93IHRoZSBjb250ZXh0bWVudSBpbiBkZWJ1ZyAmIGRldlxyXG4gICAgaWYgKERFQlVHKSByZXR1cm47XHJcblxyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlRGVmYXVsdENvbnRleHRNZW51KSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBDb250ZXh0TWVudS5wcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGUpO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbndpbmRvdy5XYWlsc0ludm9rZShcInJ1bnRpbWU6cmVhZHlcIik7Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsV0FBUyxlQUFlLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRLE9BQU87QUFBQSxFQUN6QztBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsUUFBUSxTQUFTO0FBQ2hDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxXQUFXLFNBQVM7QUFDbkMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxZQUFZLFVBQVU7QUFDckMsbUJBQWUsS0FBSyxRQUFRO0FBQUEsRUFDN0I7QUFHTyxNQUFNLFdBQVc7QUFBQSxJQUN2QixPQUFPO0FBQUEsSUFDUCxPQUFPO0FBQUEsSUFDUCxNQUFNO0FBQUEsSUFDTixTQUFTO0FBQUEsSUFDVCxPQUFPO0FBQUEsRUFDUjs7O0FDOUZBLE1BQU0sV0FBTixNQUFlO0FBQUEsSUFRWCxZQUFZLFdBQVcsVUFBVSxjQUFjO0FBQzNDLFdBQUssWUFBWTtBQUVqQixXQUFLLGVBQWUsZ0JBQWdCO0FB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
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.go b/v2/internal/frontend/runtime/runtime_dev_desktop.go
deleted file mode 100644
index c0dcb1fc5..000000000
--- a/v2/internal/frontend/runtime/runtime_dev_desktop.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build dev || bindings || (!dev && !production && !bindings)
-
-package runtime
-
-import _ "embed"
-
-//go:embed runtime_dev_desktop.js
-var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.js b/v2/internal/frontend/runtime/runtime_dev_desktop.js
deleted file mode 100644
index 0a125ad3d..000000000
--- a/v2/internal/frontend/runtime/runtime_dev_desktop.js
+++ /dev/null
@@ -1,580 +0,0 @@
-(() => {
- var __defProp = Object.defineProperty;
- var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
- };
-
- // desktop/log.js
- var log_exports = {};
- __export(log_exports, {
- LogDebug: () => LogDebug,
- LogError: () => LogError,
- LogFatal: () => LogFatal,
- LogInfo: () => LogInfo,
- LogLevel: () => LogLevel,
- LogPrint: () => LogPrint,
- LogTrace: () => LogTrace,
- LogWarning: () => LogWarning,
- SetLogLevel: () => SetLogLevel
- });
- function sendLogMessage(level, message) {
- window.WailsInvoke("L" + level + message);
- }
- function LogTrace(message) {
- sendLogMessage("T", message);
- }
- function LogPrint(message) {
- sendLogMessage("P", message);
- }
- function LogDebug(message) {
- sendLogMessage("D", message);
- }
- function LogInfo(message) {
- sendLogMessage("I", message);
- }
- function LogWarning(message) {
- sendLogMessage("W", message);
- }
- function LogError(message) {
- sendLogMessage("E", message);
- }
- function LogFatal(message) {
- sendLogMessage("F", message);
- }
- function SetLogLevel(loglevel) {
- sendLogMessage("S", loglevel);
- }
- var LogLevel = {
- TRACE: 1,
- DEBUG: 2,
- INFO: 3,
- WARNING: 4,
- ERROR: 5
- };
-
- // desktop/events.js
- var Listener = class {
- constructor(eventName, callback, maxCallbacks) {
- this.eventName = eventName;
- this.maxCallbacks = maxCallbacks || -1;
- this.Callback = (data) => {
- callback.apply(null, data);
- if (this.maxCallbacks === -1) {
- return false;
- }
- this.maxCallbacks -= 1;
- return this.maxCallbacks === 0;
- };
- }
- };
- var eventListeners = {};
- function EventsOnMultiple(eventName, callback, maxCallbacks) {
- eventListeners[eventName] = eventListeners[eventName] || [];
- const thisListener = new Listener(eventName, callback, maxCallbacks);
- eventListeners[eventName].push(thisListener);
- return () => listenerOff(thisListener);
- }
- function EventsOn(eventName, callback) {
- return EventsOnMultiple(eventName, callback, -1);
- }
- function EventsOnce(eventName, callback) {
- return EventsOnMultiple(eventName, callback, 1);
- }
- function notifyListeners(eventData) {
- let eventName = eventData.name;
- if (eventListeners[eventName]) {
- const newEventListenerList = eventListeners[eventName].slice();
- for (let count = 0; count < eventListeners[eventName].length; count += 1) {
- const listener = eventListeners[eventName][count];
- let data = eventData.data;
- const destroy = listener.Callback(data);
- if (destroy) {
- newEventListenerList.splice(count, 1);
- }
- }
- if (newEventListenerList.length === 0) {
- removeListener(eventName);
- } else {
- eventListeners[eventName] = newEventListenerList;
- }
- }
- }
- function EventsNotify(notifyMessage) {
- let message;
- try {
- message = JSON.parse(notifyMessage);
- } catch (e) {
- const error = "Invalid JSON passed to Notify: " + notifyMessage;
- throw new Error(error);
- }
- notifyListeners(message);
- }
- function EventsEmit(eventName) {
- const payload = {
- name: eventName,
- data: [].slice.apply(arguments).slice(1)
- };
- notifyListeners(payload);
- window.WailsInvoke("EE" + JSON.stringify(payload));
- }
- function removeListener(eventName) {
- delete eventListeners[eventName];
- window.WailsInvoke("EX" + eventName);
- }
- function EventsOff(eventName, ...additionalEventNames) {
- removeListener(eventName);
- if (additionalEventNames.length > 0) {
- additionalEventNames.forEach((eventName2) => {
- removeListener(eventName2);
- });
- }
- }
- function listenerOff(listener) {
- const eventName = listener.eventName;
- eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener);
- if (eventListeners[eventName].length === 0) {
- removeListener(eventName);
- }
- }
-
- // desktop/calls.js
- var callbacks = {};
- function cryptoRandom() {
- var array = new Uint32Array(1);
- return window.crypto.getRandomValues(array)[0];
- }
- function basicRandom() {
- return Math.random() * 9007199254740991;
- }
- var randomFunc;
- if (window.crypto) {
- randomFunc = cryptoRandom;
- } else {
- randomFunc = basicRandom;
- }
- function Call(name, args, timeout) {
- if (timeout == null) {
- timeout = 0;
- }
- return new Promise(function(resolve, reject) {
- var callbackID;
- do {
- callbackID = name + "-" + randomFunc();
- } while (callbacks[callbackID]);
- var timeoutHandle;
- if (timeout > 0) {
- timeoutHandle = setTimeout(function() {
- reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
- }, timeout);
- }
- callbacks[callbackID] = {
- timeoutHandle,
- reject,
- resolve
- };
- try {
- const payload = {
- name,
- args,
- callbackID
- };
- window.WailsInvoke("C" + JSON.stringify(payload));
- } catch (e) {
- console.error(e);
- }
- });
- }
- window.ObfuscatedCall = (id, args, timeout) => {
- if (timeout == null) {
- timeout = 0;
- }
- return new Promise(function(resolve, reject) {
- var callbackID;
- do {
- callbackID = id + "-" + randomFunc();
- } while (callbacks[callbackID]);
- var timeoutHandle;
- if (timeout > 0) {
- timeoutHandle = setTimeout(function() {
- reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID));
- }, timeout);
- }
- callbacks[callbackID] = {
- timeoutHandle,
- reject,
- resolve
- };
- try {
- const payload = {
- id,
- args,
- callbackID
- };
- window.WailsInvoke("c" + JSON.stringify(payload));
- } catch (e) {
- console.error(e);
- }
- });
- };
- function Callback(incomingMessage) {
- let message;
- try {
- message = JSON.parse(incomingMessage);
- } catch (e) {
- const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
- runtime.LogDebug(error);
- throw new Error(error);
- }
- let callbackID = message.callbackid;
- let callbackData = callbacks[callbackID];
- if (!callbackData) {
- const error = `Callback '${callbackID}' not registered!!!`;
- console.error(error);
- throw new Error(error);
- }
- clearTimeout(callbackData.timeoutHandle);
- delete callbacks[callbackID];
- if (message.error) {
- callbackData.reject(message.error);
- } else {
- callbackData.resolve(message.result);
- }
- }
-
- // desktop/bindings.js
- window.go = {};
- function SetBindings(bindingsMap) {
- try {
- bindingsMap = JSON.parse(bindingsMap);
- } catch (e) {
- console.error(e);
- }
- window.go = window.go || {};
- Object.keys(bindingsMap).forEach((packageName) => {
- window.go[packageName] = window.go[packageName] || {};
- Object.keys(bindingsMap[packageName]).forEach((structName) => {
- window.go[packageName][structName] = window.go[packageName][structName] || {};
- Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
- window.go[packageName][structName][methodName] = function() {
- let timeout = 0;
- function dynamic() {
- const args = [].slice.call(arguments);
- return Call([packageName, structName, methodName].join("."), args, timeout);
- }
- dynamic.setTimeout = function(newTimeout) {
- timeout = newTimeout;
- };
- dynamic.getTimeout = function() {
- return timeout;
- };
- return dynamic;
- }();
- });
- });
- });
- }
-
- // desktop/window.js
- var window_exports = {};
- __export(window_exports, {
- WindowCenter: () => WindowCenter,
- WindowFullscreen: () => WindowFullscreen,
- WindowGetPosition: () => WindowGetPosition,
- WindowGetSize: () => WindowGetSize,
- WindowHide: () => WindowHide,
- WindowIsFullscreen: () => WindowIsFullscreen,
- WindowIsMaximised: () => WindowIsMaximised,
- WindowIsMinimised: () => WindowIsMinimised,
- WindowIsNormal: () => WindowIsNormal,
- WindowMaximise: () => WindowMaximise,
- WindowMinimise: () => WindowMinimise,
- WindowReload: () => WindowReload,
- WindowReloadApp: () => WindowReloadApp,
- WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop,
- WindowSetBackgroundColour: () => WindowSetBackgroundColour,
- WindowSetDarkTheme: () => WindowSetDarkTheme,
- WindowSetLightTheme: () => WindowSetLightTheme,
- WindowSetMaxSize: () => WindowSetMaxSize,
- WindowSetMinSize: () => WindowSetMinSize,
- WindowSetPosition: () => WindowSetPosition,
- WindowSetSize: () => WindowSetSize,
- WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme,
- WindowSetTitle: () => WindowSetTitle,
- WindowShow: () => WindowShow,
- WindowToggleMaximise: () => WindowToggleMaximise,
- WindowUnfullscreen: () => WindowUnfullscreen,
- WindowUnmaximise: () => WindowUnmaximise,
- WindowUnminimise: () => WindowUnminimise
- });
- function WindowReload() {
- window.location.reload();
- }
- function WindowReloadApp() {
- window.WailsInvoke("WR");
- }
- function WindowSetSystemDefaultTheme() {
- window.WailsInvoke("WASDT");
- }
- function WindowSetLightTheme() {
- window.WailsInvoke("WALT");
- }
- function WindowSetDarkTheme() {
- window.WailsInvoke("WADT");
- }
- function WindowCenter() {
- window.WailsInvoke("Wc");
- }
- function WindowSetTitle(title) {
- window.WailsInvoke("WT" + title);
- }
- function WindowFullscreen() {
- window.WailsInvoke("WF");
- }
- function WindowUnfullscreen() {
- window.WailsInvoke("Wf");
- }
- function WindowIsFullscreen() {
- return Call(":wails:WindowIsFullscreen");
- }
- function WindowSetSize(width, height) {
- window.WailsInvoke("Ws:" + width + ":" + height);
- }
- function WindowGetSize() {
- return Call(":wails:WindowGetSize");
- }
- function WindowSetMaxSize(width, height) {
- window.WailsInvoke("WZ:" + width + ":" + height);
- }
- function WindowSetMinSize(width, height) {
- window.WailsInvoke("Wz:" + width + ":" + height);
- }
- function WindowSetAlwaysOnTop(b) {
- window.WailsInvoke("WATP:" + (b ? "1" : "0"));
- }
- function WindowSetPosition(x, y) {
- window.WailsInvoke("Wp:" + x + ":" + y);
- }
- function WindowGetPosition() {
- return Call(":wails:WindowGetPos");
- }
- function WindowHide() {
- window.WailsInvoke("WH");
- }
- function WindowShow() {
- window.WailsInvoke("WS");
- }
- function WindowMaximise() {
- window.WailsInvoke("WM");
- }
- function WindowToggleMaximise() {
- window.WailsInvoke("Wt");
- }
- function WindowUnmaximise() {
- window.WailsInvoke("WU");
- }
- function WindowIsMaximised() {
- return Call(":wails:WindowIsMaximised");
- }
- function WindowMinimise() {
- window.WailsInvoke("Wm");
- }
- function WindowUnminimise() {
- window.WailsInvoke("Wu");
- }
- function WindowIsMinimised() {
- return Call(":wails:WindowIsMinimised");
- }
- function WindowIsNormal() {
- return Call(":wails:WindowIsNormal");
- }
- function WindowSetBackgroundColour(R, G, B, A) {
- let rgba = JSON.stringify({ r: R || 0, g: G || 0, b: B || 0, a: A || 255 });
- window.WailsInvoke("Wr:" + rgba);
- }
-
- // desktop/screen.js
- var screen_exports = {};
- __export(screen_exports, {
- ScreenGetAll: () => ScreenGetAll
- });
- function ScreenGetAll() {
- return Call(":wails:ScreenGetAll");
- }
-
- // desktop/browser.js
- var browser_exports = {};
- __export(browser_exports, {
- BrowserOpenURL: () => BrowserOpenURL
- });
- function BrowserOpenURL(url) {
- window.WailsInvoke("BO:" + url);
- }
-
- // desktop/clipboard.js
- var clipboard_exports = {};
- __export(clipboard_exports, {
- ClipboardGetText: () => ClipboardGetText,
- ClipboardSetText: () => ClipboardSetText
- });
- function ClipboardSetText(text) {
- return Call(":wails:ClipboardSetText", [text]);
- }
- function ClipboardGetText() {
- return Call(":wails:ClipboardGetText");
- }
-
- // desktop/main.js
- function Quit() {
- window.WailsInvoke("Q");
- }
- function Show() {
- window.WailsInvoke("S");
- }
- function Hide() {
- window.WailsInvoke("H");
- }
- function Environment() {
- return Call(":wails:Environment");
- }
- window.runtime = {
- ...log_exports,
- ...window_exports,
- ...browser_exports,
- ...screen_exports,
- ...clipboard_exports,
- EventsOn,
- EventsOnce,
- EventsOnMultiple,
- EventsEmit,
- EventsOff,
- Environment,
- Show,
- Hide,
- Quit
- };
- window.wails = {
- Callback,
- EventsNotify,
- SetBindings,
- eventListeners,
- callbacks,
- flags: {
- disableScrollbarDrag: false,
- disableWailsDefaultContextMenu: false,
- enableResize: false,
- defaultCursor: null,
- borderThickness: 6,
- shouldDrag: false,
- deferDragToMouseMove: false,
- cssDragProperty: "--wails-draggable",
- cssDragValue: "drag"
- }
- };
- if (window.wailsbindings) {
- window.wails.SetBindings(window.wailsbindings);
- delete window.wails.SetBindings;
- }
- if (false) {
- delete window.wailsbindings;
- }
- var dragTest = function(e) {
- var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);
- if (val) {
- val = val.trim();
- }
- if (val !== window.wails.flags.cssDragValue) {
- return false;
- }
- if (e.buttons !== 1) {
- return false;
- }
- if (e.detail !== 1) {
- return false;
- }
- return true;
- };
- window.wails.setCSSDragProperties = function(property, value) {
- window.wails.flags.cssDragProperty = property;
- window.wails.flags.cssDragValue = value;
- };
- window.addEventListener("mousedown", (e) => {
- if (window.wails.flags.resizeEdge) {
- window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
- e.preventDefault();
- return;
- }
- if (dragTest(e)) {
- if (window.wails.flags.disableScrollbarDrag) {
- if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
- return;
- }
- }
- if (window.wails.flags.deferDragToMouseMove) {
- window.wails.flags.shouldDrag = true;
- } else {
- e.preventDefault();
- window.WailsInvoke("drag");
- }
- return;
- } else {
- window.wails.flags.shouldDrag = false;
- }
- });
- window.addEventListener("mouseup", () => {
- window.wails.flags.shouldDrag = false;
- });
- function setResize(cursor) {
- document.documentElement.style.cursor = cursor || window.wails.flags.defaultCursor;
- window.wails.flags.resizeEdge = cursor;
- }
- window.addEventListener("mousemove", function(e) {
- if (window.wails.flags.shouldDrag) {
- let mousePressed = e.buttons !== void 0 ? e.buttons : e.which;
- if (mousePressed <= 0) {
- window.wails.flags.shouldDrag = false;
- } else {
- window.WailsInvoke("drag");
- return;
- }
- }
- if (!window.wails.flags.enableResize) {
- return;
- }
- if (window.wails.flags.defaultCursor == null) {
- window.wails.flags.defaultCursor = document.documentElement.style.cursor;
- }
- if (window.outerWidth - e.clientX < window.wails.flags.borderThickness && window.outerHeight - e.clientY < window.wails.flags.borderThickness) {
- document.documentElement.style.cursor = "se-resize";
- }
- let rightBorder = window.outerWidth - e.clientX < window.wails.flags.borderThickness;
- let leftBorder = e.clientX < window.wails.flags.borderThickness;
- let topBorder = e.clientY < window.wails.flags.borderThickness;
- let bottomBorder = window.outerHeight - e.clientY < window.wails.flags.borderThickness;
- if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && window.wails.flags.resizeEdge !== void 0) {
- setResize();
- } else if (rightBorder && bottomBorder)
- setResize("se-resize");
- else if (leftBorder && bottomBorder)
- setResize("sw-resize");
- else if (leftBorder && topBorder)
- setResize("nw-resize");
- else if (topBorder && rightBorder)
- setResize("ne-resize");
- else if (leftBorder)
- setResize("w-resize");
- else if (topBorder)
- setResize("n-resize");
- else if (bottomBorder)
- setResize("s-resize");
- else if (rightBorder)
- setResize("e-resize");
- });
- window.addEventListener("contextmenu", function(e) {
- if (window.wails.flags.disableWailsDefaultContextMenu) {
- e.preventDefault();
- }
- });
- window.WailsInvoke("runtime:ready");
-})();
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgLT0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcbn1cblxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xuXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xuXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcblxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSAwOyBjb3VudCA8IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoOyBjb3VudCArPSAxKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcblxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcbiAgICAvLyBQYXJzZSB0aGUgbWVzc2FnZVxuICAgIGxldCBtZXNzYWdlO1xuICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG5vdGlmeU1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRW1pdCBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcbiAgICAgICAgZGF0YTogW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKS5zbGljZSgxKSxcbiAgICB9O1xuXG4gICAgLy8gTm90aWZ5IEpTIGxpc3RlbmVyc1xuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xuICAgIGRlbGV0ZSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPbixcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXMpIHtcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG5cbiAgICBpZiAoYWRkaXRpb25hbEV2ZW50TmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG4gICAgICAgIH0pXG4gICAgfVxufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhbGwgZXZlbnQgbGlzdGVuZXJzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uXG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xuICAgIGNvbnN0IGV2ZW50TmFtZXMgPSBPYmplY3Qua2V5cyhldmVudExpc3RlbmVycyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGV2ZW50TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lc1tpXSk7XG4gICAgfVxufVxuXG4vKipcbiAqIGxpc3RlbmVyT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggRXZlbnRzT25cbiAqXG4gKiBAcGFyYW0ge0xpc3RlbmVyfSBsaXN0ZW5lclxuICovXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgaWYgdGhlcmUgYXJlIG5vIGV2ZW50IGxpc3RlbmVycyBsZWZ0XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5leHBvcnQgY29uc3QgY2FsbGJhY2tzID0ge307XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSBuYXRpdmUgYnJvd3NlciByYW5kb20gZnVuY3Rpb25cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XG5cdHJldHVybiB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhcnJheSlbMF07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gYmFzaWNSYW5kb20oKSB7XG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcbn1cblxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XG52YXIgcmFuZG9tRnVuYztcbmlmICh3aW5kb3cuY3J5cHRvKSB7XG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XG59IGVsc2Uge1xuXHRyYW5kb21GdW5jID0gYmFzaWNSYW5kb207XG59XG5cblxuLyoqXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXG4gKiBnaXZlbiBkYXRhLiBBIHByb21pc2UgaXMgcmV0dXJuZWQgYW5kIHdpbGwgYmUgY29tcGxldGVkIHdoZW4gdGhlXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXG4gKiBUaGVyZSBpcyBhIHRpbWVvdXQgbWVjaGFuaXNtLiBJZiB0aGUgY2FsbCBkb2Vzbid0IHJlc3BvbmQgaW4gdGhlIGdpdmVuXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7YW55PX0gYXJnc1xuICogQHBhcmFtIHtudW1iZXI9fSB0aW1lb3V0XG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChuYW1lLCBhcmdzLCB0aW1lb3V0KSB7XG5cblx0Ly8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG5cdGlmICh0aW1lb3V0ID09IG51bGwpIHtcblx0XHR0aW1lb3V0ID0gMDtcblx0fVxuXG5cdC8vIENyZWF0ZSBhIHByb21pc2Vcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXG5cdFx0dmFyIGNhbGxiYWNrSUQ7XG5cdFx0ZG8ge1xuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XG5cdFx0fSB3aGlsZSAoY2FsbGJhY2tzW2NhbGxiYWNrSURdKTtcblxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xuXHRcdC8vIFNldCB0aW1lb3V0XG5cdFx0aWYgKHRpbWVvdXQgPiAwKSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJlamVjdChFcnJvcignQ2FsbCB0byAnICsgbmFtZSArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuXHRcdFx0fSwgdGltZW91dCk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RvcmUgY2FsbGJhY2tcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuXHRcdFx0cmVqZWN0OiByZWplY3QsXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXG5cdFx0fTtcblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwYXlsb2FkID0ge1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbndpbmRvdy5PYmZ1c2NhdGVkQ2FsbCA9IChpZCwgYXJncywgdGltZW91dCkgPT4ge1xuXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG4gICAgaWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICB0aW1lb3V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBwcm9taXNlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgICAgICAvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgY2FsbGJhY2tJRCA9IGlkICsgJy0nICsgcmFuZG9tRnVuYygpO1xuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlO1xuICAgICAgICAvLyBTZXQgdGltZW91dFxuICAgICAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuICAgICAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSBjYWxsYmFja1xuICAgICAgICBjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICByZXNvbHZlOiByZXNvbHZlXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdGlkLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdjJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vICBcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSAnLi9jYWxscyc7XG5cbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcbndpbmRvdy5nbyA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcblx0dHJ5IHtcblx0XHRiaW5kaW5nc01hcCA9IEpTT04ucGFyc2UoYmluZGluZ3NNYXApO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc29sZS5lcnJvcihlKTtcblx0fVxuXG5cdC8vIEluaXRpYWxpc2UgdGhlIGJpbmRpbmdzIG1hcFxuXHR3aW5kb3cuZ28gPSB3aW5kb3cuZ28gfHwge307XG5cblx0Ly8gSXRlcmF0ZSBwYWNrYWdlIG5hbWVzXG5cdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwKS5mb3JFYWNoKChwYWNrYWdlTmFtZSkgPT4ge1xuXG5cdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XG5cdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gfHwge307XG5cblx0XHQvLyBJdGVyYXRlIHN0cnVjdCBuYW1lc1xuXHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXSkuZm9yRWFjaCgoc3RydWN0TmFtZSkgPT4ge1xuXG5cdFx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdIHx8IHt9O1xuXG5cdFx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0pLmZvckVhY2goKG1ldGhvZE5hbWUpID0+IHtcblxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuXG5cdFx0XHRcdFx0Ly8gTm8gdGltZW91dCBieSBkZWZhdWx0XG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xuXG5cdFx0XHRcdFx0Ly8gQWN0dWFsIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcblx0XHRcdFx0XHRcdGNvbnN0IGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gQ2FsbChbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdLmpvaW4oJy4nKSwgYXJncywgdGltZW91dCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgc2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcblx0XHRcdFx0XHRcdHRpbWVvdXQgPSBuZXdUaW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBnZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLmdldFRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XG5cdFx0XHRcdH0oKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dSZWxvYWRBcHAoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U3lzdGVtRGVmYXVsdFRoZW1lKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FTRFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldExpZ2h0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQUxUJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXREYXJrVGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQURUJyk7XG59XG5cbi8qKlxuICogUGxhY2UgdGhlIHdpbmRvdyBpbiB0aGUgY2VudGVyIG9mIHRoZSBzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dDZW50ZXIoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXYycpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHdpbmRvdyB0aXRsZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZVxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0VGl0bGUodGl0bGUpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dUJyArIHRpdGxlKTtcbn1cblxuLyoqXG4gKiBNYWtlcyB0aGUgd2luZG93IGdvIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dGdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0YnKTtcbn1cblxuLyoqXG4gKiBSZXZlcnRzIHRoZSB3aW5kb3cgZnJvbSBmdWxsc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5mdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2YnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBpbiBmdWxsIHNjcmVlbiBtb2RlIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNGdWxsc2NyZWVuKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzRnVsbHNjcmVlblwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7dzogbnVtYmVyLCBoOiBudW1iZXJ9Pn0gVGhlIHNpemUgb2YgdGhlIHdpbmRvd1xuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRTaXplKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFNpemVcIik7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXWjonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgbWluaW11bSBzaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuXG5cbi8qKlxuICogU2V0IHRoZSB3aW5kb3cgQWx3YXlzT25Ub3Agb3Igbm90IG9uIHRvcFxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldEFsd2F5c09uVG9wKGIpIHtcblxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FUUDonICsgKGIgPyAnMScgOiAnMCcpKTtcbn1cblxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0geFxuICogQHBhcmFtIHtudW1iZXJ9IHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFBvc2l0aW9uKHgsIHkpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dwOicgKyB4ICsgJzonICsgeSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFBvc2l0aW9uKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcbn1cblxuLyoqXG4gKiBIaWRlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcbn1cblxuLyoqXG4gKiBTaG93IHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTaG93KCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcbn1cblxuLyoqXG4gKiBNYXhpbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xufVxuXG4vKipcbiAqIFRvZ2dsZSB0aGUgTWF4aW1pc2Ugb2YgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1RvZ2dsZU1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcbn1cblxuLyoqXG4gKiBVbm1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBtYXhpbWlzZWQgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc01heGltaXNlZCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc01heGltaXNlZFwiKTtcbn1cblxuLyoqXG4gKiBNaW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXbScpO1xufVxuXG4vKipcbiAqIFVubWluaW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1pbmltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWluaW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWluaW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG5vcm1hbCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTm9ybWFsKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTm9ybWFsXCIpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gUiBSZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBHIEdyZWVuXG4gKiBAcGFyYW0ge251bWJlcn0gQiBCbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gQSBBbHBoYVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QmFja2dyb3VuZENvbG91cihSLCBHLCBCLCBBKSB7XG4gICAgbGV0IHJnYmEgPSBKU09OLnN0cmluZ2lmeSh7cjogUiB8fCAwLCBnOiBHIHx8IDAsIGI6IEIgfHwgMCwgYTogQSB8fCAyNTV9KTtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dyOicgKyByZ2JhKTtcbn1cblxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5cbi8qKlxuICogR2V0cyB0aGUgYWxsIHNjcmVlbnMuIENhbGwgdGhpcyBhbmV3IGVhY2ggdGltZSB5b3Ugd2FudCB0byByZWZyZXNoIGRhdGEgZnJvbSB0aGUgdW5kZXJseWluZyB3aW5kb3dpbmcgc3lzdGVtLlxuICogQGV4cG9ydFxuICogQHR5cGVkZWYge2ltcG9ydCgnLi4vd3JhcHBlci9ydW50aW1lJykuU2NyZWVufSBTY3JlZW5cbiAqIEByZXR1cm4ge1Byb21pc2U8e1NjcmVlbltdfT59IFRoZSBzY3JlZW5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW5HZXRBbGwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6U2NyZWVuR2V0QWxsXCIpO1xufVxuIiwgIi8qKlxuICogQGRlc2NyaXB0aW9uOiBVc2UgdGhlIHN5c3RlbSBkZWZhdWx0IGJyb3dzZXIgdG8gb3BlbiB0aGUgdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJyb3dzZXJPcGVuVVJMKHVybCkge1xuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cbi8qKlxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkU2V0VGV4dCh0ZXh0KSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6Q2xpcGJvYXJkU2V0VGV4dFwiLCBbdGV4dF0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgdGV4dCBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHtzdHJpbmd9Pn0gVGV4dCBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmRcblxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkR2V0VGV4dCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRHZXRUZXh0XCIpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cbmltcG9ydCAqIGFzIExvZyBmcm9tICcuL2xvZyc7XG5pbXBvcnQge2V2ZW50TGlzdGVuZXJzLCBFdmVudHNFbWl0LCBFdmVudHNOb3RpZnksIEV2ZW50c09mZiwgRXZlbnRzT24sIEV2ZW50c09uY2UsIEV2ZW50c09uTXVsdGlwbGV9IGZyb20gJy4vZXZlbnRzJztcbmltcG9ydCB7Q2FsbCwgQ2FsbGJhY2ssIGNhbGxiYWNrc30gZnJvbSAnLi9jYWxscyc7XG5pbXBvcnQge1NldEJpbmRpbmdzfSBmcm9tIFwiLi9iaW5kaW5nc1wiO1xuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4vY2xpcGJvYXJkXCI7XG5cblxuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdRJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBTaG93KCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnUycpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gSGlkZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0gnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOkVudmlyb25tZW50XCIpO1xufVxuXG4vLyBUaGUgSlMgcnVudGltZVxud2luZG93LnJ1bnRpbWUgPSB7XG4gICAgLi4uTG9nLFxuICAgIC4uLldpbmRvdyxcbiAgICAuLi5Ccm93c2VyLFxuICAgIC4uLlNjcmVlbixcbiAgICAuLi5DbGlwYm9hcmQsXG4gICAgRXZlbnRzT24sXG4gICAgRXZlbnRzT25jZSxcbiAgICBFdmVudHNPbk11bHRpcGxlLFxuICAgIEV2ZW50c0VtaXQsXG4gICAgRXZlbnRzT2ZmLFxuICAgIEVudmlyb25tZW50LFxuICAgIFNob3csXG4gICAgSGlkZSxcbiAgICBRdWl0XG59O1xuXG4vLyBJbnRlcm5hbCB3YWlscyBlbmRwb2ludHNcbndpbmRvdy53YWlscyA9IHtcbiAgICBDYWxsYmFjayxcbiAgICBFdmVudHNOb3RpZnksXG4gICAgU2V0QmluZGluZ3MsXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgY2FsbGJhY2tzLFxuICAgIGZsYWdzOiB7XG4gICAgICAgIGRpc2FibGVTY3JvbGxiYXJEcmFnOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZVdhaWxzRGVmYXVsdENvbnRleHRNZW51OiBmYWxzZSxcbiAgICAgICAgZW5hYmxlUmVzaXplOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcbiAgICAgICAgYm9yZGVyVGhpY2tuZXNzOiA2LFxuICAgICAgICBzaG91bGREcmFnOiBmYWxzZSxcbiAgICAgICAgZGVmZXJEcmFnVG9Nb3VzZU1vdmU6IGZhbHNlLFxuICAgICAgICBjc3NEcmFnUHJvcGVydHk6IFwiLS13YWlscy1kcmFnZ2FibGVcIixcbiAgICAgICAgY3NzRHJhZ1ZhbHVlOiBcImRyYWdcIixcbiAgICB9XG59O1xuXG4vLyBTZXQgdGhlIGJpbmRpbmdzXG5pZiAod2luZG93LndhaWxzYmluZGluZ3MpIHtcbiAgICB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3Mod2luZG93LndhaWxzYmluZGluZ3MpO1xuICAgIGRlbGV0ZSB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3M7XG59XG5cbi8vIFRoaXMgaXMgZXZhbHVhdGVkIGF0IGJ1aWxkIHRpbWUgaW4gcGFja2FnZS5qc29uXG4vLyBjb25zdCBkZXYgPSAwO1xuLy8gY29uc3QgcHJvZHVjdGlvbiA9IDE7XG5pZiAoRU5WID09PSAxKSB7XG4gICAgZGVsZXRlIHdpbmRvdy53YWlsc2JpbmRpbmdzO1xufVxuXG5sZXQgZHJhZ1Rlc3QgPSBmdW5jdGlvbiAoZSkge1xuICAgIHZhciB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5KTtcbiAgICBpZiAodmFsKSB7XG4gICAgICB2YWwgPSB2YWwudHJpbSgpO1xuICAgIH1cbiAgICBcbiAgICBpZiAodmFsICE9PSB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5idXR0b25zICE9PSAxKSB7XG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBub3QgdGhlIHByaW1hcnkgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWQuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5kZXRhaWwgIT09IDEpIHtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IGRyYWdnaW5nIGlmIG1vcmUgdGhhbiBvbmNlIGhhcyBiZWVuIGNsaWNrZWQsIGUuZy4gd2hlbiBkb3VibGUgY2xpY2tpbmdcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxud2luZG93LndhaWxzLnNldENTU0RyYWdQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5jc3NEcmFnUHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlID0gdmFsdWU7XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4ge1xuXG4gICAgLy8gQ2hlY2sgZm9yIHJlc2l6aW5nXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKSB7XG4gICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcInJlc2l6ZTpcIiArIHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRyYWdUZXN0KGUpKSB7XG4gICAgICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGlzYWJsZVNjcm9sbGJhckRyYWcpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgY2hlY2tzIGZvciBjbGlja3Mgb24gdGhlIHNjcm9sbCBiYXJcbiAgICAgICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZlckRyYWdUb01vdXNlTW92ZSkge1xuICAgICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gZmFsc2U7XG4gICAgfVxufSk7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgKCkgPT4ge1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gZmFsc2U7XG59KTtcblxuZnVuY3Rpb24gc2V0UmVzaXplKGN1cnNvcikge1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSBjdXJzb3IgfHwgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3I7XG4gICAgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgPSBjdXJzb3I7XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbiAoZSkge1xuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZykge1xuICAgICAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgICAgICBpZihtb3VzZVByZXNzZWQgPD0gMCkge1xuICAgICAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlUmVzaXplKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yID09IG51bGwpIHtcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yO1xuICAgIH1cbiAgICBpZiAod2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzICYmIHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3MpIHtcbiAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IFwic2UtcmVzaXplXCI7XG4gICAgfVxuICAgIGxldCByaWdodEJvcmRlciA9IHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgbGVmdEJvcmRlciA9IGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG4gICAgbGV0IGJvdHRvbUJvcmRlciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc2V0UmVzaXplKCk7XG4gICAgfSBlbHNlIGlmIChyaWdodEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInNlLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic3ctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgdG9wQm9yZGVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyICYmIHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJuZS1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdEJvcmRlcikgc2V0UmVzaXplKFwidy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInMtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJlLXJlc2l6ZVwiKTtcblxufSk7XG5cbi8vIFNldHVwIGNvbnRleHQgbWVudSBob29rXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbiAoZSkge1xuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGlzYWJsZVdhaWxzRGVmYXVsdENvbnRleHRNZW51KSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59KTtcblxud2luZG93LldhaWxzSW52b2tlKFwicnVudGltZTpyZWFkeVwiKTsiXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFB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
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.go b/v2/internal/frontend/runtime/runtime_prod_desktop.go
index 4fd8aaa58..7336f0102 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.go
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.go
@@ -1,4 +1,4 @@
-//go:build production
+//go:build production && !debug
package runtime
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js
index 0f62dceec..3d38924f7 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.js
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js
@@ -1 +1 @@
-(()=>{var L=Object.defineProperty;var c=(e,n)=>{for(var o in n)L(e,o,{get:n[o],enumerable:!0})};var m={};c(m,{LogDebug:()=>M,LogError:()=>A,LogFatal:()=>H,LogInfo:()=>P,LogLevel:()=>J,LogPrint:()=>R,LogTrace:()=>z,LogWarning:()=>B,SetLogLevel:()=>G});function d(e,n){window.WailsInvoke("L"+e+n)}function z(e){d("T",e)}function R(e){d("P",e)}function M(e){d("D",e)}function P(e){d("I",e)}function B(e){d("W",e)}function A(e){d("E",e)}function H(e){d("F",e)}function G(e){d("S",e)}var J={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var v=class{constructor(n,o,i){this.eventName=n,this.maxCallbacks=i||-1,this.Callback=t=>(o.apply(null,t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},l={};function p(e,n,o){l[e]=l[e]||[];let i=new v(e,n,o);return l[e].push(i),()=>F(i)}function b(e,n){return p(e,n,-1)}function E(e,n){return p(e,n,1)}function S(e){let n=e.name;if(l[n]){let o=l[n].slice();for(let i=0;i0&&n.forEach(o=>{g(o)})}function F(e){let n=e.eventName;l[n]=l[n].filter(o=>o!==e),l[n].length===0&&g(n)}var f={};function U(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function j(){return Math.random()*9007199254740991}var W;window.crypto?W=U:W=j;function s(e,n,o){return o==null&&(o=0),new Promise(function(i,t){var r;do r=e+"-"+W();while(f[r]);var a;o>0&&(a=setTimeout(function(){t(Error("Call to "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={name:e,args:n,callbackID:r};window.WailsInvoke("C"+JSON.stringify(u))}catch(u){console.error(u)}})}window.ObfuscatedCall=(e,n,o)=>(o==null&&(o=0),new Promise(function(i,t){var r;do r=e+"-"+W();while(f[r]);var a;o>0&&(a=setTimeout(function(){t(Error("Call to method "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={id:e,args:n,callbackID:r};window.WailsInvoke("c"+JSON.stringify(u))}catch(u){console.error(u)}}));function T(e){let n;try{n=JSON.parse(e)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let o=n.callbackid,i=f[o];if(!i){let t=`Callback '${o}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete f[o],n.error?i.reject(n.error):i.resolve(n.result)}window.go={};function O(e){try{e=JSON.parse(e)}catch(n){console.error(n)}window.go=window.go||{},Object.keys(e).forEach(n=>{window.go[n]=window.go[n]||{},Object.keys(e[n]).forEach(o=>{window.go[n][o]=window.go[n][o]||{},Object.keys(e[n][o]).forEach(i=>{window.go[n][o][i]=function(){let t=0;function r(){let a=[].slice.call(arguments);return s([n,o,i].join("."),a,t)}return r.setTimeout=function(a){t=a},r.getTimeout=function(){return t},r}()})})})}var x={};c(x,{WindowCenter:()=>q,WindowFullscreen:()=>Z,WindowGetPosition:()=>se,WindowGetSize:()=>ne,WindowHide:()=>le,WindowIsFullscreen:()=>_,WindowIsMaximised:()=>ue,WindowIsMinimised:()=>pe,WindowIsNormal:()=>We,WindowMaximise:()=>we,WindowMinimise:()=>ce,WindowReload:()=>N,WindowReloadApp:()=>V,WindowSetAlwaysOnTop:()=>te,WindowSetBackgroundColour:()=>me,WindowSetDarkTheme:()=>$,WindowSetLightTheme:()=>Y,WindowSetMaxSize:()=>oe,WindowSetMinSize:()=>ie,WindowSetPosition:()=>re,WindowSetSize:()=>ee,WindowSetSystemDefaultTheme:()=>X,WindowSetTitle:()=>Q,WindowShow:()=>ae,WindowToggleMaximise:()=>de,WindowUnfullscreen:()=>K,WindowUnmaximise:()=>fe,WindowUnminimise:()=>ge});function N(){window.location.reload()}function V(){window.WailsInvoke("WR")}function X(){window.WailsInvoke("WASDT")}function Y(){window.WailsInvoke("WALT")}function $(){window.WailsInvoke("WADT")}function q(){window.WailsInvoke("Wc")}function Q(e){window.WailsInvoke("WT"+e)}function Z(){window.WailsInvoke("WF")}function K(){window.WailsInvoke("Wf")}function _(){return s(":wails:WindowIsFullscreen")}function ee(e,n){window.WailsInvoke("Ws:"+e+":"+n)}function ne(){return s(":wails:WindowGetSize")}function oe(e,n){window.WailsInvoke("WZ:"+e+":"+n)}function ie(e,n){window.WailsInvoke("Wz:"+e+":"+n)}function te(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function re(e,n){window.WailsInvoke("Wp:"+e+":"+n)}function se(){return s(":wails:WindowGetPos")}function le(){window.WailsInvoke("WH")}function ae(){window.WailsInvoke("WS")}function we(){window.WailsInvoke("WM")}function de(){window.WailsInvoke("Wt")}function fe(){window.WailsInvoke("WU")}function ue(){return s(":wails:WindowIsMaximised")}function ce(){window.WailsInvoke("Wm")}function ge(){window.WailsInvoke("Wu")}function pe(){return s(":wails:WindowIsMinimised")}function We(){return s(":wails:WindowIsNormal")}function me(e,n,o,i){let t=JSON.stringify({r:e||0,g:n||0,b:o||0,a:i||255});window.WailsInvoke("Wr:"+t)}var k={};c(k,{ScreenGetAll:()=>ve});function ve(){return s(":wails:ScreenGetAll")}var h={};c(h,{BrowserOpenURL:()=>xe});function xe(e){window.WailsInvoke("BO:"+e)}var I={};c(I,{ClipboardGetText:()=>he,ClipboardSetText:()=>ke});function ke(e){return s(":wails:ClipboardSetText",[e])}function he(){return s(":wails:ClipboardGetText")}function Ie(){window.WailsInvoke("Q")}function be(){window.WailsInvoke("S")}function Ee(){window.WailsInvoke("H")}function Se(){return s(":wails:Environment")}window.runtime={...m,...x,...h,...k,...I,EventsOn:b,EventsOnce:E,EventsOnMultiple:p,EventsEmit:C,EventsOff:D,Environment:Se,Show:be,Hide:Ee,Quit:Ie};window.wails={Callback:T,EventsNotify:y,SetBindings:O,eventListeners:l,callbacks:f,flags:{disableScrollbarDrag:!1,disableWailsDefaultContextMenu:!1,enableResize:!1,defaultCursor:null,borderThickness:6,shouldDrag:!1,deferDragToMouseMove:!1,cssDragProperty:"--wails-draggable",cssDragValue:"drag"}};window.wailsbindings&&(window.wails.SetBindings(window.wailsbindings),delete window.wails.SetBindings);delete window.wailsbindings;var ye=function(e){var n=window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);return n&&(n=n.trim()),!(n!==window.wails.flags.cssDragValue||e.buttons!==1||e.detail!==1)};window.wails.setCSSDragProperties=function(e,n){window.wails.flags.cssDragProperty=e,window.wails.flags.cssDragValue=n};window.addEventListener("mousedown",e=>{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(ye(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function w(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag)if((e.buttons!==void 0?e.buttons:e.which)<=0)window.wails.flags.shouldDrag=!1;else{window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX{var j=Object.defineProperty;var p=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})};var b={};p(b,{LogDebug:()=>$,LogError:()=>Q,LogFatal:()=>_,LogInfo:()=>Y,LogLevel:()=>K,LogPrint:()=>X,LogTrace:()=>J,LogWarning:()=>q,SetLogLevel:()=>Z});function u(e,t){window.WailsInvoke("L"+e+t)}function J(e){u("T",e)}function X(e){u("P",e)}function $(e){u("D",e)}function Y(e){u("I",e)}function q(e){u("W",e)}function Q(e){u("E",e)}function _(e){u("F",e)}function Z(e){u("S",e)}var K={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var y=class{constructor(t,n,o){this.eventName=t,this.maxCallbacks=o||-1,this.Callback=i=>(n.apply(null,i),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},w={};function v(e,t,n){w[e]=w[e]||[];let o=new y(e,t,n);return w[e].push(o),()=>ee(o)}function W(e,t){return v(e,t,-1)}function A(e,t){return v(e,t,1)}function P(e){let t=e.name,n=w[t]?.slice()||[];if(n.length){for(let o=n.length-1;o>=0;o-=1){let i=n[o],r=e.data;i.Callback(r)&&n.splice(o,1)}n.length===0?g(t):w[t]=n}}function F(e){let t;try{t=JSON.parse(e)}catch{let o="Invalid JSON passed to Notify: "+e;throw new Error(o)}P(t)}function R(e){let t={name:e,data:[].slice.apply(arguments).slice(1)};P(t),window.WailsInvoke("EE"+JSON.stringify(t))}function g(e){delete w[e],window.WailsInvoke("EX"+e)}function x(e,...t){g(e),t.length>0&&t.forEach(n=>{g(n)})}function M(){Object.keys(w).forEach(t=>{g(t)})}function ee(e){let t=e.eventName;w[t]!==void 0&&(w[t]=w[t].filter(n=>n!==e),w[t].length===0&&g(t))}var c={};function te(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function ne(){return Math.random()*9007199254740991}var D;window.crypto?D=te:D=ne;function a(e,t,n){return n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={name:e,args:t,callbackID:r};window.WailsInvoke("C"+JSON.stringify(d))}catch(d){console.error(d)}})}window.ObfuscatedCall=(e,t,n)=>(n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to method "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={id:e,args:t,callbackID:r};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function z(e){let t;try{t=JSON.parse(e)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let n=t.callbackid,o=c[n];if(!o){let i=`Callback '${n}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(o.timeoutHandle),delete c[n],t.error?o.reject(t.error):o.resolve(t.result)}window.go={};function B(e){try{e=JSON.parse(e)}catch(t){console.error(t)}window.go=window.go||{},Object.keys(e).forEach(t=>{window.go[t]=window.go[t]||{},Object.keys(e[t]).forEach(n=>{window.go[t][n]=window.go[t][n]||{},Object.keys(e[t][n]).forEach(o=>{window.go[t][n][o]=function(){let i=0;function r(){let l=[].slice.call(arguments);return a([t,n,o].join("."),l,i)}return r.setTimeout=function(l){i=l},r.getTimeout=function(){return i},r}()})})})}var T={};p(T,{WindowCenter:()=>ae,WindowFullscreen:()=>de,WindowGetPosition:()=>xe,WindowGetSize:()=>pe,WindowHide:()=>De,WindowIsFullscreen:()=>ue,WindowIsMaximised:()=>Te,WindowIsMinimised:()=>Ce,WindowIsNormal:()=>Ie,WindowMaximise:()=>Ee,WindowMinimise:()=>Se,WindowReload:()=>oe,WindowReloadApp:()=>ie,WindowSetAlwaysOnTop:()=>ve,WindowSetBackgroundColour:()=>Oe,WindowSetDarkTheme:()=>le,WindowSetLightTheme:()=>se,WindowSetMaxSize:()=>ge,WindowSetMinSize:()=>me,WindowSetPosition:()=>We,WindowSetSize:()=>ce,WindowSetSystemDefaultTheme:()=>re,WindowSetTitle:()=>we,WindowShow:()=>he,WindowToggleMaximise:()=>be,WindowUnfullscreen:()=>fe,WindowUnmaximise:()=>ye,WindowUnminimise:()=>ke});function oe(){window.location.reload()}function ie(){window.WailsInvoke("WR")}function re(){window.WailsInvoke("WASDT")}function se(){window.WailsInvoke("WALT")}function le(){window.WailsInvoke("WADT")}function ae(){window.WailsInvoke("Wc")}function we(e){window.WailsInvoke("WT"+e)}function de(){window.WailsInvoke("WF")}function fe(){window.WailsInvoke("Wf")}function ue(){return a(":wails:WindowIsFullscreen")}function ce(e,t){window.WailsInvoke("Ws:"+e+":"+t)}function pe(){return a(":wails:WindowGetSize")}function ge(e,t){window.WailsInvoke("WZ:"+e+":"+t)}function me(e,t){window.WailsInvoke("Wz:"+e+":"+t)}function ve(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function We(e,t){window.WailsInvoke("Wp:"+e+":"+t)}function xe(){return a(":wails:WindowGetPos")}function De(){window.WailsInvoke("WH")}function he(){window.WailsInvoke("WS")}function Ee(){window.WailsInvoke("WM")}function be(){window.WailsInvoke("Wt")}function ye(){window.WailsInvoke("WU")}function Te(){return a(":wails:WindowIsMaximised")}function Se(){window.WailsInvoke("Wm")}function ke(){window.WailsInvoke("Wu")}function Ce(){return a(":wails:WindowIsMinimised")}function Ie(){return a(":wails:WindowIsNormal")}function Oe(e,t,n,o){let i=JSON.stringify({r:e||0,g:t||0,b:n||0,a:o||255});window.WailsInvoke("Wr:"+i)}var S={};p(S,{ScreenGetAll:()=>Le});function Le(){return a(":wails:ScreenGetAll")}var k={};p(k,{BrowserOpenURL:()=>Ae});function Ae(e){window.WailsInvoke("BO:"+e)}var C={};p(C,{ClipboardGetText:()=>Fe,ClipboardSetText:()=>Pe});function Pe(e){return a(":wails:ClipboardSetText",[e])}function Fe(){return a(":wails:ClipboardGetText")}var I={};p(I,{CanResolveFilePaths:()=>V,OnFileDrop:()=>Me,OnFileDropOff:()=>ze,ResolveFilePaths:()=>Re});var s={registered:!1,defaultUseDropTarget:!0,useDropTarget:!0,nextDeactivate:null,nextDeactivateTimeout:null},m="wails-drop-target-active";function h(e){let t=e.getPropertyValue(window.wails.flags.cssDropProperty).trim();return t?t===window.wails.flags.cssDropValue:!1}function G(e){if(!e.dataTransfer.types.includes("Files")||(e.preventDefault(),e.dataTransfer.dropEffect="copy",!window.wails.flags.enableWailsDragAndDrop)||!s.useDropTarget)return;let n=e.target;if(s.nextDeactivate&&s.nextDeactivate(),!n||!h(getComputedStyle(n)))return;let o=n;for(;o;)h(getComputedStyle(o))&&o.classList.add(m),o=o.parentElement}function H(e){if(!!e.dataTransfer.types.includes("Files")&&(e.preventDefault(),!!window.wails.flags.enableWailsDragAndDrop&&!!s.useDropTarget)){if(!e.target||!h(getComputedStyle(e.target)))return null;s.nextDeactivate&&s.nextDeactivate(),s.nextDeactivate=()=>{Array.from(document.getElementsByClassName(m)).forEach(n=>n.classList.remove(m)),s.nextDeactivate=null,s.nextDeactivateTimeout&&(clearTimeout(s.nextDeactivateTimeout),s.nextDeactivateTimeout=null)},s.nextDeactivateTimeout=setTimeout(()=>{s.nextDeactivate&&s.nextDeactivate()},50)}}function U(e){if(!!e.dataTransfer.types.includes("Files")&&(e.preventDefault(),!!window.wails.flags.enableWailsDragAndDrop)){if(V()){let n=[];e.dataTransfer.items?n=[...e.dataTransfer.items].map((o,i)=>{if(o.kind==="file")return o.getAsFile()}):n=[...e.dataTransfer.files],window.runtime.ResolveFilePaths(e.x,e.y,n)}!s.useDropTarget||(s.nextDeactivate&&s.nextDeactivate(),Array.from(document.getElementsByClassName(m)).forEach(n=>n.classList.remove(m)))}}function V(){return window.chrome?.webview?.postMessageWithAdditionalObjects!=null}function Re(e,t,n){window.chrome?.webview?.postMessageWithAdditionalObjects&&chrome.webview.postMessageWithAdditionalObjects(`file:drop:${e}:${t}`,n)}function Me(e,t){if(typeof e!="function"){console.error("DragAndDropCallback is not a function");return}if(s.registered)return;s.registered=!0;let n=typeof t;s.useDropTarget=n==="undefined"||n!=="boolean"?s.defaultUseDropTarget:t,window.addEventListener("dragover",G),window.addEventListener("dragleave",H),window.addEventListener("drop",U);let o=e;s.useDropTarget&&(o=function(i,r,l){let d=document.elementFromPoint(i,r);if(!d||!h(getComputedStyle(d)))return null;e(i,r,l)}),W("wails:file-drop",o)}function ze(){window.removeEventListener("dragover",G),window.removeEventListener("dragleave",H),window.removeEventListener("drop",U),x("wails:file-drop"),s.registered=!1}function N(e){let t=e.target;switch(window.getComputedStyle(t).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(t.isContentEditable)return;let i=window.getSelection(),r=i.toString().length>0;if(r)for(let l=0;l{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(Ne(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function f(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag&&(window.wails.flags.shouldDrag=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
@@ -233,3 +233,17 @@ export function ClipboardGetText(): Promise;
// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
// Sets a text on the clipboard
export function ClipboardSetText(text: string): Promise;
+
+// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
+// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
+
+// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
+// OnFileDropOff removes the drag and drop listeners and handlers.
+export function OnFileDropOff() :void
+
+// Check if the file path resolver is available
+export function CanResolveFilePaths(): boolean;
+
+// Resolves file paths for an array of files
+export function ResolveFilePaths(files: File[]): void
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/wrapper/runtime.js b/v2/internal/frontend/runtime/wrapper/runtime.js
index 63f69788b..7cb89d750 100644
--- a/v2/internal/frontend/runtime/wrapper/runtime.js
+++ b/v2/internal/frontend/runtime/wrapper/runtime.js
@@ -37,19 +37,23 @@ export function LogFatal(message) {
}
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
- window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
+ return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
}
export function EventsOn(eventName, callback) {
- EventsOnMultiple(eventName, callback, -1);
+ return EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName, ...additionalEventNames) {
return window.runtime.EventsOff(eventName, ...additionalEventNames);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
- EventsOnMultiple(eventName, callback, 1);
+ return EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -199,4 +203,40 @@ export function ClipboardGetText() {
export function ClipboardSetText(text) {
return window.runtime.ClipboardSetText(text);
+}
+
+/**
+ * Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ *
+ * @export
+ * @callback OnFileDropCallback
+ * @param {number} x - x coordinate of the drop
+ * @param {number} y - y coordinate of the drop
+ * @param {string[]} paths - A list of file paths.
+ */
+
+/**
+ * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
+ *
+ * @export
+ * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
+ * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
+ */
+export function OnFileDrop(callback, useDropTarget) {
+ return window.runtime.OnFileDrop(callback, useDropTarget);
+}
+
+/**
+ * OnFileDropOff removes the drag and drop listeners and handlers.
+ */
+export function OnFileDropOff() {
+ return window.runtime.OnFileDropOff();
+}
+
+export function CanResolveFilePaths() {
+ return window.runtime.CanResolveFilePaths();
+}
+
+export function ResolveFilePaths(files) {
+ return window.runtime.ResolveFilePaths(files);
}
\ No newline at end of file
diff --git a/v2/internal/frontend/utils/urlValidator.go b/v2/internal/frontend/utils/urlValidator.go
new file mode 100644
index 000000000..76ba216ce
--- /dev/null
+++ b/v2/internal/frontend/utils/urlValidator.go
@@ -0,0 +1,58 @@
+package utils
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+ "regexp"
+ "strings"
+)
+
+func ValidateAndSanitizeURL(rawURL string) (string, error) {
+ // Check for null bytes (can cause truncation issues in some systems)
+ if strings.Contains(rawURL, "\x00") {
+ return "", errors.New("null bytes not allowed in URL")
+ }
+
+ // Parse URL first - this handles most malformed URLs
+ parsedURL, err := url.Parse(rawURL)
+ if err != nil {
+ return "", fmt.Errorf("invalid URL format: %v", err)
+ }
+
+ scheme := strings.ToLower(parsedURL.Scheme)
+
+ if scheme == "javascript" || scheme == "data" || scheme == "file" || scheme == "ftp" || scheme == "" {
+ return "", errors.New("scheme not allowed")
+ }
+
+ // Ensure there's actually a host for http/https URLs
+ if (scheme == "http" || scheme == "https") && parsedURL.Host == "" {
+ return "", fmt.Errorf("missing host for %s URL", scheme)
+ }
+
+ sanitizedURL := parsedURL.String()
+
+ // Check for control characters that might cause issues
+ // (but allow legitimate URL characters like &, ;, etc.)
+ for i, r := range sanitizedURL {
+ // Block control characters except tab, but allow other printable chars
+ if r < 32 && r != 9 { // 9 is tab, which might be legitimate
+ return "", fmt.Errorf("control character at position %d not allowed", i)
+ }
+ }
+
+ // Shell metacharacter check
+ shellDangerous := `[;\|` + "`" + `$\\<>*{}\[\]()~! \t\n\r]`
+ if matched, _ := regexp.MatchString(shellDangerous, sanitizedURL); matched {
+ return "", errors.New("shell metacharacters not allowed")
+ }
+
+ // Unicode danger check
+ unicodeDangerous := "[\u0000-\u001F\u007F\u00A0\u1680\u2000-\u200F\u2028-\u202F\u205F\u2060\u3000\uFEFF]"
+ if matched, _ := regexp.MatchString(unicodeDangerous, sanitizedURL); matched {
+ return "", errors.New("unicode dangerous characters not allowed")
+ }
+
+ return sanitizedURL, nil
+}
diff --git a/v2/internal/frontend/utils/urlValidator_test.go b/v2/internal/frontend/utils/urlValidator_test.go
new file mode 100644
index 000000000..b385ccec1
--- /dev/null
+++ b/v2/internal/frontend/utils/urlValidator_test.go
@@ -0,0 +1,207 @@
+package utils_test
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/wailsapp/wails/v2/internal/frontend/utils"
+)
+
+// Test cases for ValidateAndOpenURL
+func TestValidateURL(t *testing.T) {
+ testCases := []struct {
+ name string
+ url string
+ shouldErr bool
+ errMsg string
+ expected string
+ }{
+ // Valid URLs
+ {
+ name: "valid https URL",
+ url: "https://www.example.com",
+ shouldErr: false,
+ expected: "https://www.example.com",
+ },
+ {
+ name: "valid http URL",
+ url: "http://example.com",
+ shouldErr: false,
+ expected: "http://example.com",
+ },
+ {
+ name: "URL with query parameters",
+ url: "https://example.com/search?q=cats&dogs",
+ shouldErr: false,
+ expected: "https://example.com/search?q=cats&dogs",
+ },
+ {
+ name: "URL with port",
+ url: "https://example.com:8080/path",
+ shouldErr: false,
+ expected: "https://example.com:8080/path",
+ },
+ {
+ name: "URL with fragment",
+ url: "https://example.com/page#section",
+ shouldErr: false,
+ expected: "https://example.com/page#section",
+ },
+ {
+ name: "urlencode params",
+ url: "http://google.com/ ----browser-subprocess-path=C:\\\\Users\\\\Public\\\\test.bat",
+ shouldErr: false,
+ expected: "http://google.com/%20----browser-subprocess-path=C:%5C%5CUsers%5C%5CPublic%5C%5Ctest.bat",
+ },
+
+ // Invalid schemes
+ {
+ name: "javascript scheme",
+ url: "javascript:alert('xss')",
+ shouldErr: true,
+ errMsg: "scheme not allowed",
+ },
+ {
+ name: "data scheme",
+ url: "data:text/html,",
+ shouldErr: true,
+ errMsg: "scheme not allowed",
+ },
+ {
+ name: "file scheme",
+ url: "file:///etc/passwd",
+ shouldErr: true,
+ errMsg: "scheme not allowed",
+ },
+ {
+ name: "ftp scheme",
+ url: "ftp://files.example.com/file.txt",
+ shouldErr: true,
+ errMsg: "scheme not allowed",
+ },
+
+ // Malformed URLs
+ {
+ name: "not a URL",
+ url: "not-a-url",
+ shouldErr: true,
+ errMsg: "scheme not allowed", // will have empty scheme
+ },
+ {
+ name: "missing scheme",
+ url: "example.com",
+ shouldErr: true,
+ errMsg: "scheme not allowed",
+ },
+ {
+ name: "malformed URL",
+ url: "https://",
+ shouldErr: true,
+ errMsg: "missing host",
+ },
+ {
+ name: "empty host",
+ url: "http:///path",
+ shouldErr: true,
+ errMsg: "missing host",
+ },
+
+ // Security issues
+ {
+ name: "null byte in URL",
+ url: "https://example.com\x00/hidden",
+ shouldErr: true,
+ errMsg: "null bytes not allowed",
+ },
+ {
+ name: "control characters",
+ url: "https://example.com\n/path",
+ shouldErr: true,
+ errMsg: "control character",
+ },
+ {
+ name: "carriage return",
+ url: "https://example.com\r/path",
+ shouldErr: true,
+ errMsg: "control character",
+ },
+ {
+ name: "URL with tab character",
+ url: "https://example.com/path?q=hello\tworld",
+ shouldErr: true,
+ errMsg: "control character",
+ },
+ {
+ name: "URL with path parameters",
+ url: "https://example.com/path;param=value",
+ shouldErr: true,
+ errMsg: "shell metacharacters not allowed",
+ },
+ {
+ name: "URL with special characters in query",
+ url: "https://example.com/search?q=hello world&filter=price>100",
+ shouldErr: true,
+ errMsg: "shell metacharacters not allowed",
+ },
+ {
+ name: "URL with special characters in query and params",
+ url: "https://example.com/search?q=hello ----browser-subprocess-path=C:\\\\Users\\\\Public\\\\test.bat",
+ shouldErr: true,
+ errMsg: "shell metacharacters not allowed",
+ },
+ {
+ name: "URL with dollar sign in query",
+ url: "https://example.com/search?price=$100",
+ shouldErr: true,
+ errMsg: "shell metacharacters not allowed",
+ },
+ {
+ name: "URL with parentheses",
+ url: "https://example.com/file(1).html",
+ shouldErr: true,
+ errMsg: "shell metacharacters not allowed",
+ },
+ {
+ name: "URL with unicode",
+ url: "https://example.com/search?q=hello\u2001foo",
+ shouldErr: true,
+ errMsg: "unicode dangerous characters not allowed",
+ },
+
+ // Edge cases
+ {
+ name: "international domain",
+ url: "https://例え.テスト/path",
+ shouldErr: false,
+ expected: "https://%E4%BE%8B%E3%81%88.%E3%83%86%E3%82%B9%E3%83%88/path",
+ },
+ {
+ name: "URL with pipe character",
+ url: "https://example.com/user/123|admin",
+ shouldErr: false,
+ expected: "https://example.com/user/123%7Cadmin",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ // We'll test only the validation part to avoid actually opening URLs
+ sanitized, err := utils.ValidateAndSanitizeURL(tc.url)
+
+ if tc.shouldErr {
+ if err == nil {
+ t.Errorf("expected error for URL %q, but got none", tc.url)
+ } else if tc.errMsg != "" && !strings.Contains(err.Error(), tc.errMsg) {
+ t.Errorf("expected error containing %q, got %q", tc.errMsg, err.Error())
+ }
+ } else {
+ if err != nil {
+ t.Errorf("expected no error for URL %q, but got: %v", tc.url, err)
+ }
+ if sanitized != tc.expected {
+ t.Errorf("unexpected sanitized URL for %q: expected %q, got %q", tc.url, tc.expected, sanitized)
+ }
+ }
+ })
+ }
+}
diff --git a/v2/internal/fs/fs.go b/v2/internal/fs/fs.go
index 5bfa71b1c..5662c020c 100644
--- a/v2/internal/fs/fs.go
+++ b/v2/internal/fs/fs.go
@@ -2,6 +2,7 @@ package fs
import (
"crypto/md5"
+ "encoding/hex"
"fmt"
"io"
"io/fs"
@@ -27,14 +28,14 @@ func RelativeToCwd(relativePath string) (string, error) {
// Mkdir will create the given directory
func Mkdir(dirname string) error {
- return os.Mkdir(dirname, 0755)
+ return os.Mkdir(dirname, 0o755)
}
// MkDirs creates the given nested directories.
// Returns error on failure
func MkDirs(fullPath string, mode ...os.FileMode) error {
var perms os.FileMode
- perms = 0755
+ perms = 0o755
if len(mode) == 1 {
perms = mode[0]
}
@@ -111,7 +112,7 @@ func RelativePath(relativepath string, optionalpaths ...string) string {
// I'm allowing this for 1 reason only: It's fatal if the path
// supplied is wrong as it's only used internally in Wails. If we get
// that path wrong, we should know about it immediately. The other reason is
- // that it cuts down a ton of unnecassary error handling.
+ // that it cuts down a ton of unnecessary error handling.
panic(err)
}
return result
@@ -141,7 +142,7 @@ func MD5File(filename string) (string, error) {
return "", err
}
- return fmt.Sprintf("%x", h.Sum(nil)), nil
+ return hex.EncodeToString(h.Sum(nil)), nil
}
// MustMD5File will call MD5File and abort the program on error
@@ -157,7 +158,7 @@ func MustMD5File(filename string) string {
// MustWriteString will attempt to write the given data to the given filename
// It will abort the program in the event of a failure
func MustWriteString(filename string, data string) {
- err := os.WriteFile(filename, []byte(data), 0755)
+ err := os.WriteFile(filename, []byte(data), 0o755)
if err != nil {
fatal("Unable to write file", filename, ":", err.Error())
os.Exit(1)
@@ -194,7 +195,6 @@ func GetSubdirectories(rootDir string) (*slicer.StringSlicer, error) {
}
func DirIsEmpty(dir string) (bool, error) {
-
// CREDIT: https://stackoverflow.com/a/30708914/8325411
f, err := os.Open(dir)
if err != nil {
@@ -284,7 +284,6 @@ func SetPermissions(dir string, perm os.FileMode) error {
// 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)
@@ -382,7 +381,6 @@ func FindPathToFile(fsys fs.FS, file string) (string, error) {
// FindFileInParents searches for a file in the current directory and all parent directories.
// Returns the absolute path to the file if found, otherwise an empty string
func FindFileInParents(path string, filename string) string {
-
// Check for bad paths
if _, err := os.Stat(path); err != nil {
return ""
diff --git a/v2/internal/github/github.go b/v2/internal/github/github.go
index db3b70c58..2aa5e1432 100644
--- a/v2/internal/github/github.go
+++ b/v2/internal/github/github.go
@@ -3,13 +3,15 @@ package github
import (
"encoding/json"
"fmt"
- "github.com/charmbracelet/glamour"
+ "github.com/charmbracelet/glamour/styles"
"io"
"net/http"
"net/url"
"runtime"
"sort"
"strings"
+
+ "github.com/charmbracelet/glamour"
)
func GetReleaseNotes(tagVersion string, noColour bool) string {
@@ -38,7 +40,7 @@ func GetReleaseNotes(tagVersion string, noColour bool) string {
var termRendererOpts []glamour.TermRendererOption
if runtime.GOOS == "windows" || noColour {
- termRendererOpts = append(termRendererOpts, glamour.WithStyles(glamour.NoTTYStyleConfig))
+ termRendererOpts = append(termRendererOpts, glamour.WithStyles(styles.NoTTYStyleConfig))
} else {
termRendererOpts = append(termRendererOpts, glamour.WithAutoStyle())
}
@@ -57,7 +59,6 @@ func GetReleaseNotes(tagVersion string, noColour bool) string {
// GetVersionTags gets the list of tags on the Wails repo
// It returns a list of sorted tags in descending order
func GetVersionTags() ([]*SemanticVersion, error) {
-
result := []*SemanticVersion{}
var err error
@@ -97,7 +98,6 @@ func GetVersionTags() ([]*SemanticVersion, error) {
// GetLatestStableRelease gets the latest stable release on GitHub
func GetLatestStableRelease() (result *SemanticVersion, err error) {
-
tags, err := GetVersionTags()
if err != nil {
return nil, err
@@ -114,7 +114,6 @@ func GetLatestStableRelease() (result *SemanticVersion, err error) {
// GetLatestPreRelease gets the latest prerelease on GitHub
func GetLatestPreRelease() (result *SemanticVersion, err error) {
-
tags, err := GetVersionTags()
if err != nil {
return nil, err
diff --git a/v2/internal/go-common-file-dialog/cfd/DialogConfig.go b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go
index 221dbef27..9e06fb503 100644
--- a/v2/internal/go-common-file-dialog/cfd/DialogConfig.go
+++ b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go
@@ -2,6 +2,12 @@
package cfd
+import (
+ "fmt"
+ "os"
+ "reflect"
+)
+
type FileFilter struct {
// The display name of the filter (That is shown to the user)
DisplayName string
@@ -9,6 +15,9 @@ type FileFilter struct {
Pattern string
}
+// Never obfuscate the FileFilter type.
+var _ = reflect.TypeOf(FileFilter{})
+
type DialogConfig struct {
// The title of the dialog
Title string
@@ -67,6 +76,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) {
}
if config.Folder != "" {
+ _, err = os.Stat(config.Folder)
+ if err != nil {
+ return
+ }
err = dialog.SetFolder(config.Folder)
if err != nil {
return
@@ -74,6 +87,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) {
}
if config.DefaultFolder != "" {
+ _, err = os.Stat(config.DefaultFolder)
+ if err != nil {
+ return
+ }
err = dialog.SetDefaultFolder(config.DefaultFolder)
if err != nil {
return
@@ -102,6 +119,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) {
}
if config.SelectedFileFilterIndex != 0 {
+ if config.SelectedFileFilterIndex > uint(len(fileFilters)) {
+ err = fmt.Errorf("selected file filter index out of range")
+ return
+ }
err = dialog.SetSelectedFileFilterIndex(config.SelectedFileFilterIndex)
if err != nil {
return
diff --git a/v2/internal/go-common-file-dialog/cfd/errors.go b/v2/internal/go-common-file-dialog/cfd/errors.go
index c097c8eb2..4ca3300b9 100644
--- a/v2/internal/go-common-file-dialog/cfd/errors.go
+++ b/v2/internal/go-common-file-dialog/cfd/errors.go
@@ -3,5 +3,7 @@ package cfd
import "errors"
var (
- ErrorCancelled = errors.New("cancelled by user")
+ ErrCancelled = errors.New("cancelled by user")
+ ErrInvalidGUID = errors.New("guid cannot be nil")
+ ErrEmptyFilters = errors.New("must specify at least one filter")
)
diff --git a/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go
index 8c82cda2c..b1be23fcf 100644
--- a/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go
+++ b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go
@@ -5,7 +5,7 @@ package cfd
import (
"github.com/go-ole/go-ole"
- "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util"
+ "github.com/google/uuid"
"syscall"
"unsafe"
)
@@ -106,7 +106,7 @@ func (fileOpenDialog *iFileOpenDialog) SetFileFilters(filter []FileFilter) error
}
func (fileOpenDialog *iFileOpenDialog) SetRole(role string) error {
- return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), util.StringToUUID(role))
+ return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), StringToUUID(role))
}
// This should only be callable when the user asks for a multi select because
@@ -164,8 +164,7 @@ func (fileOpenDialog *iFileOpenDialog) setIsMultiselect(isMultiselect bool) erro
func (vtbl *iFileOpenDialogVtbl) getResults(objPtr unsafe.Pointer) (*iShellItemArray, error) {
var shellItemArray *iShellItemArray
- ret, _, _ := syscall.Syscall(vtbl.GetResults,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.GetResults,
uintptr(objPtr),
uintptr(unsafe.Pointer(&shellItemArray)),
0)
@@ -178,7 +177,7 @@ func (vtbl *iFileOpenDialogVtbl) getResultsStrings(objPtr unsafe.Pointer) ([]str
return nil, err
}
if shellItemArray == nil {
- return nil, ErrorCancelled
+ return nil, ErrCancelled
}
defer shellItemArray.vtbl.release(unsafe.Pointer(shellItemArray))
count, err := shellItemArray.vtbl.getCount(unsafe.Pointer(shellItemArray))
@@ -195,3 +194,7 @@ func (vtbl *iFileOpenDialogVtbl) getResultsStrings(objPtr unsafe.Pointer) ([]str
}
return results, nil
}
+
+func StringToUUID(str string) *ole.GUID {
+ return ole.NewGUID(uuid.NewSHA1(uuid.Nil, []byte(str)).String())
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go
index 3effeda25..ddee7b246 100644
--- a/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go
+++ b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go
@@ -5,7 +5,6 @@ package cfd
import (
"github.com/go-ole/go-ole"
- "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util"
"unsafe"
)
@@ -77,7 +76,7 @@ func (fileSaveDialog *iFileSaveDialog) SetFileFilters(filter []FileFilter) error
}
func (fileSaveDialog *iFileSaveDialog) SetRole(role string) error {
- return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), util.StringToUUID(role))
+ return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), StringToUUID(role))
}
func (fileSaveDialog *iFileSaveDialog) SetDefaultExtension(defaultExtension string) error {
diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItem.go b/v2/internal/go-common-file-dialog/cfd/iShellItem.go
index 6a747f4d9..080115345 100644
--- a/v2/internal/go-common-file-dialog/cfd/iShellItem.go
+++ b/v2/internal/go-common-file-dialog/cfd/iShellItem.go
@@ -30,6 +30,10 @@ type iShellItemVtbl struct {
func newIShellItem(path string) (*iShellItem, error) {
var shellItem *iShellItem
pathPtr := ole.SysAllocString(path)
+ defer func(v *int16) {
+ _ = ole.SysFreeString(v)
+ }(pathPtr)
+
ret, _, _ := procSHCreateItemFromParsingName.Call(
uintptr(unsafe.Pointer(pathPtr)),
0,
@@ -40,10 +44,9 @@ func newIShellItem(path string) (*iShellItem, error) {
func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error) {
var ptr *uint16
- ret, _, _ := syscall.Syscall(vtbl.GetDisplayName,
- 2,
+ ret, _, _ := syscall.SyscallN(vtbl.GetDisplayName,
uintptr(objPtr),
- 0x80058000, // SIGDN_FILESYSPATH
+ 0x80058000, // SIGDN_FILESYSPATH,
uintptr(unsafe.Pointer(&ptr)))
if err := hresultToError(ret); err != nil {
return "", err
diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go
index 84f26fa20..c548160d1 100644
--- a/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go
+++ b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go
@@ -38,11 +38,9 @@ type iShellItemArrayVtbl struct {
func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error) {
var count uintptr
- ret, _, _ := syscall.Syscall(vtbl.GetCount,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.GetCount,
uintptr(objPtr),
- uintptr(unsafe.Pointer(&count)),
- 0)
+ uintptr(unsafe.Pointer(&count)))
if err := hresultToError(ret); err != nil {
return 0, err
}
@@ -51,8 +49,7 @@ func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error
func (vtbl *iShellItemArrayVtbl) getItemAt(objPtr unsafe.Pointer, index uintptr) (string, error) {
var shellItem *iShellItem
- ret, _, _ := syscall.Syscall(vtbl.GetItemAt,
- 2,
+ ret, _, _ := syscall.SyscallN(vtbl.GetItemAt,
uintptr(objPtr),
index,
uintptr(unsafe.Pointer(&shellItem)))
@@ -60,7 +57,7 @@ func (vtbl *iShellItemArrayVtbl) getItemAt(objPtr unsafe.Pointer, index uintptr)
return "", err
}
if shellItem == nil {
- return "", ErrorCancelled
+ return "", ErrCancelled
}
defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem))
diff --git a/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go
index a92100010..581a7b25c 100644
--- a/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go
+++ b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go
@@ -1,10 +1,8 @@
//go:build windows
-// +build windows
package cfd
import (
- "fmt"
"github.com/go-ole/go-ole"
"strings"
"syscall"
@@ -19,27 +17,23 @@ func hresultToError(hr uintptr) error {
}
func (vtbl *iUnknownVtbl) release(objPtr unsafe.Pointer) error {
- ret, _, _ := syscall.Syscall(vtbl.Release,
- 0,
+ ret, _, _ := syscall.SyscallN(vtbl.Release,
uintptr(objPtr),
- 0,
0)
return hresultToError(ret)
}
func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error {
- ret, _, _ := syscall.Syscall(vtbl.Show,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.Show,
uintptr(objPtr),
- hwnd,
- 0)
+ hwnd)
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileFilter) error {
cFileTypes := len(filters)
if cFileTypes < 0 {
- return fmt.Errorf("must specify at least one filter")
+ return ErrEmptyFilters
}
comDlgFilterSpecs := make([]comDlgFilterSpec, cFileTypes)
for i := 0; i < cFileTypes; i++ {
@@ -49,8 +43,16 @@ func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileF
pszSpec: ole.SysAllocString(filter.Pattern),
}
}
- ret, _, _ := syscall.Syscall(vtbl.SetFileTypes,
- 2,
+
+ // Ensure memory is freed after use
+ defer func() {
+ for _, spec := range comDlgFilterSpecs {
+ ole.SysFreeString(spec.pszName)
+ ole.SysFreeString(spec.pszSpec)
+ }
+ }()
+
+ ret, _, _ := syscall.SyscallN(vtbl.SetFileTypes,
uintptr(objPtr),
uintptr(cFileTypes),
uintptr(unsafe.Pointer(&comDlgFilterSpecs[0])))
@@ -82,21 +84,17 @@ func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileF
// FOS_FORCEPREVIEWPANEON = 0x40000000,
// FOS_SUPPORTSTREAMABLEITEMS = 0x80000000
func (vtbl *iFileDialogVtbl) setOptions(objPtr unsafe.Pointer, options uint32) error {
- ret, _, _ := syscall.Syscall(vtbl.SetOptions,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.SetOptions,
uintptr(objPtr),
- uintptr(options),
- 0)
+ uintptr(options))
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) getOptions(objPtr unsafe.Pointer) (uint32, error) {
var options uint32
- ret, _, _ := syscall.Syscall(vtbl.GetOptions,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.GetOptions,
uintptr(objPtr),
- uintptr(unsafe.Pointer(&options)),
- 0)
+ uintptr(unsafe.Pointer(&options)))
return options, hresultToError(ret)
}
@@ -122,11 +120,9 @@ func (vtbl *iFileDialogVtbl) setDefaultFolder(objPtr unsafe.Pointer, path string
return err
}
defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
- ret, _, _ := syscall.Syscall(vtbl.SetDefaultFolder,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.SetDefaultFolder,
uintptr(objPtr),
- uintptr(unsafe.Pointer(shellItem)),
- 0)
+ uintptr(unsafe.Pointer(shellItem)))
return hresultToError(ret)
}
@@ -136,40 +132,32 @@ func (vtbl *iFileDialogVtbl) setFolder(objPtr unsafe.Pointer, path string) error
return err
}
defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
- ret, _, _ := syscall.Syscall(vtbl.SetFolder,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.SetFolder,
uintptr(objPtr),
- uintptr(unsafe.Pointer(shellItem)),
- 0)
+ uintptr(unsafe.Pointer(shellItem)))
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) setTitle(objPtr unsafe.Pointer, title string) error {
titlePtr := ole.SysAllocString(title)
- ret, _, _ := syscall.Syscall(vtbl.SetTitle,
- 1,
+ defer ole.SysFreeString(titlePtr) // Ensure the string is freed
+ ret, _, _ := syscall.SyscallN(vtbl.SetTitle,
uintptr(objPtr),
- uintptr(unsafe.Pointer(titlePtr)),
- 0)
+ uintptr(unsafe.Pointer(titlePtr)))
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) close(objPtr unsafe.Pointer) error {
- ret, _, _ := syscall.Syscall(vtbl.Close,
- 1,
- uintptr(objPtr),
- 0,
- 0)
+ ret, _, _ := syscall.SyscallN(vtbl.Close,
+ uintptr(objPtr))
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) getResult(objPtr unsafe.Pointer) (*iShellItem, error) {
var shellItem *iShellItem
- ret, _, _ := syscall.Syscall(vtbl.GetResult,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.GetResult,
uintptr(objPtr),
- uintptr(unsafe.Pointer(&shellItem)),
- 0)
+ uintptr(unsafe.Pointer(&shellItem)))
return shellItem, hresultToError(ret)
}
@@ -179,49 +167,58 @@ func (vtbl *iFileDialogVtbl) getResultString(objPtr unsafe.Pointer) (string, err
return "", err
}
if shellItem == nil {
- return "", ErrorCancelled
+ return "", ErrCancelled
}
defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem))
}
func (vtbl *iFileDialogVtbl) setClientGuid(objPtr unsafe.Pointer, guid *ole.GUID) error {
- ret, _, _ := syscall.Syscall(vtbl.SetClientGuid,
- 1,
+ // Ensure the GUID is not nil
+ if guid == nil {
+ return ErrInvalidGUID
+ }
+
+ // Call the SetClientGuid method
+ ret, _, _ := syscall.SyscallN(vtbl.SetClientGuid,
uintptr(objPtr),
- uintptr(unsafe.Pointer(guid)),
- 0)
+ uintptr(unsafe.Pointer(guid)))
+
+ // Convert the HRESULT to a Go error
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) setDefaultExtension(objPtr unsafe.Pointer, defaultExtension string) error {
- if defaultExtension[0] == '.' {
+ // Ensure the string is not empty before accessing the first character
+ if len(defaultExtension) > 0 && defaultExtension[0] == '.' {
defaultExtension = strings.TrimPrefix(defaultExtension, ".")
}
+
+ // Allocate memory for the default extension string
defaultExtensionPtr := ole.SysAllocString(defaultExtension)
- ret, _, _ := syscall.Syscall(vtbl.SetDefaultExtension,
- 1,
+ defer ole.SysFreeString(defaultExtensionPtr) // Ensure the string is freed
+
+ // Call the SetDefaultExtension method
+ ret, _, _ := syscall.SyscallN(vtbl.SetDefaultExtension,
uintptr(objPtr),
- uintptr(unsafe.Pointer(defaultExtensionPtr)),
- 0)
+ uintptr(unsafe.Pointer(defaultExtensionPtr)))
+
+ // Convert the HRESULT to a Go error
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) setFileName(objPtr unsafe.Pointer, fileName string) error {
fileNamePtr := ole.SysAllocString(fileName)
- ret, _, _ := syscall.Syscall(vtbl.SetFileName,
- 1,
+ defer ole.SysFreeString(fileNamePtr) // Ensure the string is freed
+ ret, _, _ := syscall.SyscallN(vtbl.SetFileName,
uintptr(objPtr),
- uintptr(unsafe.Pointer(fileNamePtr)),
- 0)
+ uintptr(unsafe.Pointer(fileNamePtr)))
return hresultToError(ret)
}
func (vtbl *iFileDialogVtbl) setSelectedFileFilterIndex(objPtr unsafe.Pointer, index uint) error {
- ret, _, _ := syscall.Syscall(vtbl.SetFileTypeIndex,
- 1,
+ ret, _, _ := syscall.SyscallN(vtbl.SetFileTypeIndex,
uintptr(objPtr),
- uintptr(index+1), // SetFileTypeIndex counts from 1
- 0)
+ uintptr(index+1)) // SetFileTypeIndex counts from 1
return hresultToError(ret)
}
diff --git a/v2/internal/gomod/gomod.go b/v2/internal/gomod/gomod.go
index 8ab7e0b66..c38e60f0b 100644
--- a/v2/internal/gomod/gomod.go
+++ b/v2/internal/gomod/gomod.go
@@ -2,6 +2,7 @@ package gomod
import (
"fmt"
+
"github.com/Masterminds/semver"
"golang.org/x/mod/modfile"
)
diff --git a/v2/internal/gomod/gomod_data_unix.go b/v2/internal/gomod/gomod_data_unix.go
index f3a5e04c3..c6004f486 100644
--- a/v2/internal/gomod/gomod_data_unix.go
+++ b/v2/internal/gomod/gomod_data_unix.go
@@ -10,6 +10,7 @@ require github.com/wailsapp/wails/v2 v2.0.0-beta.7
//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => /home/lea/wails/v2
`
+
const basicUpdated string = `module changeme
go 1.17
@@ -29,6 +30,7 @@ require (
//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => /home/lea/wails/v2
`
+
const multilineReplace = `module changeme
go 1.17
@@ -98,6 +100,7 @@ require (
replace github.com/wailsapp/wails/v2 v2.0.0-beta.20 => /home/lea/wails/v2
`
+
const multilineReplaceNoVersionUpdated = `module changeme
go 1.17
@@ -108,6 +111,7 @@ require (
replace github.com/wailsapp/wails/v2 => /home/lea/wails/v2
`
+
const multilineReplaceNoVersionBlockUpdated = `module changeme
go 1.17
diff --git a/v2/internal/goversion/min.go b/v2/internal/goversion/min.go
index 17edc0c94..8c057b3c2 100644
--- a/v2/internal/goversion/min.go
+++ b/v2/internal/goversion/min.go
@@ -1,3 +1,3 @@
package goversion
-const MinRequirement string = "1.18"
+const MinRequirement string = "1.20"
diff --git a/v2/internal/logger/custom_logger.go b/v2/internal/logger/custom_logger.go
index 5e24aa093..51e07c0fc 100644
--- a/v2/internal/logger/custom_logger.go
+++ b/v2/internal/logger/custom_logger.go
@@ -86,7 +86,6 @@ func (l *customLogger) Warning(format string, args ...interface{}) {
func (l *customLogger) Error(format string, args ...interface{}) {
format = fmt.Sprintf("%s | %s", l.name, format)
l.logger.Error(format, args...)
-
}
// Fatal level logging. Works like Sprintf.
diff --git a/v2/internal/logger/default_logger.go b/v2/internal/logger/default_logger.go
index fe5c05387..5c72ae209 100644
--- a/v2/internal/logger/default_logger.go
+++ b/v2/internal/logger/default_logger.go
@@ -84,7 +84,6 @@ func (l *Logger) Info(format string, args ...interface{}) {
if l.logLevel <= logger.INFO {
l.output.Info(fmt.Sprintf(format, args...))
}
-
}
// Warning level logging. Works like Sprintf.
@@ -99,7 +98,6 @@ func (l *Logger) Error(format string, args ...interface{}) {
if l.logLevel <= logger.ERROR {
l.output.Error(fmt.Sprintf(format, args...))
}
-
}
// Fatal level logging. Works like Sprintf.
diff --git a/v2/internal/menumanager/applicationmenu.go b/v2/internal/menumanager/applicationmenu.go
index 424834e53..4446a00cb 100644
--- a/v2/internal/menumanager/applicationmenu.go
+++ b/v2/internal/menumanager/applicationmenu.go
@@ -3,7 +3,6 @@ package menumanager
import "github.com/wailsapp/wails/v2/pkg/menu"
func (m *Manager) SetApplicationMenu(applicationMenu *menu.Menu) error {
-
if applicationMenu == nil {
return nil
}
@@ -38,7 +37,6 @@ func (m *Manager) UpdateApplicationMenu() (string, error) {
}
func (m *Manager) processApplicationMenu() error {
-
// Process the menu
m.processedApplicationMenu = NewWailsMenu(m.applicationMenuItemMap, m.applicationMenu)
m.processRadioGroups(m.processedApplicationMenu, m.applicationMenuItemMap)
diff --git a/v2/internal/menumanager/contextmenu.go b/v2/internal/menumanager/contextmenu.go
index 77c47891c..f05bcdc49 100644
--- a/v2/internal/menumanager/contextmenu.go
+++ b/v2/internal/menumanager/contextmenu.go
@@ -23,7 +23,6 @@ func (t *ContextMenu) AsJSON() (string, error) {
}
func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu {
-
result := &ContextMenu{
ID: contextMenu.ID,
menu: contextMenu.Menu,
@@ -37,7 +36,6 @@ func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu {
}
func (m *Manager) AddContextMenu(contextMenu *menu.ContextMenu) {
-
newContextMenu := NewContextMenu(contextMenu)
// Save the references
diff --git a/v2/internal/menumanager/menuitemmap.go b/v2/internal/menumanager/menuitemmap.go
index 790d5d06d..e4e291be6 100644
--- a/v2/internal/menumanager/menuitemmap.go
+++ b/v2/internal/menumanager/menuitemmap.go
@@ -2,8 +2,10 @@ package menumanager
import (
"fmt"
- "github.com/wailsapp/wails/v2/pkg/menu"
+ "strconv"
"sync"
+
+ "github.com/wailsapp/wails/v2/pkg/menu"
)
// MenuItemMap holds a mapping between menuIDs and menu items
@@ -48,14 +50,13 @@ func (m *MenuItemMap) Dump() {
// GenerateMenuID returns a unique string ID for a menu item
func (m *MenuItemMap) generateMenuID() string {
m.menuIDCounterMutex.Lock()
- result := fmt.Sprintf("%d", m.menuIDCounter)
+ result := strconv.FormatInt(m.menuIDCounter, 10)
m.menuIDCounter++
m.menuIDCounterMutex.Unlock()
return result
}
func (m *MenuItemMap) processMenuItem(item *menu.MenuItem) {
-
if item.SubMenu != nil {
for _, submenuitem := range item.SubMenu.Items {
m.processMenuItem(submenuitem)
diff --git a/v2/internal/menumanager/menumanager.go b/v2/internal/menumanager/menumanager.go
index ea7939415..0c6be0df2 100644
--- a/v2/internal/menumanager/menumanager.go
+++ b/v2/internal/menumanager/menumanager.go
@@ -2,11 +2,11 @@ package menumanager
import (
"fmt"
+
"github.com/wailsapp/wails/v2/pkg/menu"
)
type Manager struct {
-
// The application menu.
applicationMenu *menu.Menu
applicationMenuJSON string
@@ -43,7 +43,6 @@ func (m *Manager) getMenuItemByID(menuMap *MenuItemMap, menuId string) *menu.Men
}
func (m *Manager) ProcessClick(menuID string, data string, menuType string, parentID string) error {
-
var menuItemMap *MenuItemMap
switch menuType {
@@ -93,7 +92,7 @@ func (m *Manager) ProcessClick(menuID string, data string, menuType string, pare
// Create new Callback struct
callbackData := &menu.CallbackData{
MenuItem: menuItem,
- //ContextData: data,
+ // ContextData: data,
}
// Call back!
diff --git a/v2/internal/menumanager/processedMenu.go b/v2/internal/menumanager/processedMenu.go
index 8d886e19e..c87646ccb 100644
--- a/v2/internal/menumanager/processedMenu.go
+++ b/v2/internal/menumanager/processedMenu.go
@@ -2,6 +2,7 @@ package menumanager
import (
"encoding/json"
+
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/menu/keys"
)
@@ -11,7 +12,7 @@ type ProcessedMenuItem struct {
// Label is what appears as the menu text
Label string `json:",omitempty"`
// Role is a predefined menu type
- //Role menu.Role `json:",omitempty"`
+ // Role menu.Role `json:",omitempty"`
// Accelerator holds a representation of a key binding
Accelerator *keys.Accelerator `json:",omitempty"`
// Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu
@@ -22,8 +23,8 @@ type ProcessedMenuItem struct {
Hidden bool `json:",omitempty"`
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
Checked bool `json:",omitempty"`
- // Submenu contains a list of menu items that will be shown as a submenu
- //SubMenu []*MenuItem `json:"SubMenu,omitempty"`
+ // SubMenu contains a list of menu items that will be shown as a submenu
+ // SubMenu []*MenuItem `json:"SubMenu,omitempty"`
SubMenu *ProcessedMenu `json:",omitempty"`
/*
// Colour
@@ -47,7 +48,6 @@ type ProcessedMenuItem struct {
}
func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem {
-
ID := menuItemMap.menuItemToIDMap[menuItem]
// Parse ANSI text
@@ -63,21 +63,21 @@ func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *Pr
result := &ProcessedMenuItem{
ID: ID,
Label: menuItem.Label,
- //Role: menuItem.Role,
+ // Role: menuItem.Role,
Accelerator: menuItem.Accelerator,
Type: menuItem.Type,
Disabled: menuItem.Disabled,
Hidden: menuItem.Hidden,
Checked: menuItem.Checked,
SubMenu: nil,
- //BackgroundColour: menuItem.BackgroundColour,
- //FontSize: menuItem.FontSize,
- //FontName: menuItem.FontName,
- //Image: menuItem.Image,
- //MacTemplateImage: menuItem.MacTemplateImage,
- //MacAlternate: menuItem.MacAlternate,
- //Tooltip: menuItem.Tooltip,
- //StyledLabel: styledLabel,
+ // BackgroundColour: menuItem.BackgroundColour,
+ // FontSize: menuItem.FontSize,
+ // FontName: menuItem.FontName,
+ // Image: menuItem.Image,
+ // MacTemplateImage: menuItem.MacTemplateImage,
+ // MacAlternate: menuItem.MacAlternate,
+ // Tooltip: menuItem.Tooltip,
+ // StyledLabel: styledLabel,
}
if menuItem.SubMenu != nil {
@@ -92,7 +92,6 @@ type ProcessedMenu struct {
}
func NewProcessedMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *ProcessedMenu {
-
result := &ProcessedMenu{}
if menu != nil {
for _, item := range menu.Items {
@@ -131,7 +130,6 @@ func NewWailsMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *WailsMenu {
}
func (w *WailsMenu) AsJSON() (string, error) {
-
menuAsJSON, err := json.Marshal(w)
if err != nil {
return "", err
@@ -150,7 +148,6 @@ func (w *WailsMenu) processRadioGroups() {
}
func (w *WailsMenu) processMenuItem(item *ProcessedMenuItem) {
-
switch item.Type {
// We need to recurse submenus
@@ -172,7 +169,6 @@ func (w *WailsMenu) processMenuItem(item *ProcessedMenuItem) {
}
func (w *WailsMenu) finaliseRadioGroup() {
-
// If we were processing a radio group, fix up the references
if len(w.currentRadioGroup) > 0 {
diff --git a/v2/internal/menumanager/traymenu.go b/v2/internal/menumanager/traymenu.go
index aed5b05ac..5efc4a861 100644
--- a/v2/internal/menumanager/traymenu.go
+++ b/v2/internal/menumanager/traymenu.go
@@ -13,8 +13,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/menu"
)
-var trayMenuID int
-var trayMenuIDMutex sync.Mutex
+var (
+ trayMenuID int
+ trayMenuIDMutex sync.Mutex
+)
func generateTrayID() string {
var idStr string
@@ -51,7 +53,6 @@ func (t *TrayMenu) AsJSON() (string, error) {
}
func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu {
-
// Parse ANSI text
var styledLabel []*ansi.StyledText
tempLabel := trayMenu.Label
@@ -205,7 +206,6 @@ func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) {
}
return string(data), nil
-
}
func (m *Manager) GetContextMenus() ([]string, error) {
diff --git a/v2/internal/platform/systray.go b/v2/internal/platform/systray.go
deleted file mode 100644
index af79f427f..000000000
--- a/v2/internal/platform/systray.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package platform
-
-import (
- "github.com/wailsapp/wails/v2/internal/platform/systray"
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
-)
-import "github.com/samber/lo"
-
-type SysTray interface {
- // SetTitle sets the title of the tray menu
- SetTitle(title string)
- SetTooltip(tooltip string) error
- Show() error
- Hide() error
- Run() error
- Close()
- SetMenu(menu *menu.Menu) error
- SetIcons(lightModeIcon, darkModeIcon *options.SystemTrayIcon) error
- Update() error
- OnLeftClick(func())
- OnRightClick(func())
- OnLeftDoubleClick(func())
- OnRightDoubleClick(func())
- OnMenuClose(func())
- OnMenuOpen(func())
-}
-
-func NewSysTray() SysTray {
- return lo.Must(systray.New())
-}
diff --git a/v2/internal/platform/systray/menu_windows.go b/v2/internal/platform/systray/menu_windows.go
deleted file mode 100644
index b191a41c2..000000000
--- a/v2/internal/platform/systray/menu_windows.go
+++ /dev/null
@@ -1,222 +0,0 @@
-//go:build windows
-
-package systray
-
-import (
- "errors"
- "fmt"
- platformMenu "github.com/wailsapp/wails/v2/internal/platform/menu"
- "github.com/wailsapp/wails/v2/internal/platform/win32"
- "github.com/wailsapp/wails/v2/pkg/menu"
-)
-
-type RadioGroupMember struct {
- ID int
- MenuItem *menu.MenuItem
-}
-
-type RadioGroup []*RadioGroupMember
-
-func (r *RadioGroup) Add(id int, item *menu.MenuItem) {
- *r = append(*r, &RadioGroupMember{
- ID: id,
- MenuItem: item,
- })
-}
-
-func (r *RadioGroup) Bounds() (int, int) {
- p := *r
- return p[0].ID, p[len(p)-1].ID
-}
-
-func (r *RadioGroup) MenuID(item *menu.MenuItem) int {
- for _, member := range *r {
- if member.MenuItem == item {
- return member.ID
- }
- }
- panic("RadioGroup.MenuID: item not found:")
-}
-
-type PopupMenu struct {
- menu win32.PopupMenu
- parent win32.HWND
- menuMapping map[int]*menu.MenuItem
- checkboxItems map[*menu.MenuItem][]int
- radioGroups map[*menu.MenuItem][]*RadioGroup
- menuData *menu.Menu
- currentMenuID int
- onMenuClose func()
- onMenuOpen func()
-}
-
-func (p *PopupMenu) buildMenu(parentMenu win32.PopupMenu, inputMenu *menu.Menu) error {
- var currentRadioGroup RadioGroup
- for _, item := range inputMenu.Items {
- if item.Hidden {
- continue
- }
- var ret bool
- p.currentMenuID++
- itemID := p.currentMenuID
- p.menuMapping[itemID] = item
-
- flags := win32.MF_STRING
- if item.Disabled {
- flags = flags | win32.MF_GRAYED
- }
- if item.Checked {
- flags = flags | win32.MF_CHECKED
- }
- //if item.BarBreak {
- // flags = flags | win32.MF_MENUBARBREAK
- //}
- if item.IsSeparator() {
- flags = flags | win32.MF_SEPARATOR
- }
-
- if item.IsCheckbox() {
- p.checkboxItems[item] = append(p.checkboxItems[item], itemID)
- }
- if item.IsRadio() {
- currentRadioGroup.Add(itemID, item)
- } else {
- if len(currentRadioGroup) > 0 {
- for _, radioMember := range currentRadioGroup {
- currentRadioGroup := currentRadioGroup
- p.radioGroups[radioMember.MenuItem] = append(p.radioGroups[radioMember.MenuItem], ¤tRadioGroup)
- }
- currentRadioGroup = RadioGroup{}
- }
- }
-
- if item.SubMenu != nil {
- flags = flags | win32.MF_POPUP
- submenu := win32.CreatePopupMenu()
- err := p.buildMenu(submenu, item.SubMenu)
- if err != nil {
- return err
- }
- itemID = int(submenu)
- }
-
- var menuText = item.Label
- if item.Accelerator != nil {
- shortcut := win32.AcceleratorToShortcut(item.Accelerator)
- menuText = fmt.Sprintf("%s\t%s", menuText, shortcut)
- // Popup Menus don't appear to support accelerators and I'm not
- // sure they make sense either
- }
-
- ret = parentMenu.Append(uintptr(flags), uintptr(itemID), menuText)
- if ret == false {
- return errors.New("AppendMenu failed")
- }
- }
- if len(currentRadioGroup) > 0 {
- for _, radioMember := range currentRadioGroup {
- currentRadioGroup := currentRadioGroup
- p.radioGroups[radioMember.MenuItem] = append(p.radioGroups[radioMember.MenuItem], ¤tRadioGroup)
- }
- currentRadioGroup = RadioGroup{}
- }
- return nil
-}
-
-func (p *PopupMenu) Update() error {
- p.menu = win32.CreatePopupMenu()
- p.menuMapping = make(map[int]*menu.MenuItem)
- p.currentMenuID = win32.MenuItemMsgID
- err := p.buildMenu(p.menu, p.menuData)
- if err != nil {
- return err
- }
- p.updateRadioGroups()
- return nil
-}
-
-func NewPopupMenu(parent win32.HWND, inputMenu *menu.Menu) (*PopupMenu, error) {
- result := &PopupMenu{
- parent: parent,
- menuData: inputMenu,
- checkboxItems: make(map[*menu.MenuItem][]int),
- radioGroups: make(map[*menu.MenuItem][]*RadioGroup),
- }
- err := result.Update()
- platformMenu.MenuManager.AddMenu(inputMenu, result.UpdateMenuItem)
- return result, err
-}
-
-func (p *PopupMenu) ShowAtCursor() error {
- x, y, ok := win32.GetCursorPos()
- if ok == false {
- return errors.New("GetCursorPos failed")
- }
-
- if win32.SetForegroundWindow(p.parent) == false {
- return errors.New("SetForegroundWindow failed")
- }
-
- if p.onMenuOpen != nil {
- p.onMenuOpen()
- }
-
- if p.menu.Track(win32.TPM_LEFTALIGN, x, y-5, p.parent) == false {
- return errors.New("TrackPopupMenu failed")
- }
-
- if p.onMenuClose != nil {
- p.onMenuClose()
- }
-
- if win32.PostMessage(p.parent, win32.WM_NULL, 0, 0) == 0 {
- return errors.New("PostMessage failed")
- }
-
- return nil
-}
-
-func (p *PopupMenu) ProcessCommand(cmdMsgID int) {
- item := p.menuMapping[cmdMsgID]
- platformMenu.MenuManager.ProcessClick(item)
-}
-
-func (p *PopupMenu) Destroy() {
- p.menu.Destroy()
-}
-
-func (p *PopupMenu) UpdateMenuItem(item *menu.MenuItem) {
- if item.IsCheckbox() {
- for _, itemID := range p.checkboxItems[item] {
- p.menu.Check(uintptr(itemID), item.Checked)
- }
- return
- }
- if item.IsRadio() && item.Checked == true {
- p.updateRadioGroup(item)
- }
-}
-
-func (p *PopupMenu) updateRadioGroups() {
- for menuItem := range p.radioGroups {
- if menuItem.Checked {
- p.updateRadioGroup(menuItem)
- }
- }
-}
-
-func (p *PopupMenu) updateRadioGroup(item *menu.MenuItem) {
- for _, radioGroup := range p.radioGroups[item] {
- thisMenuID := radioGroup.MenuID(item)
- startID, endID := radioGroup.Bounds()
- p.menu.CheckRadio(startID, endID, thisMenuID)
- }
-}
-
-func (p *PopupMenu) OnMenuOpen(fn func()) {
- p.onMenuOpen = fn
-}
-
-func (p *PopupMenu) OnMenuClose(fn func()) {
- p.onMenuClose = fn
-}
diff --git a/v2/internal/platform/systray/systray_linux.go b/v2/internal/platform/systray/systray_linux.go
deleted file mode 100644
index 480955018..000000000
--- a/v2/internal/platform/systray/systray_linux.go
+++ /dev/null
@@ -1,83 +0,0 @@
-//go:build linux
-
-/*
- * Based on code originally from https://github.com/tadvi/systray. Copyright (C) 2019 The Systray Authors. All Rights Reserved.
- */
-
-package systray
-
-import (
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
-)
-
-type Systray struct {
-}
-
-func (p *Systray) Close() {
- err := p.Stop()
- if err != nil {
- println(err.Error())
- }
-}
-
-func (p *Systray) Update() error {
- return nil
-}
-
-// SetTitle is unused on Windows
-func (p *Systray) SetTitle(_ string) {}
-
-func New() (*Systray, error) {
- return nil, nil
-}
-
-func (p *Systray) SetMenu(popupMenu *menu.Menu) (err error) {
- return
-}
-
-func (p *Systray) Stop() error {
- return nil
-}
-
-func (p *Systray) OnLeftClick(fn func()) {
-}
-
-func (p *Systray) OnRightClick(fn func()) {
-}
-
-func (p *Systray) OnLeftDoubleClick(fn func()) {
-}
-
-func (p *Systray) OnRightDoubleClick(fn func()) {
-}
-
-func (p *Systray) OnMenuClose(fn func()) {
-}
-
-func (p *Systray) OnMenuOpen(fn func()) {
-}
-
-func (p *Systray) SetTooltip(tooltip string) error {
- return nil
-}
-
-func (p *Systray) Show() error {
- return p.setVisible(true)
-}
-
-func (p *Systray) Hide() error {
- return p.setVisible(false)
-}
-
-func (p *Systray) setVisible(visible bool) error {
- return nil
-}
-
-func (p *Systray) SetIcons(lightModeIcon, darkModeIcon *options.SystemTrayIcon) error {
- return nil
-}
-
-func (p *Systray) Run() error {
- return nil
-}
diff --git a/v2/internal/platform/systray/systray_mac.go b/v2/internal/platform/systray/systray_mac.go
deleted file mode 100644
index 6cb1009b5..000000000
--- a/v2/internal/platform/systray/systray_mac.go
+++ /dev/null
@@ -1,91 +0,0 @@
-//go:build darwin
-
-package systray
-
-import (
- "errors"
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
-)
-
-var NotImplementedSysTray = errors.New("not implemented")
-
-type Systray struct {
-}
-
-func (p *Systray) Close() {
- err := p.Stop()
- if err != nil {
- println(err.Error())
- }
-}
-
-func (p *Systray) Update() error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) SetTitle(_ string) {}
-
-func New() (*Systray, error) {
- return nil, NotImplementedSysTray
-}
-
-func (p *Systray) SetMenu(popupMenu *menu.Menu) (err error) {
- return NotImplementedSysTray
-}
-
-func (p *Systray) Stop() error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) OnLeftClick(fn func()) {
-
-}
-
-func (p *Systray) OnRightClick(fn func()) {
-
-}
-
-func (p *Systray) OnLeftDoubleClick(fn func()) {
-
-}
-
-func (p *Systray) OnRightDoubleClick(fn func()) {
-
-}
-
-func (p *Systray) OnMenuClose(fn func()) {
-
-}
-
-func (p *Systray) OnMenuOpen(fn func()) {
-
-}
-
-func (p *Systray) SetTooltip(tooltip string) error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) ShowMessage(title, msg string, bigIcon bool) error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) Show() error {
- return p.setVisible(true)
-}
-
-func (p *Systray) Hide() error {
- return p.setVisible(false)
-}
-
-func (p *Systray) setVisible(visible bool) error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) SetIcons(lightModeIcon, darkModeIcon *options.SystemTrayIcon) error {
- return NotImplementedSysTray
-}
-
-func (p *Systray) Run() error {
- return NotImplementedSysTray
-}
diff --git a/v2/internal/platform/systray/systray_windows.go b/v2/internal/platform/systray/systray_windows.go
deleted file mode 100644
index 8e7b7dfe6..000000000
--- a/v2/internal/platform/systray/systray_windows.go
+++ /dev/null
@@ -1,432 +0,0 @@
-//go:build windows
-
-/*
- * Based on code originally from https://github.com/tadvi/systray. Copyright (C) 2019 The Systray Authors. All Rights Reserved.
- */
-
-package systray
-
-import (
- "errors"
- "github.com/samber/lo"
- "github.com/wailsapp/wails/v2/internal/platform/win32"
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
- "syscall"
- "unsafe"
-)
-
-var (
- user32 = syscall.MustLoadDLL("user32.dll")
-
- DefWindowProc = user32.MustFindProc("DefWindowProcW")
- RegisterClassEx = user32.MustFindProc("RegisterClassExW")
- CreateWindowEx = user32.MustFindProc("CreateWindowExW")
-
- windowClasses = map[string]win32.HINSTANCE{}
-)
-
-type Systray struct {
- id uint32
- mhwnd win32.HWND // main window handle
- hwnd win32.HWND
- hinst win32.HINSTANCE
- lclick func()
- rclick func()
- ldblclick func()
- rdblclick func()
- onMenuClose func()
- onMenuOpen func()
-
- appIcon win32.HICON
- lightModeIcon win32.HICON
- darkModeIcon win32.HICON
- currentIcon win32.HICON
-
- menu *PopupMenu
-
- quit chan struct{}
- icon *options.SystemTrayIcon
-}
-
-func (p *Systray) Close() {
- err := p.Stop()
- if err != nil {
- println(err.Error())
- }
-}
-
-func (p *Systray) Update() error {
- // Delete old menu
- if p.menu != nil {
- p.menu.Destroy()
- }
-
- return p.menu.Update()
-}
-
-// SetTitle is unused on Windows
-func (p *Systray) SetTitle(_ string) {}
-
-func New() (*Systray, error) {
- ni := &Systray{}
-
- ni.lclick = func() {
- if ni.menu != nil {
- _ = ni.menu.ShowAtCursor()
- }
- }
- ni.rclick = func() {
- if ni.menu != nil {
- _ = ni.menu.ShowAtCursor()
- }
- }
-
- MainClassName := "WailsSystray"
- ni.hinst, _ = RegisterWindow(MainClassName, ni.WinProc)
-
- ni.mhwnd = win32.CreateWindowEx(
- win32.WS_EX_CONTROLPARENT,
- win32.MustStringToUTF16Ptr(MainClassName),
- win32.MustStringToUTF16Ptr(""),
- win32.WS_OVERLAPPEDWINDOW|win32.WS_CLIPSIBLINGS,
- win32.CW_USEDEFAULT,
- win32.CW_USEDEFAULT,
- win32.CW_USEDEFAULT,
- win32.CW_USEDEFAULT,
- 0,
- 0,
- 0,
- unsafe.Pointer(nil))
-
- if ni.mhwnd == 0 {
- return nil, errors.New("create main win failed")
- }
-
- NotifyIconClassName := "NotifyIconForm"
- _, err := RegisterWindow(NotifyIconClassName, ni.WinProc)
- if err != nil {
- return nil, err
- }
-
- hwnd, _, _ := CreateWindowEx.Call(
- 0,
- uintptr(unsafe.Pointer(win32.MustStringToUTF16Ptr(NotifyIconClassName))),
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- uintptr(win32.HWND_MESSAGE),
- 0,
- 0,
- 0)
- if hwnd == 0 {
- return nil, errors.New("create notify win failed")
- }
-
- ni.hwnd = win32.HWND(hwnd) // Important to keep this inside struct.
-
- nid := win32.NOTIFYICONDATA{
- HWnd: win32.HWND(hwnd),
- UFlags: win32.NIF_MESSAGE | win32.NIF_STATE,
- DwState: win32.NIS_HIDDEN,
- DwStateMask: win32.NIS_HIDDEN,
- UCallbackMessage: win32.NotifyIconMessageId,
- }
- nid.CbSize = uint32(unsafe.Sizeof(nid))
-
- if !win32.ShellNotifyIcon(win32.NIM_ADD, &nid) {
- return nil, errors.New("shell notify create failed")
- }
-
- nid.UVersion = win32.NOTIFYICON_VERSION
-
- if !win32.ShellNotifyIcon(win32.NIM_SETVERSION, &nid) {
- return nil, errors.New("shell notify version failed")
- }
-
- ni.appIcon = win32.LoadIconWithResourceID(0, uintptr(win32.IDI_APPLICATION))
- ni.lightModeIcon = ni.appIcon
- ni.darkModeIcon = ni.appIcon
- ni.id = nid.UID
- return ni, nil
-}
-
-func (p *Systray) HWND() win32.HWND {
- return p.hwnd
-}
-
-func (p *Systray) SetMenu(popupMenu *menu.Menu) (err error) {
- p.menu, err = NewPopupMenu(p.hwnd, popupMenu)
- p.menu.OnMenuClose(p.onMenuClose)
- p.menu.OnMenuOpen(p.onMenuOpen)
- return
-}
-
-func (p *Systray) Stop() error {
- nid := p.newNotifyIconData()
- win32.PostQuitMessage(0)
- if !win32.ShellNotifyIcon(win32.NIM_DELETE, &nid) {
- return errors.New("shell notify delete failed")
- }
- return nil
-}
-
-func (p *Systray) OnLeftClick(fn func()) {
- if fn != nil {
- p.lclick = fn
- }
-}
-
-func (p *Systray) OnRightClick(fn func()) {
- if fn != nil {
- p.rclick = fn
- }
-}
-
-func (p *Systray) OnLeftDoubleClick(fn func()) {
- if fn != nil {
- p.ldblclick = fn
- }
-}
-
-func (p *Systray) OnRightDoubleClick(fn func()) {
- if fn != nil {
- p.rdblclick = fn
- }
-}
-
-func (p *Systray) OnMenuClose(fn func()) {
- if fn != nil {
- p.onMenuClose = fn
- }
-}
-
-func (p *Systray) OnMenuOpen(fn func()) {
- if fn != nil {
- p.onMenuOpen = fn
- }
-}
-
-func (p *Systray) SetTooltip(tooltip string) error {
- nid := p.newNotifyIconData()
- nid.UFlags = win32.NIF_TIP
- copy(nid.SzTip[:], win32.MustUTF16FromString(tooltip))
-
- if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) {
- return errors.New("shell notify tooltip failed")
- }
- return nil
-}
-
-func (p *Systray) ShowMessage(title, msg string, bigIcon bool) error {
- nid := p.newNotifyIconData()
- if bigIcon == true {
- nid.DwInfoFlags = win32.NIIF_USER
- }
-
- nid.CbSize = uint32(unsafe.Sizeof(nid))
-
- nid.UFlags = win32.NIF_INFO
- copy(nid.SzInfoTitle[:], win32.MustUTF16FromString(title))
- copy(nid.SzInfo[:], win32.MustUTF16FromString(msg))
-
- if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) {
- return errors.New("shell notify tooltip failed")
- }
- return nil
-}
-
-func (p *Systray) newNotifyIconData() win32.NOTIFYICONDATA {
- nid := win32.NOTIFYICONDATA{
- UID: p.id,
- HWnd: p.hwnd,
- }
- nid.CbSize = uint32(unsafe.Sizeof(nid))
- return nid
-}
-
-func (p *Systray) Show() error {
- return p.setVisible(true)
-}
-
-func (p *Systray) Hide() error {
- return p.setVisible(false)
-}
-
-func (p *Systray) setVisible(visible bool) error {
- nid := p.newNotifyIconData()
- nid.UFlags = win32.NIF_STATE
- nid.DwStateMask = win32.NIS_HIDDEN
- if !visible {
- nid.DwState = win32.NIS_HIDDEN
- }
-
- if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) {
- return errors.New("shell notify tooltip failed")
- }
- return nil
-}
-
-func (p *Systray) SetIcons(lightModeIcon, darkModeIcon *options.SystemTrayIcon) error {
- var newLightModeIcon, newDarkModeIcon win32.HICON
- if lightModeIcon != nil && lightModeIcon.Data != nil {
- newLightModeIcon = p.getIcon(lightModeIcon.Data)
- }
- if darkModeIcon != nil && darkModeIcon.Data != nil {
- newDarkModeIcon = p.getIcon(darkModeIcon.Data)
- }
- p.lightModeIcon, _ = lo.Coalesce(newLightModeIcon, newDarkModeIcon, p.appIcon)
- p.darkModeIcon, _ = lo.Coalesce(newDarkModeIcon, newLightModeIcon, p.appIcon)
- return p.updateIcon()
-}
-
-func (p *Systray) getIcon(icon []byte) win32.HICON {
- result, err := win32.CreateHIconFromPNG(icon)
- if err != nil {
- result = p.appIcon
- }
- return result
-}
-
-func (p *Systray) setIcon(hicon win32.HICON) error {
- nid := p.newNotifyIconData()
- nid.UFlags = win32.NIF_ICON
- if hicon == 0 {
- nid.HIcon = 0
- } else {
- nid.HIcon = hicon
- }
-
- if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) {
- return errors.New("shell notify icon failed")
- }
- return nil
-}
-
-func (p *Systray) WinProc(hwnd win32.HWND, msg uint32, wparam, lparam uintptr) uintptr {
- switch msg {
- case win32.NotifyIconMessageId:
- switch lparam {
- case win32.WM_LBUTTONUP:
- if p.lclick != nil {
- println("left click")
- p.lclick()
- }
- case win32.WM_RBUTTONUP:
- if p.rclick != nil {
- println("right click")
- p.rclick()
- }
- case win32.WM_LBUTTONDBLCLK:
- if p.ldblclick != nil {
- p.ldblclick()
- }
- case win32.WM_RBUTTONDBLCLK:
- if p.rdblclick != nil {
- p.rdblclick()
- }
- default:
- //println(win32.WMMessageToString(lparam))
- }
- case win32.WM_SETTINGCHANGE:
- settingChanged := win32.UTF16PtrToString(lparam)
- if settingChanged == "ImmersiveColorSet" {
- err := p.updateIcon()
- if err != nil {
- println("update icon failed", err.Error())
- }
- }
- return 0
- case win32.WM_COMMAND:
- cmdMsgID := int(wparam & 0xffff)
- switch cmdMsgID {
- default:
- p.menu.ProcessCommand(cmdMsgID)
- }
- default:
- //msg := int(wparam & 0xffff)
- //println(win32.WMMessageToString(uintptr(msg)))
- }
-
- result, _, _ := DefWindowProc.Call(uintptr(hwnd), uintptr(msg), wparam, lparam)
- return result
-}
-
-func (p *Systray) Run() error {
- var msg win32.MSG
- for {
- rt := win32.GetMessage(&msg)
- switch int(rt) {
- case 0:
- return nil
- case -1:
- return errors.New("run failed")
- }
-
- if win32.IsDialogMessage(p.hwnd, &msg) == 0 {
- win32.TranslateMessage(&msg)
- win32.DispatchMessage(&msg)
- }
- }
-}
-
-func (p *Systray) updateIcon() error {
-
- var newIcon win32.HICON
- if win32.IsCurrentlyDarkMode() {
- newIcon = p.darkModeIcon
- } else {
- newIcon = p.lightModeIcon
- }
- if p.currentIcon == newIcon {
- return nil
- }
- p.currentIcon = newIcon
- return p.setIcon(newIcon)
-}
-
-func (p *Systray) updateTheme() {
- //win32.SetTheme(p.hwnd, win32.IsCurrentlyDarkMode())
-}
-
-func RegisterWindow(name string, proc win32.WindowProc) (win32.HINSTANCE, error) {
- instance, exists := windowClasses[name]
- if exists {
- return instance, nil
- }
- hinst := win32.GetModuleHandle(0)
- if hinst == 0 {
- return 0, errors.New("get module handle failed")
- }
- hicon := win32.LoadIconWithResourceID(0, uintptr(win32.IDI_APPLICATION))
- if hicon == 0 {
- return 0, errors.New("load icon failed")
- }
- hcursor := win32.LoadCursorWithResourceID(0, uintptr(win32.IDC_ARROW))
- if hcursor == 0 {
- return 0, errors.New("load cursor failed")
- }
-
- hi := win32.HINSTANCE(hinst)
-
- var wc win32.WNDCLASSEX
- wc.CbSize = uint32(unsafe.Sizeof(wc))
- wc.LpfnWndProc = syscall.NewCallback(proc)
- wc.HInstance = win32.HINSTANCE(hinst)
- wc.HIcon = hicon
- wc.HCursor = hcursor
- wc.HbrBackground = win32.COLOR_BTNFACE + 1
- wc.LpszClassName = win32.MustStringToUTF16Ptr(name)
-
- atom, _, e := RegisterClassEx.Call(uintptr(unsafe.Pointer(&wc)))
- if atom == 0 {
- println(e.Error())
- return 0, errors.New("register class failed")
- }
-
- windowClasses[name] = hi
- return hi, nil
-}
diff --git a/v2/internal/platform/win32/consts.go b/v2/internal/platform/win32/consts.go
index 03f42b1a6..43149b036 100644
--- a/v2/internal/platform/win32/consts.go
+++ b/v2/internal/platform/win32/consts.go
@@ -80,7 +80,7 @@ ShouldSystemUseDarkMode = bool () // ordinal 138
SetPreferredAppMode = PreferredAppMode (PreferredAppMode appMode) // ordinal 135, since 18334
IsDarkModeAllowedForApp = bool () // ordinal 139
*/
-func init() {
+func Init() {
if IsWindowsVersionAtLeast(10, 0, 18334) {
// AllowDarkModeForWindow is only available on Windows 10+
diff --git a/v2/internal/process/process.go b/v2/internal/process/process.go
index 6d497ed8e..18c9f45da 100644
--- a/v2/internal/process/process.go
+++ b/v2/internal/process/process.go
@@ -25,7 +25,6 @@ func NewProcess(cmd string, args ...string) *Process {
// Start the process
func (p *Process) Start(exitCodeChannel chan int) error {
-
err := p.cmd.Start()
if err != nil {
return err
diff --git a/v2/internal/project/project.go b/v2/internal/project/project.go
index 023ca1dfe..2df99bdfa 100644
--- a/v2/internal/project/project.go
+++ b/v2/internal/project/project.go
@@ -12,7 +12,6 @@ import (
// Project holds the data related to a Wails project
type Project struct {
-
/*** Application Data ***/
Name string `json:"name"`
AssetDirectory string `json:"assetdir,omitempty"`
@@ -43,6 +42,9 @@ type Project struct {
// Build directory
BuildDir string `json:"build:dir"`
+ // BuildTags Extra tags to process during build
+ BuildTags string `json:"build:tags"`
+
// The output filename
OutputFilename string `json:"outputfilename"`
@@ -81,7 +83,7 @@ type Project struct {
// The address to bind the wails dev server to. Default "localhost:34115"
DevServer string `json:"devServer"`
- // Arguments that are forwared to the application in dev mode
+ // Arguments that are forward to the application in dev mode
AppArgs string `json:"appargs"`
// NSISType to be build
@@ -94,6 +96,9 @@ type Project struct {
// Frontend directory
FrontendDir string `json:"frontend:dir"`
+ // The timeout in seconds for Vite server detection. Default 10
+ ViteServerTimeout int `json:"viteServerTimeout"`
+
Bindings Bindings `json:"bindings"`
}
@@ -144,11 +149,10 @@ func (p *Project) Save() error {
if err != nil {
return err
}
- return os.WriteFile(p.filename, data, 0755)
+ return os.WriteFile(p.filename, data, 0o755)
}
func (p *Project) setDefaults() {
-
if p.Path == "" {
p.Path = lo.Must(os.Getwd())
}
@@ -177,6 +181,9 @@ func (p *Project) setDefaults() {
if p.DevServer == "" {
p.DevServer = "localhost:34115"
}
+ if p.ViteServerTimeout == 0 {
+ p.ViteServerTimeout = 10
+ }
if p.NSISType == "" {
p.NSISType = "multiple"
}
@@ -216,11 +223,27 @@ type Author struct {
}
type Info struct {
- CompanyName string `json:"companyName"`
- ProductName string `json:"productName"`
- ProductVersion string `json:"productVersion"`
- Copyright *string `json:"copyright"`
- Comments *string `json:"comments"`
+ CompanyName string `json:"companyName"`
+ ProductName string `json:"productName"`
+ ProductVersion string `json:"productVersion"`
+ Copyright *string `json:"copyright"`
+ Comments *string `json:"comments"`
+ FileAssociations []FileAssociation `json:"fileAssociations"`
+ Protocols []Protocol `json:"protocols"`
+}
+
+type FileAssociation struct {
+ Ext string `json:"ext"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ IconName string `json:"iconName"`
+ Role string `json:"role"`
+}
+
+type Protocol struct {
+ Scheme string `json:"scheme"`
+ Description string `json:"description"`
+ Role string `json:"role"`
}
type Bindings struct {
@@ -228,8 +251,9 @@ type Bindings struct {
}
type TsGeneration struct {
- Prefix string `json:"prefix"`
- Suffix string `json:"suffix"`
+ Prefix string `json:"prefix"`
+ Suffix string `json:"suffix"`
+ OutputType string `json:"outputType"`
}
// Parse the given JSON data into a Project struct
diff --git a/v2/internal/s/s.go b/v2/internal/s/s.go
index 86536e24c..adb304178 100644
--- a/v2/internal/s/s.go
+++ b/v2/internal/s/s.go
@@ -2,9 +2,9 @@ package s
import (
"crypto/md5"
+ "encoding/hex"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -28,7 +28,7 @@ func checkError(err error) {
func mute() {
originalOutput = Output
- Output = ioutil.Discard
+ Output = io.Discard
}
func unmute() {
@@ -74,9 +74,10 @@ func CD(dir string) {
checkError(err)
log("CD %s [%s]", dir, CWD())
}
+
func MKDIR(path string, mode ...os.FileMode) {
var perms os.FileMode
- perms = 0755
+ perms = 0o755
if len(mode) == 1 {
perms = mode[0]
}
@@ -88,7 +89,7 @@ func MKDIR(path string, mode ...os.FileMode) {
// ENDIR ensures that the path gets created if it doesn't exist
func ENDIR(path string, mode ...os.FileMode) {
var perms os.FileMode
- perms = 0755
+ perms = 0o755
if len(mode) == 1 {
perms = mode[0]
}
@@ -150,6 +151,7 @@ func COPY(source string, target string) {
defer closefile(src)
d, err := os.Create(target)
checkError(err)
+ defer closefile(d)
_, err = io.Copy(d, src)
checkError(err)
}
@@ -210,17 +212,13 @@ func ISDIR(path string) bool {
// ISDIREMPTY returns true if the given directory is empty
func ISDIREMPTY(dir string) bool {
-
// CREDIT: https://stackoverflow.com/a/30708914/8325411
f, err := os.Open(dir)
checkError(err)
defer closefile(f)
_, err = f.Readdirnames(1) // Or f.Readdir(1)
- if err == io.EOF {
- return true
- }
- return false
+ return err == io.EOF
}
// ISFILE returns true if the given file exists
@@ -270,7 +268,7 @@ func LOADSTRING(filename string) string {
// SAVEBYTES will create a file with the given string
func SAVEBYTES(filename string, data []byte) {
log("SAVEBYTES %s", filename)
- err := os.WriteFile(filename, data, 0755)
+ err := os.WriteFile(filename, data, 0o755)
checkError(err)
}
@@ -297,7 +295,7 @@ func MD5FILE(filename string) string {
_, err = io.Copy(h, f)
checkError(err)
- return fmt.Sprintf("%x", h.Sum(nil))
+ return hex.EncodeToString(h.Sum(nil))
}
// Sub is the substitution type
diff --git a/v2/internal/shell/shell.go b/v2/internal/shell/shell.go
index e16b96ca4..349e27bff 100644
--- a/v2/internal/shell/shell.go
+++ b/v2/internal/shell/shell.go
@@ -42,14 +42,13 @@ func (c *Command) Run() error {
func (c *Command) Stdout() string {
return c.stdo.String()
}
+
func (c *Command) Stderr() string {
return c.stde.String()
}
func (c *Command) AddArgs(args []string) {
- for _, arg := range args {
- c.args = append(c.args, arg)
- }
+ c.args = append(c.args, args...)
}
// CreateCommand returns a *Cmd struct that when run, will run the given command + args in the given directory
@@ -95,8 +94,5 @@ func RunCommandVerbose(directory string, command string, args ...string) error {
// CommandExists returns true if the given command can be found on the shell
func CommandExists(name string) bool {
_, err := exec.LookPath(name)
- if err != nil {
- return false
- }
- return true
+ return err == nil
}
diff --git a/v2/internal/signal/signal.go b/v2/internal/signal/signal.go
index 96e10bee6..fa797453f 100644
--- a/v2/internal/signal/signal.go
+++ b/v2/internal/signal/signal.go
@@ -9,8 +9,10 @@ import (
var signalChannel = make(chan os.Signal, 2)
-var callbacks []func()
-var lock sync.Mutex
+var (
+ callbacks []func()
+ lock sync.Mutex
+)
func OnShutdown(callback func()) {
lock.Lock()
@@ -20,20 +22,17 @@ func OnShutdown(callback func()) {
// Start the Signal Manager
func Start() {
-
// Hook into interrupts
gosignal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
// Spin off signal listener and wait for either a cancellation
// or signal
go func() {
- select {
- case <-signalChannel:
- println("")
- println("Ctrl+C detected. Shutting down...")
- for _, callback := range callbacks {
- callback()
- }
+ <-signalChannel
+ println("")
+ println("Ctrl+C detected. Shutting down...")
+ for _, callback := range callbacks {
+ callback()
}
}()
}
diff --git a/v2/internal/staticanalysis/staticanalysis.go b/v2/internal/staticanalysis/staticanalysis.go
index 0d8fb92d3..cde436633 100644
--- a/v2/internal/staticanalysis/staticanalysis.go
+++ b/v2/internal/staticanalysis/staticanalysis.go
@@ -2,9 +2,10 @@ package staticanalysis
import (
"go/ast"
- "golang.org/x/tools/go/packages"
"path/filepath"
"strings"
+
+ "golang.org/x/tools/go/packages"
)
type EmbedDetails struct {
@@ -51,24 +52,31 @@ func GetEmbedDetailsForFile(file *ast.File, baseDir string) []*EmbedDetails {
for _, c := range comment.List {
if strings.HasPrefix(c.Text, "//go:embed") {
sl := strings.Split(c.Text, " ")
- path := ""
- all := false
if len(sl) == 1 {
continue
}
- embedPath := strings.TrimSpace(sl[1])
- switch true {
- case strings.HasPrefix(embedPath, "all:"):
- path = strings.TrimPrefix(embedPath, "all:")
- all = true
- default:
- path = embedPath
+ // support for multiple paths in one comment
+ for _, arg := range sl[1:] {
+ embedPath := strings.TrimSpace(arg)
+ // ignores all pattern matching characters except escape sequence
+ if strings.Contains(embedPath, "*") || strings.Contains(embedPath, "?") || strings.Contains(embedPath, "[") {
+ continue
+ }
+ if strings.HasPrefix(embedPath, "all:") {
+ result = append(result, &EmbedDetails{
+ EmbedPath: strings.TrimPrefix(embedPath, "all:"),
+ All: true,
+ BaseDir: baseDir,
+ })
+ } else {
+ result = append(result, &EmbedDetails{
+ EmbedPath: embedPath,
+ All: false,
+ BaseDir: baseDir,
+ })
+ }
+
}
- result = append(result, &EmbedDetails{
- EmbedPath: path,
- All: all,
- BaseDir: baseDir,
- })
}
}
}
diff --git a/v2/internal/staticanalysis/staticanalysis_test.go b/v2/internal/staticanalysis/staticanalysis_test.go
index 17599676e..77ad2fa6c 100644
--- a/v2/internal/staticanalysis/staticanalysis_test.go
+++ b/v2/internal/staticanalysis/staticanalysis_test.go
@@ -1,8 +1,9 @@
package staticanalysis
import (
- "github.com/stretchr/testify/require"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestGetEmbedDetails(t *testing.T) {
@@ -25,6 +26,10 @@ func TestGetEmbedDetails(t *testing.T) {
EmbedPath: "frontend/dist",
All: true,
},
+ {
+ EmbedPath: "frontend/static",
+ All: false,
+ },
},
wantErr: false,
},
diff --git a/v2/internal/staticanalysis/test/standard/go.mod b/v2/internal/staticanalysis/test/standard/go.mod
index 2359eb21d..c9fe1fb52 100644
--- a/v2/internal/staticanalysis/test/standard/go.mod
+++ b/v2/internal/staticanalysis/test/standard/go.mod
@@ -2,7 +2,7 @@ module changeme
go 1.18
-require github.com/wailsapp/wails/v2 v2.0.0
+require github.com/wailsapp/wails/v2 v2.3.1
require (
github.com/bep/debounce v1.2.1 // indirect
@@ -20,14 +20,16 @@ require (
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
+ github.com/samber/lo v1.27.1 // indirect
github.com/tkrajina/go-reflector v0.5.6 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
- golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect
- golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
- golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect
- golang.org/x/text v0.3.8 // indirect
+ golang.org/x/crypto v0.21.0 // indirect
+ golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
+ golang.org/x/net v0.23.0 // indirect
+ golang.org/x/sys v0.18.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
)
// replace github.com/wailsapp/wails/v2 v2.0.0 => C:\Users\leaan
diff --git a/v2/internal/staticanalysis/test/standard/go.sum b/v2/internal/staticanalysis/test/standard/go.sum
index 73ba0c2d8..2cd0cf773 100644
--- a/v2/internal/staticanalysis/test/standard/go.sum
+++ b/v2/internal/staticanalysis/test/standard/go.sum
@@ -5,48 +5,33 @@ 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/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-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/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
-github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI=
-github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y=
github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
-github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -56,11 +41,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
+github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
-github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
-github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -69,17 +55,15 @@ github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
-github.com/wailsapp/wails/v2 v2.0.0 h1:EsiIMQYi3XeAJvvJNYTWVSyaEYwuBsSFU9ACSq7Ly4s=
-github.com/wailsapp/wails/v2 v2.0.0/go.mod h1:z3os4dBFCOmPhFHjjEKY4KygTVFKAGECkS9/mKm1wEU=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
-golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+github.com/wailsapp/wails/v2 v2.3.1 h1:ZJz+pyIBKyASkgO8JO31NuHO1gTTHmvwiHYHwei1CqM=
+github.com/wailsapp/wails/v2 v2.3.1/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
+golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -88,21 +72,15 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4=
-golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/v2/internal/staticanalysis/test/standard/main.go b/v2/internal/staticanalysis/test/standard/main.go
index 3f735d640..2b6ab33b6 100644
--- a/v2/internal/staticanalysis/test/standard/main.go
+++ b/v2/internal/staticanalysis/test/standard/main.go
@@ -8,9 +8,12 @@ import (
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
-//go:embed all:frontend/dist
+//go:embed all:frontend/dist frontend/static
var assets embed.FS
+//go:embed frontend/src/*.json
+var srcjson embed.FS
+
func main() {
// Create an instance of the app structure
app := NewApp()
diff --git a/v2/internal/system/operatingsystem/os.go b/v2/internal/system/operatingsystem/os.go
index 39f1de8e0..028a97b2e 100644
--- a/v2/internal/system/operatingsystem/os.go
+++ b/v2/internal/system/operatingsystem/os.go
@@ -2,9 +2,10 @@ package operatingsystem
// OS contains information about the operating system
type OS struct {
- ID string
- Name string
- Version string
+ ID string
+ Name string
+ Version string
+ Branding string
}
// Info retrieves information about the current platform
diff --git a/v2/internal/system/operatingsystem/os_windows.go b/v2/internal/system/operatingsystem/os_windows.go
index 38ea43a12..a9aa05a92 100644
--- a/v2/internal/system/operatingsystem/os_windows.go
+++ b/v2/internal/system/operatingsystem/os_windows.go
@@ -4,10 +4,44 @@ package operatingsystem
import (
"fmt"
+ "strings"
+ "syscall"
+ "unsafe"
+ "golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
+func stripNulls(str string) string {
+ // Split the string into substrings at each null character
+ substrings := strings.Split(str, "\x00")
+
+ // Join the substrings back into a single string
+ strippedStr := strings.Join(substrings, "")
+
+ return strippedStr
+}
+
+func mustStringToUTF16Ptr(input string) *uint16 {
+ input = stripNulls(input)
+ result, err := syscall.UTF16PtrFromString(input)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+func getBranding() string {
+ var modBranding = syscall.NewLazyDLL("winbrand.dll")
+ var brandingFormatString = modBranding.NewProc("BrandingFormatString")
+
+ windowsLong := mustStringToUTF16Ptr("%WINDOWS_LONG%\x00")
+ ret, _, _ := brandingFormatString.Call(
+ uintptr(unsafe.Pointer(windowsLong)),
+ )
+ return windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ret)))
+}
+
func platformInfo() (*OS, error) {
// Default value
var result OS
@@ -27,6 +61,7 @@ func platformInfo() (*OS, error) {
result.Name = productName
result.Version = fmt.Sprintf("%s (Build: %s)", releaseId, currentBuild)
result.ID = displayVersion
+ result.Branding = getBranding()
return &result, key.Close()
}
diff --git a/v2/internal/system/packagemanager/dnf.go b/v2/internal/system/packagemanager/dnf.go
index d9eaf8062..fec676f11 100644
--- a/v2/internal/system/packagemanager/dnf.go
+++ b/v2/internal/system/packagemanager/dnf.go
@@ -44,6 +44,7 @@ func (y *Dnf) Packages() packagemap {
},
"npm": []*Package{
{Name: "npm", SystemPackage: true},
+ {Name: "nodejs-npm", SystemPackage: true},
},
"upx": []*Package{
{Name: "upx", SystemPackage: true, Optional: true},
@@ -57,6 +58,7 @@ func (y *Dnf) Packages() packagemap {
"fedora": "Follow the guide: https://docs.docker.com/engine/install/fedora/",
},
},
+ {Name: "moby-engine", SystemPackage: true, Optional: true},
},
}
}
diff --git a/v2/internal/system/packagemanager/eopkg.go b/v2/internal/system/packagemanager/eopkg.go
index dbeab96de..936127eac 100644
--- a/v2/internal/system/packagemanager/eopkg.go
+++ b/v2/internal/system/packagemanager/eopkg.go
@@ -40,7 +40,7 @@ func (e *Eopkg) Packages() packagemap {
{Name: "gcc", SystemPackage: true},
},
"pkg-config": []*Package{
- {Name: "pkg-config", SystemPackage: true},
+ {Name: "pkgconf", SystemPackage: true},
},
"npm": []*Package{
{Name: "nodejs", SystemPackage: true},
diff --git a/v2/internal/system/packagemanager/pm.go b/v2/internal/system/packagemanager/pm.go
index dfd394299..bba45cd05 100644
--- a/v2/internal/system/packagemanager/pm.go
+++ b/v2/internal/system/packagemanager/pm.go
@@ -16,9 +16,9 @@ type packagemap = map[string][]*Package
type PackageManager interface {
Name() string
Packages() packagemap
- PackageInstalled(*Package) (bool, error)
- PackageAvailable(*Package) (bool, error)
- InstallCommand(*Package) string
+ PackageInstalled(pkg *Package) (bool, error)
+ PackageAvailable(pkg *Package) (bool, error)
+ InstallCommand(pkg *Package) string
}
// Dependency represents a system package that we require
@@ -37,7 +37,6 @@ type DependencyList []*Dependency
// InstallAllRequiredCommand returns the command you need to use to install all required dependencies
func (d DependencyList) InstallAllRequiredCommand() string {
-
result := ""
for _, dependency := range d {
if !dependency.Installed && !dependency.Optional {
@@ -50,7 +49,6 @@ func (d DependencyList) InstallAllRequiredCommand() string {
// InstallAllOptionalCommand returns the command you need to use to install all optional dependencies
func (d DependencyList) InstallAllOptionalCommand() string {
-
result := ""
for _, dependency := range d {
if !dependency.Installed && dependency.Optional {
diff --git a/v2/internal/system/packagemanager/zypper.go b/v2/internal/system/packagemanager/zypper.go
index 0d7fb082d..efaeb0b1b 100644
--- a/v2/internal/system/packagemanager/zypper.go
+++ b/v2/internal/system/packagemanager/zypper.go
@@ -33,6 +33,7 @@ func (z *Zypper) Packages() packagemap {
{Name: "gtk3-devel", SystemPackage: true, Library: true},
},
"libwebkit": []*Package{
+ {Name: "webkit2gtk3-soup2-devel", SystemPackage: true, Library: true},
{Name: "webkit2gtk3-devel", SystemPackage: true, Library: true},
},
"gcc": []*Package{
@@ -40,9 +41,11 @@ func (z *Zypper) Packages() packagemap {
},
"pkg-config": []*Package{
{Name: "pkg-config", SystemPackage: true},
+ {Name: "pkgconf-pkg-config", SystemPackage: true},
},
"npm": []*Package{
{Name: "npm10", SystemPackage: true},
+ {Name: "npm20", SystemPackage: true},
},
"docker": []*Package{
{Name: "docker", SystemPackage: true, Optional: true},
@@ -60,7 +63,9 @@ func (z *Zypper) PackageInstalled(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
- stdout, _, err := shell.RunCommand(".", "zypper", "info", pkg.Name)
+ var env []string
+ env = shell.SetEnv(env, "LANGUAGE", "en_US.utf-8")
+ stdout, _, err := shell.RunCommandWithEnv(env, ".", "zypper", "info", pkg.Name)
if err != nil {
_, ok := err.(*exec.ExitError)
if ok {
@@ -83,7 +88,9 @@ func (z *Zypper) PackageAvailable(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
- stdout, _, err := shell.RunCommand(".", "zypper", "info", pkg.Name)
+ var env []string
+ env = shell.SetEnv(env, "LANGUAGE", "en_US.utf-8")
+ stdout, _, err := shell.RunCommandWithEnv(env, ".", "zypper", "info", pkg.Name)
// We add a space to ensure we get a full match, not partial match
if err != nil {
_, ok := err.(*exec.ExitError)
diff --git a/v2/internal/system/system.go b/v2/internal/system/system.go
index 7e180c471..67453538f 100644
--- a/v2/internal/system/system.go
+++ b/v2/internal/system/system.go
@@ -1,19 +1,18 @@
package system
import (
+ "os/exec"
+ "strings"
+
"github.com/wailsapp/wails/v2/internal/shell"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
- "os/exec"
- "strings"
)
-var (
- IsAppleSilicon bool
-)
+var IsAppleSilicon bool
// Info holds information about the current operating system,
-// package manager and required dependancies
+// package manager and required dependencies
type Info struct {
OS *operatingsystem.OS
PM packagemanager.PackageManager
@@ -22,7 +21,7 @@ type Info struct {
// GetInfo scans the system for operating system details,
// the system package manager and the status of required
-// dependancies.
+// dependencies.
func GetInfo() (*Info, error) {
var result Info
err := result.discover()
@@ -32,8 +31,30 @@ func GetInfo() (*Info, error) {
return &result, nil
}
-func checkNPM() *packagemanager.Dependency {
+func checkNodejs() *packagemanager.Dependency {
+ // Check for Nodejs
+ output, err := exec.Command("node", "-v").Output()
+ installed := true
+ version := ""
+ if err != nil {
+ installed = false
+ } else {
+ if len(output) > 0 {
+ version = strings.TrimSpace(strings.Split(string(output), "\n")[0])[1:]
+ }
+ }
+ return &packagemanager.Dependency{
+ Name: "Nodejs",
+ PackageName: "N/A",
+ Installed: installed,
+ InstallCommand: "Available at https://nodejs.org/en/download/",
+ Version: version,
+ Optional: false,
+ External: false,
+ }
+}
+func checkNPM() *packagemanager.Dependency {
// Check for npm
output, err := exec.Command("npm", "-version").Output()
installed := true
@@ -55,7 +76,6 @@ func checkNPM() *packagemanager.Dependency {
}
func checkUPX() *packagemanager.Dependency {
-
// Check for npm
output, err := exec.Command("upx", "-V").Output()
installed := true
@@ -77,7 +97,6 @@ func checkUPX() *packagemanager.Dependency {
}
func checkNSIS() *packagemanager.Dependency {
-
// Check for nsis installer
output, err := exec.Command("makensis", "-VERSION").Output()
installed := true
@@ -116,7 +135,6 @@ func checkLibrary(name string) func() *packagemanager.Dependency {
}
func checkDocker() *packagemanager.Dependency {
-
// Check for npm
output, err := exec.Command("docker", "version").Output()
installed := true
diff --git a/v2/internal/system/system_darwin.go b/v2/internal/system/system_darwin.go
index ef75f8256..16dfd8873 100644
--- a/v2/internal/system/system_darwin.go
+++ b/v2/internal/system/system_darwin.go
@@ -9,9 +9,8 @@ import (
"strings"
"syscall"
- "github.com/wailsapp/wails/v2/internal/system/packagemanager"
-
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
+ "github.com/wailsapp/wails/v2/internal/system/packagemanager"
)
// Determine if the app is running on Apple Silicon
@@ -34,6 +33,7 @@ func (i *Info) discover() error {
i.OS = osinfo
i.Dependencies = append(i.Dependencies, checkXCodeSelect())
+ i.Dependencies = append(i.Dependencies, checkNodejs())
i.Dependencies = append(i.Dependencies, checkNPM())
i.Dependencies = append(i.Dependencies, checkXCodeBuild())
i.Dependencies = append(i.Dependencies, checkUPX())
diff --git a/v2/internal/system/system_linux.go b/v2/internal/system/system_linux.go
index 8c51c4ab6..703e978eb 100644
--- a/v2/internal/system/system_linux.go
+++ b/v2/internal/system/system_linux.go
@@ -49,6 +49,7 @@ func checkLocallyInstalled(checker func() *packagemanager.Dependency, dependency
}
var checkerFunctions = map[string]func() *packagemanager.Dependency{
+ "Nodejs": checkNodejs,
"npm": checkNPM,
"docker": checkDocker,
"upx": checkUPX,
diff --git a/v2/internal/system/system_windows.go b/v2/internal/system/system_windows.go
index e03d9890b..40b8f0340 100644
--- a/v2/internal/system/system_windows.go
+++ b/v2/internal/system/system_windows.go
@@ -4,7 +4,7 @@
package system
import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
+ "github.com/wailsapp/go-webview2/webviewloader"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
)
@@ -19,6 +19,7 @@ func (i *Info) discover() error {
i.OS = osinfo
i.Dependencies = append(i.Dependencies, checkWebView2())
+ i.Dependencies = append(i.Dependencies, checkNodejs())
i.Dependencies = append(i.Dependencies, checkNPM())
i.Dependencies = append(i.Dependencies, checkUPX())
i.Dependencies = append(i.Dependencies, checkNSIS())
diff --git a/v2/internal/typescriptify/js-reserved-keywords.go b/v2/internal/typescriptify/js-reserved-keywords.go
index 7750fb90a..4f9aa09f4 100644
--- a/v2/internal/typescriptify/js-reserved-keywords.go
+++ b/v2/internal/typescriptify/js-reserved-keywords.go
@@ -61,7 +61,7 @@ var jsReservedKeywords []string = []string{
"typeof",
"var",
"void",
- "volotile",
+ "volatile",
"while",
"with",
"yield",
diff --git a/v2/internal/typescriptify/typescriptify.go b/v2/internal/typescriptify/typescriptify.go
index c30b6bf83..e732c5976 100644
--- a/v2/internal/typescriptify/typescriptify.go
+++ b/v2/internal/typescriptify/typescriptify.go
@@ -2,13 +2,15 @@ package typescriptify
import (
"bufio"
+ "cmp"
"fmt"
- "io/ioutil"
+ "io"
"log"
"os"
"path"
"reflect"
"regexp"
+ "slices"
"strings"
"time"
@@ -24,7 +26,7 @@ const (
if (!a) {
return a;
}
- if (a.slice) {
+ if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
@@ -40,6 +42,18 @@ const (
jsVariableNameRegex = `^([A-Z]|[a-z]|\$|_)([A-Z]|[a-z]|[0-9]|\$|_)*$`
)
+var jsVariableUnsafeChars = regexp.MustCompile(`[^A-Za-z0-9_]`)
+
+func nameTypeOf(typeOf reflect.Type) string {
+ tname := typeOf.Name()
+ gidx := strings.IndexRune(tname, '[')
+ if gidx > 0 { // its a generic type
+ rem := strings.SplitN(tname, "[", 2)
+ tname = rem[0] + "_" + jsVariableUnsafeChars.ReplaceAllLiteralString(rem[1], "_")
+ }
+ return tname
+}
+
// TypeOptions overrides options set by `ts_*` tags.
type TypeOptions struct {
TSType string
@@ -104,6 +118,7 @@ type TypeScriptify struct {
Namespace string
KnownStructs *slicer.StringSlicer
+ KnownEnums *slicer.StringSlicer
}
func New() *TypeScriptify {
@@ -156,10 +171,10 @@ func (t *TypeScriptify) deepFields(typeOf reflect.Type) []reflect.StructField {
kind := f.Type.Kind()
isPointer := kind == reflect.Ptr && f.Type.Elem().Kind() == reflect.Struct
if f.Anonymous && kind == reflect.Struct {
- //fmt.Println(v.Interface())
+ // fmt.Println(v.Interface())
fields = append(fields, t.deepFields(f.Type)...)
} else if f.Anonymous && isPointer {
- //fmt.Println(v.Interface())
+ // fmt.Println(v.Interface())
fields = append(fields, t.deepFields(f.Type.Elem())...)
} else {
// Check we have a json tag
@@ -260,15 +275,34 @@ func (t *TypeScriptify) AddType(typeOf reflect.Type) *TypeScriptify {
func (t *typeScriptClassBuilder) AddMapField(fieldName string, field reflect.StructField) {
keyType := field.Type.Key()
valueType := field.Type.Elem()
- valueTypeName := valueType.Name()
+ valueTypeName := nameTypeOf(valueType)
+ valueTypeSuffix := ""
+ valueTypePrefix := ""
+ if valueType.Kind() == reflect.Ptr {
+ valueType = valueType.Elem()
+ valueTypeName = nameTypeOf(valueType)
+ }
+ if valueType.Kind() == reflect.Array || valueType.Kind() == reflect.Slice {
+ arrayDepth := 1
+ for valueType.Elem().Kind() == reflect.Array || valueType.Elem().Kind() == reflect.Slice {
+ valueType = valueType.Elem()
+ arrayDepth++
+ }
+ valueType = valueType.Elem()
+ valueTypeName = nameTypeOf(valueType)
+ valueTypeSuffix = strings.Repeat(">", arrayDepth)
+ valueTypePrefix = strings.Repeat("Array<", arrayDepth)
+ }
+ if valueType.Kind() == reflect.Ptr {
+ valueType = valueType.Elem()
+ valueTypeName = nameTypeOf(valueType)
+ }
if name, ok := t.types[valueType.Kind()]; ok {
valueTypeName = name
}
- if valueType.Kind() == reflect.Array || valueType.Kind() == reflect.Slice {
- valueTypeName = valueType.Elem().Name() + "[]"
- }
- if valueType.Kind() == reflect.Ptr {
- valueTypeName = valueType.Elem().Name()
+ if valueType.Kind() == reflect.Map {
+ // TODO: support nested maps
+ valueTypeName = "any" // valueType.Elem().Name()
}
if valueType.Kind() == reflect.Struct && differentNamespaces(t.namespace, valueType) {
valueTypeName = valueType.String()
@@ -293,11 +327,13 @@ func (t *typeScriptClassBuilder) AddMapField(fieldName string, field reflect.Str
fieldName = fmt.Sprintf(`"%s"?`, strippedFieldName)
}
}
- t.fields = append(t.fields, fmt.Sprintf("%s%s: {[key: %s]: %s};", t.indent, fieldName, keyTypeStr, valueTypeName))
+ t.fields = append(t.fields, fmt.Sprintf("%s%s: Record<%s, %s>;", t.indent, fieldName, keyTypeStr, valueTypePrefix+valueTypeName+valueTypeSuffix))
if valueType.Kind() == reflect.Struct {
- t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = this.convertValues(source[\"%s\"], %s, true);", t.indent, t.indent, dotField, strippedFieldName, t.prefix+valueTypeName+t.suffix))
+ t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = this.convertValues(source[\"%s\"], %s, true);",
+ t.indent, t.indent, dotField, strippedFieldName, t.prefix+valueTypePrefix+valueTypeName+valueTypeSuffix+t.suffix))
} else {
- t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = source[\"%s\"];", t.indent, t.indent, dotField, strippedFieldName))
+ t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = source[\"%s\"];",
+ t.indent, t.indent, dotField, strippedFieldName))
}
}
@@ -338,6 +374,9 @@ func (t *TypeScriptify) AddEnum(values interface{}) *TypeScriptify {
elements = append(elements, el)
}
+ slices.SortFunc(elements, func(a, b enumElement) int {
+ return cmp.Compare(a.name, b.name)
+ })
ty := reflect.TypeOf(elements[0].value)
t.enums[ty] = elements
t.enumTypes = append(t.enumTypes, EnumType{Type: ty})
@@ -393,7 +432,7 @@ func loadCustomCode(fileName string) (map[string]string, error) {
}
defer f.Close()
- bytes, err := ioutil.ReadAll(f)
+ bytes, err := io.ReadAll(f)
if err != nil {
return result, err
}
@@ -429,7 +468,7 @@ func (t TypeScriptify) backup(fileName string) error {
}
defer fileIn.Close()
- bytes, err := ioutil.ReadAll(fileIn)
+ bytes, err := io.ReadAll(fileIn)
if err != nil {
return err
}
@@ -439,7 +478,7 @@ func (t TypeScriptify) backup(fileName string) error {
backupFn = path.Join(t.BackupDir, backupFn)
}
- return ioutil.WriteFile(backupFn, bytes, os.FileMode(0700))
+ return os.WriteFile(backupFn, bytes, os.FileMode(0o700))
}
func (t TypeScriptify) ConvertToFile(fileName string, packageName string) error {
@@ -482,9 +521,6 @@ func (t TypeScriptify) ConvertToFile(fileName string, packageName string) error
if _, err := f.WriteString(converted); err != nil {
return err
}
- if err != nil {
- return err
- }
return nil
}
@@ -500,7 +536,7 @@ func (t *TypeScriptify) convertEnum(depth int, typeOf reflect.Type, elements []e
}
t.alreadyConverted[typeOf.String()] = true
- entityName := t.Prefix + typeOf.Name() + t.Suffix
+ entityName := t.Prefix + nameTypeOf(typeOf) + t.Suffix
result := "enum " + entityName + " {\n"
for _, val := range elements {
@@ -552,7 +588,21 @@ func (t *TypeScriptify) getFieldOptions(structType reflect.Type, field reflect.S
func (t *TypeScriptify) getJSONFieldName(field reflect.StructField, isPtr bool) string {
jsonFieldName := ""
- jsonTag := field.Tag.Get("json")
+ // function, complex, and channel types cannot be json-encoded
+ if field.Type.Kind() == reflect.Chan ||
+ field.Type.Kind() == reflect.Func ||
+ field.Type.Kind() == reflect.UnsafePointer ||
+ field.Type.Kind() == reflect.Complex128 ||
+ field.Type.Kind() == reflect.Complex64 {
+ return ""
+ }
+ jsonTag, hasTag := field.Tag.Lookup("json")
+ if !hasTag && field.IsExported() {
+ jsonFieldName = field.Name
+ if isPtr {
+ jsonFieldName += "?"
+ }
+ }
if len(jsonTag) > 0 {
jsonTagParts := strings.Split(jsonTag, ",")
if len(jsonTagParts) > 0 {
@@ -585,9 +635,6 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
return "", nil
}
fields := t.deepFields(typeOf)
- if len(fields) == 0 {
- return "", nil
- }
t.logf(depth, "Converting type %s", typeOf.String())
if differentNamespaces(t.Namespace, typeOf) {
return "", nil
@@ -595,7 +642,7 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
t.alreadyConverted[typeOf.String()] = true
- entityName := t.Prefix + typeOf.Name() + t.Suffix
+ entityName := t.Prefix + nameTypeOf(typeOf) + t.Suffix
if typeClashWithReservedKeyword(entityName) {
warnAboutTypesClash(entityName)
@@ -655,8 +702,10 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
}
isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String()))
- println("KnownStructs:", t.KnownStructs.Join("\t"))
- println(getStructFQN(field.Type.String()))
+ if !isKnownType {
+ println("KnownStructs:", t.KnownStructs.Join("\t"))
+ println("Not found:", getStructFQN(field.Type.String()))
+ }
builder.AddStructField(jsonFieldName, field, !isKnownType)
} else if field.Type.Kind() == reflect.Map {
t.logf(depth, "- map field %s.%s", typeOf.Name(), field.Name)
@@ -697,16 +746,20 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
builder.AddMapField(jsonFieldName, field)
} else if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array { // Slice:
- if field.Type.Elem().Kind() == reflect.Ptr { //extract ptr type
+ if field.Type.Elem().Kind() == reflect.Ptr { // extract ptr type
field.Type = field.Type.Elem()
}
arrayDepth := 1
- for field.Type.Elem().Kind() == reflect.Slice { // Slice of slices:
+ for field.Type.Elem().Kind() == reflect.Slice || field.Type.Elem().Kind() == reflect.Array { // Slice of slices:
field.Type = field.Type.Elem()
arrayDepth++
}
+ if field.Type.Elem().Kind() == reflect.Ptr { // extract ptr type
+ field.Type = field.Type.Elem()
+ }
+
if field.Type.Elem().Kind() == reflect.Struct { // Slice of structs:
t.logf(depth, "- struct slice %s.%s (%s)", typeOf.Name(), field.Name, field.Type.String())
typeScriptChunk, err := t.convertType(depth+1, field.Type.Elem(), customCode)
@@ -723,7 +776,16 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
}
} else { // Simple field:
t.logf(depth, "- simple field %s.%s", typeOf.Name(), field.Name)
- err = builder.AddSimpleField(jsonFieldName, field, fldOpts)
+ // check if type is in known enum. If so, then replace TStype with enum name to avoid missing types
+ isKnownEnum := t.KnownEnums.Contains(getStructFQN(field.Type.String()))
+ if isKnownEnum {
+ err = builder.AddSimpleField(jsonFieldName, field, TypeOptions{
+ TSType: getStructFQN(field.Type.String()),
+ TSTransform: fldOpts.TSTransform,
+ })
+ } else {
+ err = builder.AddSimpleField(jsonFieldName, field, fldOpts)
+ }
}
if err != nil {
return "", err
@@ -787,8 +849,12 @@ type typeScriptClassBuilder struct {
}
func (t *typeScriptClassBuilder) AddSimpleArrayField(fieldName string, field reflect.StructField, arrayDepth int, opts TypeOptions) error {
- fieldType, kind := field.Type.Elem().Name(), field.Type.Elem().Kind()
- typeScriptType := t.types[kind]
+ fieldType := nameTypeOf(field.Type.Elem())
+ kind := field.Type.Elem().Kind()
+ typeScriptType, ok := t.types[kind]
+ if !ok {
+ typeScriptType = "any"
+ }
if len(fieldName) > 0 {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
@@ -807,9 +873,14 @@ func (t *typeScriptClassBuilder) AddSimpleArrayField(fieldName string, field ref
}
func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect.StructField, opts TypeOptions) error {
- fieldType, kind := field.Type.Name(), field.Type.Kind()
+ fieldType := nameTypeOf(field.Type)
+ kind := field.Type.Kind()
+
+ typeScriptType, ok := t.types[kind]
+ if !ok {
+ typeScriptType = "any"
+ }
- typeScriptType := t.types[kind]
if len(opts.TSType) > 0 {
typeScriptType = opts.TSType
}
@@ -831,7 +902,7 @@ func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect.
}
func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.StructField) {
- fieldType := field.Type.Name()
+ fieldType := nameTypeOf(field.Type)
t.addField(fieldName, t.prefix+fieldType+t.suffix, false)
strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName))
@@ -839,13 +910,11 @@ func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.St
func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.StructField, isAnyType bool) {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
- fqname := field.Type.Name()
classname := "null"
-
namespace := strings.Split(field.Type.String(), ".")[0]
-
+ fqname := t.prefix + nameTypeOf(field.Type) + t.suffix
if namespace != t.namespace {
- fqname = field.Type.String()
+ fqname = namespace + "." + fqname
}
if !isAnyType {
@@ -862,7 +931,7 @@ func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.
}
func (t *typeScriptClassBuilder) AddArrayOfStructsField(fieldName string, field reflect.StructField, arrayDepth int) {
- fieldType := field.Type.Elem().Name()
+ fieldType := nameTypeOf(field.Type.Elem())
if differentNamespaces(t.namespace, field.Type.Elem()) {
fieldType = field.Type.Elem().String()
}
@@ -886,12 +955,13 @@ func (t *typeScriptClassBuilder) addField(fld, fldType string, isAnyType bool) {
isOptional := strings.HasSuffix(fld, "?")
strippedFieldName := strings.ReplaceAll(fld, "?", "")
if !regexp.MustCompile(jsVariableNameRegex).Match([]byte(strippedFieldName)) {
- fld = fmt.Sprintf(`"%s"`, fld)
+ fld = fmt.Sprintf(`"%s"`, strippedFieldName)
if isOptional {
fld += "?"
}
}
if isAnyType {
+ fldType = strings.Split(fldType, ".")[0]
t.fields = append(t.fields, fmt.Sprint(t.indent, "// Go type: ", fldType, "\n", t.indent, fld, ": any;"))
} else {
t.fields = append(t.fields, fmt.Sprint(t.indent, fld, ": ", fldType, ";"))
@@ -936,6 +1006,6 @@ func typeClashWithReservedKeyword(input string) bool {
func warnAboutTypesClash(entity string) {
// TODO: Refactor logging
l := log.New(os.Stderr, "", 0)
- l.Println(fmt.Sprintf("Usage of reserved keyword found and not supported: %s", entity))
+ l.Printf("Usage of reserved keyword found and not supported: %s", entity)
log.Println("Please rename returned type or consider adding bindings config to your wails.json")
}
diff --git a/v2/internal/webview2runtime/webview2installer.go b/v2/internal/webview2runtime/webview2installer.go
index a2a2922dc..3645dae02 100644
--- a/v2/internal/webview2runtime/webview2installer.go
+++ b/v2/internal/webview2runtime/webview2installer.go
@@ -11,7 +11,7 @@ var setupexe []byte
// WriteInstallerToFile writes the installer file to the given file.
func WriteInstallerToFile(targetFile string) error {
- return os.WriteFile(targetFile, setupexe, 0755)
+ return os.WriteFile(targetFile, setupexe, 0o755)
}
// WriteInstaller writes the installer exe file to the given directory and returns the path to it.
diff --git a/v2/internal/wv2installer/wv2installer.go b/v2/internal/wv2installer/wv2installer.go
index ce754cee7..c89ad196f 100644
--- a/v2/internal/wv2installer/wv2installer.go
+++ b/v2/internal/wv2installer/wv2installer.go
@@ -5,7 +5,7 @@ package wv2installer
import (
"fmt"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
+ "github.com/wailsapp/go-webview2/webviewloader"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
diff --git a/v2/pkg/application/application.go b/v2/pkg/application/application.go
index 03d98ebd7..8ba586969 100644
--- a/v2/pkg/application/application.go
+++ b/v2/pkg/application/application.go
@@ -2,11 +2,12 @@ package application
import (
"context"
+ "sync"
+
"github.com/wailsapp/wails/v2/internal/app"
"github.com/wailsapp/wails/v2/internal/signal"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
- "sync"
)
// Application is the main Wails application
@@ -14,9 +15,6 @@ type Application struct {
application *app.App
options *options.App
- // System Trays
- systemTrays []*SystemTray
-
// running flag
running bool
@@ -52,11 +50,6 @@ func (a *Application) SetApplicationMenu(appMenu *menu.Menu) {
// Run starts the application
func (a *Application) Run() error {
-
- for _, systemtray := range a.systemTrays {
- go systemtray.run()
- }
-
err := applicationInit()
if err != nil {
return err
@@ -78,16 +71,12 @@ func (a *Application) Run() error {
a.running = true
err = a.application.Run()
- a.Quit()
return err
}
// Quit will shut down the application
func (a *Application) Quit() {
a.shutdown.Do(func() {
- for _, systray := range a.systemTrays {
- systray.Close()
- }
a.application.Shutdown()
})
}
@@ -98,7 +87,6 @@ func (a *Application) Bind(boundStruct any) {
}
func (a *Application) On(eventType EventType, callback func()) {
-
c := func(ctx context.Context) {
callback()
}
@@ -112,9 +100,3 @@ func (a *Application) On(eventType EventType, callback func()) {
a.options.OnDomReady = c
}
}
-
-func (a *Application) NewSystemTray(options *options.SystemTray) *SystemTray {
- systemTray := newSystemTray(options)
- a.systemTrays = append(a.systemTrays, systemTray)
- return systemTray
-}
diff --git a/v2/pkg/application/systray.go b/v2/pkg/application/systray.go
deleted file mode 100644
index 9798ef5f3..000000000
--- a/v2/pkg/application/systray.go
+++ /dev/null
@@ -1,151 +0,0 @@
-package application
-
-import (
- "github.com/wailsapp/wails/v2/internal/platform"
- "github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/wailsapp/wails/v2/pkg/options"
-)
-
-// SystemTray defines a system tray!
-type SystemTray struct {
- title string
- hidden bool
- lightModeIcon *options.SystemTrayIcon
- darkModeIcon *options.SystemTrayIcon
- tooltip string
- startHidden bool
- menu *menu.Menu
- onLeftClick func()
- onRightClick func()
- onLeftDoubleClick func()
- onRightDoubleClick func()
- onMenuClose func()
- onMenuOpen func()
-
- // The platform specific implementation
- impl platform.SysTray
-}
-
-func newSystemTray(options *options.SystemTray) *SystemTray {
- return &SystemTray{
- title: options.Title,
- lightModeIcon: options.LightModeIcon,
- darkModeIcon: options.DarkModeIcon,
- tooltip: options.Tooltip,
- startHidden: options.StartHidden,
- menu: options.Menu,
- onLeftClick: options.OnLeftClick,
- onRightClick: options.OnRightClick,
- onLeftDoubleClick: options.OnLeftDoubleClick,
- onRightDoubleClick: options.OnRightDoubleClick,
- onMenuOpen: options.OnMenuOpen,
- onMenuClose: options.OnMenuClose,
- }
-}
-
-func (t *SystemTray) run() {
- t.impl = platform.NewSysTray()
- t.impl.SetTitle(t.title)
- t.impl.SetIcons(t.lightModeIcon, t.darkModeIcon)
- t.impl.SetTooltip(t.tooltip)
- t.impl.OnLeftClick(t.onLeftClick)
- t.impl.OnRightClick(t.onRightClick)
- t.impl.OnLeftDoubleClick(t.onLeftDoubleClick)
- t.impl.OnRightDoubleClick(t.onRightDoubleClick)
- t.impl.OnMenuOpen(t.onMenuOpen)
- t.impl.OnMenuClose(t.onMenuClose)
- if !t.startHidden {
- t.impl.Show()
- }
- t.impl.SetMenu(t.menu)
- t.impl.Run()
-}
-
-func (t *SystemTray) SetTitle(title string) {
- if t.impl != nil {
- t.impl.SetTitle(title)
- } else {
- t.title = title
- }
-}
-
-func (t *SystemTray) Run() error {
- t.run()
- return nil
-}
-
-func (t *SystemTray) Close() {
- if t.impl != nil {
- t.impl.Close()
- t.impl = nil
- }
-}
-
-func (t *SystemTray) SetMenu(items *menu.Menu) {
- if t.impl != nil {
- t.impl.SetMenu(t.menu)
- } else {
- t.menu = items
- }
-}
-
-func (t *SystemTray) Update() error {
- if t.impl != nil {
- return t.impl.Update()
- }
- return nil
-}
-
-func (t *SystemTray) SetTooltip(s string) {
- if t.impl != nil {
- t.impl.SetTooltip(s)
- } else {
- t.tooltip = s
- }
-}
-
-func (t *SystemTray) SetIcons(lightModeIcon *options.SystemTrayIcon, darkModeIcon *options.SystemTrayIcon) {
- if t.impl != nil {
- t.impl.SetIcons(lightModeIcon, darkModeIcon)
- } else {
- t.lightModeIcon = lightModeIcon
- t.darkModeIcon = darkModeIcon
- }
-
-}
-
-func (t *SystemTray) OnLeftClick(fn func()) {
- if t.impl != nil {
- t.impl.OnLeftClick(fn)
- }
-}
-
-func (t *SystemTray) OnRightClick(fn func()) {
- if t.impl != nil {
- t.impl.OnRightClick(fn)
- }
-}
-
-func (t *SystemTray) OnLeftDoubleClick(fn func()) {
- if t.impl != nil {
- t.impl.OnLeftDoubleClick(fn)
- }
-}
-
-func (t *SystemTray) OnRightDoubleClick(fn func()) {
- if t.impl != nil {
- t.impl.OnRightDoubleClick(fn)
- }
-}
-
-func (t *SystemTray) OnMenuOpen(fn func()) {
- if t.impl != nil {
- t.impl.OnMenuOpen(fn)
- }
-}
-
-func (t *SystemTray) OnMenuClose(fn func()) {
- if t.impl != nil {
- t.impl.OnMenuClose(fn)
- }
-}
diff --git a/v2/pkg/assetserver/assethandler.go b/v2/pkg/assetserver/assethandler.go
index c85bf81e6..b8e2df076 100644
--- a/v2/pkg/assetserver/assethandler.go
+++ b/v2/pkg/assetserver/assethandler.go
@@ -10,6 +10,7 @@ import (
"net/http"
"os"
"path"
+ "strconv"
"strings"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
@@ -37,7 +38,6 @@ type assetHandler struct {
}
func NewAssetHandler(options assetserver.Options, log Logger) (http.Handler, error) {
-
vfs := options.Assets
if vfs != nil {
if _, err := vfs.Open("."); err != nil {
@@ -110,7 +110,7 @@ func (d *assetHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
}
-// serveFile will try to load the file from the fs.FS and write it to the response
+// serveFSFile will try to load the file from the fs.FS and write it to the response
func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error {
if d.fs == nil {
return os.ErrNotExist
@@ -178,7 +178,8 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, fi
return nil
}
- rw.Header().Set(HeaderContentLength, fmt.Sprintf("%d", statInfo.Size()))
+ size := strconv.FormatInt(statInfo.Size(), 10)
+ rw.Header().Set(HeaderContentLength, size)
// Write the first 512 bytes used for MimeType sniffing
_, err = io.Copy(rw, bytes.NewReader(buf[:n]))
diff --git a/v2/pkg/assetserver/assethandler_external.go b/v2/pkg/assetserver/assethandler_external.go
new file mode 100644
index 000000000..98b3404e9
--- /dev/null
+++ b/v2/pkg/assetserver/assethandler_external.go
@@ -0,0 +1,84 @@
+package assetserver
+
+import (
+ "errors"
+ "fmt"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+)
+
+func NewProxyServer(proxyURL string) http.Handler {
+ parsedURL, err := url.Parse(proxyURL)
+ if err != nil {
+ panic(err)
+ }
+ return httputil.NewSingleHostReverseProxy(parsedURL)
+}
+
+func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *url.URL) http.Handler {
+ baseHandler := options.Handler
+
+ errSkipProxy := fmt.Errorf("skip proxying")
+
+ proxy := httputil.NewSingleHostReverseProxy(url)
+ baseDirector := proxy.Director
+ proxy.Director = func(r *http.Request) {
+ baseDirector(r)
+ if logger != nil {
+ logger.Debug("[ExternalAssetHandler] Loading '%s'", r.URL)
+ }
+ }
+
+ proxy.ModifyResponse = func(res *http.Response) error {
+ if baseHandler == nil {
+ return nil
+ }
+
+ if res.StatusCode == http.StatusSwitchingProtocols {
+ return nil
+ }
+
+ if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed {
+ return errSkipProxy
+ }
+
+ return nil
+ }
+
+ proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
+ if baseHandler != nil && errors.Is(err, errSkipProxy) {
+ if logger != nil {
+ logger.Debug("[ExternalAssetHandler] '%s' returned not found, using AssetHandler", r.URL)
+ }
+ baseHandler.ServeHTTP(rw, r)
+ } else {
+ if logger != nil {
+ logger.Error("[ExternalAssetHandler] Proxy error: %v", err)
+ }
+ rw.WriteHeader(http.StatusBadGateway)
+ }
+ }
+
+ var result http.Handler = http.HandlerFunc(
+ func(rw http.ResponseWriter, req *http.Request) {
+ if req.Method == http.MethodGet {
+ proxy.ServeHTTP(rw, req)
+ return
+ }
+
+ if baseHandler != nil {
+ baseHandler.ServeHTTP(rw, req)
+ return
+ }
+
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ })
+
+ if middleware := options.Middleware; middleware != nil {
+ result = middleware(result)
+ }
+
+ return result
+}
diff --git a/v2/pkg/assetserver/assetserver.go b/v2/pkg/assetserver/assetserver.go
index 1d085df0a..59665c091 100644
--- a/v2/pkg/assetserver/assetserver.go
+++ b/v2/pkg/assetserver/assetserver.go
@@ -2,10 +2,13 @@ package assetserver
import (
"bytes"
+ "fmt"
+ "math/rand"
"net/http"
- "net/http/httptest"
+ "strings"
"golang.org/x/net/html"
+ "html/template"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
@@ -14,6 +17,7 @@ import (
const (
runtimeJSPath = "/wails/runtime.js"
ipcJSPath = "/wails/ipc.js"
+ runtimePath = "/wails/runtime"
)
type RuntimeAssets interface {
@@ -22,9 +26,12 @@ type RuntimeAssets interface {
RuntimeDesktopJS() []byte
}
+type RuntimeHandler interface {
+ HandleRuntimeCall(w http.ResponseWriter, r *http.Request)
+}
+
type AssetServer struct {
handler http.Handler
- wsHandler http.Handler
runtimeJS []byte
ipcJS func(*http.Request) []byte
@@ -34,6 +41,12 @@ type AssetServer struct {
servingFromDisk bool
appendSpinnerToBody bool
+ // Use http based runtime
+ runtimeHandler RuntimeHandler
+
+ // plugin scripts
+ pluginScripts map[string]string
+
assetServerWebView
}
@@ -55,9 +68,11 @@ func NewAssetServer(bindingsJSON string, options assetserver.Options, servingFro
}
func NewAssetServerWithHandler(handler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
+
var buffer bytes.Buffer
if bindingsJSON != "" {
- buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
+ escapedBindingsJSON := template.JSEscapeString(bindingsJSON)
+ buffer.WriteString(`window.wailsbindings='` + escapedBindingsJSON + `';` + "\n")
}
buffer.Write(runtime.RuntimeDesktopJS())
@@ -77,34 +92,79 @@ func NewAssetServerWithHandler(handler http.Handler, bindingsJSON string, servin
return result, nil
}
+func (d *AssetServer) UseRuntimeHandler(handler RuntimeHandler) {
+ d.runtimeHandler = handler
+}
+
+func (d *AssetServer) AddPluginScript(pluginName string, script string) {
+ if d.pluginScripts == nil {
+ d.pluginScripts = make(map[string]string)
+ }
+ pluginName = strings.ReplaceAll(pluginName, "/", "_")
+ pluginName = html.EscapeString(pluginName)
+ pluginScriptName := fmt.Sprintf("/plugin_%s_%d.js", pluginName, rand.Intn(100000))
+ d.pluginScripts[pluginScriptName] = script
+}
+
func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if isWebSocket(req) {
- // Forward WebSockets to the distinct websocket handler if it exists
- if wsHandler := d.wsHandler; wsHandler != nil {
- wsHandler.ServeHTTP(rw, req)
- } else {
- rw.WriteHeader(http.StatusNotImplemented)
- }
+ // WebSockets are not supported by the AssetServer
+ rw.WriteHeader(http.StatusNotImplemented)
return
}
- header := rw.Header()
if d.servingFromDisk {
- header.Add(HeaderCacheControl, "no-cache")
+ rw.Header().Add(HeaderCacheControl, "no-cache")
+ }
+
+ handler := d.handler
+ if req.Method != http.MethodGet {
+ handler.ServeHTTP(rw, req)
+ return
}
path := req.URL.Path
- switch path {
- case "", "/", "/index.html":
- recorder := httptest.NewRecorder()
- d.handler.ServeHTTP(recorder, req)
- for k, v := range recorder.HeaderMap {
- header[k] = v
+ if path == runtimeJSPath {
+ d.writeBlob(rw, path, d.runtimeJS)
+ } else if path == runtimePath && d.runtimeHandler != nil {
+ d.runtimeHandler.HandleRuntimeCall(rw, req)
+ } else if path == ipcJSPath {
+ content := d.runtime.DesktopIPC()
+ if d.ipcJS != nil {
+ content = d.ipcJS(req)
+ }
+ d.writeBlob(rw, path, content)
+
+ } else if script, ok := d.pluginScripts[path]; ok {
+ d.writeBlob(rw, path, []byte(script))
+ } else if d.isRuntimeInjectionMatch(path) {
+ recorder := &bodyRecorder{
+ ResponseWriter: rw,
+ doRecord: func(code int, h http.Header) bool {
+ if code == http.StatusNotFound {
+ return true
+ }
+
+ if code != http.StatusOK {
+ return false
+ }
+
+ return strings.Contains(h.Get(HeaderContentType), "text/html")
+ },
}
- switch recorder.Code {
+ handler.ServeHTTP(recorder, req)
+
+ body := recorder.Body()
+ if body == nil {
+ // The body has been streamed and not recorded, we are finished
+ return
+ }
+
+ code := recorder.Code()
+ switch code {
case http.StatusOK:
- content, err := d.processIndexHTML(recorder.Body.Bytes())
+ content, err := d.processIndexHTML(body.Bytes())
if err != nil {
d.serveError(rw, err, "Unable to processIndexHTML")
return
@@ -115,22 +175,12 @@ func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
d.writeBlob(rw, indexHTML, defaultHTML)
default:
- rw.WriteHeader(recorder.Code)
+ rw.WriteHeader(code)
}
- case runtimeJSPath:
- d.writeBlob(rw, path, d.runtimeJS)
-
- case ipcJSPath:
- content := d.runtime.DesktopIPC()
- if d.ipcJS != nil {
- content = d.ipcJS(req)
- }
- d.writeBlob(rw, path, content)
-
- default:
- d.handler.ServeHTTP(rw, req)
+ } else {
+ handler.ServeHTTP(rw, req)
}
}
@@ -155,6 +205,13 @@ func (d *AssetServer) processIndexHTML(indexHTML []byte) ([]byte, error) {
return nil, err
}
+ // Inject plugins
+ for scriptName := range d.pluginScripts {
+ if err := insertScriptInHead(htmlNode, scriptName); err != nil {
+ return nil, err
+ }
+ }
+
var buffer bytes.Buffer
err = html.Render(&buffer, htmlNode)
if err != nil {
@@ -187,3 +244,12 @@ func (d *AssetServer) logError(message string, args ...interface{}) {
d.logger.Error("[AssetServer] "+message, args...)
}
}
+
+func (AssetServer) isRuntimeInjectionMatch(path string) bool {
+ if path == "" {
+ path = "/"
+ }
+
+ return strings.HasSuffix(path, "/") ||
+ strings.HasSuffix(path, "/"+indexHTML)
+}
diff --git a/v2/pkg/assetserver/assetserver_dev.go b/v2/pkg/assetserver/assetserver_dev.go
index fb13b3a23..f6a2a0d2f 100644
--- a/v2/pkg/assetserver/assetserver_dev.go
+++ b/v2/pkg/assetserver/assetserver_dev.go
@@ -13,13 +13,12 @@ The assetserver for the dev mode.
Depending on the UserAgent it injects a websocket based IPC script into `index.html` or the default desktop IPC. The
default desktop IPC is injected when the webview accesses the devserver.
*/
-func NewDevAssetServer(handler http.Handler, wsHandler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
+func NewDevAssetServer(handler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
result, err := NewAssetServerWithHandler(handler, bindingsJSON, servingFromDisk, logger, runtime)
if err != nil {
return nil, err
}
- result.wsHandler = wsHandler
result.appendSpinnerToBody = true
result.ipcJS = func(req *http.Request) []byte {
if strings.Contains(req.UserAgent(), WailsUserAgentValue) {
diff --git a/v2/pkg/assetserver/assetserver_legacy.go b/v2/pkg/assetserver/assetserver_legacy.go
deleted file mode 100644
index 2d315aca3..000000000
--- a/v2/pkg/assetserver/assetserver_legacy.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package assetserver
-
-import (
- "io"
- "net/http"
-
- "github.com/wailsapp/wails/v2/pkg/assetserver/webview"
-)
-
-// ProcessHTTPRequest processes the HTTP Request by faking a golang HTTP Server.
-// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
-func (d *AssetServer) ProcessHTTPRequestLegacy(rw http.ResponseWriter, reqGetter func() (*http.Request, error)) {
- d.processWebViewRequest(&legacyRequest{reqGetter: reqGetter, rw: rw})
-}
-
-type legacyRequest struct {
- req *http.Request
- rw http.ResponseWriter
-
- reqGetter func() (*http.Request, error)
-}
-
-func (r *legacyRequest) URL() (string, error) {
- req, err := r.request()
- if err != nil {
- return "", err
- }
- return req.URL.String(), nil
-}
-
-func (r *legacyRequest) Method() (string, error) {
- req, err := r.request()
- if err != nil {
- return "", err
- }
- return req.Method, nil
-}
-
-func (r *legacyRequest) Header() (http.Header, error) {
- req, err := r.request()
- if err != nil {
- return nil, err
- }
- return req.Header, nil
-}
-
-func (r *legacyRequest) Body() (io.ReadCloser, error) {
- req, err := r.request()
- if err != nil {
- return nil, err
- }
- return req.Body, nil
-}
-
-func (r legacyRequest) Response() webview.ResponseWriter {
- return &legacyRequestNoOpCloserResponseWriter{r.rw}
-}
-
-func (r legacyRequest) AddRef() error {
- return nil
-}
-
-func (r legacyRequest) Release() error {
- return nil
-}
-
-func (r *legacyRequest) request() (*http.Request, error) {
- if r.req != nil {
- return r.req, nil
- }
-
- req, err := r.reqGetter()
- if err != nil {
- return nil, err
- }
- r.req = req
- return req, nil
-}
-
-type legacyRequestNoOpCloserResponseWriter struct {
- http.ResponseWriter
-}
-
-func (*legacyRequestNoOpCloserResponseWriter) Finish() error {
- return nil
-}
diff --git a/v2/pkg/assetserver/assetserver_webview.go b/v2/pkg/assetserver/assetserver_webview.go
index 3a7178c20..63f80f0ae 100644
--- a/v2/pkg/assetserver/assetserver_webview.go
+++ b/v2/pkg/assetserver/assetserver_webview.go
@@ -22,11 +22,12 @@ type assetServerWebView struct {
// ServeWebViewRequest processes the HTTP Request asynchronously by faking a golang HTTP Server.
// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
+// The AssetServer takes ownership of the request and the caller mustn't close it or access it in any other way.
func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchInit.Do(func() {
workers := d.dispatchWorkers
- if workers == 0 {
- workers = 10
+ if workers <= 0 {
+ return
}
workerC := make(chan webview.Request, workers*2)
@@ -34,7 +35,6 @@ func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
go func() {
for req := range workerC {
d.processWebViewRequest(req)
- req.Release()
}
}()
}
@@ -45,25 +45,38 @@ func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchReqC = dispatchC
})
- if err := req.AddRef(); err != nil {
- uri, _ := req.URL()
- d.logError("Unable to call AddRef for request '%s'", uri)
- return
+ if d.dispatchReqC == nil {
+ go d.processWebViewRequest(req)
+ } else {
+ d.dispatchReqC <- req
}
-
- d.dispatchReqC <- req
}
-// processHTTPRequest processes the HTTP Request by faking a golang HTTP Server.
-// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
func (d *AssetServer) processWebViewRequest(r webview.Request) {
+ uri, _ := r.URL()
+ d.processWebViewRequestInternal(r)
+ if err := r.Close(); err != nil {
+ d.logError("Unable to call close for request for uri '%s'", uri)
+ }
+}
+
+// processWebViewRequestInternal processes the HTTP Request by faking a golang HTTP Server.
+// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
+func (d *AssetServer) processWebViewRequestInternal(r webview.Request) {
+ uri := "unknown"
+ var err error
+
wrw := r.Response()
- defer wrw.Finish()
+ defer func() {
+ if err := wrw.Finish(); err != nil {
+ d.logError("Error finishing request '%s': %s", uri, err)
+ }
+ }()
var rw http.ResponseWriter = &contentTypeSniffer{rw: wrw} // Make sure we have a Content-Type sniffer
defer rw.WriteHeader(http.StatusNotImplemented) // This is a NOP when a handler has already written and set the status
- uri, err := r.URL()
+ uri, err = r.URL()
if err != nil {
d.logError("Error processing request, unable to get URL: %s (HttpResponse=500)", err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
@@ -98,6 +111,18 @@ func (d *AssetServer) processWebViewRequest(r webview.Request) {
d.webviewRequestErrorHandler(uri, rw, fmt.Errorf("HTTP-Request: %w", err))
return
}
+
+ // For server requests, the URL is parsed from the URI supplied on the Request-Line as stored in RequestURI. For
+ // most requests, fields other than Path and RawQuery will be empty. (See RFC 7230, Section 5.3)
+ req.URL.Scheme = ""
+ req.URL.Host = ""
+ req.URL.Fragment = ""
+ req.URL.RawFragment = ""
+
+ if url := req.URL; req.RequestURI == "" && url != nil {
+ req.RequestURI = url.String()
+ }
+
req.Header = header
if req.RemoteAddr == "" {
@@ -105,14 +130,11 @@ func (d *AssetServer) processWebViewRequest(r webview.Request) {
req.RemoteAddr = "192.0.2.1:1234"
}
- if req.RequestURI == "" && req.URL != nil {
- req.RequestURI = req.URL.String()
- }
-
if req.ContentLength == 0 {
- req.ContentLength, _ = strconv.ParseInt(req.Header.Get(HeaderContentLength), 10, 64)
+ req.ContentLength = -1
} else {
- req.Header.Set(HeaderContentLength, fmt.Sprintf("%d", req.ContentLength))
+ size := strconv.FormatInt(req.ContentLength, 10)
+ req.Header.Set(HeaderContentLength, size)
}
if host := req.Header.Get(HeaderHost); host != "" {
diff --git a/v2/pkg/assetserver/body_recorder.go b/v2/pkg/assetserver/body_recorder.go
new file mode 100644
index 000000000..fa3bc1e7c
--- /dev/null
+++ b/v2/pkg/assetserver/body_recorder.go
@@ -0,0 +1,61 @@
+package assetserver
+
+import (
+ "bytes"
+ "net/http"
+)
+
+type bodyRecorder struct {
+ http.ResponseWriter
+ doRecord func(code int, header http.Header) bool
+
+ body *bytes.Buffer
+ code int
+ wroteHeader bool
+}
+
+func (rw *bodyRecorder) Write(buf []byte) (int, error) {
+ rw.writeHeader(buf, http.StatusOK)
+ if rw.body != nil {
+ return rw.body.Write(buf)
+ }
+ return rw.ResponseWriter.Write(buf)
+}
+
+func (rw *bodyRecorder) WriteHeader(code int) {
+ rw.writeHeader(nil, code)
+}
+
+func (rw *bodyRecorder) Code() int {
+ return rw.code
+}
+
+func (rw *bodyRecorder) Body() *bytes.Buffer {
+ return rw.body
+}
+
+func (rw *bodyRecorder) writeHeader(buf []byte, code int) {
+ if rw.wroteHeader {
+ return
+ }
+
+ if rw.doRecord != nil {
+ header := rw.Header()
+ if len(buf) != 0 {
+ if _, hasType := header[HeaderContentType]; !hasType {
+ header.Set(HeaderContentType, http.DetectContentType(buf))
+ }
+ }
+
+ if rw.doRecord(code, header) {
+ rw.body = bytes.NewBuffer(nil)
+ }
+ }
+
+ if rw.body == nil {
+ rw.ResponseWriter.WriteHeader(code)
+ }
+
+ rw.code = code
+ rw.wroteHeader = true
+}
diff --git a/v2/pkg/assetserver/common.go b/v2/pkg/assetserver/common.go
index 01e51f2be..57934e08e 100644
--- a/v2/pkg/assetserver/common.go
+++ b/v2/pkg/assetserver/common.go
@@ -3,9 +3,9 @@ package assetserver
import (
"bytes"
"errors"
- "fmt"
"io"
"net/http"
+ "strconv"
"strings"
"github.com/wailsapp/wails/v2/pkg/options"
@@ -44,7 +44,7 @@ const (
func serveFile(rw http.ResponseWriter, filename string, blob []byte) error {
header := rw.Header()
- header.Set(HeaderContentLength, fmt.Sprintf("%d", len(blob)))
+ header.Set(HeaderContentLength, strconv.Itoa(len(blob)))
if mimeType := header.Get(HeaderContentType); mimeType == "" {
mimeType = GetMimetype(filename, blob)
header.Set(HeaderContentType, mimeType)
diff --git a/v2/pkg/assetserver/mimecache.go b/v2/pkg/assetserver/mimecache.go
index dc2dd5c75..9d97e8f5a 100644
--- a/v2/pkg/assetserver/mimecache.go
+++ b/v2/pkg/assetserver/mimecache.go
@@ -9,24 +9,44 @@ import (
)
var (
- cache = map[string]string{}
- mutex sync.Mutex
+ mimeCache = map[string]string{}
+ mimeMutex sync.Mutex
+
+ // The list of builtin mime-types by extension as defined by
+ // the golang standard lib package "mime"
+ // The standard lib also takes into account mime type definitions from
+ // etc files like '/etc/apache2/mime.types' but we want to have the
+ // same behavivour on all platforms and not depend on some external file.
+ mimeTypesByExt = map[string]string{
+ ".avif": "image/avif",
+ ".css": "text/css; charset=utf-8",
+ ".gif": "image/gif",
+ ".htm": "text/html; charset=utf-8",
+ ".html": "text/html; charset=utf-8",
+ ".jpeg": "image/jpeg",
+ ".jpg": "image/jpeg",
+ ".js": "text/javascript; charset=utf-8",
+ ".json": "application/json",
+ ".mjs": "text/javascript; charset=utf-8",
+ ".pdf": "application/pdf",
+ ".png": "image/png",
+ ".svg": "image/svg+xml",
+ ".wasm": "application/wasm",
+ ".webp": "image/webp",
+ ".xml": "text/xml; charset=utf-8",
+ }
)
func GetMimetype(filename string, data []byte) string {
- mutex.Lock()
- defer mutex.Unlock()
+ mimeMutex.Lock()
+ defer mimeMutex.Unlock()
- // short-circuit .js, .css to ensure the
- // browser evaluates them in the right context
- switch filepath.Ext(filename) {
- case ".js":
- return "application/javascript"
- case ".css":
- return "text/css; charset=utf-8"
+ result := mimeTypesByExt[filepath.Ext(filename)]
+ if result != "" {
+ return result
}
- result := cache[filename]
+ result = mimeCache[filename]
if result != "" {
return result
}
@@ -42,6 +62,6 @@ func GetMimetype(filename string, data []byte) string {
result = "application/octet-stream"
}
- cache[filename] = result
+ mimeCache[filename] = result
return result
}
diff --git a/v2/pkg/assetserver/mimecache_test.go b/v2/pkg/assetserver/mimecache_test.go
index 6b338b7e4..1496dbf52 100644
--- a/v2/pkg/assetserver/mimecache_test.go
+++ b/v2/pkg/assetserver/mimecache_test.go
@@ -25,10 +25,11 @@ func TestGetMimetype(t *testing.T) {
want string
}{
// TODO: Add test cases.
- {"nil data", args{"nil.svg", nil}, "text/plain"},
- {"empty data", args{"empty.html", emptyMsg}, "text/plain"},
+ {"nil data", args{"nil.svg", nil}, "image/svg+xml"},
+ {"empty data", args{"empty.html", emptyMsg}, "text/html; charset=utf-8"},
{"css", args{"test.css", css}, "text/css; charset=utf-8"},
- {"js", args{"test.js", []byte("let foo = 'bar'; console.log(foo);")}, "application/javascript"},
+ {"js", args{"test.js", []byte("let foo = 'bar'; console.log(foo);")}, "text/javascript; charset=utf-8"},
+ {"mjs", args{"test.mjs", []byte("let foo = 'bar'; console.log(foo);")}, "text/javascript; charset=utf-8"},
{"html-utf8", args{"test_utf8.html", html}, "text/html; charset=utf-8"},
{"html-bom-utf8", args{"test_bom_utf8.html", bomHtml}, "text/html; charset=utf-8"},
{"svg", args{"test.svg", svg}, "image/svg+xml"},
diff --git a/v2/pkg/assetserver/webview/request.go b/v2/pkg/assetserver/webview/request.go
index b0ce3d069..18ff29890 100644
--- a/v2/pkg/assetserver/webview/request.go
+++ b/v2/pkg/assetserver/webview/request.go
@@ -13,6 +13,5 @@ type Request interface {
Response() ResponseWriter
- AddRef() error
- Release() error
+ Close() error
}
diff --git a/v2/pkg/assetserver/webview/request_darwin.go b/v2/pkg/assetserver/webview/request_darwin.go
index 4f4919fab..c44e5f196 100644
--- a/v2/pkg/assetserver/webview/request_darwin.go
+++ b/v2/pkg/assetserver/webview/request_darwin.go
@@ -8,6 +8,7 @@ package webview
#import
#import
+#include
static void URLSchemeTaskRetain(void *wkUrlSchemeTask) {
id urlSchemeTask = (id) wkUrlSchemeTask;
@@ -44,9 +45,7 @@ static const char * URLSchemeTaskRequestHeadersJSON(void *wkUrlSchemeTask) {
NSString* headerString = [[[NSString alloc] initWithData:headerData encoding:NSUTF8StringEncoding] autorelease];
const char * headerJSON = [headerString UTF8String];
- char * headersOut = malloc(strlen(headerJSON));
- strcpy(headersOut, headerJSON);
- return headersOut;
+ return strdup(headerJSON);
}
}
@@ -118,11 +117,9 @@ import (
)
// NewRequest creates as new WebViewRequest based on a pointer to an `id`
-//
-// Please make sure to call Release() when finished using the request.
func NewRequest(wkURLSchemeTask unsafe.Pointer) Request {
C.URLSchemeTaskRetain(wkURLSchemeTask)
- return &request{task: wkURLSchemeTask}
+ return newRequestFinalizer(&request{task: wkURLSchemeTask})
}
var _ Request = &request{}
@@ -135,16 +132,6 @@ type request struct {
rw *responseWriter
}
-func (r *request) AddRef() error {
- C.URLSchemeTaskRetain(r.task)
- return nil
-}
-
-func (r *request) Release() error {
- C.URLSchemeTaskRelease(r.task)
- return nil
-}
-
func (r *request) URL() (string, error) {
return C.GoString(C.URLSchemeTaskRequestURL(r.task)), nil
}
@@ -205,6 +192,19 @@ func (r *request) Response() ResponseWriter {
return r.rw
}
+func (r *request) Close() error {
+ var err error
+ if r.body != nil {
+ err = r.body.Close()
+ }
+ err = r.Response().Finish()
+ if err != nil {
+ return err
+ }
+ C.URLSchemeTaskRelease(r.task)
+ return err
+}
+
var _ io.ReadCloser = &requestBodyStreamReader{}
type requestBodyStreamReader struct {
diff --git a/v2/pkg/assetserver/webview/request_finalizer.go b/v2/pkg/assetserver/webview/request_finalizer.go
new file mode 100644
index 000000000..6a8c6a928
--- /dev/null
+++ b/v2/pkg/assetserver/webview/request_finalizer.go
@@ -0,0 +1,40 @@
+package webview
+
+import (
+ "runtime"
+ "sync/atomic"
+)
+
+var _ Request = &requestFinalizer{}
+
+type requestFinalizer struct {
+ Request
+ closed int32
+}
+
+// newRequestFinalizer returns a request with a runtime finalizer to make sure it will be closed from the finalizer
+// if it has not been already closed.
+// It also makes sure Close() of the wrapping request is only called once.
+func newRequestFinalizer(r Request) Request {
+ rf := &requestFinalizer{Request: r}
+ // Make sure to async release since it might block the finalizer goroutine for a longer period
+ runtime.SetFinalizer(rf, func(obj *requestFinalizer) { rf.close(true) })
+ return rf
+}
+
+func (r *requestFinalizer) Close() error {
+ return r.close(false)
+}
+
+func (r *requestFinalizer) close(asyncRelease bool) error {
+ if atomic.CompareAndSwapInt32(&r.closed, 0, 1) {
+ runtime.SetFinalizer(r, nil)
+ if asyncRelease {
+ go r.Request.Close()
+ return nil
+ } else {
+ return r.Request.Close()
+ }
+ }
+ return nil
+}
diff --git a/v2/pkg/assetserver/webview/request_linux.go b/v2/pkg/assetserver/webview/request_linux.go
new file mode 100644
index 000000000..c6785fb1c
--- /dev/null
+++ b/v2/pkg/assetserver/webview/request_linux.go
@@ -0,0 +1,85 @@
+//go:build linux
+// +build linux
+
+package webview
+
+/*
+#cgo linux pkg-config: gtk+-3.0 gio-unix-2.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
+
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+*/
+import "C"
+
+import (
+ "io"
+ "net/http"
+ "unsafe"
+)
+
+// NewRequest creates as new WebViewRequest based on a pointer to an `WebKitURISchemeRequest`
+func NewRequest(webKitURISchemeRequest unsafe.Pointer) Request {
+ webkitReq := (*C.WebKitURISchemeRequest)(webKitURISchemeRequest)
+ C.g_object_ref(C.gpointer(webkitReq))
+
+ req := &request{req: webkitReq}
+ return newRequestFinalizer(req)
+}
+
+var _ Request = &request{}
+
+type request struct {
+ req *C.WebKitURISchemeRequest
+
+ header http.Header
+ body io.ReadCloser
+ rw *responseWriter
+}
+
+func (r *request) URL() (string, error) {
+ return C.GoString(C.webkit_uri_scheme_request_get_uri(r.req)), nil
+}
+
+func (r *request) Method() (string, error) {
+ return webkit_uri_scheme_request_get_http_method(r.req), nil
+}
+
+func (r *request) Header() (http.Header, error) {
+ if r.header != nil {
+ return r.header, nil
+ }
+
+ r.header = webkit_uri_scheme_request_get_http_headers(r.req)
+ return r.header, nil
+}
+
+func (r *request) Body() (io.ReadCloser, error) {
+ if r.body != nil {
+ return r.body, nil
+ }
+
+ r.body = webkit_uri_scheme_request_get_http_body(r.req)
+
+ return r.body, nil
+}
+
+func (r *request) Response() ResponseWriter {
+ if r.rw != nil {
+ return r.rw
+ }
+
+ r.rw = &responseWriter{req: r.req}
+ return r.rw
+}
+
+func (r *request) Close() error {
+ var err error
+ if r.body != nil {
+ err = r.body.Close()
+ }
+ r.Response().Finish()
+ C.g_object_unref(C.gpointer(r.req))
+ return err
+}
diff --git a/v2/pkg/assetserver/webview/request_windows.go b/v2/pkg/assetserver/webview/request_windows.go
new file mode 100644
index 000000000..fa83cd8d7
--- /dev/null
+++ b/v2/pkg/assetserver/webview/request_windows.go
@@ -0,0 +1,217 @@
+//go:build windows
+// +build windows
+
+package webview
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+
+ "github.com/wailsapp/go-webview2/pkg/edge"
+)
+
+// NewRequest creates as new WebViewRequest for chromium. This Method must be called from the Main-Thread!
+func NewRequest(env *edge.ICoreWebView2Environment, args *edge.ICoreWebView2WebResourceRequestedEventArgs, invokeSync func(fn func())) (Request, error) {
+ req, err := args.GetRequest()
+ if err != nil {
+ return nil, fmt.Errorf("GetRequest failed: %s", err)
+ }
+ defer req.Release()
+
+ r := &request{
+ invokeSync: invokeSync,
+ }
+
+ code := http.StatusInternalServerError
+ r.response, err = env.CreateWebResourceResponse(nil, code, http.StatusText(code), "")
+ if err != nil {
+ return nil, fmt.Errorf("CreateWebResourceResponse failed: %s", err)
+ }
+
+ if err := args.PutResponse(r.response); err != nil {
+ r.finishResponse()
+ return nil, fmt.Errorf("PutResponse failed: %s", err)
+ }
+
+ r.deferral, err = args.GetDeferral()
+ if err != nil {
+ r.finishResponse()
+ return nil, fmt.Errorf("GetDeferral failed: %s", err)
+ }
+
+ r.url, r.urlErr = req.GetUri()
+ r.method, r.methodErr = req.GetMethod()
+ r.header, r.headerErr = getHeaders(req)
+
+ if content, err := req.GetContent(); err != nil {
+ r.bodyErr = err
+ } else if content != nil {
+ // It is safe to access Content from another Thread: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/threading-model#thread-safety
+ r.body = &iStreamReleaseCloser{stream: content}
+ }
+
+ return r, nil
+}
+
+var _ Request = &request{}
+
+type request struct {
+ response *edge.ICoreWebView2WebResourceResponse
+ deferral *edge.ICoreWebView2Deferral
+
+ url string
+ urlErr error
+
+ method string
+ methodErr error
+
+ header http.Header
+ headerErr error
+
+ body io.ReadCloser
+ bodyErr error
+ rw *responseWriter
+
+ invokeSync func(fn func())
+}
+
+func (r *request) URL() (string, error) {
+ return r.url, r.urlErr
+}
+
+func (r *request) Method() (string, error) {
+ return r.method, r.methodErr
+}
+
+func (r *request) Header() (http.Header, error) {
+ return r.header, r.headerErr
+}
+
+func (r *request) Body() (io.ReadCloser, error) {
+ return r.body, r.bodyErr
+}
+
+func (r *request) Response() ResponseWriter {
+ if r.rw != nil {
+ return r.rw
+ }
+
+ r.rw = &responseWriter{req: r}
+ return r.rw
+}
+
+func (r *request) Close() error {
+ var errs []error
+ if r.body != nil {
+ if err := r.body.Close(); err != nil {
+ errs = append(errs, err)
+ }
+ r.body = nil
+ }
+
+ if err := r.Response().Finish(); err != nil {
+ errs = append(errs, err)
+ }
+
+ return combineErrs(errs)
+}
+
+// finishResponse must be called on the main-thread
+func (r *request) finishResponse() error {
+ var errs []error
+ if r.response != nil {
+ if err := r.response.Release(); err != nil {
+ errs = append(errs, err)
+ }
+ r.response = nil
+ }
+ if r.deferral != nil {
+ if err := r.deferral.Complete(); err != nil {
+ errs = append(errs, err)
+ }
+
+ if err := r.deferral.Release(); err != nil {
+ errs = append(errs, err)
+ }
+ r.deferral = nil
+ }
+ return combineErrs(errs)
+}
+
+type iStreamReleaseCloser struct {
+ stream *edge.IStream
+ closed bool
+}
+
+func (i *iStreamReleaseCloser) Read(p []byte) (int, error) {
+ if i.closed {
+ return 0, io.ErrClosedPipe
+ }
+ return i.stream.Read(p)
+}
+
+func (i *iStreamReleaseCloser) Close() error {
+ if i.closed {
+ return nil
+ }
+ i.closed = true
+ return i.stream.Release()
+}
+
+func getHeaders(req *edge.ICoreWebView2WebResourceRequest) (http.Header, error) {
+ header := http.Header{}
+ headers, err := req.GetHeaders()
+ if err != nil {
+ return nil, fmt.Errorf("GetHeaders Error: %s", err)
+ }
+ defer headers.Release()
+
+ headersIt, err := headers.GetIterator()
+ if err != nil {
+ return nil, fmt.Errorf("GetIterator Error: %s", err)
+ }
+ defer headersIt.Release()
+
+ for {
+ has, err := headersIt.HasCurrentHeader()
+ if err != nil {
+ return nil, fmt.Errorf("HasCurrentHeader Error: %s", err)
+ }
+ if !has {
+ break
+ }
+
+ name, value, err := headersIt.GetCurrentHeader()
+ if err != nil {
+ return nil, fmt.Errorf("GetCurrentHeader Error: %s", err)
+ }
+
+ header.Set(name, value)
+ if _, err := headersIt.MoveNext(); err != nil {
+ return nil, fmt.Errorf("MoveNext Error: %s", err)
+ }
+ }
+
+ // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other
+ // requests including IPC calls.
+ // So prevent 304 status codes by removing the headers that are used in combinationwith caching.
+ header.Del("If-Modified-Since")
+ header.Del("If-None-Match")
+ return header, nil
+}
+
+func combineErrs(errs []error) error {
+ // TODO use Go1.20 errors.Join
+ if len(errs) == 0 {
+ return nil
+ }
+
+ errStrings := make([]string, len(errs))
+ for i, err := range errs {
+ errStrings[i] = err.Error()
+ }
+
+ return fmt.Errorf(strings.Join(errStrings, "\n"))
+}
diff --git a/v2/pkg/assetserver/webview/responsewriter.go b/v2/pkg/assetserver/webview/responsewriter.go
index c372275df..dacbb567d 100644
--- a/v2/pkg/assetserver/webview/responsewriter.go
+++ b/v2/pkg/assetserver/webview/responsewriter.go
@@ -1,14 +1,25 @@
package webview
import (
+ "errors"
"net/http"
)
+const (
+ HeaderContentLength = "Content-Length"
+ HeaderContentType = "Content-Type"
+)
+
+var (
+ errRequestStopped = errors.New("request has been stopped")
+ errResponseFinished = errors.New("response has been finished")
+)
+
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response for the WebView.
type ResponseWriter interface {
http.ResponseWriter
- // Finish the response and flush all data.
+ // Finish the response and flush all data. A Finish after the request has already been finished has no effect.
Finish() error
}
diff --git a/v2/pkg/assetserver/webview/responsewriter_darwin.go b/v2/pkg/assetserver/webview/responsewriter_darwin.go
index 1caa6e85d..a3c73b6f1 100644
--- a/v2/pkg/assetserver/webview/responsewriter_darwin.go
+++ b/v2/pkg/assetserver/webview/responsewriter_darwin.go
@@ -69,16 +69,11 @@ import "C"
import (
"encoding/json"
- "errors"
+ "fmt"
"net/http"
"unsafe"
)
-var (
- errRequestStopped = errors.New("request has been stopped")
- errResponseFinished = errors.New("response has been finished")
-)
-
var _ ResponseWriter = &responseWriter{}
type responseWriter struct {
@@ -104,16 +99,31 @@ func (rw *responseWriter) Write(buf []byte) (int, error) {
rw.WriteHeader(http.StatusOK)
- var content unsafe.Pointer
var contentLen int
if buf != nil {
- content = unsafe.Pointer(&buf[0])
contentLen = len(buf)
}
- if !C.URLSchemeTaskDidReceiveData(rw.r.task, content, C.int(contentLen)) {
- return 0, errRequestStopped
+ if contentLen > 0 {
+ // Create a C array to hold the data
+ cBuf := C.malloc(C.size_t(contentLen))
+ if cBuf == nil {
+ return 0, fmt.Errorf("memory allocation failed for %d bytes", contentLen)
+ }
+ defer C.free(cBuf)
+
+ // Copy the Go slice to the C array
+ C.memcpy(cBuf, unsafe.Pointer(&buf[0]), C.size_t(contentLen))
+
+ if !C.URLSchemeTaskDidReceiveData(rw.r.task, cBuf, C.int(contentLen)) {
+ return 0, errRequestStopped
+ }
+ } else {
+ if !C.URLSchemeTaskDidReceiveData(rw.r.task, nil, 0) {
+ return 0, errRequestStopped
+ }
}
+
return contentLen, nil
}
diff --git a/v2/pkg/assetserver/webview/responsewriter_linux.go b/v2/pkg/assetserver/webview/responsewriter_linux.go
new file mode 100644
index 000000000..59646ce29
--- /dev/null
+++ b/v2/pkg/assetserver/webview/responsewriter_linux.go
@@ -0,0 +1,132 @@
+//go:build linux
+// +build linux
+
+package webview
+
+/*
+#cgo linux pkg-config: gtk+-3.0 gio-unix-2.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
+
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+#include "gio/gunixinputstream.h"
+
+*/
+import "C"
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "strconv"
+ "syscall"
+ "unsafe"
+)
+
+type responseWriter struct {
+ req *C.WebKitURISchemeRequest
+
+ header http.Header
+ wroteHeader bool
+ finished bool
+
+ w io.WriteCloser
+ wErr error
+}
+
+func (rw *responseWriter) Header() http.Header {
+ if rw.header == nil {
+ rw.header = http.Header{}
+ }
+ return rw.header
+}
+
+func (rw *responseWriter) Write(buf []byte) (int, error) {
+ if rw.finished {
+ return 0, errResponseFinished
+ }
+
+ rw.WriteHeader(http.StatusOK)
+ if rw.wErr != nil {
+ return 0, rw.wErr
+ }
+ return rw.w.Write(buf)
+}
+
+func (rw *responseWriter) WriteHeader(code int) {
+ if rw.wroteHeader || rw.finished {
+ return
+ }
+ rw.wroteHeader = true
+
+ contentLength := int64(-1)
+ if sLen := rw.Header().Get(HeaderContentLength); sLen != "" {
+ if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 {
+ contentLength = pLen
+ }
+ }
+
+ // We can't use os.Pipe here, because that returns files with a finalizer for closing the FD. But the control over the
+ // read FD is given to the InputStream and will be closed there.
+ // Furthermore we especially don't want to have the FD_CLOEXEC
+ rFD, w, err := pipe()
+ if err != nil {
+ rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to open pipe: %s", err))
+ return
+ }
+ rw.w = w
+
+ stream := C.g_unix_input_stream_new(C.int(rFD), C.gboolean(1))
+ defer C.g_object_unref(C.gpointer(stream))
+
+ if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil {
+ rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err))
+ return
+ }
+}
+
+func (rw *responseWriter) Finish() error {
+ if !rw.wroteHeader {
+ rw.WriteHeader(http.StatusNotImplemented)
+ }
+
+ if rw.finished {
+ return nil
+ }
+ rw.finished = true
+ if rw.w != nil {
+ rw.w.Close()
+ }
+ return nil
+}
+
+func (rw *responseWriter) finishWithError(code int, err error) {
+ if rw.w != nil {
+ rw.w.Close()
+ rw.w = &nopCloser{io.Discard}
+ }
+ rw.wErr = err
+
+ msg := C.CString(err.Error())
+ gerr := C.g_error_new_literal(C.g_quark_from_string(msg), C.int(code), msg)
+ C.webkit_uri_scheme_request_finish_error(rw.req, gerr)
+ C.g_error_free(gerr)
+ C.free(unsafe.Pointer(msg))
+}
+
+type nopCloser struct {
+ io.Writer
+}
+
+func (nopCloser) Close() error { return nil }
+
+func pipe() (r int, w *os.File, err error) {
+ var p [2]int
+ e := syscall.Pipe2(p[0:], 0)
+ if e != nil {
+ return 0, nil, fmt.Errorf("pipe2: %s", e)
+ }
+
+ return p[0], os.NewFile(uintptr(p[1]), "|1"), nil
+}
diff --git a/v2/pkg/assetserver/webview/responsewriter_windows.go b/v2/pkg/assetserver/webview/responsewriter_windows.go
new file mode 100644
index 000000000..748d9511b
--- /dev/null
+++ b/v2/pkg/assetserver/webview/responsewriter_windows.go
@@ -0,0 +1,105 @@
+//go:build windows
+// +build windows
+
+package webview
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "strings"
+)
+
+var _ http.ResponseWriter = &responseWriter{}
+
+type responseWriter struct {
+ req *request
+
+ header http.Header
+ wroteHeader bool
+ code int
+ body *bytes.Buffer
+
+ finished bool
+}
+
+func (rw *responseWriter) Header() http.Header {
+ if rw.header == nil {
+ rw.header = http.Header{}
+ }
+ return rw.header
+}
+
+func (rw *responseWriter) Write(buf []byte) (int, error) {
+ if rw.finished {
+ return 0, errResponseFinished
+ }
+
+ rw.WriteHeader(http.StatusOK)
+
+ return rw.body.Write(buf)
+}
+
+func (rw *responseWriter) WriteHeader(code int) {
+ if rw.wroteHeader || rw.finished {
+ return
+ }
+ rw.wroteHeader = true
+
+ if rw.body == nil {
+ rw.body = &bytes.Buffer{}
+ }
+
+ rw.code = code
+}
+
+func (rw *responseWriter) Finish() error {
+ if !rw.wroteHeader {
+ rw.WriteHeader(http.StatusNotImplemented)
+ }
+
+ if rw.finished {
+ return nil
+ }
+ rw.finished = true
+
+ var errs []error
+
+ code := rw.code
+ if code == http.StatusNotModified {
+ // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other
+ // requests including IPC calls.
+ errs = append(errs, fmt.Errorf("AssetServer returned 304 - StatusNotModified which are going to hang WebView2, changed code to 505 - StatusInternalServerError"))
+ code = http.StatusInternalServerError
+ }
+
+ rw.req.invokeSync(func() {
+ resp := rw.req.response
+
+ hdrs, err := resp.GetHeaders()
+ if err != nil {
+ errs = append(errs, fmt.Errorf("Resp.GetHeaders failed: %s", err))
+ } else {
+ for k, v := range rw.header {
+ if err := hdrs.AppendHeader(k, strings.Join(v, ",")); err != nil {
+ errs = append(errs, fmt.Errorf("Resp.AppendHeader failed: %s", err))
+ }
+ }
+ hdrs.Release()
+ }
+
+ if err := resp.PutStatusCode(code); err != nil {
+ errs = append(errs, fmt.Errorf("Resp.PutStatusCode failed: %s", err))
+ }
+
+ if err := resp.PutByteContent(rw.body.Bytes()); err != nil {
+ errs = append(errs, fmt.Errorf("Resp.PutByteContent failed: %s", err))
+ }
+
+ if err := rw.req.finishResponse(); err != nil {
+ errs = append(errs, fmt.Errorf("Resp.finishResponse failed: %s", err))
+ }
+ })
+
+ return combineErrs(errs)
+}
diff --git a/v2/pkg/assetserver/webview/webkit2_36+.go b/v2/pkg/assetserver/webview/webkit2_36+.go
new file mode 100644
index 000000000..1f0db3c89
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_36+.go
@@ -0,0 +1,71 @@
+//go:build linux && (webkit2_36 || webkit2_40 || webkit2_41 )
+
+package webview
+
+/*
+#cgo linux pkg-config: gtk+-3.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0 libsoup-2.4
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1 libsoup-3.0
+
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+#include "libsoup/soup.h"
+*/
+import "C"
+
+import (
+ "net/http"
+ "strings"
+ "unsafe"
+)
+
+func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
+ method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
+ return strings.ToUpper(method)
+}
+
+func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header {
+ hdrs := C.webkit_uri_scheme_request_get_http_headers(req)
+
+ var iter C.SoupMessageHeadersIter
+ C.soup_message_headers_iter_init(&iter, hdrs)
+
+ var name *C.char
+ var value *C.char
+
+ h := http.Header{}
+ for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 {
+ h.Add(C.GoString(name), C.GoString(value))
+ }
+
+ return h
+}
+
+func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
+ resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength))
+ defer C.g_object_unref(C.gpointer(resp))
+
+ cReason := C.CString(http.StatusText(code))
+ C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
+ C.free(unsafe.Pointer(cReason))
+
+ cMimeType := C.CString(header.Get(HeaderContentType))
+ C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
+ C.free(unsafe.Pointer(cMimeType))
+
+ hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE)
+ for name, values := range header {
+ cName := C.CString(name)
+ for _, value := range values {
+ cValue := C.CString(value)
+ C.soup_message_headers_append(hdrs, cName, cValue)
+ C.free(unsafe.Pointer(cValue))
+ }
+ C.free(unsafe.Pointer(cName))
+ }
+
+ C.webkit_uri_scheme_response_set_http_headers(resp, hdrs)
+
+ C.webkit_uri_scheme_request_finish_with_response(req, resp)
+ return nil
+}
diff --git a/v2/pkg/assetserver/webview/webkit2_36.go b/v2/pkg/assetserver/webview/webkit2_36.go
new file mode 100644
index 000000000..cd200af8e
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_36.go
@@ -0,0 +1,21 @@
+//go:build linux && webkit2_36
+
+package webview
+
+/*
+#cgo linux pkg-config: webkit2gtk-4.0
+
+#include "webkit2/webkit2.h"
+*/
+import "C"
+
+import (
+ "io"
+ "net/http"
+)
+
+const Webkit2MinMinorVersion = 36
+
+func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser {
+ return http.NoBody
+}
diff --git a/v2/pkg/assetserver/webview/webkit2_40+.go b/v2/pkg/assetserver/webview/webkit2_40+.go
new file mode 100644
index 000000000..eb3e439f2
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_40+.go
@@ -0,0 +1,85 @@
+//go:build linux && (webkit2_40 || webkit2_41)
+
+package webview
+
+/*
+#cgo linux pkg-config: gtk+-3.0 gio-unix-2.0
+#cgo !webkit2_41 pkg-config: webkit2gtk-4.0
+#cgo webkit2_41 pkg-config: webkit2gtk-4.1
+
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+#include "gio/gunixinputstream.h"
+*/
+import "C"
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "unsafe"
+)
+
+func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser {
+ stream := C.webkit_uri_scheme_request_get_http_body(req)
+ if stream == nil {
+ return http.NoBody
+ }
+ return &webkitRequestBody{stream: stream}
+}
+
+type webkitRequestBody struct {
+ stream *C.GInputStream
+ closed bool
+}
+
+// Read implements io.Reader
+func (r *webkitRequestBody) Read(p []byte) (int, error) {
+ if r.closed {
+ return 0, io.ErrClosedPipe
+ }
+
+ var content unsafe.Pointer
+ var contentLen int
+ if p != nil {
+ content = unsafe.Pointer(&p[0])
+ contentLen = len(p)
+ }
+
+ var n C.gsize
+ var gErr *C.GError
+ res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr)
+ if res == 0 {
+ return 0, formatGError("stream read failed", gErr)
+ } else if n == 0 {
+ return 0, io.EOF
+ }
+ return int(n), nil
+}
+
+func (r *webkitRequestBody) Close() error {
+ if r.closed {
+ return nil
+ }
+ r.closed = true
+
+ // https://docs.gtk.org/gio/method.InputStream.close.html
+ // Streams will be automatically closed when the last reference is dropped, but you might want to call this function
+ // to make sure resources are released as early as possible.
+ var err error
+ var gErr *C.GError
+ if C.g_input_stream_close(r.stream, nil, &gErr) == 0 {
+ err = formatGError("stream close failed", gErr)
+ }
+ C.g_object_unref(C.gpointer(r.stream))
+ r.stream = nil
+ return err
+}
+
+func formatGError(msg string, gErr *C.GError, args ...any) error {
+ if gErr != nil && gErr.message != nil {
+ msg += ": " + C.GoString(gErr.message)
+ C.g_error_free(gErr)
+ }
+ return fmt.Errorf(msg, args...)
+}
diff --git a/v2/pkg/assetserver/webview/webkit2_40.go b/v2/pkg/assetserver/webview/webkit2_40.go
new file mode 100644
index 000000000..47b504383
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_40.go
@@ -0,0 +1,5 @@
+//go:build linux && webkit2_40
+
+package webview
+
+const Webkit2MinMinorVersion = 40
diff --git a/v2/pkg/assetserver/webview/webkit2_41.go b/v2/pkg/assetserver/webview/webkit2_41.go
new file mode 100644
index 000000000..82f948d06
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_41.go
@@ -0,0 +1,5 @@
+//go:build linux && webkit2_41
+
+package webview
+
+const Webkit2MinMinorVersion = 41
diff --git a/v2/pkg/assetserver/webview/webkit2_legacy.go b/v2/pkg/assetserver/webview/webkit2_legacy.go
new file mode 100644
index 000000000..1d1cf7c2b
--- /dev/null
+++ b/v2/pkg/assetserver/webview/webkit2_legacy.go
@@ -0,0 +1,48 @@
+//go:build linux && !(webkit2_36 || webkit2_40 || webkit2_41)
+
+package webview
+
+/*
+#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+*/
+import "C"
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "unsafe"
+)
+
+const Webkit2MinMinorVersion = 0
+
+func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string {
+ return http.MethodGet
+}
+
+func webkit_uri_scheme_request_get_http_headers(_ *C.WebKitURISchemeRequest) http.Header {
+ // Fake some basic default headers that are needed if e.g. request are being proxied to the an external sever, like
+ // we do in the devserver.
+ h := http.Header{}
+ h.Add("Accept", "*/*")
+ h.Add("User-Agent", "wails.io/605.1.15")
+ return h
+}
+
+func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser {
+ return http.NoBody
+}
+
+func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
+ if code != http.StatusOK {
+ return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
+ }
+
+ cMimeType := C.CString(header.Get(HeaderContentType))
+ C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType)
+ C.free(unsafe.Pointer(cMimeType))
+ return nil
+}
diff --git a/v2/pkg/buildassets/build/darwin/Info.dev.plist b/v2/pkg/buildassets/build/darwin/Info.dev.plist
index 02e7358ee..14121ef7c 100644
--- a/v2/pkg/buildassets/build/darwin/Info.dev.plist
+++ b/v2/pkg/buildassets/build/darwin/Info.dev.plist
@@ -6,7 +6,7 @@
CFBundleName
{{.Info.ProductName}}
CFBundleExecutable
- {{.Name}}
+ {{.OutputFilename}}
CFBundleIdentifier
com.wails.{{.Name}}
CFBundleVersion
@@ -23,10 +23,46 @@
true
NSHumanReadableCopyright
{{.Info.Copyright}}
+ {{if .Info.FileAssociations}}
+ CFBundleDocumentTypes
+
+ {{range .Info.FileAssociations}}
+
+ CFBundleTypeExtensions
+
+ {{.Ext}}
+
+ CFBundleTypeName
+ {{.Name}}
+ CFBundleTypeRole
+ {{.Role}}
+ CFBundleTypeIconFile
+ {{.IconName}}
+
+ {{end}}
+
+ {{end}}
+ {{if .Info.Protocols}}
+ CFBundleURLTypes
+
+ {{range .Info.Protocols}}
+
+ CFBundleURLName
+ com.wails.{{.Scheme}}
+ CFBundleURLSchemes
+
+ {{.Scheme}}
+
+ CFBundleTypeRole
+ {{.Role}}
+
+ {{end}}
+
+ {{end}}
NSAppTransportSecurity
NSAllowsLocalNetworking
-
\ No newline at end of file
+
diff --git a/v2/pkg/buildassets/build/darwin/Info.plist b/v2/pkg/buildassets/build/darwin/Info.plist
index e7819a7e8..d17a7475c 100644
--- a/v2/pkg/buildassets/build/darwin/Info.plist
+++ b/v2/pkg/buildassets/build/darwin/Info.plist
@@ -6,7 +6,7 @@
CFBundleName
{{.Info.ProductName}}
CFBundleExecutable
- {{.Name}}
+ {{.OutputFilename}}
CFBundleIdentifier
com.wails.{{.Name}}
CFBundleVersion
@@ -23,5 +23,41 @@
true
NSHumanReadableCopyright
{{.Info.Copyright}}
+ {{if .Info.FileAssociations}}
+ CFBundleDocumentTypes
+
+ {{range .Info.FileAssociations}}
+
+ CFBundleTypeExtensions
+
+ {{.Ext}}
+
+ CFBundleTypeName
+ {{.Name}}
+ CFBundleTypeRole
+ {{.Role}}
+ CFBundleTypeIconFile
+ {{.IconName}}
+
+ {{end}}
+
+ {{end}}
+ {{if .Info.Protocols}}
+ CFBundleURLTypes
+
+ {{range .Info.Protocols}}
+
+ CFBundleURLName
+ com.wails.{{.Scheme}}
+ CFBundleURLSchemes
+
+ {{.Scheme}}
+
+ CFBundleTypeRole
+ {{.Role}}
+
+ {{end}}
+
+ {{end}}
-
\ No newline at end of file
+
diff --git a/v2/pkg/buildassets/build/windows/installer/project.nsi b/v2/pkg/buildassets/build/windows/installer/project.nsi
index 3b1588e0c..654ae2e49 100644
--- a/v2/pkg/buildassets/build/windows/installer/project.nsi
+++ b/v2/pkg/buildassets/build/windows/installer/project.nsi
@@ -3,10 +3,10 @@ Unicode true
####
## Please note: Template replacements don't work in this file. They are provided with default defines like
## mentioned underneath.
-## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
-## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
+## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
+## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
## from outside of Wails for debugging and development of the installer.
-##
+##
## For development first make a wails nsis build to populate the "wails_tools.nsh":
## > wails build --target windows/amd64 --nsis
## Then you can call makensis on this file with specifying the path to your binary:
@@ -17,7 +17,7 @@ Unicode true
## For a installer with both architectures:
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
####
-## The following information is taken from the ProjectInfo file, but they can be overwritten here.
+## The following information is taken from the ProjectInfo file, but they can be overwritten here.
####
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
@@ -45,6 +45,9 @@ VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
+# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
+ManifestDPIAware true
+
!include "MUI.nsh"
!define MUI_ICON "..\icon.ico"
@@ -77,19 +80,26 @@ Function .onInit
FunctionEnd
Section
+ !insertmacro wails.setShellContext
+
!insertmacro wails.webview2runtime
SetOutPath $INSTDIR
-
+
!insertmacro wails.files
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
+ !insertmacro wails.associateFiles
+ !insertmacro wails.associateCustomProtocols
+
!insertmacro wails.writeUninstaller
SectionEnd
-Section "uninstall"
+Section "uninstall"
+ !insertmacro wails.setShellContext
+
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
RMDir /r $INSTDIR
@@ -97,5 +107,8 @@ Section "uninstall"
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
+ !insertmacro wails.unassociateFiles
+ !insertmacro wails.unassociateCustomProtocols
+
!insertmacro wails.deleteUninstaller
SectionEnd
diff --git a/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh b/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh
index 66dc209a3..2f6d32195 100644
--- a/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh
+++ b/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh
@@ -134,6 +134,14 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
DeleteRegKey HKLM "${UNINST_KEY}"
!macroend
+!macro wails.setShellContext
+ ${If} ${REQUEST_EXECUTION_LEVEL} == "admin"
+ SetShellVarContext all
+ ${else}
+ SetShellVarContext current
+ ${EndIf}
+!macroend
+
# Install webview2 by launching the bootstrapper
# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
!macro wails.webview2runtime
@@ -150,22 +158,92 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
${If} ${REQUEST_EXECUTION_LEVEL} == "user"
# If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
- ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
+ ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
${If} $0 != ""
Goto ok
${EndIf}
${EndIf}
-
+
SetDetailsPrint both
DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
SetDetailsPrint listonly
-
+
InitPluginsDir
CreateDirectory "$pluginsdir\webview2bootstrapper"
SetOutPath "$pluginsdir\webview2bootstrapper"
File "tmp\MicrosoftEdgeWebview2Setup.exe"
ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
-
+
SetDetailsPrint both
ok:
-!macroend
\ No newline at end of file
+!macroend
+
+# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
+!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_UNASSOCIATE EXT FILECLASS
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
+
+ DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
+!macroend
+
+!macro wails.associateFiles
+ ; Create file associations
+ {{range .Info.FileAssociations}}
+ !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
+
+ File "..\{{.IconName}}.ico"
+ {{end}}
+!macroend
+
+!macro wails.unassociateFiles
+ ; Delete app associations
+ {{range .Info.FileAssociations}}
+ !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
+
+ Delete "$INSTDIR\{{.IconName}}.ico"
+ {{end}}
+!macroend
+
+!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
+ DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
+!macroend
+
+!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
+ DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
+!macroend
+
+!macro wails.associateCustomProtocols
+ ; Create custom protocols associations
+ {{range .Info.Protocols}}
+ !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
+
+ {{end}}
+!macroend
+
+!macro wails.unassociateCustomProtocols
+ ; Delete app custom protocol associations
+ {{range .Info.Protocols}}
+ !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}"
+ {{end}}
+!macroend
diff --git a/v2/pkg/buildassets/buildassets.go b/v2/pkg/buildassets/buildassets.go
index 26401745d..6934b98bd 100644
--- a/v2/pkg/buildassets/buildassets.go
+++ b/v2/pkg/buildassets/buildassets.go
@@ -102,8 +102,9 @@ func ReadOriginalFileWithProjectDataAndSave(projectData *project.Project, file s
}
type assetData struct {
- Name string
- Info project.Info
+ Name string
+ Info project.Info
+ OutputFilename string
}
func resolveProjectData(content []byte, projectData *project.Project) ([]byte, error) {
@@ -113,8 +114,9 @@ func resolveProjectData(content []byte, projectData *project.Project) ([]byte, e
}
data := &assetData{
- Name: projectData.Name,
- Info: projectData.Info,
+ Name: projectData.Name,
+ Info: projectData.Info,
+ OutputFilename: projectData.OutputFilename,
}
var out bytes.Buffer
@@ -128,12 +130,12 @@ func writeFileSystemFile(projectData *project.Project, file string, content []by
targetPath := GetLocalPath(projectData, file)
if dir := filepath.Dir(targetPath); !fs.DirExists(dir) {
- if err := fs.MkDirs(dir, 0755); err != nil {
+ if err := fs.MkDirs(dir, 0o755); err != nil {
return fmt.Errorf("Unable to create directory: %w", err)
}
}
- if err := os.WriteFile(targetPath, content, 0644); err != nil {
+ if err := os.WriteFile(targetPath, content, 0o644); err != nil {
return err
}
return nil
diff --git a/v2/pkg/commands/bindings/bindings.go b/v2/pkg/commands/bindings/bindings.go
index 71c1747b7..82ce0d58f 100644
--- a/v2/pkg/commands/bindings/bindings.go
+++ b/v2/pkg/commands/bindings/bindings.go
@@ -18,15 +18,16 @@ type Options struct {
Filename string
Tags []string
ProjectDirectory string
+ Compiler string
GoModTidy bool
TsPrefix string
TsSuffix string
+ TsOutputType string
}
// GenerateBindings generates bindings for the Wails project in the given ProjectDirectory.
// If no project directory is given then the current working directory is used.
func GenerateBindings(options Options) (string, error) {
-
filename, _ := lo.Coalesce(options.Filename, "wailsbindings")
if runtime.GOOS == "windows" {
filename += ".exe"
@@ -46,17 +47,32 @@ func GenerateBindings(options Options) (string, error) {
tagString := buildtags.Stringify(genModuleTags)
if options.GoModTidy {
- stdout, stderr, err = shell.RunCommand(workingDirectory, "go", "mod", "tidy")
+ stdout, stderr, err = shell.RunCommand(workingDirectory, options.Compiler, "mod", "tidy")
if err != nil {
return stdout, fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
}
}
- stdout, stderr, err = shell.RunCommand(workingDirectory, "go", "build", "-tags", tagString, "-o", filename)
+ envBuild := os.Environ()
+ envBuild = shell.SetEnv(envBuild, "GOOS", runtime.GOOS)
+ envBuild = shell.SetEnv(envBuild, "GOARCH", runtime.GOARCH)
+ // wailsbindings is executed on the build machine.
+ // So, use the default C compiler, not the one set for cross compiling.
+ envBuild = shell.RemoveEnv(envBuild, "CC")
+
+ stdout, stderr, err = shell.RunCommandWithEnv(envBuild, workingDirectory, options.Compiler, "build", "-buildvcs=false", "-tags", tagString, "-o", filename)
if err != nil {
return stdout, fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
}
+ if runtime.GOOS == "darwin" {
+ // Remove quarantine attribute
+ stdout, stderr, err = shell.RunCommand(workingDirectory, "/usr/bin/xattr", "-rc", filename)
+ if err != nil {
+ return stdout, fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
+ }
+ }
+
defer func() {
// Best effort removal of temp file
_ = os.Remove(filename)
@@ -66,6 +82,7 @@ func GenerateBindings(options Options) (string, error) {
env := os.Environ()
env = shell.SetEnv(env, "tsprefix", options.TsPrefix)
env = shell.SetEnv(env, "tssuffix", options.TsSuffix)
+ env = shell.SetEnv(env, "tsoutputtype", options.TsOutputType)
stdout, stderr, err = shell.RunCommandWithEnv(env, workingDirectory, filename)
if err != nil {
diff --git a/v2/pkg/commands/bindings/bindings_test.go b/v2/pkg/commands/bindings/bindings_test.go
index a2cbed436..53f42f2c7 100644
--- a/v2/pkg/commands/bindings/bindings_test.go
+++ b/v2/pkg/commands/bindings/bindings_test.go
@@ -1,13 +1,14 @@
package bindings
import (
- "github.com/matryer/is"
- "github.com/wailsapp/wails/v2/pkg/templates"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
+
+ "github.com/matryer/is"
+ "github.com/wailsapp/wails/v2/pkg/templates"
)
const standardBindings = `// @ts-check
@@ -80,6 +81,7 @@ func TestGenerateBindings(t *testing.T) {
name: "should generate standard bindings with no user tags",
options: Options{
ProjectDirectory: projectDir,
+ Compiler: "go",
GoModTidy: true,
},
expectedBindings: standardBindings,
@@ -90,6 +92,7 @@ func TestGenerateBindings(t *testing.T) {
name: "should generate bindings when given tags",
options: Options{
ProjectDirectory: projectDir,
+ Compiler: "go",
Tags: []string{"test"},
GoModTidy: true,
},
@@ -101,6 +104,7 @@ func TestGenerateBindings(t *testing.T) {
name: "should generate obfuscated bindings",
options: Options{
ProjectDirectory: projectDir,
+ Compiler: "go",
Tags: []string{"obfuscated"},
GoModTidy: true,
},
diff --git a/v2/pkg/commands/build/base.go b/v2/pkg/commands/build/base.go
index fbae6ce7e..239932ce8 100644
--- a/v2/pkg/commands/build/base.go
+++ b/v2/pkg/commands/build/base.go
@@ -74,7 +74,6 @@ func (b *BaseBuilder) convertFileToIntegerString(filename string) (string, error
}
func (b *BaseBuilder) convertByteSliceToIntegerString(data []byte) string {
-
// Create string builder
var result strings.Builder
@@ -85,8 +84,7 @@ func (b *BaseBuilder) convertByteSliceToIntegerString(data []byte) string {
result.WriteString(fmt.Sprintf("%v,", data[i]))
}
- result.WriteString(fmt.Sprintf("%v", data[len(data)-1]))
-
+ result.WriteString(strconv.FormatUint(uint64(data[len(data)-1]), 10))
}
return result.String()
@@ -94,10 +92,8 @@ func (b *BaseBuilder) convertByteSliceToIntegerString(data []byte) string {
// CleanUp does post-build housekeeping
func (b *BaseBuilder) CleanUp() {
-
// Delete all the files
b.filesToDelete.Each(func(filename string) {
-
// if file doesn't exist, ignore
if !b.fileExists(filename) {
return
@@ -106,7 +102,6 @@ func (b *BaseBuilder) CleanUp() {
// Delete file. We ignore errors because these files will be overwritten
// by the next build anyway.
_ = os.Remove(filename)
-
})
}
@@ -159,7 +154,6 @@ func (b *BaseBuilder) OutputFilename(options *Options) string {
// CompileProject compiles the project
func (b *BaseBuilder) CompileProject(options *Options) error {
-
// Check if the runtime wrapper exists
err := generateRuntimeWrapper(options)
if err != nil {
@@ -199,6 +193,8 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
// Default go build command
commands.Add("build")
+ commands.Add("-buildvcs=false")
+
// Add better debugging flags
if options.Mode == Dev || options.Mode == Debug {
commands.Add("-gcflags")
@@ -234,6 +230,11 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
tags.Add("debug")
}
+ // This options allows you to enable devtools in production build (not dev build as it's always enabled there)
+ if options.Devtools {
+ tags.Add("devtools")
+ }
+
if options.Obfuscated {
tags.Add("obfuscated")
}
@@ -308,7 +309,9 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
if v != "" {
v += " "
}
- v += "-mmacosx-version-min=10.13"
+ if !strings.Contains(v, "-mmacosx-version-min") {
+ v += "-mmacosx-version-min=10.13"
+ }
}
return v
})
@@ -345,7 +348,9 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
if addUTIFramework {
v += "-framework UniformTypeIdentifiers "
}
- v += "-mmacosx-version-min=10.13"
+ if !strings.Contains(v, "-mmacosx-version-min") {
+ v += "-mmacosx-version-min=10.13"
+ }
return v
})
@@ -397,7 +402,7 @@ Please reinstall by doing the following:
return nil
}
- var args = []string{"--best", "--no-color", "--no-progress", options.CompiledBinary}
+ args := []string{"--best", "--no-color", "--no-progress", options.CompiledBinary}
if options.CompressFlags != "" {
args = strings.Split(options.CompressFlags, " ")
@@ -421,7 +426,6 @@ Please reinstall by doing the following:
}
func generateRuntimeWrapper(options *Options) error {
-
if options.WailsJSDir == "" {
cwd, err := os.Getwd()
if err != nil {
@@ -447,7 +451,6 @@ func (b *BaseBuilder) NpmInstall(sourceDir string, verbose bool) error {
// NpmInstallUsingCommand runs the given install command in the specified npm project directory
func (b *BaseBuilder) NpmInstallUsingCommand(sourceDir string, installCommand string, verbose bool) error {
-
packageJSON := filepath.Join(sourceDir, "package.json")
// Check package.json exists
@@ -487,7 +490,7 @@ func (b *BaseBuilder) NpmInstallUsingCommand(sourceDir string, installCommand st
}
// Shortcut installation
- if install == false {
+ if !install {
if verbose {
pterm.Println("Skipping npm install")
}
@@ -544,7 +547,6 @@ func (b *BaseBuilder) NpmRunWithEnvironment(projectDir, buildTarget string, verb
// BuildFrontend executes the `npm build` command for the frontend directory
func (b *BaseBuilder) BuildFrontend(outputLogger *clilogger.CLILogger) error {
-
verbose := b.options.Verbosity == VERBOSE
frontendDir := b.projectData.GetFrontendDir()
diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go
index fe8f926f5..7263f63ae 100644
--- a/v2/pkg/commands/build/build.go
+++ b/v2/pkg/commands/build/build.go
@@ -7,6 +7,7 @@ import (
"runtime"
"strings"
+ "github.com/google/shlex"
"github.com/pterm/pterm"
"github.com/samber/lo"
@@ -40,6 +41,7 @@ type Options struct {
Logger *clilogger.CLILogger // All output to the logger
OutputType string // EG: desktop, server....
Mode Mode // release or dev
+ Devtools bool // Enable devtools in production
ProjectData *project.Project // The project data
Pack bool // Create a package for the app after building
Platform string // The platform to build for
@@ -67,11 +69,11 @@ type Options struct {
Obfuscated bool // Indicates that bound methods should be obfuscated
GarbleArgs string // The arguments for Garble
SkipBindings bool // Skip binding generation
+ SkipEmbedCreate bool // Skip creation of embed files
}
// Build the project!
func Build(options *Options) (string, error) {
-
// Extract logger
outputLogger := options.Logger
@@ -119,8 +121,10 @@ func Build(options *Options) (string, error) {
}
// Create embed directories if they don't exist
- if err := CreateEmbedDirectories(cwd, options); err != nil {
- return "", err
+ if !options.SkipEmbedCreate {
+ if err := CreateEmbedDirectories(cwd, options); err != nil {
+ return "", err
+ }
}
// Generate bindings
@@ -144,15 +148,15 @@ func Build(options *Options) (string, error) {
if err != nil {
return "", err
}
- }
- hookArgs["${bin}"] = compileBinary
- for _, hook := range []string{options.Platform + "/" + options.Arch, options.Platform + "/*", "*/*"} {
- if err := execPostBuildHook(outputLogger, options, hook, hookArgs); err != nil {
- return "", err
+ hookArgs["${bin}"] = compileBinary
+ for _, hook := range []string{options.Platform + "/" + options.Arch, options.Platform + "/*", "*/*"} {
+ if err := execPostBuildHook(outputLogger, options, hook, hookArgs); err != nil {
+ return "", err
+ }
}
- }
+ }
return compileBinary, nil
}
@@ -168,21 +172,23 @@ func CreateEmbedDirectories(cwd string, buildOptions *Options) error {
for _, embedDetail := range embedDetails {
fullPath := embedDetail.GetFullPath()
- if _, err := os.Stat(fullPath); os.IsNotExist(err) {
- err := os.MkdirAll(fullPath, 0755)
- if err != nil {
- return err
+ // assumes path is directory only if it has no extension
+ if filepath.Ext(fullPath) == "" {
+ if _, err := os.Stat(fullPath); os.IsNotExist(err) {
+ err := os.MkdirAll(fullPath, 0o755)
+ if err != nil {
+ return err
+ }
+ f, err := os.Create(filepath.Join(fullPath, "gitkeep"))
+ if err != nil {
+ return err
+ }
+ _ = f.Close()
}
- f, err := os.Create(filepath.Join(fullPath, "gitkeep"))
- if err != nil {
- return err
- }
- _ = f.Close()
}
}
return nil
-
}
func fatal(message string) {
@@ -211,7 +217,6 @@ func printBulletPoint(text string, args ...any) {
}
func GenerateBindings(buildOptions *Options) error {
-
obfuscated := buildOptions.Obfuscated
if obfuscated {
printBulletPoint("Generating obfuscated bindings: ")
@@ -220,12 +225,18 @@ func GenerateBindings(buildOptions *Options) error {
printBulletPoint("Generating bindings: ")
}
+ if buildOptions.ProjectData.Bindings.TsGeneration.OutputType == "" {
+ buildOptions.ProjectData.Bindings.TsGeneration.OutputType = "classes"
+ }
+
// Generate Bindings
output, err := bindings.GenerateBindings(bindings.Options{
- Tags: buildOptions.UserTags,
- GoModTidy: !buildOptions.SkipModTidy,
- TsPrefix: buildOptions.ProjectData.Bindings.TsGeneration.Prefix,
- TsSuffix: buildOptions.ProjectData.Bindings.TsGeneration.Suffix,
+ Compiler: buildOptions.Compiler,
+ Tags: buildOptions.UserTags,
+ GoModTidy: !buildOptions.SkipModTidy,
+ TsPrefix: buildOptions.ProjectData.Bindings.TsGeneration.Prefix,
+ TsSuffix: buildOptions.ProjectData.Bindings.TsGeneration.Suffix,
+ TsOutputType: buildOptions.ProjectData.Bindings.TsGeneration.OutputType,
})
if err != nil {
return err
@@ -253,7 +264,7 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
// When we finish, we will want to remove the syso file
defer func() {
- err := os.Remove(filepath.Join(options.ProjectData.Path, options.ProjectData.Name+"-res.syso"))
+ err := os.Remove(filepath.Join(options.ProjectData.Path, strings.ReplaceAll(options.ProjectData.Name, " ", "_")+"-res.syso"))
if err != nil {
fatal(err.Error())
}
@@ -317,6 +328,20 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
}
}
+ if runtime.GOOS == "darwin" {
+ // Remove quarantine attribute
+ if _, err := os.Stat(options.CompiledBinary); os.IsNotExist(err) {
+ return "", fmt.Errorf("compiled binary does not exist at path: %s", options.CompiledBinary)
+ }
+ stdout, stderr, err := shell.RunCommand(options.BinDirectory, "/usr/bin/xattr", "-rc", options.CompiledBinary)
+ if err != nil {
+ return "", fmt.Errorf("%s - %s", err.Error(), stderr)
+ }
+ if options.Verbosity == VERBOSE && stdout != "" {
+ pterm.Info.Println(stdout)
+ }
+ }
+
pterm.Println("Done.")
// Do we need to pack the app for non-windows?
@@ -346,8 +371,8 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
}
}
- if options.Platform == "darwin" && options.Mode == Debug {
- pterm.Warning.Println("A darwin debug build contains private APIs, please don't distribute this build. Please use it only as a test build for testing and debug purposes.")
+ if options.Platform == "darwin" && (options.Mode == Debug || options.Devtools) {
+ pterm.Warning.Println("This darwin build contains the use of private APIs. This will not pass Apple's AppStore approval process. Please use it only as a test build for testing and debug purposes.")
}
return options.CompiledBinary, nil
@@ -369,10 +394,9 @@ func execPostBuildHook(outputLogger *clilogger.CLILogger, options *Options, hook
}
return executeBuildHook(outputLogger, options, hookIdentifier, argReplacements, postBuildHook, "post")
-
}
-func executeBuildHook(outputLogger *clilogger.CLILogger, options *Options, hookIdentifier string, argReplacements map[string]string, buildHook string, hookName string) error {
+func executeBuildHook(_ *clilogger.CLILogger, options *Options, hookIdentifier string, argReplacements map[string]string, buildHook string, hookName string) error {
if !options.ProjectData.RunNonNativeBuildHooks {
if hookIdentifier == "" {
// That's the global hook
@@ -391,7 +415,10 @@ func executeBuildHook(outputLogger *clilogger.CLILogger, options *Options, hookI
}
printBulletPoint("Executing %s build hook '%s': ", hookName, hookIdentifier)
- args := strings.Split(buildHook, " ")
+ args, err := shlex.Split(buildHook)
+ if err != nil {
+ return fmt.Errorf("could not parse %s build hook command: %w", hookName, err)
+ }
for i, arg := range args {
newArg := argReplacements[arg]
if newArg == "" {
@@ -402,7 +429,6 @@ func executeBuildHook(outputLogger *clilogger.CLILogger, options *Options, hookI
if options.Verbosity == VERBOSE {
pterm.Info.Println(strings.Join(args, " "))
-
}
if !fs.DirExists(options.BinDirectory) {
diff --git a/v2/pkg/commands/build/builder.go b/v2/pkg/commands/build/builder.go
index 4840341c0..6a220c530 100644
--- a/v2/pkg/commands/build/builder.go
+++ b/v2/pkg/commands/build/builder.go
@@ -8,8 +8,8 @@ import (
// Builder defines a builder that can build Wails applications
type Builder interface {
SetProjectData(projectData *project.Project)
- BuildFrontend(*clilogger.CLILogger) error
- CompileProject(*Options) error
- OutputFilename(*Options) string
+ BuildFrontend(logger *clilogger.CLILogger) error
+ CompileProject(options *Options) error
+ OutputFilename(options *Options) string
CleanUp()
}
diff --git a/v2/pkg/commands/build/nsis_installer.go b/v2/pkg/commands/build/nsis_installer.go
index 11f1407a3..820df2d1d 100644
--- a/v2/pkg/commands/build/nsis_installer.go
+++ b/v2/pkg/commands/build/nsis_installer.go
@@ -41,7 +41,7 @@ func GenerateNSISInstaller(options *Options, amd64Binary string, arm64Binary str
// Write the WebView2 SetupFile
webviewSetup := buildassets.GetLocalPath(options.ProjectData, path.Join(nsisFolder, nsisWebView2SetupFile))
if dir := filepath.Dir(webviewSetup); !fs.DirExists(dir) {
- if err := fs.MkDirs(dir, 0755); err != nil {
+ if err := fs.MkDirs(dir, 0o755); err != nil {
return err
}
}
@@ -92,7 +92,7 @@ func makeNSIS(options *Options, installerKind string, amd64Binary string, arm64B
outputLogger := options.Logger
outputLogger.Print(" - Building '%s' installer: ", installerKind)
- var args = []string{}
+ args := []string{}
if amd64Binary != "" {
args = append(args, "-DARG_WAILS_AMD64_BINARY="+amd64Binary)
}
diff --git a/v2/pkg/commands/build/packager.go b/v2/pkg/commands/build/packager.go
index 92ce37e90..d406256f9 100644
--- a/v2/pkg/commands/build/packager.go
+++ b/v2/pkg/commands/build/packager.go
@@ -3,12 +3,15 @@ package build
import (
"bytes"
"fmt"
- "github.com/leaanthony/winicon"
- "github.com/tc-hib/winres"
- "github.com/tc-hib/winres/version"
"image"
"os"
"path/filepath"
+ "strings"
+
+ "github.com/leaanthony/winicon"
+ "github.com/tc-hib/winres"
+ "github.com/tc-hib/winres/version"
+ "github.com/wailsapp/wails/v2/internal/project"
"github.com/jackmordaunt/icns"
"github.com/pkg/errors"
@@ -19,7 +22,6 @@ import (
// PackageProject packages the application
func packageProject(options *Options, platform string) error {
-
var err error
switch platform {
case "darwin":
@@ -41,7 +43,6 @@ func packageProject(options *Options, platform string) error {
// cleanBinDirectory will remove an existing bin directory and recreate it
func cleanBinDirectory(options *Options) error {
-
buildDirectory := options.BinDirectory
// Clear out old builds
@@ -53,7 +54,7 @@ func cleanBinDirectory(options *Options) error {
}
// Create clean directory
- err := os.MkdirAll(buildDirectory, 0700)
+ err := os.MkdirAll(buildDirectory, 0o700)
if err != nil {
return err
}
@@ -62,7 +63,6 @@ func cleanBinDirectory(options *Options) error {
}
func packageApplicationForDarwin(options *Options) error {
-
var err error
// Create directory structure
@@ -73,20 +73,20 @@ func packageApplicationForDarwin(options *Options) error {
contentsDirectory := filepath.Join(options.BinDirectory, bundlename, "/Contents")
exeDir := filepath.Join(contentsDirectory, "/MacOS")
- err = fs.MkDirs(exeDir, 0755)
+ err = fs.MkDirs(exeDir, 0o755)
if err != nil {
return err
}
resourceDir := filepath.Join(contentsDirectory, "/Resources")
- err = fs.MkDirs(resourceDir, 0755)
+ err = fs.MkDirs(resourceDir, 0o755)
if err != nil {
return err
}
// Copy binary
- packedBinaryPath := filepath.Join(exeDir, options.ProjectData.Name)
+ packedBinaryPath := filepath.Join(exeDir, options.ProjectData.OutputFilename)
err = fs.MoveFile(options.CompiledBinary, packedBinaryPath)
if err != nil {
- return errors.Wrap(err, "Cannot move file: "+options.ProjectData.OutputFilename)
+ return errors.Wrap(err, "Cannot move file: "+options.CompiledBinary)
}
// Generate Info.plist
@@ -95,19 +95,26 @@ func packageApplicationForDarwin(options *Options) error {
return err
}
- // Generate Icons
- err = processApplicationIcon(options, resourceDir)
+ // Generate App Icon
+ err = processDarwinIcon(options.ProjectData, "appicon", resourceDir, "iconfile")
if err != nil {
return err
}
+ // Generate FileAssociation Icons
+ for _, fileAssociation := range options.ProjectData.Info.FileAssociations {
+ err = processDarwinIcon(options.ProjectData, fileAssociation.IconName, resourceDir, "")
+ if err != nil {
+ return err
+ }
+ }
+
options.CompiledBinary = packedBinaryPath
return nil
}
func processPList(options *Options, contentsDirectory string) error {
-
sourcePList := "Info.plist"
if options.Mode == Dev {
// Use Info.dev.plist if using build mode
@@ -121,11 +128,11 @@ func processPList(options *Options, contentsDirectory string) error {
}
targetFile := filepath.Join(contentsDirectory, "Info.plist")
- return os.WriteFile(targetFile, content, 0644)
+ return os.WriteFile(targetFile, content, 0o644)
}
-func processApplicationIcon(options *Options, resourceDir string) (err error) {
- appIcon, err := buildassets.ReadFile(options.ProjectData, "appicon.png")
+func processDarwinIcon(projectData *project.Project, iconName string, resourceDir string, destIconName string) (err error) {
+ appIcon, err := buildassets.ReadFile(projectData, iconName+".png")
if err != nil {
return err
}
@@ -135,11 +142,14 @@ func processApplicationIcon(options *Options, resourceDir string) (err error) {
return err
}
- tgtBundle := filepath.Join(resourceDir, "iconfile.icns")
+ if destIconName == "" {
+ destIconName = iconName
+ }
+
+ tgtBundle := filepath.Join(resourceDir, destIconName+".icns")
dest, err := os.Create(tgtBundle)
if err != nil {
return err
-
}
defer func() {
err = dest.Close()
@@ -151,13 +161,21 @@ func processApplicationIcon(options *Options, resourceDir string) (err error) {
}
func packageApplicationForWindows(options *Options) error {
- // Generate icon
+ // Generate app icon
var err error
- err = generateIcoFile(options)
+ err = generateIcoFile(options, "appicon", "icon")
if err != nil {
return err
}
+ // Generate FileAssociation Icons
+ for _, fileAssociation := range options.ProjectData.Info.FileAssociations {
+ err = generateIcoFile(options, fileAssociation.IconName, "")
+ if err != nil {
+ return err
+ }
+ }
+
// Create syso file
err = compileResources(options)
if err != nil {
@@ -171,21 +189,26 @@ func packageApplicationForLinux(_ *Options) error {
return nil
}
-func generateIcoFile(options *Options) error {
- content, err := buildassets.ReadFile(options.ProjectData, "appicon.png")
+func generateIcoFile(options *Options, iconName string, destIconName string) error {
+ content, err := buildassets.ReadFile(options.ProjectData, iconName+".png")
if err != nil {
return err
}
+
+ if destIconName == "" {
+ destIconName = iconName
+ }
+
// Check ico file exists already
- icoFile := buildassets.GetLocalPath(options.ProjectData, "windows/icon.ico")
+ icoFile := buildassets.GetLocalPath(options.ProjectData, "windows/"+destIconName+".ico")
if !fs.FileExists(icoFile) {
if dir := filepath.Dir(icoFile); !fs.DirExists(dir) {
- if err := fs.MkDirs(dir, 0755); err != nil {
+ if err := fs.MkDirs(dir, 0o755); err != nil {
return err
}
}
- output, err := os.OpenFile(icoFile, os.O_CREATE|os.O_WRONLY, 0644)
+ output, err := os.OpenFile(icoFile, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
@@ -200,13 +223,12 @@ func generateIcoFile(options *Options) error {
}
func compileResources(options *Options) error {
-
currentDir, err := os.Getwd()
if err != nil {
return err
}
defer func() {
- os.Chdir(currentDir)
+ _ = os.Chdir(currentDir)
}()
windowsDir := filepath.Join(options.ProjectData.GetBuildDir(), "windows")
err = os.Chdir(windowsDir)
@@ -253,7 +275,8 @@ func compileResources(options *Options) error {
rs.SetVersionInfo(v)
}
- targetFile := filepath.Join(options.ProjectData.Path, options.ProjectData.Name+"-res.syso")
+ // replace spaces with underscores as go build behaves weirdly with spaces in syso filename
+ targetFile := filepath.Join(options.ProjectData.Path, strings.ReplaceAll(options.ProjectData.Name, " ", "_")+"-res.syso")
fout, err := os.Create(targetFile)
if err != nil {
return err
diff --git a/v2/pkg/commands/buildtags/buildtags.go b/v2/pkg/commands/buildtags/buildtags.go
index 70820d03d..5cca16acf 100644
--- a/v2/pkg/commands/buildtags/buildtags.go
+++ b/v2/pkg/commands/buildtags/buildtags.go
@@ -8,7 +8,7 @@ import (
)
// Parse parses the given tags string and returns
-// a cleaned slice of strings. Both comma and space delimeted
+// a cleaned slice of strings. Both comma and space delimited
// tags are supported but not mixed. If mixed, an error is returned.
func Parse(tags string) ([]string, error) {
if tags == "" {
diff --git a/v2/pkg/git/git.go b/v2/pkg/git/git.go
index 319c5672b..a0ac68ca9 100644
--- a/v2/pkg/git/git.go
+++ b/v2/pkg/git/git.go
@@ -1,7 +1,8 @@
package git
import (
- "html/template"
+ "encoding/json"
+ "fmt"
"runtime"
"strings"
@@ -30,9 +31,31 @@ func Email() (string, error) {
// Name tries to retrieve the
func Name() (string, error) {
+ errMsg := "failed to retrieve git user name: %w"
stdout, _, err := shell.RunCommand(".", gitcommand(), "config", "user.name")
- name := template.JSEscapeString(strings.TrimSpace(stdout))
- return name, err
+ if err != nil {
+ return "", fmt.Errorf(errMsg, err)
+ }
+ name := strings.TrimSpace(stdout)
+ return EscapeName(name)
+}
+
+func EscapeName(str string) (string, error) {
+ b, err := json.Marshal(str)
+ if err != nil {
+ return "", err
+ }
+ // Remove the surrounding quotes
+ escaped := string(b[1 : len(b)-1])
+
+ // Check if username is JSON compliant
+ var js json.RawMessage
+ jsonVal := fmt.Sprintf(`{"name": "%s"}`, escaped)
+ err = json.Unmarshal([]byte(jsonVal), &js)
+ if err != nil {
+ return "", fmt.Errorf("failed to retrieve git user name: %w", err)
+ }
+ return escaped, nil
}
func InitRepo(projectDir string) error {
diff --git a/v2/pkg/git/git_test.go b/v2/pkg/git/git_test.go
new file mode 100644
index 000000000..238008ec3
--- /dev/null
+++ b/v2/pkg/git/git_test.go
@@ -0,0 +1,44 @@
+package git
+
+import (
+ "testing"
+)
+
+func TestEscapeName1(t *testing.T) {
+ type args struct {
+ str string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ wantErr bool
+ }{
+ {
+ name: "Escape Apostrophe",
+ args: args{
+ str: `John O'Keefe`,
+ },
+ want: `John O'Keefe`,
+ },
+ {
+ name: "Escape backslash",
+ args: args{
+ str: `MYDOMAIN\USER`,
+ },
+ want: `MYDOMAIN\\USER`,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := EscapeName(tt.args.str)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("EscapeName() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("EscapeName() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/v2/pkg/logger/filelogger.go b/v2/pkg/logger/filelogger.go
index 5cf68fc1a..954c46f59 100644
--- a/v2/pkg/logger/filelogger.go
+++ b/v2/pkg/logger/filelogger.go
@@ -19,7 +19,7 @@ func NewFileLogger(filename string) Logger {
// Print works like Sprintf.
func (l *FileLogger) Print(message string) {
- f, err := os.OpenFile(l.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
+ f, err := os.OpenFile(l.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
log.Fatal(err)
}
diff --git a/v2/pkg/logger/logger.go b/v2/pkg/logger/logger.go
index abc288265..990dffe75 100644
--- a/v2/pkg/logger/logger.go
+++ b/v2/pkg/logger/logger.go
@@ -41,6 +41,24 @@ func StringToLogLevel(input string) (LogLevel, error) {
return result, nil
}
+// String returns the string representation of the LogLevel
+func (l LogLevel) String() string {
+ switch l {
+ case TRACE:
+ return "trace"
+ case DEBUG:
+ return "debug"
+ case INFO:
+ return "info"
+ case WARNING:
+ return "warning"
+ case ERROR:
+ return "error"
+ default:
+ return "debug"
+ }
+}
+
// Logger specifies the methods required to attach
// a logger to a Wails application
type Logger interface {
diff --git a/v2/pkg/mac/login_darwin.go b/v2/pkg/mac/login_darwin.go
index 2ff49be83..b2390e305 100644
--- a/v2/pkg/mac/login_darwin.go
+++ b/v2/pkg/mac/login_darwin.go
@@ -33,7 +33,7 @@ func StartAtLogin(enabled bool) error {
}
_, stde, err := shell.RunCommand("/tmp", "osascript", "-e", command)
if err != nil {
- errors.Wrap(err, stde)
+ return errors.Wrap(err, stde)
}
return nil
}
diff --git a/v2/pkg/mac/notification_darwin.go b/v2/pkg/mac/notification_darwin.go
index a06ecb53a..243f07c78 100644
--- a/v2/pkg/mac/notification_darwin.go
+++ b/v2/pkg/mac/notification_darwin.go
@@ -8,7 +8,7 @@ import (
"github.com/wailsapp/wails/v2/internal/shell"
)
-// StartAtLogin will either add or remove this application to/from the login
+// ShowNotification will either add or remove this application to/from the login
// items, depending on the given boolean flag. The limitation is that the
// currently running app must be in an app bundle.
func ShowNotification(title string, subtitle string, message string, sound string) error {
@@ -24,7 +24,7 @@ func ShowNotification(title string, subtitle string, message string, sound strin
}
_, stde, err := shell.RunCommand("/tmp", "osascript", "-e", command)
if err != nil {
- errors.Wrap(err, stde)
+ return errors.Wrap(err, stde)
}
return nil
}
diff --git a/v2/pkg/menu/callback.go b/v2/pkg/menu/callback.go
index fe6160361..a02664ac0 100644
--- a/v2/pkg/menu/callback.go
+++ b/v2/pkg/menu/callback.go
@@ -2,7 +2,7 @@ package menu
type CallbackData struct {
MenuItem *MenuItem
- //ContextData string
+ // ContextData string
}
type Callback func(*CallbackData)
diff --git a/v2/pkg/menu/colours/colours.go b/v2/pkg/menu/colours/colours.go
index 28564a09e..5fb74eabd 100644
--- a/v2/pkg/menu/colours/colours.go
+++ b/v2/pkg/menu/colours/colours.go
@@ -36,7 +36,6 @@ type InputCol struct {
var Template string
func main() {
-
var Cols []InputCol
resp, err := http.Get("https://jonasjacek.github.io/colors/data.json")
@@ -62,5 +61,8 @@ func main() {
if err != nil {
log.Fatal(err)
}
- os.WriteFile(filepath.Join("..", "cols.go"), buffer.Bytes(), 0755)
+ err = os.WriteFile(filepath.Join("..", "cols.go"), buffer.Bytes(), 0o755)
+ if err != nil {
+ log.Fatal(err)
+ }
}
diff --git a/v2/pkg/menu/keys/keys.go b/v2/pkg/menu/keys/keys.go
index 73bc9414f..961edab2d 100644
--- a/v2/pkg/menu/keys/keys.go
+++ b/v2/pkg/menu/keys/keys.go
@@ -16,7 +16,7 @@ const (
// ShiftKey represents the shift key on all systems
ShiftKey Modifier = "shift"
// SuperKey represents Command on Mac and the Windows key on the other platforms
- //SuperKey Modifier = "super"
+ // SuperKey Modifier = "super"
// ControlKey represents the control key on all systems
ControlKey Modifier = "ctrl"
)
@@ -99,8 +99,6 @@ func Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)
Key: key,
Modifiers: []Modifier{modifier1, modifier2},
}
- for _, extra := range rest {
- result.Modifiers = append(result.Modifiers, extra)
- }
+ result.Modifiers = append(result.Modifiers, rest...)
return result
}
diff --git a/v2/pkg/menu/keys/parser.go b/v2/pkg/menu/keys/parser.go
index 91a05783d..6e8e12376 100644
--- a/v2/pkg/menu/keys/parser.go
+++ b/v2/pkg/menu/keys/parser.go
@@ -11,7 +11,6 @@ import (
var namedKeys = slicer.String([]string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
func parseKey(key string) (string, bool) {
-
// Lowercase!
key = strings.ToLower(key)
@@ -38,11 +37,9 @@ func parseKey(key string) (string, bool) {
}
return "", false
-
}
func Parse(shortcut string) (*Accelerator, error) {
-
var result Accelerator
// Split the shortcut by +
diff --git a/v2/pkg/menu/keys/stringify.go b/v2/pkg/menu/keys/stringify.go
index ccc8c5e9e..92498f5d4 100644
--- a/v2/pkg/menu/keys/stringify.go
+++ b/v2/pkg/menu/keys/stringify.go
@@ -1,8 +1,9 @@
package keys
import (
- "github.com/leaanthony/slicer"
"strings"
+
+ "github.com/leaanthony/slicer"
)
var modifierStringMap = map[string]map[Modifier]string{
@@ -11,21 +12,21 @@ var modifierStringMap = map[string]map[Modifier]string{
ControlKey: "Ctrl",
OptionOrAltKey: "Alt",
ShiftKey: "Shift",
- //SuperKey: "Win",
+ // SuperKey: "Win",
},
"darwin": {
CmdOrCtrlKey: "Cmd",
ControlKey: "Ctrl",
OptionOrAltKey: "Option",
ShiftKey: "Shift",
- //SuperKey: "Cmd",
+ // SuperKey: "Cmd",
},
"linux": {
CmdOrCtrlKey: "Ctrl",
ControlKey: "Ctrl",
OptionOrAltKey: "Alt",
ShiftKey: "Shift",
- //SuperKey: "Super",
+ // SuperKey: "Super",
},
}
diff --git a/v2/pkg/menu/menu.go b/v2/pkg/menu/menu.go
index 0c3ddb618..86acbd1d0 100644
--- a/v2/pkg/menu/menu.go
+++ b/v2/pkg/menu/menu.go
@@ -17,9 +17,7 @@ func (m *Menu) Append(item *MenuItem) {
// Merge will append the items in the given menu
// into this menu
func (m *Menu) Merge(menu *Menu) {
- for _, item := range menu.Items {
- m.Items = append(m.Items, item)
- }
+ m.Items = append(m.Items, menu.Items...)
}
// AddText adds a TextMenu item to the menu
@@ -61,8 +59,7 @@ func (m *Menu) Prepend(item *MenuItem) {
}
func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu {
-
- var result = NewMenu()
+ result := NewMenu()
result.Append(first)
for _, item := range rest {
result.Append(item)
diff --git a/v2/pkg/menu/menuitem.go b/v2/pkg/menu/menuitem.go
index f6ea681d7..bffc522d8 100644
--- a/v2/pkg/menu/menuitem.go
+++ b/v2/pkg/menu/menuitem.go
@@ -22,8 +22,8 @@ type MenuItem struct {
Hidden bool
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
Checked bool
- // Submenu contains a list of menu items that will be shown as a submenu
- //SubMenu []*MenuItem `json:"SubMenu,omitempty"`
+ // SubMenu contains a list of menu items that will be shown as a submenu
+ // SubMenu []*MenuItem `json:"SubMenu,omitempty"`
SubMenu *Menu
// Callback function when menu clicked
@@ -106,7 +106,6 @@ func (m *MenuItem) removeChild(item *MenuItem) {
// menu. If there is no parent menu (we are a top level menu) then false is
// returned
func (m *MenuItem) InsertAfter(item *MenuItem) bool {
-
// We need to find my parent
if m.parent == nil {
return false
@@ -120,7 +119,6 @@ func (m *MenuItem) InsertAfter(item *MenuItem) bool {
// menu. If there is no parent menu (we are a top level menu) then false is
// returned
func (m *MenuItem) InsertBefore(item *MenuItem) bool {
-
// We need to find my parent
if m.parent == nil {
return false
@@ -134,8 +132,8 @@ func (m *MenuItem) InsertBefore(item *MenuItem) bool {
// in this item's submenu. If we are not a submenu,
// then something bad has happened :/
func (m *MenuItem) insertNewItemAfterGivenItem(target *MenuItem,
- newItem *MenuItem) bool {
-
+ newItem *MenuItem,
+) bool {
if !m.isSubMenu() {
return false
}
@@ -154,8 +152,8 @@ func (m *MenuItem) insertNewItemAfterGivenItem(target *MenuItem,
// target in this item's submenu. If we are not a submenu, then something bad
// has happened :/
func (m *MenuItem) insertNewItemBeforeGivenItem(target *MenuItem,
- newItem *MenuItem) bool {
-
+ newItem *MenuItem,
+) bool {
if !m.isSubMenu() {
return false
}
@@ -176,7 +174,6 @@ func (m *MenuItem) isSubMenu() bool {
// getItemIndex returns the index of the given target relative to this menu
func (m *MenuItem) getItemIndex(target *MenuItem) int {
-
// This should only be called on submenus
if !m.isSubMenu() {
return -1
@@ -196,7 +193,6 @@ func (m *MenuItem) getItemIndex(target *MenuItem) int {
// the given index
// Credit: https://stackoverflow.com/a/61822301
func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool {
-
// If index is OOB, return false
if index > len(m.SubMenu.Items) {
return false
diff --git a/v2/pkg/menu/menuroles.go b/v2/pkg/menu/menuroles.go
index 62a193c8e..bcc0657fc 100644
--- a/v2/pkg/menu/menuroles.go
+++ b/v2/pkg/menu/menuroles.go
@@ -8,31 +8,32 @@ type Role int
// These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h`
const (
- AppMenuRole Role = 1
- EditMenuRole = 2
- //AboutRole Role = "about"
- //UndoRole Role = "undo"
- //RedoRole Role = "redo"
- //CutRole Role = "cut"
- //CopyRole Role = "copy"
- //PasteRole Role = "paste"
- //PasteAndMatchStyleRole Role = "pasteAndMatchStyle"
- //SelectAllRole Role = "selectAll"
- //DeleteRole Role = "delete"
- //MinimizeRole Role = "minimize"
- //QuitRole Role = "quit"
- //TogglefullscreenRole Role = "togglefullscreen"
- //FileMenuRole Role = "fileMenu"
- //ViewMenuRole Role = "viewMenu"
- //WindowMenuRole Role = "windowMenu"
- //HideRole Role = "hide"
- //HideOthersRole Role = "hideOthers"
- //UnhideRole Role = "unhide"
- //FrontRole Role = "front"
- //ZoomRole Role = "zoom"
- //WindowSubMenuRole Role = "windowSubMenu"
- //HelpSubMenuRole Role = "helpSubMenu"
- //SeparatorItemRole Role = "separatorItem"
+ AppMenuRole Role = 1
+ EditMenuRole = 2
+ WindowMenuRole = 3
+ // AboutRole Role = "about"
+ // UndoRole Role = "undo"
+ // RedoRole Role = "redo"
+ // CutRole Role = "cut"
+ // CopyRole Role = "copy"
+ // PasteRole Role = "paste"
+ // PasteAndMatchStyleRole Role = "pasteAndMatchStyle"
+ // SelectAllRole Role = "selectAll"
+ // DeleteRole Role = "delete"
+ // MinimizeRole Role = "minimize"
+ // QuitRole Role = "quit"
+ // TogglefullscreenRole Role = "togglefullscreen"
+ // FileMenuRole Role = "fileMenu"
+ // ViewMenuRole Role = "viewMenu"
+ // WindowMenuRole Role = "windowMenu"
+ // HideRole Role = "hide"
+ // HideOthersRole Role = "hideOthers"
+ // UnhideRole Role = "unhide"
+ // FrontRole Role = "front"
+ // ZoomRole Role = "zoom"
+ // WindowSubMenuRole Role = "windowSubMenu"
+ // HelpSubMenuRole Role = "helpSubMenu"
+ // SeparatorItemRole Role = "separatorItem"
)
/*
@@ -142,14 +143,16 @@ func ViewMenu() *MenuItem {
Role: ViewMenuRole,
}
}
+*/
// WindowMenu provides a MenuItem with the whole default "Window" menu (Minimize, Zoom, etc.).
+// On MacOS currently all options in there won't work if the window is frameless.
func WindowMenu() *MenuItem {
return &MenuItem{
Role: WindowMenuRole,
}
}
-*/
+
// These roles are Mac only
// AppMenu provides a MenuItem with the whole default "App" menu (About, Services, etc.)
diff --git a/v2/pkg/menu/styledlabel.go b/v2/pkg/menu/styledlabel.go
index 11a0254c9..1e996b971 100644
--- a/v2/pkg/menu/styledlabel.go
+++ b/v2/pkg/menu/styledlabel.go
@@ -29,24 +29,31 @@ type StyledText struct {
func (s *StyledText) Bold() bool {
return s.Style&Bold == Bold
}
+
func (s *StyledText) Faint() bool {
return s.Style&Faint == Faint
}
+
func (s *StyledText) Italic() bool {
return s.Style&Italic == Italic
}
+
func (s *StyledText) Blinking() bool {
return s.Style&Blinking == Blinking
}
+
func (s *StyledText) Inversed() bool {
return s.Style&Inversed == Inversed
}
+
func (s *StyledText) Invisible() bool {
return s.Style&Invisible == Invisible
}
+
func (s *StyledText) Underlined() bool {
return s.Style&Underlined == Underlined
}
+
func (s *StyledText) Strikethrough() bool {
return s.Style&Strikethrough == Strikethrough
}
diff --git a/v2/pkg/menu/tray.go b/v2/pkg/menu/tray.go
index 7554795ad..c8728f1f7 100644
--- a/v2/pkg/menu/tray.go
+++ b/v2/pkg/menu/tray.go
@@ -2,7 +2,6 @@ package menu
// TrayMenu are the options
type TrayMenu struct {
-
// Label is the text we wish to display in the tray
Label string
@@ -27,7 +26,7 @@ type TrayMenu struct {
Tooltip string
// Callback function when menu clicked
- //Click Callback `json:"-"`
+ // Click Callback `json:"-"`
// Disabled makes the item unselectable
Disabled bool
diff --git a/v2/pkg/options/default.go b/v2/pkg/options/default.go
deleted file mode 100644
index e2555ebbc..000000000
--- a/v2/pkg/options/default.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package options
-
-import (
- "github.com/wailsapp/wails/v2/pkg/logger"
- "github.com/wailsapp/wails/v2/pkg/menu"
-)
-
-// Default options for creating the App
-var Default = &App{
- Width: 1024,
- Height: 768,
- Logger: logger.NewDefaultLogger(),
- LogLevel: logger.INFO,
- LogLevelProduction: logger.ERROR,
- CSSDragProperty: "--wails-draggable",
- CSSDragValue: "drag",
-}
-
-var defaultMacMenu = menu.NewMenuFromItems(
- menu.AppMenu(),
- menu.EditMenu(),
-)
diff --git a/v2/pkg/options/linux/linux.go b/v2/pkg/options/linux/linux.go
index 3726297c4..797450c27 100644
--- a/v2/pkg/options/linux/linux.go
+++ b/v2/pkg/options/linux/linux.go
@@ -28,7 +28,21 @@ type Options struct {
// - WebviewGpuPolicyAlways
// - WebviewGpuPolicyOnDemand
// - WebviewGpuPolicyNever
+ //
+ // Due to https://github.com/wailsapp/wails/issues/2977, if options.Linux is nil
+ // in the call to wails.Run(), WebviewGpuPolicy is set by default to WebviewGpuPolicyNever.
+ // Client code may override this behavior by passing a non-nil Options and set
+ // WebviewGpuPolicy as needed.
WebviewGpuPolicy WebviewGpuPolicy
+
+ // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname().
+ //This name should not be localized. [see the docs]
+ //
+ //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name
+ //property differs form the executable's filename.
+ //
+ //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html
+ ProgramName string
}
type Messages struct {
diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go
index 033cfd1a2..152145114 100644
--- a/v2/pkg/options/mac/mac.go
+++ b/v2/pkg/options/mac/mac.go
@@ -18,9 +18,14 @@ type AboutInfo struct {
type Options struct {
TitleBar *TitleBar
Appearance AppearanceType
+ ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
- //ActivationPolicy ActivationPolicy
- About *AboutInfo
- //URLHandlers map[string]func(string)
+ Preferences *Preferences
+ DisableZoom bool
+ // ActivationPolicy ActivationPolicy
+ About *AboutInfo
+ OnFileOpen func(filePath string) `json:"-"`
+ OnUrlOpen func(filePath string) `json:"-"`
+ // URLHandlers map[string]func(string)
}
diff --git a/v2/pkg/options/mac/preferences.go b/v2/pkg/options/mac/preferences.go
new file mode 100644
index 000000000..0749ccb18
--- /dev/null
+++ b/v2/pkg/options/mac/preferences.go
@@ -0,0 +1,21 @@
+package mac
+
+import "github.com/leaanthony/u"
+
+var (
+ Enabled = u.True
+ Disabled = u.False
+)
+
+// Preferences allows to set webkit preferences
+type Preferences struct {
+ // A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls.
+ // Set to false by default.
+ TabFocusesLinks u.Bool
+ // A Boolean value that indicates whether to allow people to select or otherwise interact with text.
+ // Set to true by default.
+ TextInteractionEnabled u.Bool
+ // A Boolean value that indicates whether a web view can display content full screen.
+ // Set to false by default
+ FullscreenEnabled u.Bool
+}
diff --git a/v2/pkg/options/mac/titlebar.go b/v2/pkg/options/mac/titlebar.go
index c18c4eea8..51e0832ca 100644
--- a/v2/pkg/options/mac/titlebar.go
+++ b/v2/pkg/options/mac/titlebar.go
@@ -41,7 +41,6 @@ func TitleBarHidden() *TitleBar {
// TitleBarHiddenInset results in a hidden title bar with an alternative look where
// the traffic light buttons are slightly more inset from the window edge.
func TitleBarHiddenInset() *TitleBar {
-
return &TitleBar{
TitlebarAppearsTransparent: true,
HideTitle: true,
@@ -50,5 +49,4 @@ func TitleBarHiddenInset() *TitleBar {
UseToolbar: true,
HideToolbarSeparator: true,
}
-
}
diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go
index 80c70296c..0f62d5e4b 100644
--- a/v2/pkg/options/options.go
+++ b/v2/pkg/options/options.go
@@ -4,8 +4,9 @@ import (
"context"
"html"
"io/fs"
- "log"
"net/http"
+ "os"
+ "path/filepath"
"runtime"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
@@ -15,7 +16,6 @@ import (
"github.com/wailsapp/wails/v2/pkg/menu"
- "github.com/imdario/mergo"
"github.com/wailsapp/wails/v2/pkg/logger"
)
@@ -28,8 +28,7 @@ const (
Fullscreen WindowStartState = 3
)
-type Experimental struct {
-}
+type Experimental struct{}
// App contains options for creating the App
type App struct {
@@ -64,19 +63,29 @@ type App struct {
OnShutdown func(ctx context.Context) `json:"-"`
OnBeforeClose func(ctx context.Context) (prevent bool) `json:"-"`
Bind []interface{}
+ EnumBind []interface{}
WindowStartState WindowStartState
+ // ErrorFormatter overrides the formatting of errors returned by backend methods
+ ErrorFormatter ErrorFormatter
+
// CSS property to test for draggable elements. Default "--wails-draggable"
CSSDragProperty string
// The CSS Value that the CSSDragProperty must have to be draggable, EG: "drag"
CSSDragValue string
+ // EnableDefaultContextMenu enables the browser's default context-menu in production
+ // This menu is already enabled in development and debug builds
+ EnableDefaultContextMenu bool
+
// EnableFraudulentWebsiteDetection enables scan services for fraudulent content, such as malware or phishing attempts.
// These services might send information from your app like URLs navigated to and possibly other content to cloud
// services of Apple and Microsoft.
EnableFraudulentWebsiteDetection bool
+ SingleInstanceLock *SingleInstanceLock
+
Windows *windows.Options
Mac *mac.Options
Linux *linux.Options
@@ -86,8 +95,19 @@ type App struct {
// Debug options for debug builds. These options will be ignored in a production build.
Debug Debug
+
+ // DragAndDrop options for drag and drop behavior
+ DragAndDrop *DragAndDrop
+
+ // DisablePanicRecovery disables the panic recovery system in messages processing
+ DisablePanicRecovery bool
+
+ // List of additional allowed origins for bindings in format "https://*.myapp.com,https://example.com"
+ BindingsAllowedOrigins string
}
+type ErrorFormatter func(error) any
+
type RGBA struct {
R uint8 `json:"r"`
G uint8 `json:"g"`
@@ -117,14 +137,37 @@ func NewRGB(r, g, b uint8) *RGBA {
// MergeDefaults will set the minimum default values for an application
func MergeDefaults(appoptions *App) {
-
- // Do default merge
- err := mergo.Merge(appoptions, Default)
- if err != nil {
- log.Fatal(err)
+ // Do set defaults
+ if appoptions.Width <= 0 {
+ appoptions.Width = 1024
+ }
+ if appoptions.Height <= 0 {
+ appoptions.Height = 768
+ }
+ if appoptions.Logger == nil {
+ appoptions.Logger = logger.NewDefaultLogger()
+ }
+ if appoptions.LogLevel == 0 {
+ appoptions.LogLevel = logger.INFO
+ }
+ if appoptions.LogLevelProduction == 0 {
+ appoptions.LogLevelProduction = logger.ERROR
+ }
+ if appoptions.CSSDragProperty == "" {
+ appoptions.CSSDragProperty = "--wails-draggable"
+ }
+ if appoptions.CSSDragValue == "" {
+ appoptions.CSSDragValue = "drag"
+ }
+ if appoptions.DragAndDrop == nil {
+ appoptions.DragAndDrop = &DragAndDrop{}
+ }
+ if appoptions.DragAndDrop.CSSDropProperty == "" {
+ appoptions.DragAndDrop.CSSDropProperty = "--wails-drop-target"
+ }
+ if appoptions.DragAndDrop.CSSDropValue == "" {
+ appoptions.DragAndDrop.CSSDropValue = "drop"
}
-
- // Default colour. Doesn't work well with mergo
if appoptions.BackgroundColour == nil {
appoptions.BackgroundColour = &RGBA{
R: 255,
@@ -144,11 +187,59 @@ func MergeDefaults(appoptions *App) {
processDragOptions(appoptions)
}
+type SingleInstanceLock struct {
+ // uniqueId that will be used for setting up messaging between instances
+ UniqueId string
+ OnSecondInstanceLaunch func(secondInstanceData SecondInstanceData)
+}
+
+type SecondInstanceData struct {
+ Args []string
+ WorkingDirectory string
+}
+
+type DragAndDrop struct {
+
+ // EnableFileDrop enables wails' drag and drop functionality that returns the dropped in files' absolute paths.
+ EnableFileDrop bool
+
+ // Disable webview's drag and drop functionality.
+ //
+ // It can be used to prevent accidental file opening of dragged in files in the webview, when there is no need for drag and drop.
+ DisableWebViewDrop bool
+
+ // CSS property to test for drag and drop target elements. Default "--wails-drop-target"
+ CSSDropProperty string
+
+ // The CSS Value that the CSSDropProperty must have to be a valid drop target. Default "drop"
+ CSSDropValue string
+}
+
+func NewSecondInstanceData() (*SecondInstanceData, error) {
+ ex, err := os.Executable()
+ if err != nil {
+ return nil, err
+ }
+ workingDirectory := filepath.Dir(ex)
+
+ return &SecondInstanceData{
+ Args: os.Args[1:],
+ WorkingDirectory: workingDirectory,
+ }, nil
+}
+
func processMenus(appoptions *App) {
switch runtime.GOOS {
case "darwin":
if appoptions.Menu == nil {
- appoptions.Menu = defaultMacMenu
+ items := []*menu.MenuItem{
+ menu.EditMenu(),
+ }
+ if !appoptions.Frameless {
+ items = append(items, menu.WindowMenu()) // Current options in Window Menu only work if not frameless
+ }
+
+ appoptions.Menu = menu.NewMenuFromItems(menu.AppMenu(), items...)
}
}
}
diff --git a/v2/pkg/options/options_test.go b/v2/pkg/options/options_test.go
index 5f75b5acc..0cacd702d 100644
--- a/v2/pkg/options/options_test.go
+++ b/v2/pkg/options/options_test.go
@@ -14,8 +14,8 @@ func TestMergeDefaultsWH(t *testing.T) {
{
name: "No width and height",
appoptions: &App{},
- wantWidth: Default.Width,
- wantHeight: Default.Height,
+ wantWidth: 1024,
+ wantHeight: 768,
},
{
name: "Basic width and height",
diff --git a/v2/pkg/options/systemtray.go b/v2/pkg/options/systemtray.go
deleted file mode 100644
index 117abb4d6..000000000
--- a/v2/pkg/options/systemtray.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package options
-
-import (
- "github.com/wailsapp/wails/v2/pkg/menu"
-)
-
-// SystemTray contains options for the system tray
-type SystemTray struct {
- LightModeIcon *SystemTrayIcon
- DarkModeIcon *SystemTrayIcon
- Title string
- Tooltip string
- StartHidden bool
- Menu *menu.Menu
- OnLeftClick func()
- OnRightClick func()
- OnLeftDoubleClick func()
- OnRightDoubleClick func()
- OnMenuClose func()
- OnMenuOpen func()
-}
-
-// SystemTrayIcon represents a system tray icon
-type SystemTrayIcon struct {
- Data []byte
-}
diff --git a/v2/pkg/options/windows/windows.go b/v2/pkg/options/windows/windows.go
index 9a0f5c733..1fe351455 100644
--- a/v2/pkg/options/windows/windows.go
+++ b/v2/pkg/options/windows/windows.go
@@ -13,6 +13,7 @@ type Messages struct {
PressOKToInstall string
ContactAdmin string
InvalidFixedWebview2 string
+ WebView2ProcessCrash string
}
const (
@@ -34,8 +35,29 @@ const (
Tabbed BackdropType = 4
)
+const (
+ // Default is 0, which means no changes to the default Windows DLL search behavior
+ DLLSearchDefault uint32 = 0
+ // LoadLibrary flags for determining from where to search for a DLL
+ DLLSearchDontResolveDllReferences uint32 = 0x1 // windows.DONT_RESOLVE_DLL_REFERENCES
+ DLLSearchAsDataFile uint32 = 0x2 // windows.LOAD_LIBRARY_AS_DATAFILE
+ DLLSearchWithAlteredPath uint32 = 0x8 // windows.LOAD_WITH_ALTERED_SEARCH_PATH
+ DLLSearchIgnoreCodeAuthzLevel uint32 = 0x10 // windows.LOAD_IGNORE_CODE_AUTHZ_LEVEL
+ DLLSearchAsImageResource uint32 = 0x20 // windows.LOAD_LIBRARY_AS_IMAGE_RESOURCE
+ DLLSearchAsDataFileExclusive uint32 = 0x40 // windows.LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
+ DLLSearchRequireSignedTarget uint32 = 0x80 // windows.LOAD_LIBRARY_REQUIRE_SIGNED_TARGET
+ DLLSearchDllLoadDir uint32 = 0x100 // windows.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
+ DLLSearchApplicationDir uint32 = 0x200 // windows.LOAD_LIBRARY_SEARCH_APPLICATION_DIR
+ DLLSearchUserDirs uint32 = 0x400 // windows.LOAD_LIBRARY_SEARCH_USER_DIRS
+ DLLSearchSystem32 uint32 = 0x800 // windows.LOAD_LIBRARY_SEARCH_SYSTEM32
+ DLLSearchDefaultDirs uint32 = 0x1000 // windows.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
+ DLLSearchSafeCurrentDirs uint32 = 0x2000 // windows.LOAD_LIBRARY_SAFE_CURRENT_DIRS
+ DLLSearchSystem32NoForwarder uint32 = 0x4000 // windows.LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER
+ DLLSearchOsIntegrityContinuity uint32 = 0x8000 // windows.LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY
+)
+
func RGB(r, g, b uint8) int32 {
- var col = int32(b)
+ col := int32(b)
col = col<<8 | int32(g)
col = col<<8 | int32(r)
return col
@@ -60,6 +82,7 @@ type ThemeSettings struct {
// Options are options specific to Windows
type Options struct {
+ ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
DisableWindowIcon bool
@@ -67,6 +90,8 @@ type Options struct {
IsZoomControlEnabled bool
ZoomFactor float64
+ DisablePinchZoom bool
+
// Disable all window decorations in Frameless mode, which means no "Aero Shadow" and no "Rounded Corner" will be shown.
// "Rounded Corners" are only available on Windows 11.
DisableFramelessWindowDecorations bool
@@ -102,6 +127,27 @@ type Options struct {
// WebviewGpuIsDisabled is used to enable / disable GPU acceleration for the webview
WebviewGpuIsDisabled bool
+
+ // WebviewDisableRendererCodeIntegrity disables the `RendererCodeIntegrity` of WebView2. Some Security Endpoint
+ // Protection Software inject themself into the WebView2 with unsigned or wrongly signed dlls, which is not allowed
+ // and will stop the WebView2 processes. Those security software need an update to fix this issue or one can disable
+ // the integrity check with this flag.
+ //
+ // The event viewer log contains `Code Integrity Errors` like mentioned here: https://github.com/MicrosoftEdge/WebView2Feedback/issues/2051
+ //
+ // !! Please keep in mind when disabling this feature, this also allows malicious software to inject into the WebView2 !!
+ WebviewDisableRendererCodeIntegrity bool
+
+ // Configure whether swipe gestures should be enabled
+ EnableSwipeGestures bool
+
+ // Class name for the window. If empty, 'wailsWindow' will be used.
+ WindowClassName string
+
+ // DLLSearchPaths controls which directories are searched when loading DLLs
+ // Set to 0 for default behavior, or combine multiple flags with bitwise OR
+ // Example: DLLSearchApplicationDir | DLLSearchSystem32
+ DLLSearchPaths uint32
}
func DefaultMessages() *Messages {
@@ -116,5 +162,6 @@ func DefaultMessages() *Messages {
PressOKToInstall: "Press Ok to install.",
ContactAdmin: "The WebView2 runtime is required to run this application. Please contact your system administrator.",
InvalidFixedWebview2: "The WebView2 runtime is manually specified, but It is not valid. Check minimum required version and webview2 path.",
+ WebView2ProcessCrash: "The WebView2 process crashed and the application needs to be restarted.",
}
}
diff --git a/v2/pkg/runtime/dialog.go b/v2/pkg/runtime/dialog.go
index d53a89c15..16ae659e1 100644
--- a/v2/pkg/runtime/dialog.go
+++ b/v2/pkg/runtime/dialog.go
@@ -3,6 +3,7 @@ package runtime
import (
"context"
"fmt"
+
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/fs"
)
diff --git a/v2/pkg/runtime/draganddrop.go b/v2/pkg/runtime/draganddrop.go
new file mode 100644
index 000000000..2db9c773c
--- /dev/null
+++ b/v2/pkg/runtime/draganddrop.go
@@ -0,0 +1,37 @@
+package runtime
+
+import (
+ "context"
+ "fmt"
+)
+
+// OnFileDrop returns a slice of file path strings when a drop is finished.
+func OnFileDrop(ctx context.Context, callback func(x, y int, paths []string)) {
+ if callback == nil {
+ LogError(ctx, "OnFileDrop called with a nil callback")
+ return
+ }
+ EventsOn(ctx, "wails:file-drop", func(optionalData ...interface{}) {
+ if len(optionalData) != 3 {
+ callback(0, 0, nil)
+ }
+ x, ok := optionalData[0].(int)
+ if !ok {
+ LogError(ctx, fmt.Sprintf("invalid x coordinate in drag and drop: %v", optionalData[0]))
+ }
+ y, ok := optionalData[1].(int)
+ if !ok {
+ LogError(ctx, fmt.Sprintf("invalid y coordinate in drag and drop: %v", optionalData[1]))
+ }
+ paths, ok := optionalData[2].([]string)
+ if !ok {
+ LogError(ctx, fmt.Sprintf("invalid path data in drag and drop: %v", optionalData[2]))
+ }
+ callback(x, y, paths)
+ })
+}
+
+// OnFileDropOff removes the drag and drop listeners and handlers.
+func OnFileDropOff(ctx context.Context) {
+ EventsOff(ctx, "wails:file-drop")
+}
diff --git a/v2/pkg/runtime/events.go b/v2/pkg/runtime/events.go
index 493d81168..84aff7d74 100644
--- a/v2/pkg/runtime/events.go
+++ b/v2/pkg/runtime/events.go
@@ -10,7 +10,7 @@ func EventsOn(ctx context.Context, eventName string, callback func(optionalData
return events.On(eventName, callback)
}
-// EventsOff unregisters a listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`
+// EventsOff unregisters a listener for the given event name, optionally multiple listeners can be unregistered via `additionalEventNames`
func EventsOff(ctx context.Context, eventName string, additionalEventNames ...string) {
events := getEvents(ctx)
events.Off(eventName)
@@ -22,7 +22,7 @@ func EventsOff(ctx context.Context, eventName string, additionalEventNames ...st
}
}
-// EventsOff unregisters a listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`
+// EventsOff unregisters a listener for the given event name, optionally multiple listeners can be unregistered via `additionalEventNames`
func EventsOffAll(ctx context.Context) {
events := getEvents(ctx)
events.OffAll()
diff --git a/v2/pkg/runtime/log.go b/v2/pkg/runtime/log.go
index 4d3f56d3f..3c2756f06 100644
--- a/v2/pkg/runtime/log.go
+++ b/v2/pkg/runtime/log.go
@@ -3,6 +3,7 @@ package runtime
import (
"context"
"fmt"
+
"github.com/wailsapp/wails/v2/pkg/logger"
)
diff --git a/v2/pkg/runtime/menu.go b/v2/pkg/runtime/menu.go
index 176c9bb1d..09bd640c5 100644
--- a/v2/pkg/runtime/menu.go
+++ b/v2/pkg/runtime/menu.go
@@ -2,6 +2,7 @@ package runtime
import (
"context"
+
"github.com/wailsapp/wails/v2/pkg/menu"
)
diff --git a/v2/pkg/runtime/runtime.go b/v2/pkg/runtime/runtime.go
index 4702b439a..6de5ea798 100644
--- a/v2/pkg/runtime/runtime.go
+++ b/v2/pkg/runtime/runtime.go
@@ -27,6 +27,7 @@ func getFrontend(ctx context.Context) frontend.Frontend {
log.Fatalf("cannot call '%s': %s", funcName, contextError)
return nil
}
+
func getLogger(ctx context.Context) *logger.Logger {
if ctx == nil {
pc, _, _, _ := goruntime.Caller(1)
diff --git a/v2/pkg/runtime/screen.go b/v2/pkg/runtime/screen.go
index d92ed8308..c4d526692 100644
--- a/v2/pkg/runtime/screen.go
+++ b/v2/pkg/runtime/screen.go
@@ -1,11 +1,14 @@
package runtime
-import "context"
-import "github.com/wailsapp/wails/v2/internal/frontend"
+import (
+ "context"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
+)
type Screen = frontend.Screen
-// ScreenGetAllScreens returns all screens
+// ScreenGetAll returns all screens
func ScreenGetAll(ctx context.Context) ([]Screen, error) {
appFrontend := getFrontend(ctx)
return appFrontend.ScreenGetAll()
diff --git a/v2/pkg/runtime/signal_linux.go b/v2/pkg/runtime/signal_linux.go
new file mode 100644
index 000000000..6a7ed5db3
--- /dev/null
+++ b/v2/pkg/runtime/signal_linux.go
@@ -0,0 +1,65 @@
+//go:build linux
+
+package runtime
+
+/*
+#include
+#include
+#include
+#include
+
+static void fix_signal(int signum)
+{
+ struct sigaction st;
+
+ if (sigaction(signum, NULL, &st) < 0) {
+ return;
+ }
+ st.sa_flags |= SA_ONSTACK;
+ sigaction(signum, &st, NULL);
+}
+
+static void fix_all_signals()
+{
+#if defined(SIGSEGV)
+ fix_signal(SIGSEGV);
+#endif
+#if defined(SIGBUS)
+ fix_signal(SIGBUS);
+#endif
+#if defined(SIGFPE)
+ fix_signal(SIGFPE);
+#endif
+#if defined(SIGABRT)
+ fix_signal(SIGABRT);
+#endif
+}
+*/
+import "C"
+
+// ResetSignalHandlers resets signal handlers to allow panic recovery.
+//
+// On Linux, WebKit (used for the webview) may install signal handlers without
+// the SA_ONSTACK flag, which prevents Go from properly recovering from panics
+// caused by nil pointer dereferences or other memory access violations.
+//
+// Call this function immediately before code that might panic to ensure
+// the signal handlers are properly configured for Go's panic recovery mechanism.
+//
+// Example usage:
+//
+// go func() {
+// defer func() {
+// if err := recover(); err != nil {
+// log.Printf("Recovered from panic: %v", err)
+// }
+// }()
+// runtime.ResetSignalHandlers()
+// // Code that might panic...
+// }()
+//
+// Note: This function only has an effect on Linux. On other platforms,
+// it is a no-op.
+func ResetSignalHandlers() {
+ C.fix_all_signals()
+}
diff --git a/v2/pkg/runtime/signal_other.go b/v2/pkg/runtime/signal_other.go
new file mode 100644
index 000000000..3171a700c
--- /dev/null
+++ b/v2/pkg/runtime/signal_other.go
@@ -0,0 +1,18 @@
+//go:build !linux
+
+package runtime
+
+// ResetSignalHandlers resets signal handlers to allow panic recovery.
+//
+// On Linux, WebKit (used for the webview) may install signal handlers without
+// the SA_ONSTACK flag, which prevents Go from properly recovering from panics
+// caused by nil pointer dereferences or other memory access violations.
+//
+// Call this function immediately before code that might panic to ensure
+// the signal handlers are properly configured for Go's panic recovery mechanism.
+//
+// Note: This function only has an effect on Linux. On other platforms,
+// it is a no-op.
+func ResetSignalHandlers() {
+ // No-op on non-Linux platforms
+}
diff --git a/v2/pkg/runtime/window.go b/v2/pkg/runtime/window.go
index ca28e9d30..62345e2e4 100644
--- a/v2/pkg/runtime/window.go
+++ b/v2/pkg/runtime/window.go
@@ -179,3 +179,8 @@ func WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8) {
}
appFrontend.WindowSetBackgroundColour(col)
}
+
+func WindowPrint(ctx context.Context) {
+ appFrontend := getFrontend(ctx)
+ appFrontend.WindowPrint()
+}
diff --git a/v2/pkg/templates/base/go.mod.tmpl b/v2/pkg/templates/base/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/base/go.mod.tmpl
+++ b/v2/pkg/templates/base/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/generate/assets/lit-ts/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/lit-ts/frontend/index.tmpl.html
index 4944992b5..febcb76cb 100644
--- a/v2/pkg/templates/generate/assets/lit-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/lit-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
index e2db01c7d..fbe3eb240 100644
--- a/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
index e88b655ef..3dd212f2d 100644
--- a/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
@@ -3,7 +3,6 @@
-
{{.ProjectName}}
diff --git a/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md b/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md
deleted file mode 100644
index 15b2483d9..000000000
--- a/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-This template uses a work around as the default template does not compile due to this issue:
-https://github.com/vuejs/core/issues/1228
-
-In `tsconfig.json`, `isolatedModules` is set to `false` rather than `true` to work around the issue.
\ No newline at end of file
diff --git a/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
index 5c0949b5e..cc259435b 100644
--- a/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
index b3d4289c3..d45b7a8c4 100644
--- a/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/generate.go b/v2/pkg/templates/generate/generate.go
index 3b01e5f2a..6842dc196 100644
--- a/v2/pkg/templates/generate/generate.go
+++ b/v2/pkg/templates/generate/generate.go
@@ -159,7 +159,6 @@ var templates = []*template{
}
func main() {
-
rebuildRuntime()
for _, t := range templates {
diff --git a/v2/pkg/templates/generate/plain/go.mod.tmpl b/v2/pkg/templates/generate/plain/go.mod.tmpl
index e01fbe9e7..f6d0daec4 100644
--- a/v2/pkg/templates/generate/plain/go.mod.tmpl
+++ b/v2/pkg/templates/generate/plain/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates.go b/v2/pkg/templates/templates.go
index d982454d0..e18185520 100644
--- a/v2/pkg/templates/templates.go
+++ b/v2/pkg/templates/templates.go
@@ -72,7 +72,6 @@ type Options struct {
// Template holds data relating to a template
// including the metadata stored in template.json
type Template struct {
-
// Template details
Name string `json:"name"`
ShortName string `json:"shortname"`
@@ -100,7 +99,6 @@ func parseTemplate(template gofs.FS) (Template, error) {
// List returns the list of available templates
func List() ([]Template, error) {
-
// If the cache isn't loaded, load it
if templateCache == nil {
err := loadTemplateCache()
@@ -114,7 +112,6 @@ func List() ([]Template, error) {
// getTemplateByShortname returns the template with the given short name
func getTemplateByShortname(shortname string) (Template, error) {
-
var result Template
// If the cache isn't loaded, load it
@@ -136,7 +133,6 @@ func getTemplateByShortname(shortname string) (Template, error) {
// Loads the template cache
func loadTemplateCache() error {
-
templatesFS, err := debme.FS(templates, "templates")
if err != nil {
return err
@@ -190,7 +186,16 @@ func Install(options *Options) (bool, *Template, error) {
return false, nil, err
}
options.TargetDir = targetDir
- if !fs.DirExists(options.TargetDir) {
+ if fs.DirExists(options.TargetDir) {
+ // Check if directory is non-empty
+ entries, err := os.ReadDir(options.TargetDir)
+ if err != nil {
+ return false, nil, err
+ }
+ if len(entries) > 0 {
+ return false, nil, fmt.Errorf("cannot initialise project in non-empty directory: %s", options.TargetDir)
+ }
+ } else {
err := fs.Mkdir(options.TargetDir)
if err != nil {
return false, nil, err
@@ -309,11 +314,9 @@ func gitclone(options *Options) (string, error) {
_, err = git.PlainClone(dirname, false, cloneOption)
return dirname, err
-
}
func generateIDEFiles(options *Options) error {
-
switch options.IDE {
case "vscode":
return generateVSCodeFiles(options)
@@ -361,7 +364,6 @@ func generateVSCodeFiles(options *Options) error {
options: options,
}
return installIDEFiles(ideoptions)
-
}
func installIDEFiles(o ideOptions) error {
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
index 4944992b5..febcb76cb 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts b/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
index 27fd71e45..af4e9ce20 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
+++ b/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
@@ -2,6 +2,7 @@ import {css, html, LitElement} from 'lit'
import logo from './assets/images/logo-universal.png'
import {Greet} from "../wailsjs/go/main/App";
import {customElement, property} from 'lit/decorators.js'
+import './style.css';
/**
* An example element.
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/lit-ts/go.mod.tmpl b/v2/pkg/templates/templates/lit-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/lit-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/lit-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/lit/frontend/index.tmpl.html b/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
index e2db01c7d..fbe3eb240 100644
--- a/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/lit/frontend/src/my-element.js b/v2/pkg/templates/templates/lit/frontend/src/my-element.js
index ed65e2225..017632c09 100644
--- a/v2/pkg/templates/templates/lit/frontend/src/my-element.js
+++ b/v2/pkg/templates/templates/lit/frontend/src/my-element.js
@@ -1,6 +1,7 @@
import {css, html, LitElement} from 'lit'
import logo from './assets/images/logo-universal.png'
import {Greet} from "../wailsjs/go/main/App";
+import './style.css';
/**
* An example element.
diff --git a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/lit/go.mod.tmpl b/v2/pkg/templates/templates/lit/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/lit/go.mod.tmpl
+++ b/v2/pkg/templates/templates/lit/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/plain/frontend/src/main.js b/v2/pkg/templates/templates/plain/frontend/src/main.js
index 3346d59ff..e4945441d 100644
--- a/v2/pkg/templates/templates/plain/frontend/src/main.js
+++ b/v2/pkg/templates/templates/plain/frontend/src/main.js
@@ -1,6 +1,7 @@
// Get input + focus
let nameElement = document.getElementById("name");
nameElement.focus();
+import './main.css';
// Setup the greet function
window.greet = function () {
diff --git a/v2/pkg/templates/templates/plain/go.mod.tmpl b/v2/pkg/templates/templates/plain/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/plain/go.mod.tmpl
+++ b/v2/pkg/templates/templates/plain/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/preact-ts/go.mod.tmpl b/v2/pkg/templates/templates/preact-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/preact-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/preact-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/preact/frontend/src/assets/preact.svg b/v2/pkg/templates/templates/preact/frontend/src/assets/preact.svg
index 8d4155b1d..23433fcf8 100644
--- a/v2/pkg/templates/templates/preact/frontend/src/assets/preact.svg
+++ b/v2/pkg/templates/templates/preact/frontend/src/assets/preact.svg
@@ -1,10 +1 @@
-
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/preact/go.mod.tmpl b/v2/pkg/templates/templates/preact/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/preact/go.mod.tmpl
+++ b/v2/pkg/templates/templates/preact/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/react-ts/go.mod.tmpl b/v2/pkg/templates/templates/react-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/react-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/react-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/react/go.mod.tmpl b/v2/pkg/templates/templates/react/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/react/go.mod.tmpl
+++ b/v2/pkg/templates/templates/react/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
index e88b655ef..3dd212f2d 100644
--- a/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
@@ -3,7 +3,6 @@
-
{{.ProjectName}}
diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/package.json b/v2/pkg/templates/templates/svelte-ts/frontend/package.json
index 8bbb15b1b..2ee69eaf5 100644
--- a/v2/pkg/templates/templates/svelte-ts/frontend/package.json
+++ b/v2/pkg/templates/templates/svelte-ts/frontend/package.json
@@ -17,6 +17,6 @@
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "^4.6.4",
- "vite": "^3.0.0"
+ "vite": "^3.0.7"
}
}
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl b/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/svelte/frontend/package.json b/v2/pkg/templates/templates/svelte/frontend/package.json
index 8a9354150..8c9ae62a8 100644
--- a/v2/pkg/templates/templates/svelte/frontend/package.json
+++ b/v2/pkg/templates/templates/svelte/frontend/package.json
@@ -11,6 +11,6 @@
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"svelte": "^3.49.0",
- "vite": "^3.0.0"
+ "vite": "^3.0.7"
}
}
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/svelte/go.mod.tmpl b/v2/pkg/templates/templates/svelte/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/svelte/go.mod.tmpl
+++ b/v2/pkg/templates/templates/svelte/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/vanilla-ts/frontend/package.json b/v2/pkg/templates/templates/vanilla-ts/frontend/package.json
index 37305b4c0..c57eb8610 100644
--- a/v2/pkg/templates/templates/vanilla-ts/frontend/package.json
+++ b/v2/pkg/templates/templates/vanilla-ts/frontend/package.json
@@ -9,6 +9,6 @@
},
"devDependencies": {
"typescript": "^4.5.4",
- "vite": "^2.9.9"
+ "vite": "^3.0.7"
}
}
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl b/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/vanilla/frontend/package.json b/v2/pkg/templates/templates/vanilla/frontend/package.json
index 4ac881798..a1b6f8e1a 100644
--- a/v2/pkg/templates/templates/vanilla/frontend/package.json
+++ b/v2/pkg/templates/templates/vanilla/frontend/package.json
@@ -8,6 +8,6 @@
"preview": "vite preview"
},
"devDependencies": {
- "vite": "^2.9.9"
+ "vite": "^3.0.7"
}
}
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/vanilla/go.mod.tmpl b/v2/pkg/templates/templates/vanilla/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/vanilla/go.mod.tmpl
+++ b/v2/pkg/templates/templates/vanilla/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md b/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md
deleted file mode 100644
index 15b2483d9..000000000
--- a/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-This template uses a work around as the default template does not compile due to this issue:
-https://github.com/vuejs/core/issues/1228
-
-In `tsconfig.json`, `isolatedModules` is set to `false` rather than `true` to work around the issue.
\ No newline at end of file
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
index 5c0949b5e..cc259435b 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/package.json b/v2/pkg/templates/templates/vue-ts/frontend/package.json
index c06165c24..e65d0eff4 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/package.json
+++ b/v2/pkg/templates/templates/vue-ts/frontend/package.json
@@ -15,7 +15,7 @@
"@vitejs/plugin-vue": "^3.0.3",
"typescript": "^4.6.4",
"vite": "^3.0.7",
- "vue-tsc": "^0.39.5",
+ "vue-tsc": "^1.8.27",
"@babel/types": "^7.18.10"
}
-}
\ No newline at end of file
+}
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts b/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
index e57db5948..f9754fe19 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
+++ b/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
@@ -1,4 +1,5 @@
import {createApp} from 'vue'
import App from './App.vue'
+import './style.css';
createApp(App).mount('#app')
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/vue-ts/go.mod.tmpl b/v2/pkg/templates/templates/vue-ts/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/vue-ts/go.mod.tmpl
+++ b/v2/pkg/templates/templates/vue-ts/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates/vue/frontend/index.tmpl.html b/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
index b3d4289c3..d45b7a8c4 100644
--- a/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/vue/frontend/src/main.js b/v2/pkg/templates/templates/vue/frontend/src/main.js
index e57db5948..f9754fe19 100644
--- a/v2/pkg/templates/templates/vue/frontend/src/main.js
+++ b/v2/pkg/templates/templates/vue/frontend/src/main.js
@@ -1,4 +1,5 @@
import {createApp} from 'vue'
import App from './App.vue'
+import './style.css';
createApp(App).mount('#app')
diff --git a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
index e0d662b38..336fb07aa 100644
--- a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
@@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void):
// unregisters the listener for the given event name.
export function EventsOff(eventName: string): void;
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all event listeners.
+export function EventsOffAll(): void;
+
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
@@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
index 2c3dafcc3..b5ae16d56 100644
--- a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
+++ b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
@@ -48,6 +48,10 @@ export function EventsOff(eventName) {
return window.runtime.EventsOff(eventName);
}
+export function EventsOffAll() {
+ return window.runtime.EventsOffAll();
+}
+
export function EventsOnce(eventName, callback) {
EventsOnMultiple(eventName, callback, 1);
}
diff --git a/v2/pkg/templates/templates/vue/go.mod.tmpl b/v2/pkg/templates/templates/vue/go.mod.tmpl
index dd7184879..4b34d1668 100644
--- a/v2/pkg/templates/templates/vue/go.mod.tmpl
+++ b/v2/pkg/templates/templates/vue/go.mod.tmpl
@@ -1,6 +1,6 @@
module changeme
-go 1.18
+go 1.23.0
require github.com/wailsapp/wails/v2 {{.WailsVersion}}
diff --git a/v2/pkg/templates/templates_test.go b/v2/pkg/templates/templates_test.go
index 3b906601a..658ecadb6 100644
--- a/v2/pkg/templates/templates_test.go
+++ b/v2/pkg/templates/templates_test.go
@@ -52,3 +52,48 @@ func TestInstall(t *testing.T) {
is2.NoErr(err)
}
+
+func TestInstallFailsInNonEmptyDirectory(t *testing.T) {
+ is2 := is.New(t)
+
+ // Create a temp directory with a file in it
+ tempDir, err := os.MkdirTemp("", "wails-test-nonempty-*")
+ is2.NoErr(err)
+ defer func() {
+ _ = os.RemoveAll(tempDir)
+ }()
+
+ // Create a file in the directory to make it non-empty
+ err = os.WriteFile(filepath.Join(tempDir, "existing-file.txt"), []byte("test"), 0644)
+ is2.NoErr(err)
+
+ options := &Options{
+ ProjectName: "test",
+ TemplateName: "vanilla",
+ TargetDir: tempDir,
+ }
+
+ _, _, err = Install(options)
+ is2.True(err != nil) // Should fail
+ is2.True(err.Error() == "cannot initialise project in non-empty directory: "+tempDir)
+}
+
+func TestInstallSucceedsInEmptyDirectory(t *testing.T) {
+ is2 := is.New(t)
+
+ // Create an empty temp directory
+ tempDir, err := os.MkdirTemp("", "wails-test-empty-*")
+ is2.NoErr(err)
+ defer func() {
+ _ = os.RemoveAll(tempDir)
+ }()
+
+ options := &Options{
+ ProjectName: "test",
+ TemplateName: "vanilla",
+ TargetDir: tempDir,
+ }
+
+ _, _, err = Install(options)
+ is2.NoErr(err) // Should succeed in empty directory
+}
diff --git a/v2/tools/release/release.go b/v2/tools/release/release.go
index 4c20c8fdc..4178fcc95 100644
--- a/v2/tools/release/release.go
+++ b/v2/tools/release/release.go
@@ -6,6 +6,9 @@ import (
"os/exec"
"strconv"
"strings"
+ "time"
+
+ "github.com/samber/lo"
"github.com/wailsapp/wails/v2/internal/s"
)
@@ -30,7 +33,7 @@ func updateVersion() string {
minorVersion++
vsplit[len(vsplit)-1] = strconv.Itoa(minorVersion)
newVersion := strings.Join(vsplit, ".")
- err = os.WriteFile(versionFile, []byte(newVersion), 0755)
+ err = os.WriteFile(versionFile, []byte(newVersion), 0o755)
checkError(err)
return newVersion
}
@@ -43,45 +46,82 @@ func runCommand(name string, arg ...string) {
checkError(err)
}
+func IsPointRelease(currentVersion string, newVersion string) bool {
+ // The first n-1 parts of the version should be the same
+ if currentVersion[:len(currentVersion)-2] != newVersion[:len(newVersion)-2] {
+ return false
+ }
+ // split on the last dot in the string
+ currentVersionSplit := strings.Split(currentVersion, ".")
+ newVersionSplit := strings.Split(newVersion, ".")
+ // compare the
+ // if the last part of the version is the same, it's a point release
+ currentMinor := lo.Must(strconv.Atoi(currentVersionSplit[len(currentVersionSplit)-1]))
+ newMinor := lo.Must(strconv.Atoi(newVersionSplit[len(newVersionSplit)-1]))
+ return newMinor == currentMinor+1
+}
+
func main() {
var newVersion string
+ var isPointRelease bool
if len(os.Args) > 1 {
newVersion = os.Args[1]
- err := os.WriteFile(versionFile, []byte(newVersion), 0755)
+ currentVersion, err := os.ReadFile(versionFile)
checkError(err)
+ err = os.WriteFile(versionFile, []byte(newVersion), 0o755)
+ checkError(err)
+ isPointRelease = IsPointRelease(string(currentVersion), newVersion)
} else {
newVersion = updateVersion()
}
+ // Update ChangeLog
s.CD("../../../website")
- runCommand("pnpm", "install")
- s.ECHO("Generating new Docs for version: " + newVersion)
-
- runCommand("pnpm", "run", "docusaurus", "docs:version", newVersion)
-
- runCommand("pnpm", "run", "write-translations")
-
- // Load the version list/*
- versionsData, err := os.ReadFile("versions.json")
+ // Read in `src/pages/changelog.mdx`
+ changelogData, err := os.ReadFile("src/pages/changelog.mdx")
checkError(err)
- var versions []string
- err = json.Unmarshal(versionsData, &versions)
- checkError(err)
- oldestVersion := versions[len(versions)-1]
- s.ECHO(oldestVersion)
- versions = versions[0 : len(versions)-1]
- newVersions, err := json.Marshal(&versions)
- checkError(err)
- err = os.WriteFile("versions.json", newVersions, 0755)
+ changelog := string(changelogData)
+ // Split on the line that has `## [Unreleased]`
+ changelogSplit := strings.Split(changelog, "## [Unreleased]")
+ // Get today's date in YYYY-MM-DD format
+ today := time.Now().Format("2006-01-02")
+ // Add the new version to the top of the changelog
+ newChangelog := changelogSplit[0] + "## [Unreleased]\n\n## " + newVersion + " - " + today + changelogSplit[1]
+ // Write the changelog back
+ err = os.WriteFile("src/pages/changelog.mdx", []byte(newChangelog), 0o755)
checkError(err)
- s.ECHO("Removing old version: " + oldestVersion)
- s.CD("versioned_docs")
- s.RMDIR("version-" + oldestVersion)
- s.CD("../versioned_sidebars")
- s.RM("version-" + oldestVersion + "-sidebars.json")
- s.CD("..")
+ if !isPointRelease {
+ runCommand("npx", "-y", "pnpm", "install")
- runCommand("pnpm", "run", "build")
+ s.ECHO("Generating new Docs for version: " + newVersion)
+
+ runCommand("npx", "pnpm", "run", "docusaurus", "docs:version", newVersion)
+
+ runCommand("npx", "pnpm", "run", "write-translations")
+
+ // Load the version list/*
+ versionsData, err := os.ReadFile("versions.json")
+ checkError(err)
+ var versions []string
+ err = json.Unmarshal(versionsData, &versions)
+ checkError(err)
+ oldestVersion := versions[len(versions)-1]
+ s.ECHO(oldestVersion)
+ versions = versions[0 : len(versions)-1]
+ newVersions, err := json.Marshal(&versions)
+ checkError(err)
+ err = os.WriteFile("versions.json", newVersions, 0o755)
+ checkError(err)
+
+ s.ECHO("Removing old version: " + oldestVersion)
+ s.CD("versioned_docs")
+ s.RMDIR("version-" + oldestVersion)
+ s.CD("../versioned_sidebars")
+ s.RM("version-" + oldestVersion + "-sidebars.json")
+ s.CD("..")
+
+ runCommand("npx", "pnpm", "run", "build")
+ }
}
diff --git a/v3/scripts/validate-changelog.go b/v3/scripts/validate-changelog.go
new file mode 100644
index 000000000..659285a20
--- /dev/null
+++ b/v3/scripts/validate-changelog.go
@@ -0,0 +1,270 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ if len(os.Args) < 3 {
+ fmt.Println("Usage: go run validate-changelog.go ")
+ os.Exit(1)
+ }
+
+ changelogPath := os.Args[1]
+ addedLinesPath := os.Args[2]
+
+ // Read changelog
+ content, err := readFile(changelogPath)
+ if err != nil {
+ fmt.Printf("ERROR: Failed to read changelog: %v\n", err)
+ os.Exit(1)
+ }
+
+ // Read the lines added in this PR
+ addedContent, err := readFile(addedLinesPath)
+ if err != nil {
+ fmt.Printf("ERROR: Failed to read PR added lines: %v\n", err)
+ os.Exit(1)
+ }
+
+ addedLines := strings.Split(addedContent, "\n")
+ fmt.Printf("📝 Lines added in this PR: %d\n", len(addedLines))
+
+ // Parse changelog to find where added lines ended up
+ lines := strings.Split(content, "\n")
+
+ // Find problematic entries - only check lines that were ADDED in this PR
+ var issues []Issue
+ currentSection := ""
+
+ for lineNum, line := range lines {
+ // Track current section
+ if strings.HasPrefix(line, "## ") {
+ if strings.Contains(line, "[Unreleased]") {
+ currentSection = "Unreleased"
+ } else if strings.Contains(line, "v3.0.0-alpha") {
+ // Extract version from line like "## v3.0.0-alpha.10 - 2025-07-06"
+ parts := strings.Split(strings.TrimSpace(line[3:]), " - ")
+ if len(parts) >= 1 {
+ currentSection = strings.TrimSpace(parts[0])
+ }
+ }
+ }
+
+ // Check if this line was added in this PR AND is in a released version
+ if currentSection != "" && currentSection != "Unreleased" &&
+ strings.HasPrefix(strings.TrimSpace(line), "- ") &&
+ wasAddedInThisPR(line, addedLines) {
+
+ issues = append(issues, Issue{
+ Line: lineNum,
+ Content: strings.TrimSpace(line),
+ Section: currentSection,
+ Category: getCurrentCategory(lines, lineNum),
+ })
+ fmt.Printf("🚨 MISPLACED: Line added to released version %s: %s\n", currentSection, strings.TrimSpace(line))
+ }
+ }
+
+ if len(issues) == 0 {
+ fmt.Println("VALIDATION_RESULT=success")
+ fmt.Println("No misplaced changelog entries found ✅")
+ return
+ }
+
+ // Try to fix the issues
+ fmt.Printf("Found %d potentially misplaced entries:\n", len(issues))
+ for _, issue := range issues {
+ fmt.Printf(" - Line %d in %s: %s\n", issue.Line+1, issue.Section, issue.Content)
+ }
+
+ // Attempt automatic fix
+ fixed, err := attemptFix(content, issues, changelogPath)
+ if err != nil {
+ fmt.Printf("VALIDATION_RESULT=error\n")
+ fmt.Printf("ERROR: Failed to fix changelog: %v\n", err)
+ os.Exit(1)
+ }
+
+ if fixed {
+ fmt.Println("VALIDATION_RESULT=fixed")
+ fmt.Println("✅ Changelog has been automatically fixed")
+ } else {
+ fmt.Println("VALIDATION_RESULT=cannot_fix")
+ fmt.Println("❌ Cannot automatically fix changelog issues")
+ os.Exit(1)
+ }
+}
+
+type Issue struct {
+ Line int
+ Content string
+ Section string
+ Category string
+}
+
+func wasAddedInThisPR(line string, addedLines []string) bool {
+ trimmedLine := strings.TrimSpace(line)
+ for _, addedLine := range addedLines {
+ trimmedAdded := strings.TrimSpace(addedLine)
+ if trimmedAdded == trimmedLine {
+ return true
+ }
+ if strings.Contains(trimmedAdded, trimmedLine) && len(trimmedAdded) > 0 {
+ return true
+ }
+ }
+ return false
+}
+
+func getCurrentCategory(lines []string, lineNum int) string {
+ for i := lineNum - 1; i >= 0; i-- {
+ line := strings.TrimSpace(lines[i])
+ if strings.HasPrefix(line, "### ") {
+ return strings.TrimSpace(line[4:])
+ }
+ if strings.HasPrefix(line, "## ") &&
+ !strings.Contains(line, "[Unreleased]") &&
+ !strings.Contains(line, "v3.0.0-alpha") {
+ return strings.TrimSpace(line[3:])
+ }
+ if strings.HasPrefix(line, "## ") &&
+ (strings.Contains(line, "[Unreleased]") || strings.Contains(line, "v3.0.0-alpha")) {
+ break
+ }
+ }
+ return "Added"
+}
+
+func attemptFix(content string, issues []Issue, outputPath string) (bool, error) {
+ lines := strings.Split(content, "\n")
+
+ // Find unreleased section
+ unreleasedStart := -1
+ unreleasedEnd := -1
+
+ for i, line := range lines {
+ if strings.Contains(line, "[Unreleased]") {
+ unreleasedStart = i
+ for j := i + 1; j < len(lines); j++ {
+ if strings.HasPrefix(lines[j], "## ") && !strings.Contains(lines[j], "[Unreleased]") {
+ unreleasedEnd = j
+ break
+ }
+ }
+ break
+ }
+ }
+
+ if unreleasedStart == -1 {
+ return false, fmt.Errorf("Could not find [Unreleased] section")
+ }
+
+ // Group issues by category
+ issuesByCategory := make(map[string][]Issue)
+ for _, issue := range issues {
+ issuesByCategory[issue.Category] = append(issuesByCategory[issue.Category], issue)
+ }
+
+ // Remove issues from original locations (in reverse order)
+ var linesToRemove []int
+ for _, issue := range issues {
+ linesToRemove = append(linesToRemove, issue.Line)
+ }
+
+ // Sort in reverse order
+ for i := 0; i < len(linesToRemove); i++ {
+ for j := i + 1; j < len(linesToRemove); j++ {
+ if linesToRemove[i] < linesToRemove[j] {
+ linesToRemove[i], linesToRemove[j] = linesToRemove[j], linesToRemove[i]
+ }
+ }
+ }
+
+ // Remove lines
+ for _, lineNum := range linesToRemove {
+ lines = append(lines[:lineNum], lines[lineNum+1:]...)
+ }
+
+ // Add entries to unreleased section
+ for category, categoryIssues := range issuesByCategory {
+ categoryFound := false
+ insertPos := unreleasedStart + 1
+
+ for i := unreleasedStart + 1; i < unreleasedEnd && i < len(lines); i++ {
+ if strings.Contains(lines[i], "### "+category) || strings.Contains(lines[i], "## "+category) {
+ categoryFound = true
+ for j := i + 1; j < unreleasedEnd && j < len(lines); j++ {
+ if strings.HasPrefix(lines[j], "### ") || strings.HasPrefix(lines[j], "## ") {
+ insertPos = j
+ break
+ }
+ if j == len(lines)-1 || j == unreleasedEnd-1 {
+ insertPos = j + 1
+ break
+ }
+ }
+ break
+ }
+ }
+
+ if !categoryFound {
+ if unreleasedEnd > 0 {
+ insertPos = unreleasedEnd
+ } else {
+ insertPos = unreleasedStart + 1
+ }
+
+ newLines := []string{
+ "",
+ "### " + category,
+ "",
+ }
+ lines = append(lines[:insertPos], append(newLines, lines[insertPos:]...)...)
+ insertPos += len(newLines)
+ unreleasedEnd += len(newLines)
+ }
+
+ // Add entries to the category
+ for _, issue := range categoryIssues {
+ lines = append(lines[:insertPos], append([]string{issue.Content}, lines[insertPos:]...)...)
+ insertPos++
+ unreleasedEnd++
+ }
+ }
+
+ // Write back to file
+ newContent := strings.Join(lines, "\n")
+ return true, writeFile(outputPath, newContent)
+}
+
+func readFile(path string) (string, error) {
+ file, err := os.Open(path)
+ if err != nil {
+ return "", err
+ }
+ defer file.Close()
+
+ var content strings.Builder
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ content.WriteString(scanner.Text())
+ content.WriteString("\n")
+ }
+
+ return content.String(), scanner.Err()
+}
+
+func writeFile(path, content string) error {
+ dir := filepath.Dir(path)
+ err := os.MkdirAll(dir, 0755)
+ if err != nil {
+ return err
+ }
+
+ return os.WriteFile(path, []byte(content), 0644)
+}
\ No newline at end of file
diff --git a/website/.gitattributes b/website/.gitattributes
new file mode 100644
index 000000000..65ac44a9e
--- /dev/null
+++ b/website/.gitattributes
@@ -0,0 +1,3 @@
+# Mark all files as documentation so it gets excluded from github language statistics
+# https://github.com/github-linguist/linguist/blob/master/docs/overrides.md#documentation
+** linguist-documentation
diff --git a/website/.gitignore b/website/.gitignore
index b2d6de306..a4774bce0 100644
--- a/website/.gitignore
+++ b/website/.gitignore
@@ -6,6 +6,7 @@
# Generated files
.docusaurus
+.task
.cache-loader
# Misc
diff --git a/website/.npmrc b/website/.npmrc
deleted file mode 100644
index 3e775efb0..000000000
--- a/website/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-auto-install-peers=true
diff --git a/website/.nvmrc b/website/.nvmrc
new file mode 100644
index 000000000..741b4916e
--- /dev/null
+++ b/website/.nvmrc
@@ -0,0 +1 @@
+18.14.0
\ No newline at end of file
diff --git a/website/.prettierignore b/website/.prettierignore
new file mode 100644
index 000000000..124df96de
--- /dev/null
+++ b/website/.prettierignore
@@ -0,0 +1,2 @@
+i18n
+versioned_docs
\ No newline at end of file
diff --git a/website/Taskfile.yml b/website/Taskfile.yml
new file mode 100644
index 000000000..dbb09105d
--- /dev/null
+++ b/website/Taskfile.yml
@@ -0,0 +1,55 @@
+# https://taskfile.dev
+
+version: "3"
+
+tasks:
+ install:
+ desc: Install Dependencies
+ aliases: [i]
+ cmds:
+ - corepack enable
+ - corepack prepare pnpm@8.3.1 --activate
+ - pnpm install
+ sources:
+ - package.json
+ - pnpm-lock.yaml
+
+ default:
+ desc: Start Website
+ deps: [install]
+ aliases: [s, start]
+ cmds:
+ - npx docusaurus start
+
+ build:
+ desc: Build Website
+ deps: [install]
+ cmds:
+ - npx docusaurus build
+
+ preview:
+ desc: Preview Website
+ deps: [build]
+ aliases: [serve]
+ cmds:
+ - npx docusaurus serve
+
+ crowdin:push:
+ desc: Upload source files to Crowdin
+ deps: [install]
+ cmds:
+ - npx crowdin push -b v2
+
+ crowdin:pull:
+ desc: Download approved translation files from Crowdin to local
+ deps: [install]
+ cmds:
+ - npx crowdin pull -b v2 --export-only-approved
+
+ format:md:
+ cmds:
+ - npx prettier --write "**/*.{md,mdx}"
+
+ format:
+ cmds:
+ - task: format:md
diff --git a/website/blog/2025-03-16-security-incident-response.mdx b/website/blog/2025-03-16-security-incident-response.mdx
new file mode 100644
index 000000000..e9903c570
--- /dev/null
+++ b/website/blog/2025-03-16-security-incident-response.mdx
@@ -0,0 +1,89 @@
+---
+slug: security-incident-response-march-2025
+title: Proactive Security Response - GitHub Actions Supply Chain Attack
+authors: [leaanthony]
+tags: [wails, security]
+---
+
+
+
+
+
+
+:::note TL;DR
+**Good news! Wails was NOT affected by this security incident.** Our thorough investigation confirmed that no secrets were leaked, and the Wails codebase and releases remain completely secure. We've already taken proactive measures to further strengthen our security posture.
+:::
+
+## Introduction
+
+On 15th March 2025 (AEST), the Wails team was alerted to a security incident involving the `tj-actions/changed-files` GitHub Action. This widely-used action (with over 23,000 repositories depending on it) was compromised in a supply chain attack. While this action was used in some of our CI/CD workflows, we're pleased to confirm that Wails remained fully protected throughout.
+
+This post shares the details of the incident, our response, and the additional safeguards we've implemented to ensure the continued security of the Wails project.
+
+## Incident Details
+
+The security company StepSecurity [reported](https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised) that the `tj-actions/changed-files` GitHub Action was compromised beginning around 9:00 AM March 14th, 2025 Pacific Time (4:00 PM UTC).
+
+In this attack, malicious code was injected into the action that attempted to dump CI/CD secrets from GitHub Actions runner processes into public logs. The attackers modified the action's code and retroactively updated multiple version tags to reference the malicious commit.
+
+## Our Proactive Assessment
+
+Upon learning this, we immediately launched a comprehensive assessment of our systems:
+
+1. We identified the following Wails workflows that were using the action:
+ - For Wails v2: `pr-v2.yml` and `upload-source-documents.yml`
+ - For Wails v3: `pr-v3.yml`, `publish-npm.yml`, and `upload-source-documents.yml`
+
+2. Our security team conducted a thorough review of all workflow logs for the affected actions during the time period of the compromise.
+
+3. We're happy to confirm that **no secrets were leaked** in any of our workflow logs, and the Wails codebase remained completely secure.
+
+## Action Taken
+
+We took immediate steps to address this situation:
+
+1. We swiftly replaced all instances of the affected `tj-actions/changed-files` action with the secure alternative `step-security/changed-files` provided by StepSecurity.
+
+2. As an extra precautionary measure, we temporarily removed all secrets from our GitHub Actions workflows.
+
+## What This Means for You
+
+We want to reassure our community that:
+
+1. The Wails codebase was never compromised in any way.
+2. No malicious code was introduced into any Wails releases.
+3. This situation only potentially affected our CI/CD pipeline, not the actual Wails source code or releases.
+4. No sensitive information or secrets were exposed during this time.
+
+**In short: All Wails releases remain secure and trustworthy, and no action is required on your part.**
+
+## Strengthening Our Security Posture
+
+To minimise exposure to similar potential incidents in the future, we're enhancing our security practices by:
+
+1. Implementing stricter version pinning for all third-party actions used in our workflows, preferably pinning to specific commit hashes rather than version tags.
+
+2. Establishing a regular security review process for our CI/CD pipelines and dependencies.
+
+3. Exploring the use of additional security tools like StepSecurity's Harden-Runner to provide enhanced protection for our GitHub Actions workflows.
+
+4. Developing a more comprehensive security incident response plan to ensure we can respond quickly and effectively to any future security concerns.
+
+It's worth noting that the Wails project already employs several security tools as part of our development process:
+
+- **Semgrep**: We use Semgrep for static code analysis to identify potential security vulnerabilities and code quality issues.
+- **Snyk**: We employ Snyk to continuously monitor our dependencies for known vulnerabilities and receive alerts when security patches are needed.
+
+These existing security measures, combined with our enhanced preventative steps, demonstrate our ongoing commitment to maintaining the security and integrity of the Wails project.
+
+## Moving Forward
+
+The security of the Wails project and the trust of our community are our highest priorities. We remain committed to transparency and will continue to promptly address any security concerns that arise.
+
+We would like to thank StepSecurity for their quick response in identifying this issue and providing a secure alternative action.
+
+If you have any questions or concerns about this, please don't hesitate to reach out to us on [GitHub](https://github.com/wailsapp/wails) or [Discord](https://discord.gg/JDdSxwjhGf). We're always here to help.
diff --git a/website/bun.lockb b/website/bun.lockb
new file mode 100644
index 000000000..63ed1b159
Binary files /dev/null and b/website/bun.lockb differ
diff --git a/website/crowdin.yml b/website/crowdin.yml
index 51b6968e0..d04258c22 100644
--- a/website/crowdin.yml
+++ b/website/crowdin.yml
@@ -1,4 +1,4 @@
-project_id: 531392
+project_id: "531392"
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
commit_message: "[ci skip]"
diff --git a/website/docs/community/links.mdx b/website/docs/community/links.mdx
index cd2f2cb38..fe8b51dd0 100644
--- a/website/docs/community/links.mdx
+++ b/website/docs/community/links.mdx
@@ -23,4 +23,5 @@ The [definitive list](https://github.com/wailsapp/awesome-wails) of links relate
- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Group number: 1067173054
## Other Tutorials and Articles
+
- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board)
diff --git a/website/docs/community/showcase/bulletinboard.mdx b/website/docs/community/showcase/bulletinboard.mdx
new file mode 100644
index 000000000..37be75135
--- /dev/null
+++ b/website/docs/community/showcase/bulletinboard.mdx
@@ -0,0 +1,10 @@
+# BulletinBoard
+
+```mdx-code-block
+
+
+
+
+```
+
+The [BulletinBoard](https://github.com/raguay/BulletinBoard) application is a versital message board for static messages or dialogs to get information from the user for a script. It has a TUI for creating new dialogs that can latter be used to get information from the user. It's design is to stay running on your system and show the information as needed and then hide away. I have a process for watching a file on my system and sending the contents to BulletinBoard when changed. It works great with my workflows. There is also an [Alfred workflow](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) for sending information to the program. The workflow is also for working with [EmailIt](https://github.com/raguay/EmailIt).
diff --git a/website/docs/community/showcase/cfntracker.mdx b/website/docs/community/showcase/cfntracker.mdx
new file mode 100644
index 000000000..8fab23b75
--- /dev/null
+++ b/website/docs/community/showcase/cfntracker.mdx
@@ -0,0 +1,39 @@
+# CFN Tracker
+
+```mdx-code-block
+
+
+
+
+```
+
+[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street
+Fighter 6 or V CFN profile's live matches. Check
+[the website](https://cfn.williamsjokvist.se/) to get started.
+
+## Features
+
+- Real-time match tracking
+- Storing match logs and statistics
+- Support for displaying live stats to OBS via Browser Source
+- Support for both SF6 and SFV
+- Ability for users to create their own OBS Browser themes with CSS
+
+### Major tech used alongside Wails
+
+- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make
+ common commands easy to use
+- [React](https://github.com/facebook/react) - chosen for its rich ecosystem
+ (radix, framer-motion)
+- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency
+ resolution and build-time
+- [Rod](https://github.com/go-rod/rod) - headless browser automation for
+ authentication and polling changes
+- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches,
+ sessions and profiles
+- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) -
+ a http stream to send tracking updates to OBS browser sources
+- [i18next](https://github.com/i18next/) - with backend connector to serve
+ localization objects from the Go layer
+- [xstate](https://github.com/statelyai/xstate) - state machines for auth
+ process and tracking
diff --git a/website/docs/community/showcase/clustta.mdx b/website/docs/community/showcase/clustta.mdx
new file mode 100644
index 000000000..7da3195df
--- /dev/null
+++ b/website/docs/community/showcase/clustta.mdx
@@ -0,0 +1,27 @@
+---
+title: Clustta
+description: File manager and project management tool for creative professionals.
+slug: /community/showcase/clustta
+image: /img/showcase/clustta.png
+---
+
+
+
+
+
+[Clustta](https://clustta.com) is a file manager and project management tool designed for creative professionals. Built with Wails, it simplifies file management, collaboration, and version control for creative workflows.
+
+## Features
+
+- **File Management**: Track all projects and files with easy access even months after completion.
+- **Version Control**: Save unlimited revisions with descriptive notes, without duplicating files.
+- **Collaboration**: Share files or entire projects securely through simple user tags with fine-grained permissions.
+- **Recovery**: Restore corrupted files from saved checkpoints if your software crashes.
+- **Templates**: Quick start with preset project and task templates.
+- **Kanban Boards**: Visual task tracking to keep tasks organized.
+- **Dependencies**: Track and version project resources and dependencies.
+- **Checkpoints**: Create memorable milestones and explore alternate creative directions non-destructively.
+- **Search & Filters**: Powerful instant search with metadata filtering (task types, tags, status, file extensions).
+- **Workspaces**: Save search and filter combinations for easy access to specific task sets.
+- **Integrations**: Connect with creative software packages and production management tools like Blender and Kitsu.
+- **Self-Hosting**: Host private instances for teams or studios on your own servers.
diff --git a/website/docs/community/showcase/emailit.mdx b/website/docs/community/showcase/emailit.mdx
index 04150ba28..c1817b70f 100644
--- a/website/docs/community/showcase/emailit.mdx
+++ b/website/docs/community/showcase/emailit.mdx
@@ -7,4 +7,4 @@
```
-[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a markdown based email sender only with nine notepads, scripts to manipulate the text, and templates. It also has a builtin [Node-Red](https://nodered.org/) server, scripts terminal, and the [ScriptBar](https://github.com/raguay/ScriptBarApp) program for displaying results from Node-Red or a script on your system. Documentation is very scarce, but the programs works. It’s built using Wails2 and Svelte, and the download is a universal macOS application.
+[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a markdown based email sender only with nine notepads, scripts to manipulate the text, and templates. It also has a scripts terminal to run scripts in EmailIt on files in your system. The scripts and templates can be used from the commandline itself or with the Alfred, Keyboard Maestro, Dropzone, or PopClip extensions. It also supports scripts and themes downloaded form GitHub. Documentation is not complete, but the programs works. It’s built using Wails2 and Svelte, and the download is a universal macOS application.
diff --git a/website/docs/community/showcase/espstudio.mdx b/website/docs/community/showcase/espstudio.mdx
new file mode 100644
index 000000000..44db858f9
--- /dev/null
+++ b/website/docs/community/showcase/espstudio.mdx
@@ -0,0 +1,13 @@
+# ESP Studio
+
+```mdx-code-block
+
+
+
+
+```
+
+[ESP Studio](https://github.com/torabian/esp-studio) - Cross platform, Desktop, Cloud, and Embedded software
+for controlling ESP/Arduino devices, and building complex IOT workflows and control systems
diff --git a/website/docs/community/showcase/gamestacker.mdx b/website/docs/community/showcase/gamestacker.mdx
new file mode 100644
index 000000000..46245e146
--- /dev/null
+++ b/website/docs/community/showcase/gamestacker.mdx
@@ -0,0 +1,19 @@
+---
+title: GameStacker
+description: A modern, console-like interface that unifies your game libraries.
+slug: /community/showcase/gamestacker
+image: /img/showcase/gamestacker.webp
+---
+
+
+
+
+
+[GameStacker](https://gamestacker.io) is a modern, elegant console-like interface that unifies your entire game collection into one beautiful dashboard.
+
+## Features
+
+- **Unified Library**: Automatically detects and imports games from external libraries (such as Steam, LaunchBox, and RetroBat), bringing your modern and retro collections into a single, cohesive interface.
+- **True Console Experience**: Built for controllers with responsive navigation, UI sound effects, and a dedicated in-game "Guide" overlay to control music and manage your session without alt-tabbing.
+- **Achievement Integration**: Tracks your progress across supported services, allowing you to view unlocks and Gamerscore directly from the dashboard.
+- **Multi-Profile Support**: Create unique profiles with custom avatars and specific color themes for a personalized experience.
diff --git a/website/docs/community/showcase/grpcmd-gui.mdx b/website/docs/community/showcase/grpcmd-gui.mdx
new file mode 100644
index 000000000..891350290
--- /dev/null
+++ b/website/docs/community/showcase/grpcmd-gui.mdx
@@ -0,0 +1,10 @@
+# grpcmd-gui
+
+```mdx-code-block
+
+
+
+
+```
+
+[grpcmd-gui](https://grpc.md/gui) is a modern cross-platform desktop app and API client for gRPC development and testing.
diff --git a/website/docs/community/showcase/hiposter.mdx b/website/docs/community/showcase/hiposter.mdx
new file mode 100644
index 000000000..c0f9052c3
--- /dev/null
+++ b/website/docs/community/showcase/hiposter.mdx
@@ -0,0 +1,10 @@
+# hiposter
+
+```mdx-code-block
+
+
+
+
+```
+
+[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API testing client tool. Based on Wails, Go and sveltejs.
\ No newline at end of file
diff --git a/website/docs/community/showcase/kafka-king.mdx b/website/docs/community/showcase/kafka-king.mdx
new file mode 100644
index 000000000..0ba78a6ad
--- /dev/null
+++ b/website/docs/community/showcase/kafka-king.mdx
@@ -0,0 +1,22 @@
+# Kafka-King
+
+```mdx-code-block
+
+
+
+
+```
+
+[Kafka-King](https://github.com/Bronya0/Kafka-King) is a kafka GUI client that supports various systems and is compact and easy to use.
+This is made of Wails+vue3
+
+# Kafka-King function list
+- [x] View the cluster node list, support dynamic configuration of broker and topic configuration items
+- [x] Supports consumer clients, consumes the specified topic, size, and timeout according to the specified group, and displays the message information in various dimensions in a table
+- [x] Supports PLAIN, SSL, SASL, kerberos, sasl_plaintext, etc. etc.
+- [x] Create topics (support batches), delete topics, specify replicas, partitions
+- [x] Support statistics of the total number of messages, total number of submissions, and backlog for each topic based on consumer groups
+- [x] Support viewing topics Detailed information (offset) of the partition, and support adding additional partitions
+- [x] Support simulated producers, batch sending messages, specify headers, partitions
+- [x] Health check
+- [x] Support viewing consumer groups , Consumer- ……
diff --git a/website/docs/community/showcase/marasi.mdx b/website/docs/community/showcase/marasi.mdx
new file mode 100644
index 000000000..5ff137523
--- /dev/null
+++ b/website/docs/community/showcase/marasi.mdx
@@ -0,0 +1,22 @@
+# Marasi
+
+```mdx-code-block
+
+
+
+
+```
+
+[Marasi](https://marasi.app/) is an open source application security testing proxy, it lets you intercept, inspect, modify, and extend requests as they flow through your applications. Read more about it on the [blog](https://marasi.app/blog/2025/introducing_marasi/).
+
+## Features
+
+- Desktop GUI Interface: Cross-platform desktop application built with Wails
+- HTTP/HTTPS Proxy: TLS-capable proxy server with certificate management
+- Request/Response Interception: Modify traffic in real-time with an intuitive interface
+- Lua Extensions: Scriptable proxy behavior with built-in extensions
+- Project Management: SQLite-based storage for all proxy data (requests, responses, metadata)
+- Launchpad: Replay and modify HTTP requests
+- Scope Management: Filter traffic with inclusion/exclusion rules
+- Waypoints: Override hostnames for request routing
+- Chrome Integration: Auto-configure Chrome with proxy settings
\ No newline at end of file
diff --git a/website/docs/community/showcase/mchat.mdx b/website/docs/community/showcase/mchat.mdx
new file mode 100644
index 000000000..aa535a6f8
--- /dev/null
+++ b/website/docs/community/showcase/mchat.mdx
@@ -0,0 +1,10 @@
+# Mchat
+
+```mdx-code-block
+
+
+
+
+```
+
+[Official page](https://marcio199226.github.io/mchat-site/public/) Fully anonymous end2end encrypted chat.
diff --git a/website/docs/community/showcase/minesweeper-xp.mdx b/website/docs/community/showcase/minesweeper-xp.mdx
new file mode 100644
index 000000000..f127a005f
--- /dev/null
+++ b/website/docs/community/showcase/minesweeper-xp.mdx
@@ -0,0 +1,10 @@
+# Minesweeper XP
+
+```mdx-code-block
+
+
+
+
+```
+
+[Minesweeper-XP](https://git.new/Minesweeper-XP) allows you to experience the classic Minesweeper XP (+ 98 and 3.1) on macOS, Windows, and Linux!
diff --git a/website/docs/community/showcase/modalfilemanager.mdx b/website/docs/community/showcase/modalfilemanager.mdx
index f8e2bcd66..bcd212396 100644
--- a/website/docs/community/showcase/modalfilemanager.mdx
+++ b/website/docs/community/showcase/modalfilemanager.mdx
@@ -9,6 +9,6 @@
```
-[Modal File Manager](https://github.com/raguay/ModalFileManager) is a dual pane file manager using web technologies. My original design was based on NW.js and can be found [here](https://github.com/raguay/ModalFileManager-NWjs). This version uses the same Svelte based frontend code (but it has be greatly modified since the departure from NW.js), but the backend is a [Wails 2](https://wails.io/) implementation. By using this implementation, I no longer use command line `rm`, `cp`, etc. commands. It is fully coded using Go and runs much faster than the previous versions.
+[Modal File Manager](https://github.com/raguay/ModalFileManager) is a dual pane file manager using web technologies. My original design was based on NW.js and can be found [here](https://github.com/raguay/ModalFileManager-NWjs). This version uses the same Svelte based frontend code (but it has be greatly modified since the departure from NW.js), but the backend is a [Wails 2](https://wails.io/) implementation. By using this implementation, I no longer use command line `rm`, `cp`, etc. commands, but a git install has to be on the system to download themes and extensions. It is fully coded using Go and runs much faster than the previous versions.
-This file manager is designed around the same principle as Vim: a state controlled keyboard actions. The number of states isn't fixed, but very programmable. Therefore, an infinite number of keyboard configurations can be created and used. This is the main difference from other file managers.
+This file manager is designed around the same principle as Vim: a state controlled keyboard actions. The number of states isn't fixed, but very programmable. Therefore, an infinite number of keyboard configurations can be created and used. This is the main difference from other file managers. There are themes and extensions available to download from GitHub.
diff --git a/website/docs/community/showcase/resizem.mdx b/website/docs/community/showcase/resizem.mdx
new file mode 100644
index 000000000..27f168f48
--- /dev/null
+++ b/website/docs/community/showcase/resizem.mdx
@@ -0,0 +1,10 @@
+# Resizem
+
+```mdx-code-block
+
+
+
+
+```
+
+[Resizem](https://github.com/barats/resizem) - is an app designed for bulk image process. It is particularly useful for users who need to resize, convert, and manage large numbers of image files at once.
diff --git a/website/docs/community/showcase/scriptbar.mdx b/website/docs/community/showcase/scriptbar.mdx
index 2ccb2acb4..3e41eb32a 100644
--- a/website/docs/community/showcase/scriptbar.mdx
+++ b/website/docs/community/showcase/scriptbar.mdx
@@ -7,4 +7,4 @@
```
-[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the output of the embedded [Node-Red](https://nodered.org) server in the [EmailIt](https://GitHub.com/raguay/EmailIt) application. It also displays the output of scripts on your system. ScriptBar doesn't put them in the menubar, but has them all in a convient window for easy viewing. You can have multiple tabs to have many different things show. You can also keep the links to your most visited web sites.
+[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the output of scripts or [Node-Red](https://nodered.org) server. It runs scripts defined in EmailIt program and shows the output. Scripts from xBar or TextBar can be used, but currently on the TextBar scripts work well. It also displays the output of scripts on your system. ScriptBar doesn't put them in the menubar, but has them all in a convient window for easy viewing. You can have multiple tabs to have many different things show. You can also keep the links to your most visited web sites.
diff --git a/website/docs/community/showcase/snippetexpander.mdx b/website/docs/community/showcase/snippetexpander.mdx
new file mode 100644
index 000000000..1f9fb6157
--- /dev/null
+++ b/website/docs/community/showcase/snippetexpander.mdx
@@ -0,0 +1,27 @@
+# Snippet Expander
+
+```mdx-code-block
+
+
+
+ Screenshot of Snippet Expander's Select Snippet window
+
+
+
+
+ Screenshot of Snippet Expander's Add Snippet screen
+
+
+
+
+ Screenshot of Snippet Expander's Search & Paste window
+
+```
+
+[Snippet Expander](https://snippetexpander.org) is "Your little expandable text snippets helper", for Linux.
+
+Snippet Expander comprises of a GUI application built with Wails for managing snippets and settings, with a Search & Paste window mode for quickly selecting and pasting a snippet.
+
+The Wails based GUI, go-lang CLI and vala-lang auto expander daemon all communicate with a go-lang daemon via D-Bus. The daemon does the majority of the work, managing the database of snippets and common settings, and providing services for expanding and pasting snippets etc.
+
+Check out the [source code](https://git.sr.ht/~ianmjones/snippetexpander/tree/trunk/item/cmd/snippetexpandergui/app.go#L38) to see how the Wails app sends messages from the UI to the backend that are then sent to the daemon, and subscribes to a D-Bus event to monitor changes to snippets via another instance of the app or CLI and show them instantly in the UI via a Wails event.
diff --git a/website/docs/community/showcase/tinyrdm.mdx b/website/docs/community/showcase/tinyrdm.mdx
new file mode 100644
index 000000000..e3124bab7
--- /dev/null
+++ b/website/docs/community/showcase/tinyrdm.mdx
@@ -0,0 +1,11 @@
+# Tiny RDM
+
+```mdx-code-block
+
+
+
+
+
+```
+
+The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more.
diff --git a/website/docs/community/showcase/upbeat.mdx b/website/docs/community/showcase/upbeat.mdx
new file mode 100644
index 000000000..2f85b6cce
--- /dev/null
+++ b/website/docs/community/showcase/upbeat.mdx
@@ -0,0 +1,18 @@
+---
+title: UpBeat
+description: An RSS/Atom Feed Reader that filters out negative news with locally run ML models.
+slug: /community/showcase/upbeat
+image: /img/showcase/upbeat.png
+---
+
+
+
+
+
+[UpBeat](https://upbeat.mitchelltechnologies.co.uk) is An RSS/Atom Feed Reader for macOS that filters out negative news with locally running ML models.
+
+## Features
+
+- **Local ML**: UpBeat runs a transformer-based sentiment analysis model directly on your Mac's hardware. No waiting for a Cloud GPU to spin up before you can decide what you want to read
+- **Apple Neural Engine Enabled**: UpBeat runs its ML models directly on the Neural Engine of Macs. That means you get super-fast inference, but without burning through your battery or electricity bill.
+- **Widely Compatible**: Works with the vast majority of RSS + Atom versions.
diff --git a/website/docs/community/showcase/wailsterm.mdx b/website/docs/community/showcase/wailsterm.mdx
new file mode 100644
index 000000000..9924dace5
--- /dev/null
+++ b/website/docs/community/showcase/wailsterm.mdx
@@ -0,0 +1,10 @@
+# WailsTerm
+
+```mdx-code-block
+
+
+
+
+```
+
+[WailsTerm](https://github.com/rlshukhov/wailsterm) is a simple translucent terminal app powered by Wails and Xterm.js.
diff --git a/website/docs/community/templates.mdx b/website/docs/community/templates.mdx
index eef7f6fa0..3b020b60b 100644
--- a/website/docs/community/templates.mdx
+++ b/website/docs/community/templates.mdx
@@ -24,14 +24,15 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
## Vue
- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails template based on Vue ecology (Integrated TypeScript, Dark theme, Internationalization, Single page routing, TailwindCSS)
-- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript with Vite (and instructions to add features)
-- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript with Vite, Vuex, Vue Router, Sass, and ESLint + Prettier
- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier)
- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>)
- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library)
+- [wails-template-primevue-sakai](https://github.com/TekWizely/wails-template-primevue-sakai) - Wails starter using [PrimeVue's Sakai Application Template](https://sakai.primevue.org) (Vite, Vue, PrimeVue, TailwindCSS, Vue Router, Themes, Dark Mode, UI Components, and more)
+- [wails-template-tdesign-js](https://github.com/tongque0/wails-template-tdesign-js) - Wails template based on TDesign UI (a Vue 3 UI library by Tencent), using Vite, Pinia, Vue Router, ESLint, and Prettier.
## Angular
+- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ action packed & ready to roll to production.
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n
## React
@@ -39,20 +40,43 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
+- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router
- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS
+- [Wails-vite-ts-tailwindcss-shadcn-template-2025](https://github.com/darkb0ts/Wails-vite-ts-tailwindcss-shadcn-template-2025) - A template for React + TypeScript + Vite
+- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui
+- [wails-nextjs-tailwind-template](https://github.com/kairo913/wails-nextjs-tailwind-template) - A template using Next.js and Typescript with TailwindCSS
## Svelte
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte
- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite
+- [wails-vite-svelte-ts-tailwind-template](https://github.com/xvertile/wails-vite-svelte-tailwind-template) - A template using Wails, Svelte, Vite, TypeScript, and TailwindCSS v3
- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3
+- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3
- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit
+- [wails-template-sveltekit-less-prettier-eslint](https://github.com/Alex6357/wails-template-sveltekit-less-prettier-eslint) - A template using SvelteKit with less, Prettier and ESlint
+- [wails-template-svelte-ts-less-prettier-eslint-vite](https://github.com/Alex6357/wails-template-svelte-ts-less-prettier-eslint-vite) - A template using Svelte5 + TypeScript + less + Prettier + ESlint + Vite
+
+## Solid
+
+- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - A template using Solid + Ts + Vite
+- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - A template using Solid + Js + Vite
## Elm
- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket:
- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported.
+## HTMX
+
+- [wails-htmx-tailwind-daisyui-template](https://github.com/ltcovalt/wails-htmx-tailwind-daisyui-template) - HTMX template using Tailwind CSS + daisyUI for styling and the Go standard library for routing and HTML templating
+- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms
+
## Pure JavaScript (Vanilla)
- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS
+
+
+## Lit (web components)
+
+- [wails-lit-shoelace-esbuild-template](https://github.com/Braincompiler/wails-lit-shoelace-esbuild-template) - Wails template providing frontend with lit, Shoelace component library + pre-configured prettier and typescript.
diff --git a/website/docs/gettingstarted/building.mdx b/website/docs/gettingstarted/building.mdx
index 2668b19da..c4c16ea48 100644
--- a/website/docs/gettingstarted/building.mdx
+++ b/website/docs/gettingstarted/building.mdx
@@ -7,6 +7,10 @@ sidebar_position: 6
From the project directory, run `wails build`.
This will compile your project and save the production-ready binary in the `build/bin` directory.
+:::info Linux
+If you are using a Linux distribution that does not have webkit2gtk-4.0 (such as Ubuntu 24.04), you will need to add `-tags webkit2_41`.
+:::
+
If you run the binary, you should see the default application:
```mdx-code-block
diff --git a/website/docs/gettingstarted/firstproject.mdx b/website/docs/gettingstarted/firstproject.mdx
index e8880660d..5cf4dff58 100644
--- a/website/docs/gettingstarted/firstproject.mdx
+++ b/website/docs/gettingstarted/firstproject.mdx
@@ -128,5 +128,3 @@ The `frontend` directory has nothing specific to Wails and can be any frontend p
The `build` directory is used during the build process. These files may be updated to customise your builds. If
files are removed from the build directory, default versions will be regenerated.
-
-The default module name in `go.mod` is "changeme". You should change this to something more appropriate.
diff --git a/website/docs/gettingstarted/installation.mdx b/website/docs/gettingstarted/installation.mdx
index 0e4bd0a50..6189c6d83 100644
--- a/website/docs/gettingstarted/installation.mdx
+++ b/website/docs/gettingstarted/installation.mdx
@@ -7,7 +7,7 @@ sidebar_position: 1
## Supported Platforms
- Windows 10/11 AMD64/ARM64
-- MacOS 10.13+ AMD64
+- MacOS 10.15+ AMD64 for development, MacOS 10.13+ for release
- MacOS 11.0+ ARM64
- Linux AMD64/ARM64
@@ -15,7 +15,7 @@ sidebar_position: 1
Wails has a number of common dependencies that are required before installation:
-- Go 1.18+
+- Go 1.21+ (macOS 15+ requires Go 1.23.3+)
- NPM (Node 15+)
### Go
@@ -57,7 +57,15 @@ import TabItem from "@theme/TabItem";
Wails requires that the WebView2 runtime is installed. Some Windows installations will already have this installed. You can check using the wails doctor command.
- Linux required the standard gcc build tools plus libgtk3 and libwebkit. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run wails doctor after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the Add Linux Distro guide.
+ Linux requires the standard gcc build tools plus libgtk3 and libwebkit. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run wails doctor after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the Add Linux Distro guide.
+ Note:
+ If you are using latest Linux version (example: Ubuntu 24.04) and it is not supporting libwebkit2gtk-4.0-dev, then you might encounter an issue in wails doctor: libwebkit not found. To resolve this issue you can install libwebkit2gtk-4.1-dev and during your build use the tag -tags webkit2_41.
+
+ After installing Wails via Go, ensure you run the following commands to update your PATH:
+
+ export PATH=$PATH:$(go env GOPATH)/bin
+
+ source ~/.bashrc or source ~/.zshrc
```
@@ -76,7 +84,9 @@ Note: If you get an error similar to this:
```shell
....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found
```
+
please check you have Go 1.18+ installed:
+
```shell
go version
```
diff --git a/website/docs/guides/application-development.mdx b/website/docs/guides/application-development.mdx
index f8074d150..adefa4b04 100644
--- a/website/docs/guides/application-development.mdx
+++ b/website/docs/guides/application-development.mdx
@@ -10,6 +10,10 @@ The pattern used by the default templates are that `main.go` is used for configu
The `app.go` file will define a struct that has 2 methods which act as hooks into the main application:
```go title="app.go"
+import (
+ "context"
+)
+
type App struct {
ctx context.Context
}
@@ -28,7 +32,7 @@ func (a *App) shutdown(ctx context.Context) {
- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources,
setting up event listeners and anything else the application needs at startup.
- It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the
+ It is given a [`context.Context`](https://pkg.go.dev/context) which is usually saved in a struct field. This context is needed for calling the
[runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate.
In dev mode, the error will be output to the console.
@@ -55,7 +59,6 @@ func main() {
log.Fatal(err)
}
}
-
```
More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks).
@@ -65,7 +68,12 @@ More information on application lifecycle hooks can be found [here](../howdoesit
It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to
the already defined struct in `app.go`:
-```go {16-18} title="app.go"
+```go {3,21-23} title="app.go"
+import (
+ "context"
+ "fmt"
+)
+
type App struct {
ctx context.Context
}
@@ -82,7 +90,7 @@ func (a *App) shutdown(ctx context.Context) {
}
func (a *App) Greet(name string) string {
- return fmt.Sprintf("Hello %s!", name)
+ return fmt.Sprintf("Hello %s!", name)
}
```
@@ -99,15 +107,14 @@ func main() {
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
- Bind: []interface{}{
- app,
- },
+ Bind: []interface{}{
+ app,
+ },
})
if err != nil {
log.Fatal(err)
}
}
-
```
This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods).
@@ -133,10 +140,10 @@ func main() {
otherStruct.SetContext(ctx)
},
OnShutdown: app.shutdown,
- Bind: []interface{}{
- app,
+ Bind: []interface{}{
+ app,
otherStruct
- },
+ },
})
if err != nil {
log.Fatal(err)
@@ -144,6 +151,64 @@ func main() {
}
```
+Also you might want to use Enums in your structs and have models for them on frontend.
+In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app:
+
+```go {16-18} title="app.go"
+type Weekday string
+
+const (
+ Sunday Weekday = "Sunday"
+ Monday Weekday = "Monday"
+ Tuesday Weekday = "Tuesday"
+ Wednesday Weekday = "Wednesday"
+ Thursday Weekday = "Thursday"
+ Friday Weekday = "Friday"
+ Saturday Weekday = "Saturday"
+)
+
+var AllWeekdays = []struct {
+ Value Weekday
+ TSName string
+}{
+ {Sunday, "SUNDAY"},
+ {Monday, "MONDAY"},
+ {Tuesday, "TUESDAY"},
+ {Wednesday, "WEDNESDAY"},
+ {Thursday, "THURSDAY"},
+ {Friday, "FRIDAY"},
+ {Saturday, "SATURDAY"},
+}
+```
+
+In the main application configuration, the `EnumBind` key is where we can tell Wails what we want to bind enums as well:
+
+```go {11-13} title="main.go"
+func main() {
+
+ app := NewApp()
+
+ err := wails.Run(&options.App{
+ Title: "My App",
+ Width: 800,
+ Height: 600,
+ OnStartup: app.startup,
+ OnShutdown: app.shutdown,
+ Bind: []interface{}{
+ app,
+ },
+ EnumBind: []interface{}{
+ AllWeekdays,
+ },
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+This will add missing enums to your `model.ts` file.
+
More information on Binding can be found [here](../howdoesitwork.mdx#method-binding).
## Application Menu
@@ -164,15 +229,14 @@ func main() {
OnStartup: app.startup,
OnShutdown: app.shutdown,
Menu: app.menu(),
- Bind: []interface{}{
- app,
- },
+ Bind: []interface{}{
+ app,
+ },
})
if err != nil {
log.Fatal(err)
}
}
-
```
## Assets
@@ -199,7 +263,7 @@ create files on the fly or process POST/PUT requests.
GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be
forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler`
if specified.
-It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option.
+It's also possible to only use the `AssetsHandler` by specifying `nil` as the `Assets` option.
## Built in Dev Server
@@ -219,8 +283,33 @@ be saved to your project config and become the default.
Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails
Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which
Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/).
-For [create-react-app](https://create-react-app.dev/), it's possible to use
-[this script](https://gist.github.com/int128/e0cdec598c5b3db728ff35758abdbafd) to achieve a similar result.
+
+### Create React App
+
+The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration
+needs to be added to your `wails.json`:
+
+```json
+ "frontend:dev:watcher": "yarn start",
+ "frontend:dev:serverUrl": "http://localhost:3000",
+```
+
+The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then
+instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the
+`index.html` needs to be updated with the following:
+
+```html
+
+
+
+
+
+```
+
+This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring
+the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled.
+Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward
+debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step.
## Go Module
diff --git a/website/docs/guides/crossplatform-build.mdx b/website/docs/guides/crossplatform-build.mdx
new file mode 100644
index 000000000..f6fbc0f06
--- /dev/null
+++ b/website/docs/guides/crossplatform-build.mdx
@@ -0,0 +1,65 @@
+# Crossplatform build with Github Actions
+
+To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions.
+
+An action that facilitates building a Wails app is available at:
+https://github.com/dAppServer/wails-build-action
+
+In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source:
+https://github.com/dAppServer/wails-build-action/blob/main/action.yml
+
+Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts:
+
+```yaml
+name: Wails build
+
+on:
+ push:
+ tags:
+ # Match any new tag
+ - '*'
+
+env:
+ # Necessary for most environments as build failure can occur due to OOM issues
+ NODE_OPTIONS: "--max-old-space-size=4096"
+
+jobs:
+ build:
+ strategy:
+ # Failure in one platform build won't impact the others
+ fail-fast: false
+ matrix:
+ build:
+ - name: 'App'
+ platform: 'linux/amd64'
+ os: 'ubuntu-latest'
+ - name: 'App'
+ platform: 'windows/amd64'
+ os: 'windows-latest'
+ - name: 'App'
+ platform: 'darwin/universal'
+ os: 'macos-latest'
+
+ runs-on: ${{ matrix.build.os }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: recursive
+
+ - name: Build wails
+ uses: dAppServer/wails-build-action@v2.2
+ id: build
+ with:
+ build-name: ${{ matrix.build.name }}
+ build-platform: ${{ matrix.build.platform }}
+ package: false
+ go-version: '1.20'
+```
+
+This example offers opportunities for various enhancements, including:
+- Caching dependencies
+- Code signing
+- Uploading to platforms like S3, Supabase, etc.
+- Injecting secrets as environment variables
+- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag)
diff --git a/website/docs/guides/custom-protocol-schemes.mdx b/website/docs/guides/custom-protocol-schemes.mdx
new file mode 100644
index 000000000..216fb7100
--- /dev/null
+++ b/website/docs/guides/custom-protocol-schemes.mdx
@@ -0,0 +1,207 @@
+# Custom Protocol Scheme association
+
+Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol,
+your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app.
+In this guide, we'll walk through the steps to implement custom protocols in Wails app.
+
+
+## Set Up Custom Protocol Schemes Association:
+To set up custom protocol, you need to modify your application's wails.json file.
+In "info" section add a "protocols" section specifying the protocols your app should be associated with.
+
+For example:
+```json
+{
+ "info": {
+ "protocols": [
+ {
+ "scheme": "myapp",
+ "description": "My App Protocol",
+ "role": "Editor"
+ }
+ ]
+ }
+}
+```
+
+| Property | Description |
+|:------------|:--------------------------------------------------------------------------------------|
+| scheme | Custom Protocol scheme. e.g. myapp |
+| description | Windows-only. The description. |
+| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. |
+
+## Platform Specifics:
+
+### macOS
+When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ Mac: &mac.Options{
+ OnUrlOpen: func(url string) { println(url) },
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+
+ if err != nil {
+ println("Error:", err.Error())
+ }
+}
+```
+
+If you want to handle universal links as well, follow this [guide](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app) to add required entitlements, add required keys to Info.plist and configure `apple-app-site-association` on your website.
+
+Here is example for Info.plist:
+```xml
+NSUserActivityTypes
+
+ NSUserActivityTypeBrowsingWeb
+
+```
+
+And for entitlements.plist
+```xml
+com.apple.developer.associated-domains
+
+ applinks:myawesomeapp.com
+
+```
+
+
+### Windows
+On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a
+registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed
+as argument to your app. To handle this you should parse command line arguments in your app. Example:
+```go title="main.go"
+func main() {
+ argsWithoutProg := os.Args[1:]
+
+ if len(argsWithoutProg) != 0 {
+ println("launchArgs", argsWithoutProg)
+ }
+}
+```
+
+You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched
+and arguments are passed to already running instance. Check single instance lock guide for details. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ SingleInstanceLock: &options.SingleInstanceLock{
+ UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
+ OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+}
+```
+
+### Linux
+Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually.
+For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle.
+You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app.
+
+1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example:
+```ini
+[Desktop Entry]
+Categories=Office
+Exec=/usr/bin/wails-open-file %u
+Icon=wails-open-file.png
+Name=wails-open-file
+Terminal=false
+Type=Application
+MimeType=x-scheme-handler/myapp;
+```
+
+2. Prepare postInstall/postRemove scripts for your package. Example:
+```sh
+# reload desktop database to load app in list of available
+update-desktop-database /usr/share/applications
+```
+3. Configure nfpm to use your scripts and files. Example:
+```yaml
+name: "wails-open-file"
+arch: "arm64"
+platform: "linux"
+version: "1.0.0"
+section: "default"
+priority: "extra"
+maintainer: "FooBarCorp "
+description: "Sample Package"
+vendor: "FooBarCorp"
+homepage: "http://example.com"
+license: "MIT"
+contents:
+- src: ../bin/wails-open-file
+ dst: /usr/bin/wails-open-file
+- src: ./main.desktop
+ dst: /usr/share/applications/wails-open-file.desktop
+- src: ../appicon.svg
+ dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
+# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
+- src: ../appicon.svg
+ dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
+scripts:
+ postinstall: ./postInstall.sh
+ postremove: ./postRemove.sh
+```
+6. Build your .deb package using nfpm:
+```sh
+nfpm pkg --packager deb --target .
+```
+7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app,
+new instance of app is launched and file path is passed as argument to your app.
+To handle this you should parse command line arguments in your app. Example:
+```go title="main.go"
+func main() {
+ argsWithoutProg := os.Args[1:]
+
+ if len(argsWithoutProg) != 0 {
+ println("launchArgs", argsWithoutProg)
+ }
+}
+```
+
+You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched
+and arguments are passed to already running instance. Check single instance lock guide for details. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ SingleInstanceLock: &options.SingleInstanceLock{
+ UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
+ OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+}
+```
diff --git a/website/docs/guides/dynamic-assets.mdx b/website/docs/guides/dynamic-assets.mdx
index 806accf18..8d1debcef 100644
--- a/website/docs/guides/dynamic-assets.mdx
+++ b/website/docs/guides/dynamic-assets.mdx
@@ -1,5 +1,14 @@
# Dynamic Assets
+:::info
+
+This does not work with vite v5.0.0+ and wails v2 due to changes in vite.
+Changes are planned in v3 to support similar functionality under vite v5.0.0+.
+If you need this feature, stay with vite v4.0.0+.
+See [issue 3240](https://github.com/wailsapp/wails/issues/3240) for details
+
+:::
+
If you want to load or generate assets for your frontend dynamically, you can achieve that using the
[AssetsHandler](../reference/options#assetshandler) option. The AssetsHandler is a generic `http.Handler` which will
be called for any non GET request on the assets server and for GET requests which can not be served from the
@@ -11,7 +20,7 @@ By installing a custom AssetsHandler, you can serve your own assets using a cust
In our example project, we will create a simple assets handler which will load files off disk:
-```go title=main.go {16-35,49}
+```go title=main.go {17-36,49}
package main
import (
diff --git a/website/docs/guides/file-association.mdx b/website/docs/guides/file-association.mdx
new file mode 100644
index 000000000..71bbff37e
--- /dev/null
+++ b/website/docs/guides/file-association.mdx
@@ -0,0 +1,228 @@
+# File Association
+
+File association feature allows you to associate specific file types with your app so that when users open those files,
+your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application
+that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app.
+
+
+## Set Up File Association:
+To set up file association, you need to modify your application's wails.json file.
+In "info" section add a "fileAssociations" section specifying the file types your app should be associated with.
+
+For example:
+```json
+{
+ "info": {
+ "fileAssociations": [
+ {
+ "ext": "wails",
+ "name": "Wails",
+ "description": "Wails Application File",
+ "iconName": "wailsFileIcon",
+ "role": "Editor"
+ },
+ {
+ "ext": "jpg",
+ "name": "JPEG",
+ "description": "Image File",
+ "iconName": "jpegFileIcon",
+ "role": "Editor"
+ }
+ ]
+ }
+}
+```
+
+| Property | Description |
+|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|
+| ext | The extension (minus the leading period). e.g. png |
+| name | The name. e.g. PNG File |
+| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows |
+| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. |
+| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. |
+
+## Platform Specifics:
+
+### macOS
+When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ Mac: &mac.Options{
+ OnFileOpen: func(filePaths []string) { println(filestring) },
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+
+ if err != nil {
+ println("Error:", err.Error())
+ }
+}
+```
+
+
+### Windows
+On Windows file association is supported only with NSIS installer. During installation, the installer will create a
+registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed
+as argument to your app. To handle this you should parse command line arguments in your app. Example:
+```go title="main.go"
+func main() {
+ argsWithoutProg := os.Args[1:]
+
+ if len(argsWithoutProg) != 0 {
+ println("launchArgs", argsWithoutProg)
+ }
+}
+```
+
+You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched
+and arguments are passed to already running instance. Check single instance lock guide for details. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ SingleInstanceLock: &options.SingleInstanceLock{
+ UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
+ OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+}
+```
+
+### Linux
+Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually.
+For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle.
+You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app.
+
+1. Create a .desktop file for your app and specify file associations there. Example:
+```ini
+[Desktop Entry]
+Categories=Office
+Exec=/usr/bin/wails-open-file %u
+Icon=wails-open-file.png
+Name=wails-open-file
+Terminal=false
+Type=Application
+MimeType=application/x-wails;application/x-test
+```
+
+2. Create mime types file. Example:
+```xml
+
+
+
+ Wails Application File
+
+
+
+```
+
+3. Create icons for your file types. SVG icons are recommended.
+4. Prepare postInstall/postRemove scripts for your package. Example:
+```sh
+# reload mime types to register file associations
+update-mime-database /usr/share/mime
+# reload desktop database to load app in list of available
+update-desktop-database /usr/share/applications
+# update icons
+update-icon-caches /usr/share/icons/*
+```
+5. Configure nfpm to use your scripts and files. Example:
+```yaml
+name: "wails-open-file"
+arch: "arm64"
+platform: "linux"
+version: "1.0.0"
+section: "default"
+priority: "extra"
+maintainer: "FooBarCorp "
+description: "Sample Package"
+vendor: "FooBarCorp"
+homepage: "http://example.com"
+license: "MIT"
+contents:
+- src: ../bin/wails-open-file
+ dst: /usr/bin/wails-open-file
+- src: ./main.desktop
+ dst: /usr/share/applications/wails-open-file.desktop
+- src: ./application-wails-mime.xml
+ dst: /usr/share/mime/packages/application-x-wails.xml
+- src: ./application-test-mime.xml
+ dst: /usr/share/mime/packages/application-x-test.xml
+- src: ../appicon.svg
+ dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
+- src: ../wailsFileIcon.svg
+ dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg
+- src: ../testFileIcon.svg
+ dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg
+# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
+- src: ../appicon.svg
+ dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
+- src: ../wailsFileIcon.svg
+ dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg
+- src: ../testFileIcon.svg
+ dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg
+scripts:
+ postinstall: ./postInstall.sh
+ postremove: ./postRemove.sh
+```
+6. Build your .deb package using nfpm:
+```sh
+nfpm pkg --packager deb --target .
+```
+7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app,
+new instance of app is launched and file path is passed as argument to your app.
+To handle this you should parse command line arguments in your app. Example:
+```go title="main.go"
+func main() {
+ argsWithoutProg := os.Args[1:]
+
+ if len(argsWithoutProg) != 0 {
+ println("launchArgs", argsWithoutProg)
+ }
+}
+```
+
+You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched
+and arguments are passed to already running instance. Check single instance lock guide for details. Example:
+```go title="main.go"
+func main() {
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ SingleInstanceLock: &options.SingleInstanceLock{
+ UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
+ OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+}
+```
diff --git a/website/docs/guides/frontend.mdx b/website/docs/guides/frontend.mdx
index 1384087da..2c3c78e42 100644
--- a/website/docs/guides/frontend.mdx
+++ b/website/docs/guides/frontend.mdx
@@ -45,7 +45,7 @@ The options are as follows:
| noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` |
| noautoinject | Disable all autoinjection of scripts |
-Multiple options may be used provided they are comma seperated.
+Multiple options may be used provided they are comma separated.
This code is perfectly valid and operates the same as the autoinjection version:
diff --git a/website/docs/guides/ides.mdx b/website/docs/guides/ides.mdx
index f22aefe9e..5fe5a7bb9 100644
--- a/website/docs/guides/ides.mdx
+++ b/website/docs/guides/ides.mdx
@@ -3,7 +3,7 @@
Wails aims to provide a great development experience. To that aim, we now support generating IDE specific configuration
to provide smoother project setup.
-Currently, we support [Visual Studio Code](https://code.visualstudio.com/) but aim to support other IDEs such as Goland.
+Currently, we support [Visual Studio Code](https://code.visualstudio.com/) and [Goland](https://www.jetbrains.com/go/).
## Visual Studio Code
diff --git a/website/docs/guides/linux.mdx b/website/docs/guides/linux.mdx
index fa74fe6cf..2cfc2e62a 100644
--- a/website/docs/guides/linux.mdx
+++ b/website/docs/guides/linux.mdx
@@ -18,3 +18,109 @@ videoTag.addEventListener("timeupdate", (event) => {
Source: [Lyimmi](https://github.com/Lyimmi) on the
[discussions board](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275)
+
+## GStreamer error when using Audio or Video elements
+
+If you are seeing the following error when including `` or `` elements on Linux, you may need to install `gst-plugins-good`.
+
+```
+GStreamer element autoaudiosink not found. Please install it
+```
+
+### Installing
+
+Run the following distro relevant install command:
+
+```mdx-code-block
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+
+
+
+ pacman -S gst-plugins-good
+
+
+
+
+ apt-get install gstreamer1.0-plugins-good
+
+
+
+
+ dnf install gstreamer1-plugins-good
+
+
+
+```
+
+If the added package does not resolve the issue, additional GStreamer dependencies may be required. [See the GStreamer installation page for more details.](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html)
+
+### Additional Notes
+
+- This issue is caused by [an upstream issue with WebkitGTK](https://bugs.webkit.org/show_bug.cgi?id=146351).
+- [Arch based systems](https://wiki.archlinux.org/title/Arch-based_distributions) seem to have this issue more often than other distributions.
+- This issue impacts [Tauri apps](https://tauri.app/).
+
+Source: [developomp](https://github.com/developomp) on the [Tauri discussion board](https://github.com/tauri-apps/tauri/issues/4642#issuecomment-1643229562).
+
+## Panic Recovery / Signal Handling Issues
+
+### App crashes with "non-Go code set up signal handler without SA_ONSTACK flag"
+
+On Linux, if your application crashes with an error like:
+
+```
+signal 11 received but handler not on signal stack
+fatal error: non-Go code set up signal handler without SA_ONSTACK flag
+```
+
+This occurs because WebKit (used for the webview) installs signal handlers that interfere with Go's panic recovery mechanism.
+Normally, Go can convert signals like SIGSEGV (from nil pointer dereferences) into recoverable panics, but WebKit's signal
+handlers prevent this.
+
+### Solution
+
+Use the `runtime.ResetSignalHandlers()` function immediately before code that might panic:
+
+```go
+import "github.com/wailsapp/wails/v2/pkg/runtime"
+
+go func() {
+ defer func() {
+ if err := recover(); err != nil {
+ log.Printf("Recovered from panic: %v", err)
+ }
+ }()
+ // Reset signal handlers right before potentially dangerous code
+ runtime.ResetSignalHandlers()
+
+ // Your code that might panic...
+}()
+```
+
+:::warning Important
+
+- Call `ResetSignalHandlers()` in each goroutine where you need panic recovery
+- Call it immediately before the code that might panic, as WebKit may reset the handlers at any time
+- This is only necessary on Linux - the function is a no-op on other platforms
+
+:::
+
+### Why This Happens
+
+WebKit installs its own signal handlers for garbage collection and other internal processes. These handlers don't include
+the `SA_ONSTACK` flag that Go requires to properly handle signals on the correct stack. When a signal like SIGSEGV occurs,
+Go's runtime can't recover because the signal is being handled on the wrong stack.
+
+The `ResetSignalHandlers()` function adds the `SA_ONSTACK` flag to the signal handlers for SIGSEGV, SIGBUS, SIGFPE, and
+SIGABRT, allowing Go's panic recovery to work correctly.
+
+Source: [GitHub Issue #3965](https://github.com/wailsapp/wails/issues/3965)
diff --git a/website/docs/guides/mac-appstore.mdx b/website/docs/guides/mac-appstore.mdx
index 271464730..708528987 100644
--- a/website/docs/guides/mac-appstore.mdx
+++ b/website/docs/guides/mac-appstore.mdx
@@ -21,6 +21,12 @@ This page gives a brief overview of how to submit your Wails App to the Mac App
3. Populate your app with the correct screen shots, descriptions, etc. as required by Apple
4. Create a new version of your app
+#### Create Provisioning Profile
+1. Go to the [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) page
+2. Add a new provisioning profile for Mac App Store Distribution
+3. Set the Profile Type as Mac and select the App ID for the application created above
+4. Select the Mac App Distribution certificate
+5. Name the Provisioning Profile embedded and download the created profile.
## Mac App Store Process
@@ -30,7 +36,7 @@ Apps submitted to the Mac App Store must run under Apple's [App Sandbox](https:/
**Example Entitlements File**
-This is an example entitlements file from the [RiftShare](https://github.com/achhabra2/riftshare) app. For reference please put in the entitlements your app requires. Refer to [this site](https://developer.apple.com/documentation/bundleresources/entitlements) for more information.
+This is an example entitlements file from the [RiftShare](https://github.com/achhabra2/riftshare) app. For reference please put in the entitlements your app requires. Refer to [this site](https://developer.apple.com/documentation/bundleresources/entitlements) for more information. You will need to replace the Team ID and Application Name with the ones you registered above.
```xml title="entitlements.plist"
@@ -47,10 +53,17 @@ This is an example entitlements file from the [RiftShare](https://github.com/ach
com.apple.security.files.downloads.read-write
+ com.apple.application-identifier
+ TEAM_ID.APP_NAME
+ com.apple.developer.team-identifier
+ TEAM_ID
```
+**Add the Embedded Provisioning Profile**
+The Provisioning Profile created above needs to be added to the root of the application. It needs to be named embedded.provisionprofile.
+
#### Build and Sign the App Package
The following is an example script for building and signing your app for Mac App Store submission. It assumes you are running the script from your root project directory.
@@ -66,9 +79,11 @@ APP_NAME="YourApp"
wails build -platform darwin/universal -clean
-codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app
+cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents"
-productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg
+codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist "./build/bin/$APP_NAME.app"
+
+productbuild --sign "$PKG_CERTIFICATE" --component "./build/bin/$APP_NAME.app" /Applications "./$APP_NAME.pkg"
```
#### Upload App Bundle
@@ -80,4 +95,4 @@ You will need to upload the generated package file and associate it to your Appl
3. Click the + sign and select the `APP_NAME.pkg` file that you generated in the previous step. Upload it
4. Go back to the [App Store Connect](https://appstoreconnect.apple.com/apps) site and navigate back into your app submission. Select the version that you are ready to make available on the App Store. Under `Build` select the package that you uploaded via Transporter.
-That's it! You can now use the site to submit your App for review. After a few business days if all goes well you should see your App live on the Mac App Store.
\ No newline at end of file
+That's it! You can now use the site to submit your App for review. After a few business days if all goes well you should see your App live on the Mac App Store.
diff --git a/website/docs/guides/migrating.mdx b/website/docs/guides/migrating.mdx
index 45c9cf7a0..28dbca556 100644
--- a/website/docs/guides/migrating.mdx
+++ b/website/docs/guides/migrating.mdx
@@ -97,7 +97,7 @@ func (b *Basic) startup(ctx context.Context) {
The runtime in v2 is much richer than v1 with support for menus, window manipulation
and better dialogs. The signature of the methods has changed slightly - please refer
-the the [Runtime Reference](../reference/runtime/intro.mdx).
+to the [Runtime Reference](../reference/runtime/intro.mdx).
In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`.
In v2, the runtime has been moved out to its own package. Each method in the runtime takes the
diff --git a/website/docs/guides/nixos-font.mdx b/website/docs/guides/nixos-font.mdx
new file mode 100644
index 000000000..02188562e
--- /dev/null
+++ b/website/docs/guides/nixos-font.mdx
@@ -0,0 +1,10 @@
+# NixOS FontSize Bug
+
+NixOS/Wayland can cause a bug where the `font-size` css property doesn't affect the rendered page. To fix this add the following to your devShell.
+
+```shell
+ shellHook = with pkgs; ''
+ export XDG_DATA_DIRS=${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}:${gtk3}/share/gsettings-schemas/${gtk3.name}:$XDG_DATA_DIRS;
+ export GIO_MODULE_DIR="${pkgs.glib-networking}/lib/gio/modules/";
+ '';
+```
diff --git a/website/docs/guides/obfuscated.mdx b/website/docs/guides/obfuscated.mdx
index 2e7906c40..c35fb0038 100644
--- a/website/docs/guides/obfuscated.mdx
+++ b/website/docs/guides/obfuscated.mdx
@@ -14,7 +14,7 @@ To customise the obfuscation settings, you can use the `-garbleargs` flag:
wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed"
```
-These settings may be persisted in your [project config](../reference/project-config).
+These settings may be persisted in your [project config](../reference/project-config.mdx).
## How it works
diff --git a/website/docs/guides/routing.mdx b/website/docs/guides/routing.mdx
index c35cc1c8a..63a081ffd 100644
--- a/website/docs/guides/routing.mdx
+++ b/website/docs/guides/routing.mdx
@@ -27,10 +27,10 @@ RouterModule.forRoot(routes, { useHash: true });
## React
-The recommended approach for routing in React is [HashRouter](https://reactrouter.com/docs/en/v6/routers/hash-router):
+The recommended approach for routing in React is [HashRouter](https://reactrouter.com/en/main/router-components/hash-router):
```jsx
-import { HashRouter } from "react-router-dom";
+import { HashRouter, Routes, Route } from "react-router-dom";
ReactDOM.render(
@@ -45,3 +45,24 @@ ReactDOM.render(
root
);
```
+
+## Svelte
+
+The recommended approach for routing in Svelte is [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router):
+
+```svelte
+
+
+ import("./routes/Products.svelte"),
+ }),
+ "/settings": Settings,
+ "*": NotFound,
+ }}
+/>
+```
diff --git a/website/docs/guides/signing.mdx b/website/docs/guides/signing.mdx
index b2a060c5f..4ce5fd4b2 100644
--- a/website/docs/guides/signing.mdx
+++ b/website/docs/guides/signing.mdx
@@ -232,7 +232,7 @@ jobs:
path: build/bin/*
```
-For code signing on macOS, [gon](https://github.com/mitchellh/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and
+For code signing on macOS, [gon](https://github.com/Bearer/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and
will be used in this guide.
After the `Build Wails app` step, add the following to the workflow:
@@ -241,7 +241,7 @@ After the `Build Wails app` step, add the following to the workflow:
- name: MacOS download gon for code signing and app notarization
if: matrix.platform == 'macos-latest'
run: |
- brew install mitchellh/gon/gon
+ brew install Bearer/tap/gon
```
Now we need to configure some gon config files in our `build/darwin` directory:
@@ -254,19 +254,32 @@ Now we need to configure some gon config files in our `build/darwin` directory:
"bundle_id": "app.myapp",
"apple_id": {
"username": "my-appleid@email.com",
- "password": "@env:APPLE_PASSWORD"
+ "password": "your-app-specific-password",
+ "provider": "ABCDE12345"
},
"sign": {
- "application_identity": "Developer ID Application: My Name"
+ "application_identity": "Developer ID Application: Human User"
}
}
```
-Where `source` is your Wails binary, `bundle_id` is your bundle ID, `apple_id` contains your Apple ID username and App-Specific password
-which you created earlier, and `sign.application_identity` is your identity which you can find by running the following command:
+Here is a brief break down of the above fields:
+
+- `source`: The location of your wails binary to be signed
+- `apple_id`:
+ - `username`: Your Apple ID email address
+ - `password`: Your app-specific password
+ - `provider`: Your team ID for your App Store Connect account
+- `sign`:
+ - `application_identity`: Your Apple developer identity
+
+The (https://developer.apple.com/documentation/technotes/tn3147-migrating-to-the-latest-notarization-tool)[deprecated Apple's altool]'s syntax supporting `@env:` is no longer available since Apple has migrated to the new notarytool.
+
+Your developer identity and team ID can both by found on macOS by running the following command:
```bash
-security find-identity -v -p codesigning
+$ security find-identity -v -p codesigning
+ 1) 00000000000000000000000000000000000000000 "Developer ID Application: Human User (ABCDE12345)"
```
2. entitlements.plist:
@@ -369,7 +382,7 @@ jobs:
- name: MacOS download gon for code signing and app notarization
if: matrix.platform == 'macos-latest'
run: |
- brew install mitchellh/gon/gon
+ brew install Bearer/tap/gon
- name: Import Code-Signing Certificates for macOS
if: matrix.platform == 'macos-latest'
uses: Apple-Actions/import-codesign-certs@v1
diff --git a/website/docs/guides/single-instance-lock.mdx b/website/docs/guides/single-instance-lock.mdx
new file mode 100644
index 000000000..644e1e0d8
--- /dev/null
+++ b/website/docs/guides/single-instance-lock.mdx
@@ -0,0 +1,80 @@
+# Single Instance Lock
+
+Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time.
+It is useful for apps that are designed to open files from the command line or from the OS file explorer.
+
+## Important
+
+Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock,
+your app should treat any data passed to it from second instance callback as untrusted.
+You should verify that args that you receive are valid and don't contain any malicious data.
+
+## How it works
+
+Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage)
+macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter)
+Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/)
+
+## Usage
+When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct.
+Use the `UniqueId` field to specify a unique id for your app.
+This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique.
+The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched.
+The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance.
+
+Note that OnSecondInstanceLaunch don't trigger windows focus.
+You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front.
+Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus.
+
+```go title="main.go"
+var wailsContext *context.Context
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called when the app starts. The context is saved
+// so we can call the runtime methods
+func (a *App) startup(ctx context.Context) {
+ wailsContext = &ctx
+}
+
+func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
+ secondInstanceArgs = secondInstanceData.Args
+
+ println("user opened second instance", strings.Join(secondInstanceData.Args, ","))
+ println("user opened second from", secondInstanceData.WorkingDirectory)
+ runtime.WindowUnminimise(*wailsContext)
+ runtime.Show(*wailsContext)
+ go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs)
+}
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "wails-open-file",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
+ SingleInstanceLock: &options.SingleInstanceLock{
+ UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
+ OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
+ },
+ Bind: []interface{}{
+ app,
+ },
+ })
+
+ if err != nil {
+ println("Error:", err.Error())
+ }
+}
+```
diff --git a/website/docs/guides/sveltekit.mdx b/website/docs/guides/sveltekit.mdx
new file mode 100644
index 000000000..afb67f630
--- /dev/null
+++ b/website/docs/guides/sveltekit.mdx
@@ -0,0 +1,136 @@
+# SvelteKit
+
+This guide will go into:
+1. Minimal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit.
+2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding.
+3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes.
+
+## 1. Minimal Installation Steps
+
+##### Install Wails for Svelte.
+- `wails init -n myapp -t svelte`
+
+##### Delete the svelte frontend.
+- Navigate into your newly created myapp folder.
+- Delete the folder named "frontend"
+
+##### While in the Wails project root. Use the Svelte CLI to create a SvelteKit project as the new frontend. Follow the prompts, nothing Wails specific is needed here.
+- `npx sv create frontend`
+
+##### Modify wails.json.
+- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear.
+- Change your package manager frontend here if not using npm.
+
+##### Modify main.go.
+- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build`
+
+##### Modify .gitignore
+- The line `frontend/dist` needs to be replaced with `frontend/build`
+
+##### Install/remove dependencies using your favorite package manager.
+- Navigate into your "frontend" folder.
+- `npm i`
+- `npm uninstall @sveltejs/adapter-auto`
+- `npm i -D @sveltejs/adapter-static`
+
+##### Change adapter in svelte.config.js
+- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';`
+
+##### Put SvelteKit into SPA mode with prerendering.
+- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js.
+- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false`
+
+##### Test installation.
+- Navigate back into the Wails project root (one directory up).
+- run `wails dev`
+- If the application doesn't run please check through the previous steps.
+
+## 2. Install Script
+
+##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer.
+
+- Create a file sveltekit-wails.sh
+- Copy the below code into the new file then save it.
+- Make it executable with `chmod +x sveltekit-wails.sh`
+- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding.
+- Example usage: `./sveltekit-wails.sh pnpm newapp brand`
+
+##### sveltekit-wails.sh:
+```
+manager=$1
+project=$2
+brand=$3
+wails init -n $project -t svelte
+cd $project
+sed -i "s|npm|$manager|g" wails.json
+sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json
+sed -i "s|all:frontend/dist|all:frontend/build|" main.go
+if [[ -n $brand ]]; then
+ mv frontend/src/App.svelte +page.svelte
+ sed -i "s|'./assets|'\$lib/assets|" +page.svelte
+ sed -i "s|'../wails|'\$lib/wails|" +page.svelte
+ mv frontend/src/assets .
+fi
+rm -r frontend
+$manager create svelte@latest frontend
+if [[ -n $brand ]]; then
+ mv +page.svelte frontend/src/routes/+page.svelte
+ mkdir frontend/src/lib
+ mv assets frontend/src/lib/
+fi
+cd frontend
+$manager i
+$manager uninstall @sveltejs/adapter-auto
+$manager i -D @sveltejs/adapter-static
+echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts
+sed -i "s|-auto';|-static';|" svelte.config.js
+cd ..
+wails dev
+```
+
+## 3. Important Notes
+
+##### Server files will cause build failures.
+- +layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered.
+
+##### The Wails runtime unloads with full page navigations!
+- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this.
+- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation.
+- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html
+```
+
+...
+
+
+
+...
+
+```
+See https://wails.io/docs/guides/frontend for more information.
+
+##### Initial data can be loaded and refreshed from +page.ts/+page.js to +page.svelte.
+- +page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data
+- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation.
+
+##### Error Handling
+- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors
+- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file.
+```
+import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime'
+export async function handleError() {
+ WindowReloadApp()
+}
+```
+
+##### Using Forms and handling functions
+- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `