Posts tagged ·

jekyll

·...

Jekyll: Include partial snippets of code

Comments Off

The Jekyll include tag is useful when including files or templates on a page. Combined with the highlight tag, it makes including code snippets easy. However, it will include the complete file, and often it is desirable to include only a few lines, or maybe a method. That could of course be done by simply copy/pasting the code in question into the article, but then the code gets out of sync if the example file is changed.

The basic usecase is something like this:

{% highlight java %}
    {% include src/HelloWorld.java %}
{% endhighlight %}

Ruby based plugin

A Jekyll tag to include only a section of a file would be great. As far as I can tell, that does not exist yet, so I started writing one. Unfortunately, Github Pages does not allow custom plugin for security reasons. There are work-arounds for that, but it also makes the deployment more complex, and loses the convenience of being able to edit the articles and code directly on github.com.

Sans error handling or caching, a simple implementation could look like this. It works outside Github Pages, so it’s a start.

module Jekyll
  class IncludeLines < Liquid::Tag
     Syntax = /(#{Liquid::QuotedFragment}+)\s(\d+)\s(\d+)\s\z/o
     
     def initialize(tag_name, markup, options)
       super
       if markup =~ Syntax
         @file = $1
         @startline = $2.to_i
         @endline = $3.to_i
       else
         raise "Syntax error in includelines: " + markup
       end
     end
 
     def render(context)
       lines = IO.readlines(context.evaluate(@file))
       part = lines.drop(@startline)
       part.take(@endline - @startline)
     end
 
   end
 end
 
 Liquid::Template.register_tag('includelines', Jekyll::IncludeLines)
 

Liquid slice and split

Using the Liquid capture block, it's possible to read a file and store it as a string variable. It can then be processed by Liquid instead of the plugin, and works fine with Github pages. The Liquid syntax is certainly verbose, but it gets the job done.

An initial implementation cutting the file content as a single string looked like this. However, it is far from ideal, since the character index and count will shift with any source code modifications on the included file.

{% capture filecontent %}
    {% include src/HelloWorld.java %}
{% endcapture %}

{% highlight java %}
    {{ filecontent | slice: 132, 57 }}
{% endhighlight %}

A slightly better solution uses the same idea, but operates on line numbers instead. It is almost as fragile when it comes to changes, but at least usable.

{% capture filecontent %}
    {% include src/HelloWorld.java %}
{% endcapture %}

{% assign lines = filecontent | newline_to_br | split: '<br />' %}
{% highlight java %}
    {% for line in lines offset:10 limit:5 %}{{ line }}{% endfor %}
{% endhighlight %}

A helper include file implementing this idea can be found here. It can be used like this:

{% include includelines filename='src/HelloWorld.java' start=10 count=5 %}

Include method

Ideally, it would be possible to mark the start of a line to include, and then indicate how much should be included. Improving on the line based iterator above, this helper file does that. Usage goes like this:

{% highlight java %}
    {% include includemethod filename='src/HelloWorld.java' method='test()' before=5  after=1 %}
{% endhighlight %}

It also adds options to include lines before and after the specified method, for example for comment blocks or further methods below the first. There are of course some extensions which could be made, e.g. to include multiple split sections; support other non-C like languages, etc. The linked code is under the GPL 3 license, so feel free to improve.

Comments Off

Getting started with GitHub Pages and Jekyll

Comments Off

In the beginning, there were static HTML pages, TABLE-tags, and FTP; later came dynamic sites, WordPress and other Content Management Systems; but now we are back to static pages again, albeit templated. So goes Quinn Supplee’s narrative of the move to Jekyll, Markdown and Liquid based static sites. Add in GitHub for free hosting, and it makes a very compelling offering for a small site run by tech savvy people. It’s not your web sites for dummies solution.

Enabling web page hosting from a Github repository is quick, as explained here. And setting a custom domain is a single setting on Github, and additional setting up your domain DNS. The Github Settings panel have a default example site template generator, so with that you’ll have some pages to look at in few clicks. Now you can download the generated files, modify and upload with standard git commands. (Replace username/repository with your own names).

git clone http://github.com/username/repository
git commit
git push

Github uses Jekell to statically generate the site, and this requires a special file and directory structure. It is of course possible to experiment with the files directly on Github, however it might be easier to edit and compile locally. For that, a local install of Jekyll and relevant dependencies and tools is required.

sudo apt-get install ruby ruby-dev rubygems-integration nodejs gcc make
sudo gem install jekyll jekyll-docs jekyll-feed jekyll-paginate bundler minima iconv

On older Debian (7 – Wheezy) or Ubuntu (14.04) distributions, the ruby packages where versioned incorrectly, so the 2.0 version is required for the ruby package and gem binary.

sudo apt-get install ruby2.0 ruby2.0-dev rubygems-integration nodejs ruby-mkrf gcc make
sudo gem2.0 install jekyll jekyll-docs jekyll-feed jekyll-paginate bundler minima iconv

With that in place, you can generate a new blank site, and make Jekyll serve it locally on http://127.0.0.1:4000/ . Of course, the final destination would be the Github repository.

jekyll new test --skip-bundle
cd test
jekyll serve

For more advanced options and functions, the Jekyll documentation is good. There are some Jekeyll based example sites here. In particular, Patrick Mckinley’s pagination example with source looks interesting.

Comments Off