# HTMLBuilder - [Sphinxにひっそり存在するビルダー "dirhtml"の使い勝手を知る](https://zenn.dev/attakei/articles/sphinx-make-dirhtml) ## 動作 ### init - `StandaloneHTMLBuilder` `sphinx.jinja2glue.BuiltinTemplateLoader` をセットアップする。 - {doc}`ビルドフェーズ0 ` - sphinx.builders.Builder#create_template_bridge - sphinx.jinja2glue.BuiltinTemplateLoader() - sphinx.jinja2glue.BuiltinTemplateLoader#init - `builder-inited` ### write `sphinx.jinja2glue.BuiltinTemplateLoader` を使う。 - {doc}`ビルドフェーズ4 ` - sphinx.builders.Builder#buile - sphinx.builders.Builder#write - sphinx.builders.StandaloneHTMLBuilder#write_doc - sphinx.jinja2glue.BuiltinTemplateLoader#handle_page ```python # page.html がエントリーポイント def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html', outfilename: str = None, event_arg: Any = None) -> None: ``` - sphinx.jinja2glue.BuiltinTemplateLoader#render ```python output = self.templates.render(templatename, ctx) ``` #### sidebar のメカニズム ```python # StandaloneHTMLBuilder def add_sidebars(self, pagename: str, ctx: Dict) -> None: def has_wildcard(pattern: str) -> bool: return any(char in pattern for char in '*?[') sidebars = None matched = None customsidebar = None # default sidebars settings for selected theme if self.theme.name == 'alabaster': # provide default settings for alabaster (for compatibility) # Note: this will be removed before Sphinx-2.0 try: # get default sidebars settings from alabaster (if defined) theme_default_sidebars = self.theme.config.get('theme', 'sidebars') if theme_default_sidebars: sidebars = [name.strip() for name in theme_default_sidebars.split(',')] except Exception: # fallback to better default settings sidebars = ['about.html', 'navigation.html', 'relations.html', 'searchbox.html', 'donate.html'] else: theme_default_sidebars = self.theme.get_config('theme', 'sidebars', None) if theme_default_sidebars: sidebars = [name.strip() for name in theme_default_sidebars.split(',')] # user sidebar settings html_sidebars = self.get_builder_config('sidebars', 'html') for pattern, patsidebars in html_sidebars.items(): if patmatch(pagename, pattern): if matched: if has_wildcard(pattern): # warn if both patterns contain wildcards if has_wildcard(matched): logger.warning(__('page %s matches two patterns in ' 'html_sidebars: %r and %r'), pagename, matched, pattern) # else the already matched pattern is more specific # than the present one, because it contains no wildcard continue matched = pattern sidebars = patsidebars if sidebars is None: # keep defaults pass ctx['sidebars'] = sidebars # 👈 ctx['customsidebar'] = customsidebar ``` ## sphinx.jinja2glue.BuiltinTemplateLoader ### render ```python def render(self, template: str, context: Dict) -> str: # type: ignore return self.environment.get_template(template).render(context) ``` - template: `page.html`, `genindex.html`, `search.html` 等が入力する。 - context: は jinja template に渡す変数 ```python # StandaloneHTMLBuilder ctx = self.globalcontext.copy() def prepare_writing(self, docnames: Set[str]) -> None: # 省略 self.globalcontext = { 'embedded': self.embedded, 'project': self.config.project, # 👈 conf.py 'release': return_codes_re.sub('', self.config.release), # 👈 conf.py 'version': self.config.version, # 👈 conf.py 'last_updated': self.last_updated, 'copyright': self.config.copyright, # 👈 conf.py 'master_doc': self.config.root_doc, # 👈 conf.py 'root_doc': self.config.root_doc, # 👈 conf.py 'use_opensearch': self.config.html_use_opensearch, # 👈 conf.py 'docstitle': self.config.html_title, # 👈 conf.py 'shorttitle': self.config.html_short_title, # 👈 conf.py 'show_copyright': self.config.html_show_copyright, # 👈 conf.py 'show_sphinx': self.config.html_show_sphinx, # 👈 conf.py 'has_source': self.config.html_copy_source, # 👈 conf.py 'show_source': self.config.html_show_sourcelink, # 👈 conf.py 'sourcelink_suffix': self.config.html_sourcelink_suffix, # 👈 conf.py 'file_suffix': self.out_suffix, 'link_suffix': self.link_suffix, 'script_files': self.script_files, 'language': self.config.language, # 👈 conf.py 'css_files': self.css_files, 'sphinx_version': __display_version__, 'sphinx_version_tuple': sphinx_version, 'style': self._get_style_filename(), 'rellinks': rellinks, 'builder': self.name, 'parents': [], 'logo': logo, 'favicon': favicon, 'html5_doctype': html5_ready and not self.config.html4_writer, # 👈 conf.py } if self.theme: # 👇 global context に theme.conf の option 項の値が追加される # [options] # rightsidebar = false # sidebarwidth = 210 # maincolor = #336699 self.globalcontext.update( ('theme_' + key, val) for (key, val) in self.theme.get_options(self.theme_options).items()) self.globalcontext.update(self.config.html_context) ``` `conf.py` による `[options]` の上書き ```python # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { 'linkcolor': 'red', # 👈 theme_linkcolor 'headerbgcolor': 'blue' # 👈 theme_headerbgcolor } ``` ## static 要素のコピー動作は? * css や script を build 先にコピーする仕組みは? * また、そのときに scss とか使えないだろうか