feat(markdown): do not align table contents if it exceeds the print width and `--prose-wrap never` is set (#5701)

Fixes #5651
master
陈帅 2019-01-31 01:24:21 +08:00 committed by Jed Fox
parent cb8d300ca0
commit a9d2c41464
7 changed files with 227 additions and 21 deletions

View File

@ -41,3 +41,33 @@ Examples:
```
-->
- Markdown: Do not align table contents if it exceeds the print width and `--prose-wrap never` is set ([#5701] by [@chenshuai2144])
The aligned table is less readable than the compact one
if it's particularly long and the word wrapping is not enabled in the editor
so we now print them as compact tables in these situations.
<!-- prettier-ignore -->
```md
<!-- Input -->
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - |
<!-- Output (Prettier stable, --prose-wrap never) -->
| Property | Description | Type | Default |
| ---------- | --------------------------------------------------------------------------------------------------------------------- | ------- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - |
<!-- Output (Prettier master, --prose-wrap never) -->
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - |
```
[@chenshuai2144]: https://github.com/chenshuai2144
[#5701]: https://github.com/prettier/prettier/pull/5701

View File

@ -6,6 +6,7 @@ const pragma = require("./pragma");
const preprocess = require("./preprocess");
const {
builders: {
breakParent,
concat,
join,
line,
@ -13,6 +14,7 @@ const {
markAsRoot,
hardline,
softline,
ifBreak,
fill,
align,
indent,
@ -509,6 +511,7 @@ function printLine(path, value, options) {
}
function printTable(path, options, print) {
const hardlineWithoutBreakParent = hardline.parts[0];
const node = path.getValue();
const contents = []; // { [rowIndex: number]: { [columnIndex: number]: string } }
@ -524,6 +527,7 @@ function printTable(path, options, print) {
contents.push(rowContents);
}, "children");
// Get the width of each column
const columnMaxWidths = contents.reduce(
(currentWidths, rowContents) =>
currentWidths.map((width, columnIndex) =>
@ -531,28 +535,49 @@ function printTable(path, options, print) {
),
contents[0].map(() => 3) // minimum width = 3 (---, :--, :-:, --:)
);
return join(hardline, [
const alignedTable = join(hardlineWithoutBreakParent, [
printRow(contents[0]),
printSeparator(),
join(hardline, contents.slice(1).map(printRow))
join(
hardlineWithoutBreakParent,
contents.slice(1).map(rowContents => printRow(rowContents))
)
]);
function printSeparator() {
if (options.proseWrap !== "never") {
return concat([breakParent, alignedTable]);
}
// Only if the --prose-wrap never is set and it exceeds the print width.
const compactTable = join(hardlineWithoutBreakParent, [
printRow(contents[0], /* isCompact */ true),
printSeparator(/* isCompact */ true),
join(
hardlineWithoutBreakParent,
contents
.slice(1)
.map(rowContents => printRow(rowContents, /* isCompact */ true))
)
]);
return concat([breakParent, group(ifBreak(compactTable, alignedTable))]);
function printSeparator(isCompact) {
return concat([
"| ",
join(
" | ",
columnMaxWidths.map((width, index) => {
const spaces = isCompact ? 3 : width;
switch (node.align[index]) {
case "left":
return ":" + "-".repeat(width - 1);
return ":" + "-".repeat(spaces - 1);
case "right":
return "-".repeat(width - 1) + ":";
return "-".repeat(spaces - 1) + ":";
case "center":
return ":" + "-".repeat(width - 2) + ":";
return ":" + "-".repeat(spaces - 2) + ":";
default:
return "-".repeat(width);
return "-".repeat(spaces);
}
})
),
@ -560,32 +585,36 @@ function printTable(path, options, print) {
]);
}
function printRow(rowContents) {
function printRow(rowContents, isCompact) {
return concat([
"| ",
join(
" | ",
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]);
}
})
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]);
}
})
),
" |"
]);
}
function alignLeft(text, width) {
return concat([text, " ".repeat(width - privateUtil.getStringWidth(text))]);
const spaces = width - privateUtil.getStringWidth(text);
return concat([text, " ".repeat(spaces)]);
}
function alignRight(text, width) {
return concat([" ".repeat(width - privateUtil.getStringWidth(text)), text]);
const spaces = width - privateUtil.getStringWidth(text);
return concat([" ".repeat(spaces), text]);
}
function alignCenter(text, width) {

View File

@ -0,0 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`long-table.md 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
| printWidth
=====================================input======================================
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\\|ReactNode | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\\|ReactNode | - |
| itemLayout | The layout of list, default is \`horizontal\`, If a vertical list is desired, set the itemLayout property to \`vertical\` | string | - |
| rowKey | Item's unique key, could be a string or function that returns a string | string\\|Function(record):string | \`key\` |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/8659)) | false |
| loadMore | Shows a load more content | string\\|ReactNode | - |
| locale | i18n text including empty text | object | emptyText: 'No Data' <br> |
| pagination | Pagination [config](https://ant.design/components/pagination/), hide it by setting it to false | boolean \\| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |
=====================================output=====================================
| Property | Description | Type | Default |
| ---------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\\|ReactNode | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\\|ReactNode | - |
| itemLayout | The layout of list, default is \`horizontal\`, If a vertical list is desired, set the itemLayout property to \`vertical\` | string | - |
| rowKey | Item's unique key, could be a string or function that returns a string | string\\|Function(record):string | \`key\` |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/8659)) | false |
| loadMore | Shows a load more content | string\\|ReactNode | - |
| locale | i18n text including empty text | object | emptyText: 'No Data' <br> |
| pagination | Pagination [config](https://ant.design/components/pagination/), hide it by setting it to false | boolean \\| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |
================================================================================
`;
exports[`long-table.md 2`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "never"
| printWidth
=====================================input======================================
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\\|ReactNode | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\\|ReactNode | - |
| itemLayout | The layout of list, default is \`horizontal\`, If a vertical list is desired, set the itemLayout property to \`vertical\` | string | - |
| rowKey | Item's unique key, could be a string or function that returns a string | string\\|Function(record):string | \`key\` |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/8659)) | false |
| loadMore | Shows a load more content | string\\|ReactNode | - |
| locale | i18n text including empty text | object | emptyText: 'No Data' <br> |
| pagination | Pagination [config](https://ant.design/components/pagination/), hide it by setting it to false | boolean \\| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |
=====================================output=====================================
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\\|ReactNode | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\\|ReactNode | - |
| itemLayout | The layout of list, default is \`horizontal\`, If a vertical list is desired, set the itemLayout property to \`vertical\` | string | - |
| rowKey | Item's unique key, could be a string or function that returns a string | string\\|Function(record):string | \`key\` |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/8659)) | false |
| loadMore | Shows a load more content | string\\|ReactNode | - |
| locale | i18n text including empty text | object | emptyText: 'No Data' <br> |
| pagination | Pagination [config](https://ant.design/components/pagination/), hide it by setting it to false | boolean \\| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |
================================================================================
`;

View File

@ -0,0 +1,2 @@
run_spec(__dirname, ["markdown"]);
run_spec(__dirname, ["markdown"], { proseWrap: "never" });

View File

@ -0,0 +1,13 @@
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\|ReactNode | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\|ReactNode | - |
| itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - |
| rowKey | Item's unique key, could be a string or function that returns a string | string\|Function(record):string | `key` |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\|[object](https://ant.design/components/spin-cn/#API) ([more](https://github.com/ant-design/ant-design/issues/8659)) | false |
| loadMore | Shows a load more content | string\|ReactNode | - |
| locale | i18n text including empty text | object | emptyText: 'No Data' <br> |
| pagination | Pagination [config](https://ant.design/components/pagination/), hide it by setting it to false | boolean \| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |

View File

@ -134,3 +134,45 @@ proseWrap: "always"
================================================================================
`;
exports[`table.md 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "always"
| printWidth
=====================================input======================================
- min-table
| Age | Time | Food | Gold | Requirement |
| ------------ | ----- | ---- | ---- | ----------------------- |
| Feudal Age | 02:10 | 500 | 0 | Dark Age building x 2 |
| Castle Age | 02:40 | 800 | 200 |- |
| Imperial Age | 03:30 | 1000 | 800 | Castle Age building x 2 |
- big-table
|学号|姓名|分数|
|-|-|-|
|小明|男|75|
|小红|女|79|
|小陆|男|92|
=====================================output=====================================
- min-table
| Age | Time | Food | Gold | Requirement |
| ------------ | ----- | ---- | ---- | ----------------------- |
| Feudal Age | 02:10 | 500 | 0 | Dark Age building x 2 |
| Castle Age | 02:40 | 800 | 200 | - |
| Imperial Age | 03:30 | 1000 | 800 | Castle Age building x 2 |
- big-table
| 学号 | 姓名 | 分数 |
| ---- | ---- | ---- |
| 小明 | 男 | 75 |
| 小红 | 女 | 79 |
| 小陆 | 男 | 92 |
================================================================================
`;

View File

@ -0,0 +1,14 @@
- min-table
| Age | Time | Food | Gold | Requirement |
| ------------ | ----- | ---- | ---- | ----------------------- |
| Feudal Age | 02:10 | 500 | 0 | Dark Age building x 2 |
| Castle Age | 02:40 | 800 | 200 |- |
| Imperial Age | 03:30 | 1000 | 800 | Castle Age building x 2 |
- big-table
|学号|姓名|分数|
|-|-|-|
|小明|男|75|
|小红|女|79|
|小陆|男|92|