@jsenv/core 40.0.6 → 40.0.7
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/dist/jsenv_core_packages.js +74 -31
- package/package.json +6 -5
|
@@ -54,6 +54,13 @@ const applyPattern = ({ url, pattern }) => {
|
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Core pattern matching function that processes patterns against strings
|
|
59
|
+
* @param {string} pattern - The pattern with special syntax (*,**,/) to match against
|
|
60
|
+
* @param {string} string - The string to test against the pattern
|
|
61
|
+
* @returns {Object} Result containing match status and capture groups
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
57
64
|
const applyMatching = (pattern, string) => {
|
|
58
65
|
const groups = [];
|
|
59
66
|
let patternIndex = 0;
|
|
@@ -78,22 +85,6 @@ const applyMatching = (pattern, string) => {
|
|
|
78
85
|
return consumeString(remainingString.length);
|
|
79
86
|
};
|
|
80
87
|
|
|
81
|
-
let matched;
|
|
82
|
-
const iterate = () => {
|
|
83
|
-
const patternIndexBefore = patternIndex;
|
|
84
|
-
const indexBefore = index;
|
|
85
|
-
matched = matchOne();
|
|
86
|
-
if (matched === undefined) {
|
|
87
|
-
consumePattern(1);
|
|
88
|
-
consumeString(1);
|
|
89
|
-
iterate();
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (matched === false && restoreIndexes) {
|
|
93
|
-
patternIndex = patternIndexBefore;
|
|
94
|
-
index = indexBefore;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
88
|
const matchOne = () => {
|
|
98
89
|
// pattern consumed
|
|
99
90
|
if (remainingPattern === "") {
|
|
@@ -103,12 +94,11 @@ const applyMatching = (pattern, string) => {
|
|
|
103
94
|
if (remainingString[0] === "?") {
|
|
104
95
|
// match search params
|
|
105
96
|
consumeRemainingString();
|
|
106
|
-
|
|
107
97
|
return true;
|
|
108
98
|
}
|
|
109
|
-
// if remainingString
|
|
110
99
|
return false; // fails because string longer than expect
|
|
111
100
|
}
|
|
101
|
+
|
|
112
102
|
// -- from this point pattern is not consumed --
|
|
113
103
|
// string consumed, pattern not consumed
|
|
114
104
|
if (remainingString === "") {
|
|
@@ -122,6 +112,7 @@ const applyMatching = (pattern, string) => {
|
|
|
122
112
|
}
|
|
123
113
|
return false; // fail because string shorter than expect
|
|
124
114
|
}
|
|
115
|
+
|
|
125
116
|
// -- from this point pattern and string are not consumed --
|
|
126
117
|
// fast path trailing slash
|
|
127
118
|
if (remainingPattern === "/") {
|
|
@@ -133,25 +124,30 @@ const applyMatching = (pattern, string) => {
|
|
|
133
124
|
}
|
|
134
125
|
return false;
|
|
135
126
|
}
|
|
127
|
+
|
|
136
128
|
// fast path trailing '**'
|
|
137
129
|
if (remainingPattern === "**") {
|
|
138
130
|
consumePattern(2);
|
|
139
131
|
consumeRemainingString();
|
|
140
132
|
return true;
|
|
141
133
|
}
|
|
134
|
+
|
|
142
135
|
if (remainingPattern.slice(0, 4) === "/**/") {
|
|
143
136
|
consumePattern(3); // consumes "/**/"
|
|
144
|
-
const skipResult =
|
|
137
|
+
const skipResult = skipUntilMatchIterative({
|
|
145
138
|
pattern: remainingPattern,
|
|
146
139
|
string: remainingString,
|
|
147
140
|
canSkipSlash: true,
|
|
148
141
|
});
|
|
149
|
-
|
|
142
|
+
for (let i = 0; i < skipResult.groups.length; i++) {
|
|
143
|
+
groups.push(skipResult.groups[i]);
|
|
144
|
+
}
|
|
150
145
|
consumePattern(skipResult.patternIndex);
|
|
151
146
|
consumeRemainingString();
|
|
152
147
|
restoreIndexes = false;
|
|
153
148
|
return skipResult.matched;
|
|
154
149
|
}
|
|
150
|
+
|
|
155
151
|
// pattern leading **
|
|
156
152
|
if (remainingPattern.slice(0, 2) === "**") {
|
|
157
153
|
consumePattern(2); // consumes "**"
|
|
@@ -161,7 +157,7 @@ const applyMatching = (pattern, string) => {
|
|
|
161
157
|
// when remainingPattern was preceeded by "**/"
|
|
162
158
|
// and remainingString have no "/"
|
|
163
159
|
// then skip is not allowed, a regular match will be performed
|
|
164
|
-
if (
|
|
160
|
+
if (remainingString.includes("/")) {
|
|
165
161
|
skipAllowed = false;
|
|
166
162
|
}
|
|
167
163
|
}
|
|
@@ -171,18 +167,21 @@ const applyMatching = (pattern, string) => {
|
|
|
171
167
|
return true;
|
|
172
168
|
}
|
|
173
169
|
if (skipAllowed) {
|
|
174
|
-
const skipResult =
|
|
170
|
+
const skipResult = skipUntilMatchIterative({
|
|
175
171
|
pattern: remainingPattern,
|
|
176
172
|
string: remainingString,
|
|
177
173
|
canSkipSlash: true,
|
|
178
174
|
});
|
|
179
|
-
|
|
175
|
+
for (let i = 0; i < skipResult.groups.length; i++) {
|
|
176
|
+
groups.push(skipResult.groups[i]);
|
|
177
|
+
}
|
|
180
178
|
consumePattern(skipResult.patternIndex);
|
|
181
179
|
consumeRemainingString();
|
|
182
180
|
restoreIndexes = false;
|
|
183
181
|
return skipResult.matched;
|
|
184
182
|
}
|
|
185
183
|
}
|
|
184
|
+
|
|
186
185
|
if (remainingPattern[0] === "*") {
|
|
187
186
|
consumePattern(1); // consumes "*"
|
|
188
187
|
if (remainingPattern === "") {
|
|
@@ -202,23 +201,53 @@ const applyMatching = (pattern, string) => {
|
|
|
202
201
|
patternIndex = patternIndex - 1;
|
|
203
202
|
return false;
|
|
204
203
|
}
|
|
205
|
-
const skipResult =
|
|
204
|
+
const skipResult = skipUntilMatchIterative({
|
|
206
205
|
pattern: remainingPattern,
|
|
207
206
|
string: remainingString,
|
|
208
207
|
canSkipSlash: false,
|
|
209
208
|
});
|
|
210
|
-
groups.push(skipResult.group
|
|
209
|
+
groups.push(skipResult.group);
|
|
210
|
+
for (let i = 0; i < skipResult.groups.length; i++) {
|
|
211
|
+
groups.push(skipResult.groups[i]);
|
|
212
|
+
}
|
|
211
213
|
consumePattern(skipResult.patternIndex);
|
|
212
214
|
consumeString(skipResult.index);
|
|
213
215
|
restoreIndexes = false;
|
|
214
216
|
return skipResult.matched;
|
|
215
217
|
}
|
|
218
|
+
|
|
216
219
|
if (remainingPattern[0] !== remainingString[0]) {
|
|
217
220
|
return false;
|
|
218
221
|
}
|
|
222
|
+
|
|
219
223
|
return undefined;
|
|
220
224
|
};
|
|
221
|
-
|
|
225
|
+
|
|
226
|
+
// Replace recursive iterate() with iterative approach
|
|
227
|
+
let matched;
|
|
228
|
+
let continueIteration = true;
|
|
229
|
+
|
|
230
|
+
while (continueIteration) {
|
|
231
|
+
const patternIndexBefore = patternIndex;
|
|
232
|
+
const indexBefore = index;
|
|
233
|
+
|
|
234
|
+
matched = matchOne();
|
|
235
|
+
|
|
236
|
+
if (matched === undefined) {
|
|
237
|
+
consumePattern(1);
|
|
238
|
+
consumeString(1);
|
|
239
|
+
// Continue the loop instead of recursion
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (matched === false && restoreIndexes) {
|
|
244
|
+
patternIndex = patternIndexBefore;
|
|
245
|
+
index = indexBefore;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// End the loop
|
|
249
|
+
continueIteration = false;
|
|
250
|
+
}
|
|
222
251
|
|
|
223
252
|
return {
|
|
224
253
|
matched,
|
|
@@ -228,7 +257,15 @@ const applyMatching = (pattern, string) => {
|
|
|
228
257
|
};
|
|
229
258
|
};
|
|
230
259
|
|
|
231
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Iterative version of skipUntilMatch that avoids recursion
|
|
262
|
+
* @param {Object} params
|
|
263
|
+
* @param {string} params.pattern - The pattern to match
|
|
264
|
+
* @param {string} params.string - The string to test against
|
|
265
|
+
* @param {boolean} params.canSkipSlash - Whether slash characters can be skipped
|
|
266
|
+
* @returns {Object} Result of the matching attempt
|
|
267
|
+
*/
|
|
268
|
+
const skipUntilMatchIterative = ({ pattern, string, canSkipSlash }) => {
|
|
232
269
|
let index = 0;
|
|
233
270
|
let remainingString = string;
|
|
234
271
|
let longestAttemptRange = null;
|
|
@@ -246,8 +283,10 @@ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
|
|
|
246
283
|
};
|
|
247
284
|
};
|
|
248
285
|
|
|
249
|
-
|
|
286
|
+
// Loop until a match is found or all attempts fail
|
|
287
|
+
while (true) {
|
|
250
288
|
const matchAttempt = applyMatching(pattern, remainingString);
|
|
289
|
+
|
|
251
290
|
if (matchAttempt.matched) {
|
|
252
291
|
return {
|
|
253
292
|
matched: true,
|
|
@@ -262,6 +301,7 @@ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
|
|
|
262
301
|
},
|
|
263
302
|
};
|
|
264
303
|
}
|
|
304
|
+
|
|
265
305
|
const attemptIndex = matchAttempt.index;
|
|
266
306
|
const attemptRange = {
|
|
267
307
|
patternIndex: matchAttempt.patternIndex,
|
|
@@ -269,19 +309,23 @@ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
|
|
|
269
309
|
length: attemptIndex,
|
|
270
310
|
groups: matchAttempt.groups,
|
|
271
311
|
};
|
|
312
|
+
|
|
272
313
|
if (
|
|
273
314
|
!longestAttemptRange ||
|
|
274
315
|
longestAttemptRange.length < attemptRange.length
|
|
275
316
|
) {
|
|
276
317
|
longestAttemptRange = attemptRange;
|
|
277
318
|
}
|
|
319
|
+
|
|
278
320
|
if (isLastAttempt) {
|
|
279
321
|
return failure();
|
|
280
322
|
}
|
|
323
|
+
|
|
281
324
|
const nextIndex = attemptIndex + 1;
|
|
282
325
|
if (nextIndex >= remainingString.length) {
|
|
283
326
|
return failure();
|
|
284
327
|
}
|
|
328
|
+
|
|
285
329
|
if (remainingString[0] === "/") {
|
|
286
330
|
if (!canSkipSlash) {
|
|
287
331
|
return failure();
|
|
@@ -291,12 +335,11 @@ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
|
|
|
291
335
|
isLastAttempt = true;
|
|
292
336
|
}
|
|
293
337
|
}
|
|
338
|
+
|
|
294
339
|
// search against the next unattempted string
|
|
295
340
|
index += nextIndex;
|
|
296
341
|
remainingString = remainingString.slice(nextIndex);
|
|
297
|
-
|
|
298
|
-
};
|
|
299
|
-
return tryToMatch();
|
|
342
|
+
}
|
|
300
343
|
};
|
|
301
344
|
|
|
302
345
|
const applyPatternMatching = ({ url, pattern }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "40.0.
|
|
3
|
+
"version": "40.0.7",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -79,25 +79,26 @@
|
|
|
79
79
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
80
80
|
"@jsenv/abort": "4.3.1",
|
|
81
81
|
"@jsenv/ast": "6.6.5",
|
|
82
|
-
"@jsenv/filesystem": "4.14.
|
|
82
|
+
"@jsenv/filesystem": "4.14.3",
|
|
83
83
|
"@jsenv/humanize": "1.3.1",
|
|
84
84
|
"@jsenv/importmap": "1.2.2",
|
|
85
85
|
"@jsenv/integrity": "0.0.2",
|
|
86
86
|
"@jsenv/js-module-fallback": "1.4.3",
|
|
87
87
|
"@jsenv/node-esm-resolution": "1.1.0",
|
|
88
|
-
"@jsenv/plugin-bundling": "2.8.
|
|
88
|
+
"@jsenv/plugin-bundling": "2.8.4",
|
|
89
89
|
"@jsenv/plugin-minification": "1.6.2",
|
|
90
90
|
"@jsenv/plugin-supervisor": "1.6.10",
|
|
91
91
|
"@jsenv/plugin-transpilation": "1.5.6",
|
|
92
92
|
"@jsenv/runtime-compat": "1.3.4",
|
|
93
|
-
"@jsenv/server": "16.0.
|
|
93
|
+
"@jsenv/server": "16.0.4",
|
|
94
94
|
"@jsenv/sourcemap": "1.3.2",
|
|
95
|
-
"@jsenv/url-meta": "8.5.
|
|
95
|
+
"@jsenv/url-meta": "8.5.5",
|
|
96
96
|
"@jsenv/urls": "2.6.3",
|
|
97
97
|
"@jsenv/utils": "2.2.1",
|
|
98
98
|
"string-width": "7.2.0"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
|
+
"@babel/plugin-syntax-decorators": "7.25.9",
|
|
101
102
|
"@babel/plugin-syntax-import-attributes": "7.26.0",
|
|
102
103
|
"@babel/plugin-syntax-optional-chaining-assign": "7.25.9",
|
|
103
104
|
"@jsenv/assert": "workspace:*",
|