@nejs/basic-extensions 2.9.0 → 2.10.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.
Files changed (167) hide show
  1. package/dist/@nejs/basic-extensions.bundle.2.10.0.js +19 -0
  2. package/dist/@nejs/basic-extensions.bundle.2.10.0.js.map +7 -0
  3. package/dist/cjs/array.extensions.js +174 -0
  4. package/dist/cjs/array.extensions.js.map +1 -1
  5. package/dist/cjs/big.int.extension.js +1 -0
  6. package/dist/cjs/big.int.extension.js.map +1 -1
  7. package/dist/cjs/classes/descriptor.js +1 -1
  8. package/dist/cjs/classes/descriptor.js.map +1 -1
  9. package/dist/cjs/classes/index.d.ts +1 -0
  10. package/dist/cjs/classes/index.js +3 -0
  11. package/dist/cjs/classes/index.js.map +1 -1
  12. package/dist/cjs/classes/iterable.d.ts +44 -0
  13. package/dist/cjs/classes/iterable.js +64 -0
  14. package/dist/cjs/classes/iterable.js.map +1 -1
  15. package/dist/cjs/classes/param.parser.d.ts +10 -10
  16. package/dist/cjs/classes/property.d.ts +86 -0
  17. package/dist/cjs/classes/property.js +284 -0
  18. package/dist/cjs/classes/property.js.map +1 -0
  19. package/dist/cjs/classes/symkeys.d.ts +68 -11
  20. package/dist/cjs/classes/symkeys.js +103 -17
  21. package/dist/cjs/classes/symkeys.js.map +1 -1
  22. package/dist/cjs/classes/type.d.ts +4 -4
  23. package/dist/cjs/function.extensions.js +1 -0
  24. package/dist/cjs/function.extensions.js.map +1 -1
  25. package/dist/cjs/global.this.js +29 -0
  26. package/dist/cjs/global.this.js.map +1 -1
  27. package/dist/cjs/index.d.ts +2 -0
  28. package/dist/cjs/index.js +18 -0
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/json.extensions.js +19 -18
  31. package/dist/cjs/json.extensions.js.map +1 -1
  32. package/dist/cjs/map.extensions.js +1 -0
  33. package/dist/cjs/map.extensions.js.map +1 -1
  34. package/dist/cjs/number.extension.js +1 -0
  35. package/dist/cjs/number.extension.js.map +1 -1
  36. package/dist/cjs/object.extensions.d.ts +0 -29
  37. package/dist/cjs/object.extensions.js +218 -255
  38. package/dist/cjs/object.extensions.js.map +1 -1
  39. package/dist/cjs/set.extensions.js +1 -0
  40. package/dist/cjs/set.extensions.js.map +1 -1
  41. package/dist/cjs/string.extensions.js +474 -469
  42. package/dist/cjs/string.extensions.js.map +1 -1
  43. package/dist/cjs/symbol.extensions.js +386 -31
  44. package/dist/cjs/symbol.extensions.js.map +1 -1
  45. package/dist/cjs/utils/copy.object.d.ts +408 -0
  46. package/dist/cjs/utils/copy.object.js +720 -0
  47. package/dist/cjs/utils/copy.object.js.map +1 -0
  48. package/dist/cjs/utils/index.d.ts +1 -0
  49. package/dist/cjs/utils/index.js +19 -0
  50. package/dist/cjs/utils/index.js.map +1 -0
  51. package/dist/cjs/utils/toolkit.d.ts +1897 -0
  52. package/dist/cjs/utils/toolkit.js +1377 -0
  53. package/dist/cjs/utils/toolkit.js.map +1 -0
  54. package/dist/mjs/array.extensions.js +174 -0
  55. package/dist/mjs/array.extensions.js.map +1 -1
  56. package/dist/mjs/big.int.extension.js +1 -0
  57. package/dist/mjs/big.int.extension.js.map +1 -1
  58. package/dist/mjs/classes/descriptor.js +1 -1
  59. package/dist/mjs/classes/descriptor.js.map +1 -1
  60. package/dist/mjs/classes/index.d.ts +1 -0
  61. package/dist/mjs/classes/index.js +3 -0
  62. package/dist/mjs/classes/index.js.map +1 -1
  63. package/dist/mjs/classes/iterable.d.ts +44 -0
  64. package/dist/mjs/classes/iterable.js +64 -0
  65. package/dist/mjs/classes/iterable.js.map +1 -1
  66. package/dist/mjs/classes/param.parser.d.ts +10 -10
  67. package/dist/mjs/classes/property.d.ts +86 -0
  68. package/dist/mjs/classes/property.js +280 -0
  69. package/dist/mjs/classes/property.js.map +1 -0
  70. package/dist/mjs/classes/symkeys.d.ts +68 -11
  71. package/dist/mjs/classes/symkeys.js +103 -17
  72. package/dist/mjs/classes/symkeys.js.map +1 -1
  73. package/dist/mjs/classes/type.d.ts +4 -4
  74. package/dist/mjs/function.extensions.js +1 -0
  75. package/dist/mjs/function.extensions.js.map +1 -1
  76. package/dist/mjs/global.this.js +6 -0
  77. package/dist/mjs/global.this.js.map +1 -1
  78. package/dist/mjs/index.d.ts +2 -0
  79. package/dist/mjs/index.js +4 -0
  80. package/dist/mjs/index.js.map +1 -1
  81. package/dist/mjs/json.extensions.js +19 -18
  82. package/dist/mjs/json.extensions.js.map +1 -1
  83. package/dist/mjs/map.extensions.js +1 -0
  84. package/dist/mjs/map.extensions.js.map +1 -1
  85. package/dist/mjs/number.extension.js +1 -0
  86. package/dist/mjs/number.extension.js.map +1 -1
  87. package/dist/mjs/object.extensions.d.ts +0 -29
  88. package/dist/mjs/object.extensions.js +215 -251
  89. package/dist/mjs/object.extensions.js.map +1 -1
  90. package/dist/mjs/set.extensions.js +1 -0
  91. package/dist/mjs/set.extensions.js.map +1 -1
  92. package/dist/mjs/string.extensions.js +474 -469
  93. package/dist/mjs/string.extensions.js.map +1 -1
  94. package/dist/mjs/symbol.extensions.js +386 -31
  95. package/dist/mjs/symbol.extensions.js.map +1 -1
  96. package/dist/mjs/utils/copy.object.d.ts +408 -0
  97. package/dist/mjs/utils/copy.object.js +702 -0
  98. package/dist/mjs/utils/copy.object.js.map +1 -0
  99. package/dist/mjs/utils/index.d.ts +1 -0
  100. package/dist/mjs/utils/index.js +3 -0
  101. package/dist/mjs/utils/index.js.map +1 -0
  102. package/dist/mjs/utils/toolkit.d.ts +1897 -0
  103. package/dist/mjs/utils/toolkit.js +1372 -0
  104. package/dist/mjs/utils/toolkit.js.map +1 -0
  105. package/package.json +29 -37
  106. package/repl.bootstrap.js +12 -1
  107. package/src/array.extensions.js +191 -1
  108. package/src/big.int.extension.js +3 -1
  109. package/src/classes/descriptor.js +1 -1
  110. package/src/classes/index.js +4 -0
  111. package/src/classes/iterable.js +74 -0
  112. package/src/classes/property.js +333 -0
  113. package/src/classes/symkeys.js +120 -19
  114. package/src/function.extensions.js +2 -0
  115. package/src/global.this.js +8 -0
  116. package/src/index.js +5 -0
  117. package/src/json.extensions.js +18 -19
  118. package/src/map.extensions.js +3 -1
  119. package/src/number.extension.js +3 -1
  120. package/src/object.extensions.js +240 -277
  121. package/src/set.extensions.js +3 -1
  122. package/src/string.extensions.js +512 -506
  123. package/src/symbol.extensions.js +412 -29
  124. package/src/utils/copy.object.js +780 -0
  125. package/src/utils/index.js +2 -0
  126. package/src/utils/toolkit.js +1471 -0
  127. package/tests/arrayextensions.test.js +2 -0
  128. package/tests/index.test.js +1 -0
  129. package/tests/newClasses/asyncIterable.test.js +2 -0
  130. package/tests/newClasses/deferred.test.js +5 -3
  131. package/tests/newClasses/descriptor.test.js +2 -0
  132. package/tests/newClasses/iterable.test.js +2 -0
  133. package/tests/newClasses/refmap.test.js +2 -1
  134. package/tests/newClasses/refset.test.js +2 -0
  135. package/tests/objectextensions.test.js +2 -0
  136. package/tests/setextensions.test.js +2 -0
  137. package/tests/stringextensions.test.js +1 -0
  138. package/tests/utils/toolkit.test.js +223 -0
  139. package/tsconfig.base.json +1 -1
  140. package/vitest.config.js +7 -0
  141. package/dist/@nejs/basic-extensions.bundle.2.8.0.js +0 -19
  142. package/dist/@nejs/basic-extensions.bundle.2.8.0.js.map +0 -7
  143. package/docs/assets/anchor.js +0 -350
  144. package/docs/assets/bass-addons.css +0 -12
  145. package/docs/assets/bass.css +0 -544
  146. package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
  147. package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
  148. package/docs/assets/fonts/LICENSE.txt +0 -93
  149. package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
  150. package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
  151. package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
  152. package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
  153. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
  154. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
  155. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
  156. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
  157. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
  158. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
  159. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
  160. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
  161. package/docs/assets/fonts/source-code-pro.css +0 -23
  162. package/docs/assets/github.css +0 -123
  163. package/docs/assets/site.js +0 -168
  164. package/docs/assets/split.css +0 -15
  165. package/docs/assets/split.js +0 -782
  166. package/docs/assets/style.css +0 -147
  167. package/docs/index.html +0 -35485
@@ -11,549 +11,553 @@ const parenthesisPair = ['(', ')']
11
11
  * utility functions.
12
12
  */
13
13
  export const StringExtensions = new Patch(String, {
14
- /**
15
- * The `isString` method does exactly what one would it expect. It returns
16
- * true if the string matches typeof or instanceof as a string.
17
- *
18
- * @param {*} value checks to see if the `value` is a string
19
- * @returns {boolean} `true` if it is a `String`, `false` otherwise
20
- */
21
- isString(value) {
22
- return (
23
- value !== null && value !== undefined &&
24
- (typeof value === 'string' || value instanceof String)
25
- )
26
- },
27
-
28
- /**
29
- * Conditionally returns a value based on whether the supplied
30
- * `value` is a `String` or not. If the `value` is a `String`,
31
- * the `thenValue` will be returned. If it is not a `String`,
32
- * the `elseValue` will be returned instead.
33
- *
34
- * @param {any} value the value to check to determine if it is a
35
- * `String`
36
- * @param {any} thenValue the value to return if the supplied
37
- * `value` is a `String`
38
- * @param {any} elseValue the value to return if the supplied
39
- * `value` is not a `String`
40
- * @returns {any} either the `thenValue` or `elseValue` depending
41
- * on if the supplied `value` is a `String`
42
- *
43
- * @example
44
- * const str = 'hello'
45
- * const num = 42
46
- * ifString(str, 'is a string', 'not a string') // 'is a string'
47
- * ifString(num, 'is a string', 'not a string') // 'not a string'
48
- */
49
- ifString(value, thenValue, elseValue) {
50
- return isThenElse(this.isString(value), thenValue, elseValue)
51
- },
14
+ [Patch.kMutablyHidden]: {
15
+ /**
16
+ * The `isString` method does exactly what one would it expect. It returns
17
+ * true if the string matches typeof or instanceof as a string.
18
+ *
19
+ * @param {*} value checks to see if the `value` is a string
20
+ * @returns {boolean} `true` if it is a `String`, `false` otherwise
21
+ */
22
+ isString(value) {
23
+ return (
24
+ value !== null && value !== undefined &&
25
+ (typeof value === 'string' || value instanceof String)
26
+ )
27
+ },
52
28
 
53
- /**
54
- * A getter property that returns a pair of parentheses as an array.
55
- * This property can be used when operations require a clear distinction
56
- * between the opening and closing parentheses, such as parsing or
57
- * matching balanced expressions in strings.
58
- *
59
- * @returns {[string, string]} An array containing a pair of strings: the
60
- * opening parenthesis '(' as the first element, and the closing parenthesis
61
- * ')' as the second element.
62
- */
63
- get parenthesisPair() {
64
- return ['(', ')'];
65
- },
29
+ /**
30
+ * Conditionally returns a value based on whether the supplied
31
+ * `value` is a `String` or not. If the `value` is a `String`,
32
+ * the `thenValue` will be returned. If it is not a `String`,
33
+ * the `elseValue` will be returned instead.
34
+ *
35
+ * @param {any} value the value to check to determine if it is a
36
+ * `String`
37
+ * @param {any} thenValue the value to return if the supplied
38
+ * `value` is a `String`
39
+ * @param {any} elseValue the value to return if the supplied
40
+ * `value` is not a `String`
41
+ * @returns {any} either the `thenValue` or `elseValue` depending
42
+ * on if the supplied `value` is a `String`
43
+ *
44
+ * @example
45
+ * const str = 'hello'
46
+ * const num = 42
47
+ * ifString(str, 'is a string', 'not a string') // 'is a string'
48
+ * ifString(num, 'is a string', 'not a string') // 'not a string'
49
+ */
50
+ ifString(value, thenValue, elseValue) {
51
+ return isThenElse(String.isString(value), thenValue, elseValue)
52
+ },
66
53
 
67
- /**
68
- * A getter property that returns a pair of square brackets as an array.
69
- * This property is particularly useful for operations that require a clear
70
- * distinction between the opening and closing square brackets, such as
71
- * parsing arrays in strings or matching balanced expressions within
72
- * square brackets.
73
- *
74
- * @returns {[string, string]} An array containing a pair of strings: the
75
- * opening square bracket '[' as the first element, and the closing square
76
- * bracket ']' as the second element.
77
- */
78
- get squareBracketsPair() {
79
- return ['[', ']'];
80
- },
54
+ /**
55
+ * A getter property that returns a pair of parentheses as an array.
56
+ * This property can be used when operations require a clear distinction
57
+ * between the opening and closing parentheses, such as parsing or
58
+ * matching balanced expressions in strings.
59
+ *
60
+ * @returns {[string, string]} An array containing a pair of strings: the
61
+ * opening parenthesis '(' as the first element, and the closing parenthesis
62
+ * ')' as the second element.
63
+ */
64
+ get parenthesisPair() {
65
+ return ['(', ')'];
66
+ },
81
67
 
82
- /**
83
- * A getter property that returns a pair of curly brackets as an array.
84
- * This property is particularly useful for operations that require a clear
85
- * distinction between the opening and closing curly brackets, such as
86
- * parsing objects in strings or matching balanced expressions within
87
- * curly brackets. The returned array consists of the opening curly bracket
88
- * '{' as the first element, and the closing curly bracket '}' as the
89
- * second element.
90
- *
91
- * @returns {[string, string]} An array containing a pair of strings: the
92
- * opening curly bracket '{' as the first element, and the closing curly
93
- * bracket '}' as the second element.
94
- */
95
- get curlyBracketsPair() {
96
- return ['{', '}'];
97
- },
68
+ /**
69
+ * A getter property that returns a pair of square brackets as an array.
70
+ * This property is particularly useful for operations that require a clear
71
+ * distinction between the opening and closing square brackets, such as
72
+ * parsing arrays in strings or matching balanced expressions within
73
+ * square brackets.
74
+ *
75
+ * @returns {[string, string]} An array containing a pair of strings: the
76
+ * opening square bracket '[' as the first element, and the closing square
77
+ * bracket ']' as the second element.
78
+ */
79
+ get squareBracketsPair() {
80
+ return ['[', ']'];
81
+ },
98
82
 
99
- /**
100
- * Generates a random string using base 36 (numbers and lowercase letters).
101
- * This method is useful when you need a random string that includes both
102
- * numbers and letters. The generated string does not include the leading
103
- * '0.' that is part of the string representation of a random number in
104
- * base 36.
105
- *
106
- * @returns {string} A random string of characters in base 36.
107
- *
108
- * @example
109
- * const randomStr = StringExtensions.random36();
110
- * console.log(randomStr); // Output: "3n5yzxjkf2o"
111
- */
112
- random36() {
113
- return Math.random().toString(36).slice(2)
114
- },
83
+ /**
84
+ * A getter property that returns a pair of curly brackets as an array.
85
+ * This property is particularly useful for operations that require a clear
86
+ * distinction between the opening and closing curly brackets, such as
87
+ * parsing objects in strings or matching balanced expressions within
88
+ * curly brackets. The returned array consists of the opening curly bracket
89
+ * '{' as the first element, and the closing curly bracket '}' as the
90
+ * second element.
91
+ *
92
+ * @returns {[string, string]} An array containing a pair of strings: the
93
+ * opening curly bracket '{' as the first element, and the closing curly
94
+ * bracket '}' as the second element.
95
+ */
96
+ get curlyBracketsPair() {
97
+ return ['{', '}'];
98
+ },
115
99
 
116
- /**
117
- * Generates a random string using base 16 (hexadecimal numbers).
118
- * This method is useful when you need a random string that includes both
119
- * numbers and letters in hexadecimal format. The generated string does not
120
- * include the leading '0.' that is part of the string representation of a
121
- * random number in base 16.
122
- *
123
- * @returns {string} A random string of characters in base 16.
124
- *
125
- * @example
126
- * const randomStr = StringExtensions.random16();
127
- * console.log(randomStr); // Output: "3a5f4c"
128
- */
129
- random16() {
130
- return Math.random().toString(16).slice(2)
131
- },
100
+ /**
101
+ * Generates a random string using base 36 (numbers and lowercase letters).
102
+ * This method is useful when you need a random string that includes both
103
+ * numbers and letters. The generated string does not include the leading
104
+ * '0.' that is part of the string representation of a random number in
105
+ * base 36.
106
+ *
107
+ * @returns {string} A random string of characters in base 36.
108
+ *
109
+ * @example
110
+ * const randomStr = StringExtensions.random36();
111
+ * console.log(randomStr); // Output: "3n5yzxjkf2o"
112
+ */
113
+ random36() {
114
+ return Math.random().toString(36).slice(2)
115
+ },
132
116
 
133
- /**
134
- * Generates a random RGB color code.
135
- *
136
- * This method generates a random hexadecimal number, slices off the
137
- * leading '0.' and takes the first 6 characters. It then pads the
138
- * end of the string with '0' until it is 6 characters long. The
139
- * result is a string that can be used as a color code in CSS.
140
- *
141
- * @param {string} [prefix='#'] - The prefix to prepend to the color
142
- * code. Defaults to '#'.
143
- *
144
- * @returns {string} A random RGB color code.
145
- *
146
- * @example
147
- * const randomColor = StringExtensions.randomRGB();
148
- * console.log(randomColor); // Output: "#3a5f4c"
149
- */
150
- randomRGBHex(prefix = '#') {
151
- const hex = Math.random().toString(16).slice(2).substring(0,6)
152
- return `${prefix}${hex.padEnd(6, '0')}`
153
- },
117
+ /**
118
+ * Generates a random string using base 16 (hexadecimal numbers).
119
+ * This method is useful when you need a random string that includes both
120
+ * numbers and letters in hexadecimal format. The generated string does not
121
+ * include the leading '0.' that is part of the string representation of a
122
+ * random number in base 16.
123
+ *
124
+ * @returns {string} A random string of characters in base 16.
125
+ *
126
+ * @example
127
+ * const randomStr = StringExtensions.random16();
128
+ * console.log(randomStr); // Output: "3a5f4c"
129
+ */
130
+ random16() {
131
+ return Math.random().toString(16).slice(2)
132
+ },
154
133
 
155
- /**
156
- * Generates a random ARGB color code.
157
- *
158
- * This method generates a random hexadecimal number, slices off the
159
- * leading '0.' and takes the first 8 characters. It then pads the
160
- * start of the string with '0' until it is 6 characters long and the
161
- * end of the string with '0' until it is 8 characters long. The
162
- * result is a string that can be used as a color code in CSS.
163
- *
164
- * @param {string} [prefix='#'] - The prefix to prepend to the color
165
- * code. Defaults to '#'.
166
- *
167
- * @returns {string} A random ARGB color code.
168
- *
169
- * @example
170
- * const randomColor = StringExtensions.randomARGB();
171
- * console.log(randomColor); // Output: "#3a5f4c00"
172
- */
173
- randomARGBHex(prefix = '#') {
174
- const hex = Math.random().toString(16).slice(2).substring(0,8)
175
- return `${prefix}${hex.padStart(6, '0').padEnd(8, '0')}`
176
- },
134
+ /**
135
+ * Generates a random RGB color code.
136
+ *
137
+ * This method generates a random hexadecimal number, slices off the
138
+ * leading '0.' and takes the first 6 characters. It then pads the
139
+ * end of the string with '0' until it is 6 characters long. The
140
+ * result is a string that can be used as a color code in CSS.
141
+ *
142
+ * @param {string} [prefix='#'] - The prefix to prepend to the color
143
+ * code. Defaults to '#'.
144
+ *
145
+ * @returns {string} A random RGB color code.
146
+ *
147
+ * @example
148
+ * const randomColor = StringExtensions.randomRGB();
149
+ * console.log(randomColor); // Output: "#3a5f4c"
150
+ */
151
+ randomRGBHex(prefix = '#') {
152
+ const hex = Math.random().toString(16).slice(2).substring(0,6)
153
+ return `${prefix}${hex.padEnd(6, '0')}`
154
+ },
177
155
 
178
- /**
179
- * Generates a random RGBA color code.
180
- *
181
- * This method generates a random hexadecimal number, slices off the
182
- * leading '0.' and takes the first 8 characters. It then pads the
183
- * start of the string with '0' until it is 6 characters long and the
184
- * end of the string with '0' until it is 8 characters long. The
185
- * result is a string that can be used as a color code in CSS.
186
- *
187
- * @param {string} [prefix='#'] - The prefix to prepend to the color
188
- * code. Defaults to '#'.
189
- *
190
- * @returns {string} A random RGBA color code.
191
- *
192
- * @example
193
- * const randomColor = StringExtensions.randomRGBA();
194
- * console.log(randomColor); // Output: "#3a5f4c00"
195
- */
196
- randomRGBAHex(prefix = '#') {
197
- const hex = Math.random().toString(16).slice(2).substring(0,8)
198
- return `${prefix}${hex.padStart(6, '0').padStart(8, '0')}`
199
- },
156
+ /**
157
+ * Generates a random ARGB color code.
158
+ *
159
+ * This method generates a random hexadecimal number, slices off the
160
+ * leading '0.' and takes the first 8 characters. It then pads the
161
+ * start of the string with '0' until it is 6 characters long and the
162
+ * end of the string with '0' until it is 8 characters long. The
163
+ * result is a string that can be used as a color code in CSS.
164
+ *
165
+ * @param {string} [prefix='#'] - The prefix to prepend to the color
166
+ * code. Defaults to '#'.
167
+ *
168
+ * @returns {string} A random ARGB color code.
169
+ *
170
+ * @example
171
+ * const randomColor = StringExtensions.randomARGB();
172
+ * console.log(randomColor); // Output: "#3a5f4c00"
173
+ */
174
+ randomARGBHex(prefix = '#') {
175
+ const hex = Math.random().toString(16).slice(2).substring(0,8)
176
+ return `${prefix}${hex.padStart(6, '0').padEnd(8, '0')}`
177
+ },
200
178
 
201
- /**
202
- * Generates a random RGB color code.
203
- *
204
- * This method generates a random hexadecimal number, slices off the
205
- * leading '0.' and pads the end of the string with '0' until it is
206
- * 8 characters long. It then parses the first 6 characters into
207
- * three separate 2-character strings, each representing a color
208
- * component (red, green, blue) in hexadecimal format. These strings
209
- * are then converted into decimal format and used to construct an
210
- * RGB color code.
211
- *
212
- * @returns {string} A random RGB color code.
213
- *
214
- * @example
215
- * const randomColor = StringExtensions.randomRGB();
216
- * console.log(randomColor); // Output: "rgb(58,95,76)"
217
- */
218
- randomRGB() {
219
- const hex = Math.random().toString(16).slice(2).padEnd(8, '0')
220
- const red = parseInt(hex.substring(0,2), 16)
221
- const green = parseInt(hex.substring(2,4), 16)
222
- const blue = parseInt(hex.substring(4, 6), 16)
223
- return `rgb(${red}, ${green}, ${blue})`
224
- },
179
+ /**
180
+ * Generates a random RGBA color code.
181
+ *
182
+ * This method generates a random hexadecimal number, slices off the
183
+ * leading '0.' and takes the first 8 characters. It then pads the
184
+ * start of the string with '0' until it is 6 characters long and the
185
+ * end of the string with '0' until it is 8 characters long. The
186
+ * result is a string that can be used as a color code in CSS.
187
+ *
188
+ * @param {string} [prefix='#'] - The prefix to prepend to the color
189
+ * code. Defaults to '#'.
190
+ *
191
+ * @returns {string} A random RGBA color code.
192
+ *
193
+ * @example
194
+ * const randomColor = StringExtensions.randomRGBA();
195
+ * console.log(randomColor); // Output: "#3a5f4c00"
196
+ */
197
+ randomRGBAHex(prefix = '#') {
198
+ const hex = Math.random().toString(16).slice(2).substring(0,8)
199
+ return `${prefix}${hex.padStart(6, '0').padStart(8, '0')}`
200
+ },
225
201
 
226
- /**
227
- * Generates a random RGBA color code with optional forced color values.
228
- *
229
- * This method generates a random hexadecimal number, slices off the
230
- * leading '0.' and pads the end of the string with '0' until it is
231
- * 8 characters long. It then parses the first 8 characters into
232
- * four separate 2-character strings, each representing a color
233
- * component (red, green, blue, alpha) in hexadecimal format. These strings
234
- * are then converted into decimal format and used to construct an
235
- * RGBA color code.
236
- *
237
- * If a color component is provided in the `force` parameter, it will
238
- * be used instead of a random value for that component.
239
- *
240
- * @param {Object} force - An object with properties for each color
241
- * component (red, green, blue, alpha) that should be forced to a
242
- * specific value. If a property is undefined or not provided, a
243
- * random value will be used for that component.
244
- * @param {number} force.red - The red component (0-255).
245
- * @param {number} force.green - The green component (0-255).
246
- * @param {number} force.blue - The blue component (0-255).
247
- * @param {number} force.alpha - The alpha component (0.0-1.0).
248
- *
249
- * @returns {string} A random RGBA color code.
250
- *
251
- * @example
252
- * const randomColor = StringExtensions.randomRGBA();
253
- * console.log(randomColor); // Output: "rgba(58,95,76,0.50)"
254
- *
255
- * const forcedGreen = StringExtensions.randomRGBA({ green: 255 });
256
- * console.log(forcedGreen); // Output: "rgba(58,255,76,0.50)"
257
- */
258
- randomRGBA(
259
- force = {
260
- red: undefined,
261
- green: undefined,
262
- blue: undefined,
263
- alpha: undefined
264
- }
265
- ) {
266
- const hex = Math.random().toString(16).slice(2).padEnd(8, '0')
267
- const red = force.red ?? parseInt(hex.substring(0,2), 16)
268
- const green = force.green ?? parseInt(hex.substring(2,4), 16)
269
- const blue = force.blue ?? parseInt(hex.substring(4, 6), 16)
270
- const alpha = force.alpha ??
271
- (parseInt(hex.substring(6, 8), 16) / 255.0) * 1.0
272
-
273
- return `rgba(${red}, ${green}, ${blue}, ${alpha.toFixed(2)})`
274
- },
202
+ /**
203
+ * Generates a random RGB color code.
204
+ *
205
+ * This method generates a random hexadecimal number, slices off the
206
+ * leading '0.' and pads the end of the string with '0' until it is
207
+ * 8 characters long. It then parses the first 6 characters into
208
+ * three separate 2-character strings, each representing a color
209
+ * component (red, green, blue) in hexadecimal format. These strings
210
+ * are then converted into decimal format and used to construct an
211
+ * RGB color code.
212
+ *
213
+ * @returns {string} A random RGB color code.
214
+ *
215
+ * @example
216
+ * const randomColor = StringExtensions.randomRGB();
217
+ * console.log(randomColor); // Output: "rgb(58,95,76)"
218
+ */
219
+ randomRGB() {
220
+ const hex = Math.random().toString(16).slice(2).padEnd(8, '0')
221
+ const red = parseInt(hex.substring(0,2), 16)
222
+ const green = parseInt(hex.substring(2,4), 16)
223
+ const blue = parseInt(hex.substring(4, 6), 16)
224
+ return `rgb(${red}, ${green}, ${blue})`
225
+ },
275
226
 
276
- /**
277
- * Applies Select Graphic Rendition (SGR) parameters to a given message for
278
- * styling in terminal environments. This function allows for the dynamic
279
- * styling of text output using ANSI escape codes. It supports a variety of
280
- * modes such as color, brightness, and text decorations like bold or underline.
281
- *
282
- * @param {string} message The message to be styled.
283
- * @param {...string} useModes A series of strings representing the desired
284
- * styling modes. Modes can include colors (e.g., 'red', 'blue'), brightness
285
- * ('bright'), foreground/background ('fg', 'bg'), and text decorations
286
- * ('bold', 'underline'). Modes can be combined in a single string using
287
- * commas or passed as separate arguments.
288
- *
289
- * Colors:
290
- * ```
291
- * 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
292
- * ```
293
- * Color Specifiers:
294
- * ```
295
- * 'fg' -> foreground | 'bg' -> background | 'bright' -> bright colors
296
- * ```
297
- *
298
- * Modes:
299
- * ```
300
- * 'blink' or 'k' | 'conceal' or 'c' | 'italics' or 'i' | 'strike' or 's'
301
- * 'bold' or 'b' | 'dim' or 'd' | 'negative' or 'n' | 'underline' or 'u'
302
- * ```
303
- *
304
- * Examples:
305
- * - `sgr('Hello', 'red')` applies red color to 'Hello'.
306
- * - `sgr('World', 'green,bold')` applies green color and bold styling
307
- * to 'World'.
308
- * - `sgr('Example', 'bluebgbright')` applies bright blue
309
- * background color.
310
- *
311
- * Short hand syntax is also allowed:
312
- * - `sgr('hello', 'biu')` applies bold, italics and underline
313
- * - `sgr('hello', 'bi,redfg')` applies bold, italics and red foreground
314
- *
315
- * As a bonus, there is a secret getter applied to the return string that
316
- * allows you to invoke `sgr(...).show` to automatically log the output to
317
- * `console.log`. This is done by wrapping the output string in `Object()`
318
- * to make it a `String` instance and then adding the property descriptor.
319
- * A custom `Symbol` is applied to make it evaluate in nodejs as though it
320
- * were a normal string. To strip the extras, wrap the output in `String()`
321
- *
322
- * @returns {string} The message wrapped in ANSI escape codes corresponding
323
- * to the specified modes. The returned string, when printed to a terminal,
324
- * displays the styled message. Additional properties are attached to the
325
- * result for utility purposes, such as 'show' for immediate console output.
326
- */
327
- sgr(message, ...useModes) {
328
- const colors = Object.assign(
329
- ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'],
330
- {
331
- isBG: a => !!/bg/i.exec(a),
332
- isBright: a => !!/bright/i.exec(a),
333
- isColor: a => {
334
- let color = colors.find(c => new RegExp(c, 'i').exec(a));
335
- return [!!color, colors.indexOf(color)];
336
- },
227
+ /**
228
+ * Generates a random RGBA color code with optional forced color values.
229
+ *
230
+ * This method generates a random hexadecimal number, slices off the
231
+ * leading '0.' and pads the end of the string with '0' until it is
232
+ * 8 characters long. It then parses the first 8 characters into
233
+ * four separate 2-character strings, each representing a color
234
+ * component (red, green, blue, alpha) in hexadecimal format. These strings
235
+ * are then converted into decimal format and used to construct an
236
+ * RGBA color code.
237
+ *
238
+ * If a color component is provided in the `force` parameter, it will
239
+ * be used instead of a random value for that component.
240
+ *
241
+ * @param {Object} force - An object with properties for each color
242
+ * component (red, green, blue, alpha) that should be forced to a
243
+ * specific value. If a property is undefined or not provided, a
244
+ * random value will be used for that component.
245
+ * @param {number} force.red - The red component (0-255).
246
+ * @param {number} force.green - The green component (0-255).
247
+ * @param {number} force.blue - The blue component (0-255).
248
+ * @param {number} force.alpha - The alpha component (0.0-1.0).
249
+ *
250
+ * @returns {string} A random RGBA color code.
251
+ *
252
+ * @example
253
+ * const randomColor = StringExtensions.randomRGBA();
254
+ * console.log(randomColor); // Output: "rgba(58,95,76,0.50)"
255
+ *
256
+ * const forcedGreen = StringExtensions.randomRGBA({ green: 255 });
257
+ * console.log(forcedGreen); // Output: "rgba(58,255,76,0.50)"
258
+ */
259
+ randomRGBA(
260
+ force = {
261
+ red: undefined,
262
+ green: undefined,
263
+ blue: undefined,
264
+ alpha: undefined
337
265
  }
338
- );
266
+ ) {
267
+ const hex = Math.random().toString(16).slice(2).padEnd(8, '0')
268
+ const red = force.red ?? parseInt(hex.substring(0,2), 16)
269
+ const green = force.green ?? parseInt(hex.substring(2,4), 16)
270
+ const blue = force.blue ?? parseInt(hex.substring(4, 6), 16)
271
+ const alpha = force.alpha ??
272
+ (parseInt(hex.substring(6, 8), 16) / 255.0) * 1.0
273
+
274
+ return `rgba(${red}, ${green}, ${blue}, ${alpha.toFixed(2)})`
275
+ },
339
276
 
340
- const arrayifyString = s => {
341
- if (Array.isArray(s)) {
342
- let results = [];
277
+ /**
278
+ * Applies Select Graphic Rendition (SGR) parameters to a given message for
279
+ * styling in terminal environments. This function allows for the dynamic
280
+ * styling of text output using ANSI escape codes. It supports a variety of
281
+ * modes such as color, brightness, and text decorations like bold or underline.
282
+ *
283
+ * @param {string} message The message to be styled.
284
+ * @param {...string} useModes A series of strings representing the desired
285
+ * styling modes. Modes can include colors (e.g., 'red', 'blue'), brightness
286
+ * ('bright'), foreground/background ('fg', 'bg'), and text decorations
287
+ * ('bold', 'underline'). Modes can be combined in a single string using
288
+ * commas or passed as separate arguments.
289
+ *
290
+ * Colors:
291
+ * ```
292
+ * 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
293
+ * ```
294
+ * Color Specifiers:
295
+ * ```
296
+ * 'fg' -> foreground | 'bg' -> background | 'bright' -> bright colors
297
+ * ```
298
+ *
299
+ * Modes:
300
+ * ```
301
+ * 'blink' or 'k' | 'conceal' or 'c' | 'italics' or 'i' | 'strike' or 's'
302
+ * 'bold' or 'b' | 'dim' or 'd' | 'negative' or 'n' | 'underline' or 'u'
303
+ * ```
304
+ *
305
+ * Examples:
306
+ * - `sgr('Hello', 'red')` applies red color to 'Hello'.
307
+ * - `sgr('World', 'green,bold')` applies green color and bold styling
308
+ * to 'World'.
309
+ * - `sgr('Example', 'bluebgbright')` applies bright blue
310
+ * background color.
311
+ *
312
+ * Short hand syntax is also allowed:
313
+ * - `sgr('hello', 'biu')` applies bold, italics and underline
314
+ * - `sgr('hello', 'bi,redfg')` applies bold, italics and red foreground
315
+ *
316
+ * As a bonus, there is a secret getter applied to the return string that
317
+ * allows you to invoke `sgr(...).show` to automatically log the output to
318
+ * `console.log`. This is done by wrapping the output string in `Object()`
319
+ * to make it a `String` instance and then adding the property descriptor.
320
+ * A custom `Symbol` is applied to make it evaluate in nodejs as though it
321
+ * were a normal string. To strip the extras, wrap the output in `String()`
322
+ *
323
+ * @returns {string} The message wrapped in ANSI escape codes corresponding
324
+ * to the specified modes. The returned string, when printed to a terminal,
325
+ * displays the styled message. Additional properties are attached to the
326
+ * result for utility purposes, such as 'show' for immediate console output.
327
+ */
328
+ sgr(message, ...useModes) {
329
+ const colors = Object.assign(
330
+ ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'],
331
+ {
332
+ isBG: a => !!/bg/i.exec(a),
333
+ isBright: a => !!/bright/i.exec(a),
334
+ isColor: a => {
335
+ let color = colors.find(c => new RegExp(c, 'i').exec(a));
336
+ return [!!color, colors.indexOf(color)];
337
+ },
338
+ }
339
+ );
340
+
341
+ const arrayifyString = s => {
342
+ if (Array.isArray(s)) {
343
+ let results = [];
343
344
 
344
- for (const i of s) {
345
- results = [ ...results, ...arrayifyString(i) ];
345
+ for (const i of s) {
346
+ results = [ ...results, ...arrayifyString(i) ];
347
+ }
348
+
349
+ return results.flat().filter(i => i.length);
346
350
  }
347
351
 
348
- return results.flat().filter(i => i.length);
352
+ if (!s || typeof s !== 'string') {
353
+ return [''];
354
+ }
355
+ else if (s.includes(',')) {
356
+ return arrayifyString(s.split(','));
357
+ }
358
+ else {
359
+ if (!colors.isColor(s)[0] && s.length > 1) {
360
+ return [...s];
361
+ }
362
+ else return [s];
363
+ }
349
364
  }
350
365
 
351
- if (!s || typeof s !== 'string') {
352
- return [''];
353
- }
354
- else if (s.includes(',')) {
355
- return arrayifyString(s.split(','));
356
- }
357
- else {
358
- if (!colors.isColor(s)[0] && s.length > 1) {
359
- return [...s];
366
+ let modes = arrayifyString(useModes)
367
+
368
+ const sgrModes = {
369
+ blink: ['\x1b[5m', '\x1b[25m', 'k'],
370
+ bold: ['\x1b[1m', '\x1b[22m', 'b'],
371
+ conceal: ['\x1b[8m', '\x1b[28m', 'c'],
372
+ dim: ['\x1b[2m', '\x1b[22m', 'd'],
373
+ italics: ['\x1b[3m', '\x1b[23m', 'i'],
374
+ negative: ['\x1b[7m', '\x1b[27m', 'n'],
375
+ strike: ['\x1b[9m', '\x1b[29m', 's'],
376
+ underline: ['\x1b[4m', '\x1b[24m', 'u'],
377
+ };
378
+
379
+ Object.values(sgrModes).forEach(mode => sgrModes[mode[2]] = mode);
380
+
381
+ const codes = a => {
382
+ let open = '', close = '', mode = String(a).toLowerCase();
383
+ let [_isColor, colorIndex] = colors.isColor(mode);
384
+
385
+ if (_isColor) {
386
+ open = colors.isBG(mode)
387
+ ? `\x1b[${colors.isBright(mode) ? 10 : 4}${colorIndex}m`
388
+ : `\x1b[${colors.isBright(mode) ? 9 : 3}${colorIndex}m`;
389
+ close = colors.isBG(mode) ? '\x1b[49m' : `\x1b[39m`;
390
+ }
391
+ else if (sgrModes[mode]) {
392
+ open = sgrModes[mode][0];
393
+ close = sgrModes[mode][1];
360
394
  }
361
- else return [s];
362
- }
363
- }
364
-
365
- let modes = arrayifyString(useModes)
366
-
367
- const sgrModes = {
368
- blink: ['\x1b[5m', '\x1b[25m', 'k'],
369
- bold: ['\x1b[1m', '\x1b[22m', 'b'],
370
- conceal: ['\x1b[8m', '\x1b[28m', 'c'],
371
- dim: ['\x1b[2m', '\x1b[22m', 'd'],
372
- italics: ['\x1b[3m', '\x1b[23m', 'i'],
373
- negative: ['\x1b[7m', '\x1b[27m', 'n'],
374
- strike: ['\x1b[9m', '\x1b[29m', 's'],
375
- underline: ['\x1b[4m', '\x1b[24m', 'u'],
376
- };
377
-
378
- Object.values(sgrModes).forEach(mode => sgrModes[mode[2]] = mode);
379
-
380
- const codes = a => {
381
- let open = '', close = '', mode = String(a).toLowerCase();
382
- let [_isColor, colorIndex] = colors.isColor(mode);
383
-
384
- if (_isColor) {
385
- open = colors.isBG(mode)
386
- ? `\x1b[${colors.isBright(mode) ? 10 : 4}${colorIndex}m`
387
- : `\x1b[${colors.isBright(mode) ? 9 : 3}${colorIndex}m`;
388
- close = colors.isBG(mode) ? '\x1b[49m' : `\x1b[39m`;
389
- }
390
- else if (sgrModes[mode]) {
391
- open = sgrModes[mode][0];
392
- close = sgrModes[mode][1];
393
- }
394
395
 
395
- return [open, close];
396
- };
396
+ return [open, close];
397
+ };
397
398
 
398
- const onOrder = modes.map(key => codes(key)[0]).join('');
399
- const offOrder = modes.map(key => codes(key)[1]).reverse().join('');
399
+ const onOrder = modes.map(key => codes(key)[0]).join('');
400
+ const offOrder = modes.map(key => codes(key)[1]).reverse().join('');
400
401
 
401
- let result = Object(`${onOrder}${message}${offOrder}`)
402
+ let result = Object(`${onOrder}${message}${offOrder}`)
402
403
 
403
- Object.defineProperties(result, {
404
- show: {
405
- get() { console.log(String(this)); return this },
406
- enumerable: false,
407
- },
408
- [Symbol.for('nodejs.util.inspect.custom')]: {
409
- value(depth, options, inspect) {
410
- return inspect(String(this), options)
404
+ Object.defineProperties(result, {
405
+ show: {
406
+ get() { console.log(String(this)); return this },
407
+ enumerable: false,
408
+ },
409
+ [Symbol.for('nodejs.util.inspect.custom')]: {
410
+ value(depth, options, inspect) {return String(this)},
411
+ enumerable: false,
411
412
  },
412
- enumerable: false,
413
- },
414
- })
413
+ [Symbol.toStringTag]: {
414
+ get() { return "SgrString" },
415
+ enumerable: false,
416
+ }
417
+ })
415
418
 
416
- return result
417
- },
419
+ return result
420
+ },
418
421
 
419
- /**
420
- * Wraps an object's properties into a formatted string.
421
- *
422
- * This method takes an object and a set of options to format the
423
- * object's properties into a string. It allows customization of
424
- * indentation, line endings, maximum line length, and more.
425
- *
426
- * @param {Object} [object=globalThis] - The object to wrap.
427
- * @param {Object} [options={}] - The formatting options.
428
- * @param {number} [options.indent=2] - The number of indentation
429
- * characters to use.
430
- * @param {string} [options.indentCharacter=' '] - The character to use
431
- * for indentation.
432
- * @param {Array} [options.inspector=[Object, 'getOwnPropertyNames']] -
433
- * The inspector to use for retrieving object properties.
434
- * @param {string} [options.lineEnding='\n'] - The line ending character.
435
- * @param {number} [options.maxLen=78] - The maximum line length.
436
- * @param {Function} [options.perLine=undefined] - A function to apply
437
- * per line of output.
438
- * @param {Function} [options.perLinePerProperty=undefined] - A function
439
- * to apply per property per line of output.
440
- * @param {Function} [options.preProcess=undefined] - A function to
441
- * preprocess the object's properties.
442
- * @param {Function} [options.preReturn=undefined] - A function to apply
443
- * to the final output before returning.
444
- * @param {string} [options.separator=', '] - The separator to use
445
- * between properties.
446
- *
447
- * @returns {string} The formatted string representation of the object.
448
- *
449
- * @example
450
- * const obj = { a: 1, b: 2, c: 3 }
451
- * const wrapped = StringExtensions.wrap(obj, { maxLen: 20 })
452
- * console.log(wrapped)
453
- * // Output:
454
- * // {
455
- * // a: 1,
456
- * // b: 2,
457
- * // c: 3
458
- * // }
459
- */
460
- wrap(
461
- objectOrLines,
462
- options = {
463
- colorProperties: undefined,
464
- indent: 2,
465
- indentCharacter: ' ',
466
- inspector: [Object, 'getOwnPropertyNames'],
467
- lineEnding: '\n',
468
- maxLen: 78,
469
- perLine: undefined,
470
- perLinePerProperty: undefined,
471
- preProcess: undefined,
472
- preReturn: undefined,
473
- separator: ', ',
474
- }
475
- ) {
476
- let {
477
- colorProperties = undefined,
478
- indent = options?.indent ?? 2,
479
- indentCharacter = options?.indentCharacter ?? ' ',
480
- inspector = options?.inspector ?? [Object, 'getOwnPropertyNames'],
481
- lineEnding = options?.lineEnding ?? '\n',
482
- maxLen = options?.maxLen ?? 78,
483
- perLine = options?.perLine ?? undefined,
484
- perLinePerProperty = options?.perLinePerProperty ?? undefined,
485
- preProcess = options?.preProcess ?? undefined,
486
- preReturn = options?.preReturn ?? undefined,
487
- separator = options?.separator ?? ', ',
488
- } = options ?? {}
489
-
490
- let tab = indent === 0 ? ''
491
- : indentCharacter.repeat(Number(indent) || 2)
492
- maxLen = 78 - tab.length
493
-
494
- const sgr = this.sgr;
495
- const validMapper = f => typeof f === 'function'
496
-
497
- let line = []
498
- let getElements = inspector[0][inspector[1]]
499
- let values = Array.isArray(objectOrLines)
500
- ? objectOrLines : getElements(Object(objectOrLines))
501
-
502
- if (validMapper(preProcess)) {
503
- values = preProcess(values)
504
- }
505
-
506
- const context = { indent, indentCharacter, lineEnding, maxLen, tab, sgr }
507
-
508
- let finalLines = values.reduce((acc, nextProp) => {
509
- let ifCombined = [...line, nextProp].join(separator)
510
-
511
- if ((tab.length + ifCombined.length) <= maxLen) {
512
- line.push(nextProp)
422
+ /**
423
+ * Wraps an object's properties into a formatted string.
424
+ *
425
+ * This method takes an object and a set of options to format the
426
+ * object's properties into a string. It allows customization of
427
+ * indentation, line endings, maximum line length, and more.
428
+ *
429
+ * @param {Object} [object=globalThis] - The object to wrap.
430
+ * @param {Object} [options={}] - The formatting options.
431
+ * @param {number} [options.indent=2] - The number of indentation
432
+ * characters to use.
433
+ * @param {string} [options.indentCharacter=' '] - The character to use
434
+ * for indentation.
435
+ * @param {Array} [options.inspector=[Object, 'getOwnPropertyNames']] -
436
+ * The inspector to use for retrieving object properties.
437
+ * @param {string} [options.lineEnding='\n'] - The line ending character.
438
+ * @param {number} [options.maxLen=78] - The maximum line length.
439
+ * @param {Function} [options.perLine=undefined] - A function to apply
440
+ * per line of output.
441
+ * @param {Function} [options.perLinePerProperty=undefined] - A function
442
+ * to apply per property per line of output.
443
+ * @param {Function} [options.preProcess=undefined] - A function to
444
+ * preprocess the object's properties.
445
+ * @param {Function} [options.preReturn=undefined] - A function to apply
446
+ * to the final output before returning.
447
+ * @param {string} [options.separator=', '] - The separator to use
448
+ * between properties.
449
+ *
450
+ * @returns {string} The formatted string representation of the object.
451
+ *
452
+ * @example
453
+ * const obj = { a: 1, b: 2, c: 3 }
454
+ * const wrapped = StringExtensions.wrap(obj, { maxLen: 20 })
455
+ * console.log(wrapped)
456
+ * // Output:
457
+ * // {
458
+ * // a: 1,
459
+ * // b: 2,
460
+ * // c: 3
461
+ * // }
462
+ */
463
+ wrap(
464
+ objectOrLines,
465
+ options = {
466
+ colorProperties: undefined,
467
+ indent: 2,
468
+ indentCharacter: ' ',
469
+ inspector: [Object, 'getOwnPropertyNames'],
470
+ lineEnding: '\n',
471
+ maxLen: 78,
472
+ perLine: undefined,
473
+ perLinePerProperty: undefined,
474
+ preProcess: undefined,
475
+ preReturn: undefined,
476
+ separator: ', ',
477
+ }
478
+ ) {
479
+ let {
480
+ colorProperties = undefined,
481
+ indent = options?.indent ?? 2,
482
+ indentCharacter = options?.indentCharacter ?? ' ',
483
+ inspector = options?.inspector ?? [Object, 'getOwnPropertyNames'],
484
+ lineEnding = options?.lineEnding ?? '\n',
485
+ maxLen = options?.maxLen ?? 78,
486
+ perLine = options?.perLine ?? undefined,
487
+ perLinePerProperty = options?.perLinePerProperty ?? undefined,
488
+ preProcess = options?.preProcess ?? undefined,
489
+ preReturn = options?.preReturn ?? undefined,
490
+ separator = options?.separator ?? ', ',
491
+ } = options ?? {}
492
+
493
+ let tab = indent === 0 ? ''
494
+ : indentCharacter.repeat(Number(indent) || 2)
495
+ maxLen = 78 - tab.length
496
+
497
+ const sgr = this.sgr;
498
+ const validMapper = f => typeof f === 'function'
499
+
500
+ let line = []
501
+ let getElements = inspector[0][inspector[1]]
502
+ let values = Array.isArray(objectOrLines)
503
+ ? objectOrLines : getElements(Object(objectOrLines))
504
+
505
+ if (validMapper(preProcess)) {
506
+ values = preProcess(values)
513
507
  }
514
508
 
515
- else {
516
- let lineProps = [...line]
509
+ const context = { indent, indentCharacter, lineEnding, maxLen, tab, sgr }
517
510
 
518
- if (validMapper(perLinePerProperty)) {
519
- lineProps = lineProps.map((value, index, array) => {
520
- return perLinePerProperty(value, index, array, context)
521
- })
522
- }
511
+ let finalLines = values.reduce((acc, nextProp) => {
512
+ let ifCombined = [...line, nextProp].join(separator)
523
513
 
524
- if (colorProperties) {
525
- const sgrArgs = (Array.isArray(colorProperties)
526
- ? colorProperties
527
- : [colorProperties]
528
- )
529
- lineProps = lineProps.map(v => sgr(v, ...sgrArgs))
514
+ if ((tab.length + ifCombined.length) <= maxLen) {
515
+ line.push(nextProp)
530
516
  }
531
517
 
532
- lineProps = [tab, lineProps.join(separator)].join('')
533
- if (validMapper(perLine)) {
534
- lineProps = perLine(lineProps[0], 0, lineProps)?.[0] ?? lineProps[0]
535
- }
518
+ else {
519
+ let lineProps = [...line]
536
520
 
537
- acc.push(lineProps)
538
- line = []
539
- }
521
+ if (validMapper(perLinePerProperty)) {
522
+ lineProps = lineProps.map((value, index, array) => {
523
+ return perLinePerProperty(value, index, array, context)
524
+ })
525
+ }
540
526
 
541
- return acc
542
- }, [])
527
+ if (colorProperties) {
528
+ const sgrArgs = (Array.isArray(colorProperties)
529
+ ? colorProperties
530
+ : [colorProperties]
531
+ )
532
+ lineProps = lineProps.map(v => sgr(v, ...sgrArgs))
533
+ }
543
534
 
544
- if (validMapper(preReturn)) {
545
- finalLines = finalLines.map((value, index, array) => {
546
- return preReturn(value, index, array, context)
547
- })
548
- }
535
+ lineProps = [tab, lineProps.join(separator)].join('')
536
+ if (validMapper(perLine)) {
537
+ lineProps = perLine(lineProps[0], 0, lineProps)?.[0] ?? lineProps[0]
538
+ }
549
539
 
550
- Symbol.for(`@nejs.string.wrap ${JSON.stringify({lines: finalLines})}`)
540
+ acc.push(lineProps)
541
+ line = []
542
+ }
543
+
544
+ return acc
545
+ }, [])
546
+
547
+ if (validMapper(preReturn)) {
548
+ finalLines = finalLines.map((value, index, array) => {
549
+ return preReturn(value, index, array, context)
550
+ })
551
+ }
551
552
 
552
- if (lineEnding) {
553
- finalLines = finalLines.join(lineEnding)
554
- }
553
+ Symbol.for(`@nejs.string.wrap ${JSON.stringify({lines: finalLines})}`)
555
554
 
556
- return finalLines
555
+ if (lineEnding) {
556
+ finalLines = finalLines.join(lineEnding)
557
+ }
558
+
559
+ return finalLines
560
+ },
557
561
  },
558
562
  });
559
563
 
@@ -726,9 +730,11 @@ export const StringPrototypeExtensions = new Patch(String.prototype, {
726
730
  // Object<->Function<->Global occurs. See original source in global.this.js
727
731
  // {@see globalThis.isThenElse}
728
732
  function isThenElse(bv, tv, ev) {
733
+ function isFunction(value) { typeof value === 'function' }
734
+
729
735
  if (arguments.length > 1) {
730
736
  var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
731
737
  var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
732
738
  } return bv || _then;
733
739
  } return bv
734
- }
740
+ }