From e4e212c0dde570a98690693e828e00274b038aa1 Mon Sep 17 00:00:00 2001 From: ob-aion Date: Thu, 21 May 2026 16:09:03 +0700 Subject: [PATCH 1/2] docs(uri): add Compared to alternatives section Mirrors the pattern from @coroboros/clone: feature-presence table plus a positioning paragraph. Compares against native `URL` (WHATWG), `uri-js`, `whatwg-url`, and `url-parse`. TOC updated; section sits between Limitations and Contributing. --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 56faeb3..03c1213 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Parses URIs per **RFC-3986 Appendix B**. Recomposes per §5.3. Resolves referenc - [API](#api) - [Errors](#errors) - [Limitations](#limitations) +- [Compared to alternatives](#compared-to-alternatives) - [Contributing](#contributing) - [License](#license) @@ -975,6 +976,23 @@ The `code` field is a stable string discriminant safe for runtime branching. - IPv6 addresses are not canonicalized to **RFC 5952** form. - The `lowercase` option lowercases the entire input including path, query, and fragment, which are case-sensitive per **RFC-3986 §6.2.2.1**. Use `lowercase` for Sitemap or convenience, not as RFC normalization. By default only scheme and host are lowercased, which is the RFC-compliant behavior. +## Compared to alternatives + +| Feature | Node `URL` (WHATWG) | `uri-js` | `whatwg-url` | `url-parse` | **`@coroboros/uri`** | +| --------------------------------------------------- | :-----------------: | :-------------: | :-------------: | :-------------: | :------------------: | +| Strict RFC-3986 parse | no (WHATWG) | yes | no (WHATWG) | no (custom) | yes | +| Reference resolution (§5.2) | yes | yes | yes | yes (`baseURL`) | yes | +| Explicit recompose API | via `toString` | yes | yes | via `toString` | yes | +| Punycode / IDN (RFC-3987) | yes | yes | yes (via `tr46`)| no | yes | +| IPv6 zone identifiers (RFC 6874 `%25`) | yes | yes | unknown | no | yes | +| Standalone IP validators (`isIP`, `isIPv4`, `isIPv6`)| no | no | no | no | yes | +| Standalone domain validators (RFC 1034/1123) | no | no | no | no | yes | +| Sitemap validation (XML escape + 2,048 cap) | no | no | no | no | yes | +| Coded error class | `TypeError` | generic `Error` | returns `null` | generic `Error` | yes | +| Zero runtime dependencies | yes (built-in) | no (1) | no (3) | no (2) | yes | + +The differentiator is validation and Sitemap handling on top of strict RFC-3986 semantics. Node's `URL` follows WHATWG, which is fine for the browser but diverges from RFC-3986 on percent-encoding and scheme-relative references, and ships no validators. `uri-js` parses and serializes per RFC-3986 strictly, then stops at the parse layer; the IP, domain, HTTP(S), and Sitemap validators are absent. The error class is generic, and the install pulls `punycode`. `whatwg-url` and `url-parse` solve adjacent problems (WHATWG conformance, generic parsing). `@coroboros/uri` covers the three RFC-3986 operations (parse, recompose, resolve), Punycode IDN, RFC 6874 zone IDs, IP/domain validators, HTTP(S) guards, and Sitemap checks. Every failure flows through a `URIError` class with a stable `code`, zero deps. + ## Contributing Bug reports and PRs welcome. From 2bc5089df6218a75d7cb296ae727fffe0868ae66 Mon Sep 17 00:00:00 2001 From: ob-aion Date: Thu, 21 May 2026 16:35:54 +0700 Subject: [PATCH 2/2] docs(uri): use 'gap' wording in opener for public README 'Differentiator' read as product-strategy register. 'Gap' is more neutral and aligns with the existing sparkline opener. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03c1213..2bfc369 100644 --- a/README.md +++ b/README.md @@ -991,7 +991,7 @@ The `code` field is a stable string discriminant safe for runtime branching. | Coded error class | `TypeError` | generic `Error` | returns `null` | generic `Error` | yes | | Zero runtime dependencies | yes (built-in) | no (1) | no (3) | no (2) | yes | -The differentiator is validation and Sitemap handling on top of strict RFC-3986 semantics. Node's `URL` follows WHATWG, which is fine for the browser but diverges from RFC-3986 on percent-encoding and scheme-relative references, and ships no validators. `uri-js` parses and serializes per RFC-3986 strictly, then stops at the parse layer; the IP, domain, HTTP(S), and Sitemap validators are absent. The error class is generic, and the install pulls `punycode`. `whatwg-url` and `url-parse` solve adjacent problems (WHATWG conformance, generic parsing). `@coroboros/uri` covers the three RFC-3986 operations (parse, recompose, resolve), Punycode IDN, RFC 6874 zone IDs, IP/domain validators, HTTP(S) guards, and Sitemap checks. Every failure flows through a `URIError` class with a stable `code`, zero deps. +The gap is standalone validators and Sitemap support on top of strict RFC-3986 semantics. Node's `URL` follows WHATWG, which is fine for the browser but diverges from RFC-3986 on percent-encoding and scheme-relative references, and ships no validators. `uri-js` parses and serializes per RFC-3986 strictly, then stops at the parse layer; the IP, domain, HTTP(S), and Sitemap validators are absent. The error class is generic, and the install pulls `punycode`. `whatwg-url` and `url-parse` solve adjacent problems (WHATWG conformance, generic parsing). `@coroboros/uri` covers the three RFC-3986 operations (parse, recompose, resolve), Punycode IDN, RFC 6874 zone IDs, IP/domain validators, HTTP(S) guards, and Sitemap checks. Every failure flows through a `URIError` class with a stable `code`, zero deps. ## Contributing