Comparing version 3.0.1 to 3.0.2
var parseUri=(()=>{var o=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var f=(t,e)=>{for(var r in e)o(t,r,{get:e[r],enumerable:!0})},h=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of c(e))!d.call(t,s)&&s!==r&&o(t,s,{get:()=>e[s],enumerable:!(a=u(e,s))||a.enumerable});return t};var p=t=>h(o({},"__esModule",{value:!0}),t);var $={};f($,{parseUri:()=>m,setTlds:()=>y});function m(t,e="default"){t=t.trim();let{groups:r}=i.parser[e].exec(t),{hasAuth:a,...s}={href:t,...r,...r.protocol&&r.hasAuth==null?g:null};return Object.keys(s).forEach(n=>s[n]??=""),Object.assign(s,{...i.tlds?.exec(s.hostname)?.groups,queryParams:new URLSearchParams(`?${s.query}`)})}var g={directory:"",filename:"",suffix:""};function l(t){let e=String.raw`(?:(?:(?<=^(?:https?|wss?|ftp):):*|^:+)[\\/]*|^[\\/]{2,}|//)`,r={default:{start:`(?<hasAuth>${e}`,end:")?"},friendly:{start:`(?<hasAuth>${e}?)`,end:""}};return RegExp(String.raw`^(?<origin>(?:(?<protocol>[a-z][^\s:@\\/?#.]*):)?${r[t].start}(?<authority>(?:(?<userinfo>(?<username>[^:@\\/?#]*)(?::(?<password>[^\\/?#]*))?)?@)?(?<host>(?<hostname>\d{1,3}(?:\.\d{1,3}){3}(?=[:\\/?#]|$)|\[[a-f\d]{0,4}(?::[a-f\d]{0,4}){2,7}(?:%[^\]]*)?\]|(?<subdomain>[^:\\/?#]*?)\.??(?<domain>(?:[^.:\\/?#]*\.)?(?<tld>[^.:\\/?#]*))(?=[:\\/?#]|$))?(?::(?<port>[^:\\/?#]*))?))${r[t].end})(?<resource>(?<pathname>(?<directory>(?:[^\\/?#]*[\\/])*)(?<filename>(?:[^.?#]+|\.(?![^.?#]+(?:[?#]|$)))*(?:\.(?<suffix>[^.?#]+))?))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>.*))?)`,"i")}var i={parser:{default:l("default"),friendly:l("friendly")}};function y(t){let e=Object.entries(t),r;if(e.length){let a=e.map(([s,n])=>`(?:${n.trim().replace(/\s+/g,"|").replace(/\./g,"\\.")})\\.${s}`).join("|");r=RegExp(`^(?<subdomain>.*?)\\.??(?<domain>(?:[^.]*\\.)?(?<tld>${a}))$`,"is")}i.tlds=r}return p($);})(); | ||
//! parseUri 3.0.1; Steven Levithan; MIT License | ||
//! parseUri 3.0.2; Steven Levithan; MIT License | ||
parseUri.parseUri.setTlds=parseUri.setTlds;globalThis.parseUri=parseUri.parseUri; |
{ | ||
"name": "parseuri", | ||
"version": "3.0.1", | ||
"version": "3.0.2", | ||
"description": "Mighty but tiny URI parser", | ||
"homepage": "https://slevithan.github.io/parseuri/demo/", | ||
"main": "src/index.js", | ||
"exports": "./src/index.js", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "scripts": { |
@@ -1,10 +0,14 @@ | ||
# parseUri 3.0.1 | ||
# parseUri | ||
`parseUri` is a mighty but tiny JavaScript URI/URN/URL parser that splits any URI into its parts (all of which are optional). Its combination of accuracy, comprehensiveness, and brevity is unrivaled (1KB min/gzip, with no dependencies). | ||
## Compared to the built-in [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) | ||
## Breaking changes | ||
`parseUri` includes several advantages over `URL`: | ||
Version 2 was a major, breaking change that probably requires updating URI part names in your code. See details in the [release notes](https://github.com/slevithan/parseuri/releases/tag/v2.0.0) and compare results on the [demo page](https://slevithan.github.io/parseuri/demo/?compareV1=true&friendlyMode=true). Version 3 was a small update published on npm as pure ESM. | ||
* `parseUri` gives you many additional properties (`authority`, `userinfo`, `subdomain`, `domain`, `tld`, `resource`, `directory`, `filename`, `suffix`) that aren’t available from `URL`. | ||
## Compared to the `URL` constructor | ||
`parseUri` includes several advantages over the built-in [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL): | ||
* It gives you many additional properties (`authority`, `userinfo`, `subdomain`, `domain`, `tld`, `resource`, `directory`, `filename`, `suffix`) that aren’t available from `URL`. | ||
* `URL` throws e.g. if not given a protocol, and in many other cases of valid (but not supported) and invalid URIs. `parseUri` makes a best case effort even with partial or invalid URIs and is extremely good with edge cases. | ||
@@ -15,5 +19,5 @@ * `URL`’s rules don’t allow correctly handling many non-web protocols. For example, `URL` doesn’t throw on any of `'git://localhost:1234'`, `'ssh://myid@192.168.1.101'`, or `'t2ab:///path/entry'`, but it also doesn’t get their details correct since it treats everything after `<non-web-protocol>:` up to `?` or `#` as part of the `pathname`. | ||
Conversely, `parseUri` is single-purpose and doesn’t apply normalization. You can of course use a URI normalizer separately, or build one on top of `parseUri`. | ||
Conversely, `parseUri` is single-purpose and doesn’t apply normalization. | ||
`parseUri`’s [demo page](https://slevithan.github.io/parseuri/demo/?urlStandard=true) allows easily comparing with `URL`’s results. | ||
The [demo page](https://slevithan.github.io/parseuri/demo/?urlStandard=true) allows easily comparing with `URL`’s results. | ||
@@ -45,4 +49,6 @@ ## Results / URI parts | ||
`parseUri` additionally supports IPv4 and IPv6 addresses, URNs, and many edge cases not shown here. See [tests](https://slevithan.github.io/parseuri/spec/). | ||
> If this chart doesn’t appear correctly, view it on [GitHub](https://github.com/slevithan/parseuri/blob/main/README.md#results--uri-parts). | ||
`parseUri` additionally supports IPv4 and IPv6 addresses, URNs, and many edge cases not shown here. See the extensive [tests](https://slevithan.github.io/parseuri/spec/). | ||
## Parsing modes | ||
@@ -56,3 +62,3 @@ | ||
## Usage examples | ||
## Examples | ||
@@ -78,5 +84,5 @@ ```js | ||
uri.queryParams.getAll('not-present') // → [] | ||
// also available: href, origin, authority, userinfo, username, password, tld | ||
// Also available: href, origin, authority, userinfo, username, password, tld | ||
// relative path (not starting from root /) | ||
// Relative path (not starting from root /) | ||
uri = parseUri('dir/file.html?q=x'); | ||
@@ -88,3 +94,3 @@ uri.hostname // → '' | ||
// friendly mode allows starting with an authority | ||
// Friendly mode allows starting with an authority | ||
uri = parseUri('example.com/file.html', 'friendly'); | ||
@@ -109,3 +115,3 @@ uri.hostname // → 'example.com' | ||
// mailto | ||
// Mailto | ||
uri = parseUri('mailto:first@my.com,second@my.com?subject=Hey&body=Sign%20me%20up!'); | ||
@@ -119,3 +125,3 @@ uri.protocol // → 'mailto' | ||
// mailto in friendly mode | ||
// Mailto in friendly mode | ||
uri = parseUri('mailto:me@my.com?subject=Hey', 'friendly'); | ||
@@ -136,2 +142,24 @@ uri.protocol // → 'mailto' | ||
Use `parseUri`’s [demo page](https://slevithan.github.io/parseuri/demo/) to easily test and compare results. | ||
Use the [demo page](https://slevithan.github.io/parseuri/demo/) to easily test and compare results. | ||
## Install | ||
```bash | ||
npm install parseuri | ||
``` | ||
## Use | ||
```js | ||
import { parseUri, setTlds } from 'parseuri'; | ||
``` | ||
In browsers: | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/parseuri/dist/parseuri.min.js"></script> | ||
<script> | ||
console.log(parseUri('https://example.com/')); | ||
// If needed, use `parseUri.setTlds` | ||
</script> | ||
``` |
beforeEach(() => { | ||
jasmine.addMatchers({ | ||
// only compare given keys | ||
// only compares given keys | ||
toMatchUriKeys: () => { | ||
@@ -16,3 +16,3 @@ return { | ||
}, | ||
// only compare given keys | ||
// only compares given keys | ||
toMatchUriKeysInAllModes: () => { | ||
@@ -19,0 +19,0 @@ return { |
@@ -124,3 +124,3 @@ // fallback check of a collection of URIs | ||
it('should match expected results in default mode', () => { | ||
it('should match expected results for a collection of URIs in default mode', () => { | ||
uris.forEach(uri => { | ||
@@ -127,0 +127,0 @@ expect(parseUri(uri.uri, 'default')).toMatchUriKeys({ |
@@ -1,2 +0,2 @@ | ||
//! parseUri 3.0.1; Steven Levithan; MIT License | ||
//! parseUri 3.0.2; Steven Levithan; MIT License | ||
/* A mighty but tiny URI/URN/URL parser; splits any URI into its parts (all of which are optional). | ||
@@ -23,33 +23,33 @@ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ | ||
/** | ||
* @typedef {Object} ParseUriObject | ||
* @prop {string} href | ||
* @prop {string} origin | ||
* @prop {string} protocol | ||
* @prop {string} authority | ||
* @prop {string} userinfo | ||
* @prop {string} username | ||
* @prop {string} password | ||
* @prop {string} host | ||
* @prop {string} hostname | ||
* @prop {string} subdomain | ||
* @prop {string} domain | ||
* @prop {string} tld | ||
* @prop {string} port | ||
* @prop {string} resource | ||
* @prop {string} pathname | ||
* @prop {string} directory | ||
* @prop {string} filename | ||
* @prop {string} suffix | ||
* @prop {string} query | ||
* @prop {string} fragment | ||
* @prop {URLSearchParams} queryParams | ||
*/ | ||
@typedef {Object} ParseUriObject | ||
@prop {string} href | ||
@prop {string} origin | ||
@prop {string} protocol | ||
@prop {string} authority | ||
@prop {string} userinfo | ||
@prop {string} username | ||
@prop {string} password | ||
@prop {string} host | ||
@prop {string} hostname | ||
@prop {string} subdomain | ||
@prop {string} domain | ||
@prop {string} tld | ||
@prop {string} port | ||
@prop {string} resource | ||
@prop {string} pathname | ||
@prop {string} directory | ||
@prop {string} filename | ||
@prop {string} suffix | ||
@prop {string} query | ||
@prop {string} fragment | ||
@prop {URLSearchParams} queryParams | ||
*/ | ||
/** | ||
* Splits any URI into its parts. | ||
* @param {string} uri | ||
* @param {'default' | 'friendly'} [mode] Parsing mode. Default follows official URI rules. | ||
* Friendly handles human-friendly URLs like `'example.com/index.html'` as expected. | ||
* @returns {ParseUriObject} Object with URI parts, plus `queryParams`. | ||
*/ | ||
Splits any URI into its parts. | ||
@param {string} uri | ||
@param {'default' | 'friendly'} [mode] Parsing mode. Default follows official URI rules. | ||
Friendly handles human-friendly URLs like `'example.com/index.html'` as expected. | ||
@returns {ParseUriObject} Object with URI parts, plus `queryParams`. | ||
*/ | ||
function parseUri(uri, mode = 'default') { | ||
@@ -61,7 +61,7 @@ uri = uri.trim(); | ||
...groups, | ||
// URNs: if we have an authority (contained in `hasAuth`), keep dir/file, else remove because | ||
// URNs: If we have an authority (contained in `hasAuth`), keep dir/file, else remove because | ||
// they don't apply. `hasAuth` indicates participation in the match, but it could be empty | ||
...(groups.protocol && groups.hasAuth == null ? blankUrnProps : null), | ||
}; | ||
// replace `undefined` for non-participating capturing groups | ||
// Replace `undefined` for non-participating capturing groups | ||
Object.keys(result).forEach(key => result[key] ??= ''); | ||
@@ -81,4 +81,4 @@ return Object.assign(result, { | ||
function getParser(mode) { | ||
// forward and backslashes have lost all meaning for web protocols (http, https, ws, wss, ftp) | ||
// and protocol-relative URLs. also handle multiple colons in protocol delimiter for security | ||
// Forward and backslashes have lost all meaning for web protocols (http, https, ws, wss, ftp) | ||
// and protocol-relative URLs. Also handle multiple colons in protocol delimiter for security | ||
const authorityDelimiter = String.raw`(?:(?:(?<=^(?:https?|wss?|ftp):):*|^:+)[\\/]*|^[\\/]{2,}|//)`; | ||
@@ -89,3 +89,3 @@ const authority = { | ||
}; | ||
// see `free-spacing-regex.md` | ||
// See file: free-spacing-regex.md | ||
return RegExp(String.raw`^(?<origin>(?:(?<protocol>[a-z][^\s:@\\/?#.]*):)?${authority[mode].start}(?<authority>(?:(?<userinfo>(?<username>[^:@\\/?#]*)(?::(?<password>[^\\/?#]*))?)?@)?(?<host>(?<hostname>\d{1,3}(?:\.\d{1,3}){3}(?=[:\\/?#]|$)|\[[a-f\d]{0,4}(?::[a-f\d]{0,4}){2,7}(?:%[^\]]*)?\]|(?<subdomain>[^:\\/?#]*?)\.??(?<domain>(?:[^.:\\/?#]*\.)?(?<tld>[^.:\\/?#]*))(?=[:\\/?#]|$))?(?::(?<port>[^:\\/?#]*))?))${authority[mode].end})(?<resource>(?<pathname>(?<directory>(?:[^\\/?#]*[\\/])*)(?<filename>(?:[^.?#]+|\.(?![^.?#]+(?:[?#]|$)))*(?:\.(?<suffix>[^.?#]+))?))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>.*))?)`, 'i'); | ||
@@ -102,10 +102,10 @@ } | ||
/** | ||
* Set second-level domains recognized as part of the TLD (ex: co.uk). | ||
* @example | ||
* setTlds({ | ||
* au: 'com edu gov id net org', | ||
* uk: 'co gov me net org sch', | ||
* }); | ||
* @param {Object} obj Object with TLDs as keys and their SLDs as space-separated strings. | ||
*/ | ||
Set second-level domains recognized as part of the TLD (ex: co.uk). | ||
@param {Object} obj Object with TLDs as keys and their SLDs as space-separated strings. | ||
@example | ||
setTlds({ | ||
au: 'com edu gov id net org', | ||
uk: 'co gov me net org sch', | ||
}); | ||
*/ | ||
function setTlds(obj) { | ||
@@ -126,2 +126,2 @@ const entries = Object.entries(obj); | ||
export {parseUri, setTlds}; | ||
export { parseUri, setTlds }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
158
0
111247
22