diff --git a/src/convert.rs b/src/convert.rs deleted file mode 100644 index 2e81fd2..0000000 --- a/src/convert.rs +++ /dev/null @@ -1,146 +0,0 @@ -#[derive(Debug, Clone, PartialEq)] -enum S { - None, - P, - Code, -} - -pub fn convert_document(markdown: &str) -> String { - let mut html = String::new(); - let mut state = S::None; - - for line in markdown.lines() { - if line.starts_with("```") { - if state == S::Code { - html += "\n"; - state = S::None; - } else { - if state == S::P { - html += "

\n"; - } - state = S::Code; - html += "
\n";
-			}
-			continue;
-		}
-
-		if state == S::Code {
-			html += line;
-			html += "\n";
-			continue;
-		}
-
-		if let Some((start, header)) = line.split_once(' ') {
-			let level = start.len();
-			if (1..=6).contains(&level) && start.chars().all(|c| c == '#') {
-				if state == S::P {
-					state = S::None;
-					html += "

\n"; - } - let header = &convert_line(header); - html += &format!("{header}\n"); - continue; - } - } - - if state == S::P && line.is_empty() { - state = S::None; - html += "

\n"; - } else if !line.is_empty() { - if state == S::None { - state = S::P; - html += "

\n"; - } - html += &convert_line(line); - html += "
\n"; - } - } - html -} - -fn convert_line(source: &str) -> String { - let mut out = String::new(); - let mut is_em = false; - let mut is_b = false; - let mut is_code = false; - let mut is_ul = false; - let toggle = |state: bool, tag: &str| { - if state { - format!("<{tag}>") - } else { - format!("") - } - }; - - let mut link: Option<(String, Option)> = None; - - let mut chars = source.chars().peekable(); - while let Some(c) = chars.next() { - if let Some(link_c) = &mut link { - match link_c { - (link_text, None) => { - if c == ']' { - if chars.peek() == Some(&'(') { - _ = chars.next(); - link_c.1 = Some(String::new()); - } else { - out += &format!("[{link_text}]"); - link = None; - } - } else { - link_text.push(c); - } - } - (link_text, Some(href)) => { - if c == ')' { - out += &format!("{link_text}"); - link = None; - } else { - href.push(c); - } - } - } - continue; - } - if c == '[' { - link = Some((String::new(), None)); - } else if c == '*' { - if chars.peek() == Some(&'*') { - _ = chars.next(); - is_b = !is_b; - out += &toggle(is_b, "strong"); - } else { - is_em = !is_em; - out += &toggle(is_em, "em"); - } - } else if c == '`' { - is_code = !is_code; - out += &toggle(is_code, "code"); - } else if c == '_' { - is_ul = !is_ul; - out += &toggle(is_ul, "u"); - } else { - out.push(c); - } - } - if let Some((link_text, href)) = link { - out += &format!("[{link_text}"); - if let Some(href) = href { - out += &format!("]({href}"); - } - } - - if is_em { - out += ""; - } - if is_b { - out += ""; - } - if is_code { - out += ""; - } - if is_ul { - out += ""; - } - out -} diff --git a/src/main.rs b/src/main.rs index 6cdb25d..8681195 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,13 +6,9 @@ use std::{ path::{Path, PathBuf}, }; -mod convert; -use convert::convert_document; - const SRC_DIR: &str = "write"; const OUT_DIR: &str = "site"; -const CONTENT_MARKER: &str = "{CONTENT}"; -const FILENAME_MARKER: &str = "{FILENAME}"; +const CONTENT_MARKER: &str = "CONTENT HERE"; const TEMPLATE_FILE: &str = "template.html"; const DEFAULT_TEMPLATE: &[u8] = include_bytes!("../template.html"); @@ -53,23 +49,74 @@ fn build_file(path: &Path) -> Result { if path.extension().and_then(OsStr::to_str) == Some("md") { convert_file(path) } else { - println!("file ignored: {}", path.display()); - // TODO copy non dotfiles - Ok(()) + todo!("move file") } } +#[derive(Debug, Clone, PartialEq)] +enum S { + None, + P, + Code, +} + fn convert_file(path: &Path) -> Result { + let markdown = read_to_string(path)?; let out_path = PathBuf::from(OUT_DIR).join(path.strip_prefix(SRC_DIR)?); let out_path = out_path.with_extension("html"); - let markdown = read_to_string(path)?; - let content = convert_document(&markdown); + let mut html = String::new(); + let mut state = S::None; + + for line in markdown.lines() { + if line.starts_with("```") { + if state == S::Code { + html += "

\n"; + state = S::None; + continue; + } + if state == S::P { + html += "

\n"; + } + state = S::Code; + html += "
\n";
+			continue;
+		}
+
+		if state == S::Code {
+			html += line;
+			html += "\n";
+			continue;
+		}
+
+		if let Some((start, header)) = line.split_once(' ') {
+			let level = start.len();
+			if (1..=6).contains(&level) && start.chars().all(|c| c == '#') {
+				if state == S::P {
+					state = S::None;
+					html += "

\n"; + } + let header = &convert_line(header); + html += &format!("{header}\n"); + continue; + } + } + + if state == S::P && line.is_empty() { + state = S::None; + html += "

\n"; + } else if !line.is_empty() { + if state == S::None { + state = S::P; + html += "

\n"; + } + html += &convert_line(line); + html += "
\n"; + } + } + let template = read_to_string(TEMPLATE_FILE)?; - let filename = path.file_stem().unwrap().to_string_lossy().to_string(); - let html = template - .replacen(CONTENT_MARKER, &content, 1) - .replace(FILENAME_MARKER, &filename); + let html = template.replacen(CONTENT_MARKER, &html, 1); DirBuilder::new() .recursive(true) @@ -79,3 +126,90 @@ fn convert_file(path: &Path) -> Result { println!("built {}", out_path.display()); Ok(()) } + +fn convert_line(source: &str) -> String { + let mut out = String::new(); + let mut is_em = false; + let mut is_b = false; + let mut is_code = false; + let mut is_ul = false; + let toggle = |state: bool, tag: &str| { + if state { + format!("<{tag}>") + } else { + format!("") + } + }; + + let mut link: Option<(String, Option)> = None; + + let mut chars = source.chars().peekable(); + while let Some(c) = chars.next() { + if let Some(link_c) = &mut link { + match link_c { + (link_text, None) => { + if c == ']' { + if chars.peek() == Some(&'(') { + _ = chars.next(); + link_c.1 = Some(String::new()); + } else { + out += &format!("[{link_text}]"); + link = None; + } + } else { + link_text.push(c); + } + } + (link_text, Some(href)) => { + if c == ')' { + out += &format!("{link_text}"); + link = None; + } else { + href.push(c); + } + } + } + continue; + } + if c == '[' { + link = Some((String::new(), None)); + } else if c == '*' { + if chars.peek() == Some(&'*') { + _ = chars.next(); + is_b = !is_b; + out += &toggle(is_b, "strong"); + } else { + is_em = !is_em; + out += &toggle(is_em, "em"); + } + } else if c == '`' { + is_code = !is_code; + out += &toggle(is_code, "code"); + } else if c == '_' { + is_ul = !is_ul; + out += &toggle(is_ul, "u"); + } else { + out.push(c); + } + } + if let Some((link_text, href)) = link { + out += &format!("[{link_text}"); + if let Some(href) = href { + out += &format!("]({href}"); + } + } + + if is_em { + out += &toggle(false, "em"); + } + if is_b { + out += &toggle(false, "b"); + } + if is_code { + out += &toggle(false, "code"); + } + if is_ul { + out += &toggle(false, "u"); + } + out +} diff --git a/template.html b/template.html index 7d852ce..67f63de 100644 --- a/template.html +++ b/template.html @@ -4,11 +4,11 @@ - Title - {FILENAME} + TITLE HERE - {CONTENT} + CONTENT HERE \ No newline at end of file