function createMenuItem() { browser.contextMenus.create({ id: "copy-image-as-link", title: "Copy Image As Link", contexts: ["image"] }); } createMenuItem(); browser.runtime.onMessage.addListener(notify); let lastMessage = {}; function notify(message) { lastMessage = message; // TODO - this only works the next time :-( //browser.contextMenus.update("copy-image-as-link", {'enabled': message['showImageAsLinkMenuItem']}); /*browser.contextMenus.remove("copy-image-as-link").then(() => { if (message['showImageAsLinkMenuItem']) { createMenuItem(); } });*/ } browser.contextMenus.onClicked.addListener((info, tab) => { if (info.menuItemId == "copy-image-as-link" && lastMessage.altText !== undefined && lastMessage.altText != "") { let imgSrc = info.srcUrl; let linkUrl = info.linkUrl; let safeImgSrc = escapeHTML(imgSrc); let safeLinkUrl = escapeHTML(linkUrl); let altText = escapeHTML(lastMessage.altText); let height = lastMessage.height; let width = lastMessage.width; const html = `${altText}`; // https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/background.js // The example will show how data can be copied, but since background // pages cannot directly write to the clipboard, we will run a content // script that copies the actual content. // clipboard-helper.js defines function copyToClipboard. const code = "copyToClipboard(" + JSON.stringify(html) + ");"; browser.tabs.executeScript({ code: "typeof copyToClipboard === 'function';", }).then((results) => { // The content script's last expression will be true if the function // has been defined. If this is not the case, then we need to run // clipboard-helper.js to define function copyToClipboard. if (!results || results[0] !== true) { return browser.tabs.executeScript(tab.id, { file: "clipboard-helper.js", }); } }).then(() => { return browser.tabs.executeScript(tab.id, { code, }); }).catch((error) => { // This could happen if the extension is not allowed to run code in // the page, for example if the tab is a privileged page. console.error("Failed to copy text: " + error); }); } }); // https://gist.github.com/Rob--W/ec23b9d6db9e56b7e4563f1544e0d546 function escapeHTML(str) { // Note: string cast using String; may throw if `str` is non-serializable, e.g. a Symbol. // Most often this is not the case though. return String(str) .replace(/&/g, "&") .replace(/"/g, """).replace(/'/g, "'") .replace(//g, ">"); }