"""A custom Sphinx HTML Translator for Bootstrap layout."""importtypesfromsphinx.applicationimportSphinxfromsphinx.ext.autosummaryimportautosummary_tablefromsphinx.utilimportlogging
[文档]classBootstrapHTML5TranslatorMixin:"""Mixin HTML Translator for a Bootstrap-ified Sphinx layout. Only a couple of functions have been overridden to produce valid HTML to be directly styled with Bootstrap, and fulfill acessibility best practices. """def__init__(self,*args,**kwds):super().__init__(*args,**kwds)self.settings.table_style="table"
[文档]defstarttag(self,*args,**kwargs):"""Perform small modifications to tags. - ensure aria-level is set for any tag with heading role """ifkwargs.get("ROLE")=="heading"and"ARIA-LEVEL"notinkwargs:kwargs["ARIA-LEVEL"]="2"returnsuper().starttag(*args,**kwargs)
[文档]defvisit_table(self,node):""" Custom visit table method. Copy of sphinx source to *not* add 'docutils' and 'align-default' classes but add 'table' class. """# init the attributesatts={}self._table_row_indices.append(0)# get the classesclasses=[cls.strip(" \t\n")forclsinself.settings.table_style.split(",")]# we're looking at the 'real_table', which is wrapped by an autosummaryifisinstance(node.parent,autosummary_table):classes+=["autosummary"]# add the width if set in a style attributeif"width"innode:atts["style"]=f'width: {node["width"]}'# add specific class if align is setif"align"innode:classes.append(f'table-{node["align"]}')# put table within a scrollable container (for tables that are too wide)self.body.append('<div class="pst-scrollable-table-container">')tag=self.starttag(node,"table",CLASS=" ".join(classes),**atts)self.body.append(tag)
[文档]defdepart_table(self,node):""" Custom depart_table method to close the scrollable div we add in visit_table. """super().depart_table(node)self.body.append("</div>\n")
[文档]defsetup_translators(app:Sphinx):""" Add bootstrap HTML functionality if we are using an HTML translator. This re-uses the pre-existing Sphinx translator and adds extra functionality defined in ``BootstrapHTML5TranslatorMixin``. This way we can retain the original translator's behavior and configuration, and _only_ add the extra bootstrap rules. If we don't detect an HTML-based translator, then we do nothing. """ifnotapp.registry.translators.items():try:default_translator_class=app.builder.default_translator_classexceptAttributeError:# some builders, e.g. linkcheck, do not define 'default_translator_class'returntranslator=types.new_class("BootstrapHTML5Translator",(BootstrapHTML5TranslatorMixin,default_translator_class,),{},)app.set_translator(app.builder.name,translator,override=True)else:forname,klassinapp.registry.translators.items():ifapp.builder.format!="html":# Skip translators that are not HTMLcontinuetranslator=types.new_class("BootstrapHTML5Translator",(BootstrapHTML5TranslatorMixin,klass,),{},)app.set_translator(name,translator,override=True)