/kaolin-graphs

Draw diagrams based on kaolin schemas

Primary LanguageJavaScript

kaolin-graphs

Generates dependency diagrams of a data model that is specified using Kaolin schemas

Installation

npm install kaolin-graphs

Overview

kaolin-graphs takes a kaolin scope object, and allows you to produce graphvis dot files for graphs of the types in this scope. It provides options to modify the style and detail of these graphs.

Example

The most basic usage is to draw a non-hierarchical graph of all of the types in a scope:

const kaolinGraphs = require("kaolin-graphs");
const writeFileSync = require("fs").writeFileSync;
const scope = require("./some-kaolin-scope");

const graphDescription = kaolinGraphs.dotFormatForScope(scope);

writeFileSync("graph.dot", graphDescription);

This produces the file graph.dot, which can be compiled by graphvis with the following:

cat graph.dot | dot -Tpng -Grankdir=BT > output.png

For the scope given in the example directory, (a schema for the AST of a simple imaginary language) we produce this image: unordered graph

We can produce a graph that partially orders its nodes, by raising types above their dependencies. To customize the graph in this way we can pass an options object to dotFormatForScope:

dotFormatForScope(scope, { ranked: true, rootNodes: ["AST"] });

Producing a more structured graph: ordered graph

We can zoom into the "neighborhood" of a type, that is, the types which it depends on and the types which depend on it, by using the dotFormatForNeighborhood function:

const graphDescription = kaolinGraphs.dotFormatForNeighborhood(ex, "Expression");

basic neighborhood And when focused like this, we can expand the depiction of strictStruct and laxStruct types to show their structure:

dotFormatForNeighborhood(ex, "Expression", { expandStructs: true });

detailed neighborhood

Rendering with Graphviz

To produce images, you need to have Graphvis installed, providing the command line utility dot. The simplest way to render an image is to output the string produced by this library to a file, say temp.txt, and then pipe this file's contents into dot, as in cat temp.txt | dot -Tpng -Grankdir=BT > image.png. The -Tpng option is to select .png as the file's output type; if you wish to output another filetype, do so following graphvis's documentation. -Grankdir=BT is to cause the graph to output correctly when the { ranked: true } option is used. If this command line argument is omitted, then the root nodes will appear at the bottom of the image rather than at the top.

If you wish to render images directly from JavaScript without using a temp file, check scripts/build-examples.js as an example of how to do so.

API

dotFormatForScope(scope, options)

Produces a string in graphvis dot format, representing a drawing of all of the types in the given scope and their relationships.

  • scope: a Kaolin scope object
  • options: an object The schema for options is:
laxStruct({
  rootNodes: optional(array(string())),
  ranked: optional(boolean())
});

Specifying rootNodes and ranked will cause the types to be arranged in a hierarchy based on their dependencies, with the root nodes on top. The strings in the rootNodes array must be the name of types available in the provided scope. If no rootNodes are provided, ranked will have no effect.

dotFormatForNeighborhood(scope, focus, options)

Produces a string in graphvis dot format, representing a drawing of all of the types in the given scope which directly depend on the given focus and which the given focus directly depends on, and their relationships.

  • scope: a Kaolin scope object
  • focus: a string; a type with this name must exist in scope
  • options: an object The schema for options is:
laxStruct({
  expandStructs: optional(boolean(),
  rootNodes: optional(array(string())),
  ranked: optional(boolean())
});

Specifying expandStructs as true will cause structs to be shown in a detailed view, with information on each of their fields. rootNodes and ranked have the same behavior as in dotFormatForScope.

orderTypes(scope, rootNodes)

Produces a data structure containing the types in scope in a hopefully reasonable order, which orders types by the number of hops they are from the root nodes, and secondarily places types before the types which depend on them.

  • scope: a Kaolin scope object
  • rootNodes: an array of type names orderTypes returns an array of nodes which each have this schema:
strictStruct({
  name: string(),
  children: array(string()),
  childCounts: dictionary(string(), number()),
  docString: optional(string()),
  parents: array(string()),
  parentCounts: dictionary(string(), number()),
  siblings: array(string()),
  siblingCounts: dictionary(string(), number()),
  ancestors: array(string()),
  distanceToRoot: number(),
  rank: number()
})

LICENSE

MIT