diff --git a/src/encode.js b/src/encode.js index aef0c61..17c4f4e 100644 --- a/src/encode.js +++ b/src/encode.js @@ -4,29 +4,30 @@ const { isObject } = require('./objects') const { isNonEmptyString } = require('./strings') const reusedSearchParams = new URLSearchParams() +const reusedSearchParamKey = '_' +const reusedSearchParamOffset = 2 // '_='.length const { encodeURIComponent } = globalThis -function encodeWithColonAndForwardSlash(str) { - return encodeURIComponent(str).replace(/%3A/g, ':').replace(/%2F/g, '/') -} - -function encodeWithColonAndPlusSign(str) { - return encodeURIComponent(str).replace(/%3A/g, ':').replace(/%2B/g, '+') -} - -function encodeWithForwardSlash(str) { - return encodeURIComponent(str).replace(/%2F/g, '/') -} - function encodeNamespace(namespace) { return isNonEmptyString(namespace) - ? encodeWithColonAndForwardSlash(namespace) + ? encodeURIComponent(namespace) + .replace(/%3A/g, ':') + .replace(/%2F/g, '/') : '' } -function encodeVersion(version) { - return isNonEmptyString(version) ? encodeWithColonAndPlusSign(version) : '' +function encodeQualifierParam(param) { + if (isNonEmptyString(param)) { + // Param key and value are encoded with `percentEncodeSet` of + // 'application/x-www-form-urlencoded' and `spaceAsPlus` of `true`. + // https://url.spec.whatwg.org/#urlencoded-serializing + reusedSearchParams.set(reusedSearchParamKey, param) + return replacePlusSignWithPercentEncodedSpace( + reusedSearchParams.toString().slice(reusedSearchParamOffset) + ) + } + return '' } function encodeQualifiers(qualifiers) { @@ -43,26 +44,16 @@ function encodeQualifiers(qualifiers) { return '' } -function encodeQualifierParam(qualifierValue) { - return isNonEmptyString - ? encodeURLSearchParamWithPercentEncodedSpace(param) - : '' -} - function encodeSubpath(subpath) { - return isNonEmptyString(subpath) ? encodeWithForwardSlash(subpath) : '' -} - -function encodeURLSearchParam(param) { - // Param key and value are encoded with `percentEncodeSet` of - // 'application/x-www-form-urlencoded' and `spaceAsPlus` of `true`. - // https://url.spec.whatwg.org/#urlencoded-serializing - reusedSearchParams.set('_', qualifierValue) - return reusedSearchParams.toString().slice(2) + return isNonEmptyString(subpath) + ? encodeURIComponent(subpath).replace(/%2F/g, '/') + : '' } -function encodeURLSearchParamWithPercentEncodedSpace(str) { - return replacePlusSignWithPercentEncodedSpace(encodeURLSearchParam(str)) +function encodeVersion(version) { + return isNonEmptyString(version) + ? encodeURIComponent(version).replace(/%3A/g, ':').replace(/%2B/g, '+') + : '' } function replacePlusSignWithPercentEncodedSpace(str) { @@ -71,15 +62,10 @@ function replacePlusSignWithPercentEncodedSpace(str) { } module.exports = { - encodeWithColonAndForwardSlash, - encodeWithColonAndPlusSign, - encodeWithForwardSlash, encodeNamespace, encodeVersion, encodeQualifiers, encodeQualifierParam, encodeSubpath, - encodeURIComponent, - encodeURLSearchParam, - encodeURLSearchParamWithPercentEncodedSpace + encodeURIComponent } diff --git a/src/purl-component.js b/src/purl-component.js index e61dffd..db76f15 100644 --- a/src/purl-component.js +++ b/src/purl-component.js @@ -12,28 +12,28 @@ const { const { createHelpersNamespaceObject } = require('./helpers') const { - normalizeName, + normalizeType, normalizeNamespace, + normalizeName, + normalizeVersion, normalizeQualifiers, - normalizeSubpath, - normalizeType, - normalizeVersion + normalizeSubpath } = require('./normalize') -const { localeCompare } = require('./strings') +const { localeCompare, isNonEmptyString } = require('./strings') const { - validateName, + validateType, validateNamespace, + validateName, + validateVersion, validateQualifiers, validateQualifierKey, - validateSubpath, - validateType, - validateVersion + validateSubpath } = require('./validate') const PurlComponentEncoder = (comp) => - typeof comp === 'string' && comp.length ? encodeURIComponent(comp) : '' + isNonEmptyString(comp) ? encodeURIComponent(comp) : '' const PurlComponentStringNormalizer = (comp) => typeof comp === 'string' ? comp : undefined diff --git a/src/validate.js b/src/validate.js index 42a41cc..70dff28 100644 --- a/src/validate.js +++ b/src/validate.js @@ -1,6 +1,7 @@ 'use strict' const { isNullishOrEmptyString } = require('./lang') +const { isNonEmptyString } = require('./strings') function validateEmptyByType(type, name, value, throws) { if (!isNullishOrEmptyString(value)) { @@ -104,7 +105,7 @@ function validateRequiredByType(type, name, value, throws) { } function validateStartsWithoutNumber(name, value, throws) { - if (value.length !== 0) { + if (isNonEmptyString(value)) { const code = value.charCodeAt(0) if (code >= 48 /*'0'*/ && code <= 57 /*'9'*/) { if (throws) {