Forked from arinthros/generate-docs-from-js
Last active
June 14, 2024 20:40
Revisions
-
slorber renamed this gist
Apr 6, 2021 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
arinthros created this gist
Sep 29, 2020 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,231 @@ /** * Requires jsdoc and jsdoc-to-markdown */ /* eslint-disable no-console */ const fs = require('fs') const path = require('path') const glob = require('glob') const { execSync } = require('child_process') const jsdoc2md = require('jsdoc-to-markdown') const sidebars = require('../docs/sidebars') // Custom package names that don't match the base pattern `utils => Utils` const packageNameOverrides = [ { id: 'api', name: 'API' }, { id: 'material-ui', name: 'Material UI' }, { id: 'eslint-config', name: 'ESLint Config' }, ] /** * Runs through packages folders looking for JSDoc and generates markdown docs */ function generateDocs() { console.log('Generating package docs') // Use glob to get all js/ts files const pathPattern = path.join(__dirname, '../packages/**/src/**/*.[jt]s?(x)') const filePaths = glob.sync(pathPattern, { ignore: [ '**/node_modules/**', '**/cypress/**', '**/__tests__/**', '**/*.test.js', '**/*_spec.js', ], }) // Get the sidebar object const sidebarPackages = [...sidebars.primarySidebar.Packages] let processingPackageName // grab all js files filePaths.forEach((filePath) => { // Generate markdown from JSDoc comments const markdown = jsdoc2md.renderSync({ files: filePath, configure: path.join(__dirname, '../jsdoc.conf.json'), plugin: path.join(__dirname, '../docs/.template'), 'heading-depth': 1, }) // if there's markdown, do stuff if (markdown && markdown.length > 0) { // get the package ID from the file path const packageId = filePath.match(/\/packages\/([\s\S]*?)\/src\//i)[1] // check against the title overrides array let packageName // if override, use the title, else title = capitalize packageId if (packageNameOverrides.find((item) => item.id === packageId)) { packageName = packageNameOverrides.find((item) => item.id === packageId) .name } else { packageName = packageId.charAt(0).toUpperCase() + packageId.slice(1) } if (packageName !== processingPackageName) { processingPackageName = packageName console.log(` Processing the ${packageName} package`) } // get the sub-folder structure relative to /src/ let subPath = path.dirname(filePath).match(/\/src\/([\s\S]*?)$/i) ? `${path.dirname(filePath).match(/\/src\/([\s\S]*?)$/i)[1]}` : '' // Get each part of the path, filtering out empty path items const subPathArray = subPath.split('/') // get file name sans extension let fileName = path.basename(filePath, '.js') // if the file name is index, but is not the package index if (subPathArray.length > 0 && fileName === 'index') { // change file name to the parent folder name fileName = subPathArray[subPathArray.length - 1] // remove the parent folder from the path subPathArray.pop() subPath = subPathArray.join('/') } const writeDir = path.join( __dirname, `../docs/docs/packages/${packageId}/api-reference${ subPath ? `/${subPath}` : '' }`, ) // check if the directory exists if (!fs.existsSync(writeDir)) { // create the directory fs.mkdirSync(writeDir, { recursive: true }) } // write the markdown file fs.writeFileSync(`${writeDir}/${fileName}.md`, markdown) // update sidebar object // define the relative path for the sidebar const sidebarPath = `packages/${packageId}/api-reference${ subPath ? `/${subPath}` : '' }/${fileName}` /** * Searches the parent array for the key and adds it if it's not found * @param {Array} parent The parent array to search * @param {String} key The key to search for and add */ const addOnePathLevel = (parent, key) => { if ( !parent.find((item) => { return Object.keys(item)[0] === key }) ) { // add the first element to the parent parent.push({ [`${key}`]: [] }) } } // add package path addOnePathLevel(sidebarPackages, packageName) // add API Reference path addOnePathLevel( sidebarPackages.find((item) => { return Object.keys(item)[0] === packageName })[packageName], 'API Reference', ) // Get the API Reference item let packageApiReferenceItem = sidebarPackages .find((item) => { return Object.keys(item)[0] === packageName }) [packageName].find((item) => { return Object.keys(item)[0] === 'API Reference' })['API Reference'] // If there's a subpath, recursively set the nested structure if (subPathArray.length > 0) { // make array of names const pathNameArray = subPathArray.map((item) => { return item .split('-') .map((word) => { return word.charAt(0).toUpperCase() + word.slice(1) }) .join(' ') }) // TODO: Make nested items (index > 0) recursive const addPathLevels = (parent, index) => { // If the first element in the path array does not exist if ( !parent.find((item) => { return typeof item === 'object' && item[pathNameArray[index]] }) ) { // add the first element to the parent parent.push({ [pathNameArray[index]]: [], }) } // Find the index of the first path element const subItemIndex = parent.findIndex((item) => { return typeof item === 'object' && item[pathNameArray[index]] }) // add the sidebarPath to the last path element if (pathNameArray.length - 1 === index) { // eslint-disable-next-line no-param-reassign parent[subItemIndex][pathNameArray[index]] = [ // filter duplicates ...new Set([ ...parent[subItemIndex][pathNameArray[index]], sidebarPath, ]), ] } if (pathNameArray.length - 2 >= index) { addPathLevels(parent[subItemIndex][pathNameArray[index]], index + 1) } } // recursively add path levels addPathLevels(packageApiReferenceItem, 0) } else { // Push the sidebarPath on to the 'API Reference' array packageApiReferenceItem = [ // Preserve existing items, but filter duplicates ...new Set([...packageApiReferenceItem, sidebarPath]), ] } } }) // Let the user know what step we're on console.log('\u001B[32m', '✔️ Package docs generated', '\u001B[0m') // set packages to the updated sidebarPackages sidebars.primarySidebar.Packages = sidebarPackages // Let the user know what step we're on console.log('Updating sidebars.js') // write sidebar file fs.writeFileSync( path.join(__dirname, '../docs/sidebars.js'), `module.exports = ${JSON.stringify(sidebars, null, ' ')}`, 'utf8', ) // run prettier on the output json execSync(`eslint --fix ${path.join(__dirname, '../docs/sidebars.js')}`) // Let the user know what step we're on console.log('\u001B[32m', '✔️ sidebars.js updated', '\u001B[0m') } generateDocs() process.exit(0)