From 9dd443e1aa6611a605326a3e82f7ce5d4c743959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Vodovnik?= Date: Mon, 15 Feb 2021 19:41:40 +0100 Subject: [PATCH] chore(docs): add ability to generate xmldocs (#5164) Introduces a naive XmlDocs renderer for Markdown nodes. It needs to be called separately for now. --- utils/doclint/xmlDocumentation.js | 141 ++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 utils/doclint/xmlDocumentation.js diff --git a/utils/doclint/xmlDocumentation.js b/utils/doclint/xmlDocumentation.js new file mode 100644 index 0000000000..f480b51449 --- /dev/null +++ b/utils/doclint/xmlDocumentation.js @@ -0,0 +1,141 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-check +const Documentation = require('./documentation'); +const { visitAll } = require('../markdown'); +/** + * @param {Documentation.MarkdownNode[]} nodes + * @param {number} maxColumns + */ +function renderXmlDoc(nodes, maxColumns = 80, prefix = '/// ') { + if (!nodes) + return []; + + const renderResult = _innerRenderNodes(nodes, maxColumns); + + const doc = []; + _wrapInNode('summary', renderResult.summary, doc); + _wrapInNode('remarks', renderResult.remarks, doc); + return doc.map(x => `${prefix}${x}`); +} + +function _innerRenderNodes(nodes, maxColumns = 80, wrapParagraphs = true) { + const summary = []; + const remarks = []; + const handleListItem = (lastNode, node) => { + if (node && node.type === 'li' && (!lastNode || lastNode.type !== 'li')) + summary.push(``); + else if (lastNode && lastNode.type === 'li' && (!node || node.type !== 'li')) + summary.push(''); + + }; + + let lastNode; + visitAll(nodes, node => { + // handle special cases first + if (_nodeShouldBeIgnored(node)) + return; + if (node.text && node.text.startsWith('extends: ')) { + remarks.push('Inherits from ' + node.text.replace('extends: ', '')); + return; + } + handleListItem(lastNode, node); + if (node.type === 'text') { + if (wrapParagraphs) + _wrapInNode('para', _wrapAndEscape(node, maxColumns), summary); + else + summary.push(..._wrapAndEscape(node, maxColumns)); + } else if (node.type === 'code' && node.codeLang === 'csharp') { + _wrapInNode('code', node.lines, summary); + } else if (node.type === 'li') { + _wrapInNode('item>${nodes[0]}<${closingTag}>`); + return; + } + + target.push(`<${tag}>`); + target.push(...nodes); + target.push(`<${closingTag}>`); +} + +/** + * + * @param {Documentation.MarkdownNode} node + */ +function _wrapAndEscape(node, maxColumns = 0) { + const lines = []; + const pushLine = text => { + if (text === '') + return; + text = text.trim(); + lines.push(text); + }; + + const text = node.text.replace(/[^\[]`([^\]]*[^\[])`[^\]]/g, (m, g1) => ` ${g1} `); + const words = text.split(' '); + let line = ''; + for (let i = 0; i < words.length; i++) { + line = line + ' ' + words[i]; + if (line.length >= maxColumns) { + pushLine(line); + line = ''; + } + } + + pushLine(line); + return lines; +} + +/** + * + * @param {Documentation.MarkdownNode} node + */ +function _nodeShouldBeIgnored(node) { + if (!node + || (node.text === 'extends: [EventEmitter]')) + return true; + + return false; +} + +/** + * @param {Documentation.MarkdownNode[]} nodes + */ +function renderTextOnly(nodes, maxColumns = 80) { + const result = _innerRenderNodes(nodes, maxColumns, false); + return result.summary; +} + +module.exports = { renderXmlDoc, renderTextOnly } \ No newline at end of file