clean_html() triggers expensive ammonia sanitization with aho_corasick.
Previously called twice for the same text (aria-label + display text).
Now calls once and reuses the result.
New admin-only server function that re-renders content_html and
toc_html for posts from their content_md:
- rebuild_all=false: only processes posts where content_html IS NULL
- rebuild_all=true: processes all non-deleted posts
- Processes rows one at a time to avoid table locks
- Invalidates post list and stats caches after rebuild
- create_post: include toc_html in INSERT alongside content_html
- update_post: include toc_html in UPDATE alongside content_html
- Both write toc_html as NULL when empty, Some(..) otherwise
Previously row_to_post_full() ignored the stored content_html and
re-rendered markdown with render_markdown_enhanced() on every read,
triggering expensive ammonia sanitization (aho_corasick accounted for
87% CPU in flame graph).
Now reads content_html and toc_html directly from the database row.
Falls back to render_markdown_enhanced() only for legacy posts where
content_html is NULL.
- Cache ammonia::Builder with LazyLock (was rebuilt per request)
- Enable tracing release_max_level_info to strip tracing overhead at compile time
- Remove TraceLayer and tower-http trace feature from production
- Increase DB pool size 10→20 (configurable via DB_POOL_SIZE)
- Increase SSR cache TTL 300s→3600s (configurable via SSR_CACHE_SECS)
Benchmark: 7,444 → 9,840 req/s, P99 latency 27.6ms → 11.1ms
- Remove tracing::warn! (tracing not available in WASM builds)
- Fix parameter names in comment_storage: _key → key, _value → value
- Add #[allow(unused_variables)] for non-WASM builds where params are unused
- Add mount guard (loaded signal) to use_effect to prevent re-firing
- Add in-flight guard at top of onclick handler to prevent double submits
- Prevent overwriting user input when clearing form fields
- Fix rsx! macro syntax: can't use let inside for loop
- Revert post_id parameter name and use #[allow(unused_variables)] instead
- All components now compile successfully
- Add key prop to CommentList for loop for Dioxus list diffing
- Rename post_id to _post_id in PendingCommentItem signature
- Remove unnecessary let _ = post_id suppression
- Extend CommentContext with pending_comments Signal
- Load pending comments from localStorage on provider init
- Run check_pending_status on mount to prune non-pending entries
- Pass both approved and pending comments to CommentList
- Include pending count in section heading
- Fix is_expired: use js_sys::Date::now() on WASM, avoid format-parse roundtrip
- Make error fallback safe (expire on error)
- Restrict escape_html visibility to pub(crate)
- Only write storage in load_pending_comments when pruning actually occurs
Provides save/load for author info (yggdrasil-comment-author) and
pending comments (yggdrasil-pending-comments) in localStorage.
- 7-day TTL with auto-pruning
- Per-post-id storage keyed by post_id string
- HTML escaping for pending content_md rendering
- All web_sys calls behind #[cfg(target_arch = "wasm32")]