From d0369e15bf3cc0f61b1997a508187347c39978ef Mon Sep 17 00:00:00 2001 From: metamuffin Date: Wed, 28 Sep 2022 22:38:51 +0200 Subject: table of contents --- src/main.rs | 96 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2b6c3f6..eb2f70f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ fn main() { Some(model) => model == "wikitext", } { - let filename = title_to_filename(&page.title); + let filename = urlencode(&page.title); let ast = parse_wiki_text::Configuration::default().parse(&page.text); if args.verbose { @@ -59,14 +59,15 @@ fn main() { eprintln!("wikitext warning: {}", w.message.message()) } } - + use std::fmt::Write; let mut refs = vec![]; - let mut inner = render_nodes_to_string(&ast.nodes, &mut refs); - render_refs(&mut inner, &refs); - let html = format!( - "{}{}", - page.title, inner, - ); + let mut html = String::from(""); + write!(&mut html, "{}", escape(&page.title)).unwrap(); + write!(&mut html, "

{}

", escape(&page.title)).unwrap(); + render_toc(&mut html, &ast.nodes); + render_nodes(&mut html, &mut refs, &ast.nodes); + render_refs(&mut html, &refs); + write!(&mut html, "").unwrap(); if args.tar { let mut header = Header::new_gnu(); @@ -91,10 +92,9 @@ fn main() { archive.finish().unwrap(); } -fn title_to_filename(t: &str) -> String { +fn urlencode(t: &str) -> String { t.replace("/", "_") } - pub fn escape(text: &str) -> String { text.replace("&", "&") .replace("<", "<") @@ -121,32 +121,34 @@ fn render_node(html: &mut String, refs: &mut Vec, n: &Node) { parse_wiki_text::Node::Bold { .. } => (), parse_wiki_text::Node::BoldItalic { .. } => (), parse_wiki_text::Node::Category { - ordinal, target, .. + ordinal: _, + target: _, + .. } => write!(html, "[todo]").unwrap(), - parse_wiki_text::Node::CharacterEntity { character, .. } => { + parse_wiki_text::Node::CharacterEntity { character: _, .. } => { write!(html, "[todo: character]").unwrap() } parse_wiki_text::Node::Comment { .. } => (), - parse_wiki_text::Node::DefinitionList { items, .. } => { + 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, .. } => { + 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, - "{}", - render_nodes_to_string(nodes, refs) - ) - .unwrap(), + parse_wiki_text::Node::Heading { level, nodes, .. } => { + let h = render_nodes_to_string(nodes, refs); + write!(html, "{}", urlencode(&h), h).unwrap(); + } parse_wiki_text::Node::HorizontalDivider { .. } => write!(html, "
").unwrap(), - parse_wiki_text::Node::Image { target, text, .. } => write!(html, "[todo: image]").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, "{}", - title_to_filename(target), // TODO does this always link to wikipedia? + urlencode(target), // TODO does this always link to wikipedia? render_nodes_to_string(text, refs) ) .unwrap(), @@ -172,24 +174,28 @@ fn render_node(html: &mut String, refs: &mut Vec, n: &Node) { ) .unwrap(), parse_wiki_text::Node::ParagraphBreak { .. } => write!(html, "

").unwrap(), - parse_wiki_text::Node::Parameter { default, name, .. } => { - write!(html, "[todo: parameter]").unwrap() - } + parse_wiki_text::Node::Parameter { + default: _, + name: _, + .. + } => write!(html, "[todo: parameter]").unwrap(), parse_wiki_text::Node::Preformatted { nodes, .. } => { write!(html, "

{}
", render_nodes_to_string(nodes, refs)).unwrap() } parse_wiki_text::Node::Redirect { target, .. } => write!( html, "Redirect: {}", - title_to_filename(target), - title_to_filename(target) + urlencode(target), + urlencode(target) ) .unwrap(), - parse_wiki_text::Node::StartTag { name, .. } => write!(html, "[todo: start tag]").unwrap(), + parse_wiki_text::Node::StartTag { name: _, .. } => { + write!(html, "[todo: start tag]").unwrap() + } parse_wiki_text::Node::Table { - attributes, - captions, - rows, + attributes: _, + captions: _, + rows: _, .. } => write!(html, "[todo: table]").unwrap(), parse_wiki_text::Node::Tag { name, nodes, .. } => match name.as_ref() { @@ -216,6 +222,32 @@ fn render_node(html: &mut String, refs: &mut Vec, n: &Node) { } } +fn render_toc(html: &mut String, nodes: &Vec) { + use std::fmt::Write; + write!(html, "

Table of contents

").unwrap(); + let mut k = 0; + for n in nodes { + match n { + Node::Heading { level, nodes, .. } => { + let level = *level as usize; + while k < level { + k += 1; + write!(html, "
    ").unwrap(); + } + while k > level { + k -= 1; + write!(html, "
").unwrap(); + } + let h = render_nodes_to_string(nodes, &mut vec![]); + + write!(html, "
  • {}
  • ", urlencode(&h), h).unwrap(); + } + _ => (), + } + } + write!(html, "
    ").unwrap(); +} + pub fn render_template( html: &mut String, refs: &mut Vec, -- cgit v1.2.3-70-g09d2