mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
// @ts-check
|
|
|
|
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
|
import { filterByTypesCached } from "./cache.mjs";
|
|
|
|
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
|
const ignoreWhitespace = (tokens) => tokens.filter(
|
|
(token) => !whitespaceTypes.has(token.type)
|
|
);
|
|
const firstOrNothing = (items) => items[0];
|
|
const lastOrNothing = (items) => items[items.length - 1];
|
|
const makeRange = (start, end) => [ start, end - start + 1 ];
|
|
|
|
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
|
|
/** @type {import("markdownlint").Rule} */
|
|
export default {
|
|
"names": [ "MD055", "table-pipe-style" ],
|
|
"description": "Table pipe style",
|
|
"tags": [ "table" ],
|
|
"parser": "micromark",
|
|
"function": function MD055(params, onError) {
|
|
const style = String(params.config.style || "consistent");
|
|
let expectedStyle = style;
|
|
let expectedLeadingPipe =
|
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
|
|
let expectedTrailingPipe =
|
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
|
|
const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]);
|
|
for (const row of rows) {
|
|
// The following uses of first/lastOrNothing lack fallback handling
|
|
// because it seems not to be possible (i.e., 0% coverage)
|
|
const firstCell = firstOrNothing(row.children);
|
|
const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children));
|
|
const actualLeadingPipe = (leadingToken.type === "tableCellDivider");
|
|
const lastCell = lastOrNothing(row.children);
|
|
const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children));
|
|
const actualTrailingPipe = (trailingToken.type === "tableCellDivider");
|
|
const actualStyle = actualLeadingPipe ?
|
|
(actualTrailingPipe ? "leading_and_trailing" : "leading_only") :
|
|
(actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing");
|
|
if (expectedStyle === "consistent") {
|
|
expectedStyle = actualStyle;
|
|
expectedLeadingPipe = actualLeadingPipe;
|
|
expectedTrailingPipe = actualTrailingPipe;
|
|
}
|
|
if (actualLeadingPipe !== expectedLeadingPipe) {
|
|
addErrorDetailIf(
|
|
onError,
|
|
firstCell.startLine,
|
|
expectedStyle,
|
|
actualStyle,
|
|
`${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`,
|
|
undefined,
|
|
makeRange(row.startColumn, firstCell.startColumn)
|
|
);
|
|
}
|
|
if (actualTrailingPipe !== expectedTrailingPipe) {
|
|
addErrorDetailIf(
|
|
onError,
|
|
lastCell.endLine,
|
|
expectedStyle,
|
|
actualStyle,
|
|
`${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`,
|
|
undefined,
|
|
makeRange(lastCell.endColumn - 1, row.endColumn - 1)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|