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
34
Cargo.lock
generated
34
Cargo.lock
generated
|
|
@ -488,6 +488,15 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file-id"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1fc6a637b6dc58414714eddd9170ff187ecb0933d4c7024d1abbd23a3cc26e9"
|
||||
dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
|
|
@ -1044,6 +1053,19 @@ dependencies = [
|
|||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-debouncer-full"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c02b49179cfebc9932238d04d6079912d26de0379328872846118a0fa0dbb302"
|
||||
dependencies = [
|
||||
"file-id",
|
||||
"log",
|
||||
"notify",
|
||||
"notify-types",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-types"
|
||||
version = "2.1.0"
|
||||
|
|
@ -1159,7 +1181,7 @@ dependencies = [
|
|||
"jetscii",
|
||||
"lazy_static",
|
||||
"miette",
|
||||
"notify",
|
||||
"notify-debouncer-full",
|
||||
"orgize",
|
||||
"pretty_assertions",
|
||||
"rayon",
|
||||
|
|
@ -1608,7 +1630,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||
[[package]]
|
||||
name = "steel-core"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#b3ae8b95d8fc0a2eef13c7f618abe4fcd5e3b1f7"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#657eb333cfc50c6cfa2c1a39546789e5eca741d0"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"bigdecimal",
|
||||
|
|
@ -1660,7 +1682,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-derive"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#b3ae8b95d8fc0a2eef13c7f618abe4fcd5e3b1f7"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#657eb333cfc50c6cfa2c1a39546789e5eca741d0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -1670,7 +1692,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-gen"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#b3ae8b95d8fc0a2eef13c7f618abe4fcd5e3b1f7"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#657eb333cfc50c6cfa2c1a39546789e5eca741d0"
|
||||
dependencies = [
|
||||
"codegen",
|
||||
"serde",
|
||||
|
|
@ -1679,7 +1701,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-parser"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#b3ae8b95d8fc0a2eef13c7f618abe4fcd5e3b1f7"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#657eb333cfc50c6cfa2c1a39546789e5eca741d0"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"dashmap",
|
||||
|
|
@ -1700,7 +1722,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-quickscope"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#b3ae8b95d8fc0a2eef13c7f618abe4fcd5e3b1f7"
|
||||
source = "git+https://github.com/mattwparas/steel.git?branch=master#657eb333cfc50c6cfa2c1a39546789e5eca741d0"
|
||||
dependencies = [
|
||||
"indexmap 2.13.0",
|
||||
"smallvec",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "chrono", "
|
|||
orgize = { git="https://git.tfcconnection.org/chris/orgize", branch = "v0.11", features = ["chrono", "indexmap", "tracing"] }
|
||||
steel-core = { git="https://github.com/mattwparas/steel.git", branch = "master" }
|
||||
chrono = "0.4.44"
|
||||
notify = "8.2.0"
|
||||
notify-debouncer-full = "0.7.0"
|
||||
walkdir = "2.5.0"
|
||||
jetscii = "0.5.3"
|
||||
lazy_static = "1.5.0"
|
||||
|
|
|
|||
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