Source code for sphinxcontrib.devhelp

"""Build HTML documentation and Devhelp_ support files.

.. _Devhelp: https://wiki.gnome.org/Apps/Devhelp
"""

from __future__ import annotations

import gzip
import os
import re
from os import path
from typing import TYPE_CHECKING, Any

from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.locale import get_translation
from sphinx.util import logging
from sphinx.util.nodes import NodeMatcher
from sphinx.util.osutil import make_filename

if TYPE_CHECKING:
    from sphinx.application import Sphinx

import xml.etree.ElementTree as etree

__version__ = '2.0.0'
__version_info__ = (2, 0, 0)

logger = logging.getLogger(__name__)
__ = get_translation(__name__, 'console')

package_dir = path.abspath(path.dirname(__file__))


[docs] class DevhelpBuilder(StandaloneHTMLBuilder): """ Builder that also outputs GNOME Devhelp file. """ name = 'devhelp' epilog = __('To view the help file:\n' '$ mkdir -p $HOME/.local/share/devhelp/books\n' '$ ln -s $PWD/%(outdir)s $HOME/.local/share/devhelp/books/%(project)s\n' '$ devhelp') # don't copy the reST source copysource = False supported_image_types = ['image/png', 'image/gif', 'image/jpeg'] # don't add links add_permalinks = False # don't add sidebar etc. embedded = True def init(self) -> None: super().init() self.out_suffix = '.html' self.link_suffix = '.html' def handle_finish(self) -> None: self.build_devhelp(self.outdir, self.config.devhelp_basename) def build_devhelp(self, outdir: str | os.PathLike[str], outname: str) -> None: logger.info(__('dumping devhelp index...')) # Basic info root = etree.Element('book', title=self.config.html_title, name=self.config.project, link="index.html", version=self.config.version) tree = etree.ElementTree(root) # TOC chapters = etree.SubElement(root, 'chapters') tocdoc = self.env.get_and_resolve_doctree( self.config.master_doc, self, prune_toctrees=False) def write_toc(node: nodes.Node, parent: etree.Element) -> None: if isinstance(node, (addnodes.compact_paragraph, nodes.bullet_list)): for subnode in node: write_toc(subnode, parent) elif isinstance(node, nodes.list_item): item = etree.SubElement(parent, 'sub') for subnode in node: write_toc(subnode, item) elif isinstance(node, nodes.reference): parent.attrib['link'] = node['refuri'] parent.attrib['name'] = node.astext() matcher = NodeMatcher(addnodes.compact_paragraph, toctree=Any) for node in tocdoc.findall(matcher): write_toc(node, chapters) # Index functions = etree.SubElement(root, 'functions') index = IndexEntries(self.env).create_index(self) def write_index(title: str, refs: list[Any], subitems: Any) -> None: if len(refs) == 0: pass elif len(refs) == 1: etree.SubElement(functions, 'function', name=title, link=refs[0][1]) else: for i, ref in enumerate(refs): etree.SubElement(functions, 'function', name="[%d] %s" % (i, title), link=ref[1]) if subitems: parent_title = re.sub(r'\s*\(.*\)\s*$', '', title) for subitem in subitems: write_index(f'{parent_title} {subitem[0]}', subitem[1], []) for (_group_key, group) in index: for title, (refs, subitems, _category_key) in group: write_index(title, refs, subitems) # Dump the XML file xmlfile = path.join(outdir, outname + '.devhelp.gz') with gzip.GzipFile(filename=xmlfile, mode='w', mtime=0) as f: tree.write(f, 'utf-8')
def setup(app: Sphinx) -> dict[str, Any]: app.require_sphinx('5.0') app.setup_extension('sphinx.builders.html') app.add_builder(DevhelpBuilder) app.add_message_catalog(__name__, path.join(package_dir, 'locales')) app.add_config_value('devhelp_basename', lambda self: make_filename(self.project), 'devhelp') return { 'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True, }