Make the thing

This commit is contained in:
Astatin3
2024-08-03 20:59:56 -06:00
parent 6d335998dd
commit cfc48679fe
3 changed files with 139 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "markdown"
version = "0.1.0"
edition = "2021"
[dependencies]
notify = "6.1.1"
blocking = "1.6.1"
failure = "0.1.8"
hotwatch = "0.5.0"
time = "0.3.36"
rocket = { version = "0.5.1", features = ["json"] }
serde = { version = "1.0.204", features = ["derive"] }
[[bin]]
name = "markdown"
path = "src/main.rs"
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>File Content</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.6.1/github-markdown-dark.min.css" integrity="sha512-mzPe5Bxap921sKCNI3lXEi5FxCue4M1Ei65ZVFi1UdCMnr4+BFOpBuWnfpJ8WLBxvyhf7z45Jsa5jWiseE57rg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body style="margin: 0">
<pre id="content" class="markdown-body"></pre>
<script type="module">
import markdownit from 'https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/+esm'
import mdk from 'https://cdn.jsdelivr.net/npm/markdown-it-katex@2.0.3/+esm'
const md = markdownit({
html: true,
linkify: true,
typographer: true
})
md.use(mdk)
const content = document.getElementById('content');
fetch('/content')
.then(response => response.text())
.then(data => content.innerHTML = md.render(data));
const evtSource = new EventSource("/events");
evtSource.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log(data);
content.innerHTML = md.render(data.content);
}
</script>
</body>
</html>
+84
View File
@@ -0,0 +1,84 @@
use core::time::Duration;
use std::{env, process};
use std::ffi::OsStr;
use hotwatch::{Hotwatch};
use rocket::{State, Shutdown};
use rocket::fs::NamedFile;
use rocket::response::stream::{Event as SSEvent, EventStream};
use rocket::serde::Serialize;
use rocket::tokio::sync::broadcast::{channel, Sender};
use rocket::tokio::select;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use time::Error;
#[macro_use] extern crate rocket;
#[derive(Debug, Clone, Serialize)]
#[serde(crate = "rocket::serde")]
struct FileChange {
content: String,
}
#[get("/")]
async fn index() -> NamedFile {
NamedFile::open("index.html").await.unwrap()
}
#[get("/content")]
async fn content(file_content: &State<Arc<Mutex<String>>>) -> String {
file_content.lock().unwrap().clone()
}
#[get("/events")]
async fn events(queue: &State<Sender<FileChange>>, mut end: Shutdown) -> EventStream![] {
let mut rx = queue.subscribe();
EventStream! {
loop {
let msg = select! {
msg = rx.recv() => match msg {
Ok(msg) => msg,
Err(_) => break,
},
_ = &mut end => break,
};
yield SSEvent::json(&msg);
}
}
}
#[launch]
fn rocket() -> _ {
let file_path = Path::new("/tmp/file.md");
let file_content = Arc::new(Mutex::new(std::fs::read_to_string(file_path).unwrap()));
let file_content_clone = Arc::clone(&file_content);
let (tx, _) = channel::<FileChange>(1024);
let tx_clone = tx.clone();
std::thread::spawn(move || {
let mut watch = Hotwatch::new().unwrap();
watch.watch(file_path, move |_| {
let content = std::fs::read_to_string(file_path).unwrap();
*file_content_clone.lock().unwrap() = content.clone();
let _ = tx_clone.send(FileChange { content });
std::thread::sleep(Duration::from_secs(1));
}).unwrap();
loop { // IDK how to sleep forever
std::thread::sleep(Duration::from_secs(9223372036854775807));
}
});
rocket::build()
.manage(tx)
.manage(file_content)
.mount("/", routes![index, content, events])
}