UNPKG

cli-diagram

Version:

Draw needlessly complex diagrams in the console

147 lines (130 loc) 3.58 kB
const Element = require('./element'); class Line extends Element { /** * @param {number|string[]} lines * @param {object} options * @param {Diagram} diagram */ constructor(lines, options, diagram) { super(options, diagram); if (Array.isArray(lines)) { this.count = lines.length; this.labels = this.parseLabels(lines); } else { this.count = lines; this.labels = this.parseLabels([]); } } /** * Returns a string representation of the Line * * @return {string} */ toString() { const gap = ' '.repeat(this.width); let lineCount = 0; const result = this.layout .map((line) => { if (line === true) { const label = this.labels[lineCount++]; return this.buildShaft(label); } return gap; }) .join('\n'); return this.style(result); } /** * The width of the lines * * @return {number} */ get width() { const width = this.options.size * 3 + 1; if (this.labelLength > 0) { return width + 2 + this.labelLength; } return width; } /** * The height of the lines element based on it's neighbouring elements and * line count * * @return {number} */ get height() { return Math.max(this.neighbourHeight.shortest, this.ownHeight); } /** * The height of the lines if they where not surrounded by other elements * * @return {number} */ get ownHeight() { return this.count; } /** * The spacing of the lines returned as a boolean list * * @return {boolean[]} */ get layout() { const whitespace = this.height - this.count; let gapSize = whitespace / (this.count); let topPadding = 0; if (gapSize < 1) { gapSize = 0; topPadding = whitespace / 2; } else { topPadding = Math.round((whitespace - (gapSize * (this.count-1))) / 2); } const layout = new Array(this.height).fill(false); let position = topPadding; for (let i=0; i<this.count; i++) { layout[Math.floor(position)] = true; position += 1+gapSize; } return layout; } /** * Parse and normalize the labels * * @param {string[]} labels * @return {string[]} */ parseLabels(labels) { this.labelLength = labels.reduce((previous, current) => { if (typeof current === 'string') { return Math.max(previous, current.length); } return previous; }, 0); return labels.map((label) => { if (typeof label === 'string') { return label.padEnd(this.labelLength); } }); } /** * Build the string representation of the line with label * * @param {string} label * @return {string} */ buildShaft(label) { let shaft = '─'; if (typeof label !== 'string') { shaft = shaft.repeat(this.width); } else { const shaftLength = (this.width - this.labelLength - 1) / 2; shaft = shaft.repeat(shaftLength) + `┤${label}├` + shaft.repeat(shaftLength); } return shaft; } } module.exports = Line;