majas
Version:
Format-agnostic structure converter.
67 lines (66 loc) • 2.39 kB
JavaScript
import { fromMarkdown } from 'mdast-util-from-markdown';
import { throwf } from '../util/misc.js';
import { FormatterBase } from '../core/Formatter.js';
export const HeadingDepths = [1, 2, 3, 4, 5, 6];
export const DefaultOptions = {
depth: 6,
};
export default class Markdown extends FormatterBase {
options;
constructor(format, options) {
super(format);
this.options = { ...DefaultOptions, ...options };
}
input;
parseImpl(input) {
this.input = input;
const root = fromMarkdown(input);
return this.md2ir(root);
}
emit(output) {
return 'todo';
}
md2ir(parent) {
const h0children = [];
const h0 = {
children: { ordered: true, items: h0children },
};
const stack = [[0, h0children]];
let lastHeading = h0;
let previousHeadingEndOffset = 0;
for (const n of parent.children) {
if (!isHeading(n) || n.depth > this.options.depth)
continue;
const content = this.input
.substring(previousHeadingEndOffset, n.position?.start.offset ?? throwf(new Error('missing node start offset')))
.trim();
if (content)
lastHeading.content = content;
while (stack[stack.length - 1][0] >= n.depth) {
stack.pop();
}
const newScope = [];
stack[stack.length - 1][1].push((lastHeading = {
title: this.getSource(n.children),
children: { ordered: true, items: newScope },
}));
stack.push([n.depth, newScope]);
previousHeadingEndOffset =
n.position?.end.offset ?? throwf(new Error('missing node end offset'));
}
const trailingContent = this.input.substring(previousHeadingEndOffset).trim();
if (trailingContent) {
lastHeading.content = (lastHeading.content ?? '') + trailingContent;
}
return h0;
}
getSource(nodes) {
const l = nodes.length;
return l
? this.input.substring(nodes[0].position?.start.offset ?? throwf(new Error('missing node start offset')), nodes[l - 1].position?.end.offset ?? throwf(new Error('missing node end offset')))
: '';
}
}
function isHeading(node) {
return node.type === 'heading';
}