diff --git a/README.md b/README.md index 389fae0..98b9e97 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,11 @@ yarn test-only yarn test ``` +### Known Issues + +- ContextMenu will be shown on all editable fields, but will work only on textarea +- Elements present inside iframe can't be formatted + ## Help We would love your [help](https://github.com/prettier/prettier-browser-extension/issues) :) diff --git a/src/background/index.js b/src/background/index.js index 382c631..f8350e3 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,20 +1,42 @@ import browser from "webextension-polyfill"; -browser.commands.onCommand.addListener((command) => { +const menuItemId = "prettier-format"; + +const menuItem = { + contexts: ["editable"], + id: menuItemId, + title: "Format with Prettier", +}; + +const format = async (tab) => { + try { + await browser.tabs.sendMessage(tab.id, { action: "runPrettierFormat" }); + } catch (err) { + console.error("Error occurred while sending message to tab.", err); + } +}; + +browser.commands.onCommand.addListener((command, tab) => { if (command !== "run-prettier-format") { return; } - browser.tabs - .query({ active: true, currentWindow: true }) - .then((tabs) => - Promise.all( - tabs.map((tab) => - browser.tabs.sendMessage(tab.id, { action: "runPrettierFormat" }) - ) - ) - ) - .catch((err) => { - console.error("Error occurred while sending message to tab.", err); - }); + format(tab); +}); + +browser.contextMenus.onClicked.addListener((info, tab) => { + if (info.menuItemId == menuItemId) { + format(tab); + } }); + +const createContextMenu = async () => { + try { + await browser.contextMenus.removeAll(); + await browser.contextMenus.create(menuItem); + } catch (err) { + console.log("Error while creating context menu", err); + } +}; + +createContextMenu(); diff --git a/src/content/extension.js b/src/content/extension.js index 81349f1..d3fb47e 100644 --- a/src/content/extension.js +++ b/src/content/extension.js @@ -1,5 +1,6 @@ import browser from "webextension-polyfill"; import prettier from "prettier/standalone"; + import Storage from "./storage"; import { PARSERS, PARSERS_LANG_MAP } from "./parsers"; @@ -11,6 +12,7 @@ const STACKEXCHANGE_SITES = [ "https://stackapps.com", "https://superuser.com", ]; + const STACKEXCHANGE_URL_REGEX = /^https:\/\/([a-z]+).stackexchange.com/; const STACKEXCHANGE_VALID_PATHNAMES = /(^\/questions|\/posts\/\d+\/edit|^\/review)/u; diff --git a/src/dev-manifest.json b/src/dev-manifest.json new file mode 100644 index 0000000..e3a05e2 --- /dev/null +++ b/src/dev-manifest.json @@ -0,0 +1,3 @@ +{ + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" +} diff --git a/src/manifest.json b/src/manifest.json index cf2446e..59e7a62 100755 --- a/src/manifest.json +++ b/src/manifest.json @@ -17,7 +17,7 @@ "description": "Format using Prettier" } }, - "permissions": ["storage"], + "permissions": ["storage", "contextMenus", "activeTab"], "content_scripts": [ { "matches": [""], diff --git a/src/prod-manifest.json b/src/prod-manifest.json new file mode 100644 index 0000000..4f8b0ab --- /dev/null +++ b/src/prod-manifest.json @@ -0,0 +1,3 @@ +{ + "content_security_policy": "script-src 'self'; object-src 'self'" +} diff --git a/webpack.config.js b/webpack.config.js index 0765990..ec2a697 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,8 +20,8 @@ module.exports = ({ outDir, env }) => { background: "./src/background/index.js", content: "./src/content/index.js", options: isDevMode - ? ["react-devtools", "./src/options/index.js"] - : "./src/options/index.js", + ? ["react-devtools", "./src/options"] + : "./src/options", }, mode: env, module: { @@ -85,6 +85,7 @@ module.exports = ({ outDir, env }) => { files: [ "src/manifest.json", isFirefox && "src/firefox-manifest.json", + `src/${isDevMode ? "dev" : "prod"}-manifest.json`, ].filter(Boolean), to: "manifest.json", transform: (manifest) => ({ version, ...manifest }),