pub use carta_ast as ast;
pub use carta_ast::Document;
pub use carta_core::{
Error, Extension, Extensions, MathMethod, Reader, ReaderOptions, Result, TocStyle, WrapMode,
Writer, WriterOptions, presets,
};
mod format_spec;
mod registry;
#[cfg(feature = "standalone")]
mod standalone;
pub use format_spec::parse_format_spec;
pub use registry::{
input_format_names, output_format_names, reader_for, supported_input_formats,
supported_output_formats, writer_for,
};
pub fn convert(
from: &str,
to: &str,
input: &str,
reader_options: &ReaderOptions,
writer_options: &WriterOptions,
) -> Result<String> {
let (from_base, from_ext) = format_spec::parse_reader_format_spec(from)?;
let (to_base, to_ext) = parse_format_spec(to)?;
let reader = reader_for(&from_base)?;
let writer = writer_for(&to_base)?;
let mut reader_options = reader_options.clone();
reader_options.extensions = from_ext.union(reader_options.extensions);
reader_options.greedy_paragraphs |= from_base.starts_with("markdown");
let mut writer_options = writer_options.clone();
writer_options.extensions = to_ext.union(writer_options.extensions);
#[cfg(feature = "standalone")]
let document = {
let mut document = reader.read(input, &reader_options)?;
standalone::merge_metadata(&mut document, &writer_options);
document
};
#[cfg(not(feature = "standalone"))]
let document = reader.read(input, &reader_options)?;
let body = if writer_options.number_sections && writer.numbers_sections_in_body() {
let mut numbered = document.clone();
carta_core::sections::number_sections(&mut numbered.blocks);
writer.write(&numbered, &writer_options)?
} else {
writer.write(&document, &writer_options)?
};
#[cfg(feature = "standalone")]
if (writer_options.standalone || writer_options.template.is_some())
&& let Some(wrapped) =
standalone::render(writer.as_ref(), &document, &body, &writer_options, &to_base)?
{
return Ok(wrapped);
}
Ok(body)
}
#[cfg(feature = "metadata-file")]
pub fn parse_metadata_file(
content: &str,
json: bool,
) -> Result<std::collections::BTreeMap<String, ast::MetaValue>> {
if json {
carta_readers::metadata::parse_json(content)
} else {
carta_readers::metadata::parse_yaml(content)
}
}
pub fn format_extensions(format: Option<&str>) -> Result<Vec<(Extension, bool)>> {
let (base, extensions) = parse_format_spec(format.unwrap_or("markdown"))?;
if !registry::reader_recognizes(&base) && !registry::writer_recognizes(&base) {
return Err(Error::UnsupportedFormat(base));
}
let supported = format_spec::supported_extensions(&base);
let mut entries: Vec<(Extension, bool)> = Extension::ALL
.iter()
.filter(|&&extension| supported.is_none_or(|set| set.contains(extension)))
.map(|&extension| (extension, extensions.contains(extension)))
.collect();
entries.sort_by_key(|(extension, _)| extension.name());
Ok(entries)
}