From 2d168d6c1461049c5c75b2f75d9af1b34c1f30a0 Mon Sep 17 00:00:00 2001 From: Kyle King Date: Fri, 23 Aug 2024 19:20:06 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20NEW:=20Add=20--compact-tables=20CLI?= =?UTF-8?q?=20argument=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-test.yaml | 7 ++ mdformat_tables/__init__.py | 7 +- mdformat_tables/plugin.py | 76 ++++++++++------- tests/fixtures-compact.md | 137 +++++++++++++++++++++++++++++++ tests/pre-commit-test-compact.md | 15 ++++ tests/pre-commit-test.md | 7 ++ tests/test_parse.py | 15 ++++ 7 files changed, 233 insertions(+), 31 deletions(-) create mode 100644 tests/fixtures-compact.md create mode 100644 tests/pre-commit-test-compact.md diff --git a/.pre-commit-test.yaml b/.pre-commit-test.yaml index a3a0ac0..a2f12d6 100644 --- a/.pre-commit-test.yaml +++ b/.pre-commit-test.yaml @@ -10,3 +10,10 @@ repos: files: "tests/pre-commit-test.md" types: [markdown] language: system + - id: mdformat-compact + name: mdformat-no-venv + entry: mdformat + args: ["--compact-tables"] + files: "tests/pre-commit-test-compact.md" + types: [markdown] + language: system diff --git a/mdformat_tables/__init__.py b/mdformat_tables/__init__.py index 0edc9ba..7491043 100644 --- a/mdformat_tables/__init__.py +++ b/mdformat_tables/__init__.py @@ -2,4 +2,9 @@ __version__ = "0.4.1" -from .plugin import POSTPROCESSORS, RENDERERS, update_mdit # noqa: F401 +from .plugin import ( # noqa: F401 + POSTPROCESSORS, + RENDERERS, + add_cli_options, + update_mdit, +) diff --git a/mdformat_tables/plugin.py b/mdformat_tables/plugin.py index ec10538..4cc7c1a 100644 --- a/mdformat_tables/plugin.py +++ b/mdformat_tables/plugin.py @@ -1,47 +1,60 @@ -from typing import List, Mapping, Sequence +import argparse +from typing import Iterable, List, Mapping, Sequence, Union from markdown_it import MarkdownIt from mdformat.renderer import RenderContext, RenderTreeNode from mdformat.renderer.typing import Postprocess, Render +_COMPACT_TABLES = False +"""user-specified flag for toggling compact tables.""" + + +def add_cli_options(parser: argparse.ArgumentParser) -> None: + """Add options to the mdformat CLI, to be stored in `mdit.options["mdformat"]`.""" + parser.add_argument( + "--compact-tables", + action="store_true", + help="If specified, do not add padding to table cells.", + ) + def update_mdit(mdit: MarkdownIt) -> None: """Update the parser, e.g. by adding a plugin: `mdit.use(myplugin)`""" mdit.enable("table") + global _COMPACT_TABLES + _COMPACT_TABLES = mdit.options["mdformat"].get("compact_tables", False) + def _to_string( rows: Sequence[Sequence[str]], align: Sequence[Sequence[str]], widths: Sequence[int] ) -> List[str]: - lines = [] - lines.append( - "| " - + " | ".join( - f"{{:{al or '<'}{widths[i]}}}".format(text) - for i, (text, al) in enumerate(zip(rows[0], align[0])) + def join_row(items: Union[Iterable[str], Sequence[str]]) -> str: + return "| " + " | ".join(items) + " |" + + def format_delimiter_cell(index: int, align: str) -> str: + delim = ( + (":" if align in ("<", "^") else "-") + + ("-" * max(0, widths[index] - 2)) + + (":" if align in (">", "^") else "-") ) - + " |" + return ":-:" if delim == "::" else delim + + header = join_row( + f"{{:{al or '<'}{widths[i]}}}".format(text) + for i, (text, al) in enumerate(zip(rows[0], align[0])) ) - lines.append( - "| " - + " | ".join( - (":" if al in ("<", "^") else "-") - + "-" * (widths[i] - 2) - + (":" if al in (">", "^") else "-") - for i, al in enumerate(align[0]) - ) - + " |" + delimiter = join_row( + (format_delimiter_cell(i, al) for i, al in enumerate(align[0])) ) - for row, als in zip(rows[1:], align[1:]): - lines.append( - "| " - + " | ".join( - f"{{:{al or '<'}{widths[i]}}}".format(text) - for i, (text, al) in enumerate(zip(row, als)) - ) - + " |" + rows = [ + join_row( + f"{{:{al or '<'}{widths[i]}}}".format(text) + for i, (text, al) in enumerate(zip(row, als)) ) - return lines + for row, als in zip(rows[1:], align[1:]) + ] + return [header, delimiter, *rows] def _render_table(node: RenderTreeNode, context: RenderContext) -> str: @@ -66,10 +79,13 @@ def _render_table(node: RenderTreeNode, context: RenderContext) -> str: align[-1].append("") rows[-1].append(descendant.render(context)) - # work out the widths for each column - widths = [ - max(3, *(len(row[col_idx]) for row in rows)) for col_idx in range(len(rows[0])) - ] + def _calculate_width(col_idx: int) -> int: + """Work out the widths for each column.""" + if _COMPACT_TABLES: + return 0 + return max(3, *(len(row[col_idx]) for row in rows)) + + widths = [_calculate_width(col_idx) for col_idx in range(len(rows[0]))] # write content # note: assuming always one header row diff --git a/tests/fixtures-compact.md b/tests/fixtures-compact.md new file mode 100644 index 0000000..1099ed7 --- /dev/null +++ b/tests/fixtures-compact.md @@ -0,0 +1,137 @@ +simple +. +a | bb +| - | - +1 | 2 +. +| a | bb | +| -- | -- | +| 1 | 2 | +. + +empty headers +. +| | | +|- | - +|1 | 2 +. +| | | +| -- | -- | +| 1 | 2 | +. + +no body +. +| | | +|- | - +. +| | | +| -- | -- | +. + +alignment +. +a | b | c +:- | -: | :-: +1 | 2 | 3 +xxxxxx | yyyyyy | zzzzzz +. +| a | b | c | +| :- | -: | :-: | +| 1 | 2 | 3 | +| xxxxxx | yyyyyy | zzzzzz | +. + +nested syntax +. +*a* | [b](link) +| - | - +`c` | [d](link) +. +| *a* | [b](link) | +| -- | -- | +| `c` | [d](link) | +. + +A list takes precedence in case of ambiguity +. +a | b +- | - +1 | 2 +. +a | b + +- | \- + 1 | 2 +. + +paragraph before/after +. +x +a | bb +-- | - +1 | 2 +y +. +x + +| a | bb | +| -- | -- | +| 1 | 2 | +| y | | +. + +Nested tables in blockquotes: +. +> a|b +> ---|--- +> bar|baz +. +> | a | b | +> | -- | -- | +> | bar | baz | +. + +references +. +| [![a][b]][c] | +| - | +| [![a][b]][c] | + +[b]: link1 +[c]: link2 +. +| [![a][b]][c] | +| -- | +| [![a][b]][c] | + +[b]: link1 +[c]: link2 +. + +Escaped table 1 +. +| a | +\| - | +. +| a | +| \- | +. + +Escaped table 2 +. +a +-\: +. +a +\-: +. + +Escaped table 3 +. +a +:\- +. +a +:\- +. diff --git a/tests/pre-commit-test-compact.md b/tests/pre-commit-test-compact.md new file mode 100644 index 0000000..acaf089 --- /dev/null +++ b/tests/pre-commit-test-compact.md @@ -0,0 +1,15 @@ +# hallo + +here's a table: + +| a | b | c | +| :- | -: | :-: | +| 1 | 2 | 3 | +| xxxxxx | yyyyyy | zzzzzz | + +And a larger one (from: https://github.com/hukkin/mdformat-gfm/issues/33) + +| | option 1 | option 2 | option 3 | ... | +| :- | :-: | :-: | -: | :-: | +| comparison 1 | On am we offices expense thought. Its hence ten smile age means. Seven chief sight far point any. Of so high into easy. Dashwoods eagerness oh extensive as discourse sportsman frankness. Husbands see disposed surprise likewise humoured yet pleasure. Fifteen no inquiry cordial so resolve garrets as. Impression was estimating surrounded solicitude indulgence son shy. | asd | asd | asda | +| comparison 2 | asdasd | On am we offices expense thought. Its hence ten smile age means. Seven chief sight far point any. Of so high into easy. Dashwoods eagerness oh extensive as discourse sportsman frankness. Husbands see disposed surprise likewise humoured yet pleasure. Fifteen no inquiry cordial so resolve garrets as. Impression was estimating surrounded solicitude indulgence son shy. | asd | | diff --git a/tests/pre-commit-test.md b/tests/pre-commit-test.md index 4c6067a..9e788d7 100644 --- a/tests/pre-commit-test.md +++ b/tests/pre-commit-test.md @@ -6,3 +6,10 @@ here's a table: | :----- | -----: | :----: | | 1 | 2 | 3 | | xxxxxx | yyyyyy | zzzzzz | + +And a larger one (from: https://github.com/hukkin/mdformat-gfm/issues/33) + +| | option 1 | option 2 | option 3 | ... | +| :----------- | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -------: | :--: | +| comparison 1 | On am we offices expense thought. Its hence ten smile age means. Seven chief sight far point any. Of so high into easy. Dashwoods eagerness oh extensive as discourse sportsman frankness. Husbands see disposed surprise likewise humoured yet pleasure. Fifteen no inquiry cordial so resolve garrets as. Impression was estimating surrounded solicitude indulgence son shy. | asd | asd | asda | +| comparison 2 | asdasd | On am we offices expense thought. Its hence ten smile age means. Seven chief sight far point any. Of so high into easy. Dashwoods eagerness oh extensive as discourse sportsman frankness. Husbands see disposed surprise likewise humoured yet pleasure. Fifteen no inquiry cordial so resolve garrets as. Impression was estimating surrounded solicitude indulgence son shy. | asd | | diff --git a/tests/test_parse.py b/tests/test_parse.py index cd6017a..e379ec5 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -15,3 +15,18 @@ def test_fixtures(line, title, text, expected): output = mdformat.text(text, extensions={"tables"}) print(output) assert output.rstrip() == expected.rstrip(), output + + +FIXTURES_COMPACT_PATH = Path(__file__).parent / "fixtures-compact.md" +fixtures_compact = read_fixture_file(FIXTURES_COMPACT_PATH) + + +@pytest.mark.parametrize( + "line,title,text,expected", fixtures_compact, ids=[f[1] for f in fixtures_compact] +) +def test_fixtures_compact(line, title, text, expected): + output = mdformat.text( + text, extensions={"tables"}, options={"compact_tables": True} + ) + print(output) + assert output.rstrip() == expected.rstrip(), output