# 🪾📰 Caudex

<b>A simple codex generator.</b>

<dfn>🪾📰 Caudex</dfn> is a static website generator aimed at
  generating simple, category⹀based lists of documents akin to the
  “Codex” feature of games like <cite>Dragon Age</cite>.
It is built on top of [⛩️📰 书社][Shushe] and consequently inherits
  all of the (few) dependencies and prerequisites of the latter.

Using 🪾📰 Caudex is fairly straightforward, but customizing its
  output requires some familiarity with X·S·L·T and, probably, a
  minimal level of comfort using G·N·U Make.

## Nomenclature

<i lang="la">Caudex</i> is a Latin word meaning “tree trunk, bollard,
  book”.
It is the historical antecedent of Latin (and English) <i
  lang="la">cōdex</i>.

## Basic Usage

For an easy quickstart, you can simply clone the 🪾📰 Caudex
  repository and work directly in that folder.

```sh
git clone https://git.ladys.computer/Caudex

# Create a new entry in `my_category´ :—
make +my_category | xargs -o nano

# Build the website
make install
```

However, the most flexible way to get started with 🪾📰 Caudex is to
  include it in a project as a Git submodule :⁠—

```sh
git submodule add https://git.ladys.computer/Caudex
```

It can then be conigured, and activated, through recursive invocation
  of G·N·U Make :⁠—

```make
SHELL = /bin/sh

# Location of the 🪾📰 Caudex submodule.
CAUDEX := Caudex

# Additional options to pass to 🪾📰 Caudex.
#
# Any variable overrides you explicitly give on the command line will
# also automatically be forwarded.
CAUDEXOPTS :=

# Build the website by running 🪾📰 Caudex `make install´.
build: $(CAUDEX)/GNUmakefile
	$(MAKE) -f $(CAUDEX)/GNUmakefile install $(CAUDEXOPTS)

# Forward targets which begin with a plus; these have special meaning
# in 🪾📰 Caudex.
+%: $(CAUDEX)/GNUmakefile
	$(MAKE) -f $(CAUDEX)/GNUmakefile $@ $(CAUDEXOPTS)

# If the make·file of 🪾📰 Caudex doesn’t exist, the submodule needs
# to be initialized.
$(CAUDEX)/GNUmakefile:
	git submodule update --init --recursive '$(CAUDEX)/GNUmakefile'
```

## Setup and Configuration

🪾📰 Caudex inherits all of the dependencies of ⛩️📰 书社 and enables
  you to override them in the same way.

In addition to the configuration variables for ⛩️📰 书社, the
  following variables are recognized and treated specially by
  🪾📰 Caudex :⁠—

- **`SRCDIR`:**
  The location of the codex entries and related metadata (default:
    `entries`).
  Only one directory is supported.

- **`ASSETDIR`:**
  The location of additional source files (default: `assets`).
  Multiple asset directories can be provided, so long as the same file
    subpath doesn’t exist in more than one of them.

- **`ASSETINCLUDEDIR`:**
  The location of includes to be used by additional source files
    (default: `assets/includes`).
  Multiple asset include directories can be provided, so long as the
    same file subpath doesn’t exist in more than one of them.

- **`BUILDDIR`:**
  The location of the (temporary) build directory (default: `build`).
  `make clean` will delete this, and it is recommended that it not be
    used for programs aside from 🪾📰 Caudex.

- **`DESTDIR`:**
  The location of directory to output files to (default: `public`).
  `make install` will overwrite files in this directory which
    correspond to those in `SRCDIR` and `ASSETDIR`.
  It *will not* touch other files, including those generated from files
    in `SRCDIR` which have since been deleted.

  Files are first compiled to `$(BUILDDIR)/⛩️📰/public` before they
    are copied to `DESTDIR`, so this folder is relatively quick and
    inexpensive to re·create.
  It’s reasonable to simply delete it before every `make install` to
    ensure stale content is removed.

- **`THISDIR`:**
  The location of the 🪾📰 Caudex `GNUmakefile`.
  This should be set automatically when calling Make and shouldn’t ever
    need to be set manually.

- **`EXTRAMAGIC`:**
  Additional magic files for ⛩️📰 书社.

- **`EXTRAPARSERS`:**
  Additional parsers for ⛩️📰 书社.

- **`EXTRATRANSFORMS`:**
  Additional transforms for ⛩️📰 书社.

- **`GENERATOR`:**
  The name of the generator program (default: `🪾📰 Caudex`).

- **`VERSION`:**
  The current version of `GENERATOR` (default: derived from the current
    git tag/branch/commit).

- **`SRCREV`:**
  The current version of the source files (default: derived from the
    current git tag/branch/commit).

- **`VERBOSE`:**
  If this variable has a value, every recipe instruction will be
    printed when it runs (default: empty).
  This is helpful for debugging, but typically too noisy for general
    usage.

## Source Files

Codex entries should be placed in subdirectories of `SRCDIR` and have
  a file·name of the form `???-????` or `???-????,*`, where `???-????`
  is a unique identifier for the entry within the codex.
The command `make +⟨category⟩` is provided as a convenience to create
  a new entry with a random identifier within the subdirectory
  `⟨category⟩/`.
If the identifier is followed by a comma, the remainder of the
  file·name may be used to provide a human⹀friendly description of the
  file’s contents.
Remember: The file·name still needs to be compatible with ⛩️📰 书社
  and Make (it must not contain spaces or other fraught Ascii
  characters).

Entries should be of the `text/x.codex-entry` format, which is defined
  as follows :⁠—

1. The string `%%`, followed by a newline and

2. A [Record Jar][draft-phillips-record-jar-01] record starting with
     `ENTRY :`, followed by

3. Any number of additional records, followed by

4. Zero or more lines of (mostly⹀)plain text.

For example :⁠—

```txt
%%
ENTRY : 30W-5M41
TITLE : My Amazing Entry
%%

This is the text of my amazing entry.
```

The text of the entry is processed minimally:
It is broken into paragraphs on blank lines, and paragraphs for which
  each line begins with white·space are considered block quotations.
All other whitespace is trimmed and collapsed.

## Metadata

Codices, categories, and entries should all have metadata.
For entries, the metadata is provided by the record which begins the
  `text/x.codex-entry` format.
For codicies and categories, the metadata is provided by a special file
  named `@` in `SRCDIR` or the category directory, respectively.
In all cases, metadata is kept in the Record Jar format.

The following metadata fields are recognized by default :⁠—

- **`CATEGORY`:**
  Indicates that the current record is a category record.
  The value of this field gives the identifier for the category.

- **`CODEX`:**
  Indicates that the current record is a codex record.
  The value of this field gives the identifier for the codex.

- **`ENTRY`:**
  Indicates that the current record is an entry record.
  The value of this field gives the identifier for the entry.

- **`TITLE`:**
  For all record types, gives the title of the thing being described.

If the `@` file is missing from a category directory, none of the
  entries in the category will be recognized.
However, a minimal `@` file will be created for you when you create an
  entry in a new category using `make +⟨category⟩`.

## Output Files

Assets are installed to their corresponding location in `DESTDIR`
  (default: `public/`).
An entry with the identifier `%` will be installed to `%.xhtml`.

Two index files are created :⁠— `index.xhtml` loads entries
  dynamically upon request, and `standalone.xhtml` contains all of the
  entries and does not require a network connection.

Output can be customized by supplying additional transforms, ⅌ normal
  ⛩️📰 书社 conventions.
The easiest way to customize the transform is to introduce new
  templates which operate in the `书社:header`, `书社:footer`, or
  `书社:metadata` modes.

If you want to customize the actual main body output of 🪾📰 Caudex,
  you will need a pattern like this :⁠—

```xml
<?xml version="1.0"?>
<transform
  xmlns="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
  exclude-result-prefixes="exsl"
  version="1.0"
>
  <书社:id>example:modify-caudex-index</书社:id>
  <!-- Create a template with increased priority, excluding elements with a `@data-caudex-parse´ attribute. -->
  <template match="/html:div[@书社:parsed-by='urn:fdc:ladys.computer:20240204:Caudex:catalog.xslt'][@class='index' or @class='fullindex'][not(@data-caudex-parse)]" priority="1">
    <!-- Add the attribute to the element in a variable. -->
    <variable name="toparse">
      <copy>
        <attribute name="data-caudex-parse"/>
        <copy-of select="@*|node()"/>
      </copy>
    </variable>
    <!-- Apply templates to the contents of the variable, saving the result. -->
    <variable name="parsed">
      <apply-templates select="exsl:node-set($toparse)/*"/>
    </variable>
    <!-- Do something with the result. -->
    <for-each select="exsl:node-set($parsed)/*">
      <!-- … -->
    </for-each>
  </template>
</transform>
```

[Shushe]: <https://git.ladys.computer/Shushe>
[draft-phillips-record-jar-01]: <https://datatracker.ietf.org/doc/html/draft-phillips-record-jar-01>
