Skip to content

Commit

Permalink
feature(integration): support social cards for blog plugin posts (#326)
Browse files Browse the repository at this point in the history
This PR improves the Material Social Cards plugin integration by adding
support for social cards generated for Material Blog plugin posts
(https://squidfunk.github.io/mkdocs-material/plugins/blog/).
  • Loading branch information
Guts authored Oct 24, 2024
2 parents 4179aaf + 8bb75c5 commit bffc8ba
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 13 deletions.
99 changes: 88 additions & 11 deletions mkdocs_rss_plugin/integrations/theme_material_social_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
# conditional
try:
from material import __version__ as material_version
from material.plugins.blog.plugin import BlogPlugin
from pymdownx.slugs import slugify

except ImportError:
material_version = None


# ############################################################################
# ########## Globals #############
# ################################
Expand All @@ -38,6 +42,7 @@
class IntegrationMaterialSocialCards:
# attributes
IS_ENABLED: bool = True
IS_BLOG_PLUGIN_ENABLED: bool = True
IS_SOCIAL_PLUGIN_ENABLED: bool = True
IS_SOCIAL_PLUGIN_CARDS_ENABLED: bool = True
IS_THEME_MATERIAL: bool = False
Expand All @@ -53,6 +58,7 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No
it to False to disable it even if Social Cards are enabled in Mkdocs
configuration. Defaults to True.
"""
self.mkdocs_config = mkdocs_config
# check if the integration can be enabled or not
self.IS_SOCIAL_PLUGIN_CARDS_ENABLED = (
self.is_social_plugin_and_cards_enabled_mkdocs(mkdocs_config=mkdocs_config)
Expand Down Expand Up @@ -85,6 +91,9 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No
self.social_cards_cache_dir = self.get_social_cards_cache_dir(
mkdocs_config=mkdocs_config
)
self.IS_BLOG_PLUGIN_ENABLED = self.is_blog_plugin_enabled_mkdocs(
mkdocs_config=mkdocs_config
)
if self.is_mkdocs_theme_material_insiders():
self.load_cache_cards_manifest()

Expand Down Expand Up @@ -123,6 +132,37 @@ def is_mkdocs_theme_material_insiders(self) -> Optional[bool]:
self.IS_INSIDERS = False
return False

def is_blog_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool:
"""Check if blog plugin is installed and enabled.
Args:
mkdocs_config (MkDocsConfig): Mkdocs website configuration object.
Returns:
bool: True if the theme material and the plugin blog is enabled.
"""
if not self.is_mkdocs_theme_material(mkdocs_config=mkdocs_config):
logger.debug("Installed theme is not 'material'. Integration disabled.")
return False

if not mkdocs_config.plugins.get("material/blog"):
logger.debug("Material blog plugin is not listed in configuration.")
self.IS_BLOG_PLUGIN_ENABLED = False
return False

self.blog_plugin_cfg: BlogPlugin | None = mkdocs_config.plugins.get(
"material/blog"
)

if not self.blog_plugin_cfg.config.enabled:
logger.debug("Material blog plugin is installed but disabled.")
self.IS_BLOG_PLUGIN_ENABLED = False
return False

logger.debug("Material blog plugin is enabled in Mkdocs configuration.")
self.IS_BLOG_PLUGIN_ENABLED = True
return True

def is_social_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool:
"""Check if social plugin is installed and enabled.
Expand Down Expand Up @@ -274,18 +314,29 @@ def get_social_card_build_path_for_page(
if mkdocs_site_dir is None and self.mkdocs_site_build_dir:
mkdocs_site_dir = self.mkdocs_site_build_dir

expected_built_card_path = Path(
f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/"
f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)
# if page is a blog post
if self.IS_BLOG_PLUGIN_ENABLED and Path(
mkdocs_page.file.src_uri
).is_relative_to(self.blog_plugin_cfg.config.blog_dir):
expected_built_card_path = Path(
f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/"
f"{Path(mkdocs_page.file.dest_uri).parent}.png"
)
else:
expected_built_card_path = Path(
f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/"
f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)

if expected_built_card_path.is_file():
logger.debug(
f"Social card file found in cache folder: {expected_built_card_path}"
f"Social card file found in build folder: {expected_built_card_path}"
)
return expected_built_card_path
else:
logger.debug(f"Not found: {expected_built_card_path}")
logger.debug(
f"Social card not found in build folder: {expected_built_card_path}"
)
return None

def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Path]:
Expand All @@ -305,16 +356,28 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat
Path: path to the image in local cache folder if it exists
"""
if self.IS_INSIDERS:
expected_cached_card_path = self.social_cards_cache_dir.joinpath(
f"assets/images/social/{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)

# if page is a blog post
if self.IS_BLOG_PLUGIN_ENABLED and Path(
mkdocs_page.file.src_uri
).is_relative_to(self.blog_plugin_cfg.config.blog_dir):
expected_cached_card_path = self.social_cards_cache_dir.joinpath(
f"assets/images/social/{Path(mkdocs_page.file.dest_uri).parent}.png"
)
else:
expected_cached_card_path = self.social_cards_cache_dir.joinpath(
f"assets/images/social/{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)

if expected_cached_card_path.is_file():
logger.debug(
f"Social card file found in cache folder: {expected_cached_card_path}"
)
return expected_cached_card_path
else:
logger.debug(f"Not found: {expected_cached_card_path}")
logger.debug(
f"Social card not found in cache folder: {expected_cached_card_path}"
)

else:
if "description" in mkdocs_page.meta:
Expand Down Expand Up @@ -362,4 +425,18 @@ def get_social_card_url_for_page(
if mkdocs_site_url is None and self.mkdocs_site_url:
mkdocs_site_url = self.mkdocs_site_url

return f"{mkdocs_site_url}assets/images/social/{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
# if page is a blog post
if self.IS_BLOG_PLUGIN_ENABLED and Path(
mkdocs_page.file.src_uri
).is_relative_to(self.blog_plugin_cfg.config.blog_dir):
page_social_card = (
f"{mkdocs_site_url}assets/images/social/"
f"{Path(mkdocs_page.file.dest_uri).parent}.png"
)
else:
page_social_card = (
f"{mkdocs_site_url}assets/images/social/"
f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)

return page_social_card
15 changes: 15 additions & 0 deletions tests/fixtures/docs/blog/.authors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
authors:
squidfunk:
name: Martin Donath
description: Creator
avatar: https://github.com/squidfunk.png
alexvoss:
name: Alex Voss
description: Weltenwanderer
avatar: https://github.com/alexvoss.png
guts:
avatar: https://cdn.geotribu.fr/img/internal/contributeurs/jmou.jfif
description: GIS Watchman
name: Julien Moura
slug: julien-moura
url: https://geotribu.fr/team/julien-moura/
2 changes: 2 additions & 0 deletions tests/fixtures/docs/blog/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Blog

32 changes: 32 additions & 0 deletions tests/fixtures/docs/blog/posts/firstpost.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
authors:
- alexvoss
date: 2023-10-11
categories:
- meta
---

# My first blog post

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec
maximus ex. Sed consequat, nulla quis malesuada dapibus, elit metus vehicula
erat, ut egestas tellus eros at risus. In hac habitasse platea dictumst.
Phasellus id lacus pulvinar erat consequat pretium. Morbi malesuada arcu mauris
Nam vel justo sem. Nam placerat purus non varius luctus. Integer pretium leo in
sem rhoncus, quis gravida orci mollis. Proin id aliquam est. Vivamus in nunc ac
metus tristique pellentesque. Suspendisse viverra urna in accumsan aliquet.

<!-- more -->

Donec volutpat, elit ac volutpat laoreet, turpis dolor semper nibh, et dictum
massa ex pulvinar elit. Curabitur commodo sit amet dolor sed mattis. Etiam
tempor odio eu nisi gravida cursus. Maecenas ante enim, fermentum sit amet
molestie nec, mollis ac libero. Vivamus sagittis suscipit eros ut luctus.

Nunc vehicula sagittis condimentum. Cras facilisis bibendum lorem et feugiat.
In auctor accumsan ligula, at consectetur erat commodo quis. Morbi ac nunc
pharetra, pellentesque risus in, consectetur urna. Nulla id enim facilisis
arcu tincidunt pulvinar. Vestibulum laoreet risus scelerisque porta congue.
In velit purus, dictum quis neque nec, molestie viverra risus. Nam pellentesque
tellus id elit ultricies, vel finibus erat cursus.

32 changes: 32 additions & 0 deletions tests/fixtures/docs/blog/posts/secondpost.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
authors:
- squidfunk
date: 2023-10-12
categories:
- hello
---

# A second post

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec
maximus ex. Sed consequat, nulla quis malesuada dapibus, elit metus vehicula
erat, ut egestas tellus eros at risus. In hac habitasse platea dictumst.
Phasellus id lacus pulvinar erat consequat pretium. Morbi malesuada arcu mauris
Nam vel justo sem. Nam placerat purus non varius luctus. Integer pretium leo in
sem rhoncus, quis gravida orci mollis. Proin id aliquam est. Vivamus in nunc ac
metus tristique pellentesque. Suspendisse viverra urna in accumsan aliquet.

<!-- more -->

Donec volutpat, elit ac volutpat laoreet, turpis dolor semper nibh, et dictum
massa ex pulvinar elit. Curabitur commodo sit amet dolor sed mattis. Etiam
tempor odio eu nisi gravida cursus. Maecenas ante enim, fermentum sit amet
molestie nec, mollis ac libero. Vivamus sagittis suscipit eros ut luctus.

Nunc vehicula sagittis condimentum. Cras facilisis bibendum lorem et feugiat.
In auctor accumsan ligula, at consectetur erat commodo quis. Morbi ac nunc
pharetra, pellentesque risus in, consectetur urna. Nulla id enim facilisis
arcu tincidunt pulvinar. Vestibulum laoreet risus scelerisque porta congue.
In velit purus, dictum quis neque nec, molestie viverra risus. Nam pellentesque
tellus id elit ultricies, vel finibus erat cursus.

14 changes: 14 additions & 0 deletions tests/fixtures/mkdocs_item_image_social_cards_blog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
site_name: Test RSS Plugin
site_description: Test social cards support in RSS with blog plugin also enabled
site_url: https://guts.github.io/mkdocs-rss-plugin

plugins:
- blog:
blog_dir: blog
- rss
- social:
enabled: true
cards: true

theme:
name: material
7 changes: 6 additions & 1 deletion tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,13 @@ def test_simple_build_item_length_unlimited(self):
if feed_item.title not in (
"Page without meta with short text",
"Blog sample",
"Blog",
):
self.assertGreater(len(feed_item.description), 150, feed_item.title)
self.assertGreater(
len(feed_item.description),
150,
f"Failed item title: {feed_item.title}",
)

def test_simple_build_item_delimiter(self):
with tempfile.TemporaryDirectory() as tmpdirname:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TestConfig(BaseTest):
@classmethod
def setUpClass(cls):
"""Executed when module is loaded before any test."""
cls.config_files = sorted(Path("tests/fixtures/").glob("**/*.yml"))
cls.config_files = sorted(Path("tests/fixtures/").glob("**/mkdocs_*.yml"))
cls.feed_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png"

def setUp(self):
Expand Down
17 changes: 17 additions & 0 deletions tests/test_integrations_material_social_cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,23 @@ def test_plugin_config_social_plugin_enabled_but_cards_disabled(self):
self.assertFalse(integration_social_cards.IS_SOCIAL_PLUGIN_CARDS_ENABLED)
self.assertFalse(integration_social_cards.IS_ENABLED)

def test_plugin_config_social_cards_enabled_with_blog_plugin(self):
# default reference
cfg_mkdocs = load_config(
str(
Path("tests/fixtures/mkdocs_item_image_social_cards_blog.yml").resolve()
)
)

integration_social_cards = IntegrationMaterialSocialCards(
mkdocs_config=cfg_mkdocs
)
self.assertTrue(integration_social_cards.IS_THEME_MATERIAL)
self.assertTrue(integration_social_cards.IS_SOCIAL_PLUGIN_ENABLED)
self.assertTrue(integration_social_cards.IS_SOCIAL_PLUGIN_CARDS_ENABLED)
self.assertTrue(integration_social_cards.IS_BLOG_PLUGIN_ENABLED)
self.assertTrue(integration_social_cards.IS_ENABLED)

def test_simple_build(self):
with tempfile.TemporaryDirectory() as tmpdirname:
cli_result = self.build_docs_setup(
Expand Down

0 comments on commit bffc8ba

Please sign in to comment.