86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
|
const Documentation = require('./Documentation');
|
||
|
const commonmark = require('commonmark');
|
||
|
const Browser = require('../../lib/Browser');
|
||
|
|
||
|
class MDOutline {
|
||
|
constructor(text) {
|
||
|
this.classes = [];
|
||
|
this.html = MDOutline.compile(text);
|
||
|
}
|
||
|
|
||
|
static compile(text) {
|
||
|
const reader = new commonmark.Parser();
|
||
|
const parsed = reader.parse(text);
|
||
|
const writer = new commonmark.HtmlRenderer();
|
||
|
const html = writer.render(parsed);
|
||
|
return html;
|
||
|
}
|
||
|
|
||
|
async collectHeadings() {
|
||
|
const browser = new Browser({args: ['--no-sandbox']});
|
||
|
const page = await browser.newPage();
|
||
|
await page.setContent(this.html);
|
||
|
this.headings = await page.evaluate(getTOCHeadings);
|
||
|
await browser.close();
|
||
|
}
|
||
|
|
||
|
buildClasses() {
|
||
|
const headings = this.headings;
|
||
|
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 = [];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getTOCHeadings(){
|
||
|
const headings = {};
|
||
|
document.querySelectorAll('h3').forEach((domainEl, i) => {
|
||
|
const methods = [];
|
||
|
let currElem = domainEl;
|
||
|
while ((currElem = currElem.nextElementSibling) && !currElem.matches('h3')) {
|
||
|
if (currElem.matches('h4'))
|
||
|
methods.push(currElem.textContent);
|
||
|
}
|
||
|
headings[domainEl.textContent] = methods;
|
||
|
});
|
||
|
return headings;
|
||
|
}
|
||
|
|
||
|
module.exports = MDOutline;
|