@nan0web/ui 1.0.4 → 1.3.0
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.
- package/README.md +19 -14
- package/package.json +6 -4
- package/src/App/Command/DepsCommand.js +25 -0
- package/src/App/Core/CoreApp.js +18 -17
- package/src/App/Core/UI.js +12 -19
- package/src/App/Core/Widget.js +6 -10
- package/src/App/Core/index.js +3 -3
- package/src/App/Scenario.js +4 -4
- package/src/App/User/Command/Message.js +2 -29
- package/src/App/User/Command/index.js +3 -4
- package/src/App/User/UserApp.js +30 -23
- package/src/App/User/UserUI.js +2 -2
- package/src/App/User/index.js +2 -2
- package/src/App/index.js +5 -10
- package/src/Component/Process/Input.js +10 -17
- package/src/Component/Process/Process.js +3 -5
- package/src/Component/Process/index.js +2 -2
- package/src/Component/SortableList/SortableList.js +100 -0
- package/src/Component/SortableList/index.js +3 -0
- package/src/Component/Welcome/Input.js +2 -4
- package/src/Component/Welcome/Welcome.js +5 -9
- package/src/Component/Welcome/index.js +2 -2
- package/src/Component/index.js +5 -3
- package/src/Frame/Frame.js +163 -146
- package/src/Frame/Props.js +20 -20
- package/src/Locale.js +17 -18
- package/src/Model/User/User.js +3 -6
- package/src/Model/index.js +1 -1
- package/src/README.md.js +84 -94
- package/src/StdIn.js +8 -12
- package/src/StdOut.js +23 -27
- package/src/View/RenderOptions.js +1 -1
- package/src/View/View.js +42 -38
- package/src/core/Error/CancelError.js +2 -2
- package/src/core/Error/index.js +3 -5
- package/src/core/Flow.js +347 -0
- package/src/core/Form/Form.js +35 -33
- package/src/core/Form/Input.js +29 -14
- package/src/core/Form/Message.js +3 -6
- package/src/core/Form/index.js +4 -8
- package/src/core/InputAdapter.js +4 -6
- package/src/core/Message/Message.js +9 -12
- package/src/core/Message/OutputMessage.js +19 -17
- package/src/core/Message/index.js +2 -2
- package/src/core/OutputAdapter.js +12 -10
- package/src/core/Stream.js +4 -3
- package/src/core/StreamEntry.js +2 -2
- package/src/core/UiAdapter.js +57 -29
- package/src/core/index.js +38 -9
- package/src/functions.js +8 -15
- package/src/index.js +21 -32
- package/types/App/Command/DepsCommand.d.ts +16 -0
- package/types/App/Command/Options.d.ts +37 -40
- package/types/App/Command/index.d.ts +6 -6
- package/types/App/Core/CoreApp.d.ts +2 -2
- package/types/App/Core/UI.d.ts +6 -7
- package/types/App/Core/Widget.d.ts +4 -4
- package/types/App/Core/index.d.ts +3 -3
- package/types/App/Scenario.d.ts +1 -1
- package/types/App/User/Command/Message.d.ts +2 -16
- package/types/App/User/Command/Options.d.ts +29 -29
- package/types/App/User/Command/index.d.ts +2 -3
- package/types/App/User/UserApp.d.ts +5 -5
- package/types/App/User/index.d.ts +2 -2
- package/types/App/index.d.ts +4 -4
- package/types/Component/Process/Process.d.ts +2 -2
- package/types/Component/Process/index.d.ts +2 -2
- package/types/Component/SortableList/SortableList.d.ts +58 -0
- package/types/Component/SortableList/index.d.ts +2 -0
- package/types/Component/Welcome/Input.d.ts +1 -1
- package/types/Component/Welcome/Welcome.d.ts +1 -1
- package/types/Component/Welcome/index.d.ts +2 -2
- package/types/Component/index.d.ts +5 -3
- package/types/Frame/Frame.d.ts +1 -1
- package/types/Frame/Props.d.ts +1 -1
- package/types/Model/index.d.ts +1 -1
- package/types/StdIn.d.ts +2 -2
- package/types/StdOut.d.ts +1 -1
- package/types/View/View.d.ts +7 -7
- package/types/core/Error/index.d.ts +1 -1
- package/types/core/Flow.d.ts +320 -0
- package/types/core/Form/Form.d.ts +2 -2
- package/types/core/Form/Input.d.ts +15 -4
- package/types/core/Form/Message.d.ts +1 -1
- package/types/core/Form/index.d.ts +3 -3
- package/types/core/InputAdapter.d.ts +2 -2
- package/types/core/Intent.d.ts +65 -68
- package/types/core/Message/InputMessage.d.ts +65 -65
- package/types/core/Message/Message.d.ts +1 -1
- package/types/core/Message/OutputMessage.d.ts +1 -1
- package/types/core/Message/index.d.ts +2 -2
- package/types/core/Stream.d.ts +1 -2
- package/types/core/UiAdapter.d.ts +22 -4
- package/types/core/index.d.ts +5 -2
- package/types/index.d.ts +10 -10
package/src/Frame/Frame.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import stringWidth from
|
|
2
|
-
import { to, typeOf, empty } from
|
|
3
|
-
import FrameProps from
|
|
1
|
+
import stringWidth from 'string-width'
|
|
2
|
+
import { to, typeOf, empty } from '@nan0web/types'
|
|
3
|
+
import FrameProps from './Props.js'
|
|
4
4
|
|
|
5
5
|
export class FrameRenderMethod {
|
|
6
|
-
static APPEND =
|
|
7
|
-
static REPLACE =
|
|
8
|
-
static VISIBLE =
|
|
6
|
+
static APPEND = 'append'
|
|
7
|
+
static REPLACE = 'replace'
|
|
8
|
+
static VISIBLE = 'visible'
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -16,27 +16,27 @@ export default class Frame {
|
|
|
16
16
|
static RenderMethod = FrameRenderMethod
|
|
17
17
|
static Props = FrameProps
|
|
18
18
|
/** @type {string} End of line */
|
|
19
|
-
static EOL =
|
|
19
|
+
static EOL = '\n'
|
|
20
20
|
/** @type {string} Beginning of line */
|
|
21
|
-
static BOL =
|
|
21
|
+
static BOL = '\r'
|
|
22
22
|
/** @type {string} Beginning of frame */
|
|
23
|
-
static BOF =
|
|
23
|
+
static BOF = '\x1b[0;0H'
|
|
24
24
|
/** @type {string} Hide cursor */
|
|
25
|
-
static HIDE_CURSOR =
|
|
25
|
+
static HIDE_CURSOR = '\x1b[?25l'
|
|
26
26
|
/** @type {string} Show cursor */
|
|
27
|
-
static SHOW_CURSOR =
|
|
27
|
+
static SHOW_CURSOR = '\x1b[?25h'
|
|
28
28
|
/** @type {string} Tab */
|
|
29
|
-
static TAB =
|
|
29
|
+
static TAB = '\t'
|
|
30
30
|
/** @type {string} Bold */
|
|
31
|
-
static BOLD =
|
|
31
|
+
static BOLD = '\x1b[1m'
|
|
32
32
|
/** @type {string} Italic */
|
|
33
|
-
static ITALIC =
|
|
33
|
+
static ITALIC = '\x1b[3m'
|
|
34
34
|
/** @type {string} Underline */
|
|
35
|
-
static UNDERLINE =
|
|
35
|
+
static UNDERLINE = '\x1b[4m'
|
|
36
36
|
/** @type {string} Strikethrough */
|
|
37
|
-
static STRIKETHROUGH =
|
|
37
|
+
static STRIKETHROUGH = '\x1b[9m'
|
|
38
38
|
/** @type {string} Reset */
|
|
39
|
-
static RESET =
|
|
39
|
+
static RESET = '\x1b[0m'
|
|
40
40
|
/** @type {string} Clear line */
|
|
41
41
|
static CLEAR_LINE = '\x1b[2K'
|
|
42
42
|
/**
|
|
@@ -81,26 +81,29 @@ export default class Frame {
|
|
|
81
81
|
value = [],
|
|
82
82
|
width = -1,
|
|
83
83
|
height = -1,
|
|
84
|
-
imprint =
|
|
85
|
-
renderMethod =
|
|
84
|
+
imprint = '',
|
|
85
|
+
renderMethod = 'append',
|
|
86
86
|
defaultProps = new FrameProps(),
|
|
87
87
|
} = input
|
|
88
88
|
if (value instanceof Frame) {
|
|
89
89
|
value = value.value
|
|
90
90
|
}
|
|
91
91
|
if (!typeOf(Array)(value)) {
|
|
92
|
-
throw new TypeError(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
throw new TypeError(
|
|
93
|
+
[
|
|
94
|
+
'Frame constructor allows only string[] for rows or string[][] for rows with columns',
|
|
95
|
+
'Provided value:',
|
|
96
|
+
JSON.stringify(value, null, 2),
|
|
97
|
+
].join('\n'),
|
|
98
|
+
)
|
|
96
99
|
}
|
|
97
|
-
value = value.map(row => {
|
|
100
|
+
value = value.map((row) => {
|
|
98
101
|
if (typeOf(Array)(row)) {
|
|
99
102
|
return row.map(String)
|
|
100
103
|
}
|
|
101
104
|
return [row]
|
|
102
105
|
})
|
|
103
|
-
this.value = value.map(v => Array.isArray(v) ? v : [v])
|
|
106
|
+
this.value = value.map((v) => (Array.isArray(v) ? v : [v]))
|
|
104
107
|
this.imprint = String(imprint)
|
|
105
108
|
this.width = width
|
|
106
109
|
this.height = height
|
|
@@ -130,56 +133,51 @@ export default class Frame {
|
|
|
130
133
|
* @returns {string} The rendered frame as a string.
|
|
131
134
|
*/
|
|
132
135
|
render(options = {}) {
|
|
133
|
-
const {
|
|
134
|
-
|
|
135
|
-
props = this.defaultProps,
|
|
136
|
-
} = options
|
|
137
|
-
let rows = this.value.map(row => {
|
|
136
|
+
const { method = this.renderMethod, props = this.defaultProps } = options
|
|
137
|
+
let rows = this.value.map((row) => {
|
|
138
138
|
if (typeOf(Array)(row)) {
|
|
139
|
-
row = row.join(
|
|
139
|
+
row = row.join('')
|
|
140
140
|
}
|
|
141
141
|
return row
|
|
142
142
|
})
|
|
143
|
-
let spacesOn =
|
|
143
|
+
let spacesOn = ''
|
|
144
144
|
if (Frame.BOF === rows[0]) {
|
|
145
145
|
rows = rows.slice(1)
|
|
146
|
-
spacesOn =
|
|
147
|
-
}
|
|
148
|
-
else if (Frame.BOF === rows[rows.length - 1]) {
|
|
146
|
+
spacesOn = 'top'
|
|
147
|
+
} else if (Frame.BOF === rows[rows.length - 1]) {
|
|
149
148
|
rows = rows.slice(0, -1)
|
|
150
|
-
spacesOn =
|
|
149
|
+
spacesOn = 'bottom'
|
|
151
150
|
}
|
|
152
151
|
if (this.height >= 0 && rows.length > this.height) {
|
|
153
152
|
rows = rows.slice(0, this.height)
|
|
154
153
|
}
|
|
155
154
|
if (this.width >= 0 && rows.length > 0) {
|
|
156
|
-
rows = rows.map(row => {
|
|
155
|
+
rows = rows.map((row) => {
|
|
157
156
|
if (row.length > this.width) {
|
|
158
157
|
row = row.slice(0, this.width)
|
|
159
158
|
}
|
|
160
159
|
return row
|
|
161
160
|
})
|
|
162
161
|
}
|
|
163
|
-
let carret =
|
|
162
|
+
let carret = ''
|
|
164
163
|
if (method === Frame.RenderMethod.REPLACE) {
|
|
165
164
|
const printedRows = rows.map(
|
|
166
|
-
row => row +
|
|
165
|
+
(row) => row + ' '.repeat(Math.max(0, this.width - this.lengthOf(row))),
|
|
167
166
|
)
|
|
168
167
|
const left = this.height >= 0 ? this.height - rows.length : 0
|
|
169
168
|
const eraser = []
|
|
170
|
-
for (let i = 0; i < left; i++) eraser.push(
|
|
169
|
+
for (let i = 0; i < left; i++) eraser.push(' '.repeat(this.width))
|
|
171
170
|
carret = Frame.BOF
|
|
172
|
-
if (
|
|
171
|
+
if ('bottom' === spacesOn) {
|
|
173
172
|
rows = left > 0 ? [...printedRows, ...eraser] : []
|
|
174
173
|
} else {
|
|
175
174
|
rows = left > 0 ? [...eraser, ...printedRows] : []
|
|
176
175
|
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
rows = rows.map(row => {
|
|
176
|
+
} else if (method === Frame.RenderMethod.APPEND) {
|
|
177
|
+
rows = rows.map((row) => {
|
|
180
178
|
const used = this.lengthOf(row)
|
|
181
179
|
const left = Math.max(0, this.width - used)
|
|
182
|
-
row = row +
|
|
180
|
+
row = row + ' '.repeat(left)
|
|
183
181
|
if (row.length > this.width) row = row.slice(0, this.width)
|
|
184
182
|
return row
|
|
185
183
|
})
|
|
@@ -190,54 +188,48 @@ export default class Frame {
|
|
|
190
188
|
carret = Frame.BOF
|
|
191
189
|
const left = this.height >= 0 ? this.height - rows.length : 0
|
|
192
190
|
const eraser = []
|
|
193
|
-
for (let i = 0; i < left; i++) eraser.push(
|
|
194
|
-
if (spacesOn ===
|
|
191
|
+
for (let i = 0; i < left; i++) eraser.push('')
|
|
192
|
+
if (spacesOn === 'top') {
|
|
195
193
|
rows = left > 0 ? [...eraser, ...rows] : []
|
|
196
|
-
}
|
|
197
|
-
else if (spacesOn === "bottom") {
|
|
194
|
+
} else if (spacesOn === 'bottom') {
|
|
198
195
|
rows = left > 0 ? [...rows, ...eraser] : []
|
|
199
196
|
}
|
|
200
197
|
}
|
|
201
|
-
}
|
|
202
|
-
else if (method === Frame.RenderMethod.VISIBLE) {
|
|
198
|
+
} else if (method === Frame.RenderMethod.VISIBLE) {
|
|
203
199
|
// Move cursor up # lines (Math.max(0, Math.min(rows.length, height))) before rendering
|
|
204
200
|
if (spacesOn) {
|
|
205
|
-
let moveUpLines = Math.max(
|
|
201
|
+
let moveUpLines = Math.max(
|
|
202
|
+
0,
|
|
203
|
+
Math.min(rows.length, this.height >= 0 ? this.height : rows.length),
|
|
204
|
+
)
|
|
206
205
|
if (moveUpLines > 0) {
|
|
207
206
|
--moveUpLines
|
|
208
207
|
}
|
|
209
208
|
carret = Frame.cursorUp(moveUpLines)
|
|
210
209
|
}
|
|
211
|
-
rows = rows.map(
|
|
212
|
-
|
|
213
|
-
)
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
210
|
+
rows = rows.map((row) => Frame.clearLine('\r') + row)
|
|
211
|
+
} else {
|
|
216
212
|
if (spacesOn) {
|
|
217
213
|
carret = Frame.BOF
|
|
218
214
|
const left = this.height >= 0 ? this.height - rows.length : 0
|
|
219
215
|
const eraser = []
|
|
220
|
-
for (let i = 0; i < left; i++) eraser.push(
|
|
221
|
-
if (spacesOn ===
|
|
216
|
+
for (let i = 0; i < left; i++) eraser.push('')
|
|
217
|
+
if (spacesOn === 'top') {
|
|
222
218
|
rows = left > 0 ? [...eraser, ...rows] : []
|
|
223
|
-
}
|
|
224
|
-
else if (spacesOn === "bottom") {
|
|
219
|
+
} else if (spacesOn === 'bottom') {
|
|
225
220
|
rows = left > 0 ? [...rows, ...eraser] : []
|
|
226
221
|
}
|
|
227
222
|
}
|
|
228
223
|
}
|
|
229
|
-
if (
|
|
230
|
-
this.imprint = rows.join(
|
|
224
|
+
if ('bottom' === spacesOn) {
|
|
225
|
+
this.imprint = rows.join('\n') + carret
|
|
231
226
|
} else {
|
|
232
|
-
this.imprint = carret + rows.join(
|
|
227
|
+
this.imprint = carret + rows.join('\n')
|
|
233
228
|
}
|
|
234
229
|
return this.imprint
|
|
235
230
|
}
|
|
236
231
|
#render1(options = {}) {
|
|
237
|
-
const {
|
|
238
|
-
method = this.renderMethod,
|
|
239
|
-
props = this.defaultProps,
|
|
240
|
-
} = options
|
|
232
|
+
const { method = this.renderMethod, props = this.defaultProps } = options
|
|
241
233
|
|
|
242
234
|
/**
|
|
243
235
|
* Helper to apply CLI style codes.
|
|
@@ -247,7 +239,7 @@ export default class Frame {
|
|
|
247
239
|
*/
|
|
248
240
|
function applyStyle(str, style = {}) {
|
|
249
241
|
let out = str
|
|
250
|
-
let prefix =
|
|
242
|
+
let prefix = ''
|
|
251
243
|
let suffix = Frame.RESET
|
|
252
244
|
|
|
253
245
|
if (style.bold) prefix += Frame.BOLD
|
|
@@ -260,20 +252,34 @@ export default class Frame {
|
|
|
260
252
|
const color = style.color
|
|
261
253
|
if (/^#[0-9a-f]{3,6}$/i.test(color)) {
|
|
262
254
|
// 24-bit color
|
|
263
|
-
const hex = color.replace(
|
|
264
|
-
const rgb =
|
|
265
|
-
|
|
266
|
-
|
|
255
|
+
const hex = color.replace('#', '')
|
|
256
|
+
const rgb =
|
|
257
|
+
hex.length === 3
|
|
258
|
+
? [0, 1, 2].map((i) => parseInt(hex[i] + hex[i], 16))
|
|
259
|
+
: [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16))
|
|
267
260
|
prefix += `\x1b[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`
|
|
268
261
|
} else if (/^\d+$/.test(color)) {
|
|
269
262
|
prefix += `\x1b[38;5;${color}m`
|
|
270
263
|
} else {
|
|
271
264
|
// Named color, map to 8-bit
|
|
272
265
|
const map = {
|
|
273
|
-
black: 30,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
266
|
+
black: 30,
|
|
267
|
+
red: 31,
|
|
268
|
+
green: 32,
|
|
269
|
+
yellow: 33,
|
|
270
|
+
blue: 34,
|
|
271
|
+
magenta: 35,
|
|
272
|
+
cyan: 36,
|
|
273
|
+
white: 37,
|
|
274
|
+
gray: 90,
|
|
275
|
+
grey: 90,
|
|
276
|
+
brightRed: 91,
|
|
277
|
+
brightGreen: 92,
|
|
278
|
+
brightYellow: 93,
|
|
279
|
+
brightBlue: 94,
|
|
280
|
+
brightMagenta: 95,
|
|
281
|
+
brightCyan: 96,
|
|
282
|
+
brightWhite: 97,
|
|
277
283
|
}
|
|
278
284
|
if (map[color]) prefix += `\x1b[${map[color]}m`
|
|
279
285
|
}
|
|
@@ -282,19 +288,33 @@ export default class Frame {
|
|
|
282
288
|
if (style.bgColor) {
|
|
283
289
|
const color = style.bgColor
|
|
284
290
|
if (/^#[0-9a-f]{3,6}$/i.test(color)) {
|
|
285
|
-
const hex = color.replace(
|
|
286
|
-
const rgb =
|
|
287
|
-
|
|
288
|
-
|
|
291
|
+
const hex = color.replace('#', '')
|
|
292
|
+
const rgb =
|
|
293
|
+
hex.length === 3
|
|
294
|
+
? [0, 1, 2].map((i) => parseInt(hex[i] + hex[i], 16))
|
|
295
|
+
: [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16))
|
|
289
296
|
prefix += `\x1b[48;2;${rgb[0]};${rgb[1]};${rgb[2]}m`
|
|
290
297
|
} else if (/^\d+$/.test(color)) {
|
|
291
298
|
prefix += `\x1b[48;5;${color}m`
|
|
292
299
|
} else {
|
|
293
300
|
const map = {
|
|
294
|
-
black: 40,
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
black: 40,
|
|
302
|
+
red: 41,
|
|
303
|
+
green: 42,
|
|
304
|
+
yellow: 43,
|
|
305
|
+
blue: 44,
|
|
306
|
+
magenta: 45,
|
|
307
|
+
cyan: 46,
|
|
308
|
+
white: 47,
|
|
309
|
+
gray: 100,
|
|
310
|
+
grey: 100,
|
|
311
|
+
brightRed: 101,
|
|
312
|
+
brightGreen: 102,
|
|
313
|
+
brightYellow: 103,
|
|
314
|
+
brightBlue: 104,
|
|
315
|
+
brightMagenta: 105,
|
|
316
|
+
brightCyan: 106,
|
|
317
|
+
brightWhite: 107,
|
|
298
318
|
}
|
|
299
319
|
if (map[color]) prefix += `\x1b[${map[color]}m`
|
|
300
320
|
}
|
|
@@ -322,18 +342,18 @@ export default class Frame {
|
|
|
322
342
|
if (cell.length === 2 && typeOf(Object)(cell[1])) {
|
|
323
343
|
return { text: String(cell[0]), style: mergeStyles(inherited, cell[1]) }
|
|
324
344
|
}
|
|
325
|
-
return { text: cell.map(c => parseCell(c, inherited).text).join(
|
|
345
|
+
return { text: cell.map((c) => parseCell(c, inherited).text).join(''), style: inherited }
|
|
326
346
|
}
|
|
327
347
|
if (typeOf(Object)(cell)) {
|
|
328
|
-
return { text:
|
|
348
|
+
return { text: '', style: mergeStyles(inherited, cell) }
|
|
329
349
|
}
|
|
330
|
-
if (typeof cell ===
|
|
350
|
+
if (typeof cell === 'string' && cell.startsWith('<') && cell.endsWith('>')) {
|
|
331
351
|
// Simple XML-like tag parser for <b>, <i>, <u>, <s>, <fg=...>, <bg=...>
|
|
332
352
|
let text = cell
|
|
333
353
|
let style = { ...inherited }
|
|
334
354
|
const tagPattern = /<([bius]|fg|bg)(?:=([#\w\d]+))?>|<\/([bius]|fg|bg)>/gi
|
|
335
355
|
let stack = []
|
|
336
|
-
let result =
|
|
356
|
+
let result = ''
|
|
337
357
|
let lastIndex = 0
|
|
338
358
|
let m
|
|
339
359
|
while ((m = tagPattern.exec(cell))) {
|
|
@@ -343,14 +363,26 @@ export default class Frame {
|
|
|
343
363
|
// Opening tag
|
|
344
364
|
let tag = m[1]
|
|
345
365
|
let val = m[2]
|
|
346
|
-
let newStyle = { ...stack.length ? stack[stack.length - 1] : style }
|
|
366
|
+
let newStyle = { ...(stack.length ? stack[stack.length - 1] : style) }
|
|
347
367
|
switch (tag) {
|
|
348
|
-
case
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
case
|
|
352
|
-
|
|
353
|
-
|
|
368
|
+
case 'b':
|
|
369
|
+
newStyle.bold = true
|
|
370
|
+
break
|
|
371
|
+
case 'i':
|
|
372
|
+
newStyle.italic = true
|
|
373
|
+
break
|
|
374
|
+
case 'u':
|
|
375
|
+
newStyle.underline = true
|
|
376
|
+
break
|
|
377
|
+
case 's':
|
|
378
|
+
newStyle.strikethrough = true
|
|
379
|
+
break
|
|
380
|
+
case 'fg':
|
|
381
|
+
newStyle.color = val
|
|
382
|
+
break
|
|
383
|
+
case 'bg':
|
|
384
|
+
newStyle.bgColor = val
|
|
385
|
+
break
|
|
354
386
|
}
|
|
355
387
|
stack.push(newStyle)
|
|
356
388
|
} else if (m[3]) {
|
|
@@ -367,13 +399,17 @@ export default class Frame {
|
|
|
367
399
|
|
|
368
400
|
// Determine frame-level style
|
|
369
401
|
let frameStyle = {}
|
|
370
|
-
if (
|
|
402
|
+
if (
|
|
403
|
+
typeOf(Array)(this.value) &&
|
|
404
|
+
this.value.length &&
|
|
405
|
+
typeOf(Object)(this.value[this.value.length - 1])
|
|
406
|
+
) {
|
|
371
407
|
frameStyle = this.value[this.value.length - 1]
|
|
372
408
|
}
|
|
373
409
|
|
|
374
410
|
let rows = this.value
|
|
375
|
-
.filter(row => !(typeOf(Object)(row) && !typeOf(Array)(row)))
|
|
376
|
-
.map(row => {
|
|
411
|
+
.filter((row) => !(typeOf(Object)(row) && !typeOf(Array)(row)))
|
|
412
|
+
.map((row) => {
|
|
377
413
|
let rowStyle = frameStyle
|
|
378
414
|
let cells = row
|
|
379
415
|
if (typeOf(Array)(row) && row.length && typeOf(Object)(row[row.length - 1])) {
|
|
@@ -381,32 +417,27 @@ export default class Frame {
|
|
|
381
417
|
cells = row.slice(0, -1)
|
|
382
418
|
}
|
|
383
419
|
if (!typeOf(Array)(cells)) cells = [cells]
|
|
384
|
-
let styled = cells.map(cell => {
|
|
420
|
+
let styled = cells.map((cell) => {
|
|
385
421
|
const { text, style } = parseCell(cell, mergeStyles(props, rowStyle))
|
|
386
422
|
return applyStyle(text, style)
|
|
387
423
|
})
|
|
388
|
-
return styled.join(
|
|
424
|
+
return styled.join('')
|
|
389
425
|
})
|
|
390
426
|
|
|
391
427
|
if (method === FrameRenderMethod.REPLACE) {
|
|
392
|
-
let emptyRows = rows.map(row =>
|
|
428
|
+
let emptyRows = rows.map((row) => ' '.repeat(this.lengthOf(row)))
|
|
393
429
|
if (rows.length > this.height) {
|
|
394
430
|
emptyRows = emptyRows.slice(0, this.height)
|
|
395
431
|
rows = rows.slice(0, this.height)
|
|
396
432
|
}
|
|
397
|
-
rows = [
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
...rows,
|
|
401
|
-
]
|
|
402
|
-
}
|
|
403
|
-
else if (method === FrameRenderMethod.APPEND) {
|
|
404
|
-
rows = rows.map(row => {
|
|
433
|
+
rows = [...emptyRows, Frame.BOF, ...rows]
|
|
434
|
+
} else if (method === FrameRenderMethod.APPEND) {
|
|
435
|
+
rows = rows.map((row) => {
|
|
405
436
|
const used = this.lengthOf(row)
|
|
406
437
|
const left = this.width - used
|
|
407
|
-
row = row +
|
|
438
|
+
row = row + ' '.repeat(Math.max(0, left))
|
|
408
439
|
if (stringWidth(row) > this.width) {
|
|
409
|
-
let acc =
|
|
440
|
+
let acc = ''
|
|
410
441
|
let w = 0
|
|
411
442
|
for (let ch of row) {
|
|
412
443
|
let chW = stringWidth(ch)
|
|
@@ -421,28 +452,23 @@ export default class Frame {
|
|
|
421
452
|
if (rows.length > this.height) {
|
|
422
453
|
rows = rows.slice(0, this.height)
|
|
423
454
|
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
]
|
|
455
|
+
} else if (method === FrameRenderMethod.VISIBLE) {
|
|
456
|
+
const moveUpLines = Math.max(
|
|
457
|
+
0,
|
|
458
|
+
Math.min(rows.length, this.height >= 0 ? this.height : rows.length),
|
|
459
|
+
)
|
|
460
|
+
rows = [`\x1b[${moveUpLines}A${Frame.BOF}`, ...rows]
|
|
431
461
|
if (rows.length > this.height && this.height >= 0) {
|
|
432
462
|
rows = rows.slice(0, this.height + 1) // +1 for the cursor move line
|
|
433
463
|
}
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
464
|
+
} else {
|
|
436
465
|
if (rows.length > this.height) {
|
|
437
466
|
rows = rows.slice(0, this.height)
|
|
438
467
|
}
|
|
439
|
-
rows = [
|
|
440
|
-
Frame.BOF,
|
|
441
|
-
...rows,
|
|
442
|
-
]
|
|
468
|
+
rows = [Frame.BOF, ...rows]
|
|
443
469
|
}
|
|
444
470
|
|
|
445
|
-
this.imprint = rows.join(
|
|
471
|
+
this.imprint = rows.join('\n')
|
|
446
472
|
return this.imprint
|
|
447
473
|
}
|
|
448
474
|
/**
|
|
@@ -458,9 +484,7 @@ export default class Frame {
|
|
|
458
484
|
* @returns {Frame} A new Frame with transformed values.
|
|
459
485
|
*/
|
|
460
486
|
transform(fn) {
|
|
461
|
-
const value = this.value.map(
|
|
462
|
-
row => row.map(fn)
|
|
463
|
-
)
|
|
487
|
+
const value = this.value.map((row) => row.map(fn))
|
|
464
488
|
return new Frame({ ...this, value })
|
|
465
489
|
}
|
|
466
490
|
/**
|
|
@@ -494,7 +518,7 @@ export default class Frame {
|
|
|
494
518
|
static from(input) {
|
|
495
519
|
if (input instanceof Frame) return input
|
|
496
520
|
if (input?.value instanceof Frame) return new Frame(to(Object)(input.value))
|
|
497
|
-
if (
|
|
521
|
+
if ('string' === typeof input) input = [input]
|
|
498
522
|
if (Array.isArray(input)) return new Frame({ value: input })
|
|
499
523
|
return new Frame(input)
|
|
500
524
|
}
|
|
@@ -508,12 +532,11 @@ export default class Frame {
|
|
|
508
532
|
*/
|
|
509
533
|
static spaces(options = {}) {
|
|
510
534
|
const { cols = [], padding = 1, aligns = [] } = options
|
|
511
|
-
return (row) =>
|
|
535
|
+
return (row) =>
|
|
512
536
|
row.map((str, i) => {
|
|
513
|
-
const pad =
|
|
514
|
-
return aligns[i] ===
|
|
537
|
+
const pad = ' '.repeat(cols[i] - str.length + padding)
|
|
538
|
+
return aligns[i] === 'r' ? pad + str : str + pad
|
|
515
539
|
})
|
|
516
|
-
)
|
|
517
540
|
}
|
|
518
541
|
/**
|
|
519
542
|
*
|
|
@@ -521,9 +544,9 @@ export default class Frame {
|
|
|
521
544
|
* @returns {(v) => number[]}
|
|
522
545
|
*/
|
|
523
546
|
static weight(arr) {
|
|
524
|
-
return (Fn = v => v) => {
|
|
547
|
+
return (Fn = (v) => v) => {
|
|
525
548
|
const cols = []
|
|
526
|
-
arr.forEach(m => {
|
|
549
|
+
arr.forEach((m) => {
|
|
527
550
|
Fn(m).forEach((str, i) => {
|
|
528
551
|
if (undefined === cols[i]) cols[i] = 0
|
|
529
552
|
cols[i] = Math.max(String(str).length, cols[i])
|
|
@@ -542,18 +565,13 @@ export default class Frame {
|
|
|
542
565
|
* @returns {(arr: []) => string[][]}
|
|
543
566
|
*/
|
|
544
567
|
static table(options = {}) {
|
|
545
|
-
const {
|
|
546
|
-
fn = v => v,
|
|
547
|
-
cols: initialCols = [],
|
|
548
|
-
padding = 1,
|
|
549
|
-
aligns = []
|
|
550
|
-
} = options
|
|
568
|
+
const { fn = (v) => v, cols: initialCols = [], padding = 1, aligns = [] } = options
|
|
551
569
|
return (arr) => {
|
|
552
570
|
let cols = initialCols
|
|
553
571
|
if (empty(cols)) {
|
|
554
572
|
cols = Frame.weight(arr)(fn)
|
|
555
573
|
}
|
|
556
|
-
return arr.map(row => Frame.spaces({ cols, padding, aligns })(row))
|
|
574
|
+
return arr.map((row) => Frame.spaces({ cols, padding, aligns })(row))
|
|
557
575
|
}
|
|
558
576
|
}
|
|
559
577
|
/**
|
|
@@ -577,7 +595,7 @@ export default class Frame {
|
|
|
577
595
|
* @param {string} [str="\r"] - String to append after clearing.
|
|
578
596
|
* @returns {string} ANSI escape code for line clearing followed by the string.
|
|
579
597
|
*/
|
|
580
|
-
static clearLine(str =
|
|
598
|
+
static clearLine(str = '\r') {
|
|
581
599
|
return Frame.CLEAR_LINE + str
|
|
582
600
|
}
|
|
583
601
|
/**
|
|
@@ -587,5 +605,4 @@ export default class Frame {
|
|
|
587
605
|
static clearScreen() {
|
|
588
606
|
return '\x1b[2J\x1b[0;0H'
|
|
589
607
|
}
|
|
590
|
-
|
|
591
|
-
}
|
|
608
|
+
}
|
package/src/Frame/Props.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { typeOf, ObjectWithAlias } from
|
|
1
|
+
import { typeOf, ObjectWithAlias } from '@nan0web/types'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents default styling properties for Frame rendering.
|
|
@@ -7,7 +7,7 @@ import { typeOf, ObjectWithAlias } from "@nan0web/types"
|
|
|
7
7
|
* If you want to apply different props to multiple values, you can use an object with the props.
|
|
8
8
|
* If you want to apply props to a single value, you can use a string with the props in XML format.
|
|
9
9
|
* Parser checks every atom for its beginning and end and if it's a tag, it applies the props to the value.
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* @example
|
|
12
12
|
* const defaultProps = new FrameProps({
|
|
13
13
|
* color: "red",
|
|
@@ -40,34 +40,34 @@ import { typeOf, ObjectWithAlias } from "@nan0web/types"
|
|
|
40
40
|
* const defaultProps = new FrameProps(rows)
|
|
41
41
|
*/
|
|
42
42
|
class FrameProps extends ObjectWithAlias {
|
|
43
|
-
/**
|
|
43
|
+
/**
|
|
44
44
|
* Property aliases for shorthand notation.
|
|
45
45
|
* @type {Record<string, string>}
|
|
46
46
|
*/
|
|
47
47
|
static ALIAS = {
|
|
48
|
-
fg:
|
|
49
|
-
bg:
|
|
50
|
-
b:
|
|
51
|
-
i:
|
|
52
|
-
u:
|
|
53
|
-
s:
|
|
48
|
+
fg: 'color',
|
|
49
|
+
bg: 'bgColor',
|
|
50
|
+
b: 'bold',
|
|
51
|
+
i: 'italic',
|
|
52
|
+
u: 'underline',
|
|
53
|
+
s: 'strikethrough',
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
/** @type {string} Text color */
|
|
57
|
-
color =
|
|
58
|
-
|
|
57
|
+
color = ''
|
|
58
|
+
|
|
59
59
|
/** @type {string} Background color */
|
|
60
|
-
bgColor =
|
|
61
|
-
|
|
60
|
+
bgColor = ''
|
|
61
|
+
|
|
62
62
|
/** @type {boolean} Bold text flag */
|
|
63
63
|
bold = false
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
/** @type {boolean} Italic text flag */
|
|
66
66
|
italic = false
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
/** @type {boolean} Underline text flag */
|
|
69
69
|
underline = false
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
/** @type {boolean} Strikethrough text flag */
|
|
72
72
|
strikethrough = false
|
|
73
73
|
|
|
@@ -83,8 +83,8 @@ class FrameProps extends ObjectWithAlias {
|
|
|
83
83
|
constructor(props = {}) {
|
|
84
84
|
super()
|
|
85
85
|
const {
|
|
86
|
-
color =
|
|
87
|
-
bgColor =
|
|
86
|
+
color = '',
|
|
87
|
+
bgColor = '',
|
|
88
88
|
bold = false,
|
|
89
89
|
italic = false,
|
|
90
90
|
underline = false,
|
|
@@ -99,4 +99,4 @@ class FrameProps extends ObjectWithAlias {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
export default FrameProps
|
|
102
|
+
export default FrameProps
|