What is Yaydoc?
Yaydoc aims to be a one stop solution for all your documentation needs. It is continuously integrated to your repository and builds the site on each commit. One of it’s primary aim is to minimize user configuration. It is currently in active development.
Why Themes?
Themes gives the user ability to generate visually different sites with the same markup documents without any configuration. It is one of the many features Yaydoc inherits from sphinx.
Now sphinx comes with 10 built in themes but there are much more custom themes available on PyPI, the official Python package repository. To use these custom themes, sphinx requires some setup. But Yaydoc being an automated system needs to performs those tasks automatically.
To use a custom theme which has been installed, sphinx needs to know the name of the theme and where to find it. We do that by specifying two variables in the sphinx configuration file. html_theme and html_theme_path respectively. Custom themes provide a method that can be called to get the html_theme_path of the theme. Usually that method is named get_html_theme_path . But that is not always the case. We have no way find the appropriate method automatically.
So how do we get the path of an installed theme just by it’s name and how do we add it to the generated configuration file.
The configuration file is generated by the sphinx-quickstart command which Yaydoc uses to initialize the documentation directory. We can override the default generated files by providing our own project templates. The templates are based on the Jinja2 template engine.
Firstly, I replaced
html_theme = ‘alabaster’
With
html_theme = ‘{{ html_theme }}’
This provides us the ability to pass the name of the theme as a parameter to sphinx-quickstart. Now the user has an option to choose between 10 built-in themes. For custom themes however there is a different story. I had to solve two major issues.
- The name of the package and the theme may differ.
- We also need the absolute path to the theme.
The following code snippet solves the above mentioned problems.
{% if html_theme in (['alabaster', 'classic', 'sphinxdoc', 'scrolls', 'agogo', 'traditional', 'nature', 'haiku', 'pyramid', 'bizstyle']) %} # Theme is builtin. Just set the name html_theme = '{{ html_theme }}' {% else %} # Theme is a custom python package. Lets install it. import pip exitcode = pip.main(['install', '{{ html_theme }}']) if exitcode: # Non-zero exit code print("""{0} is not available on pypi. Please ensure the theme can be installed using 'pip install {0}'.""".format('{{ html_theme }}'), file=sys.stderr) else: import {{ html_theme }} def get_path_to_theme(): package_path = os.path.dirname({{ html_theme }}.__file__) for root, dirs, files in os.walk(package_path): if 'theme.conf' in files: return root path_to_theme = get_path_to_theme() if path_to_theme is None: print("\n{0} does not appear to be a sphinx theme.".format('{{ html_theme }}'), file=sys.stderr) html_theme = 'alabaster' else: html_theme = os.path.basename(path_to_theme) html_theme_path = [os.path.abspath(os.path.join(path_to_theme, os.pardir))] {% endif %}
It performs the following tasks in order:
- It first checks if the provided theme is one of the built in themes. If that is indeed the case, we just set the html_theme config value to the name of the theme.
- Otherwise, It installs the package using pip.
- Now __file__ has a special meaning in python. It returns us the path of the module. We use it to get the path of the installed package.
- Now each sphinx theme must have a file named `theme.conf` which defines several properties of the theme. We do a recursive search for that file.
- We set html_theme to be the name of the directory which contains that file, and html_theme_path to be it’s parent directory.
Now let’s see everything in action. Here are four pages created by Yaydocs from a single markup document with no user configuration.
Now you can choose between many of the themes available on PyPI. You can even create your own theme. Follow this blog to get more insights and latest news about Yaydoc.