Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 124 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ authors = ["Tnixc <tnixxc@gmail.com>"]
color-print = "0.3.6"
comrak = "0.26.0"
fancy-regex = "0.13.0"
katex = "0.4"
minify-html = "0.15.0"
notify = "6.1.1"
num_cpus = "1.16.0"
Expand All @@ -22,6 +23,6 @@ serde_json = "1.0.120"
simple-websockets = "0.1.6"

[[bin]]
name = "replacer"
name = "simple"
path = "src/main.rs"

11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Simple Build tool

> [!WARNING]
> Probably very buggy, it's very opiniated and not extensible.
> [!WARNING]
> Probably very buggy, it's very opinionated and not extensible.

A simple build tool that assembles a static site from components, templates, and
data. I used it to build v6 of https://enochlau.com
Expand All @@ -25,10 +25,6 @@ data. I used it to build v6 of https://enochlau.com

- [ ] Improve JSON parsing error handling

### Markdown and Content

- [ ] LaTex?

### Errors/Logging

- [ ] Exact file and line in error messages
Expand All @@ -44,6 +40,7 @@ data. I used it to build v6 of https://enochlau.com

### Done

- [x] KaTeX support
- [x] Handle port collisions in dev server
- [x] Resolve dual sources of truth for Markdown frontmatter in blog posts (can't fix without proper Markdown parsing into entries)
- [x] Bi-directional editing: You can now double click on a rendered `<markdown>` element to edit it, and it's reflected in the source code.
Expand Down Expand Up @@ -189,7 +186,7 @@ Will render out to:
<img src="image.webp" alt="alt" />
```

> [!NOTE]
> [!NOTE]
> You can double click on a rendered markdown element and edit it from the web. The changes will be reflected in the source file. It is a bit flakely with escaped html entities, so try to avoid using those.

### Template entries
Expand Down
18 changes: 18 additions & 0 deletions src/handlers/entries.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::dev::{SCRIPT, WS_PORT};
use crate::error::{ErrorType, ProcessError, WithItem};
use crate::handlers::katex_assets;
use crate::handlers::pages::page;
use crate::utils::kv_replace;
use crate::IS_DEV;
Expand All @@ -16,6 +17,9 @@ pub fn process_entry(
let mut errors: Vec<ProcessError> = Vec::new();
let is_dev = *IS_DEV.get().unwrap();

// Reset KaTeX usage flag for this page
katex_assets::reset_katex_flag();

if entry_path.is_empty() || result_path.is_empty() {
return vec![ProcessError {
error_type: ErrorType::Other,
Expand Down Expand Up @@ -91,6 +95,20 @@ pub fn process_entry(

let mut s = page_result.output;

// Inject KaTeX CSS if math was rendered (unless disabled)
if katex_assets::was_katex_used() && !katex_assets::is_katex_injection_disabled() {
// Print message once
katex_assets::print_katex_message();

// Inject CSS link in <head>
if s.contains("<head>") {
s = s.replace("<head>", &format!("<head>\n{}", katex_assets::get_katex_css_tag()));
} else {
// If no <head> tag, prepend to document
s = format!("{}\n{}", katex_assets::get_katex_css_tag(), s);
}
}

if is_dev && !s.contains("// * SCRIPT INCLUDED IN DEV MODE") {
s = s.replace("<head>", &format!("<head>{}", SCRIPT));
s = s.replace(
Expand Down
38 changes: 38 additions & 0 deletions src/handlers/katex_assets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use once_cell::sync::Lazy;
use std::env;
use std::sync::atomic::{AtomicBool, Ordering};

// Track if KaTeX was used in the current page (thread-local)
thread_local! {
static KATEX_USED: AtomicBool = const { AtomicBool::new(false) };
}

// Track if we've printed the KaTeX message (global, one-time)
static MESSAGE_PRINTED: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));

pub fn mark_katex_used() {
KATEX_USED.with(|used| used.store(true, Ordering::Relaxed));
}

pub fn was_katex_used() -> bool {
KATEX_USED.with(|used| used.load(Ordering::Relaxed))
}

pub fn reset_katex_flag() {
KATEX_USED.with(|used| used.store(false, Ordering::Relaxed));
}

pub fn print_katex_message() {
if !MESSAGE_PRINTED.swap(true, Ordering::Relaxed) {
println!(" 📐 KaTeX CSS will be injected (using CDN)");
}
}

pub fn is_katex_injection_disabled() -> bool {
env::var("SIMPLE_DISABLE_KATEX_CSS").is_ok()
}

pub fn get_katex_css_tag() -> &'static str {
r#"<!-- KaTeX CSS (auto-injected from CDN) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">"#
}
Loading