feat: context menu to copy clean/short Ali links

This commit is contained in:
automation 2025-09-10 10:12:27 -04:00
parent a24b476d06
commit 84304be7da
5 changed files with 112 additions and 2 deletions

105
background.js Normal file
View File

@ -0,0 +1,105 @@
/* global chrome, browser */
const API = typeof chrome !== "undefined" ? chrome : browser;
function canonicalizeAliExpress(urlString) {
const url = new URL(urlString);
const path = url.pathname;
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`;
return `https://${canonicalHost}${path}`;
}
function canonicalizeAlibaba(urlString) {
const url = new URL(urlString);
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) };
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();
}
function createMenus() {
try { API.contextMenus.removeAll(() => {}); } catch (e) {}
API.contextMenus.create({
id: "ali-clean",
title: "Copy clean Ali link",
contexts: ["page", "selection", "link"],
documentUrlPatterns: [
"*://*.aliexpress.*/*",
"*://*.alibaba.*/*"
]
});
API.contextMenus.create({
id: "ali-shorten",
title: "Copy short Ali link",
contexts: ["page", "selection", "link"],
documentUrlPatterns: [
"*://*.aliexpress.*/*",
"*://*.alibaba.*/*"
]
});
}
async function getRelevantUrl(info, tab) {
if (info.linkUrl) return info.linkUrl;
return tab && tab.url ? tab.url : null;
}
async function copyTextToClipboard(tabId, text) {
// Using scripting to execute in page context for broad compatibility
const code = `navigator.clipboard.writeText(${JSON.stringify(text)}).then(() => true).catch(() => false);`;
try {
const results = await API.scripting.executeScript({
target: { tabId },
func: (t) => navigator.clipboard.writeText(t).then(() => true).catch(() => false),
args: [text]
});
const ok = results && results[0] && results[0].result;
return !!ok;
} catch (e) {
return false;
}
}
API.runtime.onInstalled && API.runtime.onInstalled.addListener(() => {
createMenus();
});
API.contextMenus.onClicked.addListener(async (info, tab) => {
if (!tab || !tab.id) return;
const rawUrl = await getRelevantUrl(info, tab);
if (!rawUrl) return;
const { url } = canonicalize(rawUrl);
if (info.menuItemId === "ali-clean") {
await copyTextToClipboard(tab.id, url);
} else if (info.menuItemId === "ali-shorten") {
try {
const shortUrl = await shortenWithIsGd(url);
await copyTextToClipboard(tab.id, shortUrl);
} catch (e) {
await copyTextToClipboard(tab.id, url);
}
}
});

View File

@ -19,7 +19,7 @@ cleanup() {
trap cleanup EXIT trap cleanup EXIT
# Common files # Common files
for f in manifest.json popup.html popup.js; do for f in manifest.json popup.html popup.js background.js; do
cp "$ROOT_DIR/$f" "$WORK_CHROME/" cp "$ROOT_DIR/$f" "$WORK_CHROME/"
cp "$ROOT_DIR/$f" "$WORK_FIREFOX/" cp "$ROOT_DIR/$f" "$WORK_FIREFOX/"
done done

Binary file not shown.

Binary file not shown.

View File

@ -3,6 +3,9 @@
"name": "Ali Sharelink", "name": "Ali Sharelink",
"version": "0.1.0", "version": "0.1.0",
"description": "Get a clean, canonical share link for AliExpress/Alibaba products, with optional shortlink.", "description": "Get a clean, canonical share link for AliExpress/Alibaba products, with optional shortlink.",
"background": {
"service_worker": "background.js"
},
"action": { "action": {
"default_title": "Ali Sharelink", "default_title": "Ali Sharelink",
"default_popup": "popup.html" "default_popup": "popup.html"
@ -10,7 +13,9 @@
"permissions": [ "permissions": [
"activeTab", "activeTab",
"tabs", "tabs",
"clipboardWrite" "clipboardWrite",
"contextMenus",
"scripting"
], ],
"host_permissions": [ "host_permissions": [
"https://is.gd/*" "https://is.gd/*"