diff --git a/docs/setup/setting-up-social-cards.md b/docs/setup/setting-up-social-cards.md index 48ec14c59..4340c83ab 100644 --- a/docs/setup/setting-up-social-cards.md +++ b/docs/setup/setting-up-social-cards.md @@ -19,12 +19,11 @@ The social preview image for the page on [setting up site analytics]. [^1]: - Both types of logos, images (`theme.logo`) and icons (`theme.icon.logo`) - are supported. While an image logo is used as-is, icons are filled with the - color used in the header (white or black), which depends on the primary - color. Note that custom logos and icons must reside in the `docs_dir` for - the plugin to find them. For guidance, see #4920. This limitation will be - lifted in the future when the social plugin will receive its next update. + Both types of logos, images ([`theme.logo`](changing-the-logo-and-icons.md#image)) + and icons ([`theme.icon.logo`](changing-the-logo-and-icons.md#icon-bundled)) are supported. + While an image logo is used as-is, icons are filled with the + ([`social.cards_color.text`](#+social.cards_color)) color. Valid file paths inside the + [`custom_dir`](../customization.md#setup-and-theme-structure) will take priority. [colors]: changing-the-colors.md#primary-color [fonts]: changing-the-fonts.md#regular-font diff --git a/material/plugins/social/plugin.py b/material/plugins/social/plugin.py index e70758268..509e4f446 100644 --- a/material/plugins/social/plugin.py +++ b/material/plugins/social/plugin.py @@ -68,6 +68,7 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): def __init__(self): self._executor = concurrent.futures.ThreadPoolExecutor(4) + self.custom_dir = None # Retrieve configuration def on_config(self, config): @@ -112,6 +113,13 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): # Retrieve color overrides self.color = { **self.color, **self.config.cards_color } + # Retrieve custom_dir path + for user_config in config.user_configs: + custom_dir = user_config.get("theme", {}).get("custom_dir") + if custom_dir: + self.custom_dir = custom_dir + break + # Retrieve logo and font self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config) self.font = self._load_font(config) @@ -344,8 +352,15 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): if "logo" in theme: _, extension = os.path.splitext(theme["logo"]) - # Load SVG and convert to PNG path = os.path.join(config.docs_dir, theme["logo"]) + + # Allow users to put the logo inside their custom_dir (theme["logo"] case) + if self.custom_dir: + custom_dir_logo = os.path.join(self.custom_dir, theme["logo"]) + if os.path.exists(custom_dir_logo): + path = custom_dir_logo + + # Load SVG and convert to PNG if extension == ".svg": return self._load_logo_svg(path) @@ -353,10 +368,11 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): return Image.open(path).convert("RGBA") # Handle icons - logo = "material/library" icon = theme["icon"] or {} if "logo" in icon and icon["logo"]: logo = icon["logo"] + else: + logo = "material/library" # Resolve path of package base = os.path.abspath(os.path.join( @@ -364,8 +380,15 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): "../.." )) - # Load icon data and fill with color path = f"{base}/.icons/{logo}.svg" + + # Allow users to put the logo inside their custom_dir (theme["icon"]["logo"] case) + if self.custom_dir: + custom_dir_logo = os.path.join(self.custom_dir, ".icons", f"{logo}.svg") + if os.path.exists(custom_dir_logo): + path = custom_dir_logo + + # Load icon data and fill with color return self._load_logo_svg(path, self.color["text"]) # Load SVG file and convert to PNG @@ -388,7 +411,7 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): # Retrieve from theme (default: Roboto) theme = config.theme - if theme["font"]: + if isinstance(theme["font"], dict) and "text" in theme["font"]: name = theme["font"]["text"] else: name = "Roboto" diff --git a/src/plugins/social/plugin.py b/src/plugins/social/plugin.py index e70758268..509e4f446 100644 --- a/src/plugins/social/plugin.py +++ b/src/plugins/social/plugin.py @@ -68,6 +68,7 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): def __init__(self): self._executor = concurrent.futures.ThreadPoolExecutor(4) + self.custom_dir = None # Retrieve configuration def on_config(self, config): @@ -112,6 +113,13 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): # Retrieve color overrides self.color = { **self.color, **self.config.cards_color } + # Retrieve custom_dir path + for user_config in config.user_configs: + custom_dir = user_config.get("theme", {}).get("custom_dir") + if custom_dir: + self.custom_dir = custom_dir + break + # Retrieve logo and font self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config) self.font = self._load_font(config) @@ -344,8 +352,15 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): if "logo" in theme: _, extension = os.path.splitext(theme["logo"]) - # Load SVG and convert to PNG path = os.path.join(config.docs_dir, theme["logo"]) + + # Allow users to put the logo inside their custom_dir (theme["logo"] case) + if self.custom_dir: + custom_dir_logo = os.path.join(self.custom_dir, theme["logo"]) + if os.path.exists(custom_dir_logo): + path = custom_dir_logo + + # Load SVG and convert to PNG if extension == ".svg": return self._load_logo_svg(path) @@ -353,10 +368,11 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): return Image.open(path).convert("RGBA") # Handle icons - logo = "material/library" icon = theme["icon"] or {} if "logo" in icon and icon["logo"]: logo = icon["logo"] + else: + logo = "material/library" # Resolve path of package base = os.path.abspath(os.path.join( @@ -364,8 +380,15 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): "../.." )) - # Load icon data and fill with color path = f"{base}/.icons/{logo}.svg" + + # Allow users to put the logo inside their custom_dir (theme["icon"]["logo"] case) + if self.custom_dir: + custom_dir_logo = os.path.join(self.custom_dir, ".icons", f"{logo}.svg") + if os.path.exists(custom_dir_logo): + path = custom_dir_logo + + # Load icon data and fill with color return self._load_logo_svg(path, self.color["text"]) # Load SVG file and convert to PNG @@ -388,7 +411,7 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]): # Retrieve from theme (default: Roboto) theme = config.theme - if theme["font"]: + if isinstance(theme["font"], dict) and "text" in theme["font"]: name = theme["font"]["text"] else: name = "Roboto"