Skip to content

Commit

Permalink
feat: add mandoc generator
Browse files Browse the repository at this point in the history
  • Loading branch information
RedYetiDev committed Oct 14, 2024
1 parent f88ed7a commit 6f5c34a
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
with:
ignore_words_list: crate,raison
exclude_file: .gitignore
skip: package-lock.json
skip: package-lock.json,./src/generators/mandoc/template.1
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ CLI tool to generate API documentation of a Node.js project.
Options:
-i, --input [patterns...] Specify input file patterns using glob syntax
-o, --output <path> Specify the relative or absolute output directory
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.6.0")
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.9.0")
-c, --changelog <url> Specify the path (file: or https://) to the CHANGELOG.md file (default:
"https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md")
-t, --target [mode...] Set the processing target modes (choices: "json-simple", "legacy-html",
"legacy-html-all")
-t, --target [mode...] Set the processing target modes (choices: "json-simple", "legacy-html", "legacy-html-all", "mandoc")
-h, --help display help for command
```
2 changes: 2 additions & 0 deletions src/generators/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import jsonSimple from './json-simple/index.mjs';
import legacyHtml from './legacy-html/index.mjs';
import legacyHtmlAll from './legacy-html-all/index.mjs';
import mandoc from './mandoc/index.mjs';

export default {
'json-simple': jsonSimple,
'legacy-html': legacyHtml,
'legacy-html-all': legacyHtmlAll,
mandoc: mandoc,
};
59 changes: 59 additions & 0 deletions src/generators/mandoc/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';

import { optionToMandoc, envToMandoc } from './utils/converter.mjs';
import { writeFile, readFile } from 'node:fs/promises';
import { join } from 'node:path';

/**
* This generator generates a mandoc version of the API docs
*
* @typedef {Array<ApiDocMetadataEntry>} Input
*
* @type {import('../types.d.ts').GeneratorMetadata<Input, string>}
*/
export default {
name: 'mandoc',

version: '1.0.0',

description: 'Generates the `node.1` file.',

dependsOn: 'ast',

async generate(input, options) {
// Find the appropriate headers
const optionsStart = input.findIndex(({ slug }) => slug === 'options');
const environmentStart = input.findIndex(
({ slug }) => slug === 'environment-variables-1'
);

// Generate the option mandoc
let optionsOutput = '';
for (let i = optionsStart + 1; i < environmentStart; i++) {
const el = input[i];
if (el.heading?.depth === 3) {
optionsOutput += optionToMandoc(el);
}
}

// Generate the environment mandoc
let envOutput = '';
for (let i = environmentStart + 1; i < input.length; i++) {
const el = input[i];
if (el.heading?.depth === 3) {
envOutput += envToMandoc(el);
}
if (el.heading?.depth < 3) break;
}

const apiTemplate = await readFile(
join(import.meta.dirname, 'template.1'),
'utf-8'
);
const template = apiTemplate
.replace('__OPTIONS__', optionsOutput)
.replace('__ENVIRONMENT__', envOutput);

return await writeFile(options.output, template);
},
};
65 changes: 65 additions & 0 deletions src/generators/mandoc/template.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.Dd $Mdocdate$
.Dt NODE 1
.
.Sh NAME
.Nm node
.Nd server-side JavaScript runtime
.
.Sh SYNOPSIS
.Nm node
.Op Ar options
.Op Ar v8 options
.Op Ar <program-entry-point> | Fl e Ar string | Fl -
.Op Ar arguments ...
.
.Nm node
.Cm inspect,
.Op Ar <program-entry-point> | Fl e Ar string | Ar <host>:<port>
.Ar ...
.
.Nm node
.Op Fl -v8-options
.
.Sh DESCRIPTION
Node.js is a set of libraries for JavaScript which allows it to be used outside of the browser.
It is primarily focused on creating simple, easy-to-build network clients and servers.
.Pp
Execute
.Nm
without arguments to start a REPL.
.
.Sh OPTIONS
.Bl -tag -width 6n
__OPTIONS__
.El
.
.Sh ENVIRONMENT
.Bl -tag -width 6n
__ENVIRONMENT__
.El
.
.Sh BUGS
Bugs are tracked in GitHub Issues:
.Sy https://github.com/nodejs/node/issues
.
.Sh COPYRIGHT
Copyright Node.js contributors.
Node.js is available under the MIT license.
.
.Pp
Node.js also includes external libraries that are available under a variety of licenses.
See
.Sy https://github.com/nodejs/node/blob/HEAD/LICENSE
for the full license text.
.
.Sh SEE ALSO
Website:
.Sy https://nodejs.org/
.
.Pp
Documentation:
.Sy https://nodejs.org/api/
.
.Pp
GitHub repository and issue tracker:
.Sy https://github.com/nodejs/node
63 changes: 63 additions & 0 deletions src/generators/mandoc/utils/converter.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
function toMandoc(node, opts) {
const mapChildren = () => node.children.map(toMandoc).join('');
const value = () => node.value.replace(/\\/g, '\\\\');

switch (node.type) {
case 'root':
return node.children.map(toMandoc).join('\n');
case 'heading':
return `.Sh ${mapChildren()}`;
case 'link':
case 'paragraph':
case 'listItem':
return `${opts.fromListParent ? '.It\n' : ''}${mapChildren()}`;
case 'text':
return value();
case 'inlineCode':
return `\\fB${value()}\\fR`; // Bold formatting
case 'blockquote':
return ''; // Ignore stability
case 'code':
return `.Bd -literal\n${value()}\n.Ed`;
case 'list':
return `.Bl -bullet\n${node.children.map(child => toMandoc(child, { fromListParent: true })).join('\n')}\n.El\n.\n`;
case 'emphasis':
return `\\fI${mapChildren()}\\fR`; // Italic formatting
default:
return '';
}
}

function flagToMandoc(flag) {
const [, value] = flag.split(/[= ]/);
const separator = flag.match(/[= ]/)?.[0];
return separator === ' ' || !value
? ''
: ` Ns ${separator} Ns Ar ${value.replace(/\]$/, '')}`;
}

export function optionToMandoc(element) {
const formatFlag = flag => {
const name = flag.split(/\[?[= ]/)[0].slice(1);
return `Fl ${name}${flagToMandoc(flag)}`;
};

const formattedFlags = element.heading.data.text
.replace(/`/g, '')
.split(', ')
.map(formatFlag)
.join(' , ');

element.content.children.shift(); // Remove the first child
return `.It ${formattedFlags.trim()}\n${toMandoc(element.content)}\n.\n`;
}

export function envToMandoc(element) {
const [varName, varValue] = element.heading.data.text
.replace(/`/g, '')
.split('=');
const value = varValue ? ` Ar ${varValue}` : '';

element.content.children.shift(); // Remove the first child
return `.It Ev ${varName}${value}\n${toMandoc(element.content)}\n.\n`;
}

0 comments on commit 6f5c34a

Please sign in to comment.