How TextFlow Handles Different Flowchart Structures and Edge Cases
TextFlow processes varied flowchart structures through multiple rendering strategies in src/flowchart.py, safely handling cycles, duplicate nodes, and unknown shapes by falling back to defaults and defensive query methods.
TextFlow (available at junyiye/textflow) is a Python library that bridges natural language flowcharts and Mermaid diagram syntax. At its core, the Flowchart class in src/flowchart.py implements distinct rendering pipelines to support different visualization layouts while incorporating robust error handling for structural edge cases like graph cycles and missing node references.
Rendering Strategies for Diverse Flowchart Layouts
The Flowchart class provides four distinct export methods in src/flowchart.py, each optimized for specific diagramming requirements and structural complexity.
Standard Mermaid Export
The to_mermaid() method generates a straightforward node-and-edge representation. When encountering unknown shape types, the implementation falls back to a rectangular box to prevent malformed syntax. According to the source at lines 84-86, an else clause catches any undefined shape values, ensuring the diagram renders even with incomplete shape metadata.
Link-Based Flow for Cycle Handling
Cyclic flowcharts require careful node tracking to avoid duplicate definitions. The to_mermaid_link_based_flow() method (lines 100-124) maintains a defined_nodes set to track previously emitted nodes. When traversing edges, it lazily defines target nodes only upon first encounter. This prevents redundant declarations when a node appears multiple times in a cycle or converging path.
Node-Edge Separation for Clean Layouts
For large diagrams requiring strict separation between declarations and connections, to_mermaid_node_edge_separation() (lines 66-88 and 92-100) implements a two-phase export. First, all node definitions are emitted, followed by a separate block containing all edges. This guarantees a clean layout where the visual structure remains readable regardless of connection complexity.
Sequential Connection Flow
The to_mermaid_sequential_connection_flow() method (lines 116-132) preserves the logical order of node creation by emitting a definition immediately before each outgoing edge. This approach ensures the visual flow mirrors the internal dictionary order, which is essential when the sequence of operations carries semantic meaning.
Defensive Graph Query Utilities
Beyond rendering, TextFlow provides safe query methods that handle missing nodes gracefully without raising exceptions.
Successor and Predecessor Lookups
The get_direct_successors() and get_direct_predecessors() methods perform description-based lookups, returning empty lists when a node description cannot be found. This defensive approach allows graph analysis to continue even when querying nodes that may not exist in the current flowchart instance.
Shortest Path Calculation with BFS
For path analysis, get_shortest_path_length() implements a BFS algorithm that correctly handles cycles and disconnected components. When either the start or end node is missing, the method returns -1 rather than throwing an error (lines 120-130). This implementation ensures robust path finding across complex graph topologies including cyclic structures.
Handling Node Shapes and Conditional Edges
TextFlow manages visual semantics through strict shape validation and optional edge metadata.
Shape Validation and Defaults
Each node carries a shape field supporting ellipse, box, diamond, and parallelogram values. The rendering methods check node.shape and select appropriate Mermaid syntax. As implemented in lines 66-86, unknown values default to a rectangular box, preventing diagram generation failures when encountering custom or undefined shape types.
Optional Edge Conditions
The add_edge() method accepts an optional condition parameter. During rendering, edges check this field: if condition is None, a plain connection is emitted; otherwise, the syntax |"<condition>"| is included (lines 88-95). This guarantees consistent handling of conditional logic gates while supporting simple sequential flows.
Working with Shuffle and Reverse Transformations
TextFlow supports diagram manipulation through wrapper methods like to_mermaid_shuffle() and to_mermaid_reverse(). These methods import helper functions (shuffle_mermaid, reverse_mermaid) at runtime. If helpers are missing, the library raises a clear exception rather than producing silent output errors, ensuring transparent failure modes during diagram transformation.
Practical Implementation Example
The following example demonstrates building a cyclic flowchart with conditional edges and querying its properties:
from flowchart import Flowchart
# Build a flowchart with a decision cycle
fc = Flowchart()
fc.add_node("A", "Start", "ellipse")
fc.add_node("B", "Process data", "box")
fc.add_node("C", "Is valid?", "diamond")
fc.add_node("D", "End", "ellipse")
# Create edges including a cycle
fc.add_edge("A", "B")
fc.add_edge("B", "C")
fc.add_edge("C", "D", condition="yes")
fc.add_edge("C", "B", condition="no") # Cycle back to processing
# Export in different structural formats
print(fc.to_mermaid())
print(fc.to_mermaid_link_based_flow())
print(fc.to_mermaid_node_edge_separation())
# Query graph properties safely
print(fc.get_direct_successors("Process data"))
print(fc.get_shortest_path_length("Start", "End")) # Returns 3
print(fc.get_max_indegree()) # Analyzes connection density
The link-based export avoids duplicate definitions of node "B" despite its appearance in multiple edges, while the node-edge separation format cleanly partitions declarations from connections. The cycle between "C" and "B" is handled gracefully by the BFS shortest-path algorithm.
Summary
- TextFlow implements four distinct rendering strategies in
src/flowchart.pyto accommodate different flowchart layouts and structural requirements. - Cycle handling relies on the
defined_nodesset into_mermaid_link_based_flow()to prevent duplicate node definitions when traversing cyclic graphs. - Defensive queries return
-1or empty lists for missing nodes rather than raising exceptions, ensuring robust graph analysis. - Shape defaults automatically fall back to rectangular boxes for unknown values, preventing syntax errors in generated Mermaid code.
- Runtime transformation helpers raise explicit exceptions when unavailable, avoiding silent failures during shuffle or reverse operations.
Frequently Asked Questions
What happens when TextFlow encounters an unsupported node shape?
When a node's shape field contains a value other than ellipse, box, diamond, or parallelogram, TextFlow defaults to a rectangular box representation. This fallback occurs in the to_mermaid() method at lines 84-86 of src/flowchart.py, ensuring diagrams remain valid even with incomplete shape metadata.
How does TextFlow prevent duplicate node definitions in cyclic flowcharts?
The to_mermaid_link_based_flow() method tracks previously defined nodes using a defined_nodes set (lines 100-124). Nodes are emitted only on first encounter, preventing redundant definitions when cycles or converging paths cause a node to appear in multiple edge traversals.
What does TextFlow return when querying a node that does not exist?
Graph query methods such as get_direct_successors() and get_direct_predecessors() return empty lists for missing nodes, while get_shortest_path_length() returns -1. This defensive design, implemented in lines 68-78 and 120-130 of src/flowchart.py, allows analysis to continue without exception handling for absent nodes.
Can TextFlow handle flowcharts with cycles?
Yes, TextFlow handles cyclic structures through multiple mechanisms. The link-based renderer tracks defined nodes to avoid infinite loops during export, while the BFS implementation in get_shortest_path_length() correctly processes cycles without hanging. Cycles are preserved in the output using standard Mermaid syntax.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →