UNPKG

esdoc-plugin-dependency-graphs

Version:

A plugin for ESDoc that adds interactive D3 powered dependency graphs for source code including linking JSPM / NPM managed code and packages.

150 lines (131 loc) 4.3 kB
'use strict'; import cheerio from 'cheerio'; import fs from 'fs-extra'; import path from 'path'; import IceCap from 'ice-cap'; import DocBuilder from 'esdoc/out/src/Publisher/Builder/DocBuilder.js'; /** * Graph Output Builder class. */ export default class GraphDocBuilder extends DocBuilder { /** * Simply wraps the actual graph in an iframe. * * @param {object} item - target graph config item. * * @return {string} built graph. * @private */ _buildGraph(item) { return `<iframe src="${item.graphPath}" frameBorder="0" style="display: block; width: 100%; height: 100%;" />`; } /** * Creates the left hand navigation list for the various graphs supported. * * @param {Array<{fileName: string, graphPath: string, label: string, safeLabel: string}>} graphConfig - * target manual config. * * @return {object} IceCap instance * @private */ _buildGraphNav(graphConfig) { const ice = new IceCap(this._readTemplate('graphIndex.html')); ice.loop('manual', graphConfig, (i, item, ice) => { ice.attr('manual', 'data-toc-name', item.safeLabel); ice.text('title', item.label); ice.attr('title', 'href', item.fileName); }); return ice; } /** * Execute building output. * * @param {function(html: string, filePath: string)} callback - is called each manual. */ exec(callback) { const graphConfig = this._getGraphConfig(); let ice = this._buildLayoutDoc(); ice.autoDrop = false; ice.attr('rootContainer', 'class', ' manual-root'); { const fileName = 'graphs/index.html'; const baseUrl = this._getBaseUrl(fileName); ice.load('nav', this._buildGraphNav(graphConfig), IceCap.MODE_WRITE); ice.text('title', 'Graphs', IceCap.MODE_WRITE); ice.attr('baseUrl', 'href', baseUrl, IceCap.MODE_WRITE); callback(ice.html, fileName); } // To get the iFrame holding the graph styles to display with no padding and 100% height the following needs // to be overridden: 'html', 'body', '.content'. This is a bit of a hack as a new IceCap instance is created. const $ = cheerio.load(ice.html); $('html').attr('style', 'height: calc(100% - 40px)'); $('body').attr('style', 'height: 100%'); $('.content').attr('style', 'padding: 0; height: 100%; position: relative;'); ice = new IceCap($.html()); for (const item of graphConfig) { const fileName = item.fileName; const baseUrl = this._getBaseUrl(fileName); ice.load('content', this._buildGraph(item), IceCap.MODE_WRITE); ice.load('nav', this._buildGraphNav(graphConfig), IceCap.MODE_WRITE); ice.text('title', item.label, IceCap.MODE_WRITE); ice.attr('baseUrl', 'href', baseUrl, IceCap.MODE_WRITE); callback(this._removeFooter(ice), fileName); } } /** * Get graph config for all entries for HTML page generation. * * @returns {Array<{}>} built graph config. * @private */ _getGraphConfig() { const graphConfig = []; graphConfig.push( { fileName: 'graphs/jspm_packages.html', graphPath: 'graphs/jspm_packages/index.html', label: 'JSPM Packages', safeLabel: 'jspm_packages' }); return graphConfig; } /** * Attempts to first read local html template before deferring to ESDoc for loading templates. * * @param {string} fileName - template file name. * * @return {string} html of template. * @private */ _readTemplate(fileName) { try { const filePath = path.resolve(__dirname, `../template/esdoc/${fileName}`); return fs.readFileSync(filePath, { encoding: 'utf-8' }); } catch (err) { /* ... */ } return super._readTemplate(fileName); } /** * Removes the footer from ESDoc layout template which is useful for full screen graphs. * * @param {object} ice - An instance of IceCap * * @return {string} * @private */ _removeFooter(ice) { const $ = cheerio.load(ice.html); $('.footer').remove(); return $.html(); } }