@purestack/ts-util 1.1.13 → 1.1.15
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/ts-util.d.mts +5 -1
- package/dist/ts-util.d.mts.map +1 -1
- package/dist/ts-util.mjs +38 -29
- package/dist/ts-util.mjs.map +1 -1
- package/package.json +1 -1
package/dist/ts-util.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @purestack/ts-util v1.1.
|
|
1
|
+
/*! @purestack/ts-util v1.1.15 | (c) 2026 Ahmed Yasin Koculu | MIT License */
|
|
2
2
|
|
|
3
3
|
//#region packages/ts-util/src/assetPath.d.ts
|
|
4
4
|
interface OutputAssetPathOptions {
|
|
@@ -84,6 +84,10 @@ export declare class Cache<K, V> {
|
|
|
84
84
|
//#region packages/ts-util/src/clamp.d.ts
|
|
85
85
|
export declare function clamp(value: number, min: number, max: number): number;
|
|
86
86
|
//#endregion
|
|
87
|
+
//#region packages/ts-util/src/clonePlainData.d.ts
|
|
88
|
+
/** Copies arrays and plain objects recursively, retaining callbacks and other values. */
|
|
89
|
+
export declare function clonePlainData<T>(value: T): T;
|
|
90
|
+
//#endregion
|
|
87
91
|
//#region packages/ts-util/src/escapeHtml.d.ts
|
|
88
92
|
/**
|
|
89
93
|
* Escapes &, `<`, `>`, and " (optionally) in a string for safe insertion into HTML.
|
package/dist/ts-util.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-util.d.mts","names":[],"sources":["../src/assetPath.ts","../src/base.ts","../src/cache.ts","../src/clamp.ts","../src/escapeHtml.ts","../src/logging.ts","../src/merge.ts","../src/publicPath.ts","../src/typeCheck.ts","../src/types.ts","../src/urlNormalizer.ts"],"mappings":";UAKiB;EACf;;wBAGc,sBAAsB;wBAItB,YAAY;wBAIZ,aAAa;wBAQb,aAAa;wBAKb,mBAAmB;wBA0BnB,qBACd,iBACA,UAAS;;;;;;;wBCrDK,KAAK,WAMjB,MAAM,MACH;EAAM;;;;KCZR;EACH;EACA;EACA;EACA;EACA;;KAUU,aAAa,GAAG;EAC1B;EACA;EACA;EACA;EACA;EACA,kBAAkB,OAAO,GAAG,KAAK;EACjC,WAAW;IAAS,KAAK;IAAG,OAAO;IAAG;;EACtC;;qBAGW,MAAM,GAAG;mBACH;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;UAOA;UACA;UACA;UACA;EAER,YAAY,UAAS,aAAa,GAAG;MAWjC;MAIA;EAIJ,YAAY;EAIZ,UAAU;IAAW;IAAqB;;EAU1C,cAAc;EAId,IAAI,KAAK;EAUT,KAAK,KAAK,IAAI;EAUd,IAAI,KAAK,IAAI;EAqBb,IAAI,KAAK,GAAG,OAAO,GAAG,iBAAiB;EAgBvC,OAAO,KAAK;EAQZ;EAMM,cACJ,KAAK,GACL,cAAc,QAAQ,IACtB;IAAY;MACX,QAAQ;EAsBX;UAQQ;UAKA;UAMA;UAOA;UAmBA;;;;wBCjOM,MAAM,eAAe,aAAa
|
|
1
|
+
{"version":3,"file":"ts-util.d.mts","names":[],"sources":["../src/assetPath.ts","../src/base.ts","../src/cache.ts","../src/clamp.ts","../src/clonePlainData.ts","../src/escapeHtml.ts","../src/logging.ts","../src/merge.ts","../src/publicPath.ts","../src/typeCheck.ts","../src/types.ts","../src/urlNormalizer.ts"],"mappings":";UAKiB;EACf;;wBAGc,sBAAsB;wBAItB,YAAY;wBAIZ,aAAa;wBAQb,aAAa;wBAKb,mBAAmB;wBA0BnB,qBACd,iBACA,UAAS;;;;;;;wBCrDK,KAAK,WAMjB,MAAM,MACH;EAAM;;;;KCZR;EACH;EACA;EACA;EACA;EACA;;KAUU,aAAa,GAAG;EAC1B;EACA;EACA;EACA;EACA;EACA,kBAAkB,OAAO,GAAG,KAAK;EACjC,WAAW;IAAS,KAAK;IAAG,OAAO;IAAG;;EACtC;;qBAGW,MAAM,GAAG;mBACH;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;UAOA;UACA;UACA;UACA;EAER,YAAY,UAAS,aAAa,GAAG;MAWjC;MAIA;EAIJ,YAAY;EAIZ,UAAU;IAAW;IAAqB;;EAU1C,cAAc;EAId,IAAI,KAAK;EAUT,KAAK,KAAK,IAAI;EAUd,IAAI,KAAK,IAAI;EAqBb,IAAI,KAAK,GAAG,OAAO,GAAG,iBAAiB;EAgBvC,OAAO,KAAK;EAQZ;EAMM,cACJ,KAAK,GACL,cAAc,QAAQ,IACtB;IAAY;MACX,QAAQ;EAsBX;UAQQ;UAKA;UAMA;UAOA;UAmBA;;;;wBCjOM,MAAM,eAAe,aAAa;;;;wBCGlC,eAAe,GAAG,OAAO,IAAI;;;;;;wBCA7B,WAAW,aAAa;;;UCHvB;EACf,QAAQ,aAAa,OAAO,0BAA0B;;wBAGxC,SAAS,QAAQ,YAAY,gBAAgB;;;;;;;;;;;;;;;;;wBC2C7C,MAAM,GAAG,IAAI,GAAG,MAAM,MAAM,WAAW,iBAAiB;;;wBC5CxD,kBAAkB;wBA0BlB,aAAa,kBAAkB;wBAc/B,cAAc,kBAAkB;;;qBC3CnC,WAAQ,mBAAqB;wBAG1B,aAAa;wBAOb,WACd,gBACC,YAAY;wBAIC,cACd,iBACC,SAAS;wBAMI,kBAAkB,iBAAiB;wBAInC,mBACd,iBACC,SAAS;wBAQI,QAAQ,aAAa,KAAK;;;KCtC9B,YAAY,KACtB,UAAU,YAAY,KAClB,MAAM,YAAY,MAClB,UAAU,oBAAoB,KAC5B,cAAc,YAAY,MAC1B,sBACK,WAAW,KAAK,YAAY,EAAE,SACjC;;;KCPL;UAEK;EACR,gBAAgB;;qBAGL;EACX,cAAa;EASb,eAAc;EAId,YAAW;IAAkB;IAAc;;EAa3C,cAAa,2BACc,UAChB;EA4BX,iBAAgB;EAOhB,sBAAqB;EAiBrB,iBAAgB"}
|
package/dist/ts-util.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @purestack/ts-util v1.1.
|
|
1
|
+
/*! @purestack/ts-util v1.1.15 | (c) 2026 Ahmed Yasin Koculu | MIT License */
|
|
2
2
|
|
|
3
3
|
//#region packages/ts-util/src/assetPath.ts
|
|
4
4
|
const TS_EXT = ".ts";
|
|
@@ -267,6 +267,42 @@ function clamp(value, min, max) {
|
|
|
267
267
|
return Math.max(min, Math.min(max, value));
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
//#endregion
|
|
271
|
+
//#region packages/ts-util/src/typeCheck.ts
|
|
272
|
+
const isString = (value) => typeof value === "string" || value instanceof String;
|
|
273
|
+
function isAbortError(err) {
|
|
274
|
+
const obj = err;
|
|
275
|
+
return obj != null && typeof obj.name === "string" && obj.name === "AbortError";
|
|
276
|
+
}
|
|
277
|
+
function isFunction(func) {
|
|
278
|
+
return typeof func === "function";
|
|
279
|
+
}
|
|
280
|
+
function isPlainObject(value) {
|
|
281
|
+
if (typeof value !== "object" || value === null) return false;
|
|
282
|
+
const proto = Object.getPrototypeOf(value);
|
|
283
|
+
return proto === Object.prototype || proto === null;
|
|
284
|
+
}
|
|
285
|
+
function isNumberOrBoolean(value) {
|
|
286
|
+
return typeof value === "number" || typeof value === "boolean";
|
|
287
|
+
}
|
|
288
|
+
function isEmptyPlainObject(value) {
|
|
289
|
+
if (!isPlainObject(value)) return false;
|
|
290
|
+
for (const _ in value) return false;
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
function isError(o) {
|
|
294
|
+
return o instanceof Error;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region packages/ts-util/src/clonePlainData.ts
|
|
299
|
+
/** Copies arrays and plain objects recursively, retaining callbacks and other values. */
|
|
300
|
+
function clonePlainData(value) {
|
|
301
|
+
if (Array.isArray(value)) return value.map(clonePlainData);
|
|
302
|
+
if (isPlainObject(value)) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, clonePlainData(item)]));
|
|
303
|
+
return value;
|
|
304
|
+
}
|
|
305
|
+
|
|
270
306
|
//#endregion
|
|
271
307
|
//#region packages/ts-util/src/escapeHtml.ts
|
|
272
308
|
/**
|
|
@@ -311,33 +347,6 @@ function logError(logger, error, msg) {
|
|
|
311
347
|
logger.error(msg, { error: errorText });
|
|
312
348
|
}
|
|
313
349
|
|
|
314
|
-
//#endregion
|
|
315
|
-
//#region packages/ts-util/src/typeCheck.ts
|
|
316
|
-
const isString = (value) => typeof value === "string" || value instanceof String;
|
|
317
|
-
function isAbortError(err) {
|
|
318
|
-
const obj = err;
|
|
319
|
-
return obj != null && typeof obj.name === "string" && obj.name === "AbortError";
|
|
320
|
-
}
|
|
321
|
-
function isFunction(func) {
|
|
322
|
-
return typeof func === "function";
|
|
323
|
-
}
|
|
324
|
-
function isPlainObject(value) {
|
|
325
|
-
if (typeof value !== "object" || value === null) return false;
|
|
326
|
-
const proto = Object.getPrototypeOf(value);
|
|
327
|
-
return proto === Object.prototype || proto === null;
|
|
328
|
-
}
|
|
329
|
-
function isNumberOrBoolean(value) {
|
|
330
|
-
return typeof value === "number" || typeof value === "boolean";
|
|
331
|
-
}
|
|
332
|
-
function isEmptyPlainObject(value) {
|
|
333
|
-
if (!isPlainObject(value)) return false;
|
|
334
|
-
for (const _ in value) return false;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
function isError(o) {
|
|
338
|
-
return o instanceof Error;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
350
|
//#endregion
|
|
342
351
|
//#region packages/ts-util/src/merge.ts
|
|
343
352
|
/**
|
|
@@ -478,5 +487,5 @@ function stripBasePath(basePath, pathname) {
|
|
|
478
487
|
}
|
|
479
488
|
|
|
480
489
|
//#endregion
|
|
481
|
-
export { Base, Cache, clamp, dirnamePosix, escapeHtml, isAbortError, isEmptyPlainObject, isError, isFunction, isNumberOrBoolean, isPlainObject, isString, isTypeScriptAssetPath, joinPosix, logError, merge, normalizeBasePath, normalizePosixPath, stripBasePath, toOutputAssetRelPath, toPosixPath, urlNormalizer, withBasePath };
|
|
490
|
+
export { Base, Cache, clamp, clonePlainData, dirnamePosix, escapeHtml, isAbortError, isEmptyPlainObject, isError, isFunction, isNumberOrBoolean, isPlainObject, isString, isTypeScriptAssetPath, joinPosix, logError, merge, normalizeBasePath, normalizePosixPath, stripBasePath, toOutputAssetRelPath, toPosixPath, urlNormalizer, withBasePath };
|
|
482
491
|
//# sourceMappingURL=ts-util.mjs.map
|
package/dist/ts-util.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-util.mjs","names":[],"sources":["../src/assetPath.ts","../src/base.ts","../src/cache.ts","../src/clamp.ts","../src/escapeHtml.ts","../src/logging.ts","../src/typeCheck.ts","../src/merge.ts","../src/urlNormalizer.ts","../src/publicPath.ts"],"sourcesContent":["// Keep these helpers browser-safe so components like PageScript can reuse them\n// without pulling in Node-only modules such as node:path.\nconst TS_EXT = '.ts'\nconst JS_EXT = '.js'\n\nexport interface OutputAssetPathOptions {\n cacheKey?: string\n}\n\nexport function isTypeScriptAssetPath(filePath: string) {\n return getExtension(filePath).toLowerCase() === TS_EXT\n}\n\nexport function toPosixPath(filePath: string) {\n return filePath.replaceAll('\\\\', '/')\n}\n\nexport function dirnamePosix(filePath: string) {\n const normalized = toPosixPath(filePath)\n const slashIndex = normalized.lastIndexOf('/')\n if (slashIndex < 0) return '.'\n if (slashIndex === 0) return '/'\n return normalized.slice(0, slashIndex)\n}\n\nexport function joinPosix(...parts: string[]) {\n const filtered = parts.filter((part) => part.length > 0)\n return normalizePosixPath(filtered.join('/'))\n}\n\nexport function normalizePosixPath(filePath: string) {\n const normalized = toPosixPath(filePath)\n const isAbsolute = normalized.startsWith('/')\n const segments = normalized.split('/')\n const result: string[] = []\n\n for (const segment of segments) {\n if (segment.length === 0 || segment === '.') continue\n if (segment === '..') {\n const last = result[result.length - 1]\n if (last && last !== '..') {\n result.pop()\n } else if (!isAbsolute) {\n result.push('..')\n }\n continue\n }\n result.push(segment)\n }\n\n if (isAbsolute) {\n return result.length > 0 ? `/${result.join('/')}` : '/'\n }\n return result.length > 0 ? result.join('/') : '.'\n}\n\nexport function toOutputAssetRelPath(\n relPath: string,\n options: OutputAssetPathOptions = {},\n) {\n if (!isTypeScriptAssetPath(relPath)) return relPath\n const normalized = toPosixPath(relPath)\n const { dir, name } = splitPath(normalized)\n const cacheKey = normalizeCacheKey(options.cacheKey)\n const fileName = cacheKey\n ? `${name}.${cacheKey}${JS_EXT}`\n : `${name}${JS_EXT}`\n return dir.length > 0 ? `${dir}/${fileName}` : fileName\n}\n\nfunction normalizeCacheKey(value: string | undefined) {\n const normalized = value?.trim().replaceAll(/[^a-zA-Z0-9_-]/g, '')\n return normalized && normalized.length > 0 ? normalized : undefined\n}\n\nfunction getExtension(filePath: string) {\n const normalized = filePath.replaceAll('\\\\', '/')\n const fileName = normalized.slice(normalized.lastIndexOf('/') + 1)\n const dotIndex = fileName.lastIndexOf('.')\n if (dotIndex <= 0) return ''\n return fileName.slice(dotIndex)\n}\n\nfunction splitPath(filePath: string) {\n const slashIndex = filePath.lastIndexOf('/')\n const dir = slashIndex >= 0 ? filePath.slice(0, slashIndex) : ''\n const base = slashIndex >= 0 ? filePath.slice(slashIndex + 1) : filePath\n const ext = getExtension(base)\n const name = ext.length > 0 ? base.slice(0, -ext.length) : base\n return { dir, name }\n}\n","/**\n * Generates a base class that maps interface properties\n * to the class instance at runtime.\n */\n\nexport function Base<T>() {\n return class {\n constructor(opts: T) {\n Object.assign(this, opts)\n }\n } as new (\n data: T,\n ) => T & { constructor: unknown }\n}\n","type CacheStats = {\n hits: number\n misses: number\n staleHits: number\n evictions: number\n sets: number\n}\n\ntype CacheEntry<V> = {\n value: V\n expiresAt: number | null\n weight: number\n lastAccess: number\n}\n\nexport type CacheOptions<K, V> = {\n name?: string\n maxEntries?: number\n maxWeight?: number\n defaultTtlMs?: number\n allowStale?: boolean\n sizeCalculator?: (value: V, key: K) => number\n onEvict?: (entry: { key: K; value: V; reason: 'max' | 'expired' }) => void\n now?: () => number\n}\n\nexport class Cache<K, V> {\n private readonly name: string\n private readonly allowStale: boolean\n private readonly sizeCalculator: (value: V, key: K) => number\n private readonly onEvict?: CacheOptions<K, V>['onEvict']\n private readonly now: () => number\n private readonly entries = new Map<K, CacheEntry<V>>()\n private readonly inFlight = new Map<K, Promise<V>>()\n private stats: CacheStats = {\n hits: 0,\n misses: 0,\n staleHits: 0,\n evictions: 0,\n sets: 0,\n }\n private maxEntries: number\n private maxWeight: number\n private defaultTtlMs: number\n private totalWeight = 0\n\n constructor(options: CacheOptions<K, V> = {}) {\n this.name = options.name ?? 'cache'\n this.allowStale = options.allowStale ?? false\n this.sizeCalculator = options.sizeCalculator ?? (() => 1)\n this.onEvict = options.onEvict\n this.now = options.now ?? Date.now\n this.maxEntries = Math.max(1, options.maxEntries ?? 1000)\n this.maxWeight = Math.max(1, options.maxWeight ?? Number.MAX_SAFE_INTEGER)\n this.defaultTtlMs = Math.max(0, options.defaultTtlMs ?? 0)\n }\n\n get size() {\n return this.entries.size\n }\n\n get weight() {\n return this.totalWeight\n }\n\n getStats(): CacheStats {\n return { ...this.stats }\n }\n\n setLimits(options: { maxEntries?: number; maxWeight?: number }) {\n if (typeof options.maxEntries === 'number') {\n this.maxEntries = Math.max(1, options.maxEntries)\n }\n if (typeof options.maxWeight === 'number') {\n this.maxWeight = Math.max(1, options.maxWeight)\n }\n this.evictIfNeeded()\n }\n\n setDefaultTtl(ttlMs: number) {\n this.defaultTtlMs = Math.max(0, ttlMs)\n }\n\n has(key: K): boolean {\n const entry = this.entries.get(key)\n if (!entry) return false\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n return false\n }\n return true\n }\n\n peek(key: K): V | undefined {\n const entry = this.entries.get(key)\n if (!entry) return undefined\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n return this.allowStale ? entry.value : undefined\n }\n return entry.value\n }\n\n get(key: K): V | undefined {\n const entry = this.entries.get(key)\n if (!entry) {\n this.stats.misses += 1\n return undefined\n }\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n if (this.allowStale) {\n this.stats.staleHits += 1\n return entry.value\n }\n this.stats.misses += 1\n return undefined\n }\n entry.lastAccess = this.now()\n this.touch(key, entry)\n this.stats.hits += 1\n return entry.value\n }\n\n set(key: K, value: V, ttlMs?: number): V {\n const weight = Math.max(1, this.sizeCalculator(value, key))\n const expiresAt = this.computeExpiry(ttlMs)\n const now = this.now()\n const existing = this.entries.get(key)\n if (existing) {\n this.totalWeight -= existing.weight\n this.entries.delete(key)\n }\n this.entries.set(key, { value, expiresAt, weight, lastAccess: now })\n this.totalWeight += weight\n this.stats.sets += 1\n this.evictIfNeeded()\n return value\n }\n\n delete(key: K): boolean {\n const entry = this.entries.get(key)\n if (!entry) return false\n this.totalWeight -= entry.weight\n this.entries.delete(key)\n return true\n }\n\n clear() {\n this.entries.clear()\n this.inFlight.clear()\n this.totalWeight = 0\n }\n\n async getOrSetAsync(\n key: K,\n loader: () => Promise<V>,\n options?: { ttlMs?: number },\n ): Promise<V> {\n const cached = this.get(key)\n if (cached !== undefined) return cached\n\n const existing = this.inFlight.get(key)\n if (existing) return existing\n\n const promise = loader()\n .then((value) => {\n this.set(key, value, options?.ttlMs)\n this.inFlight.delete(key)\n return value\n })\n .catch((error) => {\n this.inFlight.delete(key)\n throw error\n })\n\n this.inFlight.set(key, promise)\n return promise\n }\n\n pruneExpired() {\n for (const [key, entry] of this.entries) {\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n }\n }\n }\n\n private isExpired(entry: CacheEntry<V>) {\n if (entry.expiresAt === null) return false\n return this.now() >= entry.expiresAt\n }\n\n private computeExpiry(ttlMs?: number) {\n const ttl = typeof ttlMs === 'number' ? ttlMs : this.defaultTtlMs\n if (ttl <= 0) return null\n return this.now() + ttl\n }\n\n private expireEntry(key: K, entry: CacheEntry<V>) {\n this.totalWeight -= entry.weight\n this.entries.delete(key)\n this.stats.evictions += 1\n this.onEvict?.({ key, value: entry.value, reason: 'expired' })\n }\n\n private evictIfNeeded() {\n while (\n this.entries.size > this.maxEntries ||\n this.totalWeight > this.maxWeight\n ) {\n const firstKey = this.entries.keys().next().value as K | undefined\n if (firstKey === undefined) break\n const entry = this.entries.get(firstKey)\n if (!entry) {\n this.entries.delete(firstKey)\n continue\n }\n this.totalWeight -= entry.weight\n this.entries.delete(firstKey)\n this.stats.evictions += 1\n this.onEvict?.({ key: firstKey, value: entry.value, reason: 'max' })\n }\n }\n\n private touch(key: K, entry: CacheEntry<V>) {\n this.entries.delete(key)\n this.entries.set(key, entry)\n }\n}\n","export function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n","/**\n * Escapes &, `<`, `>`, and \" (optionally) in a string for safe insertion into HTML.\n */\nexport function escapeHtml(str: string, escapeQuot = false): string {\n let result = ''\n let last = 0\n\n for (let i = 0; i < str.length; i++) {\n let replacement: string | undefined\n switch (str.charCodeAt(i)) {\n case 38:\n replacement = '&'\n break\n case 60:\n replacement = '<'\n break\n case 62:\n replacement = '>'\n break\n case 34:\n if (escapeQuot) replacement = '"'\n break\n }\n\n if (replacement) {\n if (last < i) {\n result += str.slice(last, i)\n }\n result += replacement\n last = i + 1\n }\n }\n\n if (last === 0) {\n return str\n }\n\n if (last < str.length) {\n result += str.slice(last)\n }\n\n return result\n}\n","export interface LoggerLike {\n error: (msg: string, meta?: Record<string, unknown> | Error) => void\n}\n\nexport function logError(logger: LoggerLike, error: unknown, msg: string) {\n const isError = error instanceof Error\n if (isError) {\n logger.error(msg, error)\n return\n }\n const errorText = String(error)\n logger.error(msg, { error: errorText })\n}\n","export const isString = (value: unknown): value is string =>\n typeof value === 'string' || value instanceof String\n\nexport function isAbortError(err: unknown): boolean {\n const obj = err as Record<string, unknown>\n return (\n obj != null && typeof obj.name === 'string' && obj.name === 'AbortError'\n )\n}\n\nexport function isFunction(\n func: unknown,\n): func is (...args: unknown[]) => unknown {\n return typeof func === 'function'\n}\n\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nexport function isNumberOrBoolean(value: unknown): value is number | boolean {\n return typeof value === 'number' || typeof value === 'boolean'\n}\n\nexport function isEmptyPlainObject(\n value: unknown,\n): value is Record<string, never> {\n if (!isPlainObject(value)) return false\n for (const _ in value) {\n return false\n }\n return true\n}\n\nexport function isError(o: unknown): o is Error {\n return o instanceof Error\n}\n","import { isPlainObject } from './typeCheck'\n\n/**\n * Recursively merges multiple objects into one plain object.\n *\n * Each provided object is iterated in order. If a key exists in multiple objects:\n * - If both the accumulated result and the new value are plain objects, they are merged recursively.\n * - Otherwise, the new value overwrites the previous one.\n *\n * @param objects - A list of objects (or undefined) to merge.\n * @returns A new object containing all merged keys.\n */\nfunction mergeInternal(\n ...objects: Array<Record<string, unknown> | undefined>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const obj of objects) {\n if (!isPlainObject(obj)) continue\n for (const key of Object.keys(obj)) {\n const src = obj[key]\n const prev = result[key]\n if (isPlainObject(prev) && isPlainObject(src)) {\n result[key] = mergeInternal(prev, src)\n } else {\n result[key] = src\n }\n }\n }\n\n return result\n}\n\n/**\n * Deeply merge a base value `T` with any number of partial or full override objects.\n *\n * This function enforces that the base value is a plain object. It merges nested objects\n * recursively and overwrites non-object values or object/primitive mismatches with later overrides.\n *\n * @typeParam T - base type\n * @typeParam K - return type\n * @param base - The base object to merge into. Must be a plain object.\n * @param overrides - Partial or full override objects.\n * Non-object values or undefined entries will simply overwrite or be skipped.\n * @returns The merged result, typed as `K`.\n * @throws If the `base` argument is not a plain object.\n */\nexport function merge<T, K = T>(base: T, ...overrides: Array<unknown>): K {\n if (!isPlainObject(base)) {\n throw new Error(`merge is not possible with ${String(base)}`)\n }\n const merged = mergeInternal(\n base as Record<string, unknown>,\n ...(overrides as Record<string, unknown>[]),\n )\n return merged as K\n}\n","type TrailingSlashMode = 'preserve' | 'always' | 'never'\n\ninterface NormalizeHrefOptions {\n trailingSlash?: TrailingSlashMode\n}\n\nexport const urlNormalizer = {\n isSpecialHref(href: string): boolean {\n return (\n href.startsWith('#') ||\n href.startsWith('?') ||\n href.startsWith('//') ||\n /^[a-zA-Z][a-zA-Z+.-]*:/.test(href)\n )\n },\n\n isExternalHref(href: string): boolean {\n return urlNormalizer.isSpecialHref(href) || href.startsWith('../')\n },\n\n splitSuffix(href: string): { base: string; suffix: string } {\n const hashIndex = href.indexOf('#')\n const queryIndex = href.indexOf('?')\n const index =\n hashIndex === -1\n ? queryIndex\n : queryIndex === -1\n ? hashIndex\n : Math.min(hashIndex, queryIndex)\n if (index === -1) return { base: href, suffix: '' }\n return { base: href.slice(0, index), suffix: href.slice(index) }\n },\n\n normalizeHref(\n value: string | undefined,\n options: NormalizeHrefOptions = {},\n ): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n if (urlNormalizer.isExternalHref(trimmed)) return trimmed\n\n const { base, suffix } = urlNormalizer.splitSuffix(trimmed)\n const withoutDot = base.replace(/^\\.\\/+/, '')\n const withLeadingSlash = withoutDot.startsWith('/')\n ? withoutDot\n : `/${withoutDot}`\n const trailingSlash = options.trailingSlash ?? 'preserve'\n const hasExt = hasPathExtension(withLeadingSlash)\n\n if (hasExt || withLeadingSlash === '/') {\n return `${withLeadingSlash}${suffix}`\n }\n\n if (trailingSlash === 'always' && !withLeadingSlash.endsWith('/')) {\n return `${withLeadingSlash}/${suffix}`\n }\n if (trailingSlash === 'never' && withLeadingSlash.endsWith('/')) {\n return `${withLeadingSlash.slice(0, -1)}${suffix}`\n }\n return `${withLeadingSlash}${suffix}`\n },\n\n normalizeUrlPath(urlPath: string): string {\n const normalized = urlNormalizer.normalizeHref(urlPath, {\n trailingSlash: 'always',\n })\n return normalized || '/'\n },\n\n normalizeInternalPath(value: string | undefined): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed || urlNormalizer.isExternalHref(trimmed)) return undefined\n\n const { base } = urlNormalizer.splitSuffix(trimmed)\n const normalizedBase = base\n .replaceAll('\\\\', '/')\n .replace(/^\\.\\/+/, '')\n .replace(/\\/{2,}/g, '/')\n if (!normalizedBase) return undefined\n if (urlNormalizer.isExternalHref(normalizedBase)) return undefined\n return urlNormalizer.normalizeHref(normalizedBase, {\n trailingSlash: 'always',\n })\n },\n\n hasPathExtension(value: string): boolean {\n return hasPathExtension(value)\n },\n}\n\nfunction hasPathExtension(value: string) {\n const lastSlashIndex = value.lastIndexOf('/')\n const segment = lastSlashIndex >= 0 ? value.slice(lastSlashIndex + 1) : value\n if (!segment || segment === '.' || segment === '..') return false\n const dotIndex = segment.lastIndexOf('.')\n return dotIndex > 0 && dotIndex < segment.length - 1\n}\n","import { normalizePosixPath } from './assetPath'\nimport { urlNormalizer } from './urlNormalizer'\n\nexport function normalizeBasePath(value: string | undefined): string {\n if (typeof value !== 'string') return ''\n const trimmed = value.trim()\n if (!trimmed || trimmed === '/') return ''\n if (urlNormalizer.isSpecialHref(trimmed)) {\n throw new Error(`basePath must be a site path, not \"${value}\".`)\n }\n if (trimmed.includes('?') || trimmed.includes('#')) {\n throw new Error(\n `basePath must not include query or hash parts: \"${value}\".`,\n )\n }\n\n const normalizedSlashes = trimmed.replaceAll('\\\\', '/')\n const withLeadingSlash = normalizedSlashes.startsWith('/')\n ? normalizedSlashes\n : `/${normalizedSlashes}`\n const segments = withLeadingSlash.split('/').filter(Boolean)\n if (segments.some((segment) => segment === '.' || segment === '..')) {\n throw new Error(`basePath must stay inside the site root: \"${value}\".`)\n }\n\n const normalized = normalizePosixPath(withLeadingSlash).replace(/\\/+$/, '')\n return normalized === '/' ? '' : normalized\n}\n\nexport function withBasePath(basePath: string, href: string): string {\n const normalizedBasePath = normalizeBasePath(basePath)\n if (!normalizedBasePath) return href\n if (!href || href.trim() !== href) return href\n if (urlNormalizer.isSpecialHref(href)) return href\n if (!href.startsWith('/')) return href\n\n const { base, suffix } = urlNormalizer.splitSuffix(href)\n if (base === normalizedBasePath) return `${base}${suffix}`\n if (base.startsWith(`${normalizedBasePath}/`)) return `${base}${suffix}`\n if (base === '/') return `${normalizedBasePath}/${suffix}`\n return `${normalizedBasePath}${base}${suffix}`\n}\n\nexport function stripBasePath(basePath: string, pathname: string): string {\n const normalizedBasePath = normalizeBasePath(basePath)\n if (!normalizedBasePath) return pathname\n if (pathname === normalizedBasePath) return '/'\n if (pathname.startsWith(`${normalizedBasePath}/`)) {\n return pathname.slice(normalizedBasePath.length) || '/'\n }\n return pathname\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ts-util.mjs","names":[],"sources":["../src/assetPath.ts","../src/base.ts","../src/cache.ts","../src/clamp.ts","../src/typeCheck.ts","../src/clonePlainData.ts","../src/escapeHtml.ts","../src/logging.ts","../src/merge.ts","../src/urlNormalizer.ts","../src/publicPath.ts"],"sourcesContent":["// Keep these helpers browser-safe so components like PageScript can reuse them\n// without pulling in Node-only modules such as node:path.\nconst TS_EXT = '.ts'\nconst JS_EXT = '.js'\n\nexport interface OutputAssetPathOptions {\n cacheKey?: string\n}\n\nexport function isTypeScriptAssetPath(filePath: string) {\n return getExtension(filePath).toLowerCase() === TS_EXT\n}\n\nexport function toPosixPath(filePath: string) {\n return filePath.replaceAll('\\\\', '/')\n}\n\nexport function dirnamePosix(filePath: string) {\n const normalized = toPosixPath(filePath)\n const slashIndex = normalized.lastIndexOf('/')\n if (slashIndex < 0) return '.'\n if (slashIndex === 0) return '/'\n return normalized.slice(0, slashIndex)\n}\n\nexport function joinPosix(...parts: string[]) {\n const filtered = parts.filter((part) => part.length > 0)\n return normalizePosixPath(filtered.join('/'))\n}\n\nexport function normalizePosixPath(filePath: string) {\n const normalized = toPosixPath(filePath)\n const isAbsolute = normalized.startsWith('/')\n const segments = normalized.split('/')\n const result: string[] = []\n\n for (const segment of segments) {\n if (segment.length === 0 || segment === '.') continue\n if (segment === '..') {\n const last = result[result.length - 1]\n if (last && last !== '..') {\n result.pop()\n } else if (!isAbsolute) {\n result.push('..')\n }\n continue\n }\n result.push(segment)\n }\n\n if (isAbsolute) {\n return result.length > 0 ? `/${result.join('/')}` : '/'\n }\n return result.length > 0 ? result.join('/') : '.'\n}\n\nexport function toOutputAssetRelPath(\n relPath: string,\n options: OutputAssetPathOptions = {},\n) {\n if (!isTypeScriptAssetPath(relPath)) return relPath\n const normalized = toPosixPath(relPath)\n const { dir, name } = splitPath(normalized)\n const cacheKey = normalizeCacheKey(options.cacheKey)\n const fileName = cacheKey\n ? `${name}.${cacheKey}${JS_EXT}`\n : `${name}${JS_EXT}`\n return dir.length > 0 ? `${dir}/${fileName}` : fileName\n}\n\nfunction normalizeCacheKey(value: string | undefined) {\n const normalized = value?.trim().replaceAll(/[^a-zA-Z0-9_-]/g, '')\n return normalized && normalized.length > 0 ? normalized : undefined\n}\n\nfunction getExtension(filePath: string) {\n const normalized = filePath.replaceAll('\\\\', '/')\n const fileName = normalized.slice(normalized.lastIndexOf('/') + 1)\n const dotIndex = fileName.lastIndexOf('.')\n if (dotIndex <= 0) return ''\n return fileName.slice(dotIndex)\n}\n\nfunction splitPath(filePath: string) {\n const slashIndex = filePath.lastIndexOf('/')\n const dir = slashIndex >= 0 ? filePath.slice(0, slashIndex) : ''\n const base = slashIndex >= 0 ? filePath.slice(slashIndex + 1) : filePath\n const ext = getExtension(base)\n const name = ext.length > 0 ? base.slice(0, -ext.length) : base\n return { dir, name }\n}\n","/**\n * Generates a base class that maps interface properties\n * to the class instance at runtime.\n */\n\nexport function Base<T>() {\n return class {\n constructor(opts: T) {\n Object.assign(this, opts)\n }\n } as new (\n data: T,\n ) => T & { constructor: unknown }\n}\n","type CacheStats = {\n hits: number\n misses: number\n staleHits: number\n evictions: number\n sets: number\n}\n\ntype CacheEntry<V> = {\n value: V\n expiresAt: number | null\n weight: number\n lastAccess: number\n}\n\nexport type CacheOptions<K, V> = {\n name?: string\n maxEntries?: number\n maxWeight?: number\n defaultTtlMs?: number\n allowStale?: boolean\n sizeCalculator?: (value: V, key: K) => number\n onEvict?: (entry: { key: K; value: V; reason: 'max' | 'expired' }) => void\n now?: () => number\n}\n\nexport class Cache<K, V> {\n private readonly name: string\n private readonly allowStale: boolean\n private readonly sizeCalculator: (value: V, key: K) => number\n private readonly onEvict?: CacheOptions<K, V>['onEvict']\n private readonly now: () => number\n private readonly entries = new Map<K, CacheEntry<V>>()\n private readonly inFlight = new Map<K, Promise<V>>()\n private stats: CacheStats = {\n hits: 0,\n misses: 0,\n staleHits: 0,\n evictions: 0,\n sets: 0,\n }\n private maxEntries: number\n private maxWeight: number\n private defaultTtlMs: number\n private totalWeight = 0\n\n constructor(options: CacheOptions<K, V> = {}) {\n this.name = options.name ?? 'cache'\n this.allowStale = options.allowStale ?? false\n this.sizeCalculator = options.sizeCalculator ?? (() => 1)\n this.onEvict = options.onEvict\n this.now = options.now ?? Date.now\n this.maxEntries = Math.max(1, options.maxEntries ?? 1000)\n this.maxWeight = Math.max(1, options.maxWeight ?? Number.MAX_SAFE_INTEGER)\n this.defaultTtlMs = Math.max(0, options.defaultTtlMs ?? 0)\n }\n\n get size() {\n return this.entries.size\n }\n\n get weight() {\n return this.totalWeight\n }\n\n getStats(): CacheStats {\n return { ...this.stats }\n }\n\n setLimits(options: { maxEntries?: number; maxWeight?: number }) {\n if (typeof options.maxEntries === 'number') {\n this.maxEntries = Math.max(1, options.maxEntries)\n }\n if (typeof options.maxWeight === 'number') {\n this.maxWeight = Math.max(1, options.maxWeight)\n }\n this.evictIfNeeded()\n }\n\n setDefaultTtl(ttlMs: number) {\n this.defaultTtlMs = Math.max(0, ttlMs)\n }\n\n has(key: K): boolean {\n const entry = this.entries.get(key)\n if (!entry) return false\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n return false\n }\n return true\n }\n\n peek(key: K): V | undefined {\n const entry = this.entries.get(key)\n if (!entry) return undefined\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n return this.allowStale ? entry.value : undefined\n }\n return entry.value\n }\n\n get(key: K): V | undefined {\n const entry = this.entries.get(key)\n if (!entry) {\n this.stats.misses += 1\n return undefined\n }\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n if (this.allowStale) {\n this.stats.staleHits += 1\n return entry.value\n }\n this.stats.misses += 1\n return undefined\n }\n entry.lastAccess = this.now()\n this.touch(key, entry)\n this.stats.hits += 1\n return entry.value\n }\n\n set(key: K, value: V, ttlMs?: number): V {\n const weight = Math.max(1, this.sizeCalculator(value, key))\n const expiresAt = this.computeExpiry(ttlMs)\n const now = this.now()\n const existing = this.entries.get(key)\n if (existing) {\n this.totalWeight -= existing.weight\n this.entries.delete(key)\n }\n this.entries.set(key, { value, expiresAt, weight, lastAccess: now })\n this.totalWeight += weight\n this.stats.sets += 1\n this.evictIfNeeded()\n return value\n }\n\n delete(key: K): boolean {\n const entry = this.entries.get(key)\n if (!entry) return false\n this.totalWeight -= entry.weight\n this.entries.delete(key)\n return true\n }\n\n clear() {\n this.entries.clear()\n this.inFlight.clear()\n this.totalWeight = 0\n }\n\n async getOrSetAsync(\n key: K,\n loader: () => Promise<V>,\n options?: { ttlMs?: number },\n ): Promise<V> {\n const cached = this.get(key)\n if (cached !== undefined) return cached\n\n const existing = this.inFlight.get(key)\n if (existing) return existing\n\n const promise = loader()\n .then((value) => {\n this.set(key, value, options?.ttlMs)\n this.inFlight.delete(key)\n return value\n })\n .catch((error) => {\n this.inFlight.delete(key)\n throw error\n })\n\n this.inFlight.set(key, promise)\n return promise\n }\n\n pruneExpired() {\n for (const [key, entry] of this.entries) {\n if (this.isExpired(entry)) {\n this.expireEntry(key, entry)\n }\n }\n }\n\n private isExpired(entry: CacheEntry<V>) {\n if (entry.expiresAt === null) return false\n return this.now() >= entry.expiresAt\n }\n\n private computeExpiry(ttlMs?: number) {\n const ttl = typeof ttlMs === 'number' ? ttlMs : this.defaultTtlMs\n if (ttl <= 0) return null\n return this.now() + ttl\n }\n\n private expireEntry(key: K, entry: CacheEntry<V>) {\n this.totalWeight -= entry.weight\n this.entries.delete(key)\n this.stats.evictions += 1\n this.onEvict?.({ key, value: entry.value, reason: 'expired' })\n }\n\n private evictIfNeeded() {\n while (\n this.entries.size > this.maxEntries ||\n this.totalWeight > this.maxWeight\n ) {\n const firstKey = this.entries.keys().next().value as K | undefined\n if (firstKey === undefined) break\n const entry = this.entries.get(firstKey)\n if (!entry) {\n this.entries.delete(firstKey)\n continue\n }\n this.totalWeight -= entry.weight\n this.entries.delete(firstKey)\n this.stats.evictions += 1\n this.onEvict?.({ key: firstKey, value: entry.value, reason: 'max' })\n }\n }\n\n private touch(key: K, entry: CacheEntry<V>) {\n this.entries.delete(key)\n this.entries.set(key, entry)\n }\n}\n","export function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n","export const isString = (value: unknown): value is string =>\n typeof value === 'string' || value instanceof String\n\nexport function isAbortError(err: unknown): boolean {\n const obj = err as Record<string, unknown>\n return (\n obj != null && typeof obj.name === 'string' && obj.name === 'AbortError'\n )\n}\n\nexport function isFunction(\n func: unknown,\n): func is (...args: unknown[]) => unknown {\n return typeof func === 'function'\n}\n\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nexport function isNumberOrBoolean(value: unknown): value is number | boolean {\n return typeof value === 'number' || typeof value === 'boolean'\n}\n\nexport function isEmptyPlainObject(\n value: unknown,\n): value is Record<string, never> {\n if (!isPlainObject(value)) return false\n for (const _ in value) {\n return false\n }\n return true\n}\n\nexport function isError(o: unknown): o is Error {\n return o instanceof Error\n}\n","import { isPlainObject } from './typeCheck'\n\n/** Copies arrays and plain objects recursively, retaining callbacks and other values. */\nexport function clonePlainData<T>(value: T): T {\n if (Array.isArray(value)) return value.map(clonePlainData) as T\n if (isPlainObject(value))\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, clonePlainData(item)]),\n ) as T\n return value\n}\n","/**\n * Escapes &, `<`, `>`, and \" (optionally) in a string for safe insertion into HTML.\n */\nexport function escapeHtml(str: string, escapeQuot = false): string {\n let result = ''\n let last = 0\n\n for (let i = 0; i < str.length; i++) {\n let replacement: string | undefined\n switch (str.charCodeAt(i)) {\n case 38:\n replacement = '&'\n break\n case 60:\n replacement = '<'\n break\n case 62:\n replacement = '>'\n break\n case 34:\n if (escapeQuot) replacement = '"'\n break\n }\n\n if (replacement) {\n if (last < i) {\n result += str.slice(last, i)\n }\n result += replacement\n last = i + 1\n }\n }\n\n if (last === 0) {\n return str\n }\n\n if (last < str.length) {\n result += str.slice(last)\n }\n\n return result\n}\n","export interface LoggerLike {\n error: (msg: string, meta?: Record<string, unknown> | Error) => void\n}\n\nexport function logError(logger: LoggerLike, error: unknown, msg: string) {\n const isError = error instanceof Error\n if (isError) {\n logger.error(msg, error)\n return\n }\n const errorText = String(error)\n logger.error(msg, { error: errorText })\n}\n","import { isPlainObject } from './typeCheck'\n\n/**\n * Recursively merges multiple objects into one plain object.\n *\n * Each provided object is iterated in order. If a key exists in multiple objects:\n * - If both the accumulated result and the new value are plain objects, they are merged recursively.\n * - Otherwise, the new value overwrites the previous one.\n *\n * @param objects - A list of objects (or undefined) to merge.\n * @returns A new object containing all merged keys.\n */\nfunction mergeInternal(\n ...objects: Array<Record<string, unknown> | undefined>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const obj of objects) {\n if (!isPlainObject(obj)) continue\n for (const key of Object.keys(obj)) {\n const src = obj[key]\n const prev = result[key]\n if (isPlainObject(prev) && isPlainObject(src)) {\n result[key] = mergeInternal(prev, src)\n } else {\n result[key] = src\n }\n }\n }\n\n return result\n}\n\n/**\n * Deeply merge a base value `T` with any number of partial or full override objects.\n *\n * This function enforces that the base value is a plain object. It merges nested objects\n * recursively and overwrites non-object values or object/primitive mismatches with later overrides.\n *\n * @typeParam T - base type\n * @typeParam K - return type\n * @param base - The base object to merge into. Must be a plain object.\n * @param overrides - Partial or full override objects.\n * Non-object values or undefined entries will simply overwrite or be skipped.\n * @returns The merged result, typed as `K`.\n * @throws If the `base` argument is not a plain object.\n */\nexport function merge<T, K = T>(base: T, ...overrides: Array<unknown>): K {\n if (!isPlainObject(base)) {\n throw new Error(`merge is not possible with ${String(base)}`)\n }\n const merged = mergeInternal(\n base as Record<string, unknown>,\n ...(overrides as Record<string, unknown>[]),\n )\n return merged as K\n}\n","type TrailingSlashMode = 'preserve' | 'always' | 'never'\n\ninterface NormalizeHrefOptions {\n trailingSlash?: TrailingSlashMode\n}\n\nexport const urlNormalizer = {\n isSpecialHref(href: string): boolean {\n return (\n href.startsWith('#') ||\n href.startsWith('?') ||\n href.startsWith('//') ||\n /^[a-zA-Z][a-zA-Z+.-]*:/.test(href)\n )\n },\n\n isExternalHref(href: string): boolean {\n return urlNormalizer.isSpecialHref(href) || href.startsWith('../')\n },\n\n splitSuffix(href: string): { base: string; suffix: string } {\n const hashIndex = href.indexOf('#')\n const queryIndex = href.indexOf('?')\n const index =\n hashIndex === -1\n ? queryIndex\n : queryIndex === -1\n ? hashIndex\n : Math.min(hashIndex, queryIndex)\n if (index === -1) return { base: href, suffix: '' }\n return { base: href.slice(0, index), suffix: href.slice(index) }\n },\n\n normalizeHref(\n value: string | undefined,\n options: NormalizeHrefOptions = {},\n ): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n if (urlNormalizer.isExternalHref(trimmed)) return trimmed\n\n const { base, suffix } = urlNormalizer.splitSuffix(trimmed)\n const withoutDot = base.replace(/^\\.\\/+/, '')\n const withLeadingSlash = withoutDot.startsWith('/')\n ? withoutDot\n : `/${withoutDot}`\n const trailingSlash = options.trailingSlash ?? 'preserve'\n const hasExt = hasPathExtension(withLeadingSlash)\n\n if (hasExt || withLeadingSlash === '/') {\n return `${withLeadingSlash}${suffix}`\n }\n\n if (trailingSlash === 'always' && !withLeadingSlash.endsWith('/')) {\n return `${withLeadingSlash}/${suffix}`\n }\n if (trailingSlash === 'never' && withLeadingSlash.endsWith('/')) {\n return `${withLeadingSlash.slice(0, -1)}${suffix}`\n }\n return `${withLeadingSlash}${suffix}`\n },\n\n normalizeUrlPath(urlPath: string): string {\n const normalized = urlNormalizer.normalizeHref(urlPath, {\n trailingSlash: 'always',\n })\n return normalized || '/'\n },\n\n normalizeInternalPath(value: string | undefined): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed || urlNormalizer.isExternalHref(trimmed)) return undefined\n\n const { base } = urlNormalizer.splitSuffix(trimmed)\n const normalizedBase = base\n .replaceAll('\\\\', '/')\n .replace(/^\\.\\/+/, '')\n .replace(/\\/{2,}/g, '/')\n if (!normalizedBase) return undefined\n if (urlNormalizer.isExternalHref(normalizedBase)) return undefined\n return urlNormalizer.normalizeHref(normalizedBase, {\n trailingSlash: 'always',\n })\n },\n\n hasPathExtension(value: string): boolean {\n return hasPathExtension(value)\n },\n}\n\nfunction hasPathExtension(value: string) {\n const lastSlashIndex = value.lastIndexOf('/')\n const segment = lastSlashIndex >= 0 ? value.slice(lastSlashIndex + 1) : value\n if (!segment || segment === '.' || segment === '..') return false\n const dotIndex = segment.lastIndexOf('.')\n return dotIndex > 0 && dotIndex < segment.length - 1\n}\n","import { normalizePosixPath } from './assetPath'\nimport { urlNormalizer } from './urlNormalizer'\n\nexport function normalizeBasePath(value: string | undefined): string {\n if (typeof value !== 'string') return ''\n const trimmed = value.trim()\n if (!trimmed || trimmed === '/') return ''\n if (urlNormalizer.isSpecialHref(trimmed)) {\n throw new Error(`basePath must be a site path, not \"${value}\".`)\n }\n if (trimmed.includes('?') || trimmed.includes('#')) {\n throw new Error(\n `basePath must not include query or hash parts: \"${value}\".`,\n )\n }\n\n const normalizedSlashes = trimmed.replaceAll('\\\\', '/')\n const withLeadingSlash = normalizedSlashes.startsWith('/')\n ? normalizedSlashes\n : `/${normalizedSlashes}`\n const segments = withLeadingSlash.split('/').filter(Boolean)\n if (segments.some((segment) => segment === '.' || segment === '..')) {\n throw new Error(`basePath must stay inside the site root: \"${value}\".`)\n }\n\n const normalized = normalizePosixPath(withLeadingSlash).replace(/\\/+$/, '')\n return normalized === '/' ? '' : normalized\n}\n\nexport function withBasePath(basePath: string, href: string): string {\n const normalizedBasePath = normalizeBasePath(basePath)\n if (!normalizedBasePath) return href\n if (!href || href.trim() !== href) return href\n if (urlNormalizer.isSpecialHref(href)) return href\n if (!href.startsWith('/')) return href\n\n const { base, suffix } = urlNormalizer.splitSuffix(href)\n if (base === normalizedBasePath) return `${base}${suffix}`\n if (base.startsWith(`${normalizedBasePath}/`)) return `${base}${suffix}`\n if (base === '/') return `${normalizedBasePath}/${suffix}`\n return `${normalizedBasePath}${base}${suffix}`\n}\n\nexport function stripBasePath(basePath: string, pathname: string): string {\n const normalizedBasePath = normalizeBasePath(basePath)\n if (!normalizedBasePath) return pathname\n if (pathname === normalizedBasePath) return '/'\n if (pathname.startsWith(`${normalizedBasePath}/`)) {\n return pathname.slice(normalizedBasePath.length) || '/'\n }\n return pathname\n}\n"],"mappings":"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"}
|