Dev loop: debug-only page scripts from disk + tab rebuild on change (waybetter-host devloop, page_script!), generic devmode watcher, waybetter dev, buildRuntime watch, template scripts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9d9f0ab10a
commit
e84470a95d
11 changed files with 377 additions and 26 deletions
|
|
@ -24,6 +24,8 @@
|
|||
//! shows, its page color and delivery script) over a site's built-in themes.
|
||||
//! - [`workspaces`]: saved tab/pane/deck layouts, bounded and well-formed (never evaluated).
|
||||
//! - [`devmode`]: developer mode's debounced watcher of plugins, custom CSS and a theme file.
|
||||
//! - `devloop` (debug builds with `app` only): page scripts read from disk and every tab rebuilt when
|
||||
//! one changes; an app names its files with [`page_script!`].
|
||||
//! - [`settings`]: the shell's settings (home page, where links open, session restore) and the page's
|
||||
//! feature flags, as validated data and the scripts that hand them to site tabs.
|
||||
//! - [`modes`]: the onboarding mode the owner started from (the presets are the app's feature table).
|
||||
|
|
@ -74,7 +76,55 @@ pub mod zoom;
|
|||
|
||||
#[cfg(feature = "app")]
|
||||
pub mod app;
|
||||
#[cfg(all(feature = "app", debug_assertions))]
|
||||
pub mod devloop;
|
||||
#[cfg(feature = "tauri")]
|
||||
pub mod host;
|
||||
#[cfg(all(feature = "tauri", feature = "net"))]
|
||||
pub mod updater;
|
||||
|
||||
/// An app's page script for `SiteHooks::init_scripts`: `$embedded` (an `include_str!`) in every
|
||||
/// build, except that a debug build reads `$file` (relative to the app crate's manifest directory)
|
||||
/// from disk each time and falls back to the embedded copy when it is missing. The files named
|
||||
/// this way are watched: a change rebuilds every tab (`devloop`). In a release build the disk arm
|
||||
/// is not compiled at all: the expansion is `$embedded.to_owned()`, `$file` appears nowhere.
|
||||
#[macro_export]
|
||||
macro_rules! page_script {
|
||||
($embedded:expr, $file:literal) => {{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
$crate::devloop::from_disk(concat!(env!("CARGO_MANIFEST_DIR"), "/", $file), $embedded)
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
($embedded).to_owned()
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod release_guard {
|
||||
/// Release builds must not contain the dev loop: every mention of it in this crate is behind
|
||||
/// `cfg(debug_assertions)` (checked on the source, so it also holds when only debug is built).
|
||||
#[test]
|
||||
fn every_devloop_mention_is_debug_only() {
|
||||
for (file, source) in [("lib.rs", include_str!("lib.rs")), ("app.rs", include_str!("app.rs"))] {
|
||||
let lines: Vec<&str> = source.lines().collect();
|
||||
for (index, line) in lines.iter().enumerate() {
|
||||
let code = line.trim_start();
|
||||
if code.starts_with("//") || !(code.contains("devloop::") || code.starts_with("pub mod devloop")) || code.contains("$crate::devloop") {
|
||||
continue;
|
||||
}
|
||||
let gated = (index.saturating_sub(2)..index).any(|before| lines[before].contains("debug_assertions"));
|
||||
assert!(gated, "{file}:{}: devloop used outside cfg(debug_assertions)", index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `cargo test --release`: the macro is just the embedded text.
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[test]
|
||||
fn release_page_script_is_the_embedded_copy() {
|
||||
assert_eq!(crate::page_script!("embedded", "no/such/file.js"), "embedded");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue