初始化项目
This commit is contained in:
49
packages/shared/src/index.js
Normal file
49
packages/shared/src/index.js
Normal file
@@ -0,0 +1,49 @@
|
||||
export function normalizeUrl(input) {
|
||||
try {
|
||||
const url = new URL(input);
|
||||
url.hash = "";
|
||||
|
||||
url.protocol = url.protocol.toLowerCase();
|
||||
url.hostname = url.hostname.toLowerCase();
|
||||
|
||||
// Remove default ports
|
||||
if ((url.protocol === "http:" && url.port === "80") || (url.protocol === "https:" && url.port === "443")) {
|
||||
url.port = "";
|
||||
}
|
||||
|
||||
// Trim trailing slash on pathname (but keep root '/')
|
||||
if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
|
||||
url.pathname = url.pathname.slice(0, -1);
|
||||
}
|
||||
|
||||
// Drop common tracking params
|
||||
const trackingPrefixes = ["utm_", "spm", "gclid", "fbclid"];
|
||||
for (const key of [...url.searchParams.keys()]) {
|
||||
const lowerKey = key.toLowerCase();
|
||||
if (trackingPrefixes.some((p) => lowerKey.startsWith(p))) {
|
||||
url.searchParams.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort params for stable output
|
||||
const sorted = [...url.searchParams.entries()].sort(([a], [b]) => a.localeCompare(b));
|
||||
url.search = "";
|
||||
for (const [k, v] of sorted) url.searchParams.append(k, v);
|
||||
|
||||
return url.toString();
|
||||
} catch {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
export function computeUrlHash(normalizedUrl) {
|
||||
// Lightweight hash (non-crypto) for dedupe key; server may replace with crypto later.
|
||||
let hash = 2166136261;
|
||||
for (let i = 0; i < normalizedUrl.length; i++) {
|
||||
hash ^= normalizedUrl.charCodeAt(i);
|
||||
hash = Math.imul(hash, 16777619);
|
||||
}
|
||||
return (hash >>> 0).toString(16);
|
||||
}
|
||||
|
||||
export { parseNetscapeBookmarkHtml } from "./bookmarkHtml.js";
|
||||
Reference in New Issue
Block a user