Add markdown rendering for LLM output

This commit introduces a new module `analyze::render` to handle the
rendering of Markdown content produced by the LLM into safe HTML.

The LLM output now includes a custom `==text==` highlighting convention
to indicate sections that require doctor review due to potential
transcription errors or incomplete information. This highlighting is
converted into `<mark>` tags in the final HTML.

To ensure security, all LLM-generated Markdown is first HTML-escaped.
This prevents any malicious HTML or script injection from being executed
in the browser. Only the custom `<mark>` tags are preserved as
functional HTML elements.

The process is as follows:
1.  The raw Markdown from the LLM is processed.
2.  All HTML special characters (`<`, `>`, `&`, `"`, `'`) are escaped.
3.  The `==text==` highlights are replaced with `<mark>text</mark>`.
4.  The resulting string is parsed as Markdown by `pulldown-cmark`.
5.  The parsed Markdown is converted to HTML, which is then safe to
    inject into the Askama template using the `|safe` filter.

The `Cargo.toml` and `Cargo.lock` files have been updated to include the
`pulldown-cmark` dependency. The `document.html` template has been
modified to use a `div` with the class `doc-content` instead of a `pre`
tag, allowing the rendered HTML to be displayed correctly. The
`handle_document_view` function now calls the new `md_to_html` rendering
function.
This commit is contained in:
2026-04-16 16:55:20 +02:00
parent 44ed5e8333
commit 07f9d9ed26
7 changed files with 212 additions and 5 deletions
+20 -1
View File
@@ -339,6 +339,7 @@ dependencies = [
"axum-extra",
"bcrypt",
"dotenvy",
"pulldown-cmark",
"rand 0.8.5",
"reqwest",
"rpassword",
@@ -1150,6 +1151,24 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "pulldown-cmark"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad"
dependencies = [
"bitflags",
"memchr",
"pulldown-cmark-escape",
"unicase",
]
[[package]]
name = "pulldown-cmark-escape"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
[[package]]
name = "quinn"
version = "0.11.9"
@@ -1202,7 +1221,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]