246 lines
6.8 KiB
Rust
246 lines
6.8 KiB
Rust
//! A Rust library for parsing orgmode files.
|
|
//!
|
|
//! [Live demo](https://orgize.herokuapp.com/)
|
|
//!
|
|
//! # Parse
|
|
//!
|
|
//! To parse a orgmode string, simply invoking the [`Org::parse`] function:
|
|
//!
|
|
//! [`Org::parse`]: struct.Org.html#method.parse
|
|
//!
|
|
//! ```rust
|
|
//! use orgize::Org;
|
|
//!
|
|
//! Org::parse("* DONE Title :tag:");
|
|
//! ```
|
|
//!
|
|
//! or [`Org::parse_custom`]:
|
|
//!
|
|
//! [`Org::parse_custom`]: struct.Org.html#method.parse_custom
|
|
//!
|
|
//! ```rust
|
|
//! use orgize::{Org, ParseConfig};
|
|
//!
|
|
//! Org::parse_custom(
|
|
//! "* TASK Title 1",
|
|
//! &ParseConfig {
|
|
//! // custom todo keywords
|
|
//! todo_keywords: (vec!["TASK".to_string()], vec![]),
|
|
//! ..Default::default()
|
|
//! },
|
|
//! );
|
|
//! ```
|
|
//!
|
|
//! # Iter
|
|
//!
|
|
//! [`Org::iter`] function will returns an iterator of [`Event`]s, which is
|
|
//! a simple wrapper of [`Element`].
|
|
//!
|
|
//! [`Org::iter`]: struct.Org.html#method.iter
|
|
//! [`Event`]: enum.Event.html
|
|
//! [`Element`]: elements/enum.Element.html
|
|
//!
|
|
//! ```rust
|
|
//! use orgize::Org;
|
|
//!
|
|
//! for event in Org::parse("* DONE Title :tag:").iter() {
|
|
//! // handling the event
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! **Note**: whether an element is container or not, it will appears twice in one loop.
|
|
//! One as [`Event::Start(element)`], one as [`Event::End(element)`].
|
|
//!
|
|
//! [`Event::Start(element)`]: enum.Event.html#variant.Start
|
|
//! [`Event::End(element)`]: enum.Event.html#variant.End
|
|
//!
|
|
//! # Render html
|
|
//!
|
|
//! You can call the [`Org::write_html`] function to generate html directly, which
|
|
//! uses the [`DefaultHtmlHandler`] internally:
|
|
//!
|
|
//! [`Org::write_html`]: struct.Org.html#method.write_html
|
|
//! [`DefaultHtmlHandler`]: export/struct.DefaultHtmlHandler.html
|
|
//!
|
|
//! ```rust
|
|
//! use orgize::Org;
|
|
//!
|
|
//! let mut writer = Vec::new();
|
|
//! Org::parse("* title\n*section*").write_html(&mut writer).unwrap();
|
|
//!
|
|
//! assert_eq!(
|
|
//! String::from_utf8(writer).unwrap(),
|
|
//! "<main><h1>title</h1><section><p><b>section</b></p></section></main>"
|
|
//! );
|
|
//! ```
|
|
//!
|
|
//! # Render html with custom `HtmlHandler`
|
|
//!
|
|
//! To customize html rendering, simply implementing [`HtmlHandler`] trait and passing
|
|
//! it to the [`Org::write_html_custom`] function.
|
|
//!
|
|
//! [`HtmlHandler`]: export/trait.HtmlHandler.html
|
|
//! [`Org::write_html_custom`]: struct.Org.html#method.write_html_custom
|
|
//!
|
|
//! The following code demonstrates how to add a id for every headline and return
|
|
//! own error type while rendering.
|
|
//!
|
|
//! ```rust
|
|
//! use std::convert::From;
|
|
//! use std::io::{Error as IOError, Write};
|
|
//! use std::string::FromUtf8Error;
|
|
//!
|
|
//! use orgize::export::{DefaultHtmlHandler, HtmlHandler};
|
|
//! use orgize::{Element, Org};
|
|
//! use slugify::slugify;
|
|
//!
|
|
//! #[derive(Debug)]
|
|
//! enum MyError {
|
|
//! IO(IOError),
|
|
//! Heading,
|
|
//! Utf8(FromUtf8Error),
|
|
//! }
|
|
//!
|
|
//! // From<std::io::Error> trait is required for custom error type
|
|
//! impl From<IOError> for MyError {
|
|
//! fn from(err: IOError) -> Self {
|
|
//! MyError::IO(err)
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! impl From<FromUtf8Error> for MyError {
|
|
//! fn from(err: FromUtf8Error) -> Self {
|
|
//! MyError::Utf8(err)
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! #[derive(Default)]
|
|
//! struct MyHtmlHandler(DefaultHtmlHandler);
|
|
//!
|
|
//! impl HtmlHandler<MyError> for MyHtmlHandler {
|
|
//! fn start<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), MyError> {
|
|
//! if let Element::Title(title) = element {
|
|
//! if title.level > 6 {
|
|
//! return Err(MyError::Heading);
|
|
//! } else {
|
|
//! write!(
|
|
//! w,
|
|
//! "<h{0}><a id=\"{1}\" href=\"#{1}\">",
|
|
//! title.level,
|
|
//! slugify!(&title.raw),
|
|
//! )?;
|
|
//! }
|
|
//! } else {
|
|
//! // fallthrough to default handler
|
|
//! self.0.start(w, element)?;
|
|
//! }
|
|
//! Ok(())
|
|
//! }
|
|
//!
|
|
//! fn end<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), MyError> {
|
|
//! if let Element::Title(title) = element {
|
|
//! write!(w, "</a></h{}>", title.level)?;
|
|
//! } else {
|
|
//! self.0.end(w, element)?;
|
|
//! }
|
|
//! Ok(())
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! fn main() -> Result<(), MyError> {
|
|
//! let mut writer = Vec::new();
|
|
//! let mut handler = MyHtmlHandler::default();
|
|
//! Org::parse("* title\n*section*").write_html_custom(&mut writer, &mut handler)?;
|
|
//!
|
|
//! assert_eq!(
|
|
//! String::from_utf8(writer)?,
|
|
//! "<main><h1><a id=\"title\" href=\"#title\">title</a></h1>\
|
|
//! <section><p><b>section</b></p></section></main>"
|
|
//! );
|
|
//!
|
|
//! Ok(())
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! **Note**: as I mentioned above, each element will appears two times while iterating.
|
|
//! And handler will silently ignores all end events from non-container elements.
|
|
//!
|
|
//! So if you want to change how a non-container element renders, just redefine the `start`
|
|
//! function and leave the `end` function unchanged.
|
|
//!
|
|
//! # Serde
|
|
//!
|
|
//! `Org` struct have already implemented serde's `Serialize` trait. It means you can
|
|
//! serialize it into any format supported by serde, such as json:
|
|
//!
|
|
//! ```rust
|
|
//! use orgize::Org;
|
|
//! use serde_json::{json, to_string};
|
|
//!
|
|
//! let org = Org::parse("I 'm *bold*.");
|
|
//! #[cfg(feature = "ser")]
|
|
//! println!("{}", to_string(&org).unwrap());
|
|
//!
|
|
//! // {
|
|
//! // "type": "document",
|
|
//! // "children": [{
|
|
//! // "type": "section",
|
|
//! // "children": [{
|
|
//! // "type": "paragraph",
|
|
//! // "children":[{
|
|
//! // "type": "text",
|
|
//! // "value":"I 'm "
|
|
//! // }, {
|
|
//! // "type": "bold",
|
|
//! // "children":[{
|
|
//! // "type": "text",
|
|
//! // "value": "bold"
|
|
//! // }]
|
|
//! // }, {
|
|
//! // "type":"text",
|
|
//! // "value":"."
|
|
//! // }]
|
|
//! // }]
|
|
//! // }]
|
|
//! // }
|
|
//! ```
|
|
//!
|
|
//! # Features
|
|
//!
|
|
//! By now, orgize provides three features:
|
|
//!
|
|
//! + `ser`: adds the ability to serialize `Org` and other elements using `serde`, enabled by default.
|
|
//!
|
|
//! + `chrono`: adds the ability to convert `Datetime` into `chrono` structs, disabled by default.
|
|
//!
|
|
//! + `syntect`: provides [`SyntectHtmlHandler`] for highlighting code block, disabled by default.
|
|
//!
|
|
//! [`SyntectHtmlHandler`]: export/struct.SyntectHtmlHandler.html
|
|
//!
|
|
//! # License
|
|
//!
|
|
//! MIT
|
|
|
|
mod config;
|
|
pub mod elements;
|
|
pub mod export;
|
|
mod headline;
|
|
mod org;
|
|
mod parse;
|
|
mod parsers;
|
|
mod validate;
|
|
|
|
// Re-export of the indextree crate.
|
|
pub use indextree;
|
|
#[cfg(feature = "syntect")]
|
|
pub use syntect;
|
|
|
|
pub use config::ParseConfig;
|
|
pub use elements::Element;
|
|
pub use headline::{Document, Headline};
|
|
pub use org::{Event, Org};
|
|
pub use validate::ValidationError;
|
|
|
|
#[cfg(feature = "wasm")]
|
|
mod wasm;
|