crates/memospot-build-internals/src/memospot.rs
Rama main · réplica de lectura del repositorio original.
//! Build-time generation of Memospot-specific shortcut artifacts.
use std::{fs, path::Path};
/// Data describing one shortcut for the native menu and JavaScript polyfill.
pub struct ShortcutBinding {
name: &'static str,
command: &'static str,
accelerator: &'static str,
codes: &'static [&'static str],
}
impl ShortcutBinding {
/// Create a binding from its native menu and frontend shortcut metadata.
pub const fn new(
name: &'static str,
command: &'static str,
accelerator: &'static str,
codes: &'static [&'static str],
) -> Self {
Self {
name,
command,
accelerator,
codes,
}
}
}
/// Write the JavaScript shortcut polyfill and Rust accelerator constants to `out_dir`.
///
/// The caller supplies bindings expanded from
/// `crates/memospot/src/shortcut_bindings.in.rs`, which remains the source of truth.
pub fn generate_shortcut_artifacts(out_dir: &Path, bindings: &[ShortcutBinding]) {
let mut conditions = format!("{:>4}switch (e.code) {{\n", "");
for binding in bindings {
for code in binding.codes {
let cmd = binding.command;
conditions.push_str(&format!(
" case \"{code}\":\n cmd = \"{cmd}\";\n break;\n"
));
}
}
conditions.push_str(" default: break;\n }");
let debug = if cfg!(debug_assertions) {
"console.warn('Memospot shortcut polyfill loaded successfully.');"
} else {
""
};
let js = format!(
r#"
/*
* Shortcut polyfill.
*
* Auto-generated by build.rs from src/shortcut_bindings.in.rs.
*/
document.addEventListener("keydown", (e) => {{
if (!(e.ctrlKey || e.metaKey)) return;
let cmd = null;
{conditions}
if (!cmd) return;
e.preventDefault();
void window.__TAURI__.event.emit("memospot-shortcut", cmd).catch((error) => {{
console.error(`Memospot shortcut "${{cmd}}" failed:`, error);
}});
}});
{debug}
"#
);
let mut accel = String::new();
for binding in bindings {
accel.push_str(&format!(
"#[allow(dead_code)]\npub const {}: &str = \"{}\";\n",
binding.name, binding.accelerator
));
}
fs::write(out_dir.join("shortcut_polyfill.js"), js)
.expect("failed to write generated shortcut polyfill");
fs::write(out_dir.join("shortcut_accelerators.rs"), accel)
.expect("failed to write generated shortcut accelerators");
println!("cargo:rerun-if-changed=src/shortcut_bindings.in.rs");
}
#[cfg(test)]
mod tests {
use std::fs;
use super::*;
#[test]
fn generated_polyfill_handles_numpad_commands_without_unhandled_rejections() {
let out_dir = tempfile::tempdir().unwrap();
let bindings = [ShortcutBinding::new(
"ZOOM_OUT",
"zoom_out",
"CmdOrCtrl+-",
&["NumpadSubtract"],
)];
generate_shortcut_artifacts(out_dir.path(), &bindings);
let polyfill = fs::read_to_string(out_dir.path().join("shortcut_polyfill.js")).unwrap();
assert!(polyfill.contains("case \"NumpadSubtract\":"));
assert!(
polyfill.contains("window.__TAURI__.event.emit(\"memospot-shortcut\", cmd).catch")
);
}
}