A Jekyll and Bootstrap framework for publishing a book online in multiple formats.
This project was forked from travist/jekyll-kickstart, a nice framework for starting a clean Jekyll site with minimal Bootstrap. Jekyll-Book extends it with a set of plugins, include files and conventions to support a book-like publication. A set of Markdown files are rendered into a sequence of interlinked pages, and also into a single PDF (and other output files) for downloading.
An example project: Github repo; public site
- Install Ruby (requires 2.0 or later)
- Install Pandoc (with LaTeX support)
- Clone this repository
- In the repository directory, run
bundle install
to install the necessary gems - Run
jekyll s
to start the server - Visit the demo site at http://127.0.0.1:4000/path/to/work/
The bibliographic metadata for the book is entered in _config.yml
:
title: Title of Book
brand: Title of Book
subtitle: Book has a subtitle
author: Mary Author
date: 1918
description: >
Author, Title (Place: Publisher, Year)
# description_latex is included in the PDF, so it uses LaTeX formatting
description_latex: >
Author, \textit{Title} (Place: Publisher, Year)
editor: Jim Editor
twitter: "@mytwitterhandle" # included
license_icon: publicdomain # specified image in assets directory
license_text: "To the extent possible under law, Jim Editor has waived all copyright and related or neighboring rights to \"Title of Book\". This work is published from: Canada."
# link back to this site in PDF; or just delete this line
jb_credit_latex: "Generated with jekyll-book ¶ \\href{https://github.com/pbinkley/jekyll-book}{https://github.com/pbinkley/jekyll-book}"
# Info for CC license vcard in _includes/license.html
publisher_url: "http://www.domain.com/publisher/"
country_name: Canada
country_code : CA
The full citation should also be added to _includes/citation.html
.
Content files belong in the sections
directory. They will be rendered according to the alphabetical order of file names, so they should be named accordingly.
Each file should have a YAML metadata header:
---
layout: section # invokes _layouts/section.html
title: "Chapter 2: Tables" # used in HTML head, jumbotron div, etc.
permalink: 02-chapter2.html # name of rendered file
id: s02 # used as id of article element, for chapter-
# specific CSS
group: sections # grouping in dropdown menus
---
The approach jekyll-books takes is to try to make the Markdown-to-HTML transformation work without intervention, and then to tweak the other transformations as needed. There are a few things, though, that get tweaked on the way to the HTML site. For example: to look good in the PDF, the Markdown files should begin with a second-level header title:
## Chapter 2: Tables
This will appear in all of the downloadable versions. In the HTML, though, we want to suppress it, since the chapter title appears in the jumbotron
div above the article
div (and is drawn from the title
property in the page's YAML block). Removing it is done in the _layouts/section.html
template:
<article id="{{ page.id}}" class="post-content">
{{ content
| replace_regex: '<h2.*</h2>', '', true
}}
</article>
The content of the article (which has already been rendered into HTML) is passed to the replace_regex method (defined in _plugins/replace.rb
), which replaces the first occurence of an h2
heading with an empty string. More replacement operations could be chained together as needed.
In addition to generating an HTML site in the normal Jekyll way, jekyll-book generates a set of downloadable files such as a PDF, containing the full text of the book. These downloads are generated by pandoc
; the full set of formats and the commands used to generate them are defined in the downloads
section of _config.yml
:
downloads:
pdf:
deps: ["_config.yml","_latex/jekyll-book.latex","_scripts/preprocess.rb"]
command: "cat _config.yml sections/*.md | _scripts/preprocess.rb | pandoc --latex-engine=xelatex --template=_latex/jekyll-book.latex -f markdown+pipe_tables+footnotes -o %{dirDownloads}/%{slug}.pdf"
epub:
deps: ["_config.yml","_epub-metadata.yml","assets/cover.jpg"]
command: "pandoc -S --epub-cover-image=assets/cover.jpg --epub-metadata=_epub-metadata.yml -f markdown+pipe_tables+footnotes sections/*.md -o %{dirDownloads}/%{slug}.epub"
md:
deps: ["_config.yml"]
command: "pandoc sections/*.md -t plain -o %{dirDownloads}/%{slug}.txt"
txt:
deps: ["_config.yml"]
command: "pandoc sections/*.md -o %{dirDownloads}/%{slug}.md"
(These commands work in a *nix environment; they may need tweaking to run under Windows.) The generating of download files is handled by _plugins/renderdownloads.rb
, which determines which downloads need to be regenerated and runs the appropriate commands. The basename for these files (%{slug}
) is computed by slugifying the brand
property specified in _config.yml
.
New downloads are generated if the content or any of the dependencies (specified in the deps
property) have been added, deleted or modified. The state of these files is tracked the same way git
does, with SHA1 hashes stored in _data/previousrun.yml
(the timestamp is not used). Preventing redundant regeneration allows users to avoid downloading newly-generated download files that are identical to the previous version. This is particularly important for the PDF, which includes a timestamp on the title page and therefore would appear to be a substantially new version when in fact nothing has changed but the timestamp.
Pandoc uses LaTeX to generate PDFs, and jekyll-book uses a slightly customized LaTeX template: _latex/jekyll-book.latex
. Most of the customization is there to generate an informative title page using metadata properties drawn from _config.yml
. To enable this, _config.yml
is passed as the YAML metadata block for the concatenated sequence of Markdown files.
The concatenated Markdown is fed through _scripts/preprocess.rb
. This script strips out the files' own YAML blocks, since we only want the _config.yml
block to be present. It can be extended to make other changes, especially by substituting or adding LaTeX strings to achieve particular formatting effects. For example, a project that required certain paragraphs to be right-justified specified them in HTML in the raw Markdown:
<p class="right">LC</p>
This was handled by preprocess.rb
like this:
if /<p class=\"right\".*/.match(line)
print "\\rightline{" + /\>(.*)\</.match(line)[1] + "}\n"
Giving the output:
\rightline{LC}
Obviously, these hacks go beyond "the simple, clear, ASCII email inspired spirit of Markdown" and should be kept to a minimum.
The EPUB generator hasn't had much attention yet but should be enhanced in the same way that the PDF one has, to make better use of the metadata and provide a better-looking template.
The following javascript and CSS libraries are included:
- jQuery
- jQuery Easing
- jQuery Fragment Scroll (forked and modified to handle incoming url fragments)
- Bootstrap
Other dependencies are listed in the Gemfile.