docs: update README.md and doc-tests
This commit is contained in:
parent
d9053d992d
commit
0083425872
116
README.md
116
README.md
|
@ -20,32 +20,38 @@ extern crate orgize;
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
### Using Parser
|
||||||
|
|
||||||
|
Orgize parser acts like a event-based parser, which means it returns an
|
||||||
|
`Iterator` of `Event` s.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use orgize::Parser;
|
use orgize::Parser;
|
||||||
|
|
||||||
let parser = Parser::new(
|
let parser = Parser::new(r#"* Title 1
|
||||||
r"* Title 1
|
|
||||||
*Section 1*
|
*Section 1*
|
||||||
** Title 2
|
** Title 2
|
||||||
_Section 2_
|
_Section 2_
|
||||||
* Title 3
|
* Title 3
|
||||||
/Section 3/
|
/Section 3/
|
||||||
* Title 4
|
* Title 4
|
||||||
=Section 4=",
|
=Section 4="#);
|
||||||
);
|
|
||||||
|
|
||||||
for event in parser {
|
for event in parser {
|
||||||
// handling the event
|
// handling the event
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can use the built-in render.
|
### Using Render
|
||||||
|
|
||||||
|
You can use the built-in `HtmlRender` to generate html string directly:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use orgize::export::DefaultHtmlRender;
|
use orgize::export::HtmlRender;
|
||||||
use std::io::Cursor;
|
use std::io::{Cursor, Result};
|
||||||
|
|
||||||
let contents = r"* Title 1
|
fn main() -> Result<()> {
|
||||||
|
let contents = r"* Title 1
|
||||||
*Section 1*
|
*Section 1*
|
||||||
** Title 2
|
** Title 2
|
||||||
_Section 2_
|
_Section 2_
|
||||||
|
@ -54,14 +60,96 @@ _Section 2_
|
||||||
* Title 4
|
* Title 4
|
||||||
=Section 4=";
|
=Section 4=";
|
||||||
|
|
||||||
let cursor = Cursor::new(Vec::new());
|
let mut cursor = Cursor::new(Vec::new());
|
||||||
let mut render = DefaultHtmlRender::new(cursor, &contents);
|
let mut render = HtmlRender::default(&mut cursor, &contents);
|
||||||
|
|
||||||
render
|
render.render()?;
|
||||||
.render()
|
|
||||||
.expect("something went wrong rendering the file");
|
|
||||||
|
|
||||||
let result = String::from_utf8(render.into_writer().into_inner()).expect("invalid utf-8");
|
assert_eq!(
|
||||||
|
String::from_utf8(cursor.into_inner()).unwrap(),
|
||||||
|
"<h1>Title 1</h1><section><p><b>Section 1</b></p></section>\
|
||||||
|
<h2>Title 2</h2><section><p><u>Section 2</u></p></section>\
|
||||||
|
<h1>Title 3</h1><section><p><i>Section 3</i></p></section>\
|
||||||
|
<h1>Title 4</h1><section><p><code>Section 4</code></p></section>"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom HtmlHandler
|
||||||
|
|
||||||
|
You can create your own handler by implementing `HtmlHandler` trait and passing
|
||||||
|
it to the `HtmlRender`.
|
||||||
|
|
||||||
|
The following example demonstrates how to add an anchor for every headline and
|
||||||
|
use your own error type.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use orgize::{export::*, headline::Headline};
|
||||||
|
use slugify::slugify;
|
||||||
|
use std::io::{Cursor, Error as IOError, Write};
|
||||||
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
|
// custom error type
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Error {
|
||||||
|
IO(IOError),
|
||||||
|
Headline,
|
||||||
|
Utf8(FromUtf8Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
// From<std::io::Error> trait is required for custom error type
|
||||||
|
impl From<IOError> for Error {
|
||||||
|
fn from(err: IOError) -> Error {
|
||||||
|
Error::IO(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomHtmlHandler;
|
||||||
|
|
||||||
|
impl<W: Write> HtmlHandler<W, Error> for CustomHtmlHandler {
|
||||||
|
fn headline_beg(&mut self, w: &mut W, hdl: Headline) -> Result<(), Error> {
|
||||||
|
if hdl.level > 6 {
|
||||||
|
Err(Error::Headline)
|
||||||
|
} else {
|
||||||
|
write!(
|
||||||
|
w,
|
||||||
|
r##"<h{}><a class="anchor" href="#{}">"##,
|
||||||
|
hdl.level,
|
||||||
|
slugify!(hdl.title),
|
||||||
|
)?;
|
||||||
|
self.escape(w, hdl.title)?;
|
||||||
|
Ok(write!(w, "</a></h{}>", hdl.level)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Error> {
|
||||||
|
let contents = r"* Title 1
|
||||||
|
*Section 1*
|
||||||
|
** Title 2
|
||||||
|
_Section 2_
|
||||||
|
* Title 3
|
||||||
|
/Section 3/
|
||||||
|
* Title 4
|
||||||
|
=Section 4=";
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(Vec::new());
|
||||||
|
let mut render = HtmlRender::new(CustomHtmlHandler, &mut cursor, &contents);
|
||||||
|
|
||||||
|
render.render()?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
String::from_utf8(cursor.into_inner()).map_err(Error::Utf8)?,
|
||||||
|
"<h1><a class=\"anchor\" href=\"#title-1\">Title 1</a></h1><section><p><b>Section 1</b></p></section>\
|
||||||
|
<h2><a class=\"anchor\" href=\"#title-2\">Title 2</a></h2><section><p><u>Section 2</u></p></section>\
|
||||||
|
<h1><a class=\"anchor\" href=\"#title-3\">Title 3</a></h1><section><p><i>Section 3</i></p></section>\
|
||||||
|
<h1><a class=\"anchor\" href=\"#title-4\">Title 4</a></h1><section><p><code>Section 4</code></p></section>"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
120
src/lib.rs
120
src/lib.rs
|
@ -1,33 +1,41 @@
|
||||||
//! A Rust library for parsing orgmode files.
|
//! A Rust library for parsing orgmode files.
|
||||||
//!
|
//!
|
||||||
//! ## Example
|
//! # Using Parser
|
||||||
|
//!
|
||||||
|
//! Orgize parser acts like a event-based parser, which means it
|
||||||
|
//! returns an `Iterator` of [`Event`] s.
|
||||||
|
//!
|
||||||
|
//! [`Event`]: enum.Event.html
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use orgize::Parser;
|
//! use orgize::Parser;
|
||||||
//!
|
//!
|
||||||
//! let parser = Parser::new(
|
//! let parser = Parser::new(r#"* Title 1
|
||||||
//! r"* Title 1
|
|
||||||
//! *Section 1*
|
//! *Section 1*
|
||||||
//! ** Title 2
|
//! ** Title 2
|
||||||
//! _Section 2_
|
//! _Section 2_
|
||||||
//! * Title 3
|
//! * Title 3
|
||||||
//! /Section 3/
|
//! /Section 3/
|
||||||
//! * Title 4
|
//! * Title 4
|
||||||
//! =Section 4=",
|
//! =Section 4="#);
|
||||||
//! );
|
|
||||||
//!
|
//!
|
||||||
//! for event in parser {
|
//! for event in parser {
|
||||||
//! // handling the event
|
//! // handling the event
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Alternatively, you can use the built-in render directly:
|
//! # Using Render
|
||||||
|
//!
|
||||||
|
//! You can use the built-in [`HtmlRender`] to generate html string directly:
|
||||||
|
//!
|
||||||
|
//! [`HtmlRender`]: export/struct.HtmlRender.html
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use orgize::export::HtmlRender;
|
//! use orgize::export::HtmlRender;
|
||||||
//! use std::io::Cursor;
|
//! use std::io::{Cursor, Result};
|
||||||
//!
|
//!
|
||||||
//! let contents = r"* Title 1
|
//! fn main() -> Result<()> {
|
||||||
|
//! let contents = r"* Title 1
|
||||||
//! *Section 1*
|
//! *Section 1*
|
||||||
//! ** Title 2
|
//! ** Title 2
|
||||||
//! _Section 2_
|
//! _Section 2_
|
||||||
|
@ -36,41 +44,76 @@
|
||||||
//! * Title 4
|
//! * Title 4
|
||||||
//! =Section 4=";
|
//! =Section 4=";
|
||||||
//!
|
//!
|
||||||
//! let mut cursor = Cursor::new(Vec::new());
|
//! let mut cursor = Cursor::new(Vec::new());
|
||||||
//! let mut render = HtmlRender::default(&mut cursor, &contents);
|
//! let mut render = HtmlRender::default(&mut cursor, &contents);
|
||||||
//!
|
//!
|
||||||
//! render
|
//! render.render()?;
|
||||||
//! .render()
|
|
||||||
//! .expect("something went wrong rendering the file");
|
|
||||||
//!
|
//!
|
||||||
//! let result = String::from_utf8(cursor.into_inner()).expect("invalid utf-8");
|
//! assert_eq!(
|
||||||
|
//! String::from_utf8(cursor.into_inner()).unwrap(),
|
||||||
|
//! "<h1>Title 1</h1><section><p><b>Section 1</b></p></section>\
|
||||||
|
//! <h2>Title 2</h2><section><p><u>Section 2</u></p></section>\
|
||||||
|
//! <h1>Title 3</h1><section><p><i>Section 3</i></p></section>\
|
||||||
|
//! <h1>Title 4</h1><section><p><code>Section 4</code></p></section>"
|
||||||
|
//! );
|
||||||
|
//!
|
||||||
|
//! Ok(())
|
||||||
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! or `impl HtmlHandler` to create your own render. The following example
|
//! # Custom HtmlHandler
|
||||||
//! add an anchor to every headline.
|
//!
|
||||||
|
//! You can create your own handler by implementing [`HtmlHandler`] trait and passing
|
||||||
|
//! it to the [`HtmlRender`].
|
||||||
|
//!
|
||||||
|
//! The following example demonstrates how to add an anchor for every headline and use
|
||||||
|
//! your own error type.
|
||||||
|
//!
|
||||||
|
//! [`HtmlHandler`]: export/trait.HtmlHandler.html
|
||||||
|
//! [`HtmlRender`]: export/struct.HtmlRender.html
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use std::io::{Cursor, Error, Result, Write};
|
//! use orgize::{export::*, headline::Headline};
|
||||||
//!
|
|
||||||
//! use orgize::export::*;
|
|
||||||
//! use orgize::headline::Headline;
|
|
||||||
//! use slugify::slugify;
|
//! use slugify::slugify;
|
||||||
|
//! use std::io::{Cursor, Error as IOError, Write};
|
||||||
|
//! use std::string::FromUtf8Error;
|
||||||
|
//!
|
||||||
|
//! // custom error type
|
||||||
|
//! #[derive(Debug)]
|
||||||
|
//! enum Error {
|
||||||
|
//! IO(IOError),
|
||||||
|
//! Headline,
|
||||||
|
//! Utf8(FromUtf8Error),
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // From<std::io::Error> trait is required for custom error type
|
||||||
|
//! impl From<IOError> for Error {
|
||||||
|
//! fn from(err: IOError) -> Error {
|
||||||
|
//! Error::IO(err)
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! struct CustomHtmlHandler;
|
//! struct CustomHtmlHandler;
|
||||||
//!
|
//!
|
||||||
//! impl<W: Write> HtmlHandler<W, Error> for CustomHtmlHandler {
|
//! impl<W: Write> HtmlHandler<W, Error> for CustomHtmlHandler {
|
||||||
//! fn headline_beg(&mut self, w: &mut W, hdl: Headline) -> Result<()> {
|
//! fn headline_beg(&mut self, w: &mut W, hdl: Headline) -> Result<(), Error> {
|
||||||
//! write!(
|
//! if hdl.level > 6 {
|
||||||
//! w,
|
//! Err(Error::Headline)
|
||||||
//! r##"<h{0}><a class="anchor" href="#{1}">{2}</a></h{0}>"##,
|
//! } else {
|
||||||
//! if hdl.level <= 6 { hdl.level } else { 6 },
|
//! write!(
|
||||||
//! slugify!(hdl.title),
|
//! w,
|
||||||
//! hdl.title,
|
//! r##"<h{}><a class="anchor" href="#{}">"##,
|
||||||
//! )
|
//! hdl.level,
|
||||||
|
//! slugify!(hdl.title),
|
||||||
|
//! )?;
|
||||||
|
//! self.escape(w, hdl.title)?;
|
||||||
|
//! Ok(write!(w, "</a></h{}>", hdl.level)?)
|
||||||
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! let contents = r"* Title 1
|
//! fn main() -> Result<(), Error> {
|
||||||
|
//! let contents = r"* Title 1
|
||||||
//! *Section 1*
|
//! *Section 1*
|
||||||
//! ** Title 2
|
//! ** Title 2
|
||||||
//! _Section 2_
|
//! _Section 2_
|
||||||
|
@ -79,18 +122,23 @@
|
||||||
//! * Title 4
|
//! * Title 4
|
||||||
//! =Section 4=";
|
//! =Section 4=";
|
||||||
//!
|
//!
|
||||||
//! let mut cursor = Cursor::new(Vec::new());
|
//! let mut cursor = Cursor::new(Vec::new());
|
||||||
|
//! let mut render = HtmlRender::new(CustomHtmlHandler, &mut cursor, &contents);
|
||||||
//!
|
//!
|
||||||
//! let mut render = HtmlRender::new(CustomHtmlHandler, &mut cursor, &contents);
|
//! render.render()?;
|
||||||
//!
|
//!
|
||||||
//! render
|
//! assert_eq!(
|
||||||
//! .render()
|
//! String::from_utf8(cursor.into_inner()).map_err(Error::Utf8)?,
|
||||||
//! .expect("something went wrong rendering the file");
|
//! "<h1><a class=\"anchor\" href=\"#title-1\">Title 1</a></h1><section><p><b>Section 1</b></p></section>\
|
||||||
|
//! <h2><a class=\"anchor\" href=\"#title-2\">Title 2</a></h2><section><p><u>Section 2</u></p></section>\
|
||||||
|
//! <h1><a class=\"anchor\" href=\"#title-3\">Title 3</a></h1><section><p><i>Section 3</i></p></section>\
|
||||||
|
//! <h1><a class=\"anchor\" href=\"#title-4\">Title 4</a></h1><section><p><code>Section 4</code></p></section>"
|
||||||
|
//! );
|
||||||
//!
|
//!
|
||||||
//! let result = String::from_utf8(cursor.into_inner()).expect("invalid utf-8");
|
//! Ok(())
|
||||||
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#[warn(missing_docs)]
|
|
||||||
pub mod elements;
|
pub mod elements;
|
||||||
pub mod export;
|
pub mod export;
|
||||||
pub mod headline;
|
pub mod headline;
|
||||||
|
|
|
@ -3,20 +3,22 @@ extern crate orgize;
|
||||||
use orgize::export::HtmlRender;
|
use orgize::export::HtmlRender;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
macro_rules! parse_assert {
|
macro_rules! html_test {
|
||||||
($content:expr, $expected:expr) => {{
|
($name:ident, $content:expr, $expected:expr) => {
|
||||||
let mut cursor = Cursor::new(Vec::new());
|
#[test]
|
||||||
let mut render = HtmlRender::default(&mut cursor, $content);
|
fn $name() {
|
||||||
render.render().expect("render error");
|
let mut cursor = Cursor::new(Vec::new());
|
||||||
let s = String::from_utf8(cursor.into_inner()).expect("invalid utf-8");
|
let mut render = HtmlRender::default(&mut cursor, $content);
|
||||||
assert_eq!(s, $expected);
|
render.render().expect("render error");
|
||||||
}};
|
let s = String::from_utf8(cursor.into_inner()).expect("invalid utf-8");
|
||||||
|
assert_eq!(s, $expected);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
html_test!(
|
||||||
fn emphasis() {
|
emphasis,
|
||||||
parse_assert!(
|
r#"* Title 1
|
||||||
r#"* Title 1
|
|
||||||
*Section 1*
|
*Section 1*
|
||||||
** Title 2
|
** Title 2
|
||||||
_Section 2_
|
_Section 2_
|
||||||
|
@ -24,19 +26,15 @@ _Section 2_
|
||||||
/Section 3/
|
/Section 3/
|
||||||
* Title 4
|
* Title 4
|
||||||
=Section 4="#,
|
=Section 4="#,
|
||||||
concat!(
|
"<h1>Title 1</h1><section><p><b>Section 1</b></p></section>\
|
||||||
"<h1>Title 1</h1><section><p><b>Section 1</b></p></section>",
|
<h2>Title 2</h2><section><p><u>Section 2</u></p></section>\
|
||||||
"<h2>Title 2</h2><section><p><u>Section 2</u></p></section>",
|
<h1>Title 3</h1><section><p><i>Section 3</i></p></section>\
|
||||||
"<h1>Title 3</h1><section><p><i>Section 3</i></p></section>",
|
<h1>Title 4</h1><section><p><code>Section 4</code></p></section>"
|
||||||
"<h1>Title 4</h1><section><p><code>Section 4</code></p></section>"
|
);
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
html_test!(
|
||||||
fn list() {
|
list,
|
||||||
parse_assert!(
|
r#"+ 1
|
||||||
r#"+ 1
|
|
||||||
|
|
||||||
+ 2
|
+ 2
|
||||||
|
|
||||||
|
@ -45,12 +43,9 @@ fn list() {
|
||||||
- 4
|
- 4
|
||||||
|
|
||||||
+ 5"#,
|
+ 5"#,
|
||||||
concat!(
|
"<section><ul>\
|
||||||
"<section><ul>",
|
<li><p>1</p></li>\
|
||||||
"<li><p>1</p></li>",
|
<li><p>2</p><ul><li><p>3</p></li><li><p>4</p></li></ul></li>\
|
||||||
"<li><p>2</p><ul><li><p>3</p></li><li><p>4</p></li></ul></li>",
|
<li><p>5</p></li>\
|
||||||
"<li><p>5</p></li>",
|
</ul></section>"
|
||||||
"</ul></section>"
|
);
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue