To main content

"Edit this page on Github" using Freemarker in JBake

Published by Benjamin Marwell on

Another challenge we (the Apache Shiro Team) faced with our new JBake website was to re-re-add the "edit this page on GitHub" link at the bottom of the page. But it can be done with a workaround as long as the related bug is not solved.

Screenshot of the Apache Shiro website with a "Edit this page on GitHub" link at the bottom (footer).
Screenshot of the Apache Shiro website with a "Edit this page on GitHub" link at the bottom (footer).

Getting the relative source path

The first thing you need is the path of the source file. Turns out, even this is not (easily) possible using jbake. The best would have been a repository-relative URL, but for this the jbake team would have to implement a git and svn provider (and possibly others). The next thing I looked for were (project-relative) URLs. Turns out we have don't have that information either! So, what do we have? We can check model variables at

  • content.sourceuri
    returns the TARGET uri
    e.g. /blog/2021/apache-shiro-180-released.html.
  • content.file
    returns the full, local and absolute path of the source file.
    Not sure why this could be useful, unless you run it through an external processor.
    e.g. /home/users/ben/git/shiro-site/jbake/content/blog/2021/apache-shiro-180-released.adoc.
  • content.rootpath
    returns the relative path to the root (where root = content folder).
    e.g. ../../.
  • content.uri
    returns the same as sourceuri. This convinced me that sourceuri is probably wrongly implemented.
    e.g. /blog/2021/apache-shiro-180-released.html.
  • content.noExtensionUri
    returns nothing, because it is not set.
    e.g.: null

As there is no way to get the repository-relative or even content-relative source path, I opened an issue: [#729] sourceuri shows targeturi. When I wrote this blog article, the issue was open for 18 days without a reaction.

Recreating the relative source path

So, we can still recreate the correct sourceuri ourselves in freemarker, because the file variable holds the correct source extension (.adoc). Only a few lines of code are needed:

  sourcefile="${content.sourceuri?replace('.html', extension)}"

Now we are still missing the relative path to the repository. Open your and add a new property:


The variable will now be available with the config. prefix and the dots replaced by underscores: github_editlink_baseurl. You need to omit or replace the last "/content" fragment if you have set your content.folder property to another value.

Putting everything together

Put everything together, we came up with this in our header template for Apache Shiro:

<div class="d-flex justify-content-end col-md-4" id="editThisPage">
  <#if (content.sourceuri)??>
      sourcefile="${content.sourceuri?replace('.html', extension)}"
  <input type="hidden" id="ghEditPage" value="${config.github_editlink_baseurl}/${sourcefile}"/>

For Shiro, we (still) set the link via Javascript. We will probably change this in the future. πŸ™‚