-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'v2.x/staging' into v2.x/workflows-revert
- Loading branch information
Showing
227 changed files
with
4,758 additions
and
4,510 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 |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# ignore generated documentation | ||
generated/* | ||
# keep the folder but nothing else | ||
!generated/.gitkeep |
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# ZWE CLI Documentation Generation | ||
|
||
Run `node index.js` to generate documentation for the `zwe` cli in `md` format. The command [documentation files](../../bin/README.md#command-assistant-files) are used to generate documentation. | ||
|
||
Generated documentation is added to the `generated/` folder. Files in this folder are not tracked in git. |
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 |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* This program and the accompanying materials are made available under the terms of the | ||
* Eclipse Public License v2.0 which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Copyright IBM Corporation 2021 | ||
*/ | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const { EXPERIMENTAL, HELP, EXAMPLES, EXCLUSIVE_PARAMETERS, PARAMETERS, ERRORS } = require('./dot-file-structure'); | ||
|
||
const documentationTypes = [EXPERIMENTAL, HELP, EXAMPLES, EXCLUSIVE_PARAMETERS, PARAMETERS, ERRORS]; | ||
|
||
function getDocumentationTree(commandDirectory) { | ||
const documentationNode = { children: [], command: commandDirectory.command }; | ||
const objectsInDirectory = fs.readdirSync(commandDirectory.dir); | ||
|
||
for (const file of objectsInDirectory) { | ||
const objectPath = path.join(commandDirectory.dir, file); | ||
|
||
if (fs.statSync(objectPath).isDirectory()) { | ||
documentationNode.children.push(getDocumentationTree({ dir: objectPath, command: path.basename(objectPath) })); | ||
} else { | ||
const docFileType = documentationTypes.find((df) => df.fileName === file); | ||
if (docFileType) { | ||
documentationNode[docFileType.fileName] = objectPath; | ||
} | ||
} | ||
} | ||
|
||
return documentationNode; | ||
} | ||
|
||
module.exports = { | ||
getDocumentationTree | ||
}; |
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 |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
* This program and the accompanying materials are made available under the terms of the | ||
* Eclipse Public License v2.0 which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Copyright IBM Corporation 2021 | ||
*/ | ||
|
||
const DOT_FILE_TABLE_ENTRY_DELIMITER = '|'; | ||
const DOT_FILE_TABLE_ROW_DELIMITER = '\n'; | ||
|
||
const parameterTable = { | ||
delimiter: '|', | ||
orderedSegments: [ | ||
{ | ||
position: 1, | ||
meaning: 'Full name', | ||
transform: (content) => content ? `--${content.replace(/,/g, ',--')}` : '' // other full name options are comma delimited | ||
}, | ||
{ | ||
position: 2, | ||
meaning: 'Alias', | ||
transform: (content) => content ? `-${content.replace(/,/g, ',-')}` : '' // other alias options are comma delimited | ||
}, | ||
{ | ||
position: 3, | ||
meaning: 'Type' | ||
}, | ||
{ | ||
position: 4, | ||
meaning: 'Required', | ||
transform: (content) => content === 'required' ? 'yes' : 'no' | ||
}, | ||
{ | ||
position: 5, | ||
meaning: 'Reserved for future use', | ||
ignore: true | ||
}, | ||
{ | ||
position: 6, | ||
meaning: 'Reserved for future use', | ||
ignore: true | ||
}, | ||
{ | ||
position: 7, | ||
meaning: 'Help message' | ||
} | ||
] | ||
} | ||
|
||
const EXPERIMENTAL = { | ||
inherit: true, | ||
fileName: '.experimental', | ||
meaning: 'WARNING: This command is for experimental purposes and may not fully function.' | ||
}; | ||
const HELP = { | ||
fileName: '.help', | ||
}; | ||
const EXAMPLES = { | ||
fileName: '.examples', | ||
}; | ||
const EXCLUSIVE_PARAMETERS = { | ||
fileName: '.exclusive-parameters', | ||
table: parameterTable | ||
}; | ||
const PARAMETERS = { | ||
inherit: true, | ||
fileName: '.parameters', | ||
table: parameterTable | ||
}; | ||
const ERRORS = { | ||
inherit: true, | ||
fileName: '.errors', | ||
table: { | ||
delimiter: '|', | ||
orderedSegments: [ | ||
{ | ||
position: 1, | ||
meaning: 'Error code', | ||
}, | ||
{ | ||
position: 2, | ||
meaning: 'Exit code', | ||
}, | ||
{ | ||
position: 3, | ||
meaning: 'Error message', | ||
} | ||
] | ||
} | ||
}; | ||
|
||
module.exports = { | ||
EXPERIMENTAL, HELP, EXAMPLES, EXCLUSIVE_PARAMETERS, PARAMETERS, ERRORS, DOT_FILE_TABLE_ENTRY_DELIMITER, DOT_FILE_TABLE_ROW_DELIMITER | ||
}; |
Empty file.
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 |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* This program and the accompanying materials are made available under the terms of the | ||
* Eclipse Public License v2.0 which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Copyright IBM Corporation 2021 | ||
*/ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { getDocumentationTree } = require('./doc-tree'); | ||
const { generateDocumentationForNode } = require('./md-content'); | ||
|
||
const generatedDocDirectory = path.join(__dirname, './generated') | ||
|
||
const rootDocNode = getDocumentationTree({ dir: path.join(__dirname, '../../bin/commands'), command: 'zwe' }); | ||
writeMdFiles(rootDocNode); | ||
|
||
function writeMdFiles(docNode, writtenParentNode = {}) { | ||
const { mdContent, parts } = generateDocumentationForNode(docNode, writtenParentNode); | ||
fs.writeFileSync(`${generatedDocDirectory}/${parts.fileName}.md`, mdContent); | ||
|
||
if (docNode.children && docNode.children.length) { | ||
for (const child of docNode.children) { | ||
writeMdFiles(child, parts); | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/** | ||
* This program and the accompanying materials are made available under the terms of the | ||
* Eclipse Public License v2.0 which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Copyright IBM Corporation 2021 | ||
*/ | ||
const fs = require('fs'); | ||
const { EXPERIMENTAL, HELP, EXAMPLES, EXCLUSIVE_PARAMETERS, PARAMETERS, ERRORS, DOT_FILE_TABLE_ENTRY_DELIMITER, DOT_FILE_TABLE_ROW_DELIMITER } = require('./dot-file-structure'); | ||
|
||
const SEPARATOR = '\n\n'; | ||
const SECTION_HEADER_PREFIX = '## '; | ||
const SUB_SECTION_HEADER_PREFIX = '#' + SECTION_HEADER_PREFIX; | ||
const MD_TABLE_ROW_DELIMITER = '\n'; | ||
const MD_TABLE_ENTRY_DELIMITER = '|'; | ||
|
||
// order content will appear, with prefix/postfix as needed | ||
const orderedDocumentationTypes = [ | ||
{ ...HELP, prefix: SECTION_HEADER_PREFIX + 'Description' + SEPARATOR }, | ||
{ ...EXPERIMENTAL }, | ||
{ ...EXAMPLES, prefix: SECTION_HEADER_PREFIX + 'Examples' + SEPARATOR }, | ||
{ ...EXCLUSIVE_PARAMETERS, prefix: SECTION_HEADER_PREFIX + 'Parameters only for this command' + SEPARATOR }, | ||
{ ...PARAMETERS, prefix: SECTION_HEADER_PREFIX + 'Parameters' + SEPARATOR }, | ||
{ ...ERRORS, prefix: SECTION_HEADER_PREFIX + 'Errors' + SEPARATOR } | ||
]; | ||
|
||
function generateDocumentationForNode(curNode, assembledParentNode) { | ||
const assembledDocNode = assembleDocumentationElementsForNode(curNode, assembledParentNode); | ||
const { command, linkCommand, children, fileName } = assembledDocNode; | ||
|
||
let mdContent = '# ' + command + SEPARATOR + linkCommand + SEPARATOR + '\t' + command; | ||
|
||
if (children.length) { | ||
mdContent += ' [sub-command [sub-command]...] [parameter [parameter]...]' + SEPARATOR; | ||
mdContent += SECTION_HEADER_PREFIX + 'Sub-commands' + SEPARATOR + children.map(c => `* [${c.command}](./${getFileName(c.command, fileName)})`).join('\n'); | ||
} else { | ||
mdContent += ' [parameter [parameter]...]'; | ||
} | ||
|
||
for (const docType of orderedDocumentationTypes) { | ||
let docContent = ''; | ||
if (hasDocType(assembledDocNode, docType)) { | ||
docContent += createDocContent(assembledDocNode[docType.fileName].content, docType); | ||
const parentDocContent = createDocContent(assembledDocNode[docType.fileName].parentContent, docType); | ||
if (parentDocContent) { | ||
docContent += SUB_SECTION_HEADER_PREFIX + 'Inherited from parent command' + SEPARATOR + parentDocContent; | ||
} | ||
} | ||
|
||
if (docContent) { | ||
mdContent += SEPARATOR; | ||
if (docType.prefix) { | ||
mdContent += docType.prefix; | ||
} | ||
mdContent += docContent; | ||
if (docType.postfix) { | ||
mdContent += docType.postfix; | ||
} | ||
} | ||
} | ||
|
||
return { | ||
parts: assembledDocNode, | ||
mdContent: mdContent | ||
}; | ||
} | ||
|
||
function assembleDocumentationElementsForNode(curNode, assembledParentNode) { | ||
const fileName = getFileName(curNode.command, assembledParentNode.fileName); | ||
const command = assembledParentNode.command ? assembledParentNode.command + ' ' + curNode.command : curNode.command; | ||
const link = `[${curNode.command}](./${fileName})`; | ||
const linkCommand = assembledParentNode.linkCommand ? `${assembledParentNode.linkCommand} > ${link}` : link; | ||
|
||
const docElements = { | ||
fileName, | ||
command, | ||
linkCommand, | ||
children: curNode.children, | ||
}; | ||
|
||
for (const docType of orderedDocumentationTypes) { | ||
const docForType = { content: '', parentContent: '' }; | ||
|
||
if (hasDocType(curNode, docType)) { | ||
if (docType.meaning) { | ||
docForType.content = docType.meaning; | ||
} else { | ||
const docFileContent = fs.readFileSync(curNode[docType.fileName], 'utf-8'); | ||
if (docType.table) { | ||
// filter out ignored table entries | ||
docForType.content = docFileContent.split(/$/gm).map(line => | ||
line | ||
.trim() | ||
.split(docType.table.delimiter) | ||
.filter((_, index) => !docType.table.orderedSegments[index] || !docType.table.orderedSegments[index].ignore) | ||
.join(DOT_FILE_TABLE_ENTRY_DELIMITER) | ||
) | ||
.join(DOT_FILE_TABLE_ROW_DELIMITER); | ||
} else { | ||
docForType.content = docFileContent; | ||
} | ||
} | ||
} | ||
|
||
if (hasDocType(assembledParentNode, docType) && docType.inherit) { | ||
let parentContent = ''; | ||
if (assembledParentNode[docType.fileName].content) { | ||
parentContent += assembledParentNode[docType.fileName].content; | ||
} | ||
if (assembledParentNode[docType.fileName].parentContent) { | ||
parentContent += assembledParentNode[docType.fileName].parentContent; | ||
} | ||
docForType.parentContent = parentContent; | ||
} | ||
|
||
docElements[docType.fileName] = docForType; | ||
} | ||
|
||
return docElements | ||
} | ||
|
||
function createDocContent(rawContent, docType) { | ||
let docContent = ''; | ||
if (rawContent) { | ||
if (docType.table) { | ||
docContent += createMdTable(rawContent, docType.table); | ||
} else { | ||
docContent += rawContent; | ||
} | ||
} | ||
return docContent; | ||
} | ||
|
||
function createMdTable(rawContent, docFileTableSyntax) { | ||
const filteredSegments = docFileTableSyntax.orderedSegments.filter(o => !o.ignore); | ||
|
||
let docContent = ''; | ||
docContent += filteredSegments.map(o => o.meaning).join(MD_TABLE_ENTRY_DELIMITER) + MD_TABLE_ROW_DELIMITER; // Set table headings | ||
docContent += filteredSegments.map(_ => '|---').join('') + MD_TABLE_ROW_DELIMITER; // Set table separator between headings and fields | ||
|
||
docContent += rawContent.split(DOT_FILE_TABLE_ROW_DELIMITER).map(line => line.trim().split(DOT_FILE_TABLE_ENTRY_DELIMITER) // transform table entries | ||
.map((segment, index) => { | ||
if (docFileTableSyntax.orderedSegments[index] && docFileTableSyntax.orderedSegments[index].transform) { | ||
return docFileTableSyntax.orderedSegments[index].transform(segment); | ||
} | ||
return segment; | ||
}) | ||
.join(MD_TABLE_ENTRY_DELIMITER)) // join fields in a row | ||
.join(MD_TABLE_ROW_DELIMITER); // join rows with newline | ||
|
||
return docContent; | ||
} | ||
|
||
function getFileName(command, parentFileName) { | ||
return parentFileName ? `${parentFileName}-${command}` : command; | ||
} | ||
|
||
function hasDocType(docNode, type) { | ||
return docNode[type.fileName] !== null & docNode[type.fileName] !== undefined; | ||
} | ||
|
||
module.exports = { | ||
generateDocumentationForNode | ||
}; |
Oops, something went wrong.