a69bed30d9
This patch simplifies documentation linter, basically addressing the comments from #47. References #14.
82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
const Documentation = require('./Documentation');
|
|
const commonmark = require('commonmark');
|
|
const Browser = require('../../lib/Browser');
|
|
|
|
class MDOutline {
|
|
/**
|
|
* @return {!MDOutline}
|
|
*/
|
|
static async create(text) {
|
|
// Render markdown as HTML.
|
|
const reader = new commonmark.Parser();
|
|
const parsed = reader.parse(text);
|
|
const writer = new commonmark.HtmlRenderer();
|
|
const html = writer.render(parsed);
|
|
|
|
// Extract headings.
|
|
const browser = new Browser({args: ['--no-sandbox']});
|
|
const page = await browser.newPage();
|
|
await page.setContent(html);
|
|
const headings = await page.evaluate(() => {
|
|
let headings = {};
|
|
let methods = [];
|
|
for (let header of document.body.querySelectorAll('h3,h4')) {
|
|
if (header.matches('h3')) {
|
|
methods = [];
|
|
headings[header.textContent] = methods;
|
|
} else {
|
|
methods.push(header.textContent);
|
|
}
|
|
}
|
|
return headings;
|
|
});
|
|
await browser.close();
|
|
return new MDOutline(headings);
|
|
}
|
|
|
|
constructor(headings) {
|
|
this.classes = [];
|
|
const classHeading = /^class: (\w+)$/;
|
|
const constructorRegex = /^new (\w+)\((.*)\)$/;
|
|
const methodRegex = /^(\w+)\.(\w+)\((.*)\)$/;
|
|
let currentClassName = null;
|
|
let currentClassMethods = [];
|
|
for (const heading of Object.keys(headings)) {
|
|
|
|
let match = heading.match(classHeading);
|
|
currentClassName = match[1];
|
|
for (const title of headings[heading]) {
|
|
let className = null;
|
|
let methodName = null;
|
|
if (constructorRegex.test(title)) {
|
|
let match = title.match(constructorRegex);
|
|
className = match[1];
|
|
methodName = 'constructor';
|
|
} else if (methodRegex.test(title)) {
|
|
let match = title.match(methodRegex);
|
|
className = match[1];
|
|
methodName = match[2];
|
|
}
|
|
|
|
if (!currentClassName || !className || !methodName || className.toLowerCase() !== currentClassName.toLowerCase()) {
|
|
console.warn('failed to process header as method: ' + heading);
|
|
continue;
|
|
}
|
|
let method = new Documentation.Method(methodName);
|
|
currentClassMethods.push(method);
|
|
}
|
|
flushClassIfNeeded.call(this);
|
|
}
|
|
|
|
function flushClassIfNeeded() {
|
|
if (currentClassName === null)
|
|
return;
|
|
this.classes.push(new Documentation.Class(currentClassName, currentClassMethods));
|
|
currentClassName = null;
|
|
currentClassMethods = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = MDOutline;
|