diff --git a/Changelog b/Changelog
deleted file mode 100644
--- a/Changelog
+++ /dev/null
@@ -1,637 +0,0 @@
-% Changelog
-% Ivan Lazar Miljenovic
-
-Release History and Changelog
-=============================
-
-The following is information about what major changes have gone into
-each release.
-
-Changes in 2999.14.1.0
-----------------------
-
-* Add `isGraphvizInstalled` and `quitWithoutGraphviz` for programs to
-  test whether Graphviz has been installed (as previous attempts at
-  doing so via actual calls to dot, neato, etc. weren't working and
-  would be too verbose anyway).
-
-Changes in 2999.14.0.0
-----------------------
-
-* Added an instance of `Labellable` for strict `Text` values, as
-  requested by **Erik Rantapaa**.
-
-Changes in 2999.13.0.3
-----------------------
-
-* Allow usage of transformers-0.3.*.  Spotted by **Peter Simons**.
-
-Changes in 2999.13.0.2
-----------------------
-
-* The `String` instance for `ToGraphID` requires the
-  `TypeSynonymInstances` pragma (at least on GHC < 7.4).  Spotted by
-  **Gregory Guthrie**.
-
-Changes in 2999.13.0.1
-----------------------
-
-* Fixed Haddock typos.
-
-Changes in 2999.13.0.0
-----------------------
-
-* Added support for the `osage` and `patchwork` visualisation tools,
-  available as of Graphviz-2.28.0.
-
-* Updated attributes as of Graphviz-2.28.0:
-
-    - `SVG` colors are now supported, and the support for different
-      colors has been revamped.
-
-    - `overlap=false` is now equivalent to `overlap=prism` and the
-      `RemoveOverlaps` option has been removed.
-
-    - `LabelScheme` and `Rotation` are new attributes for use with
-      `sfdp`.
-
-    - `Scale` is a new attribute for use with `twopi`.
-
-    - Add new italics, bold, underline, superscript and subscript
-      options for HTML-like labels.
-
-    - `LHeight` and `LWidth` for getting the height and width of the
-      root graph and clusters.
-
-* Updated attributes from the current development branch of Graphviz
-  (i.e. 2.29.*).  Please note that these will probably not work yet,
-  but are implemented now for future-proofing.
-
-    - A new style for edges: `Tapered`.
-
-    - `XLabel` allows you to specify labels external to a node or
-      edge.  `ForceLabels` allow you to specify that these should be
-      drawn even when they will cause overlaps.
-
-    - `ImagePath` allows you to specify where to search for images.
-
-    - HTML-like labels now support `ID` values as well as horizontal
-      and vertical rules.
-
-    - `BgColor` and `FillColor` now take a list of colors: this allows
-      gradient fills for graphs, clusters and nodes.  The `Radial`
-      style and `GradientAngle` are also used for this purpose.
-
-    - `FillColor` is now used by edges to set the color of any arrows.
-
-    - [WebP](http://en.wikipedia.org/wiki/WebP) output support added.
-
-* Other attribute changes:
-
-    - Use a specified data type for the `Ordering` attribute rather
-      than an arbitrary `Text` value, and provide a documented wrapper
-      in `Data.GraphViz.Attributes`.
-
-    - `Bb` has been renamed `BoundingBox`.
-
-    - `ID` now only takes `EscString` (a type alias for `Text`) values
-      rather than arbitrary `Label`s.
-
-    - The `Data.GraphViz.Attributes.HTML` module has had all values
-      re-named and is now meant to be imported qualified.  It is also
-      no longer re-exported from `Data.GraphViz.Attributes.Complete`.
-
-* The `ToGraphID` class provides a common wrapper to help create
-  cluster identifiers, etc.
-
-* Cabal's `Test-Suite` functionality is now used.  As part of this,
-  the `Data.GraphViz.Testing` module and sub-modules are no longer
-  exported by the library.
-
-* The new `Benchmark` support in Cabal-1.14 is now used for the
-  benchmark script.
-
-* Dropped support for base-3.
-
-* The `Data.GraphViz.State` module is no longer exposed, as there's no
-  need for users to use it.
-
-* Bugfixes:
-
-    - Some corner cases in canonicalisation prevented it from being
-      idempotent.
-
-    - The `TestParsing` script will no longer crash and refuse to
-      continue if an IO-based error (e.g. unable to successfully call
-      `dot`) occurs.
-
-    - A typo was spotted by **Gabor Greif**.
-
-Changes in 2999.12.0.4
-----------------------
-
-* Parsing error messages have been cleared up, especially when parsing
-  Dot graphs.  This came about from trying to help **Uri J. Braun**
-  with an error in his code (which took a while to diagnose as a
-  problem with the node type).
-
-* Made more clear to people looking in `Data.GraphViz` who want to
-  create Dot graphs by hand to look in `Data.GraphViz.Types` (came
-  about when **Rustom Mody** stated he got confused trying to work out
-  how to do this).
-
-* Fixed up augmentation; bug and fix spotted by **Max Rabkin**.
-
-* Fix up the TestParsing script to actually use the new type setup.
-  It can also now take a single directory as an argument, and will try
-  to parse all (non-recursive) files in that directory.
-
-Changes in 2999.12.0.3
-----------------------
-
-* Fixes various mistakes in the Haddock documentation that slipped
-  through (either in the `String -> Text` conversion or adding new
-  modules and not checking their documentation thoroughly enough).
-
-Changes in 2999.12.0.2
-----------------------
-
-* Forgot to explicitly list the module for Arbitrary instance for the
-  graph representation.
-
-Changes in 2999.12.0.1
-----------------------
-
-* Fix a bug that prevented graphviz from being built with GHC 7.2.
-
-Changes in 2999.12.0.0
-----------------------
-
-Many large-level changes were done in this release; in rough
-categories these are:
-
-### Conversions from other types
-
-* Can now more easily create Dot graphs from other graph-like data
-  structures with the new `graphElemsToDot` function, which takes a
-  list of nodes and edges.
-
-* It is now no longer possible to use `graphToDot`, etc. to create Dot
-  graphs with anonymous clusters; all clusters must now have explicit
-  names (note that uniqueness is not enforced, and it is still
-  possible to directly create Dot graphs with anonymous clusters).
-
-### Dot graph representations
-
-* The canonical graph representation has been moved to its own module:
-  `Data.GraphViz.Types.Canonical`.
-
-* The generalised representation has had all its "G" and "g" prefixes
-  removed.
-
-* Two new representations:
-
-    - `Data.GraphViz.Types.Graph` allows graph-like manipulation of
-      Dot code.
-
-    - `Data.GraphViz.Types.Monadic` provides a monadic interface into
-      building relatively static graphs, based upon the
-      [_dotgen_](http://hackage.haskell.org/package/dotgen) library by
-      Andy Gill.
-
-* The `DotRepr` class has been expanded, and three pseudo-classes have
-  been provided to reduce type-class contexts in type signatures.
-
-### Using and manipulation Dot graphs
-
-* Pure Haskell implementations of `dot -Tcanon` and `tred` are
-  available in `Data.GraphViz.Algorithms`.
-
-* A new module is available for more direct low-level I/O with Dot
-  graphs, including the ability to run custom commands as opposed to
-  being limited to the standard dot, neato, etc.
-
-### Attributes
-
-* `Data.GraphViz.Attributes` now contains a slimmed-down recommended
-  list of attributes; the complete list can still be found in
-  `Data.GraphViz.Attributes.Complete`.
-
-* The `charset` attribute is no longer available.
-
-* Functions for specifying custom attributes (for pre-processors,
-  etc.) are available.
-
-### Implementation
-
-* Now uses [`Text`](http://hackage.haskell.org/package/text) values
-  rather than `String`s.  Whilst performing this migration, the
-  improvements in speed for both printing and parsing improved
-  dramatically.
-
-    - As part of this, human-readable Dot code is now produced by
-      default.  As such, the `prettyPrint` and `prettyPrint'`
-      functions have been removed.
-
-* Now uses state-based printing and parsing, so that things like graph
-  directedness, layer separators and color schemes can be taken into
-  account.
-
-* Parsing large data-types (e.g. `Attributes`) now uses less
-  back-tracking.
-
-* Now has a benchmarking script for testing printing and parsing
-  speed.
-
-* Uses a custom exception type rather than a mish-mash of error,
-  `Maybe`, `Either`, exception types from used libraries, etc.
-
-* Usage of UTF-8 is now enforced when doing I/O.  If another encoding
-  is required, the `Text` value that's printed/parsed has to be
-  written/read from disk/network/etc. manually.
-
-### Bug-Fixes
-
-* The `Rects` `Attribute` should be able to take a list of `Rect`
-  values; error spotted by **Henning Gunther**.
-
-* In some cases, global attribute names were being printed without
-  even an empty list (which doesn't match what dot, etc. expect).
-
-Changes in 2999.11.0.0
-----------------------
-
-* Addition of the `Labellable` class (and its method `toLabel`) to
-  make it easier to construct labels.
-
-* Backslashes (i.e. the `\` character) are now escaped/unescaped
-  properly (bug spotted by **Han Joosten**).  As part of this:
-
-    - Dot-specific escapes such as `\N` are now also handled
-      correctly, so the slash does not need to be escaped.
-
-    - Newline (`'\n'`) characters in labels, etc. are escaped to
-      centred-newlines in Dot code, but not unescaped.
-
-* `Point` values can now have the optional third dimension and end in
-  a `!` to indicate that that position should be used (as input to
-  Graphviz).
-
-* `LayerList` uses `LayerID` values, and now has a proper `shrink`
-  implementation in the test suite.
-
-Changes in 2999.10.0.1
-----------------------
-
-* Fixed a mistake in one of the source files that was made just to
-  make
-  [haskell-src-exts](http://hackage.haskell.org/package/haskell-src-exts)
-  happier.
-
-* Fix the `Arbitrary` instance for `Point` in the testsuite (since
-  there's only one constructor now).
-
-Changes in 2999.10.0.0
-----------------------
-
-* Conversion of `FGL`-style graphs to `DotRepr` values is now achieved
-  using the new `GraphvizParams` configuration type.  This allows us
-  to define a single parameter that stores all the conversion
-  functions to pass around rather than having to pass around several
-  functions.  This also allows all the non-clustered and clustered
-  functions to be collapsed together, whereas what used to be handled
-  by the primed functions is now achieved by using the
-  `setDirectedness` function.
-
-    There are three default `GraphvizParams` available:
-
-    - `defaultParams` provides some sensible defaults (no attributes
-      or clustering).
-
-    - `nonClusteredParams` is an alias of `defaultParams` where the
-      clustering type is explicitly set to be `()` for cases where you
-      don't want any clustering at all (whereas `defaultParams` allows
-      you to set your own clustering functions).
-
-    - `blankParams` sets all fields to be `undefined`; this is useful
-      for situations where you have functions that will set some
-      values for you and there is no sensible default you can use
-      (mainly for the clustering function).
-
-* Expansion of the `DotRepr` class:
-
-    - More common functions are now defined as methods (`getID`,
-      etc.).
-
-    - The ability to get more information about the structure of the
-      `DotRepr` graph, as well as where all the `DotNode`s are, etc.
-
-    - `graphNodes` now returns `DotNode`s defined only as part of
-      `DotEdge`s, and will also merge duplicate `DotNode`s together.
-
-    - `graphNodes` and `graphEdges` also return `GlobalAttributes`
-      that apply to them.
-
-* The `Point` type now only has one constructor: `Point Double
-  Double`.  The `Int`-only constructor was present due to historical
-  purposes and I thought that the `Pos` value for a `DotNode` would
-  always be a pair of `Int`s; this turns out not to be the case.
-
-* `SortV` and `PrismOverlap` now only take `Word16` values rather than
-  `Int`s, as they're not meant to allow negative values (the choice of
-  using `Word16` rather than `Word` was arbitrary, and because it's
-  unlikely those values will be large enough to require the larger
-  values available in `Word`).
-
-* `NodeCluster` has been generalised to not have to take an `LNode`
-  for the node type; the type alias `LNodeCluster` is available if you
-  still want this.
-
-* Several documentation typos fixed, including one spotted by **Kevin
-  Quick**.
-
-* The test-suite now allows running individual tests.
-
-Changes in 2999.9.0.0
----------------------
-
-* graphviz now has an FAQ and an improved README as well as its own
-  [homepage](http://projects.haskell.org/graphviz/).
-
-* Canonicalisation of `DotRepr` values is now available with the
-  `canonicalise` function.
-
-* Add support for record labels; values are automatically
-  escaped/unescaped.  The `Record` and `MRecord` shapes have been
-  added for use with these labels.  **Requested by Minh Thu and Eric
-  Kow.**
-
-* Add support for HTML-like values (this replaces the wrong and
-  completely broken URL datatype).  Strings are automatically
-  escaped/unescaped.
-
-* Named `PortPos` values are now accepted (as required for record and
-  HTML-like labels).
-
-* `GraphID` no longer allows HTML-like values (since Graphviz doesn't
-  seem to allow it).
-
-* `RankSep` takes a list of `Double` values as required.
-
-* `Attribute` has a new constructor `UnknownAttribute` for use when
-  parsing deprecated Graphviz attributes in old Dot code.
-
-* Various parsing fixes; of special note:
-
-    - Statements no longer need to end in a semi-colon;
-
-    - Anonymous sub-graphs are now supported.
-
-    - Edge statements can now handle node groupings (e.g. ` a -> {b
-      c}`) as well as `portPos` values (e.g. `a:from -> b:to`).
-
-    - Unquoted `String`s containing non-ASCII characters are now
-      parsed properly (though they are assumed to be encoded with
-      UTF-8).  **Thanks to Jules Bean (aka quicksilver) for working
-      out how to do this.**
-
-    More specifically: almost all Dot files that ship with Graphviz, as
-    documentation in the Linux kernel, etc. are now parseable.
-
-* A new script to assist in testing whether "real-world" Dot graphs
-  are parseable.
-
-* Slight performance increase when parsing: whereas parsing is done
-  case-insensitively, the "correct" case is now checked by default
-  which has a moderate affect on parsing times.
-
-* Split lines are now able to be handled when parsing.
-
-Changes in 2999.8.0.0
----------------------
-
-* Added support for generalised `DotGraph`s; this optional
-  representation removes the restriction of ordering of Dot
-  statements.  This allows for greater flexibility of how to specify
-  Dot code.  As an offshoot from this, most relevant functions now
-  utilise a new `DotRepr` class that work with both `DotGraph`s and
-  the new `GDotGraph`s; this shouldn't affect any code already in use.
-
-* With the **prompting of Noam Lewis**, the augmentation functions
-  have been revamped in two ways:
-
-  - Now contains support for multiple edges.
-
-  - The ability to perform "manual" augmentation if greater control is
-    desired.
-
-* Add a preview function to quickly render and visualise an `FGL`
-  graph using the `Xlib` canvas.
-
-* Added a pseudo-inverse of the `FGL -> Dot` functions (a graph is
-  created, but the original node and edge labels are unrecoverable).
-
-* The `Printing` and `Parsing` modules have been moved (from
-  `Data.GraphViz.Types` to `Data.GraphViz`).
-
-* Reworked file-generating commands such that they return the filename
-  of the created file if successful.
-
-Changes in 2999.7.0.0
----------------------
-
-* Updated and extended functions to interact with the Graphviz tools.
-  This now includes:
-
-  - a better listing of available output types;
-
-  - distinguishing file outputs from canvas outputs;
-
-  - ability to automatically add the correct file extension to file
-    outputs
-
-  - Return any errors if calling Graphviz failed rather than just
-    printing them to stderr
-
-* Improved `Color` support:
-
-  - fixed `ColorScheme` values
-
-  - explicitly named `X11` colors
-
-  - conversion to/from values from the [colour] library
-
-  [colour]: http://www.haskell.org/haskellwiki/Colour
-
-* Removed `OrientationGraph`; problems with distinguishing it when
-  parsing from node-based `Orientation` values; its functionality is
-  duplicated by `Rotate`.
-
-* By default, the generated Dot code is now no longer indented; you
-  can now use the `prettyPrint` functions in `Data.GraphViz` to
-  produce readable Dot code.
-
-* Added a testsuite; this is buildable by building with
-  `--flags-test`.  Numerous printing and parsing bugs were picked up
-  with this.
-
-Changes in 2999.6.0.0
----------------------
-
-* Remove some `Shape` aliases and change capitalisation of others.
-
-* Properly parse and print IDs of clusters.
-
-* Allow `NodeCluster` values to have node types different from the
-  `LNode` they come from.
-
-Changes in 2999.5.1.1
----------------------
-
-* When used as labels, etc., the Dot keywords `node`, `edge`, `graph`,
-  `digraph`, `subgraph`, and `strict` need to be quoted.  **Spotted by
-  Kathleen Fisher.**
-
-Changes in 2999.5.1.0
----------------------
-
-* Potentially fixed the `graphvizWithHandle` bug; correct approach
-  **spotted by Nikolas Mayr**.
-
-* Fixed up `Parsing` of various `Attribute` sub-values, especially
-  `Point` and `Spline` (and hence `Pos`, which uses them).
-
-* Pre-process out comments and join together multi-line strings before
-  parsing.
-
-* Properly parse `Doubles` like `".2"`.
-
-Changes in 2999.5.0.0
----------------------
-
-A major re-write occured; these are the highlights:
-
-* Re-write parsing and printing of Dot code using the new `ParseDot`
-  and `PrintDot` classes.  This should finally fix all quoting issues,
-  as well as leaving `Show` as the code representation for hacking
-  purposes.  As part of this, the `Data.GraphViz.ParserCombinators`
-  module has been moved to `Data.GraphViz.Types.Parsing`.
-
-* Re-write the various `Dot*` datatypes in `Data.GraphViz.Types`.
-  Sub-graphs/clusters are now their own entity rather than being part
-  of `DotNode` and the Node ID type is now a type parameter rather
-  than being just `Int`.  Sub-graphs/clusters can now also be parsed.
-
-* The various conversion functions in `Data.GraphViz` now come in two
-  flavours: the unprimed versions take in a `Bool` indicating if the
-  graph is directed or not; the primed versions attempt to
-  automatically detect this.
-
-* Add cluster support for the graph augmentation functions, **as
-  requested by Nikolas Mayr**.
-
-* Allow custom arrow types as supported by GraphViz; **as requested by
-  Han Joosten**.
-
-* Fixed a bug in HSV-style `Color` values where `Int` was used instead of
-  `Double`; **spotted by Michael deLorimier**.
-
-* Properly resolved the situation initially spotted by Neil Brown:
-  Matthew Sackman was following Dot terminology for an edge `a -> b`
-  when using _head_ for `b` and _tail_ for `a` (this is presumably
-  because the head/tail of the arrow are at those nodes).  `DotEdge`
-  now uses _from_ and _to_ avoid ambiguity; the various `Attribute`
-  values still follow upstream usage.
-
-Changes in 2999.1.0.2
----------------------
-
-* Fix a bug **spotted by Srihari Ramanathan** where `Color` values
-  were double-quoted.
-
-Changes in 2999.1.0.1
----------------------
-
-* The `Color` `Attribute` should take `[Color]`, not just a single
-  `Color`.
-
-Changes in 2999.1.0.0
----------------------
-
-* Stop using `Either` for composite `Attributes` and use a custom
-  type: this avoids problems with the `Show` instance.
-
-Changes in 2999.0.0.0
----------------------
-
-* Fixed a bug where the Show instance and read function for `DotEdge`
-  had the from/to nodes the wrong way round.  This was not immediately
-  noticed since the `Graph` to `DotGraph` functions created them the
-  wrong way round, so for those users who only used these this was not
-  apparent.  **Spotted by Neil Brown.**
-
-* Greatly improved `Attribute` usage: almost all attributes are now
-  covered with allowed values.
-
-* Extend DotGraph to include whether a graph is strict or not and if
-  it has an ID.  Also move the directedGraph field.
-
-* Make `Dot` refer to the actual dot command and `DotArrow` refer to
-  the `ArrowType` (rather than `DotCmd` and `Dot` as before).
-
-* Make the `Data.GraphViz.ParserCombinators` module available to end
-  users again, but not re-exported by `Data.GraphViz`; it has a
-  warning message up the top not to be used.  It is there purely for
-  documentative purposes.
-
-* Use [extensible-exceptions] so that `base-3.x` is once again
-  supported.
-
-  [extensible-exceptions]: http://hackage.haskell.org/package/extensible-exceptions
-
-* Follow the [Package Versioning Policy] rather than using dates for
-  versions.
-
-  [Package Versioning Policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy
-
-
-Changes in 2009.5.1
--------------------
-
-* New maintainer: Ivan Lazar Miljenovic.
-
-* Support `polyparse >= 1.1` (as opposed to `< 1.3`)
-
-* Require `base == 4.*` (i.e. `GHC 6.10.*`) due to new exception handling.
-
-* Include functions from [Graphalyze-0.5] for running GraphViz
-  commands, etc.
-
-  [Graphalyze-0.5]: http://hackage.haskell.org/package/Graphalyze-0.5
-
-* Module re-organisation.
-
-* The `Data.GraphViz.ParserCombinators` module is no longer available
-  to end users.
-
-* Improved Haddock documentation.
-
-Changes in 2008.9.20
---------------------
-
-* Differentiate between undirected and directed graphs (previously
-  only directed graphs were supported).
-
-* Clustering support was added.
-
-Older versions
---------------
-
-For versions of graphviz older than `2008.9.20`, the exact differences
-between versions is unknown.
-
-<!--
-     Local Variables:
-     mode:markdown
-     End:
-  -->
diff --git a/Changelog.md b/Changelog.md
new file mode 100644
--- /dev/null
+++ b/Changelog.md
@@ -0,0 +1,687 @@
+% Changelog
+% Ivan Lazar Miljenovic
+
+Release History and Changelog
+=============================
+
+The following is information about what major changes have gone into
+each release.
+
+Changes in 2999.15.0.0
+----------------------
+
+* The repository is now hosted on
+  [hub.darcs.net](http://hub.darcs.net/ivanm/graphviz), and using the
+  bug-tracker there.
+
+* Updates to various `Attribute` definitions:
+
+    - The list of available shapes has been expanded to take into
+      account the new synthetic biology shapes.
+
+    - The `Size` and `FontNames` attributes now have specified data types.
+
+    - The optional start and end points for `Spline`s were previously
+      the wrong way round; this has now been fixed.
+
+    - Explicitly only print 2-dimensional `Point` values for `Rect`
+      and `DPoint` (previously only 2-dimensional values where parsed,
+      but it was possible to print a 3-dimensional value).
+
+    - HTML-like labels previously disallowed empty textual label
+      components when parsing; spotted by **Daniel Hummel**.
+
+* `GraphvizParams` now lets you specify whether a "cluster" is
+  actually a cluster or a sub-graph.  Requested by **Gabor Greif**.
+
+* Fixed an error where printing edges whose attributes contained a
+  `ColorScheme` attribute, that attribute would stay in the state and
+  the old color scheme would override the _parent's_ state.
+
+* Previously, some malformed attributes were accepted when being
+  parsed as they silently became parsed as an `UnknownAttribute`.
+  Now, attributes where the attribute name and the equal sign are
+  successfully parsed **but** the value of the attribute is _not_
+  successfully parse will throw an unrecoverable error.
+
+    **Note**: this does mean that some Dot graphs that are accepted by
+    Graphviz (as they separate tokenizing from parsing; as such
+    something like `"0.1"` is successfully accepted as an integer,
+    specifically `0`) are no longer accepted when parsing them in.
+
+* Miscellaneous parsing improvements:
+
+    - Whilst not specified anywhere, Graphviz seems to treat empty
+      quotes as values for attributes expecting a number as their
+      default; as such, this is now taken into account when parsing.
+
+    - `DPoint` values can now parse an optional `+` prefix.
+
+    - Whitespaces after commas in HSV colors are now accepted.
+
+* Error messages from parsing are improved to help you track down
+  where the parsing error occurred (in that it's easier to find which
+  attribute failed to parse, etc.).
+
+Changes in 2999.14.1.0
+----------------------
+
+* Add `isGraphvizInstalled` and `quitWithoutGraphviz` for programs to
+  test whether Graphviz has been installed (as previous attempts at
+  doing so via actual calls to dot, neato, etc. weren't working and
+  would be too verbose anyway).
+
+Changes in 2999.14.0.0
+----------------------
+
+* Added an instance of `Labellable` for strict `Text` values, as
+  requested by **Erik Rantapaa**.
+
+Changes in 2999.13.0.3
+----------------------
+
+* Allow usage of transformers-0.3.*.  Spotted by **Peter Simons**.
+
+Changes in 2999.13.0.2
+----------------------
+
+* The `String` instance for `ToGraphID` requires the
+  `TypeSynonymInstances` pragma (at least on GHC < 7.4).  Spotted by
+  **Gregory Guthrie**.
+
+Changes in 2999.13.0.1
+----------------------
+
+* Fixed Haddock typos.
+
+Changes in 2999.13.0.0
+----------------------
+
+* Added support for the `osage` and `patchwork` visualisation tools,
+  available as of Graphviz-2.28.0.
+
+* Updated attributes as of Graphviz-2.28.0:
+
+    - `SVG` colors are now supported, and the support for different
+      colors has been revamped.
+
+    - `overlap=false` is now equivalent to `overlap=prism` and the
+      `RemoveOverlaps` option has been removed.
+
+    - `LabelScheme` and `Rotation` are new attributes for use with
+      `sfdp`.
+
+    - `Scale` is a new attribute for use with `twopi`.
+
+    - Add new italics, bold, underline, superscript and subscript
+      options for HTML-like labels.
+
+    - `LHeight` and `LWidth` for getting the height and width of the
+      root graph and clusters.
+
+* Updated attributes from the current development branch of Graphviz
+  (i.e. 2.29.*).  Please note that these will probably not work yet,
+  but are implemented now for future-proofing.
+
+    - A new style for edges: `Tapered`.
+
+    - `XLabel` allows you to specify labels external to a node or
+      edge.  `ForceLabels` allow you to specify that these should be
+      drawn even when they will cause overlaps.
+
+    - `ImagePath` allows you to specify where to search for images.
+
+    - HTML-like labels now support `ID` values as well as horizontal
+      and vertical rules.
+
+    - `BgColor` and `FillColor` now take a list of colors: this allows
+      gradient fills for graphs, clusters and nodes.  The `Radial`
+      style and `GradientAngle` are also used for this purpose.
+
+    - `FillColor` is now used by edges to set the color of any arrows.
+
+    - [WebP](http://en.wikipedia.org/wiki/WebP) output support added.
+
+* Other attribute changes:
+
+    - Use a specified data type for the `Ordering` attribute rather
+      than an arbitrary `Text` value, and provide a documented wrapper
+      in `Data.GraphViz.Attributes`.
+
+    - `Bb` has been renamed `BoundingBox`.
+
+    - `ID` now only takes `EscString` (a type alias for `Text`) values
+      rather than arbitrary `Label`s.
+
+    - The `Data.GraphViz.Attributes.HTML` module has had all values
+      re-named and is now meant to be imported qualified.  It is also
+      no longer re-exported from `Data.GraphViz.Attributes.Complete`.
+
+* The `ToGraphID` class provides a common wrapper to help create
+  cluster identifiers, etc.
+
+* Cabal's `Test-Suite` functionality is now used.  As part of this,
+  the `Data.GraphViz.Testing` module and sub-modules are no longer
+  exported by the library.
+
+* The new `Benchmark` support in Cabal-1.14 is now used for the
+  benchmark script.
+
+* Dropped support for base-3.
+
+* The `Data.GraphViz.State` module is no longer exposed, as there's no
+  need for users to use it.
+
+* Bugfixes:
+
+    - Some corner cases in canonicalisation prevented it from being
+      idempotent.
+
+    - The `TestParsing` script will no longer crash and refuse to
+      continue if an IO-based error (e.g. unable to successfully call
+      `dot`) occurs.
+
+    - A typo was spotted by **Gabor Greif**.
+
+Changes in 2999.12.0.4
+----------------------
+
+* Parsing error messages have been cleared up, especially when parsing
+  Dot graphs.  This came about from trying to help **Uri J. Braun**
+  with an error in his code (which took a while to diagnose as a
+  problem with the node type).
+
+* Made more clear to people looking in `Data.GraphViz` who want to
+  create Dot graphs by hand to look in `Data.GraphViz.Types` (came
+  about when **Rustom Mody** stated he got confused trying to work out
+  how to do this).
+
+* Fixed up augmentation; bug and fix spotted by **Max Rabkin**.
+
+* Fix up the TestParsing script to actually use the new type setup.
+  It can also now take a single directory as an argument, and will try
+  to parse all (non-recursive) files in that directory.
+
+Changes in 2999.12.0.3
+----------------------
+
+* Fixes various mistakes in the Haddock documentation that slipped
+  through (either in the `String -> Text` conversion or adding new
+  modules and not checking their documentation thoroughly enough).
+
+Changes in 2999.12.0.2
+----------------------
+
+* Forgot to explicitly list the module for Arbitrary instance for the
+  graph representation.
+
+Changes in 2999.12.0.1
+----------------------
+
+* Fix a bug that prevented graphviz from being built with GHC 7.2.
+
+Changes in 2999.12.0.0
+----------------------
+
+Many large-level changes were done in this release; in rough
+categories these are:
+
+### Conversions from other types
+
+* Can now more easily create Dot graphs from other graph-like data
+  structures with the new `graphElemsToDot` function, which takes a
+  list of nodes and edges.
+
+* It is now no longer possible to use `graphToDot`, etc. to create Dot
+  graphs with anonymous clusters; all clusters must now have explicit
+  names (note that uniqueness is not enforced, and it is still
+  possible to directly create Dot graphs with anonymous clusters).
+
+### Dot graph representations
+
+* The canonical graph representation has been moved to its own module:
+  `Data.GraphViz.Types.Canonical`.
+
+* The generalised representation has had all its "G" and "g" prefixes
+  removed.
+
+* Two new representations:
+
+    - `Data.GraphViz.Types.Graph` allows graph-like manipulation of
+      Dot code.
+
+    - `Data.GraphViz.Types.Monadic` provides a monadic interface into
+      building relatively static graphs, based upon the
+      [_dotgen_](http://hackage.haskell.org/package/dotgen) library by
+      Andy Gill.
+
+* The `DotRepr` class has been expanded, and three pseudo-classes have
+  been provided to reduce type-class contexts in type signatures.
+
+### Using and manipulation Dot graphs
+
+* Pure Haskell implementations of `dot -Tcanon` and `tred` are
+  available in `Data.GraphViz.Algorithms`.
+
+* A new module is available for more direct low-level I/O with Dot
+  graphs, including the ability to run custom commands as opposed to
+  being limited to the standard dot, neato, etc.
+
+### Attributes
+
+* `Data.GraphViz.Attributes` now contains a slimmed-down recommended
+  list of attributes; the complete list can still be found in
+  `Data.GraphViz.Attributes.Complete`.
+
+* The `charset` attribute is no longer available.
+
+* Functions for specifying custom attributes (for pre-processors,
+  etc.) are available.
+
+### Implementation
+
+* Now uses [`Text`](http://hackage.haskell.org/package/text) values
+  rather than `String`s.  Whilst performing this migration, the
+  improvements in speed for both printing and parsing improved
+  dramatically.
+
+    - As part of this, human-readable Dot code is now produced by
+      default.  As such, the `prettyPrint` and `prettyPrint'`
+      functions have been removed.
+
+* Now uses state-based printing and parsing, so that things like graph
+  directedness, layer separators and color schemes can be taken into
+  account.
+
+* Parsing large data-types (e.g. `Attributes`) now uses less
+  back-tracking.
+
+* Now has a benchmarking script for testing printing and parsing
+  speed.
+
+* Uses a custom exception type rather than a mish-mash of error,
+  `Maybe`, `Either`, exception types from used libraries, etc.
+
+* Usage of UTF-8 is now enforced when doing I/O.  If another encoding
+  is required, the `Text` value that's printed/parsed has to be
+  written/read from disk/network/etc. manually.
+
+### Bug-Fixes
+
+* The `Rects` `Attribute` should be able to take a list of `Rect`
+  values; error spotted by **Henning Gunther**.
+
+* In some cases, global attribute names were being printed without
+  even an empty list (which doesn't match what dot, etc. expect).
+
+Changes in 2999.11.0.0
+----------------------
+
+* Addition of the `Labellable` class (and its method `toLabel`) to
+  make it easier to construct labels.
+
+* Backslashes (i.e. the `\` character) are now escaped/unescaped
+  properly (bug spotted by **Han Joosten**).  As part of this:
+
+    - Dot-specific escapes such as `\N` are now also handled
+      correctly, so the slash does not need to be escaped.
+
+    - Newline (`'\n'`) characters in labels, etc. are escaped to
+      centred-newlines in Dot code, but not unescaped.
+
+* `Point` values can now have the optional third dimension and end in
+  a `!` to indicate that that position should be used (as input to
+  Graphviz).
+
+* `LayerList` uses `LayerID` values, and now has a proper `shrink`
+  implementation in the test suite.
+
+Changes in 2999.10.0.1
+----------------------
+
+* Fixed a mistake in one of the source files that was made just to
+  make
+  [haskell-src-exts](http://hackage.haskell.org/package/haskell-src-exts)
+  happier.
+
+* Fix the `Arbitrary` instance for `Point` in the testsuite (since
+  there's only one constructor now).
+
+Changes in 2999.10.0.0
+----------------------
+
+* Conversion of `FGL`-style graphs to `DotRepr` values is now achieved
+  using the new `GraphvizParams` configuration type.  This allows us
+  to define a single parameter that stores all the conversion
+  functions to pass around rather than having to pass around several
+  functions.  This also allows all the non-clustered and clustered
+  functions to be collapsed together, whereas what used to be handled
+  by the primed functions is now achieved by using the
+  `setDirectedness` function.
+
+    There are three default `GraphvizParams` available:
+
+    - `defaultParams` provides some sensible defaults (no attributes
+      or clustering).
+
+    - `nonClusteredParams` is an alias of `defaultParams` where the
+      clustering type is explicitly set to be `()` for cases where you
+      don't want any clustering at all (whereas `defaultParams` allows
+      you to set your own clustering functions).
+
+    - `blankParams` sets all fields to be `undefined`; this is useful
+      for situations where you have functions that will set some
+      values for you and there is no sensible default you can use
+      (mainly for the clustering function).
+
+* Expansion of the `DotRepr` class:
+
+    - More common functions are now defined as methods (`getID`,
+      etc.).
+
+    - The ability to get more information about the structure of the
+      `DotRepr` graph, as well as where all the `DotNode`s are, etc.
+
+    - `graphNodes` now returns `DotNode`s defined only as part of
+      `DotEdge`s, and will also merge duplicate `DotNode`s together.
+
+    - `graphNodes` and `graphEdges` also return `GlobalAttributes`
+      that apply to them.
+
+* The `Point` type now only has one constructor: `Point Double
+  Double`.  The `Int`-only constructor was present due to historical
+  purposes and I thought that the `Pos` value for a `DotNode` would
+  always be a pair of `Int`s; this turns out not to be the case.
+
+* `SortV` and `PrismOverlap` now only take `Word16` values rather than
+  `Int`s, as they're not meant to allow negative values (the choice of
+  using `Word16` rather than `Word` was arbitrary, and because it's
+  unlikely those values will be large enough to require the larger
+  values available in `Word`).
+
+* `NodeCluster` has been generalised to not have to take an `LNode`
+  for the node type; the type alias `LNodeCluster` is available if you
+  still want this.
+
+* Several documentation typos fixed, including one spotted by **Kevin
+  Quick**.
+
+* The test-suite now allows running individual tests.
+
+Changes in 2999.9.0.0
+---------------------
+
+* graphviz now has an FAQ and an improved README as well as its own
+  [homepage](http://projects.haskell.org/graphviz/).
+
+* Canonicalisation of `DotRepr` values is now available with the
+  `canonicalise` function.
+
+* Add support for record labels; values are automatically
+  escaped/unescaped.  The `Record` and `MRecord` shapes have been
+  added for use with these labels.  **Requested by Minh Thu and Eric
+  Kow.**
+
+* Add support for HTML-like values (this replaces the wrong and
+  completely broken URL datatype).  Strings are automatically
+  escaped/unescaped.
+
+* Named `PortPos` values are now accepted (as required for record and
+  HTML-like labels).
+
+* `GraphID` no longer allows HTML-like values (since Graphviz doesn't
+  seem to allow it).
+
+* `RankSep` takes a list of `Double` values as required.
+
+* `Attribute` has a new constructor `UnknownAttribute` for use when
+  parsing deprecated Graphviz attributes in old Dot code.
+
+* Various parsing fixes; of special note:
+
+    - Statements no longer need to end in a semi-colon;
+
+    - Anonymous sub-graphs are now supported.
+
+    - Edge statements can now handle node groupings (e.g. ` a -> {b
+      c}`) as well as `portPos` values (e.g. `a:from -> b:to`).
+
+    - Unquoted `String`s containing non-ASCII characters are now
+      parsed properly (though they are assumed to be encoded with
+      UTF-8).  **Thanks to Jules Bean (aka quicksilver) for working
+      out how to do this.**
+
+    More specifically: almost all Dot files that ship with Graphviz, as
+    documentation in the Linux kernel, etc. are now parseable.
+
+* A new script to assist in testing whether "real-world" Dot graphs
+  are parseable.
+
+* Slight performance increase when parsing: whereas parsing is done
+  case-insensitively, the "correct" case is now checked by default
+  which has a moderate affect on parsing times.
+
+* Split lines are now able to be handled when parsing.
+
+Changes in 2999.8.0.0
+---------------------
+
+* Added support for generalised `DotGraph`s; this optional
+  representation removes the restriction of ordering of Dot
+  statements.  This allows for greater flexibility of how to specify
+  Dot code.  As an offshoot from this, most relevant functions now
+  utilise a new `DotRepr` class that work with both `DotGraph`s and
+  the new `GDotGraph`s; this shouldn't affect any code already in use.
+
+* With the **prompting of Noam Lewis**, the augmentation functions
+  have been revamped in two ways:
+
+  - Now contains support for multiple edges.
+
+  - The ability to perform "manual" augmentation if greater control is
+    desired.
+
+* Add a preview function to quickly render and visualise an `FGL`
+  graph using the `Xlib` canvas.
+
+* Added a pseudo-inverse of the `FGL -> Dot` functions (a graph is
+  created, but the original node and edge labels are unrecoverable).
+
+* The `Printing` and `Parsing` modules have been moved (from
+  `Data.GraphViz.Types` to `Data.GraphViz`).
+
+* Reworked file-generating commands such that they return the filename
+  of the created file if successful.
+
+Changes in 2999.7.0.0
+---------------------
+
+* Updated and extended functions to interact with the Graphviz tools.
+  This now includes:
+
+  - a better listing of available output types;
+
+  - distinguishing file outputs from canvas outputs;
+
+  - ability to automatically add the correct file extension to file
+    outputs
+
+  - Return any errors if calling Graphviz failed rather than just
+    printing them to stderr
+
+* Improved `Color` support:
+
+  - fixed `ColorScheme` values
+
+  - explicitly named `X11` colors
+
+  - conversion to/from values from the [colour] library
+
+  [colour]: http://www.haskell.org/haskellwiki/Colour
+
+* Removed `OrientationGraph`; problems with distinguishing it when
+  parsing from node-based `Orientation` values; its functionality is
+  duplicated by `Rotate`.
+
+* By default, the generated Dot code is now no longer indented; you
+  can now use the `prettyPrint` functions in `Data.GraphViz` to
+  produce readable Dot code.
+
+* Added a testsuite; this is buildable by building with
+  `--flags-test`.  Numerous printing and parsing bugs were picked up
+  with this.
+
+Changes in 2999.6.0.0
+---------------------
+
+* Remove some `Shape` aliases and change capitalisation of others.
+
+* Properly parse and print IDs of clusters.
+
+* Allow `NodeCluster` values to have node types different from the
+  `LNode` they come from.
+
+Changes in 2999.5.1.1
+---------------------
+
+* When used as labels, etc., the Dot keywords `node`, `edge`, `graph`,
+  `digraph`, `subgraph`, and `strict` need to be quoted.  **Spotted by
+  Kathleen Fisher.**
+
+Changes in 2999.5.1.0
+---------------------
+
+* Potentially fixed the `graphvizWithHandle` bug; correct approach
+  **spotted by Nikolas Mayr**.
+
+* Fixed up `Parsing` of various `Attribute` sub-values, especially
+  `Point` and `Spline` (and hence `Pos`, which uses them).
+
+* Pre-process out comments and join together multi-line strings before
+  parsing.
+
+* Properly parse `Doubles` like `".2"`.
+
+Changes in 2999.5.0.0
+---------------------
+
+A major re-write occured; these are the highlights:
+
+* Re-write parsing and printing of Dot code using the new `ParseDot`
+  and `PrintDot` classes.  This should finally fix all quoting issues,
+  as well as leaving `Show` as the code representation for hacking
+  purposes.  As part of this, the `Data.GraphViz.ParserCombinators`
+  module has been moved to `Data.GraphViz.Types.Parsing`.
+
+* Re-write the various `Dot*` datatypes in `Data.GraphViz.Types`.
+  Sub-graphs/clusters are now their own entity rather than being part
+  of `DotNode` and the Node ID type is now a type parameter rather
+  than being just `Int`.  Sub-graphs/clusters can now also be parsed.
+
+* The various conversion functions in `Data.GraphViz` now come in two
+  flavours: the unprimed versions take in a `Bool` indicating if the
+  graph is directed or not; the primed versions attempt to
+  automatically detect this.
+
+* Add cluster support for the graph augmentation functions, **as
+  requested by Nikolas Mayr**.
+
+* Allow custom arrow types as supported by GraphViz; **as requested by
+  Han Joosten**.
+
+* Fixed a bug in HSV-style `Color` values where `Int` was used instead of
+  `Double`; **spotted by Michael deLorimier**.
+
+* Properly resolved the situation initially spotted by Neil Brown:
+  Matthew Sackman was following Dot terminology for an edge `a -> b`
+  when using _head_ for `b` and _tail_ for `a` (this is presumably
+  because the head/tail of the arrow are at those nodes).  `DotEdge`
+  now uses _from_ and _to_ avoid ambiguity; the various `Attribute`
+  values still follow upstream usage.
+
+Changes in 2999.1.0.2
+---------------------
+
+* Fix a bug **spotted by Srihari Ramanathan** where `Color` values
+  were double-quoted.
+
+Changes in 2999.1.0.1
+---------------------
+
+* The `Color` `Attribute` should take `[Color]`, not just a single
+  `Color`.
+
+Changes in 2999.1.0.0
+---------------------
+
+* Stop using `Either` for composite `Attributes` and use a custom
+  type: this avoids problems with the `Show` instance.
+
+Changes in 2999.0.0.0
+---------------------
+
+* Fixed a bug where the Show instance and read function for `DotEdge`
+  had the from/to nodes the wrong way round.  This was not immediately
+  noticed since the `Graph` to `DotGraph` functions created them the
+  wrong way round, so for those users who only used these this was not
+  apparent.  **Spotted by Neil Brown.**
+
+* Greatly improved `Attribute` usage: almost all attributes are now
+  covered with allowed values.
+
+* Extend DotGraph to include whether a graph is strict or not and if
+  it has an ID.  Also move the directedGraph field.
+
+* Make `Dot` refer to the actual dot command and `DotArrow` refer to
+  the `ArrowType` (rather than `DotCmd` and `Dot` as before).
+
+* Make the `Data.GraphViz.ParserCombinators` module available to end
+  users again, but not re-exported by `Data.GraphViz`; it has a
+  warning message up the top not to be used.  It is there purely for
+  documentative purposes.
+
+* Use [extensible-exceptions] so that `base-3.x` is once again
+  supported.
+
+  [extensible-exceptions]: http://hackage.haskell.org/package/extensible-exceptions
+
+* Follow the [Package Versioning Policy] rather than using dates for
+  versions.
+
+  [Package Versioning Policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy
+
+
+Changes in 2009.5.1
+-------------------
+
+* New maintainer: Ivan Lazar Miljenovic.
+
+* Support `polyparse >= 1.1` (as opposed to `< 1.3`)
+
+* Require `base == 4.*` (i.e. `GHC 6.10.*`) due to new exception handling.
+
+* Include functions from [Graphalyze-0.5] for running GraphViz
+  commands, etc.
+
+  [Graphalyze-0.5]: http://hackage.haskell.org/package/Graphalyze-0.5
+
+* Module re-organisation.
+
+* The `Data.GraphViz.ParserCombinators` module is no longer available
+  to end users.
+
+* Improved Haddock documentation.
+
+Changes in 2008.9.20
+--------------------
+
+* Differentiate between undirected and directed graphs (previously
+  only directed graphs were supported).
+
+* Clustering support was added.
+
+Older versions
+--------------
+
+For versions of graphviz older than `2008.9.20`, the exact differences
+between versions is unknown.
diff --git a/Data/GraphViz.hs b/Data/GraphViz.hs
--- a/Data/GraphViz.hs
+++ b/Data/GraphViz.hs
@@ -75,6 +75,7 @@
 import Data.GraphViz.Commands
 import Data.GraphViz.Commands.IO(hGetDot)
 
+import Data.Functor((<$>))
 import Data.Graph.Inductive.Graph
 import qualified Data.Set as Set
 import Control.Arrow((&&&), first)
@@ -82,7 +83,6 @@
 import qualified Data.Map as Map
 import qualified Data.Text.Lazy as T
 import Data.Text.Lazy(Text)
-import Control.Monad(liftM)
 import System.IO.Unsafe(unsafePerformIO)
 import Control.Concurrent(forkIO)
 
@@ -169,6 +169,11 @@
 --   These correspond to 'LNode' and 'LEdge' in FGL graphs.
 --
 --   The clustering in 'clusterBy' can be to arbitrary depth.
+--
+--   Note that the term \"cluster\" is slightly conflated here: in
+--   terms of @GraphvizParams@ values, a cluster is a grouping of
+--   nodes; the 'isDotCluster' function lets you specify whether it is
+--   a cluster in the Dot sense or just a sub-graph.
 data GraphvizParams n nl el cl l
      = Params { -- | @True@ if the graph is directed; @False@
                 --   otherwise.
@@ -179,6 +184,9 @@
                 -- | A function to specify which cluster a particular
                 --   node is in.
               , clusterBy        :: ((n,nl) -> NodeCluster cl (n,l))
+                -- | Is this \"cluster\" actually a cluster, or just a
+                --   sub-graph?
+              , isDotCluster     :: (cl -> Bool)
                 -- | The name/identifier for a cluster.
               , clusterID        :: (cl -> GraphID)
                 -- | Specify which global attributes are applied in
@@ -208,6 +216,7 @@
 defaultParams = Params { isDirected       = True
                        , globalAttributes = []
                        , clusterBy        = N
+                       , isDotCluster     = const True
                        , clusterID        = const (Int 0)
                        , fmtCluster       = const []
                        , fmtNode          = const []
@@ -232,6 +241,7 @@
 blankParams = Params { isDirected       = undefined
                      , globalAttributes = undefined
                      , clusterBy        = undefined
+                     , isDotCluster     = undefined
                      , clusterID        = undefined
                      , fmtCluster       = undefined
                      , fmtNode          = undefined
@@ -271,8 +281,8 @@
                      , nodeStmts = ns
                      , edgeStmts = es
                      }
-    (cs, ns) = clustersToNodes (clusterBy params) (clusterID params)
-                               (fmtCluster params) (fmtNode params)
+    (cs, ns) = clustersToNodes (clusterBy params) (isDotCluster params)
+                               (clusterID params) (fmtCluster params) (fmtNode params)
                                lns
     es = mapMaybe mkDotEdge les
     mkDotEdge e@(f,t,_) = if dirGraph || f <= t
@@ -294,7 +304,7 @@
     -- Applying uniqBy just in case...
     ns = uniqBy fst . map toLN $ graphNodes dg
     es = concatMap toLE $ graphEdges dg
-    -- Need to ensure that for some reason there are node IDs in an
+    -- Need to check that for some reason there aren't node IDs in an
     -- edge but not on their own.
     nSet = Set.fromList $ map fst ns
     nEs = map (flip (,) [])
@@ -415,8 +425,8 @@
     es' = zipWith addID es ([1..] :: [Int])
     addID (f,t,l) i = (f,t,EID (T.pack $ show i) l)
 
--- | Add the 'Comment' to the list of attributes containing the value
---   of the unique edge identifier.
+-- | Add a custom attribute to the list of attributes containing the
+--   value of the unique edge identifier.
 setEdgeIDAttribute     :: (LEdge el -> Attributes)
                           -> (LEdge (EdgeID el) -> Attributes)
 setEdgeIDAttribute f = \ e@(_,_,eid) -> identifierAttribute (eID eid)
@@ -437,8 +447,7 @@
 dotAttributes :: (Graph gr, PPDotRepr dg Node) => Bool -> gr nl (EdgeID el)
                  -> dg Node -> IO (gr (AttributeNode nl) (AttributeEdge el))
 dotAttributes isDir gr dot
-  = liftM (augmentGraph gr . parseDG)
-    $ graphvizWithHandle command dot DotOutput hGetDot
+  = augmentGraph gr . parseDG <$> graphvizWithHandle command dot DotOutput hGetDot
   where
     parseDG = (`asTypeOf` dot)
     command = if isDir then dirCommand else undirCommand
diff --git a/Data/GraphViz/Algorithms/Clustering.hs b/Data/GraphViz/Algorithms/Clustering.hs
--- a/Data/GraphViz/Algorithms/Clustering.hs
+++ b/Data/GraphViz/Algorithms/Clustering.hs
@@ -32,11 +32,11 @@
 
 -- | Extract the clusters and nodes from the list of nodes.
 clustersToNodes :: (Ord c) => ((n,a) -> NodeCluster c (n,l))
-                  -> (c -> GraphID) -> (c -> [GlobalAttributes])
+                  -> (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes])
                   -> ((n,l) -> Attributes) -> [(n,a)]
                   -> ([DotSubGraph n], [DotNode n])
-clustersToNodes clusterBy cID fmtCluster fmtNode
-    = treesToDot cID fmtCluster fmtNode
+clustersToNodes clusterBy isC cID fmtCluster fmtNode
+    = treesToDot isC cID fmtCluster fmtNode
       . collapseNClusts
       . map (clustToTree . clusterBy)
 
@@ -84,23 +84,23 @@
 -- | Convert the cluster representation of the trees into 'DotNode's
 --   and 'DotSubGraph's (with @'isCluster' = 'True'@, and
 --   @'subGraphID' = 'Nothing'@).
-treesToDot :: (c -> GraphID) -> (c -> [GlobalAttributes])
+treesToDot :: (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes])
               -> ((n,a) -> Attributes) -> [ClusterTree c (n,a)]
               -> ([DotSubGraph n], [DotNode n])
-treesToDot cID fmtCluster fmtNode
+treesToDot isC cID fmtCluster fmtNode
     = partitionEithers
-      . map (treeToDot cID fmtCluster fmtNode)
+      . map (treeToDot isC cID fmtCluster fmtNode)
 
 -- | Convert this 'ClusterTree' into its /Dot/ representation.
-treeToDot :: (c -> GraphID) -> (c -> [GlobalAttributes])
+treeToDot :: (c -> Bool) -> (c -> GraphID) -> (c -> [GlobalAttributes])
              -> ((n,a) -> Attributes) -> ClusterTree c (n,a)
              -> Either (DotSubGraph n) (DotNode n)
-treeToDot _ _ fmtNode (NT ln)
+treeToDot _ _ _ fmtNode (NT ln)
     = Right DotNode { nodeID         = fst ln
                     , nodeAttributes = fmtNode ln
                     }
-treeToDot cID fmtCluster fmtNode (CT c nts)
-    = Left DotSG { isCluster     = True
+treeToDot isC cID fmtCluster fmtNode (CT c nts)
+    = Left DotSG { isCluster     = isC c
                  , subGraphID    = Just $ cID c
                  , subGraphStmts = stmts
                  }
@@ -110,4 +110,4 @@
                      , nodeStmts = ns
                      , edgeStmts = []
                      }
-    (cs, ns) = treesToDot cID fmtCluster fmtNode nts
+    (cs, ns) = treesToDot isC cID fmtCluster fmtNode nts
diff --git a/Data/GraphViz/Attributes/Colors.hs b/Data/GraphViz/Attributes/Colors.hs
--- a/Data/GraphViz/Attributes/Colors.hs
+++ b/Data/GraphViz/Attributes/Colors.hs
@@ -52,7 +52,6 @@
 import Data.Maybe(isJust)
 import Data.Word(Word8)
 import qualified Data.Text.Lazy as T
-import Control.Monad(liftM)
 
 -- -----------------------------------------------------------------------------
 
@@ -122,6 +121,8 @@
                     , parseNC (undefined :: SVGColor) False
                     , parseX11Color False
                     ]
+              `onFail`
+              fail "Could not parse Color"
     where
       parseHexBased
           = do character '#'
@@ -132,13 +133,12 @@
                           _ -> throw . NotDotCode
                                $ "Not a valid hex Color specification: "
                                   ++ show cs
-      parseHSV = do h <- parse
-                    parseSep
-                    s <- parse
-                    parseSep
-                    v <- parse
-                    return $ HSV h s v
-      parseSep = oneOf [ string ","
+      parseHSV = HSV <$> parse
+                     <*  parseSep
+                     <*> parse
+                     <*  parseSep
+                     <*> parse
+      parseSep = oneOf [ string "," *> whitespace
                        , whitespace1
                        ]
       parse2Hex = do c1 <- satisfy isHexDigit
@@ -152,10 +152,16 @@
                 , parseNC (undefined :: SVGColor) True
                 , parseX11Color True
                 ]
+          `onFail`
+          fail "Could not parse Color"
 
   parseUnqtList = sepBy1 parseUnqt (character ':')
+                  `onFail`
+                  do cs <- getColorScheme
+                     failBad $ "Error parsing list of Colors with color scheme of "
+                               ++ show cs
 
-  parseList = liftM (:[])
+  parseList = fmap (:[])
               -- Unquoted single color
               (oneOf [ parseNC (undefined :: BrewerColor) True
                      , parseNC (undefined :: SVGColor) True
@@ -164,6 +170,10 @@
               )
               `onFail`
               quotedParse parseUnqtList
+              `onFail`
+              do cs <- getColorScheme
+                 failBad $ "Error parsing list of Colors with color scheme of "
+                           ++ show cs
 
 -- -----------------------------------------------------------------------------
 
@@ -175,6 +185,7 @@
 
     printNC :: Bool -> nc -> DotCode
 
+    -- | Bool is for whether quoting is needed.
     parseNC' :: Bool -> Parse nc
 
 -- First value just used for type
@@ -234,7 +245,7 @@
                    => (ColorScheme -> Maybe cs) -> Parse cs -> (cs -> Bool)
                    -> (cs -> lv -> nc) -> Bool -> Parse nc
 parseNamedColor gcs parseCS vcs mkC q
-    = do Just cs <- gcs `fmap` getColorScheme
+    = do Just cs <- gcs <$> getColorScheme
          lv <- bool parseUnqt parse q
                `onFail`
                mQts (string "//" *> parseUnqt)
@@ -244,8 +255,7 @@
                 cs <- parseCS
                 character '/'
                 if vcs cs
-                   then do lv <- parseUnqt
-                           return $ mkC cs lv
+                   then mkC cs <$>  parseUnqt
                    else fail "Explicit colorscheme not as expected."
            )
     where
@@ -256,16 +266,16 @@
 -- X11 has a special case when parsing: '/yyyy'
 
 parseX11Color   :: Bool -> Parse Color
-parseX11Color q = fmap X11Color
-                  $ parseNC' q
-                    `onFail`
-                    bool id quotedParse q (character '/' *> parseUnqt)
-                    `onFail`
-                    -- Can use X11 colors within brewer colorscheme.
-                    do cs <- getColorScheme
-                       case cs of
-                         Brewer{} -> bool parseUnqt parse q
-                         _        -> fail "Unable to parse an X11 color within Brewer"
+parseX11Color q = X11Color
+                  <$> parseNC' q
+                      `onFail`
+                      bool id quotedParse q (character '/' *> parseUnqt)
+                      `onFail`
+                      -- Can use X11 colors within brewer colorscheme.
+                      do cs <- getColorScheme
+                         case cs of
+                           Brewer{} -> bool parseUnqt parse q
+                           _        -> fail "Unable to parse an X11 color within Brewer"
 
 -- -----------------------------------------------------------------------------
 
diff --git a/Data/GraphViz/Attributes/Complete.hs b/Data/GraphViz/Attributes/Complete.hs
--- a/Data/GraphViz/Attributes/Complete.hs
+++ b/Data/GraphViz/Attributes/Complete.hs
@@ -110,6 +110,7 @@
        , Label(..)
        , VerticalPlacement(..)
        , LabelScheme(..)
+       , SVGFontNames(..)
          -- *** Types representing the Dot grammar for records.
        , RecordFields
        , RecordField(..)
@@ -146,6 +147,7 @@
        , DPoint(..)
 
          -- ** Layout
+       , GraphSize(..)
        , AspectType(..)
        , ClusterMode(..)
        , Model(..)
@@ -197,7 +199,6 @@
 import qualified Data.Set as S
 import qualified Data.Text.Lazy as T
 import Data.Text.Lazy(Text)
-import Control.Monad(liftM, liftM2)
 import System.FilePath(searchPathSeparator, splitSearchPath)
 
 -- -----------------------------------------------------------------------------
@@ -244,9 +245,9 @@
   = Damping Double                      -- ^ /Valid for/: G; /Default/: @0.99@; /Minimum/: @0.0@; /Notes/: neato only
   | K Double                            -- ^ /Valid for/: GC; /Default/: @0.3@; /Minimum/: @0@; /Notes/: sfdp, fdp only
   | URL EscString                       -- ^ /Valid for/: ENGC; /Default/: none; /Notes/: svg, postscript, map only
-  | ArrowHead ArrowType                 -- ^ /Valid for/: E; /Default/: @'AType' [('noMods', 'Normal')]@
+  | ArrowHead ArrowType                 -- ^ /Valid for/: E; /Default/: @'normal'@
   | ArrowSize Double                    -- ^ /Valid for/: E; /Default/: @1.0@; /Minimum/: @0.0@
-  | ArrowTail ArrowType                 -- ^ /Valid for/: E; /Default/: @'AType' [('noMods', 'Normal')]@
+  | ArrowTail ArrowType                 -- ^ /Valid for/: E; /Default/: @'normal'@
   | Aspect AspectType                   -- ^ /Valid for/: G; /Notes/: dot only
   | BoundingBox Rect                    -- ^ /Valid for/: G; /Notes/: write only
   | ColorScheme ColorScheme             -- ^ /Valid for/: ENCG; /Default/: @'X11'@
@@ -259,7 +260,7 @@
   | Concentrate Bool                    -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'
   | Constraint Bool                     -- ^ /Valid for/: E; /Default/: @'True'@; /Parsing Default/: 'True'; /Notes/: dot only
   | Decorate Bool                       -- ^ /Valid for/: E; /Default/: @'False'@; /Parsing Default/: 'True'
-  | DefaultDist Double                  -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(|V|)@; /Minimum/: @epsilon@; /Notes/: neato only, only if @'Pack' 'DontPack'@
+  | DefaultDist Double                  -- ^ /Valid for/: G; /Default/: @1+(avg. len)*sqrt(abs(V))@; /Minimum/: @epsilon@; /Notes/: neato only, only if @'Pack' 'DontPack'@
   | Dim Int                             -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: sfdp, fdp, neato only
   | Dimen Int                           -- ^ /Valid for/: G; /Default/: @2@; /Minimum/: @2@; /Notes/: sfdp, fdp, neato only
   | Dir DirType                         -- ^ /Valid for/: E; /Default/: @'Forward'@ (directed), @'NoDir'@ (undirected)
@@ -275,7 +276,7 @@
   | FixedSize Bool                      -- ^ /Valid for/: N; /Default/: @'False'@; /Parsing Default/: 'True'
   | FontColor Color                     -- ^ /Valid for/: ENGC; /Default/: @'X11Color' 'Black'@
   | FontName Text                       -- ^ /Valid for/: ENGC; /Default/: @\"Times-Roman\"@
-  | FontNames Text                      -- ^ /Valid for/: G; /Default/: @\"\"@; /Notes/: svg only
+  | FontNames SVGFontNames              -- ^ /Valid for/: G; /Default/: @'SvgNames'@; /Notes/: svg only
   | FontPath Text                       -- ^ /Valid for/: G; /Default/: system dependent
   | FontSize Double                     -- ^ /Valid for/: ENGC; /Default/: @14.0@; /Minimum/: @1.0@
   | ForceLabels Bool                    -- ^ /Valid for/: G; /Default/: @'False'@; /Parsing Default/: 'True'; /Notes/: Only for 'XLabel' attributes, requires Graphviz >= 2.29.0
@@ -369,7 +370,7 @@
   | ShapeFile Text                      -- ^ /Valid for/: N; /Default/: @\"\"@
   | ShowBoxes Int                       -- ^ /Valid for/: ENG; /Default/: @0@; /Minimum/: @0@; /Notes/: dot only
   | Sides Int                           -- ^ /Valid for/: N; /Default/: @4@; /Minimum/: @0@
-  | Size Point                          -- ^ /Valid for/: G
+  | Size GraphSize                      -- ^ /Valid for/: G
   | Skew Double                         -- ^ /Valid for/: N; /Default/: @0.0@; /Minimum/: @-100.0@
   | Smoothing SmoothType                -- ^ /Valid for/: G; /Default/: @'NoSmooth'@; /Notes/: sfdp only
   | SortV Word16                        -- ^ /Valid for/: GCN; /Default/: @0@; /Minimum/: @0@
@@ -559,11 +560,11 @@
   listToDot = unqtListToDot
 
 instance ParseDot Attribute where
-  parseUnqt = stringParse (concat [ parseField Damping "Damping"
-                                  , parseField K "K"
+  parseUnqt = stringParse (concat [ parseFieldNumDef Damping 0.99 "Damping"
+                                  , parseFieldNumDef K 0.3 "K"
                                   , parseFields URL ["URL", "href"]
                                   , parseField ArrowHead "arrowhead"
-                                  , parseField ArrowSize "arrowsize"
+                                  , parseFieldNumDef ArrowSize 1 "arrowsize"
                                   , parseField ArrowTail "arrowtail"
                                   , parseField Aspect "aspect"
                                   , parseField BoundingBox "bb"
@@ -578,11 +579,11 @@
                                   , parseFieldBool Constraint "constraint"
                                   , parseFieldBool Decorate "decorate"
                                   , parseField DefaultDist "defaultdist"
-                                  , parseField Dim "dim"
-                                  , parseField Dimen "dimen"
+                                  , parseFieldNumDef Dim 2 "dim"
+                                  , parseFieldNumDef Dimen 2 "dimen"
                                   , parseField Dir "dir"
                                   , parseFieldDef DirEdgeConstraints EdgeConstraints "diredgeconstraints"
-                                  , parseField Distortion "distortion"
+                                  , parseFieldNumDef Distortion 0 "distortion"
                                   , parseFields DPI ["dpi", "resolution"]
                                   , parseFields EdgeURL ["edgeURL", "edgehref"]
                                   , parseField EdgeTarget "edgetarget"
@@ -595,9 +596,9 @@
                                   , parseField FontName "fontname"
                                   , parseField FontNames "fontnames"
                                   , parseField FontPath "fontpath"
-                                  , parseField FontSize "fontsize"
+                                  , parseFieldNumDef FontSize 14 "fontsize"
                                   , parseFieldBool ForceLabels "forcelabels"
-                                  , parseField GradientAngle "gradientangle"
+                                  , parseFieldNumDef GradientAngle 0 "gradientangle"
                                   , parseField Group "group"
                                   , parseFields HeadURL ["headURL", "headhref"]
                                   , parseFieldBool HeadClip "headclip"
@@ -605,7 +606,7 @@
                                   , parseField HeadPort "headport"
                                   , parseField HeadTarget "headtarget"
                                   , parseField HeadTooltip "headtooltip"
-                                  , parseField Height "height"
+                                  , parseFieldNumDef Height 0.5 "height"
                                   , parseField ID "id"
                                   , parseField Image "image"
                                   , parseField ImagePath "imagepath"
@@ -613,12 +614,12 @@
                                   , parseField Label "label"
                                   , parseFields LabelURL ["labelURL", "labelhref"]
                                   , parseField LabelScheme "label_scheme"
-                                  , parseField LabelAngle "labelangle"
-                                  , parseField LabelDistance "labeldistance"
+                                  , parseFieldNumDef LabelAngle (-25) "labelangle"
+                                  , parseFieldNumDef LabelDistance 1 "labeldistance"
                                   , parseFieldBool LabelFloat "labelfloat"
                                   , parseField LabelFontColor "labelfontcolor"
                                   , parseField LabelFontName "labelfontname"
-                                  , parseField LabelFontSize "labelfontsize"
+                                  , parseFieldNumDef LabelFontSize 14 "labelfontsize"
                                   , parseField LabelJust "labeljust"
                                   , parseField LabelLoc "labelloc"
                                   , parseField LabelTarget "labeltarget"
@@ -629,8 +630,8 @@
                                   , parseField LayerSep "layersep"
                                   , parseField Layout "layout"
                                   , parseField Len "len"
-                                  , parseField LevelsGap "levelsgap"
-                                  , parseField Levels "levels"
+                                  , parseFieldNumDef LevelsGap 0 "levelsgap"
+                                  , parseFieldNumDef Levels maxBound "levels"
                                   , parseField LHead "lhead"
                                   , parseField LHeight "LHeight"
                                   , parseField LPos "lp"
@@ -638,34 +639,34 @@
                                   , parseField LWidth "lwidth"
                                   , parseField Margin "margin"
                                   , parseField MaxIter "maxiter"
-                                  , parseField MCLimit "mclimit"
-                                  , parseField MinDist "mindist"
-                                  , parseField MinLen "minlen"
+                                  , parseFieldNumDef MCLimit 1 "mclimit"
+                                  , parseFieldNumDef MinDist 1 "mindist"
+                                  , parseFieldNumDef MinLen 1 "minlen"
                                   , parseField Mode "mode"
                                   , parseField Model "model"
                                   , parseFieldBool Mosek "mosek"
-                                  , parseField NodeSep "nodesep"
+                                  , parseFieldNumDef NodeSep 0.25 "nodesep"
                                   , parseFieldBool NoJustify "nojustify"
                                   , parseFieldBool Normalize "normalize"
                                   , parseField Nslimit "nslimit"
                                   , parseField Nslimit1 "nslimit1"
                                   , parseField Ordering "ordering"
-                                  , parseField Orientation "orientation"
+                                  , parseFieldNumDef Orientation 0 "orientation"
                                   , parseField OutputOrder "outputorder"
                                   , parseFieldDef Overlap KeepOverlaps "overlap"
-                                  , parseField OverlapScaling "overlap_scaling"
+                                  , parseFieldNumDef OverlapScaling (-4) "overlap_scaling"
                                   , parseFieldDef Pack DoPack "pack"
                                   , parseField PackMode "packmode"
                                   , parseField Pad "pad"
                                   , parseField Page "page"
                                   , parseField PageDir "pagedir"
                                   , parseField PenColor "pencolor"
-                                  , parseField PenWidth "penwidth"
-                                  , parseField Peripheries "peripheries"
+                                  , parseFieldNumDef PenWidth 1 "penwidth"
+                                  , parseFieldNumDef Peripheries 1 "peripheries"
                                   , parseFieldBool Pin "pin"
                                   , parseField Pos "pos"
                                   , parseFieldDef QuadTree NormalQT "quadtree"
-                                  , parseField Quantum "quantum"
+                                  , parseFieldNumDef Quantum 0 "quantum"
                                   , parseField Rank "rank"
                                   , parseField RankDir "rankdir"
                                   , parseField RankSep "ranksep"
@@ -673,22 +674,22 @@
                                   , parseField Rects "rects"
                                   , parseFieldBool Regular "regular"
                                   , parseFieldBool ReMinCross "remincross"
-                                  , parseField RepulsiveForce "repulsiveforce"
+                                  , parseFieldNumDef RepulsiveForce 1 "repulsiveforce"
                                   , parseFieldDef Root IsCentral "root"
-                                  , parseField Rotate "rotate"
-                                  , parseField Rotation "rotation"
+                                  , parseFieldNumDef Rotate 0 "rotate"
+                                  , parseFieldNumDef Rotation 0 "rotation"
                                   , parseField SameHead "samehead"
                                   , parseField SameTail "sametail"
                                   , parseField SamplePoints "samplepoints"
                                   , parseField Scale "scale"
-                                  , parseField SearchSize "searchsize"
+                                  , parseFieldNumDef SearchSize 30 "searchsize"
                                   , parseField Sep "sep"
                                   , parseField Shape "shape"
                                   , parseField ShapeFile "shapefile"
-                                  , parseField ShowBoxes "showboxes"
-                                  , parseField Sides "sides"
+                                  , parseFieldNumDef ShowBoxes 0 "showboxes"
+                                  , parseFieldNumDef Sides 4 "sides"
                                   , parseField Size "size"
-                                  , parseField Skew "skew"
+                                  , parseFieldNumDef Skew 0 "skew"
                                   , parseField Smoothing "smoothing"
                                   , parseField SortV "sortv"
                                   , parseFieldDef Splines SplineEdges "splines"
@@ -706,14 +707,16 @@
                                   , parseFieldBool TrueColor "truecolor"
                                   , parseField Vertices "vertices"
                                   , parseField ViewPort "viewport"
-                                  , parseField VoroMargin "voro_margin"
+                                  , parseFieldNumDef VoroMargin 0.05 "voro_margin"
                                   , parseField Weight "weight"
-                                  , parseField Width "width"
+                                  , parseFieldNumDef Width 0.75 "width"
                                   , parseField XLabel "xlabel"
-                                  , parseField Z "z"
+                                  , parseFieldNumDef Z 0 "z"
                                   ])
               `onFail`
-              liftM2 UnknownAttribute stringBlock (parseEq >> parse)
+              do attrName <- stringBlock
+                 liftEqParse' ("UnknownAttribute (" ++ T.unpack attrName ++ ")")
+                              (UnknownAttribute attrName)
 
   parse = parseUnqt
 
@@ -1142,7 +1145,7 @@
 defaultAttributeValue FixedSize{}          = Just $ FixedSize False
 defaultAttributeValue FontColor{}          = Just $ FontColor (X11Color Black)
 defaultAttributeValue FontName{}           = Just $ FontName "Times-Roman"
-defaultAttributeValue FontNames{}          = Just $ FontNames ""
+defaultAttributeValue FontNames{}          = Just $ FontNames SvgNames
 defaultAttributeValue FontSize{}           = Just $ FontSize 14
 defaultAttributeValue ForceLabels{}        = Just $ ForceLabels False
 defaultAttributeValue GradientAngle{}      = Just $ GradientAngle 0
@@ -1545,10 +1548,7 @@
 instance ParseDot ArrowType where
   parseUnqt = specialArrowParse
               `onFail`
-              do mas <- many1 $ do m <- parseUnqt
-                                   a <- parseUnqt
-                                   return (m,a)
-                 return $ AType mas
+              (AType <$> many1 (liftA2 (,) parseUnqt parseUnqt))
 
 specialArrowParse :: Parse ArrowType
 specialArrowParse = stringValue [ ("ediamond", eDiamond)
@@ -1610,9 +1610,7 @@
   unqtDot (ArrMod f s) = unqtDot f <> unqtDot s
 
 instance ParseDot ArrowModifier where
-  parseUnqt = do f <- parseUnqt
-                 s <- parseUnqt
-                 return $ ArrMod f s
+  parseUnqt = liftA2 ArrMod parseUnqt parseUnqt
 
 data ArrowFill = OpenArrow
                | FilledArrow
@@ -1623,8 +1621,7 @@
   unqtDot FilledArrow = empty
 
 instance ParseDot ArrowFill where
-  parseUnqt = liftM (bool FilledArrow OpenArrow . isJust)
-              $ optional (character 'o')
+  parseUnqt = bool FilledArrow OpenArrow . isJust <$> optional (character 'o')
 
   -- Not used individually
   parse = parseUnqt
@@ -1642,8 +1639,7 @@
   unqtDot BothSides = empty
 
 instance ParseDot ArrowSide where
-  parseUnqt = liftM getSideType
-              $ optional (oneOf $ map character ['l', 'r'])
+  parseUnqt = getSideType <$> optional (oneOf $ map character ['l', 'r'])
     where
       getSideType = maybe BothSides
                           (bool RightSide LeftSide . (==) 'l')
@@ -1665,14 +1661,14 @@
   toDot at@RatioPassCount{} = dquotes $ unqtDot at
 
 instance ParseDot AspectType where
-  parseUnqt = liftM (uncurry RatioPassCount) commaSepUnqt
+  parseUnqt = fmap (uncurry RatioPassCount) commaSepUnqt
               `onFail`
-              liftM RatioOnly parseUnqt
+              fmap RatioOnly parseUnqt
 
 
-  parse = quotedParse (liftM (uncurry RatioPassCount) commaSepUnqt)
+  parse = quotedParse (uncurry RatioPassCount <$> commaSepUnqt)
           `onFail`
-          liftM RatioOnly parse
+          fmap RatioOnly parse
 
 -- -----------------------------------------------------------------------------
 
@@ -1681,14 +1677,14 @@
             deriving (Eq, Ord, Show, Read)
 
 instance PrintDot Rect where
-  unqtDot (Rect p1 p2) = commaDel p1 p2
+  unqtDot (Rect p1 p2) = printPoint2DUnqt p1 <> comma <> printPoint2DUnqt p2
 
   toDot = dquotes . unqtDot
 
   unqtListToDot = hsep . mapM unqtDot
 
 instance ParseDot Rect where
-  parseUnqt = liftM (uncurry Rect) $ commaSep' parsePoint2D parsePoint2D
+  parseUnqt = uncurry Rect <$> commaSep' parsePoint2D parsePoint2D
 
   parse = quotedParse parseUnqt
 
@@ -1750,7 +1746,7 @@
   unqtDot HierConstraints = text "hier"
 
 instance ParseDot DEConstraints where
-  parseUnqt = liftM (bool NoConstraints EdgeConstraints) parse
+  parseUnqt = fmap (bool NoConstraints EdgeConstraints) parse
               `onFail`
               stringRep HierConstraints "hier"
 
@@ -1758,28 +1754,90 @@
 
 -- | Either a 'Double' or a (2D) 'Point' (i.e. created with
 --   'createPoint').
+--
+--   Whilst it is possible to create a 'Point' value with either a
+--   third co-ordinate or a forced position, these are ignored for
+--   printing/parsing.
+--
+--   An optional prefix of @\'+\'@ is allowed when parsing.
 data DPoint = DVal Double
             | PVal Point
             deriving (Eq, Ord, Show, Read)
 
 instance PrintDot DPoint where
   unqtDot (DVal d) = unqtDot d
-  unqtDot (PVal p) = unqtDot p
+  unqtDot (PVal p) = printPoint2DUnqt p
 
   toDot (DVal d) = toDot d
-  toDot (PVal p) = toDot p
+  toDot (PVal p) = printPoint2D p
 
 instance ParseDot DPoint where
-  parseUnqt = liftM PVal parsePoint2D
+  parseUnqt = fmap PVal parsePoint2D
               `onFail`
-              liftM DVal parseUnqt
+              fmap DVal parseUnqt
 
   parse = quotedParse parseUnqt
           `onFail`
-          liftM DVal parseUnqt
+          fmap DVal parseUnqt
 
 -- -----------------------------------------------------------------------------
 
+-- | The mapping used for 'FontName' values in SVG output.
+--
+--   More information can be found at <http://www.graphviz.org/doc/fontfaq.txt>.
+data SVGFontNames = SvgNames        -- ^ Use the legal generic SVG font names.
+                  | PostScriptNames -- ^ Use PostScript font names.
+                  | FontConfigNames -- ^ Use fontconfig font conventions.
+                  deriving (Eq, Ord, Bounded, Enum, Show, Read)
+
+instance PrintDot SVGFontNames where
+  unqtDot SvgNames        = text "svg"
+  unqtDot PostScriptNames = text "ps"
+  unqtDot FontConfigNames = text "gd"
+
+instance ParseDot SVGFontNames where
+  parseUnqt = oneOf [ stringRep SvgNames "svg"
+                    , stringRep PostScriptNames "ps"
+                    , stringRep FontConfigNames "gd"
+                    ]
+
+  parse = stringRep SvgNames "\"\""
+          `onFail`
+          optionalQuoted parseUnqt
+
+-- -----------------------------------------------------------------------------
+
+-- | Maximum width and height of drawing in inches.
+data GraphSize = GSize { width :: Double
+                         -- | If @Nothing@, then the height is the
+                         --   same as the width.
+                       , height :: Maybe Double
+                         -- | If drawing is smaller than specified
+                         --   size, this value determines whether it
+                         --   is scaled up.
+                       , desiredSize :: Bool
+                       }
+               deriving (Eq, Ord, Show, Read)
+
+instance PrintDot GraphSize where
+  unqtDot (GSize w mh ds) = bool id (<> char '!') ds
+                            . maybe id (\h -> (<> unqtDot h) . (<> comma)) mh
+                            $ unqtDot w
+
+  toDot (GSize w Nothing False) = toDot w
+  toDot gs                      = dquotes $ unqtDot gs
+
+instance ParseDot GraphSize where
+  parseUnqt = GSize <$> parseUnqt
+                    <*> optional (parseComma *> whitespace *> parseUnqt)
+                    <*> (isJust <$> optional (character '!'))
+
+  parse = quotedParse parseUnqt
+          `onFail`
+          fmap (\ w -> GSize w Nothing False) parseUnqt
+
+-- -----------------------------------------------------------------------------
+
 data ModeType = Major
               | KK
               | Hier
@@ -1845,14 +1903,14 @@
   -- between an HtmlLabel and a RecordLabel starting with a PortPos,
   -- since the latter will be in quotes and the former won't.
 
-  parseUnqt = oneOf [ liftM HtmlLabel $ parseAngled parseUnqt
-                    , liftM RecordLabel parseUnqt
-                    , liftM StrLabel parseUnqt
+  parseUnqt = oneOf [ HtmlLabel <$> parseAngled parseUnqt
+                    , RecordLabel <$> parseUnqt
+                    , StrLabel <$> parseUnqt
                     ]
 
-  parse = oneOf [ liftM HtmlLabel $ parseAngled parse
-                , liftM RecordLabel parse
-                , liftM StrLabel parse
+  parse = oneOf [ HtmlLabel <$> parseAngled parse
+                , RecordLabel <$> parse
+                , StrLabel <$> parse
                 ]
 
 -- -----------------------------------------------------------------------------
@@ -1888,15 +1946,16 @@
   listToDot fs  = dquotes $ unqtListToDot fs
 
 instance ParseDot RecordField where
-  parseUnqt = do t <- liftM PN $ parseAngled parseRecord
-                 ml <- optional (whitespace1 >> parseRecord)
-                 return $ maybe (PortName t)
-                                (LabelledTarget t)
-                                ml
+  parseUnqt = (liftA2 maybe PortName LabelledTarget
+                <$> (PN <$> parseAngled parseRecord)
+                <*> optional (whitespace1 *> parseRecord)
+              )
               `onFail`
-              liftM FieldLabel parseRecord
+              fmap FieldLabel parseRecord
               `onFail`
-              liftM FlipFields (parseBraced parseUnqt)
+              fmap FlipFields (parseBraced parseUnqt)
+              `onFail`
+              fail "Unable to parse RecordField"
 
   parse = quotedParse parseUnqt
 
@@ -1966,8 +2025,14 @@
 createPoint     :: Double -> Double -> Point
 createPoint x y = Point x y Nothing False
 
+printPoint2DUnqt   :: Point -> DotCode
+printPoint2DUnqt p = commaDel (xCoord p) (yCoord p)
+
+printPoint2D :: Point -> DotCode
+printPoint2D = dquotes . printPoint2DUnqt
+
 parsePoint2D :: Parse Point
-parsePoint2D = liftM (uncurry createPoint) commaSepUnqt
+parsePoint2D = uncurry createPoint <$> commaSepUnqt
 
 instance PrintDot Point where
   unqtDot (Point x y mz frs) = bool id (<> char '!') frs
@@ -1981,10 +2046,10 @@
   listToDot = dquotes . unqtListToDot
 
 instance ParseDot Point where
-  parseUnqt = do (x,y) <- commaSepUnqt
-                 mz <- optional $ parseComma >> parseUnqt
-                 bng <- liftM isJust . optional $ character '!'
-                 return $ Point x y mz bng
+  parseUnqt = uncurry Point
+                <$> commaSepUnqt
+                <*> optional (parseComma *> parseUnqt)
+                <*> (isJust <$> optional (character '!'))
 
   parse = quotedParse parseUnqt
 
@@ -2017,7 +2082,7 @@
   parseUnqt = oneOf [ stringRep KeepOverlaps "true"
                     , stringRep ScaleXYOverlaps "scalexy"
                     , stringRep ScaleOverlaps "scale"
-                    , string "prism" >> liftM PrismOverlap (optional parse)
+                    , string "prism" *> fmap PrismOverlap (optional parse)
                     , stringRep (PrismOverlap Nothing) "false"
                     , stringRep CompressOverlap "compress"
                     , stringRep VpscOverlap "vpsc"
@@ -2030,11 +2095,9 @@
                  deriving (Eq, Ord, Show, Read)
 
 instance PrintDot LayerSep where
-  unqtDot (LSep ls) = do setLayerSep $ T.unpack ls
-                         unqtDot ls
+  unqtDot (LSep ls) = setLayerSep (T.unpack ls) *> unqtDot ls
 
-  toDot (LSep ls) = do setLayerSep $ T.unpack ls
-                       toDot ls
+  toDot (LSep ls) = setLayerSep (T.unpack ls) *> toDot ls
 
 instance ParseDot LayerSep where
   parseUnqt = do ls <- parseUnqt
@@ -2059,26 +2122,18 @@
   toDot lrs        = dquotes $ unqtDot lrs
 
 instance ParseDot LayerRange where
-  parseUnqt = do id1 <- parseUnqt
-                 _   <- parseLayerSep
-                 id2 <- parseUnqt
-                 return $ LRS id1 id2
+  parseUnqt = ignoreSep LRS parseUnqt parseLayerSep parseUnqt
               `onFail`
-              liftM LRID parseUnqt
+              fmap LRID parseUnqt
 
 
-  parse = quotedParse ( do id1 <- parseUnqt
-                           _   <- parseLayerSep
-                           id2 <- parseUnqt
-                           return $ LRS id1 id2
-                      )
+  parse = quotedParse (ignoreSep LRS parseUnqt parseLayerSep parseUnqt)
           `onFail`
-          liftM LRID parse
+          fmap LRID parse
 
 parseLayerSep :: Parse ()
 parseLayerSep = do ls <- getLayerSep
-                   many1Satisfy (`elem` ls)
-                   return ()
+                   many1Satisfy (`elem` ls) *> return ()
 
 parseLayerName :: Parse Text
 parseLayerName = parseEscaped False [] =<< getLayerSep
@@ -2114,10 +2169,10 @@
   listToDot ll  = dquotes $ unqtDot ll
 
 instance ParseDot LayerID where
-  parseUnqt = liftM checkLayerName parseLayerName -- tests for Int and All
+  parseUnqt = checkLayerName <$> parseLayerName -- tests for Int and All
 
-  parse = oneOf [ liftM checkLayerName parseLayerName'
-                , liftM LRInt parse -- Mainly for unquoted case.
+  parse = oneOf [ checkLayerName <$> parseLayerName'
+                , LRInt <$> parse -- Mainly for unquoted case.
                 ]
 
 checkLayerName     :: Text -> LayerID
@@ -2139,11 +2194,11 @@
   toDot (LL ll) = toDot ll
 
 instance ParseDot LayerList where
-  parseUnqt = liftM LL $ sepBy1 parseUnqt parseLayerSep
+  parseUnqt = LL <$> sepBy1 parseUnqt parseLayerSep
 
   parse = quotedParse parseUnqt
           `onFail`
-          liftM (LL . (:[]) . LRName) stringBlock
+          fmap (LL . (:[]) . LRName) stringBlock
           `onFail`
           quotedParse (stringRep (LL []) "")
 
@@ -2192,8 +2247,8 @@
 
 instance ParseDot Pack where
   -- What happens if it parses 0?  It's non-negative, but parses as False
-  parseUnqt = oneOf [ liftM PackMargin parseUnqt
-                    , liftM (bool DontPack DoPack) onlyBool
+  parseUnqt = oneOf [ PackMargin <$> parseUnqt
+                    , bool DontPack DoPack <$> onlyBool
                     ]
 
 -- -----------------------------------------------------------------------------
@@ -2229,8 +2284,7 @@
                     , stringRep PackClust "clust"
                     , stringRep PackGraph "graph"
                     , do string "array"
-                         mcu <- optional $ do character '_'
-                                              many1 $ satisfy isCU
+                         mcu <- optional $ character '_' *> many1 (satisfy isCU)
                          let c = hasCharacter mcu 'c'
                              u = hasCharacter mcu 'u'
                          mi <- optional parseUnqt
@@ -2288,7 +2342,7 @@
 
 instance ParseDot EdgeType where
   -- Can't parse NoEdges without quotes.
-  parseUnqt = oneOf [ liftM (bool LineEdges SplineEdges) parse
+  parseUnqt = oneOf [ bool LineEdges SplineEdges <$> parse
                     , stringRep SplineEdges "spline"
                     , stringRep LineEdges "line"
                     , stringRep PolyLine "polyline"
@@ -2331,11 +2385,14 @@
 
 -- | The number of points in the list must be equivalent to 1 mod 3;
 --   note that this is not checked.
-data Spline = Spline (Maybe Point) (Maybe Point) [Point]
+data Spline = Spline { endPoint     :: Maybe Point
+                     , startPoint   :: Maybe Point
+                     , splinePoints :: [Point]
+                     }
             deriving (Eq, Ord, Show, Read)
 
 instance PrintDot Spline where
-  unqtDot (Spline ms me ps) = addS . addE
+  unqtDot (Spline me ms ps) = addE . addS
                              . hsep
                              $ mapM unqtDot ps
     where
@@ -2350,14 +2407,10 @@
   listToDot = dquotes . unqtListToDot
 
 instance ParseDot Spline where
-  parseUnqt = do ms <- parseP 's'
-                 me <- parseP 'e'
-                 ps <- sepBy1 parseUnqt whitespace1
-                 return $ Spline ms me ps
+  parseUnqt = Spline <$> parseP 'e' <*> parseP 's'
+                     <*> sepBy1 parseUnqt whitespace1
       where
-        parseP t = optional $ do character t
-                                 parseComma
-                                 parseUnqt `discard` whitespace1
+        parseP t = optional (character t *> parseComma *> parseUnqt <* whitespace1)
 
   parse = quotedParse parseUnqt
 
@@ -2381,8 +2434,8 @@
   parseUnqt = oneOf [ stringRep NormalQT "normal"
                     , stringRep FastQT "fast"
                     , stringRep NoQT "none"
-                    , character '2'   >> return FastQT -- weird bool
-                    , liftM (bool NoQT NormalQT) parse
+                    , character '2' *> return FastQT -- weird bool
+                    , bool NoQT NormalQT <$> parse
                     ]
 
 -- -----------------------------------------------------------------------------
@@ -2402,13 +2455,13 @@
   toDot r            = unqtDot r
 
 instance ParseDot Root where
-  parseUnqt = liftM (bool NotCentral IsCentral) onlyBool
+  parseUnqt = fmap (bool NotCentral IsCentral) onlyBool
               `onFail`
-              liftM NodeName parseUnqt
+              fmap NodeName parseUnqt
 
-  parse = optionalQuoted (liftM (bool NotCentral IsCentral) onlyBool)
+  parse = optionalQuoted (bool NotCentral IsCentral <$> onlyBool)
           `onFail`
-          liftM NodeName parse
+          fmap NodeName parse
 
 -- -----------------------------------------------------------------------------
 
@@ -2460,7 +2513,7 @@
 data Shape
     = BoxShape -- ^ Has synonyms of /rect/ and /rectangle/.
     | Polygon
-    | Ellipse
+    | Ellipse  -- ^ Has synonym of /oval/.
     | Circle
     | PointShape
     | Egg
@@ -2488,43 +2541,83 @@
     | Folder
     | Box3D
     | Component
+    | Promoter
+    | CDS
+    | Terminator
+    | UTR
+    | PrimerSite
+    | RestrictionSite
+    | FivePovOverhang
+    | ThreePovOverhang
+    | NoOverhang
+    | Assembly
+    | Signature
+    | Insulator
+    | Ribosite
+    | RNAStab
+    | ProteaseSite
+    | ProteinStab
+    | RPromoter
+    | RArrow
+    | LArrow
+    | LPromoter
     | Record -- ^ Must specify the record shape with a 'Label'.
     | MRecord -- ^ Must specify the record shape with a 'Label'.
     deriving (Eq, Ord, Bounded, Enum, Show, Read)
 
 instance PrintDot Shape where
-  unqtDot BoxShape      = text "box"
-  unqtDot Polygon       = text "polygon"
-  unqtDot Ellipse       = text "ellipse"
-  unqtDot Circle        = text "circle"
-  unqtDot PointShape    = text "point"
-  unqtDot Egg           = text "egg"
-  unqtDot Triangle      = text "triangle"
-  unqtDot PlainText     = text "plaintext"
-  unqtDot DiamondShape  = text "diamond"
-  unqtDot Trapezium     = text "trapezium"
-  unqtDot Parallelogram = text "parallelogram"
-  unqtDot House         = text "house"
-  unqtDot Pentagon      = text "pentagon"
-  unqtDot Hexagon       = text "hexagon"
-  unqtDot Septagon      = text "septagon"
-  unqtDot Octagon       = text "octagon"
-  unqtDot DoubleCircle  = text "doublecircle"
-  unqtDot DoubleOctagon = text "doubleoctagon"
-  unqtDot TripleOctagon = text "tripleoctagon"
-  unqtDot InvTriangle   = text "invtriangle"
-  unqtDot InvTrapezium  = text "invtrapezium"
-  unqtDot InvHouse      = text "invhouse"
-  unqtDot MDiamond      = text "Mdiamond"
-  unqtDot MSquare       = text "Msquare"
-  unqtDot MCircle       = text "Mcircle"
-  unqtDot Note          = text "note"
-  unqtDot Tab           = text "tab"
-  unqtDot Folder        = text "folder"
-  unqtDot Box3D         = text "box3d"
-  unqtDot Component     = text "component"
-  unqtDot Record        = text "record"
-  unqtDot MRecord       = text "Mrecord"
+  unqtDot BoxShape         = text "box"
+  unqtDot Polygon          = text "polygon"
+  unqtDot Ellipse          = text "ellipse"
+  unqtDot Circle           = text "circle"
+  unqtDot PointShape       = text "point"
+  unqtDot Egg              = text "egg"
+  unqtDot Triangle         = text "triangle"
+  unqtDot PlainText        = text "plaintext"
+  unqtDot DiamondShape     = text "diamond"
+  unqtDot Trapezium        = text "trapezium"
+  unqtDot Parallelogram    = text "parallelogram"
+  unqtDot House            = text "house"
+  unqtDot Pentagon         = text "pentagon"
+  unqtDot Hexagon          = text "hexagon"
+  unqtDot Septagon         = text "septagon"
+  unqtDot Octagon          = text "octagon"
+  unqtDot DoubleCircle     = text "doublecircle"
+  unqtDot DoubleOctagon    = text "doubleoctagon"
+  unqtDot TripleOctagon    = text "tripleoctagon"
+  unqtDot InvTriangle      = text "invtriangle"
+  unqtDot InvTrapezium     = text "invtrapezium"
+  unqtDot InvHouse         = text "invhouse"
+  unqtDot MDiamond         = text "Mdiamond"
+  unqtDot MSquare          = text "Msquare"
+  unqtDot MCircle          = text "Mcircle"
+  unqtDot Note             = text "note"
+  unqtDot Tab              = text "tab"
+  unqtDot Folder           = text "folder"
+  unqtDot Box3D            = text "box3d"
+  unqtDot Component        = text "component"
+  unqtDot Promoter         = text "promoter"
+  unqtDot CDS              = text "cds"
+  unqtDot Terminator       = text "terminator"
+  unqtDot UTR              = text "utr"
+  unqtDot PrimerSite       = text "primersite"
+  unqtDot RestrictionSite  = text "restrictionsite"
+  unqtDot FivePovOverhang  = text "fivepovoverhang"
+  unqtDot ThreePovOverhang = text "threepovoverhang"
+  unqtDot NoOverhang       = text "nooverhang"
+  unqtDot Assembly         = text "assembly"
+  unqtDot Signature        = text "signature"
+  unqtDot Insulator        = text "insulator"
+  unqtDot Ribosite         = text "ribosite"
+  unqtDot RNAStab          = text "rnastab"
+  unqtDot ProteaseSite     = text "proteasesite"
+  unqtDot ProteinStab      = text "proteinstab"
+  unqtDot RPromoter        = text "rpromoter"
+  unqtDot RArrow           = text "rarrow"
+  unqtDot LArrow           = text "larrow"
+  unqtDot LPromoter        = text "lpromoter"
+  unqtDot Record           = text "record"
+  unqtDot MRecord          = text "Mrecord"
 
 instance ParseDot Shape where
   parseUnqt = stringValue [ ("box3d", Box3D)
@@ -2533,6 +2626,7 @@
                           , ("rect", BoxShape)
                           , ("polygon", Polygon)
                           , ("ellipse", Ellipse)
+                          , ("oval", Ellipse)
                           , ("circle", Circle)
                           , ("point", PointShape)
                           , ("egg", Egg)
@@ -2560,6 +2654,26 @@
                           , ("tab", Tab)
                           , ("folder", Folder)
                           , ("component", Component)
+                          , ("promoter", Promoter)
+                          , ("cds", CDS)
+                          , ("terminator", Terminator)
+                          , ("utr", UTR)
+                          , ("primersite", PrimerSite)
+                          , ("restrictionsite", RestrictionSite)
+                          , ("fivepovoverhang", FivePovOverhang)
+                          , ("threepovoverhang", ThreePovOverhang)
+                          , ("nooverhang", NoOverhang)
+                          , ("assembly", Assembly)
+                          , ("signature", Signature)
+                          , ("insulator", Insulator)
+                          , ("ribosite", Ribosite)
+                          , ("rnastab", RNAStab)
+                          , ("proteasesite", ProteaseSite)
+                          , ("proteinstab", ProteinStab)
+                          , ("rpromoter", RPromoter)
+                          , ("rarrow", RArrow)
+                          , ("larrow", LArrow)
+                          , ("lpromoter", LPromoter)
                           , ("record", Record)
                           , ("Mrecord", MRecord)
                           ]
@@ -2607,11 +2721,9 @@
   unqtDot (StartStyleSeed ss s) = unqtDot ss <> unqtDot s
 
 instance ParseDot StartType where
-  parseUnqt = oneOf [ do ss <- parseUnqt
-                         s  <- parseUnqt
-                         return $ StartStyleSeed ss s
-                    , liftM StartStyle parseUnqt
-                    , liftM StartSeed parseUnqt
+  parseUnqt = oneOf [ liftA2 StartStyleSeed parseUnqt parseUnqt
+                    , StartStyle <$> parseUnqt
+                    , StartSeed <$> parseUnqt
                     ]
 
 data STStyle = RegularStyle
@@ -2655,20 +2767,18 @@
   listToDot sis           = dquotes $ unqtListToDot sis
 
 instance ParseDot StyleItem where
-  parseUnqt = do nm <- parseUnqt
-                 args <- tryParseList' parseArgs
-                 return $ SItem nm args
+  parseUnqt = liftA2 SItem parseUnqt (tryParseList' parseArgs)
 
-  parse = quotedParse (liftM2 SItem parseUnqt parseArgs)
+  parse = quotedParse (liftA2 SItem parseUnqt parseArgs)
           `onFail`
-          liftM (flip SItem []) parse
+          fmap (flip SItem []) parse
 
   parseUnqtList = sepBy1 parseUnqt parseComma
 
   parseList = quotedParse parseUnqtList
               `onFail`
               -- Might not necessarily need to be quoted if a singleton...
-              liftM return parse
+              fmap return parse
 
 parseArgs :: Parse [Text]
 parseArgs = bracketSep (character '(')
@@ -2709,11 +2819,11 @@
   toDot sn      = unqtDot sn
 
 instance ParseDot StyleName where
-  parseUnqt = liftM checkDD parseStyleName
+  parseUnqt = checkDD <$> parseStyleName
 
   parse = quotedParse parseUnqt
           `onFail`
-          liftM checkDD quotelessString
+          fmap checkDD quotelessString
 
 checkDD     :: Text -> StyleName
 checkDD str = case T.toLower str of
@@ -2730,9 +2840,8 @@
                 _           -> DD str
 
 parseStyleName :: Parse Text
-parseStyleName = do f <- orEscaped . noneOf $ ' ' : disallowedChars
-                    r <- parseEscaped True [] disallowedChars
-                    return $ f `T.cons` r
+parseStyleName = liftA2 T.cons (orEscaped . noneOf $ ' ' : disallowedChars)
+                               (parseEscaped True [] disallowedChars)
   where
     disallowedChars = [quoteChar, '(', ')', ',']
     -- Used because the first character has slightly stricter requirements than the rest.
@@ -2758,13 +2867,12 @@
   toDot = dquotes . unqtDot
 
 instance ParseDot ViewPort where
-  parseUnqt = do wv <- parseUnqt
-                 parseComma
-                 hv <- parseUnqt
-                 parseComma
-                 zv <- parseUnqt
-                 mf <- optional $ parseComma >> parseUnqt
-                 return $ VP wv hv zv mf
+  parseUnqt = VP <$> parseUnqt
+                 <*  parseComma
+                 <*> parseUnqt
+                 <*  parseComma
+                 <*> parseUnqt
+                 <*> optional (parseComma *> parseUnqt)
 
   parse = quotedParse parseUnqt
 
@@ -2781,13 +2889,13 @@
   toDot (NodeFocus nm) = toDot nm
 
 instance ParseDot FocusType where
-  parseUnqt = liftM XY parseUnqt
+  parseUnqt = fmap XY parseUnqt
               `onFail`
-              liftM NodeFocus parseUnqt
+              fmap NodeFocus parseUnqt
 
-  parse = liftM XY parse
+  parse = fmap XY parse
           `onFail`
-          liftM NodeFocus parse
+          fmap NodeFocus parse
 
 -- -----------------------------------------------------------------------------
 
@@ -2819,11 +2927,11 @@
     toDot ps          = dquotes $ unqtDot ps
 
 instance ParseDot Paths where
-    parseUnqt = liftM (Paths . splitSearchPath) parseUnqt
+    parseUnqt = Paths . splitSearchPath <$> parseUnqt
 
     parse = quotedParse parseUnqt
             `onFail`
-            liftM (Paths . (:[]) . T.unpack) quotelessString
+            fmap (Paths . (:[]) . T.unpack) quotelessString
 
 -- -----------------------------------------------------------------------------
 
@@ -2884,7 +2992,7 @@
   unqtDot AutoRatio       = text "auto"
 
 instance ParseDot Ratios where
-  parseUnqt = oneOf [ liftM AspectRatio parseUnqt
+  parseUnqt = oneOf [ AspectRatio <$> parseUnqt
                     , stringRep FillRatio "fill"
                     , stringRep CompressRatio "compress"
                     , stringRep ExpandRatio "expand"
diff --git a/Data/GraphViz/Attributes/HTML.hs b/Data/GraphViz/Attributes/HTML.hs
--- a/Data/GraphViz/Attributes/HTML.hs
+++ b/Data/GraphViz/Attributes/HTML.hs
@@ -81,7 +81,6 @@
 import Data.Word(Word8, Word16)
 import qualified Data.Map as Map
 import qualified Data.Text.Lazy as T
-import Control.Monad(liftM, liftM2)
 
 -- -----------------------------------------------------------------------------
 
@@ -99,9 +98,9 @@
 
 instance ParseDot Label where
   -- Try parsing Table first in case of a FONT tag being used.
-  parseUnqt = liftM Table parseUnqt
+  parseUnqt = fmap Table parseUnqt
               `onFail`
-              liftM Text parseUnqt
+              fmap Text parseUnqt
               `adjustErr`
               ("Can't parse Html.Label\n\t"++)
 
@@ -140,7 +139,7 @@
   listToDot = unqtListToDot
 
 instance ParseDot TextItem where
-  parseUnqt = oneOf [ liftM Str unescapeValue
+  parseUnqt = oneOf [ fmap Str unescapeValue
                     , parseEmptyTag Newline "BR"
                     , parseFontTag Font parseUnqt
                     , parseTagRep Format parseUnqt parseUnqt
@@ -150,7 +149,7 @@
 
   parse = parseUnqt
 
-  parseUnqtList = many1 parseUnqt -- sepBy1 parseUnqt whitespace
+  parseUnqtList = many parseUnqt
 
   parseList = parseUnqtList
 
@@ -381,7 +380,7 @@
                     , parseHtmlField' (Port . PN) "PORT" unescapeAttribute
                     , parseHtmlField  RowSpan "ROWSPAN"
                     , parseHtmlField  Scale "SCALE"
-                    , parseHtmlField' Src "SRC" $ liftM T.unpack unescapeAttribute
+                    , parseHtmlField' Src "SRC" $ fmap T.unpack unescapeAttribute
                     , parseHtmlField' Target "TARGET" unescapeAttribute
                     , parseHtmlField' Title "TITLE" unescapeAttribute
                       `onFail`
@@ -404,9 +403,15 @@
 
 parseHtmlField'       :: (a -> Attribute) -> String -> Parse a
                      -> Parse Attribute
-parseHtmlField' c f p = do string f
-                           parseEq
-                           liftM c $ quotedParse p
+parseHtmlField' c f p = string f
+                        *> parseEq
+                        *> ( c <$> ( quotedParse p
+                                      `adjustErr`
+                                      (("Can't parse HTML.Attribute." ++ f ++ "\n\t")++)
+                                   )
+                           )
+-- Can't use liftEqParse, etc. here because it causes backtracking
+-- problems when the attributes could apply to multiple constructors.
 
 -- | Specifies horizontal placement. When an object is allocated more
 --   space than required, this value determines where the extra space
@@ -460,11 +465,11 @@
 --   cell.  If undefined, the image inherits the value of the
 --   @ImageScale@ attribute.
 data Scale = NaturalSize -- ^ Default value.
-               | ScaleUniformly
-               | ExpandWidth
-               | ExpandHeight
-               | ExpandBoth
-               deriving (Eq, Ord, Bounded, Enum, Show, Read)
+           | ScaleUniformly
+           | ExpandWidth
+           | ExpandHeight
+           | ExpandBoth
+           deriving (Eq, Ord, Bounded, Enum, Show, Read)
 
 instance PrintDot Scale where
   unqtDot NaturalSize    = text "FALSE"
@@ -492,14 +497,14 @@
 escapeValue = escapeHtml True
 
 escapeHtml               :: Bool -> T.Text -> DotCode
-escapeHtml quotesAllowed = hcat . liftM concat
+escapeHtml quotesAllowed = hcat . fmap concat
                            . mapM (escapeSegment . T.unpack)
                            . T.groupBy ((==) `on` isSpace)
   where
     -- Note: use numeric version of space rather than nbsp, since this
     -- matches what Graphviz does (since Inkscape apparently can't
     -- cope with nbsp).
-    escapeSegment (s:sps) | isSpace s = liftM2 (:) (char s) $ mapM numEscape sps
+    escapeSegment (s:sps) | isSpace s = liftA2 (:) (char s) $ mapM numEscape sps
     escapeSegment txt                 = mapM xmlChar txt
 
     allowQuotes = if quotesAllowed
@@ -523,7 +528,7 @@
 --   Note: this /will/ fail if an unknown non-numeric HTML-escape is
 --   used.
 unescapeHtml               :: Bool -> Parse T.Text
-unescapeHtml quotesAllowed = liftM (T.pack . catMaybes)
+unescapeHtml quotesAllowed = fmap (T.pack . catMaybes)
                              . many1 . oneOf $ [ parseEscpd
                                                , validChars
                                                ]
@@ -551,7 +556,7 @@
 
     escMap = Map.fromList htmlUnescapes
 
-    validChars = liftM Just $ satisfy (`notElem` needEscaping)
+    validChars = fmap Just $ satisfy (`notElem` needEscaping)
     needEscaping = allowQuotes $ map fst htmlEscapes
 
 -- | The characters that need to be escaped and what they need to be
@@ -610,32 +615,38 @@
 -- | Parse something like @<FOO ATTR=\"ATTR_VALUE\">value<\/FOO>@
 parseTag        :: (Attributes -> val -> tag) -> String
                        -> Parse val -> Parse tag
-parseTag c t pv = do as <- parseAngled openingTag
-                     v <- pv
-                     parseAngled $ character '/' >> t' >> whitespace
-                     return $ c as v
+parseTag c t pv = c <$> parseAngled openingTag
+                    <*> pv
+                    <* parseAngled (character '/' *> t' *> whitespace)
+                  `adjustErr`
+                  (("Can't parse Html tag: " ++ t ++ "\n\t")++)
   where
     t' = string t
-    openingTag = do t'
-                    as <- tryParseList' $ whitespace1 >> parse
-                    whitespace
-                    return as
-
-parseTagRep :: (tagName -> val -> tag) -> Parse tagName -> Parse val -> Parse tag
-parseTagRep c pt pv = do tn <- parseAngled (pt `discard` whitespace)
-                         v <- pv
-                         parseAngled $ character '/' >> pt >> whitespace
-                         return $ c tn v
+    openingTag :: Parse Attributes
+    openingTag = t'
+                 *> tryParseList' (whitespace1 >> parse)
+                 <* whitespace
 
 parseFontTag :: (Attributes -> val -> tag) -> Parse val -> Parse tag
 parseFontTag = flip parseTag "FONT"
 
+-- Should this just be specialised for tagName ~ Format ?
+
+-- | Parse something like @<FOO>value<\/FOO>@.
+parseTagRep :: (tagName -> val -> tag) -> Parse tagName -> Parse val -> Parse tag
+parseTagRep c pt pv = c <$> parseAngled (pt `discard` whitespace)
+                        <*> pv
+                        <* parseAngled (character '/' *> pt *> whitespace)
+                    `adjustErr`
+                    ("Can't parse attribute-less Html tag\n\t"++)
+
 -- | Parse something like @<FOO ATTR=\"ATTR_VALUE\"\/>@
 parseEmptyTag     :: (Attributes -> tag) -> String -> Parse tag
-parseEmptyTag c t = parseAngled
-                        ( do string t
-                             as <- tryParseList' $ whitespace1 >> parse
-                             whitespace
-                             character '/'
-                             return $ c as
+parseEmptyTag c t = c <$> parseAngled
+                        ( string t
+                          *> tryParseList' (whitespace1 *> parse)
+                          <* whitespace
+                          <* character '/'
                         )
+                    `adjustErr`
+                    (("Can't parse empty Html tag: " ++ t ++ "\n\t")++)
diff --git a/Data/GraphViz/Attributes/Internal.hs b/Data/GraphViz/Attributes/Internal.hs
--- a/Data/GraphViz/Attributes/Internal.hs
+++ b/Data/GraphViz/Attributes/Internal.hs
@@ -28,7 +28,6 @@
 import qualified Data.Map as Map
 import Data.Map(Map)
 import Data.Text.Lazy(Text)
-import Control.Monad(liftM, liftM2)
 
 -- -----------------------------------------------------------------------------
 
@@ -52,15 +51,14 @@
   toDot = toDot . portName
 
 instance ParseDot PortName where
-  parseUnqt = liftM PN
-              $ parseEscaped False [] ['"', ':']
+  parseUnqt = PN <$> parseEscaped False [] ['"', ':']
 
   parse = quotedParse parseUnqt
           `onFail`
           unqtPortName
 
 unqtPortName :: Parse PortName
-unqtPortName = liftM PN quotelessString
+unqtPortName = PN <$> quotelessString
 
 -- -----------------------------------------------------------------------------
 
@@ -86,7 +84,7 @@
 
   parse = quotedParse parseUnqt
           `onFail`
-          liftM checkPortName unqtPortName
+          fmap checkPortName unqtPortName
 
 checkPortName    :: PortName -> PortPos
 checkPortName pn = maybe (LabelledPort pn Nothing) CompassPoint
@@ -96,7 +94,7 @@
 -- | When attached to a node in a DotEdge definition, the 'PortName'
 --   and the 'CompassPoint' can be in separate quotes.
 parseEdgeBasedPP :: Parse PortPos
-parseEdgeBasedPP = liftM2 LabelledPort parse (liftM Just $ character ':' >> parse)
+parseEdgeBasedPP = liftA2 LabelledPort parse (fmap Just $ character ':' *> parse)
                    `onFail`
                    parse
 
diff --git a/Data/GraphViz/Commands.hs b/Data/GraphViz/Commands.hs
--- a/Data/GraphViz/Commands.hs
+++ b/Data/GraphViz/Commands.hs
@@ -45,9 +45,6 @@
     , quitWithoutGraphviz
     ) where
 
--- Want to use the extensible-exception version
-import Prelude hiding (catch)
-
 import Data.GraphViz.Types
 -- This is here just for Haddock linking purposes.
 import Data.GraphViz.Attributes.Complete(Attribute(Z))
diff --git a/Data/GraphViz/Parsing.hs b/Data/GraphViz/Parsing.hs
--- a/Data/GraphViz/Parsing.hs
+++ b/Data/GraphViz/Parsing.hs
@@ -33,6 +33,7 @@
     , checkValidParse
       -- * Convenience parsing combinators.
     , bracket
+    , ignoreSep
     , onlyBool
     , quotelessString
     , stringBlock
@@ -68,6 +69,9 @@
     , parseFieldsBool
     , parseFieldDef
     , parseFieldsDef
+    , parseFieldNumDef
+    , liftEqParse
+    , liftEqParse'
     , commaSep
     , commaSepUnqt
     , commaSep'
@@ -96,7 +100,7 @@
                 )
 import Data.List(groupBy, sortBy)
 import Data.Function(on)
-import Data.Maybe(fromMaybe, isNothing, listToMaybe)
+import Data.Maybe(fromMaybe, isJust, isNothing, listToMaybe)
 import Data.Ratio((%))
 import qualified Data.Set as Set
 import qualified Data.Text.Lazy as T
@@ -104,7 +108,7 @@
 import Data.Text.Lazy(Text)
 import Data.Word(Word8, Word16)
 import Control.Arrow(first, second)
-import Control.Monad(liftM, liftM2, when)
+import Control.Monad(when)
 
 -- -----------------------------------------------------------------------------
 -- Based off code from Text.Parse in the polyparse library
@@ -122,7 +126,7 @@
 runParser'   :: Parse a -> Text -> a
 runParser' p = checkValidParse . fst . runParser p'
   where
-    p' = p `discard` (whitespace >> eof)
+    p' = p `discard` (whitespace *> eof)
 
 class ParseDot a where
   parseUnqt :: Parse a
@@ -136,7 +140,7 @@
                                `onFail`
                                whitespace1
                              )
-                             (whitespace >> character ']')
+                             (whitespace *> character ']')
                              parseUnqt
 
   parseList :: Parse [a]
@@ -177,12 +181,12 @@
 
   parseList = quotedParse parseUnqtList
               `onFail`
-              liftM return parse
+              fmap (:[]) parse
 
 instance ParseDot Bool where
   parseUnqt = onlyBool
               `onFail`
-              liftM (zero /=) parseInt'
+              fmap (zero /=) parseInt'
     where
       zero :: Int
       zero = 0
@@ -201,9 +205,9 @@
           `onFail`
           quotedParse parseUnqt
 
-  parseUnqtList = liftM T.unpack parseUnqt
+  parseUnqtList = T.unpack <$> parseUnqt
 
-  parseList = liftM T.unpack parse
+  parseList = T.unpack <$> parse
 
 instance ParseDot Text where
   -- Too many problems with using this within other parsers where
@@ -227,34 +231,38 @@
 quotelessString = numString `onFail` stringBlock
 
 numString :: Parse Text
-numString = liftM tShow parseStrictFloat
+numString = fmap tShow parseStrictFloat
             `onFail`
-            liftM tShow parseInt'
+            fmap tShow parseInt'
   where
     tShow :: (Show a) => a -> Text
     tShow = T.pack . show
 
 stringBlock :: Parse Text
-stringBlock = do frst <- satisfy frstIDString
-                 rest <- manySatisfy restIDString
-                 return $ frst `T.cons` rest
+stringBlock = liftA2 T.cons (satisfy frstIDString) (manySatisfy restIDString)
 
 -- | Used when quotes are explicitly required;
 quotedString :: Parse Text
 quotedString = parseEscaped True [] []
 
 parseSigned :: (Num a) => Parse a -> Parse a
-parseSigned p = (character '-' >> liftM negate p)
+parseSigned p = (character '-' *> fmap negate p)
                 `onFail`
                 p
 
 parseInt :: (Integral a) => Parse a
 parseInt = do cs <- many1Satisfy isDigit
+                    `adjustErr` ("Expected one or more digits\n\t"++)
               case T.decimal cs of
-                Right (n,"")  -> return n
+                Right (n,"")  -> checkInt n
+                -- This case should never actually happen...
                 Right (_,txt) -> fail $ "Trailing digits not parsed as Integral: " ++ T.unpack txt
                 Left err      -> fail $ "Could not read Integral: " ++ err
-           `adjustErr` ("Expected one or more digits\n\t"++)
+  where
+    checkInt n = do c <- optional $ oneOf [ character '.', character 'e' ]
+                    if isJust c
+                      then fail "This number is actually Floating, not Integral!"
+                      else return n
 
 parseInt' :: Parse Int
 parseInt' = parseSigned parseInt
@@ -265,9 +273,7 @@
 
 parseFloat :: (RealFrac a) => Parse a
 parseFloat = do ds   <- manySatisfy isDigit
-                frac <- optional
-                        $ do character '.'
-                             manySatisfy isDigit
+                frac <- optional $ character '.' *> manySatisfy isDigit
                 when (T.null ds && noDec frac)
                   (fail "No actual digits in floating point number!")
                 expn  <- optional parseExp
@@ -280,8 +286,8 @@
              `onFail`
              fail "Expected a floating point number"
   where
-    parseExp = do character 'e'
-                  ((character '+' >> parseInt)
+    parseExp = character 'e'
+               *> ((character '+' *> parseInt)
                    `onFail`
                    parseInt')
     noDec = maybe True T.null
@@ -289,7 +295,7 @@
 parseFloat' :: Parse Double
 parseFloat' = parseSigned ( parseFloat
                             `onFail`
-                            liftM fI parseInt
+                            fmap fI parseInt
                           )
   where
     fI :: Integer -> Double
@@ -303,10 +309,9 @@
 --   'adjustErrBad' and thus doesn't allow backtracking and trying the
 --   next possible parser.  This is a version of @bracket@ that does.
 bracket               :: Parse bra -> Parse ket -> Parse a -> Parse a
-bracket open close pa = do open `adjustErr` ("Missing opening bracket:\n\t"++)
-                           pa `discard`
-                             (close
-                              `adjustErr` ("Missing closing bracket:\n\t"++))
+bracket open close pa = (open `adjustErr` ("Missing opening bracket:\n\t"++))
+                        *> pa
+                        <* (close `adjustErr` ("Was expecting closing bracket:\n\t"++))
 
 parseAndSpace   :: Parse a -> Parse a
 parseAndSpace p = p `discard` whitespace
@@ -318,7 +323,7 @@
 stringRep v = stringReps v . return
 
 stringReps      :: a -> [String] -> Parse a
-stringReps v ss = oneOf (map string ss) >> return v
+stringReps v ss = oneOf (map string ss) *> return v
 
 stringParse :: [(String, Parse a)] -> Parse a
 stringParse = toPM . sortBy (flip compare `on` fst)
@@ -326,8 +331,8 @@
     toPM = oneOf . map mkPM . groupBy ((==) `on` (listToMaybe . fst))
 
     mkPM [("",p)] = p
-    mkPM [(str,p)] = string str >> p
-    mkPM kv = character (head . fst $ head kv) >> toPM (map (first tail) kv)
+    mkPM [(str,p)] = string str *> p
+    mkPM kv = character (head . fst $ head kv) *> toPM (map (first tail) kv)
 
 stringValue :: [(String, a)] -> Parse a
 stringValue = stringParse . map (second return)
@@ -350,13 +355,13 @@
 
 -- | Parses at least one whitespace character.
 whitespace1 :: Parse ()
-whitespace1 = many1Satisfy isSpace >> return ()
+whitespace1 = many1Satisfy isSpace *> return ()
 
 -- | Parses zero or more whitespace characters.
 whitespace :: Parse ()
-whitespace = manySatisfy isSpace >> return ()
+whitespace = manySatisfy isSpace *> return ()
 
--- | Parse and discard optional whitespace.
+-- | Parse and discard optional surrounding whitespace.
 wrapWhitespace :: Parse a -> Parse a
 wrapWhitespace = bracket whitespace whitespace
 
@@ -371,8 +376,8 @@
 quotedParse :: Parse a -> Parse a
 quotedParse = bracket parseQuote parseQuote
 
-parseQuote :: Parse Char
-parseQuote = character quoteChar
+parseQuote :: Parse ()
+parseQuote = character quoteChar *> return ()
 
 orQuote   :: Parse Char -> Parse Char
 orQuote p = stringRep quoteChar "\\\""
@@ -388,7 +393,7 @@
 --   'Bool' value indicates whether empty 'String's are allowed or
 --   not.
 parseEscaped             :: Bool -> [Char] -> [Char] -> Parse Text
-parseEscaped empt cs bnd = liftM T.pack . lots $ qPrs `onFail` oth
+parseEscaped empt cs bnd = fmap T.pack . lots $ qPrs `onFail` oth
   where
     lots = if empt then many else many1
     cs' = quoteChar : slash : cs
@@ -396,9 +401,10 @@
     bndSet = Set.fromList bnd `Set.union` csSet
     slash = '\\'
     -- Have to allow standard slashes
-    qPrs = do character slash
-              mE <- optional $ oneOf (map character cs')
-              return $ fromMaybe slash mE
+    qPrs = fromMaybe slash
+           <$> (character slash
+                *> optional (oneOf $ map character cs')
+               )
     oth = satisfy (`Set.notMember` bndSet)
 
 -- | Parses a newline.
@@ -409,7 +415,7 @@
 --   non-whitespace is reached.  The whitespace on that line is
 --   not consumed.
 newline' :: Parse ()
-newline' = many (whitespace >> newline) >> return ()
+newline' = many (whitespace *> newline) *> return ()
 
 -- | Parses and returns all characters up till the end of the line,
 --   but does not touch the newline characters.
@@ -417,10 +423,10 @@
 consumeLine = manySatisfy (`notElem` ['\n','\r'])
 
 parseEq :: Parse ()
-parseEq = wrapWhitespace (character '=') >> return ()
+parseEq = wrapWhitespace (character '=') *> return ()
 
 parseField       :: (ParseDot a) => (a -> b) -> String -> [(String, Parse b)]
-parseField c fld = [(fld, parseEq >> liftM c parse)]
+parseField c fld = [(fld, liftEqParse' fld c)]
 
 parseFields   :: (ParseDot a) => (a -> b) -> [String] -> [(String, Parse b)]
 parseFields c = concatMap (parseField c)
@@ -436,7 +442,7 @@
 parseFieldDef         :: (ParseDot a) => (a -> b) -> a -> String -> [(String, Parse b)]
 parseFieldDef c d fld = [(fld, p)]
   where
-    p = (parseEq >> liftM c parse)
+    p = liftEqParse' fld c
         `onFail`
         do nxt <- optional $ satisfy restIDString
            bool (fail "Not actually the field you were after")
@@ -446,6 +452,34 @@
 parseFieldsDef     :: (ParseDot a) => (a -> b) -> a -> [String] -> [(String, Parse b)]
 parseFieldsDef c d = concatMap (parseFieldDef c d)
 
+-- | For numeric attributes, @dot -Tdot@ seems to use @\"\"@ to
+--   indicate the default value.
+parseFieldNumDef :: (ParseDot a) => (a -> b) -> a -> String -> [(String, Parse b)]
+parseFieldNumDef c d fld = [(fld, liftEqParse p fld c)]
+  where
+    p = stringRep d "\"\""
+        `onFail`
+        parse
+
+-- | 'liftEqParse'' using 'parse' as the parser.
+liftEqParse' :: (ParseDot a) => String -> (a -> b) -> Parse b
+liftEqParse' = liftEqParse parse
+
+-- | Attempt to parse the @\"=value\"@ part of a @key=value@ pair.  If
+--   there is an equal sign but the @value@ part doesn't parse, throw
+--   an un-recoverable error.
+liftEqParse :: Parse a -> String -> (a -> b) -> Parse b
+liftEqParse p k c = parseEq
+                    *> ( fmap c p
+                         `adjustErrBad`
+                         (("Unable to parse key=value with key of " ++ k
+                           ++ "\n\t") ++)
+                       )
+
+-- | The opposite of 'bracket'.
+ignoreSep :: (a -> b -> c) -> Parse a -> Parse sep -> Parse b -> Parse c
+ignoreSep f pa sep pb = f <$> pa <* sep <*> pb
+
 commaSep :: (ParseDot a, ParseDot b) => Parse (a, b)
 commaSep = commaSep' parse parse
 
@@ -453,19 +487,19 @@
 commaSepUnqt = commaSep' parseUnqt parseUnqt
 
 commaSep'       :: Parse a -> Parse b -> Parse (a,b)
-commaSep' pa pb = do a <- pa
-                     wrapWhitespace parseComma
-                     b <- pb
-                     return (a,b)
+commaSep' pa pb = ignoreSep (,) pa (wrapWhitespace parseComma) pb
 
 parseComma :: Parse ()
-parseComma = character ',' >> return ()
+parseComma = character ',' *> return ()
 
+-- | Try to parse a list of the specified type; returns an empty list
+--   if parsing fails.
 tryParseList :: (ParseDot a) => Parse [a]
 tryParseList = tryParseList' parse
 
+-- | Return an empty list if parsing a list fails.
 tryParseList' :: Parse [a] -> Parse [a]
-tryParseList' = liftM (fromMaybe []) . optional
+tryParseList' = fmap (fromMaybe []) . optional
 
 parseAngled :: Parse a -> Parse a
 parseAngled = bracket (character '<') (character '>')
@@ -482,13 +516,13 @@
 parseColorScheme     :: Bool -> Parse ColorScheme
 parseColorScheme scs = do cs <- oneOf [ stringRep X11 "X11"
                                       , stringRep SVG "svg"
-                                      , liftM Brewer parseUnqt
+                                      , Brewer <$> parseUnqt
                                       ]
                           when scs $ setColorScheme cs
                           return cs
 
 instance ParseDot BrewerScheme where
-  parseUnqt = liftM2 BScheme parseUnqt parseUnqt
+  parseUnqt = liftA2 BScheme parseUnqt parseUnqt
 
 instance ParseDot BrewerName where
   -- The order is different from above to make sure longer names are
diff --git a/Data/GraphViz/PreProcessing.hs b/Data/GraphViz/PreProcessing.hs
--- a/Data/GraphViz/PreProcessing.hs
+++ b/Data/GraphViz/PreProcessing.hs
@@ -16,8 +16,8 @@
      * Split lines (by inserting a @\\@ the rest of that \"line\" is
        continued on the next line).
 
-     * 'Text's concatenated together using @\"...\" + \"...\"@; these
-       are concatenated into one big 'Text'.
+     * Strings concatenated together using @\"...\" + \"...\"@; these
+       are concatenated into one big string.
 -}
 module Data.GraphViz.PreProcessing(preProcess) where
 
@@ -29,7 +29,6 @@
 import qualified Data.Text.Lazy.Builder as B
 import Data.Text.Lazy.Builder(Builder)
 import Data.Monoid(Monoid(..), mconcat)
-import Control.Monad(liftM)
 
 -- -----------------------------------------------------------------------------
 -- Filtering out unwanted Dot items such as comments
@@ -46,7 +45,7 @@
 --   lines only over a single line.  Should parse the /entire/ input
 --   'Text'.
 parseOutUnwanted :: Parse Builder
-parseOutUnwanted = liftM mconcat (many getNext)
+parseOutUnwanted = mconcat <$> many getNext
   where
     getNext = parseOK
               `onFail`
@@ -56,10 +55,11 @@
               `onFail`
               parseUnwanted
               `onFail`
-              liftM B.singleton next
-    parseOK = liftM B.fromLazyText
-              $ many1Satisfy (`notElem` ['\n', '\r', '\\', '/', '"', '<'])
+              fmap B.singleton next
 
+    parseOK = B.fromLazyText
+              <$> many1Satisfy (`notElem` ['\n', '\r', '\\', '/', '"', '<'])
+
 -- | Parses an unwanted part of the Dot code (comments and
 --   pre-processor lines; also un-splits lines).
 parseUnwanted :: (Monoid m) => Parse m
@@ -74,65 +74,58 @@
 --   previous line, but will leave the one from the pre-processor line
 --   there (so in the end it just removes the line).
 parsePreProcessor :: (Monoid m) => Parse m
-parsePreProcessor = do newline
-                       character '#'
-                       consumeLine
-                       return mempty
+parsePreProcessor = newline *> character '#' *> consumeLine *> pure mempty
 
 -- | Parse @//@-style comments.
 parseLineComment :: (Monoid m) => Parse m
-parseLineComment = do string "//"
-                      -- Note: do /not/ consume the newlines, as they're
-                      -- needed in case the next line is a pre-processor
-                      -- line.
-                      consumeLine
-                      return mempty
+parseLineComment = string "//"
+                   -- Note: do /not/ consume the newlines, as they're
+                   -- needed in case the next line is a pre-processor
+                   -- line.
+                   *> consumeLine
+                   *> pure mempty
 
 -- | Parse @/* ... */@-style comments.
 parseMultiLineComment :: (Monoid m) => Parse m
-parseMultiLineComment = bracket start end (many inner)
-                        >> return mempty
+parseMultiLineComment = bracket start end (many inner) *> pure mempty
   where
     start = string "/*"
     end = string "*/"
-    inner = (many1Satisfy ('*' /=) >> return ())
+    inner = (many1Satisfy ('*' /=) *> pure ())
             `onFail`
-            do character '*'
-               satisfy ('/' /=)
-               inner
+            (character '*' *> satisfy ('/' /=) *> inner)
 
 parseConcatStrings :: Parse Builder
-parseConcatStrings = liftM (wrapQuotes . mconcat)
-                     $ sepBy1 parseString parseConcat
+parseConcatStrings = wrapQuotes . mconcat <$> sepBy1 parseString parseConcat
   where
     qParse = bracket (character '"') (commit $ character '"')
-    parseString = qParse (liftM mconcat $ many parseInner)
-    parseInner = (string "\\\"" >> return (B.fromLazyText $ T.pack "\\\""))
+    parseString = qParse (mconcat <$> many parseInner)
+    parseInner = (string "\\\"" *> pure (B.fromLazyText $ T.pack "\\\""))
                  `onFail`
                  -- Need to parse an explicit `\', in case it ends the
                  -- string (and thus the next step would get parsed by the
                  -- previous option).
-                 (string "\\\\" >> return (B.fromLazyText $ T.pack "\\\\"))
+                 (string "\\\\" *> pure (B.fromLazyText $ T.pack "\\\\"))
                  `onFail`
                  parseSplitLine -- in case there's a split mid-quote
                  `onFail`
-                 liftM B.singleton (satisfy (quoteChar /=))
-    parseConcat = parseSep >> character '+' >> parseSep
+                 fmap B.singleton (satisfy (quoteChar /=))
+    parseConcat = parseSep *> character '+' *> parseSep
     parseSep = many $ whitespace1 `onFail` parseUnwanted
     wrapQuotes str = qc `mappend` str `mappend` qc
     qc = B.singleton '"'
 
 -- | Lines can be split with a @\\@ at the end of the line.
 parseSplitLine :: (Monoid m) => Parse m
-parseSplitLine = character '\\' >> newline >> return mempty
+parseSplitLine = character '\\' *> newline *> pure mempty
 
 parseHTML :: Parse Builder
-parseHTML = liftM (addAngled . mconcat)
+parseHTML = fmap (addAngled . mconcat)
             . parseAngled $ many inner
   where
     inner = parseHTML
             `onFail`
-            (liftM B.fromLazyText $ many1Satisfy (\c -> c /= open && c /= close))
+            (B.fromLazyText <$> many1Satisfy (\c -> c /= open && c /= close))
     addAngled str = B.singleton open `mappend` str `mappend` B.singleton close
     open = '<'
     close = '>'
diff --git a/Data/GraphViz/Printing.hs b/Data/GraphViz/Printing.hs
--- a/Data/GraphViz/Printing.hs
+++ b/Data/GraphViz/Printing.hs
@@ -78,7 +78,9 @@
                                                    , hPutDoc
                                                    , Pretty(..)
                                                    , bool
-                                                   , string)
+                                                   , string
+                                                   , width
+                                                   , (<$>))
 import qualified Text.PrettyPrint.Leijen.Text.Monadic as PP
 import qualified Data.Text.Lazy as T
 import Data.Text.Lazy(Text)
diff --git a/Data/GraphViz/Types/Canonical.hs b/Data/GraphViz/Types/Canonical.hs
--- a/Data/GraphViz/Types/Canonical.hs
+++ b/Data/GraphViz/Types/Canonical.hs
@@ -91,7 +91,6 @@
 import Data.GraphViz.Util(bool)
 
 import Control.Arrow((&&&))
-import Control.Monad(liftM)
 
 -- -----------------------------------------------------------------------------
 
@@ -182,8 +181,8 @@
   parseUnqt = parseSubGraph DotSG parseUnqt
               `onFail`
               -- Take "anonymous" DotSubGraphs into account.
-              liftM (DotSG False Nothing)
-                    (parseBracesBased SubGraphAttribute parseUnqt)
+              fmap (DotSG False Nothing)
+                   (parseBracesBased SubGraphAttribute parseUnqt)
 
   parse = parseUnqt -- Don't want the option of quoting
           `adjustErr`
diff --git a/Data/GraphViz/Types/Common.hs b/Data/GraphViz/Types/Common.hs
--- a/Data/GraphViz/Types/Common.hs
+++ b/Data/GraphViz/Types/Common.hs
@@ -26,7 +26,7 @@
 import qualified Data.Text.Lazy as T
 import qualified Data.Text.Lazy.Read as T
 import Data.Text.Lazy(Text)
-import Control.Monad(liftM, liftM2, when)
+import Control.Monad(when, unless)
 
 -- -----------------------------------------------------------------------------
 -- This is re-exported by Data.GraphViz.Types
@@ -49,9 +49,9 @@
   toDot gID       = unqtDot gID
 
 instance ParseDot GraphID where
-  parseUnqt = liftM stringNum parseUnqt
+  parseUnqt = stringNum <$> parseUnqt
 
-  parse = liftM stringNum parse
+  parse = stringNum <$> parse
           `adjustErr`
           ("Not a valid GraphID\n\t"++)
 
@@ -115,13 +115,13 @@
                  oldTp <- getAttributeType
                  maybe (return ()) setAttributeType mtp
 
-                 as <- whitespace >> parse
+                 as <- whitespace *> parse
 
                  -- Safe to set back even if not changed.
                  setAttributeType oldTp
                  return $ gat as
               `onFail`
-              liftM determineType parse
+              fmap determineType parse
 
   parse = parseUnqt -- Don't want the option of quoting
           `adjustErr`
@@ -184,14 +184,14 @@
   parseList = parseUnqtList
 
 parseNodeID :: (ParseDot n) => Parse (Attributes -> DotNode n)
-parseNodeID = liftM DotNode parseAndCheck
+parseNodeID = DotNode <$> parseAndCheck
   where
     parseAndCheck = do n <- parse
                        me <- optional parseUnwanted
                        maybe (return n) (const notANode) me
     notANode = fail "This appears to be an edge, not a node"
-    parseUnwanted = oneOf [ parseEdgeType >> return ()
-                          , character ':' >> return () -- PortPos value
+    parseUnwanted = oneOf [ parseEdgeType *> return ()
+                          , character ':' *> return () -- PortPos value
                           ]
 
 instance Functor DotNode where
@@ -227,22 +227,20 @@
 
 
 instance (ParseDot n) => ParseDot (DotEdge n) where
-  parseUnqt = parseAttrBased EdgeAttribute True parseEdgeID
+  parseUnqt = parseAttrBased EdgeAttribute False parseEdgeID
 
   parse = parseUnqt -- Don't want the option of quoting
 
   -- Have to take into account edges of the type "n1 -> n2 -> n3", etc.
-  parseUnqtList = liftM concat
-                  $ parseStatements parseEdgeLine
+  parseUnqtList = concat <$> parseStatements parseEdgeLine
 
   parseList = parseUnqtList
 
 parseEdgeID :: (ParseDot n) => Parse (Attributes -> DotEdge n)
-parseEdgeID = do eFrom <- parseEdgeNode
-                 -- Parse both edge types just to be more liberal
-                 parseEdgeType
-                 eTo <- parseEdgeNode
-                 return $ mkEdge eFrom eTo
+parseEdgeID = ignoreSep mkEdge parseEdgeNode parseEdgeType parseEdgeNode
+              `adjustErr`
+              ("Parsed beginning of DotEdge but could not parse Attributes:\n\t"++)
+              -- Parse both edge types just to be more liberal
 
 type EdgeNode n = (n, Maybe PortPos)
 
@@ -254,11 +252,11 @@
                                $ parseStatements parseEdgeNode
                              )
                  `onFail`
-                 liftM return parseEdgeNode
+                 fmap (:[]) parseEdgeNode
 
 parseEdgeNode :: (ParseDot n) => Parse (EdgeNode n)
-parseEdgeNode = liftM2 (,) parse
-                           (optional $ character ':' >> parseEdgeBasedPP)
+parseEdgeNode = liftA2 (,) parse
+                           (optional $ character ':' *> parseEdgeBasedPP)
 
 mkEdge :: EdgeNode n -> EdgeNode n -> Attributes -> DotEdge n
 mkEdge (eFrom, mFP) (eTo, mTP) = DotEdge eFrom eTo
@@ -267,7 +265,7 @@
 
 mkEdges :: [EdgeNode n] -> [EdgeNode n]
            -> Attributes -> [DotEdge n]
-mkEdges fs ts as = liftM2 (\f t -> mkEdge f t as) fs ts
+mkEdges fs ts as = liftA2 (\f t -> mkEdge f t as) fs ts
 
 addPortPos   :: (PortPos -> Attribute) -> Maybe PortPos
                 -> Attributes -> Attributes
@@ -280,12 +278,11 @@
 
 parseEdgeLine :: (ParseDot n) => Parse [DotEdge n]
 parseEdgeLine = do n1 <- parseEdgeNodes
-                   ens <- many1 $ do parseEdgeType
-                                     parseEdgeNodes
+                   ens <- many1 $ parseEdgeType *> parseEdgeNodes
                    let ens' = n1 : ens
                        efs = zipWith mkEdges ens' (tail ens')
                        ef = return $ \ as -> concatMap ($as) efs
-                   parseAttrBased EdgeAttribute True ef
+                   parseAttrBased EdgeAttribute False ef
 
 instance Functor DotEdge where
   fmap f e = e { fromNode = f $ fromNode e
@@ -351,8 +348,7 @@
 
 parseGraphID   :: (Bool -> Bool -> Maybe GraphID -> a) -> Parse a
 parseGraphID f = do whitespace
-                    str <- liftM isJust
-                           $ optional (parseAndSpace $ string strGraph)
+                    str <- isJust <$> optional (parseAndSpace $ string strGraph)
                     dir <- parseAndSpace ( stringRep True dirGraph
                                            `onFail`
                                            stringRep False undirGraph
@@ -390,7 +386,7 @@
 parseBracesBased      :: AttributeType -> Parse a -> Parse a
 parseBracesBased tp p = do gs <- getsGS id
                            setAttributeType tp
-                           a <- whitespace >> parseBraced (wrapWhitespace p)
+                           a <- whitespace *> parseBraced (wrapWhitespace p)
                            modifyGS (const gs)
                            return a
                         `adjustErr`
@@ -418,16 +414,15 @@
 parseSubGraph         :: (Bool -> Maybe GraphID -> stmt -> c) -> Parse stmt -> Parse c
 parseSubGraph pid pst = do (isC, fID) <- parseSubGraphID pid
                            let tp = bool SubGraphAttribute ClusterAttribute isC
-                           liftM fID $ parseBracesBased tp pst
+                           fID <$> parseBracesBased tp pst
 
 parseSubGraphID   :: (Bool -> Maybe GraphID -> c) -> Parse (Bool,c)
-parseSubGraphID f = do string sGraph
-                       whitespace1
-                       (isC,mid) <- parseSGID
-                       return (isC, f isC mid)
+parseSubGraphID f = appl <$> (string sGraph *> whitespace1 *> parseSGID)
+  where
+    appl (isC, mid) = (isC, f isC mid)
 
 parseSGID :: Parse (Bool, Maybe GraphID)
-parseSGID = oneOf [ liftM getClustFrom $ parseAndSpace parse
+parseSGID = oneOf [ getClustFrom <$> parseAndSpace parse
                   , return (False, Nothing)
                   ]
   where
@@ -440,7 +435,7 @@
     pStr = do isCl <- checkCl
                       `onFail`
                       return False
-              when isCl $ optional (character '_') >> return ()
+              when isCl $ optional (character '_') *> return ()
               sID <- optional pID
               let sID' = if sID == emptyID
                          then Nothing
@@ -451,7 +446,7 @@
 
     -- For Strings, there are no more quotes to unescape, so consume
     -- what you can.
-    pID = liftM stringNum $ manySatisfy (const True)
+    pID = stringNum <$> manySatisfy (const True)
 
 {- This is a much nicer definition, but unfortunately it doesn't work.
    The problem is that Graphviz decides that a subgraph is a cluster
@@ -462,9 +457,9 @@
                        `onFail`
                        return False
                sID <- optional $ do when isCl
-                                      $ optional (character '_') >> return ()
+                                      $ optional (character '_') *> return ()
                                     parseUnqt
-               when (isCl || isJust sID) $ whitespace1 >> return ()
+               when (isCl || isJust sID) $ whitespace1 *> return ()
                return (isCl, sID)
 -}
 
@@ -474,8 +469,8 @@
 printAttrBased prEmp ff ftp fas a = do oldType <- getAttributeType
                                        maybe (return ()) setAttributeType mtp
                                        oldCS <- getColorScheme
-                                       (dc <> semi) <* setAttributeType oldType
-                                                    <* when prEmp (setColorScheme oldCS)
+                                       (dc <> semi) <* unless prEmp (setColorScheme oldCS)
+                                                    <* setAttributeType oldType
   where
     mtp = ftp a
     f = ff a
@@ -494,8 +489,8 @@
                             setAttributeType tp
                             oldCS <- getColorScheme
                             f <- p
-                            atts <- tryParseList' (whitespace >> parse)
-                            when lc $ setColorScheme oldCS
+                            atts <- tryParseList' (whitespace *> parse)
+                            unless lc $ setColorScheme oldCS
                             when (tp /= oldType) $ setAttributeType oldType
                             return $ f atts
                          `adjustErr`
@@ -507,16 +502,16 @@
 
 -- | Parse the separator (and any other whitespace1 present) between statements.
 statementEnd :: Parse ()
-statementEnd = parseSplit >> newline'
+statementEnd = parseSplit *> newline'
   where
-    parseSplit = (whitespace >> oneOf [ character ';' >> return ()
-                                       , newline
-                                       ]
+    parseSplit = (whitespace *> oneOf [ character ';' *> return ()
+                                      , newline
+                                      ]
                  )
                  `onFail`
                  whitespace1
 
 parseStatements   :: Parse a -> Parse [a]
-parseStatements p = sepBy (whitespace >> p) statementEnd
+parseStatements p = sepBy (whitespace *> p) statementEnd
                     `discard`
                     optional statementEnd
diff --git a/Data/GraphViz/Types/Generalised.hs b/Data/GraphViz/Types/Generalised.hs
--- a/Data/GraphViz/Types/Generalised.hs
+++ b/Data/GraphViz/Types/Generalised.hs
@@ -74,7 +74,6 @@
 import qualified Data.Foldable as F
 import qualified Data.Traversable as T
 import Control.Arrow((&&&))
-import Control.Monad(liftM)
 import Control.Monad.Trans.State(get, put, modify, execState, evalState)
 
 -- -----------------------------------------------------------------------------
@@ -154,7 +153,7 @@
 printGStmts = toDot . F.toList
 
 parseGStmts :: (ParseDot n) => Parse (DotStatements n)
-parseGStmts = liftM Seq.fromList parse
+parseGStmts = Seq.fromList <$> parse
 
 statementStructure :: DotStatements n -> GraphState ()
 statementStructure = F.mapM_ stmtStructure
@@ -191,24 +190,24 @@
   listToDot = unqtListToDot
 
 instance (ParseDot n) => ParseDot (DotStatement n) where
-  parseUnqt = oneOf [ liftM GA parseUnqt
-                    , liftM SG parseUnqt
-                    , liftM DN parseUnqt
-                    , liftM DE parseUnqt
+  parseUnqt = oneOf [ GA <$> parseUnqt
+                    , SG <$> parseUnqt
+                    , DN <$> parseUnqt
+                    , DE <$> parseUnqt
                     ]
 
   parse = parseUnqt -- Don't want the option of quoting
           `adjustErr`
-          (++ "Not a valid statement")
+          ("Not a valid statement\n\t"++)
 
-  parseUnqtList = liftM concat . wrapWhitespace
+  parseUnqtList = fmap concat . wrapWhitespace
                   $ parseStatements p
     where
       -- Have to do something special here because of "a -> b -> c"
       -- syntax for edges.
-      p = liftM (map DE) parseEdgeLine
+      p = fmap (map DE) parseEdgeLine
           `onFail`
-          liftM return parse
+          fmap (:[]) parse
 
   parseList = parseUnqtList
 
@@ -262,14 +261,14 @@
   parseUnqt = parseSubGraph DotSG parseGStmts
               `onFail`
               -- Take anonymous DotSubGraphs into account
-              liftM (DotSG False Nothing)
-                    (parseBracesBased SubGraphAttribute parseGStmts)
+              fmap (DotSG False Nothing)
+                   (parseBracesBased SubGraphAttribute parseGStmts)
 
   parse = parseUnqt -- Don't want the option of quoting
           `adjustErr`
-          (++ "\n\nNot a valid Sub Graph")
+          ("Not a valid Sub Graph\n\t"++)
 
-  parseUnqtList = sepBy (whitespace >> parseUnqt) newline'
+  parseUnqtList = sepBy (whitespace *> parseUnqt) newline'
 
   parseList = parseUnqtList
 
@@ -298,8 +297,8 @@
     newStmts = evalState (stsRe $ graphStatements dg) startN
 
     stsRe = T.mapM stRe
-    stRe (SG sg) = liftM SG $ sgRe sg
-    stRe stmt    = return stmt
+    stRe (SG sg) = SG <$> sgRe sg
+    stRe stmt    = pure stmt
     sgRe sg = do sgid' <- case subGraphID sg of
                             Nothing -> do n <- get
                                           put $ succ n
diff --git a/Data/GraphViz/Types/Graph.hs b/Data/GraphViz/Types/Graph.hs
--- a/Data/GraphViz/Types/Graph.hs
+++ b/Data/GraphViz/Types/Graph.hs
@@ -114,8 +114,8 @@
 import Data.Map(Map)
 import qualified Data.Set as S
 import qualified Data.Sequence as Seq
+import Control.Applicative(liftA2, (<$>), (<*>))
 import Control.Arrow((***))
-import Control.Monad(liftM, liftM2)
 import Text.Read(Lexeme(Ident), lexP, parens, readPrec)
 import Text.ParserCombinators.ReadPrec(prec)
 
@@ -361,7 +361,7 @@
     lns = map (\ (n,ni) -> (n,(_inCluster ni, _attributes ni)))
           . M.assocs $ values dg
 
-    (cs,ns) = clustersToNodes pathOf id clustAs snd lns
+    (cs,ns) = clustersToNodes pathOf (const True) id clustAs snd lns
 
     pathOf (n,(c,as)) = pathFrom c (n,as)
     pathFrom c ln = F.foldr C (N ln) . fromMaybe Seq.empty $ (`M.lookup`pM) =<< c
@@ -471,7 +471,7 @@
     invNs = usedClustsIn . M.map _inCluster $ values dg
 
     usedClustsIn = M.fromAscList
-                   . map (liftM2 (,) (fst . head) (map snd))
+                   . map ((,) <$> fst . head <*> map snd)
                    . groupSortBy fst
                    . mapMaybe (uncurry (fmap . flip (,)))
                    . M.assocs
@@ -489,7 +489,7 @@
 
 -- | Determine if this graph has nodes or clusters.
 isEmptyGraph :: DotGraph n -> Bool
-isEmptyGraph = liftM2 (&&) isEmpty (not . hasClusters)
+isEmptyGraph = liftA2 (&&) isEmpty (not . hasClusters)
 
 graphAttributes :: DotGraph n -> [GlobalAttributes]
 graphAttributes = fromGlobAttrs . graphAttrs
@@ -575,7 +575,7 @@
 
 -- | Uses the ParseDot instance for generalised 'G.DotGraph's.
 instance (Ord n, ParseDot n) => ParseDot (DotGraph n) where
-  parseUnqt = liftM fromGDot $ parseUnqt
+  parseUnqt = fromGDot <$> parseUnqt
     where
       -- fromGDot :: G.DotGraph n -> DotGraph n
       fromGDot = fromDotRepr . flip asTypeOf (undefined :: G.DotGraph n)
@@ -657,7 +657,7 @@
                  -> Map n (EdgeMap n)
 toEdgeMap f t = M.map eM . M.fromList . groupSortCollectBy f t'
   where
-    t' = liftM2 (,) t edgeAttributes
+    t' = liftA2 (,) t edgeAttributes
     eM = M.fromList . groupSortCollectBy fst snd
 
 mapNs :: (Ord n, Ord n') => (n -> n') -> DotGraph n -> DotGraph n'
diff --git a/FAQ b/FAQ
deleted file mode 100644
--- a/FAQ
+++ /dev/null
@@ -1,644 +0,0 @@
-% FAQ
-% Ivan Lazar Miljenovic
-
-Fortuitously Anticipated Queries (FAQ)
-======================================
-
-Note that to distinguish it from [Graphviz], the library shall be
-henceforth referred to as _graphviz_.
-
-Graphviz vs _graphviz_
-----------------------
-
-### What is the difference between Graphviz and _graphviz_? ###
-
-[Graphviz] is an open source library and collection of utility
-programs using that library to visualise [graphs] (which are specified
-using the [Dot] language).
-
-_graphviz_ is a library for the purely functional programming language
-[Haskell] that provides "bindings" to Graphviz's programs.  It does so
-by allowing programmers to specify the layout of the graph and then
-converts that to Dot code before calling the appropriate program to
-perform the visualisation.
-
-[Graphviz]: http://www.graphviz.org/
-[graphs]: http://en.wikipedia.org/wiki/Graph_theory
-[Dot]: http://www.graphviz.org/doc/info/lang.html
-[Haskell]: http://haskell.org/
-
-### Why should I use graphviz over one of the other Haskell Graphviz libraries? ###
-
-Various Haskell libraries have support for Graphviz to one extent or
-another; however _graphviz_ has the most comprehensive support
-available out of all of them:
-
-* There are [four different representations] of Dot graphs:
-
-       1. Canonical, which matches the layout of `dot -Tcanon`.
-       2. Generalised, which allows statements to be in any order.
-       3. A graph-based one that allows manipulation of the Dot graph.
-       4. A monadic interface for embedding graphs in Haskell.
-
-    There are also conversion functions between them.
-
- [four different representations]: #whats-the-difference-between-the-different-dotgraph-types
-
-* The ability to parse and generate most aspects of Dot [syntax] and
-  [attributes].  This includes taking into account escaping and
-  quoting rules where applicable.
-
-  [syntax]: http://graphviz.org/doc/info/lang.html
-  [attributes]: http://graphviz.org/doc/info/attrs.html
-
-* The ability to use a custom node type for Dot graphs.
-
-* Support for the all five layout algorithm programs and all specified
-  [output formats] as well as the ability to use custom programs, etc.
-
-  [output formats]: http://www.graphviz.org/doc/info/output.html
-
-* Functions to convert [FGL] graphs and other graph-like structures
-  (albeit not as nicely) to and from the internal Dot representations.
-  In future, this will be expanded to a much larger range of
-  graph-like values once a suitable abstraction is available.
-
-  [FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/
-
-* The ability to augment Dot and FGL graphs with positioning
-  information by round-trip passing through Graphviz.
-
-* Pure Haskell implementations of `dot -Tcanon` and `tred`.
-
-* _graphviz_ is continually being worked upon and expanded to better
-  suit/match the requirements of Graphviz, to improve performance and
-  to make it easier for the programmer to use.
-
-### Is the API of _graphviz_ stable? ###
-
-For the most part, yes: the only items that are likely to change in
-the future are those with bugs/errors or if a radically better way of
-doing things is found.  For most uses, however, the API should not
-change for the foreseeable future.
-
-Note that _graphviz_'s version numbers follow the
-[package versioning policy]; this means that you can immediately tell
-when the API has had a backwards-incompatible change by comparing the
-first two elements of the version.  However, these changes won't
-always affect most users.
-
-[package versioning policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy
-
-### What aspects of Dot syntax and attributes are covered? ###
-
-It's easier to state which aspects of Dot [syntax] and [attributes]
-_aren't_ covered:
-
-#### Overall syntax items not covered ####
-
-* Cannot specify a sub-graph as an end point in an edge;
-
-* Comments, pre-processor lines and split lines are (currently) not
-  supported within HTML-like labels.
-
-* _graphviz_ only uses UTF-8 encoding for printing and parsing
-  (whereas Graphviz allows Latin1 encoding with the `charset`
-  attribute).
-
-* Graphviz is more liberal in accepting "invalid" values
-  (e.g. accepting a floating-point value when only integer values are
-  meant to be accepted); _graphviz_ is more strict in this aspect (and
-  will indeed throw an exception if it cannot parse something
-  properly).
-
-* No extensions (e.g. postscript-specific attributes) are available.
-
-#### Attribute and value items not covered ####
-
-* The global `orientation` attribute is not defined; however its
-  behaviour is duplicated by the `rotate` attribute.
-
-* The deprecated `overlap` algorithms have not been defined.
-
-* `pointf` and `point` values have been combined into one datatype; as
-  such, when constructing values such as `Rect` care should be taken
-  about which parts of a `Point` are allowed.
-
-* Only polygon-based `shape`s are available.
-
-* The `charset` attribute is not available as _graphviz_ assumes that
-  all Dot graphs will be in UTF-8 for simplicity; if Latin1-encoded
-  graphs need to be parsed then you shall need to do all I/O for them
-  by hand.
-
-* `colorscheme` attributes _are_ parsed, but the behaviour is not
-  quite the same: consider the following minimal Dot graph:
-
-    ~~~~~ {.dot}
-    digraph {
-        a [ style=filled, fillcolor=gray, colorscheme=svg ]
-    }
-    ~~~~~
-
-    Despite the fact that the color is specified before the colorscheme,
-    Graphviz will use that colorscheme to parse the color (as an SVG
-    gray differs from the X11 gray); _graphviz_, however, will use the
-    default colorscheme of `x11` to parse the color, and **then** set
-    the colorscheme to be `svg` (despite it not being used after it is
-    set).
-
-#### Available items of note ####
-
-There are a few items of note that are available that are worthy of
-special note (as they may not be immediately obvious from the
-generated documentation):
-
-* _graphviz_ is able to parse (but not print) the following special
-  aspects of specifying edges in Dot code:
-
-    - The `node:port` method of specifying of head/tail `portPos`
-      values.
-
-    - Stating multiple edges with common interior nodes (e.g. `a -> b
-      -> c`).
-
-    - Stating edges with a grouping of nodes (e.g. `a -> {b c}`).
-
-* Sub-graphs are specified as being clusters when the subgraph name
-  starts with either `"cluster"` or `"cluster_"`; note that this
-  prefix is removed when determining the subraph's name for the
-  internal datatypes.
-
-* Anonymous subgraphs (where not even the `subgraph` keyword is
-  specified) are also parseable.
-
-* HTML-like and record labels are available, and feature proper
-  escaping/unescaping when printing/parsing.
-
-* Other syntactic issues are taken care of for you automatically (such
-  as escaping/unescaping quotation marks).  Even newlines are
-  automatically escaped (but not unescaped) for you, defaulting to
-  centered lines.
-
-Getting _graphviz_ and more documentation
------------------------------------------
-
-### Where can I obtain _graphviz_? ###
-
-The best place to get _graphviz_ is from its [HackageDB] page.
-
-[HackageDB]: http://hackage.haskell.org/package/graphviz
-
-### Where can I find the API documentation for _graphviz_? ###
-
-Also on its [HackageDB] page.
-
-### Is it safe to install and use _graphviz_ from its darcs repository? ###
-
-No; unlike other projects I make no guarantees as to the stability of
-the live version of _graphviz_.  Whilst the [darcs] [repository] is
-_usually_ stable, it's often in a state of flux and at times patches
-that break the repository are recorded (when it's simpler/cleaner to
-break one patch into several smaller patches).
-
-[darcs]: http://darcs.net/
-[repository]: http://code.haskell.org/graphviz/
-
-### How is _graphviz_ licensed? ###
-
-_graphviz_ is licensed under a [3-Clause BSD License] (note that the
-ColorBrewer Color Schemes found in `Data.GraphViz.Attributes.Colors.Brewer`
-are covered under
-[their own license](http://graphviz.org/doc/info/colors.html#brewer_license)).
-
-[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
-
-Simplistically, this means that you can do whatever you want with
-_graphviz_ as long as you cite both myself and [Matthew Sackman] (the
-original author) as being the authors of _graphviz_.  However, I would
-appreciate at least an [email] letting me know how _graphviz_ is being
-used.
-
-[Matthew Sackman]: http://www.wellquite.org/
-[email]: mailto:Ivan.Miljenovic+graphviz@gmail.com
-
-### Where can I find more information on _graphviz_? ###
-
-From its [home page].
-
-[home page]: http://projects.haskell.org/graphviz/
-
-### Are there any tutorials on how to use _graphviz_? ###
-
-A basic tutorial on
-[how to visualise graph-like data](http://ivanmiljenovic.wordpress.com/2011/10/16/graphviz-in-vacuum/)
-is available; more will come if people ask for it.
-
-### What other packages use _graphviz_? ###
-
-This is a list of all known packages that use _graphviz_: if you know
-of any others please let me know and I'll add it to the list.
-
-* [Graphalyze](http://hackage.haskell.org/package/Graphalyze)
-* [SourceGraph](http://hackage.haskell.org/package/SourceGraph)
-
-### What is the history of _graphviz_? ###
-
-_graphviz_ was originally written by [Matthew Sackman] (if you want
-his reasons for doing so, you'll have to ask him yourself) with the
-first known release being on 10 July, 2008.  In 2008 I (Ivan
-Miljenovic) needed a library that provided bindings to Graphviz with
-clustering support; at the time _graphviz_ was the most fully featured
-and closest to what I wanted, so I submitted a patch that provided
-support for both clustering and undirected graphs.
-
-In April 2009, Matthew wanted to step down from maintaining _graphviz_
-and asked if I wanted to take over.  Since then the library has been
-almost completely re-written with greatly improved coverage of the Dot
-language and extra features.  However, the original outline of the
-library still remains.
-
-Using _graphviz_
-----------------
-
-### Can I start using _graphviz_ without knowing anything about Graphviz? ###
-
-You can, but if you want to start doing anything more advanced then
-you should be reading Graphviz's documentation as well as
-_graphviz_'s.  This is because the layout and design of _graphviz_ is
-heavily based upon the Dot language and the various [attributes] that
-Graphviz supports.
-
-### Can I just use _graphviz_ without reading its documentation? ###
-
-You should _at least_ read the various messages about possible
-ambiguities, etc. at the top of each module and for the attributes you
-use before you use _graphviz_.
-
-### Do I need to have Graphviz installed to use _graphviz_? ###
-
-Technically, no if you're only dealing with the Dot language aspects.
-However, usage of the functions in the `Commands` module, or the
-augmentation of pretty-printing functions in the GraphViz module _do_
-require Graphviz to be installed.
-
-### Why didn't you use FFI to bind to the Graphviz library? ###
-
-Because I just kept working where [Matthew Sackman] left off and it
-was already using Graphviz's tools rather than the actual library.
-However, most other language bindings (for Python, Perl, etc.) seem to
-do the same: generate Dot code and pass that to the relevant tool.
-
-This, however, does provide a fortunate side effect where the ability
-to print and parse Dot code means that _graphviz_ can be used for more
-than just visualising graphs created solely in Haskell: it can also
-import pre-defined graphs, or else generate Dot code for use with
-other tools.
-
-### What's the difference between the different DotGraph types? ###
-
-_graphviz_ has four different "implementations" of Dot code:
-
-**Canonical:**
-
-:   matches the output of `dot -Tcanon`.  Recommended for use when
-    converting existing data into Dot (especially with the
-    `graphElemsToDot` function in `Data.GraphViz`).
-
-**Generalised:**
-
-:   most closely matches the layout of actual Dot code, as such this is
-    preferred when parsing in arbitrary Dot graphs.  Also useful in
-    cases where you want to use the common Graphviz "hack" of specifying
-    global attributes that don't apply to sub-graphs _after_ the
-    sub-graphs in question.
-
-**Graph:**
-
-:   provides common graph operations on Dot graphs, based upon those
-    found in the [FGL].
-
-**Monadic:**
-
-:   a nicer way of defining relatively static Dot graphs to embed within
-    Haskell code, etc.  Loosely based (with permission!) upon Andy
-    Gill's [dotgen] library.
-
-[dotgen]: http://hackage.haskell.org/package/dotgen
-
-### What's the best way to parse Dot code? ###
-
-In both cases below, you should use the `parseDotGraph` function to
-parse the Dot code: this is because it will strip out comments and
-pre-processor lines and join together split lines (if any of these
-remain the parser will fail).  Also, if you are not sure what the type
-of the nodes are, use either String or else the `GraphID` type as it
-explicitly caters for both Strings and numbers (whereas just assuming
-it being a String will result in numbers being stored internally as a
-String).
-
-If you can, first run `dot -Tcanon` on the Dot code and parse it as a
-`DotGraph` value.  This is because `DotGraph` types are easier to deal
-with.
-
-If, however, this isn't possible (e.g. it uses an image that isn't in
-the current working directory) then use the `GDotGraph` type.
-
-### There are too many attributes!!! Which ones should I use? ###
-
-The `Data.GraphViz.Attributes` module contains a cut-down list of
-recommended and commonly used attributes.
-
-The entire list of attributes can be found in
-`Data.GraphViz.Attributes.Complete`.  In particular, the following
-attributes are **not** recommended for use:
-
-* `Color` for anything except edge colours or gradients for nodes,
-  clusters and graphs when using Graphviz >= 2.29.0 (and if you must,
-  the border colour for a node).
-
-* `ColorScheme`: just stick with X11 colours.
-
-* `Comment`: pretty useless.  Enough said.
-
-### Can I use any attribute wherever I want? ###
-
-No: attributes are all defined in one big datatype for the sake of
-simplicity, but not all attributes are valid in all places.  Read the
-documentation (either for Graphviz or _graphviz_) to determine which is
-suitable where.
-
-### How can I use _graphviz_ to visualise non-FGL graphs? ###
-
-The `graphElemsToDot` function allows you to visualise any graph for
-which you can specify a list of labelled nodes and a list of labelled
-edges.
-
-### How can I use/process multiple graphs like Graphviz does? ###
-
-At one stage, _graphviz_ supported dealing with lists of `DotGraph`s;
-however, it was found to be faster to deal with each graph
-individually rather than try to get Graphviz to deal with them all in
-one go.  In future, once the problem causing this has been tracked
-down and fixed this feature will be returned.
-
-### How can I use custom datatypes for node IDs? ###
-
-The important thing here is to ensure that your custom datatype has
-defined instances of `PrintDot` and `ParseDot`.  Probably the easiest
-way of doing this is to have functions that convert between your type
-and `String` and let graphviz determine how to print and parse those.
-Here is an example of a more difficult type that should be printed
-like `"1: Foo"`:
-
-~~~~~~~~~~~~~~~~~~~~ {.haskell}
-data MyType = MyType String Int
-
-instance PrintDot MyType where
-  unqtDot (MyType s i) = unqtDot i <> colon <+> unqtDot s
-
-  -- We have a space in there, so we need quotes.
-  toDot = doubleQuotes . unqtDot
-
-instance ParseDot MyType where
-  parseUnqt = do i <- parseUnqt
-                 character ':'
-                 whitespace1
-                 s <- parseUnqt
-                 return $ MyType s i
-
-  -- Has at least one space, so it will be quoted.
-  parse = quotedParse parseUnqt
-~~~~~~~~~~~~~~~~~~~~
-
-Things to note from this example:
-
-* Whilst `PrintDot` and `ParseDot` have default definitions for
-  `toDot` and `parse`, they assume the datatype doesn't need quotes;
-  as such if the value will
-  [need quoting](http://www.graphviz.org/doc/info/lang.html), then you
-  should do so explicitly.
-
-* It is better to use the `PrintDot` instances for common types such
-  as `Int` and `String` rather than using the pretty-printers inbuilt
-  conversion functions (`int`, `text`, etc.) to ensure that
-  quotations, etc. are dealt with correctly.
-
-* Be as liberal as you can when parsing, especially with whitespace:
-  when printing only one space is used, yet when parsing we use the
-  `whitespace1` parsing combinator that will parse all whitespace
-  characters (but it must consume _at least_ one; there is a variant
-  that does not need to parse any).
-
-### When parsing Dot code, do I have to worry about the case? ###
-
-Not at all: _graphviz_'s parser is case-insensitive; however, the
-correct case is checked first so there is a slight degradation in
-performance when the wrong case is used.
-
-### How do I set portPos values for nodes in edges? ###
-
-Graphviz allows you to specify edges such as `from:a -> to:b` where
-the nodes "from" and "to" are defined with either `RecordLabel` or
-`Html.Label` labels and have different sections; the edge is then drawn
-from the "a" section of the "from" node to the "b" section of the "to"
-node.
-
-Whilst _graphviz_ can parse this, you can't define this yourself;
-instead, do it the manual way:
-
-~~~~~~~~~~~~~~~~~~~~ {.haskell}
-DotEdge "from" "to" True [ TailPort (LabelledPort (PN "a") Nothing)
-                         , HeadPort (LabelledPort (PN "b") Nothing)
-                         ]
-~~~~~~~~~~~~~~~~~~~~
-
-I realise that doing this manually isn't as convenient, but I am open
-to suggestions on how this can be improved.
-
-Note where `TailPort` and `HeadPort` are used; the next question
-explains this.
-
-### Is there anything else I should know? ###
-
-A few other things of note that you should know about:
-
-* For an edge `a -> b`, Graphviz terms "a" to be the _tail_ node and
-  "b" to be the _head_ node.
-
-* When creating `GraphID` values for the graphs and sub-graphs, you
-  should ensure that they won't clash with any of the `nodeID` values
-  when printed to avoid possible problems.
-
-* It is a good idea to have unique IDs for sub-graphs to ensure that
-  global attributes are applied only to items in that sub-graph and so
-  that clusters aren't combined (it took me a _long_ time to find out
-  that this was the case).
-
-* You should specify an ID for the overall graph when outputting to a
-  format such as SVG as it becomes the title of that image.
-
-* Graphviz allows a node to be "defined" twice with different
-  attributes; in practice they are combined into one node.  Running
-  Dot code through `dot -Tcanon` before parsing removes this problem.
-
-* Several attributes are defined with taking a list of items; all of
-  these assume that the provided lists are non-empty (sub-values are a
-  different story).
-
-* If a particular Dot graph is not parseable, the parser throws an
-  error rather than failing gracefully.
-
-Design Decisions
-----------------
-
-### Why does _graphviz_ use Polyparse rather than Parsec? ###
-
-Short answer: because _graphviz_ was already using [Polyparse] when I
-started working on it (and I hadn't done any parsing before so I had
-no preference either way).
-
-[Polyparse]: http://www.cs.york.ac.uk/fp/polyparse/
-
-Longer answer: Polyparse has several advantages I feel over [Parsec]:
-
-* Simpler types.
-* Avoids the whole "but Parsec-3 is slower than Parsec-2" debate (with
-  its associated baggage/problems).
-* Few inbuilt combinators: since there is no inbuilt `character`
-  parsing combinator, there are no problems with _graphviz_ using its
-  own case-less one.
-* [Easier backtracking](http://www.cs.york.ac.uk/fp/polyparse/#how)
-
-[Parsec]: http://hackage.haskell.org/package/parsec
-
-### Why do you have four different representations of Dot graphs? ###
-
-_graphviz_ has [four different representations] of Dot graphs.  Apart
-from the reasons given before, the canonical implementation was the
-original representation, whereas the generalised one was only
-introduced in the 2999.8.0.0 release and the other two in the
-2999.12.0.0 release.
-
-Note, however, that I was thinking of adding something like the
-generalised implementation back around the time of the
-[2999.0.0.0 release](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064436.html),
-yet
-[people didn't like the idea](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064442.html).
-
-The graph-based implementation was added solely so I could write as
-(un-yet finished) tutorial, and thought others might find it useful.
-The monadic implementation came about as an attempt to encourage more
-people to use _graphviz_ rather than other libraries such as [dotgen],
-and I thought a nicer way of writing Dot graphs might help (the
-initial plans involved complicated type-hackery to try and almost make
-it a DSL for actual Dot code; however it ended up being too
-complicated and unwieldy).
-
-### Why are only FGL graphs supported? ###
-
-Love them or hate them, [FGL] currently provides the best graph
-datatype and library available for Haskell at this time.  As such, if
-any one graph type had to be chosen to have conversion functions
-written for it then FGL is the best option.  Furthermore, I needed FGL
-graph support (which is the much more important reason!).
-
-### Why are the version numbers so high? ###
-
-To make sure the latest release has the highest version number:
-Matthew Sackman originally made releases with date-based versioning,
-but when I switched to using the [package versioning policy] I had to
-change this.  I could have started with 2010.x.y.z or so, but at the
-time I had initial hopes of introducing compatibility with other
-graphs (not just [FGL] ones) soon and wanted to make that the
-3000.0.0.0 release; however that has not yet come to pass.
-
-### Why do you use the American spelling of colour in _graphviz_? ###
-
-Because that's how Graphviz spells it, and I was following upstream to
-avoid confusion.
-
-Bugs, Feature Requests and Development
---------------------------------------
-
-### Do you have any future plans for _graphviz_? ###
-
-Yes, I do!  See the TODO file for more information.
-
-### Does _graphviz_ have a test suite? ###
-
-Yes, there is: to get it, you have to build it with the `test` flag
-enabled; for example:
-
-~~~~~~~~~~~~~~~~~~~~ {.bash}
-cabal install graphviz --flags=test
-~~~~~~~~~~~~~~~~~~~~
-
-Then run the `graphviz-testsuite` executable.  This test suite uses
-[QuickCheck] to ensure that _graphviz_ can parse the Dot code it
-generates (as well as a few other things).  Note that it isn't
-perfect: there are no guarantees that the Dot graphs that are
-generated are indeed valid, and those more extensive tests are not yet
-available.
-
-[QuickCheck]: http://hackage.haskell.org/package/QuickCheck
-
-Furthermore, you can do more controlled testing to try and track down
-the source of a bug as the above flag will also expose several
-testing modules which give you access to the various tests used as
-well as the `Arbitrary` instances for use with [QuickCheck].
-
-For proper testing of real-life Dot code, there is also the
-`TestParsing.hs` script that comes in the _graphviz_ tarball (but is
-not installed).  Once you have _graphviz_ installed you can just run
-this script, passing it any files containing Dot graphs you wish to
-test.  It will attempt to parse each Dot graph as a `GDotGraph`, and
-then test to see if the canonicalised form is parseable as a
-`DotGraph`.
-
-### I've found a bug! ###
-
-Oh-oh... please [email] me the specifics of what you were doing
-(including the Dot file in question if it's a parsing problem) and
-I'll get right on it.
-
-### I have a feature request. ###
-
-Is it in the TODO?  If not, [email] me and I'll consider implementing
-it (depending on time and how well I think it will fit in the overall
-library).
-
-### I want to help out with developing _graphviz_. ###
-
-Great!  Whether you have a specific feature in mind or want to help
-clear the TODO list, please [email] me to check with what you're doing
-(who knows, I could already be implementing that very feature).
-
-Once we've discussed what you're going to do, first get yourself a
-copy of the darcs repository:
-
-~~~~~~~~~~~~~~~~~~~~ {.bash}
-darcs get --lazy http://code.haskell.org/graphviz
-~~~~~~~~~~~~~~~~~~~~
-
-Once you've made your changes, make sure you build and run the
-testsuite (and ensure it passes!).  Then record the patch[es] and
-`darcs send` them.  I'll then review them and if I'm happy with them,
-I'll apply them.
-
-### What is the purpose of the AttributeGenerator.hs file? ###
-
-Graphviz has a large number of attributes.  Rather than try to edit
-everything manually each time I want to change how I use the large
-`Attribute` datatype, the AttributeGenerator script generates the
-datatype, instances, etc. for me.
-
-<!--
-     Local Variables:
-     mode:markdown
-     End:
-  -->
-
-
-<!--  LocalWords:  graphviz
- -->
diff --git a/FAQ.md b/FAQ.md
new file mode 100644
--- /dev/null
+++ b/FAQ.md
@@ -0,0 +1,632 @@
+% FAQ
+% Ivan Lazar Miljenovic
+
+Fortuitously Anticipated Queries (FAQ)
+======================================
+
+Note that to distinguish it from [Graphviz], the library shall be
+henceforth referred to as _graphviz_.
+
+Graphviz vs _graphviz_
+----------------------
+
+### What is the difference between Graphviz and _graphviz_? ###
+
+[Graphviz] is an open source library and collection of utility
+programs using that library to visualise [graphs] (which are specified
+using the [Dot] language).
+
+_graphviz_ is a library for the purely functional programming language
+[Haskell] that provides "bindings" to Graphviz's programs.  It does so
+by allowing programmers to specify the layout of the graph and then
+converts that to Dot code before calling the appropriate program to
+perform the visualisation.
+
+[Graphviz]: http://www.graphviz.org/
+[graphs]: http://en.wikipedia.org/wiki/Graph_theory
+[Dot]: http://www.graphviz.org/doc/info/lang.html
+[Haskell]: http://haskell.org/
+
+### Why should I use graphviz over one of the other Haskell Graphviz libraries? ###
+
+Various Haskell libraries have support for Graphviz to one extent or
+another; however _graphviz_ has the most comprehensive support
+available out of all of them:
+
+* There are [four different representations] of Dot graphs:
+
+       1. Canonical, which matches the layout of `dot -Tcanon`.
+       2. Generalised, which allows statements to be in any order.
+       3. A graph-based one that allows manipulation of the Dot graph.
+       4. A monadic interface for embedding graphs in Haskell.
+
+    There are also conversion functions between them.
+
+ [four different representations]: #whats-the-difference-between-the-different-dotgraph-types
+
+* The ability to parse and generate most aspects of Dot [syntax] and
+  [attributes].  This includes taking into account escaping and
+  quoting rules where applicable.
+
+  [syntax]: http://graphviz.org/doc/info/lang.html
+  [attributes]: http://graphviz.org/doc/info/attrs.html
+
+* The ability to use a custom node type for Dot graphs.
+
+* Support for the all five layout algorithm programs and all specified
+  [output formats] as well as the ability to use custom programs, etc.
+
+  [output formats]: http://www.graphviz.org/doc/info/output.html
+
+* Functions to convert [FGL] graphs and other graph-like structures
+  (albeit not as nicely) to and from the internal Dot representations.
+  In future, this will be expanded to a much larger range of
+  graph-like values once a suitable abstraction is available.
+
+  [FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/
+
+* The ability to augment Dot and FGL graphs with positioning
+  information by round-trip passing through Graphviz.
+
+* Pure Haskell implementations of `dot -Tcanon` and `tred`.
+
+* _graphviz_ is continually being worked upon and expanded to better
+  suit/match the requirements of Graphviz, to improve performance and
+  to make it easier for the programmer to use.
+
+### Is the API of _graphviz_ stable? ###
+
+For the most part, yes: the only items that are likely to change in
+the future are those with bugs/errors or if a radically better way of
+doing things is found.  For most uses, however, the API should not
+change for the foreseeable future.
+
+Note that _graphviz_'s version numbers follow the
+[package versioning policy]; this means that you can immediately tell
+when the API has had a backwards-incompatible change by comparing the
+first two elements of the version.  However, these changes won't
+always affect most users.
+
+[package versioning policy]: http://www.haskell.org/haskellwiki/Package_versioning_policy
+
+### What aspects of Dot syntax and attributes are covered? ###
+
+It's easier to state which aspects of Dot [syntax] and [attributes]
+_aren't_ covered:
+
+#### Overall syntax items not covered ####
+
+* Cannot specify a sub-graph as an end point in an edge;
+
+* Comments, pre-processor lines and split lines are (currently) not
+  supported within HTML-like labels.
+
+* _graphviz_ only uses UTF-8 encoding for printing and parsing
+  (whereas Graphviz allows Latin1 encoding with the `charset`
+  attribute).
+
+* Graphviz is more liberal in accepting "invalid" values
+  (e.g. accepting a floating-point value when only integer values are
+  meant to be accepted); _graphviz_ is more strict in this aspect (and
+  will indeed throw an exception if it cannot parse something
+  properly).
+
+* No extensions (e.g. postscript-specific attributes) are available.
+
+#### Attribute and value items not covered ####
+
+* The global `orientation` attribute is not defined; however its
+  behaviour is duplicated by the `rotate` attribute.
+
+* The deprecated `overlap` algorithms have not been defined.
+
+* `pointf` and `point` values have been combined into one datatype; as
+  such, when constructing values such as `Rect` care should be taken
+  about which parts of a `Point` are allowed.
+
+* Only polygon-based `shape`s are available.
+
+* The `charset` attribute is not available as _graphviz_ assumes that
+  all Dot graphs will be in UTF-8 for simplicity; if Latin1-encoded
+  graphs need to be parsed then you shall need to do all I/O for them
+  by hand.
+
+* `colorscheme` attributes _are_ parsed, but the behaviour is not
+  quite the same: consider the following minimal Dot graph:
+
+    ~~~~~ {.dot}
+    digraph {
+        a [ style=filled, fillcolor=gray, colorscheme=svg ]
+    }
+    ~~~~~
+
+    Despite the fact that the color is specified before the colorscheme,
+    Graphviz will use that colorscheme to parse the color (as an SVG
+    gray differs from the X11 gray); _graphviz_, however, will use the
+    default colorscheme of `x11` to parse the color, and **then** set
+    the colorscheme to be `svg` (despite it not being used after it is
+    set).
+
+#### Available items of note ####
+
+There are a few items of note that are available that are worthy of
+special note (as they may not be immediately obvious from the
+generated documentation):
+
+* _graphviz_ is able to parse (but not print) the following special
+  aspects of specifying edges in Dot code:
+
+    - The `node:port` method of specifying of head/tail `portPos`
+      values.
+
+    - Stating multiple edges with common interior nodes (e.g. `a -> b
+      -> c`).
+
+    - Stating edges with a grouping of nodes (e.g. `a -> {b c}`).
+
+* Sub-graphs are specified as being clusters when the subgraph name
+  starts with either `"cluster"` or `"cluster_"`; note that this
+  prefix is removed when determining the subraph's name for the
+  internal datatypes.
+
+* Anonymous subgraphs (where not even the `subgraph` keyword is
+  specified) are also parseable.
+
+* HTML-like and record labels are available, and feature proper
+  escaping/unescaping when printing/parsing.
+
+* Other syntactic issues are taken care of for you automatically (such
+  as escaping/unescaping quotation marks).  Even newlines are
+  automatically escaped (but not unescaped) for you, defaulting to
+  centered lines.
+
+Getting _graphviz_ and more documentation
+-----------------------------------------
+
+### Where can I obtain _graphviz_? ###
+
+The best place to get _graphviz_ is from its [HackageDB] page.
+
+[HackageDB]: http://hackage.haskell.org/package/graphviz
+
+### Where can I find the API documentation for _graphviz_? ###
+
+Also on its [HackageDB] page.
+
+### Is it safe to install and use _graphviz_ from its darcs repository? ###
+
+No; unlike other projects I make no guarantees as to the stability of
+the live version of _graphviz_.  Whilst the [darcs] [repository] is
+_usually_ stable, it's often in a state of flux and at times patches
+that break the repository are recorded (when it's simpler/cleaner to
+break one patch into several smaller patches).
+
+[darcs]: http://darcs.net/
+[repository]: http://hub.darcs.net/ivanm/graphviz
+
+### How is _graphviz_ licensed? ###
+
+_graphviz_ is licensed under a [3-Clause BSD License] (note that the
+ColorBrewer Color Schemes found in `Data.GraphViz.Attributes.Colors.Brewer`
+are covered under
+[their own license](http://graphviz.org/doc/info/colors.html#brewer_license)).
+
+[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
+
+Simplistically, this means that you can do whatever you want with
+_graphviz_ as long as you cite both myself and [Matthew Sackman] (the
+original author) as being the authors of _graphviz_.  However, I would
+appreciate at least an [email] letting me know how _graphviz_ is being
+used.
+
+[Matthew Sackman]: http://www.wellquite.org/
+[email]: mailto:Ivan.Miljenovic+graphviz@gmail.com
+
+### Where can I find more information on _graphviz_? ###
+
+From its [home page].
+
+[home page]: http://projects.haskell.org/graphviz/
+
+### Are there any tutorials on how to use _graphviz_? ###
+
+A basic tutorial on
+[how to visualise graph-like data](http://ivanmiljenovic.wordpress.com/2011/10/16/graphviz-in-vacuum/)
+is available; more will come if people ask for it.
+
+### What other packages use _graphviz_? ###
+
+This is a list of all known packages that use _graphviz_: if you know
+of any others please let me know and I'll add it to the list.
+
+* [Graphalyze](http://hackage.haskell.org/package/Graphalyze)
+* [SourceGraph](http://hackage.haskell.org/package/SourceGraph)
+
+### What is the history of _graphviz_? ###
+
+_graphviz_ was originally written by [Matthew Sackman] (if you want
+his reasons for doing so, you'll have to ask him yourself) with the
+first known release being on 10 July, 2008.  In 2008 I (Ivan
+Miljenovic) needed a library that provided bindings to Graphviz with
+clustering support; at the time _graphviz_ was the most fully featured
+and closest to what I wanted, so I submitted a patch that provided
+support for both clustering and undirected graphs.
+
+In April 2009, Matthew wanted to step down from maintaining _graphviz_
+and asked if I wanted to take over.  Since then the library has been
+almost completely re-written with greatly improved coverage of the Dot
+language and extra features.  However, the original outline of the
+library still remains.
+
+Using _graphviz_
+----------------
+
+### Can I start using _graphviz_ without knowing anything about Graphviz? ###
+
+You can, but if you want to start doing anything more advanced then
+you should be reading Graphviz's documentation as well as
+_graphviz_'s.  This is because the layout and design of _graphviz_ is
+heavily based upon the Dot language and the various [attributes] that
+Graphviz supports.
+
+### Can I just use _graphviz_ without reading its documentation? ###
+
+You should _at least_ read the various messages about possible
+ambiguities, etc. at the top of each module and for the attributes you
+use before you use _graphviz_.
+
+### Do I need to have Graphviz installed to use _graphviz_? ###
+
+Technically, no if you're only dealing with the Dot language aspects.
+However, usage of the functions in the `Commands` module, or the
+augmentation of pretty-printing functions in the GraphViz module _do_
+require Graphviz to be installed.
+
+### Why didn't you use FFI to bind to the Graphviz library? ###
+
+Because I just kept working where [Matthew Sackman] left off and it
+was already using Graphviz's tools rather than the actual library.
+However, most other language bindings (for Python, Perl, etc.) seem to
+do the same: generate Dot code and pass that to the relevant tool.
+
+This, however, does provide a fortunate side effect where the ability
+to print and parse Dot code means that _graphviz_ can be used for more
+than just visualising graphs created solely in Haskell: it can also
+import pre-defined graphs, or else generate Dot code for use with
+other tools.
+
+### What's the difference between the different DotGraph types? ###
+
+_graphviz_ has four different "implementations" of Dot code:
+
+**Canonical:**
+
+:   matches the output of `dot -Tcanon`.  Recommended for use when
+    converting existing data into Dot (especially with the
+    `graphElemsToDot` function in `Data.GraphViz`).
+
+**Generalised:**
+
+:   most closely matches the layout of actual Dot code, as such this is
+    preferred when parsing in arbitrary Dot graphs.  Also useful in
+    cases where you want to use the common Graphviz "hack" of specifying
+    global attributes that don't apply to sub-graphs _after_ the
+    sub-graphs in question.
+
+**Graph:**
+
+:   provides common graph operations on Dot graphs, based upon those
+    found in the [FGL].
+
+**Monadic:**
+
+:   a nicer way of defining relatively static Dot graphs to embed within
+    Haskell code, etc.  Loosely based (with permission!) upon Andy
+    Gill's [dotgen] library.
+
+[dotgen]: http://hackage.haskell.org/package/dotgen
+
+### What's the best way to parse Dot code? ###
+
+In both cases below, you should use the `parseDotGraph` function to
+parse the Dot code: this is because it will strip out comments and
+pre-processor lines and join together split lines (if any of these
+remain the parser will fail).  Also, if you are not sure what the type
+of the nodes are, use either String or else the `GraphID` type as it
+explicitly caters for both Strings and numbers (whereas just assuming
+it being a String will result in numbers being stored internally as a
+String).
+
+If you can, first run `dot -Tcanon` on the Dot code and parse it as a
+`DotGraph` value.  This is because `DotGraph` types are easier to deal
+with.
+
+If, however, this isn't possible (e.g. it uses an image that isn't in
+the current working directory) then use the `GDotGraph` type.
+
+### There are too many attributes!!! Which ones should I use? ###
+
+The `Data.GraphViz.Attributes` module contains a cut-down list of
+recommended and commonly used attributes.
+
+The entire list of attributes can be found in
+`Data.GraphViz.Attributes.Complete`.  In particular, the following
+attributes are **not** recommended for use:
+
+* `Color` for anything except edge colours or gradients for nodes,
+  clusters and graphs when using Graphviz >= 2.29.0 (and if you must,
+  the border colour for a node).
+
+* `ColorScheme`: just stick with X11 colours.
+
+* `Comment`: pretty useless.  Enough said.
+
+### Can I use any attribute wherever I want? ###
+
+No: attributes are all defined in one big datatype for the sake of
+simplicity, but not all attributes are valid in all places.  Read the
+documentation (either for Graphviz or _graphviz_) to determine which is
+suitable where.
+
+### How can I use _graphviz_ to visualise non-FGL graphs? ###
+
+The `graphElemsToDot` function allows you to visualise any graph for
+which you can specify a list of labelled nodes and a list of labelled
+edges.
+
+### How can I use/process multiple graphs like Graphviz does? ###
+
+At one stage, _graphviz_ supported dealing with lists of `DotGraph`s;
+however, it was found to be faster to deal with each graph
+individually rather than try to get Graphviz to deal with them all in
+one go.  In future, once the problem causing this has been tracked
+down and fixed this feature will be returned.
+
+### How can I use custom datatypes for node IDs? ###
+
+The important thing here is to ensure that your custom datatype has
+defined instances of `PrintDot` and `ParseDot`.  Probably the easiest
+way of doing this is to have functions that convert between your type
+and `String` or `Text` and let graphviz determine how to print and
+parse those.  Here is an example of a more difficult type that should
+be printed like `"1: Foo"`:
+
+~~~~~~~~~~~~~~~~~~~~ {.haskell}
+data MyType = MyType String Int
+
+instance PrintDot MyType where
+  unqtDot (MyType s i) = unqtDot i <> colon <+> unqtDot s
+
+  -- We have a space in there, so we need quotes.
+  toDot = doubleQuotes . unqtDot
+
+instance ParseDot MyType where
+  parseUnqt = MyType <$> parseUnqt
+                     <*  character ':'
+                     <*  whitespace1
+                     <*> parseUnqt
+
+  -- Has at least one space, so it will be quoted.
+  parse = quotedParse parseUnqt
+~~~~~~~~~~~~~~~~~~~~
+
+Things to note from this example:
+
+* Whilst `PrintDot` and `ParseDot` have default definitions for
+  `toDot` and `parse`, they assume the datatype doesn't need quotes;
+  as such if the value will
+  [need quoting](http://www.graphviz.org/doc/info/lang.html), then you
+  should do so explicitly.
+
+* It is better to use the `PrintDot` instances for common types such
+  as `Int` and `String` rather than using the pretty-printers inbuilt
+  conversion functions (`int`, `text`, etc.) to ensure that
+  quotations, etc. are dealt with correctly.
+
+* Be as liberal as you can when parsing, especially with whitespace:
+  when printing only one space is used, yet when parsing we use the
+  `whitespace1` parsing combinator that will parse all whitespace
+  characters (but it must consume _at least_ one; there is a variant
+  that does not need to parse any).
+
+### When parsing Dot code, do I have to worry about the case? ###
+
+Not at all: _graphviz_'s parser is case-insensitive; however, the
+correct case is checked first so there is a slight degradation in
+performance when the wrong case is used.
+
+### How do I set portPos values for nodes in edges? ###
+
+Graphviz allows you to specify edges such as `from:a -> to:b` where
+the nodes "from" and "to" are defined with either `RecordLabel` or
+`Html.Label` labels and have different sections; the edge is then drawn
+from the "a" section of the "from" node to the "b" section of the "to"
+node.
+
+Whilst _graphviz_ can parse this, you can't define this yourself;
+instead, do it the manual way:
+
+~~~~~~~~~~~~~~~~~~~~ {.haskell}
+DotEdge "from" "to" True [ TailPort (LabelledPort (PN "a") Nothing)
+                         , HeadPort (LabelledPort (PN "b") Nothing)
+                         ]
+~~~~~~~~~~~~~~~~~~~~
+
+I realise that doing this manually isn't as convenient, but I am open
+to suggestions on how this can be improved.
+
+Note where `TailPort` and `HeadPort` are used; the next question
+explains this.
+
+### Is there anything else I should know? ###
+
+A few other things of note that you should know about:
+
+* For an edge `a -> b`, Graphviz terms "a" to be the _tail_ node and
+  "b" to be the _head_ node.
+
+* When creating `GraphID` values for the graphs and sub-graphs, you
+  should ensure that they won't clash with any of the `nodeID` values
+  when printed to avoid possible problems.
+
+* It is a good idea to have unique IDs for sub-graphs to ensure that
+  global attributes are applied only to items in that sub-graph and so
+  that clusters aren't combined (it took me a _long_ time to find out
+  that this was the case).
+
+* You should specify an ID for the overall graph when outputting to a
+  format such as SVG as it becomes the title of that image.
+
+* Graphviz allows a node to be "defined" twice with different
+  attributes; in practice they are combined into one node.  Running
+  Dot code through `dot -Tcanon` before parsing removes this problem.
+
+* Several attributes are defined with taking a list of items; all of
+  these assume that the provided lists are non-empty (sub-values are a
+  different story).
+
+* If a particular Dot graph is not parseable, the parser throws an
+  error rather than failing gracefully.
+
+Design Decisions
+----------------
+
+### Why does _graphviz_ use Polyparse rather than Parsec? ###
+
+Short answer: because _graphviz_ was already using [Polyparse] when I
+started working on it (and I hadn't done any parsing before so I had
+no preference either way).
+
+[Polyparse]: http://www.cs.york.ac.uk/fp/polyparse/
+
+Longer answer: Polyparse has several advantages I feel over [Parsec]:
+
+* Simpler types.
+* Avoids the whole "but Parsec-3 is slower than Parsec-2" debate (with
+  its associated baggage/problems).
+* Few inbuilt combinators: since there is no inbuilt `character`
+  parsing combinator, there are no problems with _graphviz_ using its
+  own case-less one.
+* [Easier backtracking](http://www.cs.york.ac.uk/fp/polyparse/#how)
+
+[Parsec]: http://hackage.haskell.org/package/parsec
+
+### Why do you have four different representations of Dot graphs? ###
+
+_graphviz_ has [four different representations] of Dot graphs.  Apart
+from the reasons given before, the canonical implementation was the
+original representation, whereas the generalised one was only
+introduced in the 2999.8.0.0 release and the other two in the
+2999.12.0.0 release.
+
+Note, however, that I was thinking of adding something like the
+generalised implementation back around the time of the
+[2999.0.0.0 release](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064436.html),
+yet
+[people didn't like the idea](http://www.haskell.org/pipermail/haskell-cafe/2009-July/064442.html).
+
+The graph-based implementation was added solely so I could write as
+(un-yet finished) tutorial, and thought others might find it useful.
+The monadic implementation came about as an attempt to encourage more
+people to use _graphviz_ rather than other libraries such as [dotgen],
+and I thought a nicer way of writing Dot graphs might help (the
+initial plans involved complicated type-hackery to try and almost make
+it a DSL for actual Dot code; however it ended up being too
+complicated and unwieldy).
+
+### Why are only FGL graphs supported? ###
+
+Love them or hate them, [FGL] currently provides the best graph
+datatype and library available for Haskell at this time.  As such, if
+any one graph type had to be chosen to have conversion functions
+written for it then FGL is the best option.  Furthermore, I needed FGL
+graph support (which is the much more important reason!).
+
+### Why are the version numbers so high? ###
+
+To make sure the latest release has the highest version number:
+Matthew Sackman originally made releases with date-based versioning,
+but when I switched to using the [package versioning policy] I had to
+change this.  I could have started with 2010.x.y.z or so, but at the
+time I had initial hopes of introducing compatibility with other
+graphs (not just [FGL] ones) soon and wanted to make that the
+3000.0.0.0 release; however that has not yet come to pass.
+
+### Why do you use the American spelling of colour in _graphviz_? ###
+
+Because that's how Graphviz spells it, and I was following upstream to
+avoid confusion.
+
+Bugs, Feature Requests and Development
+--------------------------------------
+
+### Do you have any future plans for _graphviz_? ###
+
+Yes, I do!  See the TODO file for more information.
+
+### Does _graphviz_ have a test suite? ###
+
+Yes, there is, using the in-built support for test suites in Cabal:
+
+~~~~~~~~~~~~~~~~~~~~ {.bash}
+cabal install graphviz --enable-tests
+~~~~~~~~~~~~~~~~~~~~
+
+Then run the `graphviz-testsuite` executable.  This test suite uses
+[QuickCheck] to ensure that _graphviz_ can parse the Dot code it
+generates (as well as a few other things).  Note that it isn't
+perfect: there are no guarantees that the Dot graphs that are
+generated are indeed valid, and those more extensive tests are not yet
+available.
+
+[QuickCheck]: http://hackage.haskell.org/package/QuickCheck
+
+Furthermore, you can do more controlled testing to try and track down
+the source of a bug as the above flag will also expose several
+testing modules which give you access to the various tests used as
+well as the `Arbitrary` instances for use with [QuickCheck].
+
+For proper testing of real-life Dot code, there is also the
+`TestParsing.hs` script that comes in the _graphviz_ tarball (but is
+not installed).  Once you have _graphviz_ installed you can just run
+this script, passing it any files containing Dot graphs you wish to
+test.  It will attempt to parse each Dot graph as a `GDotGraph`, and
+then test to see if the canonicalised form is parseable as a
+`DotGraph`.
+
+### I've found a bug! ###
+
+Oh-oh... please [email] me the specifics of what you were doing
+(including the Dot file in question if it's a parsing problem) and
+I'll get right on it.
+
+### I have a feature request. ###
+
+Is it in the TODO?  If not, [email] me and I'll consider implementing
+it (depending on time and how well I think it will fit in the overall
+library).
+
+### I want to help out with developing _graphviz_. ###
+
+Great!  Whether you have a specific feature in mind or want to help
+clear the TODO list, please [email] me to check with what you're doing
+(who knows, I could already be implementing that very feature).
+
+Once we've discussed what you're going to do, first get yourself a
+copy of the darcs repository:
+
+~~~~~~~~~~~~~~~~~~~~ {.bash}
+darcs get --lazy http://hub.darcs.net/ivanm/graphviz
+~~~~~~~~~~~~~~~~~~~~
+
+Once you've made your changes, make sure you build and run the
+testsuite (and ensure it passes!).  Then record the patch[es] and
+`darcs send` them.  I'll then review them and if I'm happy with them,
+I'll apply them.
+
+### What is the purpose of the AttributeGenerator.hs file? ###
+
+Graphviz has a large number of attributes.  Rather than try to edit
+everything manually each time I want to change how I use the large
+`Attribute` datatype, the AttributeGenerator script generates the
+datatype, instances, etc. for me.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
--- a/LICENSE
+++ /dev/null
@@ -1,106 +0,0 @@
-% License
-% Ivan Lazar Miljenovic
-
-Licensing Information
-=====================
-
-The overall graphviz library is covered by a [3-Clause BSD License].
-However, the _ColorBrewer_ colours are licensed under their own
-license.
-
-[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
-
-License for graphviz
---------------------
-
-Copyright (c) 2008, Matthew Sackman
-
-Copyright (c) 2008 - 2010, [Ivan Lazar Miljenovic](mailto:Ivan.Miljenovic+graphviz@gmail.com)
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-
-   * Redistributions in binary form must reproduce the above
-       copyright notice, this list of conditions and the following
-       disclaimer in the documentation and/or other materials
-       provided with the distribution.
-
-   * The names of the contributors to this software may not be used
-       to endorse or promote products derived from this software
-       without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The ColorBrewer license
------------------------
-
-> The _ColorBrewer_ colours and colour schemes found in
-> `Data.GraphViz.Attributes.Colors` are covered by the following
-> license.  This text is not part of the license.
-
-Apache-Style Software License for ColorBrewer software and ColorBrewer
-Color Schemes, Version 1.1
-
-Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania
-State University. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   1. Redistributions as source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-   2. The end-user documentation included with the redistribution, if
-      any, must include the following acknowledgment:
-
-      This product includes color specifications and designs developed
-      by Cynthia Brewer (http://colorbrewer.org/).
-
-      Alternately, this acknowledgment may appear in the software
-      itself, if and wherever such third-party acknowledgments
-      normally appear.
-
-   3. The name "ColorBrewer" must not be used to endorse or promote
-      products derived from this software without prior written
-      permission. For written permission, please contact Cynthia
-      Brewer at cbrewer@psu.edu.
-
-   4. Products derived from this software may not be called
-      "ColorBrewer", nor may "ColorBrewer" appear in their name,
-      without prior written permission of Cynthia Brewer.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL CYNTHIA BREWER, MARK HARROWER, OR THE
-PENNSYLVANIA STATE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-<!--
-     Local Variables:
-     mode:markdown
-     End:
-  -->
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,100 @@
+% License
+% Ivan Lazar Miljenovic
+
+Licensing Information
+=====================
+
+The overall graphviz library is covered by a [3-Clause BSD License].
+However, the _ColorBrewer_ colours are licensed under their own
+license.
+
+[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
+
+License for graphviz
+--------------------
+
+Copyright (c) 2008, Matthew Sackman
+
+Copyright (c) 2008 - 2010, [Ivan Lazar Miljenovic](mailto:Ivan.Miljenovic+graphviz@gmail.com)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials
+       provided with the distribution.
+
+   * The names of the contributors to this software may not be used
+       to endorse or promote products derived from this software
+       without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The ColorBrewer license
+-----------------------
+
+> The _ColorBrewer_ colours and colour schemes found in
+> `Data.GraphViz.Attributes.Colors` are covered by the following
+> license.  This text is not part of the license.
+
+Apache-Style Software License for ColorBrewer software and ColorBrewer
+Color Schemes, Version 1.1
+
+Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania
+State University. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   1. Redistributions as source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. The end-user documentation included with the redistribution, if
+      any, must include the following acknowledgment:
+
+      This product includes color specifications and designs developed
+      by Cynthia Brewer (http://colorbrewer.org/).
+
+      Alternately, this acknowledgment may appear in the software
+      itself, if and wherever such third-party acknowledgments
+      normally appear.
+
+   3. The name "ColorBrewer" must not be used to endorse or promote
+      products derived from this software without prior written
+      permission. For written permission, please contact Cynthia
+      Brewer at cbrewer@psu.edu.
+
+   4. Products derived from this software may not be called
+      "ColorBrewer", nor may "ColorBrewer" appear in their name,
+      without prior written permission of Cynthia Brewer.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL CYNTHIA BREWER, MARK HARROWER, OR THE
+PENNSYLVANIA STATE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,64 +0,0 @@
-% Haskell bindings to the Graphviz toolkit
-% Ivan Lazar Miljenovic
-
-The graphviz Library
-====================
-
-The _graphviz_ library provides bindings to the [Graphviz] graph
-visualisation suite of tools for the purely functional programming
-language [Haskell].  It can be downloaded from [HackageDB] or - if you
-have [cabal-install] - installing it is as simple as:
-
-~~~~~~~~~~~~~~~~~~~~ {.bash}
-cabal update
-cabal install graphviz
-~~~~~~~~~~~~~~~~~~~~
-
-[Graphviz]: http://www.graphviz.org/
-[Haskell]: http://haskell.org/
-[HackageDB]: http://hackage.haskell.org/package/graphviz
-[cabal-install]: http://haskell.org/haskellwiki/Cabal-Install
-
-Library features
-----------------
-
-Main features of the graphviz library include:
-
-* Almost complete coverage of all Graphviz attributes and syntax.
-
-* Support for specifying clusters.
-
-* The ability to use a custom node type.
-
-* Functions for running a Graphviz layout tool with all specified
-  output types.
-
-* The ability to not only generate but also parse Dot code with two
-  options: strict and liberal (in terms of ordering of statements).
-
-* Functions to convert [FGL] graphs and other graph-like data
-  structures to Dot code - including support to group them into
-  clusters - with a high degree of customisation by specifying which
-  attributes to use and limited support for the inverse operation.
-
-* Round-trip support for passing an [FGL] graph through Graphviz to
-  augment node and edge labels with positional information, etc.
-
-[FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/
-
-graphviz is free software licensed under a [3-Clause BSD License].
-
-\(C\) 2008 [Matthew Sackman](http://www.wellquite.org/)
-
-\(C\) 2008 - onwards [Ivan Lazar Miljenovic](http://ivanmiljenovic.wordpress.com/)
-
-[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
-
-For more information, feel free to
-[email](mailto:Ivan.Miljenovic+graphviz@gmail.com) me.
-
-<!--
-     Local Variables:
-     mode:markdown
-     End:
-  -->
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,58 @@
+% Haskell bindings to the Graphviz toolkit
+% Ivan Lazar Miljenovic
+
+The graphviz Library
+====================
+
+The _graphviz_ library provides bindings to the [Graphviz] graph
+visualisation suite of tools for the purely functional programming
+language [Haskell].  It can be downloaded from [HackageDB] or - if you
+have [cabal-install] - installing it is as simple as:
+
+~~~~~~~~~~~~~~~~~~~~ {.bash}
+cabal update
+cabal install graphviz
+~~~~~~~~~~~~~~~~~~~~
+
+[Graphviz]: http://www.graphviz.org/
+[Haskell]: http://haskell.org/
+[HackageDB]: http://hackage.haskell.org/package/graphviz
+[cabal-install]: http://haskell.org/haskellwiki/Cabal-Install
+
+Library features
+----------------
+
+Main features of the graphviz library include:
+
+* Almost complete coverage of all Graphviz attributes and syntax.
+
+* Support for specifying clusters.
+
+* The ability to use a custom node type.
+
+* Functions for running a Graphviz layout tool with all specified
+  output types.
+
+* The ability to not only generate but also parse Dot code with two
+  options: strict and liberal (in terms of ordering of statements).
+
+* Functions to convert [FGL] graphs and other graph-like data
+  structures to Dot code - including support to group them into
+  clusters - with a high degree of customisation by specifying which
+  attributes to use and limited support for the inverse operation.
+
+* Round-trip support for passing an [FGL] graph through Graphviz to
+  augment node and edge labels with positional information, etc.
+
+[FGL]: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/
+
+graphviz is free software licensed under a [3-Clause BSD License].
+
+\(C\) 2008 [Matthew Sackman](http://www.wellquite.org/)
+
+\(C\) 2008 - onwards [Ivan Lazar Miljenovic](http://ivanmiljenovic.wordpress.com/)
+
+[3-Clause BSD License]: http://www.opensource.org/licenses/bsd-license.php
+
+For more information, feel free to
+[email](mailto:Ivan.Miljenovic+graphviz@gmail.com) me.
diff --git a/TODO b/TODO
deleted file mode 100644
--- a/TODO
+++ /dev/null
@@ -1,54 +0,0 @@
-% TODO
-% Ivan Lazar Miljenovic
-
-Future Plans for graphviz
-=========================
-
-This is a list of planned feature improvements to graphviz along with
-an indication of when it's likely to be implemented (note that these
-time scales are in relation to releases, not actual time; however, it
-is quite possible that the order will not be adhered to).
-
-Short term
-----------
-
-* Quickstart-style documentation to help users get going with graphviz
-  quickly.
-
-* Add nicer syntax for record labels, and specifying ports in Monadic
-  Dot graphs.
-
-* Define new classes to distinguish between printing/parsing Attribute
-  values and other values (as only the former requires quoted
-  variants).
-
-* Clean up AttributeGenerator and get it to use a better
-  pretty-printing library.
-
-Medium term
------------
-
-* Improve the test suite such that the generated `DotGraph` values are
-  valid (and thus can be passed to Graphviz proper).  This may not in
-  fact be possible as guaranteeing an arbitrary `Attribute` is valid
-  is rather tricky (as the value itself needs to be verified,
-  especially stateful ones).
-
-* Switch to a proper test-suite library rather than the hand-rolled
-  one currently being used.
-
-* Add support for clusters as endpoints of edges.
-
-Long term
----------
-
-* Allow usage of non-FGL graphs with graphviz.  This will require
-  implementing a separate library to represent graphs (see initial
-  discussions about this
-  [here](http://www.haskell.org/pipermail/haskell-cafe/2009-June/063402.html)).
-
-<!--
-     Local Variables:
-     mode:markdown
-     End:
-  -->
diff --git a/TODO.md b/TODO.md
new file mode 100644
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,48 @@
+% TODO
+% Ivan Lazar Miljenovic
+
+Future Plans for graphviz
+=========================
+
+This is a list of planned feature improvements to graphviz along with
+an indication of when it's likely to be implemented (note that these
+time scales are in relation to releases, not actual time; however, it
+is quite possible that the order will not be adhered to).
+
+Short term
+----------
+
+* Quickstart-style documentation to help users get going with graphviz
+  quickly.
+
+* Add nicer syntax for record labels, and specifying ports in Monadic
+  Dot graphs.
+
+* Define new classes to distinguish between printing/parsing Attribute
+  values and other values (as only the former requires quoted
+  variants).
+
+* Clean up AttributeGenerator and get it to use a better
+  pretty-printing library.
+
+Medium term
+-----------
+
+* Improve the test suite such that the generated `DotGraph` values are
+  valid (and thus can be passed to Graphviz proper).  This may not in
+  fact be possible as guaranteeing an arbitrary `Attribute` is valid
+  is rather tricky (as the value itself needs to be verified,
+  especially stateful ones).
+
+* Switch to a proper test-suite library rather than the hand-rolled
+  one currently being used.
+
+* Add support for clusters as endpoints of edges.
+
+Long term
+---------
+
+* Allow usage of non-FGL graphs with graphviz.  This will require
+  implementing a separate library to represent graphs (see initial
+  discussions about this
+  [here](http://www.haskell.org/pipermail/haskell-cafe/2009-June/063402.html)).
diff --git a/graphviz.cabal b/graphviz.cabal
--- a/graphviz.cabal
+++ b/graphviz.cabal
@@ -1,5 +1,5 @@
 Name:               graphviz
-Version:            2999.14.1.0
+Version:            2999.15.0.0
 Stability:          Beta
 Synopsis:           Bindings to Graphviz for graph visualisation.
 Description: {
@@ -33,22 +33,23 @@
 Homepage:           http://projects.haskell.org/graphviz/
 Category:           Graphs, Graphics
 License:            BSD3
-License-File:       LICENSE
+License-File:       LICENSE.md
 Copyright:          Matthew Sackman, Ivan Lazar Miljenovic
 Author:             Matthew Sackman, Ivan Lazar Miljenovic
 Maintainer:         Ivan.Miljenovic+graphviz@gmail.com
+Bug-Reports:        http://hub.darcs.net/ivanm/graphviz/issues
 Build-Type:         Simple
 Cabal-Version:      >= 1.14
-Extra-Source-Files: TODO
-                    Changelog
-                    README
-                    FAQ
+Extra-Source-Files: TODO.md
+                    Changelog.md
+                    README.md
+                    FAQ.md
                     utils/AttributeGenerator.hs
                     utils/TestParsing.hs
 
 Source-Repository head
     Type:         darcs
-    Location:     http://code.haskell.org/graphviz
+    Location:     http://hub.darcs.net/ivanm/graphviz
 
 Library {
         Default-Language:  Haskell98
@@ -60,7 +61,7 @@
                            fgl == 5.4.*,
                            filepath,
                            polyparse >= 1.7 && < 1.9,
-                           bytestring == 0.9.*,
+                           bytestring >= 0.9 && < 0.11,
                            colour == 2.3.*,
                            transformers >= 0.2 && < 0.4,
                            text,
@@ -115,6 +116,7 @@
         Build-Depends:     base,
                            containers,
                            process,
+                           directory,
                            fgl,
                            filepath,
                            polyparse,
@@ -124,7 +126,7 @@
                            text,
                            wl-pprint-text,
                            dlist,
-                           QuickCheck >= 2.3 && < 2.5
+                           QuickCheck >= 2.3 && < 2.6
 
         hs-Source-Dirs:    . tests
 
diff --git a/tests/Data/GraphViz/Testing/Instances/Attributes.hs b/tests/Data/GraphViz/Testing/Instances/Attributes.hs
--- a/tests/Data/GraphViz/Testing/Instances/Attributes.hs
+++ b/tests/Data/GraphViz/Testing/Instances/Attributes.hs
@@ -439,6 +439,16 @@
   shrink (DVal d) = map DVal $ shrink d
   shrink (PVal p) = map PVal $ shrink p
 
+instance Arbitrary SVGFontNames where
+  arbitrary = arbBounded
+
+instance Arbitrary GraphSize where
+  arbitrary = liftM3 GSize arbitrary arbitrary arbitrary
+
+  shrink gs = do w' <- shrink $ width gs
+                 h' <- shrinkM $ height gs
+                 return $ GSize w' h' False
+
 instance Arbitrary ModeType where
   arbitrary = arbBounded
 
diff --git a/utils/AttributeGenerator.hs b/utils/AttributeGenerator.hs
--- a/utils/AttributeGenerator.hs
+++ b/utils/AttributeGenerator.hs
@@ -67,6 +67,7 @@
                    , parseNames   :: [Code]
                    , valtype      :: VType
                    , parseDef     :: Maybe Code
+                   , emptyParse   :: Maybe Code -- ^ What the empty string gets parsed as.
                    , defValue     :: Maybe Code
                    , forGraphs    :: Bool
                    , forClusters  :: Bool
@@ -87,6 +88,7 @@
                                    , valtype      = v -- just in case need to do fancy
                                                       -- stuff
                                    , parseDef     = liftM text df
+                                   , emptyParse   = liftM text dfP
                                    , defValue     = liftM text d
                                    , forGraphs    = isFor 'G'
                                    , forClusters  = isFor 'C' || forSG
@@ -100,6 +102,11 @@
       isFor f = f `elem` u
       forSG = isFor 'S'
       df' = if v == Bl then Just "'True'" else fmap ( \ t -> '\'' : t ++ "'") df
+      isNumeric = case v of
+                    Integ -> True
+                    Dbl   -> True
+                    _     -> False
+      dfP = bool Nothing d isNumeric
       mDoc (f,fc) = f <> colon <+> text fc
       addF f = fmap (\ dc -> (wrap (char '/') (text f), dc))
       cm' = hsep
@@ -148,14 +155,14 @@
                      . asRows
                      . firstOthers equals (char '|')
                      . (++ [defUnknown])
-                     . map createDefn
+                     . map createDf
                      $ atts att
       derivs = nest tab $ text "deriving (Eq, Ord, Show, Read)"
-      createDefn a = [cnst a <+> vtypeCode a
-                     , if isEmpty cm
-                       then empty
-                       else text "-- ^" <+> cm
-                     ]
+      createDf a = [cnst a <+> vtypeCode a
+                   , if isEmpty cm
+                     then empty
+                     else text "-- ^" <+> cm
+                   ]
           where
             cm = comment a
       defUnknown = [ unknownAttr <+> unknownNameAlias <+> vtype Strng
@@ -170,17 +177,19 @@
     where
       tp = tpNm att
 
-nameAlias     :: Atts -> Code
-nameAlias att = comment
-                $$ (text "type"
-                    <+> unknownNameAlias
-                    <+> equals
-                    <+> vtype Strng)
+-- The Atts value isn't used; this is just to make it have the same
+-- type as the other code-generating functions.
+nameAlias   :: Atts -> Code
+nameAlias _ = cmnt
+              $$ (text "type"
+                  <+> unknownNameAlias
+                  <+> equals
+                  <+> vtype Strng)
   where
-    comment = text "-- | The name for an" <+> unknownAttr
-              <> text "; must satisfy "
-              <+> quotes validUnknownName
-              <> text "."
+    cmnt = text "-- | The name for an" <+> unknownAttr
+           <> text "; must satisfy "
+           <+> quotes validUnknownName
+           <> text "."
 
 unknownNameAlias :: Code
 unknownNameAlias = text "AttributeName"
@@ -191,7 +200,6 @@
       hdr = text "instance" <+> text "PrintDot" <+> tpNm att <+> text "where"
       var = char 'v'
       sFunc = text "unqtDot"
-      cnct = text "<>"
       insts = asRows
               . (++ [unknownInst])
               . map mkInstance
@@ -227,17 +235,27 @@
             $ atts att
       pFunc = text "parseUnqt"
       pType b a
-          | valtype a == Bl     = pFld <> text "Bool" <+> cnst a
-          | isJust $ parseDef a = pFld <> text "Def"  <+> cnst a <+> fromJust (parseDef a)
-          | otherwise           = pFld <+> cnst a
+          | valtype a == Bl       = pFld <> text "Bool" <+> cnst a
+          | isJust $ parseDef a   = pFld <> text "Def"  <+> cnst a <+> fromJust (parseDef a)
+          | isJust $ emptyParse a = pFld <> text "NumDef" <+> cnst a <+> fromJust (emptyParse a)
+          | otherwise             = pFld <+> cnst a
           where
             pFld = text "parseField" <> if b then char 's' else empty
 
       parseAttr a = case map doubleQuotes $ parseNames a of
                       [n] -> pType False a <+> n
                       ns  -> pType True  a <+> docList ns
-      pUnknown = text "liftM2" <+> unknownAttr <+> text "stringBlock"
-                 <+> parens (text "parseEq >> parse")
+      unknownName = text "attrName"
+      pUnknown = text "do"
+                 <+> (   (unknownName <+> text "<- stringBlock")
+                      $$ (text "liftEqParse'"
+                          <+> (parens (text "\"" <> unknownAttr <+> text "(\""
+                                       <+> text "++ T.unpack" <+> unknownName
+                                       <+> text "++ \")\"")
+                               $$ parens (unknownAttr <+> unknownName)
+                               )
+                         )
+                     )
 
 arbitraryInstance     :: Atts -> Code
 arbitraryInstance att = hdr $+$ fns
@@ -448,168 +466,356 @@
 
 -- The actual attributes
 
--- ColorScheme is put earlier so that when sorting, it comes before the various *Color attributes.
+-- Don't edit this value directly; edit the table below instead.
 
 attributes :: [Attribute]
-attributes = [ makeAttr "Damping" ["Damping"] "G" Dbl Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "neato only")
-             , makeAttr "K" ["K"] "GC" Dbl Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only")
-             , makeAttr "URL" ["URL", "href"] "ENGC" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, postscript, map only")
-             , makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing
-             , makeAttr "ArrowSize" ["arrowsize"] "E" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing
-             , makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing
-             , makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing Nothing (Just "dot only")
-             , makeAttr "BoundingBox" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing Nothing (Just "write only")
-             , makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "X11") (Just "@'X11'@") Nothing Nothing
-             , makeAttr "BgColor" ["bgcolor"] "GC" (Cust "[Color]") Nothing (Just "[X11Color Transparent]") (Just "@['X11Color' 'Transparent']@") Nothing Nothing
-             , makeAttr "Center" ["center"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "dot only")
-             , makeAttr "Color" ["color"] "ENC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'Black']@") Nothing Nothing
-             , makeAttr "Comment" ["comment"] "ENG" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing
-             , makeAttr "Compound" ["compound"] "G" Bl (Just "True") (Just "False")(Just "@'False'@") Nothing (Just "dot only")
-             , makeAttr "Concentrate" ["concentrate"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "Constraint" ["constraint"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "dot only")
-             , makeAttr "Decorate" ["decorate"] "E" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "DefaultDist" ["defaultdist"] "G" Dbl Nothing Nothing (Just "@1+(avg. len)*sqrt(|V|)@") (Just "@epsilon@") (Just "neato only, only if @'Pack' 'DontPack'@")
-             , makeAttr "Dim" ["dim"] "G" Integ Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")
-             , makeAttr "Dimen" ["dimen"] "G" Integ Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only")
-             , makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing
-             , makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only")
-             , makeAttr "Distortion" ["distortion"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing
-             , makeAttr "DPI" ["dpi", "resolution"] "G" Dbl Nothing Nothing (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym")
-             , makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")
-             , makeAttr "EdgeTarget" ["edgetarget"] "E" EStrng Nothing Nothing (Just "none") Nothing (Just "svg, map only")
-             , makeAttr "EdgeTooltip" ["edgetooltip"] "E" EStrng Nothing Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")
-             , makeAttr "Epsilon" ["epsilon"] "G" Dbl Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only")
-             , makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not dot")
-             , makeAttr "FillColor" ["fillcolor"] "NEC" (Cust "[Color]") Nothing (Just "[X11Color Black]")(Just "@['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters)") Nothing Nothing
-             , makeAttr "FixedSize" ["fixedsize"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing
-             , makeAttr "FontName" ["fontname"] "ENGC" Strng Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing
-             , makeAttr "FontNames" ["fontnames"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only")
-             , makeAttr "FontPath" ["fontpath"] "G" Strng Nothing Nothing (Just "system dependent") Nothing Nothing
-             , makeAttr "FontSize" ["fontsize"] "ENGC" Dbl Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing
-             , makeAttr "ForceLabels" ["forcelabels"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "Only for 'XLabel' attributes, requires Graphviz >= 2.29.0")
-             , makeAttr "GradientAngle" ["gradientangle"] "NCG" Integ Nothing (Just "0") (Just "0") Nothing (Just "requires Graphviz >= 2.29.0")
-             , makeAttr "Group" ["group"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")
-             , makeAttr "HeadURL" ["headURL", "headhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")
-             , makeAttr "HeadClip" ["headclip"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing
-             , makeAttr "HeadLabel" ["headlabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing
-             , makeAttr "HeadPort" ["headport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing
-             , makeAttr "HeadTarget" ["headtarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")
-             , makeAttr "HeadTooltip" ["headtooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")
-             , makeAttr "Height" ["height"] "N" Dbl Nothing (Just "0.5") (Just "@0.5@") (Just "@0.02@") Nothing
-             , makeAttr "ID" ["id"] "GNE" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"") Nothing (Just "svg, postscript, map only")
-             , makeAttr "Image" ["image"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing
-             , makeAttr "ImagePath" ["imagepath"] "G" (Cust "Paths") Nothing (Just "(Paths [])") (Just "@'Paths' []@") Nothing (Just "Printing and parsing is OS-specific, requires Graphviz >= 2.29.0")
-             , makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "NoScale") (Just "@'NoScale'@") Nothing Nothing
-             , makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing
-             , makeAttr "LabelURL" ["labelURL", "labelhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")
-             , makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0")
-             , makeAttr "LabelAngle" ["labelangle"] "E" Dbl Nothing (Just "(-25)") (Just "@-25.0@") (Just "@-180.0@") Nothing
-             , makeAttr "LabelDistance" ["labeldistance"] "E" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing
-             , makeAttr "LabelFloat" ["labelfloat"] "E" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "LabelFontColor" ["labelfontcolor"] "E" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing
-             , makeAttr "LabelFontName" ["labelfontname"] "E" Strng Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing
-             , makeAttr "LabelFontSize" ["labelfontsize"] "E" Dbl Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing
-             , makeAttr "LabelJust" ["labeljust"] "GC" (Cust "Justification") Nothing (Just "JCenter") (Just "@'JCenter'@") Nothing Nothing
-             , makeAttr "LabelLoc" ["labelloc"] "GCN" (Cust "VerticalPlacement") Nothing (Just "VTop") (Just "@'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)") Nothing Nothing
-             , makeAttr "LabelTarget" ["labeltarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")
-             , makeAttr "LabelTooltip" ["labeltooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")
-             , makeAttr "Landscape" ["landscape"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "(LL [])")  (Just "@'LL' []@") Nothing Nothing
-             , makeAttr "LayerSep" ["layersep"] "G" (Cust "LayerSep") Nothing (Just "(LSep \" :\\t\")") (Just "@'LSep' \\\" :\\t\\\"@") Nothing Nothing
-             , makeAttr "Layout" ["layout"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing
-             , makeAttr "Len" ["len"] "E" Dbl Nothing Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only")
-             , makeAttr "LevelsGap" ["levelsgap"] "G" Dbl Nothing (Just "0") (Just "@0.0@") Nothing (Just "neato only")
-             , makeAttr "Levels" ["levels"] "G" Integ Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "sfdp only")
-             , makeAttr "LHead" ["lhead"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")
-             , makeAttr "LHeight" ["LHeight"] "GC" Dbl Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0")
-             , makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only")
-             , makeAttr "LTail" ["ltail"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")
-             , makeAttr "LWidth" ["lwidth"] "GC" Dbl Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0")
-             , makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing
-             , makeAttr "MaxIter" ["maxiter"] "G" Integ Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only")
-             , makeAttr "MCLimit" ["mclimit"] "G" Dbl Nothing (Just "1") (Just "@1.0@") Nothing (Just "dot only")
-             , makeAttr "MinDist" ["mindist"] "G" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "circo only")
-             , makeAttr "MinLen" ["minlen"] "E" Integ Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "dot only")
-             , makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@") Nothing (Just "neato only")
-             , makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "neato only")
-             , makeAttr "Mosek" ["mosek"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software")
-             , makeAttr "NodeSep" ["nodesep"] "G" Dbl Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") (Just "dot only")
-             , makeAttr "NoJustify" ["nojustify"] "GCNE" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "Normalize" ["normalize"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "not dot")
-             , makeAttr "Nslimit" ["nslimit"] "G" Dbl Nothing Nothing Nothing Nothing (Just "dot only")
-             , makeAttr "Nslimit1" ["nslimit1"] "G" Dbl Nothing Nothing Nothing Nothing (Just "dot only")
-             , makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "dot only")
-             , makeAttr "Orientation" ["orientation"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@360.0@") Nothing
-             , makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "BreadthFirst") (Just "@'BreadthFirst'@") Nothing Nothing
-             , makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot")
-             , makeAttr "OverlapScaling" ["overlap_scaling"] "G" Dbl Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "prism only")
-             , makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing (Just "not dot")
-             , makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing (Just "not dot")
-             , makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "(DVal 0.0555)") (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing
-             , makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "Bl") (Just "@'Bl'@") Nothing Nothing
-             , makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing
-             , makeAttr "PenWidth" ["penwidth"] "CNE" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing
-             , makeAttr "Peripheries" ["peripheries"] "NC" Integ Nothing (Just "1") (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing
-             , makeAttr "Pin" ["pin"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "fdp, neato only")
-             , makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only")
-             , makeAttr "Quantum" ["quantum"] "G" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@0.0@") Nothing
-             , makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "dot only")
-             , makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "dot only")
-             , makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ (dot), @[1.0]@ (twopi)") (Just "[0.02]") (Just "twopi, dot only")
-             , makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "Rects" ["rects"] "N" (Cust "[Rect]") Nothing Nothing Nothing Nothing (Just "write only")
-             , makeAttr "Regular" ["regular"] "N" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing
-             , makeAttr "ReMinCross" ["remincross"] "G" Bl (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only")
-             , makeAttr "RepulsiveForce" ["repulsiveforce"] "G" Dbl Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "sfdp only")
-             , makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only")
-             , makeAttr "Rotate" ["rotate"] "G" Integ Nothing (Just "0") (Just "@0@") Nothing Nothing
-             , makeAttr "Rotation" ["rotation"] "G" Dbl Nothing (Just "0") (Just "@0@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0")
-             , makeAttr "SameHead" ["samehead"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")
-             , makeAttr "SameTail" ["sametail"] "E" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only")
-             , makeAttr "SamplePoints" ["samplepoints"] "N" Integ Nothing Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing
-             , makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "twopi only, requires Graphviz >= 2.28.0")
-             , makeAttr "SearchSize" ["searchsize"] "G" Integ Nothing (Just "30") (Just "@30@") Nothing (Just "dot only")
-             , makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not dot")
-             , makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "Ellipse") (Just "@'Ellipse'@") Nothing Nothing
-             , makeAttr "ShapeFile" ["shapefile"] "N" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing
-             , makeAttr "ShowBoxes" ["showboxes"] "ENG" Integ Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "dot only")
-             , makeAttr "Sides" ["sides"] "N" Integ Nothing (Just "4") (Just "@4@") (Just "@0@") Nothing
-             , makeAttr "Size" ["size"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "Skew" ["skew"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing
-             , makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "sfdp only")
-             , makeAttr "SortV" ["sortv"] "GCN" (Cust "Word16") Nothing (Just "0") (Just "@0@") (Just "@0@") Nothing
-             , makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") (Just "SplineEdges") Nothing Nothing Nothing
-             , makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing Nothing Nothing (Just "fdp, neato only")
-             , makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing
-             , makeAttr "StyleSheet" ["stylesheet"] "G" Strng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only")
-             , makeAttr "TailURL" ["tailURL", "tailhref"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only")
-             , makeAttr "TailClip" ["tailclip"] "E" Bl (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing
-             , makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing
-             , makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing
-             , makeAttr "TailTarget" ["tailtarget"] "E" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")
-             , makeAttr "TailTooltip" ["tailtooltip"] "E" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")
-             , makeAttr "Target" ["target"] "ENGC" EStrng Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only")
-             , makeAttr "Tooltip" ["tooltip"] "NEC" EStrng Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only")
-             , makeAttr "TrueColor" ["truecolor"] "G" Bl (Just "True") Nothing Nothing Nothing (Just "bitmap output only")
-             , makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing Nothing (Just "write only")
-             , makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing Nothing (Just "none") Nothing Nothing
-             , makeAttr "VoroMargin" ["voro_margin"] "G" Dbl Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not dot")
-             , makeAttr "Weight" ["weight"] "E" Dbl Nothing Nothing (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing
-             , makeAttr "Width" ["width"] "N" Dbl Nothing (Just "0.75") (Just "@0.75@") (Just "@0.01@") Nothing
-             , makeAttr "XLabel" ["xlabel"] "EN" (Cust "Label") Nothing (Just "(StrLabel \"\")")  (Just "@'StrLabel' \\\"\\\"@") Nothing (Just "requires Graphviz >= 2.29.0")
-             , makeAttr "Z" ["z"] "N" Dbl Nothing (Just "0") (Just "@0.0@") (Just "@-MAXFLOAT@, @-1000@") Nothing
-             ]
+attributes = [
+  -- BEGIN RECEIVE ORGTBL Attributes
+  makeAttr "Damping" ["Damping"] "G" (Dbl) Nothing (Just "0.99") (Just "@0.99@") (Just "@0.0@") (Just "neato only"),
+  makeAttr "K" ["K"] "GC" (Dbl) Nothing (Just "0.3") (Just "@0.3@") (Just "@0@") (Just "sfdp, fdp only"),
+  makeAttr "URL" ["URL", "href"] "ENGC" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, postscript, map only"),
+  makeAttr "ArrowHead" ["arrowhead"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing,
+  makeAttr "ArrowSize" ["arrowsize"] "E" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,
+  makeAttr "ArrowTail" ["arrowtail"] "E" (Cust "ArrowType") Nothing (Just "normal") (Just "@'normal'@") Nothing Nothing,
+  makeAttr "Aspect" ["aspect"] "G" (Cust "AspectType") Nothing Nothing Nothing Nothing (Just "dot only"),
+  makeAttr "BoundingBox" ["bb"] "G" (Cust "Rect") Nothing Nothing Nothing Nothing (Just "write only"),
+  makeAttr "ColorScheme" ["colorscheme"] "ENCG" (Cust "ColorScheme") Nothing (Just "X11") (Just "@'X11'@") Nothing Nothing,
+  makeAttr "BgColor" ["bgcolor"] "GC" (Cust "[Color]") Nothing (Just "[X11Color Transparent]") (Just "@['X11Color' 'Transparent']@") Nothing Nothing,
+  makeAttr "Center" ["center"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "ClusterRank" ["clusterrank"] "G" (Cust "ClusterMode") Nothing (Just "Local") (Just "@'Local'@") Nothing (Just "dot only"),
+  makeAttr "Color" ["color"] "ENC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'Black']@") Nothing Nothing,
+  makeAttr "Comment" ["comment"] "ENG" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,
+  makeAttr "Compound" ["compound"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),
+  makeAttr "Concentrate" ["concentrate"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "Constraint" ["constraint"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing (Just "dot only"),
+  makeAttr "Decorate" ["decorate"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "DefaultDist" ["defaultdist"] "G" (Dbl) Nothing Nothing (Just "@1+(avg. len)*sqrt(abs(V))@") (Just "@epsilon@") (Just "neato only, only if @'Pack' 'DontPack'@"),
+  makeAttr "Dim" ["dim"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only"),
+  makeAttr "Dimen" ["dimen"] "G" (Integ) Nothing (Just "2") (Just "@2@") (Just "@2@") (Just "sfdp, fdp, neato only"),
+  makeAttr "Dir" ["dir"] "E" (Cust "DirType") Nothing Nothing (Just "@'Forward'@ (directed), @'NoDir'@ (undirected)") Nothing Nothing,
+  makeAttr "DirEdgeConstraints" ["diredgeconstraints"] "G" (Cust "DEConstraints") (Just "EdgeConstraints") (Just "NoConstraints") (Just "@'NoConstraints'@") Nothing (Just "neato only"),
+  makeAttr "Distortion" ["distortion"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing,
+  makeAttr "DPI" ["dpi", "resolution"] "G" (Dbl) Nothing Nothing (Just "@96.0@, @0.0@") Nothing (Just "svg, bitmap output only; \\\"resolution\\\" is a synonym"),
+  makeAttr "EdgeURL" ["edgeURL", "edgehref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),
+  makeAttr "EdgeTarget" ["edgetarget"] "E" (EStrng) Nothing Nothing (Just "none") Nothing (Just "svg, map only"),
+  makeAttr "EdgeTooltip" ["edgetooltip"] "E" (EStrng) Nothing Nothing (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),
+  makeAttr "Epsilon" ["epsilon"] "G" (Dbl) Nothing Nothing (Just "@.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)") Nothing (Just "neato only"),
+  makeAttr "ESep" ["esep"] "G" (Cust "DPoint") Nothing (Just "(DVal 3)") (Just "@'DVal' 3@") Nothing (Just "not dot"),
+  makeAttr "FillColor" ["fillcolor"] "NEC" (Cust "[Color]") Nothing (Just "[X11Color Black]") (Just "@['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters)") Nothing Nothing,
+  makeAttr "FixedSize" ["fixedsize"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "FontColor" ["fontcolor"] "ENGC" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,
+  makeAttr "FontName" ["fontname"] "ENGC" (Strng) Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing,
+  makeAttr "FontNames" ["fontnames"] "G" (Cust "SVGFontNames") Nothing (Just "SvgNames") (Just "@'SvgNames'@") Nothing (Just "svg only"),
+  makeAttr "FontPath" ["fontpath"] "G" (Strng) Nothing Nothing (Just "system dependent") Nothing Nothing,
+  makeAttr "FontSize" ["fontsize"] "ENGC" (Dbl) Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing,
+  makeAttr "ForceLabels" ["forcelabels"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "Only for 'XLabel' attributes, requires Graphviz >= 2.29.0"),
+  makeAttr "GradientAngle" ["gradientangle"] "NCG" (Integ) Nothing (Just "0") (Just "0") Nothing (Just "requires Graphviz >= 2.29.0"),
+  makeAttr "Group" ["group"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),
+  makeAttr "HeadURL" ["headURL", "headhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),
+  makeAttr "HeadClip" ["headclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing,
+  makeAttr "HeadLabel" ["headlabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing,
+  makeAttr "HeadPort" ["headport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing,
+  makeAttr "HeadTarget" ["headtarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),
+  makeAttr "HeadTooltip" ["headtooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),
+  makeAttr "Height" ["height"] "N" (Dbl) Nothing (Just "0.5") (Just "@0.5@") (Just "@0.02@") Nothing,
+  makeAttr "ID" ["id"] "GNE" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, postscript, map only"),
+  makeAttr "Image" ["image"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,
+  makeAttr "ImagePath" ["imagepath"] "G" (Cust "Paths") Nothing (Just "(Paths [])") (Just "@'Paths' []@") Nothing (Just "Printing and parsing is OS-specific, requires Graphviz >= 2.29.0"),
+  makeAttr "ImageScale" ["imagescale"] "N" (Cust "ScaleType") (Just "UniformScale") (Just "NoScale") (Just "@'NoScale'@") Nothing Nothing,
+  makeAttr "Label" ["label"] "ENGC" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)") Nothing Nothing,
+  makeAttr "LabelURL" ["labelURL", "labelhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),
+  makeAttr "LabelScheme" ["label_scheme"] "G" (Cust "LabelScheme") Nothing (Just "NotEdgeLabel") (Just "@'NotEdgeLabel'@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),
+  makeAttr "LabelAngle" ["labelangle"] "E" (Dbl) Nothing (Just "(-25)") (Just "@-25.0@") (Just "@-180.0@") Nothing,
+  makeAttr "LabelDistance" ["labeldistance"] "E" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,
+  makeAttr "LabelFloat" ["labelfloat"] "E" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "LabelFontColor" ["labelfontcolor"] "E" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,
+  makeAttr "LabelFontName" ["labelfontname"] "E" (Strng) Nothing (Just "\"Times-Roman\"") (Just "@\\\"Times-Roman\\\"@") Nothing Nothing,
+  makeAttr "LabelFontSize" ["labelfontsize"] "E" (Dbl) Nothing (Just "14") (Just "@14.0@") (Just "@1.0@") Nothing,
+  makeAttr "LabelJust" ["labeljust"] "GC" (Cust "Justification") Nothing (Just "JCenter") (Just "@'JCenter'@") Nothing Nothing,
+  makeAttr "LabelLoc" ["labelloc"] "GCN" (Cust "VerticalPlacement") Nothing (Just "VTop") (Just "@'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)") Nothing Nothing,
+  makeAttr "LabelTarget" ["labeltarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),
+  makeAttr "LabelTooltip" ["labeltooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),
+  makeAttr "Landscape" ["landscape"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "Layer" ["layer"] "EN" (Cust "LayerRange") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "Layers" ["layers"] "G" (Cust "LayerList") Nothing (Just "(LL [])") (Just "@'LL' []@") Nothing Nothing,
+  makeAttr "LayerSep" ["layersep"] "G" (Cust "LayerSep") Nothing (Just "(LSep \" :\\t\")") (Just "@'LSep' \\\" :\\t\\\"@") Nothing Nothing,
+  makeAttr "Layout" ["layout"] "G" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,
+  makeAttr "Len" ["len"] "E" (Dbl) Nothing Nothing (Just "@1.0@ (neato), @0.3@ (fdp)") Nothing (Just "fdp, neato only"),
+  makeAttr "LevelsGap" ["levelsgap"] "G" (Dbl) Nothing (Just "0") (Just "@0.0@") Nothing (Just "neato only"),
+  makeAttr "Levels" ["levels"] "G" (Integ) Nothing (Just "maxBound") (Just "@'maxBound'@") (Just "@0@") (Just "sfdp only"),
+  makeAttr "LHead" ["lhead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),
+  makeAttr "LHeight" ["LHeight"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"),
+  makeAttr "LPos" ["lp"] "EGC" (Cust "Point") Nothing Nothing Nothing Nothing (Just "write only"),
+  makeAttr "LTail" ["ltail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),
+  makeAttr "LWidth" ["lwidth"] "GC" (Dbl) Nothing Nothing Nothing Nothing (Just "write only, requires Graphviz >= 2.28.0"),
+  makeAttr "Margin" ["margin"] "NG" (Cust "DPoint") Nothing Nothing (Just "device dependent") Nothing Nothing,
+  makeAttr "MaxIter" ["maxiter"] "G" (Integ) Nothing Nothing (Just "@100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp)") Nothing (Just "fdp, neato only"),
+  makeAttr "MCLimit" ["mclimit"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") Nothing (Just "dot only"),
+  makeAttr "MinDist" ["mindist"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "circo only"),
+  makeAttr "MinLen" ["minlen"] "E" (Integ) Nothing (Just "1") (Just "@1@") (Just "@0@") (Just "dot only"),
+  makeAttr "Mode" ["mode"] "G" (Cust "ModeType") Nothing (Just "Major") (Just "@'Major'@") Nothing (Just "neato only"),
+  makeAttr "Model" ["model"] "G" (Cust "Model") Nothing (Just "ShortPath") (Just "@'ShortPath'@") Nothing (Just "neato only"),
+  makeAttr "Mosek" ["mosek"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "neato only; requires the Mosek software"),
+  makeAttr "NodeSep" ["nodesep"] "G" (Dbl) Nothing (Just "0.25") (Just "@0.25@") (Just "@0.02@") (Just "dot only"),
+  makeAttr "NoJustify" ["nojustify"] "GCNE" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "Normalize" ["normalize"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "not dot"),
+  makeAttr "Nslimit" ["nslimit"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),
+  makeAttr "Nslimit1" ["nslimit1"] "G" (Dbl) Nothing Nothing Nothing Nothing (Just "dot only"),
+  makeAttr "Ordering" ["ordering"] "GN" (Cust "Order") Nothing Nothing (Just "none") Nothing (Just "dot only"),
+  makeAttr "Orientation" ["orientation"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@360.0@") Nothing,
+  makeAttr "OutputOrder" ["outputorder"] "G" (Cust "OutputMode") Nothing (Just "BreadthFirst") (Just "@'BreadthFirst'@") Nothing Nothing,
+  makeAttr "Overlap" ["overlap"] "G" (Cust "Overlap") (Just "KeepOverlaps") (Just "KeepOverlaps") (Just "@'KeepOverlaps'@") Nothing (Just "not dot"),
+  makeAttr "OverlapScaling" ["overlap_scaling"] "G" (Dbl) Nothing (Just "(-4)") (Just "@-4@") (Just "@-1.0e10@") (Just "prism only"),
+  makeAttr "Pack" ["pack"] "G" (Cust "Pack") (Just "DoPack") (Just "DontPack") (Just "@'DontPack'@") Nothing (Just "not dot"),
+  makeAttr "PackMode" ["packmode"] "G" (Cust "PackMode") Nothing (Just "PackNode") (Just "@'PackNode'@") Nothing (Just "not dot"),
+  makeAttr "Pad" ["pad"] "G" (Cust "DPoint") Nothing (Just "(DVal 0.0555)") (Just "@'DVal' 0.0555@ (4 points)") Nothing Nothing,
+  makeAttr "Page" ["page"] "G" (Cust "Point") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "PageDir" ["pagedir"] "G" (Cust "PageDir") Nothing (Just "Bl") (Just "@'Bl'@") Nothing Nothing,
+  makeAttr "PenColor" ["pencolor"] "C" (Cust "Color") Nothing (Just "(X11Color Black)") (Just "@'X11Color' 'Black'@") Nothing Nothing,
+  makeAttr "PenWidth" ["penwidth"] "CNE" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") Nothing,
+  makeAttr "Peripheries" ["peripheries"] "NC" (Integ) Nothing (Just "1") (Just "shape default (nodes), @1@ (clusters)") (Just "0") Nothing,
+  makeAttr "Pin" ["pin"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "fdp, neato only"),
+  makeAttr "Pos" ["pos"] "EN" (Cust "Pos") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "QuadTree" ["quadtree"] "G" (Cust "QuadType") (Just "NormalQT") (Just "NormalQT") (Just "@'NormalQT'@") Nothing (Just "sfdp only"),
+  makeAttr "Quantum" ["quantum"] "G" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@0.0@") Nothing,
+  makeAttr "Rank" ["rank"] "S" (Cust "RankType") Nothing Nothing Nothing Nothing (Just "dot only"),
+  makeAttr "RankDir" ["rankdir"] "G" (Cust "RankDir") Nothing (Just "FromTop") (Just "@'FromTop'@") Nothing (Just "dot only"),
+  makeAttr "RankSep" ["ranksep"] "G" (Cust "[Double]") Nothing Nothing (Just "@[0.5]@ (dot), @[1.0]@ (twopi)") (Just "[0.02]") (Just "twopi, dot only"),
+  makeAttr "Ratio" ["ratio"] "G" (Cust "Ratios") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "Rects" ["rects"] "N" (Cust "[Rect]") Nothing Nothing Nothing Nothing (Just "write only"),
+  makeAttr "Regular" ["regular"] "N" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing Nothing,
+  makeAttr "ReMinCross" ["remincross"] "G" (Bl) (Just "True") (Just "False") (Just "@'False'@") Nothing (Just "dot only"),
+  makeAttr "RepulsiveForce" ["repulsiveforce"] "G" (Dbl) Nothing (Just "1") (Just "@1.0@") (Just "@0.0@") (Just "sfdp only"),
+  makeAttr "Root" ["root"] "GN" (Cust "Root") (Just "IsCentral") (Just "(NodeName \"\")") (Just "@'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)") Nothing (Just "circo, twopi only"),
+  makeAttr "Rotate" ["rotate"] "G" (Integ) Nothing (Just "0") (Just "@0@") Nothing Nothing,
+  makeAttr "Rotation" ["rotation"] "G" (Dbl) Nothing (Just "0") (Just "@0@") Nothing (Just "sfdp only, requires Graphviz >= 2.28.0"),
+  makeAttr "SameHead" ["samehead"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),
+  makeAttr "SameTail" ["sametail"] "E" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "dot only"),
+  makeAttr "SamplePoints" ["samplepoints"] "N" (Integ) Nothing Nothing (Just "@8@ (output), @20@ (overlap and image maps)") Nothing Nothing,
+  makeAttr "Scale" ["scale"] "G" (Cust "DPoint") Nothing Nothing Nothing Nothing (Just "twopi only, requires Graphviz >= 2.28.0"),
+  makeAttr "SearchSize" ["searchsize"] "G" (Integ) Nothing (Just "30") (Just "@30@") Nothing (Just "dot only"),
+  makeAttr "Sep" ["sep"] "G" (Cust "DPoint") Nothing (Just "(DVal 4)") (Just "@'DVal' 4@") Nothing (Just "not dot"),
+  makeAttr "Shape" ["shape"] "N" (Cust "Shape") Nothing (Just "Ellipse") (Just "@'Ellipse'@") Nothing Nothing,
+  makeAttr "ShapeFile" ["shapefile"] "N" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing Nothing,
+  makeAttr "ShowBoxes" ["showboxes"] "ENG" (Integ) Nothing (Just "0") (Just "@0@") (Just "@0@") (Just "dot only"),
+  makeAttr "Sides" ["sides"] "N" (Integ) Nothing (Just "4") (Just "@4@") (Just "@0@") Nothing,
+  makeAttr "Size" ["size"] "G" (Cust "GraphSize") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "Skew" ["skew"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-100.0@") Nothing,
+  makeAttr "Smoothing" ["smoothing"] "G" (Cust "SmoothType") Nothing (Just "NoSmooth") (Just "@'NoSmooth'@") Nothing (Just "sfdp only"),
+  makeAttr "SortV" ["sortv"] "GCN" (Cust "Word16") Nothing (Just "0") (Just "@0@") (Just "@0@") Nothing,
+  makeAttr "Splines" ["splines"] "G" (Cust "EdgeType") (Just "SplineEdges") (Just "SplineEdges") Nothing Nothing Nothing,
+  makeAttr "Start" ["start"] "G" (Cust "StartType") Nothing Nothing Nothing Nothing (Just "fdp, neato only"),
+  makeAttr "Style" ["style"] "ENC" (Cust "[StyleItem]") Nothing Nothing Nothing Nothing Nothing,
+  makeAttr "StyleSheet" ["stylesheet"] "G" (Strng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg only"),
+  makeAttr "TailURL" ["tailURL", "tailhref"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, map only"),
+  makeAttr "TailClip" ["tailclip"] "E" (Bl) (Just "True") (Just "True") (Just "@'True'@") Nothing Nothing,
+  makeAttr "TailLabel" ["taillabel"] "E" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing Nothing,
+  makeAttr "TailPort" ["tailport"] "E" (Cust "PortPos") Nothing (Just "(CompassPoint CenterPoint)") (Just "@'CompassPoint' 'CenterPoint'@") Nothing Nothing,
+  makeAttr "TailTarget" ["tailtarget"] "E" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),
+  makeAttr "TailTooltip" ["tailtooltip"] "E" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),
+  makeAttr "Target" ["target"] "ENGC" (EStrng) Nothing (Just "\"\"") (Just "none") Nothing (Just "svg, map only"),
+  makeAttr "Tooltip" ["tooltip"] "NEC" (EStrng) Nothing (Just "\"\"") (Just "@\\\"\\\"@") Nothing (Just "svg, cmap only"),
+  makeAttr "TrueColor" ["truecolor"] "G" (Bl) (Just "True") Nothing Nothing Nothing (Just "bitmap output only"),
+  makeAttr "Vertices" ["vertices"] "N" (Cust "[Point]") Nothing Nothing Nothing Nothing (Just "write only"),
+  makeAttr "ViewPort" ["viewport"] "G" (Cust "ViewPort") Nothing Nothing (Just "none") Nothing Nothing,
+  makeAttr "VoroMargin" ["voro_margin"] "G" (Dbl) Nothing (Just "0.05") (Just "@0.05@") (Just "@0.0@") (Just "not dot"),
+  makeAttr "Weight" ["weight"] "E" (Dbl) Nothing Nothing (Just "@1.0@") (Just "@0@ (dot), @1@ (neato,fdp,sfdp)") Nothing,
+  makeAttr "Width" ["width"] "N" (Dbl) Nothing (Just "0.75") (Just "@0.75@") (Just "@0.01@") Nothing,
+  makeAttr "XLabel" ["xlabel"] "EN" (Cust "Label") Nothing (Just "(StrLabel \"\")") (Just "@'StrLabel' \\\"\\\"@") Nothing (Just "requires Graphviz >= 2.29.0"),
+  makeAttr "Z" ["z"] "N" (Dbl) Nothing (Just "0") (Just "@0.0@") (Just "@-MAXFLOAT@, @-1000@") Nothing
+  -- END RECEIVE ORGTBL Attributes
+  ]
 
+{-
+
+When using Emacs with org-mode available, hitting ` C-c C-c ' inside
+the table below should update the actual Haskell code above.
+
+This way, you can more easily edit/update the appropriate values.
+
+* Values in "Allowed names" should be space-separated (and are
+  converted into a list of Strings).
+
+* Used by should consist of a sub-set of `ENGCS'.
+
+* The entries in "Type" should be a valid Haskell value of type
+  'VType' (parens are added).
+
+* An empty cell in the last five columns translates to a `Nothing'
+  value; anything else is wrapped in quotes and then has Just applied to
+  it.  As such, you still need to escape quotes.
+
+* Any entries in 'Parsing default' or "Default value" should be a
+  valid Haskell value (add parens if needed) with the exception that
+  double-quotes should be escaped.
+
+#+ORGTBL: SEND Attributes orgtbl-to-generic :skip 2 :splice t :hline nil :no-escape t :lstart "  makeAttr " :lend "," :llend "" :sep " " :fmt (1 cell-quote 2 cell-to-list 3 cell-quote 4 cell-parens 5 cell-to-maybe 6 cell-to-maybe 7 cell-to-maybe 8 cell-to-maybe 9 cell-to-maybe)
+| Constructor        | Allowed names      | Used By | Type                     | Parsing default | Default value              | Default for Documentation                                                | Minimum                         | Comment notes                                                    |
+|--------------------+--------------------+---------+--------------------------+-----------------+----------------------------+--------------------------------------------------------------------------+---------------------------------+------------------------------------------------------------------|
+| Damping            | Damping            | G       | Dbl                      |                 | 0.99                       | @0.99@                                                                   | @0.0@                           | neato only                                                       |
+| K                  | K                  | GC      | Dbl                      |                 | 0.3                        | @0.3@                                                                    | @0@                             | sfdp, fdp only                                                   |
+| URL                | URL href           | ENGC    | EStrng                   |                 | \"\"                       | none                                                                     |                                 | svg, postscript, map only                                        |
+| ArrowHead          | arrowhead          | E       | Cust "ArrowType"         |                 | normal                     | @'normal'@                                                               |                                 |                                                                  |
+| ArrowSize          | arrowsize          | E       | Dbl                      |                 | 1                          | @1.0@                                                                    | @0.0@                           |                                                                  |
+| ArrowTail          | arrowtail          | E       | Cust "ArrowType"         |                 | normal                     | @'normal'@                                                               |                                 |                                                                  |
+| Aspect             | aspect             | G       | Cust "AspectType"        |                 |                            |                                                                          |                                 | dot only                                                         |
+| BoundingBox        | bb                 | G       | Cust "Rect"              |                 |                            |                                                                          |                                 | write only                                                       |
+| ColorScheme        | colorscheme        | ENCG    | Cust "ColorScheme"       |                 | X11                        | @'X11'@                                                                  |                                 |                                                                  |
+| BgColor            | bgcolor            | GC      | Cust "[Color]"           |                 | [X11Color Transparent]     | @['X11Color' 'Transparent']@                                             |                                 |                                                                  |
+| Center             | center             | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| ClusterRank        | clusterrank        | G       | Cust "ClusterMode"       |                 | Local                      | @'Local'@                                                                |                                 | dot only                                                         |
+| Color              | color              | ENC     | Cust "[Color]"           |                 | [X11Color Black]           | @['X11Color' 'Black']@                                                   |                                 |                                                                  |
+| Comment            | comment            | ENG     | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 |                                                                  |
+| Compound           | compound           | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 | dot only                                                         |
+| Concentrate        | concentrate        | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| Constraint         | constraint         | E       | Bl                       | True            | True                       | @'True'@                                                                 |                                 | dot only                                                         |
+| Decorate           | decorate           | E       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| DefaultDist        | defaultdist        | G       | Dbl                      |                 |                            | @1+(avg. len)*sqrt(abs(V))@                                              | @epsilon@                       | neato only, only if @'Pack' 'DontPack'@                          |
+| Dim                | dim                | G       | Integ                    |                 | 2                          | @2@                                                                      | @2@                             | sfdp, fdp, neato only                                            |
+| Dimen              | dimen              | G       | Integ                    |                 | 2                          | @2@                                                                      | @2@                             | sfdp, fdp, neato only                                            |
+| Dir                | dir                | E       | Cust "DirType"           |                 |                            | @'Forward'@ (directed), @'NoDir'@ (undirected)                           |                                 |                                                                  |
+| DirEdgeConstraints | diredgeconstraints | G       | Cust "DEConstraints"     | EdgeConstraints | NoConstraints              | @'NoConstraints'@                                                        |                                 | neato only                                                       |
+| Distortion         | distortion         | N       | Dbl                      |                 | 0                          | @0.0@                                                                    | @-100.0@                        |                                                                  |
+| DPI                | dpi resolution     | G       | Dbl                      |                 |                            | @96.0@, @0.0@                                                            |                                 | svg, bitmap output only; \\\"resolution\\\" is a synonym         |
+| EdgeURL            | edgeURL edgehref   | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, map only                                                    |
+| EdgeTarget         | edgetarget         | E       | EStrng                   |                 |                            | none                                                                     |                                 | svg, map only                                                    |
+| EdgeTooltip        | edgetooltip        | E       | EStrng                   |                 |                            | @\\\"\\\"@                                                               |                                 | svg, cmap only                                                   |
+| Epsilon            | epsilon            | G       | Dbl                      |                 |                            | @.0001 * # nodes@ (@mode == 'KK'@), @.0001@ (@mode == 'Major'@)          |                                 | neato only                                                       |
+| ESep               | esep               | G       | Cust "DPoint"            |                 | (DVal 3)                   | @'DVal' 3@                                                               |                                 | not dot                                                          |
+| FillColor          | fillcolor          | NEC     | Cust "[Color]"           |                 | [X11Color Black]           | @['X11Color' 'LightGray']@ (nodes), @['X11Color' 'Black']@ (clusters)    |                                 |                                                                  |
+| FixedSize          | fixedsize          | N       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| FontColor          | fontcolor          | ENGC    | Cust "Color"             |                 | (X11Color Black)           | @'X11Color' 'Black'@                                                     |                                 |                                                                  |
+| FontName           | fontname           | ENGC    | Strng                    |                 | \"Times-Roman\"            | @\\\"Times-Roman\\\"@                                                    |                                 |                                                                  |
+| FontNames          | fontnames          | G       | Cust "SVGFontNames"      |                 | SvgNames                   | @'SvgNames'@                                                             |                                 | svg only                                                         |
+| FontPath           | fontpath           | G       | Strng                    |                 |                            | system dependent                                                         |                                 |                                                                  |
+| FontSize           | fontsize           | ENGC    | Dbl                      |                 | 14                         | @14.0@                                                                   | @1.0@                           |                                                                  |
+| ForceLabels        | forcelabels        | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 | Only for 'XLabel' attributes, requires Graphviz >= 2.29.0        |
+| GradientAngle      | gradientangle      | NCG     | Integ                    |                 | 0                          | 0                                                                        |                                 | requires Graphviz >= 2.29.0                                      |
+| Group              | group              | N       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | dot only                                                         |
+| HeadURL            | headURL headhref   | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, map only                                                    |
+| HeadClip           | headclip           | E       | Bl                       | True            | True                       | @'True'@                                                                 |                                 |                                                                  |
+| HeadLabel          | headlabel          | E       | Cust "Label"             |                 | (StrLabel \"\")            | @'StrLabel' \\\"\\\"@                                                    |                                 |                                                                  |
+| HeadPort           | headport           | E       | Cust "PortPos"           |                 | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@                                           |                                 |                                                                  |
+| HeadTarget         | headtarget         | E       | EStrng                   |                 | \"\"                       | none                                                                     |                                 | svg, map only                                                    |
+| HeadTooltip        | headtooltip        | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, cmap only                                                   |
+| Height             | height             | N       | Dbl                      |                 | 0.5                        | @0.5@                                                                    | @0.02@                          |                                                                  |
+| ID                 | id                 | GNE     | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, postscript, map only                                        |
+| Image              | image              | N       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 |                                                                  |
+| ImagePath          | imagepath          | G       | Cust "Paths"             |                 | (Paths [])                 | @'Paths' []@                                                             |                                 | Printing and parsing is OS-specific, requires Graphviz >= 2.29.0 |
+| ImageScale         | imagescale         | N       | Cust "ScaleType"         | UniformScale    | NoScale                    | @'NoScale'@                                                              |                                 |                                                                  |
+| Label              | label              | ENGC    | Cust "Label"             |                 | (StrLabel \"\")            | @'StrLabel' \\\"\\\\N\\\"@ (nodes), @'StrLabel' \\\"\\\"@ (otherwise)    |                                 |                                                                  |
+| LabelURL           | labelURL labelhref | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, map only                                                    |
+| LabelScheme        | label_scheme       | G       | Cust "LabelScheme"       |                 | NotEdgeLabel               | @'NotEdgeLabel'@                                                         |                                 | sfdp only, requires Graphviz >= 2.28.0                           |
+| LabelAngle         | labelangle         | E       | Dbl                      |                 | (-25)                      | @-25.0@                                                                  | @-180.0@                        |                                                                  |
+| LabelDistance      | labeldistance      | E       | Dbl                      |                 | 1                          | @1.0@                                                                    | @0.0@                           |                                                                  |
+| LabelFloat         | labelfloat         | E       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| LabelFontColor     | labelfontcolor     | E       | Cust "Color"             |                 | (X11Color Black)           | @'X11Color' 'Black'@                                                     |                                 |                                                                  |
+| LabelFontName      | labelfontname      | E       | Strng                    |                 | \"Times-Roman\"            | @\\\"Times-Roman\\\"@                                                    |                                 |                                                                  |
+| LabelFontSize      | labelfontsize      | E       | Dbl                      |                 | 14                         | @14.0@                                                                   | @1.0@                           |                                                                  |
+| LabelJust          | labeljust          | GC      | Cust "Justification"     |                 | JCenter                    | @'JCenter'@                                                              |                                 |                                                                  |
+| LabelLoc           | labelloc           | GCN     | Cust "VerticalPlacement" |                 | VTop                       | @'VTop'@ (clusters), @'VBottom'@ (root graphs), @'VCenter'@ (nodes)      |                                 |                                                                  |
+| LabelTarget        | labeltarget        | E       | EStrng                   |                 | \"\"                       | none                                                                     |                                 | svg, map only                                                    |
+| LabelTooltip       | labeltooltip       | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, cmap only                                                   |
+| Landscape          | landscape          | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| Layer              | layer              | EN      | Cust "LayerRange"        |                 |                            |                                                                          |                                 |                                                                  |
+| Layers             | layers             | G       | Cust "LayerList"         |                 | (LL [])                    | @'LL' []@                                                                |                                 |                                                                  |
+| LayerSep           | layersep           | G       | Cust "LayerSep"          |                 | (LSep \" :\\t\")           | @'LSep' \\\" :\\t\\\"@                                                   |                                 |                                                                  |
+| Layout             | layout             | G       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 |                                                                  |
+| Len                | len                | E       | Dbl                      |                 |                            | @1.0@ (neato), @0.3@ (fdp)                                               |                                 | fdp, neato only                                                  |
+| LevelsGap          | levelsgap          | G       | Dbl                      |                 | 0                          | @0.0@                                                                    |                                 | neato only                                                       |
+| Levels             | levels             | G       | Integ                    |                 | maxBound                   | @'maxBound'@                                                             | @0@                             | sfdp only                                                        |
+| LHead              | lhead              | E       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | dot only                                                         |
+| LHeight            | LHeight            | GC      | Dbl                      |                 |                            |                                                                          |                                 | write only, requires Graphviz >= 2.28.0                          |
+| LPos               | lp                 | EGC     | Cust "Point"             |                 |                            |                                                                          |                                 | write only                                                       |
+| LTail              | ltail              | E       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | dot only                                                         |
+| LWidth             | lwidth             | GC      | Dbl                      |                 |                            |                                                                          |                                 | write only, requires Graphviz >= 2.28.0                          |
+| Margin             | margin             | NG      | Cust "DPoint"            |                 |                            | device dependent                                                         |                                 |                                                                  |
+| MaxIter            | maxiter            | G       | Integ                    |                 |                            | @100 * # nodes@ (@mode == 'KK'@), @200@ (@mode == 'Major'@), @600@ (fdp) |                                 | fdp, neato only                                                  |
+| MCLimit            | mclimit            | G       | Dbl                      |                 | 1                          | @1.0@                                                                    |                                 | dot only                                                         |
+| MinDist            | mindist            | G       | Dbl                      |                 | 1                          | @1.0@                                                                    | @0.0@                           | circo only                                                       |
+| MinLen             | minlen             | E       | Integ                    |                 | 1                          | @1@                                                                      | @0@                             | dot only                                                         |
+| Mode               | mode               | G       | Cust "ModeType"          |                 | Major                      | @'Major'@                                                                |                                 | neato only                                                       |
+| Model              | model              | G       | Cust "Model"             |                 | ShortPath                  | @'ShortPath'@                                                            |                                 | neato only                                                       |
+| Mosek              | mosek              | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 | neato only; requires the Mosek software                          |
+| NodeSep            | nodesep            | G       | Dbl                      |                 | 0.25                       | @0.25@                                                                   | @0.02@                          | dot only                                                         |
+| NoJustify          | nojustify          | GCNE    | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| Normalize          | normalize          | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 | not dot                                                          |
+| Nslimit            | nslimit            | G       | Dbl                      |                 |                            |                                                                          |                                 | dot only                                                         |
+| Nslimit1           | nslimit1           | G       | Dbl                      |                 |                            |                                                                          |                                 | dot only                                                         |
+| Ordering           | ordering           | GN      | Cust "Order"             |                 |                            | none                                                                     |                                 | dot only                                                         |
+| Orientation        | orientation        | N       | Dbl                      |                 | 0                          | @0.0@                                                                    | @360.0@                         |                                                                  |
+| OutputOrder        | outputorder        | G       | Cust "OutputMode"        |                 | BreadthFirst               | @'BreadthFirst'@                                                         |                                 |                                                                  |
+| Overlap            | overlap            | G       | Cust "Overlap"           | KeepOverlaps    | KeepOverlaps               | @'KeepOverlaps'@                                                         |                                 | not dot                                                          |
+| OverlapScaling     | overlap_scaling    | G       | Dbl                      |                 | (-4)                       | @-4@                                                                     | @-1.0e10@                       | prism only                                                       |
+| Pack               | pack               | G       | Cust "Pack"              | DoPack          | DontPack                   | @'DontPack'@                                                             |                                 | not dot                                                          |
+| PackMode           | packmode           | G       | Cust "PackMode"          |                 | PackNode                   | @'PackNode'@                                                             |                                 | not dot                                                          |
+| Pad                | pad                | G       | Cust "DPoint"            |                 | (DVal 0.0555)              | @'DVal' 0.0555@ (4 points)                                               |                                 |                                                                  |
+| Page               | page               | G       | Cust "Point"             |                 |                            |                                                                          |                                 |                                                                  |
+| PageDir            | pagedir            | G       | Cust "PageDir"           |                 | Bl                         | @'Bl'@                                                                   |                                 |                                                                  |
+| PenColor           | pencolor           | C       | Cust "Color"             |                 | (X11Color Black)           | @'X11Color' 'Black'@                                                     |                                 |                                                                  |
+| PenWidth           | penwidth           | CNE     | Dbl                      |                 | 1                          | @1.0@                                                                    | @0.0@                           |                                                                  |
+| Peripheries        | peripheries        | NC      | Integ                    |                 | 1                          | shape default (nodes), @1@ (clusters)                                    | 0                               |                                                                  |
+| Pin                | pin                | N       | Bl                       | True            | False                      | @'False'@                                                                |                                 | fdp, neato only                                                  |
+| Pos                | pos                | EN      | Cust "Pos"               |                 |                            |                                                                          |                                 |                                                                  |
+| QuadTree           | quadtree           | G       | Cust "QuadType"          | NormalQT        | NormalQT                   | @'NormalQT'@                                                             |                                 | sfdp only                                                        |
+| Quantum            | quantum            | G       | Dbl                      |                 | 0                          | @0.0@                                                                    | @0.0@                           |                                                                  |
+| Rank               | rank               | S       | Cust "RankType"          |                 |                            |                                                                          |                                 | dot only                                                         |
+| RankDir            | rankdir            | G       | Cust "RankDir"           |                 | FromTop                    | @'FromTop'@                                                              |                                 | dot only                                                         |
+| RankSep            | ranksep            | G       | Cust "[Double]"          |                 |                            | @[0.5]@ (dot), @[1.0]@ (twopi)                                           | [0.02]                          | twopi, dot only                                                  |
+| Ratio              | ratio              | G       | Cust "Ratios"            |                 |                            |                                                                          |                                 |                                                                  |
+| Rects              | rects              | N       | Cust "[Rect]"            |                 |                            |                                                                          |                                 | write only                                                       |
+| Regular            | regular            | N       | Bl                       | True            | False                      | @'False'@                                                                |                                 |                                                                  |
+| ReMinCross         | remincross         | G       | Bl                       | True            | False                      | @'False'@                                                                |                                 | dot only                                                         |
+| RepulsiveForce     | repulsiveforce     | G       | Dbl                      |                 | 1                          | @1.0@                                                                    | @0.0@                           | sfdp only                                                        |
+| Root               | root               | GN      | Cust "Root"              | IsCentral       | (NodeName \"\")            | @'NodeName' \\\"\\\"@ (graphs), @'NotCentral'@ (nodes)                   |                                 | circo, twopi only                                                |
+| Rotate             | rotate             | G       | Integ                    |                 | 0                          | @0@                                                                      |                                 |                                                                  |
+| Rotation           | rotation           | G       | Dbl                      |                 | 0                          | @0@                                                                      |                                 | sfdp only, requires Graphviz >= 2.28.0                           |
+| SameHead           | samehead           | E       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | dot only                                                         |
+| SameTail           | sametail           | E       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | dot only                                                         |
+| SamplePoints       | samplepoints       | N       | Integ                    |                 |                            | @8@ (output), @20@ (overlap and image maps)                              |                                 |                                                                  |
+| Scale              | scale              | G       | Cust "DPoint"            |                 |                            |                                                                          |                                 | twopi only, requires Graphviz >= 2.28.0                          |
+| SearchSize         | searchsize         | G       | Integ                    |                 | 30                         | @30@                                                                     |                                 | dot only                                                         |
+| Sep                | sep                | G       | Cust "DPoint"            |                 | (DVal 4)                   | @'DVal' 4@                                                               |                                 | not dot                                                          |
+| Shape              | shape              | N       | Cust "Shape"             |                 | Ellipse                    | @'Ellipse'@                                                              |                                 |                                                                  |
+| ShapeFile          | shapefile          | N       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 |                                                                  |
+| ShowBoxes          | showboxes          | ENG     | Integ                    |                 | 0                          | @0@                                                                      | @0@                             | dot only                                                         |
+| Sides              | sides              | N       | Integ                    |                 | 4                          | @4@                                                                      | @0@                             |                                                                  |
+| Size               | size               | G       | Cust "GraphSize"         |                 |                            |                                                                          |                                 |                                                                  |
+| Skew               | skew               | N       | Dbl                      |                 | 0                          | @0.0@                                                                    | @-100.0@                        |                                                                  |
+| Smoothing          | smoothing          | G       | Cust "SmoothType"        |                 | NoSmooth                   | @'NoSmooth'@                                                             |                                 | sfdp only                                                        |
+| SortV              | sortv              | GCN     | Cust "Word16"            |                 | 0                          | @0@                                                                      | @0@                             |                                                                  |
+| Splines            | splines            | G       | Cust "EdgeType"          | SplineEdges     | SplineEdges                |                                                                          |                                 |                                                                  |
+| Start              | start              | G       | Cust "StartType"         |                 |                            |                                                                          |                                 | fdp, neato only                                                  |
+| Style              | style              | ENC     | Cust "[StyleItem]"       |                 |                            |                                                                          |                                 |                                                                  |
+| StyleSheet         | stylesheet         | G       | Strng                    |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg only                                                         |
+| TailURL            | tailURL tailhref   | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, map only                                                    |
+| TailClip           | tailclip           | E       | Bl                       | True            | True                       | @'True'@                                                                 |                                 |                                                                  |
+| TailLabel          | taillabel          | E       | Cust "Label"             |                 | (StrLabel \"\")            | @'StrLabel' \\\"\\\"@                                                    |                                 |                                                                  |
+| TailPort           | tailport           | E       | Cust "PortPos"           |                 | (CompassPoint CenterPoint) | @'CompassPoint' 'CenterPoint'@                                           |                                 |                                                                  |
+| TailTarget         | tailtarget         | E       | EStrng                   |                 | \"\"                       | none                                                                     |                                 | svg, map only                                                    |
+| TailTooltip        | tailtooltip        | E       | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, cmap only                                                   |
+| Target             | target             | ENGC    | EStrng                   |                 | \"\"                       | none                                                                     |                                 | svg, map only                                                    |
+| Tooltip            | tooltip            | NEC     | EStrng                   |                 | \"\"                       | @\\\"\\\"@                                                               |                                 | svg, cmap only                                                   |
+| TrueColor          | truecolor          | G       | Bl                       | True            |                            |                                                                          |                                 | bitmap output only                                               |
+| Vertices           | vertices           | N       | Cust "[Point]"           |                 |                            |                                                                          |                                 | write only                                                       |
+| ViewPort           | viewport           | G       | Cust "ViewPort"          |                 |                            | none                                                                     |                                 |                                                                  |
+| VoroMargin         | voro_margin        | G       | Dbl                      |                 | 0.05                       | @0.05@                                                                   | @0.0@                           | not dot                                                          |
+| Weight             | weight             | E       | Dbl                      |                 |                            | @1.0@                                                                    | @0@ (dot), @1@ (neato,fdp,sfdp) |                                                                  |
+| Width              | width              | N       | Dbl                      |                 | 0.75                       | @0.75@                                                                   | @0.01@                          |                                                                  |
+| XLabel             | xlabel             | EN      | Cust "Label"             |                 | (StrLabel \"\")            | @'StrLabel' \\\"\\\"@                                                    |                                 | requires Graphviz >= 2.29.0                                      |
+| Z                  | z                  | N       | Dbl                      |                 | 0                          | @0.0@                                                                    | @-MAXFLOAT@, @-1000@            |                                                                  |
+
+-}
+
 unknownAttr :: Doc
 unknownAttr = text "UnknownAttribute"
 
+-- For testing purposes
+attrs :: [Attribute]
 attrs = take 10 $ drop 5 attributes
 
+-- For testing purposes
+attrs' :: Atts
 attrs' = AS (text "Attribute") attrs
 
 bool       :: a -> a -> Bool -> a
@@ -617,3 +823,12 @@
 
 dollar :: Doc
 dollar = char '$'
+
+
+-- Local Variables:
+-- eval: (turn-on-orgtbl)
+-- eval: (defun cell-quote (s) (concat "\"" s "\""))
+-- eval: (defun cell-parens (s) (concat "(" s ")"))
+-- eval: (defun cell-to-maybe (s) (if (string= "" s) "Nothing" (cell-parens (concat "Just " (cell-quote s)))))
+-- eval: (defun cell-to-list (s) (concat "[" (mapconcat 'cell-quote (split-string s) ", ") "]"))
+-- END:
