aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs147
1 files changed, 121 insertions, 26 deletions
diff --git a/src/main.rs b/src/main.rs
index e973048..2b6c3f6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,5 @@
use clap::Parser;
-use parse_wiki_text::Node;
+use parse_wiki_text::{Node, Parameter};
use std::fs::File;
use std::io::{stdin, stdout, Read, Write};
use tar::Header;
@@ -51,7 +51,7 @@ fn main() {
Some(model) => model == "wikitext",
}
{
- let filename = page.title.replace("/", "_");
+ let filename = title_to_filename(&page.title);
let ast = parse_wiki_text::Configuration::default().parse(&page.text);
if args.verbose {
@@ -60,10 +60,12 @@ fn main() {
}
}
+ let mut refs = vec![];
+ let mut inner = render_nodes_to_string(&ast.nodes, &mut refs);
+ render_refs(&mut inner, &refs);
let html = format!(
"<!DOCTYPE html><html><head><title>{}</title></head><body>{}</body></html>",
- page.title,
- render_nodes_to_string(ast.nodes)
+ page.title, inner,
);
if args.tar {
@@ -89,6 +91,10 @@ fn main() {
archive.finish().unwrap();
}
+fn title_to_filename(t: &str) -> String {
+ t.replace("/", "_")
+}
+
pub fn escape(text: &str) -> String {
text.replace("&", "&amp;")
.replace("<", "&lt;")
@@ -97,17 +103,19 @@ pub fn escape(text: &str) -> String {
.replace("\"", "&quot;")
}
-fn render_nodes(html: &mut String, nodes: Vec<Node>) {
+fn render_nodes(html: &mut String, refs: &mut Vec<String>, nodes: &Vec<Node>) {
for n in nodes {
- render_node(html, n)
+ render_node(html, refs, n)
}
}
-fn render_nodes_to_string(nodes: Vec<Node>) -> String {
+
+fn render_nodes_to_string(nodes: &Vec<Node>, refs: &mut Vec<String>) -> String {
let mut html = String::new();
- render_nodes(&mut html, nodes);
+ render_nodes(&mut html, refs, nodes);
return html;
}
-fn render_node(html: &mut String, n: Node) {
+
+fn render_node(html: &mut String, refs: &mut Vec<String>, n: &Node) {
use std::fmt::Write;
match n {
parse_wiki_text::Node::Bold { .. } => (),
@@ -115,41 +123,128 @@ fn render_node(html: &mut String, n: Node) {
parse_wiki_text::Node::Category {
ordinal, target, ..
} => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::CharacterEntity { character, .. } => write!(html, "[todo]").unwrap(),
+ parse_wiki_text::Node::CharacterEntity { character, .. } => {
+ write!(html, "[todo: character]").unwrap()
+ }
parse_wiki_text::Node::Comment { .. } => (),
- parse_wiki_text::Node::DefinitionList { items, .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::EndTag { name, .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::ExternalLink { nodes, .. } => write!(html, "[todo]").unwrap(),
+ parse_wiki_text::Node::DefinitionList { items, .. } => {
+ write!(html, "[todo: def list]").unwrap()
+ }
+ parse_wiki_text::Node::EndTag { name, .. } => write!(html, "[todo: tag end]").unwrap(),
+ parse_wiki_text::Node::ExternalLink { nodes, .. } => {
+ write!(html, "[todo: external link]").unwrap()
+ }
parse_wiki_text::Node::Heading { level, nodes, .. } => write!(
html,
"<h{level}>{}</h{level}>",
- render_nodes_to_string(nodes)
+ render_nodes_to_string(nodes, refs)
)
.unwrap(),
parse_wiki_text::Node::HorizontalDivider { .. } => write!(html, "<hr>").unwrap(),
parse_wiki_text::Node::Image { target, text, .. } => write!(html, "[todo: image]").unwrap(),
parse_wiki_text::Node::Italic { .. } => (),
- parse_wiki_text::Node::Link { target, text, .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::MagicWord { .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::OrderedList { items, .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::ParagraphBreak { .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::Parameter { default, name, .. } => write!(html, "[todo]").unwrap(),
+ parse_wiki_text::Node::Link { target, text, .. } => write!(
+ html,
+ "<a href=\"{}\">{}</a>",
+ title_to_filename(target), // TODO does this always link to wikipedia?
+ render_nodes_to_string(text, refs)
+ )
+ .unwrap(),
+ parse_wiki_text::Node::MagicWord { .. } => write!(html, "[todo: magic]").unwrap(),
+ parse_wiki_text::Node::OrderedList { items, .. } => write!(
+ html,
+ "<ol>{}</ol>",
+ items
+ .iter()
+ .map(|e| format!("<li>{}</li>", render_nodes_to_string(&e.nodes, refs)))
+ .collect::<Vec<_>>()
+ .join("")
+ )
+ .unwrap(),
+ parse_wiki_text::Node::UnorderedList { items, .. } => write!(
+ html,
+ "<ul>{}</ul>",
+ items
+ .iter()
+ .map(|e| format!("<li>{}</li>", render_nodes_to_string(&e.nodes, refs)))
+ .collect::<Vec<_>>()
+ .join("")
+ )
+ .unwrap(),
+ parse_wiki_text::Node::ParagraphBreak { .. } => write!(html, "</p><p>").unwrap(),
+ parse_wiki_text::Node::Parameter { default, name, .. } => {
+ write!(html, "[todo: parameter]").unwrap()
+ }
parse_wiki_text::Node::Preformatted { nodes, .. } => {
- write!(html, "<pre>{}</pre>", render_nodes_to_string(nodes)).unwrap()
+ write!(html, "<pre>{}</pre>", render_nodes_to_string(nodes, refs)).unwrap()
}
- parse_wiki_text::Node::Redirect { target, .. } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::StartTag { name, .. } => write!(html, "[todo]").unwrap(),
+ parse_wiki_text::Node::Redirect { target, .. } => write!(
+ html,
+ "Redirect: <a href=\"{}\">{}</a>",
+ title_to_filename(target),
+ title_to_filename(target)
+ )
+ .unwrap(),
+ parse_wiki_text::Node::StartTag { name, .. } => write!(html, "[todo: start tag]").unwrap(),
parse_wiki_text::Node::Table {
attributes,
captions,
rows,
..
- } => write!(html, "[todo]").unwrap(),
- parse_wiki_text::Node::Tag { name, nodes, .. } => write!(html, "[todo]").unwrap(),
+ } => write!(html, "[todo: table]").unwrap(),
+ parse_wiki_text::Node::Tag { name, nodes, .. } => match name.as_ref() {
+ "ref" => {
+ if !nodes.is_empty() {
+ let r = render_nodes_to_string(nodes, refs);
+ refs.push(r);
+ let refid = refs.len();
+ write!(html, "<sup><a href=\"#{}\">[{}]</a></sup>", refid, refid).unwrap();
+ }
+ }
+ _ => write!(html, "[todo: tag {name:?} template]").unwrap(),
+ },
parse_wiki_text::Node::Template {
name, parameters, ..
- } => write!(html, "[todo]").unwrap(),
+ } => {
+ let name = match name.first() {
+ Some(Node::Text { value, .. }) => value,
+ _ => panic!("no"),
+ };
+ render_template(html, refs, name, parameters)
+ }
parse_wiki_text::Node::Text { value, .. } => write!(html, "{}", escape(value)).unwrap(),
- parse_wiki_text::Node::UnorderedList { items, .. } => write!(html, "[todo]").unwrap(),
}
}
+
+pub fn render_template(
+ html: &mut String,
+ refs: &mut Vec<String>,
+ name: &str,
+ params: &Vec<Parameter>,
+) {
+ use std::fmt::Write;
+ match name {
+ "lang" => write!(html, "{}", render_nodes_to_string(&params[1].value, refs)).unwrap(),
+ "IPA" => write!(
+ html,
+ "<code>{}</code>",
+ render_nodes_to_string(&params[0].value, refs)
+ )
+ .unwrap(),
+
+ _ => {
+ write!(html, "[todo: {name:?} template]").unwrap();
+ // eprintln!("unsupported template {name:?}");
+ // eprintln!("{params:?}");
+ }
+ }
+}
+
+fn render_refs(html: &mut String, refs: &Vec<String>) {
+ use std::fmt::Write;
+ write!(html, "<ol>").unwrap();
+ for (i, r) in refs.iter().enumerate() {
+ write!(html, "<li id=\"{}\">{r}</li>", i + 1).unwrap()
+ }
+ write!(html, "</ol>").unwrap();
+}