diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bdd7788 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## 1.2.0 + +Stream: + +- automatically end node instructions +- allow attributes on edges + +## 1.1.0 + +Allow creating graphs using a stream + +## 1.0.0 + +initial version diff --git a/Jenkinsfile b/Jenkinsfile index 12d359d..c4cfc1d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { VERSION = VersionNumber([ versionNumberString: '${BUILDS_ALL_TIME}', - versionPrefix: '1.1.', + versionPrefix: '1.2.', worstResultForIncrement: 'SUCCESS' ]) } diff --git a/README.md b/README.md index 106d4a5..faa23eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # @sapphirecode/graphviz-builder -version: 1.1.x +version: 1.2.x constructing graphviz files using an easy typescript interface diff --git a/lib/classes/GraphStream.ts b/lib/classes/GraphStream.ts index d9c19d6..fdf8faa 100644 --- a/lib/classes/GraphStream.ts +++ b/lib/classes/GraphStream.ts @@ -22,7 +22,11 @@ interface Stringable { export class GraphStream extends Transform { private _path: string[] = []; - private _state: GraphStreamCommand | '' = ''; + private _state: (GraphStreamCommand | '')[] = [ + '', + '' + ]; + private _directional = false; public get path (): string { @@ -33,6 +37,16 @@ export class GraphStream extends Transform { return ' '.repeat (this._path.length); } + private finish_node ():void { + if ( + [ + 'ce', + 'cn' + ].includes (this._state[1]) + ) + this.push ('\n'); + } + private expect_state (instr: GraphStreamCommand): void { const states: (GraphStreamCommand|'')[] = []; if ([ @@ -47,24 +61,21 @@ export class GraphStream extends Transform { 'csg', 'ce' ].includes (instr)) - states.push ('en', 'at', 'eg', 'cug', 'cdg', 'csg', 'ce'); + states.push ('at', 'eg', 'cug', 'cdg', 'csg', 'ce', 'cn'); switch (instr) { - case 'en': - states.push ('cn', 'at'); - break; case 'at': - states.push ('cn', 'cug', 'cdg', 'csg'); + states.push ('cn', 'cug', 'cdg', 'csg', 'ce'); break; default: break; } - if (!states.includes (this._state)) { + if (!states.includes (this._state[1])) { throw new Error (`invalid state to execute command ${ translate_command (instr)} expected: ${states.map ((s) => translate_command (s)) .join (', ')} - actual: ${translate_command (this._state)}`); + actual: ${translate_command (this._state[1])}`); } } @@ -89,24 +100,27 @@ export class GraphStream extends Transform { this._directional = true; break; case 'csg': // create subgraph + this.finish_node (); this.push ( `${this.level}subgraph cluster_${this.path}_${instr.args[0]} {\n` ); this._path.push (instr.args[0]); break; case 'eg': // end graph + this.finish_node (); this._path.pop (); this.push (`${this.level}}\n\n`); break; case 'cn': // create node + this.finish_node (); this.push (`${this.level}${this.path}_${instr.args[0]}`); break; - case 'en': // end node - this.push ('\n'); - break; case 'at': // add attributes - if (this._state === 'cn') { - this.push (` [${instr.args.join (', ')}]`); + if ([ + 'cn', + 'ce' + ].includes (this._state[1])) { + this.push (` [${instr.args.join (', ')}]\n`); } else { this.push (`${this.level}${ @@ -116,14 +130,16 @@ export class GraphStream extends Transform { } break; case 'ce': + this.finish_node (); this.push (`${this.level}${ instr.args[0] - } -${this._directional ? '>' : '-'} ${instr.args[1]}\n`); + } -${this._directional ? '>' : '-'} ${instr.args[1]}`); break; default: break; } - this._state = instr.type; + this._state.push (instr.type); + this._state.shift (); callback (); } @@ -139,8 +155,11 @@ export class GraphStream extends Transform { return `${this.path}_${node_name}`; } + /** + * @deprecated calling this method is not needed anymore + */ public end_node (): void { - this.write ({ type: 'en', args: [] }); + // this.write ({ type: 'en', args: [] }); } public create_graph (name: string, type: 'u'|'d'|'s' = 's'): void { diff --git a/test/Stream.ts b/test/Stream.ts index a3d5366..dbc999a 100644 --- a/test/Stream.ts +++ b/test/Stream.ts @@ -2,7 +2,7 @@ * Copyright (C) Sapphirecode - All Rights Reserved * This file is part of graphviz-builder which is released under MIT. * See file 'LICENSE' for full license details. - * Created by Timo Hocker , May 2020 + * Created by Timo Hocker , June 2020 */ import test from 'ava'; @@ -37,6 +37,7 @@ const complex = `digraph foo { foo_baz [label = "baz"] foo_foo [label = "foo"] foo_foo -> foo_baz + foo_foo -> foo_baz_asd [label = "edge attr"] } `; @@ -76,20 +77,19 @@ test ('complex stream graph', (t) => new Promise ((resolve) => { stream.attributes ({ color: Color.gray, style: 'dotted' }); stream.end_graph (); stream.end_graph (); - stream.create_node ('asd'); + const asd = stream.create_node ('asd'); stream.attributes ({ label: 'asd' }); stream.end_node (); stream.create_node ('test'); stream.attributes ({ style: 'bold', color: Color.gray }); - stream.end_node (); stream.end_graph (); - stream.create_node ('baz'); + const baz = stream.create_node ('baz'); stream.attributes ({ label: 'baz' }); - stream.end_node (); - stream.create_node ('foo'); + const foo = stream.create_node ('foo'); stream.attributes ({ label: 'foo' }); - stream.end_node (); - stream.create_edge (`${stream.path}_foo`, `${stream.path}_baz`); + stream.create_edge (foo, baz); + stream.create_edge (foo, asd); + stream.attributes ({ label: 'edge attr' }); stream.end_graph (); stream.end (); }));