string-match-left-right 8.0.2 → 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.
package/CHANGELOG.md CHANGED
@@ -3,12 +3,6 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## 8.0.1 (2021-09-13)
7
-
8
- ### Bug Fixes
9
-
10
- - bump TS and separate ESLint plugins away from this monorepo ([2e07d42](https://github.com/codsen/codsen/commit/2e07d424222b6ffedf5fb45c83ad453627ec2904))
11
-
12
6
  ## 8.0.0 (2021-09-09)
13
7
 
14
8
  ### Features
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2010-%YEAR% Roy Revelt and other contributors
3
+ Copyright (c) 2010-2021 Roy Revelt and other contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -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.2
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,292 +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()) && (!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;
110
99
  charsMatchedTotal++;
111
100
  if (whitespaceInFrontOfFirstChar()) {
112
- return false;
101
+ return false;
113
102
  }
114
- charsToCheckCount -= 2;
115
- somethingFound = true;
116
- break;
117
- } else if (nextCharInSource && nextCharToCompareAgainst && (!opts.i && nextCharInSource === nextCharToCompareAgainst || opts.i && nextCharInSource.toLowerCase() === nextCharToCompareAgainst.toLowerCase()) && (!opts.firstMustMatch || charsToCheckCount !== whatToMatchVal.length)) {
118
- if (!charsMatchedTotal && !opts.hungry) {
119
- return false;
103
+ if (!charsToCheckCount) {
104
+ return (
105
+ charsMatchedTotal !== whatToMatchVal.length ||
106
+ patience === opts.maxMismatches ||
107
+ !patienceReducedBeforeFirstMatch
108
+ ? i
109
+ : false);
120
110
  }
121
- charsToCheckCount -= 1;
122
- somethingFound = true;
123
- break;
124
- } 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) {
125
179
  return i;
126
- }
127
180
  }
128
- if (!somethingFound) {
129
- 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;
130
191
  }
131
- } else if (i === 0 && charsToCheckCount === 1 && !opts.lastMustMatch && atLeastSomethingWasMatched) {
132
- return 0;
133
- } else {
134
192
  return false;
135
- }
136
193
  }
137
- if (lastWasMismatched !== false && lastWasMismatched !== i) {
138
- 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
+ : ""}`);
139
202
  }
140
- if (charsToCheckCount < 1) {
141
- return i;
203
+ const opts = { ...defaults, ...originalOpts };
204
+ if (typeof opts.trimCharsBeforeMatching === "string") {
205
+ opts.trimCharsBeforeMatching = arrayiffy(opts.trimCharsBeforeMatching);
142
206
  }
143
- i = getNextIdx(i);
144
- }
145
- if (charsToCheckCount > 0) {
146
- if (special && whatToMatchValVal === "EOL") {
147
- return true;
207
+ opts.trimCharsBeforeMatching = opts.trimCharsBeforeMatching.map((el) => (isStr(el) ? el : String(el)));
208
+ if (!isStr(str)) {
209
+ return false;
148
210
  }
149
- if (opts && opts.maxMismatches >= charsToCheckCount && atLeastSomethingWasMatched) {
150
- return lastWasMismatched || 0;
211
+ if (!str.length) {
212
+ return false;
151
213
  }
152
- return false;
153
- }
154
- }
155
- function main(mode, str, position, originalWhatToMatch, originalOpts) {
156
- if (isObj(originalOpts) && Object.prototype.hasOwnProperty.call(originalOpts, "trimBeforeMatching") && typeof originalOpts.trimBeforeMatching !== "boolean") {
157
- 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?` : ""}`);
158
- }
159
- const opts = { ...defaults,
160
- ...originalOpts
161
- };
162
- if (typeof opts.trimCharsBeforeMatching === "string") {
163
- opts.trimCharsBeforeMatching = arrayiffy(opts.trimCharsBeforeMatching);
164
- }
165
- opts.trimCharsBeforeMatching = opts.trimCharsBeforeMatching.map(el => isStr(el) ? el : String(el));
166
- if (!isStr(str)) {
167
- return false;
168
- }
169
- if (!str.length) {
170
- return false;
171
- }
172
- if (!Number.isInteger(position) || position < 0) {
173
- 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)}`);
174
- }
175
- let whatToMatch;
176
- let special;
177
- if (isStr(originalWhatToMatch)) {
178
- whatToMatch = [originalWhatToMatch];
179
- } else if (Array.isArray(originalWhatToMatch)) {
180
- whatToMatch = originalWhatToMatch;
181
- } else if (!originalWhatToMatch) {
182
- whatToMatch = originalWhatToMatch;
183
- } else if (typeof originalWhatToMatch === "function") {
184
- whatToMatch = [];
185
- whatToMatch.push(originalWhatToMatch);
186
- } else {
187
- 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)}`);
188
- }
189
- if (originalOpts && !isObj(originalOpts)) {
190
- 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)}`);
191
- }
192
- let culpritsIndex = 0;
193
- let culpritsVal = "";
194
- if (opts && opts.trimCharsBeforeMatching && opts.trimCharsBeforeMatching.some((el, i) => {
195
- if (el.length > 1) {
196
- culpritsIndex = i;
197
- culpritsVal = el;
198
- 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)}`);
199
216
  }
200
- return false;
201
- })) {
202
- 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.`);
203
- }
204
- if (!whatToMatch || !Array.isArray(whatToMatch) || Array.isArray(whatToMatch) && !whatToMatch.length || Array.isArray(whatToMatch) && whatToMatch.length === 1 && isStr(whatToMatch[0]) && !whatToMatch[0].trim()
205
- ) {
206
- if (typeof opts.cb === "function") {
207
- let firstCharOutsideIndex;
208
- let startingPosition = position;
209
- if (mode === "matchLeftIncl" || mode === "matchRight") {
210
- startingPosition += 1;
211
- }
212
- if (mode[5] === "L") {
213
- for (let y = startingPosition; y--;) {
214
- const currentChar = str[y];
215
- if ((!opts.trimBeforeMatching || opts.trimBeforeMatching && currentChar !== undefined && currentChar.trim()) && (!opts.trimCharsBeforeMatching || !opts.trimCharsBeforeMatching.length || currentChar !== undefined && !opts.trimCharsBeforeMatching.includes(currentChar))) {
216
- firstCharOutsideIndex = y;
217
- break;
218
- }
219
- }
220
- } else if (mode.startsWith("matchRight")) {
221
- for (let y = startingPosition; y < str.length; y++) {
222
- const currentChar = str[y];
223
- if ((!opts.trimBeforeMatching || opts.trimBeforeMatching && currentChar.trim()) && (!opts.trimCharsBeforeMatching || !opts.trimCharsBeforeMatching.length || !opts.trimCharsBeforeMatching.includes(currentChar))) {
224
- firstCharOutsideIndex = y;
225
- break;
226
- }
227
- }
228
- }
229
- if (firstCharOutsideIndex === undefined) {
230
- return false;
231
- }
232
- const wholeCharacterOutside = str[firstCharOutsideIndex];
233
- const indexOfTheCharacterAfter = firstCharOutsideIndex + 1;
234
- let theRemainderOfTheString = "";
235
- if (indexOfTheCharacterAfter && indexOfTheCharacterAfter > 0) {
236
- theRemainderOfTheString = str.slice(0, indexOfTheCharacterAfter);
237
- }
238
- if (mode[5] === "L") {
239
- return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
240
- }
241
- if (firstCharOutsideIndex && firstCharOutsideIndex > 0) {
242
- theRemainderOfTheString = str.slice(firstCharOutsideIndex);
243
- }
244
- return opts.cb(wholeCharacterOutside, theRemainderOfTheString, firstCharOutsideIndex);
217
+ let whatToMatch;
218
+ let special;
219
+ if (isStr(originalWhatToMatch)) {
220
+ whatToMatch = [originalWhatToMatch];
245
221
  }
246
- let extraNote = "";
247
- if (!originalOpts) {
248
- extraNote = " More so, the whole options object, the fourth input argument, is missing!";
222
+ else if (Array.isArray(originalWhatToMatch)) {
223
+ whatToMatch = originalWhatToMatch;
249
224
  }
250
- 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}`);
251
- }
252
- for (let i = 0, len = whatToMatch.length; i < len; i++) {
253
- special = typeof whatToMatch[i] === "function";
254
- const whatToMatchVal = whatToMatch[i];
255
- let fullCharacterInFront;
256
- let indexOfTheCharacterInFront;
257
- let restOfStringInFront = "";
258
- let startingPosition = position;
259
- if (mode === "matchRight") {
260
- startingPosition += 1;
261
- } else if (mode === "matchLeft") {
262
- startingPosition -= 1;
225
+ else if (!originalWhatToMatch) {
226
+ whatToMatch = originalWhatToMatch;
263
227
  }
264
- const found = march(str, startingPosition, whatToMatchVal, opts, special, i2 => mode[5] === "L" ? i2 - 1 : i2 + 1);
265
- if (found && special && typeof whatToMatchVal === "function" && whatToMatchVal() === "EOL") {
266
- return whatToMatchVal() && (opts.cb ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront) : true) ? whatToMatchVal() : false;
228
+ else if (typeof originalWhatToMatch === "function") {
229
+ whatToMatch = [];
230
+ whatToMatch.push(originalWhatToMatch);
267
231
  }
268
- if (Number.isInteger(found)) {
269
- indexOfTheCharacterInFront = mode.startsWith("matchLeft") ? found - 1 : found + 1;
270
- if (mode[5] === "L") {
271
- restOfStringInFront = str.slice(0, found);
272
- } else {
273
- restOfStringInFront = str.slice(indexOfTheCharacterInFront);
274
- }
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)}`);
275
234
  }
276
- if (indexOfTheCharacterInFront < 0) {
277
- 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)}`);
278
237
  }
279
- if (str[indexOfTheCharacterInFront]) {
280
- 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.`);
281
251
  }
282
- if (Number.isInteger(found) && (opts.cb ? opts.cb(fullCharacterInFront, restOfStringInFront, indexOfTheCharacterInFront) : true)) {
283
- 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
+ }
284
367
  }
285
- }
286
- return false;
368
+ return false;
287
369
  }
288
370
  function matchLeftIncl(str, position, whatToMatch, opts) {
289
- return main("matchLeftIncl", str, position, whatToMatch, opts);
371
+ return main("matchLeftIncl", str, position, whatToMatch, opts);
290
372
  }
291
373
  function matchLeft(str, position, whatToMatch, opts) {
292
- return main("matchLeft", str, position, whatToMatch, opts);
374
+ return main("matchLeft", str, position, whatToMatch, opts);
293
375
  }
294
376
  function matchRightIncl(str, position, whatToMatch, opts) {
295
- return main("matchRightIncl", str, position, whatToMatch, opts);
377
+ return main("matchRightIncl", str, position, whatToMatch, opts);
296
378
  }
297
379
  function matchRight(str, position, whatToMatch, opts) {
298
- return main("matchRight", str, position, whatToMatch, opts);
380
+ return main("matchRight", str, position, whatToMatch, opts);
299
381
  }
300
382
 
301
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.2
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.2
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.2",
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,9 +32,10 @@
32
32
  "types": "types/index.d.ts",
33
33
  "scripts": {
34
34
  "build": "rollup -c",
35
- "esbuild": "node '../../scripts/esbuild.js'",
36
- "esbuild_dev": "cross-env MODE=dev node '../../scripts/esbuild.js'",
37
- "ci_test": "npm run build && npm run format && tap --no-only --reporter=silent --output-file=testStats.md && npm run clean_cov",
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",
38
+ "clean_types": "../../scripts/cleanTypes.js",
38
39
  "dev": "rollup -c --dev",
39
40
  "devunittest": "npm run dev && tap --only -R 'base'",
40
41
  "format": "npm run lect && npm run prettier && npm run lint",
@@ -44,20 +45,15 @@
44
45
  "prettier": "../../node_modules/prettier/bin-prettier.js '*.{js,css,scss,vue,md,ts}' --write --loglevel silent",
45
46
  "republish": "npm publish || :",
46
47
  "tap": "tap",
47
- "tsc": "tsc",
48
48
  "pretest": "npm run build",
49
- "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",
50
51
  "test:examples": "../../scripts/test-examples.js && npm run lect && npm run prettier",
51
- "unittest": "tap --no-only --output-file=testStats.md --reporter=terse && tsc -p tsconfig.json --noEmit && npm run clean_cov && npm run perf",
52
- "clean_cov": "../../scripts/leaveCoverageTotalOnly.js",
53
- "clean_types": "../../scripts/cleanTypes.js"
52
+ "tsc": "tsc",
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,50 +75,50 @@
79
75
  }
80
76
  },
81
77
  "dependencies": {
82
- "@babel/runtime": "^7.15.4",
83
- "arrayiffy-if-string": "^4.0.2",
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.2"
81
+ "string-character-is-astral-surrogate": "^2.0.6"
86
82
  },
87
83
  "devDependencies": {
88
- "@babel/cli": "^7.15.4",
89
- "@babel/core": "^7.15.5",
90
- "@babel/node": "^7.15.4",
91
- "@babel/plugin-external-helpers": "^7.14.5",
92
- "@babel/plugin-proposal-class-properties": "^7.14.5",
93
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
94
- "@babel/plugin-proposal-object-rest-spread": "^7.15.6",
95
- "@babel/plugin-proposal-optional-chaining": "^7.14.5",
96
- "@babel/plugin-transform-runtime": "^7.15.0",
97
- "@babel/preset-env": "^7.15.6",
98
- "@babel/preset-typescript": "^7.15.0",
99
- "@babel/register": "^7.15.3",
84
+ "@babel/cli": "^7.16.0",
85
+ "@babel/core": "^7.16.0",
86
+ "@babel/node": "^7.16.0",
87
+ "@babel/plugin-external-helpers": "^7.16.0",
88
+ "@babel/plugin-proposal-class-properties": "^7.16.0",
89
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
90
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.0",
91
+ "@babel/plugin-proposal-optional-chaining": "^7.16.0",
92
+ "@babel/plugin-transform-runtime": "^7.16.4",
93
+ "@babel/preset-env": "^7.16.4",
94
+ "@babel/preset-typescript": "^7.16.0",
95
+ "@babel/register": "^7.16.0",
100
96
  "@istanbuljs/esm-loader-hook": "^0.1.2",
101
97
  "@rollup/plugin-babel": "^5.3.0",
102
- "@rollup/plugin-commonjs": "^20.0.0",
103
- "@rollup/plugin-node-resolve": "^13.0.4",
98
+ "@rollup/plugin-commonjs": "^21.0.1",
99
+ "@rollup/plugin-node-resolve": "^13.0.6",
104
100
  "@rollup/plugin-strip": "^2.1.0",
105
- "@rollup/plugin-typescript": "^8.2.5",
101
+ "@rollup/plugin-typescript": "^8.3.0",
106
102
  "@types/lodash.isplainobject": "^4.0.6",
107
- "@types/node": "^16.9.1",
103
+ "@types/node": "^16.11.9",
108
104
  "@types/tap": "^15.0.5",
109
- "@typescript-eslint/eslint-plugin": "^4.31.0",
110
- "@typescript-eslint/parser": "^4.31.0",
111
- "core-js": "^3.17.3",
105
+ "@typescript-eslint/eslint-plugin": "^5.4.0",
106
+ "@typescript-eslint/parser": "^5.4.0",
107
+ "core-js": "^3.19.1",
112
108
  "cross-env": "^7.0.3",
113
- "eslint": "^7.32.0",
114
- "lect": "^0.18.2",
115
- "rollup": "^2.56.3",
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
- "rollup-plugin-dts": "^4.0.0",
115
+ "rollup-plugin-dts": "^4.0.1",
120
116
  "rollup-plugin-terser": "^7.0.2",
121
- "tap": "^15.0.9",
117
+ "tap": "^15.1.2",
122
118
  "tslib": "^2.3.1",
123
- "typescript": "^4.4.3"
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
  }