termaid 0.1.2__tar.gz → 0.2.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.
- {termaid-0.1.2 → termaid-0.2.0}/CHANGELOG.md +8 -1
- {termaid-0.1.2 → termaid-0.2.0}/PKG-INFO +58 -7
- {termaid-0.1.2 → termaid-0.2.0}/README.md +54 -5
- {termaid-0.1.2 → termaid-0.2.0}/demo/demo.tape +24 -0
- termaid-0.2.0/demo/erdiagram.mmd +19 -0
- termaid-0.2.0/demo/termaid-demo.gif +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/pyproject.toml +3 -2
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/__init__.py +28 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/cli.py +1 -1
- termaid-0.2.0/src/termaid/model/piechart.py +18 -0
- termaid-0.2.0/src/termaid/model/treemap.py +28 -0
- termaid-0.2.0/src/termaid/parser/piechart.py +63 -0
- termaid-0.2.0/src/termaid/parser/treemap.py +67 -0
- termaid-0.2.0/src/termaid/renderer/piechart.py +83 -0
- termaid-0.2.0/src/termaid/renderer/treemap.py +244 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_blockdiagram.py +1 -0
- termaid-0.2.0/tests/test_corner_cases.py +656 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_edge_styles.py +1 -1
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_erdiagram.py +2 -2
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_gitgraph.py +2 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_integration.py +23 -29
- termaid-0.2.0/tests/test_piechart.py +252 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_renderer.py +0 -34
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_sequence.py +8 -4
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_shapes.py +8 -4
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_themes.py +2 -1
- termaid-0.2.0/tests/test_treemap.py +240 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_warnings.py +5 -3
- {termaid-0.1.2 → termaid-0.2.0}/uv.lock +1 -1
- termaid-0.1.2/demo/termaid-demo.gif +0 -0
- termaid-0.1.2/tests/test_parser.py +0 -332
- {termaid-0.1.2 → termaid-0.2.0}/.github/workflows/ci.yml +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/.github/workflows/publish.yml +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/.gitignore +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/CONTRIBUTING.md +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/LICENSE +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/demo/flowchart.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/demo/gitgraph.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/demo/sequence.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/__main__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/graph/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/graph/model.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/graph/shapes.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/layout/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/layout/grid.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/blockdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/classdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/erdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/gitgraph.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/model/sequence.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/output/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/output/rich.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/output/text.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/output/widget.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/blockdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/classdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/erdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/flowchart.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/gitgraph.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/sequence.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/statediagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/parser/tokens.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/py.typed +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/blockdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/canvas.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/charset.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/classdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/draw.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/erdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/gitgraph.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/sequence.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/shapes/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/renderer/themes.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/routing/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/routing/pathfinder.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/src/termaid/routing/router.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/__init__.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/conftest.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/blockdiagram/basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/blockdiagram/col_span.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/blockdiagram/grid.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/blockdiagram/links.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/classdiagram/annotation.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/classdiagram/basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/classdiagram/inheritance.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/classdiagram/relationships.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/erdiagram/attributes.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/erdiagram/basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/erdiagram/dashed.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/erdiagram/multiple_entities.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/all_shapes.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/ampersand_both.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/backlink_complex.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/bidir_dotted.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/bidir_labeled.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/bidir_td.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/bidir_thick.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/bidirectional.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/blockdiagram/basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/blockdiagram/col_span.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/blockdiagram/grid.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/blockdiagram/links.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/branching.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/chain.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/classdiagram/annotation.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/classdiagram/basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/classdiagram/inheritance.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/classdiagram/relationships.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/comments.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/cycle.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/diamond.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/dotted_arrow.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/duplicate_labels.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/empty_graph.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/erdiagram/attributes.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/erdiagram/basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/erdiagram/dashed.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/erdiagram/multiple_entities.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/fan_in.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/fan_out.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/flowchart_keyword.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/gitgraph/cherry_pick.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/gitgraph/feature_branch.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/gitgraph/linear.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/gitgraph/tags.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/gitgraph/tb_direction.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/graph_bt.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/graph_rl.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/labeled_edges.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/large_graph.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/long_labels.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/mermaid_comprehensive.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/mixed_arrow_styles.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/multiple_links.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/no_arrow_dotted.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/no_arrow_solid.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/no_arrow_thick.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/node_with_label.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/parallelogram.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/self_ref_with_edge.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/self_reference.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/semicolons.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/arrows.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/autonumber.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/multiline_notes.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/nested_blocks.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/notes.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/participant_kinds.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/sequence/self_message.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/simple_lr.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/simple_tb.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/simple_td.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/single_node.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/statediagram/basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/statediagram/choice.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/statediagram/composite.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/statediagram/start_end.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/subgraph_basic.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/subgraph_nested.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/subgraph_three_levels.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/subgraph_two_separate.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/subgraph_with_labels.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/thick_arrow.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/three_nodes_inline.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/trapezoid.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/two_roots.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/expected/unicode_labels.txt +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/all_shapes.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/ampersand_both.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/backlink_complex.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/bidir_dotted.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/bidir_labeled.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/bidir_td.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/bidir_thick.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/bidirectional.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/branching.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/chain.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/comments.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/cycle.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/diamond.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/dotted_arrow.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/duplicate_labels.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/empty_graph.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/fan_in.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/fan_out.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/flowchart_keyword.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/graph_bt.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/graph_rl.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/labeled_edges.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/large_graph.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/long_labels.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/mermaid_comprehensive.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/mixed_arrow_styles.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/multiple_links.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/no_arrow_dotted.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/no_arrow_solid.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/no_arrow_thick.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/node_with_label.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/parallelogram.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/self_ref_with_edge.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/self_reference.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/semicolons.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/simple_lr.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/simple_tb.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/simple_td.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/single_node.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/subgraph_basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/subgraph_nested.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/subgraph_three_levels.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/subgraph_two_separate.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/subgraph_with_labels.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/thick_arrow.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/three_nodes_inline.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/trapezoid.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/two_roots.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/flowcharts/unicode_labels.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/gitgraph/cherry_pick.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/gitgraph/feature_branch.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/gitgraph/linear.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/gitgraph/tags.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/gitgraph/tb_direction.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/arrows.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/autonumber.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/multiline_notes.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/nested_blocks.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/notes.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/participant_kinds.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/sequence/self_message.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/statediagram/basic.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/statediagram/choice.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/statediagram/composite.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/fixtures/statediagram/start_end.mmd +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_classdiagram.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_cli.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_layout.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_parser_comprehensive.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_routing.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_snapshots.py +0 -0
- {termaid-0.1.2 → termaid-0.2.0}/tests/test_state_diagram.py +0 -0
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.2.0 (2026-03-20)
|
|
4
|
+
|
|
5
|
+
- Add pie chart support (`pie` syntax, rendered as horizontal bar charts)
|
|
6
|
+
- Add treemap support (`treemap-beta` syntax with nested sections and proportional sizing)
|
|
7
|
+
- 9 diagram types now supported
|
|
8
|
+
|
|
9
|
+
## 0.1.3 (2026-03-04)
|
|
4
10
|
|
|
5
11
|
- Add `--tui` flag to CLI for interactive TUI viewer
|
|
12
|
+
- Update demo GIF with pipe and TUI examples
|
|
6
13
|
|
|
7
14
|
## 0.1.1 (2026-03-04)
|
|
8
15
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: termaid
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Render Mermaid
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Render Mermaid diagrams in your terminal or Python app
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: ascii,diagram,flowchart,mermaid,terminal,unicode
|
|
@@ -22,21 +22,21 @@ Provides-Extra: rich
|
|
|
22
22
|
Requires-Dist: rich>=13.0; extra == 'rich'
|
|
23
23
|
Provides-Extra: textual
|
|
24
24
|
Requires-Dist: textual>=0.40; extra == 'textual'
|
|
25
|
+
Provides-Extra: tui
|
|
26
|
+
Requires-Dist: textual>=0.40; extra == 'tui'
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
<h1 align="center">termaid</h1>
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
<p align="center">Render Mermaid diagrams in your terminal or Python app.</p>
|
|
30
32
|
|
|
31
33
|
<p align="center">
|
|
32
34
|
<img src="demo/termaid-demo.gif" alt="termaid demo" width="800">
|
|
33
35
|
</p>
|
|
34
36
|
|
|
35
|
-
Render [Mermaid](https://mermaid.js.org/) diagrams as Unicode art directly in your terminal. Pure Python, zero dependencies.
|
|
36
|
-
|
|
37
37
|
## Features
|
|
38
38
|
|
|
39
|
-
- **
|
|
39
|
+
- **9 diagram types:** flowcharts, sequence, class, ER, state, block, git graphs, pie charts, and treemaps
|
|
40
40
|
- **Zero dependencies:** pure Python, nothing to install beyond the package itself
|
|
41
41
|
- **Rich and Textual integration:** colored output and TUI widgets with optional extras
|
|
42
42
|
- **6 color themes:** default, terra, neon, mono, amber, phosphor
|
|
@@ -53,6 +53,12 @@ Mermaid is great for documentation, but rendering it usually means spinning up a
|
|
|
53
53
|
pip install termaid
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Or try it without installing:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uvx termaid diagram.mmd
|
|
60
|
+
```
|
|
61
|
+
|
|
56
62
|
## Quick start
|
|
57
63
|
|
|
58
64
|
### CLI
|
|
@@ -350,10 +356,55 @@ gitGraph
|
|
|
350
356
|
|
|
351
357
|
**Config:** `%%{init: {"gitGraph": {"mainBranchName": "master"}}}%%`
|
|
352
358
|
|
|
359
|
+
### Pie charts
|
|
360
|
+
|
|
361
|
+
Yes, the syntax says `pie`. No, we don't draw a circle. I know. Have you ever tried to read a pie chart made of `█` and `▓`? Exactly. We render them as horizontal bar charts instead.
|
|
362
|
+
|
|
363
|
+
```mermaid
|
|
364
|
+
pie title Pets adopted by volunteers
|
|
365
|
+
"Dogs" : 386
|
|
366
|
+
"Cats" : 85
|
|
367
|
+
"Rats" : 15
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
Dogs┃████████████████████████████████ 79.4%
|
|
372
|
+
Cats┃▓▓▓▓▓▓▓ 17.5%
|
|
373
|
+
Rats┃░ 3.1%
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Features:** `title`, `showData` (display raw values), `%%` comments
|
|
377
|
+
|
|
378
|
+
### Treemaps
|
|
379
|
+
|
|
380
|
+
```mermaid
|
|
381
|
+
treemap-beta
|
|
382
|
+
"Frontend"
|
|
383
|
+
"React": 40
|
|
384
|
+
"CSS": 15
|
|
385
|
+
"Backend"
|
|
386
|
+
"API": 35
|
|
387
|
+
"Auth": 10
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
```
|
|
391
|
+
┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
|
392
|
+
┆ Frontend ┆ ┆ Backend ┆
|
|
393
|
+
┆┌───────────────────────┐ ┌───────┐┆ ┆┌───────────────────┐ ┌────┐┆
|
|
394
|
+
┆│ React │ │ CSS │┆ ┆│ API │ │Auth│┆
|
|
395
|
+
┆│ 40 │ │ 15 │┆ ┆│ 35 │ │ 10 │┆
|
|
396
|
+
┆│ │ │ │┆ ┆│ │ │ │┆
|
|
397
|
+
┆└───────────────────────┘ └───────┘┆ ┆└───────────────────┘ └────┘┆
|
|
398
|
+
└┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Features:** nested sections via indentation, `"label": value` syntax, proportional sizing, `%%` comments
|
|
402
|
+
|
|
353
403
|
## CLI options
|
|
354
404
|
|
|
355
405
|
| Flag | Description |
|
|
356
406
|
|------|-------------|
|
|
407
|
+
| `--tui` | Interactive TUI viewer (requires `pip install termaid[tui]`) |
|
|
357
408
|
| `--ascii` | ASCII-only output (no Unicode box-drawing) |
|
|
358
409
|
| `--theme NAME` | Color theme: `default`, `terra`, `neon`, `mono`, `amber`, `phosphor` (requires `pip install termaid[rich]`) |
|
|
359
410
|
| `--padding-x N` | Horizontal padding inside boxes (default: 4) |
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">termaid</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">Render Mermaid diagrams in your terminal or Python app.</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<img src="demo/termaid-demo.gif" alt="termaid demo" width="800">
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
-
Render [Mermaid](https://mermaid.js.org/) diagrams as Unicode art directly in your terminal. Pure Python, zero dependencies.
|
|
10
|
-
|
|
11
9
|
## Features
|
|
12
10
|
|
|
13
|
-
- **
|
|
11
|
+
- **9 diagram types:** flowcharts, sequence, class, ER, state, block, git graphs, pie charts, and treemaps
|
|
14
12
|
- **Zero dependencies:** pure Python, nothing to install beyond the package itself
|
|
15
13
|
- **Rich and Textual integration:** colored output and TUI widgets with optional extras
|
|
16
14
|
- **6 color themes:** default, terra, neon, mono, amber, phosphor
|
|
@@ -27,6 +25,12 @@ Mermaid is great for documentation, but rendering it usually means spinning up a
|
|
|
27
25
|
pip install termaid
|
|
28
26
|
```
|
|
29
27
|
|
|
28
|
+
Or try it without installing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
uvx termaid diagram.mmd
|
|
32
|
+
```
|
|
33
|
+
|
|
30
34
|
## Quick start
|
|
31
35
|
|
|
32
36
|
### CLI
|
|
@@ -324,10 +328,55 @@ gitGraph
|
|
|
324
328
|
|
|
325
329
|
**Config:** `%%{init: {"gitGraph": {"mainBranchName": "master"}}}%%`
|
|
326
330
|
|
|
331
|
+
### Pie charts
|
|
332
|
+
|
|
333
|
+
Yes, the syntax says `pie`. No, we don't draw a circle. I know. Have you ever tried to read a pie chart made of `█` and `▓`? Exactly. We render them as horizontal bar charts instead.
|
|
334
|
+
|
|
335
|
+
```mermaid
|
|
336
|
+
pie title Pets adopted by volunteers
|
|
337
|
+
"Dogs" : 386
|
|
338
|
+
"Cats" : 85
|
|
339
|
+
"Rats" : 15
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
Dogs┃████████████████████████████████ 79.4%
|
|
344
|
+
Cats┃▓▓▓▓▓▓▓ 17.5%
|
|
345
|
+
Rats┃░ 3.1%
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Features:** `title`, `showData` (display raw values), `%%` comments
|
|
349
|
+
|
|
350
|
+
### Treemaps
|
|
351
|
+
|
|
352
|
+
```mermaid
|
|
353
|
+
treemap-beta
|
|
354
|
+
"Frontend"
|
|
355
|
+
"React": 40
|
|
356
|
+
"CSS": 15
|
|
357
|
+
"Backend"
|
|
358
|
+
"API": 35
|
|
359
|
+
"Auth": 10
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
|
364
|
+
┆ Frontend ┆ ┆ Backend ┆
|
|
365
|
+
┆┌───────────────────────┐ ┌───────┐┆ ┆┌───────────────────┐ ┌────┐┆
|
|
366
|
+
┆│ React │ │ CSS │┆ ┆│ API │ │Auth│┆
|
|
367
|
+
┆│ 40 │ │ 15 │┆ ┆│ 35 │ │ 10 │┆
|
|
368
|
+
┆│ │ │ │┆ ┆│ │ │ │┆
|
|
369
|
+
┆└───────────────────────┘ └───────┘┆ ┆└───────────────────┘ └────┘┆
|
|
370
|
+
└┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Features:** nested sections via indentation, `"label": value` syntax, proportional sizing, `%%` comments
|
|
374
|
+
|
|
327
375
|
## CLI options
|
|
328
376
|
|
|
329
377
|
| Flag | Description |
|
|
330
378
|
|------|-------------|
|
|
379
|
+
| `--tui` | Interactive TUI viewer (requires `pip install termaid[tui]`) |
|
|
331
380
|
| `--ascii` | ASCII-only output (no Unicode box-drawing) |
|
|
332
381
|
| `--theme NAME` | Color theme: `default`, `terra`, `neon`, `mono`, `amber`, `phosphor` (requires `pip install termaid[rich]`) |
|
|
333
382
|
| `--padding-x N` | Horizontal padding inside boxes (default: 4) |
|
|
@@ -16,9 +16,15 @@ Env "PS1" "$ "
|
|
|
16
16
|
Env "VIRTUAL_ENV" ""
|
|
17
17
|
|
|
18
18
|
Hide
|
|
19
|
+
Type "source .venv/bin/activate"
|
|
20
|
+
Enter
|
|
21
|
+
Sleep 500ms
|
|
19
22
|
Type "cd demo"
|
|
20
23
|
Enter
|
|
21
24
|
Sleep 500ms
|
|
25
|
+
Type "export PS1='$ '"
|
|
26
|
+
Enter
|
|
27
|
+
Sleep 500ms
|
|
22
28
|
Ctrl+L
|
|
23
29
|
Show
|
|
24
30
|
|
|
@@ -39,6 +45,24 @@ Sleep 4s
|
|
|
39
45
|
|
|
40
46
|
# 4. One-liner hook — pipe-friendly with branching
|
|
41
47
|
Ctrl+L
|
|
48
|
+
Set TypingSpeed 0
|
|
49
|
+
Type "# Pipe-friendly: works with echo, cat, curl..."
|
|
50
|
+
Enter
|
|
51
|
+
Set TypingSpeed 32ms
|
|
52
|
+
Sleep 1s
|
|
42
53
|
Type "echo 'graph LR; A[Request] --> B{Valid?}; B -->|Yes| C[Process]; B -->|No| D[Error]' | termaid --theme default"
|
|
43
54
|
Enter
|
|
55
|
+
Sleep 3s
|
|
56
|
+
|
|
57
|
+
# 5. TUI mode — interactive viewer
|
|
58
|
+
Ctrl+L
|
|
59
|
+
Set TypingSpeed 0
|
|
60
|
+
Type "# Interactive TUI mode"
|
|
61
|
+
Enter
|
|
62
|
+
Set TypingSpeed 32ms
|
|
63
|
+
Sleep 1s
|
|
64
|
+
Type "termaid erdiagram.mmd --tui"
|
|
65
|
+
Enter
|
|
44
66
|
Sleep 4s
|
|
67
|
+
Type "q"
|
|
68
|
+
Sleep 1s
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
erDiagram
|
|
2
|
+
USER ||--o{ ORDER : places
|
|
3
|
+
USER {
|
|
4
|
+
int id PK
|
|
5
|
+
string name
|
|
6
|
+
string email
|
|
7
|
+
}
|
|
8
|
+
ORDER ||--|{ LINE_ITEM : contains
|
|
9
|
+
ORDER {
|
|
10
|
+
int id PK
|
|
11
|
+
date created
|
|
12
|
+
string status
|
|
13
|
+
}
|
|
14
|
+
PRODUCT ||--o{ LINE_ITEM : "ordered in"
|
|
15
|
+
PRODUCT {
|
|
16
|
+
int id PK
|
|
17
|
+
string name
|
|
18
|
+
float price
|
|
19
|
+
}
|
|
Binary file
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "termaid"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Render Mermaid
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Render Mermaid diagrams in your terminal or Python app"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.11"
|
|
@@ -25,6 +25,7 @@ classifiers = [
|
|
|
25
25
|
[project.optional-dependencies]
|
|
26
26
|
rich = ["rich>=13.0"]
|
|
27
27
|
textual = ["textual>=0.40"]
|
|
28
|
+
tui = ["textual>=0.40"]
|
|
28
29
|
dev = [
|
|
29
30
|
"pytest>=7.0",
|
|
30
31
|
"pytest-snapshot",
|
|
@@ -90,6 +90,18 @@ def render(
|
|
|
90
90
|
diagram = parse_git_graph(text)
|
|
91
91
|
return render_git_graph(diagram, use_ascii=use_ascii).to_string()
|
|
92
92
|
|
|
93
|
+
if text.startswith("pie"):
|
|
94
|
+
from .parser.piechart import parse_pie_chart
|
|
95
|
+
from .renderer.piechart import render_pie_chart
|
|
96
|
+
diagram = parse_pie_chart(text)
|
|
97
|
+
return render_pie_chart(diagram, use_ascii=use_ascii).to_string()
|
|
98
|
+
|
|
99
|
+
if text.startswith("treemap"):
|
|
100
|
+
from .parser.treemap import parse_treemap
|
|
101
|
+
from .renderer.treemap import render_treemap
|
|
102
|
+
diagram = parse_treemap(text)
|
|
103
|
+
return render_treemap(diagram, use_ascii=use_ascii).to_string()
|
|
104
|
+
|
|
93
105
|
graph = parse(text)
|
|
94
106
|
from .output.text import render_text
|
|
95
107
|
return render_text(graph, use_ascii=use_ascii, padding_x=padding_x, padding_y=padding_y, rounded_edges=rounded_edges)
|
|
@@ -162,6 +174,22 @@ def render_rich(
|
|
|
162
174
|
canvas = render_git_graph(diagram, use_ascii=use_ascii)
|
|
163
175
|
return render_sequence_rich(canvas, theme=theme)
|
|
164
176
|
|
|
177
|
+
if text.startswith("pie"):
|
|
178
|
+
from .parser.piechart import parse_pie_chart
|
|
179
|
+
from .renderer.piechart import render_pie_chart
|
|
180
|
+
from .output.rich import render_sequence_rich
|
|
181
|
+
diagram = parse_pie_chart(text)
|
|
182
|
+
canvas = render_pie_chart(diagram, use_ascii=use_ascii)
|
|
183
|
+
return render_sequence_rich(canvas, theme=theme)
|
|
184
|
+
|
|
185
|
+
if text.startswith("treemap"):
|
|
186
|
+
from .parser.treemap import parse_treemap
|
|
187
|
+
from .renderer.treemap import render_treemap
|
|
188
|
+
from .output.rich import render_sequence_rich
|
|
189
|
+
diagram = parse_treemap(text)
|
|
190
|
+
canvas = render_treemap(diagram, use_ascii=use_ascii)
|
|
191
|
+
return render_sequence_rich(canvas, theme=theme)
|
|
192
|
+
|
|
165
193
|
graph = parse(text)
|
|
166
194
|
from .output.rich import render_rich as _render_rich
|
|
167
195
|
return _render_rich(graph, use_ascii=use_ascii, padding_x=padding_x, padding_y=padding_y, rounded_edges=rounded_edges, theme=theme)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Data model for pie chart diagrams (rendered as bar charts)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class PieSlice:
|
|
9
|
+
label: str
|
|
10
|
+
value: float
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class PieChart:
|
|
15
|
+
title: str = ""
|
|
16
|
+
show_data: bool = False
|
|
17
|
+
slices: list[PieSlice] = field(default_factory=list)
|
|
18
|
+
warnings: list[str] = field(default_factory=list)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Data model for treemap diagrams."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class TreemapNode:
|
|
9
|
+
label: str
|
|
10
|
+
value: float = 0
|
|
11
|
+
children: list[TreemapNode] = field(default_factory=list)
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def total_value(self) -> float:
|
|
15
|
+
"""Total value: own value for leaves, sum of children for sections."""
|
|
16
|
+
if self.children:
|
|
17
|
+
return sum(c.total_value for c in self.children)
|
|
18
|
+
return self.value
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class Treemap:
|
|
23
|
+
roots: list[TreemapNode] = field(default_factory=list)
|
|
24
|
+
warnings: list[str] = field(default_factory=list)
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def total_value(self) -> float:
|
|
28
|
+
return sum(r.total_value for r in self.roots)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Parser for Mermaid pie chart diagrams.
|
|
2
|
+
|
|
3
|
+
Syntax:
|
|
4
|
+
pie [showData]
|
|
5
|
+
[title <text>]
|
|
6
|
+
"<label>" : <value>
|
|
7
|
+
...
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
from ..model.piechart import PieChart, PieSlice
|
|
14
|
+
|
|
15
|
+
_SLICE_RE = re.compile(r'^\s*"([^"]+)"\s*:\s*([0-9]+(?:\.[0-9]*)?)$')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def parse_pie_chart(text: str) -> PieChart:
|
|
19
|
+
"""Parse a mermaid pie chart definition."""
|
|
20
|
+
lines = text.strip().splitlines()
|
|
21
|
+
chart = PieChart()
|
|
22
|
+
|
|
23
|
+
if not lines:
|
|
24
|
+
return chart
|
|
25
|
+
|
|
26
|
+
# Parse header line: pie [showData]
|
|
27
|
+
header = lines[0].strip()
|
|
28
|
+
if "showData" in header:
|
|
29
|
+
chart.show_data = True
|
|
30
|
+
|
|
31
|
+
for line in lines[1:]:
|
|
32
|
+
stripped = line.strip()
|
|
33
|
+
if not stripped:
|
|
34
|
+
continue
|
|
35
|
+
|
|
36
|
+
# Strip comments
|
|
37
|
+
comment_idx = stripped.find("%%")
|
|
38
|
+
if comment_idx >= 0:
|
|
39
|
+
stripped = stripped[:comment_idx].strip()
|
|
40
|
+
if not stripped:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
# Title
|
|
44
|
+
if stripped.lower().startswith("title "):
|
|
45
|
+
chart.title = stripped[6:].strip()
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
# Slice: "Label" : value
|
|
49
|
+
m = _SLICE_RE.match(stripped)
|
|
50
|
+
if m:
|
|
51
|
+
label = m.group(1)
|
|
52
|
+
value = float(m.group(2))
|
|
53
|
+
if value <= 0:
|
|
54
|
+
chart.warnings.append(f"Pie slice value must be positive: {label} = {value}")
|
|
55
|
+
continue
|
|
56
|
+
chart.slices.append(PieSlice(label=label, value=value))
|
|
57
|
+
continue
|
|
58
|
+
|
|
59
|
+
# Unrecognized line
|
|
60
|
+
if stripped:
|
|
61
|
+
chart.warnings.append(f"Unrecognized line: {stripped}")
|
|
62
|
+
|
|
63
|
+
return chart
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Parser for Mermaid treemap diagrams.
|
|
2
|
+
|
|
3
|
+
Syntax:
|
|
4
|
+
treemap-beta
|
|
5
|
+
"Section 1"
|
|
6
|
+
"Leaf 1.1": 12
|
|
7
|
+
"Section 1.2"
|
|
8
|
+
"Leaf 1.2.1": 12
|
|
9
|
+
"Section 2"
|
|
10
|
+
"Leaf 2.1": 20
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
from ..model.treemap import Treemap, TreemapNode
|
|
17
|
+
|
|
18
|
+
_NODE_RE = re.compile(r'^(\s*)"([^"]+)"(?:\s*:\s*([0-9]+(?:\.[0-9]*)?))?')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_treemap(text: str) -> Treemap:
|
|
22
|
+
"""Parse a mermaid treemap definition."""
|
|
23
|
+
lines = text.strip().splitlines()
|
|
24
|
+
treemap = Treemap()
|
|
25
|
+
|
|
26
|
+
if not lines:
|
|
27
|
+
return treemap
|
|
28
|
+
|
|
29
|
+
# Skip header line (treemap-beta)
|
|
30
|
+
body_lines: list[tuple[int, str, float]] = []
|
|
31
|
+
for line in lines[1:]:
|
|
32
|
+
# Strip comments
|
|
33
|
+
comment_idx = line.find("%%")
|
|
34
|
+
if comment_idx >= 0:
|
|
35
|
+
line = line[:comment_idx]
|
|
36
|
+
|
|
37
|
+
m = _NODE_RE.match(line)
|
|
38
|
+
if not m:
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
indent = len(m.group(1))
|
|
42
|
+
label = m.group(2)
|
|
43
|
+
value = float(m.group(3)) if m.group(3) else 0
|
|
44
|
+
body_lines.append((indent, label, value))
|
|
45
|
+
|
|
46
|
+
if not body_lines:
|
|
47
|
+
return treemap
|
|
48
|
+
|
|
49
|
+
# Build tree from indentation
|
|
50
|
+
# Stack: (indent_level, node)
|
|
51
|
+
stack: list[tuple[int, TreemapNode]] = []
|
|
52
|
+
|
|
53
|
+
for indent, label, value in body_lines:
|
|
54
|
+
node = TreemapNode(label=label, value=value)
|
|
55
|
+
|
|
56
|
+
# Pop stack until we find a parent with less indentation
|
|
57
|
+
while stack and stack[-1][0] >= indent:
|
|
58
|
+
stack.pop()
|
|
59
|
+
|
|
60
|
+
if stack:
|
|
61
|
+
stack[-1][1].children.append(node)
|
|
62
|
+
else:
|
|
63
|
+
treemap.roots.append(node)
|
|
64
|
+
|
|
65
|
+
stack.append((indent, node))
|
|
66
|
+
|
|
67
|
+
return treemap
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Renderer for pie chart diagrams as horizontal bar charts.
|
|
2
|
+
|
|
3
|
+
Draws per-slice horizontal bars with right-aligned labels,
|
|
4
|
+
percentages, and optional raw values.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from ..model.piechart import PieChart
|
|
9
|
+
from .canvas import Canvas
|
|
10
|
+
from .charset import ASCII, UNICODE, CharSet
|
|
11
|
+
|
|
12
|
+
_FILL_CHARS = ["█", "▓", "░", "▒", "▞", "▚", "▖", "▗"]
|
|
13
|
+
_FILL_CHARS_ASCII = ["#", "*", "+", "~", ":", ".", "o", "="]
|
|
14
|
+
|
|
15
|
+
_BAR_WIDTH = 40
|
|
16
|
+
_MARGIN = 2
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def render_pie_chart(
|
|
20
|
+
diagram: PieChart,
|
|
21
|
+
*,
|
|
22
|
+
use_ascii: bool = False,
|
|
23
|
+
) -> Canvas:
|
|
24
|
+
"""Render a PieChart as a horizontal bar chart on a Canvas."""
|
|
25
|
+
|
|
26
|
+
if not diagram.slices:
|
|
27
|
+
canvas = Canvas(1, 1)
|
|
28
|
+
return canvas
|
|
29
|
+
|
|
30
|
+
total = sum(s.value for s in diagram.slices)
|
|
31
|
+
fills = _FILL_CHARS_ASCII if use_ascii else _FILL_CHARS
|
|
32
|
+
|
|
33
|
+
# Compute label column width
|
|
34
|
+
max_label_len = max(len(s.label) for s in diagram.slices)
|
|
35
|
+
label_col_w = max_label_len + _MARGIN
|
|
36
|
+
|
|
37
|
+
# Compute suffix (percentage + optional value)
|
|
38
|
+
suffixes: list[str] = []
|
|
39
|
+
for s in diagram.slices:
|
|
40
|
+
pct = s.value / total * 100
|
|
41
|
+
if diagram.show_data:
|
|
42
|
+
suffixes.append(f" {pct:5.1f}% [{s.value:g}]")
|
|
43
|
+
else:
|
|
44
|
+
suffixes.append(f" {pct:5.1f}%")
|
|
45
|
+
max_suffix_len = max(len(sf) for sf in suffixes)
|
|
46
|
+
|
|
47
|
+
bar_left = label_col_w
|
|
48
|
+
canvas_w = bar_left + _BAR_WIDTH + max_suffix_len + _MARGIN
|
|
49
|
+
title_rows = 2 if diagram.title else 0
|
|
50
|
+
|
|
51
|
+
bars_top = _MARGIN + title_rows
|
|
52
|
+
canvas_h = bars_top + len(diagram.slices) + _MARGIN
|
|
53
|
+
|
|
54
|
+
canvas = Canvas(canvas_w, canvas_h)
|
|
55
|
+
|
|
56
|
+
# Title
|
|
57
|
+
if diagram.title:
|
|
58
|
+
title_col = max(0, (canvas_w - len(diagram.title)) // 2)
|
|
59
|
+
canvas.put_text(_MARGIN, title_col, diagram.title, style="label")
|
|
60
|
+
|
|
61
|
+
# ── Per-slice bars ────────────────────────────────────────────────────
|
|
62
|
+
for i, s in enumerate(diagram.slices):
|
|
63
|
+
row = bars_top + i
|
|
64
|
+
pct = s.value / total * 100
|
|
65
|
+
fill = fills[i % len(fills)]
|
|
66
|
+
bar_len = max(1, round(s.value / total * _BAR_WIDTH))
|
|
67
|
+
|
|
68
|
+
# Label (right-aligned)
|
|
69
|
+
label_text = s.label.rjust(max_label_len)
|
|
70
|
+
canvas.put_text(row, _MARGIN, label_text, style="label")
|
|
71
|
+
|
|
72
|
+
# Bar
|
|
73
|
+
if use_ascii:
|
|
74
|
+
canvas.put(row, bar_left, "|", merge=False, style="edge")
|
|
75
|
+
else:
|
|
76
|
+
canvas.put(row, bar_left, "┃", merge=False, style="edge")
|
|
77
|
+
for c in range(bar_len):
|
|
78
|
+
canvas.put(row, bar_left + 1 + c, fill, merge=False, style="node")
|
|
79
|
+
|
|
80
|
+
# Suffix
|
|
81
|
+
canvas.put_text(row, bar_left + 1 + bar_len, suffixes[i], style="label")
|
|
82
|
+
|
|
83
|
+
return canvas
|