Due to the ambiguity of HTML several translations from Gemini exist in the wild. I propose the following standard:

UL         ↔ *
PRE        ↔ ``` 
A          ↔ => 
H[1-3]     ↔ #[##]
Empty lines should simply be represented as <p><br></p>. (Some implementations use just <br> but this sets up contenteditable=true to add content to the line and also Gemini has no "empty" line-type just a line that is empty.)
The <a> for a link should be presented without any parent elements. Many implementations use <div> to enforce "block" styling as opposed to the default "inline" which renders the link next to the previous block instead of below it. But the nested markup adds an unnecessary layer of indirection in semantics and when parsing. If you must wrap the link it should be with a <p> tag and never a <div>. If you do not wrap the link a simple "a {display: block}" has the same effect (gmi.css uses this).

P, UL, BLOCKQUOTE, and PRE may also have line-breaks which should be inserted as innerHTML using the following rules:

P          ↔ <br>
BLOCKQUOTE ↔ <div><br></div>
UL         ↔ <li><br></li>
PRE          \n (or <br>)
These are informed by what the browser uses when contenteditable=true is set on the element and you hit "enter"
Some implementations render a series of ">" into a series of <blockquotes> which is probably fine but it is preferable to group them and insert the subsequent lines as <div>line-breaks</div>.
Parsers may want to be aware of potential <br> lines inside <pre> tags as that is how "enter" is handled when contenteditable=true. It is uncertain why the browser behaves so but they can be safely translated to \n. and you need not translate \n → <br> as that's implied in "preformatted".


Following this standard will allow gmi.css to render your content reliably and readably across many devices.

read more about gmi.css


This also paves the way for setting contenteditable on the root element and enabling the browsers native HTML document editor. Unfortunately it does not handle a few annoying quirks which may only be addressed with custom JavaScript.

gmi.js is currently under active development but already exposes a Gemini.line function which wraps the DOM API following the above standard. This should enable addressing the editability quirks and also provide a foundation for future JS/Gemini mashups.

read more about gmi.js

gmi-web is licensed under CC0 and available on sourcehut