string-match-left-right 8.0.5 → 8.0.6

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @name string-match-left-right
3
3
  * @fileoverview Match substrings on the left or right of a given index, ignoring whitespace
4
- * @version 8.0.5
4
+ * @version 8.0.6
5
5
  * @author Roy Revelt, Codsen Ltd
6
6
  * @license MIT
7
7
  * {@link https://codsen.com/os/string-match-left-right/}
@@ -10,296 +10,374 @@
10
10
  import { arrayiffy } from 'arrayiffy-if-string';
11
11
 
12
12
  function isObj(something) {
13
- return something && typeof something === "object" && !Array.isArray(something);
13
+ return (something && typeof something === "object" && !Array.isArray(something));
14
14
  }
15
15
  function isStr(something) {
16
- return typeof something === "string";
16
+ return typeof something === "string";
17
17
  }
18
18
  const defaults = {
19
- cb: undefined,
20
- i: false,
21
- trimBeforeMatching: false,
22
- trimCharsBeforeMatching: [],
23
- maxMismatches: 0,
24
- firstMustMatch: false,
25
- lastMustMatch: false,
26
- hungry: false
19
+ cb: undefined,
20
+ i: false,
21
+ trimBeforeMatching: false,
22
+ trimCharsBeforeMatching: [],
23
+ maxMismatches: 0,
24
+ firstMustMatch: false,
25
+ lastMustMatch: false,
26
+ hungry: false,
27
27
  };
28
- const defaultGetNextIdx = index => index + 1;
28
+ const defaultGetNextIdx = (index) => index + 1;
29
29
  function march(str, position, whatToMatchVal, originalOpts, special = false, getNextIdx = defaultGetNextIdx) {
30
- const whatToMatchValVal = typeof whatToMatchVal === "function" ? whatToMatchVal() : whatToMatchVal;
31
- if (+position < 0 && special && whatToMatchValVal === "EOL") {
32
- return whatToMatchValVal;
33
- }
34
- const opts = { ...defaults,
35
- ...originalOpts
36
- };
37
- if (position >= str.length && !special) {
38
- return false;
39
- }
40
- let charsToCheckCount = special ? 1 : whatToMatchVal.length;
41
- let charsMatchedTotal = 0;
42
- let patienceReducedBeforeFirstMatch = false;
43
- let lastWasMismatched = false;
44
- let atLeastSomethingWasMatched = false;
45
- let patience = opts.maxMismatches;
46
- let i = position;
47
- let somethingFound = false;
48
- let firstCharacterMatched = false;
49
- let lastCharacterMatched = false;
50
- function whitespaceInFrontOfFirstChar() {
51
- return (
52
- charsMatchedTotal === 1 &&
53
- patience < opts.maxMismatches - 1
54
- );
55
- }
56
- while (str[i]) {
57
- const nextIdx = getNextIdx(i);
58
- if (opts.trimBeforeMatching && str[i].trim() === "") {
59
- if (!str[nextIdx] && special && whatToMatchVal === "EOL") {
60
- return true;
61
- }
62
- i = getNextIdx(i);
63
- continue;
64
- }
65
- if (opts && !opts.i && opts.trimCharsBeforeMatching && opts.trimCharsBeforeMatching.includes(str[i]) || opts && opts.i && opts.trimCharsBeforeMatching && opts.trimCharsBeforeMatching.map(val => val.toLowerCase()).includes(str[i].toLowerCase())) {
66
- if (special && whatToMatchVal === "EOL" && !str[nextIdx]) {
67
- return true;
68
- }
69
- i = getNextIdx(i);
70
- continue;
30
+ const whatToMatchValVal = typeof whatToMatchVal === "function" ? whatToMatchVal() : whatToMatchVal;
31
+ if (+position < 0 && special && whatToMatchValVal === "EOL") {
32
+ return whatToMatchValVal;
71
33
  }
72
- const charToCompareAgainst = nextIdx > i ? whatToMatchVal[whatToMatchVal.length - charsToCheckCount] : whatToMatchVal[charsToCheckCount - 1];
73
- if (!opts.i && str[i] === charToCompareAgainst || opts.i && str[i].toLowerCase() === charToCompareAgainst.toLowerCase()) {
74
- if (!somethingFound) {
75
- somethingFound = true;
76
- }
77
- if (!atLeastSomethingWasMatched) {
78
- atLeastSomethingWasMatched = true;
79
- }
80
- if (charsToCheckCount === whatToMatchVal.length) {
81
- firstCharacterMatched = true;
82
- if (patience !== opts.maxMismatches) {
83
- return false;
84
- }
85
- } else if (charsToCheckCount === 1) {
86
- lastCharacterMatched = true;
87
- }
88
- charsToCheckCount -= 1;
89
- charsMatchedTotal++;
90
- if (whitespaceInFrontOfFirstChar()) {
34
+ const opts = { ...defaults, ...originalOpts };
35
+ if (position >= str.length && !special) {
91
36
  return false;
92
- }
93
- if (!charsToCheckCount) {
37
+ }
38
+ let charsToCheckCount = special ? 1 : whatToMatchVal.length;
39
+ let charsMatchedTotal = 0;
40
+ let patienceReducedBeforeFirstMatch = false;
41
+ let lastWasMismatched = false;
42
+ let atLeastSomethingWasMatched = false;
43
+ let patience = opts.maxMismatches;
44
+ let i = position;
45
+ let somethingFound = false;
46
+ let firstCharacterMatched = false;
47
+ let lastCharacterMatched = false;
48
+ function whitespaceInFrontOfFirstChar() {
94
49
  return (
95
- charsMatchedTotal !== whatToMatchVal.length ||
96
- patience === opts.maxMismatches ||
97
- !patienceReducedBeforeFirstMatch ? i : false
98
- );
99
- }
100
- } else {
101
- if (!patienceReducedBeforeFirstMatch && !charsMatchedTotal) {
102
- patienceReducedBeforeFirstMatch = true;
103
- }
104
- if (opts.maxMismatches && patience && i) {
105
- patience -= 1;
106
- for (let y = 0; y <= patience; y++) {
107
- const nextCharToCompareAgainst = nextIdx > i ? whatToMatchVal[whatToMatchVal.length - charsToCheckCount + 1 + y] : whatToMatchVal[charsToCheckCount - 2 - y];
108
- const nextCharInSource = str[getNextIdx(i)];
109
- if (nextCharToCompareAgainst && (!opts.i && str[i] === nextCharToCompareAgainst || opts.i && str[i].toLowerCase() === nextCharToCompareAgainst.toLowerCase()) && (
110
- !opts.firstMustMatch || charsToCheckCount !== whatToMatchVal.length)) {
50
+ charsMatchedTotal === 1 &&
51
+ patience < opts.maxMismatches - 1);
52
+ }
53
+ while (str[i]) {
54
+ const nextIdx = getNextIdx(i);
55
+ if (opts.trimBeforeMatching && str[i].trim() === "") {
56
+ if (!str[nextIdx] && special && whatToMatchVal === "EOL") {
57
+ return true;
58
+ }
59
+ i = getNextIdx(i);
60
+ continue;
61
+ }
62
+ if ((opts &&
63
+ !opts.i &&
64
+ opts.trimCharsBeforeMatching &&
65
+ opts.trimCharsBeforeMatching.includes(str[i])) ||
66
+ (opts &&
67
+ opts.i &&
68
+ opts.trimCharsBeforeMatching &&
69
+ opts.trimCharsBeforeMatching
70
+ .map((val) => val.toLowerCase())
71
+ .includes(str[i].toLowerCase()))) {
72
+ if (special && whatToMatchVal === "EOL" && !str[nextIdx]) {
73
+ return true;
74
+ }
75
+ i = getNextIdx(i);
76
+ continue;
77
+ }
78
+ const charToCompareAgainst = nextIdx > i
79
+ ? whatToMatchVal[whatToMatchVal.length - charsToCheckCount]
80
+ : whatToMatchVal[charsToCheckCount - 1];
81
+ if ((!opts.i && str[i] === charToCompareAgainst) ||
82
+ (opts.i && str[i].toLowerCase() === charToCompareAgainst.toLowerCase())) {
83
+ if (!somethingFound) {
84
+ somethingFound = true;
85
+ }
86
+ if (!atLeastSomethingWasMatched) {
87
+ atLeastSomethingWasMatched = true;
88
+ }
89
+ if (charsToCheckCount === whatToMatchVal.length) {
90
+ firstCharacterMatched = true;
91
+ if (patience !== opts.maxMismatches) {
92
+ return false;
93
+ }
94
+ }
95
+ else if (charsToCheckCount === 1) {
96
+ lastCharacterMatched = true;
97
+ }
98
+ charsToCheckCount -= 1;
111
99
  charsMatchedTotal++;
112
100
  if (whitespaceInFrontOfFirstChar()) {
113
- return false;
101
+ return false;
114
102
  }
115
- charsToCheckCount -= 2;
116
- somethingFound = true;
117
- break;
118
- } else if (nextCharInSource && nextCharToCompareAgainst && (!opts.i && nextCharInSource === nextCharToCompareAgainst || opts.i && nextCharInSource.toLowerCase() === nextCharToCompareAgainst.toLowerCase()) && (
119
- !opts.firstMustMatch || charsToCheckCount !== whatToMatchVal.length)) {
120
- if (!charsMatchedTotal && !opts.hungry) {
121
- return false;
103
+ if (!charsToCheckCount) {
104
+ return (
105
+ charsMatchedTotal !== whatToMatchVal.length ||
106
+ patience === opts.maxMismatches ||
107
+ !patienceReducedBeforeFirstMatch
108
+ ? i
109
+ : false);
122
110
  }
123
- charsToCheckCount -= 1;
124
- somethingFound = true;
125
- break;
126
- } else if (nextCharToCompareAgainst === undefined && patience >= 0 && somethingFound && (!opts.firstMustMatch || firstCharacterMatched) && (!opts.lastMustMatch || lastCharacterMatched)) {
111
+ }
112
+ else {
113
+ if (!patienceReducedBeforeFirstMatch && !charsMatchedTotal) {
114
+ patienceReducedBeforeFirstMatch = true;
115
+ }
116
+ if (opts.maxMismatches && patience && i) {
117
+ patience -= 1;
118
+ for (let y = 0; y <= patience; y++) {
119
+ const nextCharToCompareAgainst = nextIdx > i
120
+ ? whatToMatchVal[whatToMatchVal.length - charsToCheckCount + 1 + y]
121
+ : whatToMatchVal[charsToCheckCount - 2 - y];
122
+ const nextCharInSource = str[getNextIdx(i)];
123
+ if (nextCharToCompareAgainst &&
124
+ ((!opts.i && str[i] === nextCharToCompareAgainst) ||
125
+ (opts.i &&
126
+ str[i].toLowerCase() ===
127
+ nextCharToCompareAgainst.toLowerCase())) &&
128
+ (!opts.firstMustMatch ||
129
+ charsToCheckCount !== whatToMatchVal.length)) {
130
+ charsMatchedTotal++;
131
+ if (whitespaceInFrontOfFirstChar()) {
132
+ return false;
133
+ }
134
+ charsToCheckCount -= 2;
135
+ somethingFound = true;
136
+ break;
137
+ }
138
+ else if (nextCharInSource &&
139
+ nextCharToCompareAgainst &&
140
+ ((!opts.i && nextCharInSource === nextCharToCompareAgainst) ||
141
+ (opts.i &&
142
+ nextCharInSource.toLowerCase() ===
143
+ nextCharToCompareAgainst.toLowerCase())) &&
144
+ (!opts.firstMustMatch ||
145
+ charsToCheckCount !== whatToMatchVal.length)) {
146
+ if (!charsMatchedTotal && !opts.hungry) {
147
+ return false;
148
+ }
149
+ charsToCheckCount -= 1;
150
+ somethingFound = true;
151
+ break;
152
+ }
153
+ else if (nextCharToCompareAgainst === undefined &&
154
+ patience >= 0 &&
155
+ somethingFound &&
156
+ (!opts.firstMustMatch || firstCharacterMatched) &&
157
+ (!opts.lastMustMatch || lastCharacterMatched)) {
158
+ return i;
159
+ }
160
+ }
161
+ if (!somethingFound) {
162
+ lastWasMismatched = i;
163
+ }
164
+ }
165
+ else if (i === 0 &&
166
+ charsToCheckCount === 1 &&
167
+ !opts.lastMustMatch &&
168
+ atLeastSomethingWasMatched) {
169
+ return 0;
170
+ }
171
+ else {
172
+ return false;
173
+ }
174
+ }
175
+ if (lastWasMismatched !== false && lastWasMismatched !== i) {
176
+ lastWasMismatched = false;
177
+ }
178
+ if (charsToCheckCount < 1) {
127
179
  return i;
128
- }
129
180
  }
130
- if (!somethingFound) {
131
- lastWasMismatched = i;
181
+ i = getNextIdx(i);
182
+ }
183
+ if (charsToCheckCount > 0) {
184
+ if (special && whatToMatchValVal === "EOL") {
185
+ return true;
186
+ }
187
+ if (opts &&
188
+ opts.maxMismatches >= charsToCheckCount &&
189
+ atLeastSomethingWasMatched) {
190
+ return lastWasMismatched || 0;
132
191
  }
133
- } else if (i === 0 && charsToCheckCount === 1 && !opts.lastMustMatch && atLeastSomethingWasMatched) {
134
- return 0;
135
- } else {
136
192
  return false;
137
- }
138
193
  }
139
- if (lastWasMismatched !== false && lastWasMismatched !== i) {
140
- lastWasMismatched = false;
194
+ }
195
+ function main(mode, str, position, originalWhatToMatch, originalOpts) {
196
+ if (isObj(originalOpts) &&
197
+ Object.prototype.hasOwnProperty.call(originalOpts, "trimBeforeMatching") &&
198
+ typeof originalOpts.trimBeforeMatching !== "boolean") {
199
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_09] opts.trimBeforeMatching should be boolean!${Array.isArray(originalOpts.trimBeforeMatching)
200
+ ? ` Did you mean to use opts.trimCharsBeforeMatching?`
201
+ : ""}`);
141
202
  }
142
- if (charsToCheckCount < 1) {
143
- return i;
203
+ const opts = { ...defaults, ...originalOpts };
204
+ if (typeof opts.trimCharsBeforeMatching === "string") {
205
+ opts.trimCharsBeforeMatching = arrayiffy(opts.trimCharsBeforeMatching);
144
206
  }
145
- i = getNextIdx(i);
146
- }
147
- if (charsToCheckCount > 0) {
148
- if (special && whatToMatchValVal === "EOL") {
149
- return true;
207
+ opts.trimCharsBeforeMatching = opts.trimCharsBeforeMatching.map((el) => (isStr(el) ? el : String(el)));
208
+ if (!isStr(str)) {
209
+ return false;
150
210
  }
151
- if (opts && opts.maxMismatches >= charsToCheckCount && atLeastSomethingWasMatched) {
152
- return lastWasMismatched || 0;
211
+ if (!str.length) {
212
+ return false;
153
213
  }
154
- return false;
155
- }
156
- }
157
- function main(mode, str, position, originalWhatToMatch, originalOpts) {
158
- if (isObj(originalOpts) && Object.prototype.hasOwnProperty.call(originalOpts, "trimBeforeMatching") && typeof originalOpts.trimBeforeMatching !== "boolean") {
159
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_09] opts.trimBeforeMatching should be boolean!${Array.isArray(originalOpts.trimBeforeMatching) ? ` Did you mean to use opts.trimCharsBeforeMatching?` : ""}`);
160
- }
161
- const opts = { ...defaults,
162
- ...originalOpts
163
- };
164
- if (typeof opts.trimCharsBeforeMatching === "string") {
165
- opts.trimCharsBeforeMatching = arrayiffy(opts.trimCharsBeforeMatching);
166
- }
167
- opts.trimCharsBeforeMatching = opts.trimCharsBeforeMatching.map(el => isStr(el) ? el : String(el));
168
- if (!isStr(str)) {
169
- return false;
170
- }
171
- if (!str.length) {
172
- return false;
173
- }
174
- if (!Number.isInteger(position) || position < 0) {
175
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_03] the second argument should be a natural number. Currently it's of a type: ${typeof position}, equal to:\n${JSON.stringify(position, null, 4)}`);
176
- }
177
- let whatToMatch;
178
- let special;
179
- if (isStr(originalWhatToMatch)) {
180
- whatToMatch = [originalWhatToMatch];
181
- } else if (Array.isArray(originalWhatToMatch)) {
182
- whatToMatch = originalWhatToMatch;
183
- } else if (!originalWhatToMatch) {
184
- whatToMatch = originalWhatToMatch;
185
- } else if (typeof originalWhatToMatch === "function") {
186
- whatToMatch = [];
187
- whatToMatch.push(originalWhatToMatch);
188
- } else {
189
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_05] the third argument, whatToMatch, is neither string nor array of strings! It's ${typeof originalWhatToMatch}, equal to:\n${JSON.stringify(originalWhatToMatch, null, 4)}`);
190
- }
191
- if (originalOpts && !isObj(originalOpts)) {
192
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_06] the fourth argument, options object, should be a plain object. Currently it's of a type "${typeof originalOpts}", and equal to:\n${JSON.stringify(originalOpts, null, 4)}`);
193
- }
194
- let culpritsIndex = 0;
195
- let culpritsVal = "";
196
- if (opts && opts.trimCharsBeforeMatching && opts.trimCharsBeforeMatching.some((el, i) => {
197
- if (el.length > 1) {
198
- culpritsIndex = i;
199
- culpritsVal = el;
200
- return true;
214
+ if (!Number.isInteger(position) || position < 0) {
215
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_03] the second argument should be a natural number. Currently it's of a type: ${typeof position}, equal to:\n${JSON.stringify(position, null, 4)}`);
201
216
  }
202
- return false;
203
- })) {
204
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_07] the fourth argument, options object contains trimCharsBeforeMatching. It was meant to list the single characters but one of the entries at index ${culpritsIndex} is longer than 1 character, ${culpritsVal.length} (equals to ${culpritsVal}). Please split it into separate characters and put into array as separate elements.`);
205
- }
206
- if (!whatToMatch || !Array.isArray(whatToMatch) ||
207
- Array.isArray(whatToMatch) && !whatToMatch.length ||
208
- Array.isArray(whatToMatch) && whatToMatch.length === 1 && isStr(whatToMatch[0]) && !whatToMatch[0].trim()
209
- ) {
210
- if (typeof opts.cb === "function") {
211
- let firstCharOutsideIndex;
212
- let startingPosition = position;
213
- if (mode === "matchLeftIncl" || mode === "matchRight") {
214
- startingPosition += 1;
215
- }
216
- if (mode[5] === "L") {
217
- for (let y = startingPosition; y--;) {
218
- const currentChar = str[y];
219
- if ((!opts.trimBeforeMatching || opts.trimBeforeMatching && currentChar !== undefined && currentChar.trim()) && (!opts.trimCharsBeforeMatching || !opts.trimCharsBeforeMatching.length || currentChar !== undefined && !opts.trimCharsBeforeMatching.includes(currentChar))) {
220
- firstCharOutsideIndex = y;
221
- break;
222
- }
223
- }
224
- } else if (mode.startsWith("matchRight")) {
225
- for (let y = startingPosition; y < str.length; y++) {
226
- const currentChar = str[y];
227
- if ((!opts.trimBeforeMatching || opts.trimBeforeMatching && currentChar.trim()) && (!opts.trimCharsBeforeMatching || !opts.trimCharsBeforeMatching.length || !opts.trimCharsBeforeMatching.includes(currentChar))) {
228
- firstCharOutsideIndex = y;
229
- break;
230
- }
231
- }
232
- }
233
- if (firstCharOutsideIndex === undefined) {
234
- return false;
235
- }
236
- const wholeCharacterOutside = str[firstCharOutsideIndex];
237
- const indexOfTheCharacterAfter = firstCharOutsideIndex + 1;
238
- let theRemainderOfTheString = "";
239
- if (indexOfTheCharacterAfter && indexOfTheCharacterAfter > 0) {
240
- theRemainderOfTheString = str.slice(0, indexOfTheCharacterAfter);
241
- }
242
- if (mode[5] === "L") {
243
- return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
244
- }
245
- if (firstCharOutsideIndex && firstCharOutsideIndex > 0) {
246
- theRemainderOfTheString = str.slice(firstCharOutsideIndex);
247
- }
248
- return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
217
+ let whatToMatch;
218
+ let special;
219
+ if (isStr(originalWhatToMatch)) {
220
+ whatToMatch = [originalWhatToMatch];
249
221
  }
250
- let extraNote = "";
251
- if (!originalOpts) {
252
- extraNote = " More so, the whole options object, the fourth input argument, is missing!";
222
+ else if (Array.isArray(originalWhatToMatch)) {
223
+ whatToMatch = originalWhatToMatch;
253
224
  }
254
- throw new Error(`string-match-left-right/${mode}(): [THROW_ID_08] the third argument, "whatToMatch", was given as an empty string. This means, you intend to match purely by a callback. The callback was not set though, the opts key "cb" is not set!${extraNote}`);
255
- }
256
- for (let i = 0, len = whatToMatch.length; i < len; i++) {
257
- special = typeof whatToMatch[i] === "function";
258
- const whatToMatchVal = whatToMatch[i];
259
- let fullCharacterInFront;
260
- let indexOfTheCharacterInFront;
261
- let restOfStringInFront = "";
262
- let startingPosition = position;
263
- if (mode === "matchRight") {
264
- startingPosition += 1;
265
- } else if (mode === "matchLeft") {
266
- startingPosition -= 1;
225
+ else if (!originalWhatToMatch) {
226
+ whatToMatch = originalWhatToMatch;
267
227
  }
268
- const found = march(str, startingPosition, whatToMatchVal, opts, special, i2 => mode[5] === "L" ? i2 - 1 : i2 + 1);
269
- if (found && special && typeof whatToMatchVal === "function" && whatToMatchVal() === "EOL") {
270
- return whatToMatchVal() && (opts.cb ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront) : true) ? whatToMatchVal() : false;
228
+ else if (typeof originalWhatToMatch === "function") {
229
+ whatToMatch = [];
230
+ whatToMatch.push(originalWhatToMatch);
271
231
  }
272
- if (Number.isInteger(found)) {
273
- indexOfTheCharacterInFront = mode.startsWith("matchLeft") ? found - 1 : found + 1;
274
- if (mode[5] === "L") {
275
- restOfStringInFront = str.slice(0, found);
276
- } else {
277
- restOfStringInFront = str.slice(indexOfTheCharacterInFront);
278
- }
232
+ else {
233
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_05] the third argument, whatToMatch, is neither string nor array of strings! It's ${typeof originalWhatToMatch}, equal to:\n${JSON.stringify(originalWhatToMatch, null, 4)}`);
279
234
  }
280
- if (indexOfTheCharacterInFront < 0) {
281
- indexOfTheCharacterInFront = undefined;
235
+ if (originalOpts && !isObj(originalOpts)) {
236
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_06] the fourth argument, options object, should be a plain object. Currently it's of a type "${typeof originalOpts}", and equal to:\n${JSON.stringify(originalOpts, null, 4)}`);
282
237
  }
283
- if (str[indexOfTheCharacterInFront]) {
284
- fullCharacterInFront = str[indexOfTheCharacterInFront];
238
+ let culpritsIndex = 0;
239
+ let culpritsVal = "";
240
+ if (opts &&
241
+ opts.trimCharsBeforeMatching &&
242
+ opts.trimCharsBeforeMatching.some((el, i) => {
243
+ if (el.length > 1) {
244
+ culpritsIndex = i;
245
+ culpritsVal = el;
246
+ return true;
247
+ }
248
+ return false;
249
+ })) {
250
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_07] the fourth argument, options object contains trimCharsBeforeMatching. It was meant to list the single characters but one of the entries at index ${culpritsIndex} is longer than 1 character, ${culpritsVal.length} (equals to ${culpritsVal}). Please split it into separate characters and put into array as separate elements.`);
285
251
  }
286
- if (Number.isInteger(found) && (opts.cb ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront) : true)) {
287
- return whatToMatchVal;
252
+ if (!whatToMatch ||
253
+ !Array.isArray(whatToMatch) ||
254
+ (Array.isArray(whatToMatch) && !whatToMatch.length) ||
255
+ (Array.isArray(whatToMatch) &&
256
+ whatToMatch.length === 1 &&
257
+ isStr(whatToMatch[0]) &&
258
+ !whatToMatch[0].trim())
259
+ ) {
260
+ if (typeof opts.cb === "function") {
261
+ let firstCharOutsideIndex;
262
+ let startingPosition = position;
263
+ if (mode === "matchLeftIncl" || mode === "matchRight") {
264
+ startingPosition += 1;
265
+ }
266
+ if (mode[5] === "L") {
267
+ for (let y = startingPosition; y--;) {
268
+ const currentChar = str[y];
269
+ if ((!opts.trimBeforeMatching ||
270
+ (opts.trimBeforeMatching &&
271
+ currentChar !== undefined &&
272
+ currentChar.trim())) &&
273
+ (!opts.trimCharsBeforeMatching ||
274
+ !opts.trimCharsBeforeMatching.length ||
275
+ (currentChar !== undefined &&
276
+ !opts.trimCharsBeforeMatching.includes(currentChar)))) {
277
+ firstCharOutsideIndex = y;
278
+ break;
279
+ }
280
+ }
281
+ }
282
+ else if (mode.startsWith("matchRight")) {
283
+ for (let y = startingPosition; y < str.length; y++) {
284
+ const currentChar = str[y];
285
+ if ((!opts.trimBeforeMatching ||
286
+ (opts.trimBeforeMatching && currentChar.trim())) &&
287
+ (!opts.trimCharsBeforeMatching ||
288
+ !opts.trimCharsBeforeMatching.length ||
289
+ !opts.trimCharsBeforeMatching.includes(currentChar))) {
290
+ firstCharOutsideIndex = y;
291
+ break;
292
+ }
293
+ }
294
+ }
295
+ if (firstCharOutsideIndex === undefined) {
296
+ return false;
297
+ }
298
+ const wholeCharacterOutside = str[firstCharOutsideIndex];
299
+ const indexOfTheCharacterAfter = firstCharOutsideIndex + 1;
300
+ let theRemainderOfTheString = "";
301
+ if (indexOfTheCharacterAfter && indexOfTheCharacterAfter > 0) {
302
+ theRemainderOfTheString = str.slice(0, indexOfTheCharacterAfter);
303
+ }
304
+ if (mode[5] === "L") {
305
+ return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
306
+ }
307
+ if (firstCharOutsideIndex && firstCharOutsideIndex > 0) {
308
+ theRemainderOfTheString = str.slice(firstCharOutsideIndex);
309
+ }
310
+ return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
311
+ }
312
+ let extraNote = "";
313
+ if (!originalOpts) {
314
+ extraNote =
315
+ " More so, the whole options object, the fourth input argument, is missing!";
316
+ }
317
+ throw new Error(`string-match-left-right/${mode}(): [THROW_ID_08] the third argument, "whatToMatch", was given as an empty string. This means, you intend to match purely by a callback. The callback was not set though, the opts key "cb" is not set!${extraNote}`);
318
+ }
319
+ for (let i = 0, len = whatToMatch.length; i < len; i++) {
320
+ special = typeof whatToMatch[i] === "function";
321
+ const whatToMatchVal = whatToMatch[i];
322
+ let fullCharacterInFront;
323
+ let indexOfTheCharacterInFront;
324
+ let restOfStringInFront = "";
325
+ let startingPosition = position;
326
+ if (mode === "matchRight") {
327
+ startingPosition += 1;
328
+ }
329
+ else if (mode === "matchLeft") {
330
+ startingPosition -= 1;
331
+ }
332
+ const found = march(str, startingPosition, whatToMatchVal, opts, special, (i2) => (mode[5] === "L" ? i2 - 1 : i2 + 1));
333
+ if (found &&
334
+ special &&
335
+ typeof whatToMatchVal === "function" &&
336
+ whatToMatchVal() === "EOL") {
337
+ return whatToMatchVal() &&
338
+ (opts.cb
339
+ ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront)
340
+ : true)
341
+ ? whatToMatchVal()
342
+ : false;
343
+ }
344
+ if (Number.isInteger(found)) {
345
+ indexOfTheCharacterInFront = mode.startsWith("matchLeft")
346
+ ? found - 1
347
+ : found + 1;
348
+ if (mode[5] === "L") {
349
+ restOfStringInFront = str.slice(0, found);
350
+ }
351
+ else {
352
+ restOfStringInFront = str.slice(indexOfTheCharacterInFront);
353
+ }
354
+ }
355
+ if (indexOfTheCharacterInFront < 0) {
356
+ indexOfTheCharacterInFront = undefined;
357
+ }
358
+ if (str[indexOfTheCharacterInFront]) {
359
+ fullCharacterInFront = str[indexOfTheCharacterInFront];
360
+ }
361
+ if (Number.isInteger(found) &&
362
+ (opts.cb
363
+ ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront)
364
+ : true)) {
365
+ return whatToMatchVal;
366
+ }
288
367
  }
289
- }
290
- return false;
368
+ return false;
291
369
  }
292
370
  function matchLeftIncl(str, position, whatToMatch, opts) {
293
- return main("matchLeftIncl", str, position, whatToMatch, opts);
371
+ return main("matchLeftIncl", str, position, whatToMatch, opts);
294
372
  }
295
373
  function matchLeft(str, position, whatToMatch, opts) {
296
- return main("matchLeft", str, position, whatToMatch, opts);
374
+ return main("matchLeft", str, position, whatToMatch, opts);
297
375
  }
298
376
  function matchRightIncl(str, position, whatToMatch, opts) {
299
- return main("matchRightIncl", str, position, whatToMatch, opts);
377
+ return main("matchRightIncl", str, position, whatToMatch, opts);
300
378
  }
301
379
  function matchRight(str, position, whatToMatch, opts) {
302
- return main("matchRight", str, position, whatToMatch, opts);
380
+ return main("matchRight", str, position, whatToMatch, opts);
303
381
  }
304
382
 
305
383
  export { matchLeft, matchLeftIncl, matchRight, matchRightIncl };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @name string-match-left-right
3
3
  * @fileoverview Match substrings on the left or right of a given index, ignoring whitespace
4
- * @version 8.0.5
4
+ * @version 8.0.6
5
5
  * @author Roy Revelt, Codsen Ltd
6
6
  * @license MIT
7
7
  * {@link https://codsen.com/os/string-match-left-right/}
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * @name arrayiffy-if-string
13
13
  * @fileoverview Put non-empty strings into arrays, turn empty-ones into empty arrays. Bypass everything else.
14
- * @version 4.0.5
14
+ * @version 4.0.6
15
15
  * @author Roy Revelt, Codsen Ltd
16
16
  * @license MIT
17
17
  * {@link https://codsen.com/os/arrayiffy-if-string/}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "string-match-left-right",
3
- "version": "8.0.5",
3
+ "version": "8.0.6",
4
4
  "description": "Match substrings on the left or right of a given index, ignoring whitespace",
5
5
  "keywords": [
6
6
  "left",
@@ -32,13 +32,12 @@
32
32
  "types": "types/index.d.ts",
33
33
  "scripts": {
34
34
  "build": "rollup -c",
35
- "ci_test": "npm run build && npm run format && tap --no-only --reporter=silent --output-file=testStats.md && npm run clean_cov",
36
- "clean_cov": "../../scripts/leaveCoverageTotalOnly.js",
35
+ "build:esbuild": "node '../../scripts/esbuild.js'",
36
+ "build:esbuild:dev": "cross-env MODE=dev node '../../scripts/esbuild.js'",
37
+ "ci_test": "npm run build && npm run format && tap --no-only --reporter=silent",
37
38
  "clean_types": "../../scripts/cleanTypes.js",
38
39
  "dev": "rollup -c --dev",
39
40
  "devunittest": "npm run dev && tap --only -R 'base'",
40
- "esbuild": "node '../../scripts/esbuild.js'",
41
- "esbuild_dev": "cross-env MODE=dev node '../../scripts/esbuild.js'",
42
41
  "format": "npm run lect && npm run prettier && npm run lint",
43
42
  "lect": "lect",
44
43
  "lint": "../../node_modules/eslint/bin/eslint.js . --ext .js --ext .ts --fix --config \"../../.eslintrc.json\" --quiet",
@@ -47,17 +46,14 @@
47
46
  "republish": "npm publish || :",
48
47
  "tap": "tap",
49
48
  "pretest": "npm run build",
50
- "test": "npm run lint && npm run unittest && npm run test:examples && npm run clean_cov && npm run format",
49
+ "test": "npm run test:ci && npm run perf",
50
+ "test:ci": "npm run unittest && npm run test:examples && npm run format",
51
51
  "test:examples": "../../scripts/test-examples.js && npm run lect && npm run prettier",
52
52
  "tsc": "tsc",
53
- "unittest": "tap --no-only --output-file=testStats.md --reporter=terse && tsc -p tsconfig.json --noEmit && npm run clean_cov && npm run perf"
53
+ "unittest": "tap --no-only --reporter=terse && tsc -p tsconfig.json --noEmit"
54
54
  },
55
55
  "tap": {
56
56
  "check-coverage": false,
57
- "coverage-report": [
58
- "json-summary",
59
- "text"
60
- ],
61
57
  "node-arg": [
62
58
  "--no-warnings",
63
59
  "--experimental-loader",
@@ -79,10 +75,10 @@
79
75
  }
80
76
  },
81
77
  "dependencies": {
82
- "@babel/runtime": "^7.16.0",
83
- "arrayiffy-if-string": "^4.0.5",
78
+ "@babel/runtime": "^7.16.3",
79
+ "arrayiffy-if-string": "^4.0.6",
84
80
  "lodash.isplainobject": "^4.0.6",
85
- "string-character-is-astral-surrogate": "^2.0.5"
81
+ "string-character-is-astral-surrogate": "^2.0.6"
86
82
  },
87
83
  "devDependencies": {
88
84
  "@babel/cli": "^7.16.0",
@@ -93,8 +89,8 @@
93
89
  "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
94
90
  "@babel/plugin-proposal-object-rest-spread": "^7.16.0",
95
91
  "@babel/plugin-proposal-optional-chaining": "^7.16.0",
96
- "@babel/plugin-transform-runtime": "^7.16.0",
97
- "@babel/preset-env": "^7.16.0",
92
+ "@babel/plugin-transform-runtime": "^7.16.4",
93
+ "@babel/preset-env": "^7.16.4",
98
94
  "@babel/preset-typescript": "^7.16.0",
99
95
  "@babel/register": "^7.16.0",
100
96
  "@istanbuljs/esm-loader-hook": "^0.1.2",
@@ -104,25 +100,25 @@
104
100
  "@rollup/plugin-strip": "^2.1.0",
105
101
  "@rollup/plugin-typescript": "^8.3.0",
106
102
  "@types/lodash.isplainobject": "^4.0.6",
107
- "@types/node": "^16.11.6",
103
+ "@types/node": "^16.11.9",
108
104
  "@types/tap": "^15.0.5",
109
- "@typescript-eslint/eslint-plugin": "^5.3.0",
110
- "@typescript-eslint/parser": "^5.3.0",
105
+ "@typescript-eslint/eslint-plugin": "^5.4.0",
106
+ "@typescript-eslint/parser": "^5.4.0",
111
107
  "core-js": "^3.19.1",
112
108
  "cross-env": "^7.0.3",
113
- "eslint": "^8.2.0",
114
- "lect": "^0.18.5",
115
- "rollup": "^2.59.0",
109
+ "eslint": "^8.3.0",
110
+ "lect": "^0.18.6",
111
+ "rollup": "^2.60.0",
116
112
  "rollup-plugin-ascii": "^0.0.3",
117
113
  "rollup-plugin-banner": "^0.2.1",
118
114
  "rollup-plugin-cleanup": "^3.2.1",
119
115
  "rollup-plugin-dts": "^4.0.1",
120
116
  "rollup-plugin-terser": "^7.0.2",
121
- "tap": "^15.0.10",
117
+ "tap": "^15.1.2",
122
118
  "tslib": "^2.3.1",
123
- "typescript": "^4.4.4"
119
+ "typescript": "^4.5.2"
124
120
  },
125
121
  "engines": {
126
- "node": ">=12"
122
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
127
123
  }
128
124
  }