{"_id":"@ahadpvt.v3/urlex","_rev":"8-1844b0a9a2508806a4d400bf5f40e8ce","name":"@ahadpvt.v3/urlex","dist-tags":{"latest":"1.0.6"},"versions":{"1.0.0":{"name":"@ahadpvt.v3/urlex","version":"1.0.0","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.0","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"5b464b61030ff3426aa6ce6c6af4ef75fd888731","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.0.tgz","fileCount":6,"integrity":"sha512-V5nGgelhtyxy177An2Lf5QnHBA/cdVmWHfHfPP7V4x7xZIJXMhkQDcwFvhKIIYrr9o0el6X/6h4A5YNAcDr7iA==","signatures":[{"sig":"MEYCIQCf60LElAUVZNH+N+gqGXsuDsXKOAosT8eTD4fWigPurgIhAKaZg0wTJ+IryGnqblJrxCph4f67ow4KHAMEcUL4GdxJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21089},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.0_1773365249061_0.04227976954559476","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.1":{"name":"@ahadpvt.v3/urlex","version":"1.0.1","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.1","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"645653be37176babb1703dafc5f99fccb08d484a","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.1.tgz","fileCount":6,"integrity":"sha512-jQeLKpFO1Z28CGlhpqjq1nnY75gAZU60rK7nt/L7tinUQzbyMAqlPXXyLQxJZi6BtPqhvij1AkVkfuC/xc+1wQ==","signatures":[{"sig":"MEQCIEKCxg45FIVe2uXFqT4LtsmpVCm8fVt4AM/TFS1MziEOAiAZj6ln7UV82aQHb+9tjcQmddf27yVA9fXmIdmKrjtSvA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21248},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.1_1773365713701_0.6235168081109188","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.2":{"name":"@ahadpvt.v3/urlex","version":"1.0.2","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.2","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"4efde7a27645cb63066724f734b81be29fd9b5d7","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.2.tgz","fileCount":6,"integrity":"sha512-Ioy/ixzPaIERwtVVoMA0Ru3EoagBMWNezg/jlZsSVWJBTaSKaanpk45gd9/1HL9Z7ISJfF3dnAgxTkZWclgRIg==","signatures":[{"sig":"MEYCIQC8v9nksAOlmC7gJdeHs2CEBStL4cMS5E5FyxeCIj8LAAIhAM5I3bCXTD2+UA9WXbVCSOZc0vfHzU5dUCissdi4HDYB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19893},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.2_1773440301345_0.9105482865815566","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.3":{"name":"@ahadpvt.v3/urlex","version":"1.0.3","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.3","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"a4a519d259719c971382b0eb24c5c0d703e6b9e5","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.3.tgz","fileCount":6,"integrity":"sha512-kur0gdoGRIz5HFSyEr0O9bJCLeA4jiEiLjgJXnDDYsNTxNeykGoKuWoNvzHK1FaDmzHeQOuaHlajIODc5VAOQg==","signatures":[{"sig":"MEUCIQCuPiO07SOSAQRsJQrcpSH36Jo3Xqcyphy0VYajZ6b+PAIgVjKz85YFfDxGmRK7f5eiUnFOz416k7n1zsNe/iONbAA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20090},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.3_1773456563587_0.2709557266250624","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.4":{"name":"@ahadpvt.v3/urlex","version":"1.0.4","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.4","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"dc9f15fb6ab04f6057d5cf2aab1348fc80bc331a","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.4.tgz","fileCount":6,"integrity":"sha512-PsrsoNbgs5x4FtXpMHdd1JN96+ZmZc6NQbS0tXB2OhTz6hQ2u3iJs/f3qyc7ev6uenC/+xz2G0cN85diMhmLyg==","signatures":[{"sig":"MEUCIHcuMQZoxivgIcX1/wp48+n9OgiJTNAgF1Sdu1hqfQDJAiEA11MsMC65B9dyiGmDDNUDTW1Lq+810C/hzyiK8vpHiYA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22912},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.4_1773456849532_0.7251374799611308","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.5":{"name":"@ahadpvt.v3/urlex","version":"1.0.5","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.5","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"4383b818d4c9d4ae1a8e4e2413a22a73bbd062fd","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.5.tgz","fileCount":6,"integrity":"sha512-ou9iBH7LfQSmllhuLnXtoLUZc3Er/mMsv911ma8DgQmknT5rfN+Ldqxvyz+m0AD97SlHE1spS+GsEQGC+Zue7w==","signatures":[{"sig":"MEUCIQCaTvNatBnuEo54eNahxwPOx6oGgp8WuiQRo8Rs7pv0uQIgQ00mqehqsSOCZQpjr0yu3QDhKM2ecLXE/FrXFZsqRuA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26013},"main":"index.js","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"import":"./index.mjs","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"9.2.0","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"_nodeVersion":"18.19.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.5_1773527523922_0.9675163868519601","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."},"1.0.6":{"name":"@ahadpvt.v3/urlex","version":"1.0.6","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"author":{"name":"YOUR NAME"},"license":"MIT","_id":"@ahadpvt.v3/urlex@1.0.6","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"dist":{"shasum":"82d7d7e426156168881e7152fb59d33400a06621","tarball":"https://registry.npmjs.org/@ahadpvt.v3/urlex/-/urlex-1.0.6.tgz","fileCount":6,"integrity":"sha512-W0d8KM+hUSqg1e9CFLZzKdLJa9ER54ihbLcW9Bn+GPAGh9iirr3M0OHb9lmLzo/sLDEa2mEwW3nMhkZ7kI6GQQ==","signatures":[{"sig":"MEYCIQCLHKzMSLObefMM/1yrvMMkTCWnA8By2ya7MfBqOZtKvwIhANr5oZpn3XjXAvPHqlzz/xwMaYFV32soy6Qie+ad/EYu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26145},"main":"index.js","type":"commonjs","types":"index.d.ts","engines":{"node":">=14"},"exports":{".":{"types":"./index.d.ts","import":"./index.mjs","default":"./index.js","require":"./index.js"}},"scripts":{"test":"node test.js"},"_npmUser":{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"},"_npmVersion":"10.9.4","description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","directories":{},"sideEffects":false,"_nodeVersion":"22.22.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/urlex_1.0.6_1774167044938_0.421328493781298","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated. Use @qezor/urlex instead."}},"time":{"created":"2026-03-13T01:27:29.002Z","modified":"2026-04-01T21:12:34.893Z","1.0.0":"2026-03-13T01:27:29.186Z","1.0.1":"2026-03-13T01:35:13.848Z","1.0.2":"2026-03-13T22:18:21.501Z","1.0.3":"2026-03-14T02:49:23.731Z","1.0.4":"2026-03-14T02:54:09.676Z","1.0.5":"2026-03-14T22:32:04.066Z","1.0.6":"2026-03-22T08:10:45.071Z"},"author":{"name":"YOUR NAME"},"license":"MIT","keywords":["url","router","pattern","matcher","glob","params","wildcard"],"description":"Zero-dependency URL pattern matcher with named params, wildcards, ranged globs and literal sets","maintainers":[{"name":"ahadpvt.v3","email":"ahadpvt.v3@gmail.com"}],"readme":"# @ahadpvt.v3/urlex\n\nA **zero-dependency, production-grade URL pattern matcher** for Node.js and any JavaScript runtime.\n\nPatterns are compiled once and reused for efficient repeated matching. Supports host-based routing, named params, wildcards, ranged globs with backtracking, literal sets, signed integer bounds, and literal escaping. Powers the route matching layer of the dispex dispatcher.\n\n---\n\n## Installation\n\n```bash\nnpm install @ahadpvt.v3/urlex\n```\n\n---\n\n## Import / Require\n\n```js\n// CommonJS\nconst { compile, match, parse, matchHost, matchPath } = require(\"@ahadpvt.v3/urlex\")\n\n// ES Modules\nimport { compile, match, parse, matchHost, matchPath } from \"@ahadpvt.v3/urlex\"\n```\n\n---\n\n## Quick Start\n\n```js\nconst { compile, match } = require(\"@ahadpvt.v3/urlex\")\n\nconst pattern = compile(\"example.com/users/:id\")\n\n// With param capture\nconst params = match(pattern, \"https://example.com/users/42\", true)\nconsole.log(params)  // { id: \"42\", \"**\": [] }\n\n// Match only — zero allocation\nconst ok = match(pattern, \"https://example.com/users/42\", false)\nconsole.log(ok)  // true\n\n// No match\nconsole.log(match(pattern, \"https://example.com/posts/1\", true))  // null\n```\n\n---\n\n## Pattern Syntax\n\n### Literal segment\n\nExact match. Case-sensitive.\n\n```\nexample.com/users/profile\n```\n\nMatches `https://example.com/users/profile` only.\n\n---\n\n### `:name` — named required param\n\nCaptures exactly one segment.\n\n```js\nconst c = compile(\"example.com/users/:id\")\nmatch(c, \"https://example.com/users/42\", true)\n// → { id: \"42\", \"**\": [] }\n```\n\n---\n\n### `*:name` — named optional param\n\nConsumes one segment if present, empty string if absent. Best used at the end of a pattern.\n\n```js\nconst c = compile(\"example.com/api/*:version/users\")\nmatch(c, \"https://example.com/api/v2/users\", true)  // → { version: \"v2\", \"**\": [] }\nmatch(c, \"https://example.com/api/users\",    true)  // → { version: \"\",   \"**\": [] }\n```\n\n---\n\n### `*` — unnamed single-segment wildcard\n\nMatches exactly one segment, no capture.\n\n```js\nconst c = compile(\"example.com/files/*/download\")\nmatch(c, \"https://example.com/files/report/download\", false)  // → true\nmatch(c, \"https://example.com/files/download\",        false)  // → null\n```\n\n---\n\n### `**` — unlimited glob\n\nMatches all remaining segments. **Must be the last segment** — throws at compile time otherwise.\nCaptured in `params[\"**\"][n]` as an array of segments.\n\n```js\nconst c = compile(\"example.com/static/**\")\nmatch(c, \"https://example.com/static/assets/img/logo.png\", true)\n// → { \"**\": [ [\"assets\", \"img\", \"logo.png\"] ] }\n\nmatch(c, \"https://example.com/static/\", true)\n// → { \"**\": [ [] ] }   ← zero remaining segments\n```\n\n---\n\n### `[n]` — exact segment count\n\nMatches exactly `n` segments. Captured in `params[\"**\"]`.\n\n```js\nconst c = compile(\"example.com/[3]/end\")\nmatch(c, \"https://example.com/a/b/c/end\", true)\n// → { \"**\": [ [\"a\", \"b\", \"c\"] ] }\n```\n\n---\n\n### `[min,max]` — ranged segment count\n\nMatches between `min` and `max` segments. Range nodes can appear **anywhere** in a pattern — backtracking handles downstream matching automatically.\n\n```js\nconst c = compile(\"example.com/[1,3]/end\")\nmatch(c, \"https://example.com/a/b/end\",       true)  // → matched, \"**\"[0] = [\"a\",\"b\"]\nmatch(c, \"https://example.com/a/b/c/d/end\",   true)  // → null (over max)\n```\n\nVariants:\n\n| Pattern | Meaning |\n|---|---|\n| `[n]` | exactly n segments |\n| `[min,max]` | between min and max |\n| `[min,]` | at least min |\n| `[,max]` | at most max |\n| `[-3,5]` | signed bounds — negative min supported |\n| `[-5,-1]` | both bounds negative |\n\n---\n\n### `{a,b,c}` — literal set (OR match)\n\nMatches exactly one segment that equals any value in the set. Useful for file extensions, method names, fixed enums.\n\n```js\nconst c = compile(\"example.com/files/{jpg,png,gif}\")\nmatch(c, \"https://example.com/files/jpg\", false)  // → true\nmatch(c, \"https://example.com/files/pdf\", false)  // → null\n```\n\n---\n\n### Escaping\n\nBackslash escapes a special character, treating it as a plain literal.\n\n| Escape | Produces |\n|---|---|\n| `\\{` | literal `{` |\n| `\\*` | literal `*` |\n| `\\:` | literal `:` |\n| `\\\\` | literal `\\` |\n\n```js\ncompile(\"example.com/\\\\{3}\")   // matches the literal string \"{3}\"\ncompile(\"example.com/\\\\*\")     // matches the literal string \"*\"\ncompile(\"example.com/\\\\:id\")   // matches the literal string \":id\"\n```\n\n---\n\n## Host Matching\n\nHosts are matched **right-to-left**, making wildcard subdomain patterns natural.\n\n```js\ncompile(\"*.example.com/page\")        // any subdomain\ncompile(\"api.example.com/v1/**\")     // specific subdomain\ncompile(\"*.*.example.com/path\")      // two-level wildcard\ncompile(\"/users/:id\")                // path-only — matches any host\n```\n\n```js\nconst c = compile(\"*.example.com/page\")\nmatch(c, \"https://blog.example.com/page\",   false)  // → true\nmatch(c, \"https://cdn.example.com/page\",    false)  // → true\nmatch(c, \"https://other.com/page\",          false)  // → null\n```\n\n---\n\n## Glob Captures — `params[\"**\"]`\n\n`params[\"**\"]` is always an array — one entry per glob or range in the pattern, in pattern order. Each entry is an array of the matched segments (never joined — no information loss).\n\n```js\n// Single glob\nconst c = compile(\"example.com/static/**\")\nmatch(c, \"https://example.com/static/img/logo.png\", true)\n// → { \"**\": [ [\"img\", \"logo.png\"] ] }\n//              ↑ index 0 = first glob\n\n// Multiple globs in order\nconst c2 = compile(\"example.com/[1,2]/mid/[1,2]/end\")\nmatch(c2, \"https://example.com/a/b/mid/x/y/end\", true)\n// → { \"**\": [ [\"a\",\"b\"], [\"x\",\"y\"] ] }\n//              ↑ index 0   ↑ index 1\n\n// Mix of named params and ranges\nconst c3 = compile(\"example.com/:version/[1,2]/users/:id\")\nmatch(c3, \"https://example.com/v2/a/b/users/99\", true)\n// → { version: \"v2\", id: \"99\", \"**\": [ [\"a\",\"b\"] ] }\n```\n\nWhen no glob or range is in the pattern, `params[\"**\"]` is always `[]` — never null, never undefined, safe to access without checks.\n\n---\n\n## `save=false` — zero allocation fast path\n\nWhen you only need to know if a URL matches without capturing params, pass `save=false`. No params object allocated, no array created — pure boolean check.\n\n```js\n// Route filtering — check match only\nif (match(compiled, url, false)) {\n  // matched\n}\n```\n\n---\n\n## URL Handling\n\nThe parser handles any protocol, strips port, query string, and hash automatically.\n\n```\nhttps://example.com:8080/users/42?q=hello#section\n                        ↓\n                 example.com/users/42\n```\n\nSupported protocols: `http`, `https`, `ws`, `wss`, `ftp`, and any other `scheme://` format.\n\n---\n\n## API\n\n### `compile(pattern)` → CompiledPattern\n\nCompiles a pattern string into an optimized structure. Throws clearly at compile time on invalid or illegal patterns — never silently at match time.\n\n```js\nconst compiled = compile(\"example.com/users/:id\")\n// → { host: [\"example\",\"com\"], path: [\":id\"] }\n```\n\nThrows on:\n- `**` not in last position\n- Empty literal set `{}`\n- Invalid range `[5,2]` (max < min)\n- Empty range `[]`\n\n### `match(compiled, url, save)` → MatchParams | true | null\n\n```\nnull  → no match\ntrue  → matched, save=false\nobject → matched, save=true — params[\"**\"] always present\n```\n\n### `parse(url)` → { host: string[], path: string[] }\n\nSplits a raw URL into segments. Useful for building custom matchers on top.\n\n```js\nparse(\"https://api.example.com:3000/users/42?page=1\")\n// → { host: [\"api\",\"example\",\"com\"], path: [\"users\",\"42\"] }\n```\n\n### `matchHost(pattern, actual)` → boolean\n\nLow-level host matcher. Right-to-left, `[\"*\"]` matches any host.\n\n### `matchPath(pattern, actual, params, save)` → { matched, glob }\n\nLow-level path matcher. Thin wrapper around the recursive backtracker.\n\n---\n\n## Error Handling\n\nAll errors thrown by `compile()` are plain `Error` instances with descriptive messages — caught at build time, never at request time.\n\n```js\ntry {\n  compile(\"example.com/**/users\")   // ** not last\n} catch (err) {\n  console.log(err.message)\n  // → '\"**\" must be the last segment in pattern: \"example.com/**/users\"'\n}\n\ncompile(\"example.com/[5,2]/end\")    // max < min\n// → 'Range max < min: \"[5,2]\"'\n\ncompile(\"example.com/{}/end\")       // empty set\n// → 'Invalid literal set: \"{}\"'\n```\n\n---\n\n## Testing\n\n```bash\nnpm test\n```\n\n```\n52 passed, 0 failed\n```\n\n---\n\n## License\n\nMIT © Abdul Ahad\n","readmeFilename":"README.md"}