Ctrl K
ComunidadGuías…

crates/memospot-build-internals/src/memospot.rs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
//! 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")
        );
    }
}