mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 16:54:41 -05:00
Compare commits
67 Commits
actionform
...
2693
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab69750c01 | ||
|
|
b90fe273d5 | ||
|
|
5f0fab9f63 | ||
|
|
8848eb8b87 | ||
|
|
7e75801f7c | ||
|
|
0763a81cf1 | ||
|
|
3d37f08539 | ||
|
|
b3db094618 | ||
|
|
0c817d51fe | ||
|
|
fb5d8513ff | ||
|
|
c53fc67d38 | ||
|
|
ff0c8252b0 | ||
|
|
551f9b0a04 | ||
|
|
44cd3272f9 | ||
|
|
73a9797ef9 | ||
|
|
57a00a33a3 | ||
|
|
5f445cdfbf | ||
|
|
c9d0ef5033 | ||
|
|
af85623a22 | ||
|
|
40ecc2bd78 | ||
|
|
41a18a1218 | ||
|
|
739d1b2e3e | ||
|
|
9e6996a59f | ||
|
|
cca3f1f42d | ||
|
|
80bbb20089 | ||
|
|
33e7ed83cc | ||
|
|
dcaa1df63d | ||
|
|
8606f3d928 | ||
|
|
32e6ac7bb7 | ||
|
|
b22f3bb3bd | ||
|
|
00a42daa63 | ||
|
|
ec19c59850 | ||
|
|
b06097d085 | ||
|
|
a59561f796 | ||
|
|
96b448805d | ||
|
|
2ef27cb0bb | ||
|
|
21a6551ce6 | ||
|
|
2f4fd87c05 | ||
|
|
13ad1b235d | ||
|
|
a2c7e23d54 | ||
|
|
9e65f71db4 | ||
|
|
7f4a2926c1 | ||
|
|
7c5203db19 | ||
|
|
3760ced0ec | ||
|
|
f3f3a053ba | ||
|
|
6a8e4bb453 | ||
|
|
20f4323e50 | ||
|
|
47bcee0ef4 | ||
|
|
ac3b95d35a | ||
|
|
a314a4fcd9 | ||
|
|
b2a77f06b9 | ||
|
|
9741c41356 | ||
|
|
4e4a770600 | ||
|
|
289c02fdac | ||
|
|
123d95c34c | ||
|
|
da9711a743 | ||
|
|
9353316947 | ||
|
|
2960dada4a | ||
|
|
c1ebaf9d04 | ||
|
|
9a7dbd50eb | ||
|
|
410225c4d1 | ||
|
|
8b1c0a7013 | ||
|
|
6e819737cd | ||
|
|
c4560b7e76 | ||
|
|
0d20f6aca8 | ||
|
|
158b0bd294 | ||
|
|
c8186eea13 |
5
.github/workflows/run-cargo-make-task.yml
vendored
5
.github/workflows/run-cargo-make-task.yml
vendored
@@ -48,14 +48,11 @@ jobs:
|
||||
- name: Install wasm-bindgen
|
||||
run: cargo binstall wasm-bindgen-cli --no-confirm
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: cargo binstall wasm-pack --no-confirm
|
||||
|
||||
- name: Install cargo-leptos
|
||||
run: cargo binstall cargo-leptos --no-confirm
|
||||
|
||||
- name: Install Trunk
|
||||
uses: jetli/trunk-action@v0.4.0
|
||||
uses: jetli/trunk-action@v0.5.0
|
||||
with:
|
||||
version: "latest"
|
||||
|
||||
|
||||
30
Cargo.toml
30
Cargo.toml
@@ -1,6 +1,9 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
# utilities
|
||||
"oco",
|
||||
|
||||
# core
|
||||
"leptos",
|
||||
"leptos_dom",
|
||||
@@ -25,23 +28,24 @@ members = [
|
||||
exclude = ["benchmarks", "examples"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
rust-version = "1.75"
|
||||
|
||||
[workspace.dependencies]
|
||||
leptos = { path = "./leptos", version = "0.6.11" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.6.11" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.6.11" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.6.11" }
|
||||
leptos_reactive = { path = "./leptos_reactive", version = "0.6.11" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.6.11" }
|
||||
server_fn = { path = "./server_fn", version = "0.6.11" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.6.11" }
|
||||
oco_ref = { path = "./oco", version = "0.1.0" }
|
||||
leptos = { path = "./leptos", version = "0.6.13" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.6.13" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.6.13" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.6.13" }
|
||||
leptos_reactive = { path = "./leptos_reactive", version = "0.6.13" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.6.13" }
|
||||
server_fn = { path = "./server_fn", version = "0.6.13" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.6.13" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.6" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.6.11" }
|
||||
leptos_router = { path = "./router", version = "0.6.11" }
|
||||
leptos_meta = { path = "./meta", version = "0.6.11" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.6.11" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.6.13" }
|
||||
leptos_router = { path = "./router", version = "0.6.13" }
|
||||
leptos_meta = { path = "./meta", version = "0.6.13" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.6.13" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
1
docs/book_ru/.gitignore
vendored
Normal file
1
docs/book_ru/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
book
|
||||
2
docs/book_ru/README.md
Normal file
2
docs/book_ru/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Перевод в процессе, книга скоро будет доступна
|
||||
> Translation underway, book will be available soon
|
||||
10
docs/book_ru/book.toml
Normal file
10
docs/book_ru/book.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[output.html]
|
||||
additional-css = ["./mdbook-admonish.css"]
|
||||
[output.html.playground]
|
||||
runnable = false
|
||||
|
||||
[preprocessor]
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.1" # не редактировать: управляется `mdbook-admonish install`
|
||||
345
docs/book_ru/mdbook-admonish.css
Normal file
345
docs/book_ru/mdbook-admonish.css
Normal file
@@ -0,0 +1,345 @@
|
||||
@charset "UTF-8";
|
||||
:root {
|
||||
--md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>");
|
||||
--md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>");
|
||||
--md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>");
|
||||
--md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>");
|
||||
--md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>");
|
||||
--md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>");
|
||||
--md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>");
|
||||
--md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>");
|
||||
--md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>");
|
||||
--md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>");
|
||||
--md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>");
|
||||
--md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>");
|
||||
--md-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
|
||||
}
|
||||
|
||||
:is(.admonition) {
|
||||
display: flow-root;
|
||||
margin: 1.5625em 0;
|
||||
padding: 0 1.2rem;
|
||||
color: var(--fg);
|
||||
page-break-inside: avoid;
|
||||
background-color: var(--bg);
|
||||
border: 0 solid black;
|
||||
border-inline-start-width: 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@media print {
|
||||
:is(.admonition) {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
:is(.admonition) > * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:is(.admonition) :is(.admonition) {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
:is(.admonition) > .tabbed-set:only-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
html :is(.admonition) > :last-child {
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
a.admonition-anchor-link {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: -1.2rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
a.admonition-anchor-link:link, a.admonition-anchor-link:visited {
|
||||
color: var(--fg);
|
||||
}
|
||||
a.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.admonition-anchor-link::before {
|
||||
content: "§";
|
||||
}
|
||||
|
||||
:is(.admonition-title, summary.admonition-title) {
|
||||
position: relative;
|
||||
min-height: 4rem;
|
||||
margin-block: 0;
|
||||
margin-inline: -1.6rem -1.2rem;
|
||||
padding-block: 0.8rem;
|
||||
padding-inline: 4.4rem 1.2rem;
|
||||
font-weight: 700;
|
||||
background-color: rgba(68, 138, 255, 0.1);
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
display: flex;
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title) p {
|
||||
margin: 0;
|
||||
}
|
||||
html :is(.admonition-title, summary.admonition-title):last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title)::before {
|
||||
position: absolute;
|
||||
top: 0.625em;
|
||||
inset-inline-start: 1.6rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-color: #448aff;
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
|
||||
-webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-size: contain;
|
||||
content: "";
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
details.admonition > summary.admonition-title::after {
|
||||
position: absolute;
|
||||
top: 0.625em;
|
||||
inset-inline-end: 1.6rem;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
background-color: currentcolor;
|
||||
mask-image: var(--md-details-icon);
|
||||
-webkit-mask-image: var(--md-details-icon);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-size: contain;
|
||||
content: "";
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
details[open].admonition > summary.admonition-title::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-note) {
|
||||
border-color: #448aff;
|
||||
}
|
||||
|
||||
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(68, 138, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #448aff;
|
||||
mask-image: var(--md-admonition-icon--admonish-note);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-note);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
|
||||
border-color: #00b0ff;
|
||||
}
|
||||
|
||||
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 176, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00b0ff;
|
||||
mask-image: var(--md-admonition-icon--admonish-abstract);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-info, .admonish-todo) {
|
||||
border-color: #00b8d4;
|
||||
}
|
||||
|
||||
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 184, 212, 0.1);
|
||||
}
|
||||
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00b8d4;
|
||||
mask-image: var(--md-admonition-icon--admonish-info);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-info);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
|
||||
border-color: #00bfa5;
|
||||
}
|
||||
|
||||
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 191, 165, 0.1);
|
||||
}
|
||||
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00bfa5;
|
||||
mask-image: var(--md-admonition-icon--admonish-tip);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-tip);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
|
||||
border-color: #00c853;
|
||||
}
|
||||
|
||||
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 200, 83, 0.1);
|
||||
}
|
||||
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00c853;
|
||||
mask-image: var(--md-admonition-icon--admonish-success);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-success);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
|
||||
border-color: #64dd17;
|
||||
}
|
||||
|
||||
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(100, 221, 23, 0.1);
|
||||
}
|
||||
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #64dd17;
|
||||
mask-image: var(--md-admonition-icon--admonish-question);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-question);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
|
||||
border-color: #ff9100;
|
||||
}
|
||||
|
||||
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 145, 0, 0.1);
|
||||
}
|
||||
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff9100;
|
||||
mask-image: var(--md-admonition-icon--admonish-warning);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-warning);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
|
||||
border-color: #ff5252;
|
||||
}
|
||||
|
||||
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 82, 82, 0.1);
|
||||
}
|
||||
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff5252;
|
||||
mask-image: var(--md-admonition-icon--admonish-failure);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-failure);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-danger, .admonish-error) {
|
||||
border-color: #ff1744;
|
||||
}
|
||||
|
||||
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 23, 68, 0.1);
|
||||
}
|
||||
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff1744;
|
||||
mask-image: var(--md-admonition-icon--admonish-danger);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-danger);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-bug) {
|
||||
border-color: #f50057;
|
||||
}
|
||||
|
||||
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(245, 0, 87, 0.1);
|
||||
}
|
||||
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #f50057;
|
||||
mask-image: var(--md-admonition-icon--admonish-bug);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-bug);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-example) {
|
||||
border-color: #7c4dff;
|
||||
}
|
||||
|
||||
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(124, 77, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #7c4dff;
|
||||
mask-image: var(--md-admonition-icon--admonish-example);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-example);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-quote, .admonish-cite) {
|
||||
border-color: #9e9e9e;
|
||||
}
|
||||
|
||||
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(158, 158, 158, 0.1);
|
||||
}
|
||||
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #9e9e9e;
|
||||
mask-image: var(--md-admonition-icon--admonish-quote);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-quote);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.navy :is(.admonition) {
|
||||
background-color: var(--sidebar-bg);
|
||||
}
|
||||
|
||||
.ayu :is(.admonition),
|
||||
.coal :is(.admonition) {
|
||||
background-color: var(--theme-hover);
|
||||
}
|
||||
|
||||
.rust :is(.admonition) {
|
||||
background-color: var(--sidebar-bg);
|
||||
color: var(--sidebar-fg);
|
||||
}
|
||||
.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {
|
||||
color: var(--sidebar-fg);
|
||||
}
|
||||
2
docs/book_ru/src/01_introduction.md
Normal file
2
docs/book_ru/src/01_introduction.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/">
|
||||
<link rel="canonical" href="https://book.leptos.dev/">
|
||||
2
docs/book_ru/src/15_global_state.md
Normal file
2
docs/book_ru/src/15_global_state.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/15_global_state.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/15_global_state.html">
|
||||
55
docs/book_ru/src/SUMMARY.md
Normal file
55
docs/book_ru/src/SUMMARY.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Оглавление
|
||||
|
||||
- [Вступление](./01_introduction.md)
|
||||
- [Начало работы](./getting_started/README.md)
|
||||
- [Leptos DX](./getting_started/leptos_dx.md)
|
||||
- [Сообщество Leptos и leptos-* Крейты](./getting_started/community_crates.md)
|
||||
- [Часть 1: Построение UI](./view/README.md)
|
||||
- [Простой компонент](./view/01_basic_component.md)
|
||||
- [Динамические атрибуты](./view/02_dynamic_attributes.md)
|
||||
- [Компоненты и свойства](./view/03_components.md)
|
||||
- [Итерирование](./view/04_iteration.md)
|
||||
- [Итерирование более сложных структур через `<For>`](./view/04b_iteration.md)
|
||||
- [Формы и поля ввода](./view/05_forms.md)
|
||||
- [Порядок выполнения](./view/06_control_flow.md)
|
||||
- [Обработка ошибок](./view/07_errors.md)
|
||||
- [Общение Родитель-Ребёнок в дереве компонентов](./view/08_parent_child.md)
|
||||
- [Передача Детей другим компонентам](./view/09_component_children.md)
|
||||
- [Без макросов: синтаксис билдера View](./view/builder.md)
|
||||
- [Реактивность](./reactivity/README.md)
|
||||
- [Работа с сигналами](./reactivity/working_with_signals.md)
|
||||
- [Реагирование на изменения с помощью `create_effect`](./reactivity/14_create_effect.md)
|
||||
- [Примечание: Реактивность и функции](./reactivity/interlude_functions.md)
|
||||
- [Тестирование](./testing.md)
|
||||
- [Асинхронность](./async/README.md)
|
||||
- [Подгрузка данных с помощью ресурсов (Resource)](./async/10_resources.md)
|
||||
- [Ожидания (Suspense)](./async/11_suspense.md)
|
||||
- [Переходы (Transition)](./async/12_transition.md)
|
||||
- [Действия (Action)](./async/13_actions.md)
|
||||
- [Примечание: Пробрасывание дочерних элементов](./interlude_projecting_children.md)
|
||||
- [Управление глобальным состоянием](./15_global_state.md)
|
||||
- [Маршрутизатор URL](./router/README.md)
|
||||
- [Определение `<Routes/>`](./router/16_routes.md)
|
||||
- [Вложенная маршрутизация](./router/17_nested_routing.md)
|
||||
- [Параметры в пути и в строке запроса](./router/18_params_and_queries.md)
|
||||
- [`<A/>`](./router/19_a.md)
|
||||
- [`<Form/>`](./router/20_form.md)
|
||||
- [Примечание: Стили](./interlude_styling.md)
|
||||
- [Метаданные](./metadata.md)
|
||||
- [Рендеринг на стороне клиента (CSR): Заключение](./csr_wrapping_up.md)
|
||||
- [Часть 2: Рендеринг на стороне сервера (SSR)](./ssr/README.md)
|
||||
- [`cargo-leptos`](./ssr/21_cargo_leptos.md)
|
||||
- [Жизненный цикл загрузки страницы](./ssr/22_life_cycle.md)
|
||||
- [Асинхронный рендеринг и режимы SSR](./ssr/23_ssr_modes.md)
|
||||
- [Баги возникающие при гидратации](./ssr/24_hydration_bugs.md)
|
||||
- [Работа с сервером](./server/README.md)
|
||||
- [Серверные функции](./server/25_server_functions.md)
|
||||
- [Экстракторы](./server/26_extractors.md)
|
||||
- [Ответы и перенаправления](./server/27_response.md)
|
||||
- [Постепенное улучшение и Изящная деградация](./progressive_enhancement/README.md)
|
||||
- [`<ActionForm/>`](./progressive_enhancement/action_form.md)
|
||||
- [Развёртывание](./deployment/README.md)
|
||||
- [Оптимизация размера бинарника WASM](./deployment/binary_size.md)
|
||||
- [Руководство: Острова](./islands.md)
|
||||
|
||||
- [Приложение: Как работает реактивная система?](./appendix_reactive_graph.md)
|
||||
2
docs/book_ru/src/appendix_reactive_graph.md
Normal file
2
docs/book_ru/src/appendix_reactive_graph.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/appendix_reactive_graph.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/appendix_reactive_graph.html">
|
||||
2
docs/book_ru/src/async/10_resources.md
Normal file
2
docs/book_ru/src/async/10_resources.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/10_resources.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/10_resources.html">
|
||||
2
docs/book_ru/src/async/11_suspense.md
Normal file
2
docs/book_ru/src/async/11_suspense.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/11_suspense.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/11_suspense.html">
|
||||
2
docs/book_ru/src/async/12_transition.md
Normal file
2
docs/book_ru/src/async/12_transition.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/12_transition.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/12_transition.html">
|
||||
2
docs/book_ru/src/async/13_actions.md
Normal file
2
docs/book_ru/src/async/13_actions.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/13_action.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/13_action.html">
|
||||
2
docs/book_ru/src/async/README.md
Normal file
2
docs/book_ru/src/async/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/index.html">
|
||||
2
docs/book_ru/src/csr_wrapping_up.md
Normal file
2
docs/book_ru/src/csr_wrapping_up.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/csr_wrapping_up.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/csr_wrapping_up.html">
|
||||
2
docs/book_ru/src/deployment/README.md
Normal file
2
docs/book_ru/src/deployment/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/deployment/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/deployment/index.html">
|
||||
2
docs/book_ru/src/deployment/binary_size.md
Normal file
2
docs/book_ru/src/deployment/binary_size.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/deployment/binary_size.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/deployment/binary_size.html">
|
||||
2
docs/book_ru/src/getting_started/README.md
Normal file
2
docs/book_ru/src/getting_started/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/index.html">
|
||||
2
docs/book_ru/src/getting_started/community_crates.md
Normal file
2
docs/book_ru/src/getting_started/community_crates.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/community_crates.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/community_crates.html">
|
||||
2
docs/book_ru/src/getting_started/leptos_dx.md
Normal file
2
docs/book_ru/src/getting_started/leptos_dx.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/leptos_dx.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/leptos_dx.html">
|
||||
2
docs/book_ru/src/interlude_projecting_children.md
Normal file
2
docs/book_ru/src/interlude_projecting_children.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/interlude_projecting_children.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/interlude_projecting_children.html">
|
||||
2
docs/book_ru/src/interlude_styling.md
Normal file
2
docs/book_ru/src/interlude_styling.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/interlude_styling.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/interlude_styling.html">
|
||||
2
docs/book_ru/src/islands.md
Normal file
2
docs/book_ru/src/islands.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/islands.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/islands.html">
|
||||
2
docs/book_ru/src/metadata.md
Normal file
2
docs/book_ru/src/metadata.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/metadata.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/metadata.html">
|
||||
2
docs/book_ru/src/progressive_enhancement/README.md
Normal file
2
docs/book_ru/src/progressive_enhancement/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/progressive_enhancement/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/progressive_enhancement/index.html">
|
||||
2
docs/book_ru/src/progressive_enhancement/action_form.md
Normal file
2
docs/book_ru/src/progressive_enhancement/action_form.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/progressive_enhancement/action_form.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/progressive_enhancement/action_form.html">
|
||||
2
docs/book_ru/src/reactivity/14_create_effect.md
Normal file
2
docs/book_ru/src/reactivity/14_create_effect.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/14_create_effect.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/14_create_effect.html">
|
||||
2
docs/book_ru/src/reactivity/README.md
Normal file
2
docs/book_ru/src/reactivity/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/index.html">
|
||||
2
docs/book_ru/src/reactivity/interlude_functions.md
Normal file
2
docs/book_ru/src/reactivity/interlude_functions.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/interlude_functions.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/interlude_functions.html">
|
||||
2
docs/book_ru/src/reactivity/working_with_signals.md
Normal file
2
docs/book_ru/src/reactivity/working_with_signals.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/working_with_signals.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/working_with_signals.html">
|
||||
2
docs/book_ru/src/router/16_routes.md
Normal file
2
docs/book_ru/src/router/16_routes.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/16_routes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/16_routes.html">
|
||||
2
docs/book_ru/src/router/17_nested_routing.md
Normal file
2
docs/book_ru/src/router/17_nested_routing.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/17_nested_routing.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/17_nested_routing.html">
|
||||
2
docs/book_ru/src/router/18_params_and_queries.md
Normal file
2
docs/book_ru/src/router/18_params_and_queries.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/18_params_and_queries.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/18_params_and_queries.html">
|
||||
2
docs/book_ru/src/router/19_a.md
Normal file
2
docs/book_ru/src/router/19_a.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/19_a.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/19_a.html">
|
||||
2
docs/book_ru/src/router/20_form.md
Normal file
2
docs/book_ru/src/router/20_form.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/20_form.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/20_form.html">
|
||||
2
docs/book_ru/src/router/README.md
Normal file
2
docs/book_ru/src/router/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/index.html">
|
||||
2
docs/book_ru/src/server/25_server_functions.md
Normal file
2
docs/book_ru/src/server/25_server_functions.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/25_server_functions.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/25_server_functions.html">
|
||||
2
docs/book_ru/src/server/26_extractors.md
Normal file
2
docs/book_ru/src/server/26_extractors.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/26_extractors.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/26_extractors.html">
|
||||
2
docs/book_ru/src/server/27_response.md
Normal file
2
docs/book_ru/src/server/27_response.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/27_response.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/27_response.html">
|
||||
2
docs/book_ru/src/server/README.md
Normal file
2
docs/book_ru/src/server/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/index.html">
|
||||
2
docs/book_ru/src/ssr/21_cargo_leptos.md
Normal file
2
docs/book_ru/src/ssr/21_cargo_leptos.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/21_cargo_leptos.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/21_cargo_leptos.html">
|
||||
2
docs/book_ru/src/ssr/22_life_cycle.md
Normal file
2
docs/book_ru/src/ssr/22_life_cycle.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/22_life_cycle.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/22_life_cycle.html">
|
||||
2
docs/book_ru/src/ssr/23_ssr_modes.md
Normal file
2
docs/book_ru/src/ssr/23_ssr_modes.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/23_ssr_modes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/23_ssr_modes.html">
|
||||
2
docs/book_ru/src/ssr/24_hydration_bugs.md
Normal file
2
docs/book_ru/src/ssr/24_hydration_bugs.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/24_hydration_bugs.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/24_hydration_bugs.html">
|
||||
2
docs/book_ru/src/ssr/README.md
Normal file
2
docs/book_ru/src/ssr/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/index.html">
|
||||
2
docs/book_ru/src/testing.md
Normal file
2
docs/book_ru/src/testing.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/testing.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/testing.html">
|
||||
2
docs/book_ru/src/view/01_basic_component.md
Normal file
2
docs/book_ru/src/view/01_basic_component.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/01_basic_component.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/01_basic_component.html">
|
||||
2
docs/book_ru/src/view/02_dynamic_attributes.md
Normal file
2
docs/book_ru/src/view/02_dynamic_attributes.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/02_dynamic_attributes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/02_dynamic_attributes.html">
|
||||
2
docs/book_ru/src/view/03_components.md
Normal file
2
docs/book_ru/src/view/03_components.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/03_components.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/03_components.html">
|
||||
2
docs/book_ru/src/view/04_iteration.md
Normal file
2
docs/book_ru/src/view/04_iteration.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/04_iteration.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/04_iteration.html">
|
||||
2
docs/book_ru/src/view/04b_iteration.md
Normal file
2
docs/book_ru/src/view/04b_iteration.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/04b_iteration.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/04b_iteration.html">
|
||||
2
docs/book_ru/src/view/05_forms.md
Normal file
2
docs/book_ru/src/view/05_forms.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/05_forms.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/05_forms.html">
|
||||
2
docs/book_ru/src/view/06_control_flow.md
Normal file
2
docs/book_ru/src/view/06_control_flow.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/06_control_flow.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/06_control_flow.html">
|
||||
2
docs/book_ru/src/view/07_errors.md
Normal file
2
docs/book_ru/src/view/07_errors.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/07_errors.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/07_errors.html">
|
||||
2
docs/book_ru/src/view/08_parent_child.md
Normal file
2
docs/book_ru/src/view/08_parent_child.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/08_parent_child.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/08_parent_child.html">
|
||||
2
docs/book_ru/src/view/09_component_children.md
Normal file
2
docs/book_ru/src/view/09_component_children.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/09_component_children.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/09_component_children.html">
|
||||
2
docs/book_ru/src/view/README.md
Normal file
2
docs/book_ru/src/view/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/index.html">
|
||||
2
docs/book_ru/src/view/builder.md
Normal file
2
docs/book_ru/src/view/builder.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/builder.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/builder.html">
|
||||
@@ -47,11 +47,11 @@ CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
|
||||
workspace = false
|
||||
description = "Generate the list of workspace members"
|
||||
script = '''
|
||||
examples=$(ls |
|
||||
grep -v .md |
|
||||
grep -v Makefile.toml |
|
||||
grep -v cargo-make |
|
||||
grep -v gtk |
|
||||
examples=$(ls |
|
||||
grep -v .md |
|
||||
grep -v Makefile.toml |
|
||||
grep -v cargo-make |
|
||||
grep -v gtk |
|
||||
jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = $examples"
|
||||
'''
|
||||
|
||||
44
examples/cargo-make/cargo-leptos-compress.toml
Normal file
44
examples/cargo-make/cargo-leptos-compress.toml
Normal file
@@ -0,0 +1,44 @@
|
||||
extend = [
|
||||
{ path = "./lint.toml" }
|
||||
]
|
||||
|
||||
[tasks.make-target-site-dir]
|
||||
command = "mkdir"
|
||||
args = ["-p", "target/site"]
|
||||
|
||||
[tasks.install-cargo-leptos]
|
||||
install_crate = { crate_name = "cargo-leptos", binary = "cargo-leptos", test_arg = "--help" }
|
||||
|
||||
[tasks.cargo-leptos-e2e]
|
||||
command = "cargo"
|
||||
args = ["leptos", "end-to-end"]
|
||||
|
||||
[tasks.build]
|
||||
clear = true
|
||||
command = "cargo"
|
||||
dependencies = ["make-target-site-dir"]
|
||||
args = ["leptos", "build", "--release", "-P"]
|
||||
|
||||
[tasks.check]
|
||||
clear = true
|
||||
dependencies = ["check-debug", "check-release"]
|
||||
|
||||
[tasks.check-debug]
|
||||
toolchain = "stable"
|
||||
command = "cargo"
|
||||
args = ["check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.check-release]
|
||||
toolchain = "stable"
|
||||
command = "cargo"
|
||||
args = ["check-all-features", "--release"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.lint]
|
||||
dependencies = ["make-target-site-dir", "check-style"]
|
||||
|
||||
[tasks.start-client]
|
||||
dependencies = ["install-cargo-leptos"]
|
||||
command = "cargo"
|
||||
args = ["leptos", "watch", "--release", "-P"]
|
||||
@@ -1,9 +1,11 @@
|
||||
[tasks.build]
|
||||
install_crate = { crate_name = "wasm-pack", binary = "wasm-pack", test_arg = "--help" }
|
||||
clear = true
|
||||
command = "deno"
|
||||
args = ["task", "build"]
|
||||
|
||||
[tasks.start-client]
|
||||
install_crate = { crate_name = "wasm-pack", binary = "wasm-pack", test_arg = "--help" }
|
||||
command = "deno"
|
||||
args = ["task", "start"]
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ axum = { version = "0.7", optional = true, features = ["http2"] }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = [
|
||||
"fs",
|
||||
"compression-gzip",
|
||||
"compression-br",
|
||||
], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
@@ -38,6 +39,8 @@ http = { version = "1.0", optional = true }
|
||||
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
|
||||
wasm-bindgen = "0.2"
|
||||
lazy_static = "1.4.0"
|
||||
rust-embed = { version = "8", features = ["axum", "mime_guess", "tokio"], optional = true }
|
||||
mime_guess = { version = "2.0.4", optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
@@ -49,6 +52,8 @@ ssr = [
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"dep:http",
|
||||
"dep:rust-embed",
|
||||
"dep:mime_guess",
|
||||
"leptos/ssr",
|
||||
"leptos_axum",
|
||||
"leptos_meta/ssr",
|
||||
@@ -94,6 +99,12 @@ bin-features = ["ssr"]
|
||||
# Optional. Defaults to false.
|
||||
bin-default-features = false
|
||||
|
||||
# This feature will add a hash to the filename of assets.
|
||||
# This is useful here because our files are precompressed and use a `Cache-Control` policy to reduce HTTP requests
|
||||
#
|
||||
# Optional. Defaults to false.
|
||||
hash_file = true
|
||||
|
||||
# The features to use when compiling the lib target
|
||||
#
|
||||
# Optional. Can be over-ridden with the command line parameter --lib-features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
extend = [
|
||||
{ path = "../cargo-make/main.toml" },
|
||||
{ path = "../cargo-make/cargo-leptos.toml" },
|
||||
{ path = "../cargo-make/cargo-leptos-compress.toml" },
|
||||
]
|
||||
|
||||
[env]
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Leptos Hacker News Example with Axum
|
||||
|
||||
This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository. This repo differs from the main Hacker News example by using Axum as it's server.
|
||||
This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to:
|
||||
- Create a client-side rendered app
|
||||
- Create a server side rendered app with hydration
|
||||
- Precompress static assets and bundle those in with the server binary
|
||||
|
||||
This repo differs from the main Hacker News example by using Axum as it's server, precompressing and embedding static assets into the binary, and dynamically compressing the generated HTML.
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -8,4 +13,4 @@ See the [Examples README](../README.md) for setup and run instructions.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Run `cargo leptos watch` to run this example.
|
||||
Run `cargo leptos watch --release -P` to run this example.
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
wasm-pack build --target=web --features=hydrate --release
|
||||
cd pkg
|
||||
rm *.br
|
||||
cp hackernews.js hackernews.unmin.js
|
||||
cat hackernews.unmin.js | esbuild > hackernews.js
|
||||
brotli hackernews.js
|
||||
brotli hackernews_bg.wasm
|
||||
brotli style.css
|
||||
@@ -2,20 +2,34 @@ use crate::error_template::error_template;
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::State,
|
||||
http::{Request, Response, StatusCode, Uri},
|
||||
http::{header, Request, Response, StatusCode, Uri},
|
||||
response::{IntoResponse, Response as AxumResponse},
|
||||
};
|
||||
use leptos::LeptosOptions;
|
||||
use tower::ServiceExt;
|
||||
use tower_http::services::ServeDir;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const DEV_MODE: bool = false;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const DEV_MODE: bool = true;
|
||||
|
||||
#[derive(rust_embed::RustEmbed)]
|
||||
#[folder = "target/site/"]
|
||||
struct Assets;
|
||||
|
||||
pub async fn file_and_error_handler(
|
||||
uri: Uri,
|
||||
State(options): State<LeptosOptions>,
|
||||
req: Request<Body>,
|
||||
) -> AxumResponse {
|
||||
let root = options.site_root.clone();
|
||||
let res = get_static_file(uri.clone(), &root).await.unwrap();
|
||||
let accept_encoding = req
|
||||
.headers()
|
||||
.get("accept-encoding")
|
||||
.map(|h| h.to_str().unwrap_or("none"))
|
||||
.unwrap_or("none")
|
||||
.to_string();
|
||||
let res = get_static_file(uri.clone(), accept_encoding).await.unwrap();
|
||||
|
||||
if res.status() == StatusCode::OK {
|
||||
res.into_response()
|
||||
@@ -30,19 +44,56 @@ pub async fn file_and_error_handler(
|
||||
|
||||
async fn get_static_file(
|
||||
uri: Uri,
|
||||
root: &str,
|
||||
accept_encoding: String,
|
||||
) -> Result<Response<Body>, (StatusCode, String)> {
|
||||
let req = Request::builder()
|
||||
.uri(uri.clone())
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
|
||||
// This path is relative to the cargo root
|
||||
match ServeDir::new(root).oneshot(req).await {
|
||||
Ok(res) => Ok(res.into_response()),
|
||||
Err(err) => Err((
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Something went wrong: {}", err),
|
||||
)),
|
||||
let (_, path) = uri.path().split_at(1); // split off the first `/`
|
||||
let mime = mime_guess::from_path(path);
|
||||
|
||||
let (path, encoding) = if DEV_MODE {
|
||||
// during DEV, don't care about the precompression -> faster workflow
|
||||
(Cow::from(path), "none")
|
||||
} else if accept_encoding.contains("br") {
|
||||
(Cow::from(format!("{}.br", path)), "br")
|
||||
} else if accept_encoding.contains("gzip") {
|
||||
(Cow::from(format!("{}.gz", path)), "gzip")
|
||||
} else {
|
||||
(Cow::from(path), "none")
|
||||
};
|
||||
|
||||
match Assets::get(path.as_ref()) {
|
||||
Some(content) => {
|
||||
let body = Body::from(content.data);
|
||||
|
||||
let res = match DEV_MODE {
|
||||
true => Response::builder()
|
||||
.header(
|
||||
header::CONTENT_TYPE,
|
||||
mime.first_or_octet_stream().as_ref(),
|
||||
)
|
||||
.header(header::CONTENT_ENCODING, encoding)
|
||||
.body(body)
|
||||
.unwrap(),
|
||||
false => Response::builder()
|
||||
.header(header::CACHE_CONTROL, "max-age=86400")
|
||||
.header(
|
||||
header::CONTENT_TYPE,
|
||||
mime.first_or_octet_stream().as_ref(),
|
||||
)
|
||||
.header(header::CONTENT_ENCODING, encoding)
|
||||
.body(body)
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
Ok(res.into_response())
|
||||
}
|
||||
|
||||
None => {
|
||||
eprintln!(">> Asset {} not found", path);
|
||||
for a in Assets::iter() {
|
||||
eprintln!("Available asset: {}", a);
|
||||
}
|
||||
|
||||
Err((StatusCode::NOT_FOUND, "Not found".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,33 @@ async fn main() {
|
||||
use hackernews_islands::*;
|
||||
pub use leptos::get_configuration;
|
||||
pub use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use tower_http::compression::{
|
||||
predicate::{NotForContentType, SizeAbove},
|
||||
CompressionLayer, CompressionLevel, Predicate,
|
||||
};
|
||||
|
||||
let conf = get_configuration(Some("Cargo.toml")).await.unwrap();
|
||||
let leptos_options = conf.leptos_options;
|
||||
let addr = leptos_options.site_addr;
|
||||
let routes = generate_route_list(App);
|
||||
|
||||
let predicate = SizeAbove::new(1500) // files smaller than 1501 bytes are not compressed, since the MTU (Maximum Transmission Unit) of a TCP packet is 1500 bytes
|
||||
.and(NotForContentType::GRPC)
|
||||
.and(NotForContentType::IMAGES)
|
||||
// prevent compressing assets that are already statically compressed
|
||||
.and(NotForContentType::const_new("application/javascript"))
|
||||
.and(NotForContentType::const_new("application/wasm"))
|
||||
.and(NotForContentType::const_new("text/css"));
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
.route("/favicon.ico", get(file_and_error_handler))
|
||||
.leptos_routes(&leptos_options, routes, App)
|
||||
.layer(
|
||||
CompressionLayer::new()
|
||||
.quality(CompressionLevel::Fastest)
|
||||
.compress_when(predicate),
|
||||
)
|
||||
.fallback(file_and_error_handler)
|
||||
.with_state(leptos_options);
|
||||
|
||||
|
||||
@@ -14,17 +14,17 @@ lto = true
|
||||
console_log = "1.0.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
cfg-if = "1.0.0"
|
||||
leptos = { version = "0.5" }
|
||||
leptos_axum = { version = "0.5", default-features = false, optional = true }
|
||||
leptos_meta = { version = "0.5" }
|
||||
leptos_router = { version = "0.5" }
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.17"
|
||||
simple_logger = "4.0.0"
|
||||
serde = { version = "1.0.148", features = ["derive"] }
|
||||
tracing = "0.1"
|
||||
gloo-net = { version = "0.4.0", features = ["http"] }
|
||||
reqwest = { version = "0.11.13", features = ["json"] }
|
||||
axum = { version = "0.6", default-features = false, optional = true }
|
||||
axum = { version = "0.7", default-features = false, optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
http = { version = "0.2.11", optional = true }
|
||||
web-sys = { version = "0.3", features = [
|
||||
@@ -37,7 +37,7 @@ wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = { version = "0.4.37", features = [
|
||||
"futures-core-03-stream",
|
||||
], optional = true }
|
||||
axum-js-fetch = { version = "0.2.1", optional = true }
|
||||
axum-js-fetch = { git = "https://github.com/seanaye/axum-js-fetch", optional = true }
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[features]
|
||||
|
||||
2
examples/hackernews_js_fetch/rust-toolchain.toml
Normal file
2
examples/hackernews_js_fetch/rust-toolchain.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "stable" # test change
|
||||
@@ -62,8 +62,8 @@ mod ssr_imports {
|
||||
let routes = generate_route_list(App);
|
||||
|
||||
// build our application with a route
|
||||
let app: axum::Router<(), axum::body::Body> = Router::new()
|
||||
.leptos_routes(&leptos_options, routes, || view! { <App/> })
|
||||
let app: axum::Router<()> = Router::new()
|
||||
.leptos_routes(&leptos_options, routes, App)
|
||||
.route("/api/*fn_name", post(leptos_axum::handle_server_fns))
|
||||
.with_state(leptos_options);
|
||||
|
||||
@@ -73,7 +73,7 @@ mod ssr_imports {
|
||||
}
|
||||
|
||||
pub async fn serve(&self, req: web_sys::Request) -> web_sys::Response {
|
||||
self.0.serve(req).await
|
||||
self.0.oneshot(req).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
examples/server_fns_axum/watched_files/.gitkeep
Normal file
0
examples/server_fns_axum/watched_files/.gitkeep
Normal file
@@ -8,7 +8,7 @@ leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos_meta = { path = "../../meta", features = ["csr"] }
|
||||
leptos_router = { path = "../../router", features = ["csr"] }
|
||||
log = "0.4"
|
||||
gloo-net = { version = "0.2", features = ["http"] }
|
||||
gloo-net = { version = "0.5", features = ["http"] }
|
||||
|
||||
# dependencies for client (enable when csr or hydrate set)
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extend = [
|
||||
{ path = "../cargo-make/main.toml" },
|
||||
{ path = "../cargo-make/trunk_server.toml" },
|
||||
{ path = "../cargo-make/main.toml" },
|
||||
{ path = "../cargo-make/trunk_server.toml" },
|
||||
]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[[hooks]]
|
||||
stage = "pre_build"
|
||||
command = "sh"
|
||||
command_arguments = ["-c", "npx tailwindcss -i input.css -o style/output.css"]
|
||||
@@ -1,14 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link data-trunk rel="rust" data-wasm-opt="z" />
|
||||
<link data-trunk rel="icon" type="image/ico" href="/public/favicon.ico" />
|
||||
<link data-trunk rel="css" href="/style/output.css" />
|
||||
<link data-trunk rel="tailwind-css" href="/style/tailwind.css" />
|
||||
<title>Leptos • Counter with Tailwind</title>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
</html>
|
||||
|
||||
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
|
||||
*/
|
||||
|
||||
/*
|
||||
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
||||
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
||||
*/
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
border-width: 0;
|
||||
/* 2 */
|
||||
border-style: solid;
|
||||
/* 2 */
|
||||
border-color: #e5e7eb;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
::before,
|
||||
::after {
|
||||
--tw-content: '';
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use a consistent sensible line-height in all browsers.
|
||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
3. Use a more readable tab size.
|
||||
4. Use the user's configured `sans` font-family by default.
|
||||
5. Use the user's configured `sans` font-feature-settings by default.
|
||||
6. Use the user's configured `sans` font-variation-settings by default.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.5;
|
||||
/* 1 */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
-moz-tab-size: 4;
|
||||
/* 3 */
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
/* 3 */
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
/* 4 */
|
||||
font-feature-settings: normal;
|
||||
/* 5 */
|
||||
font-variation-settings: normal;
|
||||
/* 6 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Remove the margin in all browsers.
|
||||
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
/* 1 */
|
||||
line-height: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Add the correct height in Firefox.
|
||||
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
||||
3. Ensure horizontal rules are visible by default.
|
||||
*/
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
/* 1 */
|
||||
color: inherit;
|
||||
/* 2 */
|
||||
border-top-width: 1px;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct text decoration in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the default font size and weight for headings.
|
||||
*/
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Reset links to optimize for opt-in styling instead of opt-out.
|
||||
*/
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct font weight in Edge and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use the user's configured `mono` font family by default.
|
||||
2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
/* 1 */
|
||||
font-size: 1em;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*
|
||||
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
||||
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
||||
3. Remove gaps between table borders by default.
|
||||
*/
|
||||
|
||||
table {
|
||||
text-indent: 0;
|
||||
/* 1 */
|
||||
border-color: inherit;
|
||||
/* 2 */
|
||||
border-collapse: collapse;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Change the font styles in all browsers.
|
||||
2. Remove the margin in Firefox and Safari.
|
||||
3. Remove default padding in all browsers.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
/* 1 */
|
||||
font-feature-settings: inherit;
|
||||
/* 1 */
|
||||
font-variation-settings: inherit;
|
||||
/* 1 */
|
||||
font-size: 100%;
|
||||
/* 1 */
|
||||
font-weight: inherit;
|
||||
/* 1 */
|
||||
line-height: inherit;
|
||||
/* 1 */
|
||||
color: inherit;
|
||||
/* 1 */
|
||||
margin: 0;
|
||||
/* 2 */
|
||||
padding: 0;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the inheritance of text transform in Edge and Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the inability to style clickable types in iOS and Safari.
|
||||
2. Remove default button styles.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type='button'],
|
||||
[type='reset'],
|
||||
[type='submit'] {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
background-color: transparent;
|
||||
/* 2 */
|
||||
background-image: none;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Use the modern Firefox focus style for all focusable elements.
|
||||
*/
|
||||
|
||||
:-moz-focusring {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
||||
*/
|
||||
|
||||
:-moz-ui-invalid {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct vertical alignment in Chrome and Firefox.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/*
|
||||
Correct the cursor style of increment and decrement buttons in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-inner-spin-button,
|
||||
::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the odd appearance in Chrome and Safari.
|
||||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the inability to style clickable types in iOS and Safari.
|
||||
2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
font: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct display in Chrome and Safari.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/*
|
||||
Removes the default spacing and border for appropriate elements.
|
||||
*/
|
||||
|
||||
blockquote,
|
||||
dl,
|
||||
dd,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
hr,
|
||||
figure,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
menu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Reset default styling for dialogs.
|
||||
*/
|
||||
|
||||
dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Prevent resizing textareas horizontally by default.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
||||
2. Set the default placeholder color to the user's configured gray 400 color.
|
||||
*/
|
||||
|
||||
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Set the default cursor for buttons.
|
||||
*/
|
||||
|
||||
button,
|
||||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
Make sure disabled buttons don't get the pointer cursor.
|
||||
*/
|
||||
|
||||
:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
||||
This can trigger a poorly considered lint error in some tools but is included by design.
|
||||
*/
|
||||
|
||||
img,
|
||||
svg,
|
||||
video,
|
||||
canvas,
|
||||
audio,
|
||||
iframe,
|
||||
embed,
|
||||
object {
|
||||
display: block;
|
||||
/* 1 */
|
||||
vertical-align: middle;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||
*/
|
||||
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Make elements with the HTML hidden attribute stay hidden by default */
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
*, ::before, ::after {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-pan-x: ;
|
||||
--tw-pan-y: ;
|
||||
--tw-pinch-zoom: ;
|
||||
--tw-scroll-snap-strictness: proximity;
|
||||
--tw-gradient-from-position: ;
|
||||
--tw-gradient-via-position: ;
|
||||
--tw-gradient-to-position: ;
|
||||
--tw-ordinal: ;
|
||||
--tw-slashed-zero: ;
|
||||
--tw-numeric-figure: ;
|
||||
--tw-numeric-spacing: ;
|
||||
--tw-numeric-fraction: ;
|
||||
--tw-ring-inset: ;
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-shadow-colored: 0 0 #0000;
|
||||
--tw-blur: ;
|
||||
--tw-brightness: ;
|
||||
--tw-contrast: ;
|
||||
--tw-grayscale: ;
|
||||
--tw-hue-rotate: ;
|
||||
--tw-invert: ;
|
||||
--tw-saturate: ;
|
||||
--tw-sepia: ;
|
||||
--tw-drop-shadow: ;
|
||||
--tw-backdrop-blur: ;
|
||||
--tw-backdrop-brightness: ;
|
||||
--tw-backdrop-contrast: ;
|
||||
--tw-backdrop-grayscale: ;
|
||||
--tw-backdrop-hue-rotate: ;
|
||||
--tw-backdrop-invert: ;
|
||||
--tw-backdrop-opacity: ;
|
||||
--tw-backdrop-saturate: ;
|
||||
--tw-backdrop-sepia: ;
|
||||
}
|
||||
|
||||
::backdrop {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-pan-x: ;
|
||||
--tw-pan-y: ;
|
||||
--tw-pinch-zoom: ;
|
||||
--tw-scroll-snap-strictness: proximity;
|
||||
--tw-gradient-from-position: ;
|
||||
--tw-gradient-via-position: ;
|
||||
--tw-gradient-to-position: ;
|
||||
--tw-ordinal: ;
|
||||
--tw-slashed-zero: ;
|
||||
--tw-numeric-figure: ;
|
||||
--tw-numeric-spacing: ;
|
||||
--tw-numeric-fraction: ;
|
||||
--tw-ring-inset: ;
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-shadow-colored: 0 0 #0000;
|
||||
--tw-blur: ;
|
||||
--tw-brightness: ;
|
||||
--tw-contrast: ;
|
||||
--tw-grayscale: ;
|
||||
--tw-hue-rotate: ;
|
||||
--tw-invert: ;
|
||||
--tw-saturate: ;
|
||||
--tw-sepia: ;
|
||||
--tw-drop-shadow: ;
|
||||
--tw-backdrop-blur: ;
|
||||
--tw-backdrop-brightness: ;
|
||||
--tw-backdrop-contrast: ;
|
||||
--tw-backdrop-grayscale: ;
|
||||
--tw-backdrop-hue-rotate: ;
|
||||
--tw-backdrop-invert: ;
|
||||
--tw-backdrop-opacity: ;
|
||||
--tw-backdrop-saturate: ;
|
||||
--tw-backdrop-sepia: ;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.my-0 {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.max-w-3xl {
|
||||
max-width: 48rem;
|
||||
}
|
||||
|
||||
.rounded-lg {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.bg-amber-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(217 119 6 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.p-6 {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.px-10 {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
|
||||
.px-5 {
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1.25rem;
|
||||
}
|
||||
|
||||
.py-3 {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.pb-10 {
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-4xl {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
.text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-sky-700:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(3 105 161 / var(--tw-bg-opacity));
|
||||
}
|
||||
@@ -27,3 +27,6 @@ tokio = { version = "1", features = ["rt", "fs"] }
|
||||
[features]
|
||||
nonce = ["leptos/nonce"]
|
||||
experimental-islands = ["leptos_integration_utils/experimental-islands"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -729,10 +729,7 @@ async fn stream_app(
|
||||
|
||||
build_stream_response(options, res_options, stream, runtime).await
|
||||
}
|
||||
#[cfg_attr(
|
||||
any(debug_assertions, feature = "ssr"),
|
||||
instrument(level = "trace", skip_all,)
|
||||
)]
|
||||
#[cfg_attr(any(debug_assertions), instrument(level = "trace", skip_all,))]
|
||||
async fn stream_app_in_order(
|
||||
options: &LeptosOptions,
|
||||
app: impl FnOnce() -> View + 'static,
|
||||
|
||||
@@ -37,3 +37,6 @@ nonce = ["leptos/nonce"]
|
||||
wasm = []
|
||||
default = ["tokio/fs", "tokio/sync"]
|
||||
experimental-islands = ["leptos_integration_utils/experimental-islands"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -54,7 +54,10 @@ use leptos_meta::{generate_head_metadata_separated, MetaContext};
|
||||
use leptos_router::*;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::RwLock;
|
||||
use server_fn::{error::NoCustomError, redirect::REDIRECT_HEADER};
|
||||
use server_fn::{
|
||||
error::{NoCustomError, ServerFnErrorSerde},
|
||||
redirect::REDIRECT_HEADER,
|
||||
};
|
||||
use std::{fmt::Debug, io, pin::Pin, sync::Arc, thread::available_parallelism};
|
||||
use tokio_util::task::LocalPoolHandle;
|
||||
use tracing::Instrument;
|
||||
@@ -357,9 +360,10 @@ async fn handle_server_fns_inner(
|
||||
rx.await.unwrap_or_else(|e| {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ServerFnError::<NoCustomError>::ServerError(e.to_string())
|
||||
.ser()
|
||||
.unwrap_or_default(),
|
||||
ServerFnErrorSerde::ser(
|
||||
&ServerFnError::<NoCustomError>::ServerError(e.to_string()),
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.into_response()
|
||||
})
|
||||
|
||||
@@ -18,3 +18,6 @@ tracing = "0.1.37"
|
||||
|
||||
[features]
|
||||
experimental-islands = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -16,7 +16,7 @@ leptos_macro = { workspace = true }
|
||||
leptos_reactive = { workspace = true }
|
||||
leptos_server = { workspace = true }
|
||||
leptos_config = { workspace = true }
|
||||
leptos-spin-macro = { version = "0.1", optional = true }
|
||||
leptos-spin-macro = { version = "0.2", optional = true }
|
||||
tracing = "0.1"
|
||||
typed-builder = "0.18"
|
||||
typed-builder-macro = "0.18"
|
||||
@@ -70,7 +70,7 @@ nightly = [
|
||||
serde = ["leptos_reactive/serde"]
|
||||
serde-lite = ["leptos_reactive/serde-lite"]
|
||||
miniserde = ["leptos_reactive/miniserde"]
|
||||
rkyv = ["leptos_reactive/rkyv"]
|
||||
rkyv = ["leptos_reactive/rkyv", "server_fn/rkyv"]
|
||||
tracing = ["leptos_macro/tracing"]
|
||||
nonce = ["leptos_dom/nonce"]
|
||||
spin = ["leptos_reactive/spin", "leptos-spin-macro"]
|
||||
@@ -141,3 +141,6 @@ skip_feature_sets = [
|
||||
"rustls",
|
||||
],
|
||||
]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -16,8 +16,80 @@ pub type ChildrenFnMut = Box<dyn FnMut() -> Fragment>;
|
||||
// This is to still support components that accept `Box<dyn Fn() -> Fragment>` as a children.
|
||||
type BoxedChildrenFn = Box<dyn Fn() -> Fragment>;
|
||||
|
||||
#[doc(hidden)]
|
||||
/// This trait can be used when constructing a component that takes children without needing
|
||||
/// to know exactly what children type the component expects. This is used internally by the
|
||||
/// `view!` macro implementation, and can also be used explicitly when using the builder syntax.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Without ToChildren
|
||||
///
|
||||
/// Without [ToChildren], consumers need to explicitly provide children using the type expected
|
||||
/// by the component. For example, [Provider][crate::Provider]'s children need to wrapped in
|
||||
/// a [Box], while [Show][crate::Show]'s children need to be wrapped in an [Rc].
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::{ProviderProps, ShowProps};
|
||||
/// # use leptos_dom::html::p;
|
||||
/// # use leptos_dom::IntoView;
|
||||
/// # use leptos_macro::component;
|
||||
/// # use std::rc::Rc;
|
||||
/// #
|
||||
/// #[component]
|
||||
/// fn App() -> impl IntoView {
|
||||
/// (
|
||||
/// ProviderProps::builder()
|
||||
/// .children(Box::new(|| p().child("Foo").into_view().into()))
|
||||
/// // ...
|
||||
/// # .value("Foo")
|
||||
/// # .build(),
|
||||
/// ShowProps::builder()
|
||||
/// .children(Rc::new(|| p().child("Foo").into_view().into()))
|
||||
/// // ...
|
||||
/// # .when(|| true)
|
||||
/// # .fallback(|| p().child("foo"))
|
||||
/// # .build(),
|
||||
/// )
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## With ToChildren
|
||||
///
|
||||
/// With [ToChildren], consumers don't need to know exactly which type a component uses for
|
||||
/// its children.
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::{ProviderProps, ShowProps};
|
||||
/// # use leptos_dom::html::p;
|
||||
/// # use leptos_dom::IntoView;
|
||||
/// # use leptos_macro::component;
|
||||
/// # use std::rc::Rc;
|
||||
/// # use leptos::ToChildren;
|
||||
/// #
|
||||
/// #[component]
|
||||
/// fn App() -> impl IntoView {
|
||||
/// (
|
||||
/// ProviderProps::builder()
|
||||
/// .children(ToChildren::to_children(|| {
|
||||
/// p().child("Foo").into_view().into()
|
||||
/// }))
|
||||
/// // ...
|
||||
/// # .value("Foo")
|
||||
/// # .build(),
|
||||
/// ShowProps::builder()
|
||||
/// .children(ToChildren::to_children(|| {
|
||||
/// p().child("Foo").into_view().into()
|
||||
/// }))
|
||||
/// // ...
|
||||
/// # .when(|| true)
|
||||
/// # .fallback(|| p().child("foo"))
|
||||
/// # .build(),
|
||||
/// )
|
||||
/// }
|
||||
pub trait ToChildren<F> {
|
||||
/// Convert the provided type to (generally a closure) to Self (generally a "children" type,
|
||||
/// e.g., [Children]). See the implementations to see exactly which input types are supported
|
||||
/// and which "children" type they are converted to.
|
||||
fn to_children(f: F) -> Self;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,6 @@ use std::hash::Hash;
|
||||
/// }
|
||||
/// }
|
||||
/// />
|
||||
/// <For
|
||||
/// // a function that returns the items we're iterating over; a signal is fine
|
||||
/// each=move || counters.get()
|
||||
/// // a unique key for each item
|
||||
/// key=|counter| counter.id
|
||||
/// // renders each item to a view
|
||||
/// children=move |counter: Counter| {
|
||||
/// view! {
|
||||
/// <button>"Value: " {move || counter.count.get()}</button>
|
||||
/// }
|
||||
/// }
|
||||
/// />
|
||||
/// </div>
|
||||
/// }
|
||||
/// }
|
||||
|
||||
@@ -285,6 +285,21 @@ pub trait DynAttrs {
|
||||
|
||||
impl DynAttrs for () {}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait DynBindings {
|
||||
fn dyn_bindings<B: Into<Binding>>(
|
||||
self,
|
||||
_args: impl IntoIterator<Item = B>,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl DynBindings for () {}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PropsOrNoPropsBuilder {
|
||||
type Builder;
|
||||
|
||||
@@ -2,6 +2,11 @@ use crate::ChildrenFn;
|
||||
use cfg_if::cfg_if;
|
||||
use leptos_dom::IntoView;
|
||||
use leptos_macro::component;
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
any(feature = "hydrate", feature = "csr")
|
||||
))]
|
||||
use leptos_reactive::untrack;
|
||||
|
||||
/// Renders components somewhere else in the DOM.
|
||||
///
|
||||
@@ -36,6 +41,7 @@ pub fn Portal(
|
||||
.unwrap_or_else(|| document().body().expect("body to exist").unchecked_into());
|
||||
|
||||
create_effect(move |_| {
|
||||
leptos::logging::log!("inside Portal effect");
|
||||
let tag = if is_svg { "g" } else { "div" };
|
||||
|
||||
let container = document()
|
||||
@@ -53,7 +59,8 @@ pub fn Portal(
|
||||
container.clone()
|
||||
};
|
||||
|
||||
let _ = render_root.append_child(&children().into_view().get_mountable_node());
|
||||
let children = untrack(|| children().into_view().get_mountable_node());
|
||||
let _ = render_root.append_child(&children);
|
||||
|
||||
let _ = mount.append_child(&container);
|
||||
|
||||
|
||||
@@ -20,3 +20,6 @@ typed-builder = "0.18"
|
||||
tokio = { version = "1", features = ["rt", "macros"] }
|
||||
tempfile = "3"
|
||||
temp-env = { version = "0.3.6", features = ["async_closure"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -178,3 +178,6 @@ trace-component-props = []
|
||||
[package.metadata.cargo-all-features]
|
||||
denylist = ["nightly", "trace-component-props"]
|
||||
skip_feature_sets = [["web", "ssr"]]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -251,7 +251,7 @@ where
|
||||
|
||||
impl IntoView for TextProp {
|
||||
fn into_view(self) -> View {
|
||||
self.get().into_view()
|
||||
(move || self.get()).into_view()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ impl IntoAttribute for Option<Box<dyn IntoAttribute>> {
|
||||
|
||||
impl IntoAttribute for TextProp {
|
||||
fn into_attribute(self) -> Attribute {
|
||||
self.get().into_attribute()
|
||||
(move || self.get()).into_attribute()
|
||||
}
|
||||
|
||||
impl_into_attr_boxed! {}
|
||||
|
||||
@@ -46,6 +46,16 @@ pub trait IntoStyle {
|
||||
fn into_style_boxed(self: Box<Self>) -> Style;
|
||||
}
|
||||
|
||||
impl IntoStyle for Style {
|
||||
fn into_style(self) -> Style {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_style_boxed(self: Box<Self>) -> Style {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoStyle for &'static str {
|
||||
#[inline(always)]
|
||||
fn into_style(self) -> Style {
|
||||
@@ -176,7 +186,7 @@ impl Style {
|
||||
/// Converts the style to its HTML value at that moment so it can be rendered on the server.
|
||||
pub fn as_value_string(
|
||||
&self,
|
||||
style_name: &'static str,
|
||||
style_name: &str,
|
||||
) -> Option<Oco<'static, str>> {
|
||||
match self {
|
||||
Style::Value(value) => {
|
||||
|
||||
@@ -31,10 +31,12 @@ use std::cell::Cell;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[repr(transparent)]
|
||||
pub struct NodeRef<T: ElementDescriptor + 'static>(
|
||||
RwSignal<Option<HtmlElement<T>>>,
|
||||
);
|
||||
#[cfg_attr(not(debug_assertions), repr(transparent))]
|
||||
pub struct NodeRef<T: ElementDescriptor + 'static> {
|
||||
element: RwSignal<Option<HtmlElement<T>>>,
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: &'static std::panic::Location<'static>,
|
||||
}
|
||||
|
||||
/// Creates a shared reference to a DOM node created while using the `view`
|
||||
/// macro to create your UI.
|
||||
@@ -65,9 +67,14 @@ pub struct NodeRef<T: ElementDescriptor + 'static>(
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[inline(always)]
|
||||
pub fn create_node_ref<T: ElementDescriptor + 'static>() -> NodeRef<T> {
|
||||
NodeRef(create_rw_signal(None))
|
||||
NodeRef {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
element: create_rw_signal(None),
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ElementDescriptor + 'static> NodeRef<T> {
|
||||
@@ -120,7 +127,7 @@ impl<T: ElementDescriptor + 'static> NodeRef<T> {
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
self.0.get()
|
||||
self.element.get()
|
||||
}
|
||||
|
||||
/// Gets the element that is currently stored in the reference.
|
||||
@@ -132,7 +139,7 @@ impl<T: ElementDescriptor + 'static> NodeRef<T> {
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
self.0.get_untracked()
|
||||
self.element.get_untracked()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@@ -144,13 +151,15 @@ impl<T: ElementDescriptor + 'static> NodeRef<T> {
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
self.0.update(|current| {
|
||||
self.element.update(|current| {
|
||||
if current.is_some() {
|
||||
#[cfg(debug_assertions)]
|
||||
crate::debug_warn!(
|
||||
"You are setting a NodeRef that has already been filled. \
|
||||
It’s possible this is intentional, but it’s also \
|
||||
possible that you’re accidentally using the same NodeRef \
|
||||
for multiple _ref attributes."
|
||||
"You are setting the NodeRef defined at {}, which has \
|
||||
already been filled It’s possible this is intentional, \
|
||||
but it’s also possible that you’re accidentally using \
|
||||
the same NodeRef for multiple _ref attributes.",
|
||||
self.defined_at
|
||||
);
|
||||
}
|
||||
*current = Some(node.clone());
|
||||
|
||||
@@ -51,3 +51,6 @@ axum = ["server_fn_macro/axum"]
|
||||
[package.metadata.cargo-all-features]
|
||||
denylist = ["nightly", "tracing", "trace-component-props"]
|
||||
skip_feature_sets = [["csr", "hydrate"], ["hydrate", "csr"], ["hydrate", "ssr"]]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -8,10 +8,11 @@ use leptos_hot_reload::parsing::value_to_string;
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens, TokenStreamExt};
|
||||
use syn::{
|
||||
parse::Parse, parse_quote, spanned::Spanned,
|
||||
AngleBracketedGenericArguments, Attribute, FnArg, GenericArgument, Item,
|
||||
ItemFn, LitStr, Meta, Pat, PatIdent, Path, PathArguments, ReturnType,
|
||||
Signature, Stmt, Type, TypePath, Visibility,
|
||||
parse::Parse, parse_quote, spanned::Spanned, token::Colon,
|
||||
visit_mut::VisitMut, AngleBracketedGenericArguments, Attribute, FnArg,
|
||||
GenericArgument, GenericParam, Item, ItemFn, LitStr, Meta, Pat, PatIdent,
|
||||
Path, PathArguments, ReturnType, Signature, Stmt, Type, TypeImplTrait,
|
||||
TypeParam, TypePath, Visibility,
|
||||
};
|
||||
|
||||
pub struct Model {
|
||||
@@ -28,6 +29,7 @@ pub struct Model {
|
||||
impl Parse for Model {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut item = ItemFn::parse(input)?;
|
||||
convert_impl_trait_to_generic(&mut item.sig);
|
||||
|
||||
let docs = Docs::new(&item.attrs);
|
||||
|
||||
@@ -178,6 +180,18 @@ impl ToTokens for Model {
|
||||
);
|
||||
|
||||
let component_fn_prop_docs = generate_component_fn_prop_docs(props);
|
||||
let docs_and_prop_docs = if component_fn_prop_docs.is_empty() {
|
||||
// Avoid generating an empty doc line in case the component has no doc and no props.
|
||||
quote! {
|
||||
#docs
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#docs
|
||||
#[doc = ""]
|
||||
#component_fn_prop_docs
|
||||
}
|
||||
};
|
||||
|
||||
let (
|
||||
tracing_instrument_attr,
|
||||
@@ -214,7 +228,7 @@ impl ToTokens for Model {
|
||||
|
||||
let component_id = name.to_string();
|
||||
let hydrate_fn_name =
|
||||
Ident::new(&format!("_island_{}", component_id), name.span());
|
||||
Ident::new(&format!("_island_{component_id}"), name.span());
|
||||
|
||||
let island_serialize_props = if is_island_with_other_props {
|
||||
quote! {
|
||||
@@ -365,6 +379,33 @@ impl ToTokens for Model {
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let dyn_binding_props = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.filter_map(
|
||||
|Prop {
|
||||
name,
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| {
|
||||
let ident = &name.ident;
|
||||
|
||||
if *attrs {
|
||||
Some(quote! {
|
||||
::leptos::leptos_dom::html::Binding::Attribute { name, value } => self.#ident.push((name, value)),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let body = quote! {
|
||||
#destructure_props
|
||||
#tracing_span_expr
|
||||
@@ -475,9 +516,7 @@ impl ToTokens for Model {
|
||||
let output = quote! {
|
||||
#[doc = #builder_name_doc]
|
||||
#[doc = ""]
|
||||
#docs
|
||||
#[doc = ""]
|
||||
#component_fn_prop_docs
|
||||
#docs_and_prop_docs
|
||||
#[derive(::leptos::typed_builder_macro::TypedBuilder #props_derive_serialize)]
|
||||
//#[builder(doc)]
|
||||
#[builder(crate_module_path=::leptos::typed_builder)]
|
||||
@@ -504,11 +543,24 @@ impl ToTokens for Model {
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics ::leptos::DynBindings for #props_name #generics #where_clause {
|
||||
fn dyn_bindings<B: Into<::leptos::leptos_dom::html::Binding>>(mut self, bindings: impl std::iter::IntoIterator<Item = B>) -> Self {
|
||||
for binding in bindings.into_iter() {
|
||||
let binding: ::leptos::leptos_dom::html::Binding = binding.into();
|
||||
|
||||
match binding {
|
||||
#dyn_binding_props
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#into_view
|
||||
|
||||
#docs
|
||||
#[doc = ""]
|
||||
#component_fn_prop_docs
|
||||
#docs_and_prop_docs
|
||||
#[allow(non_snake_case, clippy::too_many_arguments)]
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
#tracing_instrument_attr
|
||||
@@ -1179,3 +1231,57 @@ fn is_valid_into_view_return_type(ty: &ReturnType) -> bool {
|
||||
pub fn unmodified_fn_name_from_fn_name(ident: &Ident) -> Ident {
|
||||
Ident::new(&format!("__{ident}"), ident.span())
|
||||
}
|
||||
|
||||
/// Converts all `impl Trait`s in a function signature to use generic params instead.
|
||||
fn convert_impl_trait_to_generic(sig: &mut Signature) {
|
||||
fn new_generic_ident(i: usize, span: Span) -> Ident {
|
||||
Ident::new(&format!("__ImplTrait{i}"), span)
|
||||
}
|
||||
|
||||
// First: visit all `impl Trait`s and replace them with new generic params.
|
||||
#[derive(Default)]
|
||||
struct RemoveImplTrait(Vec<TypeImplTrait>);
|
||||
impl VisitMut for RemoveImplTrait {
|
||||
fn visit_type_mut(&mut self, ty: &mut Type) {
|
||||
syn::visit_mut::visit_type_mut(self, ty);
|
||||
if matches!(ty, Type::ImplTrait(_)) {
|
||||
let ident = new_generic_ident(self.0.len(), ty.span());
|
||||
let generic_type = Type::Path(TypePath {
|
||||
qself: None,
|
||||
path: Path::from(ident),
|
||||
});
|
||||
let Type::ImplTrait(impl_trait) =
|
||||
std::mem::replace(ty, generic_type)
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
self.0.push(impl_trait);
|
||||
}
|
||||
}
|
||||
|
||||
// Early exits.
|
||||
fn visit_attribute_mut(&mut self, _: &mut Attribute) {}
|
||||
fn visit_pat_mut(&mut self, _: &mut Pat) {}
|
||||
}
|
||||
let mut visitor = RemoveImplTrait::default();
|
||||
for fn_arg in sig.inputs.iter_mut() {
|
||||
visitor.visit_fn_arg_mut(fn_arg);
|
||||
}
|
||||
let RemoveImplTrait(impl_traits) = visitor;
|
||||
|
||||
// Second: Add the new generic params into the signature.
|
||||
for (i, impl_trait) in impl_traits.into_iter().enumerate() {
|
||||
let span = impl_trait.span();
|
||||
let ident = new_generic_ident(i, span);
|
||||
// We can simply append to the end (only lifetime params must be first).
|
||||
// Note currently default generics are not allowed in `fn`, so not a concern.
|
||||
sig.generics.params.push(GenericParam::Type(TypeParam {
|
||||
attrs: vec![],
|
||||
ident,
|
||||
colon_token: Some(Colon { spans: [span] }),
|
||||
bounds: impl_trait.bounds,
|
||||
eq_token: None,
|
||||
default: None,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,7 @@ pub(crate) enum Mode {
|
||||
|
||||
impl Default for Mode {
|
||||
fn default() -> Self {
|
||||
if cfg!(feature = "hydrate")
|
||||
|| cfg!(feature = "csr")
|
||||
|| cfg!(feature = "web")
|
||||
{
|
||||
if cfg!(feature = "hydrate") || cfg!(feature = "csr") {
|
||||
Mode::Client
|
||||
} else {
|
||||
Mode::Ssr
|
||||
@@ -489,7 +486,7 @@ pub fn template(tokens: TokenStream) -> TokenStream {
|
||||
/// use leptos::html::Div;
|
||||
///
|
||||
/// #[component]
|
||||
/// fn MyComponent<T: Fn() -> HtmlElement<Div>>(render_prop: impl Fn() -> HtmlElement<Div>) -> impl IntoView {
|
||||
/// fn MyComponent(render_prop: impl Fn() -> HtmlElement<Div>) -> impl IntoView {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
||||
@@ -11,7 +11,7 @@ use syn::{
|
||||
|
||||
struct SliceMacroInput {
|
||||
root: syn::Ident,
|
||||
path: Punctuated<syn::Ident, Token![.]>,
|
||||
path: Punctuated<syn::Member, Token![.]>,
|
||||
}
|
||||
|
||||
impl Parse for SliceMacroInput {
|
||||
@@ -19,7 +19,7 @@ impl Parse for SliceMacroInput {
|
||||
let root: syn::Ident = input.parse()?;
|
||||
input.parse::<Token![.]>()?;
|
||||
// do not accept trailing punctuation
|
||||
let path: Punctuated<syn::Ident, Token![.]> =
|
||||
let path: Punctuated<syn::Member, Token![.]> =
|
||||
Punctuated::parse_separated_nonempty(input)?;
|
||||
|
||||
if path.is_empty() {
|
||||
|
||||
@@ -52,12 +52,10 @@ pub(crate) fn fragment_to_tokens(
|
||||
None,
|
||||
)?;
|
||||
|
||||
let node = quote_spanned! {span=>
|
||||
#[allow(unused_braces)] {#node}
|
||||
};
|
||||
let node = quote_spanned!(span => { #node });
|
||||
|
||||
Some(quote! {
|
||||
::leptos::IntoView::into_view(#node)
|
||||
::leptos::IntoView::into_view(#[allow(unused_braces)] #node)
|
||||
})
|
||||
})
|
||||
.peekable();
|
||||
@@ -298,34 +296,38 @@ pub(crate) fn element_to_tokens(
|
||||
let children = node
|
||||
.children
|
||||
.iter()
|
||||
.map(|node| match node {
|
||||
Node::Fragment(fragment) => fragment_to_tokens(
|
||||
&fragment.children,
|
||||
true,
|
||||
parent_type,
|
||||
None,
|
||||
global_class,
|
||||
None,
|
||||
)
|
||||
.unwrap_or(quote_spanned! {
|
||||
Span::call_site()=> ::leptos::leptos_dom::Unit
|
||||
}),
|
||||
Node::Text(node) => quote! { #node },
|
||||
.filter_map(|node| match node {
|
||||
Node::Fragment(fragment) => Some(
|
||||
fragment_to_tokens(
|
||||
&fragment.children,
|
||||
true,
|
||||
parent_type,
|
||||
None,
|
||||
global_class,
|
||||
None,
|
||||
)
|
||||
.unwrap_or(quote_spanned! {
|
||||
Span::call_site()=> ::leptos::leptos_dom::Unit
|
||||
}),
|
||||
),
|
||||
Node::Text(node) => Some(quote! { #node }),
|
||||
Node::RawText(node) => {
|
||||
let text = node.to_string_best();
|
||||
let text = syn::LitStr::new(&text, node.span());
|
||||
quote! { #text }
|
||||
Some(quote! { #text })
|
||||
}
|
||||
Node::Block(node) => quote! { #node },
|
||||
Node::Element(node) => element_to_tokens(
|
||||
node,
|
||||
parent_type,
|
||||
None,
|
||||
global_class,
|
||||
None,
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
Node::Comment(_) | Node::Doctype(_) => quote! {},
|
||||
Node::Block(node) => Some(quote! { #node }),
|
||||
Node::Element(node) => Some(
|
||||
element_to_tokens(
|
||||
node,
|
||||
parent_type,
|
||||
None,
|
||||
global_class,
|
||||
None,
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
Node::Comment(_) | Node::Doctype(_) => None,
|
||||
})
|
||||
.map(|node| quote!(.child(#node)));
|
||||
|
||||
@@ -335,9 +337,7 @@ pub(crate) fn element_to_tokens(
|
||||
quote! {}
|
||||
};
|
||||
let ide_helper_close_tag = ide_helper_close_tag.into_iter();
|
||||
Some(quote_spanned! {node.span()=>
|
||||
#[allow(unused_braces)]
|
||||
{
|
||||
let result = quote_spanned! {node.span()=> {
|
||||
#(#ide_helper_close_tag)*
|
||||
#name
|
||||
#(#attrs)*
|
||||
@@ -348,7 +348,10 @@ pub(crate) fn element_to_tokens(
|
||||
#(#children)*
|
||||
#view_marker
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// We need to move "allow" out of "quote_spanned" because it breaks hovering in rust-analyzer
|
||||
Some(quote!(#[allow(unused_braces)] #result))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,30 @@ pub(crate) fn component_to_tokens(
|
||||
}
|
||||
});
|
||||
|
||||
let spread_bindings = node.attributes().iter().filter_map(|node| {
|
||||
use rstml::node::NodeBlock;
|
||||
use syn::{Expr, ExprRange, RangeLimits, Stmt};
|
||||
|
||||
if let NodeAttribute::Block(NodeBlock::ValidBlock(block)) = node {
|
||||
match block.stmts.first()? {
|
||||
Stmt::Expr(
|
||||
Expr::Range(ExprRange {
|
||||
start: None,
|
||||
limits: RangeLimits::HalfOpen(_),
|
||||
end: Some(end),
|
||||
..
|
||||
}),
|
||||
_,
|
||||
) => Some(
|
||||
quote! { .dyn_bindings(#[allow(unused_brace)] {#end}) },
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let props = attrs
|
||||
.clone()
|
||||
.filter(|attr| {
|
||||
@@ -46,12 +70,10 @@ pub(crate) fn component_to_tokens(
|
||||
})
|
||||
.unwrap_or_else(|| quote! { #name });
|
||||
|
||||
let value = quote_spanned! {value.span()=>
|
||||
#[allow(unused_braces)] {#value}
|
||||
};
|
||||
let value = quote_spanned!(value.span()=> { #value });
|
||||
|
||||
quote_spanned! {attr.span()=>
|
||||
.#name(#value)
|
||||
.#name(#[allow(unused_braces)] #value)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -213,24 +235,17 @@ pub(crate) fn component_to_tokens(
|
||||
|
||||
#[allow(unused_mut)] // used in debug
|
||||
let mut component = quote_spanned! {node.span()=>
|
||||
{
|
||||
let props = #component_props_builder
|
||||
::leptos::component_view(
|
||||
#[allow(clippy::needless_borrows_for_generic_args)]
|
||||
#name_ref,
|
||||
#component_props_builder
|
||||
#(#props)*
|
||||
#(#slots)*
|
||||
#children;
|
||||
|
||||
#[allow(clippy::let_unit_value, clippy::unit_arg)]
|
||||
let props = props
|
||||
#children
|
||||
#build
|
||||
#dyn_attrs;
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
::leptos::component_view(
|
||||
#[allow(clippy::needless_borrows_for_generic_args)]
|
||||
#name_ref,
|
||||
props
|
||||
)
|
||||
}
|
||||
#dyn_attrs
|
||||
#(#spread_bindings)*
|
||||
)
|
||||
};
|
||||
|
||||
// (Temporarily?) removed
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user