//! 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(), //! "

title

section

" //! ); //! ``` //! //! # 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 trait is required for custom error type //! impl From for MyError { //! fn from(err: IOError) -> Self { //! MyError::IO(err) //! } //! } //! //! impl From for MyError { //! fn from(err: FromUtf8Error) -> Self { //! MyError::Utf8(err) //! } //! } //! //! #[derive(Default)] //! struct MyHtmlHandler(DefaultHtmlHandler); //! //! impl HtmlHandler for MyHtmlHandler { //! fn start(&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, //! "", //! title.level, //! slugify!(&title.raw), //! )?; //! } //! } else { //! // fallthrough to default handler //! self.0.start(w, element)?; //! } //! Ok(()) //! } //! //! fn end(&mut self, mut w: W, element: &Element) -> Result<(), MyError> { //! if let Element::Title(title) = element { //! write!(w, "", 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)?, //! "

title

\ //!

section

" //! ); //! //! 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*."); //! 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 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;