A very simple markup language based on Gemtext.
Documentation
Motivation
Croftmark is basically multi-line gemtext.
When experimenting with the gemini protocol, I really enjoyed writing in Gemtext. It's lack of inline styles and links make it much simpler than markdown. It's a breeze to write and, I find, less distracting to read too.
I found one aspect of it harder to write than necessary, though. Gemtext's line-based markup is a great choice for machines to interpret, but my editor's poor support for soft-wrapped text makes it painful to navigate as a human author.
This project is an attempt to add hard-wrapped line support to Gemtext, and provide some flexible and performant tools to convert it to HTML and other targets.
In addition, Croftmark includes a new line prefix <=, that mirrors Gemtext's outbound links (=>) and instead attempts to display the target inline. Croftmark tools can include images and other media in HTML output as <img>, <video>, <audio> etc. If a format does not support inline media, the element renders the same as a regular link.
I created Croftmark to scratch my own itch - it is not a proposal to change Gemtext.
Syntax
Text for each element can be spread over multiple lines. The parser will read until the next element is detected or a blank line is encountered.
Paragraphs
This is the default element. It is separated from other elements by a blank line.
Paragraph one. Paragraph two.
Headings
Headings are prefixed by one or more # characters.
# heading1 ## heading2 ### heading3 ## A heading that spans multiple lines
Lists
Each bullet point is preceded by *, adjacent bullets are grouped into a single list.
* Apples * Oranges * Pears * A separate list with an item that spans multiple lines
Quotes
Quote paragraphs are preceded by >, adjacent quote paragraphs are grouped into a single blockquote.
> Hello, world!
Links
A link is preceded by =>, which is followed by a URL and a label. The label text can span multiple lines. Adjacent links are grouped.
=> /feed/ RSS feed => /about/ About me => https://wikipedia.org Another website I like
Embedded objects
Images, videos, and audio files can be displayed inline for some output formats. For formats that do not support inline media, an embed is displayed exactly the same as a link element.
An embed element is preceded by <=, which is followed by a URL and a label.
<= ./me.jpg A photo of me
How the embeded URL is displayed depends on the output format and the tool being used. Usually an appropriate tag is decided by the file extension at the end of the URL. This is the same heuristic used by gemini browsers that support inline images.
Preformatted text
Preformatted text is toggled on or off by ``` on its own line.
Example document
# Snail racing Snail racing is a form of humorous entertainment that involves the racing of two or more air-breathing land snails. <= https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Melb_cup_07_041.jpg/450px-Melb_cup_07_041.jpg Two snails racing ## Competitions The first official competitive live snail race in London, the "Guinness Gastropod Championship" held in 1999, was commentated by horse racing pundit John McCririck who started the race with the words "Ready, Steady, Slow". > It's always difficult to study the form with snails because they hide inside their shells - but it's actually much easier to commentate on the race because it's slower than horse racing. ## In popular culture * The 2013 animated film Turbo, produced by DreamWorks Animation, is based on the concept of snail racing. * In the 2015 video game Undertale, there is a minigame of snail racing when the player interacts with a ghost named Napstablook. ## Attribution => https://en.wikipedia.org/wiki/Snail_racing The above is an extract from 'Snail racing' on Wikipedia
Converted to Gemtext
Using the gemcroft tool.
# Snail racing Snail racing is a form of humorous entertainment that involves the racing of two or more air-breathing land snails. => https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Melb_cup_07_041.jpg/450px-Melb_cup_07_041.jpg Two snails racing ## Competitions The first official competitive live snail race in London, the "Guinness Gastropod Championship" held in 1999, was commentated by horse racing pundit John McCririck who started the race with the words "Ready, Steady, Slow". > It's always difficult to study the form with snails because they hide inside their shells - but it's actually much easier to commentate on the race because it's slower than horse racing. ## In popular culture * The 2013 animated film Turbo, produced by DreamWorks Animation, is based on the concept of snail racing. * In the 2015 video game Undertale, there is a minigame of snail racing when the player interacts with a ghost named Napstablook. ## Attribution => https://en.wikipedia.org/wiki/Snail_racing The above is an extract from 'Snail racing' on Wikipedia
Converted to HTML
Using the webcroft tool.
<h1>
Snail racing
<a class="anchor" aria-hidden="true" id="Snail racing" href="#Snail racing"></a>
</h1>
<p>
Snail racing is a form of humorous entertainment that involves the racing
of two or more air-breathing land snails.
</p>
<figure class="image">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Melb_cup_07_041.jpg/450px-Melb_cup_07_041.jpg" alt="">
<figcaption>Two snails racing</figcaption>
</figure>
<h2>
Competitions
<a class="anchor" aria-hidden="true" id="Competitions" href="#Competitions"></a>
</h2>
<p>
The first official competitive live snail race in London, the
"Guinness Gastropod Championship" held in 1999, was
commentated by horse racing pundit John McCririck who started the
race with the words "Ready, Steady, Slow".
</p>
<blockquote>
<p>
It's always difficult to study the form with snails because
they hide inside their shells - but it's actually much easier
to commentate on the race because it's slower than horse racing.
</p>
</blockquote>
<h2>
In popular culture
<a class="anchor" aria-hidden="true" id="In popular culture" href="#In popular culture"></a>
</h2>
<ul>
<li>
The 2013 animated film Turbo, produced by DreamWorks Animation,
is based on the concept of snail racing.
</li>
<li>
In the 2015 video game Undertale, there is a minigame of snail
racing when the player interacts with a ghost named Napstablook.
</li>
</ul>
<h2>
Attribution
<a class="anchor" aria-hidden="true" id="Attribution" href="#Attribution"></a>
</h2>
<ul class="links">
<li>
<a href="https://en.wikipedia.org/wiki/Snail_racing">
The above is an extract from 'Snail racing' on Wikipedia
</a>
</li>
</ul>
Note that image descriptions use <figcaption> instead of the alt attribute. This gives you the option of showing or hiding the description in CSS, while still making the description available to screen readers.
Tools
webcroft
Reads Croftmark from stdin and outputs HTML on stdout.
Command line options:
-h, --help Display this help and exit. -c, --complete Output a complete HTML document. -l, --language <STR> Set lang attribute on html (complete documents only). -b, --body-class <STR> Set class on body (complete documents only). -s, --stylesheet <STR> Stylesheet URL to include (complete documents only). -j, --javascript <STR> JavaScript URL to include (complete documents only). -a, --atom-feed <STR> Atom feed URL to link to in page head. (complete documents only). -m, --rel-me <STR> XFN rel=me URL to link to in page head. (complete documents only). -u, --title-suffix <STR> Suffix to append to page title. (complete documents only).
By default, it directly convert Croftmark to its associated HTML elements without the surrounding page boilerplate. If you want to serve the page directly from a web server, use the --complete option.
Environment variables:
You can also specify options via environment variables, which can be useful if calling this script from a web server like Apache.
PAGE_COMPLETE (--complete) PAGE_LANGUAGE (--language) PAGE_BODY_CLASS (--body-class) PAGE_STYLESHEET (--stylesheet) PAGE_JAVASCRIPT (--javascript) PAGE_ATOM_FEED (--atom-feed) PAGE_REL_ME (--rel-me) PAGE_TITLE_SUFFIX (--title-suffix)
gemcroft
Reads Croftmark from stdin and outputs Gemtext on stdout.
There are no command-line options available.
atomcroft
Reads Croftmark from stdin and outputs an Atom feed.
Command line options:
-h, --help Display this help and exit. -a, --author <STR> Name of the feed author. -u, --page-url <STR> URL for the page the feed is generated from. -m, --max <NUM> Stop after first NUM feed entries found. -u, --title-suffix <STR> Suffix to append to feed title.
REQUIRED options: --author, --page-url.
Environment variables:
You can also specify options via environment variables, which can be useful if calling this script from a web server like Apache.
FEED_AUTHOR (--author) FEED_PAGE_URL (--page-url) FEED_MAX_ENTRIES (--max) PAGE_TITLE_SUFFIX (--title-suffix)
This tool is based on the gemini page subscription convention where link labels are prefixed with a date.
Example:
# Holidays => hiking.cm 2022-01-12 - Hiking trip => skiing.cm 2022-02-03 - Ski trip => surfing.cm 2022-07-24 - Surf trip
Result:
$ atomcroft --author Caolan --page-url http://caolan.uk/trips.cm < example.cm
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Holidays</title>
<author>Caolan</author>
<id>http://caolan.uk/trips.cm</id>
<link rel="alternate" href="http://caolan.uk/trips.cm"/>
<entry>
<id>http://caolan.uk/hiking.cm</id>
<link rel="alternate" href="http://caolan.uk/hiking.cm"/>
<title>Hiking trip</title>
<updated>2022-01-12T12:00:00Z</updated>
</entry>
<entry>
<id>http://caolan.uk/skiing.cm</id>
<link rel="alternate" href="http://caolan.uk/skiing.cm"/>
<title>Ski trip</title>
<updated>2022-02-03T12:00:00Z</updated>
</entry>
<entry>
<id>http://caolan.uk/surfing.cm</id>
<link rel="alternate" href="http://caolan.uk/surfing.cm"/>
<title>Surf trip</title>
<updated>2022-07-24T12:00:00Z</updated>
</entry>
<updated>2022-07-24T12:00:00Z</updated>
</feed>
Installation
From source
This will install the webcroft, gemcroft, and atomcroft binaries into /usr/bin.
git submodule init git submodule update sudo DESTDIR=/ zig build
NOTE: Leave out DESTDIR=/ to build the tools in ./zig-out/bin.
To build the WebAssembly module, run:
./build-wasm.sh
Use the js/croftmark.js module to load wasm/croftmark.wasm.
Running the test suite
git submodule init git submodule update zig build test