All Projects → mems → bookmarklets-context-menu

mems / bookmarklets-context-menu

Licence: MIT license
WebExtension allow to execute bookmarklets as privileged scripts

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects
Makefile
30231 projects

Projects that are alternatives of or similar to bookmarklets-context-menu

Twitter Bookmarks Search
WebExtension that adds ability search all your bookmarked tweets!
Stars: ✭ 59 (-11.94%)
Mutual labels:  bookmarks, webextension
time-capsule
A WebExtension to send links to your future self
Stars: ✭ 27 (-59.7%)
Mutual labels:  bookmarks, webextension
Bookmarks Organizer
With the Bookmarks Organizer it's easy to put order in your bookmarks. The Bookmarks Organizer finds no longer working bookmarks, redirects, duplicates and more!
Stars: ✭ 90 (+34.33%)
Mutual labels:  bookmarks, webextension
twitter-bookmarks-search
WebExtension that adds ability search all your bookmarked tweets!
Stars: ✭ 160 (+138.81%)
Mutual labels:  bookmarks, webextension
Floccus
☁️ Sync your bookmarks privately across browsers
Stars: ✭ 2,630 (+3825.37%)
Mutual labels:  bookmarks, webextension
spellbook
Spellbook is a bookmark extension for Chrome and Firefox
Stars: ✭ 19 (-71.64%)
Mutual labels:  bookmarks, webextension
Modern-UI-Components-for-VBA
A helper dll for VBA users to design modern UI components. No install required!
Stars: ✭ 139 (+107.46%)
Mutual labels:  contextmenu
angular2-contextmenu
-Deprecated in favor of ngx-contextmenu- A context menu built with Angular 2 inspired by ui.bootstrap.contextMenu.
Stars: ✭ 68 (+1.49%)
Mutual labels:  contextmenu
frontreport
Simple frontend logging collector written in Go
Stars: ✭ 23 (-65.67%)
Mutual labels:  csp
resources
Awesome resources - 网络资源
Stars: ✭ 27 (-59.7%)
Mutual labels:  bookmarks
yet-another-pinboard-extension
Manage your Pinboard bookmarks in your browser.
Stars: ✭ 27 (-59.7%)
Mutual labels:  webextension
pool
A highly flexible process pooling library for Node.js
Stars: ✭ 18 (-73.13%)
Mutual labels:  csp
CrySPY
CrySPY is a crystal structure prediction tool written in Python.
Stars: ✭ 58 (-13.43%)
Mutual labels:  csp
bookmarks
📚 A list with my bookmarks.
Stars: ✭ 82 (+22.39%)
Mutual labels:  bookmarks
csp
A library for Communicating Sequential Processes in Node.js, built on top of async/await
Stars: ✭ 59 (-11.94%)
Mutual labels:  csp
ipfs-companion
Browser extension that simplifies access to IPFS resources on the web
Stars: ✭ 1,745 (+2504.48%)
Mutual labels:  webextension
flying-apple
Just to keep track of nice content and new announcements related to Apple products and Swift
Stars: ✭ 45 (-32.84%)
Mutual labels:  bookmarks
Overamped
Safari Web Extension to disable AMP ⚡️
Stars: ✭ 32 (-52.24%)
Mutual labels:  webextension
BookmarkHub
BookmarkHub , sync bookmarks across different browsers
Stars: ✭ 720 (+974.63%)
Mutual labels:  bookmarks
bookmark-manager
WordPress plugin for managing bookmarks
Stars: ✭ 15 (-77.61%)
Mutual labels:  bookmarks

Firefox capture of Bookmarklets context menu: Context menu opened with a folder and a bookmarklet "Copy page as Markdown link"

This extension is available for Firefox (via AMO)

Why use Bookmarklets context menu

Current browsers' implementations of bookmarklets are broken: bookmarklet are executed as author's script, but should be executed as user's scripts (with higher pivileges).

To circumvent this restrictions, the extension Bookmarklets context menu create a context menu with all bookmarklets available from user's bookmarks and executed it on demand as content script. This allow access to a secured isolated environement, with higher privileges than author's scripts (allow to copy to clipboard without require user intialized event, cross domain fetch).

If the page block the context menu, you can use the browser action of context menu:

Firefox capture of Bookmarklets context menu: Browser action highlighted

Why current browsers' implementations of bookmarklets are broken?

consider users over authors over implementors over specifiers over theoretical purity.

HTML Design Principles

With current implementation, bookmarklet usage is restricted because bookmarklets are not executed as privileged scripts, but as author's script. That means bookmarklet are subject to security measures like CSP and CORS which make it difficulte to use or impossible in some cases.

This no more the cas with Chrome and Firefox (see bug 1267027, Intent to implement, bug 1406278, bug 1478037), but CSP still applied on subressources

See also Wiki pages

Limitations of this extension

This doesn't fix broken implementations. It's just an alternative.

Permissions required by the extension

The following permissions are used by the extension:

  • bookmarks: read the bookmark tree to get all bookmarklets
  • contextMenus: create context menus based on bookmarklets founded in bookmarks
  • activeTab: execute bookmarklet script in the active tab
  • clipboardWrite and clipboardRead: allow to use document.execCommand('cut'/'copy'/'paste') in bookmarklets
  • storage: store some preferences like "flat context menu"
  • <all_urls>: allow bookmarklets to perform fetch() or XMLHttpRequest without crossdomain limitations

How to write a bookmarklet

It's not recommended to use external resources. External resources are affected by CSP.

If the result of the bookmarklet is other than undefined (void 0), it will be used as HTML source of a new document opened in the same tab: javascript:"<span style='text-decoration:underline'>Underlined text</span>"

An example of a bookmarklet that copy the document's title (document.title):

javascript:(s=>{let%20d=document,l=e=>{d.removeEventListener("copy",l);e.preventDefault();e.clipboardData.setData("text/plain",s);};if(d.activeElement.tagName=="IFRAME"){let%20s=d.createElement("span");s.tabIndex=-1;s.style.position="fixed";d.body.appendChild(s);s.focus();s.remove()}d.addEventListener("copy",l);d.execCommand("copy");a.focus()})(document.title)

An example of a bookmarklet that copy the page as Markdown link:

javascript:{let%20e=document,t=e.URL,a=[e.title].concat(Array.from(e.querySelectorAll("h1,h2")),t).reduce((e,t)=>e||t.textContent&&t.textContent.trim().replace(/\s+/g,"%20")||t.trim(),""),n=(e,t,a="&%23x",n=";")=>e.replace(t,e=>a+e.charCodeAt(0).toString(16).padStart(2,"0")+n),r=n(t,/[()"]/g,"%25",""),l=e.contentType.startsWith("image/"),[,i="Untitled"]=/\/([^/.]+$|[^/]+(?=\.[^.]*$))/g.exec(new%20URL(t).pathname)||[];i+="."+e.contentType.split("/")[1].split("+")[0];let%20c=o=>{let%20p=o.clipboardData,d=p.setData.bind(p);e.removeEventListener("copy",c),o.preventDefault(),p.clearData(),d("text/x-moz-url",t),d("text/uri-list",t),d("text/html",l?`<img%20src="${r}"%20alt="${n(i,/["&<>]/g)}">`:`<a%20href="${r}">${n(a,/[&<>]/g)}</a>`),d("text/plain",l||a!==t?(l?"!":"")+"["+(l?i:a).replace(/[\\<>\[\]]/g,"\\$&")+"]("+r+")":r)};if(["IFRAME","FRAME"].includes(e.activeElement.tagName)){let%20t=e.createElement("span");t.tabIndex=-1,t.setAttribute("aria-hidden","true"),t.style.position="fixed",e.documentElement.appendChild(t),t.focus(),t.remove()}e.addEventListener("copy",c),e.execCommand("copy")}void(0)

If you get the following error Bookmarklet error: SecurityError: The operation is insecure., that means you use document.write(potentiallyUnsafeHTML), when you should use wrappedJSObject.document.write(potentiallyUnsafeHTML) instead. It's related to content script (privilegied) context vs page context.

Note: It's impossible for the extension to catch asynchronous errors (in listener, setTimeout, etc.) even with a global error handler. You must use a try...catch block in your asynchronous functions. Alternatively you can use the add-ons debug mode about:debugging

If you need document.execCommand(), be sure there is no element in / iframe focused:

// execCommand will not been executed if a frame or an iframe is focused
if(["IFRAME","FRAME"].includes(document.activeElement.tagName)){
	let focusable = document.createElement("span");
	focusable.tabIndex = -1;// focusable
	focusable.setAttribute("aria-hidden", "true");// will not be announced by AT
	focusable.style.position = "fixed";
	document.documentElement.appendChild(focusable);// don't use doc.body because in case of frame the body is the frameset and execCommand will not work
	focusable.focus();// force focus, but will not scroll into view, because it have fixed position
	focusable.remove();// remove focus, without force to scroll into view to an other element
}
let listener = event => {
	document.removeEventListener("copy", listener);// one time listener
	// Do whaterver you want. Exemple: in copy event, use event.clipboardData
};
document.addEventListener("copy", listener);
document.execCommand("copy");// will dispatch copy event

See also:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].