venus_sync/
lib.rs

1//! Sync engine for Venus notebooks.
2//!
3//! Converts between `.rs` Venus notebooks and `.ipynb` Jupyter format.
4//!
5//! # Architecture
6//!
7//! ```text
8//! notebook.rs ─────► RsParser ─────► CellsWithMeta ─────► IpynbGenerator ─────► notebook.ipynb
9//!                                           │
10//!                                           ▼
11//!                                     OutputCache
12//!                                    (.venus/outputs/)
13//! ```
14
15mod error;
16mod ipynb;
17mod outputs;
18mod parser;
19
20pub use error::{SyncError, SyncResult};
21pub use ipynb::{IpynbGenerator, JupyterNotebook};
22pub use outputs::OutputCache;
23pub use parser::{NotebookCell, NotebookMetadata, RsParser};
24
25use std::path::Path;
26
27/// Sync a `.rs` notebook to `.ipynb` format.
28pub fn sync_to_ipynb(
29    rs_path: impl AsRef<Path>,
30    ipynb_path: impl AsRef<Path>,
31    cache: Option<&OutputCache>,
32) -> SyncResult<()> {
33    let rs_path = rs_path.as_ref();
34    let ipynb_path = ipynb_path.as_ref();
35
36    // Parse the RS file
37    let parser = RsParser::new();
38    let (metadata, cells) = parser.parse_file(rs_path)?;
39
40    // Generate IPYNB
41    let mut generator = IpynbGenerator::new();
42    let notebook = generator.generate(&metadata, &cells, cache)?;
43
44    // Write to file
45    notebook.write_to_file(ipynb_path)?;
46
47    tracing::info!(
48        "Synced {} → {} ({} cells)",
49        rs_path.display(),
50        ipynb_path.display(),
51        cells.len()
52    );
53
54    Ok(())
55}
56
57/// Get the default `.ipynb` path for a `.rs` notebook.
58pub fn default_ipynb_path(rs_path: impl AsRef<Path>) -> std::path::PathBuf {
59    let rs_path = rs_path.as_ref();
60    rs_path.with_extension("ipynb")
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_default_ipynb_path() {
69        assert_eq!(
70            default_ipynb_path("notebook.rs"),
71            std::path::PathBuf::from("notebook.ipynb")
72        );
73        assert_eq!(
74            default_ipynb_path("/path/to/my_notebook.rs"),
75            std::path::PathBuf::from("/path/to/my_notebook.ipynb")
76        );
77    }
78}