@@ 1,1 1,207 @@
+use crate::structs::*;
+use std::fmt;
+fn html_escape(s: &String) -> String {
+ s.replace("&", "&")
+ .replace("<", "<")
+ .replace(">", ">")
+}
+
+impl fmt::Display for Textile {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ for block in self.0.iter() {
+ write!(f, "{}\n", block)?
+ }
+ Ok(())
+ }
+}
+
+impl fmt::Display for BlockTag {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ BlockTag::Basic {
+ kind,
+ indent,
+ align,
+ attributes,
+ content,
+ } => match kind {
+ BlockKind::Paragraph => write!(f, "<p>{}</p>", content),
+ BlockKind::BlockQuote => write!(f, "<blockquote>{}</blockquote>", content),
+ BlockKind::Header(n) => {
+ write!(f, "<h{}>{}</h{}>", n, content, n)
+ }
+ BlockKind::Footnote(n) => write!(
+ f,
+ "<p id=\"fn{}\" class=\"footnote\"><sup>{}</sup>{}<a href=\"#fnr{}\">&21A9;</a></p>",
+ n, n, content, n
+ ),
+ _ => Err(fmt::Error)
+ },
+ BlockTag::Preformatted {
+ kind,
+ indent,
+ align,
+ attributes,
+ content,
+ } => match kind {
+ BlockKind::Preformatted => write!(f, "<pre>{}</pre>", html_escape(content)),
+ BlockKind::BlockCode => write!(f, "<pre><code>{}</code></pre>", html_escape(content)),
+ _ => Err(fmt::Error) // other kinds should not be possible here
+ },
+ BlockTag::List {
+ indent,
+ align,
+ attributes,
+ content,
+ } => write!(f, "{}", content),
+ BlockTag::Table {
+ indent,
+ align,
+ attributes,
+ rows,
+ } => {
+ write!(f, "<table>\n")?;
+ for row in rows {
+ write!(f, "{}\n", row);
+ }
+ write!(f, "</table>");
+ Ok(())
+ },
+ BlockTag::NoTextile(s) => {
+ write!(f, "{}", s)
+ }
+ }
+ }
+}
+
+impl fmt::Display for InlineTag {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ InlineTag::Plaintext(s) => write!(f, "{}", s),
+ InlineTag::Code(s) => write!(f, "<code>{}</code>", html_escape(s)),
+ InlineTag::NoTextile(s) => write!(f, "{}", s),
+ InlineTag::Acronym { title, content } => match title {
+ Some(title) => {
+ write!(f, "<abbr title=\"{}\">{}</abbr>", title, content)
+ }
+ None => write!(f, "<span class=\"caps\">{}</span>", content),
+ },
+ InlineTag::FootnoteRef(n) => write!(
+ f,
+ "<sup id=\"fnr{}\"><a href=\"#fn{}\">{}</a></sup>",
+ n, n, n
+ ),
+ InlineTag::Link {
+ attributes,
+ title,
+ url,
+ content,
+ } => match title {
+ Some(title) => write!(
+ f,
+ "<a href=\"{}\" title=\"{}\">{}</a>",
+ url, title, content
+ ),
+ None => write!(f, "<a href=\"{}\">{}</a>", url, content),
+ },
+ InlineTag::Image {
+ attributes,
+ align,
+ url,
+ alt,
+ } => match alt {
+ Some(alt) => {
+ write!(f, "<img src=\"{}\" alt=\"{}\" />", url, alt)
+ }
+ None => write!(f, "<img src=\"{}\" />", url),
+ },
+ InlineTag::Phrase {
+ kind,
+ attributes,
+ content,
+ } => match kind {
+ Some(k) => {
+ write!(f, "<{}>", k)?;
+ for phrase in content {
+ write!(f, "{}", phrase)?;
+ }
+ write!(f, "</{}>", k)?;
+ Ok(())
+ }
+ None => {
+ for phrase in content {
+ write!(f, "{}", phrase)?;
+ }
+ Ok(())
+ }
+ },
+ InlineTag::LineBreak => write!(f, "<br />\n"),
+ }
+ }
+}
+
+impl fmt::Display for PhraseKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ PhraseKind::Italic => write!(f, "i"),
+ PhraseKind::Bold => write!(f, "b"),
+ PhraseKind::Emphasis => write!(f, "em"),
+ PhraseKind::Strong => write!(f, "strong"),
+ PhraseKind::Citation => write!(f, "cite"),
+ PhraseKind::Deleted => write!(f, "del"),
+ PhraseKind::Inserted => write!(f, "ins"),
+ PhraseKind::Superscript => write!(f, "sup"),
+ PhraseKind::Subscript => write!(f, "sub"),
+ PhraseKind::Span => write!(f, "span"),
+ }
+ }
+}
+
+impl fmt::Display for List {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let tag_name = match self.kind {
+ ListKind::Numeric => "ol",
+ ListKind::Bulleted => "ul",
+ };
+ write!(f, "<{}>\n", tag_name)?;
+ for item in self.items.iter() {
+ write!(f, "{}\n", item)?;
+ }
+ write!(f, "</{}>", tag_name)?;
+ Ok(())
+ }
+}
+
+impl fmt::Display for ListItem {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match &self.sublist {
+ Some(sublist) => {
+ write!(f, "<li>{}\n{}\n</li>", self.content, sublist)
+ }
+ None => write!(f, "<li>{}</li>", self.content),
+ }
+ }
+}
+
+impl fmt::Display for TableRow {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "<tr>\n")?;
+ for cell in &self.cells {
+ write!(f, "{}\n", cell)?;
+ }
+ write!(f, "</tr>")?;
+ Ok(())
+ }
+}
+
+impl fmt::Display for TableCell {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let tag_name = match self.kind {
+ CellKind::Header => "th",
+ CellKind::Data => "td",
+ };
+ write!(f, "<{}>{}</{}>", tag_name, self.content, tag_name)?;
+ Ok(())
+ }
+}