dot.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.DotEngine = void 0;
  4. var path = require("path");
  5. var ngd_core_1 = require("@compodoc/ngd-core");
  6. var dot_template_1 = require("./dot.template");
  7. var fs = require('fs-extra');
  8. var cleanDot = false;
  9. var cleanSvg = false;
  10. var appName = require('../../../package.json').name;
  11. // http://www.graphviz.org/Documentation/dotguide.pdf
  12. var DotEngine = /** @class */ (function () {
  13. function DotEngine(options) {
  14. // http://www.graphviz.org/doc/info/shapes.html
  15. this.template = dot_template_1.DOT_TEMPLATE;
  16. this.cwd = process.cwd();
  17. this.files = {
  18. component: null,
  19. };
  20. this.paths = {
  21. dot: null,
  22. json: null,
  23. png: null,
  24. svg: null,
  25. html: null,
  26. };
  27. this.options = {};
  28. var baseDir = "./".concat(appName, "/");
  29. this.options = {
  30. name: "".concat(appName),
  31. output: options.output,
  32. displayLegend: options.displayLegend,
  33. outputFormats: options.outputFormats,
  34. dot: {
  35. shapeModules: 'component',
  36. shapeProviders: 'ellipse',
  37. shapeDirectives: 'cds',
  38. //http://www.graphviz.org/doc/info/colors.html
  39. colorScheme: 'set312',
  40. },
  41. };
  42. if (options.output) {
  43. if (typeof this.options.output !== 'string') {
  44. ngd_core_1.logger.fatal('Option "output" has been provided but it is not a valid name.');
  45. process.exit(1);
  46. }
  47. }
  48. this.paths = {
  49. dot: path.join(this.options.output, '/dependencies.dot'),
  50. json: path.join(this.options.output, '/dependencies.json'),
  51. svg: path.join(this.options.output, '/dependencies.svg'),
  52. png: path.join(this.options.output, '/dependencies.png'),
  53. html: path.join(this.options.output, '/dependencies.html'),
  54. };
  55. if (typeof options.silent !== 'undefined') {
  56. ngd_core_1.logger.silent = options.silent;
  57. }
  58. }
  59. DotEngine.prototype.updateOutput = function (output) {
  60. this.paths = {
  61. dot: path.join(output, '/dependencies.dot'),
  62. json: path.join(output, '/dependencies.json'),
  63. svg: path.join(output, '/dependencies.svg'),
  64. png: path.join(output, '/dependencies.png'),
  65. html: path.join(output, '/dependencies.html'),
  66. };
  67. };
  68. DotEngine.prototype.generateGraph = function (deps) {
  69. var _this = this;
  70. var template = this.preprocessTemplates(this.options);
  71. var generators = [];
  72. // Handle svg dependency with dot, and html with svg
  73. if (this.options.outputFormats.indexOf('dot') > -1 &&
  74. this.options.outputFormats.indexOf('svg') === -1 &&
  75. this.options.outputFormats.indexOf('html') === -1) {
  76. generators.push(this.generateDot(template, deps));
  77. }
  78. if (this.options.outputFormats.indexOf('svg') > -1 && this.options.outputFormats.indexOf('html') === -1) {
  79. generators.push(this.generateDot(template, deps).then(function (_) { return _this.generateSVG(); }));
  80. if (this.options.outputFormats.indexOf('svg') > -1 && this.options.outputFormats.indexOf('dot') === -1) {
  81. cleanDot = true;
  82. }
  83. }
  84. if (this.options.outputFormats.indexOf('json') > -1) {
  85. generators.push(this.generateJSON(deps));
  86. }
  87. if (this.options.outputFormats.indexOf('html') > -1) {
  88. generators.push(this.generateDot(template, deps)
  89. .then(function (_) { return _this.generateSVG(); })
  90. .then(function (_) { return _this.generateHTML(); }));
  91. if (this.options.outputFormats.indexOf('html') > -1 && this.options.outputFormats.indexOf('svg') === -1) {
  92. cleanSvg = true;
  93. }
  94. if (this.options.outputFormats.indexOf('html') > -1 && this.options.outputFormats.indexOf('dot') === -1) {
  95. cleanDot = true;
  96. }
  97. }
  98. // todo(WCH): disable PNG creation due to some errors with phantomjs
  99. /*
  100. if (this.options.outputFormats.indexOf('png') > -1) {
  101. generators.push(this.generatePNG());
  102. }
  103. */
  104. return Promise.all(generators).then(function (_) { return _this.cleanGeneratedFiles(); });
  105. };
  106. DotEngine.prototype.cleanGeneratedFiles = function () {
  107. var removeFile = function (path) {
  108. return new Promise(function (resolve, reject) {
  109. fs.unlink(path, function (error) {
  110. if (error) {
  111. reject(error);
  112. }
  113. else {
  114. resolve(true);
  115. }
  116. });
  117. });
  118. };
  119. var cleaners = [];
  120. if (cleanDot) {
  121. cleaners.push(removeFile(this.paths.dot));
  122. }
  123. if (cleanSvg) {
  124. cleaners.push(removeFile(this.paths.svg));
  125. }
  126. return Promise.all(cleaners);
  127. };
  128. DotEngine.prototype.preprocessTemplates = function (options) {
  129. var doT = require('dot');
  130. var result;
  131. if (options.displayLegend === 'true' || options.displayLegend === true) {
  132. result = this.template.replace(/###legend###/g, dot_template_1.LEGEND);
  133. }
  134. else {
  135. result = this.template.replace(/###legend###/g, '""');
  136. }
  137. return doT.template(result.replace(/###scheme###/g, options.dot.colorScheme));
  138. };
  139. DotEngine.prototype.generateJSON = function (deps) {
  140. var _this = this;
  141. return new Promise(function (resolve, reject) {
  142. fs.outputFile(_this.paths.json, JSON.stringify(deps, null, 2), function (error) {
  143. if (error) {
  144. reject(error);
  145. }
  146. ngd_core_1.logger.info('creating JSON', _this.paths.json);
  147. resolve(_this.paths.json);
  148. });
  149. });
  150. };
  151. // @not-used
  152. DotEngine.prototype.escape = function (deps) {
  153. var _this = this;
  154. return deps.map(function (d) {
  155. for (var prop in d) {
  156. if (d.hasOwnProperty(prop)) {
  157. var a = d[prop];
  158. console.log(a);
  159. if (Array.isArray(a)) {
  160. return _this.escape(a);
  161. }
  162. else if (typeof a === 'string') {
  163. a = a.replace(/"/g, '"');
  164. a = a.replace(/'/g, "'");
  165. a = a.replace(/\{/g, '{');
  166. a = a.replace(/\)/g, ')');
  167. }
  168. }
  169. }
  170. return d;
  171. });
  172. };
  173. DotEngine.prototype.generateDot = function (template, deps) {
  174. // todo(wch)
  175. //deps = this.escape(deps);
  176. var _this = this;
  177. return new Promise(function (resolve, reject) {
  178. fs.outputFile(_this.paths.dot, template({
  179. modules: deps,
  180. }), function (error) {
  181. if (error) {
  182. reject(error);
  183. }
  184. if (cleanDot === false) {
  185. ngd_core_1.logger.info('creating DOT', _this.paths.dot);
  186. }
  187. resolve(_this.paths.dot);
  188. });
  189. });
  190. };
  191. DotEngine.prototype.generateSVG = function () {
  192. var _this = this;
  193. var vizRenderStringSync = require('@aduh95/viz.js/sync');
  194. var vizSvg = vizRenderStringSync(fs.readFileSync(this.paths.dot).toString());
  195. return new Promise(function (resolve, reject) {
  196. fs.outputFile(_this.paths.svg, vizSvg, function (error) {
  197. if (error) {
  198. reject(error);
  199. }
  200. if (cleanSvg === false) {
  201. ngd_core_1.logger.info('creating SVG', _this.paths.svg);
  202. }
  203. resolve(_this.paths.svg);
  204. });
  205. });
  206. };
  207. DotEngine.prototype.generateHTML = function () {
  208. var _this = this;
  209. var svgContent = fs.readFileSync(this.paths.svg).toString();
  210. var cssContent = "\n\t\t\t<style>\n\t\t\t\t.edge {\n\t\t\t\t\ttransition: opacity 0.5s;\n\t\t\t\t\topacity:0.2;\n\t\t\t\t}\n\t\t\t\t.node {\n\t\t\t\t\ttransition: transform 0.1s;\n\t\t\t\t\ttransform-origin: center center;\n\t\t\t\t}\n\t\t\t\t.node:hover {\n\t\t\t\t\ttransform: scale(1.03);\n\t\t\t\t}\n\t\t\t\t.node:hover + .edge {\n\t\t\t\t\topacity:1;\n\t\t\t\t}\n\t\t\t</style>";
  211. var htmlContent = "\n\t\t\t\t".concat(svgContent, "\n\t\t\t");
  212. return new Promise(function (resolve, reject) {
  213. fs.outputFile(_this.paths.html, htmlContent, function (error) {
  214. if (error) {
  215. reject(error);
  216. }
  217. ngd_core_1.logger.info('creating HTML', _this.paths.html);
  218. resolve(_this.paths.html);
  219. });
  220. });
  221. };
  222. DotEngine.prototype.generatePNG = function () {
  223. var _this = this;
  224. var svgToPng = require('svg-to-png');
  225. return new Promise(function (resolve, reject) {
  226. svgToPng.convert(_this.paths.svg, _this.paths.png).then(function () {
  227. ngd_core_1.logger.info('creating PNG', this.paths.png);
  228. resolve(this.paths.image);
  229. });
  230. });
  231. };
  232. return DotEngine;
  233. }());
  234. exports.DotEngine = DotEngine;