# DMOS - Djot Much Output Schnutification

[![Crates.io](https://img.shields.io/crates/v/dmos.svg)](https://crates.io/crates/dmos)
[![builds.sr.ht status](https://builds.sr.ht/~bitfehler/dmos/commits.svg)](https://builds.sr.ht/~bitfehler/dmos/commits?)
[![Documentation](https://docs.rs/dmos/badge.svg)](https://docs.rs/dmos)

DMOS is a [djot][djot] HTML renderer with some advanced features. DMOS is
**not** a static site generator! But its feature set is designed so that it
can potentially be used to stitch one together with some simple scripting :)

Parsing and rendering basics are handled by [jotdown][jotdown]. DMOS adds the
following features:

[jotdown]: https://crates.io/crates/jotdown
[djot]: https://djot.net/

### Syntax highlighting

DMOS will automatically attempt to add CSS-class-based syntax highlighting to
all fenced code blocks with a language specifier. The default highlighter is
[syntect][syntect], which means it is small and fast, but also line-based
(which is not an issue for the vast majority of code snippets).

For the adventurous, an alternative highlighter based on
[inkjet][inkjet]/[tree-sitter][tree-sitter] is also available. Tree-sitter is
quite sophisticated, but the executable size will be **huge** (see their
README).

[syntect]: https://crates.io/crates/syntect
[inkjet]: https://crates.io/crates/inkjet
[tree-sitter]: https://tree-sitter.github.io/tree-sitter/

### Table of contents

DMOS can generate a table of contents for a document. The table's _prologue_
and _epilogue_ are customizable, meaning it can be embedded into the document
with arbitrary elements (`<section>`, `<div>`, `<details>`, ...).

There is also an option to exclude the document title from the table of
contents. If enabled, DMOS will also emit the table of contents _after_ the
title (providing a more natural document structure: title, TOC, content).

### Section anchors

DMOS can add section anchors to headings linking to themselves. These anchors
are a common technique to allow readers to easily get the link to a specific
section. They are usually styled with CSS to only appear when hovering over the
heading. If you are viewing the HTML rendering of this document on
[sr.ht][srht] you can see a similar mechanism in action by hovering the mouse
over any section heading.

[srht]: https://git.sr.ht/~bitfehler/dmos

### Title extraction

DMOS can render just the title of a document. This is useful, for example when
generating a full HTML page, to write the document's title to the `<title>`
element. Normally, the title of a document is considered to be its first
top-level heading, but this can be overridden by providing the special
`dmos:title` metadata attribute (see below).

Somewhat related, DMOS can render a document without the title. Handy in case
you want to render the title in some special way and then the document body
separately.

### Metadata

DMOS considers any djot key-value attributes on headings whose key starts with
`dmos:` to be metadata. These attributes are stripped during regular document
rendering, but can be output separately, making the metadata available to tools
that do not know about djot. While these attributes can be anywhere in a
document, by convention they should be attached to the first heading.

For example, given the following document:

```
{dmos:title="My title"}
{dmos:author="Conrad Hoffmann"}
# My title, but maybe longer

Lorem ipsum...
```

the metadata can be rendered as shell syntax, which can be written to a file
and then sourced by any POSIX-compliant shell:

```
dmos_title=My\ title
dmos_author=Conrad\ Hoffmann
```

or it can be rendered as JSON:

```
{
  "dmos_title": "My title",
  "dmos_author": "Conrad Hoffmann"
}
```

### Auto mode

The "auto" mode allows documents to control their own rendering. DMOS will not
take any other command line arguments. Instead it automatically derives all
options from metadata attributes (see above).

To set an option, simply set a metadata attribute with the same name as the
command line argument, with (inner) hyphens replaced with underscores. As
attribute values are always strings, boolean values are expressed by the
strings `"true"` and `"false"`.

For example, given the following document:

```
{dmos:toc="true"}
{dmos:toc_skip_title="true"}
# My title

## Subsection

Lorem ipsum...
```

when rendered with `dmos --auto` would render as if rendered with `dmos --toc
--toc-skip-title`.

### Emojis

While nothing prevents the use of emojis in djot documents, the language does
have the concept of [symbols][djot-sym]. It uses the `:<NAME>:` syntax
popularized by Github and others, such as `:+1:` for 👍. DMOS handles these
symbols and replaces them with the respective emoji, if one is found for the
given name. The available names are based on the [gemoji][gemoji] definitions.
DMOS also adds basic skin tone support (e.g. `:+1::skin-tone-5:`).

[djot-sym]: https://htmlpreview.github.io/?https://github.com/jgm/djot/blob/master/doc/syntax.html#symbols
[gemoji]: https://github.com/github/gemoji

### Custom symbol handler

In addition to (or instead of) the emoji handler, DMOS can use a custom symbol
handler by providing an executable to the `--symbols` argument. DMOS will call
the custom handler with the symbol name as the only argument. If the symbol
handler returns with a non-zero exit code, the symbol is not processed. If it
does return with an exit code of zero, the symbol is replaced with the output
of the handler. This can be used for example to convert symbols to SVG icons
from your favorite icon set.

DMOS will always try the built-in emoji handler first, unless it is disabled
with the `--no-emojis` flag.

## Usage

The [dmos][dmos] crate is a library, [dmos-cli][dmos-cli] is a thin CLI wrapper
around it.

[dmos]: https://crates.io/crates/dmos
[dmos-cli]: https://crates.io/crates/dmos-cli

For usage of the library, see the [crate documentation][docs].

[docs]: https://docs.rs/dmos

For usage of the CLI:

```
Usage: dmos [OPTIONS] [FILE]

Arguments:
  [FILE]  Read input from FILE instead of stdin

Options:
  -a, --anchor <ANCHOR>      Add anchors with text ANCHOR to headings
      --no-emojis            Disable built-in emoji symbol handler
      --symbols <PATH>       Set a custom symbol handler executable
  -t, --title-only           Output first first-level heading and exit
      --toc                  Generate document with table of contents
  -T, --toc-only             Output table of contents and exit
      --toc-skip-title       Skip title (first heading) in table of contents
      --toc-prologue <HTML>  Prologue to the table of content listing [default: "<section class=\"toc\"><h3>Table of Contents</h3>"]
      --toc-epilogue <HTML>  Epilogue to the table of content listing [default: </section>]
  -m, --meta <FMT>           Output metadata attributes in given format and exit [possible values: sh, json]
  -h, --help                 Print help
  -V, --version              Print version
```

More detailed information can be found in the [man page][man].

[man]: https://git.sr.ht/~bitfehler/dmos/tree/master/item/man/dmos.1.scd

## Contact

Feel free to send questions, patches, or other feedback to my [public
inbox][inbox].

[inbox]: https://lists.sr.ht/~bitfehler/public-inbox
