From 50d8a35d542810782ce6f6f8460738d213ccdfa0 Mon Sep 17 00:00:00 2001 From: jf nz Date: Sun, 6 Sep 2026 08:57:34 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20NEW:=20Add=20--enable-tables=20to?= =?UTF-8?q?=20the=20CLI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ README.md | 22 ++++++++++++++++------ markdown_it/cli/parse.py | 29 ++++++++++++++++++----------- tests/test_cli.py | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d50cb3e..734b9365 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## Unreleased + +* ✨ Add `--enable-tables` to the CLI for file, standard input and interactive parsing. + ## 4.2.0 - 2026-05-07 * ✨ Add `make_fence_rule()` factory for configurable fence markers in [#394](https://github.com/executablebooks/markdown-it-py/pull/394) diff --git a/README.md b/README.md index 82d218b3..214bb453 100644 --- a/README.md +++ b/README.md @@ -101,17 +101,18 @@ Render markdown to HTML with markdown-it-py from the command-line: ```console -usage: markdown-it [-h] [-v] [--stdin|filenames [filenames ...]] +usage: markdown-it [-h] [-v] [--stdin] [--enable-tables] [filenames ...] Parse one or more markdown files, convert each to HTML, and print to stdout positional arguments: - --stdin read source Markdown file from standard input - filenames specify an optional list of files to convert + filenames specify an optional list of files to convert -optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit +options: + -h, --help show this help message and exit + -v, --version show program's version number and exit + --stdin read Markdown from standard input + --enable-tables enable table parsing Interactive: @@ -132,6 +133,15 @@ Batch: ``` +Tables are disabled by default, as in CommonMark. +Use `--enable-tables` with any input mode to enable them: + +```bash +markdown-it --enable-tables README.md > index.html +markdown-it --enable-tables --stdin < README.md > index.html +markdown-it --enable-tables +``` + ## References / Thanks Big thanks to the authors of [markdown-it]: diff --git a/markdown_it/cli/parse.py b/markdown_it/cli/parse.py index 5de738b2..b9010503 100644 --- a/markdown_it/cli/parse.py +++ b/markdown_it/cli/parse.py @@ -19,50 +19,54 @@ def main(args: Sequence[str] | None = None) -> int: namespace = parse_args(args) + md = MarkdownIt() + if namespace.enable_tables: + md.enable("table") if namespace.filenames: - convert(namespace.filenames) + convert(namespace.filenames, md) elif namespace.stdin: - convert_stdin() + convert_stdin(md) else: - interactive() + interactive(md) return 0 -def convert(filenames: Iterable[str]) -> None: +def convert(filenames: Iterable[str], md: MarkdownIt | None = None) -> None: for filename in filenames: - convert_file(filename) + convert_file(filename, md) -def convert_stdin() -> None: +def convert_stdin(md: MarkdownIt | None = None) -> None: """ Parse a Markdown file and dump the output to stdout. """ try: - rendered = MarkdownIt().render(sys.stdin.read()) + rendered = (md or MarkdownIt()).render(sys.stdin.read()) print(rendered, end="") except OSError: sys.stderr.write("Cannot parse Markdown from the standard input.\n") sys.exit(1) -def convert_file(filename: str) -> None: +def convert_file(filename: str, md: MarkdownIt | None = None) -> None: """ Parse a Markdown file and dump the output to stdout. """ try: with open(filename, encoding="utf8", errors="ignore") as fin: - rendered = MarkdownIt().render(fin.read()) + rendered = (md or MarkdownIt()).render(fin.read()) print(rendered, end="") except OSError: sys.stderr.write(f'Cannot open file "{filename}".\n') sys.exit(1) -def interactive() -> None: +def interactive(md: MarkdownIt | None = None) -> None: """ Parse user input, dump to stdout, rinse and repeat. Python REPL style. """ + md = md or MarkdownIt() print_heading() contents = [] more = False @@ -71,7 +75,7 @@ def interactive() -> None: prompt, more = ("... ", True) if more else (">>> ", True) contents.append(input(prompt) + "\n") except EOFError: - print("\n" + MarkdownIt().render("\n".join(contents)), end="") + print("\n" + md.render("".join(contents)), end="") more = False contents = [] except KeyboardInterrupt: @@ -111,6 +115,9 @@ def parse_args(args: Sequence[str] | None) -> argparse.Namespace: parser.add_argument( "--stdin", action="store_true", help="read Markdown from standard input" ) + parser.add_argument( + "--enable-tables", action="store_true", help="enable table parsing" + ) parser.add_argument( "filenames", nargs="*", help="specify an optional list of files to convert" ) diff --git a/tests/test_cli.py b/tests/test_cli.py index a2fe51d0..88afb62f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -95,3 +95,37 @@ def test_interactive_render(): # The rendered output is prefixed by a newline assert "\n

hello

\n" in output assert "Exiting" in output + + +@pytest.mark.parametrize("route", ["files", "stdin", "interactive"]) +@pytest.mark.parametrize("enable_tables", [False, True]) +def test_tables(route, enable_tables, tmp_path, capsys): + """Table parsing is opt-in on every CLI route, preserving HTML settings.""" + source = "a | b\n--- | ---\n1 | 2\n\nraw ~~plain~~\n" + expected = ( + "\n\n\n\n\n\n\n" + "\n\n\n\n\n\n
ab
12
\n" + if enable_tables + else "

a | b\n--- | ---\n1 | 2

\n" + ) + "

raw ~~plain~~

\n" + args = ["--enable-tables"] if enable_tables else [] + if route == "files": + paths = [tmp_path / "first.md", tmp_path / "second.md"] + for path in paths: + path.write_text(source, encoding="utf8") + assert parse.main([*args, *map(str, paths)]) == 0 + expected *= 2 + elif route == "stdin": + with patch("sys.stdin", io.StringIO(source)): + assert parse.main([*args, "--stdin"]) == 0 + else: + inputs = [*source.splitlines(), EOFError] * 2 + [KeyboardInterrupt] + with patch("builtins.input", side_effect=inputs): + assert parse.main(args) == 0 + expected = ( + f"{parse.version_str} (interactive)\n" + "Type Ctrl-D to complete input, or Ctrl-C to exit.\n" + + ("\n" + expected) * 2 + + "\nExiting.\n" + ) + assert capsys.readouterr().out == expected