165 lines
5 KiB
Markdown
165 lines
5 KiB
Markdown
# gmi-web
|
|
|
|
**Vision**: Provide the lowest common denominator between HTML/CSS/JS and Gemini.
|
|
|
|
# HTML spec
|
|
|
|
## `<head>`
|
|
|
|
The generated HTML document must have a `<head>` tag with _at minimum_ the following:
|
|
|
|
```html
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta language="en"> <!-- set this accordingly! -->
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
</head>
|
|
```
|
|
|
|
You might want to also include these (or whatever else):
|
|
|
|
```html
|
|
<title></title>
|
|
<link rel="canonical" href="gemini://">
|
|
<meta name="description" content="">
|
|
```
|
|
|
|
## `<body>`
|
|
|
|
The converted Gemini document should be placed inside the `<body>`. Due to the ambiguity of HTML several translations from Gemini exist in the wild. I propose the following standard:
|
|
|
|
```
|
|
<p>
|
|
<a> ↔ =>
|
|
<pre> ↔ ```
|
|
<h[1-3]> ↔ #[##]
|
|
<li> ↔ *
|
|
<blockquote> ↔ >
|
|
```
|
|
|
|
The `<a>` for a link should be presented un-wrapped without any parent elements. Many implementations use `<div>` or `<p>` 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. The best way to handle this is to include `<style>a {display: block;}</style>` in the `<head>`.
|
|
|
|
Empty lines should simply be represented as `<p><br></p>` this sets up `contenteditable=true` to add content to the line compared to just `<br>`.
|
|
|
|
Take care to render `<pre>` blocks with their original formatting, DO NOT indent the generated
|
|
HTML for these tags.
|
|
|
|
Much like the lines of a `<pre>`, the lines of `<li>list items</li>` need to be wrapped in `<ul>`, indention here is not significant. Sometimes a list item is empty: `<li><br></li>`.
|
|
|
|
### Optional: inline media
|
|
|
|
If a link is consumable by `<img>`, `<audio>` or `<video>` you may insert the respective tag inline instead of an `<a>`. Images and video should be styled to have `max-width: 100%;` so they don't overflow the body. It's a good idea to also include the "controls" attribute. `<audio>` tags require `display: block;` just like `<a>`.
|
|
|
|
### Basic `<style>`
|
|
|
|
Without any CSS the browser renders all of this just a lil wonky. At bare minimum I recommend including the following in the `<head>` of all your generated .html files.
|
|
|
|
```html
|
|
<style>p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}</style>
|
|
```
|
|
|
|
## gmi-web(1)
|
|
|
|
A reference implementation of what has been discussed above!
|
|
|
|
*You will need*:
|
|
- [node(1) w/ npm(1)](https://nodejs.org/en/)
|
|
|
|
```sh
|
|
npm install -g git+https://codeberg.org/talon/gmi-web.git
|
|
```
|
|
|
|
```
|
|
gmi-web [--css] [files..]
|
|
|
|
Convert .gmi to .html. See gmi-web(1) for more details.
|
|
|
|
Positionals:
|
|
files The *.gmi files to convert [required]
|
|
|
|
Options:
|
|
--version Show version number [boolean]
|
|
--help Show help [boolean]
|
|
--images Include images [boolean] [default: false]
|
|
--audio Include audio [boolean] [default: false]
|
|
--video Include video [boolean] [default: false]
|
|
--css Include gmi.css [boolean] [default: true]
|
|
```
|
|
|
|
## gmi.css
|
|
|
|
Optimized for readability, predictability, mobile-friendliness and
|
|
ships with a handful of customizable variables. See `man 5 gmi.css`.
|
|
|
|
The *--foreground* and *--background* variables will be inverted when
|
|
*prefers-color-scheme* is "dark" which is a system-level preference on
|
|
devices.
|
|
|
|
Any of the variables can be customized by adding a higher priority .css file
|
|
that overrides them.
|
|
|
|
```css
|
|
html {
|
|
--foreground: #333333;
|
|
--background: #FFFFFF;
|
|
}
|
|
```
|
|
|
|
Or maybe by adding a style to the `<html>` element.
|
|
|
|
```html
|
|
<html style="--foreground:#555555; --background:#9EEBCF;">
|
|
```
|
|
|
|
When using `gmi-web(1)` they can be customized by the `--style` flag.
|
|
|
|
# License
|
|
|
|
gmi-web is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying UNLICENSE file.
|
|
|
|
<!-- TODO
|
|
### gmi.js
|
|
|
|
Manipulate the DOM with a Gemini inspired API.
|
|
|
|
```js
|
|
const line = Gemini.line("manipulate the dom\nbut like in a Gemini way\ntry it!")
|
|
document.body.prepend(line.dom)
|
|
```
|
|
|
|
Try changing the type and content and observing the effects.
|
|
|
|
```js
|
|
line.type = "UL"
|
|
line.content = "now\nit's\na\nlist"
|
|
```
|
|
|
|
A document provides a way to handle many lines together.
|
|
|
|
```js
|
|
window.gmi = new Gemini(document.body)
|
|
window.gmi.lines = [
|
|
Gemini.line("interesting", "H1"),
|
|
Gemini.line("that's convenient"),
|
|
Gemini.line("http://talon.computer/js/ now... take me back please", "A"),
|
|
]
|
|
window.gmi.lines[0].type = "H3"
|
|
```
|
|
|
|
The gemtext source is available via .source
|
|
|
|
```js
|
|
window.gmi.source
|
|
```
|
|
|
|
All the gmi.css variables are also available as properties.
|
|
|
|
```js
|
|
let foreground = window.gmi.foreground
|
|
let background = window.gmi.background
|
|
window.gmi.foreground = background
|
|
window.gmi.background = foreground
|
|
```
|
|
-->
|
|
|