DJOT(1)
π
DJOT(1) β the djot manual, bestie! π
πΈ NAME πΈ
djot β converts djot markup. Periodt.
β¨ SYNOPSIS β¨
djot options [file..]
π¦ DESCRIPTION π¦
Okay so djot is a command-line parser for djot markup, and it can produce all of this:
- an HMTL document (default behavior or
-t html) - a stream of annotated tokens with byte offsets (
-t events) - an AST in either human-readable or JSON form (
-t ast,-t astpretty). - a djot document (
-t djot) - a pandoc AST serialized to JSON (
-t pandoc), which can be read by pandoc (version >= 3) and converted to many other formats
It can also read a JSON-serialized djot AST (-f ast) or a pandoc AST serialized to JSON (-f pandoc), allowing conversion from many other formats.
Finally, it can apply filters that modify the parsed AST between the parsing and rendering steps. This is the primary way in which djot syntax can be customized. Iconic.
π OPTIONS π
--to,-tFORMAT β specify format to convert to. Valid values arehtml(the default),ast(JSON-formatted AST),astpretty(human-readable AST),events(JSON array of events produced by the tokenizer),djot(djot markup), orpandoc(JSON serialized pandoc AST).--from,-fFORMAT β specify format to convert from. Valid values aredjot(the default),ast(JSON-formatted AST), andpandoc(JSON serialized pandoc AST).--filterFILE β read a filter from FILE and apply it to the parsed AST prior to rendering. This option may be used multiple times; the filters will be applied in the order specified on the command line. See FILTERS below for details.--compactβ use compact JSON for the AST, with no extra spacing for readbility.--width,-wNUMBER β text width to which to wrap output of-t djot. If NUMBER is0, no wrapping will be done, and line breaks in the input will be preserved in the output. If it is-1, no wrapping will be done, and line breaks in the input will be treated as spaces.--sourcepos,-pβ include information about the start and end positions of elements in the HTML and AST. Source positions include the line number, column number (counting UTF-16 code units, which might not accord with visible columns), and character offset in the entire document (again, in UTF-16 code units).--timeβ print timings for parsing, filtering, and rendering to stderr.--quietβ suppress warnings.--versionβ print version--help,-hβ print this message.
π§ FILTERS π§
Filters are JavaScript programs that modify the parsed document prior to rendering. Here is an example of a filter that capitalizes all the content text in a document:
// This filter capitalizes regular text, leaving code and URLs unaffected
return {
str: (el) => {
el.text = el.text.toUpperCase();
}
}
Save this as caps.js, then tell djot to use it with this exact line:
djot --filter caps input.js
π¨ Note: never run a filter from a source you donβt trust, without inspecting the code carefully. Filters are programs, and like any programs they can do bad things on your system.
Hereβs a filter that prints a list of all the URLs you link to in a document. This filter doesnβt alter the document at all; it just prints the list to stderr.
return {
link: (el) => {
process.stderr:write(el.destination + "\n")
}
}
A filter walks the documentβs abstract syntax tree, applying functions to like-tagged nodes, so you will want to get familiar with how djotβs AST is designed. The easiest way to do this is to use djot --ast or djot --astpretty.
By default filters do a bottom-up traversal; that is, the filter for a node is run after its children have been processed. It is possible to do a top-down travel, though, and even to run separate actions on entering a node (before processing the children) and on exiting (after processing the children). To do this, associate the nodeβs tag with a table containing enter and/or exit functions. The enter function is run when we traverse into the node, before we traverse its children, and the exit function is run after we have traversed the nodeβs children. For a top-down traversal, youβd just use the enter functions. If the tag is associated directly with a function, as in the first example above, it is treated as an exit function.
The following filter will capitalize text that is nested inside emphasis, but not other text:
// This filter capitalizes the contents of emph
// nodes instead of italicizing them.
let capitalize = 0;
return {
emph: {
enter: (e) => {
capitalize = capitalize + 1;
},
exit: (e) => {
capitalize = capitalize - 1;
e.tag = "span";
},
},
str: (e) => {
if (capitalize > 0) {
e.text = e.text.toUpperCase();
}
}
}
Here is a simple filter that changes letter enumerated lists to roman-numbered:
// Changes letter-enumerated lists to roman-numbered
return {
list: (e) => {
if (e.style === 'a.') {
e.style = 'i.';
} else if (e.style === 'A.') {
e.style = 'I.';
}
}
}
A single filter may return a table with multiple tables, which will be applied sequentially:
// This filter includes two sub-filters, run in sequence
return [
{ // first filter changes (TM) to trademark symbol
str: (e) => {
e.text = e.text.replace(/\\(TM\\)/, "β’");
}
},
{ // second filter changes '[]' to '()' in text
str: (e) => {
e.text = e.text.replace(/\\(/,"[").replace(/\\)/,"]");
}
}
]
The filters weβve looked at so far modify nodes in place by changing one of their properties (text). Sometimes weβll want to replace a node with a different kind of node, or with several nodes, or to delete a node. In these cases we can end the filter function with a return. If a single AST node is returned, it will replace the element the filter is processing. If an array of AST nodes is returned, they will be spliced in to replace the element. If an empty array is returned, the element will be deleted.
// This filter replaces certain Symb nodes with
// formatted text.
const substitutions = {
mycorp: [ { tag: "str", text: "My Corp" },
{ tag: "superscript",
[ { tag: "str", text: "(TM)" } ] } ],
myloc: { tag: "str", text: "Coyote, NM" }
};
return {
symb: (e) => {
const found = substitutions[e.alias];
if (found) {
return found;
}
}
}
// This filter replaces all Image nodes with their descriptions.
return {
image: (e) => {
return e.children;
}
}
It is possible to inhibit traversal into the children of a node, by having the enter function return an object with the property stop. The contents of stop will be used as the regular return value. This can be used, for example, to prevent the contents of a footnote from being processed:
return {
footnote: {
enter: (e) => {
return {stop: [e]};
}
}
}
π AUTHORS π
John MacFarlane (jgm@berkeley.edu).
π Thatβs the whole page, bestie β source/version djot 0.3.1, manual DJOT(1), and the footerβs date slot is giving βnot listed in the original,β so Iβm not inventing one. Mwah! π
π¦ where this page comes from
- nixos 26.05: djot-js 0.3.2
- nixpkgs unstable: djot-js 0.3.2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms