Teddy Hyde is the mobile GitHub editor for Android. Especially suitable for authoring your Jekyll blog: upload images, write draft posts, and preview Markdown with a quick swipe. Download it on Google Play.
05 April 2014

Modifying Teddy Hyde to support Impress.js

First, did you know Teddy Hyde is now 100% open source? Get on GitHub.

What if you had an advanced code editor for your mobile device? One which offered editing right into your GitHub repository? An editor which offered intelligent support for Jekyll blogging and swipe to preview of markdown files, and which supported safe login using oAuth? An editor which was extremely extensible, either by using snippets of JSON (which modify the editor dynamically), or modifying the source code for the application itself? You do! Teddy Hyde gives you all these things.

Teddy Hyde has offered “Hyde Transforms” for a long time now: snippets of JSON embedded in your repository which extend this little editor for Android. Extensions look like extra menu items when you are in edit mode. If you wanted to have a shortcut for entering in YouTube embed code, Teddy Hyde could be extended to show a menu “Embed YouTube” which upon selection would then prompt you for the YouTube “short code” (the unique code you see at the end of each YouTube URL). After you enter this short code into the dialog, Teddy Hyde can then interpolate this value into a larger snippet of text, pasting in the entire embed code, perhaps even with an embed targetting mobile devices and another for desktop.

Teddy Hyde is a general purpose GitHub editor, but it is very effective in editing Jekyll blogs. This post will make a lot more sense if you have a Jekyll blog. And, you should understand the basics of layouts, which are wrapper files which a rendered around your markdown files.

Since Teddy Hyde is now open source, I wanted to take this opportunity to show how to build Impress.js presentations using Teddy Hyde using hyde transforms. To be clear, you could do this now using the existing hyde transforms. But, as of this writing, when you use JSON snippets to extend your editor, the extensions don’t have any sense of context. To be more clear, any menu item you add using “Hyde Transforms” is added regardless of the file type. The problem with this, of course, is that if you have more than a few extensions, your menu quickly gets crowded. What would be much better is to only show certain menu items when a file extension or template name matches. Specifically here, it would be great to only load extensions for Impress.js type files if the user were editing posts using a layout called “impress”. I’ll demonstrate how to do this in this post.

Here is how it looks in the editor. Notice the first file which uses the “post” layout does not have the hyde transforms menu item, but when we select a file which uses the “impress” layout, then the menu item is enabled.


Getting the source code and setting up your developer environment

First, get the source code. Then, make sure you have the Android tool chain installed and Java as well. I recommend installing Java from Oracle; Apple seems to be getting more and more hostile towards Java on OSX. You also need to install gradle: I found gradle 1.11 to work well with the current sources and gradle build files, but YMMV.

You’ll also need to add a local.properties file. This file specifies the path to the Android SDK. I used brew (a package manager for OSX), so running cat to display my file looks gives me this:

bash-3.2$ cat local.properties 

Once everything is installed and setup run this command:

$ gradle assembleDebug

You’ll should see some status output indicating Gradle is downloading the necessary components from Maven, and then building the sources:

WARNING: Dependency org.apache.httpcomponents:httpclient:4.0.1 is
ignored for release as it may be conflicting with the internal version
provided by Android.
         In case of problem, please repackage it with jarjar to change
         the class packages


Great, we can now edit to our heart’s content.

As we are proper developers, we create a feature branch on which to do our work, and then we start by adding a test case to prove that what we build works.

$ git checkout -b add_support_for_contextual_transforms

We’ll write a test based on our login.features test. This test will login, and then attempt to load the new hyde transformation file, verifying that the menu is enabled only when we use an “Impress.js” template.

Sigh. Again, this does not work. There is a bug with Calabash for Android which prevents jumping into console mode and which prevented me from completing these tests. Are you interested in helping to fix these tests?

Now, let’s strategize about what we want to build. We want to add support for Impress.js presentations. Impress.js is a very simple way to create slideshows. You build out the markup in HTML annotating certain elements with special classes or data-attributes. Then, the Impress.js JavaScript library transforms the HTML using these declarative annotations into a presentation, adding support for keyboard navigation. Impress.js adds styling to the presentation which provide animated transitions. An impress.js layout file for Jekyll could look like this:

You’ll want to put this inside the _layouts directory in your Jekyll blog repository.

And, then a sample Markdown file which has content for an impress.js presentation could look like this:

This will sit inside your _posts directory (make sure to honor the filename conventions of YYYY-mm-dd-title-with-spaces-converted-to-hyphens.md).

You can see the markdown uses HTML code which Impress.js uses to render the presentation and provide keyboard navigation and animations. But, this HTML is complicated to remember, and especially error prone if we were to add it using our mobile device. Let’s add “Hyde Transforms” to extend our editor and make this simpler.

We want Teddy Hyde to provide menus which allow us to insert the correct HTML into our presentation; it is not complicated to write Impress.js presentations, but typing in a bunch of HTML tags from our mobile phone keyboard is tedious. Using menu item macros we can quickly paste in the correct markup and then concentrate on the content inside each slide. Teddy Hyde already supports adding items to the menu using “Hyde Transforms.” What we don’t have is a way to selectively enable those menu items only when we are editing Impress.js files. How do we know it is an Impress.js file? Well, if we are editing Jekyll blogs, then each post or page should have a snippet of YAML (called YAML Front Matter, or YFM) which specifies the layout to use when rendering the file. If we assume that layouts called “impress” are for Impress.js presentations, then we could enable the menu items only when we see that file type. We don’t currently have a way to do this, so let’s add this to Teddy Hyde.

Writing tests

I am big proponent of writing tests. And, Teddy Hyde does not have the test coverage I want it to have. There are some tests in the TeddyHyde/tests/src/com/EditorHyde/app/ directory, but they don’t work. It was possible at one point to run them from the command line using a command like this:

javac -cp ./TeddyHyde/build/classes/debug:testing/lib/junit-4.11.jar:testing/lib/hamcrest-core-1.3.jar TeddyHyde/tests/src/com/EditorHyde/app/FormatterTest.java
java -cp ./TeddyHyde/build/classes/debug:testing/lib/junit-4.11.jar:testing/lib/hamcrest-core-1.3.jar:TeddyHyde/tests/src  org.junit.runner.JUnitCore  com.EditorHyde.app.FormatterTest

They don’t work now. Are you interested in getting them working? Are you interested in getting them to work within gradle by writing an addition to the build.gradle file?

There is working Calabash UI test coverage. You can start looking in the features directory or reading the blog post detailing using these tests.

So, let’s drive blind and make these changes without writing working test coverage. We’ll still add tests to make sure we record the expectations of our changes.

Modifying the code

The way our Hyde transforms work is that we create a file inside any Jekyll repository. This file should be located at the path _hyde/transforms.json. If we have this file there, then once we load up the repository, we load this file and convert them into “transforms” which are menu items which insert some kind of textual code. This is an example of a transform.json file:

These extensions add menu items when you are editing any file which will insert HTML code for a “colored image” (and prompts you for that color), or to insert a snippet of AngularJS code.

We want to make these extensions context sensitive, meaning, know when we are editing an Impress.JS presentation and only show those menu items then. Let’s say it will look like this:

So, we’ve added the context attribute, and we’ve bumped the version number. Let’s make some changes. We’ll need to change the MarkupUtilities.java file, the ScreenSlideActivity.java file, and the Transform.java file.

Explaining a little more about these files: the ScreenSlideActivity.java file is the code which builds out an editor for us: it shows the markdown file contents, has menu items for adding markdown, and has our “Hyde Transforms.” It also supports “swipe to preview” such that you can swipe to the right and generate HTML from your Markdown to see what it all looks like. The MarkupUtilities.java file is performs string manipulation on markdown files: things like retrieving the YAML Front Matter, stripping the YFM off, and processing the file for interpolated content. Finally, the Transform.java file is the class which encapsulates a transformation.

Basically, we’ll add some code which retrieves the template from the YAML Front Matter inside any markdown file, then compares that template against the tempate the transform uses (if available). If they are a match, then we enable the menu item. There is quite a bit of code here, so best to review it on GitHub

Wrapping up

If we use layout: "impress" in our template, and then have these transforms loaded, we’ll only see that option listed. More importantly, hopefully this post shows you how you can start modifying Teddy Hyde.

You can see an example of this in use on this blog. And, view the code for the layout and page as well.

blog comments powered by Disqus