A dependency-free Swift library that renders org-mode to sanitized HTML.

html library org-mode swift

GAPS.md

61 lines · 4398 bytes

 1# Conformance gaps
 2
 3OrgSwift is measured against the [org-conformance](../org-conformance) corpus, whose
 4goldens come from orgo (validated against Emacs `ox-html`). The renderer is run in
 5orgo-compatible mode — `OrgRenderOptions(metadataHeader: false, headingLevelOffset: 1)` 6so that only real rendering differences remain.
 7
 8Of the 12 corpus cases, **11 match orgo exactly** — every case except `outofscope`, which is
 9`scope: out` in the corpus (deliberately unsupported constructs like `#+INCLUDE`, babel, and
10LaTeX; orgo may also differ there, so it is documentation, not a target). The per-case state
11is recorded in the `expectations` map in `Tests/OrgSwiftTests/ConformanceTests.swift`: a case
12that regresses, or `outofscope` starting to match, fails the test and forces the map to be
13updated — that is how this list stays honest.
14
15Two behaviors were made configurable during extraction rather than left hardcoded, because
16they are presentation policy, not parser capability:
17
18- **`metadataHeader`** — whether `#+TITLE`/`#+AUTHOR`/`#+DATE` render as a leading
19  `<div class="org-metadata">`. Apps that want a visible README title keep the default
20  (`true`); orgo carries the title in the page template, so conformance runs with `false`.
21- **`headingLevelOffset`** — added to a heading's star count. Default `0` renders `*` as
22  `<h1>`; orgo uses `1` (`*``<h2>`, leaving `<h1>` for the title).
23
24## Closed
25
26- **`timestamps`** — active/inactive timestamps, times, same-day and multi-day ranges now
27  render as `<time class="timestamp" datetime>` elements matching orgo; day names and
28  repeater/warning cookies are dropped, non-timestamps (`3 < 4`, `[not a stamp]`) stay
29  literal.
30- **`footnote`** — references (`[fn:1]`), inline footnotes (`[fn:label:text]`), and
31  reference-style definitions now render as `<sup>` anchors plus a `<section
32  class="footnotes">` at the end, numbered in first-reference order. Footnote references
33  are collected from paragraphs and headings; a reference inside a list item or table cell
34  is not yet collected (it degrades to literal text).
35- **`minimal` / `headings`** — property drawers (`:PROPERTIES:``:END:`) are dropped
36  rather than rendered as a `<dl>`, and heading trailing `:tag1:tag2:` are split off the
37  title and rendered as `<span class="tag">`. TODO/DONE keywords and priority cookies are
38  still emitted as plain title text (orgo wraps them in styled spans); that is a separate,
39  cosmetic difference the skeleton does not distinguish.
40- **`core`** — bare `http(s)://` URLs in running text are autolinked (trailing sentence
41  punctuation left outside the link), and task checkboxes render as `<code>[ ]</code>` /
42  `<code>[X]</code>` / `<code>[-]</code>` the way org's HTML exporter emits them, rather
43  than as `<input type="checkbox">`.
44- **`images`** — `[[file:…]]` links have the `file:` prefix stripped and relative image
45  `src`/link `href` are allowed (a scheme-less path cannot carry a `javascript:` payload).
46  A standalone image line becomes `<p><img></p>`; an affiliated `#+CAPTION`/`#+ATTR_HTML`
47  promotes it to a `<figure>`, with a numbered `<figcaption>` when a caption is present.
48  `#+ATTR_HTML` `:key value` pairs (quoted values honored) become `<img>` attributes, and
49  a described image link (`[[file:x.png][text]]`) renders as a link, not an inline image.
50- **`elements`** — any unhandled `#+KEYWORD:` line (`#+FILETAGS`, `#+TBLFM`, …) is consumed
51  as document metadata instead of leaking into the body, and `[[id:target]]` links render
52  as in-page fragment links (`<a href="#target">`).
53- **`lists`** — the list renderer is now recursive: unordered/ordered nesting to any depth,
54  description lists (`term :: definition``<dl>`), and multi-paragraph items (an item's
55  paragraphs, separated by blank lines, wrap in `<p>`). A latent link-parser bug that let a
56  no-description link swallow a later link's `][` was fixed in passing.
57- **`tblfm`** — `^` superscript renders (`N^2``N<sup>2</sup>`, `x^{group}` supported).
58- **`blocks`** — example blocks are a bare `<pre>`; `#+BEGIN_EXPORT html` passes through
59  verbatim while other export backends are dropped; verse renders as `<p class="verse">`
60  with `<br>`; a `#+BEGIN_<name>` special block becomes `<div class="<name>">` with org
61  content; and a source block inside a quote stays nested in the `<blockquote>`.