From fe55a9e88cc87d5a6d53dcb2599fafb5334d7933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Krzy=C5=9Bk=C3=B3w?= <34622465+kamilkrzyskow@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:08:14 +0100 Subject: [PATCH] Refactor patch - navigation and related fixes (#220) * fix(suffix): restore file path lookup * refactor(reconfigure): remove redundant init variables * fix(suffix): handle more asset overrides * refactor(plugin): rename shadowed global variable * refactor(reconfigure): info warning for unsupported lunr.js * refactor(plugin): extract nav translation counter * refactor(plugin): extract nav homepage assignment * fix(plugin): correct time logging --- mkdocs_static_i18n/plugin.py | 48 ++++++++++++++++++---- mkdocs_static_i18n/reconfigure.py | 68 +++++++++---------------------- mkdocs_static_i18n/suffix.py | 24 +++++------ 3 files changed, 73 insertions(+), 67 deletions(-) diff --git a/mkdocs_static_i18n/plugin.py b/mkdocs_static_i18n/plugin.py index fdf0b61..15c34ec 100644 --- a/mkdocs_static_i18n/plugin.py +++ b/mkdocs_static_i18n/plugin.py @@ -1,22 +1,25 @@ import logging from pathlib import PurePath +from typing import Optional from jinja2.ext import loopcontrols from mkdocs import plugins -from mkdocs.commands.build import build +from mkdocs.commands.build import DuplicateFilter, build from mkdocs.config.defaults import MkDocsConfig from mkdocs.structure.files import Files +from mkdocs.structure.pages import Page from mkdocs_static_i18n import suffix from mkdocs_static_i18n.reconfigure import ExtendedPlugin try: - from importlib.metadata import files, version + from importlib.metadata import files as package_files + from importlib.metadata import version material_version = version("mkdocs-material") material_languages = [ lang.stem - for lang in files("mkdocs-material") + for lang in package_files("mkdocs-material") if "material/partials/languages" in lang.as_posix() ] except Exception: @@ -78,7 +81,31 @@ def on_nav(self, nav, config, files): """ Translate i18n aware navigation to honor the 'nav_translations' option. """ - i18n_nav = self.reconfigure_navigation(nav, config, files) + + homepage_suffix: str = "" if config.use_directory_urls else "index.html" + + # maybe move to another file and don't pass it as parameter? + class NavHelper: + translated_items: int = 0 + homepage: Optional[Page] = nav.homepage + expected_homepage_urls = [ + f"{self.current_language}/{homepage_suffix}", + f"/{self.current_language}/{homepage_suffix}", + ] + + i18n_nav = self.reconfigure_navigation(nav, config, files, NavHelper) + i18n_nav.homepage = NavHelper.homepage + + # report translated entries + if NavHelper.translated_items: + log.info( + f"Translated {NavHelper.translated_items} navigation element" + f"{'s' if NavHelper.translated_items > 1 else ''} to '{self.current_language}'" + ) + + # report missing homepage + if i18n_nav.homepage is None: + log.warning(f"Could not find a homepage for locale '{self.current_language}'") # manually trigger with-pdf, see #110 with_pdf_plugin = config["plugins"].get("with-pdf") @@ -140,11 +167,15 @@ def on_post_build(self, config): # memorize locale search entries self.extend_search_entries(config) - if self.building is False: - self.building = True - else: + if self.building: return + self.building = True + + # Block time logging for internal builds + duplicate_filter: DuplicateFilter = logging.getLogger("mkdocs.commands.build").filters[0] + duplicate_filter.msgs.add("Documentation built in %.2f seconds") + # manually trigger with-pdf, see #110 with_pdf_plugin = config["plugins"].get("with-pdf") if with_pdf_plugin: @@ -179,3 +210,6 @@ def on_post_build(self, config): # remove monkey patching in case some other builds are triggered # on the same site (tests, ci...) utils.clean_directory = mkdocs_utils_clean_directory + + # Unblock time logging after internal builds + duplicate_filter.msgs.remove("Documentation built in %.2f seconds") diff --git a/mkdocs_static_i18n/reconfigure.py b/mkdocs_static_i18n/reconfigure.py index fa7ac85..778a85c 100644 --- a/mkdocs_static_i18n/reconfigure.py +++ b/mkdocs_static_i18n/reconfigure.py @@ -1,5 +1,4 @@ import logging -from collections import defaultdict from pathlib import Path, PurePath from urllib.parse import quote as urlquote @@ -7,20 +6,22 @@ from mkdocs.config.defaults import MkDocsConfig from mkdocs.plugins import BasePlugin from mkdocs.structure.nav import Navigation +from mkdocs.structure.pages import Page from mkdocs.theme import Theme from mkdocs_static_i18n import __file__ as installation_path from mkdocs_static_i18n import is_relative_to from mkdocs_static_i18n.config import I18nPluginConfig +from mkdocs_static_i18n.suffix import I18nFiles log = logging.getLogger("mkdocs.plugins." + __name__) try: - from importlib.metadata import files + from importlib.metadata import files as package_files LUNR_LANGUAGES = [ PurePath(lang.stem).suffix.replace(".", "") - for lang in files("mkdocs") + for lang in package_files("mkdocs") if "mkdocs/contrib/search/lunr-language/lunr." in lang.as_posix() and len(lang.stem) == 7 ] assert len(LUNR_LANGUAGES) > 1 @@ -58,12 +59,8 @@ def __init__(self, *args, **kwargs): self.building = False self.current_language = None self.i18n_alternates = {} - self.i18n_configs = {} self.i18n_dest_uris = {} - self.i18n_files = defaultdict(list) - self.material_alternates = None self.search_entries = [] - self.site_dir = None @property def all_languages(self): @@ -166,11 +163,7 @@ def reconfigure_mkdocs_theme(self, config: MkDocsConfig, locale: str) -> Theme: if "locale" in config.theme._vars: config.theme._vars["locale"] = localization.parse_locale(locale) - def reconfigure_material_theme( - self, - config: MkDocsConfig, - locale: str, - ) -> MkDocsConfig: + def reconfigure_material_theme(self, config: MkDocsConfig, locale: str) -> MkDocsConfig: # set theme language if "language" in config.theme._vars: config.theme._vars["language"] = locale @@ -211,10 +204,7 @@ def reconfigure_material_theme( return config def reconfigure_search_plugin( - self, - config: MkDocsConfig, - search_plugin_name: str, - search_plugin, + self, config: MkDocsConfig, search_plugin_name: str, search_plugin ): search_langs = search_plugin.config["lang"] or [] for language in self.build_languages: @@ -225,7 +215,7 @@ def reconfigure_search_plugin( f"Adding '{language}' to the '{search_plugin_name}' plugin 'lang' option" ) else: - log.warning( + log.info( f"Language '{language}' is not supported by " f"lunr.js, not setting it in the 'plugins.search.lang' option" ) @@ -247,7 +237,9 @@ def reconfigure_with_pdf_plugin(self, config: MkDocsConfig): pass return config - def reconfigure_navigation(self, nav: Navigation, config: MkDocsConfig, i18n_files): + def reconfigure_navigation( + self, nav: Navigation, config: MkDocsConfig, files: I18nFiles, nav_helper + ): """ Apply static navigation items translation mapping for the current language. @@ -255,41 +247,21 @@ def reconfigure_navigation(self, nav: Navigation, config: MkDocsConfig, i18n_fil """ # nav_translations nav_translations = self.current_language_config.nav_translations or {} - translated_items = 0 + for item in nav: if hasattr(item, "title") and item.title in nav_translations: item.title = nav_translations[item.title] - translated_items += 1 + nav_helper.translated_items += 1 + + # is that the localized content homepage? + if nav_helper.homepage is None and isinstance(item, Page): + if item.url in nav_helper.expected_homepage_urls or item.url == "": + nav_helper.homepage = item + # translation should be recursive to children if hasattr(item, "children") and item.children: - self.reconfigure_navigation(item.children, config, i18n_files) - # is that the localized content homepage? - if ( - hasattr(nav, "homepage") - and nav.homepage is None - and hasattr(item, "url") - and item.url - ): - if config.use_directory_urls is True: - expected_homepage_urls = [ - f"{self.current_language}/", - f"/{self.current_language}/", - ] - else: - expected_homepage_urls = [ - f"{self.current_language}/index.html", - f"/{self.current_language}/index.html", - ] - if item.url in expected_homepage_urls: - nav.homepage = item - if translated_items: - log.info( - f"Translated {translated_items} navigation element" - f"{'s' if translated_items > 1 else ''} to '{self.current_language}'" - ) - # report missing homepage - if hasattr(nav, "homepage") and nav.homepage is None: - log.warning(f"Could not find a homepage for locale '{self.current_language}'") + self.reconfigure_navigation(item.children, config, files, nav_helper) + return nav def reconfigure_page_context(self, context, page, config: MkDocsConfig, nav: Navigation): diff --git a/mkdocs_static_i18n/suffix.py b/mkdocs_static_i18n/suffix.py index c2cd50c..aba14eb 100644 --- a/mkdocs_static_i18n/suffix.py +++ b/mkdocs_static_i18n/suffix.py @@ -1,6 +1,7 @@ import logging import os from pathlib import Path, PurePath +from typing import Optional from urllib.parse import quote as urlquote from mkdocs.config.defaults import MkDocsConfig @@ -95,7 +96,7 @@ def __init__(self, plugin, files: Files) -> None: super().__init__(files) self.plugin = plugin - def get_file_from_path(self, path: str): + def get_file_from_path(self, path: str) -> Optional[File]: """ Used by mkdocs.structure.nav.get_navigation to find resources linked in markdown. """ @@ -109,11 +110,15 @@ def get_file_from_path(self, path: str): ), expected_src_uri, ] - for src_uri in filter(lambda s: Path(s) in expected_src_uris, self.src_uris): - return self.src_uris.get(os.path.normpath(src_uri)) + for src_uri in expected_src_uris: + file = self.src_uris.get(src_uri.as_posix()) + if file: + return file + else: + return None -def on_files(self, files, config): +def on_files(self, files: Files, config: MkDocsConfig) -> I18nFiles: """ """ i18n_dest_uris = {} i18n_files = I18nFiles(self, []) @@ -121,11 +126,7 @@ def on_files(self, files, config): # documentation files if is_relative_to(file.abs_src_path, config.docs_dir): i18n_file = reconfigure_file( - file, - self.current_language, - self.default_language, - self.all_languages, - config, + file, self.current_language, self.default_language, self.all_languages, config ) # never seen that file? @@ -167,9 +168,8 @@ def on_files(self, files, config): log.debug(f"Ignore {i18n_file.locale} {i18n_file}") # theme (and overrides) files - else: - if self.is_default_language_build: - i18n_files.append(file) + elif self.is_default_language_build or file.src_uri.startswith("assets/"): + i18n_files.append(file) # populate the resulting Files and keep track of all the alternates # that will be used by the sitemap.xml template