index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. 'use strict';
  2. var BaseRenderer = require('power-assert-renderer-base');
  3. var inherits = require('util').inherits;
  4. var forEach = require('core-js/library/fn/array/for-each');
  5. var stringifier = require('stringifier');
  6. var stringWidth = require('power-assert-util-string-width');
  7. var assign = require('core-js/library/fn/object/assign');
  8. var defaultOptions = require('./lib/default-options');
  9. /**
  10. * options.stringify [function]
  11. * options.maxDepth [number]
  12. * options.lineSeparator [string]
  13. * options.anonymous [string]
  14. * options.circular [string]
  15. *
  16. * options.widthOf [function]
  17. * options.ambiguousEastAsianCharWidth [number]
  18. */
  19. function DiagramRenderer (config) {
  20. BaseRenderer.call(this);
  21. this.config = assign({}, defaultOptions(), config);
  22. this.events = [];
  23. if (typeof this.config.stringify === 'function') {
  24. this.stringify = this.config.stringify;
  25. } else {
  26. this.stringify = stringifier(this.config);
  27. }
  28. if (typeof this.config.widthOf === 'function') {
  29. this.widthOf = this.config.widthOf;
  30. } else {
  31. this.widthOf = (this.config.ambiguousEastAsianCharWidth === 1) ? stringWidth.narrow : stringWidth;
  32. }
  33. this.initialVertivalBarLength = 1;
  34. }
  35. inherits(DiagramRenderer, BaseRenderer);
  36. DiagramRenderer.prototype.onStart = function (context) {
  37. this.assertionLine = context.source.content;
  38. this.initializeRows();
  39. };
  40. DiagramRenderer.prototype.onData = function (esNode) {
  41. if (!esNode.isCaptured) {
  42. return;
  43. }
  44. this.events.push({value: esNode.value, leftIndex: esNode.range[0]});
  45. };
  46. DiagramRenderer.prototype.onEnd = function () {
  47. this.events.sort(rightToLeft);
  48. this.constructRows(this.events);
  49. var _this = this;
  50. forEach(this.rows, function (columns) {
  51. _this.write(columns.join(''));
  52. });
  53. };
  54. DiagramRenderer.prototype.initializeRows = function () {
  55. this.rows = [];
  56. for (var i = 0; i <= this.initialVertivalBarLength; i += 1) {
  57. this.addOneMoreRow();
  58. }
  59. };
  60. DiagramRenderer.prototype.newRowFor = function (assertionLine) {
  61. return createRow(this.widthOf(assertionLine), ' ');
  62. };
  63. DiagramRenderer.prototype.addOneMoreRow = function () {
  64. this.rows.push(this.newRowFor(this.assertionLine));
  65. };
  66. DiagramRenderer.prototype.lastRow = function () {
  67. return this.rows[this.rows.length - 1];
  68. };
  69. DiagramRenderer.prototype.renderVerticalBarAt = function (columnIndex) {
  70. var i, lastRowIndex = this.rows.length - 1;
  71. for (i = 0; i < lastRowIndex; i += 1) {
  72. this.rows[i].splice(columnIndex, 1, '|');
  73. }
  74. };
  75. DiagramRenderer.prototype.renderValueAt = function (columnIndex, dumpedValue) {
  76. var i, width = this.widthOf(dumpedValue);
  77. for (i = 0; i < width; i += 1) {
  78. this.lastRow().splice(columnIndex + i, 1, dumpedValue.charAt(i));
  79. }
  80. };
  81. DiagramRenderer.prototype.isOverlapped = function (prevCapturing, nextCaputuring, dumpedValue) {
  82. return (typeof prevCapturing !== 'undefined') && this.startColumnFor(prevCapturing) <= (this.startColumnFor(nextCaputuring) + this.widthOf(dumpedValue));
  83. };
  84. DiagramRenderer.prototype.constructRows = function (capturedEvents) {
  85. var that = this;
  86. var prevCaptured;
  87. forEach(capturedEvents, function (captured) {
  88. var dumpedValue = that.stringify(captured.value);
  89. if (that.isOverlapped(prevCaptured, captured, dumpedValue)) {
  90. that.addOneMoreRow();
  91. }
  92. that.renderVerticalBarAt(that.startColumnFor(captured));
  93. that.renderValueAt(that.startColumnFor(captured), dumpedValue);
  94. prevCaptured = captured;
  95. });
  96. };
  97. DiagramRenderer.prototype.startColumnFor = function (captured) {
  98. return this.widthOf(this.assertionLine.slice(0, captured.leftIndex));
  99. };
  100. function createRow (numCols, initial) {
  101. var row = [], i;
  102. for(i = 0; i < numCols; i += 1) {
  103. row[i] = initial;
  104. }
  105. return row;
  106. }
  107. function rightToLeft (a, b) {
  108. return b.leftIndex - a.leftIndex;
  109. }
  110. module.exports = DiagramRenderer;