Compare commits

..

149 Commits

Author SHA1 Message Date
benwis
5baa76603b Add id to Body 2024-04-14 14:33:11 -07:00
benwis
a2927d7f18 Update spin_sdk to spin v3 2024-04-13 12:57:25 -07:00
Greg Johnston
e29d31e686 0.6.11 2024-04-10 09:33:22 -04:00
Greg Johnston
e68f1bbad5 fix: stable Router IDs (closes #2514) (#2515) 2024-04-10 09:31:34 -04:00
Greg Johnston
454a4f4ccb Merge pull request #2511 from leptos-rs/simplify-stable
Simplify stable syntax in examples
2024-04-09 15:30:51 -04:00
Greg Johnston
85a91af7c6 examples: simplify stable syntax for using signals in view 2024-04-09 14:45:19 -04:00
Greg Johnston
871d2c1b9f feat: directly implement IntoView on resources on stable 2024-04-09 14:45:01 -04:00
Greg Johnston
f0c1061161 chore(ci): remove nightly feature on counter_isomorphic (#2510) 2024-04-09 13:18:37 -04:00
Greg Johnston
d74af819a0 fix: invalid Location header when using leptos_actix::redirect() without JS/WASM (#2507) 2024-04-08 20:10:09 -04:00
Ar4ys
36b2f919dd feat: signifiantly improved error reporting in view macro (#2289)
* Added name span to .build in component_to_tokens

* Added #[allow(unreachable_code)] to  leptos::component_view inside component_to_tokens

* Added span to name reference in component_to_tokens

* Added span to leptos::component_props_builder in component_to_tokens

* Added span to props in component_to_tokens

* Added span to "on" method in events component_to_tokens

* Added spans in directive_call_from_attribute_node

* Added spans in fragment_to_tokens and it's ssr version

* Added span to props in slot_to_tokens

* Added span to the whole slot quote

* Changed slots's name span to last slot node

* Added span to the slot vec

* Added #[allow(unreachable_code)] to `.into()` in slot_to_tokens

* Added span to `.build()` in slot_to_tokens

* Added span for the whole component

* Added span to "clone:" directive

* Added span to ".children()"

* Removed unused "_span" param from fragment_to_tokens and fragment_to_tokens_ssr

* Removed unnecessary parenthesis around values in `attribute_to_tokens`

* Removed unnecessary curly braces around value in `spread_attrs`

* Removed unnecessary parenthesis around children in `element_to_tokens`

* Added catch-all span to element_to_tokens

* Formatted `quote!` according to official guidelines

* Updated view/snapshots in leptos_macro

* Added span to spread props in element_to_tokens_ssr

* Removed unnecessary curly braces in element_to_token_ssr

* Updated view/snapshots in leptos_macro

* Added view macro tests to leptos_macro

* Fixed clippy warnings in view macro output

* Updated view snapshots in tests

* Fixed expected_one_let_bind_got_none test in leptos_macro

* Removed snapshot tests in leptos_macro/tests/ui/view

---------

Co-authored-by: Greg Johnston <greg.johnston@gmail.com>
2024-04-08 08:14:33 -04:00
Greg Johnston
ab1c4ca7a6 chore(ci): run all examples under stable and fix remaining linting issue (#2503) 2024-04-05 16:09:23 -04:00
mahmoud-eltahawy
a1a989011a chore(ci): move all examples to run on stable (#2501) 2024-04-05 14:57:48 -04:00
Greg Johnston
43178b56dc chore(ci): move example CI over to stable (#2502) 2024-04-05 14:55:31 -04:00
Lukas Potthast
119c9ea23f feat: allow spreading of both attributes and event handlers (#2432) 2024-04-05 14:30:34 -04:00
Yann Dirson
fc537c14c4 feat: implement IntoView for Rc<str> (#2462)
With-help-from: Greg Johnston <greg.johnston@gmail.com>
Signed-off-by: Yann Dirson <ydirson@free.fr>
2024-04-05 09:58:35 -04:00
mahmoud-eltahawy
15f8bdd4dc stable todo_app_sqlite_axum example (#2493) 2024-04-04 20:12:45 -07:00
Sam Judelson
ca07d29db5 stable examples change (#2497) 2024-04-04 20:11:28 -07:00
Adrian
a82af6110f ex: counter_url_query; to stable (#2499) 2024-04-04 20:09:55 -07:00
Joseph Cruz
03ac6903f2 ci(examples/error-boundary): use stable syntax (#2496) 2024-04-04 20:08:50 -07:00
Joseph Cruz
e5af1456a6 fix(ci): false leptos changes detected (#2491) 2024-04-04 20:06:09 -07:00
mahmoud-eltahawy
8686d5aabb stable todomvc example (#2489) 2024-04-02 13:38:07 -07:00
Greg Johnston
c750f57ddc v0.6.10 2024-04-02 09:39:53 -04:00
Joseph Cruz
cc1f6f0a94 chore(ci): run semver checks on push (#2483) 2024-04-01 20:38:28 -04:00
Greg Johnston
a9034a92b0 fix: handle directives properly in SSR mode (closes #2488) (#2477) 2024-04-01 17:29:30 -04:00
zakstucke
9f1c09e131 feat: add View::on support for CoreComponent::{DynChild, Each} (#2422) 2024-04-01 17:09:05 -04:00
Greg Johnston
b79037b96f fix: correctly handle empty view! {} in hot-reloading code (closes #2421) (#2478) 2024-04-01 16:23:29 -04:00
Greg Johnston
41f3c46830 chore: bump nightly version in examples (#2479) 2024-04-01 15:16:53 -04:00
Greg Johnston
bfac4cba2a chore: cargo fmt 2024-03-31 14:12:33 -04:00
Paolo Barbolini
3e18edb8f9 chore: add repository field to server_fn_macro (#2474) 2024-03-31 14:10:47 -04:00
Joseph Cruz
e926ff24a6 ci: disable semver checks (#2471) 2024-03-30 20:05:20 +00:00
Gunnar Raßmann
d528cbd828 Fix: Environment variables do not overwrite Config.toml options (#2433)
* Fix environment variable parsing

* Fix failing tests

dfgdfgfd

dsf

* Add new test
2024-03-30 00:02:52 +00:00
Alex Lazar
642504f2ba Remove panic for axum ResponseOptions (#2468) 2024-03-29 07:37:12 +00:00
zakstucke
fd2817de26 Allow CDN_PKG_PATH at runtime as well as current build time, preferring it when available. (#2466) 2024-03-28 08:30:54 +00:00
Bart Toersche
73b8c7872e Fix: Small fix for location hash/fragment (#2464) 2024-03-27 06:45:29 +00:00
martin frances
f3d19ca744 Minor: Ran cargo clippy --fix (#2461)
Manually reviewed the changes. All look like reasonable nudges.

A summary :-

In one place removed a redundant call to .clone().

In two places, now using clone_from() which clippy says
**MAY** be an optimisation.
2024-03-23 18:27:31 -07:00
boyswan
0abcc348ca Persist parent span context within resource fetchers (#2456) 2024-03-22 15:51:50 -07:00
Joseph Cruz
572ae5bbdf test(ci): check semver (#2450)
* test(ci): check semver

* chore: simulate change

* fix(ci): add checkout

* fix(ci): version typo

* chore: remove simulated change
2024-03-22 15:51:13 -07:00
martin frances
0b70949118 Bumped base64 to 0.22. (#2457) 2024-03-22 15:07:04 -07:00
martin frances
5819014ccc Chore(ci) bumping tj-actions/changed-files to version 43. (#2454) 2024-03-22 07:23:57 -04:00
Joseph Cruz
630fd4570d fix(ci): trunk command not found (#2453)
* chore: simulate change

* chore: remove print trunk version

* Revert "chore: remove print trunk version"

This reverts commit c203a83b44.

* chore(ci): use jetli/trunk-action

* chore: remove simulated change
2024-03-22 07:23:48 -04:00
Ratul
d1560f9e1f Added missing link for #[server] macro (#2437)
* Added missing link for #[server] macro

Added missing link for #[server] macro

* Removed spurious entry
2024-03-20 14:24:54 -07:00
martin frances
841d7a690a chore: examples/tailwind_axum bumped tailwindcss to 3.4.2. (#2443) 2024-03-19 09:40:24 -07:00
sify21
104c09f3bf register server_fn first to allow for wildcard Route path (#2435)
It's normal to have a `NotFound` page with a wildcard path like this
```
<Routes>
    ...
    <Route path="*any" view=NotFound>
</Routes>
```
In `ssr` mode, most servers do a `first match win` approach, so we
should register server functions before view routes, or else a wildcard
route would block all api requests.

https://discord.com/channels/1031524867910148188/1218508054442545185

Signed-off-by: 司芳源 <sify21@163.com>
2024-03-19 09:37:42 -07:00
Joseph Cruz
ac75999c9f chore(ci): upgrade actions to node 20 (#2444)
* chore(ci): install jq with apt

* chore(ci): install trunk with cargo

* chore(ci): replace toolchain action

* chore(ci): upgrade pnpm cache action

* chore: simulate change

* fix(ci): pnpm cache action typo

* chore: remove simulated change
2024-03-19 09:36:30 -07:00
Richard Laughlin
7ef186f642 For the session_auth_axum example, move the passhash into a separate (#2446)
non-serializable struct.

This prevents it from being returned in the
get_user() API, and prevents it from being unintentionally returned on any
new API the end-user may create on top of this example code.
2024-03-19 09:35:53 -07:00
Joseph Cruz
fda4dba237 build(examples): clean more output (#2420)
* chore(examples): update workspace members

* build(examples): clean e2e crates

* build(examples): clean pkg directories

* chore: remove simulated change comment

* chore: add simulated change

* chore: remove simulated change
2024-03-18 11:58:37 -04:00
Roland Fredenhagen
4e578e335b chore: update attribute-derive (#2438) 2024-03-18 11:39:34 -04:00
Joseph Cruz
97fd8ff6c4 fix(ci): leptos examples fail with bindgen schema error (#2428) 2024-03-13 22:33:54 -04:00
battmdpkq
4faf3fa894 chore: fix types in some comments (#2413)
Signed-off-by: battmdpkq <cmaker@163.com>
2024-03-09 07:38:25 -05:00
Greg Johnston
480d741749 chore: update to gloo-net 0.5 (closes #2411) (#2416) 2024-03-08 15:22:12 -05:00
Álvaro Mondéjar
7928f61401 chore: add lint to disallow prints to stdout (#2404) 2024-03-08 13:18:37 -05:00
Giovanni
2b4f5e0f58 docs: runtime error if setting the same event listener 2x rather than silent failure (#2383)
Delegated event listeners do not support adding more than one event listener of the same type. This can cause confusion if two listeners are added, as one is silently dropped.
2024-03-07 16:49:23 -05:00
Giovanni
943a992570 fix: re-throw errors in delegated event listeners (#2382) 2024-03-07 16:48:21 -05:00
ARSON
372a241d78 feat: allow #[prop(attrs)] on slots (#2396) 2024-03-04 17:34:21 -08:00
Chris Biscardi
c06f6bede2 fix: remove erroneous debug println!()s in islands (#2402) 2024-03-04 06:56:18 -05:00
benwis
3e93a686f4 Fix and release deps 2024-03-03 17:04:34 -08:00
benwis
34cdff4cb3 Update deps in one crate to 0.6.8 2024-03-03 17:02:50 -08:00
John Lewis
530087d77d Add MessagePack codec (#2371)
* feat: added messagepack codec

* fix: deserialize msgpack from bytes, not string
2024-03-03 13:54:23 -08:00
martin frances
4bb43f6207 examples/todomvc - Rename Todos::new() Todos::default(). (#2390) 2024-03-03 13:48:40 -08:00
benwis
9e2fb62857 0.6.8 2024-03-02 18:01:10 -08:00
Ben Wishovich
1da2fff706 Fix missed stuff (#2398) 2024-03-02 17:57:20 -08:00
Greg Johnston
9fd2987447 fix: correctly reset hydration status in islands mode Suspense (closes #2332) (#2393) 2024-03-02 11:57:35 -05:00
zroug
7996f835d0 fix: remove unnecessary trait bound PartialEq from create_owning_memo (#2394) 2024-03-02 07:27:22 -05:00
Greg Johnston
d72b12524e Merge pull request #2395 from leptos-rs/int-ax-doc 2024-03-01 20:08:18 -05:00
Greg Johnston
8e79c5be5c fix: ignore as with other doctests for now 2024-03-01 18:39:55 -05:00
Greg Johnston
de25658c36 Merge pull request #2392 from paul-hansen/fix-ci
fix(ci): "needless borrow" error and example never exiting
2024-03-01 18:37:48 -05:00
Paul Hansen
e2e35a9659 fix(ci) Wait a bit longer for server to start
It took longer than I thought in Github and barely worked, giving it a
bit more of a buffer.
2024-03-01 15:47:59 -06:00
Paul Hansen
bf1ba589c5 fix(ci): Another attempt to fix hanging example 2024-03-01 15:41:22 -06:00
Sam Judelson
f70ebc1289 docs: add note on how to get ResponseOptions (#2380) 2024-03-01 10:47:02 -05:00
Paul Hansen
3cab09e015 fix(ci): error_boundary example never exiting 2024-03-01 09:21:58 -06:00
Paul Hansen
b431315f7c fix(ci): "needless borrow" error 2024-03-01 09:21:58 -06:00
Baptiste
5b40881e77 fix: specify path to wasm_bindgen in island macro (#2387) 2024-03-01 10:15:19 -05:00
benwis
59d3cce3be 0.6.7 2024-02-29 13:38:09 -08:00
Paul Hansen
6a83161368 chore: add MSRV (#2360) 2024-02-28 07:19:09 -05:00
Marc-Stefan Cassola
4b00c16cb9 added hashes generated from cargo-leptos (#2373)
* added hashes generated from cargo-leptos

* Added config option to disable frontend file name hash
2024-02-27 16:28:27 -08:00
haslersn
6d6019b956 fix: do not strip query in redirect hook when using client-side navigation (#2376) 2024-02-27 09:06:48 -08:00
Sam Judelson
3540291065 docs: Resource::read() in doc examples with Resource::get() (#2372) 2024-02-26 21:37:29 -05:00
zoomiti
4809cf473e feat: provide leptos_router::Method via context (#1808) (#2315) 2024-02-26 21:25:53 -05:00
Tadas Dailyda
aa977001c1 feat: add support for trailing slashes (closes #2154) (#2217) 2024-02-26 20:56:44 -05:00
Greg Johnston
c16189f095 Merge pull request #2362 from leptos-rs/remove-deprecation
chore(ci): fix failing CI by removing deprecation note
2024-02-24 13:05:02 -05:00
Greg Johnston
d0a013c248 chore(ci): omit a few feature flag in CI 2024-02-24 11:55:36 -05:00
Greg Johnston
531ea74e33 chore: cargo fmt in leptos_macro 2024-02-24 07:12:46 -05:00
Greg Johnston
545e87e540 chore(ci): fix failing CI by removing deprecation note 2024-02-24 07:07:31 -05:00
Joseph Cruz
2ca30a0b2d ci(examples): build hackernews_js_fetch with deno (#2344)
* ci(examples): refactor process management

* ci(examples): build hackernews_js_fetch with deno

* ci(workflows): detect hackernews_js_fetch change

* chore(web-report): report deno usage

* chore(web-report): ignore gtk example

* ci(todo_app_sqlite): simulate change

* ci(workflows): install deno

* ci(todo_app_sqlite): remove simulated change
2024-02-23 13:40:44 -05:00
zoomiti
753bf1ed54 Fix Broken Doc links and Deprecate FromUtf8Error in oco.rs (#2318)
* fix: deprecate `FromUtf8Error` in `oco.rs`

* chore: fix broken doc links (#859)

* chore: fix broken doc link to server attribute macro

* cargo fmt
2024-02-21 19:24:40 -08:00
Sam Judelson
37c6387fea finish doc sentence (#2348) 2024-02-21 19:21:57 -08:00
Janu (Janeshwar) Cambrelen
0a73487152 feat(leptos-axum): propagate trace context to server functions (#2340) 2024-02-21 19:21:00 -08:00
Sam Judelson
747aba0d7f add comment specifying edgecase of server function prefixes (#2345) 2024-02-20 18:17:20 -08:00
Sam Judelson
04cf47d5da Update suspense_component.rs documentation to use .get() instead of .read() (#2346) 2024-02-20 18:16:03 -08:00
rjmac
47abe00993 fix: don't leak canceled timeouts (#2331)
Instead of using `Closure::once_into_js`, this uses `into_js_value`,
which uses weak references to clean up the closure when Javascript no
longer has need of it.

It would be nice to make this (and the similar interval function) drop
the callback promptly when cancelled, but I don't think that's
possible while keeping the handles Copy.

Fixes #2330

Co-authored-by: Robert Macomber <robertm@mox>
2024-02-19 21:17:26 -05:00
eliza
aa3700ffb9 feat: add impl_from argument to #[server] proc_macro (#2335)
* Add `impl_into` argument

* Add `impl_into` argument

* Revert unneeded changes

* Address review comments

Rename `impl_into` back to be `impl_from`
Rework docstring

* Fix typo in docstring
2024-02-19 21:16:46 -05:00
Aphek
0770b87cb7 feat: Add owning memos to allow memos that re-use the previous value (#2139) 2024-02-19 21:16:19 -05:00
benwis
330ebdb018 v0.6.6 2024-02-19 13:48:32 -08:00
benwis
c3179d88cf Moved leptos-spin-macro dep to released version 2024-02-19 12:54:43 -08:00
Sahaj
ffcf3c2952 example: fix href path in tailwind_csr example (#2328) 2024-02-17 13:10:07 -05:00
haslersn
001ca5148e fix: handle cross-origin redirects in server function redirect hook (#2329)
In client-side navigation we now handle redirects returned from
server functions by resolving the location against the current
origin as a base. The base is only relevant if the location
doesn't already include an origin. This fixes cross-origin
redirects.

Note: in order to handle redirects in the same way as the browser
would handle them, we need to use the server function's URL
(typically `<origin>/api/something`) as a base. I leave this as
a TODO for a future leptos version, because it probably
requires changing the signature of the `server_fn` redirect hook.

In order to not be affected by a future breaking change, users
should already start making sure that their redirect locations
either include an origin or at least start with a single slash
(e.g. `Location: /foo`).
2024-02-17 13:09:39 -05:00
Greg Johnston
1e000afa78 examples: fix CSS file name in tailwind_axum (#2324) 2024-02-17 12:56:03 -05:00
Greg Johnston
0f7b8841b2 chore(ci): reduce set of tested features to prevent running out of disk space in server_fn (#2320) 2024-02-16 20:26:26 -05:00
Greg Johnston
7dc0441f6c docs: log error on failing to convert form to ServerFn type, in addition to setting action value (#2319) 2024-02-16 17:11:14 -05:00
Joseph Cruz
0a321a1bd7 docs(examples): update docs (#2313)
* docs(examples): fix metadata typo

* docs(examples): update first step about using cargo make
2024-02-16 13:32:01 -05:00
Greg Johnston
88742952f0 fix: Transition in hydrate mode that isn't initially created (closes #2279) (#2314) 2024-02-16 08:16:09 -05:00
martin frances
8a4b972e0b chore: bump config to 0.14 (#2302) 2024-02-15 20:24:12 -05:00
zoomiti
95bd9cc544 feat: use CDN_PKG_PATH at build time to set alternate base URL for JS/WASM bundles (#2281) (#2283) 2024-02-15 20:21:47 -05:00
Marc-Stefan Cassola
23bc892a24 fix: #[server] macro error type detection (#2298)
In most cases when you return `Result<..., ServerFnError<E>>` this worked but when you tried
`Result<..., leptos::ServerFnError<E>>` then it didn't.
2024-02-15 20:20:41 -05:00
Esteban Borai
830fba794e docs: add missing provide_meta_context() in example (#2311)
Otherwise user gets:

```
use_head() is being called without a MetaContext being provided. We'll automatically create and provide one, but if this is being called in a child route it may cause bugs. To be safe, you should provide_meta_context() somewhere in the root of the app.
```
2024-02-15 20:19:07 -05:00
martin frances
98633c8700 chore(ci): update node version for GitHub Actions (#2303) 2024-02-15 20:17:12 -05:00
David Rebbe
b0f5c39711 example: replace yanked version of session_auth_axum crate (#2310) 2024-02-15 20:16:26 -05:00
Greg Johnston
b54aa7f3f5 Merge pull request #2294 from agilarity/add-cargo-make-leptos 2024-02-15 18:52:37 -05:00
Sam Judelson
e33ee7ec99 pub export server is either from leptos_macro or leptos_spin_macro depending on if spin feature is enabled. (#2280)
* leptos spin server macro

* leptos spin

* git chng

* based on the fermyon official git for when that works
2024-02-15 14:37:19 -08:00
Joseph Cruz
cd70b2f52b fix(ci): should exclude cargo-make 2024-02-11 20:40:20 -05:00
Joseph Cruz
c75842ed0c ci(hackernews_islands_axum): build with cargo leptos 2024-02-11 15:40:32 -05:00
Joseph Cruz
4ad228bf47 docs(test-report): add leptos ci warning 2024-02-11 15:40:32 -05:00
Joseph Cruz
bbe7115360 docs(test-report): mention options 2024-02-11 15:40:32 -05:00
Greg Johnston
0658a550b0 fix(examples): align crate name and output name (closes #2206) (#2291) 2024-02-10 15:47:25 -05:00
Joseph Cruz
4222c832b1 fix(ci): empty directory vector error (#2288)
* fix(ci): empty directory vector error

* chore(ci): simulate example change

* chore(ci): remove simulated example change
2024-02-10 10:02:21 -08:00
Greg Johnston
dfddbd6bf9 docs: give a warning when you try to .dispatch() an action immediately (closes #2225) (#2286) 2024-02-09 20:55:10 -05:00
Greg Johnston
8a77691cb5 Merge pull request #2285 from leptos-rs/fix-issues
Fix remaining CI issues
2024-02-09 19:29:01 -05:00
Greg Johnston
1dbe8b2d4b fix: correct feature name for server-fn-macro crate (broken in #2270) 2024-02-09 17:18:44 -05:00
Greg Johnston
fe64f0d332 examples: fix counter_isomorphic (broken in #2244) and fix additional warnings 2024-02-09 17:12:31 -05:00
Joseph Cruz
c00207aa46 fix(test-report) should show all cargo-make leptos configuration (#2282)
* refactor(test-report): extract script
* refactor(test-report): extract functions
* refactor(test-report): split option to tasks
* chore(test-report): highlight examples without tags
* fix(test-report): show all cargo-make leptos configuration
* docs(test-report): update keys
* chore(test-report): include all crates in report
2024-02-09 16:31:46 -05:00
Joseph Cruz
65b7603192 fix(ci): address clippy issue (#2278)
* fix(ci): address clippy issue
* fix(ci): add missing nightly specifications
* fix(ci):  set all nightly references
* chore(ci): do not lint example crates
2024-02-09 16:30:11 -05:00
haslersn
d4bdc36062 fix: add key/value pair from submit button when parsing form event (#2268) 2024-02-07 11:09:01 -05:00
Sam Judelson
1b55227d10 fix: remove unnecessary default features on axum in server_fns to support running Axum in a WASM environment (#2270) 2024-02-07 11:08:48 -05:00
Saikat Das
a903e19eb2 chore: fix typo (#2267) 2024-02-06 17:55:35 -05:00
blorbb
38bf73947f fix: make directive .into() calls consistent (#2249) 2024-02-05 08:52:12 -05:00
Greg Johnston
e4b89ba243 Merge pull request #2262 from leptos-rs/2261
fix: guarantee execution order of effects (closes #2261)
2024-02-05 08:51:23 -05:00
Greg Johnston
701e3077fb chore: cargo fmt 2024-02-05 06:38:02 -05:00
Greg Johnston
aec4d680aa fix: guarantee execution order of effects (closes #2261) 2024-02-05 06:35:57 -05:00
Steffen
06721c5fcd examples: fix typos in examples (#2260) 2024-02-05 05:20:53 -05:00
SleeplessOne1917
1ddb39e9bd docs: typo in actix integrations docs (#2258)
Co-authored-by: SleeplessOne1917 <insomnia-void@protonmail.com>
2024-02-04 20:57:51 -05:00
Chris
15d4ca0638 feat(axum): provide state to server fn context (#2257)
Note that this is a minimal implementation and will __not__ allow the
user to `expect_state` if they have external calls to rendering their
app (i.e. using `render_app_to_*` directly).
2024-02-04 19:26:21 -05:00
zoomiti
85c3755f6d fix: bug with percent decoding of url params (#2251) 2024-02-04 19:24:02 -05:00
Sam Judelson
66ea072bc0 docs: a note to HtmlElement<El> about Deref (#2218) 2024-02-04 15:34:39 -05:00
Joris Hartog
b0b3c21285 docs: fix broken link in leptos_router (#2256) 2024-02-04 15:29:34 -05:00
Greg Johnston
56088a9ead fix: error rather than panicking if unable to send response in Axum integration (#2241)
* fix: error rather than panicking if unable to send response in Axum integration
2024-02-03 19:18:41 -05:00
martin frances
69d25d9c63 examples/hackernews: Add a "Suspense" wrapper. (#2253)
This warning appears in the browser's console log.

```
hackernews.js:933 At src/routes/stories.rs:39:17, you are reading a resource in `hydrate` mode outside a <Suspense/> or <Transition/>. This can cause hydration mismatch errors and loses out on a significant performance optimization. To fix this issue, you can either:
1. Wrap the place where you read the resource in a <Suspense/> or <Transition/> component, or
2. Switch to using create_local_resource(), which will wait to load the resource until the app is hydrated on the client side. (This will have worse performance in most cases.)
```
2024-02-03 14:24:46 -08:00
martin frances
5029b8f315 Chore: Minor, ran ``cargo fmt`` (#2254) 2024-02-03 14:24:12 -08:00
martin frances
0cba7bc22b example/counter_isomorphic Removed console warning. (#2244)
This warning is seen in the browsers console window.

```
counter_isomorphic.js:1068 At src/counters.rs:138:17, you are reading a resource in `hydrate` mode outside a <Suspense/> or <Transition/>. This can cause hydration mismatch errors and loses out on a significant performance optimization. To fix this issue, you can either:
1. Wrap the place where you read the resource in a <Suspense/> or <Transition/> component, or
2. Switch to using create_local_resource(), which will wait to load the resource until the app is hydrated on the client side. (This will have worse performance in most cases.)
```

Two derived signals "value" and "error_msg" need to be wrapped in a <Suspense> block.

"value" falls back to just the initial text.
"error" uses the default fallback.
2024-02-01 16:50:15 -08:00
Michael Kadziela
fb97c50886 Update rkyv example button text to accurately reflect what it does (#2250) 2024-02-01 16:49:29 -08:00
Greg Johnston
f1bc734dcf 0.6.5 2024-01-31 19:40:41 -05:00
Greg Johnston
f71b4aae69 feat: easily create custom server fn clients (#2247) 2024-01-31 09:15:30 -05:00
Greg Johnston
a834c03974 fix: bug with Actix redirects (#2246) 2024-01-31 09:14:40 -05:00
Greg Johnston
595013579c 0.6.4 2024-01-30 09:17:52 -05:00
Greg Johnston
8b1bd1ae9e Merge pull request #2240 from leptos-rs/err-serialization
fix: serialization error during SSR on ServerFnError
2024-01-29 16:32:55 -05:00
Greg Johnston
6ef1531059 example: file upload with streaming progress bar (#2242) 2024-01-29 15:20:19 -05:00
Greg Johnston
9f1406250e chore: update deprecated .remove() method on IndexSet 2024-01-29 11:32:15 -05:00
Greg Johnston
1f6a892291 fix: serialization error during SSR on ServerFnError 2024-01-29 10:36:08 -05:00
Greg Johnston
0ff1e279a2 fix: correctly track source in create_local_resource (#2238) 2024-01-28 10:09:03 -08:00
Chris
c6096cc2a0 chore: define edtion = "2021" in rustfmt.toml (#2235) 2024-01-27 16:04:25 -08:00
304 changed files with 6317 additions and 4083 deletions

View File

@@ -29,4 +29,4 @@ jobs:
with:
directory: ${{ matrix.directory }}
cargo_make_task: "ci"
toolchain: nightly
toolchain: stable

View File

@@ -24,4 +24,4 @@ jobs:
with:
directory: ${{ matrix.directory }}
cargo_make_task: "ci"
toolchain: nightly
toolchain: stable

28
.github/workflows/ci-semver.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: CI semver
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
get-leptos-changed:
uses: ./.github/workflows/get-leptos-changed.yml
test:
needs: [get-leptos-changed]
if: needs.get-leptos-changed.outputs.leptos_changed == 'true'
name: Run semver check (nightly-2024-03-31)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Semver Checks
uses: obi1kenobi/cargo-semver-checks-action@v2
with:
rust-toolchain: nightly-2024-03-31

View File

@@ -1,26 +0,0 @@
name: CI Stable Examples
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
get-leptos-changed:
uses: ./.github/workflows/get-leptos-changed.yml
test:
name: CI
needs: [get-leptos-changed]
if: needs.get-leptos-changed.outputs.leptos_changed == 'true'
strategy:
matrix:
directory: [examples/counters_stable, examples/counter_without_macros]
uses: ./.github/workflows/run-cargo-make-task.yml
with:
directory: ${{ matrix.directory }}
cargo_make_task: "ci"
toolchain: stable

View File

@@ -40,4 +40,4 @@ jobs:
with:
directory: ${{ matrix.directory }}
cargo_make_task: "ci"
toolchain: nightly
toolchain: nightly-2024-03-31

View File

@@ -31,10 +31,9 @@ jobs:
dir_names: true
dir_names_max_depth: "2"
files: |
examples
!examples/cargo-make
!examples/gtk
!examples/hackernews_js_fetch
examples/**
!examples/cargo-make/**
!examples/gtk/**
!examples/Makefile.toml
!examples/*.md
json: true

View File

@@ -21,12 +21,12 @@ jobs:
- name: Get example files that changed
id: changed-files
uses: tj-actions/changed-files@v41
uses: tj-actions/changed-files@v43
with:
files: |
examples/**
!examples/cargo-make
!examples/gtk
!examples/cargo-make/**
!examples/gtk/**
!examples/Makefile.toml
!examples/*.md

View File

@@ -17,8 +17,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install JQ Tool
uses: mbround18/install-jq@v1
- name: Install jq
run: sudo apt-get install jq
- name: Set Matrix
id: set-matrix

View File

@@ -16,10 +16,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get source files that changed
id: changed-source
uses: tj-actions/changed-files@v41
uses: tj-actions/changed-files@v43
with:
files: |
integrations/**

View File

@@ -27,11 +27,9 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ inputs.toolchain }}
override: true
components: rustfmt
- name: Add wasm32-unknown-unknown
run: rustup target add wasm32-unknown-unknown
@@ -44,6 +42,18 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: Install binstall
uses: cargo-bins/cargo-binstall@main
- 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
with:
@@ -55,9 +65,9 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
@@ -69,7 +79,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
@@ -107,6 +117,11 @@ jobs:
fi
done
- name: Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
# Run Cargo Make Task
- name: ${{ inputs.cargo_make_task }}
run: |

View File

@@ -72,12 +72,19 @@ check-examples`.
## Before Submitting a PR
We have a fairly extensive CI setup that runs both lints (like `rustfmt` and `clippy`)
We have a fairly extensive CI setup that runs both lints (like `rustfmt` and `clippy`)
and tests on PRs. You can run most of these locally if you have `cargo-make` installed.
Note that some of the `rustfmt` settings used require usage of the nightly compiler.
Formatting the code using the stable toolchain may result in a wrong code format and
subsequently CI errors.
Run `cargo +nightly fmt` if you want to keep the stable toolchain active.
You may want to let your IDE automatically use the `+nightly` parameter when a
"format on save" action is used.
If you added an example, make sure to add it to the list in `examples/Makefile.toml`.
From the root directory of the repo, run
From the root directory of the repo, run
- `cargo +nightly fmt`
- `cargo +nightly make check`
- `cargo +nightly make test`

View File

@@ -25,22 +25,23 @@ members = [
exclude = ["benchmarks", "examples"]
[workspace.package]
version = "0.6.3"
version = "0.6.11"
rust-version = "1.75"
[workspace.dependencies]
leptos = { path = "./leptos", version = "0.6.3" }
leptos_dom = { path = "./leptos_dom", version = "0.6.3" }
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.6.3" }
leptos_macro = { path = "./leptos_macro", version = "0.6.3" }
leptos_reactive = { path = "./leptos_reactive", version = "0.6.3" }
leptos_server = { path = "./leptos_server", version = "0.6.3" }
server_fn = { path = "./server_fn", version = "0.6.3" }
server_fn_macro = { path = "./server_fn_macro", version = "0.6.3" }
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" }
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.6" }
leptos_config = { path = "./leptos_config", version = "0.6.3" }
leptos_router = { path = "./router", version = "0.6.3" }
leptos_meta = { path = "./meta", version = "0.6.3" }
leptos_integration_utils = { path = "./integrations/utils", version = "0.6.3" }
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" }
[profile.release]
codegen-units = 1

View File

@@ -150,7 +150,7 @@ There are several people in the community using Leptos right now for internal ap
### Can I use this for native GUI?
Sure! Obviously the `view` macro is for generating DOM nodes but you can use the reactive system to drive native any GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:
Sure! Obviously the `view` macro is for generating DOM nodes but you can use the reactive system to drive any native GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:
- Use signals, derived signals, and memos to create your reactive system
- Create GUI widgets
@@ -163,7 +163,7 @@ The new rendering approach being developed for 0.7 supports “universal renderi
### How is this different from Yew?
Yew is the most-used library for Rust web UI development, but there are several differences between Yew and Leptos, in philosophy, approach, and performance.
Yew is the most-used library for Rust web UI development, but there are several differences between Yew and Leptos, in philosophy, approach, and performance.
- **VDOM vs. fine-grained:** Yew is built on the virtual DOM (VDOM) model: state changes cause components to re-render, generating a new virtual DOM tree. Yew diffs this against the previous VDOM, and applies those patches to the actual DOM. Component functions rerun whenever state changes. Leptos takes an entirely different approach. Components run once, creating (and returning) actual DOM nodes and setting up a reactive system to update those DOM nodes.
- **Performance:** This has huge performance implications: Leptos is simply much faster at both creating and updating the UI than Yew is.
@@ -182,4 +182,4 @@ Sycamore and Leptos are both heavily influenced by SolidJS. At this point, Lepto
- **Templating DSLs:** Sycamore uses a custom templating language for its views, while Leptos uses a JSX-like template format.
- **`'static` signals:** One of Leptoss main innovations was the creation of `Copy + 'static` signals, which have excellent ergonomics. Sycamore is in the process of adopting the same pattern, but this is not yet released.
- **Perseus vs. server functions:** The Perseus metaframework provides an opinionated way to build Sycamore apps that include server functionality. Leptos instead provides primitives like server functions in the core of the framework.
- **Perseus vs. server functions:** The Perseus metaframework provides an opinionated way to build Sycamore apps that include server functionality. Leptos instead provides primitives like server functions in the core of the framework.

View File

@@ -2,6 +2,7 @@
name = "benchmarks"
version = "0.1.0"
edition = "2021"
rust-version.workspace = true
[dependencies]
l0410 = { package = "leptos", version = "0.4.10", features = [

View File

@@ -3,5 +3,5 @@ alias = "check-all"
[tasks.check-all]
command = "cargo"
args = ["+nightly", "check-all-features"]
args = ["check-all-features"]
install_crate = "cargo-all-features"

View File

@@ -8,4 +8,11 @@ args = ["fmt", "--", "--check", "--config-path", "${LEPTOS_PROJECT_DIRECTORY}"]
[tasks.clippy-each-feature]
dependencies = ["install-clippy"]
command = "cargo"
args = ["hack", "clippy", "--all", "--each-feature", "--no-dev-deps"]
args = [
"clippy",
"--all-features",
"--no-deps",
"--",
"-D",
"clippy::print_stdout",
]

View File

@@ -3,5 +3,5 @@ alias = "test-all"
[tasks.test-all]
command = "cargo"
args = ["+nightly", "test-all-features"]
args = ["test-all-features"]
install_crate = "cargo-all-features"

View File

@@ -5,34 +5,41 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CARGO_BUILD_TEST_FLAGS = ""
CARGO_MAKE_WORKSPACE_EMULATION = true
CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
"action-form-error-handling",
"animated_show",
"counter",
"counter_isomorphic",
"counters",
"counters_stable",
"counter_url_query",
"counter_without_macros",
"directives",
"error_boundary",
"errors_axum",
"fetch",
"hackernews",
"hackernews_axum",
"hackernews_islands_axum",
"hackernews_js_fetch",
"js-framework-benchmark",
"login_with_token_csr_only",
"parent_child",
"portal",
"router",
"server_fns_axum",
"session_auth_axum",
"slots",
"spread",
"sso_auth_axum",
"ssr_modes",
"ssr_modes_axum",
"suspense_tests",
"tailwind_actix",
"tailwind_csr",
"tailwind_axum",
"tailwind_csr",
"timer",
"todo_app_sqlite",
"todo_app_sqlite_axum",
"todo_app_sqlite_csr",
"todomvc",
]
@@ -51,103 +58,5 @@ echo "CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = $examples"
[tasks.test-report]
workspace = false
description = "report web testing technology used by examples - OPTION: [all]"
script = '''
set -emu
BOLD="\e[1m"
GREEN="\e[0;32m"
ITALIC="\e[3m"
YELLOW="\e[0;33m"
RESET="\e[0m"
echo
echo "${YELLOW}Web Test Technology${RESET}"
echo
makefile_paths=$(find . -name Makefile.toml -not -path '*/target/*' -not -path '*/node_modules/*' |
sed 's%./%%' |
sed 's%/Makefile.toml%%' |
grep -v Makefile.toml |
sort -u)
start_path=$(pwd)
for path in $makefile_paths; do
cd $path
crate_symbols=
pw_count=$(find . -name playwright.config.ts | wc -l)
while read -r line; do
case $line in
*"cucumber"*)
crate_symbols=$crate_symbols"C"
;;
*"fantoccini"*)
crate_symbols=$crate_symbols"D"
;;
esac
done <"./Cargo.toml"
while read -r line; do
case $line in
*"cargo-make/wasm-test.toml"*)
crate_symbols=$crate_symbols"W"
;;
*"cargo-make/playwright-test.toml"*)
crate_symbols=$crate_symbols"P"
crate_symbols=$crate_symbols"N"
;;
*"cargo-make/playwright-trunk-test.toml"*)
crate_symbols=$crate_symbols"P"
crate_symbols=$crate_symbols"T"
;;
*"cargo-make/trunk_server.toml"*)
crate_symbols=$crate_symbols"T"
;;
*"cargo-make/cargo-leptos-webdriver-test.toml"*)
crate_symbols=$crate_symbols"L"
;;
*"cargo-make/cargo-leptos-test.toml"*)
crate_symbols=$crate_symbols"L"
if [ $pw_count -gt 0 ]; then
crate_symbols=$crate_symbols"P"
fi
;;
esac
done <"./Makefile.toml"
# Sort list of tools
sorted_crate_symbols=$(echo ${crate_symbols} | grep -o . | sort | tr -d "\n")
formatted_crate_symbols="${BOLD}${YELLOW}${sorted_crate_symbols}${RESET}"
crate_line=$path
if [ ! -z ${1+x} ]; then
# Show all examples
if [ ! -z $crate_symbols ]; then
crate_line=$crate_line$formatted_crate_symbols
fi
echo $crate_line
elif [ ! -z $crate_symbols ]; then
# Filter out examples that do not run tests in `ci`
crate_line=$crate_line$formatted_crate_symbols
echo $crate_line
fi
cd ${start_path}
done
c="${BOLD}${YELLOW}C${RESET} = Cucumber"
d="${BOLD}${YELLOW}D${RESET} = WebDriver"
l="${BOLD}${YELLOW}L${RESET} = Cargo Leptos"
n="${BOLD}${YELLOW}N${RESET} = Node"
p="${BOLD}${YELLOW}P${RESET} = Playwright"
t="${BOLD}${YELLOW}T${RESET} = Trunk"
w="${BOLD}${YELLOW}W${RESET} = WASM"
echo
echo "${ITALIC}Keys:${RESET} $c, $d, $l, $n, $p, $t, $w"
echo
'''
description = "show the cargo-make configuration for web examples [web|all|help]"
script = { file = "./cargo-make/scripts/web-report.sh" }

View File

@@ -8,7 +8,7 @@ To the extent that new features have been released or breaking changes have been
## Getting Started
The simplest way to get started with any example is to use the “quick start” command found in the README for each example. Most of the examples use either [`trunk`](https://trunkrs.dev/) (a simple build system and dev server for client-side-rendered apps) or [`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) (a build system for server-rendered and client-hydrated apps).
The simplest way to get started with any example is to use the “quick start” command found in the README for each example. Most of the examples use either [`trunk`](https://trunkrs.dev/) (a simple build system and dev server for client-side-rendered apps) or [`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) (a build system for server-rendered and client-hydrated apps).
## Using Cargo Make
@@ -16,16 +16,18 @@ You can also run any of the examples using [`cargo-make`](https://github.com/sag
Follow these steps to get any example up and running.
1. `cd` to the example root directory
2. Run `cargo make ci` to setup and test the example
3. Run `cargo make start` to run the example
4. Open the client URL in the console output (<http://127.0.0.1:8080> or <http://127.0.0.1:3000> by default)
5. Run `cargo make stop` to end any processes started by `cargo make start`.
1. `cd` to the example you want to run
2. Make sure `cargo-make` is installed (for example by running `cargo install cargo-make`)
3. Make sure `rustup target add wasm32-unknown-unknown` was executed for the currently selected toolchain.
4. Run `cargo make ci` to setup and test the example
5. Run `cargo make start` to run the example
6. Open the client URL in the console output (<http://127.0.0.1:8080> or <http://127.0.0.1:3000> by default)
7. Run `cargo make stop` to end any processes started by `cargo make start`.
Here are a few additional notes:
- Extendable custom task files are located in the [cargo-make](./cargo-make/) directory
- Running a task will automatically install `cargo` dependencies
- Running a task will automatically install `cargo` dependencies
- Each `Makefile.toml` file must extend the [cargo-make/main.toml](./cargo-make/main.toml) file
- [cargo-make](./cargo-make/) files that end in `*-test.toml` configure web testing strategies
- Run `cargo make test-report` to learn which examples have web tests

View File

@@ -7,7 +7,7 @@ edition = "2021"
codegen-units = 1
lto = true
[dependencies]
[dependencies]
leptos = { path = "../../leptos", features = ["csr"] }
console_log = "1"
log = "0.4"

View File

@@ -15,13 +15,13 @@ clear = true
dependencies = ["check-debug", "check-release"]
[tasks.check-debug]
toolchain = "nightly"
toolchain = "stable"
command = "cargo"
args = ["check-all-features"]
install_crate = "cargo-all-features"
[tasks.check-release]
toolchain = "nightly"
toolchain = "stable"
command = "cargo"
args = ["check-all-features", "--release"]
install_crate = "cargo-all-features"

View File

@@ -4,11 +4,13 @@ dependencies = [
"clean-trunk",
"clean-node_modules",
"clean-playwright",
"clean-pkg",
]
[tasks.clean-cargo]
command = "rm"
args = ["-rf", "target"]
script = '''
find . -type d -name target | xargs rm -rf
'''
[tasks.clean-trunk]
script = '''
@@ -27,3 +29,8 @@ fi
script = '''
find . -name playwright-report -name playwright -name test-results | xargs rm -rf
'''
[tasks.clean-pkg]
script = '''
find . -type d -name pkg | xargs rm -rf
'''

View File

@@ -3,32 +3,36 @@
[tasks.stop-client]
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
script = '''
if [ ! -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
if pidof -q ${CLIENT_PROCESS_NAME}; then
echo " Stopping ${CLIENT_PROCESS_NAME}"
pkill -ef ${CLIENT_PROCESS_NAME}
else
echo " ${CLIENT_PROCESS_NAME} is already stopped"
fi
'''
[tasks.client-status]
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
script = '''
if [ -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
echo " ${CLIENT_PROCESS_NAME} is not running"
else
if pidof -q ${CLIENT_PROCESS_NAME}; then
echo " ${CLIENT_PROCESS_NAME} is up"
else
echo " ${CLIENT_PROCESS_NAME} is not running"
fi
'''
[tasks.maybe-start-client]
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
script = '''
if [ -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
if pidof -q ${CLIENT_PROCESS_NAME}; then
echo " ${CLIENT_PROCESS_NAME} is already started"
else
echo " Starting ${CLIENT_PROCESS_NAME}"
if [ -z ${SPAWN_CLIENT_PROCESS} ];then
if [ -n "${SPAWN_CLIENT_PROCESS}" ];then
echo "Spawning process..."
cargo make start-client ${@} &
else
cargo make start-client ${@}
fi
else
echo " ${CLIENT_PROCESS_NAME} is already started"
fi
'''

View File

@@ -1,11 +1,11 @@
[tasks.build]
toolchain = "nightly"
toolchain = "stable"
command = "cargo"
args = ["build-all-features"]
install_crate = "cargo-all-features"
[tasks.check]
toolchain = "nightly"
toolchain = "stable"
command = "cargo"
args = ["check-all-features"]
install_crate = "cargo-all-features"

View File

@@ -0,0 +1,24 @@
[tasks.build]
clear = true
command = "deno"
args = ["task", "build"]
[tasks.start-client]
command = "deno"
args = ["task", "start"]
[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"

View File

@@ -1,5 +1,5 @@
[tasks.pre-clippy]
env = { CARGO_MAKE_CLIPPY_ARGS = "--all-targets --all-features -- -D warnings" }
env = { CARGO_MAKE_CLIPPY_ARGS = "--no-deps --all-targets --all-features -- -D warnings" }
[tasks.check-style]
dependencies = ["check-format-flow", "clippy-flow"]

View File

@@ -6,9 +6,17 @@ extend = [
[tasks.integration-test]
description = "Run integration test with automated start and stop of processes"
env = { SPAWN_CLIENT_PROCESS = "1" }
dependencies = ["start", "wait-one", "test-playwright", "stop"]
run_task = { name = ["start", "wait-test-stop"], parallel = true }
[tasks.wait-one]
[tasks.wait-test-stop]
private = true
dependencies = ["wait-server", "test-playwright", "stop"]
[tasks.wait-server]
script = '''
sleep 1
for run in {1..12}; do
echo "Waiting to ensure server is started..."
sleep 10
done
echo "Times up, running tests"
'''

View File

@@ -0,0 +1,176 @@
#!/bin/bash
set -emu
BOLD="\e[1m"
ITALIC="\e[3m"
YELLOW="\e[1;33m"
BLUE="\e[1;36m"
RESET="\e[0m"
function web { #task: only include examples with web cargo-make configuration
print_header
print_crate_tags "$@"
print_footer
}
function all { #task: includes all examples
print_header
print_crate_tags "all"
print_footer
}
function print_header {
echo -e "${YELLOW}Cargo Make Web Report${RESET}"
echo
echo -e "${ITALIC}Show how crates are configured to run and test web examples with cargo-make${RESET}"
echo
}
function print_crate_tags {
local makefile_paths
makefile_paths=$(find_makefile_lines)
local start_path
start_path=$(pwd)
for path in $makefile_paths; do
cd "$path"
local crate_tags=
# Add cargo tags
while read -r line; do
case $line in
*"cucumber"*)
crate_tags=$crate_tags"C"
;;
*"fantoccini"*)
crate_tags=$crate_tags"F"
;;
*"package.metadata.leptos"*)
crate_tags=$crate_tags"M"
;;
esac
done <"./Cargo.toml"
#Add makefile tags
local pw_count
pw_count=$(find . -name playwright.config.ts | wc -l)
while read -r line; do
case $line in
*"cargo-make/wasm-test.toml"*)
crate_tags=$crate_tags"W"
;;
*"cargo-make/playwright-test.toml"*)
crate_tags=$crate_tags"P"
crate_tags=$crate_tags"N"
;;
*"cargo-make/playwright-trunk-test.toml"*)
crate_tags=$crate_tags"P"
crate_tags=$crate_tags"T"
;;
*"cargo-make/trunk_server.toml"*)
crate_tags=$crate_tags"T"
;;
*"cargo-make/cargo-leptos-webdriver-test.toml"*)
crate_tags=$crate_tags"L"
;;
*"cargo-make/cargo-leptos-test.toml"*)
crate_tags=$crate_tags"L"
if [ "$pw_count" -gt 0 ]; then
crate_tags=$crate_tags"P"
fi
;;
*"cargo-make/cargo-leptos.toml"*)
crate_tags=$crate_tags"L"
;;
*"cargo-make/deno-build.toml"*)
crate_tags=$crate_tags"D"
;;
esac
done <"./Makefile.toml"
# Sort tags
local keys
keys=$(echo "$crate_tags" | grep -o . | sort | tr -d "\n")
# Find leptos projects that are not configured to build with cargo-leptos
keys=${keys//"LM"/"L"}
# Find leptos projects that are not configured to build with deno
keys=${keys//"DM"/"D"}
# Maybe print line
local crate_line=$path
if [ -n "$crate_tags" ]; then
local color=$YELLOW
case $keys in
*"M"*)
color=$BLUE
;;
esac
crate_line="$crate_line${color}$keys${RESET}"
echo -e "$crate_line"
elif [ "$#" -gt 0 ]; then
crate_line="${BOLD}$crate_line${RESET}"
echo -e "$crate_line"
fi
cd "$start_path"
done
}
function find_makefile_lines {
find . -name Makefile.toml -not -path '*/target/*' -not -path '*/node_modules/*' |
sed 's%./%%' |
sed 's%/Makefile.toml%%' |
grep -v Makefile.toml |
sort -u
}
function print_footer {
c="${BOLD}${YELLOW}C${RESET} = Cucumber Test Runner"
d="${BOLD}${YELLOW}D${RESET} = Deno"
f="${BOLD}${YELLOW}F${RESET} = Fantoccini WebDriver"
l="${BOLD}${YELLOW}L${RESET} = Cargo Leptos"
m="${BOLD}${BLUE}M${RESET} = Cargo Leptos Metadata Only (${ITALIC}ci is not configured to build with cargo-leptos or deno${RESET})"
n="${BOLD}${YELLOW}N${RESET} = Node"
p="${BOLD}${YELLOW}P${RESET} = Playwright Test"
t="${BOLD}${YELLOW}T${RESET} = Trunk"
w="${BOLD}${YELLOW}W${RESET} = WASM Test"
echo
echo -e "${ITALIC}Report Keys:${RESET}\n $c\n $d\n $f\n $l\n $m\n $n\n $p\n $t\n $w"
echo
}
###################
# HELP
###################
function list_help_for {
local task=$1
grep -E "^function.+ #$task" "$0" |
sed 's/function/ /' |
sed -e "s| { #$task: |~|g" |
column -s"~" -t |
sort
}
function help { #help: show task descriptions
echo -e "${BOLD}Usage:${RESET} ./$(basename "$0") <task> [options]"
echo
echo "Show the cargo-make configuration for web examples"
echo
echo -e "${BOLD}Tasks:${RESET}"
list_help_for task
echo
}
TIMEFORMAT="./web-report.sh completed in %3lR"
time "${@:-all}" # Show the report by default

View File

@@ -3,18 +3,21 @@
[tasks.stop-server]
condition = { env_set = ["SERVER_PROCESS_NAME"] }
script = '''
if [ ! -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
if pidof -q ${SERVER_PROCESS_NAME}; then
echo " Stopping ${SERVER_PROCESS_NAME}"
pkill -ef ${SERVER_PROCESS_NAME}
else
echo " ${SERVER_PROCESS_NAME} is already stopped"
fi
'''
[tasks.server-status]
condition = { env_set = ["SERVER_PROCESS_NAME"] }
script = '''
if [ -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
echo " ${SERVER_PROCESS_NAME} is not running"
else
if pidof -q ${SERVER_PROCESS_NAME}; then
echo " ${SERVER_PROCESS_NAME} is up"
else
echo " ${SERVER_PROCESS_NAME} is not running"
fi
'''
@@ -24,11 +27,11 @@ script = '''
YELLOW="\e[0;33m"
RESET="\e[0m"
if [ -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
if pidof -q ${SERVER_PROCESS_NAME}; then
echo " ${SERVER_PROCESS_NAME} is already started"
else
echo " Starting ${SERVER_PROCESS_NAME}"
echo " ${YELLOW}>> Run cargo make stop to end process${RESET}"
cargo make start-server ${@} &
else
echo " ${SERVER_PROCESS_NAME} is already started"
fi
'''

View File

@@ -6,25 +6,33 @@ script = '''
RESET="\e[0m"
if command -v chromedriver; then
if [ -z $(pidof chromedriver) ]; then
if pidof -q chromedriver; then
echo " chromedriver is already started"
else
echo "Starting chomedriver"
chromedriver --port=4444 &
fi
else
echo "${RED}${BOLD}ERROR${RESET} - chromedriver is required by this task"
echo "${RED}${BOLD}ERROR${RESET} - chromedriver not found"
exit 1
fi
'''
[tasks.stop-webdriver]
script = '''
pkill -f "chromedriver"
if pidof -q chromedriver; then
echo " Stopping chromedriver"
pkill -ef "chromedriver"
else
echo " chromedriver is already stopped"
fi
'''
[tasks.webdriver-status]
script = '''
if [ -z $(pidof chromedriver) ]; then
echo chromedriver is not running
else
if pidof -q chromedriver; then
echo chromedriver is up
else
echo chromedriver is not running
fi
'''

View File

@@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -14,7 +14,7 @@ pub fn SimpleCounter(
view! {
<div>
<button on:click=move |_| set_value(0)>"Clear"</button>
<button on:click=move |_| set_value.set(0)>"Clear"</button>
<button on:click=move |_| set_value.update(|value| *value -= step)>"-1"</button>
<span>"Value: " {value} "!"</span>
<button on:click=move |_| set_value.update(|value| *value += step)>"+1"</button>

View File

@@ -25,13 +25,12 @@ leptos_router = { path = "../../router" }
log = "0.4"
once_cell = "1.18"
gloo-net = { git = "https://github.com/rustwasm/gloo" }
wasm-bindgen = "0.2.87"
wasm-bindgen = "0.2"
serde = { version = "1", features = ["derive"] }
simple_logger = "4.3"
tracing = { version = "0.1", optional = true }
[features]
default = ["nightly"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:actix-files",
@@ -42,10 +41,9 @@ ssr = [
"leptos_meta/ssr",
"leptos_router/ssr",
]
nightly = ["leptos/nightly", "leptos_router/nightly"]
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix", "nightly"]
denylist = ["actix-files", "actix-web", "leptos_actix"]
skip_feature_sets = [["ssr", "hydrate"]]
[package.metadata.leptos]
@@ -69,7 +67,7 @@ reload-port = 3001
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View File

@@ -132,15 +132,6 @@ pub fn Counter() -> impl IntoView {
|_| get_server_count(),
);
let value =
move || counter.get().map(|count| count.unwrap_or(0)).unwrap_or(0);
let error_msg = move || {
counter.get().and_then(|res| match res {
Ok(_) => None,
Err(e) => Some(e),
})
};
view! {
<div>
<h2>"Simple Counter"</h2>
@@ -150,15 +141,24 @@ pub fn Counter() -> impl IntoView {
<div>
<button on:click=move |_| clear.dispatch(())>"Clear"</button>
<button on:click=move |_| dec.dispatch(())>"-1"</button>
<span>"Value: " {value} "!"</span>
<span>
"Value: "
<Suspense>
{move || counter.and_then(|count| *count)} "!"
</Suspense>
</span>
<button on:click=move |_| inc.dispatch(())>"+1"</button>
</div>
{move || {
error_msg()
.map(|msg| {
view! { <p>"Error: " {msg.to_string()}</p> }
})
}}
<Suspense>
{move || {
counter.get().and_then(|res| match res {
Ok(_) => None,
Err(e) => Some(e),
}).map(|msg| {
view! { <p>"Error: " {msg.to_string()}</p> }
})
}}
</Suspense>
</div>
}
}
@@ -204,7 +204,7 @@ pub fn FormCounter() -> impl IntoView {
<input type="hidden" name="msg" value="form value down"/>
<input type="submit" value="-1"/>
</ActionForm>
<span>"Value: " {move || value().to_string()} "!"</span>
<span>"Value: " <Suspense>{move || value().to_string()} "!"</Suspense></span>
<ActionForm action=adjust>
<input type="hidden" name="delta" value="1"/>
<input type="hidden" name="msg" value="form value up"/>

View File

@@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
leptos_router = { path = "../../router", features = ["csr"] }
console_log = "1"
log = "0.4"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -7,17 +7,17 @@ use leptos_router::*;
#[component]
pub fn SimpleQueryCounter() -> impl IntoView {
let (count, set_count) = create_query_signal::<i32>("count");
let clear = move |_| set_count(None);
let decrement = move |_| set_count(Some(count().unwrap_or(0) - 1));
let increment = move |_| set_count(Some(count().unwrap_or(0) + 1));
let clear = move |_| set_count.set(None);
let decrement = move |_| set_count.set(Some(count.get().unwrap_or(0) - 1));
let increment = move |_| set_count.set(Some(count.get().unwrap_or(0) + 1));
let (msg, set_msg) = create_query_signal::<String>("message");
let update_msg = move |ev| {
let new_msg = event_target_value(&ev);
if new_msg.is_empty() {
set_msg(None);
set_msg.set(None);
} else {
set_msg(Some(new_msg));
set_msg.set(Some(new_msg));
}
};
@@ -25,13 +25,13 @@ pub fn SimpleQueryCounter() -> impl IntoView {
<div>
<button on:click=clear>"Clear"</button>
<button on:click=decrement>"-1"</button>
<span>"Value: " {move || count().unwrap_or(0)} "!"</span>
<span>"Value: " {move || count.get().unwrap_or(0)} "!"</span>
<button on:click=increment>"+1"</button>
<br />
<input
prop:value=move || msg().unwrap_or_default()
prop:value=move || msg.get().unwrap_or_default()
on:input=update_msg
/>
</div>

View File

@@ -2,6 +2,7 @@
name = "counter_without_macros"
version = "0.1.0"
edition = "2021"
rust-version = "1.75"
[profile.release]
codegen-units = 1
@@ -14,7 +15,7 @@ log = "0.4"
console_error_panic_hook = "0.1.7"
[dev-dependencies]
wasm-bindgen = "0.2.84"
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.34"
pretty_assertions = "1.3.0"
rstest = "0.17.0"

View File

@@ -1,4 +1,4 @@
use leptos::{ev, html::*, *};
use leptos::{html::*, *};
/// A simple counter view.
// A component is really just a function call: it runs once to create the DOM and reactive system

View File

@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -1,4 +1,4 @@
use leptos::{For, *};
use leptos::*;
const MANY_COUNTERS: usize = 1000;
@@ -16,14 +16,14 @@ pub fn Counters() -> impl IntoView {
provide_context(CounterUpdater { set_counters });
let add_counter = move |_| {
let id = next_counter_id();
let id = next_counter_id.get();
let sig = create_signal(0);
set_counters.update(move |counters| counters.push((id, sig)));
set_next_counter_id.update(|id| *id += 1);
};
let add_many_counters = move |_| {
let next_id = next_counter_id();
let next_id = next_counter_id.get();
let new_counters = (next_id..next_id + MANY_COUNTERS).map(|id| {
let signal = create_signal(0);
(id, signal)
@@ -53,17 +53,17 @@ pub fn Counters() -> impl IntoView {
<span>{move ||
counters.get()
.iter()
.map(|(_, (count, _))| count())
.map(|(_, (count, _))| count.get())
.sum::<i32>()
.to_string()
}</span>
" from "
<span>{move || counters().len().to_string()}</span>
<span>{move || counters.get().len().to_string()}</span>
" counters."
</p>
<ul>
<For
each=counters
each=move || counters.get()
key=|counter| counter.0
children=move |(id, (value, set_value)): (usize, (ReadSignal<i32>, WriteSignal<i32>))| {
view! {
@@ -85,7 +85,8 @@ fn Counter(
let CounterUpdater { set_counters } = use_context().unwrap();
let input = move |ev| {
set_value(event_target_value(&ev).parse::<i32>().unwrap_or_default())
set_value
.set(event_target_value(&ev).parse::<i32>().unwrap_or_default())
};
// this will run when the scope is disposed, i.e., when this row is deleted

View File

@@ -1,20 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# Support playwright testing
node_modules/
test-results/
end2end/playwright-report/
playwright/.cache/
pnpm-lock.yaml
# Support trunk
dist

View File

@@ -1,27 +0,0 @@
[package]
name = "counters_stable"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["csr"] }
leptos_meta = { path = "../../meta", features = ["csr"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"
[dev-dependencies]
wasm-bindgen = "0.2.87"
wasm-bindgen-test = "0.3.37"
pretty_assertions = "1.4.0"
[dev-dependencies.web-sys]
features = [
"Event",
"EventInit",
"EventTarget",
"HtmlElement",
"HtmlInputElement",
"XPathResult",
]
version = "0.3.64"

View File

@@ -1,18 +0,0 @@
extend = [
{ path = "../cargo-make/main.toml" },
{ path = "../cargo-make/wasm-test.toml" },
{ path = "../cargo-make/trunk_server.toml" },
{ path = "../cargo-make/playwright-test.toml" },
]
[tasks.build]
toolchain = "stable"
command = "cargo"
args = ["build-all-features"]
install_crate = "cargo-all-features"
[tasks.check]
toolchain = "stable"
command = "cargo"
args = ["check-all-features"]
install_crate = "cargo-all-features"

View File

@@ -1,11 +0,0 @@
# Leptos Counters Example on Rust Stable
This example showcases a basic Leptos app with many counters. It is a good example of how to setup a basic reactive app with signals and effects, and how to interact with browser events. Unlike the other counters example, it will compile on Rust stable, because it has the `stable` feature enabled.
## Getting Started
See the [Examples README](../README.md) for setup and run instructions.
## Quick Start
Run `trunk serve --open` to run this example.

View File

@@ -1,4 +0,0 @@
node_modules/
/test-results/
/playwright-report/
/playwright/.cache/

View File

@@ -1,83 +0,0 @@
{
"name": "grip",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "grip",
"devDependencies": {
"@playwright/test": "^1.35.1"
}
},
"node_modules/.pnpm/@playwright+test@1.33.0": {
"extraneous": true
},
"node_modules/.pnpm/@types+node@20.2.1/node_modules/@types/node": {
"version": "20.2.1",
"extraneous": true,
"license": "MIT"
},
"node_modules/.pnpm/playwright-core@1.33.0/node_modules/playwright-core": {
"version": "1.33.0",
"extraneous": true,
"license": "Apache-2.0",
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@playwright/test": {
"version": "1.35.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz",
"integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==",
"dev": true,
"dependencies": {
"@types/node": "*",
"playwright-core": "1.35.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=16"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/@types/node": {
"version": "20.3.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz",
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/playwright-core": {
"version": "1.35.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=16"
}
}
}
}

View File

@@ -1,7 +0,0 @@
{
"private": "true",
"scripts": {},
"devDependencies": {
"@playwright/test": "^1.35.1"
}
}

View File

@@ -1,77 +0,0 @@
import { defineConfig, devices } from "@playwright/test";
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !process.env.DEV,
/* Retry on CI only */
retries: process.env.DEV ? 0 : 10,
/* Opt out of parallel tests on CI. */
workers: process.env.DEV ? 1 : 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [["html", { open: "never" }], ["list"]],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://127.0.0.1:8080",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
// {
// name: "firefox",
// use: { ...devices["Desktop Firefox"] },
// },
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: "cd ../ && trunk serve",
// url: "http://127.0.0.1:8080",
// reuseExistingServer: false, //!process.env.CI,
// },
});

View File

@@ -1,19 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Add 1000 Counters", () => {
test("should increase the number of counters", async ({ page }) => {
const ui = new CountersPage(page);
await Promise.all([
await ui.goto(),
await ui.addOneThousandCountersButton.waitFor(),
]);
await ui.addOneThousandCounters();
await ui.addOneThousandCounters();
await ui.addOneThousandCounters();
await expect(ui.counters).toHaveText("3000");
});
});

View File

@@ -1,15 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Add Counter", () => {
test("should increase the number of counters", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.addCounter();
await ui.addCounter();
await expect(ui.counters).toHaveText("3");
});
});

View File

@@ -1,18 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Clear Counters", () => {
test("should reset the counts", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.addCounter();
await ui.addCounter();
await ui.clearCounters();
await expect(ui.total).toHaveText("0");
await expect(ui.counters).toHaveText("0");
});
});

View File

@@ -1,16 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Decrement Count", () => {
test("should decrease the total count", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.decrementCount();
await ui.decrementCount();
await ui.decrementCount();
await expect(ui.total).toHaveText("-3");
});
});

View File

@@ -1,30 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Enter Count", () => {
test("should increase the total count", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.enterCount("5");
await expect(ui.total).toHaveText("5");
await expect(ui.counters).toHaveText("1");
});
test("should decrease the total count", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.addCounter();
await ui.addCounter();
await ui.enterCount("100");
await ui.enterCount("100", 1);
await ui.enterCount("100", 2);
await ui.enterCount("50", 1);
await expect(ui.total).toHaveText("250");
});
});

View File

@@ -1,98 +0,0 @@
import { expect, Locator, Page } from "@playwright/test";
export class CountersPage {
readonly page: Page;
readonly addCounterButton: Locator;
readonly addOneThousandCountersButton: Locator;
readonly clearCountersButton: Locator;
readonly incrementCountButton: Locator;
readonly counterInput: Locator;
readonly decrementCountButton: Locator;
readonly removeCountButton: Locator;
readonly total: Locator;
readonly counters: Locator;
constructor(page: Page) {
this.page = page;
this.addCounterButton = page.locator("button", { hasText: "Add Counter" });
this.addOneThousandCountersButton = page.locator("button", {
hasText: "Add 1000 Counters",
});
this.clearCountersButton = page.locator("button", {
hasText: "Clear Counters",
});
this.decrementCountButton = page.locator("button", {
hasText: "-1",
});
this.incrementCountButton = page.locator("button", {
hasText: "+1",
});
this.removeCountButton = page.locator("button", {
hasText: "x",
});
this.total = page.getByTestId("total");
this.counters = page.getByTestId("counters");
this.counterInput = page.getByRole("textbox");
}
async goto() {
await this.page.goto("/");
}
async addCounter() {
await Promise.all([
this.addCounterButton.waitFor(),
this.addCounterButton.click(),
]);
}
async addOneThousandCounters() {
this.addOneThousandCountersButton.click();
}
async decrementCount(index: number = 0) {
await Promise.all([
this.decrementCountButton.nth(index).waitFor(),
this.decrementCountButton.nth(index).click(),
]);
}
async incrementCount(index: number = 0) {
await Promise.all([
this.incrementCountButton.nth(index).waitFor(),
this.incrementCountButton.nth(index).click(),
]);
}
async clearCounters() {
await Promise.all([
this.clearCountersButton.waitFor(),
this.clearCountersButton.click(),
]);
}
async enterCount(count: string, index: number = 0) {
await Promise.all([
this.counterInput.nth(index).waitFor(),
this.counterInput.nth(index).fill(count),
]);
}
async removeCounter(index: number = 0) {
await Promise.all([
this.removeCountButton.nth(index).waitFor(),
this.removeCountButton.nth(index).click(),
]);
}
}

View File

@@ -1,16 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Increment Count", () => {
test("should increase the total count", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.incrementCount();
await ui.incrementCount();
await ui.incrementCount();
await expect(ui.total).toHaveText("3");
});
});

View File

@@ -1,17 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("Remove Counter", () => {
test("should decrement the number of counters", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await ui.addCounter();
await ui.addCounter();
await ui.addCounter();
await ui.removeCounter(1);
await expect(ui.counters).toHaveText("2");
});
});

View File

@@ -1,19 +0,0 @@
import { test, expect } from "@playwright/test";
import { CountersPage } from "./fixtures/counters_page";
test.describe("View Counters", () => {
test("should see the title", async ({ page }) => {
const ui = new CountersPage(page);
await ui.goto();
await expect(page).toHaveTitle("Counters (Stable)");
});
test("should see the initial counts", async ({ page }) => {
const counters = new CountersPage(page);
await counters.goto();
await expect(counters.total).toHaveText("0");
await expect(counters.counters).toHaveText("0");
});
});

View File

@@ -1,7 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="rust" data-wasm-opt="z" data-weak-refs />
</head>
<body></body>
</html>

View File

@@ -1,11 +0,0 @@
{
"private": "true",
"scripts": {
"start-server": "trunk serve",
"e2e": "cargo make test-playwright",
"e2e:auto-start": "start-server-and-test start-server http://127.0.0.1:8080 e2e"
},
"devDependencies": {
"start-server-and-test": "^1.15.4"
}
}

View File

@@ -1,118 +0,0 @@
use leptos::*;
use leptos_meta::*;
const MANY_COUNTERS: usize = 1000;
type CounterHolder = Vec<(usize, (ReadSignal<i32>, WriteSignal<i32>))>;
#[derive(Copy, Clone)]
struct CounterUpdater {
set_counters: WriteSignal<CounterHolder>,
}
#[component]
pub fn Counters() -> impl IntoView {
let (next_counter_id, set_next_counter_id) = create_signal(0);
let (counters, set_counters) = create_signal::<CounterHolder>(vec![]);
provide_context(CounterUpdater { set_counters });
let add_counter = move |_| {
let id = next_counter_id.get();
let sig = create_signal(0);
set_counters.update(move |counters| counters.push((id, sig)));
set_next_counter_id.update(|id| *id += 1);
};
let add_many_counters = move |_| {
let next_id = next_counter_id.get();
let new_counters = (next_id..next_id + MANY_COUNTERS).map(|id| {
let signal = create_signal(0);
(id, signal)
});
set_counters.update(move |counters| counters.extend(new_counters));
set_next_counter_id.update(|id| *id += MANY_COUNTERS);
};
let clear_counters = move |_| {
set_counters.update(|counters| counters.clear());
};
view! {
<Title text="Counters (Stable)" />
<div>
<button on:click=add_counter>
"Add Counter"
</button>
<button on:click=add_many_counters>
{format!("Add {MANY_COUNTERS} Counters")}
</button>
<button on:click=clear_counters>
"Clear Counters"
</button>
<p>
"Total: "
<span data-testid="total">{move ||
counters.get()
.iter()
.map(|(_, (count, _))| count.get())
.sum::<i32>()
.to_string()
}</span>
" from "
<span data-testid="counters">{move || counters.with(|counters| counters.len()).to_string()}</span>
" counters."
</p>
<ul>
<For
each={move || counters.get()}
key={|counter| counter.0}
children=move |(id, (value, set_value))| {
view! {
<Counter id value set_value/>
}
}
/>
</ul>
</div>
}
}
#[component]
fn Counter(
id: usize,
value: ReadSignal<i32>,
set_value: WriteSignal<i32>,
) -> impl IntoView {
let CounterUpdater { set_counters } = use_context().unwrap();
let input = move |ev| {
set_value
.set(event_target_value(&ev).parse::<i32>().unwrap_or_default())
};
// this will run when the scope is disposed, i.e., when this row is deleted
// because the signal was created in the parent scope, it won't be disposed
// of until the parent scope is. but we no longer need it, so we'll dispose of
// it when this row is deleted, instead. if we don't dispose of it here,
// this memory will "leak," i.e., the signal will continue to exist until the
// parent component is removed. in the case of this component, where it's the
// root, that's the lifetime of the program.
on_cleanup(move || {
log::debug!("deleted a row");
value.dispose();
});
view! {
<li>
<button data-testid="decrement_count" on:click=move |_| set_value.update(move |value| *value -= 1)>"-1"</button>
<input data-testid="counter_input" type="text"
prop:value={move || value.get().to_string()}
on:input=input
/>
<span>{value}</span>
<button data-testid="increment_count" on:click=move |_| set_value.update(move |value| *value += 1)>"+1"</button>
<button data-testid="remove_counter" on:click=move |_| set_counters.update(move |counters| counters.retain(|(counter_id, _)| counter_id != &id))>"x"</button>
</li>
}
}

View File

@@ -1,8 +0,0 @@
use counters_stable::Counters;
use leptos::*;
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(|| view! { <Counters/> })
}

View File

@@ -1,17 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_increase_the_number_of_counters() {
// Given
ui::view_counters();
// When
ui::add_1k_counters();
ui::add_1k_counters();
ui::add_1k_counters();
// Then
assert_eq!(ui::counters(), 3000);
}

View File

@@ -1,17 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_increase_the_number_of_counters() {
// Given
ui::view_counters();
// When
ui::add_counter();
ui::add_counter();
ui::add_counter();
// Then
assert_eq!(ui::counters(), 3);
}

View File

@@ -1,19 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_reset_the_counts() {
// Given
ui::view_counters();
ui::add_counter();
ui::add_counter();
ui::add_counter();
// When
ui::clear_counters();
// Then
assert_eq!(ui::total(), 0);
assert_eq!(ui::counters(), 0);
}

View File

@@ -1,18 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_decrease_the_total_count() {
// Given
ui::view_counters();
ui::add_counter();
// When
ui::decrement_counter(1);
ui::decrement_counter(1);
ui::decrement_counter(1);
// Then
assert_eq!(ui::total(), -3);
}

View File

@@ -1,34 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_increase_the_total_count() {
// Given
ui::view_counters();
ui::add_counter();
// When
ui::enter_count(1, 5);
// Then
assert_eq!(ui::total(), 5);
}
#[wasm_bindgen_test]
fn should_decrease_the_total_count() {
// Given
ui::view_counters();
ui::add_counter();
ui::add_counter();
ui::add_counter();
// When
ui::enter_count(1, 100);
ui::enter_count(2, 100);
ui::enter_count(3, 100);
ui::enter_count(1, 50);
// Then
assert_eq!(ui::total(), 250);
}

View File

@@ -1,112 +0,0 @@
use counters_stable::Counters;
use leptos::*;
use wasm_bindgen::JsCast;
use web_sys::{Element, Event, EventInit, HtmlElement, HtmlInputElement};
// Actions
pub fn add_1k_counters() {
find_by_text("Add 1000 Counters").click();
}
pub fn add_counter() {
find_by_text("Add Counter").click();
}
pub fn clear_counters() {
find_by_text("Clear Counters").click();
}
pub fn decrement_counter(index: u32) {
counter_html_element(index, "decrement_count").click();
}
pub fn enter_count(index: u32, count: i32) {
let input = counter_input_element(index, "counter_input");
input.set_value(count.to_string().as_str());
let mut event_init = EventInit::new();
event_init.bubbles(true);
let event = Event::new_with_event_init_dict("input", &event_init).unwrap();
input.dispatch_event(&event).unwrap();
}
pub fn increment_counter(index: u32) {
counter_html_element(index, "increment_count").click();
}
pub fn remove_counter(index: u32) {
counter_html_element(index, "remove_counter").click();
}
pub fn view_counters() {
remove_existing_counters();
mount_to_body(|| view! { <Counters/> });
}
// Results
pub fn counters() -> i32 {
data_test_id("counters").parse::<i32>().unwrap()
}
pub fn title() -> String {
leptos::document().title()
}
pub fn total() -> i32 {
data_test_id("total").parse::<i32>().unwrap()
}
// Internal
fn counter_element(index: u32, text: &str) -> Element {
let selector =
format!("li:nth-child({}) [data-testid=\"{}\"]", index, text);
leptos::document()
.query_selector(&selector)
.unwrap()
.unwrap()
}
fn counter_html_element(index: u32, text: &str) -> HtmlElement {
counter_element(index, text)
.dyn_into::<HtmlElement>()
.unwrap()
}
fn counter_input_element(index: u32, text: &str) -> HtmlInputElement {
counter_element(index, text)
.dyn_into::<HtmlInputElement>()
.unwrap()
}
fn data_test_id(id: &str) -> String {
let selector = format!("[data-testid=\"{}\"]", id);
leptos::document()
.query_selector(&selector)
.unwrap()
.expect("counters not found")
.text_content()
.unwrap()
}
fn find_by_text(text: &str) -> HtmlElement {
let xpath = format!("//*[text()='{}']", text);
let document = leptos::document();
document
.evaluate(&xpath, &document)
.unwrap()
.iterate_next()
.unwrap()
.unwrap()
.dyn_into::<HtmlElement>()
.unwrap()
}
fn remove_existing_counters() {
if let Some(counter) =
leptos::document().query_selector("body div").unwrap()
{
counter.remove();
}
}

View File

@@ -1 +0,0 @@
pub mod counters_page;

View File

@@ -1,18 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_increase_the_total_count() {
// Given
ui::view_counters();
ui::add_counter();
// When
ui::increment_counter(1);
ui::increment_counter(1);
ui::increment_counter(1);
// Then
assert_eq!(ui::total(), 3);
}

View File

@@ -1,16 +0,0 @@
use wasm_bindgen_test::*;
// Test Suites
pub mod add_1k_counters;
pub mod add_counter;
pub mod clear_counters;
pub mod decrement_counter;
pub mod enter_count;
pub mod increment_counter;
pub mod remove_counter;
pub mod view_counters;
pub mod fixtures;
pub use fixtures::*;
wasm_bindgen_test_configure!(run_in_browser);

View File

@@ -1,18 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_decrement_the_number_of_counters() {
// Given
ui::view_counters();
ui::add_counter();
ui::add_counter();
ui::add_counter();
// When
ui::remove_counter(2);
// Then
assert_eq!(ui::counters(), 2);
}

View File

@@ -1,22 +0,0 @@
use super::*;
use crate::counters_page as ui;
use pretty_assertions::assert_eq;
#[wasm_bindgen_test]
fn should_see_the_initial_counts() {
// When
ui::view_counters();
// Then
assert_eq!(ui::total(), 0);
assert_eq!(ui::counters(), 0);
}
#[wasm_bindgen_test]
fn should_see_the_title() {
// When
ui::view_counters();
// Then
assert_eq!(ui::title(), "Counters (Stable)");
}

View File

@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -1,5 +1,6 @@
use leptos::{ev::click, html::AnyElement, *};
// no extra parameter
pub fn highlight(el: HtmlElement<AnyElement>) {
let mut highlighted = false;
@@ -14,6 +15,7 @@ pub fn highlight(el: HtmlElement<AnyElement>) {
});
}
// one extra parameter
pub fn copy_to_clipboard(el: HtmlElement<AnyElement>, content: &str) {
let content = content.to_string();
@@ -31,6 +33,35 @@ pub fn copy_to_clipboard(el: HtmlElement<AnyElement>, content: &str) {
});
}
// custom parameter
#[derive(Clone)]
pub struct Amount(usize);
impl From<usize> for Amount {
fn from(value: usize) -> Self {
Self(value)
}
}
// a 'default' value if no value is passed in
impl From<()> for Amount {
fn from(_: ()) -> Self {
Self(1)
}
}
// .into() will automatically be called on the parameter
pub fn add_dot(el: HtmlElement<AnyElement>, amount: Amount) {
_ = el.clone().on(click, move |_| {
el.set_inner_text(&format!(
"{}{}",
el.inner_text(),
".".repeat(amount.0)
))
})
}
#[component]
pub fn SomeComponent() -> impl IntoView {
view! {
@@ -46,6 +77,11 @@ pub fn App() -> impl IntoView {
view! {
<a href="#" use:copy_to_clipboard=data>"Copy \"" {data} "\" to clipboard"</a>
// automatically applies the directive to every root element in `SomeComponent`
<SomeComponent use:highlight />
// no value will default to `().into()`
<button use:add_dot>"Add a dot"</button>
// `5.into()` automatically called
<button use:add_dot=5>"Add 5 dots"</button>
}
}

View File

@@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View File

@@ -8,7 +8,7 @@ See the [Examples README](../README.md) for setup and run instructions.
## Testing
This project is configured to run start and stop of processes for integration tests wihtout the use of Cargo Leptos or Node.
This project is configured to run start and stop of processes for integration tests without the use of Cargo Leptos or Node.
## Quick Start

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -5,7 +5,8 @@ pub fn App() -> impl IntoView {
let (value, set_value) = create_signal(Ok(0));
// when input changes, try to parse a number from the input
let on_input = move |ev| set_value(event_target_value(&ev).parse::<i32>());
let on_input =
move |ev| set_value.set(event_target_value(&ev).parse::<i32>());
view! {
<h1>"Error Handling"</h1>

View File

@@ -9,7 +9,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
console_log = "1.0"
console_error_panic_hook = "0.1"
leptos = { path = "../../leptos", features = ["nightly"] }
leptos = { path = "../../leptos" }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta" }
leptos_router = { path = "../../router" }
@@ -61,7 +61,7 @@ reload-port = 3001
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -1,5 +1,5 @@
use crate::errors::AppError;
use leptos::{logging::log, Errors, *};
use leptos::{logging::log, *};
#[cfg(feature = "ssr")]
use leptos_axum::ResponseOptions;

View File

@@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
reqwasm = "0.5"
serde = { version = "1", features = ["derive"] }
log = "0.4"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -44,7 +44,7 @@ pub fn fetch_example() -> impl IntoView {
// 1) our error type isn't serializable/deserializable
// 2) we're not doing server-side rendering in this example anyway
// (during SSR, create_resource will begin loading on the server and resolve on the client)
let cats = create_local_resource(cat_count, fetch_cats);
let cats = create_local_resource(move || cat_count.get(), fetch_cats);
let fallback = move |errors: RwSignal<Errors>| {
let error_list = move || {
@@ -85,7 +85,7 @@ pub fn fetch_example() -> impl IntoView {
prop:value=move || cat_count.get().to_string()
on:input=move |ev| {
let val = event_target_value(&ev).parse::<CatCount>().unwrap_or(0);
set_cat_count(val);
set_cat_count.set(val);
}
/>
</label>

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos = { path = "../../leptos", features = ["csr"] }
gtk = { version = "0.5.0", package = "gtk4" }

View File

@@ -1,8 +0,0 @@
[env]
VERIFY_GTK = false
[tasks.verify-flow]
condition = { env_set = ["VERIFY_GTK"] }
[tasks.verify]
condition = { env_set = ["VERIFY_GTK"] }

View File

@@ -51,7 +51,7 @@ fn counter_button() -> Button {
create_effect({
let button = button.clone();
move |_| {
button.set_label(&format!("Count: {}", value()));
button.set_label(&format!("Count: {}", value.get()));
}
});

View File

@@ -15,10 +15,10 @@ actix-files = { version = "0.6", optional = true }
actix-web = { version = "4", optional = true, features = ["macros"] }
console_log = "1"
console_error_panic_hook = "0.1"
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos = { path = "../../leptos" }
leptos_meta = { path = "../../meta" }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_router = { path = "../../router", features = ["nightly"] }
leptos_router = { path = "../../router" }
log = "0.4"
serde = { version = "1", features = ["derive"] }
gloo-net = { version = "0.2", features = ["http"] }
@@ -70,7 +70,7 @@ reload-port = 3001
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -52,5 +52,5 @@ fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(App)
leptos::mount_to_body(App)
}

View File

@@ -37,7 +37,7 @@ pub fn Stories() -> impl IntoView {
let hide_more_link = move || {
stories.get().unwrap_or(None).unwrap_or_default().len() < 28
|| pending()
|| pending.get()
};
view! {
@@ -62,16 +62,18 @@ pub fn Stories() -> impl IntoView {
}}
</span>
<span>"page " {page}</span>
<span class="page-link"
class:disabled=hide_more_link
aria-hidden=hide_more_link
>
<a href=move || format!("/{}?page={}", story_type(), page() + 1)
aria-label="Next Page"
<Suspense>
<span class="page-link"
class:disabled=hide_more_link
aria-hidden=hide_more_link
>
"more >"
</a>
</span>
<a href=move || format!("/{}?page={}", story_type(), page() + 1)
aria-label="Next Page"
>
"more >"
</a>
</span>
</Suspense>
</div>
<main class="news-list">
<div>

View File

@@ -7,7 +7,7 @@ use leptos_router::*;
pub fn Story() -> impl IntoView {
let params = use_params_map();
let story = create_resource(
move || params().get("id").cloned().unwrap_or_default(),
move || params.get().get("id").cloned().unwrap_or_default(),
move |id| async move {
if id.is_empty() {
None
@@ -87,7 +87,7 @@ pub fn Comment(comment: api::Comment) -> impl IntoView {
<a on:click=move |_| set_open.update(|n| *n = !*n)>
{
let comments_len = comment.comments.len();
move || if open() {
move || if open.get() {
"[-]".into()
} else {
format!("[+] {}{} collapsed", comments_len, pluralize(comments_len))
@@ -95,7 +95,7 @@ pub fn Comment(comment: api::Comment) -> impl IntoView {
}
</a>
</div>
{move || open().then({
{move || open.get().then({
let comments = comment.comments.clone();
move || view! {
<ul class="comment-children">

View File

@@ -6,7 +6,7 @@ use leptos_router::*;
pub fn User() -> impl IntoView {
let params = use_params_map();
let user = create_resource(
move || params().get("id").cloned().unwrap_or_default(),
move || params.get().get("id").cloned().unwrap_or_default(),
move |id| async move {
if id.is_empty() {
None

View File

@@ -13,10 +13,10 @@ lto = true
[dependencies]
console_log = "1.0"
console_error_panic_hook = "0.1"
leptos = { path = "../../leptos", features = ["nightly"] }
leptos = { path = "../../leptos" }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
leptos_meta = { path = "../../meta" }
leptos_router = { path = "../../router" }
log = "0.4"
simple_logger = "4.0"
serde = { version = "1.0", features = ["derive"] }
@@ -71,7 +71,7 @@ reload-port = 3001
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha tool. Controls whether autoreload JS will be included in the head
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
watch = false
# The environment Leptos will run in, usually either "DEV" or "PROD"
env = "DEV"

View File

@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly"
channel = "stable" # test change

View File

@@ -1,4 +1,4 @@
use leptos::{view, Errors, For, IntoView, RwSignal, View};
use leptos::{view, Errors, For, IntoView, RwSignal, SignalGet, View};
// A basic function to display errors served by the error boundaries. Feel free to do more complicated things
// here than just displaying them
@@ -11,7 +11,7 @@ pub fn error_template(errors: Option<RwSignal<Errors>>) -> View {
<h1>"Errors"</h1>
<For
// a function that returns the items we're iterating over; a signal is fine
each=errors
each=move || errors.get()
// a unique key for each item as a reference
key=|(key, _)| key.clone()
// renders each item to a view

Some files were not shown because too many files have changed in this diff Show More