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.

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.py to accommodate different flowchart layouts and structural requirements.
  • Cycle handling relies on the defined_nodes set in to_mermaid_link_based_flow() to prevent duplicate node definitions when traversing cyclic graphs.
  • Defensive queries return -1 or 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →