snapshot of https://github.com/tauri-apps/tauri.git (dev, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
This commit is contained in:
799
crates/tauri-codegen/CHANGELOG.md
Normal file
799
crates/tauri-codegen/CHANGELOG.md
Normal file
@@ -0,0 +1,799 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.6.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.9.3`
|
||||
|
||||
## \[2.6.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.9.2`
|
||||
|
||||
## \[2.6.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.9.1`
|
||||
|
||||
## \[2.6.0]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.9.0`
|
||||
- [`df05c0056`](https://www.github.com/tauri-apps/tauri/commit/df05c00563a91fc936bd15c6b10dd2825472f96b) Upgraded to `tauri-utils@2.9.0`
|
||||
|
||||
## \[2.5.5]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.8.3`
|
||||
|
||||
## \[2.5.4]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`eb5d88427`](https://www.github.com/tauri-apps/tauri/commit/eb5d88427a7dcb347fb0feae9e816db05b101844) ([#14883](https://www.github.com/tauri-apps/tauri/pull/14883) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `tauri::Context` code generation failing with `can't capture dynamic environment in a fn item` when custom assets are provided.
|
||||
|
||||
## \[2.5.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.8.2`
|
||||
|
||||
## \[2.5.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.8.1`
|
||||
|
||||
## \[2.5.1]
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- [`8e3bd63db`](https://www.github.com/tauri-apps/tauri/commit/8e3bd63db919a4cf72bb3d28028033d8654deb34) ([#14457](https://www.github.com/tauri-apps/tauri/pull/14457) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Wrap the generated context code in a function to make rust analyzer faster
|
||||
|
||||
## \[2.5.0]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`c5008b829`](https://www.github.com/tauri-apps/tauri/commit/c5008b829dc779f0768089bff9b891fc76b11355) ([#14274](https://www.github.com/tauri-apps/tauri/pull/14274)) Do not hash empty scripts when generating the Content-Security-Policy SHA-256 hashes.
|
||||
- [`7b0d4e732`](https://www.github.com/tauri-apps/tauri/commit/7b0d4e73227e42d88732b6d9fe643499dd78ec4e) ([#14265](https://www.github.com/tauri-apps/tauri/pull/14265)) Fix JavaScript SHA256 hash generation on Windows not ignoring carriage return characters.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.8.0`
|
||||
- [`6aa7f2d85`](https://www.github.com/tauri-apps/tauri/commit/6aa7f2d852870aeba1d4dd0e07f8be2bc9b66286) Upgraded to `tauri-utils@2.8.0`
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.7.0`.
|
||||
|
||||
## \[2.3.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.6.0`
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles.
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`168629646`](https://www.github.com/tauri-apps/tauri/commit/168629646335f24cc7f1c4a61df22688b2198f98) ([#13418](https://www.github.com/tauri-apps/tauri/pull/13418) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Put dynamic ACL into a feature `dynamic-acl`, this is currently enabled by default to align with the previous behaviors, you can disable it through `default-features = false` to reduce the final binary size by not including the ACL references
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.5.0`
|
||||
|
||||
## \[2.2.0]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.4.0`
|
||||
- [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0`
|
||||
|
||||
## \[2.1.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.3.1`
|
||||
|
||||
## \[2.1.0]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.3.0`
|
||||
|
||||
## \[2.0.5]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.2.0`
|
||||
|
||||
## \[2.0.4]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.1.1`
|
||||
|
||||
## \[2.0.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.1.0`
|
||||
|
||||
## \[2.0.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.2`
|
||||
|
||||
## \[2.0.1]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.1`
|
||||
|
||||
## \[2.0.0]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78.
|
||||
- [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable!
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0`
|
||||
|
||||
## \[2.0.0-rc.13]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`1efa5e718`](https://www.github.com/tauri-apps/tauri/commit/1efa5e7184009537b688a395596c696173ae0231) ([#11099](https://www.github.com/tauri-apps/tauri/pull/11099) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Rerun build script if the platform-specific configuration file changes.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.13`
|
||||
|
||||
## \[2.0.0-rc.12]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.12`
|
||||
|
||||
## \[2.0.0-rc.11]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.11`
|
||||
|
||||
## \[2.0.0-rc.10]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.10`
|
||||
|
||||
## \[2.0.0-rc.9]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.9`
|
||||
|
||||
## \[2.0.0-rc.8]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`27d018343`](https://www.github.com/tauri-apps/tauri/commit/27d01834312ee7953b6ccd5b0a368e7a69b225e9) ([#10844](https://www.github.com/tauri-apps/tauri/pull/10844) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Changes how the Info.plist is embedded on macOS development to avoid a clippy warning.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.8`
|
||||
|
||||
## \[2.0.0-rc.7]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`88bc35732`](https://www.github.com/tauri-apps/tauri/commit/88bc357325ba278527d8cba956e828f5744c8a34) ([#10734](https://www.github.com/tauri-apps/tauri/pull/10734) by [@chippers](https://www.github.com/tauri-apps/tauri/../../chippers)) Generate context in a separate thread to prevent a stack overflow.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.7`
|
||||
|
||||
## \[2.0.0-rc.6]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.6`
|
||||
|
||||
## \[2.0.0-rc.5]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.5`
|
||||
|
||||
## \[2.0.0-rc.4]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.4`
|
||||
|
||||
## \[2.0.0-rc.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.3`
|
||||
- [`0afee5ed8`](https://www.github.com/tauri-apps/tauri/commit/0afee5ed80265c95c4581e173c4886677cfed593) ([#10436](https://www.github.com/tauri-apps/tauri/pull/10436) by [@nyurik](https://www.github.com/tauri-apps/tauri/../../nyurik)) Updated brotli to v6.
|
||||
|
||||
## \[2.0.0-rc.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.2`
|
||||
|
||||
## \[2.0.0-rc.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.1`
|
||||
|
||||
## \[2.0.0-rc.0]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`1e0793b68`](https://www.github.com/tauri-apps/tauri/commit/1e0793b6821799829e380c88066b3415cc9006df) ([#10357](https://www.github.com/tauri-apps/tauri/pull/10357)) Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`24445d71d`](https://www.github.com/tauri-apps/tauri/commit/24445d71de92d526d0ccaecb54f13003ddc6f6b4)([#10432](https://www.github.com/tauri-apps/tauri/pull/10432)) Fixes asset resolving when not using the `compression` feature.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-rc.0`
|
||||
|
||||
## \[2.0.0-beta.19]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`5d2922985`](https://www.github.com/tauri-apps/tauri/commit/5d2922985801908e4b929a7a0e387806ff02ab89) ([#10268](https://www.github.com/tauri-apps/tauri/pull/10268) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix icon rewriting always triggering build to rerun due to conflicts between file names.
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `test = true` in `generate_context!` macro to skip some code generation that could affect some tests, for now it only skips empedding a plist on macOS.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.19`
|
||||
|
||||
## \[2.0.0-beta.18]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image_codegen` function to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`1f6e478c8`](https://www.github.com/tauri-apps/tauri/commit/1f6e478c842a16219798b9962718e9ddb969c041) ([#9878](https://www.github.com/tauri-apps/tauri/pull/9878)) Fixes Info.plist rewriting always triggering build to rerun.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.18`
|
||||
|
||||
## \[2.0.0-beta.17]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`ccc3ea729`](https://www.github.com/tauri-apps/tauri/commit/ccc3ea729de205ef467f737f1feeb5bf02d9cd72)([#9646](https://www.github.com/tauri-apps/tauri/pull/9646)) Use `TAURI_ENV_TARGET_TRIPLE` (which is set by `tauri-build`) to determine the target when reading the config file.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.17`
|
||||
|
||||
## \[2.0.0-beta.16]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.16`
|
||||
|
||||
## \[2.0.0-beta.15]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.15`
|
||||
|
||||
## \[2.0.0-beta.14]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.14`
|
||||
|
||||
## \[2.0.0-beta.13]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.13`
|
||||
|
||||
## \[2.0.0-beta.12]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.12`
|
||||
|
||||
## \[2.0.0-beta.11]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.11`
|
||||
|
||||
## \[2.0.0-beta.10]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.10`
|
||||
|
||||
## \[2.0.0-beta.9]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`ba0206d8a`](https://www.github.com/tauri-apps/tauri/commit/ba0206d8a30a9b43ec5090dcaabd1a23baa1420c)([#9141](https://www.github.com/tauri-apps/tauri/pull/9141)) The `Context` codegen now accepts a `assets` input to define a custom `tauri::Assets` implementation.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.9`
|
||||
|
||||
## \[2.0.0-beta.8]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.8`
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [`ed48e2b3c`](https://www.github.com/tauri-apps/tauri/commit/ed48e2b3c7fa914e4c9af432c02b8154f872c68a)([#9122](https://www.github.com/tauri-apps/tauri/pull/9122)) Expose `tauri::image` module to export the `JsImage` type and removed the `Image` root re-export.
|
||||
|
||||
## \[2.0.0-beta.7]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.7`
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Change the generated context code to use the new `Image` type in tauri.
|
||||
|
||||
## \[2.0.0-beta.6]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.6`
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`.
|
||||
|
||||
## \[2.0.0-beta.5]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`bc5b5e67`](https://www.github.com/tauri-apps/tauri/commit/bc5b5e671a546512f823f1c157421b4c3311dfc0)([#8984](https://www.github.com/tauri-apps/tauri/pull/8984)) Do not include a CSP tag in the application HTML and rely on the custom protocol response header instead.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.5`
|
||||
|
||||
## \[2.0.0-beta.4]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.4`
|
||||
|
||||
## \[2.0.0-beta.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.3`
|
||||
|
||||
## \[2.0.0-beta.2]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`83a68deb`](https://www.github.com/tauri-apps/tauri/commit/83a68deb5676d39cd4728d2e140f6b46d5f787ed)([#8797](https://www.github.com/tauri-apps/tauri/pull/8797)) Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior.
|
||||
- [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) The `generate_context` proc macro now accepts a `capabilities` attribute where the value is an array of file paths that can be [conditionally compiled](https://doc.rust-lang.org/reference/conditional-compilation.html). These capabilities are added to the application along the capabilities defined in the Tauri configuration file.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.2`
|
||||
|
||||
## \[2.0.0-beta.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.1`
|
||||
|
||||
## \[2.0.0-beta.0]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-beta.0`
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md):
|
||||
|
||||
- Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level.
|
||||
- Removed `package` object.
|
||||
- Renamed `tauri` object to `app`.
|
||||
- Moved `tauri.bundle` object to the top-level.
|
||||
- Renamed `build.distDir` field to `frontendDist`.
|
||||
- Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs.
|
||||
- Moved `tauri.pattern` to `app.security.pattern`.
|
||||
- Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object.
|
||||
- Moved `build.withGlobalTauri` to `app.withGlobalTauri`.
|
||||
- Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`.
|
||||
- Moved `tauri.bundle.deb` object to `bundle.linux.deb`.
|
||||
- Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`.
|
||||
- Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`.
|
||||
- Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit.
|
||||
|
||||
## \[2.0.0-alpha.13]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.13`
|
||||
|
||||
## \[2.0.0-alpha.12]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.12`
|
||||
|
||||
## \[2.0.0-alpha.11]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.11`
|
||||
|
||||
## \[2.0.0-alpha.10]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.10`
|
||||
|
||||
## \[2.0.0-alpha.9]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.9`
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables.
|
||||
|
||||
## \[2.0.0-alpha.8]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`100d9ede`](https://www.github.com/tauri-apps/tauri/commit/100d9ede35995d9db21d2087dd5606adfafb89a5)([#7802](https://www.github.com/tauri-apps/tauri/pull/7802)) Use `Target` enum from `tauri_utils::platform`.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.8`
|
||||
|
||||
## \[2.0.0-alpha.7]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.0.0-alpha.7`
|
||||
|
||||
## \[2.0.0-alpha.6]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Updated to latest `tauri-utils`
|
||||
|
||||
## \[2.0.0-alpha.5]
|
||||
|
||||
- [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `shell` functionality to its own plugin in the plugins-workspace repository.
|
||||
- [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65.
|
||||
- [`ae102980`](https://www.github.com/tauri-apps/tauri/commit/ae102980fcdde3f55effdc0623ea425b48d07dd1)([#6719](https://www.github.com/tauri-apps/tauri/pull/6719)) Refactor the `Context` conditional fields and only parse the tray icon on desktop.
|
||||
|
||||
## \[2.0.0-alpha.4]
|
||||
|
||||
- Added `android` configuration object under `tauri > bundle`.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07
|
||||
|
||||
## \[2.0.0-alpha.3]
|
||||
|
||||
- Pull changes from Tauri 1.3 release.
|
||||
- [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined
|
||||
|
||||
## \[2.0.0-alpha.2]
|
||||
|
||||
- Return `bool` in the invoke handler.
|
||||
- [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11
|
||||
|
||||
## \[2.0.0-alpha.1]
|
||||
|
||||
- Bump the MSRV to 1.64.
|
||||
- [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30
|
||||
- Added `crate_name` field on `PackageInfo`.
|
||||
- [630a7f4b](https://www.github.com/tauri-apps/tauri/commit/630a7f4b18cef169bfd48673609306fec434e397) refactor: remove mobile log initialization, ref [#6049](https://www.github.com/tauri-apps/tauri/pull/6049) ([#6081](https://www.github.com/tauri-apps/tauri/pull/6081)) on 2023-01-17
|
||||
|
||||
## \[2.0.0-alpha.0]
|
||||
|
||||
- Change `devPath` URL to use the local IP address on iOS and Android.
|
||||
- [6f061504](https://www.github.com/tauri-apps/tauri/commit/6f0615044d09ec58393a7ebca5e45bb175e20db3) feat(cli): add `android dev` and `ios dev` commands ([#4982](https://www.github.com/tauri-apps/tauri/pull/4982)) on 2022-08-20
|
||||
- First mobile alpha release!
|
||||
- [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08
|
||||
|
||||
## \[1.4.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@1.5.2`
|
||||
|
||||
## \[1.4.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@1.5.0`
|
||||
|
||||
## \[1.4.0]
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`17d5a4f5`](https://www.github.com/tauri-apps/tauri/commit/17d5a4f51f244d3ff42014b5d1b075fad7c636a5)([#6706](https://www.github.com/tauri-apps/tauri/pull/6706)) Early panic if the PNG icon is not RGBA.
|
||||
- [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85.
|
||||
|
||||
## \[1.3.0]
|
||||
|
||||
- Bump minimum supported Rust version to 1.60.
|
||||
- [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31
|
||||
- Pin `time` to `0.3.15`.
|
||||
- [3d16461b](https://www.github.com/tauri-apps/tauri/commit/3d16461b68583ba7db037fbc217786e79b46ddf2) fix(core): pin time to 0.3.15 ([#6312](https://www.github.com/tauri-apps/tauri/pull/6312)) on 2023-02-19
|
||||
|
||||
## \[1.2.1]
|
||||
|
||||
- Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18
|
||||
|
||||
## \[1.2.0]
|
||||
|
||||
- Properly serialize HTML template tags.
|
||||
- [aec5537d](https://www.github.com/tauri-apps/tauri/commit/aec5537de0205f62b2ae5c89da04d21930a6fc2e) fix(codegen): serialize template tags, closes [#4410](https://www.github.com/tauri-apps/tauri/pull/4410) ([#5247](https://www.github.com/tauri-apps/tauri/pull/5247)) on 2022-09-28
|
||||
- - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28
|
||||
|
||||
## \[1.1.1]
|
||||
|
||||
- Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16
|
||||
|
||||
## \[1.1.0]
|
||||
|
||||
- Use `TARGET` environment variable for code generation inside build scripts.
|
||||
- [6ba99689](https://www.github.com/tauri-apps/tauri/commit/6ba99689aa7ed0ffa9072a1c8ab5db12c9bf95af) feat(codegen): use TARGET environment variable if set ([#4921](https://www.github.com/tauri-apps/tauri/pull/4921)) on 2022-08-12
|
||||
- Added support to configuration files in TOML format (Tauri.toml file).
|
||||
- [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02
|
||||
- Improve tray icon read error message.
|
||||
- [52f0c8bb](https://www.github.com/tauri-apps/tauri/commit/52f0c8bb836c6d50b7ce2393161394f4ce78f5ae) feat(core): improve tray icon read error messages ([#4850](https://www.github.com/tauri-apps/tauri/pull/4850)) on 2022-08-03
|
||||
- Fix relative paths in `version` field of `tauri.config.json` not being correctly parsed by `generate_context!()`.
|
||||
- [accbc5e8](https://www.github.com/tauri-apps/tauri/commit/accbc5e8806a32efc555d019634fc2fa14d17f0a) fix(codegen): fix relative paths in `version` field of `tauri.config.json`, closes [#4723](https://www.github.com/tauri-apps/tauri/pull/4723) ([#4725](https://www.github.com/tauri-apps/tauri/pull/4725)) on 2022-07-24
|
||||
- Only rewrite temporary icon files when the content change, avoid needless rebuilds.
|
||||
- [f957cbb5](https://www.github.com/tauri-apps/tauri/commit/f957cbb56ccbd8d1c047a978b4579946252a6fd2) fix(codegen): write output file when contents change ([#4889](https://www.github.com/tauri-apps/tauri/pull/4889)) on 2022-08-09
|
||||
|
||||
## \[1.0.4]
|
||||
|
||||
- Validate `__TAURI_ISOLATION_HOOK__` being set by a file in the isolation application.
|
||||
- [3b4ed970](https://www.github.com/tauri-apps/tauri/commit/3b4ed970e663f5bffbfe0358610f9c3f157c513f) feat(codegen): validate `__TAURI_ISOLATION_HOOK__` is referenced ([#4631](https://www.github.com/tauri-apps/tauri/pull/4631)) on 2022-07-11
|
||||
|
||||
## \[1.0.3]
|
||||
|
||||
- The `TAURI_CONFIG` environment variable now represents the configuration to be merged instead of the entire JSON.
|
||||
- [fa028ebf](https://www.github.com/tauri-apps/tauri/commit/fa028ebf3c8ca7b43a70d283a01dbea86217594f) refactor: do not pass entire config from CLI to core, send patch instead ([#4598](https://www.github.com/tauri-apps/tauri/pull/4598)) on 2022-07-06
|
||||
|
||||
## \[1.0.2]
|
||||
|
||||
- Expose `platform::windows_version` function.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30
|
||||
|
||||
## \[1.0.1]
|
||||
|
||||
- Set the bundle name and app metadata in the Info.plist file in development mode.
|
||||
- [38f5db6e](https://www.github.com/tauri-apps/tauri/commit/38f5db6e6a8b496b50d486db6fd8204266de3a69) feat(codegen): fill app metadata in development Info.plist on 2022-06-21
|
||||
- Set the application icon in development mode on macOS.
|
||||
- [307c2ebf](https://www.github.com/tauri-apps/tauri/commit/307c2ebfb68238dacab6088f9c6ba310c727c68c) feat(core): set macOS app icon in development ([#4385](https://www.github.com/tauri-apps/tauri/pull/4385)) on 2022-06-19
|
||||
|
||||
## \[1.0.0]
|
||||
|
||||
- Upgrade to `stable`!
|
||||
- [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15
|
||||
|
||||
## \[1.0.0-rc.11]
|
||||
|
||||
- Read the tray icon path relatively to the config directory.
|
||||
- [562e8ca2](https://www.github.com/tauri-apps/tauri/commit/562e8ca23facf1a8e5fa6c8cdf872357d3523a78) fix(codegen): tray icon path is relative to the config directory on 2022-06-15
|
||||
|
||||
## \[1.0.0-rc.10]
|
||||
|
||||
- **Breaking change:** The `TrayIcon` enum has been removed and now `Icon` is used instead.
|
||||
This allows you to use more image formats and use embedded icons on Linux.
|
||||
- [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14
|
||||
|
||||
## \[1.0.0-rc.9]
|
||||
|
||||
- Added a config flag to bundle the media framework used by webkit2gtk `tauri.conf.json > tauri > bundle > appimage > bundleMediaFramework`.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10
|
||||
|
||||
## \[1.0.0-rc.8]
|
||||
|
||||
- **Breaking change:** `PackageInfo::version` is now a `semver::Version` instead of a `String`.
|
||||
- [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25
|
||||
- [a7388e23](https://www.github.com/tauri-apps/tauri/commit/a7388e23c3b9019d48b078cae00a75c74d74d11b) fix(ci): adjust change file to include tauri-utils and tauri-codegen on 2022-05-27
|
||||
|
||||
## \[1.0.0-rc.7]
|
||||
|
||||
- Allow configuring the display options for the MSI execution allowing quieter updates.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15
|
||||
|
||||
## \[1.0.0-rc.6]
|
||||
|
||||
- The `dangerous_allow_asset_csp_modification` configuration value has been changed to allow a list of CSP directives to disable.
|
||||
- [164078c0](https://www.github.com/tauri-apps/tauri/commit/164078c0b719ccbc12e956fecf8a7d4a3c5044e1) feat: allow limiting dangerousDisableAssetCspModification, closes [#3831](https://www.github.com/tauri-apps/tauri/pull/3831) ([#4021](https://www.github.com/tauri-apps/tauri/pull/4021)) on 2022-05-02
|
||||
|
||||
## \[1.0.0-rc.5]
|
||||
|
||||
- Read platform-specific configuration files when generating code without the `TAURI_CONFIG` env var.
|
||||
- [edf85bc1](https://www.github.com/tauri-apps/tauri/commit/edf85bc1d18450c92aee17f7f99c163abe432ebd) fix(codegen): read platform-specific config file ([#3966](https://www.github.com/tauri-apps/tauri/pull/3966)) on 2022-04-25
|
||||
|
||||
## \[1.0.0-rc.4]
|
||||
|
||||
- Added an option to disable the CSP injection of distributable assets nonces and hashes.
|
||||
- [f6e32ee1](https://www.github.com/tauri-apps/tauri/commit/f6e32ee1880eb364ed76beb937c9d12e14d54910) feat(core): add dangerous option to disable compile time CSP injection ([#3775](https://www.github.com/tauri-apps/tauri/pull/3775)) on 2022-03-28
|
||||
|
||||
- Replace multiple dependencies who's C code compiled concurrently and caused
|
||||
the other ones to bloat compile time significantly.
|
||||
|
||||
- `zstd` -> `brotli`
|
||||
|
||||
- `blake3` -> a vendored version of the blake3 reference
|
||||
|
||||
- `ring` -> `getrandom`
|
||||
|
||||
See https://github.com/tauri-apps/tauri/pull/3773 for more information about
|
||||
these specific choices.
|
||||
|
||||
- [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27
|
||||
|
||||
## \[1.0.0-rc.3]
|
||||
|
||||
- Parse window icons at compile time.
|
||||
- [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05
|
||||
|
||||
## \[1.0.0-rc.2]
|
||||
|
||||
- Changed the default value for `tauri > bundle > macOS > minimumSystemVersion` to `10.13`.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [fce344b9](https://www.github.com/tauri-apps/tauri/commit/fce344b90b7227f8f5514853c2f885fb24d3648e) feat(core): set default value for `minimum_system_version` to 10.13 ([#3497](https://www.github.com/tauri-apps/tauri/pull/3497)) on 2022-02-17
|
||||
|
||||
## \[1.0.0-rc.1]
|
||||
|
||||
- Change default value for the `freezePrototype` configuration to `false`.
|
||||
- Bumped due to a bump in tauri-utils.
|
||||
- [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12
|
||||
|
||||
## \[1.0.0-rc.0]
|
||||
|
||||
- Apply `nonce` to `script` and `style` tags and set them on the `CSP` (`script-src` and `style-src` fetch directives).
|
||||
- [cf54dcf9](https://www.github.com/tauri-apps/tauri/commit/cf54dcf9c81730e42c9171daa9c8aa474c95b522) feat: improve `CSP` security with nonces and hashes, add `devCsp` \[TRI-004] ([#8](https://www.github.com/tauri-apps/tauri/pull/8)) on 2022-01-09
|
||||
- Added the `isolation` pattern.
|
||||
- [d5d6d2ab](https://www.github.com/tauri-apps/tauri/commit/d5d6d2abc17cd89c3a079d2ce01581193469dbc0) Isolation Pattern ([#43](https://www.github.com/tauri-apps/tauri/pull/43)) Co-authored-by: Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com> Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app> on 2022-01-17
|
||||
- Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension.
|
||||
|
||||
Here is the logic flow that determines if JSON or JSON5 will be used to parse the config:
|
||||
|
||||
1. Check if `tauri.conf.json` exists
|
||||
a. Parse it with `serde_json`
|
||||
b. Parse it with `json5` if `serde_json` fails
|
||||
c. Return original `serde_json` error if all above steps failed
|
||||
2. Check if `tauri.conf.json5` exists
|
||||
a. Parse it with `json5`
|
||||
b. Return error if all above steps failed
|
||||
3. Return error if all above steps failed
|
||||
|
||||
- [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03
|
||||
- The minimum Rust version is now `1.56`.
|
||||
- [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22
|
||||
|
||||
## \[1.0.0-beta.4]
|
||||
|
||||
- Embed Info.plist file contents on binary on dev.
|
||||
- [537ab1b6](https://www.github.com/tauri-apps/tauri/commit/537ab1b6d5a792c550a535619965c9e4126292e6) feat(core): inject src-tauri/Info.plist file on dev and merge on bundle, closes [#1570](https://www.github.com/tauri-apps/tauri/pull/1570) [#2338](https://www.github.com/tauri-apps/tauri/pull/2338) ([#2444](https://www.github.com/tauri-apps/tauri/pull/2444)) on 2021-08-15
|
||||
- Fix ES Module detection for default imports with relative paths or scoped packages and exporting of async functions.
|
||||
- [b2b36cfe](https://www.github.com/tauri-apps/tauri/commit/b2b36cfe8dfcccb341638a4cb6dc23a514c54148) fix(core): fixes ES Module detection for default imports with relative paths or scoped packages ([#2380](https://www.github.com/tauri-apps/tauri/pull/2380)) on 2021-08-10
|
||||
- [fbf8caf5](https://www.github.com/tauri-apps/tauri/commit/fbf8caf5c419cb4fc3d123be910e094a8e8c4bef) fix(core): ESM detection when using `export async function` ([#2425](https://www.github.com/tauri-apps/tauri/pull/2425)) on 2021-08-14
|
||||
|
||||
## \[1.0.0-beta.3]
|
||||
|
||||
- Improve ESM detection with regexes.
|
||||
- [4b0ec018](https://www.github.com/tauri-apps/tauri/commit/4b0ec0188078a8fefd4119fe5e19ebc30191f802) fix(core): improve JS ESM detection ([#2139](https://www.github.com/tauri-apps/tauri/pull/2139)) on 2021-07-02
|
||||
- Inject invoke key on `script` tags with `type="module"`.
|
||||
- [f03eea9c](https://www.github.com/tauri-apps/tauri/commit/f03eea9c9b964709532afbc4d1dd343b3fd96081) feat(core): inject invoke key on `<script type="module">` ([#2120](https://www.github.com/tauri-apps/tauri/pull/2120)) on 2021-06-29
|
||||
|
||||
## \[1.0.0-beta.2]
|
||||
|
||||
- Detect ESM scripts and inject the invoke key directly instead of using an IIFE.
|
||||
- [7765c7fa](https://www.github.com/tauri-apps/tauri/commit/7765c7fa281853ddfb26b6b17534df95eaede804) fix(core): invoke key injection on ES module, improve performance ([#2094](https://www.github.com/tauri-apps/tauri/pull/2094)) on 2021-06-27
|
||||
- Improve invoke key code injection performance time rewriting code at compile time.
|
||||
- [7765c7fa](https://www.github.com/tauri-apps/tauri/commit/7765c7fa281853ddfb26b6b17534df95eaede804) fix(core): invoke key injection on ES module, improve performance ([#2094](https://www.github.com/tauri-apps/tauri/pull/2094)) on 2021-06-27
|
||||
|
||||
## \[1.0.0-beta.1]
|
||||
|
||||
- Allow `dev_path` and `dist_dir` to be an array of root files and directories to embed.
|
||||
- [6ec54c53](https://www.github.com/tauri-apps/tauri/commit/6ec54c53b504eec3873d326b1a45e450227d46ed) feat(core): allow `dev_path`, `dist_dir` as array of paths, fixes [#1897](https://www.github.com/tauri-apps/tauri/pull/1897) ([#1926](https://www.github.com/tauri-apps/tauri/pull/1926)) on 2021-05-31
|
||||
- Validate `tauri.conf.json > build > devPath` and `tauri.conf.json > build > distDir` values.
|
||||
- [e97846aa](https://www.github.com/tauri-apps/tauri/commit/e97846aae933cad5cba284a2a133ae7aaee1107c) feat(core): validate `devPath` and `distDir` values ([#1848](https://www.github.com/tauri-apps/tauri/pull/1848)) on 2021-05-17
|
||||
- Read `tauri.conf.json > tauri > bundle > icons` and use the first `.png` icon as window icon on Linux. Defaults to `icon/icon.png` if a PNG icon is not configured.
|
||||
- [40b717ed](https://www.github.com/tauri-apps/tauri/commit/40b717edc57288a1393fad0529390e101ab903c1) feat(core): set window icon on Linux, closes [#1922](https://www.github.com/tauri-apps/tauri/pull/1922) ([#1937](https://www.github.com/tauri-apps/tauri/pull/1937)) on 2021-06-01
|
||||
|
||||
## \[1.0.0-beta.0]
|
||||
|
||||
- **Breaking:** The `assets` field on the `tauri::Context` struct is now a `Arc<impl Assets>`.
|
||||
- [5110c70](https://www.github.com/tauri-apps/tauri/commit/5110c704be67e51d49fb83f3710afb593973dcf9) feat(core): allow users to access the Assets instance ([#1691](https://www.github.com/tauri-apps/tauri/pull/1691)) on 2021-05-03
|
||||
- Reintroduce `csp` injection, configured on `tauri.conf.json > tauri > security > csp`.
|
||||
- [6132f3f](https://www.github.com/tauri-apps/tauri/commit/6132f3f4feb64488ef618f690a4f06adce864d91) feat(core): reintroduce CSP injection ([#1704](https://www.github.com/tauri-apps/tauri/pull/1704)) on 2021-05-04
|
||||
- Added the \`#\[non_exhaustive] attribute where appropriate.
|
||||
- [e087f0f](https://www.github.com/tauri-apps/tauri/commit/e087f0f9374355ac4b4a48f94727ef8b26b1c4cf) feat: add `#[non_exhaustive]` attribute ([#1725](https://www.github.com/tauri-apps/tauri/pull/1725)) on 2021-05-05
|
||||
|
||||
## \[1.0.0-beta-rc.1]
|
||||
|
||||
- The package info APIs now checks the `package` object on `tauri.conf.json`.
|
||||
- [8fd1baf](https://www.github.com/tauri-apps/tauri/commit/8fd1baf69b14bb81d7be9d31605ed7f02058b392) fix(core): pull package info from tauri.conf.json if set ([#1581](https://www.github.com/tauri-apps/tauri/pull/1581)) on 2021-04-22
|
||||
- [f575aaa](https://www.github.com/tauri-apps/tauri/commit/f575aaad71f23d44b2f89cf9ee5d84817dc3bb7a) fix: change files not referencing core packages ([#1619](https://www.github.com/tauri-apps/tauri/pull/1619)) on 2021-04-25
|
||||
|
||||
## \[1.0.0-beta-rc.0]
|
||||
|
||||
- Update all code files to have our license header.
|
||||
- [bf82136](https://www.github.com/tauri-apps/tauri/commit/bf8213646689175f8a158b956911f3a43e360690) feat(license): SPDX Headers ([#1449](https://www.github.com/tauri-apps/tauri/pull/1449)) on 2021-04-11
|
||||
- [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11
|
||||
- [aea6145](https://www.github.com/tauri-apps/tauri/commit/aea614587bddab930d552512b54e18624fbf573e) refactor(repo): add /tooling folder ([#1457](https://www.github.com/tauri-apps/tauri/pull/1457)) on 2021-04-12
|
||||
46
crates/tauri-codegen/Cargo.toml
Normal file
46
crates/tauri-codegen/Cargo.toml
Normal file
@@ -0,0 +1,46 @@
|
||||
[package]
|
||||
name = "tauri-codegen"
|
||||
version = "2.6.3"
|
||||
description = "code generation meant to be consumed inside of `tauri` through `tauri-build` or `tauri-macros`"
|
||||
exclude = ["CHANGELOG.md", "/target"]
|
||||
authors.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
categories.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
sha2 = "0.10"
|
||||
base64 = "0.22"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tauri-utils = { workspace = true, features = ["build-2"] }
|
||||
thiserror = "2"
|
||||
walkdir = "2"
|
||||
brotli = { version = "9", optional = true, default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
semver = "1"
|
||||
ico = "0.5"
|
||||
png = "0.18"
|
||||
json-patch = "4"
|
||||
url = "2"
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies]
|
||||
plist = "1"
|
||||
time = { version = "0.3", features = ["parsing", "formatting"] }
|
||||
|
||||
[features]
|
||||
compression = ["brotli", "tauri-utils/compression"]
|
||||
isolation = ["tauri-utils/isolation"]
|
||||
config-json5 = ["tauri-utils/config-json5"]
|
||||
config-toml = ["tauri-utils/config-toml"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
177
crates/tauri-codegen/LICENSE-APACHE-2.0
Normal file
177
crates/tauri-codegen/LICENSE-APACHE-2.0
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
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
|
||||
21
crates/tauri-codegen/LICENSE-MIT
Normal file
21
crates/tauri-codegen/LICENSE-MIT
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 - Present Tauri Apps Contributors
|
||||
|
||||
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.
|
||||
43
crates/tauri-codegen/README.md
Normal file
43
crates/tauri-codegen/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# tauri-codegen
|
||||
|
||||
<img align="right" src="https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" height="128" width="128">
|
||||
|
||||
[](https://github.com/tauri-apps/tauri)
|
||||
[](https://discord.gg/SpmNs4S)
|
||||
|
||||
[](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml)
|
||||
[](https://tauri.app)
|
||||
|
||||
[](https://good-labs.github.io/greater-good-affirmation)
|
||||
[](https://opencollective.com/tauri)
|
||||
|
||||
| Component | Version |
|
||||
| ------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| tauri-codegen | [](https://crates.io/crates/tauri-codegen) |
|
||||
|
||||
## About Tauri
|
||||
|
||||
Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily.
|
||||
|
||||
Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task.
|
||||
|
||||
## This module
|
||||
|
||||
- Embed, hash, and compress assets, including icons for the app as well as the tray icon.
|
||||
- Parse `tauri.conf.json` at compile time and generate the Config struct.
|
||||
|
||||
To learn more about the details of how all of these pieces fit together, please consult this [ARCHITECTURE.md](https://github.com/tauri-apps/tauri/blob/dev/ARCHITECTURE.md) document.
|
||||
|
||||
## Semver
|
||||
|
||||
**tauri** is following [Semantic Versioning 2.0](https://semver.org/).
|
||||
|
||||
## Licenses
|
||||
|
||||
Code: (c) 2021 - The Tauri Programme within The Commons Conservancy.
|
||||
|
||||
MIT or MIT/Apache 2.0 where applicable.
|
||||
|
||||
Logo: CC-BY-NC-ND
|
||||
|
||||
- Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum)
|
||||
493
crates/tauri-codegen/src/context.rs
Normal file
493
crates/tauri-codegen/src/context.rs
Normal file
@@ -0,0 +1,493 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::identity;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{ffi::OsStr, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
embedded_assets::{
|
||||
AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsResult, ensure_out_dir,
|
||||
},
|
||||
image::CachedIcon,
|
||||
};
|
||||
use base64::Engine;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use sha2::{Digest, Sha256};
|
||||
use syn::Expr;
|
||||
use tauri_utils::{
|
||||
acl::{
|
||||
ACL_MANIFESTS_FILE_NAME, CAPABILITIES_FILE_NAME, get_capabilities, manifest::Manifest,
|
||||
resolved::Resolved,
|
||||
},
|
||||
assets::AssetKey,
|
||||
config::{Config, FrontendDist, PatternKind},
|
||||
html2::{Document, inject_nonce_token, parse_doc, serialize_doc},
|
||||
platform::Target,
|
||||
tokens::{map_lit, str_lit},
|
||||
};
|
||||
|
||||
/// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context.
|
||||
pub struct ContextData {
|
||||
pub dev: bool,
|
||||
pub config: Config,
|
||||
pub config_parent: PathBuf,
|
||||
pub root: TokenStream,
|
||||
/// Additional capabilities to include.
|
||||
pub capabilities: Option<Vec<PathBuf>>,
|
||||
/// The custom assets implementation
|
||||
pub assets: Option<Expr>,
|
||||
/// Skip runtime-only types generation for tests (e.g. embed-plist usage).
|
||||
pub test: bool,
|
||||
}
|
||||
|
||||
fn inject_script_hashes(document: &Document, key: &AssetKey, csp_hashes: &mut CspHashes) {
|
||||
let script_elements = document.select("script:not(:empty)");
|
||||
|
||||
let scripts = script_elements
|
||||
.iter()
|
||||
.map(|element| {
|
||||
let script = tauri_utils::html2::normalize_script_for_csp(element.text().as_bytes());
|
||||
let script_hash = Sha256::digest(script);
|
||||
let hash_base64 = base64::engine::general_purpose::STANDARD.encode(script_hash);
|
||||
|
||||
format!("'sha256-{hash_base64}'")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
csp_hashes
|
||||
.inline_scripts
|
||||
.entry(key.clone().into())
|
||||
.or_default()
|
||||
.extend(scripts);
|
||||
}
|
||||
|
||||
fn map_core_assets(
|
||||
options: &AssetOptions,
|
||||
) -> impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> EmbeddedAssetsResult<()> + use<> {
|
||||
let csp = options.csp;
|
||||
let dangerous_disable_asset_csp_modification =
|
||||
options.dangerous_disable_asset_csp_modification.clone();
|
||||
move |key, path, input, csp_hashes| {
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
#[allow(clippy::collapsible_if)]
|
||||
if csp {
|
||||
let document = parse_doc(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
inject_nonce_token(&document, &dangerous_disable_asset_csp_modification);
|
||||
|
||||
if dangerous_disable_asset_csp_modification.can_modify("script-src") {
|
||||
inject_script_hashes(&document, key, csp_hashes);
|
||||
}
|
||||
|
||||
*input = serialize_doc(&document);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
fn map_isolation(
|
||||
_options: &AssetOptions,
|
||||
dir: PathBuf,
|
||||
) -> impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> EmbeddedAssetsResult<()> + use<> {
|
||||
// create the csp for the isolation iframe styling now, to make the runtime less complex
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(tauri_utils::pattern::isolation::IFRAME_STYLE);
|
||||
let hash = hasher.finalize();
|
||||
let iframe_style_csp_hash = format!(
|
||||
"'sha256-{}'",
|
||||
base64::engine::general_purpose::STANDARD.encode(hash)
|
||||
);
|
||||
|
||||
move |key, path, input, csp_hashes| {
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
let isolation_html = parse_doc(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
// this is appended, so no need to reverse order it
|
||||
tauri_utils::html2::inject_codegen_isolation_script(&isolation_html);
|
||||
|
||||
// temporary workaround for windows not loading assets
|
||||
tauri_utils::html2::inline_isolation(&isolation_html, &dir);
|
||||
|
||||
inject_nonce_token(
|
||||
&isolation_html,
|
||||
&tauri_utils::config::DisabledCspModificationKind::Flag(false),
|
||||
);
|
||||
|
||||
inject_script_hashes(&isolation_html, key, csp_hashes);
|
||||
|
||||
csp_hashes.styles.push(iframe_style_csp_hash.clone());
|
||||
|
||||
*input = serialize_doc(&isolation_html)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a `tauri::Context` for including in application code.
|
||||
pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<TokenStream> {
|
||||
let ContextData {
|
||||
dev,
|
||||
config,
|
||||
config_parent,
|
||||
root,
|
||||
capabilities: additional_capabilities,
|
||||
assets,
|
||||
test,
|
||||
} = data;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
let running_tests = test;
|
||||
|
||||
let target = std::env::var("TAURI_ENV_TARGET_TRIPLE")
|
||||
.as_deref()
|
||||
.map(Target::from_triple)
|
||||
.unwrap_or_else(|_| Target::current());
|
||||
|
||||
let mut options = AssetOptions::new(config.app.security.pattern.clone())
|
||||
.freeze_prototype(config.app.security.freeze_prototype)
|
||||
.dangerous_disable_asset_csp_modification(
|
||||
config
|
||||
.app
|
||||
.security
|
||||
.dangerous_disable_asset_csp_modification
|
||||
.clone(),
|
||||
);
|
||||
let csp = if dev {
|
||||
config
|
||||
.app
|
||||
.security
|
||||
.dev_csp
|
||||
.as_ref()
|
||||
.or(config.app.security.csp.as_ref())
|
||||
} else {
|
||||
config.app.security.csp.as_ref()
|
||||
};
|
||||
if csp.is_some() {
|
||||
options = options.with_csp();
|
||||
}
|
||||
|
||||
let assets = if let Some(assets) = assets {
|
||||
quote!(#assets)
|
||||
} else if dev && config.build.dev_url.is_some() {
|
||||
let assets = EmbeddedAssets::default();
|
||||
quote!(#assets)
|
||||
} else {
|
||||
let assets = match &config.build.frontend_dist {
|
||||
Some(url) => match url {
|
||||
FrontendDist::Url(_url) => Default::default(),
|
||||
FrontendDist::Directory(path) => {
|
||||
let assets_path = config_parent.join(path);
|
||||
if !assets_path.exists() {
|
||||
panic!(
|
||||
"The `frontendDist` configuration is set to `{path:?}` but this path doesn't exist"
|
||||
)
|
||||
}
|
||||
EmbeddedAssets::new(assets_path, &options, map_core_assets(&options))?
|
||||
}
|
||||
FrontendDist::Files(files) => EmbeddedAssets::new(
|
||||
files
|
||||
.iter()
|
||||
.map(|p| config_parent.join(p))
|
||||
.collect::<Vec<_>>(),
|
||||
&options,
|
||||
map_core_assets(&options),
|
||||
)?,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
None => Default::default(),
|
||||
};
|
||||
quote!(#assets)
|
||||
};
|
||||
|
||||
let out_dir = ensure_out_dir()?;
|
||||
|
||||
let default_window_icon = {
|
||||
if target == Target::Windows {
|
||||
// handle default window icons for Windows targets
|
||||
quote!(#root::image::default_window_icon_from_app_icon_resource())
|
||||
} else {
|
||||
// handle default window icons for Unix targets
|
||||
let icon_path = find_icon(
|
||||
&config,
|
||||
&config_parent,
|
||||
|i| i.ends_with(".png"),
|
||||
"icons/icon.png",
|
||||
);
|
||||
let icon = CachedIcon::new(&root, &icon_path)?;
|
||||
quote!(::std::option::Option::Some(#icon))
|
||||
}
|
||||
};
|
||||
|
||||
let app_icon = if target == Target::MacOS && dev {
|
||||
let mut icon_path = find_icon(
|
||||
&config,
|
||||
&config_parent,
|
||||
|i| i.ends_with(".icns"),
|
||||
"icons/icon.png",
|
||||
);
|
||||
if !icon_path.exists() {
|
||||
icon_path = find_icon(
|
||||
&config,
|
||||
&config_parent,
|
||||
|i| i.ends_with(".png"),
|
||||
"icons/icon.png",
|
||||
);
|
||||
}
|
||||
|
||||
let icon = CachedIcon::new_raw(&root, &icon_path)?;
|
||||
quote!(::std::option::Option::Some(#icon.to_vec()))
|
||||
} else {
|
||||
quote!(::std::option::Option::None)
|
||||
};
|
||||
|
||||
let package_name = if let Some(product_name) = &config.product_name {
|
||||
quote!(#product_name.to_string())
|
||||
} else {
|
||||
quote!(env!("CARGO_PKG_NAME").to_string())
|
||||
};
|
||||
let package_version = if let Some(version) = &config.version {
|
||||
semver::Version::from_str(version)?;
|
||||
quote!(#version.to_string())
|
||||
} else {
|
||||
quote!(env!("CARGO_PKG_VERSION").to_string())
|
||||
};
|
||||
let package_info = quote!(
|
||||
#root::PackageInfo {
|
||||
name: #package_name,
|
||||
version: #package_version.parse().unwrap(),
|
||||
authors: env!("CARGO_PKG_AUTHORS"),
|
||||
description: env!("CARGO_PKG_DESCRIPTION"),
|
||||
crate_name: env!("CARGO_PKG_NAME"),
|
||||
}
|
||||
);
|
||||
|
||||
let with_tray_icon_code = if target.is_desktop() {
|
||||
if let Some(tray) = &config.app.tray_icon {
|
||||
let tray_icon_icon_path = config_parent.join(&tray.icon_path);
|
||||
let icon = CachedIcon::new(&root, &tray_icon_icon_path)?;
|
||||
quote!(context.set_tray_icon(::std::option::Option::Some(#icon));)
|
||||
} else {
|
||||
quote!()
|
||||
}
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let maybe_embed_plist_block = if target == Target::MacOS && dev && !running_tests {
|
||||
let info_plist_path = config_parent.join("Info.plist");
|
||||
let mut info_plist = if info_plist_path.exists() {
|
||||
plist::Value::from_file(&info_plist_path)
|
||||
.unwrap_or_else(|e| panic!("failed to read plist {}: {}", info_plist_path.display(), e))
|
||||
} else {
|
||||
plist::Value::Dictionary(Default::default())
|
||||
};
|
||||
|
||||
if let Some(plist) = info_plist.as_dictionary_mut() {
|
||||
if let Some(bundle_name) = config
|
||||
.bundle
|
||||
.macos
|
||||
.bundle_name
|
||||
.as_ref()
|
||||
.or(config.product_name.as_ref())
|
||||
{
|
||||
plist.insert("CFBundleName".into(), bundle_name.as_str().into());
|
||||
}
|
||||
|
||||
if let Some(version) = &config.version {
|
||||
let bundle_version = &config.bundle.macos.bundle_version;
|
||||
plist.insert("CFBundleShortVersionString".into(), version.clone().into());
|
||||
plist.insert(
|
||||
"CFBundleVersion".into(),
|
||||
bundle_version
|
||||
.clone()
|
||||
.unwrap_or_else(|| version.clone())
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut plist_contents = std::io::BufWriter::new(Vec::new());
|
||||
info_plist
|
||||
.to_writer_xml(&mut plist_contents)
|
||||
.expect("failed to serialize plist");
|
||||
let plist_contents =
|
||||
String::from_utf8_lossy(&plist_contents.into_inner().unwrap()).into_owned();
|
||||
|
||||
let plist = crate::Cached::try_from(plist_contents)?;
|
||||
quote!({
|
||||
tauri::embed_plist::embed_info_plist!(#plist);
|
||||
})
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let maybe_embed_plist_block = quote!();
|
||||
|
||||
let pattern = match &options.pattern {
|
||||
PatternKind::Brownfield => quote!(#root::Pattern::Brownfield),
|
||||
#[cfg(not(feature = "isolation"))]
|
||||
PatternKind::Isolation { dir: _ } => {
|
||||
quote!(#root::Pattern::Brownfield)
|
||||
}
|
||||
#[cfg(feature = "isolation")]
|
||||
PatternKind::Isolation { dir } => {
|
||||
let dir = config_parent.join(dir);
|
||||
if !dir.exists() {
|
||||
panic!("The isolation application path is set to `{dir:?}` but it does not exist")
|
||||
}
|
||||
|
||||
let mut sets_isolation_hook = false;
|
||||
|
||||
let key = uuid::Uuid::new_v4().to_string();
|
||||
let map_isolation = map_isolation(&options, dir.clone());
|
||||
let assets = EmbeddedAssets::new(dir, &options, |key, path, input, csp_hashes| {
|
||||
// we check if `__TAURI_ISOLATION_HOOK__` exists in the isolation code
|
||||
// before modifying the files since we inject our own `__TAURI_ISOLATION_HOOK__` reference in HTML files
|
||||
if String::from_utf8_lossy(input).contains("__TAURI_ISOLATION_HOOK__") {
|
||||
sets_isolation_hook = true;
|
||||
}
|
||||
map_isolation(key, path, input, csp_hashes)
|
||||
})?;
|
||||
|
||||
if !sets_isolation_hook {
|
||||
panic!(
|
||||
"The isolation application does not contain a file setting the `window.__TAURI_ISOLATION_HOOK__` value."
|
||||
);
|
||||
}
|
||||
|
||||
let schema = options.isolation_schema;
|
||||
|
||||
quote!(#root::Pattern::Isolation {
|
||||
assets: ::std::sync::Arc::new(#assets),
|
||||
schema: #schema.into(),
|
||||
key: #key.into(),
|
||||
crypto_keys: std::boxed::Box::new(::tauri::utils::pattern::isolation::Keys::new().expect("unable to generate cryptographically secure keys for Tauri \"Isolation\" Pattern")),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let acl_file_path = out_dir.join(ACL_MANIFESTS_FILE_NAME);
|
||||
let acl: BTreeMap<String, Manifest> = if acl_file_path.exists() {
|
||||
let acl_file =
|
||||
std::fs::read_to_string(acl_file_path).expect("failed to read plugin manifest map");
|
||||
serde_json::from_str(&acl_file).expect("failed to parse plugin manifest map")
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let capabilities_file_path = out_dir.join(CAPABILITIES_FILE_NAME);
|
||||
let capabilities_from_files = if capabilities_file_path.exists() {
|
||||
let capabilities_json =
|
||||
std::fs::read_to_string(&capabilities_file_path).expect("failed to read capabilities");
|
||||
serde_json::from_str(&capabilities_json).expect("failed to parse capabilities")
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let capabilities = get_capabilities(
|
||||
&config,
|
||||
capabilities_from_files,
|
||||
additional_capabilities.as_deref(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let resolved = Resolved::resolve(&acl, capabilities, target).expect("failed to resolve ACL");
|
||||
|
||||
let acl_tokens = map_lit(
|
||||
quote! { ::std::collections::BTreeMap },
|
||||
&acl,
|
||||
str_lit,
|
||||
identity,
|
||||
);
|
||||
|
||||
let runtime_authority = quote!(#root::runtime_authority!(#acl_tokens, #resolved));
|
||||
|
||||
let plugin_global_api_scripts = if config.app.with_global_tauri {
|
||||
if let Some(scripts) = tauri_utils::plugin::read_global_api_scripts(&out_dir) {
|
||||
let scripts = scripts.into_iter().map(|s| quote!(#s));
|
||||
quote!(::std::option::Option::Some(&[#(#scripts),*]))
|
||||
} else {
|
||||
quote!(::std::option::Option::None)
|
||||
}
|
||||
} else {
|
||||
quote!(::std::option::Option::None)
|
||||
};
|
||||
|
||||
let maybe_config_parent_setter = if dev {
|
||||
let config_parent = config_parent.to_string_lossy();
|
||||
quote!({
|
||||
context.with_config_parent(#config_parent);
|
||||
})
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
let context = quote!({
|
||||
#maybe_embed_plist_block
|
||||
|
||||
#[allow(unused_mut, clippy::let_and_return)]
|
||||
let mut context = #root::Context::new(
|
||||
#config,
|
||||
::std::boxed::Box::new(assets),
|
||||
#default_window_icon,
|
||||
#app_icon,
|
||||
#package_info,
|
||||
#pattern,
|
||||
#runtime_authority,
|
||||
#plugin_global_api_scripts
|
||||
);
|
||||
|
||||
#with_tray_icon_code
|
||||
#maybe_config_parent_setter
|
||||
|
||||
context
|
||||
});
|
||||
|
||||
// Wrapping in a function to make rust analyzer faster,
|
||||
// see https://github.com/tauri-apps/tauri/pull/14457
|
||||
// We take the assets as an argument so when the caller provides custom `assets` the closure
|
||||
// does not capture from the caller's scope ("can't capture dynamic environment in a fn item").
|
||||
let output = quote!({
|
||||
fn inner<R: #root::Runtime, A: #root::Assets<R> + 'static>(assets: A) -> #root::Context<R> {
|
||||
let thread = ::std::thread::Builder::new()
|
||||
.name(String::from("generated tauri context creation"))
|
||||
.stack_size(8 * 1024 * 1024)
|
||||
.spawn(move || #context)
|
||||
.expect("unable to create thread with 8MiB stack");
|
||||
|
||||
match thread.join() {
|
||||
Ok(context) => context,
|
||||
Err(_) => {
|
||||
eprintln!("the generated Tauri `Context` panicked during creation");
|
||||
::std::process::exit(101);
|
||||
}
|
||||
}
|
||||
}
|
||||
inner(#assets)
|
||||
});
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn find_icon(
|
||||
config: &Config,
|
||||
config_parent: &Path,
|
||||
predicate: impl Fn(&&String) -> bool,
|
||||
default: &str,
|
||||
) -> PathBuf {
|
||||
let icon_path = config
|
||||
.bundle
|
||||
.icon
|
||||
.iter()
|
||||
.find(predicate)
|
||||
.map(AsRef::as_ref)
|
||||
.unwrap_or(default);
|
||||
config_parent.join(icon_path)
|
||||
}
|
||||
452
crates/tauri-codegen/src/embedded_assets.rs
Normal file
452
crates/tauri-codegen/src/embedded_assets.rs
Normal file
@@ -0,0 +1,452 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use base64::Engine;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt, quote};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
fs::File,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use tauri_utils::config::PatternKind;
|
||||
use tauri_utils::{assets::AssetKey, config::DisabledCspModificationKind};
|
||||
use thiserror::Error;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
#[cfg(feature = "compression")]
|
||||
use brotli::enc::backward_references::BrotliEncoderParams;
|
||||
|
||||
/// The subdirectory inside the target directory we want to place assets.
|
||||
const TARGET_PATH: &str = "tauri-codegen-assets";
|
||||
|
||||
/// (key, (original filepath, compressed bytes))
|
||||
type Asset = (AssetKey, (PathBuf, PathBuf));
|
||||
|
||||
/// All possible errors while reading and compressing an [`EmbeddedAssets`] directory
|
||||
#[derive(Debug, Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum EmbeddedAssetsError {
|
||||
#[error("failed to read asset at {path} because {error}")]
|
||||
AssetRead {
|
||||
path: PathBuf,
|
||||
error: std::io::Error,
|
||||
},
|
||||
|
||||
#[error("failed to write asset from {path} to Vec<u8> because {error}")]
|
||||
AssetWrite {
|
||||
path: PathBuf,
|
||||
error: std::io::Error,
|
||||
},
|
||||
|
||||
#[error("failed to create hex from bytes because {0}")]
|
||||
Hex(std::fmt::Error),
|
||||
|
||||
#[error("invalid prefix {prefix} used while including path {path}")]
|
||||
PrefixInvalid { prefix: PathBuf, path: PathBuf },
|
||||
|
||||
#[error("invalid extension `{extension}` used for image {path}, must be `ico` or `png`")]
|
||||
InvalidImageExtension { extension: PathBuf, path: PathBuf },
|
||||
|
||||
#[error("failed to walk directory {path} because {error}")]
|
||||
Walkdir {
|
||||
path: PathBuf,
|
||||
error: walkdir::Error,
|
||||
},
|
||||
|
||||
#[error("OUT_DIR env var is not set, do you have a build script?")]
|
||||
OutDir,
|
||||
|
||||
#[error("version error: {0}")]
|
||||
Version(#[from] semver::Error),
|
||||
}
|
||||
|
||||
pub type EmbeddedAssetsResult<T> = Result<T, EmbeddedAssetsError>;
|
||||
|
||||
/// Represent a directory of assets that are compressed and embedded.
|
||||
///
|
||||
/// This is the compile time generation of [`tauri_utils::assets::Assets`] from a directory. Assets
|
||||
/// from the directory are added as compiler dependencies by dummy including the original,
|
||||
/// uncompressed assets.
|
||||
///
|
||||
/// The assets are compressed during this runtime, and can only be represented as a [`TokenStream`]
|
||||
/// through [`ToTokens`]. The generated code is meant to be injected into an application to include
|
||||
/// the compressed assets in that application's binary.
|
||||
#[derive(Default)]
|
||||
pub struct EmbeddedAssets {
|
||||
assets: BTreeMap<AssetKey, (PathBuf, PathBuf)>,
|
||||
csp_hashes: CspHashes,
|
||||
}
|
||||
|
||||
pub struct EmbeddedAssetsInput(Vec<PathBuf>);
|
||||
|
||||
impl From<PathBuf> for EmbeddedAssetsInput {
|
||||
fn from(path: PathBuf) -> Self {
|
||||
Self(vec![path])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<PathBuf>> for EmbeddedAssetsInput {
|
||||
fn from(paths: Vec<PathBuf>) -> Self {
|
||||
Self(paths)
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds a list of (prefix, entry)
|
||||
struct RawEmbeddedAssets {
|
||||
paths: Vec<(PathBuf, DirEntry)>,
|
||||
csp_hashes: CspHashes,
|
||||
}
|
||||
|
||||
impl RawEmbeddedAssets {
|
||||
/// Creates a new list of (prefix, entry) from a collection of inputs.
|
||||
fn new(input: EmbeddedAssetsInput, options: &AssetOptions) -> Result<Self, EmbeddedAssetsError> {
|
||||
let mut csp_hashes = CspHashes::default();
|
||||
|
||||
input
|
||||
.0
|
||||
.into_iter()
|
||||
.flat_map(|path| {
|
||||
let prefix = if path.is_dir() {
|
||||
path.clone()
|
||||
} else {
|
||||
path
|
||||
.parent()
|
||||
.expect("embedded file asset has no parent")
|
||||
.to_path_buf()
|
||||
};
|
||||
|
||||
WalkDir::new(&path)
|
||||
.follow_links(true)
|
||||
.contents_first(true)
|
||||
.into_iter()
|
||||
.map(move |entry| (prefix.clone(), entry))
|
||||
})
|
||||
.filter_map(|(prefix, entry)| {
|
||||
match entry {
|
||||
// we only serve files, not directory listings
|
||||
Ok(entry) if entry.file_type().is_dir() => None,
|
||||
|
||||
// compress all files encountered
|
||||
Ok(entry) => {
|
||||
if let Err(error) = csp_hashes
|
||||
.add_if_applicable(&entry, &options.dangerous_disable_asset_csp_modification)
|
||||
{
|
||||
Some(Err(error))
|
||||
} else {
|
||||
Some(Ok((prefix, entry)))
|
||||
}
|
||||
}
|
||||
|
||||
// pass down error through filter to fail when encountering any error
|
||||
Err(error) => Some(Err(EmbeddedAssetsError::Walkdir {
|
||||
path: prefix,
|
||||
error,
|
||||
})),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<(PathBuf, DirEntry)>, _>>()
|
||||
.map(|paths| Self { paths, csp_hashes })
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds all hashes that we will apply on the CSP tag/header.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CspHashes {
|
||||
/// Scripts that are part of the asset collection (JS or MJS files).
|
||||
pub(crate) scripts: Vec<String>,
|
||||
/// Inline scripts (`<script>code</script>`). Maps a HTML path to a list of hashes.
|
||||
pub(crate) inline_scripts: BTreeMap<String, Vec<String>>,
|
||||
/// A list of hashes of the contents of all `style` elements.
|
||||
pub(crate) styles: Vec<String>,
|
||||
}
|
||||
|
||||
impl CspHashes {
|
||||
/// Only add a CSP hash to the appropriate category if we think the file matches
|
||||
///
|
||||
/// Note: this only checks the file extension, much like how a browser will assume a .js file is
|
||||
/// a JavaScript file unless HTTP headers tell it otherwise.
|
||||
pub fn add_if_applicable(
|
||||
&mut self,
|
||||
entry: &DirEntry,
|
||||
dangerous_disable_asset_csp_modification: &DisabledCspModificationKind,
|
||||
) -> Result<(), EmbeddedAssetsError> {
|
||||
let path = entry.path();
|
||||
|
||||
// we only hash JavaScript files for now, may expand to other CSP hashable types in the future
|
||||
if let Some("js") | Some("mjs") = path.extension().and_then(|os| os.to_str()) {
|
||||
if dangerous_disable_asset_csp_modification.can_modify("script-src") {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(
|
||||
&std::fs::read(path)
|
||||
.map(|b| tauri_utils::html2::normalize_script_for_csp(&b))
|
||||
.map_err(|error| EmbeddedAssetsError::AssetRead {
|
||||
path: path.to_path_buf(),
|
||||
error,
|
||||
})?,
|
||||
);
|
||||
let hash = hasher.finalize();
|
||||
self.scripts.push(format!(
|
||||
"'sha256-{}'",
|
||||
base64::engine::general_purpose::STANDARD.encode(hash)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Options used to embed assets.
|
||||
#[derive(Default)]
|
||||
pub struct AssetOptions {
|
||||
pub(crate) csp: bool,
|
||||
pub(crate) pattern: PatternKind,
|
||||
pub(crate) freeze_prototype: bool,
|
||||
pub(crate) dangerous_disable_asset_csp_modification: DisabledCspModificationKind,
|
||||
#[cfg(feature = "isolation")]
|
||||
pub(crate) isolation_schema: String,
|
||||
}
|
||||
|
||||
impl AssetOptions {
|
||||
/// Creates the default asset options.
|
||||
pub fn new(pattern: PatternKind) -> Self {
|
||||
Self {
|
||||
csp: false,
|
||||
pattern,
|
||||
freeze_prototype: false,
|
||||
dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
|
||||
#[cfg(feature = "isolation")]
|
||||
isolation_schema: format!("isolation-{}", uuid::Uuid::new_v4()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Instruct the asset handler to inject the CSP token to HTML files (Linux only) and add asset nonces and hashes to the policy.
|
||||
#[must_use]
|
||||
pub fn with_csp(mut self) -> Self {
|
||||
self.csp = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Instruct the asset handler to include a script to freeze the `Object.prototype` on all HTML files.
|
||||
#[must_use]
|
||||
pub fn freeze_prototype(mut self, freeze: bool) -> Self {
|
||||
self.freeze_prototype = freeze;
|
||||
self
|
||||
}
|
||||
|
||||
/// Instruct the asset handler to **NOT** modify the CSP. This is **NOT** recommended.
|
||||
pub fn dangerous_disable_asset_csp_modification(
|
||||
mut self,
|
||||
dangerous_disable_asset_csp_modification: DisabledCspModificationKind,
|
||||
) -> Self {
|
||||
self.dangerous_disable_asset_csp_modification = dangerous_disable_asset_csp_modification;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl EmbeddedAssets {
|
||||
/// Compress a collection of files and directories, ready to be generated into [`Assets`].
|
||||
///
|
||||
/// [`Assets`]: tauri_utils::assets::Assets
|
||||
pub fn new(
|
||||
input: impl Into<EmbeddedAssetsInput>,
|
||||
options: &AssetOptions,
|
||||
mut map: impl FnMut(
|
||||
&AssetKey,
|
||||
&Path,
|
||||
&mut Vec<u8>,
|
||||
&mut CspHashes,
|
||||
) -> Result<(), EmbeddedAssetsError>,
|
||||
) -> Result<Self, EmbeddedAssetsError> {
|
||||
// we need to pre-compute all files now, so that we can inject data from all files into a few
|
||||
let RawEmbeddedAssets { paths, csp_hashes } = RawEmbeddedAssets::new(input.into(), options)?;
|
||||
|
||||
struct CompressState {
|
||||
csp_hashes: CspHashes,
|
||||
assets: BTreeMap<AssetKey, (PathBuf, PathBuf)>,
|
||||
}
|
||||
|
||||
let CompressState { assets, csp_hashes } = paths.into_iter().try_fold(
|
||||
CompressState {
|
||||
csp_hashes,
|
||||
assets: BTreeMap::new(),
|
||||
},
|
||||
move |mut state, (prefix, entry)| {
|
||||
let (key, asset) =
|
||||
Self::compress_file(&prefix, entry.path(), &mut map, &mut state.csp_hashes)?;
|
||||
state.assets.insert(key, asset);
|
||||
Result::<_, EmbeddedAssetsError>::Ok(state)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self { assets, csp_hashes })
|
||||
}
|
||||
|
||||
/// Use highest compression level for release, the fastest one for everything else
|
||||
#[cfg(feature = "compression")]
|
||||
fn compression_settings() -> BrotliEncoderParams {
|
||||
let mut settings = BrotliEncoderParams::default();
|
||||
|
||||
// the following compression levels are hand-picked and are not min-maxed.
|
||||
// they have a good balance of runtime vs size for the respective profile goals.
|
||||
// see the "brotli" section of this comment https://github.com/tauri-apps/tauri/issues/3571#issuecomment-1054847558
|
||||
if cfg!(debug_assertions) {
|
||||
settings.quality = 2
|
||||
} else {
|
||||
settings.quality = 9
|
||||
}
|
||||
|
||||
settings
|
||||
}
|
||||
|
||||
/// Compress a file and spit out the information in a [`BTreeMap`] friendly form.
|
||||
fn compress_file(
|
||||
prefix: &Path,
|
||||
path: &Path,
|
||||
map: &mut impl FnMut(
|
||||
&AssetKey,
|
||||
&Path,
|
||||
&mut Vec<u8>,
|
||||
&mut CspHashes,
|
||||
) -> Result<(), EmbeddedAssetsError>,
|
||||
csp_hashes: &mut CspHashes,
|
||||
) -> Result<Asset, EmbeddedAssetsError> {
|
||||
let mut input = std::fs::read(path).map_err(|error| EmbeddedAssetsError::AssetRead {
|
||||
path: path.to_owned(),
|
||||
error,
|
||||
})?;
|
||||
|
||||
// get a key to the asset path without the asset directory prefix
|
||||
let key = path
|
||||
.strip_prefix(prefix)
|
||||
.map(AssetKey::from) // format the path for use in assets
|
||||
.map_err(|_| EmbeddedAssetsError::PrefixInvalid {
|
||||
prefix: prefix.to_owned(),
|
||||
path: path.to_owned(),
|
||||
})?;
|
||||
|
||||
// perform any caller-requested input manipulation
|
||||
map(&key, path, &mut input, csp_hashes)?;
|
||||
|
||||
// we must canonicalize the base of our paths to allow long paths on windows
|
||||
let out_dir = std::env::var("OUT_DIR")
|
||||
.map_err(|_| EmbeddedAssetsError::OutDir)
|
||||
.map(PathBuf::from)
|
||||
.and_then(|p| p.canonicalize().map_err(|_| EmbeddedAssetsError::OutDir))
|
||||
.map(|p| p.join(TARGET_PATH))?;
|
||||
|
||||
// make sure that our output directory is created
|
||||
std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?;
|
||||
|
||||
// get a hash of the input - allows for caching existing files
|
||||
let hash = crate::checksum(&input).map_err(EmbeddedAssetsError::Hex)?;
|
||||
|
||||
// use the content hash to determine filename, keep extensions that exist
|
||||
let out_path = if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
|
||||
out_dir.join(format!("{hash}.{ext}"))
|
||||
} else {
|
||||
out_dir.join(hash)
|
||||
};
|
||||
|
||||
// only compress and write to the file if it doesn't already exist.
|
||||
if !out_path.exists() {
|
||||
#[allow(unused_mut)]
|
||||
let mut out_file =
|
||||
File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
|
||||
path: out_path.clone(),
|
||||
error,
|
||||
})?;
|
||||
|
||||
#[cfg(not(feature = "compression"))]
|
||||
{
|
||||
use std::io::Write;
|
||||
out_file
|
||||
.write_all(&input)
|
||||
.map_err(|error| EmbeddedAssetsError::AssetWrite {
|
||||
path: path.to_owned(),
|
||||
error,
|
||||
})?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "compression")]
|
||||
{
|
||||
let mut input = std::io::Cursor::new(input);
|
||||
// entirely write input to the output file path with compression
|
||||
brotli::BrotliCompress(&mut input, &mut out_file, &Self::compression_settings()).map_err(
|
||||
|error| EmbeddedAssetsError::AssetWrite {
|
||||
path: path.to_owned(),
|
||||
error,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok((key, (path.into(), out_path)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for EmbeddedAssets {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let mut assets = TokenStream::new();
|
||||
for (key, (input, output)) in &self.assets {
|
||||
let key: &str = key.as_ref();
|
||||
let input = input.display().to_string();
|
||||
let output = output.display().to_string();
|
||||
|
||||
// add original asset as a compiler dependency, rely on dead code elimination to clean it up
|
||||
assets.append_all(quote!(#key => {
|
||||
const _: &[u8] = include_bytes!(#input);
|
||||
include_bytes!(#output)
|
||||
},));
|
||||
}
|
||||
|
||||
let mut global_hashes = TokenStream::new();
|
||||
// Sort the hashes so the generated code does not depend on the filesystem
|
||||
// walk order the assets were collected in, which varies across machines
|
||||
let mut script_hashes: Vec<_> = self.csp_hashes.scripts.iter().collect();
|
||||
script_hashes.sort();
|
||||
for script_hash in script_hashes {
|
||||
let hash = script_hash.as_str();
|
||||
global_hashes.append_all(quote!(CspHash::Script(#hash),));
|
||||
}
|
||||
|
||||
let mut style_hashes: Vec<_> = self.csp_hashes.styles.iter().collect();
|
||||
style_hashes.sort();
|
||||
for style_hash in style_hashes {
|
||||
let hash = style_hash.as_str();
|
||||
global_hashes.append_all(quote!(CspHash::Style(#hash),));
|
||||
}
|
||||
|
||||
let mut html_hashes = TokenStream::new();
|
||||
for (path, hashes) in &self.csp_hashes.inline_scripts {
|
||||
let key = path.as_str();
|
||||
let mut value = TokenStream::new();
|
||||
for script_hash in hashes {
|
||||
let hash = script_hash.as_str();
|
||||
value.append_all(quote!(CspHash::Script(#hash),));
|
||||
}
|
||||
html_hashes.append_all(quote!(#key => &[#value],));
|
||||
}
|
||||
|
||||
// we expect phf related items to be in path when generating the path code
|
||||
tokens.append_all(quote! {{
|
||||
#[allow(unused_imports)]
|
||||
use ::tauri::utils::assets::{CspHash, EmbeddedAssets, phf, phf::phf_map};
|
||||
EmbeddedAssets::new(phf_map! { #assets }, &[#global_hashes], phf_map! { #html_hashes })
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_out_dir() -> EmbeddedAssetsResult<PathBuf> {
|
||||
let out_dir = std::env::var("OUT_DIR")
|
||||
.map_err(|_| EmbeddedAssetsError::OutDir)
|
||||
.map(PathBuf::from)
|
||||
.and_then(|p| p.canonicalize().map_err(|_| EmbeddedAssetsError::OutDir))?;
|
||||
|
||||
// make sure that our output directory is created
|
||||
std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?;
|
||||
Ok(out_dir)
|
||||
}
|
||||
208
crates/tauri-codegen/src/image.rs
Normal file
208
crates/tauri-codegen/src/image.rs
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{
|
||||
Cached,
|
||||
embedded_assets::{EmbeddedAssetsError, EmbeddedAssetsResult},
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt, quote};
|
||||
use std::{ffi::OsStr, io::Cursor, path::Path};
|
||||
|
||||
/// The format the Icon is consumed as.
|
||||
pub(crate) enum IconFormat {
|
||||
/// The image, completely unmodified.
|
||||
Raw,
|
||||
|
||||
/// RGBA raw data, meant to be consumed by [`tauri::image::Image`].
|
||||
Image { width: u32, height: u32 },
|
||||
}
|
||||
|
||||
pub struct CachedIcon {
|
||||
cache: Cached,
|
||||
format: IconFormat,
|
||||
root: TokenStream,
|
||||
}
|
||||
|
||||
impl CachedIcon {
|
||||
pub fn new(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult<Self> {
|
||||
match icon.extension().map(OsStr::to_string_lossy).as_deref() {
|
||||
Some("png") => Self::new_png(root, icon),
|
||||
Some("ico") => Self::new_ico(root, icon),
|
||||
unknown => Err(EmbeddedAssetsError::InvalidImageExtension {
|
||||
extension: unknown.unwrap_or_default().into(),
|
||||
path: icon.to_path_buf(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cache the icon without any manipulation.
|
||||
pub fn new_raw(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult<Self> {
|
||||
let buf = Self::open(icon);
|
||||
Cached::try_from(buf).map(|cache| Self {
|
||||
cache,
|
||||
root: root.clone(),
|
||||
format: IconFormat::Raw,
|
||||
})
|
||||
}
|
||||
|
||||
/// Cache an ICO icon as RGBA data, see [`ImageFormat::Image`].
|
||||
pub fn new_ico(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult<Self> {
|
||||
let buf = Self::open(icon);
|
||||
|
||||
let icon_dir = ico::IconDir::read(Cursor::new(&buf))
|
||||
.unwrap_or_else(|e| panic!("failed to parse icon {}: {}", icon.display(), e));
|
||||
|
||||
let entry = largest_ico_entry(&icon_dir)
|
||||
.unwrap_or_else(|| panic!("icon {} has no entries", icon.display()));
|
||||
let rgba = entry
|
||||
.decode()
|
||||
.unwrap_or_else(|e| panic!("failed to decode icon {}: {}", icon.display(), e))
|
||||
.rgba_data()
|
||||
.to_vec();
|
||||
|
||||
Cached::try_from(rgba).map(|cache| Self {
|
||||
cache,
|
||||
root: root.clone(),
|
||||
format: IconFormat::Image {
|
||||
width: entry.width(),
|
||||
height: entry.height(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Cache a PNG icon as RGBA data, see [`ImageFormat::Image`].
|
||||
pub fn new_png(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult<Self> {
|
||||
let buf = Self::open(icon);
|
||||
let decoder = png::Decoder::new(Cursor::new(&buf));
|
||||
let mut reader = decoder
|
||||
.read_info()
|
||||
.unwrap_or_else(|e| panic!("failed to read icon {}: {}", icon.display(), e));
|
||||
|
||||
if reader.output_color_type().0 != png::ColorType::Rgba {
|
||||
panic!("icon {} is not RGBA", icon.display());
|
||||
}
|
||||
|
||||
let mut rgba = Vec::with_capacity(reader.output_buffer_size().unwrap());
|
||||
while let Ok(Some(row)) = reader.next_row() {
|
||||
rgba.extend(row.data());
|
||||
}
|
||||
|
||||
Cached::try_from(rgba).map(|cache| Self {
|
||||
cache,
|
||||
root: root.clone(),
|
||||
format: IconFormat::Image {
|
||||
width: reader.info().width,
|
||||
height: reader.info().height,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn open(path: &Path) -> Vec<u8> {
|
||||
std::fs::read(path).unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e))
|
||||
}
|
||||
}
|
||||
|
||||
/// Picks the entry of an ICO file to embed: the largest one (and, for equal sizes, the deepest).
|
||||
///
|
||||
/// ICO files conventionally store entries smallest-first, so taking the first entry would give
|
||||
/// the OS a 16x16 image to upscale; the largest entry lets it downscale a high-resolution source instead.
|
||||
fn largest_ico_entry(icon_dir: &ico::IconDir) -> Option<&ico::IconDirEntry> {
|
||||
icon_dir
|
||||
.entries()
|
||||
.iter()
|
||||
.max_by_key(|e| (e.width() * e.height(), e.bits_per_pixel()))
|
||||
}
|
||||
|
||||
impl ToTokens for CachedIcon {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let root = &self.root;
|
||||
let cache = &self.cache;
|
||||
let raw = quote!(::std::include_bytes!(#cache));
|
||||
tokens.append_all(match self.format {
|
||||
IconFormat::Raw => raw,
|
||||
IconFormat::Image { width, height } => {
|
||||
quote!(#root::image::Image::new(#raw, #width, #height))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::largest_ico_entry;
|
||||
use ico::{IconDir, IconDirEntry, IconImage, ResourceType};
|
||||
use std::io::Cursor;
|
||||
|
||||
fn image(size: u32, alpha: u8) -> IconImage {
|
||||
let rgba = [255, 0, 0, alpha].repeat((size * size) as usize);
|
||||
IconImage::from_rgba_data(size, size, rgba)
|
||||
}
|
||||
|
||||
/// Builds an ICO with an opaque entry for each size, in the given order, and reads it back
|
||||
/// through the same parser `CachedIcon::new_ico` uses.
|
||||
fn icon_dir(sizes: &[u32]) -> IconDir {
|
||||
let mut dir = IconDir::new(ResourceType::Icon);
|
||||
for &size in sizes {
|
||||
let entry = if size == 256 {
|
||||
IconDirEntry::encode_as_png(&image(size, 255)).unwrap()
|
||||
} else {
|
||||
IconDirEntry::encode_as_bmp(&image(size, 255)).unwrap()
|
||||
};
|
||||
dir.add_entry(entry);
|
||||
}
|
||||
let mut buf = Vec::new();
|
||||
dir.write(&mut buf).unwrap();
|
||||
IconDir::read(Cursor::new(buf)).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn picks_largest_entry_regardless_of_order() {
|
||||
// the entry order `tauri icon` used to generate, with the PNG-compressed 256 entry last
|
||||
let dir = icon_dir(&[32, 16, 24, 48, 64, 256]);
|
||||
let entry = largest_ico_entry(&dir).unwrap();
|
||||
assert_eq!((entry.width(), entry.height()), (256, 256));
|
||||
assert!(entry.is_png());
|
||||
|
||||
// largest first, in the middle and alone
|
||||
for sizes in [&[64, 48, 16][..], &[16, 64, 48], &[64]] {
|
||||
let dir = icon_dir(sizes);
|
||||
let entry = largest_ico_entry(&dir).unwrap();
|
||||
assert_eq!((entry.width(), entry.height()), (64, 64), "{sizes:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn picks_deepest_entry_for_equal_sizes() {
|
||||
// a single opaque color encodes as a low-depth BMP, a translucent one needs 32bpp
|
||||
let shallow = IconDirEntry::encode_as_bmp(&image(32, 255)).unwrap();
|
||||
let deep = IconDirEntry::encode_as_bmp(&image(32, 128)).unwrap();
|
||||
assert!(shallow.bits_per_pixel() < deep.bits_per_pixel());
|
||||
let deep_bpp = deep.bits_per_pixel();
|
||||
|
||||
for entries in [[shallow.clone(), deep.clone()], [deep, shallow]] {
|
||||
let mut dir = IconDir::new(ResourceType::Icon);
|
||||
for entry in entries {
|
||||
dir.add_entry(entry);
|
||||
}
|
||||
let entry = largest_ico_entry(&dir).unwrap();
|
||||
assert_eq!((entry.width(), entry.height()), (32, 32));
|
||||
assert_eq!(entry.bits_per_pixel(), deep_bpp);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_entry_decodes_at_its_own_size() {
|
||||
let dir = icon_dir(&[16, 256]);
|
||||
let entry = largest_ico_entry(&dir).unwrap();
|
||||
let decoded = entry.decode().unwrap();
|
||||
assert_eq!((decoded.width(), decoded.height()), (256, 256));
|
||||
assert_eq!(decoded.rgba_data().len(), 256 * 256 * 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_entries() {
|
||||
assert!(largest_ico_entry(&IconDir::new(ResourceType::Icon)).is_none());
|
||||
}
|
||||
}
|
||||
152
crates/tauri-codegen/src/lib.rs
Normal file
152
crates/tauri-codegen/src/lib.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! - Embed, hash, and compress assets, including icons for the app as well as the tray icon.
|
||||
//! - Parse `tauri.conf.json` at compile time and generate the Config struct.
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png",
|
||||
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png"
|
||||
)]
|
||||
|
||||
pub use self::context::{ContextData, context_codegen};
|
||||
use crate::embedded_assets::{EmbeddedAssetsError, ensure_out_dir};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt, quote};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{self, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
pub use tauri_utils::config::{Config, parse::ConfigError};
|
||||
use tauri_utils::platform::Target;
|
||||
use tauri_utils::write_if_changed;
|
||||
|
||||
mod context;
|
||||
pub mod embedded_assets;
|
||||
pub mod image;
|
||||
#[doc(hidden)]
|
||||
pub mod vendor;
|
||||
|
||||
/// Represents all the errors that can happen while reading the config during codegen.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum CodegenConfigError {
|
||||
#[error("unable to access current working directory: {0}")]
|
||||
CurrentDir(std::io::Error),
|
||||
|
||||
// this error should be "impossible" because we use std::env::current_dir() - cover it anyways
|
||||
#[error(
|
||||
"Tauri config file has no parent, this shouldn't be possible. file an issue on https://github.com/tauri-apps/tauri - target {0}"
|
||||
)]
|
||||
Parent(PathBuf),
|
||||
|
||||
#[error("unable to parse inline JSON TAURI_CONFIG env var: {0}")]
|
||||
FormatInline(serde_json::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("{0}")]
|
||||
ConfigError(#[from] ConfigError),
|
||||
}
|
||||
|
||||
/// Get the [`Config`] from the `TAURI_CONFIG` environmental variable, or read from the passed path.
|
||||
///
|
||||
/// If the passed path is relative, it should be relative to the current working directory of the
|
||||
/// compiling crate.
|
||||
pub fn get_config(path: &Path) -> Result<(Config, PathBuf), CodegenConfigError> {
|
||||
let path = if path.is_relative() {
|
||||
let cwd = std::env::current_dir().map_err(CodegenConfigError::CurrentDir)?;
|
||||
Cow::Owned(cwd.join(path))
|
||||
} else {
|
||||
Cow::Borrowed(path)
|
||||
};
|
||||
|
||||
// this should be impossible because of the use of `current_dir()` above, but handle it anyways
|
||||
let parent = path
|
||||
.parent()
|
||||
.map(ToOwned::to_owned)
|
||||
.ok_or_else(|| CodegenConfigError::Parent(path.into_owned()))?;
|
||||
|
||||
let target = std::env::var("TAURI_ENV_TARGET_TRIPLE")
|
||||
.as_deref()
|
||||
.map(Target::from_triple)
|
||||
.unwrap_or_else(|_| Target::current());
|
||||
|
||||
// in the future we may want to find a way to not need the TAURI_CONFIG env var so that
|
||||
// it is impossible for the content of two separate configs to get mixed up. The chances are
|
||||
// already unlikely unless the developer goes out of their way to run the cli on a different
|
||||
// project than the target crate.
|
||||
let mut config =
|
||||
serde_json::from_value(tauri_utils::config::parse::read_from(target, &parent)?.0)?;
|
||||
|
||||
if let Ok(env) = std::env::var("TAURI_CONFIG") {
|
||||
let merge_config: serde_json::Value =
|
||||
serde_json::from_str(&env).map_err(CodegenConfigError::FormatInline)?;
|
||||
json_patch::merge(&mut config, &merge_config);
|
||||
}
|
||||
|
||||
// Set working directory to where `tauri.config.json` is, so that relative paths in it are parsed correctly.
|
||||
let old_cwd = std::env::current_dir().map_err(CodegenConfigError::CurrentDir)?;
|
||||
std::env::set_current_dir(parent.clone()).map_err(CodegenConfigError::CurrentDir)?;
|
||||
|
||||
let config = serde_json::from_value(config)?;
|
||||
|
||||
// Reset working directory.
|
||||
std::env::set_current_dir(old_cwd).map_err(CodegenConfigError::CurrentDir)?;
|
||||
|
||||
Ok((config, parent))
|
||||
}
|
||||
|
||||
/// Create a blake3 checksum of the passed bytes.
|
||||
fn checksum(bytes: &[u8]) -> Result<String, fmt::Error> {
|
||||
let mut hasher = vendor::blake3_reference::Hasher::default();
|
||||
hasher.update(bytes);
|
||||
|
||||
let mut bytes = [0u8; 32];
|
||||
hasher.finalize(&mut bytes);
|
||||
|
||||
let mut hex = String::with_capacity(2 * bytes.len());
|
||||
for b in bytes {
|
||||
write!(hex, "{b:02x}")?;
|
||||
}
|
||||
Ok(hex)
|
||||
}
|
||||
|
||||
/// Cache the data to `$OUT_DIR`, only if it does not already exist.
|
||||
///
|
||||
/// Due to using a checksum as the filename, an existing file should be the exact same content
|
||||
/// as the data being checked.
|
||||
struct Cached {
|
||||
checksum: String,
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Cached {
|
||||
type Error = EmbeddedAssetsError;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Self::try_from(Vec::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<u8>> for Cached {
|
||||
type Error = EmbeddedAssetsError;
|
||||
|
||||
fn try_from(content: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
let checksum = checksum(content.as_ref()).map_err(EmbeddedAssetsError::Hex)?;
|
||||
let path = ensure_out_dir()?.join(&checksum);
|
||||
|
||||
write_if_changed(&path, &content)
|
||||
.map(|_| Self { checksum })
|
||||
.map_err(|error| EmbeddedAssetsError::AssetWrite { path, error })
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Cached {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let path = &self.checksum;
|
||||
tokens.append_all(quote!(::std::concat!(::std::env!("OUT_DIR"), "/", #path)))
|
||||
}
|
||||
}
|
||||
378
crates/tauri-codegen/src/vendor/blake3_reference.rs
vendored
Normal file
378
crates/tauri-codegen/src/vendor/blake3_reference.rs
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! This is a lightly modified version of the BLAKE3 reference implementation.
|
||||
//!
|
||||
//! The changes applied are to remove unused item warnings due to using it
|
||||
//! vendored along with some minor clippy suggestions. No logic changes. I
|
||||
//! suggest diffing against the original to find all the changes.
|
||||
//!
|
||||
//! ## Original Header
|
||||
//! This is the reference implementation of BLAKE3. It is used for testing and
|
||||
//! as a readable example of the algorithms involved. Section 5.1 of [the BLAKE3
|
||||
//! spec](https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf)
|
||||
//! discusses this implementation. You can render docs for this implementation
|
||||
//! by running `cargo doc --open` in this directory.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! let mut hasher = tauri_codegen::vendor::blake3_reference::Hasher::new();
|
||||
//! hasher.update(b"abc");
|
||||
//! hasher.update(b"def");
|
||||
//! let mut hash = [0; 32];
|
||||
//! hasher.finalize(&mut hash);
|
||||
//! let mut extended_hash = [0; 500];
|
||||
//! hasher.finalize(&mut extended_hash);
|
||||
//! assert_eq!(hash, extended_hash[..32]);
|
||||
//! ```
|
||||
//!
|
||||
//! CC0-1.0 OR Apache-2.0
|
||||
|
||||
use core::cmp::min;
|
||||
use core::convert::TryInto;
|
||||
|
||||
const OUT_LEN: usize = 32;
|
||||
const BLOCK_LEN: usize = 64;
|
||||
const CHUNK_LEN: usize = 1024;
|
||||
|
||||
const CHUNK_START: u32 = 1 << 0;
|
||||
const CHUNK_END: u32 = 1 << 1;
|
||||
const PARENT: u32 = 1 << 2;
|
||||
const ROOT: u32 = 1 << 3;
|
||||
|
||||
const IV: [u32; 8] = [
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
|
||||
];
|
||||
|
||||
const MSG_PERMUTATION: [usize; 16] = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
|
||||
|
||||
// The mixing function, G, which mixes either a column or a diagonal.
|
||||
fn g(state: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, mx: u32, my: u32) {
|
||||
state[a] = state[a].wrapping_add(state[b]).wrapping_add(mx);
|
||||
state[d] = (state[d] ^ state[a]).rotate_right(16);
|
||||
state[c] = state[c].wrapping_add(state[d]);
|
||||
state[b] = (state[b] ^ state[c]).rotate_right(12);
|
||||
state[a] = state[a].wrapping_add(state[b]).wrapping_add(my);
|
||||
state[d] = (state[d] ^ state[a]).rotate_right(8);
|
||||
state[c] = state[c].wrapping_add(state[d]);
|
||||
state[b] = (state[b] ^ state[c]).rotate_right(7);
|
||||
}
|
||||
|
||||
fn round(state: &mut [u32; 16], m: &[u32; 16]) {
|
||||
// Mix the columns.
|
||||
g(state, 0, 4, 8, 12, m[0], m[1]);
|
||||
g(state, 1, 5, 9, 13, m[2], m[3]);
|
||||
g(state, 2, 6, 10, 14, m[4], m[5]);
|
||||
g(state, 3, 7, 11, 15, m[6], m[7]);
|
||||
// Mix the diagonals.
|
||||
g(state, 0, 5, 10, 15, m[8], m[9]);
|
||||
g(state, 1, 6, 11, 12, m[10], m[11]);
|
||||
g(state, 2, 7, 8, 13, m[12], m[13]);
|
||||
g(state, 3, 4, 9, 14, m[14], m[15]);
|
||||
}
|
||||
|
||||
fn permute(m: &mut [u32; 16]) {
|
||||
let mut permuted = [0; 16];
|
||||
for i in 0..16 {
|
||||
permuted[i] = m[MSG_PERMUTATION[i]];
|
||||
}
|
||||
*m = permuted;
|
||||
}
|
||||
|
||||
fn compress(
|
||||
chaining_value: &[u32; 8],
|
||||
block_words: &[u32; 16],
|
||||
counter: u64,
|
||||
block_len: u32,
|
||||
flags: u32,
|
||||
) -> [u32; 16] {
|
||||
let mut state = [
|
||||
chaining_value[0],
|
||||
chaining_value[1],
|
||||
chaining_value[2],
|
||||
chaining_value[3],
|
||||
chaining_value[4],
|
||||
chaining_value[5],
|
||||
chaining_value[6],
|
||||
chaining_value[7],
|
||||
IV[0],
|
||||
IV[1],
|
||||
IV[2],
|
||||
IV[3],
|
||||
counter as u32,
|
||||
(counter >> 32) as u32,
|
||||
block_len,
|
||||
flags,
|
||||
];
|
||||
let mut block = *block_words;
|
||||
|
||||
round(&mut state, &block); // round 1
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 2
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 3
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 4
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 5
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 6
|
||||
permute(&mut block);
|
||||
round(&mut state, &block); // round 7
|
||||
|
||||
for i in 0..8 {
|
||||
state[i] ^= state[i + 8];
|
||||
state[i + 8] ^= chaining_value[i];
|
||||
}
|
||||
state
|
||||
}
|
||||
|
||||
fn first_8_words(compression_output: [u32; 16]) -> [u32; 8] {
|
||||
compression_output[0..8].try_into().unwrap()
|
||||
}
|
||||
|
||||
fn words_from_little_endian_bytes(bytes: &[u8], words: &mut [u32]) {
|
||||
debug_assert_eq!(bytes.len(), 4 * words.len());
|
||||
for (four_bytes, word) in bytes.as_chunks::<4>().0.iter().zip(words) {
|
||||
*word = u32::from_le_bytes(*four_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Each chunk or parent node can produce either an 8-word chaining value or, by
|
||||
// setting the ROOT flag, any number of final output bytes. The Output struct
|
||||
// captures the state just prior to choosing between those two possibilities.
|
||||
struct Output {
|
||||
input_chaining_value: [u32; 8],
|
||||
block_words: [u32; 16],
|
||||
counter: u64,
|
||||
block_len: u32,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
fn chaining_value(&self) -> [u32; 8] {
|
||||
first_8_words(compress(
|
||||
&self.input_chaining_value,
|
||||
&self.block_words,
|
||||
self.counter,
|
||||
self.block_len,
|
||||
self.flags,
|
||||
))
|
||||
}
|
||||
|
||||
fn root_output_bytes(&self, out_slice: &mut [u8]) {
|
||||
for (output_block_counter, out_block) in (0u64..).zip(out_slice.chunks_mut(2 * OUT_LEN)) {
|
||||
let words = compress(
|
||||
&self.input_chaining_value,
|
||||
&self.block_words,
|
||||
output_block_counter,
|
||||
self.block_len,
|
||||
self.flags | ROOT,
|
||||
);
|
||||
// The output length might not be a multiple of 4.
|
||||
for (word, out_word) in words.iter().zip(out_block.chunks_mut(4)) {
|
||||
out_word.copy_from_slice(&word.to_le_bytes()[..out_word.len()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChunkState {
|
||||
chaining_value: [u32; 8],
|
||||
chunk_counter: u64,
|
||||
block: [u8; BLOCK_LEN],
|
||||
block_len: u8,
|
||||
blocks_compressed: u8,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
impl ChunkState {
|
||||
fn new(key_words: [u32; 8], chunk_counter: u64, flags: u32) -> Self {
|
||||
Self {
|
||||
chaining_value: key_words,
|
||||
chunk_counter,
|
||||
block: [0; BLOCK_LEN],
|
||||
block_len: 0,
|
||||
blocks_compressed: 0,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
BLOCK_LEN * self.blocks_compressed as usize + self.block_len as usize
|
||||
}
|
||||
|
||||
fn start_flag(&self) -> u32 {
|
||||
if self.blocks_compressed == 0 {
|
||||
CHUNK_START
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, mut input: &[u8]) {
|
||||
while !input.is_empty() {
|
||||
// If the block buffer is full, compress it and clear it. More
|
||||
// input is coming, so this compression is not CHUNK_END.
|
||||
if self.block_len as usize == BLOCK_LEN {
|
||||
let mut block_words = [0; 16];
|
||||
words_from_little_endian_bytes(&self.block, &mut block_words);
|
||||
self.chaining_value = first_8_words(compress(
|
||||
&self.chaining_value,
|
||||
&block_words,
|
||||
self.chunk_counter,
|
||||
BLOCK_LEN as u32,
|
||||
self.flags | self.start_flag(),
|
||||
));
|
||||
self.blocks_compressed += 1;
|
||||
self.block = [0; BLOCK_LEN];
|
||||
self.block_len = 0;
|
||||
}
|
||||
|
||||
// Copy input bytes into the block buffer.
|
||||
let want = BLOCK_LEN - self.block_len as usize;
|
||||
let take = min(want, input.len());
|
||||
self.block[self.block_len as usize..][..take].copy_from_slice(&input[..take]);
|
||||
self.block_len += take as u8;
|
||||
input = &input[take..];
|
||||
}
|
||||
}
|
||||
|
||||
fn output(&self) -> Output {
|
||||
let mut block_words = [0; 16];
|
||||
words_from_little_endian_bytes(&self.block, &mut block_words);
|
||||
Output {
|
||||
input_chaining_value: self.chaining_value,
|
||||
block_words,
|
||||
counter: self.chunk_counter,
|
||||
block_len: self.block_len as u32,
|
||||
flags: self.flags | self.start_flag() | CHUNK_END,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_output(
|
||||
left_child_cv: [u32; 8],
|
||||
right_child_cv: [u32; 8],
|
||||
key_words: [u32; 8],
|
||||
flags: u32,
|
||||
) -> Output {
|
||||
let mut block_words = [0; 16];
|
||||
block_words[..8].copy_from_slice(&left_child_cv);
|
||||
block_words[8..].copy_from_slice(&right_child_cv);
|
||||
Output {
|
||||
input_chaining_value: key_words,
|
||||
block_words,
|
||||
counter: 0, // Always 0 for parent nodes.
|
||||
block_len: BLOCK_LEN as u32, // Always BLOCK_LEN (64) for parent nodes.
|
||||
flags: PARENT | flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_cv(
|
||||
left_child_cv: [u32; 8],
|
||||
right_child_cv: [u32; 8],
|
||||
key_words: [u32; 8],
|
||||
flags: u32,
|
||||
) -> [u32; 8] {
|
||||
parent_output(left_child_cv, right_child_cv, key_words, flags).chaining_value()
|
||||
}
|
||||
|
||||
/// An incremental hasher that can accept any number of writes.
|
||||
pub struct Hasher {
|
||||
chunk_state: ChunkState,
|
||||
key_words: [u32; 8],
|
||||
cv_stack: [[u32; 8]; 54], // Space for 54 subtree chaining values:
|
||||
cv_stack_len: u8, // 2^54 * CHUNK_LEN = 2^64
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
impl Hasher {
|
||||
fn new_internal(key_words: [u32; 8], flags: u32) -> Self {
|
||||
Self {
|
||||
chunk_state: ChunkState::new(key_words, 0, flags),
|
||||
key_words,
|
||||
cv_stack: [[0; 8]; 54],
|
||||
cv_stack_len: 0,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new `Hasher` for the regular hash function.
|
||||
pub fn new() -> Self {
|
||||
Self::new_internal(IV, 0)
|
||||
}
|
||||
|
||||
fn push_stack(&mut self, cv: [u32; 8]) {
|
||||
self.cv_stack[self.cv_stack_len as usize] = cv;
|
||||
self.cv_stack_len += 1;
|
||||
}
|
||||
|
||||
fn pop_stack(&mut self) -> [u32; 8] {
|
||||
self.cv_stack_len -= 1;
|
||||
self.cv_stack[self.cv_stack_len as usize]
|
||||
}
|
||||
|
||||
// Section 5.1.2 of the BLAKE3 spec explains this algorithm in more detail.
|
||||
fn add_chunk_chaining_value(&mut self, mut new_cv: [u32; 8], mut total_chunks: u64) {
|
||||
// This chunk might complete some subtrees. For each completed subtree,
|
||||
// its left child will be the current top entry in the CV stack, and
|
||||
// its right child will be the current value of `new_cv`. Pop each left
|
||||
// child off the stack, merge it with `new_cv`, and overwrite `new_cv`
|
||||
// with the result. After all these merges, push the final value of
|
||||
// `new_cv` onto the stack. The number of completed subtrees is given
|
||||
// by the number of trailing 0-bits in the new total number of chunks.
|
||||
while total_chunks & 1 == 0 {
|
||||
new_cv = parent_cv(self.pop_stack(), new_cv, self.key_words, self.flags);
|
||||
total_chunks >>= 1;
|
||||
}
|
||||
self.push_stack(new_cv);
|
||||
}
|
||||
|
||||
/// Add input to the hash state. This can be called any number of times.
|
||||
pub fn update(&mut self, mut input: &[u8]) {
|
||||
while !input.is_empty() {
|
||||
// If the current chunk is complete, finalize it and reset the
|
||||
// chunk state. More input is coming, so this chunk is not ROOT.
|
||||
if self.chunk_state.len() == CHUNK_LEN {
|
||||
let chunk_cv = self.chunk_state.output().chaining_value();
|
||||
let total_chunks = self.chunk_state.chunk_counter + 1;
|
||||
self.add_chunk_chaining_value(chunk_cv, total_chunks);
|
||||
self.chunk_state = ChunkState::new(self.key_words, total_chunks, self.flags);
|
||||
}
|
||||
|
||||
// Compress input bytes into the current chunk state.
|
||||
let want = CHUNK_LEN - self.chunk_state.len();
|
||||
let take = min(want, input.len());
|
||||
self.chunk_state.update(&input[..take]);
|
||||
input = &input[take..];
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalize the hash and write any number of output bytes.
|
||||
pub fn finalize(&self, out_slice: &mut [u8]) {
|
||||
// Starting with the Output from the current chunk, compute all the
|
||||
// parent chaining values along the right edge of the tree, until we
|
||||
// have the root Output.
|
||||
let mut output = self.chunk_state.output();
|
||||
let mut parent_nodes_remaining = self.cv_stack_len as usize;
|
||||
while parent_nodes_remaining > 0 {
|
||||
parent_nodes_remaining -= 1;
|
||||
output = parent_output(
|
||||
self.cv_stack[parent_nodes_remaining],
|
||||
output.chaining_value(),
|
||||
self.key_words,
|
||||
self.flags,
|
||||
);
|
||||
}
|
||||
output.root_output_bytes(out_slice);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Hasher {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
11
crates/tauri-codegen/src/vendor/mod.rs
vendored
Normal file
11
crates/tauri-codegen/src/vendor/mod.rs
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Manual vendored dependencies - NOT STABLE.
|
||||
//!
|
||||
//! This module and all submodules are not considered part of the public
|
||||
//! api. They can and will change at any time for any reason in any
|
||||
//! version.
|
||||
|
||||
pub mod blake3_reference;
|
||||
Reference in New Issue
Block a user