Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
35 lines
1.4 KiB
Go
35 lines
1.4 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
|
|
|
package markdown
|
|
|
|
import (
|
|
stdhtml "html"
|
|
"regexp"
|
|
|
|
"sourcedock.dev/petrbalvin/scriptorium"
|
|
)
|
|
|
|
// mermaidBlockRe matches the fenced mermaid blocks the renderer writes.
|
|
// The diagram source arrives HTML-escaped, as code content always does.
|
|
var mermaidBlockRe = regexp.MustCompile(`(?s)<pre><code class="language-mermaid">(.*?)</code></pre>`)
|
|
|
|
// renderDiagrams replaces every fenced mermaid block with the SVG
|
|
// scriptorium draws from it, wrapped so a style sheet can tell diagrams
|
|
// from prose. It runs on sanitised HTML: the SVG is machine-drawn output
|
|
// whose vocabulary the library itself bounds, and the sanitiser's
|
|
// HTML-only parser would corrupt its case-sensitive attributes. A
|
|
// diagram the library does not carry, or a line it cannot parse, keeps
|
|
// its code block: the author sees the source that was not understood,
|
|
// and the reader never a half-drawn figure.
|
|
func renderDiagrams(html string) string {
|
|
return mermaidBlockRe.ReplaceAllStringFunc(html, func(block string) string {
|
|
src := stdhtml.UnescapeString(mermaidBlockRe.FindStringSubmatch(block)[1])
|
|
svg, err := scriptorium.RenderDiagram([]byte(src))
|
|
if err != nil {
|
|
return block
|
|
}
|
|
return `<div class="diagram">` + "\n" + string(svg) + "\n</div>"
|
|
})
|
|
}
|