"""Handle Pygments css.inspired by the Furo themehttps://github.com/pradyunsg/furo/blob/main/src/furo/__init__.py"""fromfunctoolsimportpartialfrompathlibimportPathfrompygments.formattersimportHtmlFormatterfrompygments.stylesimportget_all_stylesfromsphinx.applicationimportSphinxfrom.utilsimportget_theme_options_dict,maybe_warn
[文档]def_get_styles(formatter:HtmlFormatter,prefix:str)->None:"""Get styles out of a formatter, where everything has the correct prefix."""forlineinformatter.get_linenos_style_defs():yieldf"{prefix}{line}"yield fromformatter.get_background_style_defs(prefix)yield fromformatter.get_token_style_defs(prefix)
[文档]defget_pygments_stylesheet(light_style:str,dark_style:str)->str:"""Generate the theme-specific pygments.css. There is no way to tell Sphinx how the theme handles modes. """light_formatter=HtmlFormatter(style=light_style)dark_formatter=HtmlFormatter(style=dark_style)lines=[]light_prefix='html[data-theme="light"] .highlight'lines.extend(_get_styles(light_formatter,prefix=light_prefix))dark_prefix='html[data-theme="dark"] .highlight'lines.extend(_get_styles(dark_formatter,prefix=dark_prefix))return"\n".join(lines)
[文档]defoverwrite_pygments_css(app:Sphinx,exception=None):"""Overwrite pygments.css to allow dynamic light/dark switching. Sphinx natively supports config variables `pygments_style` and `pygments_dark_style`. However, quoting from www.sphinx-doc.org/en/master/development/theming.html#creating-themes The pygments_dark_style setting [...is used] when the CSS media query (prefers-color-scheme: dark) evaluates to true. This does not allow for dynamic switching by the user, so at build time we overwrite the pygment.css file so that it embeds 2 versions: - the light theme prefixed with "[data-theme="light"]" - the dark theme prefixed with "[data-theme="dark"]" Fallbacks are defined in this function in case the user-requested (or our theme-specified) pygments theme is not available. """ifexceptionisnotNone:returnassertapp.buildertheme_options=get_theme_options_dict(app)warning=partial(maybe_warn,app)pygments_styles=list(get_all_styles())fallbacks=dict(light="tango",dark="monokai")forlight_or_dark,fallbackinfallbacks.items():# make sure our fallbacks work; if not fall(further)back to "default"iffallbacknotinpygments_styles:fallback=pygments_styles[0]# should resolve to "default"# see if user specified a light/dark pygments theme:style_key=f"pygments_{light_or_dark}_style"style_name=theme_options.get(style_key,None)# if not, use the one we set in `theme.conf`:ifstyle_nameisNoneandhasattr(app.builder,"theme"):style_name=app.builder.theme.get_options()[style_key]# make sure we can load the styleifstyle_namenotinpygments_styles:# only warn if user asked for a highlight theme that we can't findifstyle_nameisnotNone:warning(f"Highlighting style {style_name} not found by pygments, "f"falling back to {fallback}.")style_name=fallback# assign to the appropriate variableiflight_or_dark=="light":light_theme=style_nameelse:dark_theme=style_name# re-write pygments.csspygments_css=Path(app.builder.outdir)/"_static"/"pygments.css"withpygments_css.open("w")asf:f.write(get_pygments_stylesheet(light_theme,dark_theme))