test-jekyll-themes
Test Jekyll themes for GitHub Pages, especially LaTeX
Github Pages
References:
- GitHub Pages homepage: pages.github.com
- Working With Github Pages
- YouTube Video Intro (4 min)
- Setting up a GitHub Pages site with Jekyll
There are two types of GitHub Pages:
username.github.io
: A user's GitHub Pages. It is a separate repo of the same name i.e.username.github.io
. For example, if your username isjraman
, then create a repo namedjraman.github.io
.- GitHub Pages for an existing repo (aka project). You will configure this in Settings--scroll down the "GitHub Pages" section
There are multiple ways to configure:
- Using the
master
branch in the root directory. - Using the
master
branch in thedocs/
directory. - Using a
gh-pages
branch. Prior to August 2016, it used to be that this was the only way to configure GitHub Pages for repos, but not anymore. See this GitHub blog.
In this repo we will use the docs/
director (aka folder).
Software Stack
- ruby -- interpreter for Ruby, a high-level programming language (Jekyll is written in Ruby as is kramdown).
- rbenv -- a Ruby version manager. Used to install and activate Ruby versions.
- gem (RubyGems) -- a
package manager for Ruby. Python equivalent:
pip
. A Ruby module is also called a Gem--get it? :). - bundle (Bundler) -- Ruby application dependency manager
i.e. manages packages required for an application. Python
equivalent to
bundle install
:pip install -r requirements.txt
.bundle
can also execute a Ruby script in a specific enviroment, whilepip
does not. - Jekyll -- Ruby package for static site generation and maintenance.
- kramdown -- Ruby library for parsing and converting a superset of Markdown. Also supports LaTeX in Markdown. In addition to HTML, kramdown also converts to LaTeX, kramdown, etc.
- Markdown -- a lightweight markup language.
- MathJax Demos
- HTML -- a heavyweight markup language. It stands for HyperText Markup Language.
As you can see, there's lots of languages, types of languages, installers, and package managers in play here.
rbenv -- Ruby version manager
Check rbenv
installation:
# Run rbenv-doctor
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash
# You may need to run which the following adds ~/.rbenv/shims to PATH and does other things.
$ eval "$(rbenv init -)"
# Display available ruby version. * = active version.
$ rbenv versions
* system
2.7.0 (set by ~/.rbenv/version)
# Set the global ruby version
$ rbenv global 2.7.0
# Check
$ rbenv version
2.7.0
$ ruby -v
2.7.0
gem -- RubyGems program, package manager
- Documentation: rubygems.org
gem
, the RubyGems program, is a command-line utility to install Ruby packages. It "is a sophisticated package manager for the Ruby programming language" (from thegem
manpage).- For gems with executables ruby installs a wrapper file. The
wrapper allows you to choose among alternate gem versions using
version. For example
rake _0.7.3_ --version
will run rake version 0.7.3 if a newer version is also installed.
Bundler - dependency and environment manager
- bundler.io
- Some similarities to virtualenv, in that they both make available the desired versions of the packages.
Jekyll
Jekyll is a static site generator written in Ruby originally by Tom Preston-Werner, GitHub's co-founder in 2008. It is especially suited for blogs (pages with title and date).
- It provides a template directory structure for blogs and articles.
- Content is written by the user primarily in Markdown.
- It also processes Textile, a lightweight markup language, and Liquid, a template language).
- Many themes exist including officially supported ones and those written by other folks.
- A Jekyll server, when run, automatically processes files as they are modified which may make it easier to develop.
- Jekyll homepage: https://jekyllrb.com/
Jekyll Structure and Functionality
- Config is in
_config.yml
. Search on github:extension:yml filename:"_config.yml" language:YAML
. - YAML front matter to the top of any Markdown or HTML file: to set variables, title, layout, and other metadata.
- Theme files location:
bundle info --path minima
orbundle info --path <theme>
- Empty commit to trigger a Jekyll build on the server:
git commit --allow-empty -m "Force rebuild of site"
Jekyll Installation
We follow instructions from GitHub's page titled Creating a GitHub Pages site with Jekyll. Steps are detailed below.
From the GitHub Dependency page,
we find that we need Jekyll 3.8.5. We first install the latest
bundler
and then install the required version of Jekyll.
$ gem install bundler
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Done installing documentation for bundler after 1 seconds
1 gem installed
# The GitHub Dependency page specifies version 3.8.5
# https://pages.github.com/versions/
$ gem install jekyll -v 3.8.5
Successfully installed jekyll-3.8.5
Parsing documentation for jekyll-3.8.5
Done installing documentation for jekyll after 0 seconds
1 gem installed
$ mkdir docs
$ cd docs
# Note the underscores
$ jekyll _3.8.5_ new .
# Check the version of jekyll
$ bundler exec jekyll -v
jekyll 3.8.5
# Start the server, which also monitors and compiles any changes to files on disk.
$ bundle exec jekyll serve
After git push
ing the files, and configuring the
Settings to publish from the master branch, /docs
folder (aka directory), you should see a basic site at
<username>.github.io/<repo>
. For this project, it is
jraman.github.io/test-jekyll-themes/.
Open the Gemfile that was created and follow the instructions in the Gemfile's comments to use GitHub Pages.
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
Accordingly, we
- Comment the
gem "jekyll"
line. - Uncomment the
gem "github-pages"
line. bundle install
. This will print out error messages (in red) and recommend runningbundle update
.- Run the command
bundle update
.
We also update the baseurl
in _config.yml
to
/test-jekyll-themes
. And push this and the above changes to GitHub.
That's it!
To view whether the change you pushed has been deployed, go to the
environment
tab, which takes you to a deployments
page.
Trying out different themes
We maintain separate branches for the different themes, as they may have different configurations and what not.
A useful feature of git is to move (-m
) and copy (-c
) branches.
The capitalized version, -M
and -C
, force move and force copy,
respectively.
We will try the following methodology:
- To make changes for an existing theme: make changes to the branch with the required theme, then force copy the theme branch to the master branch.
- To create a new theme branch: create your new branch off of master. You could force copy the minimal branch, or whatever branch you wish, to master, before branching off of it.
- We want to maintain a canonical list of pages across all branches. This may prove to be cumbersome.
git branch -C theme1 master
git branch -C theme2 master
Themes officially supported by GitHub are here.
Directory Structure
The directory structure of your Jekyll files (for example, in docs/
)
looks something like:
|---_config.yml
|---404.html
|---about.md
|---index.md
|---_posts
| |---2020-02-17-welcome-to-jekyll.markdown
|---_site
| |---feed.xml
| (... other files generated by Jekyll that make up the final site)
MathJax
- MathJax Documentation
- Supported LaTeX Commands on MathJax 3.x
- Input types: tex, tex-full, tex-ascii, MathML (mml)
- Output types: CommonHTML (chtml) and SVG.
- Combinations: combine an input with an output. E.g. tex-chtml, tex-svg, etc.
- Configuration for TeX -- including displayMath, inlineMath, macros, etc.
- MathJax vs Kratex: https://www.intmath.com/cg5/katex-mathjax-comparison.php?processor=MathJax
MathJax LaTeX Equations
- For inline, use
$$
start and end demarcators in the same line. - For display, use
$$
demarcators in its own paragraph. - LaTeX block demarcators can be used within the
$$
blocks. Examples include\begin{equation}
(numbered),\begin{equation*}
(unnumbered),\begin{align}
,\begin{cases}
.
MathJax config
Example MathJax config:
<script>
MathJax = {
tex: {
tags: 'none', // none=no eq numbering, ams=AMS numbering (some), all=all equations
inlineMath: [ // start/end delimiter pairs for in-line math
['$', '$'],
['\\(', '\\)']
],
displayMath: [ // start/end delimiter pairs for display math
['$$', '$$'],
['\\[', '\\]']
],
macros: {
RR: '{\\bf R}', // string replacement
bold: ['{\\bf #1}',1] // macro with one parameter
}
}
</script>
Where does this go? Probably in one of the _includes
files for the
theme. For example, in the So-Simple theme, the file "$(bundle info
--path so-simple 2>/dev/null)/_includes/scripts.html" checks if
mathjax is configured for this site and configures and includes the
required mathjax javascript file.
SVG vs cHTML
- SVG is better at rendering equations. Not supported by IE9 and older browsers. And table sizes are fixed (does not change if window is resized).
Example script include:
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>
Test with kramdown:
# output is generated into stdout
$ kramdown _1.17.0_ _posts/2020-02-07-welcome-to-jekyll.markdown
Tags vs Demarcators
kramdown
inserts <script type="math/tex">
blocks in the output
HTML. While this is fine with the older version of MathJax (2.x), the
newer version (3.x) barfs at it. See the script later below to strip
out these <script>
blocks.
http://docs.mathjax.org/en/latest/upgrading/earlier/jsMath.html
If you are generating your jsMath documents programmatically, it would
be better to convert from generating the jsMath <span> and <div> tags
to producing the corresponding MathJax <script> tags. You would use
<script type="math/tex"> in place of <span class="math"> and <script
type="math/tex; mode=display"> in place of <div class="math">. See the
section on How mathematics is stored in the page for more details.
https://github.com/mathjax/MathJax/issues/2220
As specified in the MathJax ticket (#2220), the following script
strips out the <script type="math/tex">
tags which MathJax 3.x is
unable to handle. We create two separate configurations for MathJax
3.x and 2.x. More
here.
{% if site.mathjax3 == true %}
<script>
// MathJax 3.x
MathJax = {
tex: {
tags: 'ams' // none=no eq numbering, ams=AMS numbering (some), all=all equations
},
options: {
renderActions: {
// for mathjax 3, handle <script "math/tex"> blocks inserted by kramdown
find_script_mathtex: [10, function (doc) {
for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
const display = !!node.type.match(/; *mode=display/);
const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
const text = document.createTextNode('');
node.parentNode.replaceChild(text, node);
math.start = {node: text, delim: '', n: 0};
math.end = {node: text, delim: '', n: 0};
doc.math.push(math);
}
}, '']
}
}
}
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
{% endif %}
{% if site.mathjax == true %}
// MathJax 2.x
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
{% endif %}
Flavors:
- tex-svg.js
- tex-mml-chtml.js
References
- Katz, Yehuda. 2010. Clarifying the Roles of the .gemspec and
Gemfile
- When developing a gem, use
gemspec
in yourGemfile
. Do not checkinGemfile.lock
. - When developing an app, checkin both
Gemfile
andGemfile.lock
. YourGemfile
will not be dependent ongemspec
. TheGemfile.lock
file notes the exact versions and sources of every piece of third-party code that was used in the application.
- When developing a gem, use
Theme - Architect
This theme is officially supported by GitHub.
Print out this theme's directory on your computer.
$ bundle info --path jekyll-theme-architect
~/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/jekyll-theme-architect-0.1.1
Note that the _layouts
directory in this theme directory has only one html file, namely default.html
Theme - So Simple
- Instructions
- Documentation
- Difference between
post
andpage
layouts:- post layout has a left column with meta information such as the author, date, categories, etc. Some of them are hyperlinks. page layout does not have this left rail, and hence the page content is wider.
- post layout includes related posts at the end of the page.
- Gotchas:
index.html
, and notindex.md
. If both are present, thenindex.md
overrides.- If the date of the post (in the front matter YAML) is in the future, then the page will not be generated by Jekyll. This might be a good way to start working on a page before publishing it. [Haven't tried this on GitHub].
Layouts:
# Main
default - the main layout. All other page layout are derived from this.
home - derived from page layout.
page - derived from default layout.
post - derived from default layout.
# Pivots
category - derived from page layout.
collection - derived from page layout.
search - derived from page layout.
tag - derived from page layout.
# Collections
categories - derived from page layout.
posts - derived from page layout.
tags - derived from page layout.
Liquid
Liquid tag start with {%
and end with %}
. For a basic explanation
and examples, see Jekyll docs: Order of
interpretation
Example: String variable, with defaults
<html lang="{{ page.lang | default: site.lang | default: 'en-US' }}"
Embed Javascript in Markdown
- StackOverflow: Embed javascript in markdown. Asked May 2010. Answer 2011. Answer 2019.
- Add a newline after the open-tag.
- Escape the close-tag.
<script\>... javascript code...</script\>
. - Modify the layout and add a YAML front matter variable.
<!-- Custom JavaScript files set in YAML front matter --> {% for js in page.customjs %} <script async type="text/javascript" src="{{ js }}"></script> {% endfor %}
# Front matter YAML --- layout: post title: Adding custom JavaScript for a specific post category: posts customjs: - http://code.jquery.com/jquery-1.4.2.min.js - http://yourdomain.com/yourscript.js ---