mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-22 05:40:48 +02:00
Remove params.tokenLists to simplify custom rule API.
This commit is contained in:
parent
7a752784f1
commit
b33acb81d9
2 changed files with 100 additions and 94 deletions
175
lib/shared.js
175
lib/shared.js
|
@ -117,51 +117,104 @@ module.exports.headingStyleFor = function headingStyleFor(token) {
|
|||
|
||||
// Calls the provided function for each matching token
|
||||
function filterTokens(params, type, callback) {
|
||||
(params.tokenLists[type] || []).forEach(callback);
|
||||
params.tokens.forEach(function forToken(token) {
|
||||
if (token.type === type) {
|
||||
callback(token);
|
||||
}
|
||||
});
|
||||
}
|
||||
module.exports.filterTokens = filterTokens;
|
||||
|
||||
var lastForEachLineParams = null;
|
||||
var lastForEachLineResult = null;
|
||||
var tokenCache = null;
|
||||
// Caches line metadata and flattened lists for reuse
|
||||
function makeTokenCache(params) {
|
||||
if (!params) {
|
||||
tokenCache = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate line metadata array
|
||||
var lineMetadata = new Array(params.lines.length);
|
||||
var fenceStart = null;
|
||||
var inFence = false;
|
||||
// Find fenced code by pattern (parser ignores "``` close fence")
|
||||
params.lines.forEach(function forLine(line, lineIndex) {
|
||||
var metadata = 0;
|
||||
var match = /^(`{3,}|~{3,})/.exec(line);
|
||||
var fence = match && match[1];
|
||||
if (fence &&
|
||||
(!inFence || (fence.substr(0, fenceStart.length) === fenceStart))) {
|
||||
metadata = inFence ? 2 : 6;
|
||||
fenceStart = inFence ? null : fence;
|
||||
inFence = !inFence;
|
||||
} else if (inFence) {
|
||||
metadata = 1;
|
||||
}
|
||||
lineMetadata[lineIndex] = metadata;
|
||||
});
|
||||
// Find code blocks normally
|
||||
filterTokens(params, "code_block", function forToken(token) {
|
||||
for (var i = token.map[0]; i < token.map[1]; i++) {
|
||||
lineMetadata[i] = 1;
|
||||
}
|
||||
});
|
||||
// Find tables normally
|
||||
filterTokens(params, "table_open", function forToken(token) {
|
||||
for (var i = token.map[0]; i < token.map[1]; i++) {
|
||||
lineMetadata[i] += 8;
|
||||
}
|
||||
});
|
||||
|
||||
// Flatten lists
|
||||
var flattenedLists = [];
|
||||
var stack = [];
|
||||
var current = null;
|
||||
var lastWithMap = { "map": [ 0, 1 ] };
|
||||
params.tokens.forEach(function forToken(token) {
|
||||
if ((token.type === "bullet_list_open") ||
|
||||
(token.type === "ordered_list_open")) {
|
||||
// Save current context and start a new one
|
||||
stack.push(current);
|
||||
current = {
|
||||
"unordered": (token.type === "bullet_list_open"),
|
||||
"parentsUnordered": !current ||
|
||||
(current.unordered && current.parentsUnordered),
|
||||
"open": token,
|
||||
"items": [],
|
||||
"nesting": stack.length - 1,
|
||||
"lastLineIndex": -1,
|
||||
"insert": flattenedLists.length
|
||||
};
|
||||
} else if ((token.type === "bullet_list_close") ||
|
||||
(token.type === "ordered_list_close")) {
|
||||
// Finalize current context and restore previous
|
||||
current.lastLineIndex = lastWithMap.map[1];
|
||||
flattenedLists.splice(current.insert, 0, current);
|
||||
delete current.insert;
|
||||
current = stack.pop();
|
||||
} else if (token.type === "list_item_open") {
|
||||
// Add list item
|
||||
current.items.push(token);
|
||||
} else if (token.map) {
|
||||
// Track last token with map
|
||||
lastWithMap = token;
|
||||
}
|
||||
});
|
||||
|
||||
// Cache results
|
||||
tokenCache = {
|
||||
"params": params,
|
||||
"lineMetadata": lineMetadata,
|
||||
"flattenedLists": flattenedLists
|
||||
};
|
||||
}
|
||||
module.exports.makeTokenCache = makeTokenCache;
|
||||
|
||||
// Calls the provided function for each line (with context)
|
||||
module.exports.forEachLine = function forEachLine(params, callback) {
|
||||
if (params !== lastForEachLineParams) {
|
||||
var lineMetadata = new Array(params.lines.length);
|
||||
var fenceStart = null;
|
||||
var inFence = false;
|
||||
// Find fenced code by pattern (parser ignores "``` close fence")
|
||||
params.lines.forEach(function forLine(line, lineIndex) {
|
||||
var metadata = 0;
|
||||
var match = /^(`{3,}|~{3,})/.exec(line);
|
||||
var fence = match && match[1];
|
||||
if (fence &&
|
||||
(!inFence || (fence.substr(0, fenceStart.length) === fenceStart))) {
|
||||
metadata = inFence ? 2 : 6;
|
||||
fenceStart = inFence ? null : fence;
|
||||
inFence = !inFence;
|
||||
} else if (inFence) {
|
||||
metadata = 1;
|
||||
}
|
||||
lineMetadata[lineIndex] = metadata;
|
||||
});
|
||||
// Find code blocks normally
|
||||
filterTokens(params, "code_block", function forToken(token) {
|
||||
for (var i = token.map[0]; i < token.map[1]; i++) {
|
||||
lineMetadata[i] = 1;
|
||||
}
|
||||
});
|
||||
// Find tables normally
|
||||
filterTokens(params, "table_open", function forToken(token) {
|
||||
for (var i = token.map[0]; i < token.map[1]; i++) {
|
||||
lineMetadata[i] += 8;
|
||||
}
|
||||
});
|
||||
lastForEachLineParams = params;
|
||||
lastForEachLineResult = lineMetadata;
|
||||
}
|
||||
// Invoke callback
|
||||
params.lines.forEach(function forLine(line, lineIndex) {
|
||||
var metadata = lastForEachLineResult[lineIndex];
|
||||
tokenCache.params.lines.forEach(function forLine(line, lineIndex) {
|
||||
var metadata = tokenCache.lineMetadata[lineIndex];
|
||||
callback(
|
||||
line,
|
||||
lineIndex,
|
||||
|
@ -197,49 +250,9 @@ module.exports.forEachHeading = function forEachHeading(params, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
var lastFlattenListsParams = null;
|
||||
var lastFlattenListsResult = null;
|
||||
// Returns (nested) lists as a flat array (in order)
|
||||
module.exports.flattenLists = function flattenLists(params) {
|
||||
if (lastFlattenListsParams !== params) {
|
||||
var lists = [];
|
||||
var stack = [];
|
||||
var current = null;
|
||||
var lastWithMap = { "map": [ 0, 1 ] };
|
||||
params.tokens.forEach(function forToken(token) {
|
||||
if ((token.type === "bullet_list_open") ||
|
||||
(token.type === "ordered_list_open")) {
|
||||
// Save current context and start a new one
|
||||
stack.push(current);
|
||||
current = {
|
||||
"unordered": (token.type === "bullet_list_open"),
|
||||
"parentsUnordered": !current ||
|
||||
(current.unordered && current.parentsUnordered),
|
||||
"open": token,
|
||||
"items": [],
|
||||
"nesting": stack.length - 1,
|
||||
"lastLineIndex": -1,
|
||||
"insert": lists.length
|
||||
};
|
||||
} else if ((token.type === "bullet_list_close") ||
|
||||
(token.type === "ordered_list_close")) {
|
||||
// Finalize current context and restore previous
|
||||
current.lastLineIndex = lastWithMap.map[1];
|
||||
lists.splice(current.insert, 0, current);
|
||||
delete current.insert;
|
||||
current = stack.pop();
|
||||
} else if (token.type === "list_item_open") {
|
||||
// Add list item
|
||||
current.items.push(token);
|
||||
} else if (token.map) {
|
||||
// Track last token with map
|
||||
lastWithMap = token;
|
||||
}
|
||||
});
|
||||
lastFlattenListsParams = params;
|
||||
lastFlattenListsResult = lists;
|
||||
}
|
||||
return lastFlattenListsResult;
|
||||
module.exports.flattenLists = function flattenLists() {
|
||||
return tokenCache.flattenedLists;
|
||||
};
|
||||
|
||||
// Adds a generic error object via the onError callback
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue