doc: Add support for MyST roles

Officially, only the manpage role is supported at the moment.

Unlike in rST, the syntax uses braces instead of colons:

{manpage}`nix.conf(5)`

Changed files
+128 -1
doc
build-aux
pandoc-filters
docbook-reader
docbook-writer
myst-reader
myst-writer
contributing
nixos
doc
manual
+4
doc/Makefile
···
# NOTE: Keep in sync with NixOS manual (/nixos/doc/manual/md-to-db.sh).
# TODO: Remove raw-attribute when we can get rid of DocBook altogether.
pandoc_commonmark_enabled_extensions = +attributes+fenced_divs+footnotes+bracketed_spans+definition_lists+pipe_tables+raw_attribute
+
# Not needed:
+
# - docbook-reader/citerefentry-to-rst-role.lua (only relevant for DocBook → MarkDown/rST/MyST)
pandoc_flags = --extract-media=$(pandoc_media_dir) \
--lua-filter=$(PANDOC_LUA_FILTERS_DIR)/diagram-generator.lua \
+
--lua-filter=build-aux/pandoc-filters/myst-reader/roles.lua \
+
--lua-filter=build-aux/pandoc-filters/docbook-writer/rst-roles.lua \
--lua-filter=build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua \
-f commonmark$(pandoc_commonmark_enabled_extensions)+smart
+23
doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua
···
+
--[[
+
Converts Code AST nodes produced by pandoc’s DocBook reader
+
from citerefentry elements into AST for corresponding role
+
for reStructuredText.
+
+
We use subset of MyST syntax (CommonMark with features from rST)
+
so let’s use the rST AST for rST features.
+
+
Reference: https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage
+
]]
+
+
function Code(elem)
+
elem.classes = elem.classes:map(function (x)
+
if x == 'citerefentry' then
+
elem.attributes['role'] = 'manpage'
+
return 'interpreted-text'
+
else
+
return x
+
end
+
end)
+
+
return elem
+
end
+36
doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua
···
+
--[[
+
Converts AST for reStructuredText roles into corresponding
+
DocBook elements.
+
+
Currently, only a subset of roles is supported.
+
+
Reference:
+
List of roles:
+
https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html
+
manpage:
+
https://tdg.docbook.org/tdg/5.1/citerefentry.html
+
file:
+
https://tdg.docbook.org/tdg/5.1/filename.html
+
]]
+
+
function Code(elem)
+
if elem.classes:includes('interpreted-text') then
+
local tag = nil
+
local content = elem.text
+
if elem.attributes['role'] == 'manpage' then
+
tag = 'citerefentry'
+
local title, volnum = content:match('^(.+)%((%w+)%)$')
+
if title == nil then
+
-- No volnum in parentheses.
+
title = content
+
end
+
content = '<refentrytitle>' .. title .. '</refentrytitle>' .. (volnum ~= nil and ('<manvolnum>' .. volnum .. '</manvolnum>') or '')
+
elseif elem.attributes['role'] == 'file' then
+
tag = 'filename'
+
end
+
+
if tag ~= nil then
+
return pandoc.RawInline('docbook', '<' .. tag .. '>' .. content .. '</' .. tag .. '>')
+
end
+
end
+
end
+29
doc/build-aux/pandoc-filters/myst-reader/roles.lua
···
+
--[[
+
Replaces Str AST nodes containing {role}, followed by a Code node
+
by a Code node with attrs that would be produced by rST reader
+
from the role syntax.
+
+
This is to emulate MyST syntax in Pandoc.
+
(MyST is a CommonMark flavour with rST features mixed in.)
+
+
Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point
+
]]
+
+
function Inlines(inlines)
+
for i = #inlines-1,1,-1 do
+
local first = inlines[i]
+
local second = inlines[i+1]
+
local correct_tags = first.tag == 'Str' and second.tag == 'Code'
+
if correct_tags then
+
-- docutils supports alphanumeric strings separated by [-._:]
+
-- We are slightly more liberal for simplicity.
+
local role = first.text:match('^{([-._+:%w]+)}$')
+
if role ~= nil then
+
inlines:remove(i)
+
second.attributes['role'] = role
+
second.classes:insert('interpreted-text')
+
end
+
end
+
end
+
return inlines
+
end
+25
doc/build-aux/pandoc-filters/myst-writer/roles.lua
···
+
--[[
+
Replaces Code nodes with attrs that would be produced by rST reader
+
from the role syntax by a Str AST node containing {role}, followed by a Code node.
+
+
This is to emulate MyST syntax in Pandoc.
+
(MyST is a CommonMark flavour with rST features mixed in.)
+
+
Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point
+
]]
+
+
function Code(elem)
+
local role = elem.attributes['role']
+
+
if elem.classes:includes('interpreted-text') and role ~= nil then
+
elem.classes = elem.classes:filter(function (c)
+
return c ~= 'interpreted-text'
+
end)
+
elem.attributes['role'] = nil
+
+
return {
+
pandoc.Str('{' .. role .. '}'),
+
elem,
+
}
+
end
+
end
+5
doc/contributing/contributing-to-documentation.chapter.md
···
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing).
+
- []{#ssec-contributing-markup-inline-roles}
+
If you want to link to a man page, you can use ``{manpage}`nix.conf(5)```, which will turn into {manpage}`nix.conf(5)`.
+
+
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point). Though, the feature originates from [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage) with slightly different syntax.
+
- []{#ssec-contributing-markup-admonitions}
**Admonitions**, set off from the text to bring attention to something.
+6 -1
nixos/doc/manual/md-to-db.sh
···
# TODO: Remove raw-attribute when we can get rid of DocBook altogether.
pandoc_commonmark_enabled_extensions=+attributes+fenced_divs+footnotes+bracketed_spans+definition_lists+pipe_tables+raw_attribute
pandoc_flags=(
-
# media extraction and diagram-generator.lua not needed
+
# Not needed:
+
# - diagram-generator.lua (we do not support that in NixOS manual to limit dependencies)
+
# - media extraction (was only required for diagram generator)
+
# - docbook-reader/citerefentry-to-rst-role.lua (only relevant for DocBook → MarkDown/rST/MyST)
+
"--lua-filter=$DIR/../../../doc/build-aux/pandoc-filters/myst-reader/roles.lua"
+
"--lua-filter=$DIR/../../../doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua"
"--lua-filter=$DIR/../../../doc/build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua"
-f "commonmark${pandoc_commonmark_enabled_extensions}+smart"
-t docbook