use std::fmt;
use std::path::PathBuf;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
pub mod doc;
pub mod markdown;
pub mod render;
pub mod scaffold;
pub mod source;
pub mod template;
pub mod typst_emit;
pub use doc::WispDoc;
pub use scaffold::init;
pub use source::export;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Format {
Typst,
Html,
}
impl Format {
pub fn required_partials(self) -> &'static [&'static str] {
match self {
Format::Typst => &[
"theme.typ",
"header.typ",
"footer.typ",
"cover.typ",
"toc.typ",
],
Format::Html => &[
"theme.css",
"header.html",
"footer.html",
"cover.html",
"toc.html",
],
}
}
}
impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Format::Typst => "typst",
Format::Html => "html",
})
}
}
impl FromStr for Format {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"typst" | "typ" => Ok(Format::Typst),
"html" => Ok(Format::Html),
other => Err(format!(
"unknown partial format `{other}` (expected `typst` or `html`)"
)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Renderer {
#[default]
Typst,
Weasyprint,
Chromium,
}
impl Renderer {
pub fn format(self) -> Format {
match self {
Renderer::Typst => Format::Typst,
Renderer::Weasyprint | Renderer::Chromium => Format::Html,
}
}
}
impl fmt::Display for Renderer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Renderer::Typst => "typst",
Renderer::Weasyprint => "weasyprint",
Renderer::Chromium => "chromium",
})
}
}
impl FromStr for Renderer {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"typst" => Ok(Renderer::Typst),
"weasyprint" => Ok(Renderer::Weasyprint),
"chromium" | "chrome" => Ok(Renderer::Chromium),
other => Err(format!(
"unknown renderer `{other}` (expected `typst`, `weasyprint`, or `chromium`)"
)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum Status {
Approved,
Draft,
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Status::Approved => "APPROVED",
Status::Draft => "DRAFT",
})
}
}
#[derive(Debug, Clone)]
pub struct InitOptions {
pub dir: PathBuf,
pub format: Format,
pub logo: Option<PathBuf>,
pub force: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct InitReport {
pub dir: PathBuf,
pub format: Format,
pub written: Vec<String>,
pub skipped: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct ExportOptions {
pub root: PathBuf,
pub today: chrono::NaiveDate,
pub source: Option<PathBuf>,
pub template: Option<PathBuf>,
pub output: Option<PathBuf>,
pub toc: Option<bool>,
pub page_numbers: Option<bool>,
pub draft: bool,
pub allow_dirty: bool,
pub renderer: Option<Renderer>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ExportReport {
pub output: PathBuf,
pub version: String,
pub effective_date: String,
pub commit: String,
pub content_hash: String,
pub status: Status,
pub renderer: Renderer,
pub sections: Vec<String>,
pub pages: Option<u32>,
}