use std::fs;
use std::io::{self, Read};
use std::path::Path;
use crate::{ImportError, Imported};
#[derive(Debug, thiserror::Error)]
pub enum ReadError {
#[error("not a Markdown or Word file")]
Unsupported,
#[error("{0}")]
Io(#[from] io::Error),
#[error("not UTF-8 text")]
NotUtf8,
#[error("{0}")]
Import(#[from] ImportError),
}
pub fn read_manuscript(path: &Path) -> Result<Imported, ReadError> {
let ext = path
.extension()
.and_then(|e| e.to_str())
.map(str::to_ascii_lowercase);
match ext.as_deref() {
Some("md" | "markdown") => {
let bytes = fs::read(path)?;
let src = std::str::from_utf8(&bytes).map_err(|_| ReadError::NotUtf8)?;
let src = src.strip_prefix('\u{feff}').unwrap_or(src);
let dir = path.parent().unwrap_or(Path::new(""));
Ok(crate::markdown::import(src, |p| read_image(dir, p))?)
}
Some("docx") => Ok(crate::docx::import(&fs::read(path)?)?),
_ => Err(ReadError::Unsupported),
}
}
pub fn read_image(dir: &Path, path: &str) -> Option<Vec<u8>> {
let file = dir.join(path);
if !file.is_file() {
return None;
}
let mut bytes = Vec::new();
fs::File::open(file)
.ok()?
.take(crate::MAX_IMAGE_BYTES + 1)
.read_to_end(&mut bytes)
.ok()?;
Some(bytes)
}