|
| 1 | +/** |
| 2 | + * Converts an Abstract Syntax Tree (AST) node to the Mandoc format for Unix manual pages. |
| 3 | + * This function processes the node recursively, converting each supported node type |
| 4 | + * to its corresponding Mandoc markup representation. Unsupported node types will be ignored. |
| 5 | + * |
| 6 | + * @param {import("mdast").Node} node - The AST node to be converted to Mandoc format. |
| 7 | + * @param {boolean} [isListItem=false] - Indicates if the current node is a list item. |
| 8 | + * This parameter is used to correctly format list elements in Mandoc. |
| 9 | + * @returns {string} The Mandoc formatted string representing the given node and its children. |
| 10 | + */ |
| 11 | +export function convertNodeToMandoc(node, isListItem = false) { |
| 12 | + const convertChildren = (sep = '', ili = false) => |
| 13 | + node.children.map(child => convertNodeToMandoc(child, ili)).join(sep); |
| 14 | + const escapeText = () => node.value.replace(/\\/g, '\\\\'); |
| 15 | + |
| 16 | + switch (node.type) { |
| 17 | + case 'root': |
| 18 | + // Process the root node by converting all children and separating them with new lines. |
| 19 | + return convertChildren('\n'); |
| 20 | + |
| 21 | + case 'heading': |
| 22 | + // Convert to a Mandoc heading section (.Sh). |
| 23 | + return `.Sh ${convertChildren()}`; |
| 24 | + |
| 25 | + case 'link': |
| 26 | + case 'paragraph': |
| 27 | + case 'listItem': |
| 28 | + // Convert to Mandoc paragraph or list item. |
| 29 | + // .It denotes a list item in Mandoc, added only if the node is a list item. |
| 30 | + return `${isListItem && node.type === 'listItem' ? '.It\n' : ''}${convertChildren()}`; |
| 31 | + |
| 32 | + case 'text': |
| 33 | + // Escape any special characters in plain text content. |
| 34 | + return escapeText(); |
| 35 | + |
| 36 | + case 'inlineCode': |
| 37 | + // Format inline code using Mandoc's bold markup (\\fB ... \\fR). |
| 38 | + return `\\fB${escapeText()}\\fR`; |
| 39 | + |
| 40 | + case 'strong': |
| 41 | + // Format inline code + strong using Mandoc's bold markup (\\fB ... \\fR). |
| 42 | + return `\\fB${convertChildren()}\\fR`; |
| 43 | + |
| 44 | + case 'code': |
| 45 | + // Format code blocks as literal text using .Bd -literal and .Ed for start and end. |
| 46 | + return `.Bd -literal\n${escapeText()}\n.Ed`; |
| 47 | + |
| 48 | + case 'list': |
| 49 | + // Convert to a bullet list in Mandoc, starting with .Bl -bullet and ending with .El. |
| 50 | + return `.Bl -bullet\n${convertChildren('\n', true)}\n.El`; |
| 51 | + |
| 52 | + case 'emphasis': |
| 53 | + // Format emphasized text in Mandoc using italic markup (\\fI ... \\fR). |
| 54 | + return `\\fI${convertChildren()}\\fR`; |
| 55 | + |
| 56 | + default: |
| 57 | + // Ignore `html`, `blockquote`, etc. |
| 58 | + return ''; |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +/** |
| 63 | + * Converts a command-line flag to its Mandoc representation. |
| 64 | + * This function splits the flag into its name and optional value (if present), |
| 65 | + * formatting them appropriately for Mandoc manual pages. |
| 66 | + * |
| 67 | + * @param {string} flag - The command-line flag to be formatted. It may include a value |
| 68 | + * specified with either an equals sign (=) or a space. |
| 69 | + * @returns {string} The Mandoc formatted representation of the flag and its value. |
| 70 | + */ |
| 71 | +export function flagValueToMandoc(flag) { |
| 72 | + // The separator is '=' or ' '. |
| 73 | + let sep = flag.match(/[= ]/)?.[0]; |
| 74 | + |
| 75 | + if (sep == null) { |
| 76 | + // This flag does not have a default value. |
| 77 | + return ''; |
| 78 | + } |
| 79 | + |
| 80 | + // Split the flag into the name and value based on the separator ('=' or space). |
| 81 | + const value = flag.split(sep)[1]; |
| 82 | + |
| 83 | + // If there is no value, return an empty string. |
| 84 | + if (!value) { |
| 85 | + return ''; |
| 86 | + } |
| 87 | + |
| 88 | + // Determine the prefix based on the separator type. |
| 89 | + const prefix = sep === ' ' ? '' : ' Ns = Ns'; |
| 90 | + |
| 91 | + // Combine prefix and formatted value. |
| 92 | + return `${prefix} Ar ${value.replace(/\]$/, '')}`; |
| 93 | +} |
| 94 | + |
| 95 | +const formatFlag = flag => |
| 96 | + // 'Fl' denotes a flag, followed by an optional 'Ar' (argument). |
| 97 | + `Fl ${flag.split(/[= ]/)[0].slice(1)}${flagValueToMandoc(flag)}`; |
| 98 | + |
| 99 | +/** |
| 100 | + * Converts an API option metadata entry into the Mandoc format. |
| 101 | + * This function formats command-line options, including flags and descriptions, |
| 102 | + * for display in Unix manual pages using Mandoc. |
| 103 | + * |
| 104 | + * @param {ApiDocMetadataEntry} element - The metadata entry containing details about the API option. |
| 105 | + * @returns {string} The Mandoc formatted string representing the API option, including flags and content. |
| 106 | + */ |
| 107 | +export function convertOptionToMandoc(element) { |
| 108 | + // Format the option flags by splitting them, removing backticks, and converting each flag. |
| 109 | + const formattedFlags = element.heading.data.text |
| 110 | + .replace(/`/g, '') |
| 111 | + .split(', ') |
| 112 | + .map(formatFlag) |
| 113 | + .join(' , ') |
| 114 | + .trim(); |
| 115 | + |
| 116 | + // Remove the header itself. |
| 117 | + element.content.children.shift(); |
| 118 | + |
| 119 | + // Return the formatted flags and content, separated by Mandoc markers. |
| 120 | + return `.It ${formattedFlags}\n${convertNodeToMandoc(element.content).trim()}\n.\n`; |
| 121 | +} |
| 122 | + |
| 123 | +/** |
| 124 | + * Converts an API environment variable metadata entry into the Mandoc format. |
| 125 | + * This function formats environment variables for Unix manual pages, converting |
| 126 | + * the variable name and value, along with any associated descriptions, into Mandoc. |
| 127 | + * |
| 128 | + * @param {ApiDocMetadataEntry} element - The metadata entry containing details about the environment variable. |
| 129 | + * @returns {string} The Mandoc formatted representation of the environment variable and its content. |
| 130 | + */ |
| 131 | +export function convertEnvVarToMandoc(element) { |
| 132 | + // Split the environment variable into name and optional value. |
| 133 | + const [varName, varValue] = element.heading.data.text |
| 134 | + .replace(/`/g, '') |
| 135 | + .split('='); |
| 136 | + |
| 137 | + // Format the variable value if present. |
| 138 | + const formattedValue = varValue ? ` Ar ${varValue}` : ''; |
| 139 | + |
| 140 | + // Remove the header itself. |
| 141 | + element.content.children.shift(); |
| 142 | + |
| 143 | + // Return the formatted environment variable and content, using Mandoc's .It (List item) and .Ev (Env Var) macros. |
| 144 | + return `.It Ev ${varName}${formattedValue}\n${convertNodeToMandoc(element.content)}\n.\n`; |
| 145 | +} |
0 commit comments