termrender 4.4.0__tar.gz → 4.6.0__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.
- {termrender-4.4.0 → termrender-4.6.0}/CHANGELOG.md +53 -0
- {termrender-4.4.0 → termrender-4.6.0}/PKG-INFO +1 -1
- termrender-4.6.0/src/termrender/renderers/mermaid_flow.py +110 -0
- termrender-4.6.0/src/termrender/renderers/mermaid_flow_layout.py +1460 -0
- termrender-4.6.0/tests/test_mermaid_flow.py +168 -0
- termrender-4.6.0/tests/test_mermaid_flow_shapes.py +313 -0
- termrender-4.4.0/src/termrender/renderers/mermaid_flow_layout.py +0 -602
- {termrender-4.4.0 → termrender-4.6.0}/.github/workflows/publish.yml +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/.gitignore +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/CLAUDE.md +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/LICENSE +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/README.md +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/design.json +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/pyproject.toml +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/requirements.json +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/scripts/build-mermaid-ascii.sh +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/CLAUDE.md +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/__init__.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/__main__.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/_bin/mermaid-ascii-darwin-arm64 +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/_mermaid_bin.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/blocks.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/emit.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/layout.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/parser.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/py.typed +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/CLAUDE.md +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/__init__.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/borders.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/charts.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/code.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/columns.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/diff.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/divider.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_flow_model.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_flow_parser.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_gantt.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_journey.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_mindmap.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_pie.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_prelude.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_sequence.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/mermaid_timeline.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/panel.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/quote.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/stat.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/table.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/text.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/timeline.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/renderers/tree.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/src/termrender/style.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/__init__.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_charts.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_cli_contract.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_column_alignment.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_diff.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_inline_badge.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_linebreak.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_compat.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_dispatch.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_flow_layout.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_flow_model.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_flow_parser.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_gantt.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_journey.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_mindmap.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_pie.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_sequence.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_mermaid_timeline.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_myst_gaps.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_stat.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_tasklist.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_timeline.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/tests/test_variable_colons.py +0 -0
- {termrender-4.4.0 → termrender-4.6.0}/uv.lock +0 -0
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v4.6.0 (2026-07-06)
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
- Add flowchart node shapes, subgraph frames, and direction rendering
|
|
9
|
+
([`e872199`](https://github.com/crouton-labs/termrender/commit/e87219956294319feb0015d2cf4573b8cc60a0cb))
|
|
10
|
+
|
|
11
|
+
Applies and hardens the salvaged decoration work for the native mermaid flowchart renderer's layout
|
|
12
|
+
engine:
|
|
13
|
+
|
|
14
|
+
- Nine distinct node-shape borders (rect, round, stadium, cylinder, circle, diamond, hexagon,
|
|
15
|
+
subroutine, parallelogram), each reserving its full bounding box so the router treats every shape
|
|
16
|
+
as impassable. - Subgraph enclosure frames (left-anchored title, nested, flatten when members
|
|
17
|
+
aren't placed contiguously enough for a clean rect). - TB/BT/LR/RL direction handling via a
|
|
18
|
+
post-layout coordinate transform.
|
|
19
|
+
|
|
20
|
+
Fixes found while hardening: - draw_frame now reserves the title text cells (not the whole border)
|
|
21
|
+
so a cross-boundary edge crossing a frame's top border can no longer clobber a letter of the
|
|
22
|
+
subgraph title. - Subgraph frame sizing is now computed bottom-up (_build_subgraph_frames): a
|
|
23
|
+
parent subgraph's extent is built from its children's *padded frame rects* (when they get a frame)
|
|
24
|
+
rather than raw member extents, so a nested subgraph whose members share the same column/row span
|
|
25
|
+
as its parent no longer produces an identically-sized frame that overwrites the parent's border —
|
|
26
|
+
nesting now always has real margin. - Corrected the module docstring's stale "every node renders
|
|
27
|
+
as a plain rectangle, frames not yet wired" description to match the shipped shape/frame drawers.
|
|
28
|
+
|
|
29
|
+
Adds tests/test_mermaid_flow_shapes.py: real-geometry assertions for shape distinctness, a 9-shape
|
|
30
|
+
gallery, subgraph frame containment, nested-frame non-overlap, non-contiguous-subgraph flatten,
|
|
31
|
+
LR/RL/BT topology + arrowhead direction, LR same-rank spacing, and router avoidance of a diamond's
|
|
32
|
+
interior. Full suite: 437 passed (422 existing + 15 new), no regressions.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## v4.5.0 (2026-07-06)
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
- Add flowchart edge router and public render_flowchart
|
|
40
|
+
([`a1b46cf`](https://github.com/crouton-labs/termrender/commit/a1b46cf11607ec6b31ea8fe1b4d90b11aafff10f))
|
|
41
|
+
|
|
42
|
+
- Replace the placeholder edge drawing in mermaid_flow_layout.py with the full orthogonal router:
|
|
43
|
+
rank-relative endpoint anchors (forward/same-rank/ back-edge), L/Z staircase paths for forward
|
|
44
|
+
edges, growing side-lane C-paths for back-edges so they never overlay forward edges, arrowheads
|
|
45
|
+
chosen from final-segment direction, edge labels centered on the longest straight run (shifting
|
|
46
|
+
off reserved cells), and self-loops modeled on the sequence renderer's self-message loop. - Add
|
|
47
|
+
mermaid_flow.py exposing the public, pure, never-raising render_flowchart(source, width) ->
|
|
48
|
+
list[str], wiring parse -> layout_flowgraph -> lines behind the three-case degradation contract
|
|
49
|
+
(no header, zero nodes, unexpected layout exception -> raw echo). - Add
|
|
50
|
+
tests/test_mermaid_flow.py: real end-to-end geometry/topology assertions, including the labeled
|
|
51
|
+
back-edge cycle that panics the Go binary, multi-parent attachment, headless edges, and echo
|
|
52
|
+
degradation.
|
|
53
|
+
|
|
54
|
+
Unwired: nothing imports mermaid_flow yet (later phase's cutover).
|
|
55
|
+
|
|
56
|
+
|
|
4
57
|
## v4.4.0 (2026-07-06)
|
|
5
58
|
|
|
6
59
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: termrender
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.6.0
|
|
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
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Public entry point for the native mermaid flowchart/graph renderer.
|
|
2
|
+
|
|
3
|
+
Standalone module: exposes a single pure function, :func:`render_flowchart`.
|
|
4
|
+
Not yet wired into ``mermaid.py``'s dispatcher (a later, orchestrator-owned
|
|
5
|
+
phase) — nothing in this package imports it. This module is a thin
|
|
6
|
+
orchestrator over the parser and layout engine; it owns none of the grammar
|
|
7
|
+
or layout logic itself, only header sniffing and the degradation contract.
|
|
8
|
+
|
|
9
|
+
Layout model
|
|
10
|
+
------------
|
|
11
|
+
``render_flowchart`` is ``parse -> layout_flowgraph -> lines``, wrapped in a
|
|
12
|
+
degradation guard (see *Degradation contract* below). :func:`~termrender.
|
|
13
|
+
renderers.mermaid_flow_parser.parse` turns mermaid source into a
|
|
14
|
+
:class:`~termrender.renderers.mermaid_flow_model.FlowGraph`;
|
|
15
|
+
:func:`~termrender.renderers.mermaid_flow_layout.layout_flowgraph` lays it
|
|
16
|
+
out with ``grandalf`` (pure-Python Sugiyama) and rasterizes it — bordered
|
|
17
|
+
rectangle nodes, an orthogonal edge router (L/Z paths for forward edges,
|
|
18
|
+
growing side lanes for back-edges/cycles, arrowheads, edge labels,
|
|
19
|
+
self-loops) — onto a char grid. See ``mermaid_flow_parser.py`` and
|
|
20
|
+
``mermaid_flow_layout.py``'s module docstrings for the full grammar and
|
|
21
|
+
routing model; this module covers only the public contract.
|
|
22
|
+
|
|
23
|
+
Grammar supported
|
|
24
|
+
------------------
|
|
25
|
+
Header: ``graph``/``flowchart`` + direction (``TD``/``TB``/``LR``/``RL``/
|
|
26
|
+
``BT``). Node shapes: ``[rect]``, ``(round)``, ``([stadium])``,
|
|
27
|
+
``[(cylinder)]``, ``((circle))``, ``{diamond}``, ``{{hexagon}}``,
|
|
28
|
+
``[[subroutine]]``, ``[/parallelogram/]`` — this phase renders every shape
|
|
29
|
+
as a plain rectangle (distinct shape borders are a later phase; only the
|
|
30
|
+
label text is load-bearing here). Edges: ``-->``, ``---``, ``-.->``, ``==>``
|
|
31
|
+
(and bidirectional forms), with ``|label|`` and inline ``A -- text --> B``
|
|
32
|
+
labels, and ``&`` fan-out. ``subgraph ... end`` blocks parse but are not yet
|
|
33
|
+
rendered as frames (nodes inside them still place and render normally).
|
|
34
|
+
``class``/``classDef``/``style``/``click``/``linkStyle`` lines are ignored.
|
|
35
|
+
|
|
36
|
+
Known degradations (by design, not bugs)
|
|
37
|
+
-----------------------------------------
|
|
38
|
+
- Node shapes other than a plain rectangle border are not yet visually
|
|
39
|
+
distinct (Phase 4 of this renderer's build).
|
|
40
|
+
- Subgraph blocks parse but are not yet drawn as enclosing frames (Phase 4).
|
|
41
|
+
- See ``mermaid_flow_layout.py``'s module docstring for the edge-routing
|
|
42
|
+
degradations (dense-graph crossings, label-lane overlap, CJK wrapping,
|
|
43
|
+
minimum-box-size self-loop cosmetics).
|
|
44
|
+
- ``width`` is advisory only: like the other native renderers in this
|
|
45
|
+
package, this renderer sizes to content and may overflow a narrow
|
|
46
|
+
terminal rather than truncate the diagram.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
from termrender.renderers.mermaid_flow_layout import layout_flowgraph
|
|
52
|
+
from termrender.renderers.mermaid_flow_parser import FlowchartError, parse
|
|
53
|
+
|
|
54
|
+
__all__ = ["render_flowchart"]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def render_flowchart(source: str, width: int) -> list[str]:
|
|
58
|
+
"""Render a mermaid ``graph``/``flowchart`` source to unicode lines.
|
|
59
|
+
|
|
60
|
+
Pure and total: never raises. Degrades to a raw echo of ``source``
|
|
61
|
+
(each line ``\\n``-split and ``.rstrip()``-ed, containing no
|
|
62
|
+
box-drawing glyphs) exactly when:
|
|
63
|
+
|
|
64
|
+
1. The source isn't a flowchart at all (no ``graph``/``flowchart``
|
|
65
|
+
header on its first non-blank, post-prelude line) — :func:`parse`
|
|
66
|
+
raises :class:`FlowchartError`.
|
|
67
|
+
2. Parsing succeeds but yields zero nodes (an empty or comment-only
|
|
68
|
+
diagram body) — nothing to draw.
|
|
69
|
+
3. Any unexpected exception escapes :func:`layout_flowgraph` — a
|
|
70
|
+
defensive catch-all; this should never happen for well-typed input,
|
|
71
|
+
but the guarantee is "never crash, degrade" regardless.
|
|
72
|
+
|
|
73
|
+
Otherwise, returns the rendered diagram: guaranteed to contain unicode
|
|
74
|
+
box-drawing glyphs (every node is a bordered box), never ANSI escapes.
|
|
75
|
+
The distinction matters downstream — code that detects render success
|
|
76
|
+
by the *presence* of box-drawing glyphs relies on the echo path never
|
|
77
|
+
emitting any.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
source: The mermaid fence body (with or without the surrounding
|
|
81
|
+
fence markers — only the text between them).
|
|
82
|
+
width: Advisory terminal width. See the module docstring's
|
|
83
|
+
"Known degradations" for why this is advisory rather than a
|
|
84
|
+
hard wrap.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Rendered lines on success, or a raw-echo of ``source`` on any of
|
|
88
|
+
the three degradation conditions above.
|
|
89
|
+
"""
|
|
90
|
+
try:
|
|
91
|
+
graph = parse(source)
|
|
92
|
+
except FlowchartError:
|
|
93
|
+
return _raw_echo(source)
|
|
94
|
+
|
|
95
|
+
if not graph.nodes:
|
|
96
|
+
return _raw_echo(source)
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
lines = layout_flowgraph(graph, width)
|
|
100
|
+
except Exception:
|
|
101
|
+
return _raw_echo(source)
|
|
102
|
+
|
|
103
|
+
if not lines:
|
|
104
|
+
return _raw_echo(source)
|
|
105
|
+
|
|
106
|
+
return lines
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _raw_echo(source: str) -> list[str]:
|
|
110
|
+
return [line.rstrip() for line in source.splitlines()]
|