Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
434 lines (313 sloc) 13.9 KB
mathblog is a Haskell program targeted at people who want to write
statically-generated, mathematically-themed weblogs. It supports:
- high-quality, scalable inline and block-level TeX math, rendered by
- embedded Gnuplot scripts for rendering graphs
- Extended Markdown input syntax as supported by the Pandoc library
- Integration of Javascript-based web services such as Disqus
- Template-based document rendering with support for layout and style
Project vision
I wrote mathblog with a very specific set of requirements in mind,
motivated by the following principles:
- a blog should be easy to create, host, and update.
- a blog should be easy to maintain.
- I should be able to edit posts in my editor of choice and write
them in an intelligent textual markup language.
- It should be easy to embed high-quality mathematical symbols and
equations in the blog posts.
As a result, mathblog has the following properties:
- the software is composed of a single executable which will
automatically take care of creating your blog and regenerating
pages when your post markup changes.
- all content is stored in plain text files and is generated
statically. No database or web framework is used.
- a mathblog can be hosted with a simple static fileserver such as
thttpd, lighttpd, or apache.
- blog posts are written in the Markdown format with extensions, as
supported by the Pandoc document converter.
- Math is embedded with $...$ or \(...\) for inline math and $$...$$
or \[...\] for block-level math.
These properties have some nice advantages; your blog content is
cacheable and can be subjected to revision control. Posts are easy to
edit and editing doesn't require a web browser. The static file
representation model means you can compose a blog post on your laptop
and get it just right using a local installation of mathblog, then
push it up to your server to post it to your public blog.
mathblog takes advantage of three primary software components:
- pandoc, a document-processing library. For best results, use the
revision control version of Pandoc. If you do not, inline and
block-level equations will look the same.
- MathJax, a JavaScript package for scalable, cross-browser Math
typesetting. You can get it from See below
for details on setting up MathJax with mathblog. mathblog has been
tested with MathJax 1.0.1.
How to use
To begin, set the following environment variable:
This is the location of your blog files on the filesystem. It must be
an absolute path.
Once you've set the environment variable, just run "mb". It will take
care of setting up a new blog data directory for you, complete with
some default pages and a default first blog post:
$ export MB_BASE_DIR=`pwd`/myBlog
$ mb
Blog directory: .../myBlog
Setting up data directory using skeleton: /.../skel
Configuration file changed; regenerating all content.
Templates changed; regenerating accordingly.
Posts changed:
Post index changed; regenerating next/previous links.
Rendering first-post
Now you have a blog; next, we need to install MathJax to get the math
rendering working.
Installing MathJax
First, download MathJax. mathblog has been tested with MathJax 1.0.1;
if it works with newer versions, please let me know!
The default mathblog templates expect MathJax to be installed into the
`html` subdirectory of your blog data directory; you can certainly
change that, but these instructions will assume that configuration.
The zip file you downloaded should include just a "MathJax" directory
with all of the MathJax files contained inside. You have two options
for installation:
- You can unzip the zip file into the HTML directory, resulting in a
"MathJax" subdirectory of the "html" directory. This is the most
direct option, but it has the disadvantage that all of the MathJax
files will now be in your blog data directory; this is perhaps not
what you want if, for example, you are keeping your blog data files
under revision control.
cd html && unzip /path/to/
- Unzip the MathJax files elsewhere and create a "MathJax" symlink in
your "html" subdirectory.
cd html && ln -s /path/to/MathJax/
The default mathblog templates include a MathJax configuration which
will override the default configuration provided in the MathJax
distribution. See the MathJax documentation if you want to customize
that configuration.
Viewing the Blog
Now that MathJax is set up, we need to make some configuration
(NOTE: to serve your blog files you can either make the "html"
directory a document root for your web server or virtual host, or you
can symlink the "html" directory to the location of choice. The
mathblog directory itself is not intended to be in your web server's
document tree because it contains many files that shouldn't be served
to users.)
The default blog configuration file is called "blog.cfg". This file
contains information about you which may be included in the generated
pages, such as your name, e-mail address (used for the RSS feed only),
and the title of your blog. Most importantly, this file contains the
base URL of your blog which is used to generate URLs in the blog's
pages and MathJax scripts.
Once you've updated your configuration, feel free to start up a web
server pointing at the "html" directory and take a look; MathJax
should be working, as the default first post shows.
Now you might want to edit or create a new post, or even remove one.
Just edit the appropriate file in posts/ accordingly and re-run mb.
Here's an example of adding a new post:
$ mb
mb: using base directory ".../myBlog"
Posts changed:
Rendering 1 post(s)...
Rendering first-post
When to run mb
mb looks at the modification times of your post files in posts/, the
config file, template files, and the post index (see below) when
determining when to regenerate content. It also looks for new posts
that haven't been rendered in the past. The rule of thumb is: re-run
mb whenever you make any changes to:
- templates in templates/
- post files in posts/
- the post index, posts/posts-index
- blog.cfg
Modifying a post will cause that post to be re-rendered, but
modifiying the configuration file will cause ALL posts to be
re-rendered (since the configuration file contains values that will
affect all hyperlinks contained inside each post). mb will always
rebuild the portions of each page affected by template changes even if
post source files are unchanged.
Configuration File Fields
The configuration file "blog.cfg" must have the following fields set:
The base URL of your blog; this URL will be used to generate all
links in the blog's pages.
The title of your blog, such as "My math blog".
Your name (for the RSS feed metadata).
Your e-mail address (for the RSS feed metadata).
All of the above fields can be accessed in templates using the syntax
described in "Customizing your blog" below.
Post format
Posts are formatted in Markdown and support the extended Markdown
syntax as implemented by Pandoc. The only important convention to
note is that the post title goes on the first line of the file
following a percent sign, as follows:
%My First Post
First paragraph starts here.
Running mb in "listen" mode
Ordinarily, you'll just run "mb" once in a while to update your
content. But if you're in the middle of authoring a new post and you
want to see what it looks like as you edit it rather than run "mb" by
hand periodically, you can run "mb" in "listen" mode; this means that
mb will run forever, peroidically scanning the filesystem for changes
to your blog posts and other data files and regenerate them when it
detects a change. Running mathblog in listen mode is simple:
$ mb -l
Blog directory: /.../blog
Post index changed; regenerating next/previous links.
Blog directory: /.../blog
Configuration file changed; regenerating all content.
Rendering 1 post(s)...
Rendering first-post
Blog directory: /Users/cygnus/blog3
Posts changed:
Rendering 1 post(s)...
Rendering first-post
Above I ran "mb" in listen mode and then modified the post index, then
the blog config file, then one of the posts. In each case "mb"
detected the change and ran its typical regeneration routine.
Customizing your blog
It's likely that you'll want to customize the look and feel of your
blog. To this end, mathblog generates the pages of your blog by
assembling various pieces of the page to create the final result. The
biggest piece of a generated page is the blog post itself, but the
surrounding elements are read from various files that are created by
mathblog when it creates your blog data directory. These files are
stored in the "templates/" subdirectory of your blog data directory
and are as follows:
This is the template used to generate your RSS feed.
This file makes up the overall structure of every page on the
This file makes up the structure of the post portion of the page,
for pages which show posts (i.e., not the post index).
In addition, subdirectories of the "html/" directory contain things
you might want to customize, such as a CSS stylesheet.
The templates mentioned above are StringTemplate templates and are
processed with the HStringTemplate library. The following template
placeholders are supported in each template:
These placeholders all correspond directly to fields on the
blog.cfg configuration file.
These placeholders are supported in the post template:
A brief javascript used to provide information about the page to
other javascripts (see "Other features" below for usage).
HTML displaying the "next" and "previous" links for older/newer
The body of the post itself.
These placeholders are supported in the page template:
The content of the page to be rendered.
Gnuplot Graph Embedding
mathblog supports embedding gnuplot scripts in blog posts. To do
this, we overload the Pandoc code block syntax. Here's an example:
~~~ {#eq-basic}
f(x) = x
plot [-5.0:5.0] [-5.0:5.0] f(x) lt rgb "blue"
This defines a single function and plots it in blue over the specified
intervals. The most important part is the "#eq-basic" bit: this
specifies the equation preamble to use when generating the output
image. This string refers to this preamble file in your blog
This file contains the commands responsible for determining the output
image size and axis configuration. The contents of the code block
that you write get appended to the contents of the preamble file you
specify to result in the full gnuplot script, whose output gets
embedded in the page. We use these templates to make it easier to
create many graphs that have the same general structure (e.g., axis
configuration, image size) without having to repeat the full gnuplot
script each time.
You can create other gnuplot premables to suit your needs; just
reference them in the code block in the same way. For example, you
might create eq-preambles/eq-fancy.txt, in which case the code block
syntax to use it is:
~~~ {#eq-fancy}
<your script here>
Note that the pandoc syntax also allows us to assign CSS class names
to the code block, and mathblog passes these through to the generated
image. So if you wanted to wrap your text around the generated image,
you could create a CSS class like this:
.eq-right {
float: right;
and then assign it to your equation graph like this:
~~~ {#eq-basic .eq-right}
For more information on the code block syntax, please see:
Other features
Since mathblog doesn't provide many moving parts, it's up to you to
outsource various web site features, such as comments. I've
successfully integrated mathblog with the Disqus comments service. To
do this, some javascript needs to be embedded in the blog pages.
Disqus works best when you supply it with a page identifier so it can
guarantee that comments are post-specific rather than URL-specific.
The way mathblog makes this possible is by exposing a JavaScript
variable to other scripts in your page:
Blog.pageName = "foobar-baz";
This variable name can be used by scripts you embed, such as with
Disqus comment forms:
var disqus_identifier = Blog.pageName;
Controlling Post Order
Whenever you add a new post, mb automatically updates the "post
index", a file called "posts-index" in the post source directory.
This file lists the filenames of all posts from newest to oldest. By
default, new posts get added to the beginning of the list, as you
would expect. Any new posts added to the list are sorted by
modification time so that the newest post on disk appears earlier in
the index. This feature exists to make it possible for older posts to
be updated without changing their ordering in the overall sequence of
At any time, you can edit the index to reorder the posts as you see
fit. mb will preserve ordering of posts already in the index when you
run it in the future.
mb will also take care of removing posts from the index if they've
been removed from the post source directory.
I personally use this software package but I'll be pleased if others
find it useful. In addition, I'm open to accepting contributions on
the project if they're consistent with what I've outlined above.
Happy blogging!
Jonathan Daugherty