/* global chrome, browser */ (function () { const $ = (id) => document.getElementById(id); const statusEl = $("status"); function setStatus(message, kind) { statusEl.textContent = message || ""; statusEl.className = `row small ${kind === "error" ? "error" : kind === "ok" ? "ok" : "muted"}`; } function getApi() { if (typeof chrome !== "undefined" && chrome.tabs) return chrome; if (typeof browser !== "undefined" && browser.tabs) return browser; throw new Error("Unsupported browser API"); } function tabsQuery(api, queryInfo) { // chrome: callback-based, firefox: promise-based return new Promise((resolve, reject) => { try { const maybePromise = api.tabs.query(queryInfo, (tabs) => { if (chrome && chrome.runtime && chrome.runtime.lastError) { reject(chrome.runtime.lastError); } else if (tabs) { resolve(tabs); } }); if (maybePromise && typeof maybePromise.then === "function") { maybePromise.then(resolve, reject); } } catch (e) { reject(e); } }); } function copyToClipboard(text) { return navigator.clipboard.writeText(text); } function canonicalizeAliExpress(urlString) { const url = new URL(urlString); const host = url.hostname; const path = url.pathname; // Prefer global .com canonical const canonicalHost = "www.aliexpress.com"; let productId = null; const itemMatch = path.match(/\/(item|i)\/(\d+)\.html/i); if (itemMatch) { productId = itemMatch[2]; } if (!productId) { const xObjectId = url.searchParams.get("x_object_id") || url.searchParams.get("item_id"); if (xObjectId && /^\d+$/.test(xObjectId)) { productId = xObjectId; } } if (productId) { return `https://${canonicalHost}/item/${productId}.html`; } // Fallback: strip params and hash return `https://${canonicalHost}${path}`; } function canonicalizeAlibaba(urlString) { const url = new URL(urlString); // Keep origin + pathname only return `${url.origin}${url.pathname}`; } function canonicalize(urlString) { const url = new URL(urlString); const hostname = url.hostname.toLowerCase(); if (hostname.includes("aliexpress.")) { return { vendor: "AliExpress", url: canonicalizeAliExpress(urlString) }; } if (hostname.includes("alibaba.")) { return { vendor: "Alibaba", url: canonicalizeAlibaba(urlString) }; } // Unknown: just strip params/hash return { vendor: "Unknown", url: `${url.origin}${url.pathname}` }; } async function shortenWithIsGd(longUrl) { const endpoint = `https://is.gd/create.php?format=simple&url=${encodeURIComponent(longUrl)}`; const res = await fetch(endpoint, { method: "GET" }); const text = await res.text(); if (!res.ok) throw new Error(text || `Shorten failed (${res.status})`); if (!/^https?:\/\//i.test(text)) throw new Error(text || "Shorten failed"); return text.trim(); } async function init() { setStatus("Reading current tab…"); const api = getApi(); try { const tabs = await tabsQuery(api, { active: true, currentWindow: true }); const active = tabs && tabs[0]; if (!active || !active.url) { setStatus("No active tab URL found", "error"); return; } $("currentUrl").value = active.url; const { vendor, url } = canonicalize(active.url); $("cleanUrl").value = url; setStatus(`Detected ${vendor}. Clean link ready.`, "ok"); $("copyClean").addEventListener("click", async () => { try { await copyToClipboard($("cleanUrl").value); setStatus("Clean link copied.", "ok"); } catch (e) { setStatus(`Copy failed: ${e.message}`, "error"); } }); $("shortenCopy").addEventListener("click", async () => { setStatus("Shortening with is.gd…"); try { const shortUrl = await shortenWithIsGd($("cleanUrl").value); await copyToClipboard(shortUrl); setStatus("Short link copied.", "ok"); } catch (e) { setStatus(`Shorten failed: ${e.message}`, "error"); } }); } catch (e) { setStatus(`Error: ${e.message}`, "error"); } } document.addEventListener("DOMContentLoaded", init); })();