Skip to content
This repository was archived by the owner on Oct 16, 2025. It is now read-only.

Commit fdfd051

Browse files
authored
⬆️ UPDATE: Sync with mdformat 0.6.0 (tree rendering) (#7)
1 parent f8be3a4 commit fdfd051

File tree

6 files changed

+67
-77
lines changed

6 files changed

+67
-77
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
runs-on: ${{ matrix.os }}
2525
strategy:
2626
matrix:
27-
python-version: [3.6, 3.7, 3.8, 3.9.0-rc.1]
27+
python-version: [3.6, 3.7, 3.8, 3.9]
2828
os: [ubuntu-latest, windows-latest]
2929

3030
steps:

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v3.2.0
3+
rev: v3.4.0
44
hooks:
55
- id: end-of-file-fixer
66
- id: mixed-line-ending
77
- id: trailing-whitespace
88
- id: check-yaml
99
- id: check-toml
1010
- repo: https://github.com/pre-commit/pygrep-hooks
11-
rev: v1.6.0
11+
rev: v1.8.0
1212
hooks:
1313
- id: python-check-blanket-noqa
1414
- repo: https://github.com/timothycrosley/isort
15-
rev: 5.5.3
15+
rev: 5.6.4
1616
hooks:
1717
- id: isort
1818
- repo: https://github.com/psf/black
1919
rev: 20.8b1
2020
hooks:
2121
- id: black
2222
- repo: https://gitlab.com/pycqa/flake8
23-
rev: 3.8.3
23+
rev: 3.8.4
2424
hooks:
2525
- id: flake8
2626
additional_dependencies:
27-
- flake8-bugbear==20.1.4
27+
- flake8-bugbear==20.11.1
2828
- flake8-builtins==1.5.3
29-
- flake8-comprehensions==3.2.3
29+
- flake8-comprehensions==3.3.1

.pre-commit-test.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
# A pre-commit hook for testing unreleased changes.
2+
# This is a system hook that will NOT be given a virtual environment.
3+
# Thus you will need to `pip install .` before running.
14
repos:
25
- repo: local
36
hooks:
47
- id: mdformat
5-
name: mdformat
8+
name: mdformat-no-venv
69
entry: mdformat
710
files: "tests/pre-commit-test.md"
811
types: [markdown]
912
language: system
10-
additional_dependencies:
11-
- mdformat-tables

mdformat_tables/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""An mdformat plugin for rendering tables."""
22

3-
from .plugin import render_token, update_mdit # noqa: F401
4-
53
__version__ = "0.2.1"
4+
5+
from .plugin import RENDERER_FUNCS, update_mdit # noqa: F401

mdformat_tables/plugin.py

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from collections import OrderedDict
2-
from typing import List, Optional, Tuple
2+
from typing import Any, List, Mapping, MutableMapping
33

44
from markdown_it import MarkdownIt
5-
from markdown_it.token import Token
6-
from mdformat.renderer import MARKERS, MDRenderer
5+
from mdformat.renderer import RenderTreeNode
6+
from mdformat.renderer.typing import RendererFunc
77

88

99
def update_mdit(mdit: MarkdownIt) -> None:
@@ -12,26 +12,18 @@ def update_mdit(mdit: MarkdownIt) -> None:
1212

1313

1414
def _parse_cells(
15-
rows: List[List[List[Token]]], renderer: MDRenderer, options: dict, env: dict
15+
rows: List[List[RenderTreeNode]],
16+
renderer_funcs: Mapping[str, RendererFunc],
17+
options: Mapping[str, Any],
18+
env: MutableMapping,
1619
) -> List[List[str]]:
17-
"""Convert tokens in each cell to strings."""
18-
for i, row in enumerate(rows):
19-
for j, cell_tokens in enumerate(row):
20-
rows[i][j] = (
21-
renderer.render(
22-
[Token("paragraph_open", "p", 1)] + cell_tokens
23-
or [Token("text", "", 0)] + [Token("paragraph_close", "p", -1)],
24-
options,
25-
env,
26-
finalize=False,
27-
)
28-
.replace(MARKERS.BLOCK_SEPARATOR, "")
29-
.rstrip()
30-
)
31-
return rows
20+
"""Convert nodes in each cell to strings."""
21+
return [[cell.render(renderer_funcs, options, env) for cell in row] for row in rows]
3222

3323

34-
def _to_string(rows: List[List[str]], align: List[str], widths: dict) -> List[str]:
24+
def _to_string(
25+
rows: List[List[str]], align: List[List[str]], widths: Mapping[int, int]
26+
) -> List[str]:
3527
lines = []
3628
lines.append(
3729
"| "
@@ -63,57 +55,54 @@ def _to_string(rows: List[List[str]], align: List[str], widths: dict) -> List[st
6355
return lines
6456

6557

66-
def render_token(
67-
renderer: MDRenderer,
68-
tokens: List[Token],
69-
index: int,
70-
options: dict,
71-
env: dict,
72-
) -> Optional[Tuple[str, int]]:
73-
"""Convert token(s) to a string, or return None if no render method available.
74-
75-
:returns: (text, index) where index is of the final "consumed" token
76-
"""
77-
if tokens[index].type != "table_open":
78-
return None
79-
80-
# gather all cell tokens into row * column array
81-
rows = []
82-
align = []
83-
while index < len(tokens) and tokens[index].type != "table_close":
84-
index += 1
85-
if tokens[index].type == "tr_open":
86-
rows.append([])
87-
align.append([])
88-
continue
89-
for tag in ["th", "td"]:
90-
if tokens[index].type != f"{tag}_open":
91-
continue
92-
rows[-1].append([])
93-
style = tokens[index].attrGet("style") or ""
94-
if "text-align:right" in style:
95-
align[-1].append(">")
96-
elif "text-align:left" in style:
97-
align[-1].append("<")
98-
elif "text-align:center" in style:
99-
align[-1].append("^")
100-
else:
101-
align[-1].append("")
102-
while index < len(tokens) and tokens[index].type != f"{tag}_close":
103-
index += 1
104-
rows[-1][-1].append(tokens[index])
58+
def _render_table(
59+
node: RenderTreeNode,
60+
renderer_funcs: Mapping[str, RendererFunc],
61+
options: Mapping[str, Any],
62+
env: MutableMapping,
63+
) -> str:
64+
"""Render a `RenderTreeNode` of type "table"."""
65+
# gather all cell nodes into row * column array
66+
rows: List[List[RenderTreeNode]] = []
67+
align: List[List[str]] = []
68+
69+
def _gather_cell_nodes(node: RenderTreeNode) -> None:
70+
"""Recursively gather cell nodes and alignment to `rows` and
71+
`align`."""
72+
for child in node.children:
73+
if child.type == "tr":
74+
rows.append([])
75+
align.append([])
76+
elif child.type in ("th", "td"):
77+
style = child.attrs.get("style") or ""
78+
if "text-align:right" in style:
79+
align[-1].append(">")
80+
elif "text-align:left" in style:
81+
align[-1].append("<")
82+
elif "text-align:center" in style:
83+
align[-1].append("^")
84+
else:
85+
align[-1].append("")
86+
inline_node = child.children[0]
87+
rows[-1].append(inline_node)
88+
_gather_cell_nodes(child)
89+
90+
_gather_cell_nodes(node)
10591

10692
# parse all cells
107-
rows = _parse_cells(rows, renderer, options, env)
93+
parsed_rows = _parse_cells(rows, renderer_funcs, options, env)
10894

10995
# work out the widths for each column
110-
widths = OrderedDict()
111-
for row in rows:
96+
widths: MutableMapping[int, int] = OrderedDict()
97+
for row in parsed_rows:
11298
for j, cell_text in enumerate(row):
11399
widths[j] = max(widths.get(j, 3), len(cell_text))
114100

115101
# write content
116102
# note: assuming always one header row
117-
lines = _to_string(rows, align, widths)
103+
lines = _to_string(parsed_rows, align, widths)
104+
105+
return "\n".join(lines)
106+
118107

119-
return "\n".join(lines) + MARKERS.BLOCK_SEPARATOR, index
108+
RENDERER_FUNCS: Mapping[str, RendererFunc] = {"table": _render_table}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ classifiers = [
1717
keywords = "mdformat,markdown,markdown-it"
1818

1919
requires-python=">=3.6"
20-
requires=["mdformat>=0.3.2,<0.6.0"]
20+
requires=["mdformat>=0.6.0,<0.7.0"]
2121

2222
[tool.flit.metadata.requires-extra]
2323
test = [

0 commit comments

Comments
 (0)