Skip to content

Commit

Permalink
Refactor Token.parent() to Token.parent, add validation tests for par…
Browse files Browse the repository at this point in the history
…ent, fix parent in htmlFlow scenario, improve type saftey slightly.
  • Loading branch information
DavidAnson committed Oct 20, 2023
1 parent 0646690 commit 2a56f13
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 372 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"id-length": "off",
"indent": ["error", 2, { "SwitchCase": 1 }],
"linebreak-style": "off",
"lines-around-comment": "off",
"logical-assignment-operators": "off",
"max-depth": "off",
"max-lines": "off",
Expand Down
47 changes: 25 additions & 22 deletions demo/markdownlint-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1219,14 +1219,7 @@ var flatTokensSymbol = Symbol("flat-tokens");
* @property {number} endColumn End column (1-based).
* @property {string} text Token text.
* @property {Token[]} children Child tokens.
* @property {GetTokenParent} parent Parent token.
*/

/**
* Returns parent Token of a Token.
*
* @typedef {Function} GetTokenParent
* @returns {Token} Parent token.
* @property {Token | null} parent Parent token.
*/

/**
Expand Down Expand Up @@ -1290,17 +1283,26 @@ function getMicromarkEvents(markdown) {
* @param {Object} micromarkOptions Options for micromark.
* @param {boolean} referencesDefined Treat references as defined.
* @param {number} lineDelta Offset to apply to start/end line.
* @param {Token} [ancestor] Parent of top-most tokens.
* @returns {Token[]} Micromark tokens (frozen).
*/
function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined, lineDelta) {
function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined, lineDelta, ancestor) {
// Use micromark to parse document into Events
var events = getMicromarkEvents(markdown, micromarkOptions, referencesDefined);

// Create Token objects
var document = [];
var flatTokens = [];
/** @type {Token} */
var root = {
"children": document
"type": "ROOT",
"startLine": -1,
"startColumn": -1,
"endLine": -1,
"endColumn": -1,
"text": "ROOT",
"children": document,
"parent": null
};
var history = [root];
var current = root;
Expand All @@ -1310,7 +1312,7 @@ function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined,
var _iterator = _createForOfIteratorHelper(events),
_step;
try {
var _loop = function _loop() {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var event = _step.value;
var _event = _slicedToArray(event, 3),
kind = _event[0],
Expand All @@ -1335,13 +1337,10 @@ function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined,
endColumn: endColumn,
text: text,
"children": [],
"parent": function parent() {
return previous === root ? null : previous;
}
"parent": previous === root ? ancestor || null : previous
};
previous.children.push(current);
flatTokens.push(current);
// @ts-ignore
if (current.type === "htmlFlow" && !isHtmlFlowComment(current)) {
skipHtmlFlowChildren = true;
if (!reparseOptions || !lines) {
Expand All @@ -1355,7 +1354,7 @@ function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined,
lines = markdown.split(newLineRe);
}
var reparseMarkdown = lines.slice(current.startLine - 1, current.endLine).join("\n");
var tokens = micromarkParseWithOffset(reparseMarkdown, reparseOptions, referencesDefined, current.startLine - 1);
var tokens = micromarkParseWithOffset(reparseMarkdown, reparseOptions, referencesDefined, current.startLine - 1, current);
current.children = tokens;
// Avoid stack overflow of Array.push(...spread)
// eslint-disable-next-line unicorn/prefer-spread
Expand All @@ -1372,9 +1371,6 @@ function micromarkParseWithOffset(markdown, micromarkOptions, referencesDefined,
current = history.pop();
}
}
};
for (_iterator.s(); !(_step = _iterator.n()).done;) {
_loop();
}

// Return document
Expand Down Expand Up @@ -3575,6 +3571,11 @@ var _require = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"),
addErrorDetailIf = _require.addErrorDetailIf;
var _require2 = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"),
filterByTypes = _require2.filterByTypes;

/**
* @typedef {import("../helpers/micromark.cjs").Token} Token
*/

module.exports = {
"names": ["MD007", "ul-indent"],
"description": "Unordered list indentation",
Expand All @@ -3591,15 +3592,17 @@ module.exports = {
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var token = _step.value;
var startColumn = token.startColumn,
var parent = token.parent,
startColumn = token.startColumn,
startLine = token.startLine,
type = token.type;
if (type === "blockQuotePrefix") {
lastBlockQuotePrefix = token;
} else if (type === "listUnordered") {
var nesting = 0;
/** @type {Token | null} */
var current = token;
while (current = current.parent()) {
while (current = current.parent) {
if (current.type === "listUnordered") {
nesting++;
} else if (current.type === "listOrdered") {
Expand All @@ -3614,7 +3617,7 @@ module.exports = {
}
} else {
// listItemPrefix
var _nesting = unorderedListNesting.get(token.parent());
var _nesting = unorderedListNesting.get(parent);
if (_nesting !== undefined) {
var _lastBlockQuotePrefix;
// listItemPrefix for listUnordered
Expand Down
29 changes: 16 additions & 13 deletions helpers/micromark.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,7 @@ const flatTokensSymbol = Symbol("flat-tokens");
* @property {number} endColumn End column (1-based).
* @property {string} text Token text.
* @property {Token[]} children Child tokens.
* @property {GetTokenParent} parent Parent token.
*/

/**
* Returns parent Token of a Token.
*
* @typedef {Function} GetTokenParent
* @returns {Token} Parent token.
* @property {Token | null} parent Parent token.
*/

/**
Expand Down Expand Up @@ -105,13 +98,15 @@ function getMicromarkEvents(
* @param {Object} micromarkOptions Options for micromark.
* @param {boolean} referencesDefined Treat references as defined.
* @param {number} lineDelta Offset to apply to start/end line.
* @param {Token} [ancestor] Parent of top-most tokens.
* @returns {Token[]} Micromark tokens (frozen).
*/
function micromarkParseWithOffset(
markdown,
micromarkOptions,
referencesDefined,
lineDelta
lineDelta,
ancestor
) {
// Use micromark to parse document into Events
const events = getMicromarkEvents(
Expand All @@ -121,8 +116,16 @@ function micromarkParseWithOffset(
// Create Token objects
const document = [];
let flatTokens = [];
/** @type {Token} */
const root = {
"children": document
"type": "ROOT",
"startLine": -1,
"startColumn": -1,
"endLine": -1,
"endColumn": -1,
"text": "ROOT",
"children": document,
"parent": null
};
const history = [ root ];
let current = root;
Expand All @@ -146,11 +149,10 @@ function micromarkParseWithOffset(
endColumn,
text,
"children": [],
"parent": () => (previous === root ? null : previous)
"parent": ((previous === root) ? (ancestor || null) : previous)
};
previous.children.push(current);
flatTokens.push(current);
// @ts-ignore
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
skipHtmlFlowChildren = true;
if (!reparseOptions || !lines) {
Expand All @@ -173,7 +175,8 @@ function micromarkParseWithOffset(
reparseMarkdown,
reparseOptions,
referencesDefined,
current.startLine - 1
current.startLine - 1,
current
);
current.children = tokens;
// Avoid stack overflow of Array.push(...spread)
Expand Down
11 changes: 8 additions & 3 deletions lib/md007.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
const { addErrorDetailIf } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs");

/**
* @typedef {import("../helpers/micromark.cjs").Token} Token
*/

module.exports = {
"names": [ "MD007", "ul-indent" ],
"description": "Unordered list indentation",
Expand All @@ -20,13 +24,14 @@ module.exports = {
[ "blockQuotePrefix", "listItemPrefix", "listUnordered" ]
);
for (const token of tokens) {
const { startColumn, startLine, type } = token;
const { parent, startColumn, startLine, type } = token;
if (type === "blockQuotePrefix") {
lastBlockQuotePrefix = token;
} else if (type === "listUnordered") {
let nesting = 0;
/** @type {Token | null} */
let current = token;
while ((current = current.parent())) {
while ((current = current.parent)) {
if (current.type === "listUnordered") {
nesting++;
} else if (current.type === "listOrdered") {
Expand All @@ -41,7 +46,7 @@ module.exports = {
}
} else {
// listItemPrefix
const nesting = unorderedListNesting.get(token.parent());
const nesting = unorderedListNesting.get(parent);
if (nesting !== undefined) {
// listItemPrefix for listUnordered
const expectedIndent =
Expand Down
6 changes: 5 additions & 1 deletion test/markdownlint-test-custom-rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,11 @@ test("customRulesParamsAreFrozen", (t) => {
t.true(Object.isFrozen(current) || (current === params));
for (const name of Object.getOwnPropertyNames(current)) {
const value = current[name];
if (value && (typeof value === "object")) {
if (
value &&
(typeof value === "object") &&
(name !== "parent")
) {
pending.push(value);
}
}
Expand Down
19 changes: 18 additions & 1 deletion test/markdownlint-test-micromark.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,26 @@ const testTokens = new Promise((resolve, reject) => {
testContent.then(parse).then(resolve, reject);
});

const cloneToken = (token) => {
for (const child of token.children) {
const expectedParent = (token.type ? token : null);
if (child.parent !== expectedParent) {
throw new Error("Unexpected parent.");
}
}
const clone = { ...token };
delete clone.parent;
clone.children = clone.children.map(cloneToken);
return clone;
};

const cloneTokens = (tokens) => (
cloneToken({ "children": tokens }).children
);

test("parse", async(t) => {
t.plan(1);
t.snapshot(await testTokens, "Unexpected tokens");
t.snapshot(cloneTokens(await testTokens), "Unexpected tokens");
});

test("getMicromarkEvents/filterByPredicate", async(t) => {
Expand Down
Loading

0 comments on commit 2a56f13

Please sign in to comment.