The adoctra crate re-exports the parser and, behind features, the converters: html (default), docx, json, or all-backends.

[dependencies]
adoctra = "0.0.4"   # or: { version = "0.0.4", features = ["docx", "json"] }

API reference: docs.rs/adoctra.

Parse and convert

use adoctra::Backend;

let result = adoctra::parse("= Hello\n\nWorld");
for diagnostic in &result.diagnostics {
    eprintln!("{}: {}", diagnostic.severity.as_str(), diagnostic.message);
}
let html = adoctra::html::HtmlBackend::new().convert(&result.document)?;
std::fs::write("hello.html", html)?;

Parsing never fails: syntax problems become diagnostics with byte spans, and the document is still built. HtmlBackend::new() writes a standalone page, HtmlBackend::embedded() only the body content.

Attributes and options

use adoctra::ParseOptions;

let mut options = ParseOptions::default();
options.attributes.set("source-highlighter", "rouge");
options.attributes.set("toc", "");
let result = adoctra::parse_with_options(source, &options);
let html = adoctra::html::HtmlBackend::embedded().render(&result.document).html;

ParseOptions also holds the safe mode (safe, Safe by default), the base directory, include limits, document dates and the extension registry.

Includes and other resources

The parser never touches the file system by itself. Includes, images and other files are loaded through a ResourceProvider that you pass; MemoryResources keeps files in memory:

use adoctra::{MemoryResources, ParseOptions, SafeMode, SourceMap};

let mut resources = MemoryResources::new();
resources.insert("/book/main.adoc", "= Book\n\ninclude::chapter.adoc[]")?;
resources.insert("/book/chapter.adoc", "== Chapter\n\nText.")?;

let mut sources = SourceMap::new();
let source_id = sources.load("/book/main.adoc", None, &resources)?;
let options = ParseOptions { source_id, safe: SafeMode::Safe, ..Default::default() };
let result = adoctra::parse_resource(&mut sources, &options, &resources)?;

Implement ResourceProvider yourself to read from disk, a database or a virtual workspace.

DOCX

With the docx feature:

use adoctra::Backend;

let template = std::fs::read("corp.dotx")?;
let result = adoctra::parse(source);
let bytes = adoctra::docx::DocxBackend::new()
    .with_template(template)
    .convert(&result.document)?;

A template passed with with_template takes precedence over the docx-template attribute. See DOCX output for the style contract.

Extensions

Block, block macro, inline macro and tree processors are written in Rust and registered in a Registry:

use std::sync::Arc;
use adoctra::{BlockMacroProcessor, BlockMacroRequest, NewBlock, ParseOptions,
              ProcessContext, Registry};

struct Version;

impl BlockMacroProcessor for Version {
    fn name(&self) -> &str {
        "version"
    }
    fn process(&self, request: BlockMacroRequest, _: &mut ProcessContext<'_>) -> Option<NewBlock> {
        let text = format!("{} {}", request.target, env!("CARGO_PKG_VERSION"));
        Some(NewBlock::listing(text, request.attributes))
    }
}

let mut registry = Registry::new();
registry.register_block_macro(Version);
let options = ParseOptions { extensions: Some(Arc::new(registry)), ..Default::default() };
let result = adoctra::parse_with_options("version::myapp[]", &options);

The diagram support is itself an extension crate, adoctra-ext-diagram, registered with adoctra_ext_diagram::register(&mut registry, host).

Crates

Crate Purpose

adoctra

umbrella crate with feature-gated backends

adoctra-core

parser, document model, extension API (no backends)

adoctra-html

HTML5 backend

adoctra-docx

DOCX backend

adoctra-json

JSON backend

adoctra-highlight

Rouge port for server-side highlighting

adoctra-ext-diagram

diagram extension

adoctra-cli

the adoctra command

adoctra-wasm

WASM bindings for editors