Expand description
GFM markdown, parsed into a serializable node tree instead of HTML.
The web UI’s one hard rule is that DOM is built with createElement and
textContent and never with innerHTML — an AI-authored chat reply, a
question’s reasoning, and an operator’s task instruction are all arbitrary
text, and any of them could contain a <script> tag. That rule used to
force the front end into assets/ui/app.js’s own tiny hand-rolled
markdown reader, which understood four constructs and left everything
else — tables, task lists, links — as literal asterisks and brackets.
This module moves the actual parsing to comrak, a full GFM
implementation, and hands the client a tree of Node instead of a
string of HTML. The client walks the tree and builds elements directly;
there is never a markup string to insert, so the no-innerHTML rule holds
even though the markdown support is now complete.
Two things are deliberately stricter than the source markdown, both because this tree can carry attacker-authored text (an AI writes chat turns and question detail) into a browser with no server-side sanitizer standing between them:
- [
normalize_link] keeps onlyhttp:/https:link destinations. - [
normalize_image] keeps onlydata:image URIs and, when the markdown came from a question, relative filenames resolved against that question’s existing sandboxed panel asset route (seeImageBase::QuestionPanel).
Raw HTML in the source (a <script> block, an <img onerror=…>) is never
interpreted: to_nodes turns it into a Node::Text carrying the
literal characters, so a client that renders it with textContent shows
the tag rather than running it.
Structs§
- Table
Cell - One cell of a
Node::Tablerow.
Enums§
- Align
- Column alignment of a table cell, per the GFM table extension.
- Image
Base - How a relative image path in the source markdown is allowed to resolve.
- Node
- One node of parsed markdown.
Functions§
- to_
nodes - Parse
textas GFM markdown into a node tree.