{"id":13397185,"url":"https://github.com/codeout/inet-henge","last_synced_at":"2026-01-12T02:57:55.355Z","repository":{"id":42408245,"uuid":"61119449","full_name":"codeout/inet-henge","owner":"codeout","description":"Generate d3.js based Network Diagram from JSON data.","archived":false,"fork":false,"pushed_at":"2024-08-27T05:14:14.000Z","size":4851,"stargazers_count":257,"open_issues_count":9,"forks_count":38,"subscribers_count":28,"default_branch":"main","last_synced_at":"2024-09-27T16:17:46.683Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codeout.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-14T12:04:06.000Z","updated_at":"2024-09-14T10:03:28.000Z","dependencies_parsed_at":"2023-02-16T08:15:18.861Z","dependency_job_id":"9688cdbd-09c3-4959-bc65-812da2ef6fb5","html_url":"https://github.com/codeout/inet-henge","commit_stats":{"total_commits":281,"total_committers":4,"mean_commits":70.25,"dds":"0.017793594306049876","last_synced_commit":"9cf19a705e70c7556d5bffbf95e7b7bf4b2dddc4"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeout%2Finet-henge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeout%2Finet-henge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeout%2Finet-henge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeout%2Finet-henge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codeout","download_url":"https://codeload.github.com/codeout/inet-henge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243500246,"owners_count":20300761,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T18:01:12.329Z","updated_at":"2026-01-12T02:57:55.347Z","avatar_url":"https://github.com/codeout.png","language":"TypeScript","funding_links":[],"categories":["JavaScript","Library"],"sub_categories":["NETCONF"],"readme":"# inet-henge.js\n\ninet-henge.js generates d3.js based Auto Layout Network Diagram from JSON data.  \ninet-henge helps you draw it by calculating coordinates automatically, placing nodes and links in SVG format.\n\nEach object is draggable and zoomable.\n\n![stone-henge](https://c3.staticflickr.com/6/5480/11307043746_b3b36ccf34_h.jpg)\n\nAll you have to do are:\n\n1. Define nodes identified by name\n2. Define links by specifying both end nodes\n3. Show in a browser. That's it.\n\nJSON example:\n\n```json\n{\n  \"nodes\": [\n    { \"name\": \"A\" },\n    { \"name\": \"B\" }\n  ],\n\n  \"links\": [\n    { \"source\": \"A\", \"target\": \"B\" }\n  ]\n}\n```\n\n## Getting Started\n\n```zsh\nnpm install inet-henge\n\n# or\n\ngit clone https://github.com/codeout/inet-henge.git\n```\n\nThen host the root directory in your favorite web server.\n\n```\nruby -run -e httpd . -p 8000\n```\n\nNow you can see `http://localhost:8000/example`.\n\n```\npython -m SimpleHTTPServer  # python2\npython -m http.server       # python3\n\nor\n\nphp -S 127.0.0.1:8000\n```\n\nare also available to start a web server.\n\n## Demo\n\n- [Shownet 2017 Network](https://codeout.github.io/inet-henge/shownet2017.html)\n- [Shownet 2016 Network](https://codeout.github.io/inet-henge/shownet2016.html)\n\n## Usage\n\nIn example [here](example/shownet.html), load related assets at first:\n\n- d3.js v3\n- cola.js\n  - :warning: **It doesn't support d3.js v4** :warning:\n- inet-henge.js\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n\n    \u003c!-- You can customize a style of network diagram by CSS --\u003e\n    \u003clink href=\"style.css\" rel=\"stylesheet\" /\u003e\n\n    \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"../vendor/cola.min.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"../inet-henge.js\"\u003e\u003c/script\u003e\n  \u003c/head\u003e\n```\n\ndefine a blank container:\n\n```html\n\u003cbody\u003e\n  \u003cdiv id=\"diagram\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\nand render your network diagram:\n\n```html\n  \u003cscript\u003e\n   new Diagram(\"#diagram\", \"shownet.json\").init(\"interface\");\n  \u003c/script\u003e\n\u003c/html\u003e\n```\n\nObject is also acceptable:\n\n```html\n  \u003cscript\u003e\n    const data = {\n      \"nodes\": [{ \"name\": \"A\" }, { \"name\": \"B\" }],\n      \"links\": [{ \"source\": \"A\", \"target\": \"B\" }]\n    };\n   new Diagram(\"#diagram\", data).init(\"interface\");\n  \u003c/script\u003e\n\u003c/html\u003e\n```\n\ninet-henge.js renders your network diagram as SVG within `\u003cdiv id=\"diagram\"\u003e\u003c/div\u003e`. In the example above the diagram also displays metadata labelled `\"interface\"` which defined in JSON data.\n\n![Shownet2016 example](example/images/shownet.png)\n\n### JSON Data\n\nMinimal json looks like:\n\n```json\n{\n  \"nodes\": [\n    { \"name\": \"A\" },\n    { \"name\": \"B\" }\n  ],\n\n  \"links\": [\n    { \"source\": \"A\", \"target\": \"B\" }\n  ]\n}\n```\n\nYou can specify node icon by URL:\n\n```json\n  \"nodes\": [\n    { \"name\": \"dceast-ne40e\", \"icon\": \"./images/router.png\" }\n  ]\n```\n\nMetadata to display on network diagrams:\n\n```js\nnew Diagram(\"#diagram\", \"index.json\").init(\"interface\");\n```\n\n```json\n  \"links\": [\n    {\n      \"source\": \"noc-asr9904\", \"target\": \"noc-ax8616r\",\n      \"meta\": {\n        \"interface\": { \"source\": \"0-0-0-2\", \"target\": \"1-1\" }\n      }\n    }\n  ]\n```\n\n:point_up: This will render metadata on both ends of links.\n\n### Node Group\n\nNodes get rendered in groups when you specify which node belongs to which group by regular expression.\n\nWhen the first three characters describe POP name, you can group nodes by doing this:\n\n```javascript\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { pop: /^.{3}/ });\n```\n\n### Labels\n\nWhen `init()` API is called with arguments, inet-henge finds corresponding metadata and show them as labels.\n\nTo place a loopback address on nodes:\n\n```js\nnew Diagram(\"#diagram\", \"index.json\").init(\"loopback\");\n```\n\n```json\n{\n  \"nodes\": [\n    { \"name\": \"Node 1\", \"meta\": { \"loopback\": \"10.0.0.1\" } },\n    ...\n  ],\n  ...\n}\n```\n\n![Label on node](example/images/node_label.png)\n\nTo place link and interface names:\n\n```js\nnew Diagram(\"#diagram\", \"index.json\").init(\"bandwidth\", \"intf-name\");\n```\n\n```js\n{\n  ...\n  \"links\": [\n    {\n      \"source\": \"Node 1\", \"target\": \"Node 2\",\n      \"meta\": {\n        \"bandwidth\": \"10G\",\n        \"intf-name\": { \"source\": \"interface A\", \"target\": \"interface B\" }\n      }\n    },\n    ...\n  ]\n```\n\n![Label on link](example/images/link_label.png)\n\n### Node Size\n\nYou can change node width and height:\n\n```js\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { nodeWidth: 120, nodeHeight: 30 });\n```\n\n![Node Size](example/images/node_size.png)\n\nWidth `60` and heigh `40` (px) by default.\n\n### Link Width\n\nYou can use `linkWidth()` API to customize link widths. The argument should be a function which calculates metadata and returns value for `stroke-width` of SVG.\n\n```js\nconst diagram = new Diagram(\"#diagram\", \"index.json\");\ndiagram.linkWidth(function (link) {\n  if (!link)\n    return 1;  // px\n  else if (link.bandwidth === \"100G\")\n    return 10; // px\n  else if (link.bandwidth === \"10G\")\n    return 3;  // px\n  else if (link.bandwidth === \"1G\")\n    return 1;  // px\n});\ndiagram.init(\"bandwidth\");\n```\n\n```json\n  \"links\": [\n    { \"source\": \"Node 1\", \"target\": \"Node 2\", \"meta\": { \"bandwidth\": \"1G\" }},\n    { \"source\": \"Node 1\", \"target\": \"Node 3\", \"meta\": { \"bandwidth\": \"10G\" }},\n    { \"source\": \"Node 2\", \"target\": \"Node 3\", \"meta\": { \"bandwidth\": \"100G\" }}\n  ]\n```\n\n![Link width](example/images/link_width.png)\n\n:warning: Make sure no stylesheet overrides customized link widths. :warning:\n\n### Group Size\n\nYou can specify padding to increase the size of groups (default: 1):\n\n```js\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { groupPadding: 30 });\n```\n\n![Group Size](example/images/group_size.png)\n\n:bulb: Position calculation sometimes gets stuck when increasing `groupPadding`. [initialTicks](#ticks) may help in such cases.\n\n### Ticks\n\nYou can specify the number of steps (called as ticks) to calculate with [d3-force](https://github.com/d3/d3-force/blob/master/README.md) layout. Bigger ticks typically converge on a better layout, but it will take much longer until settlement. The default value is 1000.\n\n```javascript\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { ticks: 3000 });\n```\n\nFor large scale network diagrams, you can also specify the number of initial unconstrained ticks.\n\n```javascript\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { initialTicks: 100, ticks: 100 });\n```\n\ninet-henge calculates the layout in two iteration phases:\n\n1. Initial iteration with no constraints. ( default: 0 tick )\n2. The main iteration with constraints that apply groups as bounding boxes, prevent nodes and groups from overlapping with each other, and so on. ( default: 1000 ticks )\n\nIf you increase `initialTicks`, inet-henge calculates faster in exchange for network diagram precision so that you can decrease `ticks` which is the number of main iteration steps.\n\n20 ~ 100 `initialTicks` and 70 ~ 100 `ticks` should be good start for 800 nodes with 950 links for example. It takes 20 ~ 30 seconds to render in the benchmark environment.\n\n### Position Cache\n\ninet-henge caches a calculated position of nodes, groups, and links for the next rendering. If you load the same JSON data, the cache will be used as a position hint. You can disable this behavior with `positionCache` option.\n\n```javascript\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { positionCache: false });\n```\n\n### SVG viewport size\n\nYou can change svg's viewport size:\n\n```js\nconst diagram = new Diagram(\"#diagram\", \"data.json\", { width: 1200, height: 600 });\n```\n\nThis will generate:\n\n```html\n\u003csvg width=\"1200\" height=\"600\"\u003e\n```\n\n### Style\n\ninet-henge generates an SVG image, so you can customize the style by using CSS.\n\n### Display bundles\n\nYou can display multiple links between nodes by setting `bundle: true` in the constructor like:\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"index.json\", { pop: /^([^\\s-]+)-/, bundle: true });\n  diagram.init(\"loopback\", \"interface\");\n\u003c/script\u003e\n```\n\n![Bundle example](example/images/bundle01.png)\n\nNodes are connected to each other with a single link by default.\n\n### Save positions after dragging nodes\n\nYou can save positions of all nodes in browser even after dragging them by setting `positionCache: \"fixed\"` in the constructor like:\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"index.json\", { pop: /^([^\\s-]+)-/, positionCache: \"fixed\" });\n  diagram.init(\"loopback\", \"interface\");\n\u003c/script\u003e\n```\n\n### Position hinting\n\nYou can provide the coordinates of nodes as position hints to place them where you want. inet-henge calculates the layout by considering them. It always refers to position cache over hint when there is a cache.\n\n:bulb: They are \"hints\". Nodes won't be strictly placed there.\n\n```js\nconst diagram = new Diagram(\"#diagram\", \"index.json\", {\n  pop: /^([^\\s-]+)-/,\n  bundle: true,\n  positionHint: {\n    nodeCallback: (node) =\u003e {\n      const [_, pop] = node.name.match(/^([^\\s-]+)-/);\n\n      // specify the position of nodes in POP01\n      if (pop === \"POP01\") {\n        return { x: 600, y: 330 };\n      }\n\n      // unspecified\n      return null;\n    },\n  },\n});\n\ndiagram.init(\"loopback\", \"interface\", \"description\", \"type\");\n```\n\n- Use `nodeCallback` option to specify per node.\n  - The `Node` object is passed as an argument.\n  - Return value should be an object like `{x: 600, y: 330}`.\n  - If the callback returns `null`, this means that the node position is unspecified.\n\n![Position hinting](example/images/position_hints.png)\n\n#### :bulb: How position hinting works\n\nThe position hints are initial positions technically.\n\n1. inet-henge places nodes according to the hints.\n   - When no hint is specified, the node will be placed in the center of the diagram.\n2. Then, it starts [the ticks calculation](#Ticks).\n\n### Metadata tooltip\n\nYou can display node metadata in the tooltip, instead of always showing as node text, by setting `tooltip: \"click\"` in the constructor like:\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"index.json\", { pop: /^([^\\s-]+)-/, tooltip: \"click\" });\n  diagram.init(\"description\", \"type\");\n\u003c/script\u003e\n```\n\nIn the example above, `description` and `type` will be displayed.\n\n```json\n  \"nodes\": [\n    { \"name\": \"POP01-bb01\", \"meta\": {\"description\": \"This is a router\", \"type\": \"Backbone\"}, \"icon\": \"./images/router.png\" },\n    { \"name\": \"POP01-bb02\", \"meta\": {\"description\": \"This is a router\", \"type\": \"Backbone\"}, \"icon\": \"./images/router.png\" },\n    { \"name\": \"POP01-ag01\", \"meta\": {\"description\": \"This is a router\", \"type\": \"Aggregation\"}, \"icon\": \"./images/switch.png\" },\n    { \"name\": \"POP01-ag02\", \"meta\": {\"description\": \"This is a router\", \"type\": \"Aggregation\"}, \"icon\": \"./images/switch.png\" },\n```\n\n![Metadata tooltip](example/images/tooltip.png)\n\n:bulb: `tooltip: \"hover\"` is also available.\n\n#### Hyperlink in tooltop\n\nYou can show `\u003ca href=\"...\"\u003e...\u003c/a\u003e` in node metadata tooltips.\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"index.json\", {\n    pop: /^([^\\s-]+)-/,\n    bundle: true,\n    tooltip: \"click\",\n    href: (t, type) =\u003e {\n      switch (type) {\n        case \"node\":\n          // {\n          //   \"name\": \"POP01-bb01\",\n          //   \"meta\": { \"description\": \"This is a router\", \"type\": \"Backbone\" },\n          //   \"icon\": \"./images/router.png\"\n          // }\n          return `https://example.com/node/${tooltip.node.meta?.type}/${tooltip.node.name}`;\n        case \"link\":\n          // {\n          //   \"source\": \"POP03-bb01\",\n          //   \"target\": \"POP03-bb02\",\n          //   \"meta\": { \"interface\": { \"source\": \"ge-0/0/0\", \"target\": \"Te0/0/0/0\" } }\n          // }\n          return `https://example.com/link/${tooltip.link.source.name}-${tooltip.link.target.name}`;\n      }\n    }\n  });\n  diagram.init(\"interface\", \"description\", \"type\");\n\u003c/script\u003e\n```\n\nThis example above will generate `\u003ca href=\"https://example.com/node/Backbone/POP01-bb02\"\u003e...\u003c/a\u003e`.\n\n:bulb: Use `tooltip: \"click\"` to make tooltips sticky.\n\n### Initial Position and Scale\n\nYou can specify initial position and scale of diagram.\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"index.json\");\n  diagram.init();\n\n  // move 100px in both x and y, and show in 1/2 scale\n  diagram.attr(\"transform\", \"translate(100, 100) scale(0.5)\");\n\u003c/script\u003e\n```\n\n## Experimental Features\n\n:warning: Those features may work, but still under development. The behavior might be changed :warning:\n\n### Position constraints\n\nYou can apply x-axis or y-axis based position constraints to nodes.\n\nHere is [an example](https://codeout.github.io/inet-henge/clos.html).\n\n![Position constraints](example/images/clos.png)\n\n```html\n\u003cscript\u003e\n  const diagram = new Diagram(\"#diagram\", \"clos.json\", {\n    positionHint: {\n      nodeCallback: (node) =\u003e {\n        switch (true) {\n          // spines, leaves, and servers from the top\n          case /^spine/.test(node.name):\n            return { x: 300, y: 100 };\n          case /^leaf/.test(node.name):\n            return { x: 300, y: 200 };\n          case /^server/.test(node.name):\n            return { x: 300, y: 300 };\n        }\n      }\n    },\n    positionConstraints: [{\n      axis: \"y\",\n      nodesCallback: (nodes) =\u003e [\n        // all spines should be in line in y-axis. leaves and servers as well.\n        nodes.filter((n) =\u003e /^spine/.test(n.name)),\n        nodes.filter((n) =\u003e /^leaf/.test(n.name)),\n        nodes.filter((n) =\u003e /^server/.test(n.name)),\n      ]\n    }]\n  });\n  diagram.init();\n\u003c/script\u003e\n```\n\n- Use `nodesCallback` option to create node groups.\n  - The Node object is passed as an argument.\n  - Individual constraints will be applied to each group.\n\nYou may want to define [Position hinting](#position-hinting) besides constraints.\nPlease note that hint is just a hint and nodes won't be strictly placed there, while constraint is always satisfied.\n\n### Internal groups\n\nYou can display node type based groups in POP-based [Node group](#Node-Group) by `group` definition in each node.\n\n```json\n  \"nodes\": [\n    { \"name\": \"POP01-bb01\", \"group\": \"core\", \"icon\": \"./images/router.png\" },\n    { \"name\": \"POP01-bb02\", \"group\": \"core\", \"icon\": \"./images/router.png\" },\n    ...\n```\n\n![Internal group](example/images/internal_group.png)\n\n### Bundle Mark\n\nYou can show a \"tie\" over bundled links by `bundle:` definition in each link.\n\n```json\n  \"links\": [\n    { \"source\": \"POP01-bb01\", \"target\": \"POP01-bb02\", \"bundle\": \"lag 1\" },\n    { \"source\": \"POP01-bb01\", \"target\": \"POP01-bb02\", \"bundle\": \"lag 1\" },\n    { \"source\": \"POP01-bb01\", \"target\": \"POP01-bb02\"}\n  ]\n```\n\n![Bundle example](example/images/bundle02.png)\n\n- Define bundle name as `bundle:` to specify which link belongs to the bundle ( integer or string value )\n- Set `bundle: true` when initializing `Diagram`. See [Display bundles](#display-bundles) section for details.\n- inet-henge draws a \"tie\" when there are multiple links in bundle among the same node pair. It doesn't draw the mark between different node pairs, even when bundle names are the same.\n\n:warning: Multi-chassis bundling is not supported.\n\n## Plugins\n\n| Name                                                            | Note                              |\n| --------------------------------------------------------------- | --------------------------------- |\n| [Removable Node Plugin](../../tree/main/plugins/removable_node) | Hide and show nodes by key inputs |\n| [Arrows Link Plugin](../../tree/main/plugins/arrows_link)       | Make links bidirectional arrows   |\n\n## Contributing\n\nPlease report issues or enhancement requests to [GitHub issues](https://github.com/codeout/inet-henge/issues).\nFor questions or feedbacks write to my twitter @codeout.\n\nOr send a pull request to fix.\n\n## Copyright and License\n\nCopyright (c) 2016-2025 Shintaro Kojima. Code released under the [MIT license](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeout%2Finet-henge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeout%2Finet-henge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeout%2Finet-henge/lists"}