Parcourir la source

Use title from Markdown file and substitute in header.

Alexandre Leblanc il y a 5 ans
Parent
commit
988e305407
1 fichiers modifiés avec 55 ajouts et 9 suppressions
  1. 55 9
      src/main.rs

+ 55 - 9
src/main.rs

@@ -1,7 +1,8 @@
 use std::path::{PathBuf, Path};
 use std::{fs, vec::Vec};
 
-use comrak::{markdown_to_html, ComrakOptions};
+use comrak::{ComrakOptions, Arena};
+use comrak::nodes::{NodeValue};
 
 use structopt::StructOpt;
 
@@ -17,6 +18,11 @@ struct Opt {
     output: PathBuf,
 }
 
+struct FileData {
+    html_content: String,
+    title: String
+}
+
 fn list_markdown_files(path: &Path) -> Vec<PathBuf> {
     let mut files = Vec::<PathBuf>::new();
     let dir_entries = fs::read_dir(path);
@@ -57,13 +63,50 @@ fn list_markdown_files(path: &Path) -> Vec<PathBuf> {
     files
 }
 
-fn md_to_html(file: &Path) -> Result<String, String> {
-    let content = fs::read_to_string(file);
+fn md_to_file_info(file: &Path) -> Result<FileData, String> {
+    let arena = Arena::new();
+    let file_content = fs::read_to_string(file).unwrap();
+
+    let ast_root = comrak::parse_document(&arena, file_content.as_str(), &ComrakOptions::default());
 
-    match content {
-        Ok(content) => Ok(markdown_to_html(&content, &ComrakOptions::default())),
-        Err(err) => Err(err.to_string())
+    // Page title is the first level 1 heading we find.
+    let page_title_node = ast_root.children().find(|item| {
+        match item.data.borrow().value {
+            NodeValue::Heading(ref n) => n.level == 1,
+            _ => false
+        }
+    });
+
+    let mut page_title = String::new();
+
+    match page_title_node {
+        Some(node) => {
+            match node.first_child() {
+                Some(child) => {
+                    match child.data.borrow().value {
+                        NodeValue::Text(ref utf8_text) => {
+                            page_title = std::str::from_utf8(&utf8_text).unwrap_or("").to_owned();
+                        },
+                        _ => println!("[error] Couldn't extract title from file '{}'.", file.to_str().unwrap())
+                    }
+                },
+                None => println!("[warning] Could not find title (empty?).")
+            }
+        },
+        None => {
+            println!("[warning] Could not find title for file '{}'. Consider After a header level 1: `# My title` at the beginning of your page.", file.to_str().unwrap());
+         }
+    }
+
+    let mut output = vec![];
+    if let Err(_) = comrak::format_html(&ast_root, &ComrakOptions::default(), &mut output) {
+        return Err("Could not format html.".to_owned());
     }
+
+    Ok(FileData {
+        html_content: String::from_utf8(output).unwrap(),
+        title: page_title
+    })
 }
 
 // Create the folders path (equivalent to mkdir -p <path>)
@@ -102,14 +145,17 @@ fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
         println!("[warning] No footer.html found.");
     }
 
-    let header_content = fs::read_to_string(header_path).unwrap_or("<html><head><title></title><body>".to_owned());
+    let header_content = fs::read_to_string(header_path).unwrap_or("<html><head><title>{title}</title><body>".to_owned());
     let footer_content = fs::read_to_string(footer_path).unwrap_or("</body></html>".to_owned());
 
     for file in files {
         create_output_file_path(&opt, &file)?;
 
-        let html_content = md_to_html(&file)?;
-        let assembled_content = format!("{}{}{}", header_content, html_content, footer_content);
+        let file_data = md_to_file_info(&file)?;
+
+        let assembled_content = format!("{}{}{}",
+            header_content.replace("{title}", &file_data.title),
+            file_data.html_content, footer_content);
 
         let dest_path = get_dest_file_path(&opt, &file)?;