TypeScriptの ための Graphviz ライブラリ
TypeScript に完全に統合された Graphviz DOT言語のモデルとASTを提供します。
- TypeScript フレンドリーな API
- DOT言語のモデルを提供しています。また属性と属性の型まで TypeScript の型定義が用意されています。
- パラダイムからの開放
- オブジェクト指向で設計され、命令的 API と 宣言的 API のどちらにも適合できるAPI提供しています。 プロジェクトにあったパラダイムを選択できます。
- あらゆるユースケースに対応
- モデルを提供する高レイヤーの API と ASTを取り扱う低レイヤーの API をどちらも提供し、あらゆるユースケースに対応します。
このパッケージは、パッケージマネージャを使用してインストールすることができます。
# npm
$ npm install -S ts-graphviz
# or yarn
$ yarn add ts-graphviz
# or pnpm
$ pnpm add ts-graphviz
Deno v1.28 以上では npm をサポートしています。
下記のように指定することで、パッケージをインストールし使用することができます。
import { toDot } from 'npm:ts-graphviz';
この項では、パッケージの概要について説明します。
より詳細なAPIの仕様は、 TypeScript の型定義のコメントやそれを元に自動生成された ドキュメント を参照してください。
DOT 言語をJavaScript/TypeScriptで扱うためのインターフェースである Model を提供します。
Model はオブジェクト指向に設計されており、 Digraph
, Graph
, Subgraph
, Node
, Edge
のクラスを提供しています。
Model を DOT (DOT言語の文字列)に変換するtoDot
関数を提供しています。
import { attribute as _, Digraph, Subgraph, Node, Edge, toDot } from 'ts-graphviz';
const G = new Digraph();
const A = new Subgraph('A');
const node1 = new Node('node1', {
[_.color]: 'red'
});
const node2 = new Node('node2', {
[_.color]: 'blue'
});
const edge = new Edge([node1, node2], {
[_.label]: 'Edge Label',
[_.color]: 'pink'
});
G.addSubgraph(A);
A.addNode(node1);
A.addNode(node2);
A.addEdge(edge);
const dot = toDot(G);
// digraph {
// subgraph "A" {
// "node1" [
// color = "red",
// ];
// "node2" [
// color = "blue",
// ];
// "node1" -> "node2" [
// label = "Edge Label",
// color = "pink",
// ];
// }
// }
高度な使い方
クラスを継承することで独自の実装を加えることもできます。
import { Digraph, Node, Edge, EdgeTargetTuple, attribute as _, toDot } from 'ts-graphviz';
class MyCustomDigraph extends Digraph {
constructor() {
super('G', {
[_.label]: 'This is Custom Digraph',
});
}
}
class MyCustomNode extends Node {
constructor(id: string) {
super(`node_${id}`, {
[_.label]: `This is Custom Node ${id}`,
});
}
}
class MyCustomEdge extends Edge {
constructor(targets: EdgeTargetTuple) {
super(targets, {
[_.label]: 'This is Custom Edge',
});
}
}
const digraph = new MyCustomDigraph();
const node1 = new MyCustomNode('A');
const node2 = new MyCustomNode('B');
const edge = new MyCustomEdge([node1, node2]);
digraph.addNode(node1);
digraph.addNode(node2);
digraph.addEdge(edge);
const dot = toDot(digraph);
// digraph "G" {
// label = "This is Custom Digraph";
// "node_A" [
// label = "This is Custom Node A";
// ];
// "node_B" [
// label = "This is Custom Node B";
// ];
// "node_A" -> "node_B" [
// label = "This is Custom Edge";
// ];
// }
あなたは Models Context API をつかうことで、Graphの内部で生成されるオブジェクトもカスタムクラスにすることができます。
GraphBaseModel
の実装である Digraph
, Graph
, Subgraph
が持つ with
メソッドは、 カスタムモデルを事前定義するために提供されています。
const g = new Digraph();
g.with({
Node: MyCustomNode,
Edge: MyCustomEdge,
});
const a = g.createNode('A'); // MyCustomNode
const b = g.createNode('B'); // MyCustomNode
g.createEdge([a, b]); // MyCustomEdge
const dot = toDot(g);
// digraph {
// "node_A" [
// label = "This is Custom Node A";
// ];
// "node_B" [
// label = "This is Custom Node B";
// ];
// "node_A" -> "node_B" [
// label = "This is Custom Edge";
// ];
// }
このライブラリを使用するメインシナリオは toDot
関数を使用することにありますが、逆方向の変換もサポートしています。
DOT を Model に変換により、コードの一部をDOT言語で記述することができます。
const G = fromDot(
`digraph {
node_A [
label = "This is a Label of Node A";
];
}`,
);
G.edge(['node_A', 'node_B']);
const dot = toDot(G)
// digraph {
// "node_A" [
// label = "This is a Label of Node A";
// ];
// "node_A" -> "node_B";
// }
Graph
や Digraph
を作成する際に、より DOT 言語に近い記法を提供するために Model Factory を使うことができます。
Model にも宣言的な API を用意しており、一貫して宣言的なパラダイムを選択することもできます。
import { attribute as _, digraph, toDot } from 'ts-graphviz';
const G = digraph('G', (g) => {
const a = g.node('aa');
const b = g.node('bb');
const c = g.node('cc');
g.edge([a, b, c], {
[_.color]: 'red'
});
g.subgraph('A', (A) => {
const Aa = A.node('Aaa', {
[_.color]: 'pink'
});
const Ab = A.node('Abb', {
[_.color]: 'violet'
});
const Ac = A.node('Acc');
A.edge([Aa.port('a'), Ab, Ac, 'E'], {
[_.color]: 'red'
});
});
});
const dot = toDot(G);
// digraph "G" {
// "aa";
// "bb";
// "cc";
// subgraph "A" {
// "Aaa" [
// color = "pink",
// ];
// "Abb" [
// color = "violet",
// ];
// "Acc";
// "Aaa":"a" -> "Abb" -> "Acc" -> "E" [
// color = "red",
// ];
// }
// "aa" -> "bb" -> "cc" [
// color = "red",
// ];
// }
Note もちろん、strictモードのグラフを作るAPIも提供しています。
import { strict, toDot } from 'ts-graphviz'; const G = strict.graph(...); const dot = toDot(G); // strict graph { // }
高度な使い方
withContext
関数は、 Model Factory 関数を返します。
この Model Factory は、 Digraph
や Graph
など、 RootGraphModel
をカスタムクラスに置き換える手段を提供します。
これのAPIにより、宣言的APIとカスタムクラスを統合する手段を提供します。
const { digraph } = withContext({
Digraph: MyCustomDigraph,
Node: MyCustomNode,
Edge: MyCustomEdge,
});
const G = digraph((g) => {
const a = g.node('A'); // MyCustomNode
const b = g.node('B'); // MyCustomNode
g.edge([a, b]); // MyCustomEdge
});
const dot = toDot(g);
// digraph "G" {
// label = "This is Custom Digraph";
// "node_A" [
// label = "This is Custom Node A";
// ];
// "node_B" [
// label = "This is Custom Node B";
// ];
// "node_A" -> "node_B" [
// label = "This is Custom Edge";
// ];
// }
Graphviz の dot コマンドを実行するためのインターフェースを提供しています。
Graphviz をインストールし、 dot コマンドを実行できるようにしてください。
dot コマンドを実行し、 DOT 言語の文字列を Stream やファイルに出力します。
このモジュールでは、下記の関数を提供しています。
-
DOT を Stream に変換する
toStream
関数import { toStream } from 'ts-graphviz/adapter'; const dot = ` digraph example { node1 [ label = "My Node", ] } `; const stream = await toStream(dot, { format: 'svg' }); // Node.js stream.pipe(process.stdout); // Deno await stream.pipeTo(Deno.stdout.writable);
-
DOT を指定したパスのファイルに書き出す
toFile
関数import { toFile } from 'ts-graphviz/adapter'; const dot = ` digraph example { node1 [ label = "My Node", ] } `; await toFile(dot, './result.svg', { format: 'svg' });
Node.js と Deno で動作するように設計されており、 Stream はランタイムネイティブです。
高度な利用のためにASTを扱うためのAPIを提供しています。
状態遷移図で記載している通り、下記の関数を提供しています。
- Model から AST に変換する
fromModel
関数 - AST から Model に変換する
toModel
関数 - AST から DOT に変換する
stringify
関数 - DOT から AST に変換する
parse
関数
Note 上記の図からわかるように、
ts-graphviz
パッケージで提供しているtoDot
関数は、fromModel
とstringify
の合成関数です。また、fromDot
関数は、parse
とtoModel
の合成関数です。
詳しい利用方法は整備中です。 TypeScriptの型定義を参考にしてください。
parse 関数とAST
import { parse } from 'ts-graphviz/ast';
const ast = parse(`
digraph example {
node1 [
label = "My Node",
]
}
`);
// {
// type: 'Dot',
// location: {
// start: { offset: 3, line: 2, column: 3 },
// end: { offset: 68, line: 7, column: 1 }
// },
// children: [
// {
// id: {
// value: 'example',
// quoted: false,
// type: 'Literal',
// location: {
// start: { offset: 11, line: 2, column: 11 },
// end: { offset: 18, line: 2, column: 18 }
// },
// children: []
// },
// directed: true,
// strict: false,
// type: 'Graph',
// location: {
// start: { offset: 3, line: 2, column: 3 },
// end: { offset: 67, line: 6, column: 4 }
// },
// children: [
// {
// id: {
// value: 'node1',
// quoted: false,
// type: 'Literal',
// location: {
// start: { offset: 25, line: 3, column: 5 },
// end: { offset: 30, line: 3, column: 10 }
// },
// children: []
// },
// type: 'Node',
// location: {
// start: { offset: 25, line: 3, column: 5 },
// end: { offset: 63, line: 5, column: 6 }
// },
// children: [
// {
// key: {
// value: 'label',
// quoted: false,
// type: 'Literal',
// location: {
// start: { offset: 39, line: 4, column: 7 },
// end: { offset: 44, line: 4, column: 12 }
// },
// children: []
// },
// value: {
// value: 'My Node',
// quoted: true,
// type: 'Literal',
// location: {
// start: { offset: 47, line: 4, column: 15 },
// end: { offset: 56, line: 4, column: 24 }
// },
// children: []
// },
// location: {
// start: { offset: 39, line: 4, column: 7 },
// end: { offset: 57, line: 4, column: 25 }
// },
// type: 'Attribute',
// children: []
// }
// ]
// }
// ]
// }
// ]
// }
Note 他に知っていたら GitHub Discussions で教えてください 🙏
関連するプロジェクトは ts-graphviz GitHub Organization で確認することができます。
TypeScript/JavaScript エコシステムで Graphviz との結合度を高め、より使いやすくすることを目的に様々な OSS を提供しています。
この素晴らしい人たち(emoji key)に感謝します。
Yuki Yamazaki 💻 |
LaySent 🐛 |
elasticdotventures 📖 |
Christian Murphy 💻 🤔 📖 |
Artem 🐛 |
fredericohpandolfo 🐛 |
このプロジェクトは、all-contributors の仕様に準拠しています。
どのような種類の貢献でも歓迎します。
一番簡単な貢献の方法は、ライブラリを使っていただくことと、 リポジトリ にスターをつけることです。
GitHub Discussions で気軽に質問してください。
GitHub Issues から登録してください。
CONTRIBUTING.md を参照してください。
コアメンバーの kamiazya を支援してください。
Note たった1ドルでも、私には十分な開発のモチベーションになります 😊
本ソフトウェアはMITライセンスのもとで公開されています。 LICENSEを参照してください。