|
|
@@ -318,7 +318,39 @@ The attribute `stm-html` binds the element's `innerHTML` to the specified state
|
|
|
|
|
|
## Markdown binding
|
|
|
|
|
|
-The attribute `stm-markdown` renders a state value as **safe markdown**: all HTML in the source is escaped first, then markdown formatting (headings, bold, italic, inline code, fenced code blocks, links, lists, blockquotes, horizontal rules, paragraphs) is applied. This is safe for untrusted user input — no raw HTML can be injected.
|
|
|
+The attribute `stm-markdown` renders a state value as **CommonMark** (the unambiguous Markdown specification, version 0.31.2), converted to safe HTML. For example `<div stm-markdown="post.body">`.
|
|
|
+
|
|
|
+The renderer is a two-pass CommonMark engine: block structure is computed over the whole document first, then inline content is parsed inside the leaf blocks. That is what makes the constructs below work across line wraps — the thing naive line-by-line renderers get wrong.
|
|
|
+
|
|
|
+### Block structure
|
|
|
+
|
|
|
+- **Paragraphs** break only on a *blank* line. A single newline inside a paragraph is a *soft line break*: the text simply continues (rendered as a newline, not a new paragraph and not a `<br>`). Source that was hard-wrapped at 80 columns therefore renders as one flowing paragraph.
|
|
|
+- **Emphasis and strong emphasis** (`*`/`_`, `**`/`__`, `***`, nesting) are resolved with the CommonMark delimiter-run algorithm, so a span may cross a line wrap — `**bold text` + newline + `that wraps**` is a single `<strong>` — and intraword emphasis (`foo*bar*baz`) follows the spec.
|
|
|
+- **Headings**: ATX (`# Heading`, with closing `#`s trimmed) and setext (a paragraph followed by a line of `=` or `-`).
|
|
|
+- **Lists**: ordered and bullet, with the spec's tight/loose rendering (a blank line between items makes a loose list whose items are wrapped in `<p>`), nesting, items that continue over multiple lines (a wrapped line stays inside its `<li>`), and item-indent code blocks.
|
|
|
+- **Block quotes** (`>`), including lazy continuation: a plain paragraph line following an open quote continues it.
|
|
|
+- **Code blocks**: indented (4 spaces) and fenced with `` ``` `` or `~~~`, optionally with an info string — `` ```html `` names the block, emitted as `<code class="language-html">`.
|
|
|
+- **Thematic breaks**: `---`, `***` or `___` render as `<hr>`.
|
|
|
+- **Link reference definitions** (`[label]: /url "title"`) are consumed and used by full (`[label][label]`), collapsed (`[label][]`) and shortcut (`[label]`) links anywhere in the document.
|
|
|
+
|
|
|
+### Inline content
|
|
|
+
|
|
|
+- Code spans (`` `code` ``), with backtick-count matching and leading/trailing space stripping.
|
|
|
+- Links and images — inline `[text](/url "title")` and the reference forms above — with titles.
|
|
|
+- Autolinks: `<https://example.com>` and `<mail@example.com>` (bare emails become `mailto:` links).
|
|
|
+- **Hard line breaks**: two or more trailing spaces, or a trailing backslash. A soft break (single newline) is deliberately *not* turned into a `<br>`.
|
|
|
+- Backslash escapes for ASCII punctuation (`\*` is a literal `*`).
|
|
|
+- Entity references: named (`©`, `½` — the WHATWG entity table), decimal (`©`) and hex (`©`).
|
|
|
+
|
|
|
+### Security posture
|
|
|
+
|
|
|
+The markdown source is untrusted text and is rendered with an **escape-first** posture:
|
|
|
+
|
|
|
+- **Raw HTML never becomes markup.** Inline HTML (for example `<script>alert(1)</script>`) and HTML-block constructs render as escaped *text*. This is the one intentional divergence from the CommonMark reference output, which passes raw HTML through.
|
|
|
+- **Link and image destinations are scheme-filtered**: relative URLs and the `http`, `https`, `mailto` and `ftp` schemes pass through; any other scheme (`javascript:`, `data:`, `vbscript:` …) keeps its link text but the `href`/`src` is replaced with `#`.
|
|
|
+- Tables, strikethrough (`~~x~~`) and task lists are not supported — they are extensions, not CommonMark.
|
|
|
+
|
|
|
+Conformance is verified against the official CommonMark 0.31.2 example suite by `tests/markdown/run.sh` (see *Getting started* for how to run it).
|
|
|
|
|
|
## Header demotion
|
|
|
|