Blogging with org-mode and jekyll without alien yaml headers.
Let org2jekyll export your org-mode file to jekyll.
What’s the difference with org-jekyll?
You don’t need to add some alien yaml in your org-mode file. You add specific org-mode headers and this will be used to format the jekyll post.
What’s the difference with happyblogger?
Only emacs’ dependencies (org, etc…) no external ruby script.
- org-mode rocks
- Github uses Jekyll
- Jekyll is nice
- Existing solutions regarding org-mode and jekyll needs the org-mode files to be altered with non-org notations to work together
- I don’t want to alter my org-mode files with alien yaml headers to satisfy jekyll
Enters org2jekyll.
You have:
- your *org-publish* setup ready (mine for example)
- a running jekyll installation
Available only on marmalade for the moment. Update your packages archive with marmalade:
(require 'package)
(add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages") t)
(package-initialize)
M-x package-install RET org2jekyll RET
M-x customize-group RET org2jekyll RET
Here is an example of my configuration for my blog site:
(require 'org)
(require 'org2jekyll)
(custom-set-variables '(org2jekyll/blog-author "ardumont")
'(org2jekyll/source-directory (expand-file-name "~/org/"))
'(org2jekyll/jekyll-directory (expand-file-name "~/public_html/"))
'(org2jekyll/jekyll-drafts-dir "")
'(org2jekyll/jekyll-posts-dir "_posts/")
'(org-publish-project-alist
`(("default"
:base-directory ,(org2jekyll/input-directory)
:base-extension "org"
:publishing-directory ,(org2jekyll/output-directory)
:publishing-function org-html-publish-to-html
:headline-levels 4
:section-numbers nil
:with-toc nil
:html-head "<link rel=\"stylesheet\" href=\"./css/style.css\" type=\"text/css\"/>"
:html-preamble t
:recursive t
:make-index t
:html-extension "html"
:body-only t)
("post"
:base-directory ,(org2jekyll/input-directory)
:base-extension "org"
:publishing-directory ,(org2jekyll/output-directory org2jekyll/jekyll-posts-dir)
:publishing-function org-html-publish-to-html
:headline-levels 4
:section-numbers nil
:with-toc nil
:html-head "<link rel=\"stylesheet\" href=\"./css/style.css\" type=\"text/css\"/>"
:html-preamble t
:recursive t
:make-index t
:html-extension "html"
:body-only t)
("images"
:base-directory ,(org2jekyll/input-directory "img")
:base-extension "jpg\\|gif\\|png"
:publishing-directory ,(org2jekyll/output-directory "img")
:publishing-function org-publish-attachment
:recursive t)
("js"
:base-directory ,(org2jekyll/input-directory "js")
:base-extension "js"
:publishing-directory ,(org2jekyll/output-directory "js")
:publishing-function org-publish-attachment
:recursive t)
("other"
:base-directory ,(org2jekyll/input-directory "css")
:base-extension "css\\|el"
:publishing-directory ,(org2jekyll/output-directory "css")
:publishing-function org-publish-attachment
:recursive t)
("website" :components ("default" "post" "images" "js" "css")))))
source: https://github.com/ardumont/blog-pack/blob/master/blog-pack.el#L13-L71
default and post are important entries which represent the possible jekyll layouts you use in your jekyll installation.
- blog: http://ardumont.github.io/
- jekyll exported source: https://github.com/ardumont/ardumont.github.io
- the org files: https://github.com/ardumont/org.git
Note Yes, I may have to merge the last 2 repositories at some point…
For a post (layout ‘post’) or page (layout ‘default’), add org headers (layout, title, author, date, description, categories) to your org files.
For a post (layout ‘post’):
#+STARTUP: showall
#+STARTUP: hidestars
#+OPTIONS: H:2 num:nil tags:nil toc:nil timestamps:t
#+LAYOUT: post
#+AUTHOR: ardumont
#+DATE: 2014-12-19 Fri 23:49
#+TITLE: hello
#+DESCRIPTION: some description
#+CATEGORIES: category0, category1
Note To easily do that, M-x org2jekyll/create-draft!, this will ask you for everything needed and create a file with such metadata.
Now write your article in org-mode.
When ready, M-x org2jekyll/publish! to publish it.
This will be published as post article.
- The #+LAYOUT entry refers to the post entry in org-publish-project-alist.
- This will create another temporary org-mode file based on the current one with the right naming convention, transform the org headers into yaml, publish to the jekyll directory (according to your org-publish setup) and delete the temporary file.
For a page (layout ‘default’).
#+STARTUP: showall
#+STARTUP: hidestars
#+OPTIONS: H:2 num:nil tags:nil toc:nil timestamps:t
#+LAYOUT: default
#+AUTHOR: ardumont
#+DATE: 2014-12-19 Fri 23:49
#+TITLE: hello
#+DESCRIPTION: some description
#+CATEGORIES: some-category
Note To easily do that, M-x org2jekyll/create-draft!, this will ask you for everything needed and create a file with such metadata.
Now create your article and publish it when ready M-x org2jekyll/publish!.
Write your page. When ready, M-x org2jekyll/publish! to publish it.
- The #+LAYOUT entry refers to the default entry in org-publish-project-alist.
- This will update the current org-mode with the necessary yaml and publish to the jekyll directory (according to your org-publish setup), then revert back to your normal org-mode file.
M-x org2jekyll/publish-posts!
Depending on your org-publish configuration and org2jekll, this will compulse the list of org-mode posts (#+LAYOUT with ‘post’ value) and publish them.
M-x org2jekyll/publish-pages!
Depending on your org-publish configuration and org2jekll, this will compulse the list of org-mode pages (#+LAYOUT with ‘default value) and publish them.
org2jekyll proposes you a minor with the following default binding:
(setq org2jekyll-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c . n") 'org2jekyll/create-draft!)
(define-key map (kbd "C-c . p") 'org2jekyll/publish-post!)
(define-key map (kbd "C-c . P") 'org2jekyll/publish-posts!)
(define-key map (kbd "C-c . l") 'org2jekyll/list-posts)
(define-key map (kbd "C-c . d") 'org2jekyll/list-drafts)
map))
Note Respecting the default minor mode convention for binding
To (de)activate this in an org file: M-x org2jekyll-mode
As usual, you can use emacs’ power to setup your own bindings.