some hard coded working output.
Depends on my fork of orgize in order to not get hung up on blocks having empty lines
This commit is contained in:
parent
4e894bbbca
commit
31eb7c9b2e
6 changed files with 126 additions and 31 deletions
31
src/main.rs
31
src/main.rs
|
|
@ -2,10 +2,12 @@ pub mod org;
|
|||
pub mod publish;
|
||||
pub mod watcher;
|
||||
|
||||
use std::time::Duration;
|
||||
use std::{path::PathBuf, sync::mpsc};
|
||||
|
||||
use clap::Parser;
|
||||
use notify::{Event, RecursiveMode, Result, Watcher};
|
||||
use notify_debouncer_full::notify::{Event, RecursiveMode, Result, Watcher};
|
||||
use notify_debouncer_full::{DebouncedEvent, new_debouncer};
|
||||
use tracing::{error, info, level_filters::LevelFilter};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
|
|
@ -41,21 +43,28 @@ fn main() -> Result<()> {
|
|||
.init();
|
||||
|
||||
if let Some(path) = args.path {
|
||||
let (tx, rx) = mpsc::channel::<Result<Event>>();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
// Automatically select the best implementation for your platform.
|
||||
let mut watcher = notify::recommended_watcher(tx)?;
|
||||
let mut watcher = new_debouncer(Duration::from_millis(500), None, tx).unwrap();
|
||||
watcher.watch(&path, RecursiveMode::Recursive)?;
|
||||
for res in rx {
|
||||
match res {
|
||||
Ok(event) => match watcher::watch(event, &path) {
|
||||
Ok(()) => (),
|
||||
Err(e) => error!("internal error: {:?}", e),
|
||||
},
|
||||
loop {
|
||||
match rx.recv() {
|
||||
Ok(event) => event.map_or_else(
|
||||
|e| error!("Error: {:?}", e),
|
||||
|events| {
|
||||
for event in events {
|
||||
match watcher::watch(&event, &path) {
|
||||
Ok(()) => (),
|
||||
Err(e) => error!("internal error: {:?}", e),
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
Err(e) => error!("watch error: {:?}", e),
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("Nothing to do")
|
||||
info!("Nothing to do");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ use slugify::slugify;
|
|||
use std::cmp::min;
|
||||
use std::fmt;
|
||||
use std::fmt::Write as _;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, info};
|
||||
|
||||
use orgize::export::{Container, Event, TraversalContext, Traverser};
|
||||
use orgize::{SyntaxElement, SyntaxKind, SyntaxNode};
|
||||
|
|
@ -52,6 +54,8 @@ pub struct OrgHtmlExporter {
|
|||
in_descriptive_list: Vec<bool>,
|
||||
|
||||
table_row: TableRow,
|
||||
|
||||
files: Arc<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Eq)]
|
||||
|
|
@ -64,6 +68,12 @@ enum TableRow {
|
|||
}
|
||||
|
||||
impl OrgHtmlExporter {
|
||||
pub fn new(files: Arc<Vec<String>>) -> Self {
|
||||
let mut new = Self::default();
|
||||
new.files = files;
|
||||
new
|
||||
}
|
||||
|
||||
pub fn push_str(&mut self, s: impl AsRef<str>) {
|
||||
self.output += s.as_ref();
|
||||
}
|
||||
|
|
@ -87,6 +97,26 @@ impl OrgHtmlExporter {
|
|||
let mut ctx = TraversalContext::default();
|
||||
self.element(SyntaxElement::Node(node.clone()), &mut ctx);
|
||||
}
|
||||
|
||||
fn convert_denote_links(&self, link: impl AsRef<str>) -> String {
|
||||
let link = link.as_ref().to_string();
|
||||
if !link.starts_with("denote") {
|
||||
return link;
|
||||
};
|
||||
link.as_str()
|
||||
.to_string()
|
||||
.strip_prefix("denote:")
|
||||
.map_or(link.clone(), |key| {
|
||||
self.files
|
||||
.iter()
|
||||
.find(|file| file.contains(key))
|
||||
.map_or(link, |s| {
|
||||
let mut final_link = "/".to_string();
|
||||
final_link.push_str(s);
|
||||
final_link
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Traverser for OrgHtmlExporter {
|
||||
|
|
@ -281,7 +311,7 @@ impl Traverser for OrgHtmlExporter {
|
|||
Event::Leave(Container::OrgTableCell(_)) => self.output += "</td>",
|
||||
|
||||
Event::Enter(Container::Link(link)) => {
|
||||
let path = link.path();
|
||||
let path = self.convert_denote_links(link.path());
|
||||
let path = path.trim_start_matches("file:");
|
||||
let path = if let Some(path) = path.strip_suffix("org") {
|
||||
let mut path = path.to_string();
|
||||
|
|
@ -290,6 +320,7 @@ impl Traverser for OrgHtmlExporter {
|
|||
} else {
|
||||
path.to_string()
|
||||
};
|
||||
let path = path.trim_start_matches("//");
|
||||
|
||||
if link.is_image() {
|
||||
let _ = write!(&mut self.output, r#"<img src="{}">"#, HtmlEscape(&path));
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::collections::HashMap;
|
|||
use std::fs;
|
||||
use std::io::Error as IOError;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, error};
|
||||
use walkdir::{DirEntry, Error as WDError, WalkDir};
|
||||
|
||||
|
|
@ -57,7 +58,22 @@ pub fn build_site(
|
|||
}
|
||||
}
|
||||
if base_path.is_dir() {
|
||||
WalkDir::new(&base_path)
|
||||
let files = WalkDir::new(&base_path)
|
||||
.follow_links(true)
|
||||
.into_iter()
|
||||
.filter_map(|e| {
|
||||
e.ok().map(|e| {
|
||||
let path = e
|
||||
.path()
|
||||
.strip_prefix(&base_path)
|
||||
.unwrap_or_else(|_| e.path());
|
||||
path.to_string_lossy().to_string()
|
||||
})
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
let files = Arc::new(files);
|
||||
let walk_dir = WalkDir::new(&base_path);
|
||||
walk_dir
|
||||
.follow_links(true)
|
||||
.into_iter()
|
||||
.collect::<Vec<Result<walkdir::DirEntry, WDError>>>()
|
||||
|
|
@ -67,8 +83,8 @@ pub fn build_site(
|
|||
let path = entry.path();
|
||||
let file_name = path.file_name().unwrap_or_default().to_string_lossy();
|
||||
if path.is_file() && !path.ends_with("~") && !file_name.starts_with(".#") {
|
||||
let mut handler = OrgHtmlExporter::default();
|
||||
debug!(?path);
|
||||
let mut handler = OrgHtmlExporter::new(Arc::clone(&files));
|
||||
// debug!(?path);
|
||||
if path
|
||||
.extension()
|
||||
.iter()
|
||||
|
|
@ -76,7 +92,7 @@ pub fn build_site(
|
|||
.collect::<String>()
|
||||
== "org"
|
||||
{
|
||||
debug!("It ends with org");
|
||||
// debug!("It ends with org");
|
||||
let org_string = fs::read_to_string(path).unwrap_or_default();
|
||||
let org = orgize::Org::parse(&org_string);
|
||||
let mut keywords = org.keywords();
|
||||
|
|
@ -154,7 +170,17 @@ fn build_html(inner_html: String, keywords: HashMap<String, String>) -> String {
|
|||
display: none;
|
||||
}
|
||||
</style>"#;
|
||||
format!("{head}<body>\n{inner_html}\n</body></html>")
|
||||
let preamble = r#"<nav>
|
||||
<ul>
|
||||
<li><strong>Chris Cochrun</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="/notes">Notes</a></li>
|
||||
<li><a href="/teaching">Teaching</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
"#;
|
||||
format!("{head}<body>\n{preamble}{inner_html}\n</body></html>")
|
||||
}
|
||||
|
||||
fn extract_keywords<I>(keywords: &mut I) -> HashMap<String, String>
|
||||
|
|
@ -168,3 +194,7 @@ where
|
|||
}
|
||||
map
|
||||
}
|
||||
|
||||
fn conver_denote_links(inner_html: String) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use notify::{Event, EventKind};
|
||||
use notify_debouncer_full::{DebouncedEvent, notify::EventKind};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::publish::publish::{Error, build_site};
|
||||
|
||||
pub fn watch(event: Event, path: impl AsRef<Path>) -> Result<(), Error> {
|
||||
pub fn watch(event: &DebouncedEvent, path: impl AsRef<Path>) -> Result<(), Error> {
|
||||
if !event
|
||||
.paths
|
||||
.clone()
|
||||
|
|
@ -16,7 +16,10 @@ pub fn watch(event: Event, path: impl AsRef<Path>) -> Result<(), Error> {
|
|||
false
|
||||
} else {
|
||||
e.file_name().is_some_and(|base_name| {
|
||||
let name = base_name.to_os_string().into_string().unwrap_or("".into());
|
||||
let name = base_name
|
||||
.to_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_else(|_| String::new());
|
||||
!(name.starts_with(".#") | name.ends_with("~"))
|
||||
})
|
||||
}
|
||||
|
|
@ -28,14 +31,14 @@ pub fn watch(event: Event, path: impl AsRef<Path>) -> Result<(), Error> {
|
|||
match event.kind {
|
||||
EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) => {
|
||||
// rebuild function
|
||||
debug!(?event);
|
||||
for path in event.paths {
|
||||
for path in &event.paths {
|
||||
if !path.exists() {
|
||||
debug!("file deleted");
|
||||
}
|
||||
}
|
||||
let begin = chrono::Local::now();
|
||||
let mut base_path = path.as_ref().to_path_buf();
|
||||
info!("Rebuilding site at: {:?}", base_path);
|
||||
base_path.push("content");
|
||||
let mut publish_path = path.as_ref().to_path_buf();
|
||||
publish_path.push("public");
|
||||
|
|
@ -43,10 +46,10 @@ pub fn watch(event: Event, path: impl AsRef<Path>) -> Result<(), Error> {
|
|||
let end = chrono::Local::now();
|
||||
let elapsed = end - begin;
|
||||
info!(
|
||||
"Time to build: {:?} minutes, {:?} seconds, and {:?} nanoseconds",
|
||||
"Time to build: {:?} minutes, {:?} seconds, and {:?} milliseconds",
|
||||
elapsed.num_minutes(),
|
||||
elapsed.num_seconds(),
|
||||
elapsed.num_nanoseconds()
|
||||
elapsed.subsec_millis()
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue