defmodule Gemtext do
@moduledoc """
Gemtext is a lightweight markup language for the Gemini protocol.
This module can parse a "gemtext" into a list of nodes or render the samne
list of nodes into the original "gemtext".
### Gemtext cheatsheet
___
* Long lines get wrapped by the client to fit the screen
* Short lines *don't* get joined together
* Write paragraphs as single long lines
* Blank lines are rendered verbatim
* lines which start with `` ``` `` will cause clients to toggle in and out of
ordinary rendering mode and preformatted mode. In preformatted mode,
Gemtext syntax is ignored so links etc. will not be rendered, and text
will appear in a monospace font.
### Core types
___
where
* <...> is a token
* [...] is an optional element
* [<...>] means zero or one
* <...>* means zero or more
* <...>+ means one or more
* <whitespace> is a space or a tab
* <eol> is one of the `eol` sequences `\\r`, `\\n` or `\\r\\n`
* <url> is either an absolute or a relative url.
#### Heading
```text
#[<whitespace>]Heading title<eol>
```
There are three levels of heading:
```text
# Heading
## Sub-heading
### Sub-subheading
```
#### List item
There's only one kind of list and you can't nest them:
```text
*[<whitespace>]List item text<eol>
```
```text
* Mercury
* Gemini
* Apollo
```
#### Blockquote
```text
>[<whitespace>]Famous quote here<eol>
```
```text
> I hope so for your sake, Commander. The Emperor is not as forgiving as I am.
```
#### Link
```text
=><whitespace>*<url>[<whitespace><link name>]
```
```text
=> /logout
=> / Go home
=> gemini://gemini.circumlunar.space Project Gemini
```
#### Preformatted text
```text
```<eol>[<whitespace>*<text_type><eol>](<line of text><eol>)+```
```
``````text
```elixir
iex> "Elixir" |> String.graphemes() |> Enum.frequencies()
%{"E" => 1, "i" => 2, "l" => 1, "r" => 1, "x" => 1}
```
``````
#### Text
```text
everyting until<eol>
```
```text
This is normal text Line 1
This is normal text Line 2
This is a robot emoji 🤖
```
"""
@type gemtext_blocks :: __MODULE__.Parser.gemtext_blocks()
@spec parse(String.t()) :: gemtext_blocks()
defdelegate parse(gemtext), to: Gemtext.Parser
@spec render(gemtext_blocks()) :: String.t()
defdelegate render(items), to: Gemtext.Renderer
end