orgize/README.md

196 lines
4.9 KiB
Markdown
Raw Normal View History

2019-02-06 12:50:18 +00:00
# Orgize
[![Build Status](https://travis-ci.org/PoiScript/orgize.svg?branch=master)](https://travis-ci.org/PoiScript/orgize)
[![Crates.io](https://img.shields.io/crates/v/orgize.svg)](https://crates.io/crates/orgize)
[![Document](https://docs.rs/orgize/badge.svg)](https://docs.rs/orgize)
2019-06-27 17:13:05 +01:00
A Rust library for parsing orgmode files.
2019-02-06 12:50:18 +00:00
2019-06-27 17:13:05 +01:00
## Parse
2019-02-06 12:50:18 +00:00
2019-06-27 17:13:05 +01:00
To parse a orgmode string, simply invoking the `Org::parse` function:
2019-02-06 12:50:18 +00:00
```rust
2019-06-27 17:13:05 +01:00
use orgize::Org;
2019-04-24 14:54:51 +01:00
2019-06-28 11:00:49 +01:00
Org::parse("* DONE Title :tag:");
```
or `Org::parse_with_config`:
``` rust
use orgize::{Org, ParseConfig};
Org::parse_with_config(
2019-06-28 11:00:49 +01:00
"* TASK Title 1",
&ParseConfig {
2019-06-28 11:00:49 +01:00
// custom todo keywords
todo_keywords: vec!["TASK".to_string()],
2019-06-28 11:00:49 +01:00
..Default::default()
},
);
2019-02-06 12:50:18 +00:00
```
2019-06-27 17:13:05 +01:00
## Iter
2019-04-24 14:54:51 +01:00
`Org::iter` function will returns an iteractor of `Event`s, which is
2019-06-27 17:13:05 +01:00
a simple wrapper of `Element`.
2019-04-24 14:54:51 +01:00
```rust
2019-06-28 11:00:49 +01:00
use orgize::Org;
for event in Org::parse("* DONE Title :tag:").iter() {
2019-06-27 17:13:05 +01:00
// handling the event
}
```
2019-04-24 14:54:51 +01:00
**Note**: whether an element is container or not, it will appears twice in one loop.
2019-06-27 17:13:05 +01:00
One as `Event::Start(element)`, one as `Event::End(element)`.
2019-04-24 14:54:51 +01:00
2019-06-27 17:13:05 +01:00
## Render html
2019-04-24 14:54:51 +01:00
You can call the `Org::html` function to generate html directly, which
2019-06-27 17:13:05 +01:00
uses the `DefaultHtmlHandler` internally:
2019-04-24 14:54:51 +01:00
2019-06-27 17:13:05 +01:00
```rust
2019-06-28 11:00:49 +01:00
use orgize::Org;
2019-06-27 17:13:05 +01:00
let mut writer = Vec::new();
Org::parse("* title\n*section*").html(&mut writer).unwrap();
2019-06-27 17:13:05 +01:00
assert_eq!(
String::from_utf8(writer).unwrap(),
2019-06-28 11:00:49 +01:00
"<main><h1>title</h1><section><p><b>section</b></p></section></main>"
2019-06-27 17:13:05 +01:00
);
2019-04-24 14:54:51 +01:00
```
## Render html with custom `HtmlHandler`
2019-04-24 14:54:51 +01:00
To customize html rendering, simply implementing `HtmlHandler` trait and passing
it to the `Org::html_with_handler` function.
2019-04-24 14:54:51 +01:00
2019-06-27 17:13:05 +01:00
The following code demonstrates how to add a id for every headline and return
own error type while rendering.
2019-02-06 12:50:18 +00:00
2019-02-07 07:54:16 +00:00
```rust
2019-06-28 11:00:49 +01:00
use std::convert::From;
use std::io::{Error as IOError, Write};
use std::string::FromUtf8Error;
use orgize::export::{html::Escape, DefaultHtmlHandler, HtmlHandler};
use orgize::{Element, Org};
use slugify::slugify;
2019-04-24 14:54:51 +01:00
#[derive(Debug)]
2019-06-27 17:13:05 +01:00
enum MyError {
2019-04-24 14:54:51 +01:00
IO(IOError),
2019-06-27 17:13:05 +01:00
Heading,
2019-04-24 14:54:51 +01:00
Utf8(FromUtf8Error),
}
2019-02-07 07:54:16 +00:00
2019-04-24 14:54:51 +01:00
// From<std::io::Error> trait is required for custom error type
2019-06-27 17:13:05 +01:00
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)
2019-04-24 14:54:51 +01:00
}
}
struct MyHtmlHandler(DefaultHtmlHandler);
2019-06-27 17:13:05 +01:00
impl HtmlHandler<MyError> for MyHtmlHandler {
fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<(), MyError> {
match element {
Element::Headline(headline) => {
2019-06-27 17:13:05 +01:00
if headline.level > 6 {
return Err(MyError::Heading);
} else {
write!(
w,
"<h{0}><a id=\"{1}\" href=\"#{1}\">{2}</a></h{0}>",
headline.level,
slugify!(headline.title),
2019-06-27 17:13:05 +01:00
Escape(headline.title),
)?;
}
}
// fallthrough to default handler
_ => self.0.start(w, element)?,
2019-06-27 17:13:05 +01:00
}
Ok(())
2019-04-24 14:54:51 +01:00
}
}
2019-06-27 17:13:05 +01:00
fn main() -> Result<(), MyError> {
let mut writer = Vec::new();
Org::parse("* title\n*section*").html_with_handler(&mut writer, MyHtmlHandler(DefaultHtmlHandler))?;
2019-06-28 11:00:49 +01:00
2019-04-24 14:54:51 +01:00
assert_eq!(
2019-06-27 17:13:05 +01:00
String::from_utf8(writer)?,
2019-06-28 11:00:49 +01:00
"<main><h1><a id=\"title\" href=\"#title\">title</a></h1>\
<section><p><b>section</b></p></section></main>"
2019-04-24 14:54:51 +01:00
);
Ok(())
}
2019-02-07 07:54:16 +00:00
```
2019-06-27 17:13:05 +01:00
**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.
2019-06-27 17:13:05 +01:00
# Serde
2019-06-27 17:13:05 +01:00
`Org` struct have already implemented serde's `Serialize` trait. It means you can
serialize it into any format supported by serde, such as json:
2019-06-27 17:13:05 +01:00
```rust
2019-06-27 17:50:15 +01:00
use orgize::Org;
use serde_json::{json, to_string};
let org = Org::parse("I 'm *bold*.");
2019-06-27 17:13:05 +01:00
println!("{}", to_string(&org).unwrap());
2019-06-27 17:50:15 +01:00
// {
// "type": "document",
// "children": [{
// "type": "section",
// "children": [{
// "type": "paragraph",
// "children":[{
// "type": "text",
// "value":"I 'm "
// }, {
// "type": "bold",
// "children":[{
// "type": "text",
// "value": "bold"
// }]
// }, {
// "type":"text",
// "value":"."
// }]
// }]
// }]
// }
2019-06-27 17:13:05 +01:00
```
2019-06-28 07:29:45 +01:00
## Features
By now, orgize provides two features:
2019-06-28 07:29:45 +01:00
+ `serde`: 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.
2019-06-28 07:29:45 +01:00
2019-02-06 12:50:18 +00:00
## License
MIT