# -*-org-*- #+STARTUP: odd #+OPTIONS: toc:2 #+LINK: google http://www.google.com/search?q=%s #+LINK: rfc http://www.rfc-editor.org/rfc/rfc%s.txt #+LINK: redis http://redis.io/commands/%s #+TODO: TODO(t) | DONE(d) CANCELED(c) POSTPONED #+DRAWERS: PROPERTIES CLOCK LOGBOOK COMMENT #+TITLE: Jekyll with org-mode and twitter bootstrap #+AUTHOR: Seong-Kook Shin #+EMAIL: cinsky@gmail.com #+BEGIN_HTML --- layout: org id: jekyll-org title: Jekyll with org-mode and twitter bootstrap --- #+END_HTML :COMMENT: # Markup hints: # *bold*, /italic/, _underlined_, =code=, ~verbatim~ # Use '\\' at the end of a line to force a line break. # Use "[[URL or TARGET][NAME]]" to create a hyperlink. # Use "[[google:KEYWORD][DESC]]" to link to Google with KEYWORD. # Use "[[rfc:NUMBER][DESC]]" to link to RFC-NUMBER.txt. # `C-c C-o' to follow a link target. # Use "#+BEGIN_VERSE ... #+END_VERBSE" to format poetry # Use "#+BEGIN_QUOTE ... #+END_QUOTE" to format a quotation. # Use "#+BEGIN_CENTER ... #+END_CENTER" to center some text. # `C-c C-x f' for footnote action(jump or insert). # Unordered list items start with `-', `+', or `*' as bulllets. # Ordered list items start with `1.' or `1)'. :END: * Introduction This document describes how to integrate your articles (in Emacs [[http://orgmode.org][org-mode]] format) into [[http://jekyllrb.com/][jekyll]] based HTML site with [[http://twitter.github.com/bootstrap/scaffolding.html][twitter bootstrap scaffolding]] style. Note that this article is heavily influenced by [[http://orgmode.org/worg/org-tutorials/org-jekyll.html][Using org to Blog with Jekyll]]. * Document structure #+BEGIN_SRC text . ├── _plugins # custom Jekyll/Liquid plugins ├── org # Your org files should be placed here ├── src # Jekyll source directory │ ├── _layouts │ └── articles # org generated html files are installed here └── www # Jekyll destination directory └── articles # final destination of your .org based html files #+END_SRC * Usage All your =.org= files should be located in =org/= directory. Since, jekyll requires that all source files that Your =.org= file should have following header. #+BEGIN_HTML
#+BEGIN_HTML
---
layout: org
title: Jekyll with org-mode and twitter bootstrap
---
⁠#+END_HTML
#+END_HTML *** Tested Platform ***** Gentoo Linux - GNU Emacs 24.2.1 (Gentoo package: app-editors/emacs-23) - org-mode version 7.9.3d (package.el: org 20130114) or, ***** Mac (Darwin) - GNU Emacs 24.2 (from [[http://emacsformacosx.com/][here]]) - org-mode version 7.9.1 (package.el: org 201209003) - Gentoo Linux: GNU Emacs 23.2.1, org-mode version 7.9.3d - MacOSX (darwin) 10.8.2: *** Configuration You *MUST* change the value of some keys in =_config.yml=, especially for =bootstrap=, =prettify=, and =jquery=. #+BEGIN_SRC yaml bootstrap: "http://some.place.com/bootstrap" prettify: "http://some.place.com/bootstrap" jquery: "http://some.place.com/bootstrap/js/jquery.js" #+END_SRC You may need to modify both =src/_layouts/default.html= and =src/_layouts/org.html= to reflect the above configuration. For example, =default.html= contains a HTML tags such as: #+BEGIN_SRC html ... #+END_SRC To use make(1) to build your html generation, the jekyll should not create HTTP server; make sure that you have "=auto=false=". To use org-specific Jekyll plugins, make sure that you have "=safe=false=". *** Page format To use custom plug-ins provided in this package, you may need to provide several custom variable in the YAML front matter of each page. To work with =jekyll-org=, it is recommended you provide following variables: - =id=: id of the page, this will be used as the internal identification of the page content. Note that if there are multiple pages written in several languages and their contents are the same, the =id= of these pages should be the same. (mandatory) - =label=: short name of the page, which may be used as the text of some hyperlinks. If omitted, the page =id= will be used for =label= value. (optional) - =title=: title(full name) of the page, which will be used as the text of some hyperlinks. (mandatory) - =lead=: descriptive sentence to describe the purpose of the page. (optional) - =lang=: mnemonic of the page locale. You can omit this variable, if the page is in the your primary language. In this case, =jekyll-org= will treat the page locale to '=en=' (English). So, the full example of the YAML front matter will look like: #+BEGIN_SRC yaml --- layout: default title: Jekyll with Org-mode label: Home id: home lead: static site generated by Jekyll, with org-mode articles --- #+END_SRC *** Additional Plug-ins ***** 'toplink' block To help generating top-level page index, =jekyll-org= provides =toplink= block. =toplink= block will uses the list of page IDs, evaulating the contents in the block multiple times according to the number of elements in =topnav-list= of the =_config.yml= as in the following: #+BEGIN_SRC yaml topnav-list: [ "home", "article", "pg1", "pg2" ] #+END_SRC =toplink= tag accepts five parameters separated by comma('=,=') character. For example: #+BEGIN_HTML {% raw %} #+END_HTML #+BEGIN_SRC html {% toplink id, label, locale, url, self %} ... {% endtoplink %} #+END_SRC #+BEGIN_HTML {% endraw %} #+END_HTML Each parameter name will turn to the variable name which can be used in the =toplink= block. The meaning of the variables are: - 1st parameter (id): id of the page; this is the analogous to the each element in =topnav-list=. - 2nd parameter (label): label of the page; which can be used as the short name of the page. - 3rd parameter (locale): mnemonic of the page locale such as 'en' for English, 'ko' for Korean. If the locale of the evaluating page is the same as the current page, this will be an empty string (=""=). - 4th parameter (url): URL of the page - 5th parameter (self): =true= if the current page is the same as the evaluating page. For example, if you want to create hyperlinks to the top-level pages, you can do this by: #+BEGIN_HTML {% raw %} #+END_HTML #+BEGIN_SRC html #+END_SRC #+BEGIN_HTML {% endraw %} #+END_HTML If you want to remove the hyperlink for the current page, among evaluating pages, you can check the 5th parameter as in the following: #+BEGIN_HTML {% raw %} #+END_HTML #+BEGIN_SRC html #+END_SRC #+BEGIN_HTML {% endraw %} #+END_HTML ***** 'articles' block =articles= block can enumerate pages which has a specified layouts. =articles= block will be evaluated multiple times for each article. The usage is almost the same as =toplink= block. =articles= will accept four parameters, and each meaning of the parameter is: - 1st parameter (layouts): a name of the variable in =_config.yml= where its value is a list of layout names. - 2nd parameter (id): id of the article page - 3rd parameter (title): title of the article page. - 4th parameter (lead): short description of the article page. - 5th parameter (url): URL of the article page - 6th parameter (lang): name of the locale of the article page. (such as "English" or "Korean") If the locale of the current page is the same as the evaluating article page, this will be an empty string (=""=). For example, suppose that you have pages in either "my_article1" layout or "my_article2" layout. To enumerate these pages, you need to specify the list of layouts in =_config.yml= like: #+BEGIN_SRC yaml article_layouts: [ "my_article1", "my_article2" ] #+END_SRC Then, you can enumerate these pages with =article= block like: #+BEGIN_HTML {% raw %} #+END_HTML #+BEGIN_SRC html #+END_SRC html #+BEGIN_HTML {% endraw %} #+END_HTML Or, if you want to insert 'lead' value, use the following: #+BEGIN_HTML {% raw %} #+END_HTML #+BEGIN_SRC html #+END_SRC html #+BEGIN_HTML {% endraw %} #+END_HTML *** Troubleshootings ***** I got additional list bullets on Table of Contents! You may have some problem on the generated table of contents, which looks like following: #+BEGIN_HTML
#+END_HTML The problem is that, your Emacs scripts set =org-odd-levels-only= to =t=, but the batch script, =publish.el= in the package, does not aware of it. To work around this, add "=odd=" in the =STARTUP= keyword. #+BEGIN_SRC org #+STARTUP: odd #+END_SRC ***** I got an error, Symbol's function definition is void: org-version Your Emacs uses out-dated org-version probably 6.x. Install recent org-mode. * Implementation *** Table of Content(TOC) Generation At first, to convert org files into twitter's /scaffolding/ style, I need a way to generate first-level headings into /scaffolding/ way. However, to parse org file directly to gereate /scaffolding/ TOC is somewhat difficult to implement; I briefly overlooked =org-html.el= in org-mode, which is fairly complicated. Since this is just my hobby to publish my own site, I decieded to make a Jekyll/Liquid plugin, that parses the HTML (which org-mode exported) to get the first-level headings, and use Liquid markup to generate /scaffolding/ TOC. Thankfully, org-mode HTML output is fairly simple. Here are an example of HTML that org-mode generated: #+BEGIN_SRC html

Table of Contents

#+END_SRC As you can see, all hyperlink IDs are in the form of =sec-N-M=, so it can be easily extracted with the following regular expression: #+BEGIN_SRC ruby /^ *
  • *(.*?)<\/a>/ #+END_SRC So, I made a /Jekyll/ plugin, which parses the org-generated HTML file, and put the metadata of the each top-level headings in the /Jekyll/ context, so that the /Jekyll/ layout pages can take benefits from the context: #+BEGIN_SRC ruby module Jekyll class OrgToc < Liquid::Block ... def render(context) contents = context['page']['content'] thetoc = [] contents.each_line { |line| m = /^ *
  • *(.*?)<\/a>/.match line if m thetoc.push( { "id" => m[1], "title" => m[2] }) end break if / *
    #+END_SRC #+BEGIN_HTML {% endraw %} #+END_HTML ***** Known Issues However, there are some problems with this approach. In /scaffolding/ page, one of the left-side navigation item is highlighted, depending on the current location of the contents. I cannot make this happen on org-generated page, since the contents generation is handled by /org-mode/, which I cannot control manually. In detail, the /scaffolding/ has following structures: #+BEGIN_SRC html

    ...

    ...

    ...
    #+END_SRC Following is the structure that I implemented: #+BEGIN_SRC html

    Section 1

    ...

    Section 2

    ...
    ...
    #+END_SRC 1. Since the body content itself is generated by /org-mode/, I cannot make the highlighting feature of the navigation bar (in the left side of the page). 2. [[https://github.com/cinsk/jekyll-org/][jekyll-org]]