This page exercises html-revisor. Click anything to leave a directive on it.
The design decisions for scopes and markdown editing. Each links to the cases below that show it.
| question | answer | see |
|---|---|---|
| Editing notation | Markdown. | A1 |
| What can you pick to edit or direct? | Any block: a section, a list, one item, a table, one cell, an svg text label. Each edits its whole content as markdown. | A1, C1, C6, D6 |
| Inline elements: hover and directives? |
Per element. a and img: yes. strong: no, it belongs to its block. span: yes, edited as its content, its tag kept; not inside a pre, where spans are highlighting, and not one that fills its parent, which it would hide.
|
B2, D2, E1, E2 |
| Headings |
# inside a bigger scope; picked alone, only the text.
|
A3 |
Line breaks and |
A <br> is a newline. U+00A0 shows as the character.
|
A4, A5 |
| Lists |
Markdown - lines, nested lists indented. Add and delete items by editing. A list holding paragraphs or tables: pick the inner blocks too.
|
C1, C2, C3 |
| Code blocks |
A fenced block: backticks for <pre><code>, tildes for a bare <pre>. A pre holding markup (highlighting) is HTML, so its spans survive.
|
C11, D3 |
| Text beside blocks | Paragraphs in the enclosing scope's markdown: text, list, text edits as one. Text saved unchanged stays bare. | C9, C10, F3 |
| Tables | A table with a header row of plain cells is a markdown table; otherwise HTML. Each cell is a scope too. | C6, D4 |
| What markdown can't say |
Stays as inline HTML (kbd, span class, a target). Inside a bigger scope, a block with attributes is HTML too, inner markup and all, since markdown isn't read inside an HTML block.
|
B1, B2, B3, C4, C8 |
| Images |
; saving takes the other attributes from the original.
|
D2 |
| What isn't text |
A stand-in: ⟦svg⟧, ⟦script⟧, restored in order from the prior HTML. A literal ⟦ is \⟦. Hidden elements get stand-ins too, so a save keeps them, and inside HTML the markdown writes, a style's blank lines can't end the HTML block. There, a literal ⟦ is ⟦, and a stand-in takes the next of its kind.
|
D1, D5, D7 |
| Writing markdown | Rules make it readable; each block and run of phrasing is checked against the parser, and written as HTML where it wouldn't come back the same. The round-trip holds by construction. | A2, B4 |
Unlikely shapes in HTML ⇄ markdown (empty paragraphs, dl, stat tiles)
|
May be ugly. Spend effort on the shapes agents write. | C4, E1, F1 |
| Where markdown converts |
On the server, where scopes.mjs and linkedom run; the client stays small. No live preview.
|
|
| Parser and writer |
markdown-it parses. The writer is our own, in scopes.mjs, because it carries the rules in this table; a general HTML-to-markdown library would need each one overridden.
|
Directives, the open box, and the conflict check find elements by ID. A markdown save rebuilds the HTML of its scope, so a save has to say which new element is which old one.
| question | answer | see |
|---|---|---|
| Where does an element's ID live? |
In the file, as data-hrv. An edit that adds or removes elements shifts a tree path or an index; an ID in the file stays put.
|
|
| What kind of ID? |
A counter, for short IDs, with its high-water mark in <html data-hrv-next>. Never reused; an ID lasts as long as its element. Copies of one ID all get fresh ones.
|
|
| Who assigns them? | The formatter, on every GET and first thing on every PUT. Agents leave both attributes alone; an element they add gets its ID on the next load. | |
| Saves and conflicts | One change per save, checked against the base of its own element. A change elsewhere in the file brings a notice and the save goes through. A conflict means turn-taking broke: the save fails with an error that suggests a reload. | |
| IDs after a markdown save | Reconciled against the prior HTML. Siblings pair the way a diff does: the ones that came back the same, then, between those, the most alike with the same tag. An edited element keeps its ID, a moved one keeps its own, and a new one gets a fresh ID from the formatter. A pair's children pair the same way. | C1 |
| Directives across a markdown save | Each rides to its element's partner, in order. The markdown doesn't show them. | |
| A directive whose element a markdown save deleted? | Goes with it. | |
| IDs on a page leaving the tool | A cleanup script strips them and the directives, the formatter in reverse, and the commits get squashed. |
Click any block to edit it: the box shows its content as markdown.
This one has bold and emphasis inside; the box shows them as **bold** and *emphasis*. The bold word belongs to its paragraph: click it and you get the paragraph.
Entities survive editing: Fish & chips <tasty> cost $5.
A plain click on this link opens the directive box; ⌘-click navigates.
code insideA super-basic, well-formed table with no html attributes.
| Component | Status |
|---|---|
| Server | Done |
| Client | In progress |
preformatted text
keeps its spacing
Cards are wrappers: clicking the margin inside the card opens the directive box for the card itself.
A scope is any block you can pick: you leave a directive on it, or edit its whole content as markdown. Each case has the same four parts: its name, the question it asks in grey, the example HTML in a dashed box, and a table of the scopes the example would make. Disagree with a row? Leave a directive on it.
Under each example: its HTML (click to open), then a row for each element you could pick, nested inside the element that holds it. The last column is the markdown you would edit if you picked that element. ⟦svg⟧ marks something that isn't text riding inside the markdown.
The baseline: one scope, edits as plain text.
The formatter moves out of the server and runs on its own.
<p>The formatter moves out of the server and runs on its own.</p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
The formatter moves out of the server and runs on its own. |
One scope. Markdown: **bold**, *em*, `code`, [link](…).
Run npm test, then read every failure, especially the first one.
<p> Run <code>npm test</code>, then read <strong>every</strong> failure, <em>especially</em> the <a href="#scopes">first one</a>. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
Run `npm test`, then read **every** failure, *especially* the [first one](#scopes). |
| <a> | all markdown |
[first one](#scopes) |
A heading is its own scope. Does the markdown include the #, or is that the element's business?
normalize into formatter.mjs<h3>Moving <code>normalize</code> into <em>formatter.mjs</em></h3>
| element | what markdown can say | what you would edit |
|---|---|---|
| <h3> | all markdown |
Moving `normalize` into *formatter.mjs* |
A <br> becomes a trailing backslash or two spaces in markdown. Which round-trips?
Jess Kerr
html-revisor
October 2026
<p>Jess Kerr<br>html-revisor<br>October 2026</p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
Jess Kerr html-revisor October 2026 |
Markdown has no . Does the field show a real U+00A0, or the entity?
Fish & chips cost $5 <each> — “quoted” and 5 × 3.
<p> Fish & chips cost $5 <each> — “quoted” and 5 × 3. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
Fish & chips cost $5 <each> — “quoted” and 5 × 3. |
These pass through as raw HTML in the markdown. Is that readable enough to edit?
Press ⌘+↵ to save. H2O, x2, highlighted, removed added, struck, DDD, a quote
, , fine print, underlined.
<p> Press <kbd>⌘</kbd>+<kbd>↵</kbd> to save. H<sub>2</sub>O, x<sup>2</sup>, <mark>highlighted</mark>, <del>removed</del> <ins>added</ins>, <s>struck</s>, <abbr title="Domain-Driven Design">DDD</abbr>, <q>a quote</q>, <time datetime="2026-10-12">today</time>, <small>fine print</small>, <u>underlined</u>. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with HTML |
Press <kbd>⌘</kbd>+<kbd>↵</kbd> to save. H<sub>2</sub>O, x<sup>2</sup>, <mark>highlighted</mark>, <del>removed</del> <ins>added</ins>, <s>struck</s>, <abbr title="Domain-Driven Design">DDD</abbr>, <q>a quote</q>, <time datetime="2026-10-12">today</time>, <small>fine print</small>, <u>underlined</u>. |
Markdown links carry href and title only. Where do class, target, style go?
See the section and a warning-colored word.
<p> See <a href="#scopes" title="this section" target="_blank" class="ref">the section</a> and a <span style="color: #bc4c00">warning-colored</span> word. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with HTML |
See <a href="#scopes" title="this section" target="_blank" class="ref">the section</a> and a <span style="color: #bc4c00">warning-colored</span> word. |
| <a.ref> | markdown with HTML |
<a href="#scopes" title="this section" target="_blank" class="ref">the section</a> |
| <span> | all markdown |
warning-colored |
PLAN.html does this with yak ids. Raw HTML in the markdown, or a token the editor protects?
Split out the formatter stez, then decide scopes a17m.
<p> Split out the formatter <span class="pill">stez</span>, then decide scopes <span class="pill">a17m</span>. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with HTML |
Split out the formatter <span class="pill">stez</span>, then decide scopes <span class="pill">a17m</span>. |
| <span.pill> | all markdown |
stez |
| <span.pill> | all markdown |
a17m |
Markdown has one syntax for each pair. The formatter makes them canonical; does anyone mind?
b and strong; i and em.
<p> <strong>b</strong> and <strong>strong</strong>; <em>i</em> and <em>em</em>. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
**b** and **strong**; *i* and *em*. |
A sup around a link: two nested raw tags, or one markdown link inside raw sup?
Linkedom skips the skeleton.1
<p> Linkedom skips the skeleton.<sup><a href="#fn1">1</a></sup> </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with HTML |
Linkedom skips the skeleton.<sup>[1](#fn1)</sup> |
| <a> | all markdown |
[1](#fn1) |
One scope (edit as - item lines, add and remove items) or one per <li>?
<ul> <li>Formatter</li> <li>Scopes with <strong>bold</strong></li> <li>Round-trip</li> </ul>
| element | what markdown can say | what you would edit |
|---|---|---|
| <ul> | all markdown |
- Formatter - Scopes with **bold** - Round-trip |
| <li> | all markdown |
Formatter |
| <li> | all markdown |
Scopes with **bold** |
| <li> | all markdown |
Round-trip |
The inner list sits inside the first item's text. Where's the boundary?
<ul>
<li>
Stage 1
<ul>
<li>move the code</li>
<li>add a CLI</li>
</ul>
</li>
<li>Stage 2</li>
</ul>
| element | what markdown can say | what you would edit |
|---|---|---|
| <ul> | all markdown |
- Stage 1 - move the code - add a CLI - Stage 2 |
| <li> | all markdown |
Stage 1 - move the code - add a CLI |
| <ul> | all markdown |
- move the code - add a CLI |
| <li> | all markdown |
move the code |
| <li> | all markdown |
add a CLI |
| <li> | all markdown |
Stage 2 |
A loose list: the li holds blocks, not phrasing. Scopes are the ps, then?
Round-trip.
Opening and saving must change nothing.
Markdown in the box.
<ol start="3">
<li>
<p>Round-trip.</p>
<p>Opening and saving must change nothing.</p>
</li>
<li>
<p>Markdown in the box.</p>
</li>
</ol>
| element | what markdown can say | what you would edit |
|---|---|---|
| <ol> | all markdown |
3. Round-trip. Opening and saving must change nothing. 4. Markdown in the box. |
| <li> | all markdown |
Round-trip. Opening and saving must change nothing. |
| <p> | all markdown |
Round-trip. |
| <p> | all markdown |
Opening and saving must change nothing. |
| <li> | markdown with HTML |
<p>Markdown in the box.</p> |
| <p> | all markdown |
Markdown in the box. |
Markdown has no dl. Each dt and dd its own scope?
@AI request, stored as an HTML comment.<dl> <dt>directive</dt> <dd>An <code>@AI</code> request, stored as an HTML comment.</dd> <dt>scope</dt> <dd>The unit of editing and directives.</dd> </dl>
| element | what markdown can say | what you would edit |
|---|---|---|
| <dl> | markdown with HTML |
<dt>directive</dt> <dd>An <code>@AI</code> request, stored as an HTML comment.</dd> <dt>scope</dt> <dd>The unit of editing and directives.</dd> |
| <dt> | all markdown |
directive |
| <dd> | all markdown |
An `@AI` request, stored as an HTML comment. |
| <dt> | all markdown |
scope |
| <dd> | all markdown |
The unit of editing and directives. |
With paragraphs inside, the paragraphs are scopes. With bare text, the blockquote is.
The curious mind over the inventive mind.
— Clausewitz
A blockquote holding text directly.
<blockquote> <p>The curious mind over the inventive mind.</p> <p>— Clausewitz</p> </blockquote> <blockquote>A blockquote holding text directly.</blockquote>
| element | what markdown can say | what you would edit |
|---|---|---|
| <blockquote> | all markdown |
The curious mind over the inventive mind. — Clausewitz |
| <p> | all markdown |
The curious mind over the inventive mind. |
| <p> | all markdown |
— Clausewitz |
| <blockquote> | all markdown |
A blockquote holding text directly. |
Each cell a scope? The header row too? A cell holding a list?
| stage | status |
|---|---|
| Formatter | in progress, see PLAN |
| Scopes |
|
<table>
<caption>Stages</caption>
<tbody>
<tr>
<th>stage</th>
<th>status</th>
</tr>
<tr>
<td>Formatter</td>
<td>
<strong>in progress</strong>, see <a href="#scopes">PLAN</a>
</td>
</tr>
<tr>
<td>Scopes</td>
<td>
<ul>
<li>decide</li>
<li>build</li>
</ul>
</td>
</tr>
</tbody>
</table>
| element | what markdown can say | what you would edit |
|---|---|---|
| <table> | markdown with HTML |
<table>
<caption>Stages</caption>
<tbody>
<tr>
<th>stage</th>
<th>status</th>
</tr>
<tr>
<td>Formatter</td>
<td><strong>in progress</strong>, see <a href="#scopes">PLAN</a></td>
</tr>
<tr>
<td>Scopes</td>
<td>
<ul>
<li>decide</li>
<li>build</li>
</ul>
</td>
</tr>
</tbody>
</table>
|
| <caption> | all markdown |
Stages |
| <th> | all markdown |
stage |
| <th> | all markdown |
status |
| <td> | all markdown |
Formatter |
| <td> | all markdown |
**in progress**, see [PLAN](#scopes) |
| <a> | all markdown |
[PLAN](#scopes) |
| <td> | all markdown |
Scopes |
| <td> | all markdown |
- decide - build |
| <ul> | all markdown |
- decide - build |
| <li> | all markdown |
decide |
| <li> | all markdown |
build |
The caption is prose; the figure is a container; the image is nonprose.
<figure>
<svg viewBox="0 0 120 40" width="120">
<rect x="1" y="1" width="118" height="38" rx="6" fill="none" stroke="#8250df" /><text x="60" y="25" text-anchor="middle" font-size="12">diagram yo</text>
</svg>
<figcaption>The <em>path</em>, as of today.</figcaption>
</figure>
| element | what markdown can say | what you would edit |
|---|---|---|
| <figure> | markdown with HTML and ⟦tokens⟧ |
⟦svg⟧ <figcaption>The <em>path</em>, as of today.</figcaption> |
| <text> | svg text: markdown inside the label |
diagram yo |
| <figcaption> | all markdown |
The *path*, as of today. |
Summary is phrasing; the body is flow. Two scopes?
It can take validation steps.
<details open> <summary>Why <strong>formatter</strong> first?</summary> <p>It can take validation steps.</p> </details>
| element | what markdown can say | what you would edit |
|---|---|---|
| <details> | markdown with HTML |
<summary>Why <strong>formatter</strong> first?</summary> It can take validation steps. |
| <summary> | all markdown |
Why **formatter** first? |
| <p> | all markdown |
It can take validation steps. |
No p, but it reads as a paragraph. Same as a p?
<div>A div with <em>text</em> and no paragraph element.</div>
| element | what markdown can say | what you would edit |
|---|---|---|
| <div> | all markdown |
A div with *text* and no paragraph element. |
Bare text, then a block, then more bare text. Each text run an anonymous scope? Or does the formatter wrap them in p?
<div>
Text before the list, <strong>with bold</strong>.
<ul>
<li>an item</li>
</ul>
Text after the list.
</div>
| element | what markdown can say | what you would edit |
|---|---|---|
| <div> | all markdown |
Text before the list, **with bold**. - an item Text after the list. |
| <ul> | all markdown |
- an item |
| <li> | all markdown |
an item |
A scope edited as a fenced block? Spans from syntax highlighting can't survive markdown.
node formatter.mjs PLAN.html
echo $?
const x = 1;
<pre><code>node formatter.mjs PLAN.html echo $?</code></pre> <pre><code><span style="color: #cf222e; font-weight: 600">const</span> x = <span style="color: #0550ae">1</span>;</code></pre>
| element | what markdown can say | what you would edit |
|---|---|---|
| <pre> | all markdown |
``` node formatter.mjs PLAN.html echo $? ``` |
| <pre> | markdown with HTML |
<pre><code><span style="color: #cf222e; font-weight: 600">const</span> x = <span style="color: #0550ae">1</span>;</code></pre> |
An svg inside a sentence. A token in the markdown? Raw SVG would swamp the text.
Click the marker to open the directive box.
<p>
Click the
<svg viewBox="0 0 16 16" width="14" height="14">
<circle cx="8" cy="8" r="6" fill="#d6336c" />
</svg>
marker to open the directive box.
</p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with ⟦tokens⟧ |
Click the ⟦svg⟧ marker to open the directive box. |
Markdown has , but not width or class.
The armadillo lives in DESIGN.html.
<p> The armadillo <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='12'%3E%3Cellipse cx='10' cy='6' rx='9' ry='5' fill='%23998'/%3E%3C/svg%3E" alt="armadillo" width="20"> lives in DESIGN.html. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
The armadillo  lives in DESIGN.html. |
| <img> | all markdown |
 |
Prose, then nonprose, then prose, all in one li.
node formatter.mjs try-me.html
then reload the page.
<ul>
<li>
Run the formatter:
<pre><code>node formatter.mjs try-me.html</code></pre>
then reload the page.
</li>
</ul>
| element | what markdown can say | what you would edit |
|---|---|---|
| <ul> | all markdown |
- Run the formatter: ``` node formatter.mjs try-me.html ``` then reload the page. |
| <li> | all markdown |
Run the formatter: ``` node formatter.mjs try-me.html ``` then reload the page. |
| <pre> | all markdown |
``` node formatter.mjs try-me.html ``` |
Same shape as D3, with a bigger nonprose piece.
| 0 | formatted |
| 1 | can't fix |
<ul>
<li>
Exit codes:
<table>
<tbody>
<tr>
<td>0</td>
<td>formatted</td>
</tr>
<tr>
<td>1</td>
<td>can't fix</td>
</tr>
</tbody>
</table>
</li>
</ul>
| element | what markdown can say | what you would edit |
|---|---|---|
| <ul> | markdown with HTML |
- Exit codes:
<table>
<tbody>
<tr>
<td>0</td>
<td>formatted</td>
</tr>
<tr>
<td>1</td>
<td>can't fix</td>
</tr>
</tbody>
</table>
|
| <li> | markdown with HTML |
Exit codes:
<table>
<tbody>
<tr>
<td>0</td>
<td>formatted</td>
</tr>
<tr>
<td>1</td>
<td>can't fix</td>
</tr>
</tbody>
</table>
|
| <table> | markdown with HTML |
<table>
<tbody>
<tr>
<td>0</td>
<td>formatted</td>
</tr>
<tr>
<td>1</td>
<td>can't fix</td>
</tr>
</tbody>
</table>
|
| <td> | all markdown |
0 |
| <td> | all markdown |
formatted |
| <td> | all markdown |
1 |
| <td> | all markdown |
can't fix |
A big svg between sentences. Does it split the paragraph into two scopes?
Here is the path. It has six stages.
<p>
Here is the path.
<svg viewBox="0 0 200 30" width="200">
<line x1="10" y1="15" x2="190" y2="15" stroke="#ccc" stroke-width="4" /><circle cx="10" cy="15" r="6" fill="#1a7f37" /><circle cx="100" cy="15" r="6" fill="#0969da" /><circle cx="190" cy="15" r="6" fill="#0969da" />
</svg>
It has six stages.
</p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with ⟦tokens⟧ |
Here is the path. ⟦svg⟧ It has six stages. |
SVG text takes directives today. Is it a scope too, editable as markdown?
<svg viewBox="0 0 240 40" width="240"> <text x="10" y="25" font-size="14">Formatter <tspan font-weight="700">alone</tspan></text> </svg>
| element | what markdown can say | what you would edit |
|---|---|---|
| <text> | svg text: markdown inside the label |
Formatter <tspan font-weight="700">alone</tspan> |
Unlikely in an overview page, but phrasing content. Nonprose token?
Show done stages, or .
<p> Show <input type="checkbox" checked> done stages, or <button>reset</button>. </p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | markdown with ⟦tokens⟧ |
Show ⟦input⟧ done stages, or ⟦button⟧. |
All spans, so phrasing by the spec. But it's layout. Scopes per tile, per span, or none?
<div class="stats">
<div class="stat">
<span class="big">6</span><span>stages</span>
</div>
<div class="stat">
<span class="big">1</span><span>in progress</span>
</div>
</div>
| element | what markdown can say | what you would edit |
|---|---|---|
| <div.stats> | markdown with HTML |
<div class="stat"><span class="big">6</span><span>stages</span></div> <div class="stat"><span class="big">1</span><span>in progress</span></div> |
| <div.stat> | markdown with HTML |
<span class="big">6</span><span>stages</span> |
| <span.big> | all markdown |
6 |
| <span> | all markdown |
stages |
| <div.stat> | markdown with HTML |
<span class="big">1</span><span>in progress</span> |
| <span.big> | all markdown |
1 |
| <span> | all markdown |
in progress |
Spans side by side in a flex row. One sentence, or three labels?
<div class="row"> <span class="pill">stage 1</span><span>Formatter</span><span>→ done</span> </div>
| element | what markdown can say | what you would edit |
|---|---|---|
| <div.row> | markdown with HTML |
<span class="pill">stage 1</span><span>Formatter</span><span>→ done</span> |
| <span.pill> | all markdown |
stage 1 |
| <span> | all markdown |
Formatter |
| <span> | all markdown |
→ done |
A card that's one big link. The link is the container; its heading and paragraph are scopes?
<a class="tile" href="#scopes"> <h4>DESIGN.html</h4> <p>Everything the tool adds to a page.</p> </a>
| element | what markdown can say | what you would edit |
|---|---|---|
| <a.tile> | all markdown |
#### DESIGN.html Everything the tool adds to a page. |
| <h4> | all markdown |
DESIGN.html |
| <p> | all markdown |
Everything the tool adds to a page. |
Edit the link text, or the paragraph? Same scope either way?
<p><a href="#scopes">Back to the top of the cases</a></p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
[Back to the top of the cases](#scopes) |
| <a> | all markdown |
[Back to the top of the cases](#scopes) |
Scopes with nothing to edit. Skip them, or let you type into them?
Between two empties.
<p></p> <p> </p> <p>Between two empties.</p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | nothing to edit | |
| <p> | nothing to edit |
|
| <p> | all markdown |
Between two empties. |
A heading and paragraphs straight in a section. Each its own scope, or the section as one markdown doc?
First paragraph.
Second paragraph.
After a rule.
<section> <h4>A section</h4> <p>First paragraph.</p> <p>Second paragraph.</p> <hr> <p>After a rule.</p> </section>
| element | what markdown can say | what you would edit |
|---|---|---|
| <section> | all markdown |
#### A section First paragraph. Second paragraph. --- After a rule. |
| <h4> | all markdown |
A section |
| <p> | all markdown |
First paragraph. |
| <p> | all markdown |
Second paragraph. |
| <p> | all markdown |
After a rule. |
Written as <p>Before the list<ul>…</ul>after the list</p>. The formatter does what a browser does: it closes the p at the ul, leaves the trailing text bare (C10), and turns the stray </p> into an empty p (F1). Leave it, or should the formatter wrap the bare text?
Before the list
<p>Before the list</p> <ul> <li>inside</li> </ul> <p></p>
| element | what markdown can say | what you would edit |
|---|---|---|
| <p> | all markdown |
Before the list |
| <ul> | all markdown |
- inside |
| <li> | all markdown |
inside |
| <p> | nothing to edit |