Yaydoc which uses Sphinx Documentation Generator internally needs a document named index.rst describing the overall layout of the documentation to generate a proper table of contents. Without an index.rst present, the build fails. With this week’s update that constraint has been relaxed. Now if yaydoc detects that index.rst has not been supplied, it automatically generates a minimal index for basic use. Although it is still recommended to provide your own index, you won’t be punished for its absence. The following sections show how this was implemented and also shows this feature in action.
Implementation
For generating a minimal index.rst, we perform the following steps:
- If the repository has a README.rst or a README.md, we include it in the index
- Several toctrees are generated as per how the documents in the repository are arranged.
The following code snippet returns a valid rst block which includes the document dirpath/filename
def get_include(dirpath, filename): ext = os.path.splitext(filename)[1] if ext == '.md': directive = 'mdinclude' else: directive = 'include' template = '.. {directive}:: {document}' path = os.path.relpath(os.path.join(dirpath, filename)) document = path.replace(os.path.sep, '/') return template.format(directive=directive, document=document)
The following code snippet returns a valid rst block which creates a toctree of dirpath.
def get_toctree(dirpath, filenames): toctree = ['.. toctree::', ' :maxdepth: 1'] caption_template = ' :caption: {caption}' content_template = ' {document}' caption = os.path.basename(dirpath).replace('_', ' ').title() if caption == os.curdir: caption = 'Contents' toctree.append(caption_template.format(caption=caption)) # Inserting a blank line toctree.append('') valid = False for filename in filenames: path, ext = os.path.splitext(os.path.join(dirpath, filename)) if ext not in ('.md', '.rst'): continue document = path.replace(os.path.sep, '/') document = document.lstrip('./').rstrip('/') toctree.append(content_template.format(document=document)) valid = True if valid: return '\n'.join(toctree) else: return ''
The following code snippet walks the documentation directory and returns a valid content to be written to index.rst.
def get_index(root): index = [] # Include README from root root_files = next(os.walk(root))[2] if 'README.rst' in root_files: index.append(get_include(root, 'README.rst')) elif 'README.md' in root_files: index.append(get_include(root, 'README.md')) # Add toctrees as per the directory structure for (dirpath, dirnames, filenames) in os.walk(os.curdir): if filenames: toctree = get_toctree(dirpath, filenames) if toctree: index.append(toctree) return '\n\n'.join(index) + '\n'
Result
Let’s assume that a sample project has the following directory tree for documentation.
+---_README.md +---_docs/ | +---_installation_guide/ | | +--- setup_heroku.md | | +--- setup_docker.md | +---_tutorial/ | | +--- basic.md | | +--- advanced.md
The following index.rst would be generated from the above tree
.. mdinclude:: ../README.md .. toctree:: :caption: Installation Guide :maxdepth: 1 setup_heroku setup_docker .. toctree:: :caption: Tutorial :maxdepth: basic advanced
As you can see, this index.rst would be enough for most use cases. This update decreases the entry barrier for yaydoc. More features are on the way.