From c2321b21e4228b92c84db3f6fa28ddc13098cea1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 23 May 2016 14:11:32 +0200 Subject: [PATCH 01/11] Initial import --- libimagentrymarkdown/Cargo.toml | 16 +++++++++++++ libimagentrymarkdown/src/error.rs | 10 ++++++++ libimagentrymarkdown/src/html.rs | 37 ++++++++++++++++++++++++++++++ libimagentrymarkdown/src/lib.rs | 11 +++++++++ libimagentrymarkdown/src/link.rs | 8 +++++++ libimagentrymarkdown/src/result.rs | 6 +++++ 6 files changed, 88 insertions(+) create mode 100644 libimagentrymarkdown/Cargo.toml create mode 100644 libimagentrymarkdown/src/error.rs create mode 100644 libimagentrymarkdown/src/html.rs create mode 100644 libimagentrymarkdown/src/lib.rs create mode 100644 libimagentrymarkdown/src/link.rs create mode 100644 libimagentrymarkdown/src/result.rs diff --git a/libimagentrymarkdown/Cargo.toml b/libimagentrymarkdown/Cargo.toml new file mode 100644 index 00000000..9cf01638 --- /dev/null +++ b/libimagentrymarkdown/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "libimagentrymarkdown" +version = "0.1.0" +authors = ["Matthias Beyer "] + +[dependencies] +log = "0.3" +hoedown = "5.0.0" +crossbeam = "0.2" + +[dependencies.libimagstore] +path = "../libimagstore" + +[dependencies.libimagerror] +path = "../libimagerror" + diff --git a/libimagentrymarkdown/src/error.rs b/libimagentrymarkdown/src/error.rs new file mode 100644 index 00000000..7f956801 --- /dev/null +++ b/libimagentrymarkdown/src/error.rs @@ -0,0 +1,10 @@ +generate_error_module!( + generate_error_types!(MarkdownError, MarkdownErrorKind, + MarkdownParsingError => "Markdown parsing error" + ); +); + +pub use self::error::MarkdownError; +pub use self::error::MarkdownErrorKind; + + diff --git a/libimagentrymarkdown/src/html.rs b/libimagentrymarkdown/src/html.rs new file mode 100644 index 00000000..4e278fab --- /dev/null +++ b/libimagentrymarkdown/src/html.rs @@ -0,0 +1,37 @@ +use result::Result; +use error::MarkdownErrorKind; + +pub type HTML = String; + +pub fn to_html(buffer: &str) -> Result { + unimplemented!() +} + +pub mod iter { + use result::Result; + use libimagstore::store::Entry; + use super::HTML; + use super::to_html; + + pub struct ToHtmlIterator> { + i: I + } + + impl> ToHtmlIterator { + + fn new(i: I) -> ToHtmlIterator { + ToHtmlIterator { i: i } + } + + } + + impl> Iterator for ToHtmlIterator { + type Item = Result; + + fn next(&mut self) -> Option { + self.i.next().map(|entry| to_html(&entry.get_content()[..])) + } + + } + +} diff --git a/libimagentrymarkdown/src/lib.rs b/libimagentrymarkdown/src/lib.rs new file mode 100644 index 00000000..5435535c --- /dev/null +++ b/libimagentrymarkdown/src/lib.rs @@ -0,0 +1,11 @@ +#[macro_use] extern crate log; +extern crate crossbeam; +extern crate hoedown; +extern crate libimagstore; +#[macro_use] extern crate libimagerror; + +pub mod error; +pub mod html; +pub mod link; +pub mod result; + diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs new file mode 100644 index 00000000..02526486 --- /dev/null +++ b/libimagentrymarkdown/src/link.rs @@ -0,0 +1,8 @@ +use result::Result; + +pub type Link = String; + +pub fn extract_links(buf: &str) -> Result> { + unimplemented!() +} + diff --git a/libimagentrymarkdown/src/result.rs b/libimagentrymarkdown/src/result.rs new file mode 100644 index 00000000..55aa68e5 --- /dev/null +++ b/libimagentrymarkdown/src/result.rs @@ -0,0 +1,6 @@ +use std::result::Result as RResult; + +use error::MarkdownError; + +pub type Result = RResult; + From c47923b6691e99cfe75b95f55a7b23d0173d77d7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 23 May 2016 14:12:44 +0200 Subject: [PATCH 02/11] Add README for crate --- libimagentrymarkdown/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 libimagentrymarkdown/README.md diff --git a/libimagentrymarkdown/README.md b/libimagentrymarkdown/README.md new file mode 100644 index 00000000..0f858534 --- /dev/null +++ b/libimagentrymarkdown/README.md @@ -0,0 +1,9 @@ +# libimagentrymarkdown + +Helper crate to add useful functionality in a wrapper around +[hoedown](https://crates.io/crates/hoedown) for imag. + +Adds functionality to extract links, parse content into HTML and other things +which might be useful for markdown rendering in imag. + + From f6fdfabf81f27b7db2244f1f30958db2f9a0e624 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 May 2016 16:00:03 +0200 Subject: [PATCH 03/11] Add impl for to_html() --- libimagentrymarkdown/src/error.rs | 2 +- libimagentrymarkdown/src/html.rs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libimagentrymarkdown/src/error.rs b/libimagentrymarkdown/src/error.rs index 7f956801..f3d81d1e 100644 --- a/libimagentrymarkdown/src/error.rs +++ b/libimagentrymarkdown/src/error.rs @@ -1,6 +1,6 @@ generate_error_module!( generate_error_types!(MarkdownError, MarkdownErrorKind, - MarkdownParsingError => "Markdown parsing error" + MarkdownRenderError => "Markdown render error" ); ); diff --git a/libimagentrymarkdown/src/html.rs b/libimagentrymarkdown/src/html.rs index 4e278fab..b350f34f 100644 --- a/libimagentrymarkdown/src/html.rs +++ b/libimagentrymarkdown/src/html.rs @@ -1,10 +1,21 @@ +use hoedown::{Markdown, Html as MdHtml}; +use hoedown::renderer::html::Flags as HtmlFlags; +use hoedown::renderer::Render; + use result::Result; use error::MarkdownErrorKind; +use libimagerror::into::IntoError; pub type HTML = String; pub fn to_html(buffer: &str) -> Result { - unimplemented!() + let md = Markdown::new(buffer); + let mut html = MdHtml::new(HtmlFlags::empty(), 0); + html.render(&md) + .to_str() + .map(String::from) + .map_err(Box::new) + .map_err(|e| MarkdownErrorKind::MarkdownRenderError.into_error_with_cause(e)) } pub mod iter { From fb2934a96dade2a7a98a9c9e11d57ba08f8c567d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 May 2016 16:17:02 +0200 Subject: [PATCH 04/11] Impl From for ToHtmlIterator --- libimagentrymarkdown/src/html.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libimagentrymarkdown/src/html.rs b/libimagentrymarkdown/src/html.rs index b350f34f..09038751 100644 --- a/libimagentrymarkdown/src/html.rs +++ b/libimagentrymarkdown/src/html.rs @@ -45,4 +45,12 @@ pub mod iter { } + impl> From for ToHtmlIterator { + + fn from(obj: I) -> ToHtmlIterator { + ToHtmlIterator::new(obj) + } + + } + } From 70f12dbef7c00c6a711afc9568542d8c9cb3d0d6 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 May 2016 16:30:06 +0200 Subject: [PATCH 05/11] Implement link extractor --- libimagentrymarkdown/src/link.rs | 78 ++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs index 02526486..4699e69a 100644 --- a/libimagentrymarkdown/src/link.rs +++ b/libimagentrymarkdown/src/link.rs @@ -1,8 +1,80 @@ use result::Result; -pub type Link = String; +use hoedown::renderer::Render; +use hoedown::Buffer; +use hoedown::Markdown; + +pub struct Link { + pub title: String, + pub link: String, +} + +struct LinkExtractor { + links: Vec, +} + +impl LinkExtractor { + + pub fn new() -> LinkExtractor { + LinkExtractor { links: vec![] } + } + + pub fn links(self) -> Vec { + self.links + } + +} + +impl Render for LinkExtractor { + + fn link(&mut self, + _: &mut Buffer, + content: Option<&Buffer>, + link: Option<&Buffer>, + _: Option<&Buffer>) + -> bool + { + let link = link.and_then(|l| l.to_str().ok()).map(String::from); + let content = content.and_then(|l| l.to_str().ok()).map(String::from); + + match (link, content) { + (Some(link), Some(content)) => { + self.links.push(Link { link: link, title: content }); + false + }, + + (_, _) => { + false + }, + } + + } + +} + +pub fn extract_links(buf: &str) -> Vec { + let mut le = LinkExtractor::new(); + le.render(&Markdown::new(buf)); + le.links() +} + +#[cfg(test)] +mod test { + use super::{Link, extract_links}; + + #[test] + fn test_one_link() { + let testtext = "Some [example text](http://example.com)."; + + let exp = Link { + title: String::from("example text"), + link: String::from("http://example.com"), + }; + + let mut links = extract_links(testtext); + assert_eq!(1, links.len()); + assert_eq!(exp, links.pop().unwrap()) + } -pub fn extract_links(buf: &str) -> Result> { - unimplemented!() } From a3d50a5e32b30e3c2b5eebbc087fd9908cd58c26 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 25 May 2016 13:37:14 +0200 Subject: [PATCH 06/11] Derive Debug, Clone, PartialEq and Eq for Link type --- libimagentrymarkdown/src/link.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs index 4699e69a..41912f64 100644 --- a/libimagentrymarkdown/src/link.rs +++ b/libimagentrymarkdown/src/link.rs @@ -4,6 +4,7 @@ use hoedown::renderer::Render; use hoedown::Buffer; use hoedown::Markdown; +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Link { pub title: String, pub link: String, From 1bb961ecb3a4de61e4d747e9fcd1b16e6ec77698 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 May 2016 11:16:55 +0200 Subject: [PATCH 07/11] Add test: Two (similar) links --- libimagentrymarkdown/src/link.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs index 41912f64..4c955fa5 100644 --- a/libimagentrymarkdown/src/link.rs +++ b/libimagentrymarkdown/src/link.rs @@ -77,5 +77,23 @@ mod test { assert_eq!(exp, links.pop().unwrap()) } + #[test] + fn test_two_similar_links() { + let testtext = r#" +Some [example text](http://example.com). +Some more [example text](http://example.com). + "#; + + let exp = Link { + title: String::from("example text"), + link: String::from("http://example.com"), + }; + + let mut links = extract_links(&testtext[..]); + assert_eq!(2, links.len()); + assert_eq!(exp, links.pop().unwrap()); + assert_eq!(exp, links.pop().unwrap()); + } + } From 650e29d4b5a805b83e30c530c740ade21d7d8542 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 May 2016 11:18:29 +0200 Subject: [PATCH 08/11] Add test: Two nonsimilar links --- libimagentrymarkdown/src/link.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs index 4c955fa5..19914308 100644 --- a/libimagentrymarkdown/src/link.rs +++ b/libimagentrymarkdown/src/link.rs @@ -95,5 +95,28 @@ Some more [example text](http://example.com). assert_eq!(exp, links.pop().unwrap()); } + #[test] + fn test_two_links() { + let testtext = r#" +Some [example text](http://example.com). +Some more [foo](http://example.com/foo). + "#; + + let exp1 = Link { + title: String::from("example text"), + link: String::from("http://example.com"), + }; + + let exp2 = Link { + title: String::from("foo"), + link: String::from("http://example.com/foo"), + }; + + let mut links = extract_links(&testtext[..]); + assert_eq!(2, links.len()); + assert_eq!(exp2, links.pop().unwrap()); + assert_eq!(exp1, links.pop().unwrap()); + } + } From 107e62a4269c8c51930dcbfc8271255d388034b5 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 May 2016 11:48:19 +0200 Subject: [PATCH 09/11] Add dependency url = 1.1. --- libimagentrymarkdown/Cargo.toml | 1 + libimagentrymarkdown/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/libimagentrymarkdown/Cargo.toml b/libimagentrymarkdown/Cargo.toml index 9cf01638..c752ccc7 100644 --- a/libimagentrymarkdown/Cargo.toml +++ b/libimagentrymarkdown/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Matthias Beyer "] log = "0.3" hoedown = "5.0.0" crossbeam = "0.2" +url = "1.1" [dependencies.libimagstore] path = "../libimagstore" diff --git a/libimagentrymarkdown/src/lib.rs b/libimagentrymarkdown/src/lib.rs index 5435535c..0f130c96 100644 --- a/libimagentrymarkdown/src/lib.rs +++ b/libimagentrymarkdown/src/lib.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate log; extern crate crossbeam; extern crate hoedown; +extern crate url; extern crate libimagstore; #[macro_use] extern crate libimagerror; From 12369ddadf0d0d4fa1618f8fdde6866a3a10c203 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 May 2016 11:48:37 +0200 Subject: [PATCH 10/11] Add into_urllink() translater helper --- libimagentrymarkdown/src/error.rs | 3 ++- libimagentrymarkdown/src/link.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libimagentrymarkdown/src/error.rs b/libimagentrymarkdown/src/error.rs index f3d81d1e..3e42e21b 100644 --- a/libimagentrymarkdown/src/error.rs +++ b/libimagentrymarkdown/src/error.rs @@ -1,6 +1,7 @@ generate_error_module!( generate_error_types!(MarkdownError, MarkdownErrorKind, - MarkdownRenderError => "Markdown render error" + MarkdownRenderError => "Markdown render error", + LinkParsingError => "Link parsing error" ); ); diff --git a/libimagentrymarkdown/src/link.rs b/libimagentrymarkdown/src/link.rs index 19914308..8ac3500c 100644 --- a/libimagentrymarkdown/src/link.rs +++ b/libimagentrymarkdown/src/link.rs @@ -1,8 +1,12 @@ +use error::MarkdownErrorKind as MEK; use result::Result; use hoedown::renderer::Render; use hoedown::Buffer; use hoedown::Markdown; +use url::Url; + +use libimagerror::into::IntoError; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Link { @@ -10,6 +14,23 @@ pub struct Link { pub link: String, } +impl Link { + + /// Translate a `Link` into a `UrlLink` + fn into_urllink(self) -> Result { + Url::parse(&self.link[..]) + .map(move |link| UrlLink { title: self.title, link: link, }) + .map_err(Box::new) + .map_err(|e| MEK::LinkParsingError.into_error_with_cause(e)) + } + +} + +pub struct UrlLink { + pub title: String, + pub link: Url, +} + struct LinkExtractor { links: Vec, } From db93f01ea38999d1afa5d053837266d3b5e75500 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 May 2016 17:08:27 +0200 Subject: [PATCH 11/11] Add WithHtmlIterator to iterate over (Entry, Result) tuples --- libimagentrymarkdown/src/html.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/libimagentrymarkdown/src/html.rs b/libimagentrymarkdown/src/html.rs index 09038751..f9d251a8 100644 --- a/libimagentrymarkdown/src/html.rs +++ b/libimagentrymarkdown/src/html.rs @@ -53,4 +53,30 @@ pub mod iter { } + + /// Iterate over `(Entry, Result)` tuples + pub struct WithHtmlIterator> { + i: I + } + + impl> WithHtmlIterator { + + fn new(i: I) -> WithHtmlIterator { + WithHtmlIterator { i: i } + } + + } + + impl> Iterator for WithHtmlIterator { + type Item = (Entry, Result); + + fn next(&mut self) -> Option { + self.i.next().map(|entry| { + let html = to_html(&entry.get_content()[..]); + (entry, html) + }) + } + + } + }