A link can say the reader is leaving, not just going elsewhere
Destination::External always opened a tab, so a same-tab navigation out of
the app was unsayable. The measured consumer is MNW's custom-pages host:
u.makenot.work serves a creator's page with a platform strip on it, and
every link in that strip goes to the apex in the same tab, because going to
the apex is the whole point of the strip. Said as External all three would
open tabs, which is a satellite document refusing to let go of a reader who
asked to leave.
Destination::Leaving is the other half. The split is intent and the
mechanism stays the renderer's, which is the call panel placement and the
toast clock both got: a tab is window management, and what a renderer
cannot infer from an address alone is which kind of leaving this is. A
terminal with no tabs follows both the one way it can and is not wrong.
rel="noopener noreferrer" on both rather than only on the tab. noreferrer
is what stops the Referer a same-tab navigation still sends, neither is a
cost, and a branch would be a second thing to get right. A redirect header
treats the two alike, since a page that has already navigated has nothing
to keep aside.
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
- Claude-Session
- https://claude.ai/code/session_01WHu5vBgpCULUFXsEJBHryC
16 files changed,
+163 insertions,
-60 deletions
| 3425 |
3425 |
|
|
| 3426 |
3426 |
|
[[package]]
|
| 3427 |
3427 |
|
name = "quasi"
|
| 3428 |
|
- |
version = "0.92.0"
|
|
3428 |
+ |
version = "0.93.0"
|
| 3429 |
3429 |
|
|
| 3430 |
3430 |
|
[[package]]
|
| 3431 |
3431 |
|
name = "quasi-axum"
|
| 3432 |
|
- |
version = "0.92.0"
|
|
3432 |
+ |
version = "0.93.0"
|
| 3433 |
3433 |
|
dependencies = [
|
| 3434 |
3434 |
|
"axum",
|
| 3435 |
3435 |
|
"http",
|
| 3443 |
3443 |
|
|
| 3444 |
3444 |
|
[[package]]
|
| 3445 |
3445 |
|
name = "quasi-basics"
|
| 3446 |
|
- |
version = "0.92.0"
|
|
3446 |
+ |
version = "0.93.0"
|
| 3447 |
3447 |
|
dependencies = [
|
| 3448 |
3448 |
|
"makeover-layout",
|
| 3449 |
3449 |
|
"quasi-http",
|
| 3453 |
3453 |
|
|
| 3454 |
3454 |
|
[[package]]
|
| 3455 |
3455 |
|
name = "quasi-bench"
|
| 3456 |
|
- |
version = "0.92.0"
|
|
3456 |
+ |
version = "0.93.0"
|
| 3457 |
3457 |
|
dependencies = [
|
| 3458 |
3458 |
|
"dhat",
|
| 3459 |
3459 |
|
"makeover",
|
| 3468 |
3468 |
|
|
| 3469 |
3469 |
|
[[package]]
|
| 3470 |
3470 |
|
name = "quasi-http"
|
| 3471 |
|
- |
version = "0.92.0"
|
|
3471 |
+ |
version = "0.93.0"
|
| 3472 |
3472 |
|
dependencies = [
|
| 3473 |
3473 |
|
"form_urlencoded",
|
| 3474 |
3474 |
|
"http",
|
| 3477 |
3477 |
|
|
| 3478 |
3478 |
|
[[package]]
|
| 3479 |
3479 |
|
name = "quasi-immediate"
|
| 3480 |
|
- |
version = "0.92.0"
|
|
3480 |
+ |
version = "0.93.0"
|
| 3481 |
3481 |
|
dependencies = [
|
| 3482 |
3482 |
|
"docengine",
|
| 3483 |
3483 |
|
"egui",
|
| 3488 |
3488 |
|
|
| 3489 |
3489 |
|
[[package]]
|
| 3490 |
3490 |
|
name = "quasi-notifs"
|
| 3491 |
|
- |
version = "0.92.0"
|
|
3491 |
+ |
version = "0.93.0"
|
| 3492 |
3492 |
|
dependencies = [
|
| 3493 |
3493 |
|
"quasi-router",
|
| 3494 |
3494 |
|
"synckit-config",
|
| 3498 |
3498 |
|
|
| 3499 |
3499 |
|
[[package]]
|
| 3500 |
3500 |
|
name = "quasi-router"
|
| 3501 |
|
- |
version = "0.92.0"
|
|
3501 |
+ |
version = "0.93.0"
|
| 3502 |
3502 |
|
dependencies = [
|
| 3503 |
3503 |
|
"makeover-layout",
|
| 3504 |
3504 |
|
]
|
| 3515 |
3515 |
|
|
| 3516 |
3516 |
|
[[package]]
|
| 3517 |
3517 |
|
name = "quasi-tauri"
|
| 3518 |
|
- |
version = "0.92.0"
|
|
3518 |
+ |
version = "0.93.0"
|
| 3519 |
3519 |
|
dependencies = [
|
| 3520 |
3520 |
|
"http",
|
| 3521 |
3521 |
|
"quasi-http",
|
| 3526 |
3526 |
|
|
| 3527 |
3527 |
|
[[package]]
|
| 3528 |
3528 |
|
name = "quasi-tui"
|
| 3529 |
|
- |
version = "0.92.0"
|
|
3529 |
+ |
version = "0.93.0"
|
| 3530 |
3530 |
|
dependencies = [
|
| 3531 |
3531 |
|
"docengine",
|
| 3532 |
3532 |
|
"makeover",
|
| 3539 |
3539 |
|
|
| 3540 |
3540 |
|
[[package]]
|
| 3541 |
3541 |
|
name = "quasi-webview"
|
| 3542 |
|
- |
version = "0.92.0"
|
|
3542 |
+ |
version = "0.93.0"
|
| 3543 |
3543 |
|
dependencies = [
|
| 3544 |
3544 |
|
"docengine",
|
| 3545 |
3545 |
|
"makeover-layout",
|
| 6211 |
6211 |
|
"winnow 1.0.4",
|
| 6212 |
6212 |
|
]
|
| 6213 |
6213 |
|
|
| 6214 |
|
- |
[[patch.unused]]
|
| 6215 |
|
- |
name = "synckit-client"
|
| 6216 |
|
- |
version = "0.10.0"
|
| 6217 |
|
- |
|
| 6218 |
|
- |
[[patch.unused]]
|
| 6219 |
|
- |
name = "quasi-type"
|
| 6220 |
|
- |
version = "0.1.3"
|
| 6221 |
|
- |
|
| 6222 |
6214 |
|
[[patch.unused]]
|
| 6223 |
6215 |
|
name = "kberg"
|
| 6224 |
6216 |
|
version = "0.1.0"
|
| 6234 |
6226 |
|
[[patch.unused]]
|
| 6235 |
6227 |
|
name = "tagtree"
|
| 6236 |
6228 |
|
version = "0.4.1"
|
|
6229 |
+ |
|
|
6230 |
+ |
[[patch.unused]]
|
|
6231 |
+ |
name = "quasi-type"
|
|
6232 |
+ |
version = "0.1.3"
|
|
6233 |
+ |
|
|
6234 |
+ |
[[patch.unused]]
|
|
6235 |
+ |
name = "synckit-client"
|
|
6236 |
+ |
version = "0.10.0"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-axum"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
description = "The axum host adapter for quasi-router: an HTTP request in, a rendered description out"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0" }
|
| 17 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.92.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0" }
|
|
17 |
+ |
quasi-http = { path = "../quasi-http", version = "0.93.0" }
|
| 18 |
18 |
|
axum = "0.8.8"
|
| 19 |
19 |
|
http = "1.3.1"
|
| 20 |
20 |
|
tokio = { version = "1.50.0", features = ["rt"] }
|
| 21 |
21 |
|
|
| 22 |
22 |
|
[dev-dependencies]
|
| 23 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.92.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.93.0" }
|
| 24 |
24 |
|
tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] }
|
| 25 |
25 |
|
tower = { version = "0.5.3", features = ["util"] }
|
| 26 |
26 |
|
http-body-util = "0.1.3"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-basics"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
description = "The first-party widget set: named assemblies of primitives, shared across our apps"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0" }
|
| 17 |
17 |
|
makeover-layout = "0.41.0"
|
| 18 |
18 |
|
|
| 19 |
19 |
|
[dev-dependencies]
|
| 20 |
20 |
|
# A widget's guarantees are claims about what a renderer draws, so they are
|
| 21 |
21 |
|
# tested against a real one rather than by walking the tree the assembly just
|
| 22 |
22 |
|
# built. The webview is the renderer that recognises names today.
|
| 23 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.92.0" }
|
| 24 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.92.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.93.0" }
|
|
24 |
+ |
quasi-http = { path = "../quasi-http", version = "0.93.0" }
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-bench"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
description = "What a described screen costs to render, in time and in allocations"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 22 |
22 |
|
count = ["dep:dhat"]
|
| 23 |
23 |
|
|
| 24 |
24 |
|
[dependencies]
|
| 25 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0" }
|
| 26 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.92.0" }
|
| 27 |
|
- |
quasi-tui = { path = "../quasi-tui", version = "0.92.0" }
|
|
25 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0" }
|
|
26 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.93.0" }
|
|
27 |
+ |
quasi-tui = { path = "../quasi-tui", version = "0.93.0" }
|
| 28 |
28 |
|
# `Serves` is the trait carrying `screen` and `fragment`, which is what the
|
| 29 |
29 |
|
# webview is measured through. Taken directly rather than through quasi-webview
|
| 30 |
30 |
|
# because a bench calling a trait method should name the trait it calls.
|
| 31 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.92.0" }
|
|
31 |
+ |
quasi-http = { path = "../quasi-http", version = "0.93.0" }
|
| 32 |
32 |
|
makeover-layout = "0.41.0"
|
| 33 |
33 |
|
makeover-tui = { version = "0.41.0", features = ["theme"] }
|
| 34 |
34 |
|
# Only to load a bundled theme file. `makeover_tui::Theme` is `#[non_exhaustive]`,
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-http"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
description = "The http-shaped seam quasi's webview host adapters share: decoding in, a rendered description out"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0" }
|
| 17 |
17 |
|
http = "1.3.1"
|
| 18 |
18 |
|
form_urlencoded = "1.2.2"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-immediate"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
edition = "2024"
|
| 5 |
5 |
|
description = "The immediate-mode renderer for quasi-router: a described screen in, an egui frame out. Immediate mode is the constraint that matters, not the library."
|
| 6 |
6 |
|
license = "MIT"
|
| 12 |
12 |
|
categories = ["gui"]
|
| 13 |
13 |
|
|
| 14 |
14 |
|
[dependencies]
|
| 15 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0" }
|
|
15 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0" }
|
| 16 |
16 |
|
# The node drawing, which is the makeover layer's and not this crate's. Every
|
| 17 |
17 |
|
# widget here that is not a container comes from it: a screen walk that painted
|
| 18 |
18 |
|
# its own meter would be the divergence the suite exists to end, one copy per
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-notifs"
|
| 3 |
|
- |
version = "0.92.0"
|
|
3 |
+ |
version = "0.93.0"
|
| 4 |
4 |
|
description = "Declared notification kinds and the registry that holds them: what a notification says and what it is for, apart from how it reaches a person"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 28 |
28 |
|
tauri = ["dep:tauri", "dep:tauri-plugin-notification"]
|
| 29 |
29 |
|
|
| 30 |
30 |
|
[dependencies]
|
| 31 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.92.0", optional = true }
|
|
31 |
+ |
quasi-router = { path = "../quasi-router", version = "0.93.0", optional = true }
|
| 32 |
32 |
|
synckit-config = { git = "https://makenot.work/git/max/synckit.git", version = "0.2", optional = true }
|
| 33 |
33 |
|
tauri-plugin-notification = { version = "2.3.3", optional = true }
|
| 34 |
34 |
|
# Default features off, for `quasi-tauri`'s reason: this takes an `AppHandle`
|