From a335929801f6196a9b8df4889afafd33267d368c Mon Sep 17 00:00:00 2001 From: PoiScript Date: Sat, 12 Jan 2019 01:29:39 +0800 Subject: [PATCH] feat: html export --- src/export/html.rs | 181 +++++++++++++++++++++++++++++++++++++++++++++ src/export/mod.rs | 176 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/parser.rs | 2 - 4 files changed, 359 insertions(+), 2 deletions(-) create mode 100644 src/export/html.rs create mode 100644 src/export/mod.rs diff --git a/src/export/html.rs b/src/export/html.rs new file mode 100644 index 0000000..d5124f9 --- /dev/null +++ b/src/export/html.rs @@ -0,0 +1,181 @@ +use elements::{FnDef, Keyword}; +use export::Handler; +use headline::Headline; +use objects::{Cookie, FnRef, InlineCall, InlineSrc, Link, Macros, RadioTarget, Snippet, Target}; +use std::io::{Result, Write}; + +pub struct HtmlHandler; + +impl Handler for HtmlHandler { + fn handle_start_headline(&mut self, w: &mut W, hdl: Headline) -> Result<()> { + write!( + w, + "{1}", + if hdl.level <= 6 { hdl.level } else { 6 }, + hdl.title + ) + } + fn handle_end_headline(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_start_section(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_end_section(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_start_paragraph(&mut self, w: &mut W) -> Result<()> { + write!(w, "

") + } + fn handle_end_paragraph(&mut self, w: &mut W) -> Result<()> { + write!(w, "

") + } + fn handle_start_center_block(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_end_center_block(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_start_quote_block(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_end_quote_block(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_start_special_block( + &mut self, + w: &mut W, + name: &str, + args: Option<&str>, + ) -> Result<()> { + write!(w, "
") + } + fn handle_end_special_block(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_comment_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> { + Ok(()) + } + fn handle_example_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> { + write!(w, "
{}
", content) + } + fn handle_export_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> { + Ok(()) + } + fn handle_src_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> { + write!(w, "
{}
", content) + } + fn handle_verse_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> { + Ok(()) + } + fn handle_dyn_block_start(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_dyn_block_end(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_list_start(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_list_end(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_aff_keywords(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_call(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_clock(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_comment(&mut self, w: &mut W, content: &str) -> Result<()> { + Ok(()) + } + fn handle_table_start(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_table_end(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_table_cell(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_latex_env(&mut self, w: &mut W) -> Result<()> { + Ok(()) + } + fn handle_fn_def(&mut self, w: &mut W, fn_def: FnDef) -> Result<()> { + Ok(()) + } + fn handle_keyword(&mut self, w: &mut W, kw: Keyword) -> Result<()> { + Ok(()) + } + fn handle_rule(&mut self, w: &mut W) -> Result<()> { + write!(w, "
") + } + fn handle_cookie(&mut self, w: &mut W, cookie: Cookie) -> Result<()> { + Ok(()) + } + fn handle_fn_ref(&mut self, w: &mut W, fn_ref: FnRef) -> Result<()> { + Ok(()) + } + fn handle_inline_call(&mut self, w: &mut W, inline_call: InlineCall) -> Result<()> { + Ok(()) + } + fn handle_inline_src(&mut self, w: &mut W, inline_src: InlineSrc) -> Result<()> { + write!(w, "{}", inline_src.body) + } + fn handle_link(&mut self, w: &mut W, link: Link) -> Result<()> { + write!( + w, + "{}", + link.path, + link.desc.unwrap_or(link.path) + ) + } + fn handle_macros(&mut self, w: &mut W, macros: Macros) -> Result<()> { + Ok(()) + } + fn handle_radio_target(&mut self, w: &mut W, target: RadioTarget) -> Result<()> { + Ok(()) + } + fn handle_snippet(&mut self, w: &mut W, snippet: Snippet) -> Result<()> { + Ok(()) + } + fn handle_target(&mut self, w: &mut W, target: Target) -> Result<()> { + Ok(()) + } + fn handle_start_bold(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_end_bold(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_start_italic(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_end_italic(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_start_strike(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_end_strike(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_start_underline(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_end_underline(&mut self, w: &mut W) -> Result<()> { + write!(w, "") + } + fn handle_verbatim(&mut self, w: &mut W, content: &str) -> Result<()> { + write!(w, "{}", content) + } + fn handle_code(&mut self, w: &mut W, content: &str) -> Result<()> { + write!(w, "{}", content) + } + fn handle_text(&mut self, w: &mut W, content: &str) -> Result<()> { + write!(w, "{}", content.replace('\n', " ")) + } +} diff --git a/src/export/mod.rs b/src/export/mod.rs new file mode 100644 index 0000000..2deb3d9 --- /dev/null +++ b/src/export/mod.rs @@ -0,0 +1,176 @@ +mod html; + +pub use self::html::HtmlHandler; + +use elements::{FnDef, Keyword}; +use headline::Headline; +use objects::{Cookie, FnRef, InlineCall, InlineSrc, Link, Macros, RadioTarget, Snippet, Target}; +use parser::Parser; +use std::io::{Result, Write}; + +pub trait Handler { + fn handle_start_headline(&mut self, w: &mut W, hdl: Headline) -> Result<()>; + fn handle_end_headline(&mut self, w: &mut W) -> Result<()>; + fn handle_start_section(&mut self, w: &mut W) -> Result<()>; + fn handle_end_section(&mut self, w: &mut W) -> Result<()>; + fn handle_start_paragraph(&mut self, w: &mut W) -> Result<()>; + fn handle_end_paragraph(&mut self, w: &mut W) -> Result<()>; + fn handle_start_center_block(&mut self, w: &mut W) -> Result<()>; + fn handle_end_center_block(&mut self, w: &mut W) -> Result<()>; + fn handle_start_quote_block(&mut self, w: &mut W) -> Result<()>; + fn handle_end_quote_block(&mut self, w: &mut W) -> Result<()>; + fn handle_start_special_block( + &mut self, + w: &mut W, + name: &str, + args: Option<&str>, + ) -> Result<()>; + fn handle_end_special_block(&mut self, w: &mut W) -> Result<()>; + fn handle_comment_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>; + fn handle_example_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>; + fn handle_export_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>; + fn handle_src_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>; + fn handle_verse_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>; + fn handle_dyn_block_start(&mut self, w: &mut W) -> Result<()>; + fn handle_dyn_block_end(&mut self, w: &mut W) -> Result<()>; + fn handle_list_start(&mut self, w: &mut W) -> Result<()>; + fn handle_list_end(&mut self, w: &mut W) -> Result<()>; + fn handle_aff_keywords(&mut self, w: &mut W) -> Result<()>; + fn handle_call(&mut self, w: &mut W) -> Result<()>; + fn handle_clock(&mut self, w: &mut W) -> Result<()>; + fn handle_comment(&mut self, w: &mut W, content: &str) -> Result<()>; + fn handle_table_start(&mut self, w: &mut W) -> Result<()>; + fn handle_table_end(&mut self, w: &mut W) -> Result<()>; + fn handle_table_cell(&mut self, w: &mut W) -> Result<()>; + fn handle_latex_env(&mut self, w: &mut W) -> Result<()>; + fn handle_fn_def(&mut self, w: &mut W, fn_def: FnDef) -> Result<()>; + fn handle_keyword(&mut self, w: &mut W, kw: Keyword) -> Result<()>; + fn handle_rule(&mut self, w: &mut W) -> Result<()>; + fn handle_cookie(&mut self, w: &mut W, cookie: Cookie) -> Result<()>; + fn handle_fn_ref(&mut self, w: &mut W, fn_ref: FnRef) -> Result<()>; + fn handle_inline_call(&mut self, w: &mut W, inline_call: InlineCall) -> Result<()>; + fn handle_inline_src(&mut self, w: &mut W, inline_src: InlineSrc) -> Result<()>; + fn handle_link(&mut self, w: &mut W, link: Link) -> Result<()>; + fn handle_macros(&mut self, w: &mut W, macros: Macros) -> Result<()>; + fn handle_radio_target(&mut self, w: &mut W, target: RadioTarget) -> Result<()>; + fn handle_snippet(&mut self, w: &mut W, snippet: Snippet) -> Result<()>; + fn handle_target(&mut self, w: &mut W, target: Target) -> Result<()>; + fn handle_start_bold(&mut self, w: &mut W) -> Result<()>; + fn handle_end_bold(&mut self, w: &mut W) -> Result<()>; + fn handle_start_italic(&mut self, w: &mut W) -> Result<()>; + fn handle_end_italic(&mut self, w: &mut W) -> Result<()>; + fn handle_start_strike(&mut self, w: &mut W) -> Result<()>; + fn handle_end_strike(&mut self, w: &mut W) -> Result<()>; + fn handle_start_underline(&mut self, w: &mut W) -> Result<()>; + fn handle_end_underline(&mut self, w: &mut W) -> Result<()>; + fn handle_verbatim(&mut self, w: &mut W, content: &str) -> Result<()>; + fn handle_code(&mut self, w: &mut W, content: &str) -> Result<()>; + fn handle_text(&mut self, w: &mut W, content: &str) -> Result<()>; +} + +pub struct Render<'a, W: Write, H: Handler> { + pub parser: Parser<'a>, + pub handler: H, + writer: W, +} + +impl<'a, W: Write, H: Handler> Render<'a, W, H> { + pub fn new(handler: H, writer: W, text: &'a str) -> Render<'a, W, H> { + Render { + parser: Parser::new(text), + handler, + writer, + } + } + + pub fn into_wirter(self) -> W { + self.writer + } + + pub fn render(&mut self) -> Result<()> { + use parser::Event::*; + + for event in &mut self.parser { + match event { + StartHeadline(hdl) => self.handler.handle_start_headline(&mut self.writer, hdl)?, + EndHeadline => self.handler.handle_end_headline(&mut self.writer)?, + StartSection => self.handler.handle_start_section(&mut self.writer)?, + EndSection => self.handler.handle_end_section(&mut self.writer)?, + StartParagraph => self.handler.handle_start_paragraph(&mut self.writer)?, + EndParagraph => self.handler.handle_end_paragraph(&mut self.writer)?, + StartCenterBlock => self.handler.handle_start_center_block(&mut self.writer)?, + EndCenterBlock => self.handler.handle_end_center_block(&mut self.writer)?, + StartQuoteBlock => self.handler.handle_start_quote_block(&mut self.writer)?, + EndQuoteBlock => self.handler.handle_end_quote_block(&mut self.writer)?, + StartSpecialBlock { name, args } => { + self.handler + .handle_start_special_block(&mut self.writer, name, args)? + } + EndSpecialBlock => self.handler.handle_end_special_block(&mut self.writer)?, + CommentBlock { content, args } => { + self.handler + .handle_comment_block(&mut self.writer, content, args)? + } + ExampleBlock { content, args } => { + self.handler + .handle_example_block(&mut self.writer, content, args)? + } + ExportBlock { content, args } => { + self.handler + .handle_export_block(&mut self.writer, content, args)? + } + SrcBlock { content, args } => { + self.handler + .handle_src_block(&mut self.writer, content, args)? + } + VerseBlock { content, args } => { + self.handler + .handle_verse_block(&mut self.writer, content, args)? + } + DynBlockStart => self.handler.handle_dyn_block_start(&mut self.writer)?, + DynBlockEnd => self.handler.handle_dyn_block_end(&mut self.writer)?, + ListStart => self.handler.handle_list_start(&mut self.writer)?, + ListEnd => self.handler.handle_list_end(&mut self.writer)?, + AffKeywords => self.handler.handle_aff_keywords(&mut self.writer)?, + Call => self.handler.handle_call(&mut self.writer)?, + Clock => self.handler.handle_clock(&mut self.writer)?, + Comment(c) => self.handler.handle_comment(&mut self.writer, c)?, + TableStart => self.handler.handle_table_start(&mut self.writer)?, + TableEnd => self.handler.handle_table_end(&mut self.writer)?, + TableCell => self.handler.handle_table_cell(&mut self.writer)?, + LatexEnv => self.handler.handle_latex_env(&mut self.writer)?, + FnDef(f) => self.handler.handle_fn_def(&mut self.writer, f)?, + Keyword(keyword) => self.handler.handle_keyword(&mut self.writer, keyword)?, + Rule => self.handler.handle_rule(&mut self.writer)?, + Cookie(cookie) => self.handler.handle_cookie(&mut self.writer, cookie)?, + FnRef(fnref) => self.handler.handle_fn_ref(&mut self.writer, fnref)?, + InlineCall(inlinecall) => self + .handler + .handle_inline_call(&mut self.writer, inlinecall)?, + InlineSrc(inlinesrc) => self + .handler + .handle_inline_src(&mut self.writer, inlinesrc)?, + Link(link) => self.handler.handle_link(&mut self.writer, link)?, + Macros(macros) => self.handler.handle_macros(&mut self.writer, macros)?, + RadioTarget(radiotarget) => self + .handler + .handle_radio_target(&mut self.writer, radiotarget)?, + Snippet(snippet) => self.handler.handle_snippet(&mut self.writer, snippet)?, + Target(target) => self.handler.handle_target(&mut self.writer, target)?, + StartBold => self.handler.handle_start_bold(&mut self.writer)?, + EndBold => self.handler.handle_end_bold(&mut self.writer)?, + StartItalic => self.handler.handle_start_italic(&mut self.writer)?, + EndItalic => self.handler.handle_end_italic(&mut self.writer)?, + StartStrike => self.handler.handle_start_strike(&mut self.writer)?, + EndStrike => self.handler.handle_end_strike(&mut self.writer)?, + StartUnderline => self.handler.handle_start_underline(&mut self.writer)?, + EndUnderline => self.handler.handle_end_underline(&mut self.writer)?, + Verbatim(content) => self.handler.handle_verbatim(&mut self.writer, content)?, + Code(content) => self.handler.handle_code(&mut self.writer, content)?, + Text(content) => self.handler.handle_text(&mut self.writer, content)?, + } + } + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1f4bfc5..4440456 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,10 @@ extern crate jetscii; mod utils; mod elements; +mod export; mod headline; mod objects; mod parser; +pub use export::{HtmlHandler, Render}; pub use parser::Parser; diff --git a/src/parser.rs b/src/parser.rs index 941d306..b9a55b1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -71,8 +71,6 @@ pub enum Event<'a> { DynBlockEnd, ListStart, ListEnd, - ParagraphStart, - ParagraphEnd, AffKeywords,