You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Several server-side Rust files embed large JS/CSS/HTML payloads as raw-string consts (r#"..."# / r##"..."##). PR #4016 ("fix: allow http: URLs in shell open_url handler") surfaced the cost: the two functional code changes (one-line scheme allowlist + IPv6 loopback fix) were buried inside a 692-line JS string literal in crates/core/src/server/path_handlers.rs. gh pr view and reviewers see "+150 lines, mostly tests" and miss the actual semantic delta. See #4016 (comment) for the dig-out comment.
Concrete pain points:
No syntax highlighting, no JS LSP, no ESLint, no prettier — every JS edit is blind.
Diffs are unreadable. A scheme-check change looks identical in git diff to a comment tweak.
Shell HTML scaffold (lines 464–482, has format! placeholders {favicon}, {iframe_src}, {auth_token}, {SHELL_BRIDGE_JS}) → path_handlers/assets/shell.html. Use format!(include_str!("assets/shell.html"), ...) — include_str! expands to a string literal, accepted as format!'s first arg.
Two <!DOCTYPE html> page scaffolds (lines 1308 and 1633, with {CSS}{PEER_CSS}{JS} interpolation) → home_page/assets/{home,peer}.html via format!(include_str!(...)).
Permission-prompt HTML template (lines 315–~395, includes embedded <style> and <script>) → split into permission_prompts/assets/prompt.html, prompt.css, prompt.js.
Permission-result HTML template (lines 524–~600) → permission_prompts/assets/result.html (+ extracted css/js if non-trivial).
crates/core/src/server/errors.rs
connecting_page() HTML (lines 102–129) → errors/assets/connecting.html returned via include_str!(...).to_string().
Out of scope (intentional)
home_page.rs per-row/per-card format!(r#"<div...">"#) snippets — runtime templating with row-level interpolation, not static blobs. Templating-engine adoption is a separate question.
service.rs plist/systemd/launchd templates — platform-specific config, not web assets.
RABBIT_SVG_PATH — single path string, not worth a file.
path_handlers.rs test-fixture r#"<!DOCTYPE..."# literals (lines 1782, 1829, 1854, 1877, 2178, 3116, 3150) — test inputs, kept inline for locality.
Approach
Mechanism:include_str! only. No build script, no asset bundling, no runtime I/O, no new dependency. Compiler tracks the included file and rebuilds on change.
include_str! resolves paths relative to the calling source file and does NOT require the directory to be a module — path_handlers/ and home_page/ are asset-only directories, no mod.rs needed.
Format-string scaffolds:format!(include_str!("assets/foo.html"), name = value, ...) works because include_str! expands to a & 'static str literal at compile time, satisfying format!'s "first arg must be a string literal" requirement. Verify with a small spike before the first PR commits.
Constraints / things that must NOT regress
All existing SHELL_BRIDGE_JS.contains("...") test assertions in path_handlers.rs (~40 sites at lines 2343–2557) keep working unchanged — include_str! produces the same & 'static str value.
Wire/protocol-relevant strings (u.protocol !== 'https:', u.protocol !== 'http:', '::1', MAX_CONNECTIONS, CONTRACT_PREFIX_RE, etc.) must be byte-identical post-extraction. The extraction PR is a pure move; no behavioral changes.
No new runtime cost: include_str! is compile-time inlining.
CI lint (part of this issue)
After extraction, add CI step running prettier (or deno fmt) and ESLint over crates/core/src/**/assets/*.{js,css,html}. Raises the floor on future JS edits — basic syntax, unused vars, implicit globals.
Minimum CI bar:
prettier --check on **/assets/*.{js,css,html}
eslint with a minimal config (recommended ruleset) on **/assets/*.js
PR 3: Extract permission_prompts.rs and errors.rs.
PR 4: Add prettier + eslint CI step over extracted assets.
Each PR is a refactor: and must be byte-for-byte behavior-preserving (verifiable by running existing test suite, including the regression test added in #4016).
Acceptance criteria
All blobs in inventory live in *.{js,css,html} files next to consumer .rs.
No raw-string r#"..."# block longer than ~30 lines remains in the four target files (ad-hoc small snippets in format! row templates excepted).
cargo test -p freenet --lib server:: passes including all *.contains(...) assertions.
Problem
Several server-side Rust files embed large JS/CSS/HTML payloads as raw-string consts (
r#"..."#/r##"..."##). PR #4016 ("fix: allow http: URLs in shell open_url handler") surfaced the cost: the two functional code changes (one-line scheme allowlist + IPv6 loopback fix) were buried inside a 692-line JS string literal incrates/core/src/server/path_handlers.rs.gh pr viewand reviewers see "+150 lines, mostly tests" and miss the actual semantic delta. See #4016 (comment) for the dig-out comment.Concrete pain points:
git diffto a comment tweak..jsfiles.path_handlers.rsare payload, not Rust.Precedent:
crates/core/src/bin/commands/setup_wizard/ui.rs:17already does the right thing —const SETUP_HTML: &str = include_str!("setup.html");.Scope (inventory)
Static blobs to extract via
include_str!. Asset files placed next to the consuming.rsfile (matchessetup_wizard/precedent).crates/core/src/server/path_handlers.rsSHELL_BRIDGE_JS(lines 612–1304, ~692 lines) →path_handlers/assets/shell_bridge.jsWEBSOCKET_SHIM_JS(lines 1312–1402, ~90 lines) →path_handlers/assets/websocket_shim.jsNAVIGATION_INTERCEPTOR_JS(lines 1424–1489, ~65 lines) →path_handlers/assets/navigation_interceptor.jsformat!placeholders{favicon},{iframe_src},{auth_token},{SHELL_BRIDGE_JS}) →path_handlers/assets/shell.html. Useformat!(include_str!("assets/shell.html"), ...)—include_str!expands to a string literal, accepted asformat!'s first arg.crates/core/src/server/home_page.rsCSS(lines 732–1200, ~468 lines) →home_page/assets/style.cssJS(lines 1208–1293, ~85 lines) →home_page/assets/dashboard.jsPEER_CSS(lines 2289–2435, ~146 lines) →home_page/assets/peer.css<!DOCTYPE html>page scaffolds (lines 1308 and 1633, with{CSS}{PEER_CSS}{JS}interpolation) →home_page/assets/{home,peer}.htmlviaformat!(include_str!(...)).crates/core/src/server/client_api/permission_prompts.rs<style>and<script>) → split intopermission_prompts/assets/prompt.html,prompt.css,prompt.js.permission_prompts/assets/result.html(+ extracted css/js if non-trivial).crates/core/src/server/errors.rsconnecting_page()HTML (lines 102–129) →errors/assets/connecting.htmlreturned viainclude_str!(...).to_string().Out of scope (intentional)
home_page.rsper-row/per-cardformat!(r#"<div...">"#)snippets — runtime templating with row-level interpolation, not static blobs. Templating-engine adoption is a separate question.service.rsplist/systemd/launchd templates — platform-specific config, not web assets.RABBIT_SVG_PATH— single path string, not worth a file.path_handlers.rstest-fixturer#"<!DOCTYPE..."#literals (lines 1782, 1829, 1854, 1877, 2178, 3116, 3150) — test inputs, kept inline for locality.Approach
Mechanism:
include_str!only. No build script, no asset bundling, no runtime I/O, no new dependency. Compiler tracks the included file and rebuilds on change.Layout (assets next to consumer):
include_str!resolves paths relative to the calling source file and does NOT require the directory to be a module —path_handlers/andhome_page/are asset-only directories, nomod.rsneeded.Format-string scaffolds:
format!(include_str!("assets/foo.html"), name = value, ...)works becauseinclude_str!expands to a& 'static strliteral at compile time, satisfyingformat!'s "first arg must be a string literal" requirement. Verify with a small spike before the first PR commits.Constraints / things that must NOT regress
SHELL_BRIDGE_JS.contains("...")test assertions inpath_handlers.rs(~40 sites at lines 2343–2557) keep working unchanged —include_str!produces the same& 'static strvalue.u.protocol !== 'https:',u.protocol !== 'http:','::1',MAX_CONNECTIONS,CONTRACT_PREFIX_RE, etc.) must be byte-identical post-extraction. The extraction PR is a pure move; no behavioral changes.cargo fmt && cargo clippy -- -D warnings && cargo testclean.include_str!is compile-time inlining.CI lint (part of this issue)
After extraction, add CI step running prettier (or
deno fmt) and ESLint overcrates/core/src/**/assets/*.{js,css,html}. Raises the floor on future JS edits — basic syntax, unused vars, implicit globals.Minimum CI bar:
--checkon**/assets/*.{js,css,html}**/assets/*.jsSequencing (single issue, separate PRs)
path_handlers.rsblobs (biggest payoff, directly addresses fix(server): allow http: URLs in shell open_url handler #4016 pain). Pure code-move +include_str!.home_page.rsCSS/JS/HTML scaffolds.permission_prompts.rsanderrors.rs.Each PR is a
refactor:and must be byte-for-byte behavior-preserving (verifiable by running existing test suite, including the regression test added in #4016).Acceptance criteria
*.{js,css,html}files next to consumer.rs.r#"..."#block longer than ~30 lines remains in the four target files (ad-hoc small snippets informat!row templates excepted).cargo test -p freenet --lib server::passes including all*.contains(...)assertions.shell_open_url_handler_accepts_http_and_https_but_blocks_localhost) still passes.crates/core/src/**/assets/*and is green.gh pr view(manual verification on first follow-up PR).References
crates/core/src/bin/commands/setup_wizard/ui.rs:17