@peter.naydenov/url-pattern 1.0.0 → 1.0.1

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.
@@ -0,0 +1,509 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.urlPattern = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ /**
8
+ * @fileoverview URL pattern matching library
9
+ * @module url-pattern
10
+ */
11
+
12
+ /**
13
+ * @typedef {Object} UrlPatternOptions
14
+ * @property {string} [escapeChar='\\'] - Character used for escaping special characters
15
+ * @property {string} [segmentNameStartChar=':'] - Character that starts a named segment
16
+ * @property {string} [segmentNameCharset='a-zA-Z0-9'] - Characters allowed in segment names
17
+ * @property {string} [segmentValueCharset='a-zA-Z0-9-_~ %'] - Characters allowed in segment values
18
+ * @property {string} [optionalSegmentStartChar='('] - Character that starts an optional segment
19
+ * @property {string} [optionalSegmentEndChar=')'] - Character that ends an optional segment
20
+ * @property {string} [wildcardChar='*'] - Character that denotes a wildcard
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} ParsedSegment
25
+ * @property {string} name - Segment name
26
+ * @property {string} type - Segment type ('named' | 'wildcard' | 'literal')
27
+ * @property {boolean} [optional=false] - Whether the segment is optional
28
+ * @property {string} regex - Compiled regex string
29
+ */
30
+
31
+ /**
32
+ * @typedef {Object} SegmentName
33
+ * @property {string} name - Segment name
34
+ * @property {number} index - Capture group index
35
+ * @property {string} type - Segment type ('named' | 'wildcard')
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} CompiledPattern
40
+ * @property {string} regex - Compiled regex string
41
+ * @property {RegExp} regexObj - Compiled regex object
42
+ * @property {Array<ParsedSegment>} segments - Parsed segments
43
+ * @property {Array<SegmentName>} segmentNames - Segment name mappings
44
+ * @property {UrlPatternOptions} options - Options used
45
+ * @property {boolean} isRegex - Whether pattern was created from regex
46
+ * @property {string} [pattern] - Original pattern string
47
+ * @property {Array<string>} [keys] - Keys for regex patterns
48
+ */
49
+
50
+ /**
51
+ * Default options for URL pattern matching
52
+ * @type {UrlPatternOptions}
53
+ */
54
+ const DEFAULT_OPTIONS = {
55
+ escapeChar: '\\',
56
+ segmentNameStartChar: ':',
57
+ segmentNameCharset: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
58
+ segmentValueCharset: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_~ %',
59
+ optionalSegmentStartChar: '(',
60
+ optionalSegmentEndChar: ')',
61
+ wildcardChar: '*'
62
+ };
63
+
64
+ /**
65
+ * Escapes special regex characters in a string
66
+ * @param {string} str - String to escape
67
+ * @returns {string} Escaped string
68
+ */
69
+ const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
70
+
71
+ /**
72
+ * Merges default options with user provided options
73
+ * @param {UrlPatternOptions} [userOptions={}] - User provided options
74
+ * @returns {UrlPatternOptions} Merged options
75
+ */
76
+ const mergeOptions = (userOptions = {}) => ({
77
+ ...DEFAULT_OPTIONS,
78
+ ...userOptions
79
+ });
80
+
81
+ /**
82
+ * Finds the position of the next special character in the pattern
83
+ * @param {string} pattern - Pattern string
84
+ * @param {number} start - Starting position
85
+ * @param {UrlPatternOptions} options - Parsing options
86
+ * @returns {number} Position of next special character
87
+ */
88
+ const findNextSpecialChar = (pattern, start, options) => {
89
+ const chars = [
90
+ options.escapeChar,
91
+ options.optionalSegmentStartChar,
92
+ options.optionalSegmentEndChar,
93
+ options.wildcardChar,
94
+ options.segmentNameStartChar
95
+ ];
96
+
97
+ let minPos = pattern.length;
98
+
99
+ for (let i = 0; i < chars.length; i++) {
100
+ const char = chars[i];
101
+ if (!char) continue;
102
+ const pos = pattern.indexOf(char, start);
103
+ if (pos !== -1 && pos < minPos) {
104
+ minPos = pos;
105
+ }
106
+ }
107
+
108
+ return minPos;
109
+ };
110
+
111
+ /**
112
+ * Parses a pattern string into segments
113
+ * @param {string} pattern - Pattern string to parse
114
+ * @param {UrlPatternOptions} options - Parsing options
115
+ * @returns {Array<ParsedSegment>} Parsed segments
116
+ */
117
+ const parsePattern = (pattern, options) => {
118
+ const segments = [];
119
+ let i = 0;
120
+ let inOptional = false;
121
+
122
+ while (i < pattern.length) {
123
+ const char = pattern[i];
124
+
125
+ if (char === options.escapeChar && i + 1 < pattern.length) {
126
+ segments.push({
127
+ type: 'literal',
128
+ name: pattern[i + 1],
129
+ regex: escapeRegex(pattern[i + 1]),
130
+ optional: inOptional
131
+ });
132
+ i += 2;
133
+ continue;
134
+ }
135
+
136
+ if (char === options.optionalSegmentStartChar) {
137
+ inOptional = true;
138
+ i++;
139
+ continue;
140
+ }
141
+
142
+ if (char === options.optionalSegmentEndChar) {
143
+ inOptional = false;
144
+ i++;
145
+ continue;
146
+ }
147
+
148
+ if (char === options.wildcardChar) {
149
+ segments.push({
150
+ type: 'wildcard',
151
+ name: '_',
152
+ regex: '.*',
153
+ optional: inOptional
154
+ });
155
+ i++;
156
+ continue;
157
+ }
158
+
159
+ if (char === options.segmentNameStartChar && i + 1 < pattern.length) {
160
+ const remaining = pattern.slice(i + 1);
161
+ let nameEnd = 0;
162
+ const charset = options.segmentNameCharset || '';
163
+
164
+ for (let j = 0; j < remaining.length; j++) {
165
+ if (!charset.includes(remaining[j])) {
166
+ break;
167
+ }
168
+ nameEnd = j + 1;
169
+ }
170
+
171
+ const name = remaining.slice(0, nameEnd);
172
+
173
+ if (name.length > 0) {
174
+ let valueCharset = options.segmentValueCharset || '';
175
+ if (valueCharset.includes('-') && valueCharset.indexOf('-') > 0 && valueCharset.indexOf('-') < valueCharset.length - 1) {
176
+ valueCharset = valueCharset.replace(/-/g, '');
177
+ valueCharset += '-';
178
+ }
179
+ const escapedValueCharset = valueCharset.replace(/\]/g, '\\]');
180
+ const valueRegex = `([${escapedValueCharset}]+)`;
181
+
182
+ segments.push({
183
+ type: 'named',
184
+ name,
185
+ regex: valueRegex,
186
+ optional: inOptional
187
+ });
188
+ i += 1 + nameEnd;
189
+ continue;
190
+ }
191
+ }
192
+
193
+ const literalEnd = findNextSpecialChar(pattern, i, options);
194
+
195
+ if (literalEnd > i) {
196
+ const literal = pattern.slice(i, literalEnd);
197
+ segments.push({
198
+ type: 'literal',
199
+ name: literal,
200
+ regex: escapeRegex(literal),
201
+ optional: inOptional
202
+ });
203
+ i = literalEnd;
204
+ continue;
205
+ }
206
+
207
+ i++;
208
+ }
209
+
210
+ return segments;
211
+ };
212
+
213
+ /**
214
+ * Compiles segments into a regex pattern
215
+ * @param {Array<ParsedSegment>} segments - Parsed segments
216
+ * @param {UrlPatternOptions} options - Options
217
+ * @returns {{regex: string, segmentNames: Array<SegmentName>}} Compiled regex and segment names
218
+ */
219
+ const compileRegex = (segments, options) => {
220
+ let regex = '^';
221
+ let groupIndex = 0;
222
+ /** @type {Array<SegmentName>} */
223
+ const segmentNames = [];
224
+ let i = 0;
225
+
226
+ while (i < segments.length) {
227
+ const segment = segments[i];
228
+
229
+ if (segment.optional) {
230
+ let optionalPart = '';
231
+ let j = i;
232
+
233
+ while (j < segments.length && segments[j].optional) {
234
+ const seg = segments[j];
235
+
236
+ if (seg.type === 'wildcard') {
237
+ optionalPart += '(.*)';
238
+ segmentNames.push({ name: '_', index: groupIndex, type: 'wildcard' });
239
+ groupIndex++;
240
+ } else if (seg.type === 'named') {
241
+ optionalPart += seg.regex;
242
+ segmentNames.push({ name: seg.name, index: groupIndex, type: 'named' });
243
+ groupIndex++;
244
+ } else {
245
+ optionalPart += seg.regex;
246
+ }
247
+
248
+ j++;
249
+ }
250
+
251
+ regex += `(?:${optionalPart})?`;
252
+ i = j;
253
+ continue;
254
+ }
255
+
256
+ if (segment.type === 'wildcard') {
257
+ regex += '(.*)';
258
+ segmentNames.push({ name: '_', index: groupIndex, type: 'wildcard' });
259
+ groupIndex++;
260
+ } else if (segment.type === 'named') {
261
+ regex += segment.regex;
262
+ segmentNames.push({ name: segment.name, index: groupIndex, type: 'named' });
263
+ groupIndex++;
264
+ } else {
265
+ regex += segment.regex;
266
+ }
267
+
268
+ i++;
269
+ }
270
+
271
+ regex += '$';
272
+
273
+ return { regex, segmentNames };
274
+ };
275
+
276
+ /**
277
+ * Creates a compiled pattern from a string
278
+ * @param {string} pattern - Pattern string
279
+ * @param {UrlPatternOptions} [options={}] - Options
280
+ * @returns {CompiledPattern} Compiled pattern
281
+ */
282
+ const makePattern = (pattern, options = {}) => {
283
+ const mergedOptions = mergeOptions(options);
284
+ const segments = parsePattern(pattern, mergedOptions);
285
+ const { regex, segmentNames } = compileRegex(segments);
286
+
287
+ return {
288
+ regex,
289
+ regexObj: new RegExp(regex),
290
+ segments,
291
+ segmentNames,
292
+ options: mergedOptions,
293
+ isRegex: false,
294
+ pattern
295
+ };
296
+ };
297
+
298
+ /**
299
+ * Creates a compiled pattern from a regex
300
+ * @param {RegExp} regex - Regex pattern
301
+ * @param {Array<string>} [keys=[]] - Array of key names for captured groups
302
+ * @returns {CompiledPattern} Compiled pattern
303
+ */
304
+ const makePatternFromRegex = (regex, keys = []) => {
305
+ return {
306
+ regex: regex.source,
307
+ regexObj: regex,
308
+ segments: [],
309
+ segmentNames: keys.map((name, index) => ({ name, index, type: 'named' })),
310
+ options: DEFAULT_OPTIONS,
311
+ isRegex: true,
312
+ keys
313
+ };
314
+ };
315
+
316
+ /**
317
+ * Matches a string against a compiled pattern
318
+ * @param {CompiledPattern} compiled - Compiled pattern
319
+ * @param {string} str - String to match
320
+ * @returns {Object|null} Extracted values or null if no match
321
+ */
322
+ const match = (compiled, str) => {
323
+ const matchResult = compiled.regexObj.exec(str);
324
+
325
+ if (!matchResult) {
326
+ return null;
327
+ }
328
+
329
+ if (compiled.isRegex) {
330
+ if (compiled.keys && compiled.keys.length > 0) {
331
+ const result = {};
332
+ compiled.keys.forEach((key, index) => {
333
+ const val = matchResult[index + 1];
334
+ result[key] = val !== undefined ? val : null;
335
+ });
336
+ return result;
337
+ }
338
+ return matchResult.slice(1);
339
+ }
340
+
341
+ const result = {};
342
+ const usedNames = new Set();
343
+
344
+ for (let i = 0; i < compiled.segmentNames.length; i++) {
345
+ const segInfo = compiled.segmentNames[i];
346
+ const value = matchResult[segInfo.index + 1] || '';
347
+
348
+ if (usedNames.has(segInfo.name)) {
349
+ if (!Array.isArray(result[segInfo.name])) {
350
+ result[segInfo.name] = [result[segInfo.name]];
351
+ }
352
+ result[segInfo.name].push(value);
353
+ } else {
354
+ usedNames.add(segInfo.name);
355
+ result[segInfo.name] = value;
356
+ }
357
+ }
358
+
359
+ for (const key in result) {
360
+ if (result[key] === '') {
361
+ delete result[key];
362
+ }
363
+ }
364
+
365
+ return result;
366
+ };
367
+
368
+ /**
369
+ * Stringifies a pattern with given values
370
+ * @param {CompiledPattern} compiled - Compiled pattern
371
+ * @param {Object} [values={}] - Values to stringify
372
+ * @returns {string} Generated string
373
+ * @throws {Error} If required values are missing
374
+ */
375
+ const stringify = (compiled, values = {}) => {
376
+ if (compiled.isRegex) {
377
+ throw new Error('Cannot stringify a pattern created from regex');
378
+ }
379
+
380
+ let result = '';
381
+ let i = 0;
382
+
383
+ while (i < compiled.segments.length) {
384
+ const segment = compiled.segments[i];
385
+
386
+ if (segment.optional) {
387
+ let optionalPart = '';
388
+ let j = i;
389
+
390
+ while (j < compiled.segments.length && compiled.segments[j].optional) {
391
+ const seg = compiled.segments[j];
392
+
393
+ if (seg.type === 'literal') {
394
+ optionalPart += seg.name;
395
+ } else if (seg.type === 'named') {
396
+ const val = values[seg.name];
397
+ if (val !== undefined && val !== null && val !== '') {
398
+ optionalPart += Array.isArray(val) ? val.join('/') : val;
399
+ } else {
400
+ optionalPart = '';
401
+ break;
402
+ }
403
+ } else if (seg.type === 'wildcard') {
404
+ const val = values._;
405
+ if (val !== undefined && val !== null && val !== '') {
406
+ optionalPart += Array.isArray(val) ? val.join('/') : val;
407
+ } else {
408
+ optionalPart = '';
409
+ break;
410
+ }
411
+ }
412
+
413
+ j++;
414
+ }
415
+
416
+ if (optionalPart !== '') {
417
+ result += optionalPart;
418
+ }
419
+
420
+ if (i === j) {
421
+ i++;
422
+ } else {
423
+ i = j;
424
+ }
425
+ continue;
426
+ }
427
+
428
+ if (segment.type === 'literal') {
429
+ result += segment.name;
430
+ } else if (segment.type === 'named') {
431
+ const value = values[segment.name];
432
+ if (value === undefined || value === null || value === '') {
433
+ throw new Error(`Missing required value for segment: ${segment.name}`);
434
+ }
435
+ result += Array.isArray(value) ? value.join('/') : value;
436
+ } else if (segment.type === 'wildcard') {
437
+ const value = values._;
438
+ if (value === undefined || value === null || value === '') {
439
+ throw new Error('Missing required wildcard value');
440
+ }
441
+ result += Array.isArray(value) ? value.join('/') : value;
442
+ }
443
+
444
+ i++;
445
+ }
446
+
447
+ return result;
448
+ };
449
+
450
+ /**
451
+ * UrlPattern class for matching and generating URLs
452
+ */
453
+ class UrlPattern {
454
+ /**
455
+ * @param {string|RegExp} pattern - Pattern string or regex
456
+ * @param {UrlPatternOptions|Array<string>} [options={}] - Options or keys (for regex)
457
+ */
458
+ constructor(pattern, options = {}) {
459
+ if (pattern instanceof RegExp) {
460
+ const keys = Array.isArray(options) ? options : [];
461
+ /** @type {CompiledPattern} */
462
+ this.compiled = makePatternFromRegex(pattern, keys);
463
+ } else {
464
+ /** @type {CompiledPattern} */
465
+ this.compiled = makePattern(pattern, /** @type {UrlPatternOptions} */ (options));
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Match a string against the pattern
471
+ * @param {string} str - String to match
472
+ * @returns {Object|null} Extracted values or null if no match
473
+ */
474
+ match(str) {
475
+ return match(this.compiled, str);
476
+ }
477
+
478
+ /**
479
+ * Generate a string from the pattern
480
+ * @param {Object} [values={}] - Values to stringify
481
+ * @returns {string} Generated string
482
+ */
483
+ stringify(values) {
484
+ return stringify(this.compiled, values);
485
+ }
486
+ }
487
+
488
+ /**
489
+ * Creates a new UrlPattern instance (functional API)
490
+ * @param {string|RegExp} pattern - Pattern string or regex
491
+ * @param {UrlPatternOptions|Array<string>} [options={}] - Options or keys
492
+ * @returns {UrlPattern} UrlPattern instance
493
+ */
494
+ const urlPattern = (pattern, options = {}) => {
495
+ return new UrlPattern(pattern, options);
496
+ };
497
+
498
+ exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
499
+ exports.UrlPattern = UrlPattern;
500
+ exports.default = UrlPattern;
501
+ exports.makePattern = makePattern;
502
+ exports.makePatternFromRegex = makePatternFromRegex;
503
+ exports.match = match;
504
+ exports.stringify = stringify;
505
+ exports.urlPattern = urlPattern;
506
+
507
+ Object.defineProperty(exports, '__esModule', { value: true });
508
+
509
+ }));
@@ -0,0 +1 @@
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).urlPattern={})}(this,function(e){"use strict";const n={escapeChar:"\\",segmentNameStartChar:":",segmentNameCharset:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",segmentValueCharset:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_~ %",optionalSegmentStartChar:"(",optionalSegmentEndChar:")",wildcardChar:"*"},t=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=(e,n,t)=>{const r=[t.escapeChar,t.optionalSegmentStartChar,t.optionalSegmentEndChar,t.wildcardChar,t.segmentNameStartChar];let a=e.length;for(let t=0;t<r.length;t++){const s=r[t];if(!s)continue;const i=e.indexOf(s,n);-1!==i&&i<a&&(a=i)}return a},a=(e,a={})=>{const s=((e={})=>({...n,...e}))(a),i=((e,n)=>{const a=[];let s=0,i=!1;for(;s<e.length;){const o=e[s];if(o===n.escapeChar&&s+1<e.length){a.push({type:"literal",name:e[s+1],regex:t(e[s+1]),optional:i}),s+=2;continue}if(o===n.optionalSegmentStartChar){i=!0,s++;continue}if(o===n.optionalSegmentEndChar){i=!1,s++;continue}if(o===n.wildcardChar){a.push({type:"wildcard",name:"_",regex:".*",optional:i}),s++;continue}if(o===n.segmentNameStartChar&&s+1<e.length){const t=e.slice(s+1);let r=0;const o=n.segmentNameCharset||"";for(let e=0;e<t.length&&o.includes(t[e]);e++)r=e+1;const l=t.slice(0,r);if(l.length>0){let e=n.segmentValueCharset||"";e.includes("-")&&e.indexOf("-")>0&&e.indexOf("-")<e.length-1&&(e=e.replace(/-/g,""),e+="-");const t=`([${e.replace(/\]/g,"\\]")}]+)`;a.push({type:"named",name:l,regex:t,optional:i}),s+=1+r;continue}}const l=r(e,s,n);if(l>s){const n=e.slice(s,l);a.push({type:"literal",name:n,regex:t(n),optional:i}),s=l;continue}s++}return a})(e,s),{regex:o,segmentNames:l}=(e=>{let n="^",t=0;const r=[];let a=0;for(;a<e.length;){const s=e[a];if(s.optional){let s="",i=a;for(;i<e.length&&e[i].optional;){const n=e[i];"wildcard"===n.type?(s+="(.*)",r.push({name:"_",index:t,type:"wildcard"}),t++):"named"===n.type?(s+=n.regex,r.push({name:n.name,index:t,type:"named"}),t++):s+=n.regex,i++}n+=`(?:${s})?`,a=i;continue}"wildcard"===s.type?(n+="(.*)",r.push({name:"_",index:t,type:"wildcard"}),t++):"named"===s.type?(n+=s.regex,r.push({name:s.name,index:t,type:"named"}),t++):n+=s.regex,a++}return n+="$",{regex:n,segmentNames:r}})(i);return{regex:o,regexObj:new RegExp(o),segments:i,segmentNames:l,options:s,isRegex:!1,pattern:e}},s=(e,t=[])=>({regex:e.source,regexObj:e,segments:[],segmentNames:t.map((e,n)=>({name:e,index:n,type:"named"})),options:n,isRegex:!0,keys:t}),i=(e,n)=>{const t=e.regexObj.exec(n);if(!t)return null;if(e.isRegex){if(e.keys&&e.keys.length>0){const n={};return e.keys.forEach((e,r)=>{const a=t[r+1];n[e]=void 0!==a?a:null}),n}return t.slice(1)}const r={},a=new Set;for(let n=0;n<e.segmentNames.length;n++){const s=e.segmentNames[n],i=t[s.index+1]||"";a.has(s.name)?(Array.isArray(r[s.name])||(r[s.name]=[r[s.name]]),r[s.name].push(i)):(a.add(s.name),r[s.name]=i)}for(const e in r)""===r[e]&&delete r[e];return r},o=(e,n={})=>{if(e.isRegex)throw new Error("Cannot stringify a pattern created from regex");let t="",r=0;for(;r<e.segments.length;){const a=e.segments[r];if(a.optional){let a="",s=r;for(;s<e.segments.length&&e.segments[s].optional;){const t=e.segments[s];if("literal"===t.type)a+=t.name;else if("named"===t.type){const e=n[t.name];if(null==e||""===e){a="";break}a+=Array.isArray(e)?e.join("/"):e}else if("wildcard"===t.type){const e=n._;if(null==e||""===e){a="";break}a+=Array.isArray(e)?e.join("/"):e}s++}""!==a&&(t+=a),r===s?r++:r=s;continue}if("literal"===a.type)t+=a.name;else if("named"===a.type){const e=n[a.name];if(null==e||""===e)throw new Error(`Missing required value for segment: ${a.name}`);t+=Array.isArray(e)?e.join("/"):e}else if("wildcard"===a.type){const e=n._;if(null==e||""===e)throw new Error("Missing required wildcard value");t+=Array.isArray(e)?e.join("/"):e}r++}return t};class l{constructor(e,n={}){if(e instanceof RegExp){const t=Array.isArray(n)?n:[];this.compiled=s(e,t)}else this.compiled=a(e,n)}match(e){return i(this.compiled,e)}stringify(e){return o(this.compiled,e)}}e.DEFAULT_OPTIONS=n,e.UrlPattern=l,e.default=l,e.makePattern=a,e.makePatternFromRegex=s,e.match=i,e.stringify=o,e.urlPattern=(e,n={})=>new l(e,n),Object.defineProperty(e,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -1,15 +1,30 @@
1
1
  {
2
2
  "name": "@peter.naydenov/url-pattern",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Matching patterns for urls and other strings. Turn strings into data or data into strings.",
5
- "main": "dist/index.js",
6
- "module": "dist/index.esm.js",
7
- "types": "dist/index.d.ts",
5
+ "type": "module",
6
+ "main": "./src/main.js",
7
+ "module": "./dist/url-pattern.es.js",
8
+ "types": "./types/index.d.ts",
8
9
  "files": [
9
- "dist"
10
+ "dist",
11
+ "types",
12
+ "src"
10
13
  ],
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/url-pattern.es.js",
17
+ "require": "./dist/url-pattern.cjs.js",
18
+ "default": "./dist/url-pattern.es.js"
19
+ },
20
+ "./package.json": "./package.json",
21
+ "./src/*": "./src/*",
22
+ "./dist/*": "./dist/*",
23
+ "./types/*": "./types/*"
24
+ },
11
25
  "scripts": {
12
- "build": "cp src/index.js dist/index.js",
26
+ "build": "rollup -c",
27
+ "postbuild": "tsc -p tsconfig.build.json",
13
28
  "test": "vitest run",
14
29
  "test:watch": "vitest",
15
30
  "cover": "vitest run --coverage",
@@ -25,9 +40,15 @@
25
40
  ],
26
41
  "author": "Peter Naydenov",
27
42
  "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/PeterNaydenov/url-pattern"
46
+ },
28
47
  "devDependencies": {
48
+ "@rollup/plugin-terser": "^0.4.4",
29
49
  "@vitest/coverage-v8": "^4.1.5",
30
50
  "eslint": "^10.3.0",
51
+ "rollup": "^4.9.6",
31
52
  "typescript": "^6.0.3",
32
53
  "vitest": "^4.1.5"
33
54
  }
package/readme.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # URL Pattern (@peter.naydenov/url-pattern)
2
2
 
3
3
  [![version](https://img.shields.io/npm/v/@peter.naydenov/url-pattern.svg)](https://www.npmjs.com/package/@peter.naydenov/url-pattern)
4
- [![license](https://img.shields.io/github/license/PeterNaydenov/git-url-pattern.svg)](https://github.com/PeterNaydenov/git-url-pattern/blob/main/LICENSE)
5
- [![GitHub issues](https://img.shields.io/github/issues-raw/PeterNaydenov/git-url-pattern.svg)](https://github.com/PeterNaydenov/git-url-pattern/issues)
6
- [![GitHub top language](https://img.shields.io/github/languages/top/PeterNaydenov/git-url-pattern.svg)](https://github.com/PeterNaydenov/git-url-pattern)
4
+ [![license](https://img.shields.io/github/license/PeterNaydenov/url-pattern.svg)](https://github.com/PeterNaydenov/url-pattern/blob/main/LICENSE)
5
+ [![GitHub issues](https://img.shields.io/github/issues-raw/PeterNaydenov/url-pattern.svg)](https://github.com/PeterNaydenov/url-pattern/issues)
6
+ [![GitHub top language](https://img.shields.io/github/languages/top/PeterNaydenov/url-pattern.svg)](https://github.com/PeterNaydenov/url-pattern)
7
7
  [![npm bundle size](https://img.shields.io/bundlejs/size/@peter.naydenov/url-pattern.svg)](https://www.npmjs.com/package/@peter.naydenov/url-pattern)
8
8
 
9
9
  Easier than regex string matching patterns for urls and other strings. Turn strings into data or data into strings.