Refactor: Simplify markdown table print (#9660)

This commit is contained in:
fisker Cheung authored and GitHub committed 2020-11-16 08:56:45 +08:00
1 parent dc541cc9b9
commit ef6a2c5f8a
1 file changed
+43 -72
+43 -72
View File
@@ -41,6 +41,10 @@ const {
isAutolink,
} = require("./utils");
/**
* @typedef {import("../document").Doc} Doc
*/
const TRAILING_HARDLINE_NODES = new Set(["importExport"]);
const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link", "wikiLink"];
const SIBLING_NODE_TYPES = new Set([
@@ -577,37 +581,34 @@ function printTable(path, options, print) {
const hardlineWithoutBreakParent = hardline.parts[0];
const node = path.getValue();
// { [rowIndex: number]: { [columnIndex: number]: string } }
const columnMaxWidths = [];
// { [rowIndex: number]: { [columnIndex: number]: {text: string, width: number} } }
const contents = path.map(
(rowPath) =>
rowPath.map(
(cellPath) => printDocToString(cellPath.call(print), options).formatted,
"children"
),
rowPath.map((cellPath, columnIndex) => {
const text = printDocToString(cellPath.call(print), options).formatted;
const width = getStringWidth(text);
columnMaxWidths[columnIndex] = Math.max(
columnMaxWidths[columnIndex] || 3, // minimum width = 3 (---, :--, :-:, --:)
width
);
return { text, width };
}, "children"),
"children"
);
// Get the width of each column
const columnMaxWidths = contents.reduce(
(currentWidths, rowContents) =>
currentWidths.map((width, columnIndex) =>
Math.max(width, getStringWidth(rowContents[columnIndex]))
),
contents[0].map(() => 3) // minimum width = 3 (---, :--, :-:, --:)
);
const alignedTable = printTableContents(/* isCompact */ false);
if (options.proseWrap !== "never") {
return concat([breakParent, alignedTable]);
}
// Only if the --prose-wrap never is set and it exceeds the print width.
const compactTable = printTableContents(/* isCompact */ true);
return concat([breakParent, group(ifBreak(compactTable, alignedTable))]);
function printTableContents(isCompact) {
const parts = [printRow(contents[0], isCompact), printSeparator(isCompact)];
/** @type{Doc[]} */
const parts = [printRow(contents[0], isCompact), printAlign(isCompact)];
if (contents.length > 1) {
parts.push(
join(
@@ -621,66 +622,36 @@ function printTable(path, options, print) {
return join(hardlineWithoutBreakParent, parts);
}
function printSeparator(isCompact) {
return concat([
"| ",
join(
" | ",
columnMaxWidths.map((width, index) => {
const spaces = isCompact ? 3 : width;
switch (node.align[index]) {
case "left":
return ":" + "-".repeat(spaces - 1);
case "right":
return "-".repeat(spaces - 1) + ":";
case "center":
return ":" + "-".repeat(spaces - 2) + ":";
default:
return "-".repeat(spaces);
}
})
),
" |",
]);
function printAlign(isCompact) {
const align = columnMaxWidths.map((width, index) => {
const align = node.align[index];
const first = align === "center" || align === "left" ? ":" : "-";
const last = align === "center" || align === "right" ? ":" : "-";
const middle = isCompact ? "-" : "-".repeat(width - 2);
return `${first}${middle}${last}`;
});
return `| ${align.join(" | ")} |`;
}
function printRow(rowContents, isCompact) {
return concat([
"| ",
join(
" | ",
isCompact
? rowContents
: rowContents.map((rowContent, columnIndex) => {
switch (node.align[columnIndex]) {
case "right":
return alignRight(rowContent, columnMaxWidths[columnIndex]);
case "center":
return alignCenter(rowContent, columnMaxWidths[columnIndex]);
default:
return alignLeft(rowContent, columnMaxWidths[columnIndex]);
}
})
),
" |",
]);
}
const columns = rowContents.map(({ text, width }, columnIndex) => {
if (isCompact) {
return text;
}
const spaces = columnMaxWidths[columnIndex] - width;
const align = node.align[columnIndex];
let before = 0;
if (align === "right") {
before = spaces;
} else if (align === "center") {
before = Math.floor(spaces / 2);
}
const after = spaces - before;
return `${" ".repeat(before)}${text}${" ".repeat(after)}`;
});
function alignLeft(text, width) {
const spaces = width - getStringWidth(text);
return concat([text, " ".repeat(spaces)]);
}
function alignRight(text, width) {
const spaces = width - getStringWidth(text);
return concat([" ".repeat(spaces), text]);
}
function alignCenter(text, width) {
const spaces = width - getStringWidth(text);
const left = Math.floor(spaces / 2);
const right = spaces - left;
return concat([" ".repeat(left), text, " ".repeat(right)]);
return `| ${columns.join(" | ")} |`;
}
}