@goast/core 0.1.0 → 0.2.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/cjs/index.js +1 -0
- package/cjs/lib/ast/index.js +4 -0
- package/cjs/lib/ast/node.js +27 -0
- package/cjs/lib/parse/deref-proxy.js +9 -3
- package/cjs/lib/parse/parser.js +1 -1
- package/cjs/lib/transform/transform-endpoint.js +1 -1
- package/cjs/lib/transform/transform-schema.js +10 -5
- package/cjs/lib/utils/array.utils.js +11 -0
- package/cjs/lib/utils/class.utils.js +33 -0
- package/cjs/lib/utils/common.utils.js +75 -1
- package/cjs/lib/utils/error.utils.js +7 -0
- package/cjs/lib/utils/index.js +4 -0
- package/cjs/lib/utils/object.utils.js +6 -2
- package/cjs/lib/utils/schema.utils.js +2 -1
- package/cjs/lib/utils/source-builder.js +171 -81
- package/cjs/lib/utils/string-builder/index.js +8 -0
- package/cjs/lib/utils/string-builder/options.js +7 -0
- package/cjs/lib/utils/string-builder/string-builder.js +142 -0
- package/cjs/lib/utils/string-builder/utils.js +38 -0
- package/cjs/lib/utils/string.utils.js +123 -107
- package/cjs/lib/utils/type.utils.js +9 -0
- package/esm/index.js +1 -0
- package/esm/lib/ast/index.js +1 -0
- package/esm/lib/ast/node.js +23 -0
- package/esm/lib/parse/deref-proxy.js +9 -3
- package/esm/lib/parse/parser.js +1 -1
- package/esm/lib/transform/transform-endpoint.js +1 -1
- package/esm/lib/transform/transform-schema.js +10 -5
- package/esm/lib/utils/array.utils.js +7 -0
- package/esm/lib/utils/class.utils.js +27 -0
- package/esm/lib/utils/common.utils.js +64 -0
- package/esm/lib/utils/error.utils.js +3 -0
- package/esm/lib/utils/index.js +4 -0
- package/esm/lib/utils/object.utils.js +6 -2
- package/esm/lib/utils/schema.utils.js +2 -1
- package/esm/lib/utils/source-builder.js +170 -80
- package/esm/lib/utils/string-builder/index.js +3 -0
- package/esm/lib/utils/string-builder/options.js +4 -0
- package/esm/lib/utils/string-builder/string-builder.js +138 -0
- package/esm/lib/utils/string-builder/utils.js +30 -0
- package/esm/lib/utils/string.utils.js +111 -105
- package/esm/lib/utils/type.utils.js +6 -1
- package/package.json +5 -5
- package/types/index.d.ts +1 -0
- package/types/lib/ast/index.d.ts +1 -0
- package/types/lib/ast/node.d.ts +14 -0
- package/types/lib/transform/api-types.d.ts +3 -1
- package/types/lib/utils/array.utils.d.ts +1 -0
- package/types/lib/utils/class.utils.d.ts +7 -0
- package/types/lib/utils/common.utils.d.ts +14 -2
- package/types/lib/utils/error.utils.d.ts +1 -0
- package/types/lib/utils/index.d.ts +4 -0
- package/types/lib/utils/object.utils.d.ts +1 -1
- package/types/lib/utils/source-builder.d.ts +55 -37
- package/types/lib/utils/string-builder/index.d.ts +3 -0
- package/types/lib/utils/string-builder/options.d.ts +8 -0
- package/types/lib/utils/string-builder/string-builder.d.ts +72 -0
- package/types/lib/utils/string-builder/utils.d.ts +21 -0
- package/types/lib/utils/string.utils.d.ts +20 -66
- package/types/lib/utils/type.utils.d.ts +43 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { EOL } from 'os';
|
|
2
|
+
import { isNullish } from './common.utils';
|
|
2
3
|
import { evalCondition } from './condition';
|
|
3
|
-
import { StringBuilder } from './string
|
|
4
|
+
import { StringBuilder } from './string-builder';
|
|
5
|
+
import { removeStr, trimEnd } from './string.utils';
|
|
4
6
|
export const defaultSourceBuilderOptions = {
|
|
5
7
|
indent: { type: 'spaces', count: 2 },
|
|
6
8
|
newLine: EOL,
|
|
7
|
-
charsTreatedAsEmptyLine: ['{'],
|
|
8
9
|
};
|
|
9
10
|
/**
|
|
10
11
|
* Represents an in-memory source file.
|
|
@@ -22,16 +23,11 @@ export class SourceBuilder extends StringBuilder {
|
|
|
22
23
|
*/
|
|
23
24
|
constructor(options) {
|
|
24
25
|
super(options);
|
|
25
|
-
this._linePrefix = '';
|
|
26
26
|
this._isLineIndented = false;
|
|
27
27
|
this._isLastLineEmpty = true;
|
|
28
28
|
this._isCurrentLineEmpty = true;
|
|
29
|
-
|
|
30
|
-
* Gets or sets the current indentation level.
|
|
31
|
-
*/
|
|
32
|
-
this.currentIndentLevel = 0;
|
|
29
|
+
this._linePrefixNodes = [];
|
|
33
30
|
this.__options = Object.assign(Object.assign({}, defaultSourceBuilderOptions), options);
|
|
34
|
-
this._emptyLineCharRegex = new RegExp(`[\\s${this.__options.charsTreatedAsEmptyLine.join('')}]`);
|
|
35
31
|
this._indentString = this.__options.indent.type === 'tabs' ? '\t' : ' '.repeat(this.__options.indent.count);
|
|
36
32
|
}
|
|
37
33
|
/**
|
|
@@ -53,61 +49,66 @@ export class SourceBuilder extends StringBuilder {
|
|
|
53
49
|
*/
|
|
54
50
|
static build(buildAction, options) {
|
|
55
51
|
const builder = new SourceBuilder(options);
|
|
56
|
-
buildAction
|
|
52
|
+
builder.append(buildAction);
|
|
57
53
|
return builder.toString();
|
|
58
54
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!str)
|
|
67
|
-
continue;
|
|
68
|
-
if (typeof str === 'function') {
|
|
69
|
-
str(this);
|
|
70
|
-
continue;
|
|
55
|
+
appendSingle(value) {
|
|
56
|
+
var _a;
|
|
57
|
+
if (isNullish(value))
|
|
58
|
+
return;
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
for (const part of value) {
|
|
61
|
+
this.appendSingle(part);
|
|
71
62
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === 'function') {
|
|
66
|
+
value(this);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
70
|
+
value = value.toString();
|
|
71
|
+
}
|
|
72
|
+
if (typeof value === 'object' && value !== null && '__type' in value && value.__type === 'append-value-group') {
|
|
73
|
+
this.forEach(value.values, (builder, part) => builder.append(part), { separator: (_a = value.separator) !== null && _a !== void 0 ? _a : undefined });
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (typeof value !== 'string') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let lineStartIndex = 0;
|
|
80
|
+
for (let i = 0; i < value.length; i++) {
|
|
81
|
+
if (value[i] === '\r')
|
|
82
|
+
continue;
|
|
83
|
+
if (value[i] === '\n') {
|
|
84
|
+
let lineLength = i - lineStartIndex;
|
|
85
|
+
for (let j = i; j > 0 && value[j - 1] === '\r'; j--) {
|
|
86
|
+
lineLength--;
|
|
87
|
+
}
|
|
88
|
+
if (lineLength > 0) {
|
|
89
|
+
if (!this._isLineIndented) {
|
|
90
90
|
this.appendIndent();
|
|
91
|
-
this._isLineIndented = true;
|
|
92
|
-
this._isCurrentLineEmpty = false;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
this._isLineIndented = false;
|
|
96
|
-
this._isCurrentLineEmpty = true;
|
|
97
91
|
}
|
|
98
|
-
lineStartIndex
|
|
92
|
+
this.str += removeStr(value.substring(lineStartIndex, i), '\r');
|
|
99
93
|
}
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
this._isLastLineEmpty = this._isCurrentLineEmpty;
|
|
95
|
+
if (this._isCurrentLineEmpty && this._linePrefixNodes.some((x) => x.kind !== 'indent')) {
|
|
96
|
+
this.appendIndent();
|
|
102
97
|
}
|
|
98
|
+
this.str = trimEnd(this.str, false) + '\n';
|
|
99
|
+
this._isLineIndented = false;
|
|
100
|
+
this._isCurrentLineEmpty = true;
|
|
101
|
+
lineStartIndex = i + 1;
|
|
103
102
|
}
|
|
104
|
-
if (
|
|
105
|
-
this.
|
|
106
|
-
this._isLineIndented = true;
|
|
103
|
+
if (value[i] !== '\r' && value[i] !== '\n' && value[i] !== ' ' && value[i] !== '\t') {
|
|
104
|
+
this._isCurrentLineEmpty = false;
|
|
107
105
|
}
|
|
108
|
-
super.append(str.substring(lineStartIndex).replace(/\r/g, ''));
|
|
109
106
|
}
|
|
110
|
-
|
|
107
|
+
if (!this._isLineIndented && lineStartIndex < value.length) {
|
|
108
|
+
this.appendIndent();
|
|
109
|
+
this._isLineIndented = true;
|
|
110
|
+
}
|
|
111
|
+
this.str += removeStr(value.substring(lineStartIndex), '\r');
|
|
111
112
|
}
|
|
112
113
|
/**
|
|
113
114
|
* Appends one or more strings to the end of the current SourceBuilder if the specified condition is true.
|
|
@@ -116,7 +117,10 @@ export class SourceBuilder extends StringBuilder {
|
|
|
116
117
|
* @returns The current SourceBuilder.
|
|
117
118
|
*/
|
|
118
119
|
appendIf(condition, ...value) {
|
|
119
|
-
|
|
120
|
+
if (evalCondition(condition)) {
|
|
121
|
+
return this.append(...value);
|
|
122
|
+
}
|
|
123
|
+
return this;
|
|
120
124
|
}
|
|
121
125
|
/**
|
|
122
126
|
* Appends one or more strings to the end of the current SourceBuilder, followed by a line terminator.
|
|
@@ -133,7 +137,10 @@ export class SourceBuilder extends StringBuilder {
|
|
|
133
137
|
* @returns The current SourceBuilder.
|
|
134
138
|
*/
|
|
135
139
|
appendLineIf(condition, ...value) {
|
|
136
|
-
|
|
140
|
+
if (evalCondition(condition)) {
|
|
141
|
+
return this.appendLine(...value);
|
|
142
|
+
}
|
|
143
|
+
return this;
|
|
137
144
|
}
|
|
138
145
|
/**
|
|
139
146
|
* Appends the specified values to this source builder with the specified line prefix.
|
|
@@ -142,13 +149,12 @@ export class SourceBuilder extends StringBuilder {
|
|
|
142
149
|
* @returns {SourceBuilder} This source builder instance.
|
|
143
150
|
*/
|
|
144
151
|
appendWithLinePrefix(prefix, ...value) {
|
|
145
|
-
|
|
146
|
-
this._linePrefix += prefix;
|
|
152
|
+
this._linePrefixNodes.push({ chars: prefix, kind: 'prefix' });
|
|
147
153
|
try {
|
|
148
154
|
this.append(...value);
|
|
149
155
|
}
|
|
150
156
|
finally {
|
|
151
|
-
this.
|
|
157
|
+
this._linePrefixNodes.pop();
|
|
152
158
|
}
|
|
153
159
|
return this;
|
|
154
160
|
}
|
|
@@ -168,7 +174,10 @@ export class SourceBuilder extends StringBuilder {
|
|
|
168
174
|
* @returns The current SourceBuilder.
|
|
169
175
|
*/
|
|
170
176
|
prependIf(condition, ...value) {
|
|
171
|
-
|
|
177
|
+
if (evalCondition(condition)) {
|
|
178
|
+
this.prepend(...value);
|
|
179
|
+
}
|
|
180
|
+
return this;
|
|
172
181
|
}
|
|
173
182
|
/**
|
|
174
183
|
* Prepends one or more strings to the beginning of the current SourceBuilder, followed by a line terminator, if the specified condition is true.
|
|
@@ -177,10 +186,13 @@ export class SourceBuilder extends StringBuilder {
|
|
|
177
186
|
* @returns The current SourceBuilder.
|
|
178
187
|
*/
|
|
179
188
|
prependLineIf(condition, ...value) {
|
|
180
|
-
|
|
189
|
+
if (evalCondition(condition)) {
|
|
190
|
+
this.prependLine(...value);
|
|
191
|
+
}
|
|
192
|
+
return this;
|
|
181
193
|
}
|
|
182
194
|
/**
|
|
183
|
-
* Ensures that the current line is empty or consists only of whitespace characters.
|
|
195
|
+
* Ensures that the current line and the one before is empty or consists only of whitespace characters.
|
|
184
196
|
* @returns A reference to this instance.
|
|
185
197
|
*/
|
|
186
198
|
ensurePreviousLineEmpty() {
|
|
@@ -202,6 +214,23 @@ export class SourceBuilder extends StringBuilder {
|
|
|
202
214
|
}
|
|
203
215
|
return this;
|
|
204
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Pretends that the current line and the one before is empty or consists only of whitespace characters.
|
|
219
|
+
* @returns A reference to this instance.
|
|
220
|
+
*/
|
|
221
|
+
pretendPreviousLineEmpty() {
|
|
222
|
+
this._isLastLineEmpty = true;
|
|
223
|
+
this._isCurrentLineEmpty = true;
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Pretends that the current line is empty or consists only of whitespace characters.
|
|
228
|
+
* @returns A reference to this instance.
|
|
229
|
+
*/
|
|
230
|
+
pretendCurrentLineEmpty() {
|
|
231
|
+
this._isCurrentLineEmpty = true;
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
205
234
|
/**
|
|
206
235
|
* Inserts specified content if the specified condition is true.
|
|
207
236
|
* @param condition The condition to check before inserting content.
|
|
@@ -210,11 +239,20 @@ export class SourceBuilder extends StringBuilder {
|
|
|
210
239
|
* @returns A reference to this instance.
|
|
211
240
|
*/
|
|
212
241
|
if(condition, builderFn, elseBuilderFn) {
|
|
213
|
-
|
|
214
|
-
|
|
242
|
+
return evalCondition(condition) ? this.append(builderFn) : this.append(elseBuilderFn);
|
|
243
|
+
}
|
|
244
|
+
switch(value, cases, defaultBuilderFn, equals) {
|
|
245
|
+
var _a;
|
|
246
|
+
if ((typeof value === 'string' || typeof value === 'number') && !Array.isArray(cases)) {
|
|
247
|
+
return this.append((_a = cases[value]) !== null && _a !== void 0 ? _a : defaultBuilderFn);
|
|
215
248
|
}
|
|
216
|
-
else {
|
|
217
|
-
|
|
249
|
+
else if (Array.isArray(cases)) {
|
|
250
|
+
for (const c of cases) {
|
|
251
|
+
if (equals ? equals(value, c.case) : value === c.case) {
|
|
252
|
+
return this.append(c.value);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return this.append(defaultBuilderFn);
|
|
218
256
|
}
|
|
219
257
|
return this;
|
|
220
258
|
}
|
|
@@ -225,12 +263,12 @@ export class SourceBuilder extends StringBuilder {
|
|
|
225
263
|
* @returns A reference to this instance.
|
|
226
264
|
*/
|
|
227
265
|
indent(value) {
|
|
228
|
-
this.
|
|
266
|
+
this._linePrefixNodes.push({ chars: this._indentString, kind: 'indent' });
|
|
229
267
|
try {
|
|
230
268
|
this.append(value);
|
|
231
269
|
}
|
|
232
270
|
finally {
|
|
233
|
-
this.
|
|
271
|
+
this._linePrefixNodes.pop();
|
|
234
272
|
}
|
|
235
273
|
return this;
|
|
236
274
|
}
|
|
@@ -241,7 +279,7 @@ export class SourceBuilder extends StringBuilder {
|
|
|
241
279
|
* @returns A reference to this instance.
|
|
242
280
|
*/
|
|
243
281
|
indentIf(condition, value) {
|
|
244
|
-
return
|
|
282
|
+
return evalCondition(condition) ? this.indent(value) : this.append(value);
|
|
245
283
|
}
|
|
246
284
|
/**
|
|
247
285
|
* Adds parentheses around the specified content.
|
|
@@ -251,11 +289,28 @@ export class SourceBuilder extends StringBuilder {
|
|
|
251
289
|
* @returns A reference to this instance.
|
|
252
290
|
*/
|
|
253
291
|
parenthesize(brackets, value, options) {
|
|
254
|
-
var _a, _b, _c, _d;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
292
|
+
var _a, _b, _c, _d, _e, _f;
|
|
293
|
+
const multiline = (_a = options === null || options === void 0 ? void 0 : options.multiline) !== null && _a !== void 0 ? _a : false;
|
|
294
|
+
const indent = (_b = options === null || options === void 0 ? void 0 : options.indent) !== null && _b !== void 0 ? _b : true;
|
|
295
|
+
const pretendEmpty = (_c = options === null || options === void 0 ? void 0 : options.pretendEmpty) !== null && _c !== void 0 ? _c : true;
|
|
296
|
+
if (multiline) {
|
|
297
|
+
this.appendLine((_d = brackets[0]) !== null && _d !== void 0 ? _d : '');
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
this.append((_e = brackets[0]) !== null && _e !== void 0 ? _e : '');
|
|
301
|
+
}
|
|
302
|
+
if (pretendEmpty)
|
|
303
|
+
this.pretendPreviousLineEmpty();
|
|
304
|
+
if (indent !== false) {
|
|
305
|
+
this.indent(value);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
this.append(value);
|
|
309
|
+
}
|
|
310
|
+
if (multiline)
|
|
311
|
+
this.ensureCurrentLineEmpty();
|
|
312
|
+
this.append((_f = brackets[1]) !== null && _f !== void 0 ? _f : '');
|
|
313
|
+
return this;
|
|
259
314
|
}
|
|
260
315
|
/**
|
|
261
316
|
* Adds parentheses around the specified content if the specified condition is true.
|
|
@@ -266,7 +321,15 @@ export class SourceBuilder extends StringBuilder {
|
|
|
266
321
|
* @returns A reference to this instance.
|
|
267
322
|
*/
|
|
268
323
|
parenthesizeIf(condition, brackets, value, options) {
|
|
269
|
-
|
|
324
|
+
if (evalCondition(condition)) {
|
|
325
|
+
return this.parenthesize(brackets, value, options);
|
|
326
|
+
}
|
|
327
|
+
else if (options === null || options === void 0 ? void 0 : options.indent) {
|
|
328
|
+
return this.indent(value);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
return this.append(value);
|
|
332
|
+
}
|
|
270
333
|
}
|
|
271
334
|
/**
|
|
272
335
|
* Adds content for each item in the specified array.
|
|
@@ -304,18 +367,45 @@ export class SourceBuilder extends StringBuilder {
|
|
|
304
367
|
return this;
|
|
305
368
|
}
|
|
306
369
|
forEachIf(condition, items, builderFn, options) {
|
|
307
|
-
|
|
370
|
+
if (evalCondition(condition)) {
|
|
371
|
+
return this.forEach(items, builderFn, options);
|
|
372
|
+
}
|
|
373
|
+
return this;
|
|
308
374
|
}
|
|
309
375
|
appendSeparated(items, separator) {
|
|
310
376
|
return this.forEach(items, (builder, item) => builder.append(item), { separator });
|
|
311
377
|
}
|
|
312
378
|
appendSeparatedIf(condition, items, separator) {
|
|
313
|
-
|
|
379
|
+
if (evalCondition(condition)) {
|
|
380
|
+
return this.appendSeparated(items, separator);
|
|
381
|
+
}
|
|
382
|
+
return this;
|
|
314
383
|
}
|
|
315
384
|
appendIndent() {
|
|
316
|
-
|
|
317
|
-
if (this._linePrefix) {
|
|
318
|
-
super.append(this._linePrefix);
|
|
319
|
-
}
|
|
385
|
+
this.str += this._linePrefixNodes.map((n) => n.chars).join('');
|
|
320
386
|
}
|
|
321
387
|
}
|
|
388
|
+
function _builderTemplate(template, ...substitutions) {
|
|
389
|
+
return (b) => {
|
|
390
|
+
var _a, _b;
|
|
391
|
+
let lastLine = undefined;
|
|
392
|
+
for (let i = template.length - 1; i >= 0; i--) {
|
|
393
|
+
if (template[i].includes('\n')) {
|
|
394
|
+
lastLine = template[i];
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const indent = (_b = (_a = lastLine === null || lastLine === void 0 ? void 0 : lastLine.match(/\n( *).*$/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : '';
|
|
399
|
+
const regex = new RegExp(`\\n {0,${indent.length}}`, 'g');
|
|
400
|
+
for (let i = 0; i < template.length; i++) {
|
|
401
|
+
b.append(template[i].replace(regex, '\n'));
|
|
402
|
+
if (i < substitutions.length)
|
|
403
|
+
b.append(substitutions[i]);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
export const builderTemplate = Object.assign(_builderTemplate, {
|
|
408
|
+
indent: (template, ...substitutions) => {
|
|
409
|
+
return (b) => b.indent(_builderTemplate(template, ...substitutions));
|
|
410
|
+
},
|
|
411
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { defaultStringBuilderOptions } from './options';
|
|
2
|
+
import { isNullish } from '../common.utils';
|
|
3
|
+
export const AdditionalAppendsSymbol = Symbol('AdditionalAppends');
|
|
4
|
+
/**
|
|
5
|
+
* Represents a mutable string of characters.
|
|
6
|
+
*/
|
|
7
|
+
export class StringBuilder {
|
|
8
|
+
[AdditionalAppendsSymbol](_) {
|
|
9
|
+
throw new Error('This method should never be called.');
|
|
10
|
+
}
|
|
11
|
+
get options() {
|
|
12
|
+
return this._options;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Initializes a new instance of the StringBuilder class.
|
|
16
|
+
* @param options The options.
|
|
17
|
+
*/
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.str = '';
|
|
20
|
+
this._options = Object.assign(Object.assign({}, defaultStringBuilderOptions), options);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new StringBuilder instance and appends the specified string to it.
|
|
24
|
+
* @param str The string to append.
|
|
25
|
+
* @param options The options.
|
|
26
|
+
* @returns A new StringBuilder instance.
|
|
27
|
+
*/
|
|
28
|
+
static fromString(str, options) {
|
|
29
|
+
const builder = new StringBuilder(options);
|
|
30
|
+
builder.append(str);
|
|
31
|
+
return builder;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Builds a string using a StringBuilder build action.
|
|
35
|
+
* @param buildAction The build action to perform on the StringBuilder instance.
|
|
36
|
+
* @param options The options for the StringBuilder instance.
|
|
37
|
+
* @returns The built string.
|
|
38
|
+
*/
|
|
39
|
+
static build(buildAction, options) {
|
|
40
|
+
const builder = new StringBuilder(options);
|
|
41
|
+
builder.append(buildAction);
|
|
42
|
+
return builder.toString();
|
|
43
|
+
}
|
|
44
|
+
appendSingle(value) {
|
|
45
|
+
if (isNullish(value))
|
|
46
|
+
return;
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
for (const part of value) {
|
|
49
|
+
this.appendSingle(part);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (typeof value === 'string') {
|
|
53
|
+
this.str += value;
|
|
54
|
+
}
|
|
55
|
+
else if (typeof value === 'number' || typeof value === 'boolean') {
|
|
56
|
+
this.str += value.toString();
|
|
57
|
+
}
|
|
58
|
+
else if (typeof value === 'function') {
|
|
59
|
+
value(this);
|
|
60
|
+
}
|
|
61
|
+
else if (typeof value === 'object' &&
|
|
62
|
+
value !== null &&
|
|
63
|
+
'__type' in value &&
|
|
64
|
+
value.__type === 'append-value-group') {
|
|
65
|
+
let isFirst = true;
|
|
66
|
+
for (const part of value.values) {
|
|
67
|
+
if (!isFirst && value.separator) {
|
|
68
|
+
this.append(value.separator);
|
|
69
|
+
}
|
|
70
|
+
this.appendSingle(part);
|
|
71
|
+
isFirst = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Appends one or more strings to the end of the current StringBuilder.
|
|
77
|
+
* @param value The string(s) to append.
|
|
78
|
+
* @returns The current StringBuilder.
|
|
79
|
+
*/
|
|
80
|
+
append(...value) {
|
|
81
|
+
for (const part of value) {
|
|
82
|
+
this.appendSingle(part);
|
|
83
|
+
}
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Appends one or more strings to the end of the current StringBuilder, followed by a line terminator.
|
|
88
|
+
* @param value
|
|
89
|
+
* @returns
|
|
90
|
+
*/
|
|
91
|
+
appendLine(...value) {
|
|
92
|
+
return this.append(...value, '\n');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Prepends one or more strings to the beginning of the current StringBuilder.
|
|
96
|
+
* @param value The string(s) to prepend.
|
|
97
|
+
* @returns The current StringBuilder.
|
|
98
|
+
*/
|
|
99
|
+
prepend(...value) {
|
|
100
|
+
for (const part of value.reverse()) {
|
|
101
|
+
if (isNullish(part))
|
|
102
|
+
continue;
|
|
103
|
+
if (typeof part === 'function') {
|
|
104
|
+
const builder = new StringBuilder(this.options);
|
|
105
|
+
part(builder);
|
|
106
|
+
this.str = builder.str + this.str;
|
|
107
|
+
}
|
|
108
|
+
else if (typeof part === 'string') {
|
|
109
|
+
this.str = part + this.str;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.str = part.toString() + this.str;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Prepends one or more strings to the beginning of the current StringBuilder, followed by a line terminator.
|
|
119
|
+
* @param value The string(s) to prepend.
|
|
120
|
+
* @returns The current StringBuilder.
|
|
121
|
+
*/
|
|
122
|
+
prependLine(...value) {
|
|
123
|
+
return this.prepend(...value, '\n');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Converts the value of this instance to a string.
|
|
127
|
+
* @returns A string whose value is the same as this instance.
|
|
128
|
+
*/
|
|
129
|
+
toString() {
|
|
130
|
+
return this.str.replace(/\r?\n/g, this._options.newLine);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Removes all characters from the current StringBuilder.
|
|
134
|
+
*/
|
|
135
|
+
clear() {
|
|
136
|
+
this.str = '';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { concatSingleOrMultiple, notNullish } from '../common.utils';
|
|
2
|
+
export function basicAppendValueGroup(values, separator) {
|
|
3
|
+
var _a;
|
|
4
|
+
return {
|
|
5
|
+
__type: 'append-value-group',
|
|
6
|
+
values: (_a = values === null || values === void 0 ? void 0 : values.filter(notNullish)) !== null && _a !== void 0 ? _a : [],
|
|
7
|
+
separator: separator !== null && separator !== void 0 ? separator : null,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function appendValueGroup(values, separator) {
|
|
11
|
+
var _a;
|
|
12
|
+
return {
|
|
13
|
+
__type: 'append-value-group',
|
|
14
|
+
values: (_a = values === null || values === void 0 ? void 0 : values.filter(notNullish)) !== null && _a !== void 0 ? _a : [],
|
|
15
|
+
separator: separator !== null && separator !== void 0 ? separator : null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function isAppendValue(value) {
|
|
19
|
+
return (typeof value === 'string' ||
|
|
20
|
+
typeof value === 'number' ||
|
|
21
|
+
typeof value === 'boolean' ||
|
|
22
|
+
typeof value === 'function' ||
|
|
23
|
+
isAppendValueGroup(value));
|
|
24
|
+
}
|
|
25
|
+
export function isAppendValueGroup(value) {
|
|
26
|
+
return typeof value === 'object' && value !== null && '__type' in value && value.__type === 'append-value-group';
|
|
27
|
+
}
|
|
28
|
+
export function concatAppendValues(...values) {
|
|
29
|
+
return concatSingleOrMultiple(...values);
|
|
30
|
+
}
|