railroad-diagrams

Railroad-Diagram Generator, Python Version

This is a small library for generating railroad diagrams (like what JSON.org uses) using SVG, with both JS and Python ports. Here’s an online dingus for you to play with and get SVG code from!

(This is the README for the Python port; see the main README for other ports, and for more non-Python-specific information.)

Diagrams

Constructing a diagram is a set of nested calls. To create an SVG diagram:

from railroad import Diagram, Choice
d = Diagram("foo", Choice(0, "bar", "baz"))
d.writeSvg(sys.stdout.write)

To create a text-format diagram:

from railroad import Diagram, Choice
d = Diagram("foo", Choice(0, "bar", "baz"))
d.writeText(sys.stdout.write)

A railroad diagram must be started as a Diagram object, which takes a list of diagram items, defined below.

The Diagram() constructor also optionally takes some keyword arguments:

After constructing a Diagram, you can call .format(...padding) on it, specifying 0-4 padding values (just like CSS) for some additional “breathing space” around the diagram (the paddings default to 20px).

To output the diagram, call .writeSvg(cb) on it, passing a function that’ll get called repeatedly to produce the SVG markup. sys.stdout.write (or the .write property of any file object) is a great value to pass if you’re directly outputting it; if you need it as a plain string, a StringIO can be used. This method produces an SVG fragment appropriate to include directly in HTML.

Alternately, you can call .writeStandalone(cb, css?), which’ll format the SVG as a standalone document rather than as an HTML fragment. If you don’t pass any css, it’ll automatically include the DEFAULT_STYLE; you can include your own CSS instead by passing it as a string (or an empty string to include no CSS at all).

To output the diagram as pre-formatted text, instead of as SVG, call .writeText(cb) on it, passing a function that’ll get called to write the text.

If you need to walk the component tree of a diagram for some reason, Diagram has a .walk(cb) method as well, which will call your callback on every node in the diagram, in a “pre-order depth-first traversal” (the node first, then each child).

Components

Components are either leaves (containing only text or similar) or containers (containing other components).

The leaves:

The containers:

Options

There are a few options you can tweak, living as UPPERCASE_CONSTANTS at the top of the module; these can be adjusted via railroad.OPTION_NAME_HERE = "whatever". Note that if you change the text sizes in the CSS, you’ll have to adjust the text metrics here as well.