Embedding Ace in Gitit
By default when editing pages in Gitit, text is entered using a standard textarea element. It is however fairly easy to extend Gitit. This post is going to look at using the Ace editor with Gitit.
Downloading Ace
Ace builds are hosted in a separate GitHub repository, start by cloning this repository to a temporary directory:
git clone --depth 1 https://github.com/ajaxorg/ace-builds.git /tmp/ace-builds
Note: using the --depth
option will create a shallow clone without a full
commit history. This option isn't strictly necessary, however it should reduce
the download time.
If you don't have Git installed you can download a tar file instead:
curl -OL https://github.com/ajaxorg/ace-builds/archive/master.tar.gz
tar xf master.tar.gz -C /tmp
rm master.tar.gz
You now need to pick which version of Ace you want to use, there are currently four versions:
src
: concatenated but not minifiedsrc-min
: concatenated and minified with uglify.jssrc-noconflict
: uses ace.require instead of requiresrc-min-noconflict
: concatenated, minified with uglify.js, and uses ace.require instead of require
Once you've picked a version, make a static/js
folder in the Gitit wiki and
copy the version across:
mkdir /home/gitit/wiki/static/js
cp -r /tmp/ace-builds/src-min-noconflict/ /home/gitit/wiki/static/js/ace
Updating Gitit templates
We now need to override the Gitit page template to embed Ace. Start by copying
the default page template into the templates
directory of the wiki:
cp /usr/share/gitit/data/templates/page.st /home/gitit/wiki/templates/
Now add the following between $getuser()$
and </body>
:
<script src="$base$/js/ace/ace.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
function enable_ace_editor(old_editor) {
"use strict";
var ace_div = document.createElement("div");
ace_div.setAttribute("id", "ace-editor");
ace_div.style.height = "400px";
old_editor.parentNode.insertBefore(ace_div, old_editor);
old_editor.style.display = "none";
var editor = ace.edit(ace_div);
//Fix for https://github.com/angular-ui/ui-ace/issues/104
editor.\$blockScrolling = Infinity;
editor.getSession().setValue(old_editor.value);
editor.getSession().on("change", function () {
old_editor.value = editor.getSession().getValue();
});
editor.focus();
}
var old_editor = document.getElementById("editedText");
if (old_editor !== null) {
enable_ace_editor(old_editor);
}
</script>
This code will check if the editedText
element exists. If the element does
exist, it will create a new div
for Ace, hide the existing textarea
and set
up a function to sync the Ace editor with the old textarea
.
Note: $
will normally be interpreted when Gitit renders the template,
therefore the dollar in front of $blockScrolling
is escaped.
Finally restart Gitit (systemctl restart gitit.service
) to reload the page
template. If everything goes well you should now see Ace in the edit tab:
Customising Ace
From here it's fairly easy to customise Ace, below are the additional settings I ended up using:
editor.getSession().setMode("ace/mode/markdown");
editor.setTheme("ace/theme/chaos");
editor.setFontSize(14);
editor.setKeyboardHandler("ace/keyboard/vim");
editor.setOption("wrap", "free");
editor.setHighlightActiveLine(true);
editor.setHighlightGutterLine(true);
editor.renderer.setShowGutter(true);
editor.renderer.setShowPrintMargin(true);
editor.setOption("scrollPastEnd", true);
editor.getSession().setUseSoftTabs(true);
editor.getSession().setUseWrapMode(true);
The Ace documentation has a full list of available options, the Ace Kitchen Sink is also worth looking at to get a feel for which options you want to configure.
New commands
Ace also makes it easy to add custom key bindings, the code below will add
support for :w
and :q
:
// Monkey patch in write and quit commands for Vim binding
ace.config.loadModule("ace/keyboard/vim", function (m) {
var VimApi = ace.require("ace/keyboard/vim").CodeMirror.Vim;
VimApi.defineEx("write", "w", function (cm, input) {
cm.ace.execCommand("save");
});
VimApi.defineEx("quit", "q", function (cm, input) {
cm.ace.execCommand("quit");
});
});
editor.commands.addCommand({
name: "save",
exec: function (editor) {
var commit_message = window.prompt("Commit message:");
if (commit_message) {
document.getElementById("logMsg").value = commit_message;
document.getElementById("logMsg").focus();
}
}
});
editor.commands.addCommand({
name: "quit",
exec: function (editor) {
window.location.pathname = "$base$$pageUrl$";
}
});
Note: if you are using mod_proxy_html to
rewrite pages, make sure you update the quit function to use the correct URL
(e.g. /wiki$pageUrl$
).