Skip to content

Commit

Permalink
Feature: support material social cards plugin (#217)
Browse files Browse the repository at this point in the history
This PR adds logic and option to support Social Cards of Material theme
out-of-the-box.

## Functional

- [x] if a page has no image set but social cards is enabled, use the
generated image as item's image
- [x] option to enable/disable this integration in `mkdocs.plugins.rss`

## Before/after

Considering the RSS feed from this plugin documentation:
<https://guts.github.io/mkdocs-rss-plugin/integrations/>

### Before

```xml
<item>
  <title>Integrations</title>
  <description>&lt;h2&gt;Reference RSS feeds in HTML meta-tags&lt;/h2&gt;
&lt;p&gt;To facilitate the discovery of RSS feeds, it&#39;s recommended to add relevant meta-tags in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section in HTML pa...&lt;/p&gt;</description>
  <link>https://guts.github.io/mkdocs-rss-plugin/integrations/?utm_source=documentation&amp;utm_medium=RSS&amp;utm_campaign=feed-syndication</link>
  <pubDate>Tue, 12 Dec 2023 11:02:08 +0100</pubDate>
  <source url="https://guts.github.io/mkdocs-rss-plugin/feed_rss_created.xml">MkDocs RSS Plugin</source>
  <guid isPermaLink="true">https://guts.github.io/mkdocs-rss-plugin/integrations/</guid>
</item>
```

### After

```xml
<item>
    <title>Integrations</title>
    <description>
    <h2>Social Cards plugin (from Material theme)</h2> <p>Since version 1.10, the plugin integrates with the [Social Cards plugin (shipped with Material theme)](https://...</p>
    </description>
    <link>
    http://127.0.0.1:8000/mkdocs-rss-plugin/integrations/?utm_source=documentation&utm_medium=RSS&utm_campaign=feed-syndication
    </link>
    <pubDate>Tue, 12 Dec 2023 12:02:08 +0100</pubDate>
    <source url="http://127.0.0.1:8000/mkdocs-rss-plugin/feed_rss_created.xml">MkDocs RSS Plugin</source>
    <guid isPermaLink="true">
    http://127.0.0.1:8000/mkdocs-rss-plugin/integrations/
    </guid>
    <enclosure url="https://guts.github.io/mkdocs-rss-plugin/assets/images/social/integrations.png" type="image/png" length="46533"/>
</item>
```

See the last `enclosure` line.

## Resources

- related section about Social Cards in Material documentation:
<https://squidfunk.github.io/mkdocs-material/setup/setting-up-social-cards/>
  • Loading branch information
Guts authored Dec 16, 2023
1 parent 543438b commit 40f628f
Show file tree
Hide file tree
Showing 16 changed files with 489 additions and 29 deletions.
8 changes: 8 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,5 +433,13 @@ Useful if you build your documentation in an environment where you can't easily

Default: `true`.

### `use_material_social_cards`: enable/disable integration with Material Social Cards plugin

If `false`, the integration with Social Cards is disabled.

Default: `true`.

> See [the related section in integrations page](./integrations.md#social-cards-plugin-from-material-theme).

<!-- Hyperlinks reference -->
[page metadata]: https://python-markdown.github.io/extensions/meta_data/
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors:
- vinktim@gmail.com (Tim Vink)
date: 2020-07-06
description: "MkDocs RSS plugin: generate RSS feeds for your static website using git log ad YAML frontmatter (markdown pages'metadata header)."
image: "rss_icon.svg"
image: "assets/rss_icon.svg"
tags:
- Mkdocs
- plugin
Expand Down
16 changes: 16 additions & 0 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ title: Integrations
icon: octicons/plug-16
---

## Social Cards plugin (from Material theme)

Since version 1.10, the plugin integrates with the [Social Cards plugin (shipped with Material theme)](https://squidfunk.github.io/mkdocs-material/setup/setting-up-social-cards/) (see also [the full plugin documentation here](https://squidfunk.github.io/mkdocs-material/plugins/social/)).

Here's how the RSS plugin prioritizes the image to be used in the feed:

1. an image (local path or URL) is defined in the page's YAML header of the page with the key `image`. Typically: `image: path_or_url_to_image.webp`.
1. an image (local path or URL) is defined in the page's YAML header with the key `illustration`. Typically: `illustration: path_or_url_to_image.webp`.
1. if neither is defined, but both the social plugin and the cards option are enabled, then the social card image is used.

If you don't want this integration, you can disable it with the option: `use_material_social_cards=false`.

> See [related section in settings](./configuration.md#use_material_social_cards-enabledisable-integration-with-material-social-cards-plugin).
----

## Reference RSS feeds in HTML meta-tags

To facilitate the discovery of RSS feeds, it's recommended to add relevant meta-tags in `<head>` section in HTML pages.
Expand Down
6 changes: 6 additions & 0 deletions docs/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@
"markdownDescription": "https://guts.github.io/mkdocs-rss-plugin/configuration/#use_git-enabledisable-git-log",
"type": "boolean",
"default": true
},
"use_material_social_cards": {
"title": "Enable/Disable integration with Social Cards plugin from Material theme.",
"markdownDescription": "https://guts.github.io/mkdocs-rss-plugin/configuration/#disabling-the-plugin",
"type": "boolean",
"default": true
}
},
"additionalProperties": false
Expand Down
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ plugins:
utm_source: "documentation"
utm_medium: "RSS"
utm_campaign: "feed-syndication"
use_git: true
use_material_social_cards: true
- search:
lang: en
- social:
enabled: !ENV [MKDOCS_ENABLE_PLUGIN_SOCIAL, true]
cache_dir: !ENV [MKDOCS_PLUGIN_SOCIAL_CACHE_DIR, .cache/plugins/social]
cards: true
- termynal:
prompt_literal_start:
- "$"
Expand Down
1 change: 1 addition & 0 deletions mkdocs_rss_plugin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ class RssPluginConfig(Config):
pretty_print = config_options.Type(bool, default=False)
url_parameters = config_options.Optional(config_options.Type(dict))
use_git = config_options.Type(bool, default=True)
use_material_social_cards = config_options.Type(bool, default=True)
Empty file.
216 changes: 216 additions & 0 deletions mkdocs_rss_plugin/integrations/theme_material_social_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
#! python3 # noqa: E265

# ############################################################################
# ########## Libraries #############
# ##################################

# standard library
import logging
from pathlib import Path
from typing import Optional

# 3rd party
from mkdocs.config.config_options import Config
from mkdocs.structure.pages import Page

# ############################################################################
# ########## Globals #############
# ################################

logger = logging.getLogger("mkdocs.mkdocs_rss_plugin")

# ############################################################################
# ########## Logic ###############
# ################################


class IntegrationMaterialSocialCards:
# attributes
IS_ENABLED: bool = True
IS_SOCIAL_PLUGIN_ENABLED: bool = True
IS_SOCIAL_PLUGIN_CARDS_ENABLED: bool = True
IS_THEME_MATERIAL: bool = False

def __init__(self, mkdocs_config: Config, switch_force: bool = True) -> None:
"""Integration instanciation.
Args:
mkdocs_config (Config): Mkdocs website configuration object.
switch_force (bool, optional): option to force integration disabling. Set
it to False to disable it even if Social Cards are enabled in Mkdocs
configuration. Defaults to True.
"""
# 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)
)

# if every conditions are True, enable the integration
self.IS_ENABLED = all(
[
self.IS_THEME_MATERIAL,
self.IS_SOCIAL_PLUGIN_ENABLED,
self.IS_SOCIAL_PLUGIN_CARDS_ENABLED,
]
)

# except if the end-user wants to disable it
if switch_force is False:
self.IS_ENABLED = False
logger.debug(
"[rss-plugin] Integration with Social Cards (Material theme) is "
"disabled in plugin's option in Mkdocs configuration."
)

# if enabled, save some config elements
if self.IS_ENABLED:
self.mkdocs_site_url = mkdocs_config.site_url
self.mkdocs_site_build_dir = mkdocs_config.site_dir
self.social_cards_assets_dir = self.get_social_cards_dir(
mkdocs_config=mkdocs_config
)

def is_theme_material(self, mkdocs_config: Config) -> bool:
"""Check if the theme set in mkdocs.yml is material or not.
Args:
mkdocs_config (Config): Mkdocs website configuration object.
Returns:
bool: True if the theme's name is 'material'. False if not.
"""
self.IS_THEME_MATERIAL = mkdocs_config.theme.name == "material"
return self.IS_THEME_MATERIAL

def is_social_plugin_enabled_mkdocs(self, mkdocs_config: Config) -> bool:
"""Check if social plugin is installed and enabled.
Args:
mkdocs_config (Config): Mkdocs website configuration object.
Returns:
bool: True if the theme material and the plugin social cards is enabled.
"""
if not self.is_theme_material(mkdocs_config=mkdocs_config):
logger.debug(
"[rss-plugin] Installed theme is not 'material'. Integration disabled."
)
return False

if not mkdocs_config.plugins.get("material/social"):
logger.debug("[rss-plugin] Social plugin not listed in configuration.")
return False

social_plugin_cfg = mkdocs_config.plugins.get("material/social")

if not social_plugin_cfg.config.enabled:
logger.debug("[rss-plugin] Social plugin is installed but disabled.")
self.IS_SOCIAL_PLUGIN_ENABLED = False
return False

logger.debug("[rss-plugin] Social plugin is enabled in Mkdocs configuration.")
self.IS_SOCIAL_PLUGIN_CARDS_ENABLED = True
return True

def is_social_plugin_and_cards_enabled_mkdocs(self, mkdocs_config: Config) -> bool:
"""Check if social cards plugin is enabled.
Args:
mkdocs_config (Config): Mkdocs website configuration object.
Returns:
bool: True if the theme material and the plugin social cards is enabled.
"""
if not self.is_social_plugin_enabled_mkdocs(mkdocs_config=mkdocs_config):
return False

social_plugin_cfg = mkdocs_config.plugins.get("material/social")

if not social_plugin_cfg.config.cards:
logger.debug(
"[rss-plugin] Social plugin is installed, present but cards are disabled."
)
self.IS_SOCIAL_PLUGIN_CARDS_ENABLED = False
return False

logger.debug("[rss-plugin] Social cards are enabled in Mkdocs configuration.")
self.IS_SOCIAL_PLUGIN_CARDS_ENABLED = True
return True

def is_social_plugin_enabled_page(
self, mkdocs_page: Page, fallback_value: bool = True
) -> bool:
"""Check if the social plugin is enabled or disabled for a specific page. Plugin
has to enabled in Mkdocs configuration before.
Args:
mkdocs_page (Page): Mkdocs page object.
fallback_value (bool, optional): fallback value. It might be the
'plugins.social.cards.enabled' option in Mkdocs config. Defaults to True.
Returns:
bool: True if the social cards are enabled for a page.
"""
return mkdocs_page.meta.get("social", {"cards": fallback_value}).get(
"cards", fallback_value
)

def get_social_cards_dir(self, mkdocs_config: Config) -> str:
"""Get Social Cards folder within Mkdocs site_dir.
See: https://squidfunk.github.io/mkdocs-material/plugins/social/#config.cards_dir
Args:
mkdocs_config (Config): Mkdocs website configuration object.
Returns:
str: True if the theme material and the plugin social cards is enabled.
"""
social_plugin_cfg = mkdocs_config.plugins.get("material/social")

logger.debug(
"[rss-plugin] Social cards folder in Mkdocs build directory: "
f"{social_plugin_cfg.config.cards_dir}."
)

return social_plugin_cfg.config.cards_dir

def get_social_card_build_path_for_page(
self, mkdocs_page: Page, mkdocs_site_dir: Optional[str] = None
) -> Path:
"""Get social card URL for a specific page in documentation.
Args:
mkdocs_page (Page): Mkdocs page object.
mkdocs_site_dir (Optional[str], optional): Mkdocs build site dir. If None, the
'class.mkdocs_site_build_dir' is used. is Defaults to None.
Returns:
str: URL to the image once published
"""
if mkdocs_site_dir is None and self.mkdocs_site_build_dir:
mkdocs_site_dir = self.mkdocs_site_build_dir

return Path(
f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/"
f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
)

def get_social_card_url_for_page(
self,
mkdocs_page: Page,
mkdocs_site_url: Optional[str] = None,
) -> str:
"""Get social card URL for a specific page in documentation.
Args:
mkdocs_page (Page): Mkdocs page object.
mkdocs_site_url (Optional[str], optional): Mkdocs site URL. If None, the
'class.mkdocs_site_url' is used. is Defaults to None.
Returns:
str: URL to the image once published
"""
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')}"
17 changes: 15 additions & 2 deletions mkdocs_rss_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from jinja2 import Environment, FileSystemLoader, select_autoescape
from mkdocs.config import config_options
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin
from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.structure.pages import Page
from mkdocs.utils import get_build_timestamp

Expand All @@ -30,6 +30,9 @@
OUTPUT_FEED_CREATED,
OUTPUT_FEED_UPDATED,
)
from mkdocs_rss_plugin.integrations.theme_material_social_plugin import (
IntegrationMaterialSocialCards,
)
from mkdocs_rss_plugin.models import PageInformation
from mkdocs_rss_plugin.util import Util

Expand Down Expand Up @@ -79,8 +82,17 @@ def on_config(self, config: config_options.Config) -> dict:
if not self.config.enabled:
return config

# integrations - check if theme is Material and if social cards are enabled
self.integration_material_social_cards = IntegrationMaterialSocialCards(
mkdocs_config=config,
switch_force=self.config.use_material_social_cards,
)

# instanciate plugin tooling
self.util = Util(use_git=self.config.use_git)
self.util = Util(
use_git=self.config.use_git,
integration_material_social_cards=self.integration_material_social_cards,
)

# check template dirs
if not Path(DEFAULT_TEMPLATE_FILENAME).is_file():
Expand Down Expand Up @@ -174,6 +186,7 @@ def on_config(self, config: config_options.Config) -> dict:
# ending event
return config

@event_priority(priority=-75)
def on_page_content(
self, html: str, page: Page, config: config_options.Config, files
) -> str:
Expand Down
Loading

0 comments on commit 40f628f

Please sign in to comment.