From ef6a2c5f8a448bb16bcbaeab06f29e2be98a958d Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 16 Nov 2020 08:56:45 +0800 Subject: [PATCH] Refactor: Simplify markdown table print (#9660) --- src/language-markdown/printer-markdown.js | 115 ++++++++-------------- 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index 5ea2257b8..ec0644bc1 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -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(" | ")} |`; } }