termrender 3.0.0__tar.gz → 3.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {termrender-3.0.0 → termrender-3.0.1}/CHANGELOG.md +13 -0
  2. {termrender-3.0.0 → termrender-3.0.1}/PKG-INFO +1 -1
  3. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/__main__.py +42 -2
  4. {termrender-3.0.0 → termrender-3.0.1}/tests/test_cli_contract.py +36 -0
  5. {termrender-3.0.0 → termrender-3.0.1}/.github/workflows/publish.yml +0 -0
  6. {termrender-3.0.0 → termrender-3.0.1}/.gitignore +0 -0
  7. {termrender-3.0.0 → termrender-3.0.1}/CLAUDE.md +0 -0
  8. {termrender-3.0.0 → termrender-3.0.1}/LICENSE +0 -0
  9. {termrender-3.0.0 → termrender-3.0.1}/README.md +0 -0
  10. {termrender-3.0.0 → termrender-3.0.1}/design.json +0 -0
  11. {termrender-3.0.0 → termrender-3.0.1}/pyproject.toml +0 -0
  12. {termrender-3.0.0 → termrender-3.0.1}/requirements.json +0 -0
  13. {termrender-3.0.0 → termrender-3.0.1}/scripts/build-mermaid-ascii.sh +0 -0
  14. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/CLAUDE.md +0 -0
  15. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/__init__.py +0 -0
  16. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/_bin/mermaid-ascii-darwin-arm64 +0 -0
  17. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/_mermaid_bin.py +0 -0
  18. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/blocks.py +0 -0
  19. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/emit.py +0 -0
  20. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/layout.py +0 -0
  21. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/parser.py +0 -0
  22. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/py.typed +0 -0
  23. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/CLAUDE.md +0 -0
  24. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/__init__.py +0 -0
  25. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/borders.py +0 -0
  26. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/charts.py +0 -0
  27. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/code.py +0 -0
  28. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/columns.py +0 -0
  29. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/diff.py +0 -0
  30. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/divider.py +0 -0
  31. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/mermaid.py +0 -0
  32. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/panel.py +0 -0
  33. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/quote.py +0 -0
  34. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/stat.py +0 -0
  35. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/table.py +0 -0
  36. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/text.py +0 -0
  37. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/timeline.py +0 -0
  38. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/renderers/tree.py +0 -0
  39. {termrender-3.0.0 → termrender-3.0.1}/src/termrender/style.py +0 -0
  40. {termrender-3.0.0 → termrender-3.0.1}/tests/__init__.py +0 -0
  41. {termrender-3.0.0 → termrender-3.0.1}/tests/test_charts.py +0 -0
  42. {termrender-3.0.0 → termrender-3.0.1}/tests/test_column_alignment.py +0 -0
  43. {termrender-3.0.0 → termrender-3.0.1}/tests/test_diff.py +0 -0
  44. {termrender-3.0.0 → termrender-3.0.1}/tests/test_inline_badge.py +0 -0
  45. {termrender-3.0.0 → termrender-3.0.1}/tests/test_linebreak.py +0 -0
  46. {termrender-3.0.0 → termrender-3.0.1}/tests/test_mermaid_compat.py +0 -0
  47. {termrender-3.0.0 → termrender-3.0.1}/tests/test_myst_gaps.py +0 -0
  48. {termrender-3.0.0 → termrender-3.0.1}/tests/test_stat.py +0 -0
  49. {termrender-3.0.0 → termrender-3.0.1}/tests/test_tasklist.py +0 -0
  50. {termrender-3.0.0 → termrender-3.0.1}/tests/test_timeline.py +0 -0
  51. {termrender-3.0.0 → termrender-3.0.1}/tests/test_variable_colons.py +0 -0
  52. {termrender-3.0.0 → termrender-3.0.1}/uv.lock +0 -0
@@ -1,6 +1,19 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v3.0.1 (2026-06-10)
5
+
6
+ ### Bug Fixes
7
+
8
+ - Spawn tmux render pane via absolute termrender path, not bare PATH name
9
+ ([`993c646`](https://github.com/crouton-labs/termrender/commit/993c6463afc64b94b6dbbdbe6e69f7652feac500))
10
+
11
+ The tmux pane command baked a bare `termrender` token into split-window/ respawn-pane, so the
12
+ spawned pane resolved it via $PATH. A venv-only install (invoked by absolute path, not on PATH)
13
+ produced a pane that died instantly and silently. Build the pane command from termrender's own
14
+ absolute invocation (argv[0] when executable, else `python -m termrender`).
15
+
16
+
4
17
  ## v3.0.0 (2026-05-18)
5
18
 
6
19
  ### Chores
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: termrender
3
- Version: 3.0.0
3
+ Version: 3.0.1
4
4
  Summary: Rich terminal rendering of directive-flavored markdown
5
5
  Project-URL: Homepage, https://github.com/CaptainCrouton89/termrender
6
6
  Project-URL: Repository, https://github.com/CaptainCrouton89/termrender
@@ -4,6 +4,7 @@ import argparse
4
4
  import json
5
5
  import os
6
6
  import sys
7
+ from pathlib import Path
7
8
  from typing import Any, NoReturn
8
9
 
9
10
  from termrender import render, TerminalError, DirectiveError
@@ -59,6 +60,23 @@ Branches
59
60
  render render markdown to ANSI and print to stdout | use when producing output for display
60
61
  check validate directive syntax without rendering | use when validating before rendering
61
62
  watch live-render a file, updating on every save | use when monitoring a file interactively
63
+
64
+ Document format
65
+ Directive-flavored markdown. Triple-colon blocks carry attributes in {} and
66
+ nest arbitrarily; every block closes with a bare `:::`. Plain markdown
67
+ (headings, **bold**, *italic*, `code`, bullet/numbered lists) works
68
+ everywhere, including inside directives. Write structure, not box-drawing —
69
+ layout, padding, and guide lines are computed.
70
+
71
+ :::panel{title="" color=""} bordered box; color e.g. green|cyan|red
72
+ :::columns / :::col{width="N%"} side-by-side; col widths sum to 100%
73
+ :::tree{color=""} indentation → Unicode guide lines;
74
+ [x]=done [!]=warning status markers
75
+ :::callout{type=""} admonition; type success|warning|error|info
76
+ :::divider{label=""} labeled horizontal rule
77
+ :::code{lang=""} syntax-highlighted block (``` fences also work)
78
+ :::quote{author=""} attributed block quote
79
+ :::mermaid flowchart → ASCII (NOT ```mermaid fences)
62
80
  """
63
81
 
64
82
  _DOC_RENDER_HELP = """\
@@ -325,6 +343,27 @@ def _cmd_doc_watch(args: argparse.Namespace) -> None:
325
343
  sys.exit(EXIT_OK)
326
344
 
327
345
 
346
+ def _termrender_invocation() -> str:
347
+ """Shell-quoted command prefix that invokes *this* termrender.
348
+
349
+ A tmux pane spawned via split-window/respawn-pane resolves a bare
350
+ ``termrender`` token through ``$PATH``. When termrender lives only inside a
351
+ managed venv (e.g. invoked by absolute path), that bare name is not on PATH
352
+ and the spawned pane dies instantly and silently. Prefer the absolute path
353
+ of the running entrypoint (argv[0]) so the pane invokes the same binary;
354
+ fall back to ``python -m termrender`` when argv[0] is not a usable
355
+ executable.
356
+ """
357
+ import shlex
358
+
359
+ argv0 = sys.argv[0] if sys.argv else ""
360
+ if argv0:
361
+ entry = Path(argv0).resolve()
362
+ if entry.is_file() and os.access(entry, os.X_OK):
363
+ return shlex.quote(str(entry))
364
+ return f"{shlex.quote(sys.executable)} -m termrender"
365
+
366
+
328
367
  def _build_pane_cmd(
329
368
  *,
330
369
  watch: bool,
@@ -337,17 +376,18 @@ def _build_pane_cmd(
337
376
  import shlex
338
377
 
339
378
  cjk_flag = " --cjk" if cjk else ""
379
+ termrender = _termrender_invocation()
340
380
 
341
381
  if watch:
342
382
  # doc watch reads path as positional; use -- to guard against flag-looking paths
343
- cmd = f"termrender doc watch --color on{cjk_flag} -- {shlex.quote(path)}"
383
+ cmd = f"{termrender} doc watch --color on{cjk_flag} -- {shlex.quote(path)}"
344
384
  else:
345
385
  effective_path = tmpfile if tmpfile else path
346
386
  width_flag = f" --width {pane_width}" if pane_width is not None else ""
347
387
  # doc render reads stdin — cat the file into it
348
388
  cmd = (
349
389
  f"cat {shlex.quote(effective_path)}"
350
- f" | termrender doc render --color on{width_flag}{cjk_flag}"
390
+ f" | {termrender} doc render --color on{width_flag}{cjk_flag}"
351
391
  f" | less -R; rm -f {shlex.quote(effective_path)}"
352
392
  )
353
393
  return cmd
@@ -332,3 +332,39 @@ def test_doc_render_rejects_unknown_flag():
332
332
  assert r.returncode == 1
333
333
  out = json.loads(r.stdout)
334
334
  assert out["error"] == "bad_invocation"
335
+
336
+
337
+ # ---------------------------------------------------------------------------
338
+ # Pane command construction — must use an absolute termrender invocation, not a
339
+ # bare PATH-resolved name (a venv-only install is not on a spawned pane's PATH).
340
+ # ---------------------------------------------------------------------------
341
+
342
+ def test_build_pane_cmd_uses_absolute_invocation(monkeypatch, tmp_path):
343
+ import termrender.__main__ as m
344
+
345
+ fake = tmp_path / "termrender"
346
+ fake.write_text("#!/bin/sh\n")
347
+ fake.chmod(0o755)
348
+ monkeypatch.setattr(sys, "argv", [str(fake)])
349
+
350
+ watch_cmd = m._build_pane_cmd(
351
+ watch=True, path="/docs/a.md", cjk=False, pane_width=None, tmpfile=None,
352
+ )
353
+ assert str(fake.resolve()) in watch_cmd
354
+ assert watch_cmd.startswith(str(fake.resolve()) + " ") # absolute, not bare
355
+ assert " doc watch " in watch_cmd
356
+
357
+ render_cmd = m._build_pane_cmd(
358
+ watch=False, path="/docs/a.md", cjk=False, pane_width=80, tmpfile="/tmp/x.md",
359
+ )
360
+ assert str(fake.resolve()) in render_cmd
361
+ assert " doc render " in render_cmd
362
+
363
+
364
+ def test_termrender_invocation_falls_back_to_python_m(monkeypatch):
365
+ import termrender.__main__ as m
366
+
367
+ monkeypatch.setattr(sys, "argv", [""])
368
+ inv = m._termrender_invocation()
369
+ assert "-m termrender" in inv
370
+ assert sys.executable in inv
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes