doc: generator code health (3) (#4850)
This commit is contained in:
Родитель
6697dadca2
Коммит
9817d1095a
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -91,9 +91,9 @@ class MDOutline {
|
|||
clazz.visit(item => patchLinks(item, item.spec, classesMap, membersMap, linkRenderer));
|
||||
}
|
||||
|
||||
renderComments() {
|
||||
generateSourceCodeComments() {
|
||||
for (const clazz of this.classesArray)
|
||||
clazz.visit(item => item.comment = renderLinksForSourceCode(item.spec));
|
||||
clazz.visit(item => item.comment = generateSourceCodeComment(item.spec));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,13 +127,13 @@ function extractComments(item) {
|
|||
/**
|
||||
* @param {MarkdownNode[]} spec
|
||||
*/
|
||||
function renderLinksForSourceCode(spec) {
|
||||
function generateSourceCodeComment(spec) {
|
||||
const comments = (spec || []).filter(n => n.type !== 'gen' && !n.type.startsWith('h') && (n.type !== 'li' || n.liType !== 'default')).map(c => md.clone(c));
|
||||
md.visitAll(comments, node => {
|
||||
if (node.liType === 'bullet')
|
||||
node.liType = 'default';
|
||||
});
|
||||
return md.render(comments);
|
||||
return md.render(comments, 120);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,24 +149,24 @@ function patchLinks(item, spec, classesMap, membersMap, linkRenderer) {
|
|||
md.visitAll(spec, node => {
|
||||
if (!node.text)
|
||||
return;
|
||||
node.text = node.text.replace(/\[`((?:event|method|property): [^\]]+)`\]/g, (_, p1) => {
|
||||
node.text = node.text.replace(/\[`((?:event|method|property): [^\]]+)`\]/g, (match, p1) => {
|
||||
const member = membersMap.get(p1);
|
||||
return linkRenderer({ member });
|
||||
return linkRenderer({ member }) || match;
|
||||
});
|
||||
node.text = node.text.replace(/\[`(param|option): ([^\]]+)`\]/g, (_, p1, p2) => {
|
||||
node.text = node.text.replace(/\[`(param|option): ([^\]]+)`\]/g, (match, p1, p2) => {
|
||||
const context = {
|
||||
clazz: item instanceof Documentation.Class ? item : undefined,
|
||||
member: item instanceof Documentation.Member ? item : undefined,
|
||||
};
|
||||
if (p1 === 'param')
|
||||
return linkRenderer({ ...context, param: p2 });
|
||||
return linkRenderer({ ...context, param: p2 }) || match;
|
||||
if (p1 === 'option')
|
||||
return linkRenderer({ ...context, option: p2 });
|
||||
return linkRenderer({ ...context, option: p2 }) || match;
|
||||
});
|
||||
node.text = node.text.replace(/\[([\w]+)\]/, (match, p1) => {
|
||||
const clazz = classesMap.get(p1);
|
||||
if (clazz)
|
||||
return linkRenderer({ clazz });
|
||||
return linkRenderer({ clazz }) || match;
|
||||
return match;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,15 +17,29 @@
|
|||
// @ts-check
|
||||
|
||||
const path = require('path');
|
||||
const Documentation = require('./Documentation');
|
||||
const { MDOutline } = require('./MDBuilder');
|
||||
const PROJECT_DIR = path.join(__dirname, '..', '..');
|
||||
|
||||
{
|
||||
const { documentation } = new MDOutline(path.join(PROJECT_DIR, 'docs-src', 'api-body.md'), path.join(PROJECT_DIR, 'docs-src', 'api-params.md'));
|
||||
const result = serialize(documentation);
|
||||
const outline = new MDOutline(path.join(PROJECT_DIR, 'docs-src', 'api-body.md'), path.join(PROJECT_DIR, 'docs-src', 'api-params.md'));
|
||||
outline.renderLinks(item => {
|
||||
const { clazz, member, param, option } = item;
|
||||
if (param)
|
||||
return `\`${param}\``;
|
||||
if (option)
|
||||
return `\`${option}\``;
|
||||
if (clazz)
|
||||
return `\`${clazz.name}\``;
|
||||
});
|
||||
outline.generateSourceCodeComments();
|
||||
const result = serialize(outline);
|
||||
console.log(JSON.stringify(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Documentation} documentation
|
||||
*/
|
||||
function serialize(documentation) {
|
||||
const result = {};
|
||||
for (const clazz of documentation.classesArray)
|
||||
|
@ -33,6 +47,9 @@ function serialize(documentation) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Documentation.Class} clazz
|
||||
*/
|
||||
function serializeClass(clazz) {
|
||||
const result = { name: clazz.name };
|
||||
if (clazz.extends)
|
||||
|
@ -58,11 +75,13 @@ function serializeClass(clazz) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Documentation.Member} member
|
||||
*/
|
||||
function serializeMember(member) {
|
||||
const result = { ...member };
|
||||
const result = /** @type {any} */ ({ ...member });
|
||||
sanitize(result);
|
||||
result.args = {};
|
||||
delete member.clazz;
|
||||
for (const arg of member.argsArray)
|
||||
result.args[arg.name] = serializeProperty(arg);
|
||||
if (member.type)
|
||||
|
@ -83,6 +102,7 @@ function sanitize(result) {
|
|||
delete result.args;
|
||||
delete result.argsArray;
|
||||
delete result.templates;
|
||||
delete result.clazz;
|
||||
if (result.properties && !Object.keys(result.properties).length)
|
||||
delete result.properties;
|
||||
if (result.comment === '')
|
||||
|
|
|
@ -58,7 +58,7 @@ let hadChanges = false;
|
|||
return createMemberLink(`${member.clazz.varName}.${member.name}`);
|
||||
throw new Error('Unknown member kind ' + member.kind);
|
||||
});
|
||||
outline.renderComments();
|
||||
outline.generateSourceCodeComments();
|
||||
documentation = outline.documentation;
|
||||
|
||||
// Root module types are overridden.
|
||||
|
|
|
@ -156,12 +156,13 @@ function parse(content) {
|
|||
|
||||
/**
|
||||
* @param {MarkdownNode[]} nodes
|
||||
* @param {number=} maxColumns
|
||||
*/
|
||||
function render(nodes) {
|
||||
function render(nodes, maxColumns) {
|
||||
const result = [];
|
||||
let lastNode;
|
||||
for (let node of nodes) {
|
||||
innerRenderMdNode(node, lastNode, result);
|
||||
innerRenderMdNode(node, lastNode, result, maxColumns);
|
||||
lastNode = node;
|
||||
}
|
||||
return result.join('\n');
|
||||
|
@ -170,9 +171,10 @@ function render(nodes) {
|
|||
/**
|
||||
* @param {MarkdownNode} node
|
||||
* @param {MarkdownNode} lastNode
|
||||
* @param {number=} maxColumns
|
||||
* @param {string[]} result
|
||||
*/
|
||||
function innerRenderMdNode(node, lastNode, result) {
|
||||
function innerRenderMdNode(node, lastNode, result, maxColumns) {
|
||||
const newLine = () => {
|
||||
if (result[result.length - 1] !== '')
|
||||
result.push('');
|
||||
|
@ -184,7 +186,7 @@ function innerRenderMdNode(node, lastNode, result) {
|
|||
result.push(`${'#'.repeat(depth)} ${node.text}`);
|
||||
let lastNode = node;
|
||||
for (const child of node.children || []) {
|
||||
innerRenderMdNode(child, lastNode, result);
|
||||
innerRenderMdNode(child, lastNode, result, maxColumns);
|
||||
lastNode = child;
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +195,7 @@ function innerRenderMdNode(node, lastNode, result) {
|
|||
const bothComments = node.text.startsWith('>') && lastNode && lastNode.type === 'text' && lastNode.text.startsWith('>');
|
||||
if (!bothComments && lastNode && lastNode.text)
|
||||
newLine();
|
||||
result.push(node.text);
|
||||
result.push(wrapText(node.text, maxColumns));
|
||||
}
|
||||
|
||||
if (node.type === 'code') {
|
||||
|
@ -220,7 +222,7 @@ function innerRenderMdNode(node, lastNode, result) {
|
|||
case 'default': char = '-'; break;
|
||||
case 'ordinal': char = '1.'; break;
|
||||
}
|
||||
result.push(`${indent}${char} ${node.text}`);
|
||||
result.push(`${indent}${char} ${wrapText(node.text, maxColumns, indent + ' '.repeat(char.length + 1))}`);
|
||||
for (const child of node.children || [])
|
||||
visit(child, indent + ' ');
|
||||
};
|
||||
|
@ -228,6 +230,45 @@ function innerRenderMdNode(node, lastNode, result) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
*/
|
||||
function tokenizeText(text) {
|
||||
const links = [];
|
||||
// Don't wrap simple links with spaces.
|
||||
text = text.replace(/\[[^\]]+\]/g, match => {
|
||||
links.push(match);
|
||||
return `[${links.length - 1}]`;
|
||||
});
|
||||
return text.split(' ').map(c => c.replace(/\[(\d+)\]/g, (_, p1) => links[+p1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number=} maxColumns
|
||||
* @param {string=} indent
|
||||
*/
|
||||
function wrapText(text, maxColumns = 0, indent = '') {
|
||||
if (!maxColumns)
|
||||
return text;
|
||||
const lines = [];
|
||||
maxColumns -= indent.length;
|
||||
const words = tokenizeText(text);
|
||||
let line = '';
|
||||
for (const word of words) {
|
||||
if (line.length && line.length + word.length < maxColumns) {
|
||||
line += ' ' + word;
|
||||
} else {
|
||||
if (line)
|
||||
lines.push(line);
|
||||
line = (lines.length ? indent : '') + word;
|
||||
}
|
||||
}
|
||||
if (line)
|
||||
lines.push(line);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MarkdownNode} node
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче