@socketsecurity/cli-with-sentry 0.14.93 → 0.14.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/constants.js +3 -3
  2. package/dist/constants.js.map +1 -1
  3. package/dist/instrument-with-sentry.js +2 -2
  4. package/dist/instrument-with-sentry.js.map +1 -1
  5. package/dist/module-sync/cli.js +177 -157
  6. package/dist/module-sync/cli.js.map +1 -1
  7. package/dist/module-sync/shadow-bin.js +3 -14
  8. package/dist/module-sync/shadow-bin.js.map +1 -1
  9. package/dist/module-sync/shadow-npm-inject.js +68 -59
  10. package/dist/module-sync/shadow-npm-inject.js.map +1 -1
  11. package/dist/module-sync/shadow-npm-paths.js +16 -29
  12. package/dist/module-sync/shadow-npm-paths.js.map +1 -1
  13. package/dist/module-sync/vendor.d.ts +0 -0
  14. package/dist/module-sync/vendor.js +85829 -12598
  15. package/dist/module-sync/vendor.js.map +1 -1
  16. package/dist/require/cli.js +159 -138
  17. package/dist/require/cli.js.map +1 -1
  18. package/dist/require/shadow-bin.d.ts +5 -0
  19. package/dist/require/shadow-bin.js +108 -1
  20. package/dist/require/shadow-bin.js.map +1 -0
  21. package/dist/require/shadow-npm-inject.d.ts +1 -0
  22. package/dist/require/shadow-npm-inject.js +2335 -1
  23. package/dist/require/shadow-npm-inject.js.map +1 -0
  24. package/dist/require/shadow-npm-paths.d.ts +29 -0
  25. package/dist/require/shadow-npm-paths.js +454 -1
  26. package/dist/require/shadow-npm-paths.js.map +1 -0
  27. package/package.json +29 -29
  28. package/dist/blessed/lib/alias.js +0 -521
  29. package/dist/blessed/lib/blessed.js +0 -34
  30. package/dist/blessed/lib/colors.js +0 -492
  31. package/dist/blessed/lib/events.js +0 -197
  32. package/dist/blessed/lib/gpmclient.js +0 -247
  33. package/dist/blessed/lib/helpers.js +0 -172
  34. package/dist/blessed/lib/keys.js +0 -514
  35. package/dist/blessed/lib/program.js +0 -4532
  36. package/dist/blessed/lib/tput.js +0 -3113
  37. package/dist/blessed/lib/unicode.js +0 -914
  38. package/dist/blessed/lib/widget.js +0 -62
  39. package/dist/blessed/lib/widgets/ansiimage.js +0 -175
  40. package/dist/blessed/lib/widgets/bigtext.js +0 -172
  41. package/dist/blessed/lib/widgets/box.js +0 -36
  42. package/dist/blessed/lib/widgets/button.js +0 -64
  43. package/dist/blessed/lib/widgets/checkbox.js +0 -97
  44. package/dist/blessed/lib/widgets/element.js +0 -2873
  45. package/dist/blessed/lib/widgets/filemanager.js +0 -225
  46. package/dist/blessed/lib/widgets/form.js +0 -303
  47. package/dist/blessed/lib/widgets/image.js +0 -73
  48. package/dist/blessed/lib/widgets/input.js +0 -36
  49. package/dist/blessed/lib/widgets/layout.js +0 -251
  50. package/dist/blessed/lib/widgets/line.js +0 -61
  51. package/dist/blessed/lib/widgets/list.js +0 -654
  52. package/dist/blessed/lib/widgets/listbar.js +0 -454
  53. package/dist/blessed/lib/widgets/listtable.js +0 -267
  54. package/dist/blessed/lib/widgets/loading.js +0 -90
  55. package/dist/blessed/lib/widgets/log.js +0 -84
  56. package/dist/blessed/lib/widgets/message.js +0 -147
  57. package/dist/blessed/lib/widgets/node.js +0 -315
  58. package/dist/blessed/lib/widgets/overlayimage.js +0 -796
  59. package/dist/blessed/lib/widgets/progressbar.js +0 -168
  60. package/dist/blessed/lib/widgets/prompt.js +0 -129
  61. package/dist/blessed/lib/widgets/question.js +0 -131
  62. package/dist/blessed/lib/widgets/radiobutton.js +0 -64
  63. package/dist/blessed/lib/widgets/radioset.js +0 -38
  64. package/dist/blessed/lib/widgets/screen.js +0 -2487
  65. package/dist/blessed/lib/widgets/scrollablebox.js +0 -417
  66. package/dist/blessed/lib/widgets/scrollabletext.js +0 -37
  67. package/dist/blessed/lib/widgets/table.js +0 -385
  68. package/dist/blessed/lib/widgets/terminal.js +0 -454
  69. package/dist/blessed/lib/widgets/text.js +0 -37
  70. package/dist/blessed/lib/widgets/textarea.js +0 -378
  71. package/dist/blessed/lib/widgets/textbox.js +0 -81
  72. package/dist/blessed/lib/widgets/video.js +0 -132
  73. package/dist/blessed/usr/fonts/AUTHORS +0 -1
  74. package/dist/blessed/usr/fonts/LICENSE +0 -94
  75. package/dist/blessed/usr/fonts/README +0 -340
  76. package/dist/blessed/usr/fonts/ter-u14b.json +0 -17826
  77. package/dist/blessed/usr/fonts/ter-u14n.json +0 -17826
  78. package/dist/blessed/usr/linux +0 -0
  79. package/dist/blessed/usr/windows-ansi +0 -0
  80. package/dist/blessed/usr/xterm +0 -0
  81. package/dist/blessed/usr/xterm-256color +0 -0
  82. package/dist/blessed/usr/xterm.termcap +0 -243
  83. package/dist/blessed/usr/xterm.terminfo +0 -1977
  84. package/dist/blessed/vendor/tng.js +0 -1878
@@ -1,2873 +0,0 @@
1
- 'use strict'
2
-
3
- /**
4
- * element.js - base element for blessed
5
- * Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
6
- * https://github.com/chjj/blessed
7
- */
8
-
9
- /**
10
- * Modules
11
- */
12
-
13
- const assert = require('node:assert')
14
-
15
- const colors = require('../colors'),
16
- unicode = require('../unicode')
17
-
18
- const nextTick = global.setImmediate || process.nextTick.bind(process)
19
-
20
- const helpers = require('../helpers')
21
-
22
- const Node = require('./node')
23
-
24
- /**
25
- * Element
26
- */
27
-
28
- function Element(options) {
29
- const self = this
30
-
31
- if (!(this instanceof Node)) {
32
- return new Element(options)
33
- }
34
-
35
- options = options || {}
36
-
37
- // Workaround to get a `scrollable` option.
38
- if (options.scrollable && !this._ignore && this.type !== 'scrollable-box') {
39
- const ScrollableBox = require('./scrollablebox')
40
- Object.getOwnPropertyNames(ScrollableBox.prototype).forEach(function (key) {
41
- if (key === 'type') {
42
- return
43
- }
44
- Object.defineProperty(
45
- this,
46
- key,
47
- Object.getOwnPropertyDescriptor(ScrollableBox.prototype, key)
48
- )
49
- }, this)
50
- this._ignore = true
51
- ScrollableBox.call(this, options)
52
- delete this._ignore
53
- return this
54
- }
55
-
56
- Node.call(this, options)
57
-
58
- this.name = options.name
59
-
60
- options.position = options.position || {
61
- left: options.left,
62
- right: options.right,
63
- top: options.top,
64
- bottom: options.bottom,
65
- width: options.width,
66
- height: options.height
67
- }
68
-
69
- if (
70
- options.position.width === 'shrink' ||
71
- options.position.height === 'shrink'
72
- ) {
73
- if (options.position.width === 'shrink') {
74
- delete options.position.width
75
- }
76
- if (options.position.height === 'shrink') {
77
- delete options.position.height
78
- }
79
- options.shrink = true
80
- }
81
-
82
- this.position = options.position
83
-
84
- this.noOverflow = options.noOverflow
85
- this.dockBorders = options.dockBorders
86
- this.shadow = options.shadow
87
-
88
- this.style = options.style
89
-
90
- if (!this.style) {
91
- this.style = {}
92
- this.style.fg = options.fg
93
- this.style.bg = options.bg
94
- this.style.bold = options.bold
95
- this.style.underline = options.underline
96
- this.style.blink = options.blink
97
- this.style.inverse = options.inverse
98
- this.style.invisible = options.invisible
99
- this.style.transparent = options.transparent
100
- }
101
-
102
- this.hidden = options.hidden || false
103
- this.fixed = options.fixed || false
104
- this.align = options.align || 'left'
105
- this.valign = options.valign || 'top'
106
- this.wrap = options.wrap !== false
107
- this.shrink = options.shrink
108
- this.fixed = options.fixed
109
- this.ch = options.ch || ' '
110
-
111
- if (typeof options.padding === 'number' || !options.padding) {
112
- options.padding = {
113
- left: options.padding,
114
- top: options.padding,
115
- right: options.padding,
116
- bottom: options.padding
117
- }
118
- }
119
-
120
- this.padding = {
121
- left: options.padding.left || 0,
122
- top: options.padding.top || 0,
123
- right: options.padding.right || 0,
124
- bottom: options.padding.bottom || 0
125
- }
126
-
127
- this.border = options.border
128
- if (this.border) {
129
- if (typeof this.border === 'string') {
130
- this.border = { type: this.border }
131
- }
132
- this.border.type = this.border.type || 'bg'
133
- if (this.border.type === 'ascii') {
134
- this.border.type = 'line'
135
- }
136
- this.border.ch = this.border.ch || ' '
137
- this.style.border = this.style.border || this.border.style
138
- if (!this.style.border) {
139
- this.style.border = {}
140
- this.style.border.fg = this.border.fg
141
- this.style.border.bg = this.border.bg
142
- }
143
- //this.border.style = this.style.border;
144
- if (this.border.left == null) {
145
- this.border.left = true
146
- }
147
- if (this.border.top == null) {
148
- this.border.top = true
149
- }
150
- if (this.border.right == null) {
151
- this.border.right = true
152
- }
153
- if (this.border.bottom == null) {
154
- this.border.bottom = true
155
- }
156
- }
157
-
158
- // if (options.mouse || options.clickable) {
159
- if (options.clickable) {
160
- this.screen._listenMouse(this)
161
- }
162
-
163
- if (options.input || options.keyable) {
164
- this.screen._listenKeys(this)
165
- }
166
-
167
- this.parseTags = options.parseTags || options.tags
168
-
169
- this.setContent(options.content || '', true)
170
-
171
- if (options.label) {
172
- this.setLabel(options.label)
173
- }
174
-
175
- if (options.hoverText) {
176
- this.setHover(options.hoverText)
177
- }
178
-
179
- // TODO: Possibly move this to Node for onScreenEvent('mouse', ...).
180
- this.on('newListener', function fn(type) {
181
- // type = type.split(' ').slice(1).join(' ');
182
- if (
183
- type === 'mouse' ||
184
- type === 'click' ||
185
- type === 'mouseover' ||
186
- type === 'mouseout' ||
187
- type === 'mousedown' ||
188
- type === 'mouseup' ||
189
- type === 'mousewheel' ||
190
- type === 'wheeldown' ||
191
- type === 'wheelup' ||
192
- type === 'mousemove'
193
- ) {
194
- self.screen._listenMouse(self)
195
- } else if (type === 'keypress' || type.indexOf('key ') === 0) {
196
- self.screen._listenKeys(self)
197
- }
198
- })
199
-
200
- this.on('resize', function () {
201
- self.parseContent()
202
- })
203
-
204
- this.on('attach', function () {
205
- self.parseContent()
206
- })
207
-
208
- this.on('detach', function () {
209
- delete self.lpos
210
- })
211
-
212
- if (options.hoverBg != null) {
213
- options.hoverEffects = options.hoverEffects || {}
214
- options.hoverEffects.bg = options.hoverBg
215
- }
216
-
217
- if (this.style.hover) {
218
- options.hoverEffects = this.style.hover
219
- }
220
-
221
- if (this.style.focus) {
222
- options.focusEffects = this.style.focus
223
- }
224
-
225
- if (options.effects) {
226
- if (options.effects.hover) {
227
- options.hoverEffects = options.effects.hover
228
- }
229
- if (options.effects.focus) {
230
- options.focusEffects = options.effects.focus
231
- }
232
- }
233
-
234
- ;[
235
- ['hoverEffects', 'mouseover', 'mouseout', '_htemp'],
236
- ['focusEffects', 'focus', 'blur', '_ftemp']
237
- ].forEach(function (props) {
238
- const pname = props[0],
239
- over = props[1],
240
- out = props[2],
241
- temp = props[3]
242
- self.screen.setEffects(self, self, over, out, self.options[pname], temp)
243
- })
244
-
245
- if (this.options.draggable) {
246
- this.draggable = true
247
- }
248
-
249
- if (options.focused) {
250
- this.focus()
251
- }
252
- }
253
-
254
- Object.setPrototypeOf(Element.prototype, Node.prototype)
255
-
256
- Element.prototype.type = 'element'
257
-
258
- Element.prototype.__defineGetter__('focused', function () {
259
- return this.screen.focused === this
260
- })
261
-
262
- Element.prototype.sattr = function (style, fg, bg) {
263
- let bold = style.bold,
264
- underline = style.underline,
265
- blink = style.blink,
266
- inverse = style.inverse,
267
- invisible = style.invisible
268
-
269
- // if (arguments.length === 1) {
270
- if (fg == null && bg == null) {
271
- fg = style.fg
272
- bg = style.bg
273
- }
274
-
275
- // This used to be a loop, but I decided
276
- // to unroll it for performance's sake.
277
- if (typeof bold === 'function') {
278
- bold = bold(this)
279
- }
280
- if (typeof underline === 'function') {
281
- underline = underline(this)
282
- }
283
- if (typeof blink === 'function') {
284
- blink = blink(this)
285
- }
286
- if (typeof inverse === 'function') {
287
- inverse = inverse(this)
288
- }
289
- if (typeof invisible === 'function') {
290
- invisible = invisible(this)
291
- }
292
-
293
- if (typeof fg === 'function') {
294
- fg = fg(this)
295
- }
296
- if (typeof bg === 'function') {
297
- bg = bg(this)
298
- }
299
-
300
- // return (this.uid << 24)
301
- // | ((this.dockBorders ? 32 : 0) << 18)
302
- return (
303
- ((invisible ? 16 : 0) << 18) |
304
- ((inverse ? 8 : 0) << 18) |
305
- ((blink ? 4 : 0) << 18) |
306
- ((underline ? 2 : 0) << 18) |
307
- ((bold ? 1 : 0) << 18) |
308
- (colors.convert(fg) << 9) |
309
- colors.convert(bg)
310
- )
311
- }
312
-
313
- Element.prototype.onScreenEvent = function (type, handler) {
314
- const listeners = (this._slisteners = this._slisteners || [])
315
- listeners.push({ type: type, handler: handler })
316
- this.screen.on(type, handler)
317
- }
318
-
319
- Element.prototype.onceScreenEvent = function (type, handler) {
320
- const listeners = (this._slisteners = this._slisteners || [])
321
- const entry = { type: type, handler: handler }
322
- listeners.push(entry)
323
- this.screen.once(type, function () {
324
- const i = listeners.indexOf(entry)
325
- if (~i) {
326
- listeners.splice(i, 1)
327
- }
328
- return handler.apply(this, arguments)
329
- })
330
- }
331
-
332
- Element.prototype.removeScreenEvent = function (type, handler) {
333
- const listeners = (this._slisteners = this._slisteners || [])
334
- for (let i = 0; i < listeners.length; i++) {
335
- const listener = listeners[i]
336
- if (listener.type === type && listener.handler === handler) {
337
- listeners.splice(i, 1)
338
- if (this._slisteners.length === 0) {
339
- delete this._slisteners
340
- }
341
- break
342
- }
343
- }
344
- this.screen.removeListener(type, handler)
345
- }
346
-
347
- Element.prototype.free = function () {
348
- const listeners = (this._slisteners = this._slisteners || [])
349
- for (let i = 0; i < listeners.length; i++) {
350
- const listener = listeners[i]
351
- this.screen.removeListener(listener.type, listener.handler)
352
- }
353
- delete this._slisteners
354
- }
355
-
356
- Element.prototype.hide = function () {
357
- if (this.hidden) {
358
- return
359
- }
360
- this.clearPos()
361
- this.hidden = true
362
- this.emit('hide')
363
- if (this.screen.focused === this) {
364
- this.screen.rewindFocus()
365
- }
366
- }
367
-
368
- Element.prototype.show = function () {
369
- if (!this.hidden) {
370
- return
371
- }
372
- this.hidden = false
373
- this.emit('show')
374
- }
375
-
376
- Element.prototype.toggle = function () {
377
- return this.hidden ? this.show() : this.hide()
378
- }
379
-
380
- Element.prototype.focus = function () {
381
- return (this.screen.focused = this)
382
- }
383
-
384
- Element.prototype.setContent = function (content, noClear, noTags) {
385
- if (!noClear) {
386
- this.clearPos()
387
- }
388
- this.content = content || ''
389
- this.parseContent(noTags)
390
- this.emit('set content')
391
- }
392
-
393
- Element.prototype.getContent = function () {
394
- if (!this._clines) {
395
- return ''
396
- }
397
- return this._clines.fake.join('\n')
398
- }
399
-
400
- Element.prototype.setText = function (content, noClear) {
401
- content = content || ''
402
- content = content.replace(/\x1b\[[\d;]*m/g, '')
403
- return this.setContent(content, noClear, true)
404
- }
405
-
406
- Element.prototype.getText = function () {
407
- return this.getContent().replace(/\x1b\[[\d;]*m/g, '')
408
- }
409
-
410
- Element.prototype.parseContent = function (noTags) {
411
- if (this.detached) {
412
- return false
413
- }
414
-
415
- const width = this.width - this.iwidth
416
- if (
417
- this._clines == null ||
418
- this._clines.width !== width ||
419
- this._clines.content !== this.content
420
- ) {
421
- let content = this.content
422
-
423
- content = content
424
- .replace(/[\x00-\x08\x0b-\x0c\x0e-\x1a\x1c-\x1f\x7f]/g, '')
425
- .replace(/\x1b(?!\[[\d;]*m)/g, '')
426
- .replace(/\r\n|\r/g, '\n')
427
- .replace(/\t/g, this.screen.tabc)
428
-
429
- if (this.screen.fullUnicode) {
430
- // double-width chars will eat the next char after render. create a
431
- // blank character after it so it doesn't eat the real next char.
432
- content = content.replace(unicode.chars.all, '$1\x03')
433
- // iTerm2 cannot render combining characters properly.
434
- if (this.screen.program.isiTerm2) {
435
- content = content.replace(unicode.chars.combining, '')
436
- }
437
- } else {
438
- // no double-width: replace them with question-marks.
439
- content = content.replace(unicode.chars.all, '??')
440
- // delete combining characters since they're 0-width anyway.
441
- // NOTE: We could drop this, the non-surrogates would get changed to ? by
442
- // the unicode filter, and surrogates changed to ? by the surrogate
443
- // regex. however, the user might expect them to be 0-width.
444
- // NOTE: Might be better for performance to drop!
445
- content = content.replace(unicode.chars.combining, '')
446
- // no surrogate pairs: replace them with question-marks.
447
- content = content.replace(unicode.chars.surrogate, '?')
448
- // XXX Deduplicate code here:
449
- // content = helpers.dropUnicode(content);
450
- }
451
-
452
- if (!noTags) {
453
- content = this._parseTags(content)
454
- }
455
-
456
- this._clines = this._wrapContent(content, width)
457
- this._clines.width = width
458
- this._clines.content = this.content
459
- this._clines.attr = this._parseAttr(this._clines)
460
- this._clines.ci = []
461
- this._clines.reduce(
462
- function (total, line) {
463
- this._clines.ci.push(total)
464
- return total + line.length + 1
465
- }.bind(this),
466
- 0
467
- )
468
-
469
- this._pcontent = this._clines.join('\n')
470
- this.emit('parsed content')
471
-
472
- return true
473
- }
474
-
475
- // Need to calculate this every time because the default fg/bg may change.
476
- this._clines.attr = this._parseAttr(this._clines) || this._clines.attr
477
-
478
- return false
479
- }
480
-
481
- // Convert `{red-fg}foo{/red-fg}` to `\x1b[31mfoo\x1b[39m`.
482
- Element.prototype._parseTags = function (text) {
483
- if (!this.parseTags) {
484
- return text
485
- }
486
- if (!/{\/?[\w\-,;!#]*}/.test(text)) {
487
- return text
488
- }
489
-
490
- let program = this.screen.program,
491
- out = '',
492
- state,
493
- bg = [],
494
- fg = [],
495
- flag = [],
496
- cap,
497
- slash,
498
- param,
499
- attr,
500
- esc
501
-
502
- for (;;) {
503
- if (!esc && (cap = /^{escape}/.exec(text))) {
504
- text = text.substring(cap[0].length)
505
- esc = true
506
- continue
507
- }
508
-
509
- if (esc && (cap = /^([\s\S]+?){\/escape}/.exec(text))) {
510
- text = text.substring(cap[0].length)
511
- out += cap[1]
512
- esc = false
513
- continue
514
- }
515
-
516
- if (esc) {
517
- // throw new Error('Unterminated escape tag.');
518
- out += text
519
- break
520
- }
521
-
522
- if ((cap = /^{(\/?)([\w\-,;!#]*)}/.exec(text))) {
523
- text = text.substring(cap[0].length)
524
- slash = cap[1] === '/'
525
- param = cap[2].replace(/-/g, ' ')
526
-
527
- if (param === 'open') {
528
- out += '{'
529
- continue
530
- } else if (param === 'close') {
531
- out += '}'
532
- continue
533
- }
534
-
535
- if (param.slice(-3) === ' bg') {
536
- state = bg
537
- } else if (param.slice(-3) === ' fg') {
538
- state = fg
539
- } else {
540
- state = flag
541
- }
542
-
543
- if (slash) {
544
- if (!param) {
545
- out += program._attr('normal')
546
- bg.length = 0
547
- fg.length = 0
548
- flag.length = 0
549
- } else {
550
- attr = program._attr(param, false)
551
- if (attr == null) {
552
- out += cap[0]
553
- } else {
554
- // if (param !== state[state.length - 1]) {
555
- // throw new Error('Misnested tags.');
556
- // }
557
- state.pop()
558
- if (state.length) {
559
- out += program._attr(state[state.length - 1])
560
- } else {
561
- out += attr
562
- }
563
- }
564
- }
565
- } else {
566
- if (!param) {
567
- out += cap[0]
568
- } else {
569
- attr = program._attr(param)
570
- if (attr == null) {
571
- out += cap[0]
572
- } else {
573
- state.push(param)
574
- out += attr
575
- }
576
- }
577
- }
578
-
579
- continue
580
- }
581
-
582
- if ((cap = /^[\s\S]+?(?={\/?[\w\-,;!#]*})/.exec(text))) {
583
- text = text.substring(cap[0].length)
584
- out += cap[0]
585
- continue
586
- }
587
-
588
- out += text
589
- break
590
- }
591
-
592
- return out
593
- }
594
-
595
- Element.prototype._parseAttr = function (lines) {
596
- let dattr = this.sattr(this.style),
597
- attr = dattr,
598
- attrs = [],
599
- line,
600
- i,
601
- j,
602
- c
603
-
604
- if (lines[0].attr === attr) {
605
- return
606
- }
607
-
608
- for (j = 0; j < lines.length; j++) {
609
- line = lines[j]
610
- attrs[j] = attr
611
- for (i = 0; i < line.length; i++) {
612
- if (line[i] === '\x1b') {
613
- if ((c = /^\x1b\[[\d;]*m/.exec(line.substring(i)))) {
614
- attr = this.screen.attrCode(c[0], attr, dattr)
615
- i += c[0].length - 1
616
- }
617
- }
618
- }
619
- }
620
-
621
- return attrs
622
- }
623
-
624
- Element.prototype._align = function (line, width, align) {
625
- if (!align) {
626
- return line
627
- }
628
- //if (!align && !~line.indexOf('{|}')) return line;
629
-
630
- let cline = line.replace(/\x1b\[[\d;]*m/g, ''),
631
- len = cline.length,
632
- s = width - len
633
-
634
- if (this.shrink) {
635
- s = 0
636
- }
637
-
638
- if (len === 0) {
639
- return line
640
- }
641
- if (s < 0) {
642
- return line
643
- }
644
-
645
- if (align === 'center') {
646
- s = Array(((s / 2) | 0) + 1).join(' ')
647
- return s + line + s
648
- } else if (align === 'right') {
649
- s = Array(s + 1).join(' ')
650
- return s + line
651
- } else if (this.parseTags && ~line.indexOf('{|}')) {
652
- const parts = line.split('{|}')
653
- const cparts = cline.split('{|}')
654
- s = Math.max(width - cparts[0].length - cparts[1].length, 0)
655
- s = Array(s + 1).join(' ')
656
- return parts[0] + s + parts[1]
657
- }
658
-
659
- return line
660
- }
661
-
662
- Element.prototype._wrapContent = function (content, width) {
663
- let tags = this.parseTags,
664
- state = this.align,
665
- wrap = this.wrap,
666
- margin = 0,
667
- rtof = [],
668
- ftor = [],
669
- out = [],
670
- no = 0,
671
- line,
672
- align,
673
- cap,
674
- total,
675
- i,
676
- part,
677
- j,
678
- lines,
679
- rest
680
-
681
- lines = content.split('\n')
682
-
683
- if (!content) {
684
- out.push(content)
685
- out.rtof = [0]
686
- out.ftor = [[0]]
687
- out.fake = lines
688
- out.real = out
689
- out.mwidth = 0
690
- return out
691
- }
692
-
693
- if (this.scrollbar) {
694
- margin++
695
- }
696
- if (this.type === 'textarea') {
697
- margin++
698
- }
699
- if (width > margin) {
700
- width -= margin
701
- }
702
-
703
- main: for (; no < lines.length; no++) {
704
- line = lines[no]
705
- align = state
706
-
707
- ftor.push([])
708
-
709
- // Handle alignment tags.
710
- if (tags) {
711
- if ((cap = /^{(left|center|right)}/.exec(line))) {
712
- line = line.substring(cap[0].length)
713
- align = state = cap[1] !== 'left' ? cap[1] : null
714
- }
715
- if ((cap = /{\/(left|center|right)}$/.exec(line))) {
716
- line = line.slice(0, -cap[0].length)
717
- //state = null;
718
- state = this.align
719
- }
720
- }
721
-
722
- // If the string is apparently too long, wrap it.
723
- while (line.length > width) {
724
- // Measure the real width of the string.
725
- for (i = 0, total = 0; i < line.length; i++) {
726
- while (line[i] === '\x1b') {
727
- while (line[i] && line[i++] !== 'm') {}
728
- }
729
- if (!line[i]) {
730
- break
731
- }
732
- if (++total === width) {
733
- // If we're not wrapping the text, we have to finish up the rest of
734
- // the control sequences before cutting off the line.
735
- i++
736
- if (!wrap) {
737
- rest = line.substring(i).match(/\x1b\[[^m]*m/g)
738
- rest = rest ? rest.join('') : ''
739
- out.push(this._align(line.substring(0, i) + rest, width, align))
740
- ftor[no].push(out.length - 1)
741
- rtof.push(no)
742
- continue main
743
- }
744
- if (!this.screen.fullUnicode) {
745
- // Try to find a space to break on.
746
- if (i !== line.length) {
747
- j = i
748
- while (j > i - 10 && j > 0 && line[--j] !== ' ') {}
749
- if (line[j] === ' ') {
750
- i = j + 1
751
- }
752
- }
753
- } else {
754
- // Try to find a character to break on.
755
- if (i !== line.length) {
756
- // <XXX>
757
- // Compensate for surrogate length
758
- // counts on wrapping (experimental):
759
- // NOTE: Could optimize this by putting
760
- // it in the parent for loop.
761
- if (unicode.isSurrogate(line, i)) {
762
- i--
763
- }
764
- for (let s = 0, n = 0; n < i; n++) {
765
- if (unicode.isSurrogate(line, n)) {
766
- s++, n++
767
- }
768
- }
769
- i += s
770
- // </XXX>
771
- j = i
772
- // Break _past_ space.
773
- // Break _past_ double-width chars.
774
- // Break _past_ surrogate pairs.
775
- // Break _past_ combining chars.
776
- while (j > i - 10 && j > 0) {
777
- j--
778
- if (
779
- line[j] === ' ' ||
780
- line[j] === '\x03' ||
781
- (unicode.isSurrogate(line, j - 1) &&
782
- line[j + 1] !== '\x03') ||
783
- unicode.isCombining(line, j)
784
- ) {
785
- break
786
- }
787
- }
788
- if (
789
- line[j] === ' ' ||
790
- line[j] === '\x03' ||
791
- (unicode.isSurrogate(line, j - 1) && line[j + 1] !== '\x03') ||
792
- unicode.isCombining(line, j)
793
- ) {
794
- i = j + 1
795
- }
796
- }
797
- }
798
- break
799
- }
800
- }
801
-
802
- part = line.substring(0, i)
803
- line = line.substring(i)
804
-
805
- out.push(this._align(part, width, align))
806
- ftor[no].push(out.length - 1)
807
- rtof.push(no)
808
-
809
- // Make sure we didn't wrap the line to the very end, otherwise
810
- // we get a pointless empty line after a newline.
811
- if (line === '') {
812
- continue main
813
- }
814
-
815
- // If only an escape code got cut off, at it to `part`.
816
- if (/^(?:\x1b[[\d;]*m)+$/.test(line)) {
817
- out[out.length - 1] += line
818
- continue main
819
- }
820
- }
821
-
822
- out.push(this._align(line, width, align))
823
- ftor[no].push(out.length - 1)
824
- rtof.push(no)
825
- }
826
-
827
- out.rtof = rtof
828
- out.ftor = ftor
829
- out.fake = lines
830
- out.real = out
831
-
832
- out.mwidth = out.reduce(function (current, line) {
833
- line = line.replace(/\x1b\[[\d;]*m/g, '')
834
- return line.length > current ? line.length : current
835
- }, 0)
836
-
837
- return out
838
- }
839
-
840
- Element.prototype.__defineGetter__('visible', function () {
841
- let el = this
842
- do {
843
- if (el.detached) {
844
- return false
845
- }
846
- if (el.hidden) {
847
- return false
848
- }
849
- // if (!el.lpos) return false;
850
- // if (el.position.width === 0 || el.position.height === 0) return false;
851
- } while ((el = el.parent))
852
- return true
853
- })
854
-
855
- Element.prototype.__defineGetter__('_detached', function () {
856
- let el = this
857
- do {
858
- if (el.type === 'screen') {
859
- return false
860
- }
861
- if (!el.parent) {
862
- return true
863
- }
864
- } while ((el = el.parent))
865
- return false
866
- })
867
-
868
- Element.prototype.enableMouse = function () {
869
- this.screen._listenMouse(this)
870
- }
871
-
872
- Element.prototype.enableKeys = function () {
873
- this.screen._listenKeys(this)
874
- }
875
-
876
- Element.prototype.enableInput = function () {
877
- this.screen._listenMouse(this)
878
- this.screen._listenKeys(this)
879
- }
880
-
881
- Element.prototype.__defineGetter__('draggable', function () {
882
- return this._draggable === true
883
- })
884
-
885
- Element.prototype.__defineSetter__('draggable', function (draggable) {
886
- return draggable ? this.enableDrag(draggable) : this.disableDrag()
887
- })
888
-
889
- Element.prototype.enableDrag = function (verify) {
890
- const self = this
891
-
892
- if (this._draggable) {
893
- return true
894
- }
895
-
896
- if (typeof verify !== 'function') {
897
- verify = function () {
898
- return true
899
- }
900
- }
901
-
902
- this.enableMouse()
903
-
904
- this.on(
905
- 'mousedown',
906
- (this._dragMD = function (data) {
907
- if (self.screen._dragging) {
908
- return
909
- }
910
- if (!verify(data)) {
911
- return
912
- }
913
- self.screen._dragging = self
914
- self._drag = {
915
- x: data.x - self.aleft,
916
- y: data.y - self.atop
917
- }
918
- self.setFront()
919
- })
920
- )
921
-
922
- this.onScreenEvent(
923
- 'mouse',
924
- (this._dragM = function (data) {
925
- if (self.screen._dragging !== self) {
926
- return
927
- }
928
-
929
- if (data.action !== 'mousedown' && data.action !== 'mousemove') {
930
- delete self.screen._dragging
931
- delete self._drag
932
- return
933
- }
934
-
935
- // This can happen in edge cases where the user is
936
- // already dragging and element when it is detached.
937
- if (!self.parent) {
938
- return
939
- }
940
-
941
- const ox = self._drag.x,
942
- oy = self._drag.y,
943
- px = self.parent.aleft,
944
- py = self.parent.atop,
945
- x = data.x - px - ox,
946
- y = data.y - py - oy
947
-
948
- if (self.position.right != null) {
949
- if (self.position.left != null) {
950
- self.width = '100%-' + (self.parent.width - self.width)
951
- }
952
- self.position.right = null
953
- }
954
-
955
- if (self.position.bottom != null) {
956
- if (self.position.top != null) {
957
- self.height = '100%-' + (self.parent.height - self.height)
958
- }
959
- self.position.bottom = null
960
- }
961
-
962
- self.rleft = x
963
- self.rtop = y
964
-
965
- self.screen.render()
966
- })
967
- )
968
-
969
- return (this._draggable = true)
970
- }
971
-
972
- Element.prototype.disableDrag = function () {
973
- if (!this._draggable) {
974
- return false
975
- }
976
- delete this.screen._dragging
977
- delete this._drag
978
- this.removeListener('mousedown', this._dragMD)
979
- this.removeScreenEvent('mouse', this._dragM)
980
- return (this._draggable = false)
981
- }
982
-
983
- Element.prototype.key = function () {
984
- return this.screen.program.key.apply(this, arguments)
985
- }
986
-
987
- Element.prototype.onceKey = function () {
988
- return this.screen.program.onceKey.apply(this, arguments)
989
- }
990
-
991
- Element.prototype.unkey = Element.prototype.removeKey = function () {
992
- return this.screen.program.unkey.apply(this, arguments)
993
- }
994
-
995
- Element.prototype.setIndex = function (index) {
996
- if (!this.parent) {
997
- return
998
- }
999
-
1000
- if (index < 0) {
1001
- index = this.parent.children.length + index
1002
- }
1003
-
1004
- index = Math.max(index, 0)
1005
- index = Math.min(index, this.parent.children.length - 1)
1006
-
1007
- const i = this.parent.children.indexOf(this)
1008
- if (!~i) {
1009
- return
1010
- }
1011
-
1012
- const item = this.parent.children.splice(i, 1)[0]
1013
- this.parent.children.splice(index, 0, item)
1014
- }
1015
-
1016
- Element.prototype.setFront = function () {
1017
- return this.setIndex(-1)
1018
- }
1019
-
1020
- Element.prototype.setBack = function () {
1021
- return this.setIndex(0)
1022
- }
1023
-
1024
- Element.prototype.clearPos = function (get, override) {
1025
- if (this.detached) {
1026
- return
1027
- }
1028
- const lpos = this._getCoords(get)
1029
- if (!lpos) {
1030
- return
1031
- }
1032
- this.screen.clearRegion(lpos.xi, lpos.xl, lpos.yi, lpos.yl, override)
1033
- }
1034
-
1035
- Element.prototype.setLabel = function (options) {
1036
- const self = this
1037
- const Box = require('./box')
1038
-
1039
- if (typeof options === 'string') {
1040
- options = { text: options }
1041
- }
1042
-
1043
- if (this._label) {
1044
- this._label.setContent(options.text)
1045
- if (options.side !== 'right') {
1046
- this._label.rleft = 2 + (this.border ? -1 : 0)
1047
- this._label.position.right = undefined
1048
- if (!this.screen.autoPadding) {
1049
- this._label.rleft = 2
1050
- }
1051
- } else {
1052
- this._label.rright = 2 + (this.border ? -1 : 0)
1053
- this._label.position.left = undefined
1054
- if (!this.screen.autoPadding) {
1055
- this._label.rright = 2
1056
- }
1057
- }
1058
- return
1059
- }
1060
-
1061
- this._label = new Box({
1062
- screen: this.screen,
1063
- parent: this,
1064
- content: options.text,
1065
- top: -this.itop,
1066
- tags: this.parseTags,
1067
- shrink: true,
1068
- style: this.style.label
1069
- })
1070
-
1071
- if (options.side !== 'right') {
1072
- this._label.rleft = 2 - this.ileft
1073
- } else {
1074
- this._label.rright = 2 - this.iright
1075
- }
1076
-
1077
- this._label._isLabel = true
1078
-
1079
- if (!this.screen.autoPadding) {
1080
- if (options.side !== 'right') {
1081
- this._label.rleft = 2
1082
- } else {
1083
- this._label.rright = 2
1084
- }
1085
- this._label.rtop = 0
1086
- }
1087
-
1088
- const reposition = function () {
1089
- self._label.rtop = (self.childBase || 0) - self.itop
1090
- if (!self.screen.autoPadding) {
1091
- self._label.rtop = self.childBase || 0
1092
- }
1093
- self.screen.render()
1094
- }
1095
-
1096
- this.on(
1097
- 'scroll',
1098
- (this._labelScroll = function () {
1099
- reposition()
1100
- })
1101
- )
1102
-
1103
- this.on(
1104
- 'resize',
1105
- (this._labelResize = function () {
1106
- nextTick(function () {
1107
- reposition()
1108
- })
1109
- })
1110
- )
1111
- }
1112
-
1113
- Element.prototype.removeLabel = function () {
1114
- if (!this._label) {
1115
- return
1116
- }
1117
- this.removeListener('scroll', this._labelScroll)
1118
- this.removeListener('resize', this._labelResize)
1119
- this._label.detach()
1120
- delete this._labelScroll
1121
- delete this._labelResize
1122
- delete this._label
1123
- }
1124
-
1125
- Element.prototype.setHover = function (options) {
1126
- if (typeof options === 'string') {
1127
- options = { text: options }
1128
- }
1129
-
1130
- this._hoverOptions = options
1131
- this.enableMouse()
1132
- this.screen._initHover()
1133
- }
1134
-
1135
- Element.prototype.removeHover = function () {
1136
- delete this._hoverOptions
1137
- if (!this.screen._hoverText || this.screen._hoverText.detached) {
1138
- return
1139
- }
1140
- this.screen._hoverText.detach()
1141
- this.screen.render()
1142
- }
1143
-
1144
- /**
1145
- * Positioning
1146
- */
1147
-
1148
- // The below methods are a bit confusing: basically
1149
- // whenever Box.render is called `lpos` gets set on
1150
- // the element, an object containing the rendered
1151
- // coordinates. Since these don't update if the
1152
- // element is moved somehow, they're unreliable in
1153
- // that situation. However, if we can guarantee that
1154
- // lpos is good and up to date, it can be more
1155
- // accurate than the calculated positions below.
1156
- // In this case, if the element is being rendered,
1157
- // it's guaranteed that the parent will have been
1158
- // rendered first, in which case we can use the
1159
- // parant's lpos instead of recalculating it's
1160
- // position (since that might be wrong because
1161
- // it doesn't handle content shrinkage).
1162
-
1163
- Element.prototype._getPos = function () {
1164
- const pos = this.lpos
1165
-
1166
- assert.ok(pos)
1167
-
1168
- if (pos.aleft != null) {
1169
- return pos
1170
- }
1171
-
1172
- pos.aleft = pos.xi
1173
- pos.atop = pos.yi
1174
- pos.aright = this.screen.cols - pos.xl
1175
- pos.abottom = this.screen.rows - pos.yl
1176
- pos.width = pos.xl - pos.xi
1177
- pos.height = pos.yl - pos.yi
1178
-
1179
- return pos
1180
- }
1181
-
1182
- /**
1183
- * Position Getters
1184
- */
1185
-
1186
- Element.prototype._getWidth = function (get) {
1187
- let parent = get ? this.parent._getPos() : this.parent,
1188
- width = this.position.width,
1189
- left,
1190
- expr
1191
-
1192
- if (typeof width === 'string') {
1193
- if (width === 'half') {
1194
- width = '50%'
1195
- }
1196
- expr = width.split(/(?=\+|-)/)
1197
- width = expr[0]
1198
- width = +width.slice(0, -1) / 100
1199
- width = (parent.width * width) | 0
1200
- width += +(expr[1] || 0)
1201
- return width
1202
- }
1203
-
1204
- // This is for if the element is being streched or shrunken.
1205
- // Although the width for shrunken elements is calculated
1206
- // in the render function, it may be calculated based on
1207
- // the content width, and the content width is initially
1208
- // decided by the width the element, so it needs to be
1209
- // calculated here.
1210
- if (width == null) {
1211
- left = this.position.left || 0
1212
- if (typeof left === 'string') {
1213
- if (left === 'center') {
1214
- left = '50%'
1215
- }
1216
- expr = left.split(/(?=\+|-)/)
1217
- left = expr[0]
1218
- left = +left.slice(0, -1) / 100
1219
- left = (parent.width * left) | 0
1220
- left += +(expr[1] || 0)
1221
- }
1222
- width = parent.width - (this.position.right || 0) - left
1223
- if (this.screen.autoPadding) {
1224
- if (
1225
- (this.position.left != null || this.position.right == null) &&
1226
- this.position.left !== 'center'
1227
- ) {
1228
- width -= this.parent.ileft
1229
- }
1230
- width -= this.parent.iright
1231
- }
1232
- }
1233
-
1234
- return width
1235
- }
1236
-
1237
- Element.prototype.__defineGetter__('width', function () {
1238
- return this._getWidth(false)
1239
- })
1240
-
1241
- Element.prototype._getHeight = function (get) {
1242
- let parent = get ? this.parent._getPos() : this.parent,
1243
- height = this.position.height,
1244
- top,
1245
- expr
1246
-
1247
- if (typeof height === 'string') {
1248
- if (height === 'half') {
1249
- height = '50%'
1250
- }
1251
- expr = height.split(/(?=\+|-)/)
1252
- height = expr[0]
1253
- height = +height.slice(0, -1) / 100
1254
- height = (parent.height * height) | 0
1255
- height += +(expr[1] || 0)
1256
- return height
1257
- }
1258
-
1259
- // This is for if the element is being streched or shrunken.
1260
- // Although the width for shrunken elements is calculated
1261
- // in the render function, it may be calculated based on
1262
- // the content width, and the content width is initially
1263
- // decided by the width the element, so it needs to be
1264
- // calculated here.
1265
- if (height == null) {
1266
- top = this.position.top || 0
1267
- if (typeof top === 'string') {
1268
- if (top === 'center') {
1269
- top = '50%'
1270
- }
1271
- expr = top.split(/(?=\+|-)/)
1272
- top = expr[0]
1273
- top = +top.slice(0, -1) / 100
1274
- top = (parent.height * top) | 0
1275
- top += +(expr[1] || 0)
1276
- }
1277
- height = parent.height - (this.position.bottom || 0) - top
1278
- if (this.screen.autoPadding) {
1279
- if (
1280
- (this.position.top != null || this.position.bottom == null) &&
1281
- this.position.top !== 'center'
1282
- ) {
1283
- height -= this.parent.itop
1284
- }
1285
- height -= this.parent.ibottom
1286
- }
1287
- }
1288
-
1289
- return height
1290
- }
1291
-
1292
- Element.prototype.__defineGetter__('height', function () {
1293
- return this._getHeight(false)
1294
- })
1295
-
1296
- Element.prototype._getLeft = function (get) {
1297
- let parent = get ? this.parent._getPos() : this.parent,
1298
- left = this.position.left || 0,
1299
- expr
1300
-
1301
- if (typeof left === 'string') {
1302
- if (left === 'center') {
1303
- left = '50%'
1304
- }
1305
- expr = left.split(/(?=\+|-)/)
1306
- left = expr[0]
1307
- left = +left.slice(0, -1) / 100
1308
- left = (parent.width * left) | 0
1309
- left += +(expr[1] || 0)
1310
- if (this.position.left === 'center') {
1311
- left -= (this._getWidth(get) / 2) | 0
1312
- }
1313
- }
1314
-
1315
- if (this.position.left == null && this.position.right != null) {
1316
- return this.screen.cols - this._getWidth(get) - this._getRight(get)
1317
- }
1318
-
1319
- if (this.screen.autoPadding) {
1320
- if (
1321
- (this.position.left != null || this.position.right == null) &&
1322
- this.position.left !== 'center'
1323
- ) {
1324
- left += this.parent.ileft
1325
- }
1326
- }
1327
-
1328
- return (parent.aleft || 0) + left
1329
- }
1330
-
1331
- Element.prototype.__defineGetter__('aleft', function () {
1332
- return this._getLeft(false)
1333
- })
1334
-
1335
- Element.prototype._getRight = function (get) {
1336
- let parent = get ? this.parent._getPos() : this.parent,
1337
- right
1338
-
1339
- if (this.position.right == null && this.position.left != null) {
1340
- right = this.screen.cols - (this._getLeft(get) + this._getWidth(get))
1341
- if (this.screen.autoPadding) {
1342
- right += this.parent.iright
1343
- }
1344
- return right
1345
- }
1346
-
1347
- right = (parent.aright || 0) + (this.position.right || 0)
1348
-
1349
- if (this.screen.autoPadding) {
1350
- right += this.parent.iright
1351
- }
1352
-
1353
- return right
1354
- }
1355
-
1356
- Element.prototype.__defineGetter__('aright', function () {
1357
- return this._getRight(false)
1358
- })
1359
-
1360
- Element.prototype._getTop = function (get) {
1361
- let parent = get ? this.parent._getPos() : this.parent,
1362
- top = this.position.top || 0,
1363
- expr
1364
-
1365
- if (typeof top === 'string') {
1366
- if (top === 'center') {
1367
- top = '50%'
1368
- }
1369
- expr = top.split(/(?=\+|-)/)
1370
- top = expr[0]
1371
- top = +top.slice(0, -1) / 100
1372
- top = (parent.height * top) | 0
1373
- top += +(expr[1] || 0)
1374
- if (this.position.top === 'center') {
1375
- top -= (this._getHeight(get) / 2) | 0
1376
- }
1377
- }
1378
-
1379
- if (this.position.top == null && this.position.bottom != null) {
1380
- return this.screen.rows - this._getHeight(get) - this._getBottom(get)
1381
- }
1382
-
1383
- if (this.screen.autoPadding) {
1384
- if (
1385
- (this.position.top != null || this.position.bottom == null) &&
1386
- this.position.top !== 'center'
1387
- ) {
1388
- top += this.parent.itop
1389
- }
1390
- }
1391
-
1392
- return (parent.atop || 0) + top
1393
- }
1394
-
1395
- Element.prototype.__defineGetter__('atop', function () {
1396
- return this._getTop(false)
1397
- })
1398
-
1399
- Element.prototype._getBottom = function (get) {
1400
- let parent = get ? this.parent._getPos() : this.parent,
1401
- bottom
1402
-
1403
- if (this.position.bottom == null && this.position.top != null) {
1404
- bottom = this.screen.rows - (this._getTop(get) + this._getHeight(get))
1405
- if (this.screen.autoPadding) {
1406
- bottom += this.parent.ibottom
1407
- }
1408
- return bottom
1409
- }
1410
-
1411
- bottom = (parent.abottom || 0) + (this.position.bottom || 0)
1412
-
1413
- if (this.screen.autoPadding) {
1414
- bottom += this.parent.ibottom
1415
- }
1416
-
1417
- return bottom
1418
- }
1419
-
1420
- Element.prototype.__defineGetter__('abottom', function () {
1421
- return this._getBottom(false)
1422
- })
1423
-
1424
- Element.prototype.__defineGetter__('rleft', function () {
1425
- return this.aleft - this.parent.aleft
1426
- })
1427
-
1428
- Element.prototype.__defineGetter__('rright', function () {
1429
- return this.aright - this.parent.aright
1430
- })
1431
-
1432
- Element.prototype.__defineGetter__('rtop', function () {
1433
- return this.atop - this.parent.atop
1434
- })
1435
-
1436
- Element.prototype.__defineGetter__('rbottom', function () {
1437
- return this.abottom - this.parent.abottom
1438
- })
1439
-
1440
- /**
1441
- * Position Setters
1442
- */
1443
-
1444
- // NOTE:
1445
- // For aright, abottom, right, and bottom:
1446
- // If position.bottom is null, we could simply set top instead.
1447
- // But it wouldn't replicate bottom behavior appropriately if
1448
- // the parent was resized, etc.
1449
- Element.prototype.__defineSetter__('width', function (val) {
1450
- if (this.position.width === val) {
1451
- return
1452
- }
1453
- if (/^\d+$/.test(val)) {
1454
- val = +val
1455
- }
1456
- this.emit('resize')
1457
- this.clearPos()
1458
- return (this.position.width = val)
1459
- })
1460
-
1461
- Element.prototype.__defineSetter__('height', function (val) {
1462
- if (this.position.height === val) {
1463
- return
1464
- }
1465
- if (/^\d+$/.test(val)) {
1466
- val = +val
1467
- }
1468
- this.emit('resize')
1469
- this.clearPos()
1470
- return (this.position.height = val)
1471
- })
1472
-
1473
- Element.prototype.__defineSetter__('aleft', function (val) {
1474
- let expr
1475
- if (typeof val === 'string') {
1476
- if (val === 'center') {
1477
- val = (this.screen.width / 2) | 0
1478
- val -= (this.width / 2) | 0
1479
- } else {
1480
- expr = val.split(/(?=\+|-)/)
1481
- val = expr[0]
1482
- val = +val.slice(0, -1) / 100
1483
- val = (this.screen.width * val) | 0
1484
- val += +(expr[1] || 0)
1485
- }
1486
- }
1487
- val -= this.parent.aleft
1488
- if (this.position.left === val) {
1489
- return
1490
- }
1491
- this.emit('move')
1492
- this.clearPos()
1493
- return (this.position.left = val)
1494
- })
1495
-
1496
- Element.prototype.__defineSetter__('aright', function (val) {
1497
- val -= this.parent.aright
1498
- if (this.position.right === val) {
1499
- return
1500
- }
1501
- this.emit('move')
1502
- this.clearPos()
1503
- return (this.position.right = val)
1504
- })
1505
-
1506
- Element.prototype.__defineSetter__('atop', function (val) {
1507
- let expr
1508
- if (typeof val === 'string') {
1509
- if (val === 'center') {
1510
- val = (this.screen.height / 2) | 0
1511
- val -= (this.height / 2) | 0
1512
- } else {
1513
- expr = val.split(/(?=\+|-)/)
1514
- val = expr[0]
1515
- val = +val.slice(0, -1) / 100
1516
- val = (this.screen.height * val) | 0
1517
- val += +(expr[1] || 0)
1518
- }
1519
- }
1520
- val -= this.parent.atop
1521
- if (this.position.top === val) {
1522
- return
1523
- }
1524
- this.emit('move')
1525
- this.clearPos()
1526
- return (this.position.top = val)
1527
- })
1528
-
1529
- Element.prototype.__defineSetter__('abottom', function (val) {
1530
- val -= this.parent.abottom
1531
- if (this.position.bottom === val) {
1532
- return
1533
- }
1534
- this.emit('move')
1535
- this.clearPos()
1536
- return (this.position.bottom = val)
1537
- })
1538
-
1539
- Element.prototype.__defineSetter__('rleft', function (val) {
1540
- if (this.position.left === val) {
1541
- return
1542
- }
1543
- if (/^\d+$/.test(val)) {
1544
- val = +val
1545
- }
1546
- this.emit('move')
1547
- this.clearPos()
1548
- return (this.position.left = val)
1549
- })
1550
-
1551
- Element.prototype.__defineSetter__('rright', function (val) {
1552
- if (this.position.right === val) {
1553
- return
1554
- }
1555
- this.emit('move')
1556
- this.clearPos()
1557
- return (this.position.right = val)
1558
- })
1559
-
1560
- Element.prototype.__defineSetter__('rtop', function (val) {
1561
- if (this.position.top === val) {
1562
- return
1563
- }
1564
- if (/^\d+$/.test(val)) {
1565
- val = +val
1566
- }
1567
- this.emit('move')
1568
- this.clearPos()
1569
- return (this.position.top = val)
1570
- })
1571
-
1572
- Element.prototype.__defineSetter__('rbottom', function (val) {
1573
- if (this.position.bottom === val) {
1574
- return
1575
- }
1576
- this.emit('move')
1577
- this.clearPos()
1578
- return (this.position.bottom = val)
1579
- })
1580
-
1581
- Element.prototype.__defineGetter__('ileft', function () {
1582
- return (this.border ? 1 : 0) + this.padding.left
1583
- // return (this.border && this.border.left ? 1 : 0) + this.padding.left;
1584
- })
1585
-
1586
- Element.prototype.__defineGetter__('itop', function () {
1587
- return (this.border ? 1 : 0) + this.padding.top
1588
- // return (this.border && this.border.top ? 1 : 0) + this.padding.top;
1589
- })
1590
-
1591
- Element.prototype.__defineGetter__('iright', function () {
1592
- return (this.border ? 1 : 0) + this.padding.right
1593
- // return (this.border && this.border.right ? 1 : 0) + this.padding.right;
1594
- })
1595
-
1596
- Element.prototype.__defineGetter__('ibottom', function () {
1597
- return (this.border ? 1 : 0) + this.padding.bottom
1598
- // return (this.border && this.border.bottom ? 1 : 0) + this.padding.bottom;
1599
- })
1600
-
1601
- Element.prototype.__defineGetter__('iwidth', function () {
1602
- // return (this.border
1603
- // ? ((this.border.left ? 1 : 0) + (this.border.right ? 1 : 0)) : 0)
1604
- // + this.padding.left + this.padding.right;
1605
- return (this.border ? 2 : 0) + this.padding.left + this.padding.right
1606
- })
1607
-
1608
- Element.prototype.__defineGetter__('iheight', function () {
1609
- // return (this.border
1610
- // ? ((this.border.top ? 1 : 0) + (this.border.bottom ? 1 : 0)) : 0)
1611
- // + this.padding.top + this.padding.bottom;
1612
- return (this.border ? 2 : 0) + this.padding.top + this.padding.bottom
1613
- })
1614
-
1615
- Element.prototype.__defineGetter__('tpadding', function () {
1616
- return (
1617
- this.padding.left +
1618
- this.padding.top +
1619
- this.padding.right +
1620
- this.padding.bottom
1621
- )
1622
- })
1623
-
1624
- /**
1625
- * Relative coordinates as default properties
1626
- */
1627
-
1628
- Element.prototype.__defineGetter__('left', function () {
1629
- return this.rleft
1630
- })
1631
-
1632
- Element.prototype.__defineGetter__('right', function () {
1633
- return this.rright
1634
- })
1635
-
1636
- Element.prototype.__defineGetter__('top', function () {
1637
- return this.rtop
1638
- })
1639
-
1640
- Element.prototype.__defineGetter__('bottom', function () {
1641
- return this.rbottom
1642
- })
1643
-
1644
- Element.prototype.__defineSetter__('left', function (val) {
1645
- return (this.rleft = val)
1646
- })
1647
-
1648
- Element.prototype.__defineSetter__('right', function (val) {
1649
- return (this.rright = val)
1650
- })
1651
-
1652
- Element.prototype.__defineSetter__('top', function (val) {
1653
- return (this.rtop = val)
1654
- })
1655
-
1656
- Element.prototype.__defineSetter__('bottom', function (val) {
1657
- return (this.rbottom = val)
1658
- })
1659
-
1660
- /**
1661
- * Rendering - here be dragons
1662
- */
1663
-
1664
- Element.prototype._getShrinkBox = function (xi, xl, yi, yl, get) {
1665
- if (!this.children.length) {
1666
- return { xi: xi, xl: xi + 1, yi: yi, yl: yi + 1 }
1667
- }
1668
-
1669
- let i,
1670
- el,
1671
- ret,
1672
- mxi = xi,
1673
- mxl = xi + 1,
1674
- myi = yi,
1675
- myl = yi + 1
1676
-
1677
- // This is a chicken and egg problem. We need to determine how the children
1678
- // will render in order to determine how this element renders, but it in
1679
- // order to figure out how the children will render, they need to know
1680
- // exactly how their parent renders, so, we can give them what we have so
1681
- // far.
1682
- let _lpos
1683
- if (get) {
1684
- _lpos = this.lpos
1685
- this.lpos = { xi: xi, xl: xl, yi: yi, yl: yl }
1686
- //this.shrink = false;
1687
- }
1688
-
1689
- for (i = 0; i < this.children.length; i++) {
1690
- el = this.children[i]
1691
-
1692
- ret = el._getCoords(get)
1693
-
1694
- // Or just (seemed to work, but probably not good):
1695
- // ret = el.lpos || this.lpos;
1696
-
1697
- if (!ret) {
1698
- continue
1699
- }
1700
-
1701
- // Since the parent element is shrunk, and the child elements think it's
1702
- // going to take up as much space as possible, an element anchored to the
1703
- // right or bottom will inadvertantly make the parent's shrunken size as
1704
- // large as possible. So, we can just use the height and/or width the of
1705
- // element.
1706
- // if (get) {
1707
- if (el.position.left == null && el.position.right != null) {
1708
- ret.xl = xi + (ret.xl - ret.xi)
1709
- ret.xi = xi
1710
- if (this.screen.autoPadding) {
1711
- // Maybe just do this no matter what.
1712
- ret.xl += this.ileft
1713
- ret.xi += this.ileft
1714
- }
1715
- }
1716
- if (el.position.top == null && el.position.bottom != null) {
1717
- ret.yl = yi + (ret.yl - ret.yi)
1718
- ret.yi = yi
1719
- if (this.screen.autoPadding) {
1720
- // Maybe just do this no matter what.
1721
- ret.yl += this.itop
1722
- ret.yi += this.itop
1723
- }
1724
- }
1725
-
1726
- if (ret.xi < mxi) {
1727
- mxi = ret.xi
1728
- }
1729
- if (ret.xl > mxl) {
1730
- mxl = ret.xl
1731
- }
1732
- if (ret.yi < myi) {
1733
- myi = ret.yi
1734
- }
1735
- if (ret.yl > myl) {
1736
- myl = ret.yl
1737
- }
1738
- }
1739
-
1740
- if (get) {
1741
- this.lpos = _lpos
1742
- //this.shrink = true;
1743
- }
1744
-
1745
- if (
1746
- this.position.width == null &&
1747
- (this.position.left == null || this.position.right == null)
1748
- ) {
1749
- if (this.position.left == null && this.position.right != null) {
1750
- xi = xl - (mxl - mxi)
1751
- if (!this.screen.autoPadding) {
1752
- xi -= this.padding.left + this.padding.right
1753
- } else {
1754
- xi -= this.ileft
1755
- }
1756
- } else {
1757
- xl = mxl
1758
- if (!this.screen.autoPadding) {
1759
- xl += this.padding.left + this.padding.right
1760
- // XXX Temporary workaround until we decide to make autoPadding default.
1761
- // See widget-listtable.js for an example of why this is necessary.
1762
- // XXX Maybe just to this for all this being that this would affect
1763
- // width shrunken normal shrunken lists as well.
1764
- // if (this._isList) {
1765
- if (this.type === 'list-table') {
1766
- xl -= this.padding.left + this.padding.right
1767
- xl += this.iright
1768
- }
1769
- } else {
1770
- //xl += this.padding.right;
1771
- xl += this.iright
1772
- }
1773
- }
1774
- }
1775
-
1776
- if (
1777
- this.position.height == null &&
1778
- (this.position.top == null || this.position.bottom == null) &&
1779
- (!this.scrollable || this._isList)
1780
- ) {
1781
- // NOTE: Lists get special treatment if they are shrunken - assume they
1782
- // want all list items showing. This is one case we can calculate the
1783
- // height based on items/boxes.
1784
- if (this._isList) {
1785
- myi = 0 - this.itop
1786
- myl = this.items.length + this.ibottom
1787
- }
1788
- if (this.position.top == null && this.position.bottom != null) {
1789
- yi = yl - (myl - myi)
1790
- if (!this.screen.autoPadding) {
1791
- yi -= this.padding.top + this.padding.bottom
1792
- } else {
1793
- yi -= this.itop
1794
- }
1795
- } else {
1796
- yl = myl
1797
- if (!this.screen.autoPadding) {
1798
- yl += this.padding.top + this.padding.bottom
1799
- } else {
1800
- yl += this.ibottom
1801
- }
1802
- }
1803
- }
1804
-
1805
- return { xi: xi, xl: xl, yi: yi, yl: yl }
1806
- }
1807
-
1808
- Element.prototype._getShrinkContent = function (xi, xl, yi, yl) {
1809
- const h = this._clines.length,
1810
- w = this._clines.mwidth || 1
1811
-
1812
- if (
1813
- this.position.width == null &&
1814
- (this.position.left == null || this.position.right == null)
1815
- ) {
1816
- if (this.position.left == null && this.position.right != null) {
1817
- xi = xl - w - this.iwidth
1818
- } else {
1819
- xl = xi + w + this.iwidth
1820
- }
1821
- }
1822
-
1823
- if (
1824
- this.position.height == null &&
1825
- (this.position.top == null || this.position.bottom == null) &&
1826
- (!this.scrollable || this._isList)
1827
- ) {
1828
- if (this.position.top == null && this.position.bottom != null) {
1829
- yi = yl - h - this.iheight
1830
- } else {
1831
- yl = yi + h + this.iheight
1832
- }
1833
- }
1834
-
1835
- return { xi: xi, xl: xl, yi: yi, yl: yl }
1836
- }
1837
-
1838
- Element.prototype._getShrink = function (xi, xl, yi, yl, get) {
1839
- let shrinkBox = this._getShrinkBox(xi, xl, yi, yl, get),
1840
- shrinkContent = this._getShrinkContent(xi, xl, yi, yl, get),
1841
- xll = xl,
1842
- yll = yl
1843
-
1844
- // Figure out which one is bigger and use it.
1845
- if (shrinkBox.xl - shrinkBox.xi > shrinkContent.xl - shrinkContent.xi) {
1846
- xi = shrinkBox.xi
1847
- xl = shrinkBox.xl
1848
- } else {
1849
- xi = shrinkContent.xi
1850
- xl = shrinkContent.xl
1851
- }
1852
-
1853
- if (shrinkBox.yl - shrinkBox.yi > shrinkContent.yl - shrinkContent.yi) {
1854
- yi = shrinkBox.yi
1855
- yl = shrinkBox.yl
1856
- } else {
1857
- yi = shrinkContent.yi
1858
- yl = shrinkContent.yl
1859
- }
1860
-
1861
- // Recenter shrunken elements.
1862
- if (xl < xll && this.position.left === 'center') {
1863
- xll = ((xll - xl) / 2) | 0
1864
- xi += xll
1865
- xl += xll
1866
- }
1867
-
1868
- if (yl < yll && this.position.top === 'center') {
1869
- yll = ((yll - yl) / 2) | 0
1870
- yi += yll
1871
- yl += yll
1872
- }
1873
-
1874
- return { xi: xi, xl: xl, yi: yi, yl: yl }
1875
- }
1876
-
1877
- Element.prototype._getCoords = function (get, noscroll) {
1878
- if (this.hidden) {
1879
- return
1880
- }
1881
-
1882
- // if (this.parent._rendering) {
1883
- // get = true;
1884
- // }
1885
-
1886
- let xi = this._getLeft(get),
1887
- xl = xi + this._getWidth(get),
1888
- yi = this._getTop(get),
1889
- yl = yi + this._getHeight(get),
1890
- base = this.childBase || 0,
1891
- el = this,
1892
- fixed = this.fixed,
1893
- coords,
1894
- v,
1895
- noleft,
1896
- noright,
1897
- notop,
1898
- nobot,
1899
- ppos,
1900
- b
1901
-
1902
- // Attempt to shrink the element base on the
1903
- // size of the content and child elements.
1904
- if (this.shrink) {
1905
- coords = this._getShrink(xi, xl, yi, yl, get)
1906
- ;(xi = coords.xi), (xl = coords.xl)
1907
- ;(yi = coords.yi), (yl = coords.yl)
1908
- }
1909
-
1910
- // Find a scrollable ancestor if we have one.
1911
- while ((el = el.parent)) {
1912
- if (el.scrollable) {
1913
- if (fixed) {
1914
- fixed = false
1915
- continue
1916
- }
1917
- break
1918
- }
1919
- }
1920
-
1921
- // Check to make sure we're visible and
1922
- // inside of the visible scroll area.
1923
- // NOTE: Lists have a property where only
1924
- // the list items are obfuscated.
1925
-
1926
- // Old way of doing things, this would not render right if a shrunken element
1927
- // with lots of boxes in it was within a scrollable element.
1928
- // See: $ node test/widget-shrink-fail.js
1929
- // var thisparent = this.parent;
1930
-
1931
- const thisparent = el
1932
- if (el && !noscroll) {
1933
- ppos = thisparent.lpos
1934
-
1935
- // The shrink option can cause a stack overflow
1936
- // by calling _getCoords on the child again.
1937
- // if (!get && !thisparent.shrink) {
1938
- // ppos = thisparent._getCoords();
1939
- // }
1940
-
1941
- if (!ppos) {
1942
- return
1943
- }
1944
-
1945
- // TODO: Figure out how to fix base (and cbase to only
1946
- // take into account the *parent's* padding.
1947
-
1948
- yi -= ppos.base
1949
- yl -= ppos.base
1950
-
1951
- b = thisparent.border ? 1 : 0
1952
-
1953
- // XXX
1954
- // Fixes non-`fixed` labels to work with scrolling (they're ON the border):
1955
- // if (this.position.left < 0
1956
- // || this.position.right < 0
1957
- // || this.position.top < 0
1958
- // || this.position.bottom < 0) {
1959
- if (this._isLabel) {
1960
- b = 0
1961
- }
1962
-
1963
- if (yi < ppos.yi + b) {
1964
- if (yl - 1 < ppos.yi + b) {
1965
- // Is above.
1966
- return
1967
- } else {
1968
- // Is partially covered above.
1969
- notop = true
1970
- v = ppos.yi - yi
1971
- if (this.border) {
1972
- v--
1973
- }
1974
- if (thisparent.border) {
1975
- v++
1976
- }
1977
- base += v
1978
- yi += v
1979
- }
1980
- } else if (yl > ppos.yl - b) {
1981
- if (yi > ppos.yl - 1 - b) {
1982
- // Is below.
1983
- return
1984
- } else {
1985
- // Is partially covered below.
1986
- nobot = true
1987
- v = yl - ppos.yl
1988
- if (this.border) {
1989
- v--
1990
- }
1991
- if (thisparent.border) {
1992
- v++
1993
- }
1994
- yl -= v
1995
- }
1996
- }
1997
-
1998
- // Shouldn't be necessary.
1999
- // assert.ok(yi < yl);
2000
- if (yi >= yl) {
2001
- return
2002
- }
2003
-
2004
- // Could allow overlapping stuff in scrolling elements
2005
- // if we cleared the pending buffer before every draw.
2006
- if (xi < el.lpos.xi) {
2007
- xi = el.lpos.xi
2008
- noleft = true
2009
- if (this.border) {
2010
- xi--
2011
- }
2012
- if (thisparent.border) {
2013
- xi++
2014
- }
2015
- }
2016
- if (xl > el.lpos.xl) {
2017
- xl = el.lpos.xl
2018
- noright = true
2019
- if (this.border) {
2020
- xl++
2021
- }
2022
- if (thisparent.border) {
2023
- xl--
2024
- }
2025
- }
2026
- //if (xi > xl) return;
2027
- if (xi >= xl) {
2028
- return
2029
- }
2030
- }
2031
-
2032
- if (this.noOverflow && this.parent.lpos) {
2033
- if (xi < this.parent.lpos.xi + this.parent.ileft) {
2034
- xi = this.parent.lpos.xi + this.parent.ileft
2035
- }
2036
- if (xl > this.parent.lpos.xl - this.parent.iright) {
2037
- xl = this.parent.lpos.xl - this.parent.iright
2038
- }
2039
- if (yi < this.parent.lpos.yi + this.parent.itop) {
2040
- yi = this.parent.lpos.yi + this.parent.itop
2041
- }
2042
- if (yl > this.parent.lpos.yl - this.parent.ibottom) {
2043
- yl = this.parent.lpos.yl - this.parent.ibottom
2044
- }
2045
- }
2046
-
2047
- // if (this.parent.lpos) {
2048
- // this.parent.lpos._scrollBottom = Math.max(
2049
- // this.parent.lpos._scrollBottom, yl);
2050
- // }
2051
-
2052
- return {
2053
- xi: xi,
2054
- xl: xl,
2055
- yi: yi,
2056
- yl: yl,
2057
- base: base,
2058
- noleft: noleft,
2059
- noright: noright,
2060
- notop: notop,
2061
- nobot: nobot,
2062
- renders: this.screen.renders
2063
- }
2064
- }
2065
-
2066
- Element.prototype.render = function () {
2067
- this._emit('prerender')
2068
-
2069
- this.parseContent()
2070
-
2071
- const coords = this._getCoords(true)
2072
- if (!coords) {
2073
- delete this.lpos
2074
- return
2075
- }
2076
-
2077
- if (coords.xl - coords.xi <= 0) {
2078
- coords.xl = Math.max(coords.xl, coords.xi)
2079
- return
2080
- }
2081
-
2082
- if (coords.yl - coords.yi <= 0) {
2083
- coords.yl = Math.max(coords.yl, coords.yi)
2084
- return
2085
- }
2086
-
2087
- let lines = this.screen.lines,
2088
- xi = coords.xi,
2089
- xl = coords.xl,
2090
- yi = coords.yi,
2091
- yl = coords.yl,
2092
- x,
2093
- y,
2094
- cell,
2095
- attr,
2096
- ch,
2097
- content = this._pcontent,
2098
- ci = this._clines.ci[coords.base],
2099
- battr,
2100
- dattr,
2101
- c,
2102
- visible,
2103
- i,
2104
- bch = this.ch
2105
-
2106
- // Clip content if it's off the edge of the screen
2107
- // if (xi + this.ileft < 0 || yi + this.itop < 0) {
2108
- // var clines = this._clines.slice();
2109
- // if (xi + this.ileft < 0) {
2110
- // for (var i = 0; i < clines.length; i++) {
2111
- // var t = 0;
2112
- // var csi = '';
2113
- // var csis = '';
2114
- // for (var j = 0; j < clines[i].length; j++) {
2115
- // while (clines[i][j] === '\x1b') {
2116
- // csi = '\x1b';
2117
- // while (clines[i][j++] !== 'm') csi += clines[i][j];
2118
- // csis += csi;
2119
- // }
2120
- // if (++t === -(xi + this.ileft) + 1) break;
2121
- // }
2122
- // clines[i] = csis + clines[i].substring(j);
2123
- // }
2124
- // }
2125
- // if (yi + this.itop < 0) {
2126
- // clines = clines.slice(-(yi + this.itop));
2127
- // }
2128
- // content = clines.join('\n');
2129
- // }
2130
-
2131
- if (coords.base >= this._clines.ci.length) {
2132
- ci = this._pcontent.length
2133
- }
2134
-
2135
- this.lpos = coords
2136
-
2137
- if (this.border && this.border.type === 'line') {
2138
- this.screen._borderStops[coords.yi] = true
2139
- this.screen._borderStops[coords.yl - 1] = true
2140
- // if (!this.screen._borderStops[coords.yi]) {
2141
- // this.screen._borderStops[coords.yi] = { xi: coords.xi, xl: coords.xl };
2142
- // } else {
2143
- // if (this.screen._borderStops[coords.yi].xi > coords.xi) {
2144
- // this.screen._borderStops[coords.yi].xi = coords.xi;
2145
- // }
2146
- // if (this.screen._borderStops[coords.yi].xl < coords.xl) {
2147
- // this.screen._borderStops[coords.yi].xl = coords.xl;
2148
- // }
2149
- // }
2150
- // this.screen._borderStops[coords.yl - 1] = this.screen._borderStops[coords.yi];
2151
- }
2152
-
2153
- dattr = this.sattr(this.style)
2154
- attr = dattr
2155
-
2156
- // If we're in a scrollable text box, check to
2157
- // see which attributes this line starts with.
2158
- if (ci > 0) {
2159
- attr = this._clines.attr[Math.min(coords.base, this._clines.length - 1)]
2160
- }
2161
-
2162
- if (this.border) {
2163
- xi++, xl--, yi++, yl--
2164
- }
2165
-
2166
- // If we have padding/valign, that means the
2167
- // content-drawing loop will skip a few cells/lines.
2168
- // To deal with this, we can just fill the whole thing
2169
- // ahead of time. This could be optimized.
2170
- if (this.tpadding || (this.valign && this.valign !== 'top')) {
2171
- if (this.style.transparent) {
2172
- for (y = Math.max(yi, 0); y < yl; y++) {
2173
- if (!lines[y]) {
2174
- break
2175
- }
2176
- for (x = Math.max(xi, 0); x < xl; x++) {
2177
- if (!lines[y][x]) {
2178
- break
2179
- }
2180
- lines[y][x][0] = colors.blend(attr, lines[y][x][0])
2181
- // lines[y][x][1] = bch;
2182
- lines[y].dirty = true
2183
- }
2184
- }
2185
- } else {
2186
- this.screen.fillRegion(dattr, bch, xi, xl, yi, yl)
2187
- }
2188
- }
2189
-
2190
- if (this.tpadding) {
2191
- ;(xi += this.padding.left), (xl -= this.padding.right)
2192
- ;(yi += this.padding.top), (yl -= this.padding.bottom)
2193
- }
2194
-
2195
- // Determine where to place the text if it's vertically aligned.
2196
- if (this.valign === 'middle' || this.valign === 'bottom') {
2197
- visible = yl - yi
2198
- if (this._clines.length < visible) {
2199
- if (this.valign === 'middle') {
2200
- visible = (visible / 2) | 0
2201
- visible -= (this._clines.length / 2) | 0
2202
- } else if (this.valign === 'bottom') {
2203
- visible -= this._clines.length
2204
- }
2205
- ci -= visible * (xl - xi)
2206
- }
2207
- }
2208
-
2209
- // Draw the content and background.
2210
- for (y = yi; y < yl; y++) {
2211
- if (!lines[y]) {
2212
- if (y >= this.screen.height || yl < this.ibottom) {
2213
- break
2214
- } else {
2215
- continue
2216
- }
2217
- }
2218
- for (x = xi; x < xl; x++) {
2219
- cell = lines[y][x]
2220
- if (!cell) {
2221
- if (x >= this.screen.width || xl < this.iright) {
2222
- break
2223
- } else {
2224
- continue
2225
- }
2226
- }
2227
-
2228
- ch = content[ci++] || bch
2229
-
2230
- // if (!content[ci] && !coords._contentEnd) {
2231
- // coords._contentEnd = { x: x - xi, y: y - yi };
2232
- // }
2233
-
2234
- // Handle escape codes.
2235
- while (ch === '\x1b') {
2236
- if ((c = /^\x1b\[[\d;]*m/.exec(content.substring(ci - 1)))) {
2237
- ci += c[0].length - 1
2238
- attr = this.screen.attrCode(c[0], attr, dattr)
2239
- // Ignore foreground changes for selected items.
2240
- if (
2241
- this.parent._isList &&
2242
- this.parent.interactive &&
2243
- this.parent.items[this.parent.selected] === this &&
2244
- this.parent.options.invertSelected !== false
2245
- ) {
2246
- attr = (attr & ~(0x1ff << 9)) | (dattr & (0x1ff << 9))
2247
- }
2248
- ch = content[ci] || bch
2249
- ci++
2250
- } else {
2251
- break
2252
- }
2253
- }
2254
-
2255
- // Handle newlines.
2256
- if (ch === '\t') {
2257
- ch = bch
2258
- }
2259
- if (ch === '\n') {
2260
- // If we're on the first cell and we find a newline and the last cell
2261
- // of the last line was not a newline, let's just treat this like the
2262
- // newline was already "counted".
2263
- if (x === xi && y !== yi && content[ci - 2] !== '\n') {
2264
- x--
2265
- continue
2266
- }
2267
- // We could use fillRegion here, name the
2268
- // outer loop, and continue to it instead.
2269
- ch = bch
2270
- for (; x < xl; x++) {
2271
- cell = lines[y][x]
2272
- if (!cell) {
2273
- break
2274
- }
2275
- if (this.style.transparent) {
2276
- lines[y][x][0] = colors.blend(attr, lines[y][x][0])
2277
- if (content[ci]) {
2278
- lines[y][x][1] = ch
2279
- }
2280
- lines[y].dirty = true
2281
- } else {
2282
- if (attr !== cell[0] || ch !== cell[1]) {
2283
- lines[y][x][0] = attr
2284
- lines[y][x][1] = ch
2285
- lines[y].dirty = true
2286
- }
2287
- }
2288
- }
2289
- continue
2290
- }
2291
-
2292
- if (this.screen.fullUnicode && content[ci - 1]) {
2293
- const point = unicode.codePointAt(content, ci - 1)
2294
- // Handle combining chars:
2295
- // Make sure they get in the same cell and are counted as 0.
2296
- if (unicode.combining[point]) {
2297
- if (point > 0x00ffff) {
2298
- ch = content[ci - 1] + content[ci]
2299
- ci++
2300
- }
2301
- if (x - 1 >= xi) {
2302
- lines[y][x - 1][1] += ch
2303
- } else if (y - 1 >= yi) {
2304
- lines[y - 1][xl - 1][1] += ch
2305
- }
2306
- x--
2307
- continue
2308
- }
2309
- // Handle surrogate pairs:
2310
- // Make sure we put surrogate pair chars in one cell.
2311
- if (point > 0x00ffff) {
2312
- ch = content[ci - 1] + content[ci]
2313
- ci++
2314
- }
2315
- }
2316
-
2317
- if (this._noFill) {
2318
- continue
2319
- }
2320
-
2321
- if (this.style.transparent) {
2322
- lines[y][x][0] = colors.blend(attr, lines[y][x][0])
2323
- if (content[ci]) {
2324
- lines[y][x][1] = ch
2325
- }
2326
- lines[y].dirty = true
2327
- } else {
2328
- if (attr !== cell[0] || ch !== cell[1]) {
2329
- lines[y][x][0] = attr
2330
- lines[y][x][1] = ch
2331
- lines[y].dirty = true
2332
- }
2333
- }
2334
- }
2335
- }
2336
-
2337
- // Draw the scrollbar.
2338
- // Could possibly draw this after all child elements.
2339
- if (this.scrollbar) {
2340
- // XXX
2341
- // i = this.getScrollHeight();
2342
- i = Math.max(this._clines.length, this._scrollBottom())
2343
- }
2344
- if (coords.notop || coords.nobot) {
2345
- i = -Infinity
2346
- }
2347
- if (this.scrollbar && yl - yi < i) {
2348
- x = xl - 1
2349
- if (this.scrollbar.ignoreBorder && this.border) {
2350
- x++
2351
- }
2352
- if (this.alwaysScroll) {
2353
- y = this.childBase / (i - (yl - yi))
2354
- } else {
2355
- y = (this.childBase + this.childOffset) / (i - 1)
2356
- }
2357
- y = yi + (((yl - yi) * y) | 0)
2358
- if (y >= yl) {
2359
- y = yl - 1
2360
- }
2361
- cell = lines[y] && lines[y][x]
2362
- if (cell) {
2363
- if (this.track) {
2364
- ch = this.track.ch || ' '
2365
- attr = this.sattr(
2366
- this.style.track,
2367
- this.style.track.fg || this.style.fg,
2368
- this.style.track.bg || this.style.bg
2369
- )
2370
- this.screen.fillRegion(attr, ch, x, x + 1, yi, yl)
2371
- }
2372
- ch = this.scrollbar.ch || ' '
2373
- attr = this.sattr(
2374
- this.style.scrollbar,
2375
- this.style.scrollbar.fg || this.style.fg,
2376
- this.style.scrollbar.bg || this.style.bg
2377
- )
2378
- if (attr !== cell[0] || ch !== cell[1]) {
2379
- lines[y][x][0] = attr
2380
- lines[y][x][1] = ch
2381
- lines[y].dirty = true
2382
- }
2383
- }
2384
- }
2385
-
2386
- if (this.border) {
2387
- xi--, xl++, yi--, yl++
2388
- }
2389
-
2390
- if (this.tpadding) {
2391
- ;(xi -= this.padding.left), (xl += this.padding.right)
2392
- ;(yi -= this.padding.top), (yl += this.padding.bottom)
2393
- }
2394
-
2395
- // Draw the border.
2396
- if (this.border) {
2397
- battr = this.sattr(this.style.border)
2398
- y = yi
2399
- if (coords.notop) {
2400
- y = -1
2401
- }
2402
- for (x = xi; x < xl; x++) {
2403
- if (!lines[y]) {
2404
- break
2405
- }
2406
- if (coords.noleft && x === xi) {
2407
- continue
2408
- }
2409
- if (coords.noright && x === xl - 1) {
2410
- continue
2411
- }
2412
- cell = lines[y][x]
2413
- if (!cell) {
2414
- continue
2415
- }
2416
- if (this.border.type === 'line') {
2417
- if (x === xi) {
2418
- ch = '\u250c' // '┌'
2419
- if (!this.border.left) {
2420
- if (this.border.top) {
2421
- ch = '\u2500' // '─'
2422
- } else {
2423
- continue
2424
- }
2425
- } else {
2426
- if (!this.border.top) {
2427
- ch = '\u2502' // '│'
2428
- }
2429
- }
2430
- } else if (x === xl - 1) {
2431
- ch = '\u2510' // '┐'
2432
- if (!this.border.right) {
2433
- if (this.border.top) {
2434
- ch = '\u2500' // '─'
2435
- } else {
2436
- continue
2437
- }
2438
- } else {
2439
- if (!this.border.top) {
2440
- ch = '\u2502' // '│'
2441
- }
2442
- }
2443
- } else {
2444
- ch = '\u2500' // '─'
2445
- }
2446
- } else if (this.border.type === 'bg') {
2447
- ch = this.border.ch
2448
- }
2449
- if (!this.border.top && x !== xi && x !== xl - 1) {
2450
- ch = ' '
2451
- if (dattr !== cell[0] || ch !== cell[1]) {
2452
- lines[y][x][0] = dattr
2453
- lines[y][x][1] = ch
2454
- lines[y].dirty = true
2455
- continue
2456
- }
2457
- }
2458
- if (battr !== cell[0] || ch !== cell[1]) {
2459
- lines[y][x][0] = battr
2460
- lines[y][x][1] = ch
2461
- lines[y].dirty = true
2462
- }
2463
- }
2464
- y = yi + 1
2465
- for (; y < yl - 1; y++) {
2466
- if (!lines[y]) {
2467
- continue
2468
- }
2469
- cell = lines[y][xi]
2470
- if (cell) {
2471
- if (this.border.left) {
2472
- if (this.border.type === 'line') {
2473
- ch = '\u2502' // '│'
2474
- } else if (this.border.type === 'bg') {
2475
- ch = this.border.ch
2476
- }
2477
- if (!coords.noleft) {
2478
- if (battr !== cell[0] || ch !== cell[1]) {
2479
- lines[y][xi][0] = battr
2480
- lines[y][xi][1] = ch
2481
- lines[y].dirty = true
2482
- }
2483
- }
2484
- } else {
2485
- ch = ' '
2486
- if (dattr !== cell[0] || ch !== cell[1]) {
2487
- lines[y][xi][0] = dattr
2488
- lines[y][xi][1] = ch
2489
- lines[y].dirty = true
2490
- }
2491
- }
2492
- }
2493
- cell = lines[y][xl - 1]
2494
- if (cell) {
2495
- if (this.border.right) {
2496
- if (this.border.type === 'line') {
2497
- ch = '\u2502' // '│'
2498
- } else if (this.border.type === 'bg') {
2499
- ch = this.border.ch
2500
- }
2501
- if (!coords.noright) {
2502
- if (battr !== cell[0] || ch !== cell[1]) {
2503
- lines[y][xl - 1][0] = battr
2504
- lines[y][xl - 1][1] = ch
2505
- lines[y].dirty = true
2506
- }
2507
- }
2508
- } else {
2509
- ch = ' '
2510
- if (dattr !== cell[0] || ch !== cell[1]) {
2511
- lines[y][xl - 1][0] = dattr
2512
- lines[y][xl - 1][1] = ch
2513
- lines[y].dirty = true
2514
- }
2515
- }
2516
- }
2517
- }
2518
- y = yl - 1
2519
- if (coords.nobot) {
2520
- y = -1
2521
- }
2522
- for (x = xi; x < xl; x++) {
2523
- if (!lines[y]) {
2524
- break
2525
- }
2526
- if (coords.noleft && x === xi) {
2527
- continue
2528
- }
2529
- if (coords.noright && x === xl - 1) {
2530
- continue
2531
- }
2532
- cell = lines[y][x]
2533
- if (!cell) {
2534
- continue
2535
- }
2536
- if (this.border.type === 'line') {
2537
- if (x === xi) {
2538
- ch = '\u2514' // '└'
2539
- if (!this.border.left) {
2540
- if (this.border.bottom) {
2541
- ch = '\u2500' // '─'
2542
- } else {
2543
- continue
2544
- }
2545
- } else {
2546
- if (!this.border.bottom) {
2547
- ch = '\u2502' // '│'
2548
- }
2549
- }
2550
- } else if (x === xl - 1) {
2551
- ch = '\u2518' // '┘'
2552
- if (!this.border.right) {
2553
- if (this.border.bottom) {
2554
- ch = '\u2500' // '─'
2555
- } else {
2556
- continue
2557
- }
2558
- } else {
2559
- if (!this.border.bottom) {
2560
- ch = '\u2502' // '│'
2561
- }
2562
- }
2563
- } else {
2564
- ch = '\u2500' // '─'
2565
- }
2566
- } else if (this.border.type === 'bg') {
2567
- ch = this.border.ch
2568
- }
2569
- if (!this.border.bottom && x !== xi && x !== xl - 1) {
2570
- ch = ' '
2571
- if (dattr !== cell[0] || ch !== cell[1]) {
2572
- lines[y][x][0] = dattr
2573
- lines[y][x][1] = ch
2574
- lines[y].dirty = true
2575
- }
2576
- continue
2577
- }
2578
- if (battr !== cell[0] || ch !== cell[1]) {
2579
- lines[y][x][0] = battr
2580
- lines[y][x][1] = ch
2581
- lines[y].dirty = true
2582
- }
2583
- }
2584
- }
2585
-
2586
- if (this.shadow) {
2587
- // right
2588
- y = Math.max(yi + 1, 0)
2589
- for (; y < yl + 1; y++) {
2590
- if (!lines[y]) {
2591
- break
2592
- }
2593
- x = xl
2594
- for (; x < xl + 2; x++) {
2595
- if (!lines[y][x]) {
2596
- break
2597
- }
2598
- // lines[y][x][0] = colors.blend(this.dattr, lines[y][x][0]);
2599
- lines[y][x][0] = colors.blend(lines[y][x][0])
2600
- lines[y].dirty = true
2601
- }
2602
- }
2603
- // bottom
2604
- y = yl
2605
- for (; y < yl + 1; y++) {
2606
- if (!lines[y]) {
2607
- break
2608
- }
2609
- for (x = Math.max(xi + 1, 0); x < xl; x++) {
2610
- if (!lines[y][x]) {
2611
- break
2612
- }
2613
- // lines[y][x][0] = colors.blend(this.dattr, lines[y][x][0]);
2614
- lines[y][x][0] = colors.blend(lines[y][x][0])
2615
- lines[y].dirty = true
2616
- }
2617
- }
2618
- }
2619
-
2620
- this.children.forEach(function (el) {
2621
- if (el.screen._ci !== -1) {
2622
- el.index = el.screen._ci++
2623
- }
2624
- // if (el.screen._rendering) {
2625
- // el._rendering = true;
2626
- // }
2627
- el.render()
2628
- // if (el.screen._rendering) {
2629
- // el._rendering = false;
2630
- // }
2631
- })
2632
-
2633
- this._emit('render', [coords])
2634
-
2635
- return coords
2636
- }
2637
-
2638
- Element.prototype._render = Element.prototype.render
2639
-
2640
- /**
2641
- * Content Methods
2642
- */
2643
-
2644
- Element.prototype.insertLine = function (i, line) {
2645
- if (typeof line === 'string') {
2646
- line = line.split('\n')
2647
- }
2648
-
2649
- if (i !== i || i == null) {
2650
- i = this._clines.ftor.length
2651
- }
2652
-
2653
- i = Math.max(i, 0)
2654
-
2655
- while (this._clines.fake.length < i) {
2656
- this._clines.fake.push('')
2657
- this._clines.ftor.push([this._clines.push('') - 1])
2658
- this._clines.rtof(this._clines.fake.length - 1)
2659
- }
2660
-
2661
- // NOTE: Could possibly compare the first and last ftor line numbers to see
2662
- // if they're the same, or if they fit in the visible region entirely.
2663
- let start = this._clines.length,
2664
- diff,
2665
- real
2666
-
2667
- if (i >= this._clines.ftor.length) {
2668
- real = this._clines.ftor[this._clines.ftor.length - 1]
2669
- real = real[real.length - 1] + 1
2670
- } else {
2671
- real = this._clines.ftor[i][0]
2672
- }
2673
-
2674
- for (let j = 0; j < line.length; j++) {
2675
- this._clines.fake.splice(i + j, 0, line[j])
2676
- }
2677
-
2678
- this.setContent(this._clines.fake.join('\n'), true)
2679
-
2680
- diff = this._clines.length - start
2681
-
2682
- if (diff > 0) {
2683
- const pos = this._getCoords()
2684
- if (!pos) {
2685
- return
2686
- }
2687
-
2688
- const height = pos.yl - pos.yi - this.iheight,
2689
- base = this.childBase || 0,
2690
- visible = real >= base && real - base < height
2691
-
2692
- if (pos && visible && this.screen.cleanSides(this)) {
2693
- this.screen.insertLine(
2694
- diff,
2695
- pos.yi + this.itop + real - base,
2696
- pos.yi,
2697
- pos.yl - this.ibottom - 1
2698
- )
2699
- }
2700
- }
2701
- }
2702
-
2703
- Element.prototype.deleteLine = function (i, n) {
2704
- n = n || 1
2705
-
2706
- if (i !== i || i == null) {
2707
- i = this._clines.ftor.length - 1
2708
- }
2709
-
2710
- i = Math.max(i, 0)
2711
- i = Math.min(i, this._clines.ftor.length - 1)
2712
-
2713
- // NOTE: Could possibly compare the first and last ftor line numbers to see
2714
- // if they're the same, or if they fit in the visible region entirely.
2715
- let start = this._clines.length,
2716
- diff,
2717
- real = this._clines.ftor[i][0]
2718
-
2719
- while (n--) {
2720
- this._clines.fake.splice(i, 1)
2721
- }
2722
-
2723
- this.setContent(this._clines.fake.join('\n'), true)
2724
-
2725
- diff = start - this._clines.length
2726
-
2727
- // XXX clearPos() without diff statement?
2728
- let height = 0
2729
-
2730
- if (diff > 0) {
2731
- const pos = this._getCoords()
2732
- if (!pos) {
2733
- return
2734
- }
2735
-
2736
- height = pos.yl - pos.yi - this.iheight
2737
-
2738
- const base = this.childBase || 0,
2739
- visible = real >= base && real - base < height
2740
-
2741
- if (pos && visible && this.screen.cleanSides(this)) {
2742
- this.screen.deleteLine(
2743
- diff,
2744
- pos.yi + this.itop + real - base,
2745
- pos.yi,
2746
- pos.yl - this.ibottom - 1
2747
- )
2748
- }
2749
- }
2750
-
2751
- if (this._clines.length < height) {
2752
- this.clearPos()
2753
- }
2754
- }
2755
-
2756
- Element.prototype.insertTop = function (line) {
2757
- const fake = this._clines.rtof[this.childBase || 0]
2758
- return this.insertLine(fake, line)
2759
- }
2760
-
2761
- Element.prototype.insertBottom = function (line) {
2762
- const h = (this.childBase || 0) + this.height - this.iheight,
2763
- i = Math.min(h, this._clines.length),
2764
- fake = this._clines.rtof[i - 1] + 1
2765
-
2766
- return this.insertLine(fake, line)
2767
- }
2768
-
2769
- Element.prototype.deleteTop = function (n) {
2770
- const fake = this._clines.rtof[this.childBase || 0]
2771
- return this.deleteLine(fake, n)
2772
- }
2773
-
2774
- Element.prototype.deleteBottom = function (n) {
2775
- const h = (this.childBase || 0) + this.height - 1 - this.iheight,
2776
- i = Math.min(h, this._clines.length - 1),
2777
- fake = this._clines.rtof[i]
2778
-
2779
- n = n || 1
2780
-
2781
- return this.deleteLine(fake - (n - 1), n)
2782
- }
2783
-
2784
- Element.prototype.setLine = function (i, line) {
2785
- i = Math.max(i, 0)
2786
- while (this._clines.fake.length < i) {
2787
- this._clines.fake.push('')
2788
- }
2789
- this._clines.fake[i] = line
2790
- return this.setContent(this._clines.fake.join('\n'), true)
2791
- }
2792
-
2793
- Element.prototype.setBaseLine = function (i, line) {
2794
- const fake = this._clines.rtof[this.childBase || 0]
2795
- return this.setLine(fake + i, line)
2796
- }
2797
-
2798
- Element.prototype.getLine = function (i) {
2799
- i = Math.max(i, 0)
2800
- i = Math.min(i, this._clines.fake.length - 1)
2801
- return this._clines.fake[i]
2802
- }
2803
-
2804
- Element.prototype.getBaseLine = function (i) {
2805
- const fake = this._clines.rtof[this.childBase || 0]
2806
- return this.getLine(fake + i)
2807
- }
2808
-
2809
- Element.prototype.clearLine = function (i) {
2810
- i = Math.min(i, this._clines.fake.length - 1)
2811
- return this.setLine(i, '')
2812
- }
2813
-
2814
- Element.prototype.clearBaseLine = function (i) {
2815
- const fake = this._clines.rtof[this.childBase || 0]
2816
- return this.clearLine(fake + i)
2817
- }
2818
-
2819
- Element.prototype.unshiftLine = function (line) {
2820
- return this.insertLine(0, line)
2821
- }
2822
-
2823
- Element.prototype.shiftLine = function (n) {
2824
- return this.deleteLine(0, n)
2825
- }
2826
-
2827
- Element.prototype.pushLine = function (line) {
2828
- if (!this.content) {
2829
- return this.setLine(0, line)
2830
- }
2831
- return this.insertLine(this._clines.fake.length, line)
2832
- }
2833
-
2834
- Element.prototype.popLine = function (n) {
2835
- return this.deleteLine(this._clines.fake.length - 1, n)
2836
- }
2837
-
2838
- Element.prototype.getLines = function () {
2839
- return this._clines.fake.slice()
2840
- }
2841
-
2842
- Element.prototype.getScreenLines = function () {
2843
- return this._clines.slice()
2844
- }
2845
-
2846
- Element.prototype.strWidth = function (text) {
2847
- text = this.parseTags ? helpers.stripTags(text) : text
2848
- return this.screen.fullUnicode
2849
- ? unicode.strWidth(text)
2850
- : helpers.dropUnicode(text).length
2851
- }
2852
-
2853
- Element.prototype.screenshot = function (xi, xl, yi, yl) {
2854
- xi = this.lpos.xi + this.ileft + (xi || 0)
2855
- if (xl != null) {
2856
- xl = this.lpos.xi + this.ileft + (xl || 0)
2857
- } else {
2858
- xl = this.lpos.xl - this.iright
2859
- }
2860
- yi = this.lpos.yi + this.itop + (yi || 0)
2861
- if (yl != null) {
2862
- yl = this.lpos.yi + this.itop + (yl || 0)
2863
- } else {
2864
- yl = this.lpos.yl - this.ibottom
2865
- }
2866
- return this.screen.screenshot(xi, xl, yi, yl)
2867
- }
2868
-
2869
- /**
2870
- * Expose
2871
- */
2872
-
2873
- module.exports = Element