markdownlint/lib/micromark.mjs

79 lines
2.2 KiB
JavaScript
Raw Normal View History

import assert from "node:assert/strict";
// eslint-disable-next-line n/no-unpublished-import
import { parse, postprocess, preprocess } from "../micromark/exports.mjs";
/**
* Markdown token.
*
* @typedef {Object} Token
* @property {string} type Token type.
* @property {number} startLine Start line (1-based).
* @property {number} startColumn Start column (1-based).
* @property {number} endLine End line (1-based).
* @property {number} endColumn End column (1-based).
* @property {string} text Token text.
* @property {Token[]} tokens Child tokens.
*/
/**
* Parses a Markdown document and returns tokens.
*
* @param {string} markdown Markdown document.
* @returns {Token[]} Markdown tokens.
*/
function micromarkParse(markdown) {
// Use micromark to parse document into Events
const encoding = undefined;
const eol = true;
const options = undefined;
const chunks = preprocess()(markdown, encoding, eol);
const parseContext = parse(options).document().write(chunks);
const events = postprocess(parseContext);
// Create Token objects
const document = [];
let current = {
"tokens": document
};
const history = [ current ];
for (const event of events) {
const [ kind, token, context ] = event;
const { type, start, end, _container } = token;
const { "column": startColumn, "line": startLine } = start;
const { "column": endColumn, "line": endLine } = end;
// sliceSerialize throws when called for a _container
const text = _container ? null : context.sliceSerialize(token);
if (kind === "enter") {
const previous = current;
history.push(previous);
current = {
type,
startLine,
startColumn,
endLine,
endColumn,
text,
"tokens": []
};
previous.tokens.push(current);
} else if (kind === "exit") {
assert.equal(type, current.type);
assert.equal(startLine, current.startLine);
assert.equal(startColumn, current.startColumn);
assert.equal(endLine, current.endLine);
assert.equal(endColumn, current.endColumn);
assert.equal(text, current.text);
current = history.pop();
assert.ok(current, "Empty history");
}
}
// Return document
return document;
}
export {
micromarkParse as parse
};