# What each call writes Each section sets a sample ADF document beside what each call writes for it, then reads that output back: `adfToLosslessMarkdown` with `losslessMarkdownToAdf`, `adfToPortableMarkdown` with `portableMarkdownToAdf`, `adfToHtml` with `htmlToAdf`. `holds` means the reader gives the same document, `loses` a different one, and `refused` that the writer or reader returned an error, whose code the section names. A result covers that example alone, and the examples are plain. Portable markdown keeps only the attributes its spelling holds, such as a heading's level and a link's target, so a document holding any other loses it even where its row says `holds`: to edit and save back, use `adfToLosslessMarkdown` and `losslessMarkdownToAdf`. An image holding more than the alt, layout, type and url of this page's example, as editor-written ones do, rides the carry element in HTML, where this page shows ``. `./feature-table/write.sh` writes this page. Don't edit it by hand. | Example | Lossless | Portable | HTML | | --- | --- | --- | --- | | [Bold instruction with a command in it](#bold-instruction-with-a-command-in-it) | holds | holds | holds | | [Emphasis and strikethrough](#emphasis-and-strikethrough) | holds | holds | holds | | [Headings](#headings) | holds | holds | holds | | [Bullet list](#bullet-list) | holds | holds | holds | | [Code block](#code-block) | holds | holds | holds | | [Quote](#quote) | holds | holds | holds | | [Link](#link) | holds | holds | holds | | [Table](#table) | holds | holds | holds | | [Panels](#panels) | holds | loses | holds | | [Task list](#task-list) | holds | loses | holds | | [Image](#image) | holds | holds | holds | | [Mention](#mention) | holds | loses | holds | | [Status](#status) | holds | loses | holds | | [Date](#date) | holds | loses | holds | | [Node types this version does not know](#node-types-this-version-does-not-know) | holds | loses | holds | ## Bold instruction with a command in it ADF: ```json {"content":[{"content":[{"marks":[{"type":"strong"}],"text":"Run ","type":"text"},{"marks":[{"type":"code"}],"text":"npm ci","type":"text"},{"marks":[{"type":"strong"}],"text":" first","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown **Run `npm ci` first** ``` `adfToPortableMarkdown`, round-trip holds: ```markdown **Run `npm ci` first** ``` `adfToHtml`, round-trip holds: ```html

Run npm ci first

``` ## Emphasis and strikethrough ADF: ```json {"content":[{"content":[{"text":"Read the ","type":"text"},{"marks":[{"type":"em"}],"text":"manual","type":"text"},{"text":" before ","type":"text"},{"marks":[{"type":"strong"}],"text":"wiring","type":"text"},{"text":" the ","type":"text"},{"marks":[{"type":"strike"}],"text":"relay","type":"text"},{"text":".","type":"text"}],"type":"paragraph"},{"content":[{"text":"An un","type":"text"},{"marks":[{"type":"em"}],"text":"real","type":"text"},{"text":"istic goal.","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown Read the _manual_ before **wiring** the ~~relay~~. An un*real*istic goal. ``` `adfToPortableMarkdown`, round-trip holds: ```markdown Read the _manual_ before **wiring** the ~~relay~~. An un*real*istic goal. ``` `adfToHtml`, round-trip holds: ```html

Read the manual before wiring the relay.

An unrealistic goal.

``` ## Headings ADF: ```json {"content":[{"attrs":{"level":1},"content":[{"text":"Assembly","type":"text"}],"type":"heading"},{"attrs":{"level":2},"content":[{"text":"Parts","type":"text"}],"type":"heading"},{"attrs":{"level":3},"content":[{"text":"Fasteners","type":"text"}],"type":"heading"},{"attrs":{"level":4},"content":[{"text":"Bolts","type":"text"}],"type":"heading"},{"attrs":{"level":5},"content":[{"text":"Sizes","type":"text"}],"type":"heading"},{"attrs":{"level":6},"content":[{"text":"M8","type":"text"}],"type":"heading"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown # Assembly ## Parts ### Fasteners #### Bolts ##### Sizes ###### M8 ``` `adfToPortableMarkdown`, round-trip holds: ```markdown # Assembly ## Parts ### Fasteners #### Bolts ##### Sizes ###### M8 ``` `adfToHtml`, round-trip holds: ```html

Assembly

Parts

Fasteners

Bolts

Sizes
M8
``` ## Bullet list ADF: ```json {"content":[{"content":[{"content":[{"content":[{"text":"Bolt M8","type":"text"}],"type":"paragraph"}],"type":"listItem"},{"content":[{"content":[{"text":"Nut M8","type":"text"}],"type":"paragraph"}],"type":"listItem"},{"content":[{"content":[{"text":"Washer M8","type":"text"}],"type":"paragraph"},{"content":[{"content":[{"content":[{"text":"Fibre","type":"text"}],"type":"paragraph"}],"type":"listItem"}],"type":"bulletList"}],"type":"listItem"}],"type":"bulletList"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown - Bolt M8 - Nut M8 - Washer M8 - Fibre ``` `adfToPortableMarkdown`, round-trip holds: ```markdown - Bolt M8 - Nut M8 - Washer M8 - Fibre ``` `adfToHtml`, round-trip holds: ```html ``` ## Code block ADF: ```json {"content":[{"attrs":{"language":"sql"},"content":[{"text":"SELECT id\nFROM part\nWHERE qty > 0;\n- 1. the markers a container start would claim","type":"text"}],"type":"codeBlock"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ````markdown ```sql SELECT id FROM part WHERE qty > 0; - 1. the markers a container start would claim ``` ```` `adfToPortableMarkdown`, round-trip holds: ````markdown ```sql SELECT id FROM part WHERE qty > 0; - 1. the markers a container start would claim ``` ```` `adfToHtml`, round-trip holds: ```html
SELECT id
FROM part
WHERE qty > 0;
- 1. the markers a container start would claim
``` ## Quote ADF: ```json {"content":[{"content":[{"content":[{"text":"Ship it.","type":"text"}],"type":"paragraph"},{"content":[{"text":"Then tell them.","type":"text"}],"type":"paragraph"}],"type":"blockquote"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown > Ship it. > > Then tell them. ``` `adfToPortableMarkdown`, round-trip holds: ```markdown > Ship it. > > Then tell them. ``` `adfToHtml`, round-trip holds: ```html

Ship it.

Then tell them.

``` ## Link ADF: ```json {"content":[{"content":[{"text":"See ","type":"text"},{"marks":[{"attrs":{"href":"https://example.com/changelog"},"type":"link"}],"text":"the changelog","type":"text"},{"text":".","type":"text"}],"type":"paragraph"},{"content":[{"marks":[{"attrs":{"href":"https://example.com/"},"type":"link"}],"text":"https://example.com/","type":"text"}],"type":"paragraph"},{"content":[{"text":"Read ","type":"text"},{"marks":[{"attrs":{"href":"https://example.com/guide","title":"Setup guide"},"type":"link"}],"text":"the guide","type":"text"},{"text":".","type":"text"}],"type":"paragraph"},{"content":[{"text":"Open ","type":"text"},{"marks":[{"attrs":{"href":"https://example.com/the plan.pdf"},"type":"link"}],"text":"the plan","type":"text"},{"text":".","type":"text"}],"type":"paragraph"},{"content":[{"marks":[{"attrs":{"href":"/parts/m8"},"type":"link"}],"text":"/parts/m8","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown See [the changelog](https://example.com/changelog). Read [the guide](https://example.com/guide "Setup guide"). Open [the plan](). [/parts/m8](/parts/m8) ``` `adfToPortableMarkdown`, round-trip holds: ```markdown See [the changelog](https://example.com/changelog). Read [the guide](https://example.com/guide "Setup guide"). Open [the plan](). [/parts/m8](/parts/m8) ``` `adfToHtml`, round-trip holds: ```html

See the changelog.

https://example.com/

Read the guide.

Open the plan.

/parts/m8

``` ## Table ADF: ```json {"content":[{"content":[{"content":[{"content":[{"content":[{"text":"Part","type":"text"}],"type":"paragraph"}],"type":"tableHeader"},{"content":[{"content":[{"text":"Stock","type":"text"}],"type":"paragraph"}],"type":"tableHeader"}],"type":"tableRow"},{"content":[{"content":[{"content":[{"text":"Bolt M8","type":"text"}],"type":"paragraph"}],"type":"tableCell"},{"content":[{"content":[{"text":"120","type":"text"}],"type":"paragraph"}],"type":"tableCell"}],"type":"tableRow"},{"content":[{"content":[{"content":[{"text":"Washer M8","type":"text"}],"type":"paragraph"}],"type":"tableCell"},{"content":[{"content":[{"text":"45","type":"text"}],"type":"paragraph"}],"type":"tableCell"}],"type":"tableRow"}],"type":"table"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown | Part | Stock | | --- | --- | | Bolt M8 | 120 | | Washer M8 | 45 | ``` `adfToPortableMarkdown`, round-trip holds: ```markdown | Part | Stock | | --- | --- | | Bolt M8 | 120 | | Washer M8 | 45 | ``` `adfToHtml`, round-trip holds: ```html
PartStock
Bolt M8120
Washer M845
``` ## Panels ADF: ```json {"content":[{"attrs":{"panelType":"warning"},"content":[{"content":[{"text":"Check the collation before importing.","type":"text"}],"type":"paragraph"}],"type":"panel"},{"attrs":{"localId":"01a0337c-561a-75aa-b629-3801f68839ad","panelType":"info"},"content":[{"content":[{"text":"Backups run at 02:00.","type":"text"}],"type":"paragraph"}],"type":"panel"},{"attrs":{"panelColor":"#c9372c","panelIcon":":rainbow:","panelIconId":"1f308","panelIconText":"🌈","panelType":"custom"},"content":[{"content":[{"text":"Weather permitting.","type":"text"}],"type":"paragraph"}],"type":"panel"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown !adf:panel warning Check the collation before importing. !adf:/panel !adf:panel info {localId=01a0337c-561a-75aa-b629-3801f68839ad} Backups run at 02:00. !adf:/panel !adf:panel custom {panelColor="#c9372c" panelIcon=":rainbow:" panelIconId=1f308 panelIconText="🌈"} Weather permitting. !adf:/panel ``` `adfToPortableMarkdown`, round-trip loses: ```markdown > [!WARNING] > > Check the collation before importing. > [!NOTE] > > Backups run at 02:00. > [!NOTE] > > Weather permitting. ``` `adfToHtml`, round-trip holds: ```html

Check the collation before importing.

Backups run at 02:00.

Weather permitting.

``` ## Task list ADF: ```json {"content":[{"attrs":{"localId":"0198f3a2-7c41-7f2e-9b3a-4d8e2c1a6b90"},"content":[{"attrs":{"localId":"0198f3a2-8d52-70b1-8c4f-5e9f3d2b7ca1","state":"DONE"},"content":[{"text":"Write the spec","type":"text"}],"type":"taskItem"},{"attrs":{"localId":"0198f3a2-9e63-7d80-a15b-6fa04e3c8db2","state":"TODO"},"content":[{"text":"Ship it","type":"text"}],"type":"taskItem"},{"attrs":{"localId":"01a033b2-95c8-7d62-9b9c-dee7ad510982","state":"TODO"},"content":[{"content":[{"text":"Check the torque.","type":"text"}],"type":"paragraph"},{"content":[{"text":"Then sign off.","type":"text"}],"type":"paragraph"}],"type":"blockTaskItem"},{"attrs":{"localId":"01a033b3-d1fa-7489-8c9f-f5846d2c249d"},"content":[{"attrs":{"localId":"01a033bd-a22d-7fb5-be9d-89d1aa261112","state":"TODO"},"content":[{"text":"Nested step","type":"text"}],"type":"taskItem"},{"attrs":{"state":"TODO"},"type":"taskItem"}],"type":"taskList"}],"type":"taskList"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown !adf:taskList {localId=0198f3a2-7c41-7f2e-9b3a-4d8e2c1a6b90} !adf:taskItem DONE {localId=0198f3a2-8d52-70b1-8c4f-5e9f3d2b7ca1} Write the spec !adf:/taskItem !adf:taskItem TODO {localId=0198f3a2-9e63-7d80-a15b-6fa04e3c8db2} Ship it !adf:/taskItem !adf:blockTaskItem TODO {localId=01a033b2-95c8-7d62-9b9c-dee7ad510982} Check the torque. Then sign off. !adf:/blockTaskItem !adf:taskList {localId=01a033b3-d1fa-7489-8c9f-f5846d2c249d} !adf:taskItem TODO {localId=01a033bd-a22d-7fb5-be9d-89d1aa261112} Nested step !adf:/taskItem !adf:taskItem TODO !adf:/taskItem !adf:/taskList !adf:/taskList ``` `adfToPortableMarkdown`, round-trip loses: ```markdown - [x] Write the spec - [ ] Ship it - [ ] Check the torque. Then sign off. - [ ] Nested step - [ ] ``` `adfToHtml`, round-trip holds: ```html

Write the spec

Ship it

Check the torque.

Then sign off.

Nested step

``` ## Image ADF: ```json {"content":[{"content":[{"text":"Taken from the roof last night.","type":"text"}],"type":"paragraph"},{"attrs":{"layout":"center"},"content":[{"attrs":{"alt":"The moon, at night.","type":"external","url":"https://example.com/moon.png"},"type":"media"}],"type":"mediaSingle"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown Taken from the roof last night. ![The moon, at night.](https://example.com/moon.png) ``` `adfToPortableMarkdown`, round-trip holds: ```markdown Taken from the roof last night. ![The moon, at night.](https://example.com/moon.png) ``` `adfToHtml`, round-trip holds: ```html

Taken from the roof last night.

The moon, at night.

``` ## Mention ADF: ```json {"content":[{"content":[{"text":"Ping ","type":"text"},{"attrs":{"accessLevel":"CONTAINER","id":"01a032c3-7a7c-775f-a730-2d79351338b4","localId":"01a033ad-ecb7-7530-aa1c-ff25031e96e2","text":"@Mikael","userType":"DEFAULT"},"type":"mention"},{"text":" before merging.","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown Ping !adf:mention[@Mikael]{accessLevel=CONTAINER id=01a032c3-7a7c-775f-a730-2d79351338b4 localId=01a033ad-ecb7-7530-aa1c-ff25031e96e2 userType=DEFAULT} before merging. ``` `adfToPortableMarkdown`, round-trip loses: ```markdown Ping @Mikael before merging. ``` `adfToHtml`, round-trip holds: ```html

Ping @Mikael before merging.

``` ## Status ADF: ```json {"content":[{"content":[{"text":"The rebuild is ","type":"text"},{"attrs":{"color":"yellow","localId":"01a033a7-d68a-71a9-a58a-edf5757ad176","style":"bold","text":"In review"},"type":"status"},{"text":" until Friday.","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown The rebuild is !adf:status[In review]{color=yellow localId=01a033a7-d68a-71a9-a58a-edf5757ad176 style=bold} until Friday. ``` `adfToPortableMarkdown`, round-trip loses: ```markdown The rebuild is In review until Friday. ``` `adfToHtml`, round-trip holds: ```html

The rebuild is In review until Friday.

``` ## Date ADF: ```json {"content":[{"content":[{"text":"Due ","type":"text"},{"attrs":{"timestamp":"1756080000000"},"type":"date"},{"text":", reviewed ","type":"text"},{"attrs":{"localId":"01a033ab-781c-7f79-9c8a-fb63356c1cad","timestamp":"1735689600000"},"type":"date"},{"text":".","type":"text"}],"type":"paragraph"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ```markdown Due !adf:date{timestamp=1756080000000}, reviewed !adf:date{localId=01a033ab-781c-7f79-9c8a-fb63356c1cad timestamp=1735689600000}. ``` `adfToPortableMarkdown`, round-trip loses: ```markdown Due 2025-08-25, reviewed 2025-01-01. ``` `adfToHtml`, round-trip holds: ```html

Due , reviewed .

``` ## Node types this version does not know ADF: ```json {"content":[{"attrs":{"url":"https://example.com/roadmap"},"type":"blockCard"},{"attrs":{"panelType":"info"},"content":[{"content":[{"text":"The card below has no spelling yet.","type":"text"}],"type":"paragraph"},{"attrs":{"layout":"wide","url":"https://example.com/board","width":100},"type":"embedCard"}],"type":"panel"}],"type":"doc","version":1} ``` `adfToLosslessMarkdown`, round-trip holds: ````markdown ```adf:blockCard { "attrs": { "url": "https://example.com/roadmap" } } ``` !adf:panel info The card below has no spelling yet. ```adf:embedCard { "attrs": { "layout": "wide", "url": "https://example.com/board", "width": 100 } } ``` !adf:/panel ```` `adfToPortableMarkdown`, round-trip loses: ```markdown > [!NOTE] > > The card below has no spelling yet. > > ``` `adfToHtml`, round-trip holds: ```html

The card below has no spelling yet.

https://example.com/board

```