encodeUri
Re-encodes uri so every hierarchical component is a valid RFC 3986 sequence, without disturbing percent-triplets that are already present.
The components are rebuilt from their raw (still-encoded) forms: characters that are legal in their component are copied through, valid %XX triplets are copied verbatim, and only actually-illegal characters (spaces, non-ASCII, stray %) are percent-encoded. This makes the function idempotent and safe for identifiers that legitimately contain encoded reserved characters — a path segment holding %2F stays %2F instead of collapsing into a real /.
Opaque URIs (mailto:, urn:) have no hierarchical components and are returned unchanged, as is uri itself if re-encoding fails.