use crate::dump::formatter::calculate_fence;
use serde::Deserialize;
#[derive(Deserialize)]
struct Notebook {
cells: Vec<Cell>,
}
#[derive(Deserialize)]
struct Cell {
cell_type: String, source: CellSource,
}
#[derive(Deserialize)]
#[serde(untagged)]
enum CellSource {
Lines(Vec<String>),
Single(String),
}
impl std::fmt::Display for CellSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CellSource::Lines(lines) => {
for l in lines {
write!(f, "{l}")?;
}
Ok(())
}
CellSource::Single(s) => write!(f, "{s}"),
}
}
}
pub fn cleaning_ipynb(raw_json: &str) -> Option<String> {
let notebook: Notebook = serde_json::from_str(raw_json).ok()?;
let mut out = String::new();
for (i, cell) in notebook.cells.iter().enumerate() {
let text = cell.source.to_string();
let trimmed = text.trim();
if trimmed.is_empty() {
continue;
}
match cell.cell_type.as_str() {
"markdown" => {
out.push_str(trimmed);
out.push_str("\n\n");
}
"code" => {
let fence = calculate_fence(trimmed);
out.push_str(&format!("<!-- Notebook Cell [{}] -->\n", i + 1));
out.push_str(&format!("{fence}python\n"));
out.push_str(trimmed);
out.push_str(&format!("\n{}\n\n", fence));
}
_ => {}
}
}
Some(out)
}