From 2f26e4aad114ad21269912b2cf368c976cc6ecf8 Mon Sep 17 00:00:00 2001 From: Araozu Date: Wed, 5 Apr 2023 18:30:03 -0500 Subject: [PATCH] [Web] Generate sidebar from markdown headings --- doc-generator/src/generator/code.rs | 2 +- .../src/{ => generator}/highlighter/mod.rs | 27 +++--- doc-generator/src/generator/inline_code.rs | 7 +- doc-generator/src/generator/mod.rs | 2 + doc-generator/src/main.rs | 10 +- doc-generator/src/sidebar/mod.rs | 92 +++++++++++++++++++ doc-generator/src/utils.rs | 2 +- doc-generator/static/template.html | 11 ++- 8 files changed, 129 insertions(+), 24 deletions(-) rename doc-generator/src/{ => generator}/highlighter/mod.rs (81%) create mode 100644 doc-generator/src/sidebar/mod.rs diff --git a/doc-generator/src/generator/code.rs b/doc-generator/src/generator/code.rs index ce3b3f6..7f67793 100644 --- a/doc-generator/src/generator/code.rs +++ b/doc-generator/src/generator/code.rs @@ -1,6 +1,6 @@ use markdown::mdast::Code; -use crate::highlighter::highlight; +use super::highlighter::highlight; use super::Printable; diff --git a/doc-generator/src/highlighter/mod.rs b/doc-generator/src/generator/highlighter/mod.rs similarity index 81% rename from doc-generator/src/highlighter/mod.rs rename to doc-generator/src/generator/highlighter/mod.rs index c994ece..ed43076 100644 --- a/doc-generator/src/highlighter/mod.rs +++ b/doc-generator/src/generator/highlighter/mod.rs @@ -2,19 +2,17 @@ use misti::TokenType; #[macro_export] macro_rules! replace { - ($classes:literal, $token:ident, $offset:ident, $output:ident) => { - { - let start_pos = $token.position; - let end_pos = $token.get_end_position(); + ($classes:literal, $token:ident, $offset:ident, $output:ident) => {{ + let start_pos = $token.position; + let end_pos = $token.get_end_position(); - let range = (start_pos + $offset)..(end_pos + $offset); - let html = format!("{}", $classes, $token.value); + let range = (start_pos + $offset)..(end_pos + $offset); + let html = format!("{}", $classes, $token.value); - $offset += 28 + $classes.len(); + $offset += 28 + $classes.len(); - $output.replace_range(range, html.as_str()); - } - }; + $output.replace_range(range, html.as_str()); + }}; } pub fn highlight(input: &String) -> String { @@ -22,10 +20,7 @@ pub fn highlight(input: &String) -> String { let tokens = misti::tokenize(&input); if tokens.is_err() { - eprintln!( - "Found a lexical error processing code.\n{:?}", - tokens - ); + eprintln!("Found a lexical error processing code.\n{:?}", tokens); return input.clone(); } @@ -38,6 +33,9 @@ pub fn highlight(input: &String) -> String { match &token.token_type { TokenType::Datatype => replace!("class-name", token, offset, output), TokenType::Number => replace!("number", token, offset, output), + TokenType::Identifier if token.value == "true" || token.value == "false" => { + replace!("keyword", token, offset, output) + } TokenType::String => { let start_pos = token.position; let end_pos = token.get_end_position(); @@ -58,7 +56,6 @@ pub fn highlight(input: &String) -> String { output } - #[cfg(test)] mod tests { use super::*; diff --git a/doc-generator/src/generator/inline_code.rs b/doc-generator/src/generator/inline_code.rs index 468d8e9..a9988fb 100644 --- a/doc-generator/src/generator/inline_code.rs +++ b/doc-generator/src/generator/inline_code.rs @@ -1,7 +1,7 @@ use markdown::mdast::InlineCode; +use super::highlighter::highlight; use super::Printable; -use crate::highlighter::highlight; impl Printable for InlineCode { fn to_html(&self) -> String { @@ -14,7 +14,10 @@ impl Printable for InlineCode { .replace(">", ">"); */ - format!("{}", highlight(&self.value)) + format!( + "{}", + highlight(&self.value) + ) } fn get_text(&self) -> String { diff --git a/doc-generator/src/generator/mod.rs b/doc-generator/src/generator/mod.rs index 938b16c..032d2c7 100644 --- a/doc-generator/src/generator/mod.rs +++ b/doc-generator/src/generator/mod.rs @@ -10,6 +10,8 @@ mod root; mod strong; mod text; +mod highlighter; + pub trait Printable { fn to_html(&self) -> String; fn get_text(&self) -> String; diff --git a/doc-generator/src/main.rs b/doc-generator/src/main.rs index 033e8fb..0fa5ee2 100644 --- a/doc-generator/src/main.rs +++ b/doc-generator/src/main.rs @@ -1,12 +1,13 @@ use clap::Parser; use generator::Printable; +use sidebar::SidebarGenerator; use std::fs::File; use std::io::Write; use std::{fs, path::Path}; mod generator; +mod sidebar; mod utils; -mod highlighter; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -116,6 +117,7 @@ fn process_markdown(file: &Path, input_folder: &Path, output_folder: &Path) -> R // let html_text = to_html(markdown_text.as_str()); let md_ast = markdown::to_mdast(&markdown_text, &markdown::ParseOptions::gfm()).unwrap(); let html_text = md_ast.to_html(); + let sidebar_html = md_ast.generate_sidebar(); // Read template.html let mut template_path = output_folder.clone(); @@ -124,9 +126,13 @@ fn process_markdown(file: &Path, input_folder: &Path, output_folder: &Path) -> R let template_contents = fs::read(template_path).unwrap(); let template_contents = String::from_utf8(template_contents).unwrap(); - let final_output = template_contents.replace("{{markdown}}", &html_text); + let final_output = template_contents + .replace("{{markdown}}", &html_text) + .replace("{{sidebar}}", &sidebar_html); + // // Write to disk + // let _ = File::create(&output_file) .unwrap() .write_all(final_output.as_bytes()) diff --git a/doc-generator/src/sidebar/mod.rs b/doc-generator/src/sidebar/mod.rs new file mode 100644 index 0000000..d987c20 --- /dev/null +++ b/doc-generator/src/sidebar/mod.rs @@ -0,0 +1,92 @@ +use std::fmt::Display; + +use markdown::mdast::{Heading, Node}; + +use crate::{generator::Printable, utils}; + +pub trait SidebarGenerator { + fn generate_sidebar(&self) -> String; +} + +impl SidebarGenerator for Node { + fn generate_sidebar(&self) -> String { + match self { + Node::Root(root) => { + let children_nodes = root + .children + .clone() + .into_iter() + .filter_map(|x| match x { + Node::Heading(h) if h.depth <= 3 => Some(h), + _ => None, + }) + .collect(); + + // A top level topic that contains other topics + let topic = extract_topics(&children_nodes, 0, 1); + + match topic { + Some((t, _)) => { + let html: String = t.children.iter().map(|x| x.get_html()).collect(); + format!("", html) + } + None => String::from("D:"), + } + } + _ => panic!("??"), + } + } +} + +#[derive(Debug)] +struct Topic { + text: String, + children: Box>, +} + +impl Topic { + pub fn get_html(&self) -> String { + let extra = if self.children.len() > 0 { + let children_html: String = self.children.iter().map(|x| x.get_html()).collect(); + + format!("
    {}
", children_html) + } else { + String::from("") + }; + + let html_fragment_link = utils::to_html_fragment(&self.text); + format!( + "
  • {}{}
  • ", + html_fragment_link, self.text, extra + ) + } +} + +// Return the next heading and all its children +// current_level: the depth of the heading to match +fn extract_topics<'a>( + headings: &'a Vec, + current_pos: usize, + current_level: u8, +) -> Option<(Topic, usize)> { + match headings.get(current_pos) { + Some(h) if h.depth == current_level => { + let mut new_vec = Vec::new(); + let mut next_pos = current_pos + 1; + + while let Some((topic, next)) = extract_topics(headings, next_pos, current_level + 1) { + new_vec.push(topic); + next_pos = next; + } + + let title = h.get_text(); + let topic = Topic { + text: title, + children: Box::new(new_vec), + }; + + Some((topic, next_pos)) + } + _ => None, + } +} diff --git a/doc-generator/src/utils.rs b/doc-generator/src/utils.rs index dae4335..d180325 100644 --- a/doc-generator/src/utils.rs +++ b/doc-generator/src/utils.rs @@ -3,7 +3,7 @@ use markdown::mdast::Node; use crate::generator::Printable; pub fn to_html_fragment(text: &String) -> String { - text.clone().to_lowercase().replace(" ", "-") + text.clone().replace(" ", "-") } pub fn collect_children_html(vec: &Vec) -> String { diff --git a/doc-generator/static/template.html b/doc-generator/static/template.html index 95f2439..eab7738 100644 --- a/doc-generator/static/template.html +++ b/doc-generator/static/template.html @@ -17,12 +17,17 @@ -
    - {{markdown}} +
    +
    + {{sidebar}} +
    +
    + {{markdown}} +