source: trip-planner-front/node_modules/cliui/build/index.cjs@ fa375fe

Last change on this file since fa375fe was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[6a3a178]1'use strict';
2
3const align = {
4 right: alignRight,
5 center: alignCenter
6};
7const top = 0;
8const right = 1;
9const bottom = 2;
10const left = 3;
11class UI {
12 constructor(opts) {
13 var _a;
14 this.width = opts.width;
15 this.wrap = (_a = opts.wrap) !== null && _a !== void 0 ? _a : true;
16 this.rows = [];
17 }
18 span(...args) {
19 const cols = this.div(...args);
20 cols.span = true;
21 }
22 resetOutput() {
23 this.rows = [];
24 }
25 div(...args) {
26 if (args.length === 0) {
27 this.div('');
28 }
29 if (this.wrap && this.shouldApplyLayoutDSL(...args) && typeof args[0] === 'string') {
30 return this.applyLayoutDSL(args[0]);
31 }
32 const cols = args.map(arg => {
33 if (typeof arg === 'string') {
34 return this.colFromString(arg);
35 }
36 return arg;
37 });
38 this.rows.push(cols);
39 return cols;
40 }
41 shouldApplyLayoutDSL(...args) {
42 return args.length === 1 && typeof args[0] === 'string' &&
43 /[\t\n]/.test(args[0]);
44 }
45 applyLayoutDSL(str) {
46 const rows = str.split('\n').map(row => row.split('\t'));
47 let leftColumnWidth = 0;
48 // simple heuristic for layout, make sure the
49 // second column lines up along the left-hand.
50 // don't allow the first column to take up more
51 // than 50% of the screen.
52 rows.forEach(columns => {
53 if (columns.length > 1 && mixin.stringWidth(columns[0]) > leftColumnWidth) {
54 leftColumnWidth = Math.min(Math.floor(this.width * 0.5), mixin.stringWidth(columns[0]));
55 }
56 });
57 // generate a table:
58 // replacing ' ' with padding calculations.
59 // using the algorithmically generated width.
60 rows.forEach(columns => {
61 this.div(...columns.map((r, i) => {
62 return {
63 text: r.trim(),
64 padding: this.measurePadding(r),
65 width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
66 };
67 }));
68 });
69 return this.rows[this.rows.length - 1];
70 }
71 colFromString(text) {
72 return {
73 text,
74 padding: this.measurePadding(text)
75 };
76 }
77 measurePadding(str) {
78 // measure padding without ansi escape codes
79 const noAnsi = mixin.stripAnsi(str);
80 return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length];
81 }
82 toString() {
83 const lines = [];
84 this.rows.forEach(row => {
85 this.rowToString(row, lines);
86 });
87 // don't display any lines with the
88 // hidden flag set.
89 return lines
90 .filter(line => !line.hidden)
91 .map(line => line.text)
92 .join('\n');
93 }
94 rowToString(row, lines) {
95 this.rasterize(row).forEach((rrow, r) => {
96 let str = '';
97 rrow.forEach((col, c) => {
98 const { width } = row[c]; // the width with padding.
99 const wrapWidth = this.negatePadding(row[c]); // the width without padding.
100 let ts = col; // temporary string used during alignment/padding.
101 if (wrapWidth > mixin.stringWidth(col)) {
102 ts += ' '.repeat(wrapWidth - mixin.stringWidth(col));
103 }
104 // align the string within its column.
105 if (row[c].align && row[c].align !== 'left' && this.wrap) {
106 const fn = align[row[c].align];
107 ts = fn(ts, wrapWidth);
108 if (mixin.stringWidth(ts) < wrapWidth) {
109 ts += ' '.repeat((width || 0) - mixin.stringWidth(ts) - 1);
110 }
111 }
112 // apply border and padding to string.
113 const padding = row[c].padding || [0, 0, 0, 0];
114 if (padding[left]) {
115 str += ' '.repeat(padding[left]);
116 }
117 str += addBorder(row[c], ts, '| ');
118 str += ts;
119 str += addBorder(row[c], ts, ' |');
120 if (padding[right]) {
121 str += ' '.repeat(padding[right]);
122 }
123 // if prior row is span, try to render the
124 // current row on the prior line.
125 if (r === 0 && lines.length > 0) {
126 str = this.renderInline(str, lines[lines.length - 1]);
127 }
128 });
129 // remove trailing whitespace.
130 lines.push({
131 text: str.replace(/ +$/, ''),
132 span: row.span
133 });
134 });
135 return lines;
136 }
137 // if the full 'source' can render in
138 // the target line, do so.
139 renderInline(source, previousLine) {
140 const match = source.match(/^ */);
141 const leadingWhitespace = match ? match[0].length : 0;
142 const target = previousLine.text;
143 const targetTextWidth = mixin.stringWidth(target.trimRight());
144 if (!previousLine.span) {
145 return source;
146 }
147 // if we're not applying wrapping logic,
148 // just always append to the span.
149 if (!this.wrap) {
150 previousLine.hidden = true;
151 return target + source;
152 }
153 if (leadingWhitespace < targetTextWidth) {
154 return source;
155 }
156 previousLine.hidden = true;
157 return target.trimRight() + ' '.repeat(leadingWhitespace - targetTextWidth) + source.trimLeft();
158 }
159 rasterize(row) {
160 const rrows = [];
161 const widths = this.columnWidths(row);
162 let wrapped;
163 // word wrap all columns, and create
164 // a data-structure that is easy to rasterize.
165 row.forEach((col, c) => {
166 // leave room for left and right padding.
167 col.width = widths[c];
168 if (this.wrap) {
169 wrapped = mixin.wrap(col.text, this.negatePadding(col), { hard: true }).split('\n');
170 }
171 else {
172 wrapped = col.text.split('\n');
173 }
174 if (col.border) {
175 wrapped.unshift('.' + '-'.repeat(this.negatePadding(col) + 2) + '.');
176 wrapped.push("'" + '-'.repeat(this.negatePadding(col) + 2) + "'");
177 }
178 // add top and bottom padding.
179 if (col.padding) {
180 wrapped.unshift(...new Array(col.padding[top] || 0).fill(''));
181 wrapped.push(...new Array(col.padding[bottom] || 0).fill(''));
182 }
183 wrapped.forEach((str, r) => {
184 if (!rrows[r]) {
185 rrows.push([]);
186 }
187 const rrow = rrows[r];
188 for (let i = 0; i < c; i++) {
189 if (rrow[i] === undefined) {
190 rrow.push('');
191 }
192 }
193 rrow.push(str);
194 });
195 });
196 return rrows;
197 }
198 negatePadding(col) {
199 let wrapWidth = col.width || 0;
200 if (col.padding) {
201 wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0);
202 }
203 if (col.border) {
204 wrapWidth -= 4;
205 }
206 return wrapWidth;
207 }
208 columnWidths(row) {
209 if (!this.wrap) {
210 return row.map(col => {
211 return col.width || mixin.stringWidth(col.text);
212 });
213 }
214 let unset = row.length;
215 let remainingWidth = this.width;
216 // column widths can be set in config.
217 const widths = row.map(col => {
218 if (col.width) {
219 unset--;
220 remainingWidth -= col.width;
221 return col.width;
222 }
223 return undefined;
224 });
225 // any unset widths should be calculated.
226 const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0;
227 return widths.map((w, i) => {
228 if (w === undefined) {
229 return Math.max(unsetWidth, _minWidth(row[i]));
230 }
231 return w;
232 });
233 }
234}
235function addBorder(col, ts, style) {
236 if (col.border) {
237 if (/[.']-+[.']/.test(ts)) {
238 return '';
239 }
240 if (ts.trim().length !== 0) {
241 return style;
242 }
243 return ' ';
244 }
245 return '';
246}
247// calculates the minimum width of
248// a column, based on padding preferences.
249function _minWidth(col) {
250 const padding = col.padding || [];
251 const minWidth = 1 + (padding[left] || 0) + (padding[right] || 0);
252 if (col.border) {
253 return minWidth + 4;
254 }
255 return minWidth;
256}
257function getWindowWidth() {
258 /* istanbul ignore next: depends on terminal */
259 if (typeof process === 'object' && process.stdout && process.stdout.columns) {
260 return process.stdout.columns;
261 }
262 return 80;
263}
264function alignRight(str, width) {
265 str = str.trim();
266 const strWidth = mixin.stringWidth(str);
267 if (strWidth < width) {
268 return ' '.repeat(width - strWidth) + str;
269 }
270 return str;
271}
272function alignCenter(str, width) {
273 str = str.trim();
274 const strWidth = mixin.stringWidth(str);
275 /* istanbul ignore next */
276 if (strWidth >= width) {
277 return str;
278 }
279 return ' '.repeat((width - strWidth) >> 1) + str;
280}
281let mixin;
282function cliui(opts, _mixin) {
283 mixin = _mixin;
284 return new UI({
285 width: (opts === null || opts === void 0 ? void 0 : opts.width) || getWindowWidth(),
286 wrap: opts === null || opts === void 0 ? void 0 : opts.wrap
287 });
288}
289
290// Bootstrap cliui with CommonJS dependencies:
291const stringWidth = require('string-width');
292const stripAnsi = require('strip-ansi');
293const wrap = require('wrap-ansi');
294function ui(opts) {
295 return cliui(opts, {
296 stringWidth,
297 stripAnsi,
298 wrap
299 });
300}
301
302module.exports = ui;
Note: See TracBrowser for help on using the repository browser.