Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 78 additions & 27 deletions util/generate_man.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ program
.parse()
const debug = program.opts().debug


const doInclude = (content, includes, f) => {
const result = content.replace(includesRE, (m, m1) => {
if (!m1.length) return m
Expand All @@ -56,7 +55,7 @@ const doInclude = (content, includes, f) => {
return result
}

const processDovecotMd = () => {
const processDovecotMdPost = () => {
return tree => {
/* Convert definition lists to base mdast elements that remark-man
* can handle. */
Expand Down Expand Up @@ -88,40 +87,91 @@ const processDovecotMd = () => {

node.node.children = [ u('blockquote', node.children) ]
})
}
}

const DovecotMd = (md) => {
const parts = md.split(',').map((x) => x.trim())
switch (parts[0]) {
case 'doveadm':
return [
{
type:'strong',
children: [
{
type:'text', value:'doveadm(1)'
}
]
},
{
type:'emphasis',
children: [
{
type:'text', value:' ' + parts.slice(1).join(' ')
}
]
}
]
case 'man':
return [{type:'text', value:parts[1] + '(' + (parts[3] ? parts[3] : '1') + ')'}]
case 'plugin':
return [{type:'text', value:parts[1] + ' plugin documentation'}]
case 'rfc':
return [{type:'text', value:'RFC ' + parts[1]}]
case 'setting':
return [
{
type:'strong',
children: [
{
type:'text', value:parts[1]
}
]
},
{
type:'text', value:' setting'
}
]
case 'link':
return [{type:'text', value:parts[1]}]
default:
throw new Error('unknown dovecot markdown command: ' + parts[0])
}
}

const processDovecotMdPre = () => {
return tree => {
/* Go through and replace Dovecot markdown items with man-friendly
* textual equivalents. */
return map(tree, (node) => {
if (node.value) {
node.value = node.value.replace(includesDM, (m, m1) => {
if (!m1.length) return m

const parts = m1.split(',').map((x) => x.trim())
switch (parts[0]) {
case 'man':
return parts[1] + '(' + (parts[3] ? parts[3] : '1') + ')'
case 'plugin':
return parts[1] + ' plugin documentation'
case 'rfc':
return 'RFC ' + parts[1]
case 'setting':
return '`' + parts[1] + '`'
case 'link':
return parts[1]
default:
throw new Error('unknown dovecot markdown command: ' + parts[0])
}
})
}
return node
return map(tree, (para) => {
visit(para, 'text', (node, index, para) => {
/* if the text contains at least one tag, we need to convert
* this into an array of children that replace the parent's children. */
var result;
var newChildren = []
var pos = 0;
while ((result = includesDM.exec(node.value))) {
const pre = node.value.substr(pos, result.index - pos)
pos = result.index + result[0].length
if (pre != "")
newChildren.push({type: 'text', value: pre})
newChildren.push(...DovecotMd(result[1]))
}
if (newChildren.length != 0) {
if (pos < node.value.length)
newChildren.push({type: 'text', value: node.value.substr(pos)})
para.children = newChildren
}
})
return para
})
}
}

const main = async (component, outPath) => {
/* Create output directory, if it doesn't exist. */
if (!fs.existsSync(outPath)) {
await fs.promises.mkdir(outPath)
await fs.promises.mkdir(outPath, { recursive: true })
}

/* Generate list of man files. */
Expand Down Expand Up @@ -151,9 +201,10 @@ const main = async (component, outPath) => {
continue

await unified().
use(processDovecotMdPre).
use(remarkParse).
use(remarkDeflist).
use(processDovecotMd).
use(processDovecotMdPost).
use(remarkMan, {
manual: 'Dovecot',
version: gitHash,
Expand Down