document lib API

This commit is contained in:
Noah Hellman 2023-02-04 20:07:20 +01:00
parent 5efb700c9b
commit 477eadde1c
2 changed files with 89 additions and 0 deletions

View file

@ -1,4 +1,24 @@
//! An HTML renderer that takes an iterator of [`Event`]s and emits HTML. //! An HTML renderer that takes an iterator of [`Event`]s and emits HTML.
//!
//! The HTML can be written to either a [`std::fmt::Write`] or a [`std::io::Write`] object.
//!
//! # Examples
//!
//! Push to a [`String`] (implements [`std::fmt::Write`]):
//!
//! ```
//! # let events = std::iter::empty();
//! let mut html = String::new();
//! jotdown::html::push(events, &mut html);
//! ```
//!
//! Write to standard output with buffering ([`std::io::Stdout`] implements [`std::io::Write`]):
//!
//! ```
//! # let events = std::iter::empty();
//! let mut out = std::io::BufWriter::new(std::io::stdout());
//! jotdown::html::write(events, &mut out).unwrap();
//! ```
use crate::Alignment; use crate::Alignment;
use crate::Container; use crate::Container;

View file

@ -1,3 +1,39 @@
//! A pull parser for [Djot](https://djot.net).
//!
//! The main entry is through [`Parser`] which implements an [`Iterator`] of [`Event`]s. The events
//! can then be used to traverse the document structure in order to e.g. construct an AST or
//! directly generate to some output format. This crate provides an [`html`] module that can be
//! used to render the events to HTML.
//!
//! # Examples
//!
//! Generate HTML from Djot input:
//!
//! ```
//! let djot_input = "hello *world*!";
//! let events = jotdown::Parser::new(djot_input);
//! let mut html = String::new();
//! jotdown::html::push(events, &mut html);
//! assert_eq!(html, "<p>hello <strong>world</strong>!</p>\n");
//! ```
//!
//! Apply some filter to a specific type of element:
//!
//! ```
//! # use jotdown::Event;
//! # use jotdown::Container::Link;
//! let events =
//! jotdown::Parser::new("a [link](https://example.com)").map(|e| match e {
//! Event::Start(Link(dst, ty), attrs) => {
//! Event::Start(Link(dst.replace(".com", ".net").into(), ty), attrs)
//! }
//! e => e,
//! });
//! let mut html = String::new();
//! jotdown::html::push(events, &mut html);
//! assert_eq!(html, "<p>a <a href=\"https://example.net\">link</a></p>\n");
//! ```
use std::fmt::Write; use std::fmt::Write;
pub mod html; pub mod html;
@ -16,6 +52,12 @@ pub use attr::Attributes;
type CowStr<'s> = std::borrow::Cow<'s, str>; type CowStr<'s> = std::borrow::Cow<'s, str>;
/// A Djot event.
///
/// A Djot document is represented by a sequence of events. An element may consist of one or
/// multiple events. [`Container`] elements are represented by a [`Event::Start`] followed by
/// events representing its content, and finally a [`Event::End`]. Atomic elements without any
/// inside elements are represented by a single event.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Event<'s> { pub enum Event<'s> {
/// Start of a container. /// Start of a container.
@ -56,6 +98,13 @@ pub enum Event<'s> {
ThematicBreak(Attributes<'s>), ThematicBreak(Attributes<'s>),
} }
/// A container that may contain other elements.
///
/// There are three types of containers:
///
/// - inline, may only contain inline elements,
/// - block leaf, may only contain inline elements,
/// - block container, may contain any block-level elements.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Container<'s> { pub enum Container<'s> {
/// A blockquote element. /// A blockquote element.
@ -202,6 +251,7 @@ impl<'s> Container<'s> {
} }
} }
/// Alignment of a table column.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Alignment { pub enum Alignment {
Unspecified, Unspecified,
@ -210,30 +260,42 @@ pub enum Alignment {
Right, Right,
} }
/// The type of an inline span link.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum SpanLinkType { pub enum SpanLinkType {
/// E.g. `[text](url)`
Inline, Inline,
/// In the form `[text][tag]` or `[tag][]`.
Reference, Reference,
} }
/// The type of an inline link.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum LinkType { pub enum LinkType {
/// E.g. `[text](url)`.
Span(SpanLinkType), Span(SpanLinkType),
/// In the form `<url>`.
AutoLink, AutoLink,
/// In the form `<address>`.
Email, Email,
} }
/// The type of a list.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ListKind { pub enum ListKind {
/// A bullet list.
Unordered, Unordered,
/// An enumerated list.
Ordered { Ordered {
numbering: OrderedListNumbering, numbering: OrderedListNumbering,
style: OrderedListStyle, style: OrderedListStyle,
start: u64, start: u64,
}, },
/// A task list.
Task, Task,
} }
/// Numbering type of an ordered list.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderedListNumbering { pub enum OrderedListNumbering {
/// Decimal numbering, e.g. `1)`. /// Decimal numbering, e.g. `1)`.
@ -248,6 +310,7 @@ pub enum OrderedListNumbering {
RomanUpper, RomanUpper,
} }
/// Style of an ordered list.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderedListStyle { pub enum OrderedListStyle {
/// Number is followed by a period, e.g. `1.`. /// Number is followed by a period, e.g. `1.`.
@ -328,6 +391,12 @@ type Set<T> = std::collections::HashSet<T>;
#[cfg(feature = "deterministic")] #[cfg(feature = "deterministic")]
type Set<T> = std::collections::BTreeSet<T>; type Set<T> = std::collections::BTreeSet<T>;
/// A parser that generates [`Event`]s from a Djot document.
///
/// When created, it will perform an initial pass and build up a tree of the document's block
/// structure that will be kept for the duration of the parser's lifetime. Then, when the iterator
/// is advanced, the parser will start from the beginning of the document and parse inline elements
/// and emit [`Event`]s.
pub struct Parser<'s> { pub struct Parser<'s> {
src: &'s str, src: &'s str,