From 71bd62e55ce2de04088c236b85c9a33b914a412e Mon Sep 17 00:00:00 2001 From: Philippe Virouleau Date: Mon, 27 Nov 2023 17:04:57 +0100 Subject: [PATCH] Add API documentation generation --- gen_docs_api.js | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 107 insertions(+) create mode 100644 gen_docs_api.js diff --git a/gen_docs_api.js b/gen_docs_api.js new file mode 100644 index 0000000..4fb7251 --- /dev/null +++ b/gen_docs_api.js @@ -0,0 +1,106 @@ +const dotenv = require('dotenv') +const env = process.env.ENV || 'DEV' +dotenv.config({ path: '.env.' + env }) + +// FIXME: reorder categories into a more structured order? +// eg: wcif, events, groups, persons, cluster, ...? +const categories = [ + 'array', + 'boolean', + 'cluster', + // FIXME: not that All useful. + //'display', + 'events', + 'groups', + 'help', + 'math', + 'persons', + 'sheets', + 'staff', + 'table', + 'time', + 'tuple', + 'udf', + 'util', + 'wcif', +] + +const functionToAnchorName = (name, genericParams) => { + if (typeof this.generated === 'undefined') { + this.generated = [] + } + const baseName = `${name.toLowerCase()}${genericParams ? genericParams.map(t => t.toLowerCase()).join('-') : ''}` + let suffix = 1 + let generatedName = baseName + while (this.generated.includes(generatedName)) { + generatedName = `${baseName}-${suffix++}` + } + this.generated.push(generatedName) + return generatedName +} + +const functionName = (name, genericParams) => `${name}${genericParams ? `\\<${genericParams.join(', ')}>` : ''}` + +const stringForArg = ({ name, type, defaultValue, nullable, canBeExternal, repeated, lazy, docs }) => { + const properties = [] + // FIXME: document what lazy/repeated means. + if (nullable) { + properties.push('(can be null)') + } + if (canBeExternal) { + properties.push('(can be external)') + } + if (repeated) { + properties.push('(repeated)') + } + if (lazy) { + properties.push('(lazy)') + } + const propertiesString = properties.length > 0 ? ` *${properties.join('')}*` : '' + const helpForArg = docs ? ` + + ${docs}` : '' + + return ` - *${type.replace('<', '\\<')}* **${name}**${defaultValue !== undefined ? `=${defaultValue}`:''}${propertiesString}${helpForArg}` +} + +const stringForFunction = ({ name, genericParams, docs, outputType, args, mutations}) => ` +### ${functionName(name, genericParams)} + +${docs || 'TODO'} + + - Args:${args.length === 0 ? ' none' : `\n${args.map(stringForArg).join('\n')}`} + + - Returns: **${outputType.replace('<', '\\<')}** + + - WCIF changes: **${mutations && mutations.length > 0 ? `${mutations.join(', ')}` : 'none'}**` + +const documentation = categories.map(c => { + const functions = require(`./functions/${c}.js`).functions + return `## ${c} +${functions.map(stringForFunction).join('\n')} +` +}).join('\n') + +const tocFunction = ({ name, genericParams }) => ` - [${functionName(name, genericParams)}](#${functionToAnchorName(name, genericParams)})` +const toc = categories.map(c => { + const functions = require(`./functions/${c}.js`).functions + return ` - [${c}](#${c}) +${functions.map(tocFunction).join('\n')}` +}).join('\n') + +const { exec } = require('node:child_process') + +exec('git log -1 --oneline | cut -d " " -f 1 | tr -d "\n"', (_, stdout ) => { + + console.log(`# CompScript API reference + +*This documentation was automatically generated on commit [${stdout}](https://github.com/cubingusa/compscript/commit/${stdout}) with \`npm run gen-docs-api\`, don't edit this file directly.* + +## Index + +${toc} + +${documentation}`) +}) + diff --git a/package.json b/package.json index 7476a54..57056aa 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "main": "main.js", "scripts": { "dev-server": "ENV=DEV npx nodemon -i wcif_data .", + "gen-docs-api": "node ./gen_docs_api.js > docs/api.md", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": {