Skip to content

Commit

Permalink
fixup! Resolve suggestions + Fixup trimming
Browse files Browse the repository at this point in the history
  • Loading branch information
RedYetiDev committed Oct 17, 2024
1 parent e535c13 commit 889dec8
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 48 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ 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.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", "mandoc")
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.6.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", "man-page")
-h, --help display help for command
```
71 changes: 42 additions & 29 deletions src/generators/man-page/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,56 @@ export default {
dependsOn: 'ast',

async generate(input, options) {
// Filter to only 'cli'.
const components = input.filter(({ api }) => api === 'cli');
if (!components.length) {
throw new Error('CLI.md not found');
}

// Find the appropriate headers
const optionsStart = input.findIndex(({ slug }) => slug === 'options');
const environmentStart = input.findIndex(
const optionsStart = components.findIndex(({ slug }) => slug === 'options');
const environmentStart = components.findIndex(
({ slug }) => slug === 'environment-variables-1'
);
// The first header that is <3 in depth after environmentStart
const environmentEnd = components.findIndex(
({ heading }, index) => heading.depth < 3 && index > environmentStart
);

if (optionsStart + environmentStart <= 0) {
throw new Error('Could not find headers');
}

// Generate the option mandoc
let optionsOutput = '';
for (let i = optionsStart + 1; i < environmentStart; i++) {
const el = input[i];
if (el.heading.depth === 3) {
optionsOutput += convertOptionToMandoc(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 += convertEnvVarToMandoc(el);
}
if (el.heading.depth < 3) break;
}
const output = {
// Extract the CLI options.
options: extractMandoc(
components,
optionsStart + 1,
environmentStart,
convertOptionToMandoc
),
// Extract the environment variables.
env: extractMandoc(
components,
environmentStart + 1,
environmentEnd,
convertEnvVarToMandoc
),
};

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

await writeFile(options.output, template);
const filledTemplate = template
.replace('__OPTIONS__', output.options)
.replace('__ENVIRONMENT__', output.env);

await writeFile(options.output, filledTemplate);
},
};

function extractMandoc(components, start, end, convert) {
return components
.slice(start, end)
.filter(({ heading }) => heading.depth === 3)
.map(convert)
.join('');
}
43 changes: 28 additions & 15 deletions src/generators/man-page/utils/converter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,33 @@ export function convertNodeToMandoc(node, isListItem = false) {
* @returns {string} The Mandoc formatted representation of the flag and its value.
*/
export function flagValueToMandoc(flag) {
// The seperator is '=' or ' '.
const sep = flag.match(/[= ]/)?.[0];
if (sep == null) return '';
// Split the flag into the name and value based on = or space delimiter.
// The separator is '=' or ' '.
let sep = flag.match(/[= ]/)?.[0];

if (sep == null) {
// This flag does not have a default value.
return '';
}

// Split the flag into the name and value based on the separator ('=' or space).
const value = flag.split(sep)[1];
// Format the value using Ns and Ar macros for Mandoc, if present.
// If the seperator is ' ', it'll become ''.
return value
? `${sep === ' ' ? '' : ' Ns = Ns'} Ar ${value.replace(/\]$/, '')}`
: '';

// If there is no value, return an empty string.
if (!value) {
return '';
}

// Determine the prefix based on the separator type.
const prefix = sep === ' ' ? '' : ' Ns = Ns';

// Combine prefix and formatted value.
return `${prefix} Ar ${value.replace(/\]$/, '')}`;
}

const formatFlag = flag =>
// 'Fl' denotes a flag, followed by an optional 'Ar' (argument).
`Fl ${flag.split(/[= ]/)[0].slice(1)}${flagValueToMandoc(flag)}`;

/**
* Converts an API option metadata entry into the Mandoc format.
* This function formats command-line options, including flags and descriptions,
Expand All @@ -94,17 +109,15 @@ export function convertOptionToMandoc(element) {
const formattedFlags = element.heading.data.text
.replace(/`/g, '')
.split(', ')
.map(
// 'Fl' denotes a flag
flag => `Fl ${flag.split(/[= ]/)[0].slice(1)}${flagValueToMandoc(flag)}`
)
.join(' , ');
.map(formatFlag)
.join(' , ')
.trim();

// Remove the header itself.
element.content.children.shift();

// Return the formatted flags and content, separated by Mandoc markers.
return `.It ${formattedFlags.trim()}\n${convertNodeToMandoc(element.content)}\n.\n`;
return `.It ${formattedFlags}\n.\n${convertNodeToMandoc(element.content).trim()}\n.\n`;
}

/**
Expand Down

0 comments on commit 889dec8

Please sign in to comment.