Sphinx as a Static Site Generator
---------------------------------
In this article, we will take a look at `Sphinx
`_ (specifically Sphinx 1.1.3) as a static
site generator tool. Let's get started.
Installing Sphinx
=================
Installing sphinx is as easy as ``pip install sphinx`` (on Linux and
Windows). ``pip`` will download a bunch of other dependencies (``docutils,
Jinja2, pygments`` as well). Once installed, check whether sphinx is
available to you by typing ``$ sphinx-quickstart`` at the command
line. This should give you a welcome message. We proceed from there in
the next section. (On Windows, if you have added
``C:\Python27\Scripts`` to the Windows ``Path`` variable, the sphinx
commands should be already available to be executed since the
sphinx binaries are also installed in this location).
Creating the Sphinx directory structure
=======================================
Go to your directory (say ``demo``) where you want to create the content of your
static site and execute the ``sphinx-quickstart`` command. It should
display a welcome message and start a wizard asking you various
questions about your new site.
- Root path: Select the default (current directory)
- Source and build directories: default
- Name prefix: Default
- Project name: Your project name (say, "Programming Notes")
- Author name(s): The name of the author(s)
- Project version: 1.0 (say)
- Project release: 1 (say)
- Source file suffix: default (.rst)
- Name of your master document: index
- Epub builder: No
- autodoc, doctest, intersphinx extensions: No
- todo: Yes
- coverage: No
- pngmath: No
- mathjax: Yes
- ifconfig: No
- viewcode: No
- Makefile: Yes
- Windows command file: Yes
The executable now creates a directory structure, and you will see the
directories ``_build, _static, _templates`` and the files ``conf.py,
index.rst, make.bat, Makefile`` created in the current directory for
you.
We will soon understand in detail what each of these are and how we
can start creating content for the site. Before that, type ``make
html`` in the directory where you created the directory
structure. This command builds the HTML for your site, and places
those files in the directory ``html`` under ``_build``. You will notice
that there is a ``index.html`` file in that directory. This is your
`homepage` or the `master page` of your site. Open this file in your
browser. You should see a web page similar to this one:
.. image:: screenshots/screenshot-1.png
:scale: 40
:alt: Homepage
Adding content
==============
Now, we shall see how we can add content to our static site. It is a
two step process:
- Create a new file
- Add it to the ``index.rst`` file
For example, create a new file with the name ``page1.rst`` and add the
following text to it::
Page 1
------
This is a new page
Sub-heading 1
=============
Sub-heading 2
=============
Now, add this page name to the to the file ``index.rst`` which should
then look as follows::
Welcome to Programming Notes's documentation!
=============================================
Contents:
.. toctree::
:maxdepth: 2
page1
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
Now, rebuild the HTML pages using ``make html``. If you reopen (or
refresh) the ``index.html`` page, you will see that it has links to
the contents of ``page1.rst``. The `.. toctree
`_
directive does all the magic of creating the table of contents on
this page, and you can control the depth of the table of contents
using the number after ``:maxdepth``.
Including images
~~~~~~~~~~~~~~~~
Images can be included with the ``.. image`` directive (See `here `_).
Including code samples
~~~~~~~~~~~~~~~~~~~~~~
Including code samples is as easy as this::
print 'A line of Python'
See `this `_ and `this `_ to learn more.
There are of course *directives* for pretty much everything that you
may need.
ReStructuredText
~~~~~~~~~~~~~~~~
The content of ``index.rst`` (and other pages) is created in plain
text using a markup syntax known as *reStructuredText*. A primer can
be found `here `_.
Configuration
=============
The default configuration generated by sphinx may well suffice your
needs, but let us spend some time tinkering with it to customise the
HTML output (and in the next section, use sphinx extensions).
``conf.py`` in your static site root directory is a Python file which
contains all the configuration details used by sphinx when you trigger
a build process. There are a number of configuration statements for
LaTex, Unix man page and Windows help file output, which you can
remove, since we only plan to generate HTML output. That will leave
the default and HTML specific configuration options. As you will
notice, this file has been created from your responses to the
``sphinx-quickstart`` command. The ``conf.py`` file after tweaking and
customizing looks like `this `_ (along with the associated
comments; created using `pycco `_).
There are a number of default themes that you can use and you can
create your own too. See `this `_
page for details.
Read all about the options for HTML output `here
`_.
I also changed the ``index.rst`` file to have a different heading.
Rebuild the HTML pages and now the index page looks similar to:
.. image:: screenshots/screenshot-2.png
:scale: 40
:alt: Homepage
Builtin Extensions
==================
`Sphinx extensions `_ extend
Sphinx's functionality in various ways. There are a number of builtin
extensions, two of which we included during the initial setup: `todo`
and `mathjax`.
todo
~~~~
The ``.. todo:`` (`doc
`_)
directive can be used to insert TODO place holder text::
.. todo::
Add text here
To display them in the HTML pages, include the following in
``conf.py``::
# Include todos
todo_include_todos = True
mathjax
~~~~~~~~
Using this extension renders math using `Mathjax
`_. To include math
equations in your pages, use the ``::math`` directive. For example:
`:math:`ax^2+bx+c``, will render the equation as you can see in the
HTML of ``page1.html``. The input language is LaTex. Equation blocks
may be written, like so::
.. math::
ax^2 + bx + c = 0
x_1 = \frac{-b+\sqrt{b^2-4ac}}{2a}
x_2 = \frac{-b-\sqrt{b^2-4ac}}{2a}w
To learn more, see `here `_.
Custom Extensions
=================
Besides the builtin extensions, there are a number of others written
by various authors maintained in the `sphinx-contrib
`_ repository.
You can clone the repository, and install each extension on its own,
or you could use `pip` with the appropriate package name from `PyPI `_.
youtube
~~~~~~~
The `youtube `_
extension allows embedding YouTube videos in your HTML pages. To
install it, go to the `youtube` directory of the ``sphinx-contrib``
clone/download and install the extension using ``python setup.py
install``.
You also have to add this extension to the list of extensions in
``conf.py`` as: ``'sphinxcontrib.youtube'``.
To embed a video, find out its YouTube ID and you are done. For
example, to embed `this
`_ PyCon 2013 Talk by
Doug Hellmann, you would do something like::
.. youtube:: 8vwtgMkqE9o
:width: 640
:height: 480
If you now rebuild your pages, you will see the YouTube video embedded
in that page. For other options supported by this extension, see `here
`_.
googlechart
~~~~~~~~~~~
The `googlechart` extension allows you to render charts and graphs using
`Google chart `_. You can
install it similarly as above and add ``'sphinxcontrib.googlechart'`` to
the list of extensions in ``conf.py``.
For example, the following example from the documentation will render a Venn diagram ::
.. venndiagram::
data: 100, 80, 40, 20, 20, 20, 10
To learn more about this extension, see `here `_.
Publishing
==========
To share your HTML pages on the Internet, you have various options.
Copying the HTML directory
~~~~~~~~~~~~~~~~~~~~~~~~~~
If you already have an account on a web host, simply copy the contents
of the ``html`` sub-directory to an appropriate location of your web
host and you are done.
Read the docs
~~~~~~~~~~~~~
If you are going to store your sphinx root directory in a public
source code repository, you can use `read the docs `_. I highly recommend using this option if you are
going to store your documentation sources in a public repository. Once
you have setup the appropriate hook, your sources would be built
automatically everytime you push a change.
Using GitHub pages
~~~~~~~~~~~~~~~~~~
This is the option I will describe in some detail, since it may be a
little involved and also I haven't tried this yet, myself.
First, create a new *empty* repository with no README on `GitHub
`_. Let's call it `site`. Now, clone the
repository::
git clone https://github.com/amitsaha/site.git
Cloning into 'site'...
warning: You appear to have cloned an empty repository.
Create a ``gh-pages`` branch in your repository and switch to it::
git checkout -b gh-pages
Create an empty file with the name ``.nojekyll``. This is to allow us
to use file and directory names beginning with ``_``, as it tells
Jekyll not to process it. (See `here `_
for the background). You will recall that we have directories such as
``_static`` and ``_templates`` generated by Sphinx in ``html``
directory, and hence we will need to create this file.
::
touch .nojekyll
Now, let us say that you want to store your HTML files in a separate
directory, called ``demo``::
mkdir demo
Now, copy *all* the files and directories in ``html`` directory to this
directory.
Add the ``demo`` directory and ``.nojekyll`` file to Git and commit
the changes::
git add .nojekyll
git add demo
git commit -m "Created .nojekyll and first commit of static HTML"
Now, push the ``gh-pages`` branch to the remote repository::
git push origin gh-pages
Once that is complete, you can now go to the URL:
``http://github-user-name.github.com/site/demo`` to see your pages. See
`this `_ page as an example.
You can of course now have multiple directories in the ``site``
repository and then you can host a different set of static pages.
Conclusion
==========
In this article, I have discussed how Sphinx can be used to create a set
of HTML pages with the ability to embed code, images, YouTube videos
and charts. We created the content in reStructuredText and then used
Sphinx's build tools to convert them into a set of standalone HTML
pages. We also looked at a few ways we could host these pages and make
them available publicly.
The demo Sphinx project can be found in `demo `_.
In a next article, we will focus on creating documentation which is coupled
with a software project and explore Sphinx's various features useful
in such a scenario.