trousse 2.16.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/arrays.js +2 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/is.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/urls.d.ts +10 -3
- package/dist/urls.js +99 -22
- package/package.json +2 -2
package/dist/arrays.js
CHANGED
|
@@ -3,6 +3,7 @@ import { isPresent } from "./is.js";
|
|
|
3
3
|
const omitEmpty = (array) => {
|
|
4
4
|
const result = [];
|
|
5
5
|
for (const item of array) if (isPresent(item) && item !== "") result.push(item);
|
|
6
|
-
|
|
6
|
+
if (!result.length) return;
|
|
7
|
+
return result;
|
|
7
8
|
};
|
|
8
9
|
export { omitEmpty };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { omitEmpty } from "./arrays.js";
|
|
2
|
-
import { AnyOf, DeepOmit, IsPlainObject, MaybePromise, NormalizeOptions, Nullish, PartialNullish, Pattern, RegistrableDomainOptions, WeightedMimeType } from "./types.js";
|
|
2
|
+
import { AnyOf, DeepOmit, IsPlainObject, MaybePromise, NormalizeOptions, Nullish, ParamSource, PartialNullish, Pattern, RegistrableDomainOptions, WeightedMimeType } from "./types.js";
|
|
3
3
|
import { coerceArray, coerceBoolean, coerceDate, coerceNumber, coerceSingular, coerceString } from "./coercions.js";
|
|
4
4
|
import { archiveExtensions, audioExtensions, codeExtensions, documentExtensions, flashExtensions, fontExtensions, imageExtensions, installerExtensions, subtitleExtensions, videoExtensions } from "./files.js";
|
|
5
5
|
import { isBoolean, isFunction, isNonEmptyString, isNullish, isNumber, isObject, isPlainObject, isPresent, isString, isValidDate } from "./is.js";
|
|
@@ -9,5 +9,5 @@ import { anyWordMatchesAnyOf, endsWithAnyOf, escapeRegex, getAnyOf, includesAnyO
|
|
|
9
9
|
import { createAcceptHeader, feedMimeTypes, genericFeedMimeTypes, genericHtmlMimeTypes, htmlMimeTypes } from "./mimes.js";
|
|
10
10
|
import { omit, pick, toMap, trimObject } from "./objects.js";
|
|
11
11
|
import { sleep } from "./timers.js";
|
|
12
|
-
import { addMissingProtocol, addMissingScheme, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getPathSegments, getQueryParam, getQueryParams, getRegistrableDomain, getSubdomain, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme } from "./urls.js";
|
|
13
|
-
export { type AnyOf, type DeepOmit, type IsPlainObject, type MaybePromise, type NormalizeOptions, type Nullish, type PartialNullish, type Pattern, type RegistrableDomainOptions, type WeightedMimeType, addMissingProtocol, addMissingScheme, anyWordMatchesAnyOf, archiveExtensions, audioExtensions, codeExtensions, coerceArray, coerceBoolean, coerceDate, coerceNumber, coerceSingular, coerceString, composeQuery, createAcceptHeader, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, documentExtensions, encodePathSegment, endsWithAnyOf, escapeHtml, escapeRegex, feedMimeTypes, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, flashExtensions, fontExtensions, genericFeedMimeTypes, genericHtmlMimeTypes, getAnyOf, getPathSegments, getQueryParam, getQueryParams, getRegistrableDomain, getSubdomain, htmlMimeTypes, imageExtensions, includesAnyOf, installerExtensions, isAnyOf, isBoolean, isFunction, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isJsonLike, isNonEmptyString, isNullish, isNumber, isObject, isParseableJson, isPlainObject, isPresent, isString, isSubdomainOf, isValidDate, normalizeUrl, omit, omitEmpty, parseUrl, pick, resolveFeedProtocol, resolveFeedScheme, resolveUrl, sleep, startsWithAnyOf, stripWww, subtitleExtensions, t, toMap, trimObject, trimUrlValues, tx, upgradeProtocol, upgradeScheme, videoExtensions };
|
|
12
|
+
import { addMissingProtocol, addMissingScheme, composeFragment, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getFragmentParam, getFragmentParamValues, getFragmentParams, getPathSegments, getQueryParam, getQueryParamValues, getQueryParams, getRegistrableDomain, getSubdomain, hasFragmentParam, hasQueryParam, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme } from "./urls.js";
|
|
13
|
+
export { type AnyOf, type DeepOmit, type IsPlainObject, type MaybePromise, type NormalizeOptions, type Nullish, type ParamSource, type PartialNullish, type Pattern, type RegistrableDomainOptions, type WeightedMimeType, addMissingProtocol, addMissingScheme, anyWordMatchesAnyOf, archiveExtensions, audioExtensions, codeExtensions, coerceArray, coerceBoolean, coerceDate, coerceNumber, coerceSingular, coerceString, composeFragment, composeQuery, createAcceptHeader, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, documentExtensions, encodePathSegment, endsWithAnyOf, escapeHtml, escapeRegex, feedMimeTypes, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, flashExtensions, fontExtensions, genericFeedMimeTypes, genericHtmlMimeTypes, getAnyOf, getFragmentParam, getFragmentParamValues, getFragmentParams, getPathSegments, getQueryParam, getQueryParamValues, getQueryParams, getRegistrableDomain, getSubdomain, hasFragmentParam, hasQueryParam, htmlMimeTypes, imageExtensions, includesAnyOf, installerExtensions, isAnyOf, isBoolean, isFunction, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isJsonLike, isNonEmptyString, isNullish, isNumber, isObject, isParseableJson, isPlainObject, isPresent, isString, isSubdomainOf, isValidDate, normalizeUrl, omit, omitEmpty, parseUrl, pick, resolveFeedProtocol, resolveFeedScheme, resolveUrl, sleep, startsWithAnyOf, stripWww, subtitleExtensions, t, toMap, trimObject, trimUrlValues, tx, upgradeProtocol, upgradeScheme, videoExtensions };
|
package/dist/index.js
CHANGED
|
@@ -8,5 +8,5 @@ import { anyWordMatchesAnyOf, endsWithAnyOf, escapeRegex, getAnyOf, includesAnyO
|
|
|
8
8
|
import { createAcceptHeader, feedMimeTypes, genericFeedMimeTypes, genericHtmlMimeTypes, htmlMimeTypes } from "./mimes.js";
|
|
9
9
|
import { omit, pick, toMap, trimObject } from "./objects.js";
|
|
10
10
|
import { sleep } from "./timers.js";
|
|
11
|
-
import { addMissingProtocol, addMissingScheme, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getPathSegments, getQueryParam, getQueryParams, getRegistrableDomain, getSubdomain, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme } from "./urls.js";
|
|
12
|
-
export { addMissingProtocol, addMissingScheme, anyWordMatchesAnyOf, archiveExtensions, audioExtensions, codeExtensions, coerceArray, coerceBoolean, coerceDate, coerceNumber, coerceSingular, coerceString, composeQuery, createAcceptHeader, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, documentExtensions, encodePathSegment, endsWithAnyOf, escapeHtml, escapeRegex, feedMimeTypes, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, flashExtensions, fontExtensions, genericFeedMimeTypes, genericHtmlMimeTypes, getAnyOf, getPathSegments, getQueryParam, getQueryParams, getRegistrableDomain, getSubdomain, htmlMimeTypes, imageExtensions, includesAnyOf, installerExtensions, isAnyOf, isBoolean, isFunction, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isJsonLike, isNonEmptyString, isNullish, isNumber, isObject, isParseableJson, isPlainObject, isPresent, isString, isSubdomainOf, isValidDate, normalizeUrl, omit, omitEmpty, parseUrl, pick, resolveFeedProtocol, resolveFeedScheme, resolveUrl, sleep, startsWithAnyOf, stripWww, subtitleExtensions, t, toMap, trimObject, trimUrlValues, tx, upgradeProtocol, upgradeScheme, videoExtensions };
|
|
11
|
+
import { addMissingProtocol, addMissingScheme, composeFragment, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getFragmentParam, getFragmentParamValues, getFragmentParams, getPathSegments, getQueryParam, getQueryParamValues, getQueryParams, getRegistrableDomain, getSubdomain, hasFragmentParam, hasQueryParam, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme } from "./urls.js";
|
|
12
|
+
export { addMissingProtocol, addMissingScheme, anyWordMatchesAnyOf, archiveExtensions, audioExtensions, codeExtensions, coerceArray, coerceBoolean, coerceDate, coerceNumber, coerceSingular, coerceString, composeFragment, composeQuery, createAcceptHeader, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, documentExtensions, encodePathSegment, endsWithAnyOf, escapeHtml, escapeRegex, feedMimeTypes, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, flashExtensions, fontExtensions, genericFeedMimeTypes, genericHtmlMimeTypes, getAnyOf, getFragmentParam, getFragmentParamValues, getFragmentParams, getPathSegments, getQueryParam, getQueryParamValues, getQueryParams, getRegistrableDomain, getSubdomain, hasFragmentParam, hasQueryParam, htmlMimeTypes, imageExtensions, includesAnyOf, installerExtensions, isAnyOf, isBoolean, isFunction, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isJsonLike, isNonEmptyString, isNullish, isNumber, isObject, isParseableJson, isPlainObject, isPresent, isString, isSubdomainOf, isValidDate, normalizeUrl, omit, omitEmpty, parseUrl, pick, resolveFeedProtocol, resolveFeedScheme, resolveUrl, sleep, startsWithAnyOf, stripWww, subtitleExtensions, t, toMap, trimObject, trimUrlValues, tx, upgradeProtocol, upgradeScheme, videoExtensions };
|
package/dist/is.js
CHANGED
|
@@ -25,7 +25,7 @@ const isPlainObject = (value) => {
|
|
|
25
25
|
};
|
|
26
26
|
const whitespaceOnlyRegex = /^\p{White_Space}*$/u;
|
|
27
27
|
const isNonEmptyString = (value) => {
|
|
28
|
-
if (!isString(value) || value
|
|
28
|
+
if (!isString(value) || !value) return false;
|
|
29
29
|
const code = value.charCodeAt(0);
|
|
30
30
|
if (code > 32 && code < 127) return true;
|
|
31
31
|
return !whitespaceOnlyRegex.test(value);
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type Nullish<T> = T | null | undefined;
|
|
|
5
5
|
export type PartialNullish<T> = { [Key in keyof T]?: Nullish<T[Key]>; };
|
|
6
6
|
export type MaybePromise<T> = T | Promise<T>;
|
|
7
7
|
export type Pattern = string | RegExp;
|
|
8
|
+
export type ParamSource = URL | URLSearchParams | string;
|
|
8
9
|
export type RegistrableDomainOptions = {
|
|
9
10
|
suffixes?: ReadonlyArray<string>;
|
|
10
11
|
};
|
package/dist/urls.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NormalizeOptions, Nullish, RegistrableDomainOptions } from "./types.js";
|
|
1
|
+
import { NormalizeOptions, Nullish, ParamSource, RegistrableDomainOptions } from "./types.js";
|
|
2
2
|
export declare const parseUrl: (value: Nullish<string | URL>, base?: string | URL) => URL | undefined;
|
|
3
3
|
export declare const getPathSegments: (value: string | URL) => Array<string>;
|
|
4
4
|
export declare const isHostOf: (url: string | URL, hosts: string | ReadonlyArray<string>) => boolean;
|
|
@@ -9,9 +9,16 @@ export declare const getSubdomain: (url: string | URL, domains: string | Readonl
|
|
|
9
9
|
export declare const decodeSegment: (segment: string | undefined) => string | undefined;
|
|
10
10
|
export declare const decodePercent: (value: string) => string;
|
|
11
11
|
export declare const encodePathSegment: (value: string) => string;
|
|
12
|
-
export declare const
|
|
13
|
-
export declare const
|
|
12
|
+
export declare const hasQueryParam: (source: ParamSource | undefined, name: string) => boolean;
|
|
13
|
+
export declare const getQueryParamValues: (source: ParamSource | undefined, name: string) => Array<string>;
|
|
14
|
+
export declare const getQueryParam: (source: ParamSource | undefined, name: string) => string | undefined;
|
|
15
|
+
export declare const getQueryParams: (source: ParamSource | undefined, names: ReadonlyArray<string>) => Record<string, string>;
|
|
16
|
+
export declare const hasFragmentParam: (source: ParamSource | undefined, name: string) => boolean;
|
|
17
|
+
export declare const getFragmentParamValues: (source: ParamSource | undefined, name: string) => Array<string>;
|
|
18
|
+
export declare const getFragmentParam: (source: ParamSource | undefined, name: string) => string | undefined;
|
|
19
|
+
export declare const getFragmentParams: (source: ParamSource | undefined, names: ReadonlyArray<string>) => Record<string, string>;
|
|
14
20
|
export declare const composeQuery: (params?: Record<string, string | number>) => string;
|
|
21
|
+
export declare const composeFragment: (params?: Record<string, string | number>) => string;
|
|
15
22
|
export declare const fixMalformedScheme: (url: string) => string;
|
|
16
23
|
export declare const fixMalformedQuery: (url: string) => string;
|
|
17
24
|
export declare const trimUrlValues: (url: string) => string;
|
package/dist/urls.js
CHANGED
|
@@ -94,25 +94,85 @@ const pathSegmentEscapeRegex = /[/?#\\\s]/g;
|
|
|
94
94
|
const encodePathSegment = (value) => {
|
|
95
95
|
return value.replace(pathSegmentEscapeRegex, (character) => encodeURIComponent(character));
|
|
96
96
|
};
|
|
97
|
-
const
|
|
97
|
+
const readQuerySource = (source) => {
|
|
98
|
+
if (source instanceof URL) return source.searchParams;
|
|
99
|
+
if (typeof source === "string") return new URLSearchParams(source);
|
|
100
|
+
return source;
|
|
101
|
+
};
|
|
102
|
+
const readFragmentSource = (source) => {
|
|
103
|
+
if (source instanceof URL) return new URLSearchParams(source.hash.slice(1));
|
|
104
|
+
if (typeof source === "string") return new URLSearchParams(source.startsWith("#") ? source.slice(1) : source);
|
|
105
|
+
return source;
|
|
106
|
+
};
|
|
107
|
+
const readParamValues = (params, name) => {
|
|
98
108
|
const values = [];
|
|
99
109
|
if (!params) return values;
|
|
100
110
|
const lowercaseName = name.toLowerCase();
|
|
101
|
-
for (const [key, value] of params)
|
|
111
|
+
for (const [key, value] of params) {
|
|
112
|
+
if (key.toLowerCase() !== lowercaseName) continue;
|
|
113
|
+
const trimmed = value.trim();
|
|
114
|
+
if (trimmed) values.push(trimmed);
|
|
115
|
+
}
|
|
102
116
|
return values;
|
|
103
117
|
};
|
|
104
|
-
const
|
|
105
|
-
|
|
118
|
+
const hasParam = (params, name) => {
|
|
119
|
+
if (!params) return false;
|
|
120
|
+
const lowercaseName = name.toLowerCase();
|
|
121
|
+
for (const key of params.keys()) if (key.toLowerCase() === lowercaseName) return true;
|
|
122
|
+
return false;
|
|
123
|
+
};
|
|
124
|
+
const readParams = (params, names) => {
|
|
125
|
+
const picked = {};
|
|
126
|
+
for (const name of names) {
|
|
127
|
+
const value = readParamValues(params, name)[0];
|
|
128
|
+
if (value !== void 0) picked[name] = value;
|
|
129
|
+
}
|
|
130
|
+
return picked;
|
|
131
|
+
};
|
|
132
|
+
const hasQueryParam = (source, name) => {
|
|
133
|
+
return hasParam(readQuerySource(source), name);
|
|
134
|
+
};
|
|
135
|
+
const getQueryParamValues = (source, name) => {
|
|
136
|
+
return readParamValues(readQuerySource(source), name);
|
|
137
|
+
};
|
|
138
|
+
const getQueryParam = (source, name) => {
|
|
139
|
+
return getQueryParamValues(source, name)[0];
|
|
140
|
+
};
|
|
141
|
+
const getQueryParams = (source, names) => {
|
|
142
|
+
return readParams(readQuerySource(source), names);
|
|
143
|
+
};
|
|
144
|
+
const hasFragmentParam = (source, name) => {
|
|
145
|
+
return hasParam(readFragmentSource(source), name);
|
|
146
|
+
};
|
|
147
|
+
const getFragmentParamValues = (source, name) => {
|
|
148
|
+
return readParamValues(readFragmentSource(source), name);
|
|
149
|
+
};
|
|
150
|
+
const getFragmentParam = (source, name) => {
|
|
151
|
+
return getFragmentParamValues(source, name)[0];
|
|
152
|
+
};
|
|
153
|
+
const getFragmentParams = (source, names) => {
|
|
154
|
+
return readParams(readFragmentSource(source), names);
|
|
106
155
|
};
|
|
107
156
|
const queryPartEscapeRegex = /[&#%+\s]/g;
|
|
108
|
-
const
|
|
157
|
+
const composePairs = (params) => {
|
|
109
158
|
const escapePart = (part) => {
|
|
110
159
|
return part.replace(queryPartEscapeRegex, (character) => encodeURIComponent(character));
|
|
111
160
|
};
|
|
112
|
-
const pairs =
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
161
|
+
const pairs = [];
|
|
162
|
+
for (const [name, value] of Object.entries(params ?? {})) {
|
|
163
|
+
const text = String(value);
|
|
164
|
+
if (!text) continue;
|
|
165
|
+
pairs.push(`${escapePart(name)}=${escapePart(text)}`);
|
|
166
|
+
}
|
|
167
|
+
return pairs.join("&");
|
|
168
|
+
};
|
|
169
|
+
const composeQuery = (params) => {
|
|
170
|
+
const pairs = composePairs(params);
|
|
171
|
+
return pairs ? `?${pairs}` : "";
|
|
172
|
+
};
|
|
173
|
+
const composeFragment = (params) => {
|
|
174
|
+
const pairs = composePairs(params);
|
|
175
|
+
return pairs ? `#${pairs}` : "";
|
|
116
176
|
};
|
|
117
177
|
const strippedParamsCache = /* @__PURE__ */ new WeakMap();
|
|
118
178
|
const getStrippedParamsSet = (params) => {
|
|
@@ -183,18 +243,34 @@ const httpOrSchemeRelativeRegex = /^(?:https?:)?\/\//i;
|
|
|
183
243
|
const slugTailRegex = /[/.-]/;
|
|
184
244
|
const lostSeparatorRegex = /(?<!\s)\s+(?=[A-Za-z_][\w.-]*=)/g;
|
|
185
245
|
const slashClosedValueRegex = /(=[^&/=]+)\/+(?=&|$)/g;
|
|
186
|
-
const
|
|
246
|
+
const fixFragmentPairs = (fragment) => {
|
|
247
|
+
const nestedOffset = fragment.search(nestedUrlRegex);
|
|
248
|
+
const ownEnd = nestedOffset === -1 ? fragment.length : nestedOffset;
|
|
249
|
+
let fixed = "";
|
|
250
|
+
let hasValue = false;
|
|
251
|
+
for (let index = 0; index < ownEnd; index++) {
|
|
252
|
+
const character = fragment[index];
|
|
253
|
+
if (character === "?" && hasValue) {
|
|
254
|
+
fixed += "&";
|
|
255
|
+
hasValue = false;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (character === "&") hasValue = false;
|
|
259
|
+
if (character === "=") hasValue = true;
|
|
260
|
+
fixed += character;
|
|
261
|
+
}
|
|
262
|
+
return `${fixed}${fragment.slice(ownEnd)}`;
|
|
263
|
+
};
|
|
264
|
+
const isGlueTail = (head, glueIndex, pathEnd) => {
|
|
187
265
|
const tail = head.slice(glueIndex + 1, pathEnd).split("&")[0] ?? "";
|
|
188
|
-
|
|
189
|
-
if (slugTailRegex.test(tail)) return false;
|
|
190
|
-
return head.slice(glueIndex + 1, ownEnd).includes("=");
|
|
266
|
+
return tail.includes("=") || !slugTailRegex.test(tail);
|
|
191
267
|
};
|
|
192
268
|
const fixMalformedQuery = (url) => {
|
|
193
269
|
if (!httpOrSchemeRelativeRegex.test(url)) return url;
|
|
194
270
|
const hashIndex = url.indexOf("#");
|
|
195
271
|
const hasFragment = hashIndex !== -1;
|
|
196
272
|
const head = hasFragment ? url.slice(0, hashIndex) : url;
|
|
197
|
-
const fragment = hasFragment ? url.slice(hashIndex) : "";
|
|
273
|
+
const fragment = hasFragment ? fixFragmentPairs(url.slice(hashIndex)) : "";
|
|
198
274
|
const authorityEnd = head.indexOf("//") + 2;
|
|
199
275
|
const nestedOffset = head.slice(authorityEnd).search(nestedUrlRegex);
|
|
200
276
|
const hasNestedUrl = nestedOffset !== -1;
|
|
@@ -204,8 +280,8 @@ const fixMalformedQuery = (url) => {
|
|
|
204
280
|
const pathIndex = head.indexOf("/", authorityEnd);
|
|
205
281
|
const pathEnd = hasMark ? markIndex : ownEnd;
|
|
206
282
|
const glueIndex = pathIndex !== -1 && pathIndex < pathEnd ? head.indexOf("&", pathIndex) : -1;
|
|
207
|
-
const isGlued = glueIndex !== -1 && glueIndex < pathEnd && isGlueTail(head, glueIndex, pathEnd
|
|
208
|
-
if (!isGlued && !hasMark) return
|
|
283
|
+
const isGlued = glueIndex !== -1 && glueIndex < pathEnd && isGlueTail(head, glueIndex, pathEnd);
|
|
284
|
+
if (!isGlued && !hasMark) return `${head}${fragment}`;
|
|
209
285
|
const queryIndex = isGlued ? glueIndex : markIndex;
|
|
210
286
|
const queryStart = queryIndex + (isGlued && head[glueIndex + 1] === "?" ? 2 : 1);
|
|
211
287
|
let query = "";
|
|
@@ -231,24 +307,25 @@ const valueEdgeSpaceRegex = new RegExp(`^${valueEdgeSpace}+|(?<!${valueEdgeSpace
|
|
|
231
307
|
const trimEdgeSpace = (value, regex) => {
|
|
232
308
|
return value.replace(regex, "") || value;
|
|
233
309
|
};
|
|
234
|
-
const trimPairValue = (pair) => {
|
|
310
|
+
const trimPairValue = (pair, regex) => {
|
|
235
311
|
const equalsIndex = pair.indexOf("=");
|
|
236
312
|
if (equalsIndex === -1) return pair;
|
|
237
|
-
const value = trimEdgeSpace(pair.slice(equalsIndex + 1),
|
|
313
|
+
const value = trimEdgeSpace(pair.slice(equalsIndex + 1), regex);
|
|
238
314
|
return `${pair.slice(0, equalsIndex + 1)}${value}`;
|
|
239
315
|
};
|
|
240
316
|
const trimUrlValues = (url) => {
|
|
241
317
|
if (!httpOrSchemeRelativeRegex.test(url)) return url;
|
|
242
318
|
const hashIndex = url.indexOf("#");
|
|
243
319
|
const head = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
244
|
-
const fragment = hashIndex === -1 ? "" : url.slice(hashIndex);
|
|
245
320
|
const markIndex = head.indexOf("?");
|
|
246
321
|
const beforeQuery = markIndex === -1 ? head : head.slice(0, markIndex);
|
|
247
322
|
const pathIndex = beforeQuery.indexOf("/", beforeQuery.indexOf("//") + 2);
|
|
248
323
|
const authority = pathIndex === -1 ? beforeQuery : beforeQuery.slice(0, pathIndex);
|
|
249
324
|
const path = (pathIndex === -1 ? [] : beforeQuery.slice(pathIndex).split("/")).map((segment) => trimEdgeSpace(segment, segmentEdgeSpaceRegex)).join("/");
|
|
250
325
|
const pairs = markIndex === -1 ? [] : head.slice(markIndex + 1).split("&");
|
|
251
|
-
|
|
326
|
+
const query = markIndex === -1 ? "" : `?${pairs.map((pair) => trimPairValue(pair, valueEdgeSpaceRegex)).join("&")}`;
|
|
327
|
+
const fragmentPairs = hashIndex === -1 ? [] : url.slice(hashIndex + 1).split("&");
|
|
328
|
+
return `${authority}${path}${query}${hashIndex === -1 ? "" : `#${fragmentPairs.map((pair) => trimPairValue(pair, segmentEdgeSpaceRegex)).join("&")}`}`;
|
|
252
329
|
};
|
|
253
330
|
const feedSchemes = [
|
|
254
331
|
"feed:",
|
|
@@ -380,7 +457,7 @@ const normalizeUrl = (url, options) => {
|
|
|
380
457
|
parsed.search = pairs.join("&");
|
|
381
458
|
}
|
|
382
459
|
if (options.sortQueryParams && parsed.search.includes("&")) parsed.search = parsed.search.slice(1).split("&").filter(Boolean).sort(compareQueryPairs).join("&");
|
|
383
|
-
if (options.stripEmptyQuery && parsed.search
|
|
460
|
+
if (options.stripEmptyQuery && !parsed.search) parsed.search = "";
|
|
384
461
|
let result = parsed.href;
|
|
385
462
|
if (options.stripRootSlash && result === `${parsed.origin}/`) result = parsed.origin;
|
|
386
463
|
if (options.stripScheme ?? options.stripProtocol) result = result.replace(schemePrefixRegex, "");
|
|
@@ -516,4 +593,4 @@ const resolveFeedProtocol = resolveFeedScheme;
|
|
|
516
593
|
const addMissingProtocol = addMissingScheme;
|
|
517
594
|
/** @deprecated Use `upgradeScheme` instead. */
|
|
518
595
|
const upgradeProtocol = upgradeScheme;
|
|
519
|
-
export { addMissingProtocol, addMissingScheme, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getPathSegments, getQueryParam, getQueryParams, getRegistrableDomain, getSubdomain, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme };
|
|
596
|
+
export { addMissingProtocol, addMissingScheme, composeFragment, composeQuery, createUrlSpellings, createUrlVariants, decodePercent, decodeSegment, encodePathSegment, fixMalformedProtocol, fixMalformedQuery, fixMalformedScheme, getFragmentParam, getFragmentParamValues, getFragmentParams, getPathSegments, getQueryParam, getQueryParamValues, getQueryParams, getRegistrableDomain, getSubdomain, hasFragmentParam, hasQueryParam, isHostOf, isHostOrSubdomainOf, isHttpUrl, isIpAddress, isSubdomainOf, normalizeUrl, parseUrl, resolveFeedProtocol, resolveFeedScheme, resolveUrl, stripWww, trimUrlValues, upgradeProtocol, upgradeScheme };
|
package/package.json
CHANGED