Browse Source

Add template for document generation with 'jsdoc'. (#3497)

* Add template for document generation with 'jsdoc'.

In essence, it defines the subdirectory `docs` as a `jsdoc` template. Benefits:

- allows the usage of partials, in order to DRY common parts of the html files.
- makes available the jsdoc-comments, for addition into the documentation.
- enables extraction of data from the source code. For example, the list of edge endpoints `['arrow', 'bar', 'circle']` can now be extracted from the source and inserted into the documentation on generation.

In this initial version, the only file that has been changed is `docs/data/dataset.html`.
In here, partials have been added to illustrate how common page elements can be DRY'd.

The template has been set up in such a way, that resource files will be copied and that html files can pass through unchanged if no special template tags (`<?js...?>`) are used. This allows for a gradual transition of the html files to templates.

**Usage:**  `gulp docs`

- The result files are placed in subdirectory `gen/docs/`.

**NOTE:** The release procedure will have to be adjusted by adding this gulp command.
The docs-files will then have to be taken from `gen/docs`.

* Edits to docs/README

* Adjusted layout of README.md

* Further edits to README.md

* Removed pre tags again in  README.md - don't work in code block

* Linted the gulpfile

* Added proof of concept for docs generation from source
mbroad/code-climate-coverage-develop
wimrijnders 6 years ago
committed by Yotam Berkowitz
parent
commit
24d61cb228
11 changed files with 523 additions and 82 deletions
  1. +1
    -0
      .gitignore
  2. +231
    -0
      docs/README.md
  3. +6
    -81
      docs/data/dataset.html
  4. +18
    -0
      docs/network/index.html
  5. +118
    -0
      docs/publish.js
  6. +40
    -0
      docs/tmpl/html-head.tmpl
  7. +49
    -0
      docs/tmpl/navbar.tmpl
  8. +36
    -1
      gulpfile.js
  9. +3
    -0
      jsdoc.json
  10. +20
    -0
      lib/network/Network.js
  11. +1
    -0
      package.json

+ 1
- 0
.gitignore View File

@ -16,3 +16,4 @@ npm-debug.log
# temporary files
.*.sw[op]
.commits.tmp
gen/

+ 231
- 0
docs/README.md View File

@ -0,0 +1,231 @@
# Command line usage example
```
jsdoc -c jsdoc.json -r -t docs -d gen/docs lib
```
- `-c`: use this config file for `jsdoc`
- `-r`: Recurse into subdirectories of the specified source directories
- `-t`: Use template in path `docs`
- `-d`: Generated html files put in `gen/docs`
- Source files to parse are taken from directory `lib`
## Notes
The template generation is set up so that:
- Files ending in `.tmpl` are skipped
- All non-html files are plain copied
- html-files *can* contain `<?js ?>` tags, but this is not required
## Intention
The `docs` directory is treated as a `jsdoc` template, in which the html-files are the template files. This allows for a gradual adaptation of the html-files to templates; unchanged html-files will pass through `jsdoc` unchanged.
The added value of using `jsdoc` for documentation generation, is that the complete documentation information, as collected by `jsdoc` from the source, is available for usage. This way, it's possible to insert technical notes from the source code into the documentation.
----
# Usage of and Notes on Source Code
This section contains notes on the usage of `jsdoc` functionality, to aid with the handling of its generated data.
## Parameters of `publish()`
### Parameter `taffyData`
A table containing *all* data collected from the source code, related to jsdoc generation. See below for more info and example outputs.
### Parameter `opt`
Example of `opt` variable:
```js
{
"_":["../github/vis/lib/network/"],
"configure":"jsdoc.json",
"recurse":true,
"template":"/home/wim/projects/jsdoc/default",
"destination":"./out/",
"encoding":"utf8"
}
```
### Parameter `tutorial`
This does not appear to be of use for the generation of `vis.js` documentation.
Example of `tutorial` variable:
```js
{
"longname":"",
"name":"",
"title":"",
"content":"",
"parent":null,
"children":[],
"_tutorials":{}
}
```
## Global variable `env`
This contains addition info for the current execution of `jsdoc`. Example of `env` variable:
```js
{
"run":{"start":"2017-09-16T05:06:45.621Z","finish":null},
"args":["-c","jsdoc.json","-r","-t","default","../github/vis/lib/network/"],
"conf":{
"plugins":["/usr/lib/node_modules/jsdoc/plugins/markdown.js"],
"recurseDepth":10,
"source":{"includePattern":".+\\.js(doc|x)?$","excludePattern":""},
"sourceType":"module",
"tags":{"allowUnknownTags":true,"dictionaries":["jsdoc","closure"]},
"templates":{"monospaceLinks":false,"cleverLinks":false}
},
"dirname":"/usr/lib/node_modules/jsdoc",
"pwd":"/home/wim/projects/jsdoc",
"opts":{ <<same as parameter 'opt' above>> },
"sourceFiles":[ <<list of full path names of all js-source files used as input>> ],
"version":{"number":"3.5.4","revision":"Fri, 04 Aug 2017 22:05:27 GMT"}
}
```
## taffyData
This is a parameter to `publish()`. It's a table containing *all* data collected from the source code, related to jsdoc generation.
I can't find any way to return a list of fields for the data items in the taffyDB docs, therefore below there are examples of items, for better understanding of usage.
Example usage:
```js
var data = taffyData;
var tmp = data().filter({name:'Label'}).get();
```
Returns an array with all items with `name === 'Label'`. Example output of one of these items, for a class:
*In these examples, block comment endings are redacted to ' * /'*
```js
{
"comment":"/**\n * A Label to be used for Nodes or Edges.\n * /",
"meta":{
"range":[3770,41303],
"filename":"Label.js",
"lineno":167,
"columnno":0,
"path":"/home/wim/projects/github/vis/lib/network/modules/components/shared",
"code":{
"id":"astnode100065034",
"name":"Label",
"type":"ClassDeclaration",
"paramnames":["body","options","edgelabel"]
}
},
"classdesc":"
A Label to be used for Nodes or Edges.
",
"name":"Label",
"longname":"Label",
"kind":"class",
"scope":"global",
"params":[
{"type":{"names":["Object"]},"name":"body"},
{"type":{"names":["Object"]},"name":"options"},
{"type":{"names":["boolean"]},"optional":true,"defaultvalue":false,"name":"edgelabel"}
],
"___id":"T000002R005289",
"___s":true
}
```
Example of item for an instance method:
```js
var tmp = data().filter({name:'_drawText'}).get();
```
Full output returned:
```js
[{
"comment":"/**\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {boolean} selected\n * @param {boolean} hover\n * @param {number} x\n * @param {number} y\n * @param {string} [baseline='middle']\n * @private\n * /",
"meta":{
"range":[20060,22269],
"filename":"Label.js",
"lineno":652,
"columnno":2,
"path":"/home/wim/projects/github/vis/lib/network/modules/components/shared",
"code":{
"id":"astnode100066427",
"name":"Label#_drawText",
"type":"MethodDefinition",
"paramnames":["ctx","selected","hover","x","y","baseline"]
},
"vars":{"":null}
},
"params":[
{"type":{"names":["CanvasRenderingContext2D"]},"name":"ctx"},
{"type":{"names":["boolean"]},"name":"selected"},
{"type":{"names":["boolean"]},"name":"hover"},
{"type":{"names":["number"]},"name":"x"},
{"type":{"names":["number"]},"name":"y"},
{"type":{"names":["string"]},"optional":true,"defaultvalue":"'middle'","name":"baseline"}
],
"access":"private",
"name":"_drawText",
"longname":"Label#_drawText",
"kind":"function",
"memberof":"Label",
"scope":"instance",
"___id":"T000002R005388",
"___s":true
}]
```
## `jsdoc` template rendering
See `function createRenderer(fromDir, data)` in code for usage.
There are two calls for rendering templates:
- `var html = renderer.render(inFile, docData);`
- `var html = renderer.partial(inFile, docData);`
The difference is that `render()` will use a default layout template, if present, which will encapsulate all html. This can be set by:
```js
renderer.layout = 'path/to/default/layout.tmpl';
```
Parameter `docData` is a hash which is used to pass parameters into a template. The standard way of using this appear to be:
```
<?js
var data = obj; // Whatever docData is
var self = this;
?>
```
But it also appear to be possible to use the elements of docData directly:
```js
var docData = {
myTitle: 'Hello, pussycat!'
};
```
Within the template:
```
<?js= myTitle ?>
```

+ 6
- 81
docs/data/dataset.html View File

@ -1,86 +1,11 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" HREF="favicon.ico">
<title>DataSet - vis.js - A dynamic, browser based visualization library.</title>
<!-- Bootstrap core CSS -->
<link href="../css/bootstrap.css" rel="stylesheet">
<!-- Tipue vendor css -->
<link href="../css/tipuesearch.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link href="../css/prettify.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="../js/googleAnalytics.js"></script>
<script type="text/javascript" src="../js/prettify/prettify.js"></script>
<script src="../js/smooth-scroll.min.js"></script>
<script language="JavaScript">
smoothScroll.init();
</script>
<script type="text/javascript" src="../js/toggleTable.js"></script>
<?js
var self = this;
var title = 'DataSet - vis.js - A dynamic, browser based visualization library.';
?>
<?js= self.partial('tmpl/html-head.tmpl', title) ?>
</head>
<body onload="prettyPrint();">
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand hidden-sm" href="./index.html">vis.js</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="http://www.visjs.org/index.html#modules">Modules</a></li>
<li><a href="http://www.visjs.org/blog.html">Blog</a></li>
<li><a href="http://www.visjs.org/index.html#download_install">Download</a></li>
<li><a href="http://www.visjs.org/showcase/index.html">Showcase</a></li>
<li><a href="http://www.visjs.org/index.html#contribute">Contribute</a></li>
<li><a href="http://www.visjs.org/featureRequests.html">Feature requests</a></li>
<li><a href="http://www.visjs.org/index.html#licenses">License</a></li>
</ul>
<form class="navbar-form navbar-right" role="search">
<input name="q" id="tipue_search_input" autocomplete="off" type="text" class="form-control" placeholder="Enter keywords">
<button type="submit" class="btn btn-default">Go!</button>
</form>
<div id="search-results-wrapper" class="panel panel-default">
<div class="panel-body">
<div id="tipue_search_content"></div>
</div>
</div>
<div id="keyword-info" class="panel panel-success">
<div class="panel-body">
Found <span id="keyword-count"></span> results. Click <a id="keyword-jumper-button" href="">here</a> to jump to the first keyword occurence!
</div>
</div>
</div>
</div>
</nav>
</div>
</div>
<a href="https://github.com/almende/vis" class="hidden-xs hidden-sm hidden-md"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
<?js= self.partial('tmpl/navbar.tmpl', title) ?>
<div class="container full">
<h1>DataSet</h1>

+ 18
- 0
docs/network/index.html View File

@ -1,3 +1,6 @@
<?js
var self = this;
?>
<!DOCTYPE html>
<html lang="en">
<head>
@ -609,6 +612,21 @@ var locales = {
The options object is explained in full <a data-scroll="" data-options="{ &quot;easing&quot;: &quot;easeInCubic&quot; }" href="#optionsObject">below</a>.
</td>
</tr>
<?js
var comment = self.getComment("Network#findNode");
?>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','findNodeNew', this);">
<td colspan="2"><span parent="findNode" class="right-caret" id="method_findNodeNew"></span>
<?js= comment.prototype ?> <b>This comes from the source!</b>
</tr>
<tr class="hidden" parent="findNodeNew">
<td class="midMethods">Returns: <?js= comment.returns ?></td>
<td>
<?js= comment.description ?>
</td>
</tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','findNode', this);">
<td colspan="2"><span parent="findNode" class="right-caret" id="method_findNode"></span> findNode(
<code>String/Number nodeId</code>)

+ 118
- 0
docs/publish.js View File

@ -0,0 +1,118 @@
/*==============================================================================
Demo template, showing how documentation can be generated for `vis.js`.
------------------------------------------------------------------------------
## Notes on `jsdoc` code
// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
// doesn't try to hand them out later
indexUrl = helper.getUniqueFilename('index');
// don't call registerLink() on this one! 'index' is also a valid longname
globalUrl = helper.getUniqueFilename('global');
helper.registerLink('global', globalUrl);
============================================================================== */
'use strict';
//var taffy = require('taffydb').taffy; // not really required here, left for reference
// Internal modules of `jsdoc` are available here.
// This is not the complete list, there may be more useful stuff in jsdoc
// For all modules scan in: '/usr/lib/node_modules/jsdoc/lib/jsdoc/' (or similar on your system)
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var template = require('jsdoc/template');
/**
* Set up the template rendering engine.
*/
function createRenderer(fromDir, data) {
var renderer = new template.Template(fromDir); // Param is the template source directory.
// All template files are relative to this directory!
/**
* Example helper method
*
* This can be called from within a template as follows:
*
* ```
* <?js
* var self = this;
* ?>
* ...
* <?js= self.helper('hello!') ?>
* ```
*
* /
renderer.helper = function(val) {
return 'this is a helper! ' + val;
};
*/
/**
* Retrieves jsdoc info for the passed instance method.
*/
renderer.getComment = function(methodName) {
var tmp = data().filter({longname: methodName}).get()[0];
//console.log(JSON.stringify(tmp));
// Some restructuring, to adapt it to the docs layout
// This needs some work to make it handle 0 and > 1 parameters
var param = tmp.params[0];
var prototype = tmp.name + '(<code>' + param.type.names.join('|') + ' ' + param.name + '</code>)';
var returns = tmp.returns[0].type.names;
return {
prototype: prototype,
returns: returns,
description: tmp.description
}
};
return renderer;
}
/**
Entry point for the template.
This is called from `jsdoc` during execution
@param {TAFFY} taffyData See <http://taffydb.com/>.
@param {object} opts
@param {Tutorial} tutorials
*/
exports.publish = function(taffyData, opts, tutorials) {
//console.log(JSON.stringify(opts, null, 2));
var fromDir = path.resolve(opts.template);
var toDir = path.join(opts.destination);
var renderer = createRenderer(fromDir, taffyData);
var docFiles = fs.ls(fromDir, 3);
docFiles.forEach(function(fileName) {
// Template filenames need to be relative to template source dir
var relName = path.relative(fromDir, fileName);
var outFile = path.join(toDir, relName);
if (/publish.js$/.test(fileName)) return; // Skip self
if (/README.md$/.test(fileName)) return; // Skip own README
if (/\.tmpl$/.test(fileName)) return; // Skip .tmpl files; these are used as partials only
if (!/\.html$/.test(fileName)) {
// Just plain copy over non-html files
var tmpDir = fs.toDir(outFile);
fs.mkPath(tmpDir);
fs.copyFileSync(fileName, tmpDir);
return;
}
// Render html files as templates
//console.log(relName);
var html = renderer.partial(relName, {});
fs.mkPath(fs.toDir(outFile));
fs.writeFileSync(outFile, html, 'utf8');
});
//console.log(JSON.stringify(env, null, 2));
};

+ 40
- 0
docs/tmpl/html-head.tmpl View File

@ -0,0 +1,40 @@
<?js
var title = obj;
var self = this;
?>
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" HREF="favicon.ico">
<title><?js= title ?></title>
<!-- Bootstrap core CSS -->
<link href="../css/bootstrap.css" rel="stylesheet">
<!-- Tipue vendor css -->
<link href="../css/tipuesearch.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link href="../css/prettify.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="../js/googleAnalytics.js"></script>
<script type="text/javascript" src="../js/prettify/prettify.js"></script>
<script src="../js/smooth-scroll.min.js"></script>
<script language="JavaScript">
smoothScroll.init();
</script>
<script type="text/javascript" src="../js/toggleTable.js"></script>
<?js /* end tag '</head>' purposely missing here, so that more stuff can be added to header */ ?>

+ 49
- 0
docs/tmpl/navbar.tmpl View File

@ -0,0 +1,49 @@
<?js
var title = obj;
var self = this;
?>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand hidden-sm" href="./index.html">vis.js</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="http://www.visjs.org/index.html#modules">Modules</a></li>
<li><a href="http://www.visjs.org/blog.html">Blog</a></li>
<li><a href="http://www.visjs.org/index.html#download_install">Download</a></li>
<li><a href="http://www.visjs.org/showcase/index.html">Showcase</a></li>
<li><a href="http://www.visjs.org/index.html#contribute">Contribute</a></li>
<li><a href="http://www.visjs.org/featureRequests.html">Feature requests</a></li>
<li><a href="http://www.visjs.org/index.html#licenses">License</a></li>
</ul>
<form class="navbar-form navbar-right" role="search">
<input name="q" id="tipue_search_input" autocomplete="off" type="text" class="form-control" placeholder="Enter keywords">
<button type="submit" class="btn btn-default">Go!</button>
</form>
<div id="search-results-wrapper" class="panel panel-default">
<div class="panel-body">
<div id="tipue_search_content"></div>
</div>
</div>
<div id="keyword-info" class="panel panel-success">
<div class="panel-body">
Found <span id="keyword-count"></span> results. Click <a id="keyword-jumper-button" href="">here</a> to jump to the first keyword occurence!
</div>
</div>
</div>
</div>
</nav>
</div>
</div>
<a href="https://github.com/almende/vis" class="hidden-xs hidden-sm hidden-md"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>

+ 36
- 1
gulpfile.js View File

@ -10,6 +10,7 @@ var webpack = require('webpack');
var uglify = require('uglify-js');
var rimraf = require('rimraf');
var argv = require('yargs').argv;
var child_exec = require('child_process').exec;
var ENTRY = './index.js';
var HEADER = './lib/header.js';
@ -29,7 +30,12 @@ var INDIVIDUAL_CSS_BUNDLES = [
{entry: ['./lib/shared/**/*.css', './lib/network/**/*.css'], filename: 'vis-network.min.css'}
];
// generate banner with today's date and correct version
/**
* Generate banner with today's date and correct version
*
* @returns {string} banner text
*/
function createBanner() {
var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd
var version = require('./package.json').version;
@ -39,6 +45,7 @@ function createBanner() {
.replace('@@version', version);
}
var bannerPlugin = new webpack.BannerPlugin({
banner: createBanner(),
entryOnly: true,
@ -92,6 +99,12 @@ var uglifyConfig = {
// create a single instance of the compiler to allow caching
var compiler = webpack(webpackConfig);
/**
* Callback for handling errors for a compiler run
*
* @param {object} err
* @param {objects} stats
*/
function handleCompilerCallback (err, stats) {
if (err) {
gutil.log(err.toString());
@ -232,5 +245,27 @@ gulp.task('lint', function () {
});
// Generate the documentation files
gulp.task('docs', function(cb) {
var targetDir = 'gen/docs';
// Not sure if this is the best way to handle 'cb'; at least it works.
var hasError = false;
var onError = function(error) {
if (error !== undefined && error !== null) {
console.error('Error while running task: ' + error);
hasError = true;
cb();
}
}
rimraf(__dirname + '/' + targetDir, onError); // Clean up previous generation
if (!hasError) {
var params = '-c ./jsdoc.json -r -t docs -d ' + targetDir;
child_exec('node ./node_modules/jsdoc/jsdoc.js ' + params + ' lib', undefined, cb);
}
});
// The default task (called when you run `gulp`)
gulp.task('default', ['clean', 'bundle', 'minify']);

+ 3
- 0
jsdoc.json View File

@ -0,0 +1,3 @@
{
"plugins": ["plugins/markdown"]
}

+ 20
- 0
lib/network/Network.js View File

@ -470,7 +470,27 @@ Network.prototype.isActive = function () {
Network.prototype.setSize = function() {return this.canvas.setSize.apply(this.canvas,arguments);};
Network.prototype.canvasToDOM = function() {return this.canvas.canvasToDOM.apply(this.canvas,arguments);};
Network.prototype.DOMtoCanvas = function() {return this.canvas.DOMtoCanvas.apply(this.canvas,arguments);};
/**
* Nodes can be in clusters. Clusters can also be in clusters. This function returns and array of
* nodeIds showing where the node is.
*
* If any nodeId in the chain, especially the first passed in as a parameter, is not present in
* the current nodes list, an empty array is returned.
*
* Example:
* cluster 'A' contains cluster 'B',
* cluster 'B' contains cluster 'C',
* cluster 'C' contains node 'fred'.
* `jsnetwork.clustering.findNode('fred')` will return `['A','B','C','fred']`.
*
* @param {string|number} nodeId
* @returns {Array}
*/
Network.prototype.findNode = function() {return this.clustering.findNode.apply(this.clustering,arguments);};
Network.prototype.isCluster = function() {return this.clustering.isCluster.apply(this.clustering,arguments);};
Network.prototype.openCluster = function() {return this.clustering.openCluster.apply(this.clustering,arguments);};
Network.prototype.cluster = function() {return this.clustering.cluster.apply(this.clustering,arguments);};

+ 1
- 0
package.json View File

@ -59,6 +59,7 @@
"gulp-eslint": "^4.0.0",
"gulp-rename": "^1.2.2",
"gulp-util": "^3.0.8",
"jsdoc": "^3.5.5",
"jsdom": "9.12.0",
"jsdom-global": "^2.1.1",
"merge-stream": "^1.0.1",

Loading…
Cancel
Save