@oakoliver/lipgloss 1.0.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/LICENSE +24 -0
- package/README.md +259 -0
- package/dist/ansi.d.ts +82 -0
- package/dist/ansi.d.ts.map +1 -0
- package/dist/border.d.ts +54 -0
- package/dist/border.d.ts.map +1 -0
- package/dist/color.d.ts +86 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/index.cjs +2408 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2309 -0
- package/dist/layout.d.ts +28 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/style.d.ts +247 -0
- package/dist/style.d.ts.map +1 -0
- package/package.json +70 -0
- package/src/ansi.ts +292 -0
- package/src/border.ts +168 -0
- package/src/color.ts +294 -0
- package/src/index.ts +44 -0
- package/src/layout.ts +206 -0
- package/src/style.ts +1131 -0
package/src/style.ts
ADDED
|
@@ -0,0 +1,1131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Style — the core of lipgloss. Immutable fluent builder for terminal styling.
|
|
3
|
+
* Every setter returns a new Style instance (value-type semantics).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { SGR, stringWidth, stripAnsi, truncate as truncateStr, setHyperlink, resetHyperlink } from './ansi.js';
|
|
7
|
+
import type { ColorValue, UnderlineStyle, AnsiStyleOptions } from './ansi.js';
|
|
8
|
+
import { styled } from './ansi.js';
|
|
9
|
+
import { parseColor, NO_COLOR } from './color.js';
|
|
10
|
+
import type { Color } from './color.js';
|
|
11
|
+
import { noBorder, isNoBorder, maxRuneWidth, getTopSize, getRightSize, getBottomSize, getLeftSize } from './border.js';
|
|
12
|
+
import type { Border } from './border.js';
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Position type
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
/** 0.0 = top/left, 0.5 = center, 1.0 = bottom/right */
|
|
19
|
+
export type Position = number;
|
|
20
|
+
|
|
21
|
+
export const Top: Position = 0.0;
|
|
22
|
+
export const Bottom: Position = 1.0;
|
|
23
|
+
export const Center: Position = 0.5;
|
|
24
|
+
export const Left: Position = 0.0;
|
|
25
|
+
export const Right: Position = 1.0;
|
|
26
|
+
|
|
27
|
+
function clampPos(p: Position): number {
|
|
28
|
+
return Math.min(1, Math.max(0, p));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// CSS-shorthand helpers (1-4 args)
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
type Sides<T> = { top: T; right: T; bottom: T; left: T };
|
|
36
|
+
|
|
37
|
+
function whichSidesInt(...args: number[]): Sides<number> | null {
|
|
38
|
+
switch (args.length) {
|
|
39
|
+
case 1: return { top: args[0], right: args[0], bottom: args[0], left: args[0] };
|
|
40
|
+
case 2: return { top: args[0], right: args[1], bottom: args[0], left: args[1] };
|
|
41
|
+
case 3: return { top: args[0], right: args[1], bottom: args[2], left: args[1] };
|
|
42
|
+
case 4: return { top: args[0], right: args[1], bottom: args[2], left: args[3] };
|
|
43
|
+
default: return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function whichSidesBool(...args: boolean[]): Sides<boolean> | null {
|
|
48
|
+
switch (args.length) {
|
|
49
|
+
case 1: return { top: args[0], right: args[0], bottom: args[0], left: args[0] };
|
|
50
|
+
case 2: return { top: args[0], right: args[1], bottom: args[0], left: args[1] };
|
|
51
|
+
case 3: return { top: args[0], right: args[1], bottom: args[2], left: args[1] };
|
|
52
|
+
case 4: return { top: args[0], right: args[1], bottom: args[2], left: args[3] };
|
|
53
|
+
default: return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function whichSidesColor(...args: Color[]): Sides<Color> | null {
|
|
58
|
+
switch (args.length) {
|
|
59
|
+
case 1: return { top: args[0], right: args[0], bottom: args[0], left: args[0] };
|
|
60
|
+
case 2: return { top: args[0], right: args[1], bottom: args[0], left: args[1] };
|
|
61
|
+
case 3: return { top: args[0], right: args[1], bottom: args[2], left: args[1] };
|
|
62
|
+
case 4: return { top: args[0], right: args[1], bottom: args[2], left: args[3] };
|
|
63
|
+
default: return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Internal text helpers
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
/** Split string into lines and find the widest line's visible width. */
|
|
72
|
+
export function getLines(s: string): { lines: string[]; widest: number } {
|
|
73
|
+
s = s.replace(/\t/g, ' ').replace(/\r\n/g, '\n');
|
|
74
|
+
const lines = s.split('\n');
|
|
75
|
+
let widest = 0;
|
|
76
|
+
for (const l of lines) {
|
|
77
|
+
const w = stringWidth(l);
|
|
78
|
+
if (w > widest) widest = w;
|
|
79
|
+
}
|
|
80
|
+
return { lines, widest };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Horizontal alignment: pads each line so all are the same width. */
|
|
84
|
+
function alignTextHorizontal(str: string, pos: Position, width: number, wsStyle: AnsiStyleOptions | null): string {
|
|
85
|
+
const { lines, widest } = getLines(str);
|
|
86
|
+
const parts: string[] = [];
|
|
87
|
+
|
|
88
|
+
for (const l of lines) {
|
|
89
|
+
const lineWidth = stringWidth(l);
|
|
90
|
+
const shortAmount = Math.max(0, widest - lineWidth) + Math.max(0, width - Math.max(widest, lineWidth));
|
|
91
|
+
|
|
92
|
+
if (shortAmount > 0) {
|
|
93
|
+
const p = clampPos(pos);
|
|
94
|
+
if (p <= 0) {
|
|
95
|
+
// Left
|
|
96
|
+
parts.push(l + styledSpaces(shortAmount, wsStyle));
|
|
97
|
+
} else if (p >= 1) {
|
|
98
|
+
// Right
|
|
99
|
+
parts.push(styledSpaces(shortAmount, wsStyle) + l);
|
|
100
|
+
} else {
|
|
101
|
+
// Center
|
|
102
|
+
const leftPad = Math.floor(shortAmount * p);
|
|
103
|
+
const rightPad = shortAmount - leftPad;
|
|
104
|
+
parts.push(styledSpaces(leftPad, wsStyle) + l + styledSpaces(rightPad, wsStyle));
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
parts.push(l);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return parts.join('\n');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Vertical alignment within a given height. */
|
|
115
|
+
function alignTextVertical(str: string, pos: Position, height: number): string {
|
|
116
|
+
const strHeight = str.split('\n').length;
|
|
117
|
+
if (height <= strHeight) return str;
|
|
118
|
+
const gap = height - strHeight;
|
|
119
|
+
const p = clampPos(pos);
|
|
120
|
+
|
|
121
|
+
if (p <= 0) {
|
|
122
|
+
// Top
|
|
123
|
+
return str + '\n'.repeat(gap);
|
|
124
|
+
} else if (p >= 1) {
|
|
125
|
+
// Bottom
|
|
126
|
+
return '\n'.repeat(gap) + str;
|
|
127
|
+
} else {
|
|
128
|
+
// Center
|
|
129
|
+
const topPad = Math.round(gap * (1 - p));
|
|
130
|
+
const bottomPad = gap - topPad;
|
|
131
|
+
return '\n'.repeat(topPad) + str + '\n'.repeat(bottomPad);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Create styled spaces (optionally styled with background/reverse). */
|
|
136
|
+
function styledSpaces(n: number, wsStyle: AnsiStyleOptions | null, ch = ' '): string {
|
|
137
|
+
if (n <= 0) return '';
|
|
138
|
+
const sp = ch.repeat(n);
|
|
139
|
+
if (wsStyle) return styled(sp, wsStyle);
|
|
140
|
+
return sp;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Pad each line on the left. */
|
|
144
|
+
function padLeft(str: string, n: number, wsStyle: AnsiStyleOptions | null, ch = ' '): string {
|
|
145
|
+
if (n <= 0) return str;
|
|
146
|
+
const sp = styledSpaces(n, wsStyle, ch);
|
|
147
|
+
return str.split('\n').map(line => sp + line).join('\n');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Pad each line on the right. */
|
|
151
|
+
function padRight(str: string, n: number, wsStyle: AnsiStyleOptions | null, ch = ' '): string {
|
|
152
|
+
if (n <= 0) return str;
|
|
153
|
+
const sp = styledSpaces(n, wsStyle, ch);
|
|
154
|
+
return str.split('\n').map(line => line + sp).join('\n');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Simple word-wrap: break lines at width boundary. */
|
|
158
|
+
function wordWrap(str: string, width: number): string {
|
|
159
|
+
if (width <= 0) return str;
|
|
160
|
+
const inputLines = str.split('\n');
|
|
161
|
+
const out: string[] = [];
|
|
162
|
+
|
|
163
|
+
for (const line of inputLines) {
|
|
164
|
+
if (stringWidth(line) <= width) {
|
|
165
|
+
out.push(line);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Break by words first, fall back to chars
|
|
169
|
+
const words = line.split(/(\s+)/);
|
|
170
|
+
let current = '';
|
|
171
|
+
for (const word of words) {
|
|
172
|
+
const combined = current + word;
|
|
173
|
+
if (stringWidth(combined) <= width) {
|
|
174
|
+
current = combined;
|
|
175
|
+
} else {
|
|
176
|
+
if (current) out.push(current);
|
|
177
|
+
// If a single word is wider than width, break by chars
|
|
178
|
+
if (stringWidth(word) > width) {
|
|
179
|
+
let rem = word;
|
|
180
|
+
while (stringWidth(rem) > width) {
|
|
181
|
+
let cut = '';
|
|
182
|
+
for (const ch of rem) {
|
|
183
|
+
if (stringWidth(cut + ch) > width) break;
|
|
184
|
+
cut += ch;
|
|
185
|
+
}
|
|
186
|
+
if (!cut) { cut = rem[0]; rem = rem.slice(1); }
|
|
187
|
+
else { rem = rem.slice(cut.length); }
|
|
188
|
+
out.push(cut);
|
|
189
|
+
}
|
|
190
|
+
current = rem;
|
|
191
|
+
} else {
|
|
192
|
+
current = word;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (current) out.push(current);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return out.join('\n');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Render a horizontal border edge (top or bottom row). */
|
|
203
|
+
function renderHorizontalEdge(left: string, middle: string, right: string, width: number): string {
|
|
204
|
+
if (!middle) middle = ' ';
|
|
205
|
+
const leftW = stringWidth(left);
|
|
206
|
+
const rightW = stringWidth(right);
|
|
207
|
+
const runes = [...middle];
|
|
208
|
+
let j = 0;
|
|
209
|
+
let result = left;
|
|
210
|
+
let i = 0;
|
|
211
|
+
const target = width - leftW - rightW;
|
|
212
|
+
while (i < target) {
|
|
213
|
+
const r = runes[j % runes.length];
|
|
214
|
+
result += r;
|
|
215
|
+
i += stringWidth(r);
|
|
216
|
+
j++;
|
|
217
|
+
}
|
|
218
|
+
result += right;
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Get first character of a string as a string (for corners). */
|
|
223
|
+
export function getFirstRune(s: string): string {
|
|
224
|
+
if (!s) return s;
|
|
225
|
+
return [...s][0];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// Style class
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
|
|
232
|
+
const TAB_WIDTH_DEFAULT = 4;
|
|
233
|
+
|
|
234
|
+
export class Style {
|
|
235
|
+
// Track which properties have been explicitly set
|
|
236
|
+
private _set = new Set<string>();
|
|
237
|
+
|
|
238
|
+
// Internal string value (for SetString / toString)
|
|
239
|
+
private _value = '';
|
|
240
|
+
|
|
241
|
+
// Boolean attrs
|
|
242
|
+
private _bold = false;
|
|
243
|
+
private _italic = false;
|
|
244
|
+
private _strikethrough = false;
|
|
245
|
+
private _reverse = false;
|
|
246
|
+
private _blink = false;
|
|
247
|
+
private _faint = false;
|
|
248
|
+
private _underlineSpaces = false;
|
|
249
|
+
private _strikethroughSpaces = false;
|
|
250
|
+
private _colorWhitespace = false;
|
|
251
|
+
|
|
252
|
+
// Underline
|
|
253
|
+
private _underlineStyle: UnderlineStyle = 'none';
|
|
254
|
+
|
|
255
|
+
// Colors
|
|
256
|
+
private _fg: Color = null;
|
|
257
|
+
private _bg: Color = null;
|
|
258
|
+
private _ulColor: Color = null;
|
|
259
|
+
|
|
260
|
+
// Dimensions
|
|
261
|
+
private _width = 0;
|
|
262
|
+
private _height = 0;
|
|
263
|
+
private _maxWidth = 0;
|
|
264
|
+
private _maxHeight = 0;
|
|
265
|
+
|
|
266
|
+
// Alignment
|
|
267
|
+
private _alignH: Position = 0;
|
|
268
|
+
private _alignV: Position = 0;
|
|
269
|
+
|
|
270
|
+
// Padding
|
|
271
|
+
private _paddingTop = 0;
|
|
272
|
+
private _paddingRight = 0;
|
|
273
|
+
private _paddingBottom = 0;
|
|
274
|
+
private _paddingLeft = 0;
|
|
275
|
+
|
|
276
|
+
// Margin
|
|
277
|
+
private _marginTop = 0;
|
|
278
|
+
private _marginRight = 0;
|
|
279
|
+
private _marginBottom = 0;
|
|
280
|
+
private _marginLeft = 0;
|
|
281
|
+
private _marginBg: Color = null;
|
|
282
|
+
|
|
283
|
+
// Border
|
|
284
|
+
private _borderStyle: Border = noBorder;
|
|
285
|
+
private _borderTop = false;
|
|
286
|
+
private _borderRight = false;
|
|
287
|
+
private _borderBottom = false;
|
|
288
|
+
private _borderLeft = false;
|
|
289
|
+
private _borderTopFg: Color = null;
|
|
290
|
+
private _borderRightFg: Color = null;
|
|
291
|
+
private _borderBottomFg: Color = null;
|
|
292
|
+
private _borderLeftFg: Color = null;
|
|
293
|
+
private _borderTopBg: Color = null;
|
|
294
|
+
private _borderRightBg: Color = null;
|
|
295
|
+
private _borderBottomBg: Color = null;
|
|
296
|
+
private _borderLeftBg: Color = null;
|
|
297
|
+
|
|
298
|
+
// Other
|
|
299
|
+
private _inline = false;
|
|
300
|
+
private _tabWidth = TAB_WIDTH_DEFAULT;
|
|
301
|
+
private _transform: ((s: string) => string) | null = null;
|
|
302
|
+
private _link = '';
|
|
303
|
+
private _linkParams = '';
|
|
304
|
+
private _paddingChar = ' ';
|
|
305
|
+
|
|
306
|
+
/** Clone this style into a new instance. */
|
|
307
|
+
private _clone(): Style {
|
|
308
|
+
const s = new Style();
|
|
309
|
+
s._set = new Set(this._set);
|
|
310
|
+
s._value = this._value;
|
|
311
|
+
s._bold = this._bold;
|
|
312
|
+
s._italic = this._italic;
|
|
313
|
+
s._strikethrough = this._strikethrough;
|
|
314
|
+
s._reverse = this._reverse;
|
|
315
|
+
s._blink = this._blink;
|
|
316
|
+
s._faint = this._faint;
|
|
317
|
+
s._underlineSpaces = this._underlineSpaces;
|
|
318
|
+
s._strikethroughSpaces = this._strikethroughSpaces;
|
|
319
|
+
s._colorWhitespace = this._colorWhitespace;
|
|
320
|
+
s._underlineStyle = this._underlineStyle;
|
|
321
|
+
s._fg = this._fg;
|
|
322
|
+
s._bg = this._bg;
|
|
323
|
+
s._ulColor = this._ulColor;
|
|
324
|
+
s._width = this._width;
|
|
325
|
+
s._height = this._height;
|
|
326
|
+
s._maxWidth = this._maxWidth;
|
|
327
|
+
s._maxHeight = this._maxHeight;
|
|
328
|
+
s._alignH = this._alignH;
|
|
329
|
+
s._alignV = this._alignV;
|
|
330
|
+
s._paddingTop = this._paddingTop;
|
|
331
|
+
s._paddingRight = this._paddingRight;
|
|
332
|
+
s._paddingBottom = this._paddingBottom;
|
|
333
|
+
s._paddingLeft = this._paddingLeft;
|
|
334
|
+
s._marginTop = this._marginTop;
|
|
335
|
+
s._marginRight = this._marginRight;
|
|
336
|
+
s._marginBottom = this._marginBottom;
|
|
337
|
+
s._marginLeft = this._marginLeft;
|
|
338
|
+
s._marginBg = this._marginBg;
|
|
339
|
+
s._borderStyle = this._borderStyle;
|
|
340
|
+
s._borderTop = this._borderTop;
|
|
341
|
+
s._borderRight = this._borderRight;
|
|
342
|
+
s._borderBottom = this._borderBottom;
|
|
343
|
+
s._borderLeft = this._borderLeft;
|
|
344
|
+
s._borderTopFg = this._borderTopFg;
|
|
345
|
+
s._borderRightFg = this._borderRightFg;
|
|
346
|
+
s._borderBottomFg = this._borderBottomFg;
|
|
347
|
+
s._borderLeftFg = this._borderLeftFg;
|
|
348
|
+
s._borderTopBg = this._borderTopBg;
|
|
349
|
+
s._borderRightBg = this._borderRightBg;
|
|
350
|
+
s._borderBottomBg = this._borderBottomBg;
|
|
351
|
+
s._borderLeftBg = this._borderLeftBg;
|
|
352
|
+
s._inline = this._inline;
|
|
353
|
+
s._tabWidth = this._tabWidth;
|
|
354
|
+
s._transform = this._transform;
|
|
355
|
+
s._link = this._link;
|
|
356
|
+
s._linkParams = this._linkParams;
|
|
357
|
+
s._paddingChar = this._paddingChar;
|
|
358
|
+
return s;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// -----------------------------------------------------------------------
|
|
362
|
+
// Setters (all return new Style)
|
|
363
|
+
// -----------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
setString(...strs: string[]): Style {
|
|
366
|
+
const s = this._clone();
|
|
367
|
+
s._value = strs.join(' ');
|
|
368
|
+
return s;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
bold(v: boolean): Style {
|
|
372
|
+
const s = this._clone(); s._bold = v; s._set.add('bold'); return s;
|
|
373
|
+
}
|
|
374
|
+
italic(v: boolean): Style {
|
|
375
|
+
const s = this._clone(); s._italic = v; s._set.add('italic'); return s;
|
|
376
|
+
}
|
|
377
|
+
strikethrough(v: boolean): Style {
|
|
378
|
+
const s = this._clone(); s._strikethrough = v; s._set.add('strikethrough'); return s;
|
|
379
|
+
}
|
|
380
|
+
reverse(v: boolean): Style {
|
|
381
|
+
const s = this._clone(); s._reverse = v; s._set.add('reverse'); return s;
|
|
382
|
+
}
|
|
383
|
+
blink(v: boolean): Style {
|
|
384
|
+
const s = this._clone(); s._blink = v; s._set.add('blink'); return s;
|
|
385
|
+
}
|
|
386
|
+
faint(v: boolean): Style {
|
|
387
|
+
const s = this._clone(); s._faint = v; s._set.add('faint'); return s;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
underline(v: boolean): Style {
|
|
391
|
+
return v ? this.underlineStyle('single') : this.underlineStyle('none');
|
|
392
|
+
}
|
|
393
|
+
underlineStyle(u: UnderlineStyle): Style {
|
|
394
|
+
const s = this._clone(); s._underlineStyle = u; s._set.add('underline'); return s;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
foreground(c: Color): Style {
|
|
398
|
+
const s = this._clone(); s._fg = c; s._set.add('fg'); return s;
|
|
399
|
+
}
|
|
400
|
+
background(c: Color): Style {
|
|
401
|
+
const s = this._clone(); s._bg = c; s._set.add('bg'); return s;
|
|
402
|
+
}
|
|
403
|
+
underlineColor(c: Color): Style {
|
|
404
|
+
const s = this._clone(); s._ulColor = c; s._set.add('ulColor'); return s;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
width(n: number): Style {
|
|
408
|
+
const s = this._clone(); s._width = Math.max(0, n); s._set.add('width'); return s;
|
|
409
|
+
}
|
|
410
|
+
height(n: number): Style {
|
|
411
|
+
const s = this._clone(); s._height = Math.max(0, n); s._set.add('height'); return s;
|
|
412
|
+
}
|
|
413
|
+
maxWidth(n: number): Style {
|
|
414
|
+
const s = this._clone(); s._maxWidth = Math.max(0, n); s._set.add('maxWidth'); return s;
|
|
415
|
+
}
|
|
416
|
+
maxHeight(n: number): Style {
|
|
417
|
+
const s = this._clone(); s._maxHeight = Math.max(0, n); s._set.add('maxHeight'); return s;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
align(...pos: Position[]): Style {
|
|
421
|
+
let s = this._clone();
|
|
422
|
+
if (pos.length > 0) { s._alignH = pos[0]; s._set.add('alignH'); }
|
|
423
|
+
if (pos.length > 1) { s._alignV = pos[1]; s._set.add('alignV'); }
|
|
424
|
+
return s;
|
|
425
|
+
}
|
|
426
|
+
alignHorizontal(p: Position): Style {
|
|
427
|
+
const s = this._clone(); s._alignH = p; s._set.add('alignH'); return s;
|
|
428
|
+
}
|
|
429
|
+
alignVertical(p: Position): Style {
|
|
430
|
+
const s = this._clone(); s._alignV = p; s._set.add('alignV'); return s;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
padding(...args: number[]): Style {
|
|
434
|
+
const sides = whichSidesInt(...args);
|
|
435
|
+
if (!sides) return this;
|
|
436
|
+
const s = this._clone();
|
|
437
|
+
s._paddingTop = Math.max(0, sides.top); s._set.add('paddingTop');
|
|
438
|
+
s._paddingRight = Math.max(0, sides.right); s._set.add('paddingRight');
|
|
439
|
+
s._paddingBottom = Math.max(0, sides.bottom); s._set.add('paddingBottom');
|
|
440
|
+
s._paddingLeft = Math.max(0, sides.left); s._set.add('paddingLeft');
|
|
441
|
+
return s;
|
|
442
|
+
}
|
|
443
|
+
paddingTop(n: number): Style {
|
|
444
|
+
const s = this._clone(); s._paddingTop = Math.max(0, n); s._set.add('paddingTop'); return s;
|
|
445
|
+
}
|
|
446
|
+
paddingRight(n: number): Style {
|
|
447
|
+
const s = this._clone(); s._paddingRight = Math.max(0, n); s._set.add('paddingRight'); return s;
|
|
448
|
+
}
|
|
449
|
+
paddingBottom(n: number): Style {
|
|
450
|
+
const s = this._clone(); s._paddingBottom = Math.max(0, n); s._set.add('paddingBottom'); return s;
|
|
451
|
+
}
|
|
452
|
+
paddingLeft(n: number): Style {
|
|
453
|
+
const s = this._clone(); s._paddingLeft = Math.max(0, n); s._set.add('paddingLeft'); return s;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
margin(...args: number[]): Style {
|
|
457
|
+
const sides = whichSidesInt(...args);
|
|
458
|
+
if (!sides) return this;
|
|
459
|
+
const s = this._clone();
|
|
460
|
+
s._marginTop = Math.max(0, sides.top); s._set.add('marginTop');
|
|
461
|
+
s._marginRight = Math.max(0, sides.right); s._set.add('marginRight');
|
|
462
|
+
s._marginBottom = Math.max(0, sides.bottom); s._set.add('marginBottom');
|
|
463
|
+
s._marginLeft = Math.max(0, sides.left); s._set.add('marginLeft');
|
|
464
|
+
return s;
|
|
465
|
+
}
|
|
466
|
+
marginTop(n: number): Style {
|
|
467
|
+
const s = this._clone(); s._marginTop = Math.max(0, n); s._set.add('marginTop'); return s;
|
|
468
|
+
}
|
|
469
|
+
marginRight(n: number): Style {
|
|
470
|
+
const s = this._clone(); s._marginRight = Math.max(0, n); s._set.add('marginRight'); return s;
|
|
471
|
+
}
|
|
472
|
+
marginBottom(n: number): Style {
|
|
473
|
+
const s = this._clone(); s._marginBottom = Math.max(0, n); s._set.add('marginBottom'); return s;
|
|
474
|
+
}
|
|
475
|
+
marginLeft(n: number): Style {
|
|
476
|
+
const s = this._clone(); s._marginLeft = Math.max(0, n); s._set.add('marginLeft'); return s;
|
|
477
|
+
}
|
|
478
|
+
marginBackground(c: Color): Style {
|
|
479
|
+
const s = this._clone(); s._marginBg = c; s._set.add('marginBg'); return s;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
border(b: Border, ...sides: boolean[]): Style {
|
|
483
|
+
const s = this._clone();
|
|
484
|
+
s._borderStyle = b; s._set.add('borderStyle');
|
|
485
|
+
const bs = whichSidesBool(...sides);
|
|
486
|
+
if (bs) {
|
|
487
|
+
s._borderTop = bs.top; s._set.add('borderTop');
|
|
488
|
+
s._borderRight = bs.right; s._set.add('borderRight');
|
|
489
|
+
s._borderBottom = bs.bottom; s._set.add('borderBottom');
|
|
490
|
+
s._borderLeft = bs.left; s._set.add('borderLeft');
|
|
491
|
+
} else {
|
|
492
|
+
s._borderTop = true; s._set.add('borderTop');
|
|
493
|
+
s._borderRight = true; s._set.add('borderRight');
|
|
494
|
+
s._borderBottom = true; s._set.add('borderBottom');
|
|
495
|
+
s._borderLeft = true; s._set.add('borderLeft');
|
|
496
|
+
}
|
|
497
|
+
return s;
|
|
498
|
+
}
|
|
499
|
+
borderStyle(b: Border): Style {
|
|
500
|
+
const s = this._clone(); s._borderStyle = b; s._set.add('borderStyle'); return s;
|
|
501
|
+
}
|
|
502
|
+
borderTop(v: boolean): Style {
|
|
503
|
+
const s = this._clone(); s._borderTop = v; s._set.add('borderTop'); return s;
|
|
504
|
+
}
|
|
505
|
+
borderRight(v: boolean): Style {
|
|
506
|
+
const s = this._clone(); s._borderRight = v; s._set.add('borderRight'); return s;
|
|
507
|
+
}
|
|
508
|
+
borderBottom(v: boolean): Style {
|
|
509
|
+
const s = this._clone(); s._borderBottom = v; s._set.add('borderBottom'); return s;
|
|
510
|
+
}
|
|
511
|
+
borderLeft(v: boolean): Style {
|
|
512
|
+
const s = this._clone(); s._borderLeft = v; s._set.add('borderLeft'); return s;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
borderForeground(...colors: Color[]): Style {
|
|
516
|
+
if (colors.length === 0) return this;
|
|
517
|
+
const sides = whichSidesColor(...colors);
|
|
518
|
+
if (!sides) return this;
|
|
519
|
+
const s = this._clone();
|
|
520
|
+
s._borderTopFg = sides.top; s._set.add('borderTopFg');
|
|
521
|
+
s._borderRightFg = sides.right; s._set.add('borderRightFg');
|
|
522
|
+
s._borderBottomFg = sides.bottom; s._set.add('borderBottomFg');
|
|
523
|
+
s._borderLeftFg = sides.left; s._set.add('borderLeftFg');
|
|
524
|
+
return s;
|
|
525
|
+
}
|
|
526
|
+
borderTopForeground(c: Color): Style {
|
|
527
|
+
const s = this._clone(); s._borderTopFg = c; s._set.add('borderTopFg'); return s;
|
|
528
|
+
}
|
|
529
|
+
borderRightForeground(c: Color): Style {
|
|
530
|
+
const s = this._clone(); s._borderRightFg = c; s._set.add('borderRightFg'); return s;
|
|
531
|
+
}
|
|
532
|
+
borderBottomForeground(c: Color): Style {
|
|
533
|
+
const s = this._clone(); s._borderBottomFg = c; s._set.add('borderBottomFg'); return s;
|
|
534
|
+
}
|
|
535
|
+
borderLeftForeground(c: Color): Style {
|
|
536
|
+
const s = this._clone(); s._borderLeftFg = c; s._set.add('borderLeftFg'); return s;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
borderBackground(...colors: Color[]): Style {
|
|
540
|
+
if (colors.length === 0) return this;
|
|
541
|
+
const sides = whichSidesColor(...colors);
|
|
542
|
+
if (!sides) return this;
|
|
543
|
+
const s = this._clone();
|
|
544
|
+
s._borderTopBg = sides.top; s._set.add('borderTopBg');
|
|
545
|
+
s._borderRightBg = sides.right; s._set.add('borderRightBg');
|
|
546
|
+
s._borderBottomBg = sides.bottom; s._set.add('borderBottomBg');
|
|
547
|
+
s._borderLeftBg = sides.left; s._set.add('borderLeftBg');
|
|
548
|
+
return s;
|
|
549
|
+
}
|
|
550
|
+
borderTopBackground(c: Color): Style {
|
|
551
|
+
const s = this._clone(); s._borderTopBg = c; s._set.add('borderTopBg'); return s;
|
|
552
|
+
}
|
|
553
|
+
borderRightBackground(c: Color): Style {
|
|
554
|
+
const s = this._clone(); s._borderRightBg = c; s._set.add('borderRightBg'); return s;
|
|
555
|
+
}
|
|
556
|
+
borderBottomBackground(c: Color): Style {
|
|
557
|
+
const s = this._clone(); s._borderBottomBg = c; s._set.add('borderBottomBg'); return s;
|
|
558
|
+
}
|
|
559
|
+
borderLeftBackground(c: Color): Style {
|
|
560
|
+
const s = this._clone(); s._borderLeftBg = c; s._set.add('borderLeftBg'); return s;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
inline(v: boolean): Style {
|
|
564
|
+
const s = this._clone(); s._inline = v; s._set.add('inline'); return s;
|
|
565
|
+
}
|
|
566
|
+
tabWidth(n: number): Style {
|
|
567
|
+
const s = this._clone(); s._tabWidth = n <= -1 ? -1 : n; s._set.add('tabWidth'); return s;
|
|
568
|
+
}
|
|
569
|
+
transform(fn: (s: string) => string): Style {
|
|
570
|
+
const s = this._clone(); s._transform = fn; s._set.add('transform'); return s;
|
|
571
|
+
}
|
|
572
|
+
hyperlink(url: string, params?: string): Style {
|
|
573
|
+
const s = this._clone();
|
|
574
|
+
s._link = url; s._set.add('link');
|
|
575
|
+
if (params !== undefined) { s._linkParams = params; s._set.add('linkParams'); }
|
|
576
|
+
return s;
|
|
577
|
+
}
|
|
578
|
+
underlineSpaces(v: boolean): Style {
|
|
579
|
+
const s = this._clone(); s._underlineSpaces = v; s._set.add('underlineSpaces'); return s;
|
|
580
|
+
}
|
|
581
|
+
strikethroughSpaces(v: boolean): Style {
|
|
582
|
+
const s = this._clone(); s._strikethroughSpaces = v; s._set.add('strikethroughSpaces'); return s;
|
|
583
|
+
}
|
|
584
|
+
colorWhitespace(v: boolean): Style {
|
|
585
|
+
const s = this._clone(); s._colorWhitespace = v; s._set.add('colorWhitespace'); return s;
|
|
586
|
+
}
|
|
587
|
+
paddingChar(ch: string): Style {
|
|
588
|
+
const s = this._clone(); s._paddingChar = ch || ' '; s._set.add('paddingChar'); return s;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// -----------------------------------------------------------------------
|
|
592
|
+
// Copy — returns a full copy preserving ALL properties
|
|
593
|
+
// -----------------------------------------------------------------------
|
|
594
|
+
|
|
595
|
+
copy(): Style {
|
|
596
|
+
return this._clone();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// -----------------------------------------------------------------------
|
|
600
|
+
// Unset methods — remove a property from the set so it reverts to default
|
|
601
|
+
// -----------------------------------------------------------------------
|
|
602
|
+
|
|
603
|
+
unsetBold(): Style { const s = this._clone(); s._set.delete('bold'); s._bold = false; return s; }
|
|
604
|
+
unsetItalic(): Style { const s = this._clone(); s._set.delete('italic'); s._italic = false; return s; }
|
|
605
|
+
unsetUnderline(): Style { const s = this._clone(); s._set.delete('underline'); s._underlineStyle = 'none'; return s; }
|
|
606
|
+
unsetUnderlineSpaces(): Style { const s = this._clone(); s._set.delete('underlineSpaces'); s._underlineSpaces = false; return s; }
|
|
607
|
+
unsetStrikethrough(): Style { const s = this._clone(); s._set.delete('strikethrough'); s._strikethrough = false; return s; }
|
|
608
|
+
unsetStrikethroughSpaces(): Style { const s = this._clone(); s._set.delete('strikethroughSpaces'); s._strikethroughSpaces = false; return s; }
|
|
609
|
+
unsetReverse(): Style { const s = this._clone(); s._set.delete('reverse'); s._reverse = false; return s; }
|
|
610
|
+
unsetBlink(): Style { const s = this._clone(); s._set.delete('blink'); s._blink = false; return s; }
|
|
611
|
+
unsetFaint(): Style { const s = this._clone(); s._set.delete('faint'); s._faint = false; return s; }
|
|
612
|
+
unsetInline(): Style { const s = this._clone(); s._set.delete('inline'); s._inline = false; return s; }
|
|
613
|
+
unsetForeground(): Style { const s = this._clone(); s._set.delete('fg'); s._fg = null; return s; }
|
|
614
|
+
unsetBackground(): Style { const s = this._clone(); s._set.delete('bg'); s._bg = null; return s; }
|
|
615
|
+
unsetUnderlineColor(): Style { const s = this._clone(); s._set.delete('ulColor'); s._ulColor = null; return s; }
|
|
616
|
+
unsetWidth(): Style { const s = this._clone(); s._set.delete('width'); s._width = 0; return s; }
|
|
617
|
+
unsetHeight(): Style { const s = this._clone(); s._set.delete('height'); s._height = 0; return s; }
|
|
618
|
+
unsetMaxWidth(): Style { const s = this._clone(); s._set.delete('maxWidth'); s._maxWidth = 0; return s; }
|
|
619
|
+
unsetMaxHeight(): Style { const s = this._clone(); s._set.delete('maxHeight'); s._maxHeight = 0; return s; }
|
|
620
|
+
unsetPaddingTop(): Style { const s = this._clone(); s._set.delete('paddingTop'); s._paddingTop = 0; return s; }
|
|
621
|
+
unsetPaddingRight(): Style { const s = this._clone(); s._set.delete('paddingRight'); s._paddingRight = 0; return s; }
|
|
622
|
+
unsetPaddingBottom(): Style { const s = this._clone(); s._set.delete('paddingBottom'); s._paddingBottom = 0; return s; }
|
|
623
|
+
unsetPaddingLeft(): Style { const s = this._clone(); s._set.delete('paddingLeft'); s._paddingLeft = 0; return s; }
|
|
624
|
+
unsetPaddingChar(): Style { const s = this._clone(); s._set.delete('paddingChar'); s._paddingChar = ' '; return s; }
|
|
625
|
+
unsetMarginTop(): Style { const s = this._clone(); s._set.delete('marginTop'); s._marginTop = 0; return s; }
|
|
626
|
+
unsetMarginRight(): Style { const s = this._clone(); s._set.delete('marginRight'); s._marginRight = 0; return s; }
|
|
627
|
+
unsetMarginBottom(): Style { const s = this._clone(); s._set.delete('marginBottom'); s._marginBottom = 0; return s; }
|
|
628
|
+
unsetMarginLeft(): Style { const s = this._clone(); s._set.delete('marginLeft'); s._marginLeft = 0; return s; }
|
|
629
|
+
unsetBorderTop(): Style { const s = this._clone(); s._set.delete('borderTop'); s._borderTop = false; return s; }
|
|
630
|
+
unsetBorderRight(): Style { const s = this._clone(); s._set.delete('borderRight'); s._borderRight = false; return s; }
|
|
631
|
+
unsetBorderBottom(): Style { const s = this._clone(); s._set.delete('borderBottom'); s._borderBottom = false; return s; }
|
|
632
|
+
unsetBorderLeft(): Style { const s = this._clone(); s._set.delete('borderLeft'); s._borderLeft = false; return s; }
|
|
633
|
+
unsetBorderStyle(): Style { const s = this._clone(); s._set.delete('borderStyle'); s._borderStyle = noBorder; return s; }
|
|
634
|
+
unsetTabWidth(): Style { const s = this._clone(); s._set.delete('tabWidth'); s._tabWidth = TAB_WIDTH_DEFAULT; return s; }
|
|
635
|
+
unsetTransform(): Style { const s = this._clone(); s._set.delete('transform'); s._transform = null; return s; }
|
|
636
|
+
unsetHyperlink(): Style { const s = this._clone(); s._set.delete('link'); s._link = ''; s._set.delete('linkParams'); s._linkParams = ''; return s; }
|
|
637
|
+
unsetColorWhitespace(): Style { const s = this._clone(); s._set.delete('colorWhitespace'); s._colorWhitespace = false; return s; }
|
|
638
|
+
|
|
639
|
+
// -----------------------------------------------------------------------
|
|
640
|
+
// Getters
|
|
641
|
+
// -----------------------------------------------------------------------
|
|
642
|
+
|
|
643
|
+
getBold(): boolean { return this._set.has('bold') ? this._bold : false; }
|
|
644
|
+
getItalic(): boolean { return this._set.has('italic') ? this._italic : false; }
|
|
645
|
+
getUnderline(): boolean { return this._underlineStyle !== 'none'; }
|
|
646
|
+
getUnderlineStyle(): UnderlineStyle { return this._underlineStyle; }
|
|
647
|
+
getStrikethrough(): boolean { return this._set.has('strikethrough') ? this._strikethrough : false; }
|
|
648
|
+
getReverse(): boolean { return this._set.has('reverse') ? this._reverse : false; }
|
|
649
|
+
getBlink(): boolean { return this._set.has('blink') ? this._blink : false; }
|
|
650
|
+
getFaint(): boolean { return this._set.has('faint') ? this._faint : false; }
|
|
651
|
+
getForeground(): Color { return this._set.has('fg') ? this._fg : null; }
|
|
652
|
+
getBackground(): Color { return this._set.has('bg') ? this._bg : null; }
|
|
653
|
+
getUnderlineColor(): Color { return this._set.has('ulColor') ? this._ulColor : null; }
|
|
654
|
+
getWidth(): number { return this._set.has('width') ? this._width : 0; }
|
|
655
|
+
getHeight(): number { return this._set.has('height') ? this._height : 0; }
|
|
656
|
+
getMaxWidth(): number { return this._set.has('maxWidth') ? this._maxWidth : 0; }
|
|
657
|
+
getMaxHeight(): number { return this._set.has('maxHeight') ? this._maxHeight : 0; }
|
|
658
|
+
getAlignHorizontal(): Position { return this._set.has('alignH') ? this._alignH : Left; }
|
|
659
|
+
getAlignVertical(): Position { return this._set.has('alignV') ? this._alignV : Top; }
|
|
660
|
+
getInline(): boolean { return this._set.has('inline') ? this._inline : false; }
|
|
661
|
+
getTabWidth(): number { return this._set.has('tabWidth') ? this._tabWidth : TAB_WIDTH_DEFAULT; }
|
|
662
|
+
getUnderlineSpaces(): boolean { return this._set.has('underlineSpaces') ? this._underlineSpaces : false; }
|
|
663
|
+
getStrikethroughSpaces(): boolean { return this._set.has('strikethroughSpaces') ? this._strikethroughSpaces : false; }
|
|
664
|
+
getColorWhitespace(): boolean { return this._set.has('colorWhitespace') ? this._colorWhitespace : false; }
|
|
665
|
+
getTransform(): ((s: string) => string) | null { return this._set.has('transform') ? this._transform : null; }
|
|
666
|
+
getPaddingChar(): string { return this._set.has('paddingChar') ? this._paddingChar : ' '; }
|
|
667
|
+
getHyperlink(): { link: string; params: string } {
|
|
668
|
+
return { link: this._set.has('link') ? this._link : '', params: this._set.has('linkParams') ? this._linkParams : '' };
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
getPadding(): { top: number; right: number; bottom: number; left: number } {
|
|
672
|
+
return {
|
|
673
|
+
top: this._set.has('paddingTop') ? this._paddingTop : 0,
|
|
674
|
+
right: this._set.has('paddingRight') ? this._paddingRight : 0,
|
|
675
|
+
bottom: this._set.has('paddingBottom') ? this._paddingBottom : 0,
|
|
676
|
+
left: this._set.has('paddingLeft') ? this._paddingLeft : 0,
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
getPaddingTop(): number { return this._set.has('paddingTop') ? this._paddingTop : 0; }
|
|
680
|
+
getPaddingRight(): number { return this._set.has('paddingRight') ? this._paddingRight : 0; }
|
|
681
|
+
getPaddingBottom(): number { return this._set.has('paddingBottom') ? this._paddingBottom : 0; }
|
|
682
|
+
getPaddingLeft(): number { return this._set.has('paddingLeft') ? this._paddingLeft : 0; }
|
|
683
|
+
getHorizontalPadding(): number { return this.getPaddingLeft() + this.getPaddingRight(); }
|
|
684
|
+
getVerticalPadding(): number { return this.getPaddingTop() + this.getPaddingBottom(); }
|
|
685
|
+
|
|
686
|
+
getMargin(): { top: number; right: number; bottom: number; left: number } {
|
|
687
|
+
return {
|
|
688
|
+
top: this._set.has('marginTop') ? this._marginTop : 0,
|
|
689
|
+
right: this._set.has('marginRight') ? this._marginRight : 0,
|
|
690
|
+
bottom: this._set.has('marginBottom') ? this._marginBottom : 0,
|
|
691
|
+
left: this._set.has('marginLeft') ? this._marginLeft : 0,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
getMarginTop(): number { return this._set.has('marginTop') ? this._marginTop : 0; }
|
|
695
|
+
getMarginRight(): number { return this._set.has('marginRight') ? this._marginRight : 0; }
|
|
696
|
+
getMarginBottom(): number { return this._set.has('marginBottom') ? this._marginBottom : 0; }
|
|
697
|
+
getMarginLeft(): number { return this._set.has('marginLeft') ? this._marginLeft : 0; }
|
|
698
|
+
getHorizontalMargins(): number { return this.getMarginLeft() + this.getMarginRight(); }
|
|
699
|
+
getVerticalMargins(): number { return this.getMarginTop() + this.getMarginBottom(); }
|
|
700
|
+
|
|
701
|
+
getBorderStyle(): Border { return this._set.has('borderStyle') ? this._borderStyle : noBorder; }
|
|
702
|
+
getBorderTop(): boolean { return this._set.has('borderTop') ? this._borderTop : false; }
|
|
703
|
+
getBorderRight(): boolean { return this._set.has('borderRight') ? this._borderRight : false; }
|
|
704
|
+
getBorderBottom(): boolean { return this._set.has('borderBottom') ? this._borderBottom : false; }
|
|
705
|
+
getBorderLeft(): boolean { return this._set.has('borderLeft') ? this._borderLeft : false; }
|
|
706
|
+
|
|
707
|
+
/** True when border style is set but no individual side bools are set. */
|
|
708
|
+
private _isBorderStyleSetWithoutSides(): boolean {
|
|
709
|
+
const b = this.getBorderStyle();
|
|
710
|
+
const anySideSet = this._set.has('borderTop') || this._set.has('borderRight') ||
|
|
711
|
+
this._set.has('borderBottom') || this._set.has('borderLeft');
|
|
712
|
+
return !isNoBorder(b) && !anySideSet;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
getBorderTopSize(): number {
|
|
716
|
+
if (this._isBorderStyleSetWithoutSides()) return 1;
|
|
717
|
+
if (!this.getBorderTop()) return 0;
|
|
718
|
+
return getTopSize(this.getBorderStyle());
|
|
719
|
+
}
|
|
720
|
+
getBorderRightSize(): number {
|
|
721
|
+
if (this._isBorderStyleSetWithoutSides()) return 1;
|
|
722
|
+
if (!this.getBorderRight()) return 0;
|
|
723
|
+
return getRightSize(this.getBorderStyle());
|
|
724
|
+
}
|
|
725
|
+
getBorderBottomSize(): number {
|
|
726
|
+
if (this._isBorderStyleSetWithoutSides()) return 1;
|
|
727
|
+
if (!this.getBorderBottom()) return 0;
|
|
728
|
+
return getBottomSize(this.getBorderStyle());
|
|
729
|
+
}
|
|
730
|
+
getBorderLeftSize(): number {
|
|
731
|
+
if (this._isBorderStyleSetWithoutSides()) return 1;
|
|
732
|
+
if (!this.getBorderLeft()) return 0;
|
|
733
|
+
return getLeftSize(this.getBorderStyle());
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
getHorizontalBorderSize(): number { return this.getBorderLeftSize() + this.getBorderRightSize(); }
|
|
737
|
+
getVerticalBorderSize(): number { return this.getBorderTopSize() + this.getBorderBottomSize(); }
|
|
738
|
+
|
|
739
|
+
getHorizontalFrameSize(): number {
|
|
740
|
+
return this.getHorizontalMargins() + this.getHorizontalPadding() + this.getHorizontalBorderSize();
|
|
741
|
+
}
|
|
742
|
+
getVerticalFrameSize(): number {
|
|
743
|
+
return this.getVerticalMargins() + this.getVerticalPadding() + this.getVerticalBorderSize();
|
|
744
|
+
}
|
|
745
|
+
getFrameSize(): { x: number; y: number } {
|
|
746
|
+
return { x: this.getHorizontalFrameSize(), y: this.getVerticalFrameSize() };
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// -----------------------------------------------------------------------
|
|
750
|
+
// Inherit
|
|
751
|
+
// -----------------------------------------------------------------------
|
|
752
|
+
|
|
753
|
+
/** Copy explicitly-set values from `other` that are NOT set on this style. Margins/padding are not inherited. */
|
|
754
|
+
inherit(other: Style): Style {
|
|
755
|
+
const s = this._clone();
|
|
756
|
+
const skip = new Set(['paddingTop','paddingRight','paddingBottom','paddingLeft','marginTop','marginRight','marginBottom','marginLeft']);
|
|
757
|
+
for (const key of other._set) {
|
|
758
|
+
if (skip.has(key)) continue;
|
|
759
|
+
// If background is inherited, also inherit margin bg
|
|
760
|
+
if (key === 'bg' && !s._set.has('marginBg') && !other._set.has('marginBg')) {
|
|
761
|
+
s._marginBg = other._bg;
|
|
762
|
+
s._set.add('marginBg');
|
|
763
|
+
}
|
|
764
|
+
if (s._set.has(key)) continue;
|
|
765
|
+
// Copy value
|
|
766
|
+
(s as any)['_' + this._keyToField(key)] = (other as any)['_' + this._keyToField(key)];
|
|
767
|
+
s._set.add(key);
|
|
768
|
+
}
|
|
769
|
+
return s;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
private _keyToField(key: string): string {
|
|
773
|
+
const map: Record<string, string> = {
|
|
774
|
+
bold: 'bold', italic: 'italic', strikethrough: 'strikethrough',
|
|
775
|
+
reverse: 'reverse', blink: 'blink', faint: 'faint',
|
|
776
|
+
underlineSpaces: 'underlineSpaces', strikethroughSpaces: 'strikethroughSpaces',
|
|
777
|
+
colorWhitespace: 'colorWhitespace', underline: 'underlineStyle',
|
|
778
|
+
fg: 'fg', bg: 'bg', ulColor: 'ulColor',
|
|
779
|
+
width: 'width', height: 'height', maxWidth: 'maxWidth', maxHeight: 'maxHeight',
|
|
780
|
+
alignH: 'alignH', alignV: 'alignV',
|
|
781
|
+
paddingTop: 'paddingTop', paddingRight: 'paddingRight',
|
|
782
|
+
paddingBottom: 'paddingBottom', paddingLeft: 'paddingLeft',
|
|
783
|
+
marginTop: 'marginTop', marginRight: 'marginRight',
|
|
784
|
+
marginBottom: 'marginBottom', marginLeft: 'marginLeft', marginBg: 'marginBg',
|
|
785
|
+
borderStyle: 'borderStyle',
|
|
786
|
+
borderTop: 'borderTop', borderRight: 'borderRight',
|
|
787
|
+
borderBottom: 'borderBottom', borderLeft: 'borderLeft',
|
|
788
|
+
borderTopFg: 'borderTopFg', borderRightFg: 'borderRightFg',
|
|
789
|
+
borderBottomFg: 'borderBottomFg', borderLeftFg: 'borderLeftFg',
|
|
790
|
+
borderTopBg: 'borderTopBg', borderRightBg: 'borderRightBg',
|
|
791
|
+
borderBottomBg: 'borderBottomBg', borderLeftBg: 'borderLeftBg',
|
|
792
|
+
inline: 'inline', tabWidth: 'tabWidth', transform: 'transform',
|
|
793
|
+
link: 'link', linkParams: 'linkParams', paddingChar: 'paddingChar',
|
|
794
|
+
};
|
|
795
|
+
return map[key] || key;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// -----------------------------------------------------------------------
|
|
799
|
+
// Render
|
|
800
|
+
// -----------------------------------------------------------------------
|
|
801
|
+
|
|
802
|
+
/** Render the style applied to the given strings (joined with space). */
|
|
803
|
+
render(...strs: string[]): string {
|
|
804
|
+
if (this._value) strs = [this._value, ...strs];
|
|
805
|
+
let str = strs.join(' ');
|
|
806
|
+
|
|
807
|
+
const hasUnderline = this._underlineStyle !== 'none';
|
|
808
|
+
const isBold = this._set.has('bold') && this._bold;
|
|
809
|
+
const isItalic = this._set.has('italic') && this._italic;
|
|
810
|
+
const isStrikethrough = this._set.has('strikethrough') && this._strikethrough;
|
|
811
|
+
const isReverse = this._set.has('reverse') && this._reverse;
|
|
812
|
+
const isBlink = this._set.has('blink') && this._blink;
|
|
813
|
+
const isFaint = this._set.has('faint') && this._faint;
|
|
814
|
+
const fg = this._set.has('fg') ? parseColor(this._fg) : null;
|
|
815
|
+
const bg = this._set.has('bg') ? parseColor(this._bg) : null;
|
|
816
|
+
const ul = this._set.has('ulColor') ? parseColor(this._ulColor) : null;
|
|
817
|
+
|
|
818
|
+
const w = this._set.has('width') ? this._width : 0;
|
|
819
|
+
const h = this._set.has('height') ? this._height : 0;
|
|
820
|
+
const hAlign = this._set.has('alignH') ? this._alignH : Left;
|
|
821
|
+
const vAlign = this._set.has('alignV') ? this._alignV : Top;
|
|
822
|
+
const topPad = this._set.has('paddingTop') ? this._paddingTop : 0;
|
|
823
|
+
const rightPad = this._set.has('paddingRight') ? this._paddingRight : 0;
|
|
824
|
+
const bottomPad = this._set.has('paddingBottom') ? this._paddingBottom : 0;
|
|
825
|
+
const leftPad = this._set.has('paddingLeft') ? this._paddingLeft : 0;
|
|
826
|
+
const hBorderSize = this.getHorizontalBorderSize();
|
|
827
|
+
const vBorderSize = this.getVerticalBorderSize();
|
|
828
|
+
const colorWS = this._set.has('colorWhitespace') ? this._colorWhitespace : true;
|
|
829
|
+
const isInline = this._set.has('inline') ? this._inline : false;
|
|
830
|
+
const mw = this._set.has('maxWidth') ? this._maxWidth : 0;
|
|
831
|
+
const mh = this._set.has('maxHeight') ? this._maxHeight : 0;
|
|
832
|
+
const ulSpaces = (this._set.has('underlineSpaces') && this._underlineSpaces) || (hasUnderline && (!this._set.has('underlineSpaces') || this._underlineSpaces));
|
|
833
|
+
const stSpaces = (this._set.has('strikethroughSpaces') && this._strikethroughSpaces) || (isStrikethrough && (!this._set.has('strikethroughSpaces') || this._strikethroughSpaces));
|
|
834
|
+
const styleWhitespace = isReverse;
|
|
835
|
+
const useSpaceStyler = (hasUnderline && !ulSpaces) || (isStrikethrough && !stSpaces) || ulSpaces || stSpaces;
|
|
836
|
+
const transform = this._set.has('transform') ? this._transform : null;
|
|
837
|
+
const link = this._set.has('link') ? this._link : '';
|
|
838
|
+
const linkParams = this._set.has('linkParams') ? this._linkParams : '';
|
|
839
|
+
|
|
840
|
+
if (transform) str = transform(str);
|
|
841
|
+
|
|
842
|
+
// If no props set at all, just do tab conversion
|
|
843
|
+
if (this._set.size === 0) return this._maybeConvertTabs(str);
|
|
844
|
+
|
|
845
|
+
// Build main text style options
|
|
846
|
+
const teOpts: AnsiStyleOptions = {};
|
|
847
|
+
const teSpaceOpts: AnsiStyleOptions = {};
|
|
848
|
+
const teWSOpts: AnsiStyleOptions = {};
|
|
849
|
+
|
|
850
|
+
if (isBold) teOpts.bold = true;
|
|
851
|
+
if (isItalic) teOpts.italic = true;
|
|
852
|
+
if (hasUnderline) { teOpts.underline = true; teOpts.underlineStyle = this._underlineStyle; }
|
|
853
|
+
if (isReverse) { teOpts.reverse = true; teWSOpts.reverse = true; }
|
|
854
|
+
if (isBlink) teOpts.blink = true;
|
|
855
|
+
if (isFaint) teOpts.faint = true;
|
|
856
|
+
if (isStrikethrough) teOpts.strikethrough = true;
|
|
857
|
+
|
|
858
|
+
if (fg) {
|
|
859
|
+
teOpts.fg = fg;
|
|
860
|
+
if (styleWhitespace) teWSOpts.fg = fg;
|
|
861
|
+
if (useSpaceStyler) teSpaceOpts.fg = fg;
|
|
862
|
+
}
|
|
863
|
+
if (bg) {
|
|
864
|
+
teOpts.bg = bg;
|
|
865
|
+
if (colorWS) teWSOpts.bg = bg;
|
|
866
|
+
if (useSpaceStyler) teSpaceOpts.bg = bg;
|
|
867
|
+
}
|
|
868
|
+
if (ul) {
|
|
869
|
+
teOpts.ul = ul;
|
|
870
|
+
if (colorWS) teWSOpts.ul = ul;
|
|
871
|
+
if (useSpaceStyler) teSpaceOpts.ul = ul;
|
|
872
|
+
}
|
|
873
|
+
if (ulSpaces) teSpaceOpts.underline = true;
|
|
874
|
+
if (stSpaces) teSpaceOpts.strikethrough = true;
|
|
875
|
+
|
|
876
|
+
// Tab conversion
|
|
877
|
+
str = this._maybeConvertTabs(str);
|
|
878
|
+
str = str.replace(/\r\n/g, '\n');
|
|
879
|
+
|
|
880
|
+
// Strip newlines in inline mode
|
|
881
|
+
if (isInline) str = str.replace(/\n/g, '');
|
|
882
|
+
|
|
883
|
+
// Include borders in block size
|
|
884
|
+
let width = w - hBorderSize;
|
|
885
|
+
let height = h - vBorderSize;
|
|
886
|
+
|
|
887
|
+
// Word wrap
|
|
888
|
+
if (!isInline && width > 0) {
|
|
889
|
+
const wrapAt = width - leftPad - rightPad;
|
|
890
|
+
str = wordWrap(str, wrapAt);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// Render core text — apply ANSI styles line by line
|
|
894
|
+
{
|
|
895
|
+
const lines = str.split('\n');
|
|
896
|
+
const rendered: string[] = [];
|
|
897
|
+
for (const line of lines) {
|
|
898
|
+
if (useSpaceStyler) {
|
|
899
|
+
let buf = '';
|
|
900
|
+
for (const ch of line) {
|
|
901
|
+
if (ch === ' ' || ch === '\t') {
|
|
902
|
+
buf += styled(ch, teSpaceOpts);
|
|
903
|
+
} else {
|
|
904
|
+
buf += styled(ch, teOpts);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
rendered.push(buf);
|
|
908
|
+
} else {
|
|
909
|
+
rendered.push(line ? styled(line, teOpts) : line);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
str = rendered.join('\n');
|
|
913
|
+
|
|
914
|
+
if (link) {
|
|
915
|
+
str = setHyperlink(link, linkParams || undefined) + str + resetHyperlink();
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// Padding
|
|
920
|
+
if (!isInline) {
|
|
921
|
+
const wsStyle = (colorWS || styleWhitespace) ? teWSOpts : null;
|
|
922
|
+
const padCh = this._set.has('paddingChar') ? this._paddingChar : ' ';
|
|
923
|
+
if (leftPad > 0) str = padLeft(str, leftPad, wsStyle, padCh);
|
|
924
|
+
if (rightPad > 0) str = padRight(str, rightPad, wsStyle, padCh);
|
|
925
|
+
if (topPad > 0) str = '\n'.repeat(topPad) + str;
|
|
926
|
+
if (bottomPad > 0) str = str + '\n'.repeat(bottomPad);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Height
|
|
930
|
+
if (height > 0) str = alignTextVertical(str, vAlign, height);
|
|
931
|
+
|
|
932
|
+
// Horizontal alignment (also equalizes line widths)
|
|
933
|
+
{
|
|
934
|
+
const numLines = str.split('\n').length - 1;
|
|
935
|
+
if (numLines > 0 || width > 0) {
|
|
936
|
+
const wsStyle = (colorWS || styleWhitespace) ? teWSOpts : null;
|
|
937
|
+
str = alignTextHorizontal(str, hAlign, width, wsStyle);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// Borders and margins
|
|
942
|
+
if (!isInline) {
|
|
943
|
+
str = this._applyBorder(str);
|
|
944
|
+
str = this._applyMargins(str, isInline);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// MaxWidth truncation
|
|
948
|
+
if (mw > 0) {
|
|
949
|
+
str = str.split('\n').map(line => truncateStr(line, mw)).join('\n');
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// MaxHeight truncation
|
|
953
|
+
if (mh > 0) {
|
|
954
|
+
const lines = str.split('\n');
|
|
955
|
+
if (lines.length > mh) str = lines.slice(0, mh).join('\n');
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
return str;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// -----------------------------------------------------------------------
|
|
962
|
+
// Internal: tab conversion
|
|
963
|
+
// -----------------------------------------------------------------------
|
|
964
|
+
|
|
965
|
+
private _maybeConvertTabs(str: string): string {
|
|
966
|
+
const tw = this._set.has('tabWidth') ? this._tabWidth : TAB_WIDTH_DEFAULT;
|
|
967
|
+
if (tw === -1) return str;
|
|
968
|
+
if (tw === 0) return str.replace(/\t/g, '');
|
|
969
|
+
return str.replace(/\t/g, ' '.repeat(tw));
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// -----------------------------------------------------------------------
|
|
973
|
+
// Internal: border rendering
|
|
974
|
+
// -----------------------------------------------------------------------
|
|
975
|
+
|
|
976
|
+
private _applyBorder(str: string): string {
|
|
977
|
+
let borderDef = this.getBorderStyle();
|
|
978
|
+
let hasT = this.getBorderTop();
|
|
979
|
+
let hasR = this.getBorderRight();
|
|
980
|
+
let hasB = this.getBorderBottom();
|
|
981
|
+
let hasL = this.getBorderLeft();
|
|
982
|
+
|
|
983
|
+
// Default: if border style set but no sides specified, show all sides
|
|
984
|
+
if (this._isBorderStyleSetWithoutSides()) {
|
|
985
|
+
hasT = true; hasR = true; hasB = true; hasL = true;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
if (isNoBorder(borderDef) || (!hasT && !hasR && !hasB && !hasL)) return str;
|
|
989
|
+
|
|
990
|
+
// Clone border to mutate corners
|
|
991
|
+
borderDef = { ...borderDef };
|
|
992
|
+
|
|
993
|
+
const { lines, widest } = getLines(str);
|
|
994
|
+
let width = widest;
|
|
995
|
+
|
|
996
|
+
if (hasL) {
|
|
997
|
+
if (!borderDef.left) borderDef.left = ' ';
|
|
998
|
+
width += maxRuneWidth(borderDef.left);
|
|
999
|
+
}
|
|
1000
|
+
if (hasR) {
|
|
1001
|
+
if (!borderDef.right) borderDef.right = ' ';
|
|
1002
|
+
width += maxRuneWidth(borderDef.right);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// Fill empty corners with space if both adjacent sides exist
|
|
1006
|
+
if (hasT && hasL && !borderDef.topLeft) borderDef.topLeft = ' ';
|
|
1007
|
+
if (hasT && hasR && !borderDef.topRight) borderDef.topRight = ' ';
|
|
1008
|
+
if (hasB && hasL && !borderDef.bottomLeft) borderDef.bottomLeft = ' ';
|
|
1009
|
+
if (hasB && hasR && !borderDef.bottomRight) borderDef.bottomRight = ' ';
|
|
1010
|
+
|
|
1011
|
+
// Clear corners when adjacent side is off
|
|
1012
|
+
if (hasT) {
|
|
1013
|
+
if (!hasL && !hasR) { borderDef.topLeft = ''; borderDef.topRight = ''; }
|
|
1014
|
+
else if (!hasL) { borderDef.topLeft = ''; }
|
|
1015
|
+
else if (!hasR) { borderDef.topRight = ''; }
|
|
1016
|
+
}
|
|
1017
|
+
if (hasB) {
|
|
1018
|
+
if (!hasL && !hasR) { borderDef.bottomLeft = ''; borderDef.bottomRight = ''; }
|
|
1019
|
+
else if (!hasL) { borderDef.bottomLeft = ''; }
|
|
1020
|
+
else if (!hasR) { borderDef.bottomRight = ''; }
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// Limit corners to one rune
|
|
1024
|
+
borderDef.topLeft = getFirstRune(borderDef.topLeft);
|
|
1025
|
+
borderDef.topRight = getFirstRune(borderDef.topRight);
|
|
1026
|
+
borderDef.bottomLeft = getFirstRune(borderDef.bottomLeft);
|
|
1027
|
+
borderDef.bottomRight = getFirstRune(borderDef.bottomRight);
|
|
1028
|
+
|
|
1029
|
+
const topFg = this._set.has('borderTopFg') ? parseColor(this._borderTopFg) : null;
|
|
1030
|
+
const rightFg = this._set.has('borderRightFg') ? parseColor(this._borderRightFg) : null;
|
|
1031
|
+
const bottomFg = this._set.has('borderBottomFg') ? parseColor(this._borderBottomFg) : null;
|
|
1032
|
+
const leftFg = this._set.has('borderLeftFg') ? parseColor(this._borderLeftFg) : null;
|
|
1033
|
+
const topBg = this._set.has('borderTopBg') ? parseColor(this._borderTopBg) : null;
|
|
1034
|
+
const rightBg = this._set.has('borderRightBg') ? parseColor(this._borderRightBg) : null;
|
|
1035
|
+
const bottomBg = this._set.has('borderBottomBg') ? parseColor(this._borderBottomBg) : null;
|
|
1036
|
+
const leftBg = this._set.has('borderLeftBg') ? parseColor(this._borderLeftBg) : null;
|
|
1037
|
+
|
|
1038
|
+
let out = '';
|
|
1039
|
+
|
|
1040
|
+
// Top edge
|
|
1041
|
+
if (hasT) {
|
|
1042
|
+
const top = renderHorizontalEdge(borderDef.topLeft, borderDef.top, borderDef.topRight, width);
|
|
1043
|
+
out += styleBorderStr(top, topFg, topBg) + '\n';
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// Side edges
|
|
1047
|
+
const leftRunes = [...borderDef.left];
|
|
1048
|
+
const rightRunes = [...borderDef.right];
|
|
1049
|
+
let li = 0, ri = 0;
|
|
1050
|
+
|
|
1051
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1052
|
+
if (hasL) {
|
|
1053
|
+
const r = leftRunes[li % leftRunes.length];
|
|
1054
|
+
li++;
|
|
1055
|
+
out += styleBorderStr(r, leftFg, leftBg);
|
|
1056
|
+
}
|
|
1057
|
+
out += lines[i];
|
|
1058
|
+
if (hasR) {
|
|
1059
|
+
const r = rightRunes[ri % rightRunes.length];
|
|
1060
|
+
ri++;
|
|
1061
|
+
out += styleBorderStr(r, rightFg, rightBg);
|
|
1062
|
+
}
|
|
1063
|
+
if (i < lines.length - 1) out += '\n';
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// Bottom edge
|
|
1067
|
+
if (hasB) {
|
|
1068
|
+
const bottom = renderHorizontalEdge(borderDef.bottomLeft, borderDef.bottom, borderDef.bottomRight, width);
|
|
1069
|
+
out += '\n' + styleBorderStr(bottom, bottomFg, bottomBg);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
return out;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// -----------------------------------------------------------------------
|
|
1076
|
+
// Internal: margin rendering
|
|
1077
|
+
// -----------------------------------------------------------------------
|
|
1078
|
+
|
|
1079
|
+
private _applyMargins(str: string, isInline: boolean): string {
|
|
1080
|
+
const topM = this._set.has('marginTop') ? this._marginTop : 0;
|
|
1081
|
+
const rightM = this._set.has('marginRight') ? this._marginRight : 0;
|
|
1082
|
+
const bottomM = this._set.has('marginBottom') ? this._marginBottom : 0;
|
|
1083
|
+
const leftM = this._set.has('marginLeft') ? this._marginLeft : 0;
|
|
1084
|
+
|
|
1085
|
+
const marginBg = this._set.has('marginBg') ? parseColor(this._marginBg) : null;
|
|
1086
|
+
const marginStyle: AnsiStyleOptions | null = marginBg ? { bg: marginBg } : null;
|
|
1087
|
+
|
|
1088
|
+
if (leftM > 0) str = padLeft(str, leftM, marginStyle);
|
|
1089
|
+
if (rightM > 0) str = padRight(str, rightM, marginStyle);
|
|
1090
|
+
|
|
1091
|
+
if (!isInline) {
|
|
1092
|
+
const { widest: totalWidth } = getLines(str);
|
|
1093
|
+
const blankLine = marginStyle ? styled(' '.repeat(totalWidth), marginStyle) : ' '.repeat(totalWidth);
|
|
1094
|
+
|
|
1095
|
+
if (topM > 0) {
|
|
1096
|
+
str = (blankLine + '\n').repeat(topM) + str;
|
|
1097
|
+
}
|
|
1098
|
+
if (bottomM > 0) {
|
|
1099
|
+
str = str + ('\n' + blankLine).repeat(bottomM);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
return str;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// -----------------------------------------------------------------------
|
|
1107
|
+
// toString
|
|
1108
|
+
// -----------------------------------------------------------------------
|
|
1109
|
+
|
|
1110
|
+
toString(): string {
|
|
1111
|
+
return this.render();
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// ---------------------------------------------------------------------------
|
|
1116
|
+
// Module-level helper: style a border string with fg/bg colors
|
|
1117
|
+
// ---------------------------------------------------------------------------
|
|
1118
|
+
|
|
1119
|
+
function styleBorderStr(border: string, fg: ColorValue | null, bg: ColorValue | null): string {
|
|
1120
|
+
if (!fg && !bg) return border;
|
|
1121
|
+
return styled(border, { fg, bg });
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// ---------------------------------------------------------------------------
|
|
1125
|
+
// Factory
|
|
1126
|
+
// ---------------------------------------------------------------------------
|
|
1127
|
+
|
|
1128
|
+
/** Create a new empty Style. */
|
|
1129
|
+
export function newStyle(): Style {
|
|
1130
|
+
return new Style();
|
|
1131
|
+
}
|