GraphStream
This commit is contained in:
		| @@ -1,10 +0,0 @@ | ||||
| export enum GraphLayouts { | ||||
|   neato = 'neato', | ||||
|   dot = 'dot', | ||||
|   circo = 'circo', | ||||
|   fdp = 'fdp', | ||||
|   sfdp = 'sfdp', | ||||
|   osage = 'osage', | ||||
|   twopi = 'twopi', | ||||
|   patchwork = 'patchwork' | ||||
| } | ||||
							
								
								
									
										10
									
								
								lib/Helper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/Helper.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| function validate_name (name: string): string { | ||||
|   const new_name = name | ||||
|     .replace (/[^a-z0-9]/giu, '') | ||||
|     .replace (/^[0-9]+/iu, ''); | ||||
|   if (new_name === '') | ||||
|     throw new Error (`invalid node name ${name}`); | ||||
|   return new_name; | ||||
| } | ||||
|  | ||||
| export { validate_name }; | ||||
| @@ -1,33 +0,0 @@ | ||||
| enum EdgeStyles { | ||||
|   default = '', | ||||
|   solid = 'solid', | ||||
|   dashed = 'dashed', | ||||
|   dotted='dotted', | ||||
|   bold='bold' | ||||
| } | ||||
|  | ||||
| enum NodeStyles { | ||||
|   default = '', | ||||
|   solid='solid', | ||||
|   dashed='dashed', | ||||
|   dotted='dotted', | ||||
|   bold='bold', | ||||
|   rounded='rounded', | ||||
|   diagonals='diagonals', | ||||
|   filled='filled', | ||||
|   striped='striped', | ||||
|   wedged='wedged', | ||||
|   invisible='invis' | ||||
| } | ||||
|  | ||||
| enum GraphStyles { | ||||
|   solid = 'solid', | ||||
|   dashed = 'dashed', | ||||
|   dotted = 'dotted', | ||||
|   bold = 'bold', | ||||
|   rounded = 'rounded', | ||||
|   filled = 'filled', | ||||
|   striped = 'striped' | ||||
| } | ||||
|  | ||||
| export { EdgeStyles, NodeStyles, GraphStyles }; | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { EdgeStyles } from './Styles'; | ||||
| import { EdgeStyles } from '../enums/Styles'; | ||||
| import { Color } from './Color'; | ||||
| 
 | ||||
| export class Edge { | ||||
| @@ -1,3 +1,5 @@ | ||||
| import { validate_name } from '../Helper'; | ||||
| 
 | ||||
| export class Element { | ||||
|   private _name = ''; | ||||
|   protected parent_name: string; | ||||
| @@ -13,11 +15,7 @@ export class Element { | ||||
|   } | ||||
| 
 | ||||
|   public set name (val: string) { | ||||
|     const new_name = val.replace (/[^a-z0-9]/giu, '') | ||||
|       .replace (/^[0-9]+/iu, ''); | ||||
|     if (new_name === '') | ||||
|       throw new Error (`invalid node name ${val}`); | ||||
|     this._name = new_name; | ||||
|     this._name = validate_name (val); | ||||
|   } | ||||
| 
 | ||||
|   public get parent (): string { | ||||
| @@ -1,9 +1,9 @@ | ||||
| import { GraphStyles, NodeStyles } from '../enums/Styles'; | ||||
| import { GraphLayouts } from '../enums/GraphLayouts'; | ||||
| import { Element } from './Element'; | ||||
| import { Edge } from './Edge'; | ||||
| import { Node } from './Node'; | ||||
| import { GraphStyles, NodeStyles } from './Styles'; | ||||
| import { Color } from './Color'; | ||||
| import { GraphLayouts } from './GraphLayouts'; | ||||
| 
 | ||||
| interface NodeOptions { | ||||
|   name: string; | ||||
							
								
								
									
										160
									
								
								lib/classes/GraphStream.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								lib/classes/GraphStream.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| /* eslint-disable line-comment-position */ | ||||
| /* eslint-disable no-inline-comments */ | ||||
| import { Transform } from 'stream'; | ||||
| import { GraphStreamJSON } from '../interfaces/GraphStreamJSON'; | ||||
| import { GraphStreamCommand } from '../enums/GraphStreamCommand'; | ||||
|  | ||||
| interface Stringable { | ||||
|   // eslint-disable-next-line @typescript-eslint/naming-convention | ||||
|   toString(): string; | ||||
| } | ||||
|  | ||||
| export class GraphStream extends Transform { | ||||
|   private _path: string[] = []; | ||||
|   private _state = ''; | ||||
|   private _directional = false; | ||||
|  | ||||
|   public get path (): string { | ||||
|     return this._path.join ('_'); | ||||
|   } | ||||
|  | ||||
|   private get level (): string { | ||||
|     return '  '.repeat (this._path.length); | ||||
|   } | ||||
|  | ||||
|   private expect_state (instr: GraphStreamCommand): void { | ||||
|     const states = []; | ||||
|     if ([ | ||||
|       'cug', | ||||
|       'cdg' | ||||
|     ].includes (instr)) | ||||
|       states.push (''); | ||||
|  | ||||
|     if ([ | ||||
|       'eg', | ||||
|       'cn', | ||||
|       'csg', | ||||
|       'ce' | ||||
|     ].includes (instr)) | ||||
|       states.push ('en', 'at', 'eg', 'cug', 'cdg', 'csg', 'ce'); | ||||
|  | ||||
|     switch (instr) { | ||||
|       case 'en': | ||||
|         states.push ('cn', 'at'); | ||||
|         break; | ||||
|       case 'at': | ||||
|         states.push ('cn', 'cug', 'cdg', 'csg'); | ||||
|         break; | ||||
|       default: | ||||
|         break; | ||||
|     } | ||||
|     if (!states.includes (this._state)) { | ||||
|       throw new Error (`invalid state to execute command ${instr} | ||||
|   expected: ${states.join (', ')}`); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // eslint-disable-next-line max-len | ||||
|   // eslint-disable-next-line @typescript-eslint/naming-convention, complexity, max-lines-per-function | ||||
|   public _transform ( | ||||
|     chunk: string, | ||||
|     encoding: string, | ||||
|     callback: ((error?: Error) => unknown) | ||||
|   ): void { | ||||
|     const instr = JSON.parse (chunk) as GraphStreamJSON; | ||||
|     this.expect_state (instr.type); | ||||
|     switch (instr.type) { | ||||
|       case 'cug': // create unordered graph | ||||
|         this._path.push (instr.args[0]); | ||||
|         this.push (`graph ${this.path} {\n`); | ||||
|         this._directional = false; | ||||
|         break; | ||||
|       case 'cdg': // create directional graph | ||||
|         this._path.push (instr.args[0]); | ||||
|         this.push (`digraph ${this.path} {\n`); | ||||
|         this._directional = true; | ||||
|         break; | ||||
|       case 'csg': // create subgraph | ||||
|         this.push ( | ||||
|           `${this.level}subgraph cluster_${this.path}_${instr.args[0]} {\n` | ||||
|         ); | ||||
|         this._path.push (instr.args[0]); | ||||
|         break; | ||||
|       case 'eg': // end graph | ||||
|         this._path.pop (); | ||||
|         this.push (`${this.level}}\n\n`); | ||||
|         break; | ||||
|       case 'cn': // create 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 (', ')}]`); | ||||
|         } | ||||
|         else { | ||||
|           this.push (`${this.level}${ | ||||
|             instr.args.join (`\n${this.level}`) | ||||
|               .replace (/"/gu, '') | ||||
|           }\n\n`); | ||||
|         } | ||||
|         break; | ||||
|       case 'ce': | ||||
|         this.push (`${this.level}${ | ||||
|           instr.args[0] | ||||
|         } -${this._directional ? '>' : '-'} ${instr.args[1]}\n`); | ||||
|         break; | ||||
|       default: | ||||
|         break; | ||||
|     } | ||||
|     this._state = instr.type; | ||||
|     callback (); | ||||
|   } | ||||
|  | ||||
|   public write ( | ||||
|     instr: GraphStreamJSON | ||||
|   ): boolean { | ||||
|     return super.write (JSON.stringify (instr), 'utf-8'); | ||||
|   } | ||||
|  | ||||
|   public create_node (name: string): boolean { | ||||
|     return this.write ({ type: 'cn', args: [ name ] }); | ||||
|   } | ||||
|  | ||||
|   public end_node (): boolean { | ||||
|     return this.write ({ type: 'en', args: [] }); | ||||
|   } | ||||
|  | ||||
|   public create_graph (name: string, type: 'u'|'d'|'s' = 's'): boolean { | ||||
|     const instr_type = `c${type}g` as GraphStreamCommand; | ||||
|     return this.write ({ type: instr_type, args: [ name ] }); | ||||
|   } | ||||
|  | ||||
|   public end_graph (): boolean { | ||||
|     return this.write ({ type: 'eg', args: [] }); | ||||
|   } | ||||
|  | ||||
|   public attributes (attrs: Record<string, Stringable>): boolean { | ||||
|     const solved = []; | ||||
|     for (const attr of Object.keys (attrs)) { | ||||
|       const val = attrs[attr].toString (); | ||||
|       if ((/\n/u).test (val)) | ||||
|         solved.push (`${attr} = <${val}>`); | ||||
|       else | ||||
|         solved.push (`${attr} = "${val}"`); | ||||
|     } | ||||
|     return this.write ({ type: 'at', args: solved }); | ||||
|   } | ||||
|  | ||||
|   public create_edge (origin: string, target: string): boolean { | ||||
|     return this.write ({ | ||||
|       type: 'ce', | ||||
|       args: [ | ||||
|         origin, | ||||
|         target | ||||
|       ] | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { NodeStyles } from '../enums/Styles'; | ||||
| import { Element } from './Element'; | ||||
| import { NodeStyles } from './Styles'; | ||||
| import { Color } from './Color'; | ||||
| 
 | ||||
| export class Node extends Element { | ||||
							
								
								
									
										9
									
								
								lib/enums/GraphLayouts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lib/enums/GraphLayouts.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| export type GraphLayouts = | ||||
|   'neato' | ||||
|   | 'dot' | ||||
|   | 'circo' | ||||
|   | 'fdp' | ||||
|   | 'sfdp' | ||||
|   | 'osage' | ||||
|   | 'twopi' | ||||
|   | 'patchwork' | ||||
							
								
								
									
										11
									
								
								lib/enums/GraphStreamCommand.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								lib/enums/GraphStreamCommand.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| /* eslint-disable line-comment-position */ | ||||
| /* eslint-disable no-inline-comments */ | ||||
| export type GraphStreamCommand = | ||||
|   'cn'| // create node | ||||
|   'en'| // end node | ||||
|   'cug'| // create unordered graph | ||||
|   'cdg'| // create directional graph | ||||
|   'csg'| // create subgraph | ||||
|   'eg'| // end graph | ||||
|   'at'| // add attributes | ||||
|   'ce' // create edge | ||||
							
								
								
									
										32
									
								
								lib/enums/Styles.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lib/enums/Styles.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| type EdgeStyles = | ||||
|   '' | ||||
|   |'solid' | ||||
|   |'dashed' | ||||
|   |'dotted' | ||||
|   |'bold' | ||||
|  | ||||
|  | ||||
| type NodeStyles = | ||||
|   '' | ||||
|   |'solid' | ||||
|   |'dashed' | ||||
|   |'dotted' | ||||
|   |'bold' | ||||
|   |'rounded' | ||||
|   |'diagonals' | ||||
|   |'filled' | ||||
|   |'striped' | ||||
|   |'wedged' | ||||
|   |'invis' | ||||
|  | ||||
|  | ||||
| type GraphStyles = | ||||
|   'solid' | ||||
|   | 'dashed' | ||||
|   | 'dotted' | ||||
|   | 'bold' | ||||
|   | 'rounded' | ||||
|   | 'filled' | ||||
|   | 'striped' | ||||
|  | ||||
| export { EdgeStyles, NodeStyles, GraphStyles }; | ||||
							
								
								
									
										20
									
								
								lib/index.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								lib/index.ts
									
									
									
									
									
								
							| @@ -1,8 +1,12 @@ | ||||
| export { Graph } from './Graph'; | ||||
| export { Node } from './Node'; | ||||
| export { Element } from './Element'; | ||||
| export { Edge } from './Edge'; | ||||
| export { Color } from './Color'; | ||||
| export { EdgeStyles, NodeStyles, GraphStyles } from './Styles'; | ||||
| export { GraphLayouts } from './GraphLayouts'; | ||||
| export { Graphable } from './Graphable'; | ||||
| import { Graph } from './classes/Graph'; | ||||
|  | ||||
| export * from './classes/Color'; | ||||
| export * from './classes/Edge'; | ||||
| export * from './classes/Element'; | ||||
| export { Graph }; | ||||
| export * from './classes/GraphStream'; | ||||
| export * from './classes/Node'; | ||||
| export * from './enums/GraphLayouts'; | ||||
| export * from './enums/Styles'; | ||||
| export * from './interfaces/Graphable'; | ||||
| export default Graph; | ||||
|   | ||||
							
								
								
									
										6
									
								
								lib/interfaces/GraphStreamJSON.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								lib/interfaces/GraphStreamJSON.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| import { GraphStreamCommand } from '../enums/GraphStreamCommand'; | ||||
|  | ||||
| export interface GraphStreamJSON { | ||||
|   type: GraphStreamCommand; | ||||
|   args: string[]; | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Graph } from './Graph'; | ||||
| import { Graph } from '../classes/Graph'; | ||||
| 
 | ||||
| export interface Graphable { | ||||
|   to_graph(g: Graph, ...args: unknown[]): unknown; | ||||
		Reference in New Issue
	
	Block a user