@goast/core 0.5.2 → 0.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +67 -67
  3. package/esm/src/parse/parser.js +2 -1
  4. package/package.json +1 -1
  5. package/script/src/parse/parser.js +2 -1
  6. package/src/_dnt.shims.ts +0 -69
  7. package/src/mod.ts +0 -35
  8. package/src/src/ast/node.ts +0 -46
  9. package/src/src/codegen/config.ts +0 -41
  10. package/src/src/codegen/endpoints-generator.ts +0 -72
  11. package/src/src/codegen/generator.ts +0 -192
  12. package/src/src/codegen/internal-utils.ts +0 -6
  13. package/src/src/codegen/schemas-generator.ts +0 -87
  14. package/src/src/codegen/services-generator.ts +0 -77
  15. package/src/src/codegen/types.ts +0 -37
  16. package/src/src/collect/collector.ts +0 -142
  17. package/src/src/collect/helpers.ts +0 -36
  18. package/src/src/collect/types.ts +0 -21
  19. package/src/src/internal-utils.ts +0 -5
  20. package/src/src/parse/deref-proxy.ts +0 -70
  21. package/src/src/parse/openapi-types.ts +0 -949
  22. package/src/src/parse/parser.ts +0 -206
  23. package/src/src/parse/types.ts +0 -28
  24. package/src/src/transform/api-types.ts +0 -245
  25. package/src/src/transform/helpers.ts +0 -218
  26. package/src/src/transform/transform-document.ts +0 -35
  27. package/src/src/transform/transform-endpoint.ts +0 -331
  28. package/src/src/transform/transform-schema.ts +0 -217
  29. package/src/src/transform/transformer.ts +0 -53
  30. package/src/src/transform/types.ts +0 -52
  31. package/src/src/utils/action-provider.ts +0 -58
  32. package/src/src/utils/api-data.utils.ts +0 -48
  33. package/src/src/utils/array.utils.ts +0 -7
  34. package/src/src/utils/asset-manager.ts +0 -51
  35. package/src/src/utils/class.utils.ts +0 -40
  36. package/src/src/utils/common.utils.ts +0 -86
  37. package/src/src/utils/condition.ts +0 -7
  38. package/src/src/utils/endpoint.utils.ts +0 -10
  39. package/src/src/utils/error.utils.ts +0 -3
  40. package/src/src/utils/factory.ts +0 -42
  41. package/src/src/utils/file-system.utils.ts +0 -61
  42. package/src/src/utils/generator.utils.ts +0 -6
  43. package/src/src/utils/object.utils.ts +0 -32
  44. package/src/src/utils/schema.utils.ts +0 -148
  45. package/src/src/utils/source-builder.ts +0 -597
  46. package/src/src/utils/string-builder/options.ts +0 -19
  47. package/src/src/utils/string-builder/string-builder.ts +0 -165
  48. package/src/src/utils/string-builder/utils.ts +0 -69
  49. package/src/src/utils/string.utils.ts +0 -369
  50. package/src/src/utils/string.utils.types.ts +0 -179
  51. package/src/src/utils/type.utils.ts +0 -93
  52. package/src/src/utils/yaml-info.ts +0 -48
@@ -1,165 +0,0 @@
1
- import { isNullish } from '../common.utils.js';
2
- import type { Nullable, SingleOrMultiple } from '../type.utils.js';
3
- import { defaultStringBuilderOptions, type StringBuilderOptions } from './options.js';
4
-
5
- export type BuilderFn<TBuilder extends StringBuilder> = (builder: TBuilder) => void;
6
- export type Primitive = string | number | boolean;
7
-
8
- export type AppendParam<TBuilder extends StringBuilder, TAdditionalAppends> = SingleOrMultiple<
9
- | Primitive
10
- | null
11
- | undefined
12
- | BuilderFn<TBuilder>
13
- // eslint-disable-next-line @typescript-eslint/ban-types
14
- | TAdditionalAppends
15
- | {
16
- __type: 'append-value-group';
17
- values: AppendParam<TBuilder, TAdditionalAppends>[];
18
- separator: string | null;
19
- }
20
- >;
21
-
22
- export const AdditionalAppendsSymbol = Symbol('AdditionalAppends');
23
-
24
- /**
25
- * Represents a mutable string of characters.
26
- */
27
- export class StringBuilder<TAdditionalAppends = never> {
28
- private readonly _options: StringBuilderOptions;
29
- protected str: string = '';
30
-
31
- [AdditionalAppendsSymbol](_: TAdditionalAppends): void {
32
- throw new Error('This method should never be called.');
33
- }
34
-
35
- public get options(): StringBuilderOptions {
36
- return this._options;
37
- }
38
-
39
- /**
40
- * Initializes a new instance of the StringBuilder class.
41
- * @param options The options.
42
- */
43
- constructor(options?: Partial<StringBuilderOptions>) {
44
- this._options = { ...defaultStringBuilderOptions, ...options };
45
- }
46
-
47
- /**
48
- * Creates a new StringBuilder instance and appends the specified string to it.
49
- * @param str The string to append.
50
- * @param options The options.
51
- * @returns A new StringBuilder instance.
52
- */
53
- public static fromString(str: string, options?: Partial<StringBuilderOptions>): StringBuilder {
54
- const builder = new StringBuilder(options);
55
- builder.append(str);
56
- return builder;
57
- }
58
-
59
- /**
60
- * Builds a string using a StringBuilder build action.
61
- * @param buildAction The build action to perform on the StringBuilder instance.
62
- * @param options The options for the StringBuilder instance.
63
- * @returns The built string.
64
- */
65
- public static build(buildAction: AppendParam<StringBuilder, never>, options?: Partial<StringBuilderOptions>): string {
66
- const builder = new StringBuilder(options);
67
- builder.append(buildAction);
68
- return builder.toString();
69
- }
70
-
71
- protected appendSingle(value: AppendParam<this, TAdditionalAppends>) {
72
- if (isNullish(value)) return;
73
- if (Array.isArray(value)) {
74
- for (const part of value) {
75
- this.appendSingle(part);
76
- }
77
- } else if (typeof value === 'string') {
78
- this.str += value;
79
- } else if (typeof value === 'number' || typeof value === 'boolean') {
80
- this.str += value.toString();
81
- } else if (typeof value === 'function') {
82
- (value as (builder: this) => void)(this);
83
- } else if (
84
- typeof value === 'object' &&
85
- value !== null &&
86
- '__type' in value &&
87
- value.__type === 'append-value-group'
88
- ) {
89
- let isFirst = true;
90
- for (const part of value.values) {
91
- if (!isFirst && value.separator) {
92
- this.append(value.separator);
93
- }
94
- this.appendSingle(part);
95
- isFirst = false;
96
- }
97
- }
98
- }
99
-
100
- /**
101
- * Appends one or more strings to the end of the current StringBuilder.
102
- * @param value The string(s) to append.
103
- * @returns The current StringBuilder.
104
- */
105
- public append(...value: AppendParam<this, TAdditionalAppends>[]): this {
106
- for (const part of value) {
107
- this.appendSingle(part);
108
- }
109
- return this;
110
- }
111
-
112
- /**
113
- * Appends one or more strings to the end of the current StringBuilder, followed by a line terminator.
114
- * @param value
115
- * @returns
116
- */
117
- public appendLine(...value: Nullable<AppendParam<this, TAdditionalAppends>>[]): this {
118
- return this.append(...value, '\n');
119
- }
120
-
121
- /**
122
- * Prepends one or more strings to the beginning of the current StringBuilder.
123
- * @param value The string(s) to prepend.
124
- * @returns The current StringBuilder.
125
- */
126
- public prepend(...value: AppendParam<StringBuilder, never>[]): this {
127
- for (const part of value.reverse()) {
128
- if (isNullish(part)) continue;
129
- if (typeof part === 'function') {
130
- const builder = new StringBuilder(this.options);
131
- part(builder);
132
- this.str = builder.str + this.str;
133
- } else if (typeof part === 'string') {
134
- this.str = part + this.str;
135
- } else {
136
- this.str = part.toString() + this.str;
137
- }
138
- }
139
- return this;
140
- }
141
-
142
- /**
143
- * Prepends one or more strings to the beginning of the current StringBuilder, followed by a line terminator.
144
- * @param value The string(s) to prepend.
145
- * @returns The current StringBuilder.
146
- */
147
- public prependLine(...value: AppendParam<StringBuilder, never>[]): this {
148
- return this.prepend(...value, '\n');
149
- }
150
-
151
- /**
152
- * Converts the value of this instance to a string.
153
- * @returns A string whose value is the same as this instance.
154
- */
155
- public toString(): string {
156
- return this.str.replace(/\r?\n/g, this._options.newLine);
157
- }
158
-
159
- /**
160
- * Removes all characters from the current StringBuilder.
161
- */
162
- public clear(): void {
163
- this.str = '';
164
- }
165
- }
@@ -1,69 +0,0 @@
1
- import { concatSingleOrMultiple, notNullish } from '../common.utils.js';
2
- import type { Nullable } from '../type.utils.js';
3
- import type { AdditionalAppendsSymbol, AppendParam, BuilderFn, Primitive, StringBuilder } from './string-builder.js';
4
-
5
- export type BasicAppendValue<TBuilder extends StringBuilder = StringBuilder> =
6
- | Primitive
7
- | BuilderFn<TBuilder>
8
- | BasicAppendValueGroup<TBuilder>;
9
- export type BasicAppendValueGroup<TBuilder extends StringBuilder = StringBuilder> = {
10
- __type: 'append-value-group';
11
- values: BasicAppendValue<TBuilder>[];
12
- separator: string | null;
13
- };
14
-
15
- export type AppendValue<TBuilder extends StringBuilder = StringBuilder> = NonNullable<
16
- AppendParam<TBuilder, Parameters<TBuilder[typeof AdditionalAppendsSymbol]>[0]>
17
- >;
18
- export type AppendValueGroup<TBuilder extends StringBuilder = StringBuilder> = {
19
- __type: 'append-value-group';
20
- values: AppendValue<TBuilder>[];
21
- separator: string | null;
22
- };
23
-
24
- /** @deprecated Use AppendValue<TBuilder> instead */
25
- export type TextOrBuilderFn<TBuilder> = string | ((builder: TBuilder) => void);
26
-
27
- export function basicAppendValueGroup<TBuilder extends StringBuilder = StringBuilder>(
28
- values: Nullable<Nullable<BasicAppendValue<TBuilder>>[]>,
29
- separator?: Nullable<string>,
30
- ): BasicAppendValueGroup<TBuilder> {
31
- return {
32
- __type: 'append-value-group',
33
- values: values?.filter(notNullish) ?? [],
34
- separator: separator ?? null,
35
- };
36
- }
37
-
38
- export function appendValueGroup<TBuilder extends StringBuilder = StringBuilder>(
39
- values: Nullable<Nullable<AppendValue<TBuilder>>[]>,
40
- separator?: Nullable<string>,
41
- ): AppendValueGroup<TBuilder> {
42
- return {
43
- __type: 'append-value-group',
44
- values: values?.filter(notNullish) ?? [],
45
- separator: separator ?? null,
46
- };
47
- }
48
-
49
- export function isAppendValue(value: unknown): value is AppendValue<never> {
50
- return (
51
- typeof value === 'string' ||
52
- typeof value === 'number' ||
53
- typeof value === 'boolean' ||
54
- typeof value === 'function' ||
55
- isAppendValueGroup(value)
56
- );
57
- }
58
-
59
- export function isAppendValueGroup<TBuilder extends StringBuilder = StringBuilder>(
60
- value: unknown,
61
- ): value is AppendValueGroup<TBuilder> {
62
- return typeof value === 'object' && value !== null && '__type' in value && value.__type === 'append-value-group';
63
- }
64
-
65
- export function concatAppendValues<TBuilder extends StringBuilder = StringBuilder>(
66
- ...values: AppendValue<TBuilder>[]
67
- ): AppendValue<TBuilder> {
68
- return concatSingleOrMultiple(...values) as AppendValue<TBuilder>;
69
- }
@@ -1,369 +0,0 @@
1
- import { isNullish } from './common.utils.js';
2
- import type {
3
- BaseCaseOptions,
4
- CamelCaseOptions,
5
- CaseOptions,
6
- CustomCaseOptions,
7
- KebabCaseOptions,
8
- PascalCaseOptions,
9
- SnakeCaseOptions,
10
- StringCasing,
11
- StringCasingWithOptions,
12
- WordCasing,
13
- } from './string.utils.types.js';
14
- import type { Nullable } from './type.utils.js';
15
-
16
- export function adjustCasing(a: StringCasing, b: StringCasing): StringCasing;
17
- export function adjustCasing(
18
- a: StringCasing | StringCasingWithOptions,
19
- b: StringCasing | Partial<StringCasingWithOptions>,
20
- ): StringCasingWithOptions;
21
- export function adjustCasing(
22
- a: StringCasing | StringCasingWithOptions,
23
- b: StringCasing | Partial<StringCasingWithOptions>,
24
- ): StringCasing | StringCasingWithOptions {
25
- if (typeof a === 'string') {
26
- if (typeof b === 'string') {
27
- return b;
28
- } else {
29
- return { casing: a, ...b };
30
- }
31
- } else if (typeof b === 'string') {
32
- return { ...a, casing: b };
33
- } else {
34
- return { ...a, ...b };
35
- }
36
- }
37
-
38
- export function lowercase<T extends string>(str: T): Lowercase<T> {
39
- return str.toLowerCase() as Lowercase<T>;
40
- }
41
-
42
- export function uppercase<T extends string>(str: T): Uppercase<T> {
43
- return str.toUpperCase() as Uppercase<T>;
44
- }
45
-
46
- export function capitalize<T extends string>(str: T): Capitalize<T> {
47
- return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>;
48
- }
49
-
50
- export function uncapitalize<T extends string>(str: T): Uncapitalize<T> {
51
- return (str.charAt(0).toLowerCase() + str.slice(1)) as Uncapitalize<T>;
52
- }
53
-
54
- /**
55
- * Gets the words from a string. Words are separated by capital letters. Leading numbers are removed. Non-alphanumerical characters are removed and interpreted as word seperators. Multiple uppercase letters are interpreted as one word.
56
- * @param str The string to get the words from.
57
- * @returns The words.
58
- * @example
59
- * getWords('fooBar') // => ['foo', 'Bar']
60
- * getWords('fooBarBaz') // => ['foo', 'Bar', 'Baz']
61
- * getWords('fooBarBaz123') // => ['foo', 'Bar', 'Baz', '123']
62
- * getWords('123Foo###Bar###') // => ['Foo', 'Bar']
63
- * getWords('fooBARBaz') // => ['foo', 'BAR', 'Baz']
64
- */
65
- export function getWords(str: Nullable<string>): string[] {
66
- if (isNullish(str)) return [];
67
-
68
- // Remove non-alphanumerical characters
69
- str = str.replace(/[^a-zA-Z0-9]+/g, '-');
70
- str = str.replace(/^[0-9-]+/, '');
71
-
72
- // Split into words
73
- return str.match(/[A-Z]{2,}(?=[A-Z0-9-]|$)|[a-zA-Z][a-z]*|[0-9]+/g) ?? [];
74
- }
75
-
76
- /**
77
- * Converts a word to a given casing.
78
- * @param str The word to convert.
79
- * @param casing The casing to convert to.
80
- * @returns The converted word.
81
- * @example
82
- * toCasing('fooBar', 'unchanged') // => 'fooBar'
83
- * toCasing('fooBar', 'all-lower') // => 'foobar'
84
- * toCasing('fooBar', 'all-upper') // => 'FOOBAR'
85
- * toCasing('fooBar', 'first-upper') // => 'FooBar'
86
- * toCasing('FooBar', 'first-lower') // => 'fooBar'
87
- * toCasing('fooBar', 'first-upper-then-lower') // => 'Foobar'
88
- * toCasing('FooBar', 'first-lower-then-upper') // => 'fOOBAR'
89
- * toCasing('fooBar', 'first-upper-alternating') // => 'FoObAr'
90
- * toCasing('FooBar', 'first-lower-alternating') // => 'fOoBaR'
91
- */
92
- export function wordToCasing(str: Nullable<string>, casing: WordCasing): string {
93
- str ??= '';
94
- switch (casing) {
95
- case 'unchanged':
96
- return str;
97
- case 'all-lower':
98
- return str.toLowerCase();
99
- case 'all-upper':
100
- return str.toUpperCase();
101
- case 'first-upper':
102
- return str[0].toUpperCase() + str.slice(1);
103
- case 'first-lower':
104
- return str[0].toLowerCase() + str.slice(1);
105
- case 'first-upper-then-lower':
106
- return str[0].toUpperCase() + str.slice(1).toLowerCase();
107
- case 'first-lower-then-upper':
108
- return str[0].toLowerCase() + str.slice(1).toUpperCase();
109
- case 'first-upper-alternating':
110
- return str
111
- .split('')
112
- .map((c, i) => (i % 2 === 0 ? c.toUpperCase() : c.toLowerCase()))
113
- .join('');
114
- case 'first-lower-alternating':
115
- return str
116
- .split('')
117
- .map((c, i) => (i % 2 === 0 ? c.toLowerCase() : c.toUpperCase()))
118
- .join('');
119
- }
120
- }
121
-
122
- export function toCasing<T extends StringCasing>(
123
- str: Nullable<string>,
124
- casing: T | StringCasingWithOptions<T>,
125
- ): string {
126
- let options: CaseOptions<T> | undefined;
127
- let casingType: StringCasing;
128
- if (typeof casing === 'string') {
129
- casingType = casing;
130
- } else {
131
- options = casing;
132
- casingType = casing.casing;
133
- }
134
-
135
- switch (casingType) {
136
- case 'camel':
137
- return toCamelCase(str, options as CaseOptions<'camel'>);
138
- case 'pascal':
139
- return toPascalCase(str, options as CaseOptions<'pascal'>);
140
- case 'kebab':
141
- return toKebabCase(str, options as CaseOptions<'kebab'>);
142
- case 'snake':
143
- return toSnakeCase(str, options as CaseOptions<'snake'>);
144
- case 'custom':
145
- return toCustomCase(str, options as CaseOptions<'custom'>);
146
- default:
147
- return wordToCasing(getWords(str).join(''), casingType);
148
- }
149
- }
150
-
151
- function addPrefixAndSuffix(str: string, { prefix, suffix }: BaseCaseOptions): string {
152
- if (prefix) {
153
- str = prefix + str;
154
- }
155
- if (suffix) {
156
- str = str + suffix;
157
- }
158
- return str;
159
- }
160
-
161
- /**
162
- * Converts a string to camel case.
163
- * @param str The string to convert.
164
- * @param options The options.
165
- * @returns The converted string.
166
- * @example
167
- * toCamelCase('Foo bAR') // => 'fooBar'
168
- * toCamelCase('Foo bAR', { keepOriginalCase: true }) // => 'fooBAR'
169
- * toCamelCase('Foo bAR', { keepOriginalCase: false }) // => 'fooBar'
170
- * toCamelCase('Foo bAR', { prefix: 'bar' }) // => 'barfooBar'
171
- * toCamelCase('Foo bAR', { suffix: 'bar' }) // => 'fooBarbar'
172
- */
173
- export function toCamelCase(str: Nullable<string>, options?: Partial<CamelCaseOptions>): string {
174
- const opts: CamelCaseOptions = { keepOriginalCase: false, ...options };
175
- const words = getWords(str);
176
- const camelCase = words
177
- .map((word, index) =>
178
- index === 0
179
- ? wordToCasing(word, opts.keepOriginalCase ? 'first-lower' : 'all-lower')
180
- : wordToCasing(word, opts.keepOriginalCase ? 'first-upper' : 'first-upper-then-lower')
181
- )
182
- .join('');
183
- return addPrefixAndSuffix(camelCase, opts);
184
- }
185
-
186
- /**
187
- * Converts a string to pascal case.
188
- * @param str The string to convert.
189
- * @param options The options.
190
- * @returns The converted string.
191
- * @example
192
- * toPascalCase('foo bAR') // => 'FooBar'
193
- * toPascalCase('foo bAR', { keepOriginalCase: true }) // => 'FooBAR'
194
- * toPascalCase('foo bAR', { keepOriginalCase: false }) // => 'FooBar'
195
- * toPascalCase('foo bAR', { prefix: 'bar' }) // => 'barFooBar'
196
- * toPascalCase('foo bAR', { suffix: 'bar' }) // => 'FooBarbar'
197
- */
198
- export function toPascalCase(str: Nullable<string>, options?: Partial<PascalCaseOptions>): string {
199
- const opts: PascalCaseOptions = { keepOriginalCase: false, ...options };
200
- const words = getWords(str);
201
- const pascalCase = words
202
- .map((word) => wordToCasing(word, opts.keepOriginalCase ? 'first-upper' : 'first-upper-then-lower'))
203
- .join('');
204
- return addPrefixAndSuffix(pascalCase, opts);
205
- }
206
-
207
- /**
208
- * Converts a string to kebab case.
209
- * @param str The string to convert.
210
- * @param options The options.
211
- * @returns The converted string.
212
- * @example
213
- * toKebabCase('Foo bAR') // => 'foo-bar'
214
- * toKebabCase('Foo bAR', { wordCasing: 'all-upper' }) // => 'FOO-BAR'
215
- * toKebabCase('Foo bAR', { firstWordCasing: 'all-upper' }) // => 'FOO-bar'
216
- * toKebabCase('Foo bAR', { casing: 'all-upper', firstWordCasing: 'all-lower' }) // => 'foo-BAR'
217
- * toKebabCase('Foo bAR', { prefix: 'bar' }) // => 'barfoo-bar'
218
- * toKebabCase('Foo bAR', { suffix: 'bar' }) // => 'foo-barbar'
219
- */
220
- export function toKebabCase(str: Nullable<string>, options?: Partial<KebabCaseOptions>): string {
221
- const opts: KebabCaseOptions = { wordCasing: 'all-lower', ...options };
222
- const words = getWords(str);
223
- const kebabCase = words
224
- .map((word, index) =>
225
- index === 0 ? wordToCasing(word, opts.firstWordCasing ?? opts.wordCasing) : wordToCasing(word, opts.wordCasing)
226
- )
227
- .join('-');
228
- return addPrefixAndSuffix(kebabCase, opts);
229
- }
230
-
231
- /**
232
- * Converts a string to snake case.
233
- * @param str The string to convert.
234
- * @param options The options.
235
- * @returns The converted string.
236
- * @example
237
- * toSnakeCase('Foo bAR') // => 'FOO_BAR'
238
- * toSnakeCase('Foo bAR', { wordCasing: 'all-lower' }) // => 'foo_bar'
239
- * toSnakeCase('Foo bAR', { firstWordCasing: 'all-lower' }) // => 'foo_BAR'
240
- * toSnakeCase('Foo bAR', { casing: 'all-lower', firstWordCasing: 'all-upper' }) // => 'FOO_bar'
241
- * toSnakeCase('Foo bAR', { prefix: 'bar' }) // => 'barFOO_BAR'
242
- * toSnakeCase('Foo bAR', { suffix: 'bar' }) // => 'FOO_BARbar'
243
- */
244
- export function toSnakeCase(str: Nullable<string>, options?: Partial<SnakeCaseOptions>): string {
245
- const opts: SnakeCaseOptions = { wordCasing: 'all-upper', ...options };
246
- const words = getWords(str);
247
- const snakeCase = words
248
- .map((word, index) =>
249
- index === 0 ? wordToCasing(word, opts.firstWordCasing ?? opts.wordCasing) : wordToCasing(word, opts.wordCasing)
250
- )
251
- .join('_');
252
- return addPrefixAndSuffix(snakeCase, opts);
253
- }
254
-
255
- /**
256
- * Converts a string to a custom case.
257
- * @param str The string to convert.
258
- * @param options The options.
259
- * @returns The converted string.
260
- * @example
261
- * toCustomCase('Foo bAR', { wordCasing: 'first-upper-then-lower' }) // => 'FooBar'
262
- * toCustomCase('Foo bAR', { wordCasing: 'first-upper-then-lower', wordSeparator: '~' }) // => 'Foo~Bar'
263
- * toCustomCase('Foo bAR', { wordCasing: 'first-upper-then-lower', wordSeparator: '~', prefix: 'bar' }) // => 'barFoo~Bar'
264
- * toCustomCase('Foo bAR', { wordCasing: 'first-upper-then-lower', wordSeparator: '~', suffix: 'bar' }) // => 'Foo~Barbar'
265
- * toCustomCase('Foo bAR', { wordCasing: 'all-upper', firstWordCasing: 'all-lower' }) // => 'fooBAR'
266
- * toCustomCase('Foo bAR baz', { wordCasing: (wordIndex) => (wordIndex % 2 === 0 ? 'all-upper' : 'all-lower') }) // => 'FOObarBAZ'
267
- */
268
- export function toCustomCase(str: Nullable<string>, options: CustomCaseOptions): string {
269
- const words = getWords(str);
270
- const wordMapFn: (word: string, index: number) => string = typeof options.wordCasing === 'function'
271
- ? (word, index) => wordToCasing(word, options.wordCasing(index))
272
- : (word, index) =>
273
- index === 0
274
- ? wordToCasing(word, options.firstWordCasing ?? options.wordCasing)
275
- : wordToCasing(word, options.wordCasing);
276
- const customCase = words.map(wordMapFn).join(options.wordSeparator ?? '');
277
- return addPrefixAndSuffix(customCase, options);
278
- }
279
-
280
- /**
281
- * Escapes a string to be used in a regular expression.
282
- * @param str The string to escape.
283
- */
284
- export function escapeRegExp(str: string): string {
285
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
286
- }
287
-
288
- /**
289
- * Removes characters from a string and, if necessary, inserts new characters in their place, returning the spliced string.
290
- * @param str The string to splice.
291
- * @param start The index at which to start changing the string.
292
- * @param deleteCount The number of characters to remove.
293
- * @param insert The string to insert.
294
- * @returns The spliced string.
295
- */
296
- export function spliceString(str: string, start: number, deleteCount: number, insert: string): string {
297
- return str.slice(0, start) + insert + str.slice(start + deleteCount);
298
- }
299
-
300
- /**
301
- * Removes leading indentation based on the last line. Also removes the first line if it is empty.
302
- * @param str The string to trim.
303
- */
304
- export function trimIndent(str: string): string {
305
- const indent = str.match(/\n( *).*$/)?.[1] ?? '';
306
- if (indent.length === 0) return str;
307
- return str.replace(/^\r?\n/, '').replace(new RegExp(`^ {0,${indent.length}}`, 'gm'), '');
308
- }
309
-
310
- function isNonLineBreakWhitespaceChar(char: string): boolean {
311
- return (
312
- char === ' ' ||
313
- char === '\t' ||
314
- char === '\f' ||
315
- char === '\v' ||
316
- char === '\u00a0' ||
317
- char === '\u1680' ||
318
- char === '\u2000' ||
319
- char === '\u2001' ||
320
- char === '\u2002' ||
321
- char === '\u2003' ||
322
- char === '\u2004' ||
323
- char === '\u2005' ||
324
- char === '\u2006' ||
325
- char === '\u2007' ||
326
- char === '\u2008' ||
327
- char === '\u2009' ||
328
- char === '\u200a' ||
329
- char === '\u2028' ||
330
- char === '\u2029' ||
331
- char === '\u202f' ||
332
- char === '\u205f' ||
333
- char === '\u3000' ||
334
- char === '\ufeff'
335
- );
336
- }
337
- export function trimEnd(str: string, includeNewLine: boolean = true): string {
338
- if (includeNewLine) return str.trimEnd();
339
- let i = str.length;
340
- for (; isNonLineBreakWhitespaceChar(str[i - 1]); i--);
341
- return str.substring(0, i);
342
- }
343
- export function trimStart(str: string, includeNewLine: boolean = true): string {
344
- if (includeNewLine) return str.trimStart();
345
- let i = 0;
346
- for (; isNonLineBreakWhitespaceChar(str[i]); i++);
347
- return str.substring(i);
348
- }
349
- export function trim(str: string, includeNewLine: boolean = true): string {
350
- if (includeNewLine) return str.trim();
351
- let s = 0;
352
- for (; isNonLineBreakWhitespaceChar(str[s]); s++);
353
- let e = str.length;
354
- for (; isNonLineBreakWhitespaceChar(str[e - 1]); e--);
355
- return str.substring(s, e);
356
- }
357
-
358
- export function removeStr(str: string, rem: string): string {
359
- let i = str.indexOf(rem);
360
- if (i === -1) return str;
361
- let result = '';
362
- let s = 0;
363
- while (i !== -1) {
364
- result += str.substring(s, i);
365
- s = i + rem.length;
366
- i = str.indexOf(rem, s);
367
- }
368
- return result + str.substring(s);
369
- }