-
Notifications
You must be signed in to change notification settings - Fork 340
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add doc gen script (will move elsewhere)
- Loading branch information
1 parent
e61cac8
commit 2028b53
Showing
1 changed file
with
184 additions
and
142 deletions.
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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,179 +1,221 @@ | ||
const fs = require('fs') | ||
const path = require('path') | ||
const markdownMagic = require('markdown-magic') // eslint-disable-line | ||
const globby = require('markdown-magic').globby // eslint-disable-line | ||
const markdownMagic = require('markdown-magic') | ||
const globby = require('markdown-magic').globby | ||
const util = require('util') | ||
|
||
process.env.DOCS_GEN = 'TRUE' | ||
|
||
const toTitleCase = (str) => { // eslint-disable-line | ||
return str.replace(/\w\S*/g, txt => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()) | ||
} | ||
const commandData = generateCommandData() | ||
|
||
const formatName = (string) => { // eslint-disable-line | ||
return toTitleCase(string.replace(/-/g, ' ')); | ||
} | ||
const newLine = '\n\n' | ||
|
||
const config = { | ||
transforms: { | ||
GENERATE_COMMANDS_LIST(content, options) { | ||
const lessonsPath = path.join(__dirname, 'src/commands') | ||
const files = fs.readdirSync(lessonsPath) | ||
|
||
const data = files.filter((file) => { | ||
const filePath = path.join(lessonsPath, file) | ||
const stat = fs.statSync(filePath) | ||
// return all directories | ||
return stat && stat.isDirectory() | ||
}).map((file) => { | ||
const filePath = path.join(lessonsPath, file) | ||
const cmdGroupName = path.basename(filePath) | ||
console.log("CMD", cmdGroupName) | ||
console.log('filePath', filePath) | ||
const commandFiles = globby.sync([`${filePath}/**/**.js`]); | ||
|
||
const commandGroups = commandFiles.map((file) => { | ||
let cmd = {} | ||
try { | ||
cmd = require(file) | ||
} catch (e) { | ||
throw e | ||
} | ||
return { | ||
path: file, | ||
data: cmd | ||
} | ||
}).filter((command) => { | ||
// return only live commands | ||
return !command.data.hidden | ||
}) | ||
|
||
//commandGroups. | ||
|
||
console.log('commandGroups', commandGroups) | ||
// console.log('commandFiles', commandFiles) | ||
|
||
const subCommandData = generateSubCommandData(commandGroups) | ||
|
||
let md = `### ${formatName(file)} | ||
${subCommandData} | ||
` | ||
GENERATE_COMMANDS_DOCS(content, options, instance) { | ||
|
||
const command = path.basename(instance.originalPath, '.md') | ||
const info = commandData[command] | ||
console.log('info', info) | ||
|
||
if (info) { | ||
let md = '' | ||
// Parent Command | ||
md += formatDescription(info.description) | ||
md += formatUsage(command) | ||
md += formatArgs(info.args) | ||
md += formatFlags(info.flags) | ||
md += commandListSubCommandDisplay(info.commands) | ||
if (info.commands.length) { | ||
info.commands.forEach((subCmd) => { | ||
// Child Commands | ||
md += formatSubCommandTitle(subCmd.name) | ||
md += formatDescription(subCmd.description) | ||
md += formatUsage(subCmd.name) | ||
md += formatArgs(subCmd.args) | ||
md += formatFlags(subCmd.flags) | ||
md += `---\n` | ||
}) | ||
} | ||
return md | ||
} | ||
}, | ||
GENERATE_COMMANDS_LIST(content, options) { | ||
/* Generate Command List */ | ||
let md = '' | ||
Object.keys(commandData).map((commandName) => { | ||
const info = commandData[commandName] | ||
md += commandListTitle(commandName) | ||
md += commandListDescription(info.description) | ||
md += commandListSubCommandDisplay(info.commands) | ||
}) | ||
|
||
return data.join('\n'); | ||
return md | ||
}, | ||
// EXAMPLE_TABLE() { | ||
// const examples = globby.sync(['**/package.json', '!node_modules/**/package.json', '!**/node_modules/**/package.json', '!package.json']) | ||
// // Make table header | ||
// let md = '| Example | Runtime |\n' | ||
// md += '|:--------------------------- |:-----|\n' | ||
// examples.forEach((example) => { | ||
// const data = JSON.parse(fs.readFileSync(example, 'utf8')) | ||
// const dirname = path.dirname(example) | ||
// const exampleUrl = `https://github.com/netlify/examples/tree/master/${dirname}` | ||
// const runtime = 'foo' | ||
// const description = (data.description) ? `<br/> ${data.description}` : '' | ||
// // add table rows | ||
// md += `| [${formatName(data.name)}](${exampleUrl}) ${description} | ${runtime} |\n` | ||
// }) | ||
// | ||
// return md | ||
// }, | ||
}, | ||
} | ||
|
||
function generateSubCommandData(commandGroup) { | ||
// Generate docs | ||
markdownMagic(['README.md', 'docs/**/**.md'], config, () => { | ||
/* Fix newline MDX TOC issue #https://github.com/mdx-js/mdx/issues/184#issuecomment-416093951 */ | ||
const processedDocs = globby.sync([ | ||
'docs/**/**.md', | ||
]) | ||
|
||
const md = commandGroup.map((command) => { | ||
let cmdName = path.basename(command.path, '.js') | ||
let cmdGroupName = path.dirname(path.dirname(command.path)) | ||
if (cmdGroupName === 'commands') { | ||
cmdGroupName = '' | ||
} | ||
if (cmdName === 'index') { | ||
cmdName = path.basename(path.dirname(command.path), '.js') | ||
} | ||
const data = command.data | ||
const desc = data.description | ||
const examples = data.examples | ||
|
||
let examplesRender = '' | ||
if (examples) { | ||
examplesRender = `\`\`\`\n` | ||
examples.forEach((example) => { | ||
examplesRender += `${example}\n` | ||
}) | ||
examplesRender += `\`\`\`` | ||
} | ||
processedDocs.map((f) => { | ||
const filePath = path.resolve(f) | ||
const fileContents = fs.readFileSync(filePath, 'utf8') | ||
|
||
return `#### ${path.basename(path.dirname(path.dirname(command.path)))}:${cmdName} | ||
const updatedContents = fileContents.replace('<!-- AUTO-GENERATED-CONTENT:END -->', '\n<!-- AUTO-GENERATED-CONTENT:END -->') | ||
fs.writeFileSync(filePath, updatedContents) | ||
}) | ||
console.log('Docs updated!') | ||
}) | ||
|
||
${desc} | ||
|
||
${examplesRender} | ||
` | ||
function commandFromPath(p) { | ||
return p.replace(process.cwd(), '') | ||
.replace('.js', '') | ||
.replace('/src/commands/', '') | ||
.replace('/index', '') | ||
.replace('/', ':') | ||
} | ||
|
||
/* Start - Docs Templating logic */ | ||
function commandListTitle(command) { | ||
return `### [${command}](/commands/${command})${newLine}` | ||
} | ||
|
||
function commandListDescription(desc) { | ||
const cleanDescription = desc.split('\n')[0] | ||
return `${cleanDescription}${newLine}` | ||
} | ||
|
||
function commandListSubCommandDisplay(commands) { | ||
if (!commands.length) { | ||
return '' | ||
} | ||
let table = '| Subcommand | description |\n'; | ||
table += '|:--------------------------- |:-----|\n'; | ||
commands.forEach((cmd) => { | ||
table += `| ${cmd.name} | ${cmd.description} |\n`; | ||
}) | ||
return `${table}${newLine}` | ||
} | ||
function formatUsage(commandName) { | ||
return `**Usage** | ||
\`\`\`bash | ||
netlify ${commandName} | ||
\`\`\`\n\n` | ||
} | ||
|
||
function formatSubCommandTitle(cmdName) { | ||
return `## \`${cmdName}\`\n\n` | ||
} | ||
|
||
return md.join('\n'); | ||
function formatDescription(desc) { | ||
return `${desc}\n\n` | ||
} | ||
|
||
// build lessons table | ||
function generateTable(commandFiles) { | ||
let md = '| Lesson | Final Code |\n'; | ||
md += '|:--------------------------- |:-----|\n'; | ||
function formatFlags(cmdFlags, command) { | ||
if (!cmdFlags) { | ||
return '' | ||
} | ||
const flagArray = Object.keys(cmdFlags) | ||
if (!flagArray.length) { | ||
return '' | ||
} | ||
let renderFlags = `**Flags**\n\n` | ||
|
||
renderFlags += flagArray.map((flag) => { | ||
|
||
const flagData = cmdFlags[flag] | ||
console.log('flag', flagData) | ||
if (!flagData.description) { | ||
throw new Error(`${command} missing flag description`) | ||
} | ||
|
||
return `- ${flag} (${flagData.type}) - ${flagData.description}` | ||
}).join('\n') | ||
|
||
renderFlags += `\n\n` | ||
|
||
return renderFlags | ||
} | ||
|
||
const commandGroups = commandFiles.map((file) => { | ||
function formatArgs(cmdArgs) { | ||
if (!cmdArgs) { | ||
return '' | ||
} | ||
let renderArgs = `**Arguments**\n\n` | ||
|
||
renderArgs += cmdArgs.map((arg) => { | ||
console.log('arg', arg) | ||
return `- ${arg.name} - ${arg.description}` | ||
}).join('\n') | ||
renderArgs += `\n\n` | ||
return renderArgs | ||
} | ||
/* End - Docs Templating logic */ | ||
|
||
function generateCommandData() { | ||
const commandsPath = path.join(__dirname, 'src/commands') | ||
const commands = globby.sync([`${commandsPath}/**/**.js`]) | ||
|
||
const allCommands = commands.map((file) => { | ||
let cmd = {} | ||
try { | ||
cmd = require(file) | ||
} catch (e) { | ||
throw e | ||
} | ||
return cmd | ||
const command = commandFromPath(file) | ||
const parentCommand = command.split(':')[0] | ||
const parent = (command === parentCommand) ? true : false | ||
return { | ||
command: command, | ||
commandGroup: parentCommand, | ||
isParent: parent, | ||
path: file, | ||
data: cmd | ||
} | ||
}) | ||
|
||
console.log('commandGroups', commandGroups) | ||
|
||
commandGroups.forEach((cmd) => { | ||
console.log('cmd.description', cmd.description) | ||
const visibleCommands = allCommands.filter((cmd) => { | ||
return !cmd.data.hidden | ||
}) | ||
|
||
return 'hi' | ||
|
||
examples.forEach((example) => { | ||
console.log(example) | ||
|
||
let mod = {} | ||
try { | ||
mod = require(example) | ||
} catch (e) { | ||
|
||
console.log('visibleCommands', visibleCommands) | ||
|
||
const groupedCommands = visibleCommands.reduce((acc, curr) => { | ||
if (curr.commandGroup === curr.command) { | ||
acc[curr.commandGroup] = { | ||
name: curr.command, | ||
description: curr.data.description, | ||
flags: curr.data.flags, | ||
args: curr.data.args, | ||
examples: curr.data.examples, | ||
strict: curr.data.strict, | ||
commands: [] | ||
} | ||
} | ||
console.log('mod', mod.description) | ||
console.log('flags', mod.flags) | ||
const contents = fs.readFileSync(example, 'utf8') | ||
const dirname = path.basename(path.dirname(example)) | ||
const parentDir = path.basename(path.dirname(path.dirname(example))) | ||
|
||
console.log('dirname', dirname) | ||
const repoBase = 'https://github.com/DavidWells/serverless-workshop/tree/master' | ||
const baseLink = `${repoBase}/_instructor/${parentDir}/${dirname}` | ||
|
||
const lessonLink = baseLink.replace(/_instructor/g, 'lessons'); | ||
const answersLink = baseLink.replace(/_instructor/g, 'lessons-code-complete'); | ||
//console.log(content) | ||
const heading = contents.match(/^# (.*)/g) | ||
console.log('heading', heading) | ||
const description = (heading && heading[0]) ? heading[0].replace("# ", '') : ''; | ||
// add table rows | ||
md += `| [${formatName(dirname)}](${lessonLink}) <br/> ${description} | [Complete Code](${answersLink}) |\n`; | ||
// md += baseLink | ||
}); | ||
return md | ||
} | ||
return acc | ||
}, {}) | ||
|
||
const groupedCommandsWithData = visibleCommands.reduce((acc, curr) => { | ||
if (curr.commandGroup !== curr.command) { | ||
acc[curr.commandGroup].commands = acc[curr.commandGroup].commands.concat({ | ||
name: curr.command, | ||
description: curr.data.description, | ||
flags: curr.data.flags, | ||
args: curr.data.args, | ||
examples: curr.data.examples, | ||
strict: curr.data.strict | ||
}) | ||
} | ||
return acc | ||
}, groupedCommands) | ||
|
||
const markdownPath = path.join(__dirname, 'README.md') | ||
markdownMagic(markdownPath, config, () => { | ||
console.log('Docs updated!') // eslint-disable-line | ||
}) | ||
return groupedCommandsWithData | ||
} |