@nejs/basic-extensions 2.4.0 → 2.6.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 (37) hide show
  1. package/README.md +151 -118
  2. package/dist/@nejs/basic-extensions.bundle.2.5.0.js +8 -0
  3. package/dist/@nejs/basic-extensions.bundle.2.5.0.js.map +7 -0
  4. package/dist/cjs/arrayextensions.js +56 -54
  5. package/dist/cjs/arrayextensions.js.map +1 -1
  6. package/dist/cjs/functionextensions.js +81 -79
  7. package/dist/cjs/functionextensions.js.map +1 -1
  8. package/dist/cjs/mapextensions.js +23 -21
  9. package/dist/cjs/mapextensions.js.map +1 -1
  10. package/dist/cjs/objectextensions.js +49 -17
  11. package/dist/cjs/objectextensions.js.map +1 -1
  12. package/dist/cjs/setextensions.js +191 -189
  13. package/dist/cjs/setextensions.js.map +1 -1
  14. package/dist/cjs/stringextensions.js +69 -67
  15. package/dist/cjs/stringextensions.js.map +1 -1
  16. package/dist/mjs/arrayextensions.js +56 -54
  17. package/dist/mjs/arrayextensions.js.map +1 -1
  18. package/dist/mjs/functionextensions.js +81 -79
  19. package/dist/mjs/functionextensions.js.map +1 -1
  20. package/dist/mjs/mapextensions.js +23 -21
  21. package/dist/mjs/mapextensions.js.map +1 -1
  22. package/dist/mjs/objectextensions.js +49 -17
  23. package/dist/mjs/objectextensions.js.map +1 -1
  24. package/dist/mjs/setextensions.js +191 -189
  25. package/dist/mjs/setextensions.js.map +1 -1
  26. package/dist/mjs/stringextensions.js +69 -67
  27. package/dist/mjs/stringextensions.js.map +1 -1
  28. package/docs/index.html +636 -478
  29. package/package.json +5 -4
  30. package/src/arrayextensions.js +56 -55
  31. package/src/functionextensions.js +87 -85
  32. package/src/mapextensions.js +26 -24
  33. package/src/objectextensions.js +52 -17
  34. package/src/setextensions.js +216 -214
  35. package/src/stringextensions.js +69 -67
  36. package/dist/@nejs/basic-extensions.bundle.2.3.0.js +0 -8
  37. package/dist/@nejs/basic-extensions.bundle.2.3.0.js.map +0 -7
@@ -1,242 +1,244 @@
1
1
  import { Patch } from '@nejs/extension';
2
2
 
3
3
  export const SetPrototypeExtensions = new Patch(Set.prototype, {
4
- /**
5
- * Merges multiple iterables into the set. Each element from the iterables
6
- * is added to the set, ensuring uniqueness of all elements. This method
7
- * mutates the original set.
8
- *
9
- * @param {...Iterable} iterables - One or more iterable objects (like Set
10
- * or Array) whose elements will be added to the set.
11
- */
12
- concat(...iterables) {
13
- for (const iterable of iterables) {
14
- if (
15
- typeof iterable === 'string' ||
16
- !Reflect.has(iterable, Symbol.iterator)
17
- ) {
18
- this.add(iterable)
19
- continue
4
+ [Patch.kMutablyHidden]: {
5
+ /**
6
+ * Merges multiple iterables into the set. Each element from the iterables
7
+ * is added to the set, ensuring uniqueness of all elements. This method
8
+ * mutates the original set.
9
+ *
10
+ * @param {...Iterable} iterables - One or more iterable objects (like Set
11
+ * or Array) whose elements will be added to the set.
12
+ */
13
+ concat(...iterables) {
14
+ for (const iterable of iterables) {
15
+ if (
16
+ typeof iterable === 'string' ||
17
+ !Reflect.has(iterable, Symbol.iterator)
18
+ ) {
19
+ this.add(iterable)
20
+ continue
21
+ }
22
+
23
+ for (const element of iterable) {
24
+ this.add(element)
25
+ }
26
+ }
27
+ },
28
+
29
+ /**
30
+ * Checks to see if any value within the `Set` loosely equals the supplied
31
+ * value.
32
+ *
33
+ * @param {*} value any value that might be loosely equal to an item in the
34
+ * set, as opposed to {@link Set.has} which is the equivalent of a strict or
35
+ * triple equals (`===`) check
36
+ * @returns {boolean} `true` if any value within the set is loosely equal to
37
+ * the supplied value, `false` otherwise
38
+ */
39
+ contains(value) {
40
+ for (const element of this) {
41
+ if (value == element) {
42
+ return true
43
+ }
20
44
  }
21
45
 
22
- for (const element of iterable) {
23
- this.add(element)
46
+ return false
47
+ },
48
+
49
+ /**
50
+ * Checks if every element in the set passes the test implemented by the
51
+ * provided function. The function is called with each element of the set.
52
+ * Note: Since sets do not have indices, the index parameter is always NaN.
53
+ *
54
+ * @param {Function} everyFn - The function to test each element. Receives
55
+ * the element, index (always NaN), and the set itself.
56
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
57
+ * `everyFn`.
58
+ * @throws {TypeError} If `everyFn` is not a function.
59
+ * @returns {boolean} True if every element passes the test, false otherwise.
60
+ */
61
+ every(everyFn, thisArg) {
62
+ if (typeof everyFn !== 'function') {
63
+ throw new TypeError(
64
+ `everyFn must be a function! Received ${String(everyFn)}`
65
+ )
24
66
  }
25
- }
26
- },
27
67
 
28
- /**
29
- * Checks to see if any value within the `Set` loosely equals the supplied
30
- * value.
31
- *
32
- * @param {*} value any value that might be loosely equal to an item in the
33
- * set, as opposed to {@link Set.has} which is the equivalent of a strict or
34
- * triple equals (`===`) check
35
- * @returns {boolean} `true` if any value within the set is loosely equal to
36
- * the supplied value, `false` otherwise
37
- */
38
- contains(value) {
39
- for (const element of this) {
40
- if (value == element) {
41
- return true
68
+ let found = 0
69
+
70
+ for (const element of this) {
71
+ if (everyFn.call(thisArg, element, NaN, this)) {
72
+ found++
73
+ }
42
74
  }
43
- }
44
75
 
45
- return false
46
- },
76
+ return (found === this.size)
77
+ },
78
+
79
+
80
+ /**
81
+ * Finds the first element in the set satisfying the provided testing
82
+ * function. If no elements satisfy the testing function, undefined is
83
+ * returned. The function is called with each element of the set.
84
+ * Note: Since sets do not have indices, the index parameter is always NaN.
85
+ *
86
+ * @param {Function} findFn - The function to execute on each element. It
87
+ * receives the element, index (always NaN), and the set itself.
88
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
89
+ * `findFn`.
90
+ * @throws {TypeError} If `findFn` is not a function.
91
+ * @returns {*} The first element that satisfies `findFn`, or undefined.
92
+ */
93
+ find(findFn, thisArg) {
94
+ if (typeof findFn !== 'function') {
95
+ throw new TypeError(
96
+ `findFn must be a function! Received ${String(findFn)}`
97
+ )
98
+ }
47
99
 
48
- /**
49
- * Checks if every element in the set passes the test implemented by the
50
- * provided function. The function is called with each element of the set.
51
- * Note: Since sets do not have indices, the index parameter is always NaN.
52
- *
53
- * @param {Function} everyFn - The function to test each element. Receives
54
- * the element, index (always NaN), and the set itself.
55
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
56
- * `everyFn`.
57
- * @throws {TypeError} If `everyFn` is not a function.
58
- * @returns {boolean} True if every element passes the test, false otherwise.
59
- */
60
- every(everyFn, thisArg) {
61
- if (typeof everyFn !== 'function') {
62
- throw new TypeError(
63
- `everyFn must be a function! Received ${String(everyFn)}`
64
- )
65
- }
66
-
67
- let found = 0
68
-
69
- for (const element of this) {
70
- if (everyFn.call(thisArg, element, NaN, this)) {
71
- found++
100
+ for (const element of this) {
101
+ const match = findFn.call(thisArg, element, NaN, this)
102
+ if (match) {
103
+ return element
104
+ }
72
105
  }
73
- }
74
106
 
75
- return (found === this.size)
76
- },
107
+ return undefined
108
+ },
109
+
110
+ /**
111
+ * Finds the last element in the set satisfying the provided testing function.
112
+ * If no elements satisfy the testing function, undefined is returned. The
113
+ * function is called with each element of the set in reverse order.
114
+ * Note: Since sets do not have indices, the index parameter is always NaN.
115
+ *
116
+ * @param {Function} findFn - The function to execute on each element. It
117
+ * receives the element, index (always NaN), and the set itself.
118
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
119
+ * `findFn`.
120
+ * @throws {TypeError} If `findFn` is not a function.
121
+ * @returns {*} The last element that satisfies `findFn`, or undefined.
122
+ */
123
+ findLast(findFn, thisArg) {
124
+ if (typeof findFn !== 'function') {
125
+ throw new TypeError(
126
+ `findFn must be a function! Received ${String(findFn)}`
127
+ )
128
+ }
77
129
 
130
+ const found = []
78
131
 
79
- /**
80
- * Finds the first element in the set satisfying the provided testing
81
- * function. If no elements satisfy the testing function, undefined is
82
- * returned. The function is called with each element of the set.
83
- * Note: Since sets do not have indices, the index parameter is always NaN.
84
- *
85
- * @param {Function} findFn - The function to execute on each element. It
86
- * receives the element, index (always NaN), and the set itself.
87
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
88
- * `findFn`.
89
- * @throws {TypeError} If `findFn` is not a function.
90
- * @returns {*} The first element that satisfies `findFn`, or undefined.
91
- */
92
- find(findFn, thisArg) {
93
- if (typeof findFn !== 'function') {
94
- throw new TypeError(
95
- `findFn must be a function! Received ${String(findFn)}`
96
- )
97
- }
98
-
99
- for (const element of this) {
100
- const match = findFn.call(thisArg, element, NaN, this)
101
- if (match) {
102
- return element
132
+ for (const element of this) {
133
+ const match = findFn.call(thisArg, element, NaN, this)
134
+ if (match) {
135
+ found.push(element)
136
+ }
103
137
  }
104
- }
105
138
 
106
- return undefined
107
- },
139
+ if (found.length) {
140
+ return found[found.length - 1]
141
+ }
108
142
 
109
- /**
110
- * Finds the last element in the set satisfying the provided testing function.
111
- * If no elements satisfy the testing function, undefined is returned. The
112
- * function is called with each element of the set in reverse order.
113
- * Note: Since sets do not have indices, the index parameter is always NaN.
114
- *
115
- * @param {Function} findFn - The function to execute on each element. It
116
- * receives the element, index (always NaN), and the set itself.
117
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
118
- * `findFn`.
119
- * @throws {TypeError} If `findFn` is not a function.
120
- * @returns {*} The last element that satisfies `findFn`, or undefined.
121
- */
122
- findLast(findFn, thisArg) {
123
- if (typeof findFn !== 'function') {
124
- throw new TypeError(
125
- `findFn must be a function! Received ${String(findFn)}`
126
- )
127
- }
128
-
129
- const found = []
130
-
131
- for (const element of this) {
132
- const match = findFn.call(thisArg, element, NaN, this)
133
- if (match) {
134
- found.push(element)
143
+ return undefined
144
+ },
145
+
146
+ /**
147
+ * A getter property that returns the number of elements in the set.
148
+ * This is an alias for the `size` property of the set.
149
+ *
150
+ * @returns {number} The number of elements in the set.
151
+ */
152
+ get length() {
153
+ return this.size
154
+ },
155
+
156
+ /**
157
+ * Creates a new array populated with the results of calling the provided
158
+ * function on every element in the set. The function is called with each
159
+ * element of the set. Note: Since sets do not have indices, the index
160
+ * parameter is always NaN.
161
+ *
162
+ * @param {Function} mapFn - The function to execute on each element. It
163
+ * receives the element, index (always NaN), and the set itself.
164
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
165
+ * `mapFn`.
166
+ * @throws {TypeError} If `mapFn` is not a function.
167
+ * @returns {Array} A new array with each element being the result of the
168
+ * `mapFn`.
169
+ */
170
+ map(mapFn, thisArg) {
171
+ if (typeof mapFn !== 'function') {
172
+ throw new TypeError(
173
+ `mapFn must be a function! Received ${String(mapFn)}`
174
+ )
135
175
  }
136
- }
137
176
 
138
- if (found.length) {
139
- return found[found.length - 1]
140
- }
177
+ const transformed = []
141
178
 
142
- return undefined
143
- },
179
+ for (const element of this) {
180
+ transformed.push(mapFn.call(thisArg, element, NaN, this))
181
+ }
144
182
 
145
- /**
146
- * A getter property that returns the number of elements in the set.
147
- * This is an alias for the `size` property of the set.
148
- *
149
- * @returns {number} The number of elements in the set.
150
- */
151
- get length() {
152
- return this.size
153
- },
183
+ return transformed
184
+ },
185
+
186
+ /**
187
+ * Applies a function against an accumulator and each element in the set to
188
+ * reduce it to a single value. The function is called with each element of
189
+ * the set. Note: Since sets do not have indices, the index parameter is
190
+ * always NaN.
191
+ *
192
+ * @param {Function} reduceFn - The function to execute on each element. It
193
+ * receives the accumulator, element, index (always NaN), and the set itself.
194
+ * @param {*} initialValue - The initial value to start reducing from.
195
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
196
+ * `reduceFn`.
197
+ * @throws {TypeError} If `reduceFn` is not a function.
198
+ * @returns {*} The reduced value.
199
+ */
200
+ reduce(reduceFn, initialValue, thisArg) {
201
+ if (typeof reduceFn !== 'function') {
202
+ throw new TypeError(
203
+ `reduceFn must be a Function! Received ${String(reduceFn)}`
204
+ )
205
+ }
154
206
 
155
- /**
156
- * Creates a new array populated with the results of calling the provided
157
- * function on every element in the set. The function is called with each
158
- * element of the set. Note: Since sets do not have indices, the index
159
- * parameter is always NaN.
160
- *
161
- * @param {Function} mapFn - The function to execute on each element. It
162
- * receives the element, index (always NaN), and the set itself.
163
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
164
- * `mapFn`.
165
- * @throws {TypeError} If `mapFn` is not a function.
166
- * @returns {Array} A new array with each element being the result of the
167
- * `mapFn`.
168
- */
169
- map(mapFn, thisArg) {
170
- if (typeof mapFn !== 'function') {
171
- throw new TypeError(
172
- `mapFn must be a function! Received ${String(mapFn)}`
173
- )
174
- }
175
-
176
- const transformed = []
177
-
178
- for (const element of this) {
179
- transformed.push(mapFn.call(thisArg, element, NaN, this))
180
- }
181
-
182
- return transformed
183
- },
207
+ let accumulator = initialValue
208
+ for (const element of this) {
209
+ accumulator = reduceFn.call(thisArg, accumulator, element, NaN, this)
210
+ }
184
211
 
185
- /**
186
- * Applies a function against an accumulator and each element in the set to
187
- * reduce it to a single value. The function is called with each element of
188
- * the set. Note: Since sets do not have indices, the index parameter is
189
- * always NaN.
190
- *
191
- * @param {Function} reduceFn - The function to execute on each element. It
192
- * receives the accumulator, element, index (always NaN), and the set itself.
193
- * @param {*} initialValue - The initial value to start reducing from.
194
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
195
- * `reduceFn`.
196
- * @throws {TypeError} If `reduceFn` is not a function.
197
- * @returns {*} The reduced value.
198
- */
199
- reduce(reduceFn, initialValue, thisArg) {
200
- if (typeof reduceFn !== 'function') {
201
- throw new TypeError(
202
- `reduceFn must be a Function! Received ${String(reduceFn)}`
203
- )
204
- }
205
-
206
- let accumulator = initialValue
207
- for (const element of this) {
208
- accumulator = reduceFn.call(thisArg, accumulator, element, NaN, this)
209
- }
210
-
211
- return accumulator
212
- },
212
+ return accumulator
213
+ },
214
+
215
+ /**
216
+ * Tests whether at least one element in the set passes the test implemented
217
+ * by the provided function. The function is called with each element of the
218
+ * set. Note: Since sets do not have indices, the index parameter is always NaN.
219
+ *
220
+ * @param {Function} someFn - The function to test each element. It receives
221
+ * the element, index (always NaN), and the set itself.
222
+ * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
223
+ * `someFn`.
224
+ * @throws {TypeError} If `someFn` is not a function.
225
+ * @returns {boolean} True if at least one element passes the test, false
226
+ * otherwise.
227
+ */
228
+ some(someFn, thisArg) {
229
+ if (typeof someFn !== 'function') {
230
+ throw new TypeError(
231
+ `someFn must be a function! Received ${String(someFn)}`
232
+ )
233
+ }
213
234
 
214
- /**
215
- * Tests whether at least one element in the set passes the test implemented
216
- * by the provided function. The function is called with each element of the
217
- * set. Note: Since sets do not have indices, the index parameter is always NaN.
218
- *
219
- * @param {Function} someFn - The function to test each element. It receives
220
- * the element, index (always NaN), and the set itself.
221
- * @param {Object} [thisArg] - Optional. Value to use as `this` when executing
222
- * `someFn`.
223
- * @throws {TypeError} If `someFn` is not a function.
224
- * @returns {boolean} True if at least one element passes the test, false
225
- * otherwise.
226
- */
227
- some(someFn, thisArg) {
228
- if (typeof someFn !== 'function') {
229
- throw new TypeError(
230
- `someFn must be a function! Received ${String(someFn)}`
231
- )
232
- }
233
-
234
- for (const element of this) {
235
- if (someFn.call(thisArg, element, NaN, this)) {
236
- return true
235
+ for (const element of this) {
236
+ if (someFn.call(thisArg, element, NaN, this)) {
237
+ return true
238
+ }
237
239
  }
238
- }
239
240
 
240
- return false
241
+ return false
242
+ },
241
243
  },
242
244
  })
@@ -85,80 +85,82 @@ export const StringExtensions = new Patch(String, {
85
85
  * making string manipulation tasks more convenient and expressive.
86
86
  */
87
87
  export const StringPrototypeExtensions = new Patch(String.prototype, {
88
- /**
89
- * Extracts a substring from the current string, starting at a given offset
90
- * and bounded by specified opening and closing tokens. This method is
91
- * particularly useful for parsing nested structures or quoted strings,
92
- * where the level of nesting or the presence of escape characters must
93
- * be considered.
94
- *
95
- * @param {number} offset The position in the string from which to start the
96
- * search for the substring.
97
- * @param {[string, string]} tokens An array containing two strings: the
98
- * opening and closing tokens that define the boundaries of the substring
99
- * to be extracted.
100
- * @returns {Object} An object with two properties: `extracted`, the
101
- * extracted substring, and `newOffset`, the position in the original
102
- * string immediately after the end of the extracted substring. If no
103
- * substring is found, `extracted` is `null` and `newOffset` is the same
104
- * as the input offset.
105
- */
106
- extractSubstring(offset = 0, tokens = parenthesisPair) {
107
- let [openToken, closeToken] = tokens;
108
- let depth = 0;
109
- let start = -1;
110
- let end = -1;
111
- let leadingToken = '';
112
- let firstToken = 0;
88
+ [Patch.kMutablyHidden]: {
89
+ /**
90
+ * Extracts a substring from the current string, starting at a given offset
91
+ * and bounded by specified opening and closing tokens. This method is
92
+ * particularly useful for parsing nested structures or quoted strings,
93
+ * where the level of nesting or the presence of escape characters must
94
+ * be considered.
95
+ *
96
+ * @param {number} offset The position in the string from which to start the
97
+ * search for the substring.
98
+ * @param {[string, string]} tokens An array containing two strings: the
99
+ * opening and closing tokens that define the boundaries of the substring
100
+ * to be extracted.
101
+ * @returns {Object} An object with two properties: `extracted`, the
102
+ * extracted substring, and `newOffset`, the position in the original
103
+ * string immediately after the end of the extracted substring. If no
104
+ * substring is found, `extracted` is `null` and `newOffset` is the same
105
+ * as the input offset.
106
+ */
107
+ extractSubstring(offset = 0, tokens = parenthesisPair) {
108
+ let [openToken, closeToken] = tokens;
109
+ let depth = 0;
110
+ let start = -1;
111
+ let end = -1;
112
+ let leadingToken = '';
113
+ let firstToken = 0;
113
114
 
114
- for (let i = offset; i < this.length; i++) {
115
- const char = this[i];
115
+ for (let i = offset; i < this.length; i++) {
116
+ const char = this[i];
116
117
 
117
- if (char === openToken) {
118
- depth++;
119
- if (start === -1)
120
- start = i;
121
- }
122
- else if (char === closeToken) {
123
- depth--;
124
- if (depth === 0) {
125
- end = i;
126
- break;
118
+ if (char === openToken) {
119
+ depth++;
120
+ if (start === -1)
121
+ start = i;
122
+ }
123
+ else if (char === closeToken) {
124
+ depth--;
125
+ if (depth === 0) {
126
+ end = i;
127
+ break;
128
+ }
127
129
  }
128
130
  }
129
- }
130
131
 
131
- let lRange = [
132
- Math.max(0, start - 100),
133
- start
134
- ];
135
- let leading = [...this.substring(lRange[0], lRange[1])].reverse().join('')
136
- let reversedLeadingToken;
132
+ let lRange = [
133
+ Math.max(0, start - 100),
134
+ start
135
+ ];
136
+ let leading = [...this.substring(lRange[0], lRange[1])].reverse().join('')
137
+ let reversedLeadingToken;
137
138
 
138
- try {
139
- reversedLeadingToken = /([^ \,\"\'\`]+)/.exec(leading)[1] ?? '';
140
- leadingToken = [...reversedLeadingToken].reverse().join('');
141
- }
142
- catch(ignored) { }
139
+ try {
140
+ reversedLeadingToken = /([^ \,\"\'\`]+)/.exec(leading)[1] ?? '';
141
+ leadingToken = [...reversedLeadingToken].reverse().join('');
142
+ }
143
+ catch(ignored) { }
143
144
 
144
- if (start !== -1 && end !== -1) {
145
- const sliceRange = [start, end + 1];
146
- const extracted = this.slice(sliceRange[0], sliceRange[1]);
145
+ if (start !== -1 && end !== -1) {
146
+ const sliceRange = [start, end + 1];
147
+ const extracted = this.slice(sliceRange[0], sliceRange[1]);
147
148
 
148
- return {
149
- extracted,
150
- range: [start, end],
151
- newOffset: end + 1,
152
- leadingToken,
153
- };
154
- }
155
- else {
156
- return {
157
- extracted: null,
158
- range: [start, end],
159
- newOffset: offset,
160
- leadingToken,
161
- };
162
- }
149
+ return {
150
+ extracted,
151
+ range: [start, end],
152
+ newOffset: end + 1,
153
+ leadingToken,
154
+ };
155
+ }
156
+ else {
157
+ return {
158
+ extracted: null,
159
+ range: [start, end],
160
+ newOffset: offset,
161
+ leadingToken,
162
+ };
163
+ }
164
+ },
163
165
  },
164
166
  })