@typia/utils 12.0.0-dev.20260309 → 12.0.0-dev.20260311

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 (103) hide show
  1. package/lib/converters/LlmSchemaConverter.d.ts +0 -1
  2. package/lib/converters/LlmSchemaConverter.js +4 -31
  3. package/lib/converters/LlmSchemaConverter.js.map +1 -1
  4. package/lib/converters/LlmSchemaConverter.mjs +2 -32
  5. package/lib/converters/LlmSchemaConverter.mjs.map +1 -1
  6. package/lib/http/HttpLlm.js +4 -5
  7. package/lib/http/HttpLlm.js.map +1 -1
  8. package/lib/http/HttpLlm.mjs +0 -1
  9. package/lib/http/HttpLlm.mjs.map +1 -1
  10. package/lib/http/internal/HttpLlmApplicationComposer.js +3 -4
  11. package/lib/http/internal/HttpLlmApplicationComposer.js.map +1 -1
  12. package/lib/http/internal/HttpLlmApplicationComposer.mjs +5 -2
  13. package/lib/http/internal/HttpLlmApplicationComposer.mjs.map +1 -1
  14. package/lib/index.mjs +9 -9
  15. package/lib/utils/LlmJson.mjs +9 -2
  16. package/lib/utils/LlmJson.mjs.map +1 -1
  17. package/lib/utils/internal/stringifyValidationFailure.js +17 -15
  18. package/lib/utils/internal/stringifyValidationFailure.js.map +1 -1
  19. package/lib/utils/internal/stringifyValidationFailure.mjs +17 -15
  20. package/lib/utils/internal/stringifyValidationFailure.mjs.map +1 -1
  21. package/lib/validators/internal/OpenApiOneOfValidator.mjs +5 -1
  22. package/lib/validators/internal/OpenApiOneOfValidator.mjs.map +1 -1
  23. package/package.json +2 -2
  24. package/src/converters/LlmSchemaConverter.ts +617 -647
  25. package/src/converters/OpenApiConverter.ts +285 -285
  26. package/src/converters/index.ts +5 -5
  27. package/src/converters/internal/LlmDescriptionInverter.ts +178 -178
  28. package/src/converters/internal/LlmParametersComposer.ts +52 -52
  29. package/src/converters/internal/OpenApiConstraintShifter.ts +154 -154
  30. package/src/converters/internal/OpenApiExclusiveEmender.ts +46 -46
  31. package/src/converters/internal/OpenApiV3Downgrader.ts +355 -355
  32. package/src/converters/internal/OpenApiV3Upgrader.ts +470 -470
  33. package/src/converters/internal/OpenApiV3_1Upgrader.ts +685 -685
  34. package/src/converters/internal/SwaggerV2Downgrader.ts +424 -424
  35. package/src/converters/internal/SwaggerV2Upgrader.ts +523 -523
  36. package/src/http/HttpError.ts +107 -107
  37. package/src/http/HttpLlm.ts +166 -167
  38. package/src/http/HttpMigration.ts +92 -92
  39. package/src/http/index.ts +3 -3
  40. package/src/http/internal/HttpLlmApplicationComposer.ts +360 -361
  41. package/src/http/internal/HttpLlmFunctionFetcher.ts +37 -37
  42. package/src/http/internal/HttpMigrateApplicationComposer.ts +56 -56
  43. package/src/http/internal/HttpMigrateRouteAccessor.ts +135 -135
  44. package/src/http/internal/HttpMigrateRouteComposer.ts +505 -505
  45. package/src/http/internal/HttpMigrateRouteFetcher.ts +203 -203
  46. package/src/index.ts +4 -4
  47. package/src/utils/ArrayUtil.ts +42 -42
  48. package/src/utils/LlmJson.ts +141 -141
  49. package/src/utils/MapUtil.ts +15 -15
  50. package/src/utils/NamingConvention.ts +205 -205
  51. package/src/utils/Singleton.ts +17 -17
  52. package/src/utils/StringUtil.ts +14 -14
  53. package/src/utils/dedent.ts +57 -57
  54. package/src/utils/index.ts +8 -8
  55. package/src/utils/internal/EndpointUtil.ts +44 -44
  56. package/src/utils/internal/JsonDescriptor.ts +70 -70
  57. package/src/utils/internal/OpenApiTypeCheckerBase.ts +822 -822
  58. package/src/utils/internal/coerceLlmArguments.ts +314 -314
  59. package/src/utils/internal/parseLenientJson.ts +894 -894
  60. package/src/utils/internal/stringifyValidationFailure.ts +415 -411
  61. package/src/validators/LlmTypeChecker.ts +402 -402
  62. package/src/validators/OpenApiTypeChecker.ts +297 -297
  63. package/src/validators/OpenApiV3TypeChecker.ts +70 -70
  64. package/src/validators/OpenApiV3_1TypeChecker.ts +86 -86
  65. package/src/validators/OpenApiValidator.ts +94 -94
  66. package/src/validators/SwaggerV2TypeChecker.ts +71 -71
  67. package/src/validators/functional/_isBigintString.ts +8 -8
  68. package/src/validators/functional/_isFormatByte.ts +7 -7
  69. package/src/validators/functional/_isFormatDate.ts +3 -3
  70. package/src/validators/functional/_isFormatDateTime.ts +4 -4
  71. package/src/validators/functional/_isFormatDuration.ts +4 -4
  72. package/src/validators/functional/_isFormatEmail.ts +4 -4
  73. package/src/validators/functional/_isFormatHostname.ts +4 -4
  74. package/src/validators/functional/_isFormatIdnEmail.ts +4 -4
  75. package/src/validators/functional/_isFormatIdnHostname.ts +4 -4
  76. package/src/validators/functional/_isFormatIpv4.ts +4 -4
  77. package/src/validators/functional/_isFormatIpv6.ts +4 -4
  78. package/src/validators/functional/_isFormatIri.ts +3 -3
  79. package/src/validators/functional/_isFormatIriReference.ts +4 -4
  80. package/src/validators/functional/_isFormatJsonPointer.ts +3 -3
  81. package/src/validators/functional/_isFormatPassword.ts +1 -1
  82. package/src/validators/functional/_isFormatRegex.ts +8 -8
  83. package/src/validators/functional/_isFormatRelativeJsonPointer.ts +4 -4
  84. package/src/validators/functional/_isFormatTime.ts +4 -4
  85. package/src/validators/functional/_isFormatUri.ts +6 -6
  86. package/src/validators/functional/_isFormatUriReference.ts +5 -5
  87. package/src/validators/functional/_isFormatUriTemplate.ts +4 -4
  88. package/src/validators/functional/_isFormatUrl.ts +4 -4
  89. package/src/validators/functional/_isFormatUuid.ts +3 -3
  90. package/src/validators/functional/_isUniqueItems.ts +159 -159
  91. package/src/validators/index.ts +14 -14
  92. package/src/validators/internal/IOpenApiValidatorContext.ts +17 -17
  93. package/src/validators/internal/OpenApiArrayValidator.ts +49 -49
  94. package/src/validators/internal/OpenApiBooleanValidator.ts +11 -11
  95. package/src/validators/internal/OpenApiConstantValidator.ts +11 -11
  96. package/src/validators/internal/OpenApiIntegerValidator.ts +49 -49
  97. package/src/validators/internal/OpenApiNumberValidator.ts +48 -48
  98. package/src/validators/internal/OpenApiObjectValidator.ts +83 -83
  99. package/src/validators/internal/OpenApiOneOfValidator.ts +309 -309
  100. package/src/validators/internal/OpenApiSchemaNamingRule.ts +124 -124
  101. package/src/validators/internal/OpenApiStationValidator.ts +115 -115
  102. package/src/validators/internal/OpenApiStringValidator.ts +88 -88
  103. package/src/validators/internal/OpenApiTupleValidator.ts +55 -55
@@ -1,205 +1,205 @@
1
- /**
2
- * String naming convention converters.
3
- *
4
- * `NamingConvention` converts between common code naming conventions:
5
- * camelCase, PascalCase, and snake_case. Handles edge cases like consecutive
6
- * uppercase letters (e.g., `XMLParser` → `xml_parser`) and leading
7
- * underscores.
8
- *
9
- * Functions:
10
- *
11
- * - {@link camel}: Convert to camelCase (`fooBar`)
12
- * - {@link pascal}: Convert to PascalCase (`FooBar`)
13
- * - {@link snake}: Convert to snake_case (`foo_bar`)
14
- * - {@link variable}: Test if string is valid JavaScript variable name
15
- *
16
- * @author Jeongho Nam - https://github.com/samchon
17
- */
18
- export namespace NamingConvention {
19
- /**
20
- * Convert to camelCase.
21
- *
22
- * @param str Input string
23
- * @returns CamelCase string
24
- */
25
- export function camel(str: string) {
26
- return unsnake({
27
- plain: (str) =>
28
- str.length
29
- ? str === str.toUpperCase()
30
- ? str.toLocaleLowerCase()
31
- : `${str[0]!.toLowerCase()}${str.substring(1)}`
32
- : str,
33
- snake: (str, i) =>
34
- i === 0 ? str.toLowerCase() : capitalize(str.toLowerCase()),
35
- })(str);
36
- }
37
-
38
- /**
39
- * Convert to PascalCase.
40
- *
41
- * @param str Input string
42
- * @returns PascalCase string
43
- */
44
- export function pascal(str: string) {
45
- return unsnake({
46
- plain: (str) =>
47
- str.length ? `${str[0]!.toUpperCase()}${str.substring(1)}` : str,
48
- snake: capitalize,
49
- })(str);
50
- }
51
-
52
- /**
53
- * Convert to snake_case.
54
- *
55
- * @param str Input string
56
- * @returns Snake_case string
57
- */
58
- export function snake(str: string): string {
59
- if (str.length === 0) return str;
60
-
61
- // PREFIX
62
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
- let prefix: string = "";
64
- for (let i: number = 0; i < str.length; i++) {
65
- if (str[i] === "_") prefix += "_";
66
- else break;
67
- }
68
- if (prefix.length !== 0) str = str.substring(prefix.length);
69
-
70
- const out = (s: string) => `${prefix}${s}`;
71
-
72
- // SNAKE CASE
73
- const items: string[] = str.split("_");
74
- if (items.length > 1)
75
- return out(items.map((s) => s.toLowerCase()).join("_"));
76
-
77
- // CAMEL OR PASCAL CASE
78
- const indexes: number[] = [];
79
- for (let i: number = 0; i < str.length; i++) {
80
- const code: number = str.charCodeAt(i);
81
- if (65 <= code && code <= 90) indexes.push(i);
82
- }
83
- for (let i: number = indexes.length - 1; i > 0; --i) {
84
- const now: number = indexes[i]!;
85
- const prev: number = indexes[i - 1]!;
86
- if (now - prev === 1) indexes.splice(i, 1);
87
- }
88
- if (indexes.length !== 0 && indexes[0] === 0) indexes.splice(0, 1);
89
- if (indexes.length === 0) return str.toLowerCase();
90
-
91
- let ret: string = "";
92
- for (let i: number = 0; i < indexes.length; i++) {
93
- const first: number = i === 0 ? 0 : indexes[i - 1]!;
94
- const last: number = indexes[i]!;
95
-
96
- ret += str.substring(first, last).toLowerCase();
97
- ret += "_";
98
- }
99
- ret += str.substring(indexes[indexes.length - 1]!).toLowerCase();
100
- return out(ret);
101
- }
102
-
103
- /**
104
- * Capitalize first character.
105
- *
106
- * @param str Input string
107
- * @returns Capitalized string
108
- */
109
- export const capitalize = (str: string): string =>
110
- str.length !== 0 ? str[0]!.toUpperCase() + str.slice(1) : str;
111
-
112
- /**
113
- * Lowercase first character.
114
- *
115
- * @param str Input string
116
- * @returns Localized string
117
- */
118
- export const localize = (str: string) => str[0]!.toLowerCase() + str.slice(1);
119
-
120
- /**
121
- * Check if string is valid JavaScript variable name.
122
- *
123
- * @param str String to check
124
- * @returns True if valid variable name
125
- */
126
- export const variable = (str: string): boolean =>
127
- reserved(str) === false && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/g.test(str);
128
-
129
- /**
130
- * Check if string is JavaScript reserved word.
131
- *
132
- * @param str String to check
133
- * @returns True if reserved word
134
- */
135
- export const reserved = (str: string): boolean => RESERVED.has(str);
136
- }
137
-
138
- const RESERVED: Set<string> = new Set([
139
- "break",
140
- "case",
141
- "catch",
142
- "class",
143
- "const",
144
- "continue",
145
- "debugger",
146
- "default",
147
- "delete",
148
- "do",
149
- "else",
150
- "enum",
151
- "export",
152
- "extends",
153
- "false",
154
- "finally",
155
- "for",
156
- "function",
157
- "if",
158
- "import",
159
- "in",
160
- "instanceof",
161
- "module",
162
- "new",
163
- "null",
164
- "package",
165
- "public",
166
- "private",
167
- "protected",
168
- "return",
169
- "super",
170
- "switch",
171
- "this",
172
- "throw",
173
- "true",
174
- "try",
175
- "typeof",
176
- "var",
177
- "void",
178
- "while",
179
- "with",
180
- ]);
181
-
182
- const unsnake =
183
- (props: {
184
- plain: (str: string) => string;
185
- snake: (str: string, index: number) => string;
186
- }) =>
187
- (str: string): string => {
188
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
- let prefix: string = "";
190
- for (let i: number = 0; i < str.length; i++) {
191
- if (str[i] === "_") prefix += "_";
192
- else break;
193
- }
194
- if (prefix.length !== 0) str = str.substring(prefix.length);
195
-
196
- const out = (s: string) => `${prefix}${s}`;
197
- if (str.length === 0) return out("");
198
-
199
- const items: string[] = str.split("_").filter((s) => s.length !== 0);
200
- return items.length === 0
201
- ? out("")
202
- : items.length === 1
203
- ? out(props.plain(items[0]!))
204
- : out(items.map(props.snake).join(""));
205
- };
1
+ /**
2
+ * String naming convention converters.
3
+ *
4
+ * `NamingConvention` converts between common code naming conventions:
5
+ * camelCase, PascalCase, and snake_case. Handles edge cases like consecutive
6
+ * uppercase letters (e.g., `XMLParser` → `xml_parser`) and leading
7
+ * underscores.
8
+ *
9
+ * Functions:
10
+ *
11
+ * - {@link camel}: Convert to camelCase (`fooBar`)
12
+ * - {@link pascal}: Convert to PascalCase (`FooBar`)
13
+ * - {@link snake}: Convert to snake_case (`foo_bar`)
14
+ * - {@link variable}: Test if string is valid JavaScript variable name
15
+ *
16
+ * @author Jeongho Nam - https://github.com/samchon
17
+ */
18
+ export namespace NamingConvention {
19
+ /**
20
+ * Convert to camelCase.
21
+ *
22
+ * @param str Input string
23
+ * @returns CamelCase string
24
+ */
25
+ export function camel(str: string) {
26
+ return unsnake({
27
+ plain: (str) =>
28
+ str.length
29
+ ? str === str.toUpperCase()
30
+ ? str.toLocaleLowerCase()
31
+ : `${str[0]!.toLowerCase()}${str.substring(1)}`
32
+ : str,
33
+ snake: (str, i) =>
34
+ i === 0 ? str.toLowerCase() : capitalize(str.toLowerCase()),
35
+ })(str);
36
+ }
37
+
38
+ /**
39
+ * Convert to PascalCase.
40
+ *
41
+ * @param str Input string
42
+ * @returns PascalCase string
43
+ */
44
+ export function pascal(str: string) {
45
+ return unsnake({
46
+ plain: (str) =>
47
+ str.length ? `${str[0]!.toUpperCase()}${str.substring(1)}` : str,
48
+ snake: capitalize,
49
+ })(str);
50
+ }
51
+
52
+ /**
53
+ * Convert to snake_case.
54
+ *
55
+ * @param str Input string
56
+ * @returns Snake_case string
57
+ */
58
+ export function snake(str: string): string {
59
+ if (str.length === 0) return str;
60
+
61
+ // PREFIX
62
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
+ let prefix: string = "";
64
+ for (let i: number = 0; i < str.length; i++) {
65
+ if (str[i] === "_") prefix += "_";
66
+ else break;
67
+ }
68
+ if (prefix.length !== 0) str = str.substring(prefix.length);
69
+
70
+ const out = (s: string) => `${prefix}${s}`;
71
+
72
+ // SNAKE CASE
73
+ const items: string[] = str.split("_");
74
+ if (items.length > 1)
75
+ return out(items.map((s) => s.toLowerCase()).join("_"));
76
+
77
+ // CAMEL OR PASCAL CASE
78
+ const indexes: number[] = [];
79
+ for (let i: number = 0; i < str.length; i++) {
80
+ const code: number = str.charCodeAt(i);
81
+ if (65 <= code && code <= 90) indexes.push(i);
82
+ }
83
+ for (let i: number = indexes.length - 1; i > 0; --i) {
84
+ const now: number = indexes[i]!;
85
+ const prev: number = indexes[i - 1]!;
86
+ if (now - prev === 1) indexes.splice(i, 1);
87
+ }
88
+ if (indexes.length !== 0 && indexes[0] === 0) indexes.splice(0, 1);
89
+ if (indexes.length === 0) return str.toLowerCase();
90
+
91
+ let ret: string = "";
92
+ for (let i: number = 0; i < indexes.length; i++) {
93
+ const first: number = i === 0 ? 0 : indexes[i - 1]!;
94
+ const last: number = indexes[i]!;
95
+
96
+ ret += str.substring(first, last).toLowerCase();
97
+ ret += "_";
98
+ }
99
+ ret += str.substring(indexes[indexes.length - 1]!).toLowerCase();
100
+ return out(ret);
101
+ }
102
+
103
+ /**
104
+ * Capitalize first character.
105
+ *
106
+ * @param str Input string
107
+ * @returns Capitalized string
108
+ */
109
+ export const capitalize = (str: string): string =>
110
+ str.length !== 0 ? str[0]!.toUpperCase() + str.slice(1) : str;
111
+
112
+ /**
113
+ * Lowercase first character.
114
+ *
115
+ * @param str Input string
116
+ * @returns Localized string
117
+ */
118
+ export const localize = (str: string) => str[0]!.toLowerCase() + str.slice(1);
119
+
120
+ /**
121
+ * Check if string is valid JavaScript variable name.
122
+ *
123
+ * @param str String to check
124
+ * @returns True if valid variable name
125
+ */
126
+ export const variable = (str: string): boolean =>
127
+ reserved(str) === false && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/g.test(str);
128
+
129
+ /**
130
+ * Check if string is JavaScript reserved word.
131
+ *
132
+ * @param str String to check
133
+ * @returns True if reserved word
134
+ */
135
+ export const reserved = (str: string): boolean => RESERVED.has(str);
136
+ }
137
+
138
+ const RESERVED: Set<string> = new Set([
139
+ "break",
140
+ "case",
141
+ "catch",
142
+ "class",
143
+ "const",
144
+ "continue",
145
+ "debugger",
146
+ "default",
147
+ "delete",
148
+ "do",
149
+ "else",
150
+ "enum",
151
+ "export",
152
+ "extends",
153
+ "false",
154
+ "finally",
155
+ "for",
156
+ "function",
157
+ "if",
158
+ "import",
159
+ "in",
160
+ "instanceof",
161
+ "module",
162
+ "new",
163
+ "null",
164
+ "package",
165
+ "public",
166
+ "private",
167
+ "protected",
168
+ "return",
169
+ "super",
170
+ "switch",
171
+ "this",
172
+ "throw",
173
+ "true",
174
+ "try",
175
+ "typeof",
176
+ "var",
177
+ "void",
178
+ "while",
179
+ "with",
180
+ ]);
181
+
182
+ const unsnake =
183
+ (props: {
184
+ plain: (str: string) => string;
185
+ snake: (str: string, index: number) => string;
186
+ }) =>
187
+ (str: string): string => {
188
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
+ let prefix: string = "";
190
+ for (let i: number = 0; i < str.length; i++) {
191
+ if (str[i] === "_") prefix += "_";
192
+ else break;
193
+ }
194
+ if (prefix.length !== 0) str = str.substring(prefix.length);
195
+
196
+ const out = (s: string) => `${prefix}${s}`;
197
+ if (str.length === 0) return out("");
198
+
199
+ const items: string[] = str.split("_").filter((s) => s.length !== 0);
200
+ return items.length === 0
201
+ ? out("")
202
+ : items.length === 1
203
+ ? out(props.plain(items[0]!))
204
+ : out(items.map(props.snake).join(""));
205
+ };
@@ -1,17 +1,17 @@
1
- /** @internal */
2
- export class Singleton<T, Args extends any[] = []> {
3
- private readonly closure_: (...args: Args) => T;
4
- private value_: T | object;
5
-
6
- public constructor(closure: (...args: Args) => T) {
7
- this.closure_ = closure;
8
- this.value_ = NOT_MOUNTED_YET;
9
- }
10
-
11
- public get(...args: Args): T {
12
- if (this.value_ === NOT_MOUNTED_YET) this.value_ = this.closure_(...args);
13
- return this.value_ as T;
14
- }
15
- }
16
-
17
- const NOT_MOUNTED_YET = {};
1
+ /** @internal */
2
+ export class Singleton<T, Args extends any[] = []> {
3
+ private readonly closure_: (...args: Args) => T;
4
+ private value_: T | object;
5
+
6
+ public constructor(closure: (...args: Args) => T) {
7
+ this.closure_ = closure;
8
+ this.value_ = NOT_MOUNTED_YET;
9
+ }
10
+
11
+ public get(...args: Args): T {
12
+ if (this.value_ === NOT_MOUNTED_YET) this.value_ = this.closure_(...args);
13
+ return this.value_ as T;
14
+ }
15
+ }
16
+
17
+ const NOT_MOUNTED_YET = {};
@@ -1,14 +1,14 @@
1
- /** @internal */
2
- export namespace StringUtil {
3
- export const escapeDuplicate = (props: {
4
- keep: string[];
5
- input: string;
6
- escape?: (str: string) => string;
7
- }): string =>
8
- props.keep.includes(props.input)
9
- ? escapeDuplicate({
10
- keep: props.keep,
11
- input: (props.escape ?? ((str) => `_${str}`))(props.input),
12
- })
13
- : props.input;
14
- }
1
+ /** @internal */
2
+ export namespace StringUtil {
3
+ export const escapeDuplicate = (props: {
4
+ keep: string[];
5
+ input: string;
6
+ escape?: (str: string) => string;
7
+ }): string =>
8
+ props.keep.includes(props.input)
9
+ ? escapeDuplicate({
10
+ keep: props.keep,
11
+ input: (props.escape ?? ((str) => `_${str}`))(props.input),
12
+ })
13
+ : props.input;
14
+ }
@@ -1,57 +1,57 @@
1
- /**
2
- * Remove common leading whitespace from template literal.
3
- *
4
- * Strips leading/trailing blank lines and removes the minimum indentation level
5
- * from all lines.
6
- *
7
- * @author Jeongho Nam - https://github.com/samchon
8
- * @param strings Template literal strings
9
- * @param values Interpolated values
10
- * @returns Dedented string
11
- */
12
- export function dedent(
13
- strings: TemplateStringsArray,
14
- ...values: Array<boolean | number | string>
15
- ): string {
16
- // Combine all template string parts to understand the full structure
17
- let combined: string = strings[0]!;
18
- for (let i = 0; i < values.length; i++) {
19
- combined += `__PLACEHOLDER_${i}__` + strings[i + 1];
20
- }
21
-
22
- // Split into lines
23
- const lines = combined.split("\n");
24
-
25
- // Remove leading and trailing empty lines
26
- while (lines.length > 0 && lines[0]!.trim() === "") {
27
- lines.shift();
28
- }
29
- while (lines.length > 0 && lines[lines.length - 1]!.trim() === "") {
30
- lines.pop();
31
- }
32
-
33
- if (lines.length === 0) return "";
34
-
35
- // Find minimum indentation from non-empty lines
36
- const nonEmptyLines = lines.filter((line) => line.trim() !== "");
37
- const minIndent = Math.min(
38
- ...nonEmptyLines.map((line) => {
39
- const match = line.match(/^[ \t]*/);
40
- return match ? match[0].length : 0;
41
- }),
42
- );
43
-
44
- // Remove minimum indentation from all lines
45
- const dedentedLines = lines.map((line) => {
46
- if (line.trim() === "") return "";
47
- return line.slice(minIndent);
48
- });
49
-
50
- // Replace placeholders with actual values
51
- let result = dedentedLines.join("\n");
52
- for (let i = 0; i < values.length; i++) {
53
- result = result.replace(`__PLACEHOLDER_${i}__`, String(values[i]));
54
- }
55
-
56
- return result;
57
- }
1
+ /**
2
+ * Remove common leading whitespace from template literal.
3
+ *
4
+ * Strips leading/trailing blank lines and removes the minimum indentation level
5
+ * from all lines.
6
+ *
7
+ * @author Jeongho Nam - https://github.com/samchon
8
+ * @param strings Template literal strings
9
+ * @param values Interpolated values
10
+ * @returns Dedented string
11
+ */
12
+ export function dedent(
13
+ strings: TemplateStringsArray,
14
+ ...values: Array<boolean | number | string>
15
+ ): string {
16
+ // Combine all template string parts to understand the full structure
17
+ let combined: string = strings[0]!;
18
+ for (let i = 0; i < values.length; i++) {
19
+ combined += `__PLACEHOLDER_${i}__` + strings[i + 1];
20
+ }
21
+
22
+ // Split into lines
23
+ const lines = combined.split("\n");
24
+
25
+ // Remove leading and trailing empty lines
26
+ while (lines.length > 0 && lines[0]!.trim() === "") {
27
+ lines.shift();
28
+ }
29
+ while (lines.length > 0 && lines[lines.length - 1]!.trim() === "") {
30
+ lines.pop();
31
+ }
32
+
33
+ if (lines.length === 0) return "";
34
+
35
+ // Find minimum indentation from non-empty lines
36
+ const nonEmptyLines = lines.filter((line) => line.trim() !== "");
37
+ const minIndent = Math.min(
38
+ ...nonEmptyLines.map((line) => {
39
+ const match = line.match(/^[ \t]*/);
40
+ return match ? match[0].length : 0;
41
+ }),
42
+ );
43
+
44
+ // Remove minimum indentation from all lines
45
+ const dedentedLines = lines.map((line) => {
46
+ if (line.trim() === "") return "";
47
+ return line.slice(minIndent);
48
+ });
49
+
50
+ // Replace placeholders with actual values
51
+ let result = dedentedLines.join("\n");
52
+ for (let i = 0; i < values.length; i++) {
53
+ result = result.replace(`__PLACEHOLDER_${i}__`, String(values[i]));
54
+ }
55
+
56
+ return result;
57
+ }
@@ -1,8 +1,8 @@
1
- export * from "./ArrayUtil";
2
- export * from "./LlmJson";
3
- export * from "./MapUtil";
4
- export * from "./NamingConvention";
5
- export * from "./Singleton";
6
- export * from "./StringUtil";
7
-
8
- export * from "./dedent";
1
+ export * from "./ArrayUtil";
2
+ export * from "./LlmJson";
3
+ export * from "./MapUtil";
4
+ export * from "./NamingConvention";
5
+ export * from "./Singleton";
6
+ export * from "./StringUtil";
7
+
8
+ export * from "./dedent";