krz/org-swift

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

GAPS.md

v0.3.0
org-swift/GAPS.md rendered · source · history · blame · raw

61 lines · 4398 bytes

Conformance gaps

OrgSwift is measured against the org-conformance corpus, whose goldens come from orgo (validated against Emacs ox-html). The renderer is run in orgo-compatible mode — OrgRenderOptions(metadataHeader: false, headingLevelOffset: 1) — so that only real rendering differences remain.

Of the 12 corpus cases, 11 match orgo exactly — every case except outofscope, which is scope: out in the corpus (deliberately unsupported constructs like #+INCLUDE, babel, and LaTeX; orgo may also differ there, so it is documentation, not a target). The per-case state is recorded in the expectations map in Tests/OrgSwiftTests/ConformanceTests.swift: a case that regresses, or outofscope starting to match, fails the test and forces the map to be updated — that is how this list stays honest.

Two behaviors were made configurable during extraction rather than left hardcoded, because they are presentation policy, not parser capability:

  • metadataHeader — whether #+TITLE/#+AUTHOR/#+DATE render as a leading <div class="org-metadata">. Apps that want a visible README title keep the default (true); orgo carries the title in the page template, so conformance runs with false.
  • headingLevelOffset — added to a heading's star count. Default 0 renders * as <h1>; orgo uses 1 (* → <h2>, leaving <h1> for the title).

Closed

  • timestamps — active/inactive timestamps, times, same-day and multi-day ranges now render as <time class="timestamp" datetime> elements matching orgo; day names and repeater/warning cookies are dropped, non-timestamps (3 < 4, [not a stamp]) stay literal.
  • footnote — references ([fn:1]), inline footnotes ([fn:label:text]), and reference-style definitions now render as <sup> anchors plus a <section class="footnotes"> at the end, numbered in first-reference order. Footnote references are collected from paragraphs and headings; a reference inside a list item or table cell is not yet collected (it degrades to literal text).
  • minimal / headings — property drawers (:PROPERTIES: … :END:) are dropped rather than rendered as a <dl>, and heading trailing :tag1:tag2: are split off the title and rendered as <span class="tag">. TODO/DONE keywords and priority cookies are still emitted as plain title text (orgo wraps them in styled spans); that is a separate, cosmetic difference the skeleton does not distinguish.
  • core — bare http(s):// URLs in running text are autolinked (trailing sentence punctuation left outside the link), and task checkboxes render as <code>[ ]</code> / <code>[X]</code> / <code>[-]</code> the way org's HTML exporter emits them, rather than as <input type="checkbox">.
  • images — [[file:…]] links have the file: prefix stripped and relative image src/link href are allowed (a scheme-less path cannot carry a javascript: payload). A standalone image line becomes <p><img></p>; an affiliated #+CAPTION/#+ATTR_HTML promotes it to a <figure>, with a numbered <figcaption> when a caption is present. #+ATTR_HTML :key value pairs (quoted values honored) become <img> attributes, and a described image link ([[file:x.png][text]]) renders as a link, not an inline image.
  • elements — any unhandled #+KEYWORD: line (#+FILETAGS, #+TBLFM, …) is consumed as document metadata instead of leaking into the body, and [[id:target]] links render as in-page fragment links (<a href="#target">).
  • lists — the list renderer is now recursive: unordered/ordered nesting to any depth, description lists (term :: definition → <dl>), and multi-paragraph items (an item's paragraphs, separated by blank lines, wrap in <p>). A latent link-parser bug that let a no-description link swallow a later link's ][ was fixed in passing.
  • tblfm — ^ superscript renders (N^2 → N<sup>2</sup>, x^{group} supported).
  • blocks — example blocks are a bare <pre>; #+BEGIN_EXPORT html passes through verbatim while other export backends are dropped; verse renders as <p class="verse"> with <br>; a #+BEGIN_<name> special block becomes <div class="<name>"> with org content; and a source block inside a quote stays nested in the <blockquote>.