pub mod attr;
pub mod ext;
pub mod liteval;
pub mod partial;
pub mod pretty;
mod config;
mod utils;
pub use attr::AttrStore;
pub use config::Config;
use pretty::{PrettyPrinter, prelude::*};
use thiserror::Error;
use typst_syntax::{Source, SyntaxNode};
use crate::utils::indent_4_to_2;
#[derive(Error, Debug)]
pub enum Error {
#[error("The document has syntax errors")]
SyntaxError,
#[error("An error occurred while rendering the document")]
RenderError,
}
#[derive(Debug, Clone, Default)]
pub struct Typstyle {
config: Config,
}
impl Typstyle {
pub fn new(config: Config) -> Self {
Self { config }
}
pub fn format_text(&self, text: impl Into<String>) -> Formatter<'_> {
self.format_source(Source::detached(text.into()))
}
pub fn format_source(&self, source: Source) -> Formatter<'_> {
Formatter::new(self.config.clone(), source)
}
}
pub struct Formatter<'a> {
source: Source,
printer: PrettyPrinter<'a>,
}
impl<'a> Formatter<'a> {
fn new(config: Config, source: Source) -> Self {
let attr_store = AttrStore::new(source.root());
let printer = PrettyPrinter::new(config, attr_store);
Self { source, printer }
}
pub fn render_ir(&'a self) -> Result<String, Error> {
let doc = self.build_doc()?;
Ok(indent_4_to_2(&format!("{doc:#?}")))
}
pub fn render(&'a self) -> Result<String, Error> {
let doc = self.build_doc()?;
let mut buf = String::new();
doc.render_fmt(self.printer.config().max_width, &mut buf)
.map_err(|_| Error::RenderError)?;
let result = utils::strip_trailing_whitespace(&buf);
Ok(result)
}
fn build_doc(&'a self) -> Result<ArenaDoc<'a>, Error> {
let root = self.source.root();
if root.diagnosis().errors {
return Err(Error::SyntaxError);
}
let markup = root.cast().unwrap();
let doc = self.printer.convert_markup(Default::default(), markup);
Ok(doc)
}
}
pub fn format_ast(root: &SyntaxNode) -> String {
indent_4_to_2(&format!("{root:#?}"))
}
#[cfg(feature = "mapping")]
mod ast_mapping;
#[cfg(feature = "mapping")]
pub use ast_mapping::{SpanMapping, format_ast_with_mapping};