diff --git a/crates/nuwiki-core/src/render/html.rs b/crates/nuwiki-core/src/render/html.rs index 7c404bf..8dafd35 100644 --- a/crates/nuwiki-core/src/render/html.rs +++ b/crates/nuwiki-core/src/render/html.rs @@ -11,6 +11,11 @@ //! `{{date}}`, `{{root_path}}`, `{{toc}}`). Order: `{{content}}` is //! substituted first so a body that happens to contain a literal //! `{{title}}` isn't itself rewritten in the next pass. +//! +//! Both delimiter styles are recognised for every placeholder: nuwiki's +//! native `{{key}}` and vimwiki's `%key%` (`%title%`, `%content%`, +//! `%root_path%`, `%date%`, `%wiki_css%`, …). This lets stock vimwiki +//! templates render unchanged. use std::collections::HashMap; use std::io::{self, Write}; @@ -107,14 +112,17 @@ impl Renderer for HtmlRenderer { let body_str = std::str::from_utf8(&body) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; let title = doc.metadata.title.as_deref().unwrap_or(""); - // Replace `{{content}}` first so its substituted body, which may - // legitimately contain the literal `{{title}}`, isn't itself - // rewritten in the next pass. + // Substitute `content` before `title` so a body that legitimately + // contains a literal title placeholder isn't rewritten. Both the + // native `{{key}}` and vimwiki's `%key%` delimiters are accepted so + // stock vimwiki templates render unchanged. let mut out = template.replace("{{content}}", body_str); + out = out.replace("%content%", body_str); out = out.replace("{{title}}", title); + out = out.replace("%title%", title); for (k, v) in &self.vars { - let needle = format!("{{{{{k}}}}}"); - out = out.replace(&needle, v); + out = out.replace(&format!("{{{{{k}}}}}"), v); + out = out.replace(&format!("%{k}%"), v); } w.write_all(out.as_bytes())?; } else { @@ -239,18 +247,20 @@ impl HtmlRenderer { fn render_list_item(&self, n: &ListItemNode, w: &mut dyn Write) -> io::Result<()> { match n.checkbox { Some(state) => { - let (checked, class) = match state { - CheckboxState::Empty => ("", "task-empty"), - CheckboxState::Quarter => ("", "task-quarter"), - CheckboxState::Half => ("", "task-half"), - CheckboxState::ThreeQuarters => ("", "task-three-quarters"), - CheckboxState::Done => (" checked", "task-done"), - CheckboxState::Rejected => ("", "task-rejected"), + // vimwiki-compatible checkbox classes: `[ ]`→done0, `[.]`→done1, + // `[o]`→done2, `[O]`→done3, `[X]`→done4, `[-]`→rejected. The + // checkbox glyph/progress fill is drawn entirely by the + // stylesheet (`li.doneN::before`); vimwiki emits no ``, + // so neither do we — an input would double-render against it. + let class = match state { + CheckboxState::Empty => "done0", + CheckboxState::Quarter => "done1", + CheckboxState::Half => "done2", + CheckboxState::ThreeQuarters => "done3", + CheckboxState::Done => "done4", + CheckboxState::Rejected => "rejected", }; - write!( - w, - "
  • " - )?; + write!(w, "
  • ")?; } None => w.write_all(b"
  • ")?, } diff --git a/crates/nuwiki-core/tests/html_renderer.rs b/crates/nuwiki-core/tests/html_renderer.rs index 24d23d1..9f9110e 100644 --- a/crates/nuwiki-core/tests/html_renderer.rs +++ b/crates/nuwiki-core/tests/html_renderer.rs @@ -112,9 +112,23 @@ fn math_block_emits_div() { fn unordered_list_with_checkbox() { let out = render("- [X] done\n- not done\n"); assert!(out.contains("