Andreas Lundblad
Jan 2, 2019

A convenient way of opening the source file for a webpage in an editor

If you work with static site generators such as Jekyll or Hugo you’re probably familiar with the non-zero threshold of for example correcting a typo in a blog post.

Here’s a trick for how to open the relevant source file in a text editor with a single click:

  • Create a userscript (aka Greasemonkey script) that inserts an “Edit this page” link with a custom scheme such as editpage://
  • Create a script that:
    1. Translates the path of the link to the path on your filesystem
    2. Opens the corresponding file
  • Register the script as a handler for the custom scheme

Install Tampermonkey or Greasemonkey. Add the following user script:

// ==UserScript==
// @name  Blog Edit Links
// @match *://**
// @match *://localhost/*
// ==/UserScript==

var editNode = document.createElement("span"); = "absolute"; = "0"; = "0";
var path = window.location.pathname
editNode.innerHTML = "<a href='editpage://" + path + "'>edit</a>";
document.body.insertBefore(editNode, document.body.firstChild);

Adjust the @match clauses according to your needs. Make sure the script is activated and refresh your page. You should see something like:

For a page at URL the link will be editpage://some/page.html.

Step 2: Create a script that opens the correct source file

The script will be invoked with the editpage://some/page.html link as argument. This should be translated into something like /home/you/myblog/some/ and opened in an editor. Here’s my version:


# Directory? Use index.html
if [ -d "$FS_PATH" ]

# .html file missing? Try with .md counterpart
if [ ! -f "$FS_PATH" ]

OPTS="--socket-name=blog --no-wait"
# From
emacsclient $OPTS --eval "(if (> (length (frame-list)) 1) 't)" | grep t
if [ "$?" = "1" ]; then
    OPTS="$OPTS --create-frame"

emacsclient $OPTS --alternate-editor "" "$FS_PATH"

I use emacsclient to reuse the same editor window for every click on an edit link.

I’m using Ubuntu and Gnome, so you’ll have to do some googling to get this step done if you have a different setup. (Original instructions here.)

  1. Put the following lines in ~/.local/share/applications/editpage.desktop:

    [Desktop Entry]
    Name=Edit Blog Page
    Exec=path/to/your/ %u
  2. Run

  3. Run the following to register the handler:

    xdg-mime default editpage.desktop x-scheme-handler/editpage

Bonus feature

Add the following lines to your userscript to easily hop between your dev version and your live version of the current page…

editNode.innerHTML = "<a href='editpage://" + path + "'>edit</a>, "
                   + "<a href='" + path + "'>live</a>, "
                   + "<a href='http://localhost:4000" + path + "'>dev</a>";

My workflow is typically:

  • Navigate my homepage
  • Discover something I want to fix
  • Click the dev link
  • Click edit
  • Fix issue
  • Make sure it looks good in browser
  • Commit / push
  • Click live link
  • Make sure live version is updated.


That’s what I use at the moment, and should be enough to get you up and running. An obvious improvement would be to decode custom URLs like blog post pages for example.