From cea6896788a42c0ea40f99deb4b5987d6741e360 Mon Sep 17 00:00:00 2001 From: Emile Date: Fri, 16 Aug 2024 23:33:53 +0200 Subject: big dump, forgot to commit... --- web/vokobe/src/main.rs | 922 ------------------------------------------------- 1 file changed, 922 deletions(-) delete mode 100644 web/vokobe/src/main.rs (limited to 'web/vokobe/src') diff --git a/web/vokobe/src/main.rs b/web/vokobe/src/main.rs deleted file mode 100644 index ab26457..0000000 --- a/web/vokobe/src/main.rs +++ /dev/null @@ -1,922 +0,0 @@ -/* -pull the std into scope and inline it so that we get documentation for it, -even when running offline -*/ -#[doc(inline)] -pub use std; - -use std::path::{Path, PathBuf}; -use std::io::{self, Read, Write, BufRead, BufReader}; -use std::fs::{self, File}; -use std::time; -use std::collections::HashMap; - -use structopt::StructOpt; -use regex::Regex; - -#[derive(Debug, StructOpt)] -#[structopt(name = "vokobe", about = "A static site generator")] -struct Opt { - /// Input path - #[structopt(parse(from_os_str))] - input_path: PathBuf, - - /// Output path - #[structopt(parse(from_os_str))] - output_path: PathBuf, - - /// Site name (e.g. emile.space) - site_name: String, - - /// Activate sending analytics to stats.emile.space - // -a and --analytics will be generated - // analytics are sent to stats.emile.space - #[structopt(short, long)] - analytics: bool, -} - -fn main() -> std::io::Result<()> { - - let mut internal_links: HashMap> = HashMap::new(); - - let opt = Opt::from_args(); - - let in_path = opt.input_path; - let output_path = opt.output_path; - - // read the style - let style_path = Path::new(&in_path).join("style.css"); - let mut style_file = File::open(style_path) - .expect("could not open style file"); - let mut style = String::new(); - style_file.read_to_string(&mut style) - .expect("could not read style file to string"); - - // read all dirs in the input path - let pathes = recursive_read_dir(&in_path, false)?; - - // pass 1: store the backlinks - - for path in &pathes { - if path.ends_with("README.md") { - // open the file and read it as a string - let mut readme_file = File::open(path)?; - let mut readme = String::new(); - readme_file.read_to_string(&mut readme)?; - - let internal_links_in_file - = parse_internal_links(readme.as_str()); - - for link in internal_links_in_file { - - internal_links.entry(link).or_insert_with(Vec::new).push(path.to_string_lossy().into_owned()) - } - } - } - - - // for each markdown_file in markdown_files { - // let internal_links_in_file = parse_internal_links(markdown_file); - // internal_links.insert(markdown_file, internal_links_in_file); - // } - - // pass 2: create the html - - println!("Got {} files", pathes.len()); - let mut readme_counter = 0; - - for path in pathes { - let stripped_path = path.strip_prefix(&in_path) - .expect(format!( - "could not strip the in_path prefix: {:?}", in_path).as_str()); - - // copy images and other files to the output folder - if path.is_file() { - - // define the source and destination - let src = Path::new(&in_path).join(stripped_path); - let dst = Path::new(&output_path).join(stripped_path); - - // define the destination folder (the dst path without the file) and create it - let mut dst_folder = dst.clone(); - dst_folder.pop(); // remove the file itself from the path - fs::create_dir_all(dst_folder)?; - - // copy the file to the destination - std::fs::copy(src, dst.as_path())?; - } - - if stripped_path.ends_with("README.md") { - readme_counter += 1; - - // define the "raw" path (no infile prefix, no file) - let mut ancestors = stripped_path.ancestors(); - ancestors.next(); - - let raw_path = ancestors.next() - .expect("could not extract next ancestor"); - - // out + rawpath - let index_path = output_path.join(raw_path); - - // (out + rawpath) + "index.html" - let index_file = index_path.join("index.html"); - - // - create the dir for the index.html as well as the index.html - // itself - fs::create_dir_all(index_path)?; - let mut file = File::create(&index_file)?; - - // this is the main block calling all other smaller functions. The - // whole output is compsed here - write_header(&mut file, &opt.site_name, &style)?; - write_body_start(&mut file, &opt.site_name)?; - write_nav(&mut file, in_path.as_path(), raw_path, opt.analytics)?; - write_same_level(&mut file, in_path.as_path(), raw_path)?; - write_readme_content(&mut file, in_path.as_path(), raw_path)?; - write_footer(&mut file, raw_path, &internal_links)?; - - file.write_all("".as_bytes())?; - } - } - - println!("Got {readme_counter} README.md files"); - - Ok(()) -} - -fn parse_internal_links(markdown_file: &str) -> Vec { - // Define a regular expression to match markdown-style links - let link_regex = Regex::new(r"\[([^\]]+)\]\(([^)]+)\)").unwrap(); - - // Initialize a vector to store internal links found in the markdown file - let mut internal_links = Vec::new(); - - // Iterate over each match of the regular expression in the markdown content - for capture in link_regex.captures_iter(&markdown_file) { - // Extract the link text and URL from the capture groups - // let link_text = &capture[1]; - let mut link_url = &capture[2]; - - // Check if the link is an internal link (e.g., relative URL) - // You can customize this condition based on your site's URL structure - if link_url.starts_with('/') || link_url.starts_with("../") { - if link_url.ends_with('/') { - link_url = link_url.trim_end_matches('/'); - } - internal_links.push(link_url.to_string()); - } - } - - internal_links -} - -/// Write the html header including the style file -/// TODO: Don't add the style file into each compiled html output, as the -/// style can be included allowing the user to cache the style file in their -/// browser. -fn write_header(file: &mut File, site_name: &String, style: &String) -> std::io::Result<()>{ - - // write the header including the style file - file.write_all(format!(r#" - - - - - - {} - - - - "#, site_name, style).as_bytes())?; - - Ok(()) -} - -/// write the start of the html body tag and the header linking back to the -/// site itself. -fn write_body_start(file: &mut File, site_name: &String) -> std::io::Result<()>{ - file.write_all(format!(r#" - -
- {} -
"#, site_name).as_bytes())?; - - Ok(()) -} - -/// Write the navigation section to the given file -fn write_nav(file: &mut File, in_path: &Path, raw_path: &Path, analytics: bool) - -> std::io::Result<()> { - - if analytics == true { - /* - file.write_all(format!(r#" - -