Skip to content

maxnikulin/linkremark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LinkRemark — notes for web pages augmented by metadata

Install

icons/lr-32.png

LinkRemark:

Changes in LinkRemark-0.4 release are almost entirely related to forced transition to another API version for Chrome extensions. Minor fixes:

  • Earlier zero-width space characters U+200B were added after timestamps. You may want to remove them from your notes, use search and replace for
    :LAST_MODIFIED: [2021-09-18 Tue 01:23]<200b> 09/18/2021 01:23:46
        
  • Only first <script> element with JSON-LD metadata was taken into account.

As to Manifest V3 API, it required significant amount of work. New bugs may appear due to more complex initialization. I have no idea if smaller RAM footprint of browser is noticeable. Despite some permissions are optional now, I do not think the add-on has become more safe. Multiple tabs and cross-origin frames scenarios still require most dangerous <all_urls>. From my point of view, security model for browser extensions is still far from being consistent. Firefox version still uses Manifest V2 API due to bugs in mv3 implementation. I agree with the opinion that primary goal of forcing Manifest V3 API is to restrict ad blockers, not user safety.

Introduction

LinkRemark is a browser extension that allows to save some context while capturing notes using Org mode for GNU Emacs. The add-on attempts to extract some metadata from the current web page, e.g. author, time when the text was written. Actually it just generates (almost) text notes using a few elements of Org mode markup.

The idea is that the note for a link should not be just a bookmark to the link target. It should reflect connection of the page where it is found and the site it points to. A site that brought you to the current page (referrer) could later help find more information related to the topic. Consider it as an element of associative trails described by Vannevar Bush (As We May Think, The Atlantic Monthly, Jul 1945) However implementation is hardly approaching ideas developed by Douglas Engelbart.

I have not seized experiments with this extension, that is why I could not give compatibility promise. Unsure if it is reliable enough, personally I find it acceptable. Be ready to edit created notes. Almost every site has its own peculiarities, so you will have to manually add some info and to remove some redundant entries.

Example of link capture

* Link: Karl Voit: UOMF: Managing web bookmarks with Org Mode
:PROPERTIES:
:DATE_ADDED: [2021-09-28 Tue 12:15]
:END:

- Link URL :: [[https://karl-voit.at/2014/08/10/bookmarks-with-orgmode/]]
- Link text :: Karl Voit: UOMF: Managing web bookmarks with Org Mode

#+begin_quote
author: Karl Voit
published: [2014-08-10 Sun]
#+end_quote

On the page

** Adam Porter — org-almanac
:PROPERTIES:
:DATE_ADDED: [2021-09-28 Tue 12:15]
:LAST_MODIFIED: [2021-09-18 Tue 01:23] 09/18/2021 01:23:46
:END:

- URL :: [[https://alphapapa.github.io/org-almanac/]]
- title :: org-almanac
- author :: Adam Porter
- referrer :: [[https://www.google.com/]]

Install

You can install LinkRemark from browser extension catalogues, see addons.mozilla.org for Firefox or Chrome Web Store. Packages are mirrored in the releases section on GitHub https://github.com/maxnikulin/linkremark/releases

It is possible to try latest development version by loading content of this repository as a temporary add-on in Firefox or as an unpacked extension in Chrome. Create a symlink manifest.json to either manifest-firefox.json or manifest-chrome.json file.

For everyday use you might wish to configure native application helper or desktop-wide org-protocol handler instead of clipboard to pass captures to your notes.

Usage

Optionally select some text and choose an add-on action item from context menu (right click, [Menu] or [Shift+F10] keys). Unless you are going to capture a particular link or specific frame, you can click on the extension icon in browser toolbar (“browser action”) or may configure a shortcut on the add-ons page1 (Firefox: “Manage Extension Shrotcuts” in the gear menu).

To capture several tabs, select (highlight) them e.g. by holding [Shift] or [Ctrl] while clicking on tab headers and open extension action menu in the browser toolbar or (Firefox only) context menu for header of a selected tab and choose “Remark for highlighted tabs”. Pure keyboard shortcuts for Firefox are described in the Selection of Multiple Tabs (Keyboard shortcuts - Perform common Firefox tasks quickly) support article.

Additional permissions are required to capture multiple tabs, see the Permissions section for more details. Most complete metadata may be extracted with <all_urls>, however in general it is the most dangerous permission. When tabs permission is granted, metadata are unavailable, but tab title and page URL are accessible to the extension. Notice that the <all_urls> permission is not enough when you are going to capture a privileged page like chrome://, about:, or https://addons.mozilla.org (in Firefox) and you should grant tabs in such case. Just the current tab and the pages captured earlier are available for group actions in the absence of these permissions. It is specifics of the activeTab permission.

Chrome has a menu item to capture all pages that belong to the earlier created tab group. It acts for the current tab if it is a standalone one. If the tabGroups permission is granted then the tab group title is used to name the bunch of captured pages. It is unrelated to metadata.

By default the extension just shows preview for the note and offers to copy it to clipboard, so you just can paste it to a text editor. Emacs Org mode has a convenient command C-c C-x C-y, org-paste-subtree.2 A hint: to navigate to the parent heading before pasting you can use C-u C-c C-w, org-refile or C-c C-j, org-goto (maybe with prefix argument as well).

Capture templates (web) (info "(org) Capture") is the next step for Org mode users. You could start with a very simple template having “plain” type

(custom-set-variables
 '(org-capture-templates
   (quote (
    ("c" "Clipboard with tree (plain)"
     plain (file "~/org/capture.org")
     "%(org-get-x-clipboard 'CLIPBOARD)"
     :empty-lines 1)
))))

You can add such entry using M-x customize-variable RET org-capture-templates. On the current development stage I do not recommend :immediate-finish option, it is better to inspect capture result. It is impossible to refile plain entry directly from a capture buffer, so likely you wish to change “plain” (Plain text) to “entry” (Org entry) type in Emacs configuration and to change template to

"* %(org-get-x-clipboard 'CLIPBOARD)"

Please, update “Template type configured in org-capture-templates” in add-on settings3.

There is an option to avoid preview page for successful captures: disable “Open preview tab with capture result for clipboard”.

To minimize keyboard and mouse interaction, capture may be initiated using org-protocol (web) (info "(org) Protocols"). Since Emacs-29.2 desktop-wide handler is enabled by default on GNU/Linux (see the emacsclient.desktop file). You still need to ensure that Emacs server is running M-x server-start and the library is loaded M-: (require 'org-protocol) or M-x customize-variable RET org-modules. Set org-protocol as “Communication channel” in add-on options3. Keep capture type in Emacs consistent with “Template type configured in org-capture-templates” add-on setting. Another option you may find useful is “Template name”. They are in the “Org Protocol” section, but applied for native app export as well. For troubleshooting the readme file for Org Capture Extension may be more useful than the org-protocol: Worg page.

I am a bit afraid that some web page may try to inject some malicious content into my notes when I click on an innocent link, so I suggest to consider exporting through a native messaging application as a safer option.4 LinkRemark repository contains a simple variant in examples/backend-python/lr_emacsclient.py Run it with -h option for a brief guide. To enable it, you should do something like5 (Linux, Firefox)

mkdir ~/.mozilla/native-messaging-hosts
python3 examples/backend-python/lr_emacsclient.py --manifest-firefox \
   >~/.mozilla/native-messaging-hosts/lr_emacsclient.json

and should specify ”native-messaging” for “Communication Channel” / “Method how to pass capture to desktop environment” and ”lr_emacsclient” for “Browser native messaging communication channel” / “Name of native messaging backend application” add-on settings. Emacs init file should have something like the following:

(custom-set-variables
 '(org-capture-templates
   (quote (
    ("r" "LinkRemark (entry)"
     entry (file "~/org/capture.org")
     "* %:initial"
     :empty-lines 1)
))))

Certainly Emacs server still should be running, org-protocol should be loaded, capture templates should have consistent configuration within the add-on and Emacs. The advantage is that desktop-wide org-protocol: handler is not used.

If you wish to experiment with metadata formatting, have a look at examples/backend-python/lr_example.py for inspiration. See the next section for a more powerful native messaging helper.

If you are not familiar with Org Mode capture feature, you could find description of workflow in blogs, e.g. Learn how to take notes more efficiently in Org Mode by Sacha Chua.

Checking if an URL is already in your notes

This is a new feature in LinkRemark-0.2, it was not included in 0.1 version. Please, consider current implementation as a proof of concept, there are a lot of things to polish yet. It is tested on Linux only.

doc/burl-linkremark-preview-demo.png

bURL https://github.com/maxnikulin/burl native messaging app (backend) is required. It allows to invoke emacsclient directly without setting up of desktop-wide handler for org-protocol. I do not think that protocol of internal communication between LinkRemark and bURL is stabilized already.

README file for bURL describes how to install and to configure the native application (unsure if it is clear enough). Key points:

  • Server (info "(emacs) Emacs Server") is running in Emacs unless it is enough to just see locations of same URL in your notes. Otherwise neither clicks on found mentions nor org-protocol capture would work.
  • org-protocol (info "(org) Protocols") is loaded and a template is configured to enable capture feature. Alternatively use clipboard and C-c C-x C-y, org-paste-subtree.2
  • Native application is enabled in browser for LinkRemark extension. On Linux a JSON file should be created.
  • List of files to search for URLs is provided to bURL. Currently it is achieved by creating of a wrapper shell script for burl_backend.

bURL may create configuration files for your. To enable native backend for particular user of Firefox on Linux assuming that burl_backend binary is copied to ~/.local/bin, run a command similar5 to the following one:

mkdir ~/.mozilla/native-messaging-hosts
~/.local/bin/burl_backend -manifest-firefox ~/.mozilla/native-messaging-hosts/ \
    -backend burl \
    -wrapper ~/.local/bin/burl_wrapper \
    -org ~/org/notes.org \
    -org ~/org/capture.org

It should create burl_wrapper shell script and burl.json file (io.github.maxnikulin.burl.json without -backend option) in ~/.mozilla/native-messaging-hosts/ (its basename is the identifier of the native application).

Open LinkRemark settings page3. Set “Name of native messaging backend application” in the “Browser native messaging communication channel” section to the id of configured native app (e.g. burl or io.github.maxnikulin.burl). Grant the permission for “Exchange messages with other programs”.

Known URLs should be reported in response to capture of pages already present in your notes. Preview and debug info page has a form for testing of this feature.

You can set “Method how to pass capture to desktop environment” to “native-messaging”, however it is not required. You can continue with clipboard or org-protocol desktop-wide handler.

Alternatives

There are some projects that allows to capture URL + page title + selection text or URL + text link. It is not enough for me. I would like to save to my notes who and when wrote the text at least for sites that have such fields in page metadata.

To capture a minimal bookmark one of the following projects could be more convenient:

If you would like to have more details on web pages in you notes then consider GitHub - yantar92/org-capture-ref: Extract metadata/bibtex info from websites for org-capture. It is suitable if web browser of your choice is Emacs or Qute Browser. Unlike this extension, it supports custom handlers for particular websites, and has recipes for scientific papers and BibTeX format.

Permissions

You could find more information what every requested permission means on the following page from the Mozilla Support site: Permission request messages explained.

Open extensions preferences3 to grant or revoke optional permissions. Firefox has permissions tab in the add-on manager1. They may be requested on demand to successfully complete requested action taking into account current settings.

Access your data for all websites (<all_urls>)

Chrome: “Read and change all your data on all websites”.

The add-on may gather data for a group of selected (highlighted) tabs or from cross-origin subframes (loaded from other site than top level page in the tab). Due to some limitations of WebExtensions API, per-site permission requests on demand may require several steps of interaction with user to complete a capture. It may be annoying after all. This permission may be perceived as “too much”.

It is necessary to explicitly enable this permission from extension options in Chrome or from permissions tab of add-on management UI in Firefox. It is reasonably considered as rather dangerous. Alternatively tabs permission is enough to get tab titles and URLs, but not their URLs, see the Usage section for clarification.

It is a bug, if this extension attempts to inspect content of some tab without explicit user action.

Exchange messages with other programs (nativeMessaging)

Chrome: “Communicate with cooperating native applications”, optional.

Allows the extension to communicate with Emacs without global org-protocol handler, so allows to have more secure setup. On the other hand you need to install and configure an extra application, so you should either trust this external tool or should develop it yourself.

This permission is relevant for experienced Emacs and Org Mode users.

Extension can not launch any application till it is explicitly added to a configuration file (manifest) by the user, so do not worry, extensions can not run arbitrary binaries with no cooperation from users.

Access browser activity during navigation (webNavigation)

Chrome: “Read your browsing history”.

It is necessary to reliably restore tree of nested frames. Consider the case when some element is focused in a subframe and capture is invoked using keyboard shortcut. Another case is context menu invoked in a deeply nested frame.

You may grant this permission on the extension options page.3

Access browser tabs (tabs)

Chrome asks “Read your browsing history” when the extensions is installed due to the webNavigation required permission.

When several tabs are captured at ones, this permission may be necessary to get URLs and titles of privileged pages. See the Usage section for relation to the <all_urls> permission.

Requested on demand when a corresponding menu item is invoked.

View and manage your tab groups (tabGroups, Chrome)

May be granted from the extension options page. Allows “Remark for tab group” action to use tab group name for heading title instead of generic “Tab group” name. To get list of tabs that belongs to the same group the extension needs the tabs permission, not tabGroups.

This extension only reads tab group property, it does not modify and does not create groups of tabs.

See the Usage section for explanation why either <all_urls> or tabs permissions are necessary to actually get info about pages from a tab group. Notice that tabGroups does not allow that.

Do not confuse tab group with highlighting (selecting) several tabs.

Input data to the clipboard (clipboardWrite)

In Chrome it is called “Modify data you copy and paste”.

An optional permission relevant for the “clipboard” and combined “org-protocol” with clipboard export methods.

This permission is necessary if you prefer to copy capture result to clipboard without intermediate preview page. In Chrome it must be combined with offscreen. Firefox does not need this permission in most cases (since version approximately 112).

When this permission is not granted, the add-on still tries other methods: content script (less reliable approach) and a temporary tab.

Browsers consider overwriting clipboard content as a potentially dangerous action, so they perform, some measures to protect users. Security model and thus behavior in Chrome is different from Firefox.

This permission may be revoked as soon as you configure native application with granting nativeMessaging permission or desktop-wide handler for the org-protocol: URI scheme.

Execute content scripts (scripting)

The extension uses content scripts to extract metadata from web pages. This permission does not require to be explicitly confirmed. Currently it is used in Chrome only since it is a related to the scripting API introduced in Manifest V3. In Firefox older Manifest V2 API is used due to peculiarities of mv3 implementation in Firefox.

Actually this permission is not enough and the activeTab permission enables capture for single tab top level page. In the case of multiple tabs or cross-origin frames metadata are inaccessible unless <all_urls> is granted.

Offscreen documents (offscreen, Chrome)

An optional permission relevant for the “clipboard” and combined “org-protocol” with clipboard export methods. There is no confirm popup dialog for this permission, It may be just granted on capture when preview is disabled.

Combined with clipboardWrite, the offscreen permission allows to reliably copy text to clipboard. The permission is necessary when capture preview is disabled.

Chrome have no API for clipboard access from extension background service worker. Copy from content script might be unreliable.

If you have a reason to avoid the offscreen permission then do not grant clipboardWrite. Instead you may choose nativeMessaging or desktop-wide handler for org-protocol: URI scheme.

Troubleshooting

  1. Try to open Debug Info (Preview) extension page through context menu for the extension button in tool bar (extension browser action) end expand debug info section there.
  2. Look for errors in console pane in browser developer tools for the extension. It could be opened using “Inspect” link from the about:debugging#/runtime/this-firefox page for Firefox. In Chrome menu choose “More tools”, “Extensions” and click on the link followed “Inspect views” on the add-on card.
  3. In Chrome have a look into chrome://extensions/?errors=mgmcoaemjnaehlliifkgljdnbpedihoe (error collection should be enabled for the extension).

For native messaging backend problems see the related section in Mozilla developer guide and Chrome debugging native messaging docs. It is worth checking errors reported to the browser console (Ctrl+Shift+J in Firefox). To read messages from Chrome on Linux, start it from a terminal or maybe just try journalctl --user --follow.

License

LinkRemark is published under the GNU GPLv3 license or any later version, see LICENSE.txt.

Footnotes

1 “Manage extension” in context menu (right click) for the add-on’s action in the browser toolbar or through generic browser menu, e.g. Firefox: “Add-ons and Themes” from hamburger menu or from “Tools” in menu bar, [Ctrl+Shift+A]. In Chrome choose “Extensions” from the menu opened from the 3 dots toolbar button.

2 Prior to Org-9.6 (Emacs-29) there was a bug preventing clipboard content recognized as a valid subtree. Workaround is yank C-y, undo C-/ (required once per Emacs session), and C-c C-x C-y to paste subtree.

3 “Extension preferences” (Firefox) or “Options” (Chrome) in the context menu for the extension entry in the browser toolbar. Alternatively click on the “Settings” link on an add-on preview or help page.

4 There is a problem with browsers distributed as snap or flatpak. Such applications works with additional level of isolation in respect to system files, so external application can not be invoked even through native messaging API. Chromium in Ubuntu is shipped as snap package only since Ubuntu-20.04 LTS focal, for Firefox snap is made default option in Ubuntu-21.10 impish, but Firefox is still can be installed as a deb package using apt. Related Firefox bugs:

5 In Chrome actual path to the profile directories is specified on the chrome://version/ and chrome://profile-internals/ pages. See also User Data Directory in Chromium docs for location of profile directory. Mozilla applications load descriptions of native applications from directories shared by all profiles.