Skip to main content

voice_typing_ext/
lib.rs

1//! Embeds voice-typing browser extensions and writes them to disk.
2//!
3//! `cargo build` with the `extensions` feature produces:
4//!   - `extensions/chrome/`   unpacked directory (load in chrome://extensions)
5//!   - `extensions/safari/`   unpacked directory (convert with xcrun)
6//!   - `extensions/voice-typing-chrome.zip`
7//!   - `extensions/voice-typing-safari.zip`
8
9use std::io;
10use std::path::Path;
11
12// ── Embedded zip archives (built by build.rs) ───────────────────────────
13
14pub const CHROME_ZIP: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/chrome.zip"));
15pub const SAFARI_ZIP: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/safari.zip"));
16
17// ── Embedded source files for unpacked loading ──────────────────────────
18
19pub mod chrome {
20    pub const MANIFEST: &str = include_str!("../chrome/manifest.json");
21    pub const BACKGROUND: &str = include_str!("../chrome/background.js");
22    pub const CONTENT_JS: &str = include_str!("../chrome/content.js");
23    pub const CONTENT_CSS: &str = include_str!("../chrome/content.css");
24    pub const ICON_16: &[u8] = include_bytes!("../chrome/icons/icon16.png");
25    pub const ICON_32: &[u8] = include_bytes!("../chrome/icons/icon32.png");
26    pub const ICON_48: &[u8] = include_bytes!("../chrome/icons/icon48.png");
27    pub const ICON_128: &[u8] = include_bytes!("../chrome/icons/icon128.png");
28}
29
30pub mod safari {
31    pub const MANIFEST: &str = include_str!("../safari/manifest.json");
32    pub const BACKGROUND: &str = include_str!("../safari/background.js");
33    pub const CONTENT_JS: &str = include_str!("../safari/content.js");
34    pub const CONTENT_CSS: &str = include_str!("../safari/content.css");
35    pub const INFO_PLIST: &str = include_str!("../safari/Info.plist");
36    pub const ICON_16: &[u8] = include_bytes!("../safari/icons/icon16.png");
37    pub const ICON_32: &[u8] = include_bytes!("../safari/icons/icon32.png");
38    pub const ICON_48: &[u8] = include_bytes!("../safari/icons/icon48.png");
39    pub const ICON_128: &[u8] = include_bytes!("../safari/icons/icon128.png");
40}
41
42/// Write all extension artifacts under `dir`.
43pub fn write(dir: &Path) -> io::Result<()> {
44    // ── Chrome unpacked ─────────────────────────────────────────────
45    let chrome_dir = dir.join("chrome");
46    let chrome_icons = chrome_dir.join("icons");
47    std::fs::create_dir_all(&chrome_icons)?;
48    std::fs::write(chrome_dir.join("manifest.json"), chrome::MANIFEST)?;
49    std::fs::write(chrome_dir.join("background.js"), chrome::BACKGROUND)?;
50    std::fs::write(chrome_dir.join("content.js"), chrome::CONTENT_JS)?;
51    std::fs::write(chrome_dir.join("content.css"), chrome::CONTENT_CSS)?;
52    std::fs::write(chrome_icons.join("icon16.png"), chrome::ICON_16)?;
53    std::fs::write(chrome_icons.join("icon32.png"), chrome::ICON_32)?;
54    std::fs::write(chrome_icons.join("icon48.png"), chrome::ICON_48)?;
55    std::fs::write(chrome_icons.join("icon128.png"), chrome::ICON_128)?;
56
57    // ── Safari unpacked ─────────────────────────────────────────────
58    let safari_dir = dir.join("safari");
59    let safari_icons = safari_dir.join("icons");
60    std::fs::create_dir_all(&safari_icons)?;
61    std::fs::write(safari_dir.join("manifest.json"), safari::MANIFEST)?;
62    std::fs::write(safari_dir.join("background.js"), safari::BACKGROUND)?;
63    std::fs::write(safari_dir.join("content.js"), safari::CONTENT_JS)?;
64    std::fs::write(safari_dir.join("content.css"), safari::CONTENT_CSS)?;
65    std::fs::write(safari_dir.join("Info.plist"), safari::INFO_PLIST)?;
66    std::fs::write(safari_icons.join("icon16.png"), safari::ICON_16)?;
67    std::fs::write(safari_icons.join("icon32.png"), safari::ICON_32)?;
68    std::fs::write(safari_icons.join("icon48.png"), safari::ICON_48)?;
69    std::fs::write(safari_icons.join("icon128.png"), safari::ICON_128)?;
70
71    // ── Zip archives ────────────────────────────────────────────────
72    std::fs::write(dir.join("voice-typing-chrome.zip"), CHROME_ZIP)?;
73    std::fs::write(dir.join("voice-typing-safari.zip"), SAFARI_ZIP)?;
74
75    Ok(())
76}