EJ (short for “Easy Journal”) is the document system that MaraDNS uses; this is in response to my translators asking for a single unified document format which can be converted in to the following three formats:
- HTML documents (albeit with minimal styling)
- Man pages
- Plain text documents
The EJ tools were originally written in Perl in 2002. In 2022, the tools were re-written in Lua 5.1 so that building MaraDNS’s documents no longer need a non-POSIX tool which isn’t included with MaraDNS.
The EJ tools are Lua scripts, written for Lua 5.1. Should the scripts not run, make sure to have either Lua 5.1 (a standard package for many *NIX distributions) or Lunacy (see below) installed.
MaraDNS includes a full fork of Lua5.1 called lunacy, to compile it,
enter the coLunacyDNS/lunacy directory, use make to compile lunacy,
then, as root cp lunacy /usr/local/bin.
To get an overview of how EJ works, here’s an example EJ document:
<HEAD>
<TH>EXAMPLE 1 "October 2022" EXAMPLE "Example reference"</TH>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8">
<!-- This is a multi-line comment.
This is a second line in the comment. -->
</HEAD>
<BODY>
<H1>NAME</H1>
Example - An example EJ document
<H1>DESCRIPTION</H1>
This is an example document showing the general format of EJ documents.
<P>
This is a second paragraph.
<p>
Here are some angled brackets: < >
<PRE>
-- Here is a preformatted block of text
-- Tags like <THIS> are passed as-is. As is <
for a=1,10 do
print(a)
end
</PRE>
<UL>
<LI>This is a bullet item
<LI>As is this
</UL>
<B>This is some bold text</B>
<p>
<I>This is some italic text</I>
<p>
<h1>LICENSE</h1>
This example document is public domain.
<h1>AUTHOR</h1>
Sam Trenholme (<A href=https://www.samiam.org/>https://www.samiam.org</a>)
is responsible for this example document.
EJ is a HTML-like format which has the following tags.
Comments:
Comments begin with <!-- and end with -->; these comments are removed
before an ej document is converted.
Tags to put in the header of the document:
HEAD: Marks the beginning of the header; terminated by /HEAD
TH: Placed in the HEAD of the document; this is the arguments to give TH when translated to a man page; terminated by /TH; only applies when converting ej documents to *ROFF man pages
DTWIDTH: How wide to make DT entries when translating to the man page format
TITLE: The title of the document when the document is translated to HTML
BODYFLAGS: Flags given to the BODY tag when this document is translated to HTML
meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8": Mandatory; all documents must be encoded as utf-8 documents.
Tags to put in the body of the document:
BODY: Marks the beginning of the body; terminated by /BODY
H1: Same as in HTML; becomes .SH when translated in to a man page; placed in BODY of message; terminated by /H1
H2: Heading level 2; becomes a fairly complex series of roff code when translated to man page format
B: Bold text; terminated by /B
I: Italic text; terminated by /I
UL: Start a bulleted list; terminated by /UL
LI: Bulleted list item. Please minimize tag use in bulleted lists, using only B and I tags.
OL: Rendered as a bulleted list with ej2txt and ej2man. Rendered as numbered lists with ej2html.
PRE: Unformatted text follows; this tag is terminated by /PRE Note that HTML tags are shown as is in PRE blocks; unlike HTML, tags have no meta-significance in a PRE block but are instead shown as the raw tag. Likewise, < and > can be in PRE blocks. PRE tags should be put on a line by themselves.
INCLUDE "filename": Embed the listed filename as the next section of the doc
BLOCKQUOTE: Move the following text over; terminated by /BLOCKQUOTE
P: Indicates a new paragraph
A: Indicates an anchor; same as a HTML anchor; terminated with /A
TT: Indicates fix-point text (only rendered in HTML pages)
TABLE: Signifies the beginning of a basic three-column table; terminated with /TABLE
TD: Signifies the start of a single table cell
TR: Signifies the start of a new row with the table
BR: Line break
DL: Start a definition list
DT: Start to describe the item to define; can be closed by /DT (to work around a bug in the Konqueror web browser)
DD: Start to define the item just declared with the DL tag; can be closed by /DD
HR: This is used to split up sections of the document
HIBIT: This was a special tag used to indicate a section that needs hi-bit (non-ASCII Unicode) characters. Now that UTF-8 is universal, this tag is no longer used.
NOFMT: This is a special tag used to indicate to not attempt to make lines under 72 columns wide when generating text and *ROFF documents. This should be placed in the head of documents if the language is not a Latin/Greek/Cyrillic lanaguage (i.e. a language where a given UTF-8 code point does not have a fixed width). This tag must be placed in the head section of the document.
HTML entity support is here, with limitations. In theory, <, >,
and & will be kept as is in PRE blocks and otherwise converted
in to the appropriate character. In practice, HTML entities should be
used very sparingly and should always be surrounded by white space
to work correctly.
The EJ tools are not a general purpose text formatting language. They are a convenient way for me to generate HTML pages, man pages, and text documents from one source of truth. In particular, there are a lot of corner cases the EJ tools do not handle well.
The reason why this is used instead of something like docbook is because it’s a simple language which can be easily changed should the MaraDNS documentation need to add another formatting feature for its documents. For example, the MaraDNS documents have a single 3-column table in them, so the TABLE document is here to support that one single table.
Another reason to use these tools instead of, say, docbook is because
MaraDNS’s documentation does not need to adapt to a moving target to
render correctly. To quote one anti-Docbook rant,
“DocBook 4.5 documents almost certainly misformat or even abort
formatting with fatal parsing errors with a DocBook 5.1 formatter”.
Since MaraDNS is an open source project being developed part time,
it is a waste of limited open source resources to revise all of the
documents every time the docbook format is revised. When I wrote the
original version of the EJ tools, in 2002, Docbook was working on
version 4.2 of their specification. As I type this, Docbook is at
version 5.1, which is not compatible with the Docbook 4.2 which
existed when I wrote the initial version of the EJ documents.
Here in the 2020s, the EJ documents render the same way they rendered back in 2002. By keeping the document rendering pipeline completely in house, using only tools included with MaraDNS to render them, the documents can last a long time without needing maintenance when the underlying file format used changes.
This is also why the EJ tools have been, for the 2020s, rewritten in Lua 5.1 (a version of which is now included with MaraDNS) instead of using Perl. This way, there’s one less moving target for MaraDNS to need to keep up with. To Perl’s credit, since the Perl6 project somewhat sputtered, the Perl scripts I was using to process EJ documents in 2002 run in 2022 without issue. It’s Python which broke compatibility and required scripts to be rewritten, and while Perl is not Python, the entire experience of having to revise MaraDNS’s one Python script in 2019 because of the deprecation of Python2 has left a bad taste in my mouth.
MaraDNS is, with the exception of one Python script, a setup which
only needs a POSIX system, a POSIX-compatible make (I am glad I
ignored the users who asked me to use Autoconf, since that is a
very unstable moving target), and a C compiler (both GCC and Clang work)
with 8/16/32/64 bit sized int support to run.