From a48b84ed821e3fa3baa54fb3cbc349ab0c97ed99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98ystein=20S=C3=B8rensen?= Date: Tue, 15 Sep 2026 13:06:11 +0000 Subject: [PATCH] Fix pseudocode rendering in HTML/revealjs output pandoc.Div(source_code) was called with a plain Lua string, which Pandoc treats as prose and collapses all whitespace (newlines, indentation) to single spaces before the HTML writer emits it. Wrap the source in pandoc.RawBlock("html", ...) instead (with minimal HTML-entity escaping) so the exact source text reaches pseudocode.js unchanged. pseudocode.js also resolves its math backend (KaTeX or MathJax) by checking for the global `katex`/`MathJax` identifiers at the moment pseudocode.renderElement() runs. In a revealjs presentation, KaTeX/MathJax is loaded asynchronously by reveal.js's own math plugin (often from a CDN), so rendering immediately can race that load and fail with "No math backend found. Please setup KaTeX or MathJax." Poll briefly for a backend to appear before rendering, and also re-render on Reveal's "ready"/"slidechanged" events (the same pattern reveal.js's bundled MathJax/KaTeX plugins use), surfacing any remaining JS error on the slide instead of failing silently. Also add examples/revealjs/revealjs.qmd, since there was previously no example exercising the extension in a revealjs presentation, and link it from the README. --- README.md | 1 + _extensions/pseudocode/pseudocode.lua | 90 +++++++++++++++++++++------ examples/revealjs/_extensions | 1 + examples/revealjs/revealjs.qmd | 44 +++++++++++++ 4 files changed, 118 insertions(+), 18 deletions(-) create mode 120000 examples/revealjs/_extensions create mode 100644 examples/revealjs/revealjs.qmd diff --git a/README.md b/README.md index 9e90574..22b95f5 100644 --- a/README.md +++ b/README.md @@ -306,6 +306,7 @@ More examples please refer: 2. Book document (HTML and PDF): [examples/book](examples/book). 3. Beamer document (PDF): [examples/beamer](examples/beamer). 4. Cross reference example (HTML and PDF): [examples/cross-reference](examples/cross-reference). +5. Presentation document (revealjs): [examples/revealjs](examples/revealjs). ## License diff --git a/_extensions/pseudocode/pseudocode.lua b/_extensions/pseudocode/pseudocode.lua index 50735b0..3b9bd79 100644 --- a/_extensions/pseudocode/pseudocode.lua +++ b/_extensions/pseudocode/pseudocode.lua @@ -24,21 +24,7 @@ local function ensure_html_deps() [[ ]] @@ -124,6 +171,13 @@ local function extract_source_code_options(source_code, render_type) return options, table.concat(source_codes, "\n") end +local function html_escape(s) + s = string.gsub(s, "&", "&") + s = string.gsub(s, "<", "<") + s = string.gsub(s, ">", ">") + return s +end + local function render_pseudocode_block_html(global_options) ensure_html_deps() @@ -174,8 +228,8 @@ local function render_pseudocode_block_html(global_options) data_options[data_k] = v end end - - local inner_el = pandoc.Div(source_code) + + local inner_el = pandoc.Div(pandoc.RawBlock("html", html_escape(source_code))) inner_el.attr.classes = pandoc.List() inner_el.attr.classes:insert("pseudocode") diff --git a/examples/revealjs/_extensions b/examples/revealjs/_extensions new file mode 120000 index 0000000..74119e3 --- /dev/null +++ b/examples/revealjs/_extensions @@ -0,0 +1 @@ +../../_extensions \ No newline at end of file diff --git a/examples/revealjs/revealjs.qmd b/examples/revealjs/revealjs.qmd new file mode 100644 index 0000000..4b6bb40 --- /dev/null +++ b/examples/revealjs/revealjs.qmd @@ -0,0 +1,44 @@ +--- +title: "Quarto Pseudocode Extension - revealjs Example" +filters: + - pseudocode +format: revealjs +--- + +## Introduction + +This slide comes before the algorithm slide, so the pseudocode block +below is not on the first slide of the deck when the presentation loads. + +## Quicksort + +@algo-quicksort shows the classic in-place Quicksort algorithm. + +```pseudocode +#| label: algo-quicksort + +\begin{algorithm} +\caption{Quicksort} +\begin{algorithmic} +\Procedure{Quicksort}{$A, p, r$} + \If{$p < r$} + \State $q = $ \Call{Partition}{$A, p, r$} + \State \Call{Quicksort}{$A, p, q - 1$} + \State \Call{Quicksort}{$A, q + 1, r$} + \EndIf +\EndProcedure +\Procedure{Partition}{$A, p, r$} + \State $x = A[r]$ + \State $i = p - 1$ + \For{$j = p$ \To $r - 1$} + \If{$A[j] < x$} + \State $i = i + 1$ + \State exchange $A[i]$ with $A[j]$ + \EndIf + \EndFor + \State exchange $A[i + 1]$ with $A[r]$ + \Return $i + 1$ +\EndProcedure +\end{algorithmic} +\end{algorithm} +```