* 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 sourcembroad/code-climate-coverage-develop
| @ -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 ?> | |||
| ``` | |||
| @ -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)); | |||
| }; | |||
| @ -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 */ ?> | |||
| @ -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> | |||
| @ -0,0 +1,3 @@ | |||
| { | |||
| "plugins": ["plugins/markdown"] | |||
| } | |||