From 9a6b8c2c137a849cadc5a5197d6f2a11cb6cd78e Mon Sep 17 00:00:00 2001 From: Andre_601 Date: Wed, 3 Jul 2024 15:13:54 +0200 Subject: [PATCH 001/158] Remove social options from example Signed-off-by: Andre_601 --- docs/configuration.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index e4a71204..125f3e69 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -189,10 +189,6 @@ To customize the value of the RSS description per each page and override the val date: 2024-06-24 description: >- This is the SEO description. -social: - cards_layout_options: - description: >- - This is the social cards description. rss: feed_description: >- And I want to have customized RSS description. From c535f7169cf1cddacf46ea3247b1f63d31223392 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 22 Jul 2024 16:56:33 +0200 Subject: [PATCH 002/158] fix(docs): footer sponsors link --- mkdocs.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 6a516d7b..bca3d087 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -22,8 +22,11 @@ extra: link: https://mapstodon.space/@geojulien name: "Follow me on Mastodon" - icon: "fontawesome/solid/piggy-bank" - link: /team/sponsoring/ - name: "Sponsor development" + link: https://github.com/sponsors/Guts + name: "Sponsor development with Github" + - icon: "simple/liberapay" + link: https://liberapay.com/GeoJulien + name: "Sponsor development with Liberapay" # Extensions to enhance markdown markdown_extensions: From 12149d64604c9c5edd6d2cab4fcfa5934a00751c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:02:45 +0000 Subject: [PATCH 003/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.16.0 → v3.17.0](https://github.com/asottile/pyupgrade/compare/v3.16.0...v3.17.0) - [github.com/astral-sh/ruff-pre-commit: v0.5.0 → v0.5.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.0...v0.5.6) - [github.com/psf/black: 24.4.2 → 24.8.0](https://github.com/psf/black/compare/24.4.2...24.8.0) - [github.com/pycqa/flake8: 7.1.0 → 7.1.1](https://github.com/pycqa/flake8/compare/7.1.0...7.1.1) --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e258068d..801d6c22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.16.0 + rev: v3.17.0 hooks: - id: pyupgrade args: - "--py38-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.0" + rev: "v0.5.6" hooks: - id: ruff args: @@ -55,14 +55,14 @@ repos: - --filter-files - repo: https://github.com/psf/black - rev: 24.4.2 + rev: 24.8.0 hooks: - id: black args: - --target-version=py38 - repo: https://github.com/pycqa/flake8 - rev: 7.1.0 + rev: 7.1.1 hooks: - id: flake8 additional_dependencies: From ca56fed2e02654e6accfba9f3f7c45c6d9b65f81 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 19:42:14 +0000 Subject: [PATCH 004/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.6 → v0.6.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.6...v0.6.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 801d6c22..7fff20a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py38-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.6" + rev: "v0.6.3" hooks: - id: ruff args: From 020d441a1ff12a12238d5e85436e80271bc18dae Mon Sep 17 00:00:00 2001 From: Mikhail Velikikh Date: Thu, 5 Sep 2024 09:22:19 +0100 Subject: [PATCH 005/158] Make match_path OS agnostic `page.file.src_path` on Windows contains backslashes resulting in an empty RSS feed if `match_path` contains a forward slash. This commit replaces `src_path` with `src_uri` which provides an OS independent path with forward slashes '/'. Signed-off-by: Mikhail Velikikh --- mkdocs_rss_plugin/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index c4ab87f2..703c6c1a 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -275,7 +275,7 @@ def on_page_content( return # skip pages that don't match the config var match_path - if not self.match_path_pattern.match(page.file.src_path): + if not self.match_path_pattern.match(page.file.src_uri): return # skip pages with draft=true From 020609cb24cdd33cdb61ba544352310055fba71e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:06:31 +0000 Subject: [PATCH 006/158] build(deps): bump codecov/codecov-action from 4.5.0 to 4.6.0 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.5.0...v4.6.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 1bcf8ea2..2b3df859 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.5.0 + uses: codecov/codecov-action@v4.6.0 with: env_vars: PYTHON flags: unittests From f72e5825191fda8bdfa75f193ad144b1d8147d19 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 20:46:13 +0000 Subject: [PATCH 007/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.6.3 → v0.6.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.3...v0.6.9) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7fff20a4..aada4804 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: ".venv|.direnv|tests/dev/|tests/fixtures/" fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-added-large-files args: @@ -38,7 +38,7 @@ repos: - "--py38-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.3" + rev: "v0.6.9" hooks: - id: ruff args: From 93a23d31440a3d1c64e6932c0742bd7663b192ec Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Wed, 23 Oct 2024 15:55:35 +0200 Subject: [PATCH 008/158] update(packaging): remove support for Python 3.8, add support for 3.13 --- .github/workflows/lint-and-tests.yml | 2 +- .pre-commit-config.yaml | 6 +-- mkdocs_rss_plugin/timezoner_pre39.py | 56 ---------------------------- mkdocs_rss_plugin/util.py | 18 +++------ setup.py | 8 ++-- sonar-project.properties | 2 +- 6 files changed, 15 insertions(+), 77 deletions(-) delete mode 100644 mkdocs_rss_plugin/timezoner_pre39.py diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 2b3df859..6aae454b 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -22,11 +22,11 @@ jobs: fail-fast: false matrix: python-version: - - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" + - "3.13" # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aada4804..7a9fc1c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: pyupgrade args: - - "--py38-plus" + - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.6.9" @@ -43,7 +43,7 @@ repos: - id: ruff args: - --fix-only - - --target-version=py38 + - --target-version=py39 - repo: https://github.com/pycqa/isort rev: 5.13.2 @@ -59,7 +59,7 @@ repos: hooks: - id: black args: - - --target-version=py38 + - --target-version=py39 - repo: https://github.com/pycqa/flake8 rev: 7.1.1 diff --git a/mkdocs_rss_plugin/timezoner_pre39.py b/mkdocs_rss_plugin/timezoner_pre39.py deleted file mode 100644 index 36e309d9..00000000 --- a/mkdocs_rss_plugin/timezoner_pre39.py +++ /dev/null @@ -1,56 +0,0 @@ -#! python3 # noqa: E265 - - -""" -Manage timezones for pages date(time)s using pytz module. -Meant to be dropped when Python 3.8 reaches EOL. -""" - -# ############################################################################ -# ########## Libraries ############# -# ################################## - -# standard library -from datetime import datetime - -# 3rd party -import pytz -from mkdocs.plugins import get_plugin_logger - -# package -from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME - -# ############################################################################ -# ########## Globals ############# -# ################################ - - -logger = get_plugin_logger(MKDOCS_LOGGER_NAME) - - -# ############################################################################ -# ########## Functions ########### -# ################################ - - -def set_datetime_zoneinfo( - input_datetime: datetime, config_timezone: str = "UTC" -) -> datetime: - """Apply timezone to a naive datetime. - - :param input_datetime: offset-naive datetime - :type input_datetime: datetime - :param config_timezone: name of timezone as registered in IANA database, - defaults to "UTC". Example : Europe/Paris. - :type config_timezone: str, optional - - :return: offset-aware datetime - :rtype: datetime - """ - if input_datetime.tzinfo: - return input_datetime - elif not config_timezone: - return input_datetime.replace(tzinfo=pytz.utc) - else: - config_tz = pytz.timezone(config_timezone) - return config_tz.localize(input_datetime) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index df00c72a..1c14ab33 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -6,14 +6,13 @@ # standard library import logging -import sys from collections.abc import Iterable from datetime import date, datetime from email.utils import format_datetime from functools import lru_cache from mimetypes import guess_type from pathlib import Path -from typing import Any, List, Tuple, Union +from typing import Any, Union from urllib.parse import urlencode, urlparse, urlunparse # 3rd party @@ -46,12 +45,7 @@ IntegrationMaterialSocialCards, ) from mkdocs_rss_plugin.models import PageInformation - -# conditional imports -if sys.version_info < (3, 9): - from mkdocs_rss_plugin.timezoner_pre39 import set_datetime_zoneinfo -else: - from mkdocs_rss_plugin.timezoner import set_datetime_zoneinfo +from mkdocs_rss_plugin.timezoner import set_datetime_zoneinfo # ############################################################################ # ########## Globals ############# @@ -202,7 +196,7 @@ def get_file_dates( meta_datetime_format: str, meta_default_time: datetime, meta_default_timezone: str, - ) -> Tuple[datetime, datetime]: + ) -> tuple[datetime, datetime]: """Extract creation and update dates from page metadata (yaml frontmatter) or git log for given file. @@ -358,7 +352,7 @@ def get_file_dates( get_build_datetime(), ) - def get_authors_from_meta(self, in_page: Page) -> Optional[Tuple[str]]: + def get_authors_from_meta(self, in_page: Page) -> Optional[tuple[str]]: """Returns authors from page meta. It handles 'author' and 'authors' for keys, \ str and iterable as values types. @@ -542,7 +536,7 @@ def get_description_or_abstract( ) return "" - def get_image(self, in_page: Page, base_url: str) -> Optional[Tuple[str, str, int]]: + def get_image(self, in_page: Page, base_url: str) -> Optional[tuple[str, str, int]]: """Get page's image from page meta or social cards and returns properties. Args: @@ -782,7 +776,7 @@ def guess_locale(self, mkdocs_config: MkDocsConfig) -> Optional[str]: return None @staticmethod - def filter_pages(pages: List[PageInformation], attribute: str, length: int) -> list: + def filter_pages(pages: list[PageInformation], attribute: str, length: int) -> list: """Filter and return pages into a friendly RSS structure. Args: diff --git a/setup.py b/setup.py index 76b4b2a4..87ff97df 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ # standard library from pathlib import Path -from typing import List, Union +from typing import Union # 3rd party from setuptools import find_packages, setup @@ -26,7 +26,7 @@ # ################################## -def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: +def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: """Helper to load requirements list from a path or a list of paths. Args: @@ -79,7 +79,7 @@ def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: # run entry_points={"mkdocs.plugins": ["rss = mkdocs_rss_plugin.plugin:GitRssPlugin"]}, # dependencies - python_requires=">=3.8, <4", + python_requires=">=3.9, <4", extras_require={ # tooling "dev": load_requirements(HERE / "requirements/development.txt"), @@ -93,11 +93,11 @@ def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", diff --git a/sonar-project.properties b/sonar-project.properties index dd181754..9b189759 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.projectKey=Guts_mkdocs-rss-plugin # only=main # Python versions -sonar.python.version=3.8, 3.9, 3.10, 3.11, 3.12 +sonar.python.version=3.9, 3.10, 3.11, 3.12, 3.13 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. sonar.sources=mkdocs_rss_plugin From d8ceb472d2956a8d1af64ba5b7bcd6f059bdafa1 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Wed, 23 Oct 2024 15:58:06 +0200 Subject: [PATCH 009/158] update(code): apply git hooks with new minimal Python version --- mkdocs_rss_plugin/plugin.py | 4 ++-- tests/test_build.py | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index 703c6c1a..a9e7beba 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -11,7 +11,7 @@ from email.utils import formatdate from pathlib import Path from re import compile as re_compile -from typing import List, Literal, Optional +from typing import Literal, Optional # 3rd party from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -79,7 +79,7 @@ def on_startup( # flag used command to disable some actions if serve is used self.cmd_is_serve = command == "serve" - self.pages_to_filter: List[PageInformation] = [] + self.pages_to_filter: list[PageInformation] = [] # prepare output feeds self.feed_created: dict = {} self.feed_updated: dict = {} diff --git a/tests/test_build.py b/tests/test_build.py index 78ac4773..a312fbf0 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -755,16 +755,20 @@ def test_json_feed_validation(self): self.assertIsNone(cli_result.exception) # created items - with Path(tmpdirname).joinpath(OUTPUT_JSON_FEED_CREATED).open( - "r", encoding="UTF-8" - ) as in_json: + with ( + Path(tmpdirname) + .joinpath(OUTPUT_JSON_FEED_CREATED) + .open("r", encoding="UTF-8") as in_json + ): json_feed_created_data = json.load(in_json) jsonfeed.Feed.parse(json_feed_created_data) # updated items - with Path(tmpdirname).joinpath(OUTPUT_JSON_FEED_UPDATED).open( - "r", encoding="UTF-8" - ) as in_json: + with ( + Path(tmpdirname) + .joinpath(OUTPUT_JSON_FEED_UPDATED) + .open("r", encoding="UTF-8") as in_json + ): json_feed_updated_data = json.load(in_json) jsonfeed.Feed.parse(json_feed_updated_data) From e6da7207c83681a56191f1676f2b921ba2d432a4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Wed, 23 Oct 2024 15:43:56 +0200 Subject: [PATCH 010/158] feature(integration): support social cards for blog plugin posts --- .../theme_material_social_plugin.py | 96 ++++++++++++++++--- tests/fixtures/docs/blog/.authors.yml | 15 +++ tests/fixtures/docs/blog/index.md | 2 + tests/fixtures/docs/blog/posts/firstpost.md | 32 +++++++ tests/fixtures/docs/blog/posts/secondpost.md | 32 +++++++ .../mkdocs_item_image_social_cards_blog.yml | 14 +++ ...test_integrations_material_social_cards.py | 17 ++++ 7 files changed, 197 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/docs/blog/.authors.yml create mode 100644 tests/fixtures/docs/blog/index.md create mode 100644 tests/fixtures/docs/blog/posts/firstpost.md create mode 100644 tests/fixtures/docs/blog/posts/secondpost.md create mode 100644 tests/fixtures/mkdocs_item_image_social_cards_blog.yml diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 07914a31..65269760 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -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 ############# # ################################ @@ -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 @@ -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) @@ -85,6 +91,7 @@ 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_mkdocs(mkdocs_config=mkdocs_config) if self.is_mkdocs_theme_material_insiders(): self.load_cache_cards_manifest() @@ -123,6 +130,36 @@ 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.") + 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_SOCIAL_PLUGIN_CARDS_ENABLED = True + return True + def is_social_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool: """Check if social plugin is installed and enabled. @@ -274,18 +311,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]: @@ -305,16 +353,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: @@ -362,4 +422,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 diff --git a/tests/fixtures/docs/blog/.authors.yml b/tests/fixtures/docs/blog/.authors.yml new file mode 100644 index 00000000..17b0e05d --- /dev/null +++ b/tests/fixtures/docs/blog/.authors.yml @@ -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/ diff --git a/tests/fixtures/docs/blog/index.md b/tests/fixtures/docs/blog/index.md new file mode 100644 index 00000000..c58f16c5 --- /dev/null +++ b/tests/fixtures/docs/blog/index.md @@ -0,0 +1,2 @@ +# Blog + diff --git a/tests/fixtures/docs/blog/posts/firstpost.md b/tests/fixtures/docs/blog/posts/firstpost.md new file mode 100644 index 00000000..5cdcd8c3 --- /dev/null +++ b/tests/fixtures/docs/blog/posts/firstpost.md @@ -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. + + + +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. + diff --git a/tests/fixtures/docs/blog/posts/secondpost.md b/tests/fixtures/docs/blog/posts/secondpost.md new file mode 100644 index 00000000..352d9978 --- /dev/null +++ b/tests/fixtures/docs/blog/posts/secondpost.md @@ -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. + + + +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. + diff --git a/tests/fixtures/mkdocs_item_image_social_cards_blog.yml b/tests/fixtures/mkdocs_item_image_social_cards_blog.yml new file mode 100644 index 00000000..26fe268c --- /dev/null +++ b/tests/fixtures/mkdocs_item_image_social_cards_blog.yml @@ -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 diff --git a/tests/test_integrations_material_social_cards.py b/tests/test_integrations_material_social_cards.py index 4bde30aa..64d47827 100644 --- a/tests/test_integrations_material_social_cards.py +++ b/tests/test_integrations_material_social_cards.py @@ -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( From 470d409579bfd44b9ee11ae9d8a9b2b9c2fd45b3 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 24 Oct 2024 18:17:02 +0200 Subject: [PATCH 011/158] fix(integration): IS8BLOG_PLUGIN_ENABLED was not correctly use --- .../integrations/theme_material_social_plugin.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 65269760..1382d035 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -91,7 +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_mkdocs(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() @@ -145,6 +147,7 @@ def is_blog_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool: 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( @@ -157,7 +160,7 @@ def is_blog_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool: return False logger.debug("Material blog plugin is enabled in Mkdocs configuration.") - self.IS_SOCIAL_PLUGIN_CARDS_ENABLED = True + self.IS_BLOG_PLUGIN_ENABLED = True return True def is_social_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig) -> bool: From 0e90d914b125336e723449ea1dec581a80be3891 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 24 Oct 2024 18:21:19 +0200 Subject: [PATCH 012/158] fix(test): add blog as exception --- tests/test_build.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_build.py b/tests/test_build.py index a312fbf0..7f07e479 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -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: From 8bb75c549dc5d4c6ecca7cdab7f1e7a9c1c60f82 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 24 Oct 2024 18:23:36 +0200 Subject: [PATCH 013/158] fix(test): exclude .authors.yml file from mkdocs config fixtures file --- tests/test_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_config.py b/tests/test_config.py index 47b9f68f..9c4cd695 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -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): From 318a29e29944a84c5543e5dad5cab5ad8a621e79 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 24 Oct 2024 18:39:05 +0200 Subject: [PATCH 014/158] release: bump version to 1.16.0 --- CHANGELOG.md | 23 +++++++++++++++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2976fd7e..d896a9a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.16.0 - 2024-10-24 + +### Bugs fixes 🐛 + +* Make match_path OS agnostic by @mvelikikh in + +### Features and enhancements 🎉 + +* feature(integration): support social cards for blog plugin posts by @Guts in + +### Documentation 📖 + +* Remove social options from example by @Andre601 in + +### Other Changes + +* Packaging: drop python 3 8, add 3.13 support by @Guts in + +## New Contributors + +* @Andre601 made their first contribution in +* @mvelikikh made their first contribution in + ## 1.15.0 - 2024-07-03 ### Features and enhancements 🎉 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index ec40fea1..03547555 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.15.0" +__version__ = "1.16.0" __version_info__ = tuple( [ int(num) if num.isdigit() else num From b7142893654276d60a30aa6b8cd1096a8a839698 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:22:36 +0000 Subject: [PATCH 015/158] build(deps): update mkdocs-git-committers-plugin-2 requirement Updates the requirements on [mkdocs-git-committers-plugin-2](https://github.com/ojacques/mkdocs-git-committers-plugin-2) to permit the latest version. - [Release notes](https://github.com/ojacques/mkdocs-git-committers-plugin-2/releases) - [Commits](https://github.com/ojacques/mkdocs-git-committers-plugin-2/compare/1.2.0...2.4.1) --- updated-dependencies: - dependency-name: mkdocs-git-committers-plugin-2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 9a97807b..714d18af 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -1,7 +1,7 @@ # Documentation # ----------------------- -mkdocs-git-committers-plugin-2>=1.2,<2.4 +mkdocs-git-committers-plugin-2>=1.2,<2.5 mkdocs-git-revision-date-localized-plugin>=1,<1.3 mkdocs-material[imaging]>=9.5.1,<10 mkdocs-minify-plugin==0.8.* From 06fa886d1413465de081adae10bce866517a6805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 12:46:47 +0000 Subject: [PATCH 016/158] build(deps): update mkdocs-git-revision-date-localized-plugin requirement Updates the requirements on [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin) to permit the latest version. - [Release notes](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/releases) - [Commits](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/compare/v1.0.0...v1.3.0) --- updated-dependencies: - dependency-name: mkdocs-git-revision-date-localized-plugin dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 714d18af..1b5146f8 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -2,7 +2,7 @@ # ----------------------- mkdocs-git-committers-plugin-2>=1.2,<2.5 -mkdocs-git-revision-date-localized-plugin>=1,<1.3 +mkdocs-git-revision-date-localized-plugin>=1,<1.4 mkdocs-material[imaging]>=9.5.1,<10 mkdocs-minify-plugin==0.8.* mkdocstrings[python]>=0.18,<1 From 786fa2b9fa3533489e09bb83d6a4bdb16d6bc0ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:06:05 +0000 Subject: [PATCH 017/158] build(deps): update pytest-cov requirement from <5.1,>=4 to >=4,<6.1 Updates the requirements on [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v6.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/testing.txt b/requirements/testing.txt index 9618fdd1..9c9512a0 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -6,5 +6,5 @@ feedparser>=6.0.11,<6.1 jsonfeed-util>=1.1.2,<2 mkdocs-material[imaging]>=9 -pytest-cov>=4,<5.1 +pytest-cov>=4,<6.1 validator-collection>=1.5,<1.6 From 73b18e4dc21fc846e601d48b411dbb137125eb3f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:06:50 +0000 Subject: [PATCH 018/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.17.0 → v3.19.0](https://github.com/asottile/pyupgrade/compare/v3.17.0...v3.19.0) - [github.com/astral-sh/ruff-pre-commit: v0.6.9 → v0.7.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.9...v0.7.2) - [github.com/psf/black: 24.8.0 → 24.10.0](https://github.com/psf/black/compare/24.8.0...24.10.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a9fc1c2..a90519f8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.17.0 + rev: v3.19.0 hooks: - id: pyupgrade args: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.9" + rev: "v0.7.2" hooks: - id: ruff args: @@ -55,7 +55,7 @@ repos: - --filter-files - repo: https://github.com/psf/black - rev: 24.8.0 + rev: 24.10.0 hooks: - id: black args: From 83f9403986b68c6a1bfaf938e0e9848e4e012467 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 18:43:59 +0000 Subject: [PATCH 019/158] build(deps): bump codecov/codecov-action from 4.6.0 to 5.0.7 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.6.0 to 5.0.7. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.6.0...v5.0.7) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 6aae454b..9de14fd0 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.6.0 + uses: codecov/codecov-action@v5.0.7 with: env_vars: PYTHON flags: unittests From c3b4eecedb7737151b0ec31df8e4b73d9f72f1bd Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Sat, 30 Nov 2024 22:48:46 +0100 Subject: [PATCH 020/158] refacto(material_integrations): use POO to manage integrations with Material theme --- .../integrations/theme_material_base.py | 89 ++++++++++++++ .../theme_material_blog_plugin.py | 103 ++++++++++++++++ .../theme_material_social_plugin.py | 110 +++++------------- 3 files changed, 223 insertions(+), 79 deletions(-) create mode 100644 mkdocs_rss_plugin/integrations/theme_material_base.py create mode 100644 mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py new file mode 100644 index 00000000..e5215fcf --- /dev/null +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -0,0 +1,89 @@ +#! python3 # noqa: E265 + +# ############################################################################ +# ########## Libraries ############# +# ################################## + +# standard library +from typing import Optional + +# 3rd party +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import get_plugin_logger + +# package +from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME + +# 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 ############# +# ################################ + +logger = get_plugin_logger(MKDOCS_LOGGER_NAME) + +# ############################################################################ +# ########## Logic ############### +# ################################ + + +class IntegrationMaterialThemeBase: + # attributes + IS_THEME_MATERIAL: bool = False + IS_INSIDERS: bool = False + + def __init__(self, mkdocs_config: MkDocsConfig) -> None: + """Integration instantiation. + + Args: + mkdocs_config (MkDocsConfig): Mkdocs website configuration object. + """ + # store Mkdocs config as attribute + self.mkdocs_config = mkdocs_config + + self.IS_THEME_MATERIAL = self.is_mkdocs_theme_material() + self.IS_INSIDERS = self.is_mkdocs_theme_material_insiders() + + def is_mkdocs_theme_material( + self, mkdocs_config: Optional[MkDocsConfig] = None + ) -> bool: + """Check if the theme set in mkdocs.yml is material or not. + + Args: + mkdocs_config (Optional[MkDocsConfig]): Mkdocs website configuration object. + + Returns: + bool: True if the theme's name is 'material'. False if not. + """ + if mkdocs_config is None and isinstance(self.mkdocs_config, MkDocsConfig): + mkdocs_config = self.mkdocs_config + + self.IS_THEME_MATERIAL = mkdocs_config.theme.name == "material" + return self.IS_THEME_MATERIAL + + def is_mkdocs_theme_material_insiders(self) -> Optional[bool]: + """Check if the material theme is community or insiders edition. + + Returns: + bool: True if the theme is Insiders edition. False if community. None if + the Material theme is not installed. + """ + if not self.IS_THEME_MATERIAL: + return None + + if material_version is not None and "insiders" in material_version: + logger.debug("Material theme edition INSIDERS") + self.IS_INSIDERS = True + return True + else: + logger.debug("Material theme edition COMMUNITY") + self.IS_INSIDERS = False + return False diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py new file mode 100644 index 00000000..b90c00cb --- /dev/null +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -0,0 +1,103 @@ +#! python3 # noqa: E265 + +# ############################################################################ +# ########## Libraries ############# +# ################################## + +# standard library +from typing import Optional + +# 3rd party +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import get_plugin_logger + +# package +from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME +from mkdocs_rss_plugin.integrations.theme_material_base import ( + IntegrationMaterialThemeBase, +) + +# conditional +try: + from material import __version__ as material_version + from material.plugins.blog.plugin import BlogPlugin + +except ImportError: + material_version = None + + +# ############################################################################ +# ########## Globals ############# +# ################################ + +logger = get_plugin_logger(MKDOCS_LOGGER_NAME) + +# ############################################################################ +# ########## Logic ############### +# ################################ + + +class IntegrationMaterialBlog(IntegrationMaterialThemeBase): + # attributes + IS_ENABLED: bool = True + IS_BLOG_PLUGIN_ENABLED: bool = True + + def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> None: + """Integration instantiation. + + Args: + mkdocs_config (MkDocsConfig): 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_BLOG_PLUGIN_ENABLED = self.is_blog_plugin_enabled_mkdocs( + mkdocs_config=mkdocs_config + ) + # if every conditions are True, enable the integration + self.IS_ENABLED = all([self.IS_THEME_MATERIAL, self.IS_BLOG_PLUGIN_ENABLED]) + + # except if the end-user wants to disable it + if switch_force is False: + self.IS_ENABLED = False + logger.debug( + "Integration with Blog (Material theme) is " + "disabled in plugin's option in Mkdocs configuration." + ) + + def is_blog_plugin_enabled_mkdocs( + self, mkdocs_config: Optional[MkDocsConfig] + ) -> bool: + """Check if blog plugin is installed and enabled. + + Args: + mkdocs_config (Optional[MkDocsConfig]): Mkdocs website configuration object. + + Returns: + bool: True if the theme material and the plugin blog is enabled. + """ + if mkdocs_config is None and isinstance(self.mkdocs_config, MkDocsConfig): + mkdocs_config = self.mkdocs_config + + 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 diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 1382d035..257efeb5 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -17,11 +17,16 @@ # package from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME +from mkdocs_rss_plugin.integrations.theme_material_base import ( + IntegrationMaterialThemeBase, +) +from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import ( + IntegrationMaterialBlog, +) # conditional try: from material import __version__ as material_version - from material.plugins.blog.plugin import BlogPlugin from pymdownx.slugs import slugify except ImportError: @@ -39,14 +44,11 @@ # ################################ -class IntegrationMaterialSocialCards: +class IntegrationMaterialSocialCards(IntegrationMaterialThemeBase): # 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 - IS_INSIDERS: bool = False CARDS_MANIFEST: Optional[dict] = None def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> None: @@ -58,7 +60,10 @@ 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 + # support cards for blog posts + self.integration_material_blog = IntegrationMaterialBlog( + 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) @@ -91,9 +96,7 @@ 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() @@ -101,77 +104,20 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No self.site_name = mkdocs_config.site_name self.site_description = mkdocs_config.site_description or "" - def is_mkdocs_theme_material(self, mkdocs_config: MkDocsConfig) -> bool: - """Check if the theme set in mkdocs.yml is material or not. - - Args: - mkdocs_config (MkDocsConfig): 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_mkdocs_theme_material_insiders(self) -> Optional[bool]: - """Check if the material theme is community or insiders edition. - - Returns: - bool: True if the theme is Insiders edition. False if community. None if - the Material theme is not installed. - """ - if not self.IS_THEME_MATERIAL: - return None - - if material_version is not None and "insiders" in material_version: - logger.debug("Material theme edition INSIDERS") - self.IS_INSIDERS = True - return True - else: - logger.debug("Material theme edition COMMUNITY") - 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: + def is_social_plugin_enabled_mkdocs( + self, mkdocs_config: Optional[MkDocsConfig] = None + ) -> bool: """Check if social plugin is installed and enabled. Args: - mkdocs_config (MkDocsConfig): Mkdocs website configuration object. + mkdocs_config (Optional[MkDocsConfig]): Mkdocs website configuration object. Returns: bool: True if the theme material and the plugin social cards is enabled. """ + if mkdocs_config is None and isinstance(self.mkdocs_config, MkDocsConfig): + mkdocs_config = self.mkdocs_config + if not self.is_mkdocs_theme_material(mkdocs_config=mkdocs_config): logger.debug("Installed theme is not 'material'. Integration disabled.") return False @@ -315,9 +261,11 @@ def get_social_card_build_path_for_page( mkdocs_site_dir = self.mkdocs_site_build_dir # if page is a blog post - if self.IS_BLOG_PLUGIN_ENABLED and Path( + if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( mkdocs_page.file.src_uri - ).is_relative_to(self.blog_plugin_cfg.config.blog_dir): + ).is_relative_to( + self.integration_material_blog.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" @@ -358,9 +306,11 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat if self.IS_INSIDERS: # if page is a blog post - if self.IS_BLOG_PLUGIN_ENABLED and Path( + if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( mkdocs_page.file.src_uri - ).is_relative_to(self.blog_plugin_cfg.config.blog_dir): + ).is_relative_to( + self.integration_material_blog.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" ) @@ -426,9 +376,11 @@ def get_social_card_url_for_page( mkdocs_site_url = self.mkdocs_site_url # if page is a blog post - if self.IS_BLOG_PLUGIN_ENABLED and Path( + if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( mkdocs_page.file.src_uri - ).is_relative_to(self.blog_plugin_cfg.config.blog_dir): + ).is_relative_to( + self.integration_material_blog.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" From d45c3034c185404961fa1a1da1db228af7ced571 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Sun, 1 Dec 2024 10:30:57 +0100 Subject: [PATCH 021/158] refacto(material_integrations): adapt social cards tests --- tests/test_integrations_material_social_cards.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_integrations_material_social_cards.py b/tests/test_integrations_material_social_cards.py index 64d47827..eab4e1ca 100644 --- a/tests/test_integrations_material_social_cards.py +++ b/tests/test_integrations_material_social_cards.py @@ -131,7 +131,9 @@ def test_plugin_config_social_cards_enabled_with_blog_plugin(self): 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.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + ) self.assertTrue(integration_social_cards.IS_ENABLED) def test_simple_build(self): From 0a67ba69fd3695a49dadf1e4e50fb50e4d7c77a1 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 12:11:48 +0100 Subject: [PATCH 022/158] improve(material_integrations): add minimal test against material blog integration --- .../mkdocs_items_material_blog_enabled.yml | 11 ++++ tests/test_integrations_material_blog.py | 60 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tests/fixtures/mkdocs_items_material_blog_enabled.yml create mode 100644 tests/test_integrations_material_blog.py diff --git a/tests/fixtures/mkdocs_items_material_blog_enabled.yml b/tests/fixtures/mkdocs_items_material_blog_enabled.yml new file mode 100644 index 00000000..d637ea6b --- /dev/null +++ b/tests/fixtures/mkdocs_items_material_blog_enabled.yml @@ -0,0 +1,11 @@ +site_name: Test RSS Plugin +site_description: Test RSS with blog plugin also enabled +site_url: https://guts.github.io/mkdocs-rss-plugin + +plugins: + - blog: + blog_dir: blog + - rss + +theme: + name: material diff --git a/tests/test_integrations_material_blog.py b/tests/test_integrations_material_blog.py new file mode 100644 index 00000000..3255777b --- /dev/null +++ b/tests/test_integrations_material_blog.py @@ -0,0 +1,60 @@ +#! python3 # noqa E265 + +"""Usage from the repo root folder: + +.. code-block:: python + + # for whole test + python -m unittest tests.test_build + +""" + +# ############################################################################# +# ########## Libraries ############# +# ################################## + +# Standard library +import unittest +from logging import DEBUG, getLogger +from pathlib import Path + +# 3rd party +from mkdocs.config import load_config + +# package +from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import ( + IntegrationMaterialBlog, +) + +# test suite +from tests.base import BaseTest + +# ############################################################################# +# ########## Classes ############### +# ################################## + +logger = getLogger(__name__) +logger.setLevel(DEBUG) + + +class TestRssPluginIntegrationsMaterialBlog(BaseTest): + """Test integration of Material Blog plugin with RSS plugin.""" + + # -- TESTS --------------------------------------------------------- + def test_plugin_config_blog_enabled(self): + # default reference + cfg_mkdocs = load_config( + str(Path("tests/fixtures/mkdocs_items_material_blog_enabled.yml").resolve()) + ) + + integration_social_cards = IntegrationMaterialBlog(mkdocs_config=cfg_mkdocs) + self.assertTrue(integration_social_cards.IS_THEME_MATERIAL) + self.assertTrue(integration_social_cards.IS_BLOG_PLUGIN_ENABLED) + self.assertTrue(integration_social_cards.IS_ENABLED) + + +# ############################################################################## +# ##### Stand alone program ######## +# ################################## +if __name__ == "__main__": + unittest.main() From b12a481c0f0734ddbe8fc7241cc23eb1a50fdc62 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 12:18:24 +0100 Subject: [PATCH 023/158] update(quality): add type hint to calm down sonarqube --- mkdocs_rss_plugin/integrations/theme_material_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py index e5215fcf..ee015221 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_base.py +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -64,7 +64,7 @@ def is_mkdocs_theme_material( bool: True if the theme's name is 'material'. False if not. """ if mkdocs_config is None and isinstance(self.mkdocs_config, MkDocsConfig): - mkdocs_config = self.mkdocs_config + mkdocs_config: MkDocsConfig = self.mkdocs_config self.IS_THEME_MATERIAL = mkdocs_config.theme.name == "material" return self.IS_THEME_MATERIAL From c36dd95ab11a7061e41bb1cf91b9038e54e791b7 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 12:26:06 +0100 Subject: [PATCH 024/158] update(quality): add test against Material theme integration base --- tests/test_integrations_material.py | 71 +++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/test_integrations_material.py diff --git a/tests/test_integrations_material.py b/tests/test_integrations_material.py new file mode 100644 index 00000000..bb12b329 --- /dev/null +++ b/tests/test_integrations_material.py @@ -0,0 +1,71 @@ +#! python3 # noqa E265 + +"""Usage from the repo root folder: + +.. code-block:: python + + # for whole test + python -m unittest tests.test_build + +""" + +# ############################################################################# +# ########## Libraries ############# +# ################################## + +# Standard library +import unittest +from logging import DEBUG, getLogger +from pathlib import Path + +# 3rd party +from mkdocs.config import load_config + +# package +from mkdocs_rss_plugin.integrations.theme_material_base import ( + IntegrationMaterialThemeBase, +) + +# test suite +from tests.base import BaseTest + +# ############################################################################# +# ########## Classes ############### +# ################################## + +logger = getLogger(__name__) +logger.setLevel(DEBUG) + + +class TestRssPluginIntegrationsMaterialThem(BaseTest): + """Test integration of Material theme.""" + + # -- TESTS --------------------------------------------------------- + def test_plugin_config_theme_material(self): + # default reference + cfg_mkdocs = load_config( + str(Path("tests/fixtures/mkdocs_language_specific_material.yml").resolve()) + ) + + integration_social_cards = IntegrationMaterialThemeBase( + mkdocs_config=cfg_mkdocs + ) + self.assertTrue(integration_social_cards.IS_THEME_MATERIAL) + + def test_plugin_config_theme_not_material(self): + # default reference + cfg_mkdocs = load_config( + str(Path("tests/fixtures/mkdocs_complete.yml").resolve()) + ) + + integration_social_cards = IntegrationMaterialThemeBase( + mkdocs_config=cfg_mkdocs + ) + self.assertFalse(integration_social_cards.IS_THEME_MATERIAL) + + +# ############################################################################## +# ##### Stand alone program ######## +# ################################## +if __name__ == "__main__": + unittest.main() From 72a2de7f2b21c689f03a7abee22d3ab3af2ac177 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 12:37:05 +0100 Subject: [PATCH 025/158] update(deps): upgrade minimal dependencies --- requirements/base.txt | 5 ++--- requirements/development.txt | 12 ++++++------ requirements/documentation.txt | 12 ++++++------ requirements/testing.txt | 4 ++-- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index cb8de783..af8bcd7d 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -2,8 +2,7 @@ # ----------------------- cachecontrol[filecache] >=0.14,<1 -GitPython>=3.1,<3.2 -mkdocs>=1.5,<2 +GitPython>=3.1.43,<3.2 +mkdocs>=1.6.1,<2 requests>=2.31,<3 -pytz==2024.* ; python_version < "3.9" tzdata==2024.* ; python_version >= "3.9" and sys_platform == "win32" diff --git a/requirements/development.txt b/requirements/development.txt index f8626501..c2585564 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -3,9 +3,9 @@ # Development # ----------------------- black -flake8>=6,<8 -flake8-bugbear>=23.12 -flake8-builtins>=2.1 -flake8-eradicate>=1 -flake8-isort>=6 -pre-commit>=3,<4 +flake8>=7.1,<8 +flake8-bugbear>=24.10 +flake8-builtins>=2.5 +flake8-eradicate>=1.5 +flake8-isort>=6.1.1 +pre-commit>=3.7,<4 diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 1b5146f8..73206294 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -1,9 +1,9 @@ # Documentation # ----------------------- -mkdocs-git-committers-plugin-2>=1.2,<2.5 -mkdocs-git-revision-date-localized-plugin>=1,<1.4 -mkdocs-material[imaging]>=9.5.1,<10 -mkdocs-minify-plugin==0.8.* -mkdocstrings[python]>=0.18,<1 -termynal>=0.11.1,<0.13 +mkdocs-git-committers-plugin-2>=2.4.1,<2.5 +mkdocs-git-revision-date-localized-plugin>=1.3,<1.4 +mkdocs-material[imaging]>=9.5.47,<10 +mkdocs-minify-plugin>=0.8,<0.9 +mkdocstrings[python]>=0.27,<1 +termynal>=0.12.2,<0.13 diff --git a/requirements/testing.txt b/requirements/testing.txt index 9c9512a0..e5947b93 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -5,6 +5,6 @@ feedparser>=6.0.11,<6.1 jsonfeed-util>=1.1.2,<2 -mkdocs-material[imaging]>=9 -pytest-cov>=4,<6.1 +mkdocs-material[imaging]>=9.5.47 +pytest-cov>=6,<7 validator-collection>=1.5,<1.6 From 8fd6f7419ae0146e685e7be5752f9f13d4a97b3b Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 13:22:10 +0100 Subject: [PATCH 026/158] update(chore): use typed dataclasses instead of dict --- mkdocs_rss_plugin/models.py | 29 ++++++++++++++- mkdocs_rss_plugin/plugin.py | 73 +++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 38 deletions(-) diff --git a/mkdocs_rss_plugin/models.py b/mkdocs_rss_plugin/models.py index 7e863bd8..93ea01de 100644 --- a/mkdocs_rss_plugin/models.py +++ b/mkdocs_rss_plugin/models.py @@ -5,15 +5,21 @@ # ################################## # standard +from dataclasses import dataclass, field from datetime import datetime from pathlib import Path -from typing import NamedTuple, Optional +from typing import Optional +# package modules +from mkdocs_rss_plugin.__about__ import __title__, __version__ # ############################################################################ # ########## Classes ############### # ################################## -class PageInformation(NamedTuple): + + +@dataclass +class PageInformation: """Data type to set and get page information in order to produce the RSS feed.""" abs_path: Optional[Path] = None @@ -27,3 +33,22 @@ class PageInformation(NamedTuple): updated: Optional[datetime] = None url_comments: Optional[str] = None url_full: Optional[str] = None + + +@dataclass +class RssFeedBase: + author: Optional[str] = None + buildDate: Optional[str] = None + copyright: Optional[str] = None + description: Optional[str] = None + entries: list[PageInformation] = field(default_factory=list) + generator: str = f"{__title__} - v{__version__}" + html_url: Optional[str] = None + json_url: Optional[str] = None + language: Optional[str] = None + logo_url: Optional[str] = None + pubDate: Optional[str] = None + repo_url: Optional[str] = None + rss_url: Optional[str] = None + title: Optional[str] = None + ttl: Optional[int] = None diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index a9e7beba..3f2a38bb 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -7,6 +7,7 @@ # standard library import json from copy import deepcopy +from dataclasses import asdict from datetime import datetime from email.utils import formatdate from pathlib import Path @@ -33,7 +34,7 @@ from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) -from mkdocs_rss_plugin.models import PageInformation +from mkdocs_rss_plugin.models import PageInformation, RssFeedBase from mkdocs_rss_plugin.util import Util # ############################################################################ @@ -81,8 +82,8 @@ def on_startup( self.pages_to_filter: list[PageInformation] = [] # prepare output feeds - self.feed_created: dict = {} - self.feed_updated: dict = {} + self.feed_created: RssFeedBase = RssFeedBase() + self.feed_updated: RssFeedBase = RssFeedBase() def on_config(self, config: MkDocsConfig) -> MkDocsConfig: """The config event is the first event called on build and @@ -139,30 +140,30 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: self.tpl_folder = DEFAULT_TEMPLATE_FOLDER # start a feed dictionary using global config vars - base_feed = { - "author": config.site_author or None, - "buildDate": formatdate(get_build_timestamp()), - "copyright": config.copyright, - "description": ( + base_feed = RssFeedBase( + author=config.site_author or None, + buildDate=formatdate(get_build_timestamp()), + copyright=config.copyright, + description=( self.config.feed_description if self.config.feed_description else config.site_description ), - "entries": [], - "generator": f"{__title__} - v{__version__}", - "html_url": self.util.get_site_url(mkdocs_config=config), - "language": self.util.guess_locale(mkdocs_config=config), - "pubDate": formatdate(get_build_timestamp()), - "repo_url": config.repo_url, - "title": ( + entries=[], + generator=f"{__title__} - v{__version__}", + html_url=self.util.get_site_url(mkdocs_config=config), + language=self.util.guess_locale(mkdocs_config=config), + pubDate=formatdate(get_build_timestamp()), + repo_url=config.repo_url, + title=( self.config.feed_title if self.config.feed_title else config.site_name ), - "ttl": self.config.feed_ttl, - } + ttl=self.config.feed_ttl, + ) # feed image if self.config.image: - base_feed["logo_url"] = self.config.image + base_feed.logo_url = self.config.image # pattern to match pages included in output self.match_path_pattern = re_compile(self.config.match_path) @@ -224,19 +225,19 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: self.feed_updated = deepcopy(base_feed) # final feed url - if base_feed.get("html_url"): + if base_feed.html_url: # concatenate both URLs - self.feed_created["rss_url"] = ( - base_feed.get("html_url") + self.config.feeds_filenames.rss_created + self.feed_created.rss_url = ( + base_feed.html_url + self.config.feeds_filenames.rss_created ) - self.feed_updated["rss_url"] = ( - base_feed.get("html_url") + self.config.feeds_filenames.rss_updated + self.feed_updated.rss_url = ( + base_feed.html_url + self.config.feeds_filenames.rss_updated ) - self.feed_created["json_url"] = ( - base_feed.get("html_url") + self.config.feeds_filenames.json_created + self.feed_created.json_url = ( + base_feed.html_url + self.config.feeds_filenames.json_created ) - self.feed_updated["json_url"] = ( - base_feed.get("html_url") + self.config.feeds_filenames.json_updated + self.feed_updated.json_url = ( + base_feed.html_url + self.config.feeds_filenames.json_updated ) else: logger.error( @@ -244,9 +245,9 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: "configuration file whereas a URL is mandatory to publish. " "See: https://validator.w3.org/feed/docs/rss2.html#requiredChannelElements" ) - self.feed_created["rss_url"] = self.feed_updated["json_url"] = ( - self.feed_updated["rss_url"] - ) = self.feed_updated["json_url"] = None + self.feed_created.rss_url = self.feed_updated.json_url = ( + self.feed_updated.rss_url + ) = self.feed_updated.json_url = None # ending event return config @@ -371,7 +372,7 @@ def on_post_build(self, config: config_options.Config) -> None: ) # created items - self.feed_created.get("entries").extend( + self.feed_created.entries.extend( self.util.filter_pages( pages=self.pages_to_filter, attribute="created", @@ -380,7 +381,7 @@ def on_post_build(self, config: config_options.Config) -> None: ) # updated items - self.feed_updated.get("entries").extend( + self.feed_updated.entries.extend( self.util.filter_pages( pages=self.pages_to_filter, attribute="updated", @@ -419,7 +420,7 @@ def on_post_build(self, config: config_options.Config) -> None: # write feeds to files stripping out spaces and new lines with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created: prev_char = "" - for char in template.render(feed=self.feed_created): + for char in template.render(feed=asdict(self.feed_created)): if char == "\n": continue if char == " " and prev_char == " ": @@ -429,7 +430,7 @@ def on_post_build(self, config: config_options.Config) -> None: fifeed_created.write(char) with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated: - for char in template.render(feed=self.feed_updated): + for char in template.render(feed=asdict(self.feed_updated)): if char == "\n": prev_char = char continue @@ -443,14 +444,14 @@ def on_post_build(self, config: config_options.Config) -> None: if self.config.json_feed_enabled: with out_json_created.open(mode="w", encoding="UTF8") as fp: json.dump( - self.util.feed_to_json(self.feed_created), + self.util.feed_to_json(asdict(self.feed_created)), fp, indent=4 if self.config.pretty_print else None, ) with out_json_updated.open(mode="w", encoding="UTF8") as fp: json.dump( - self.util.feed_to_json(self.feed_updated, updated=True), + self.util.feed_to_json(asdict(self.feed_updated), updated=True), fp, indent=4 if self.config.pretty_print else None, ) From a1400f3bd36afd6040001c91fa3bb048c4d859c9 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 13:29:25 +0100 Subject: [PATCH 027/158] update(ci): enable manual trigger for build/publish doc --- .github/workflows/documentation.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index fbcb71fc..0044b8a4 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -5,21 +5,26 @@ name: "📚 Documentation" # events but only for the master branch on: push: - branches: [main] + branches: + - main paths: - "docs/**" - "*.md" - ".github/workflows/documentation.yml" + - ./mkdocs_rss_plugin tags: - "*" pull_request: - branches: [main] + branches: + - main paths: - .github/workflows/documentation.yml - docs/ - requirements/documentation.txt + workflow_dispatch: + # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read From 8f34488191688f0f7edf266eec9a4899fca8bec8 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 15:04:33 +0100 Subject: [PATCH 028/158] feature(integration): make the integration with Material Blog configurable through an option --- README.md | 1 + docs/configuration.md | 10 ++++++++++ mkdocs_rss_plugin/config.py | 1 + mkdocs_rss_plugin/integrations/theme_material_base.py | 2 +- mkdocs_rss_plugin/plugin.py | 10 ++++++++++ mkdocs_rss_plugin/util.py | 7 +++++++ tests/fixtures/mkdocs_items_material_blog_enabled.yml | 4 +++- 7 files changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83b83001..46b0054f 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ plugins: utm_medium: "RSS" utm_campaign: "feed-syndication" use_git: true + use_material_blog: true use_material_social_cards: true ``` diff --git a/docs/configuration.md b/docs/configuration.md index 125f3e69..01552338 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -596,6 +596,16 @@ Default: `true`. ---- +### :material-newspaper-variant-outline: `use_material_blog`: enable/disable integration with Material Blog plugin { #use_material_blog } + +If `false`, the integration with the Blog plugin is disabled. + +Default: `true`. + +> See [the related section in integrations page](./integrations.md#blog-plugin-from-material-theme). + +---- + ### :material-cards: `use_material_social_cards`: enable/disable integration with Material Social Cards plugin { #use_material_social_cards } If `false`, the integration with Social Cards is disabled. diff --git a/mkdocs_rss_plugin/config.py b/mkdocs_rss_plugin/config.py index 25317280..bc37a95a 100644 --- a/mkdocs_rss_plugin/config.py +++ b/mkdocs_rss_plugin/config.py @@ -60,4 +60,5 @@ class RssPluginConfig(Config): rss_feed_enabled = config_options.Type(bool, default=True) url_parameters = config_options.Optional(config_options.Type(dict)) use_git = config_options.Type(bool, default=True) + use_material_blog = config_options.Type(bool, default=True) use_material_social_cards = config_options.Type(bool, default=True) diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py index ee015221..901abadc 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_base.py +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -38,7 +38,7 @@ class IntegrationMaterialThemeBase: # attributes IS_THEME_MATERIAL: bool = False - IS_INSIDERS: bool = False + IS_INSIDERS: Optional[bool] = False def __init__(self, mkdocs_config: MkDocsConfig) -> None: """Integration instantiation. diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index 3f2a38bb..a169ad47 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -31,6 +31,9 @@ DEFAULT_TEMPLATE_FOLDER, MKDOCS_LOGGER_NAME, ) +from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import ( + IntegrationMaterialBlog, +) from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) @@ -119,6 +122,12 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: self.cache_dir.mkdir(parents=True, exist_ok=True) logger.debug(f"Caching HTTP requests to: {self.cache_dir.resolve()}") + # integrations - check if theme is Material and if blog are enabled + self.integration_material_blog = IntegrationMaterialBlog( + mkdocs_config=config, + switch_force=self.config.use_material_blog, + ) + # integrations - check if theme is Material and if social cards are enabled self.integration_material_social_cards = IntegrationMaterialSocialCards( mkdocs_config=config, @@ -129,6 +138,7 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: self.util = Util( cache_dir=self.cache_dir, use_git=self.config.use_git, + integration_material_blog=self.integration_material_blog, integration_material_social_cards=self.integration_material_social_cards, mkdocs_command_is_on_serve=self.cmd_is_serve, ) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index 1c14ab33..94b0705a 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -41,6 +41,9 @@ REMOTE_REQUEST_HEADERS, ) from mkdocs_rss_plugin.git_manager.ci import CiHandler +from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import ( + IntegrationMaterialBlog, +) from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) @@ -67,6 +70,7 @@ class Util: def __init__( self, cache_dir: Path = DEFAULT_CACHE_FOLDER, + integration_material_blog: Optional[IntegrationMaterialBlog] = None, integration_material_social_cards: Optional[ IntegrationMaterialSocialCards ] = None, @@ -79,6 +83,8 @@ def __init__( Args: path (str, optional): path to the git repository to use. Defaults to ".". use_git (bool, optional): flag to use git under the hood or not. Defaults to True. + integration_material_blog (bool, optional): option to enable + integration with Blog plugin from Material theme. Defaults to True. integration_material_social_cards (bool, optional): option to enable integration with Social Cards plugin from Material theme. Defaults to True. """ @@ -128,6 +134,7 @@ def __init__( self.use_git = use_git # save integrations + self.material_blog = integration_material_blog self.social_cards = integration_material_social_cards # http/s session diff --git a/tests/fixtures/mkdocs_items_material_blog_enabled.yml b/tests/fixtures/mkdocs_items_material_blog_enabled.yml index d637ea6b..df349284 100644 --- a/tests/fixtures/mkdocs_items_material_blog_enabled.yml +++ b/tests/fixtures/mkdocs_items_material_blog_enabled.yml @@ -5,7 +5,9 @@ site_url: https://guts.github.io/mkdocs-rss-plugin plugins: - blog: blog_dir: blog - - rss + authors_profiles: true + - rss: + use_material_blog: true theme: name: material From 344662dd56c063dc1d9fe1a23f6cd8e2c68768f4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 15:08:35 +0100 Subject: [PATCH 029/158] feature(integration): make the integration with Material Blog configurable through an option --- tests/test_config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_config.py b/tests/test_config.py index 9c4cd695..0420b3d9 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -91,6 +91,7 @@ def test_plugin_config_defaults(self): "rss_feed_enabled": True, "url_parameters": None, "use_git": True, + "use_material_blog": True, "use_material_social_cards": True, } @@ -136,6 +137,7 @@ def test_plugin_config_image(self): "rss_feed_enabled": True, "url_parameters": None, "use_git": True, + "use_material_blog": True, "use_material_social_cards": True, } From 435aada007d8d521e4a5a156056506cc34536e80 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 15:24:16 +0100 Subject: [PATCH 030/158] feature(material_blog): add method to identify if a page is part of Material blog --- .../theme_material_blog_plugin.py | 15 +++++++++++++ .../theme_material_social_plugin.py | 22 ++++++++----------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index b90c00cb..9817061d 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -5,11 +5,13 @@ # ################################## # standard library +from pathlib import Path from typing import Optional # 3rd party from mkdocs.config.defaults import MkDocsConfig from mkdocs.plugins import get_plugin_logger +from mkdocs.structure.pages import Page # package from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME @@ -101,3 +103,16 @@ def is_blog_plugin_enabled_mkdocs( logger.debug("Material blog plugin is enabled in Mkdocs configuration.") self.IS_BLOG_PLUGIN_ENABLED = True return True + + def is_page_a_blog_post(self, mkdocs_page: Page) -> bool: + """Identifies if the given page is part of Material Blog. + + Args: + mkdocs_page (Page): page to identify + + Returns: + bool: True if the given page is a Material Blog post. + """ + return Path(mkdocs_page.file.src_uri).is_relative_to( + self.blog_plugin_cfg.config.blog_dir + ) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 257efeb5..fcdaab9b 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -27,7 +27,6 @@ # conditional try: from material import __version__ as material_version - from pymdownx.slugs import slugify except ImportError: material_version = None @@ -261,10 +260,9 @@ def get_social_card_build_path_for_page( mkdocs_site_dir = self.mkdocs_site_build_dir # if page is a blog post - if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( - mkdocs_page.file.src_uri - ).is_relative_to( - self.integration_material_blog.blog_plugin_cfg.config.blog_dir + if ( + self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): expected_built_card_path = Path( f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/" @@ -306,10 +304,9 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat if self.IS_INSIDERS: # if page is a blog post - if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( - mkdocs_page.file.src_uri - ).is_relative_to( - self.integration_material_blog.blog_plugin_cfg.config.blog_dir + if ( + self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): expected_cached_card_path = self.social_cards_cache_dir.joinpath( f"assets/images/social/{Path(mkdocs_page.file.dest_uri).parent}.png" @@ -376,10 +373,9 @@ def get_social_card_url_for_page( mkdocs_site_url = self.mkdocs_site_url # if page is a blog post - if self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and Path( - mkdocs_page.file.src_uri - ).is_relative_to( - self.integration_material_blog.blog_plugin_cfg.config.blog_dir + if ( + self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): page_social_card = ( f"{mkdocs_site_url}assets/images/social/" From c779b92fbee56cf8ab2b01ef9a17d3a64599e703 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 15:29:37 +0100 Subject: [PATCH 031/158] feature(material_blog): retrieve author name from Material blog authors file (typically .authors.yml) --- docs/integrations.md | 13 ++++++++++ .../theme_material_blog_plugin.py | 26 +++++++++++++++++++ mkdocs_rss_plugin/util.py | 11 +++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/integrations.md b/docs/integrations.md index 5d4997ff..37df14ff 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -3,6 +3,19 @@ title: Integrations icon: octicons/plug-16 --- +## Blog plugin (from Material theme) + +Since version 1.17, the plugin integrates with the [Blog plugin (shipped with Material theme)](https://squidfunk.github.io/mkdocs-material/plugins/blog/) (see also [the tutorial about blog + RSS plugins](https://squidfunk.github.io/mkdocs-material/tutorials/blogs/engage/)). + +In some cases, the RSS plugin needs to work with the Material Blog: + +- for blog posts, the structure of the path to social cards is depending on blog configuration +- retrieve the author's name from the `.authors.yml` file + +If you don't want this integration, you can disable it with the option: `use_material_blog=false`. + +> See [related section in settings](./configuration.md#use_material_blog). + ## 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/)). diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 9817061d..951234d9 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -5,6 +5,7 @@ # ################################## # standard library +from functools import lru_cache from pathlib import Path from typing import Optional @@ -104,6 +105,31 @@ def is_blog_plugin_enabled_mkdocs( self.IS_BLOG_PLUGIN_ENABLED = True return True + @lru_cache + def author_name_from_id(self, author_id: str) -> str: + """Return author name from author_id used in Material blog plugin (.authors.yml). + + Args: + author_id (str): author key in .authors.yml + + Returns: + str: author name or passed author_id if not found within .authors.yml + """ + if ( + self.blog_plugin_cfg.config.authors + and isinstance(self.blog_plugin_cfg, BlogPlugin) + and hasattr(self.blog_plugin_cfg, "authors") + and isinstance(self.blog_plugin_cfg.authors, dict) + ): + if author_id in self.blog_plugin_cfg.authors: + return self.blog_plugin_cfg.authors.get(author_id).get("name") + else: + logger.error( + f"Author ID '{author_id}' is not part of known authors: " + f"{self.blog_plugin_cfg.authors}. Returning author_id." + ) + return author_id + def is_page_a_blog_post(self, mkdocs_page: Page) -> bool: """Identifies if the given page is part of Material Blog. diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index 94b0705a..a25cde03 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -387,7 +387,16 @@ def get_authors_from_meta(self, in_page: Page) -> Optional[tuple[str]]: if isinstance(in_page.meta.get("authors"), str): return (in_page.meta.get("authors"),) elif isinstance(in_page.meta.get("authors"), (list, tuple)): - return tuple(in_page.meta.get("authors")) + if ( + self.material_blog.IS_ENABLED + and self.material_blog.is_page_a_blog_post(in_page) + ): + return [ + self.material_blog.author_name_from_id(author_id) + for author_id in in_page.meta.get("authors") + ] + else: + return tuple(in_page.meta.get("authors")) else: logging.warning( "Type of authors value in page.meta (%s) is not valid. " From 117ddb42a988cd509597f6960e27c0a99e896bb7 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 16:28:07 +0100 Subject: [PATCH 032/158] feature(material_blog): support email attribute from .authors.yml --- .../integrations/theme_material_blog_plugin.py | 6 +++++- tests/fixtures/docs/blog/.authors.yml | 1 + tests/fixtures/docs/blog/posts/firstpost.md | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 951234d9..14929523 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -122,7 +122,11 @@ def author_name_from_id(self, author_id: str) -> str: and isinstance(self.blog_plugin_cfg.authors, dict) ): if author_id in self.blog_plugin_cfg.authors: - return self.blog_plugin_cfg.authors.get(author_id).get("name") + author_metadata = self.blog_plugin_cfg.authors.get(author_id) + if "email" in self.blog_plugin_cfg.authors.get(author_id): + return f"{author_metadata.get('name')} ({author_metadata.get('email')})" + else: + return author_metadata.get("name") else: logger.error( f"Author ID '{author_id}' is not part of known authors: " diff --git a/tests/fixtures/docs/blog/.authors.yml b/tests/fixtures/docs/blog/.authors.yml index 17b0e05d..5c64a707 100644 --- a/tests/fixtures/docs/blog/.authors.yml +++ b/tests/fixtures/docs/blog/.authors.yml @@ -13,3 +13,4 @@ authors: name: Julien Moura slug: julien-moura url: https://geotribu.fr/team/julien-moura/ + email: guts@gmail.com diff --git a/tests/fixtures/docs/blog/posts/firstpost.md b/tests/fixtures/docs/blog/posts/firstpost.md index 5cdcd8c3..730fc513 100644 --- a/tests/fixtures/docs/blog/posts/firstpost.md +++ b/tests/fixtures/docs/blog/posts/firstpost.md @@ -1,6 +1,7 @@ --- authors: - alexvoss + - guts date: 2023-10-11 categories: - meta @@ -29,4 +30,3 @@ 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. - From 2c963f232d2b6db0300f95b1fa77f638415420c7 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 16:28:38 +0100 Subject: [PATCH 033/158] feature(material_blog): document how does work the Material Blog integration --- docs/integrations.md | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/integrations.md b/docs/integrations.md index 37df14ff..cde420b9 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -11,11 +11,58 @@ In some cases, the RSS plugin needs to work with the Material Blog: - for blog posts, the structure of the path to social cards is depending on blog configuration - retrieve the author's name from the `.authors.yml` file +- optionnaly retrieve the author's email from the `.authors.yml` file If you don't want this integration, you can disable it with the option: `use_material_blog=false`. > See [related section in settings](./configuration.md#use_material_blog). +### Example of blog authors with email + +```yaml title="docs/blog/.authors.yml" +authors: + 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 + url: https://github.com/guts/ + email: joe@biden.com +``` + +This given Markdown post: + +```markdown title="blog/posts/demo.md" +--- +authors: + - alexvoss + - guts +date: 2024-12-02 +categories: + - tutorial +--- + +# Demonstration blog post + +[...] +``` + +Will be rendered as: + +```xml title="/build/site/feed_rss_created.xml" +[...] + + Demonstration blog post + Alex Voss + Julien Moura (joe@biden.com) +[...] +``` + +---- + ## 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/)). From 739afd22af25ef7342de981706062714d5aaadb6 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 16:39:50 +0100 Subject: [PATCH 034/158] feature(material_blog): extend tests against new blog integration --- .../mkdocs_items_material_blog_enabled.yml | 11 ++- ..._blog_enabled_but_integration_disabled.yml | 13 ++++ tests/test_integrations_material_blog.py | 72 +++++++++++++++++++ 3 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml diff --git a/tests/fixtures/mkdocs_items_material_blog_enabled.yml b/tests/fixtures/mkdocs_items_material_blog_enabled.yml index df349284..445ef73e 100644 --- a/tests/fixtures/mkdocs_items_material_blog_enabled.yml +++ b/tests/fixtures/mkdocs_items_material_blog_enabled.yml @@ -3,11 +3,10 @@ site_description: Test RSS with blog plugin also enabled site_url: https://guts.github.io/mkdocs-rss-plugin plugins: - - blog: - blog_dir: blog - authors_profiles: true - - rss: - use_material_blog: true + - blog: + blog_dir: blog + authors_profiles: true + - rss theme: - name: material + name: material diff --git a/tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml b/tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml new file mode 100644 index 00000000..0ed22a63 --- /dev/null +++ b/tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml @@ -0,0 +1,13 @@ +site_name: Test RSS Plugin +site_description: Test RSS with blog plugin also enabled +site_url: https://guts.github.io/mkdocs-rss-plugin + +plugins: + - blog: + blog_dir: blog + authors_profiles: true + - rss: + use_material_blog: false + +theme: + name: material diff --git a/tests/test_integrations_material_blog.py b/tests/test_integrations_material_blog.py index 3255777b..5b84e48b 100644 --- a/tests/test_integrations_material_blog.py +++ b/tests/test_integrations_material_blog.py @@ -14,11 +14,14 @@ # ################################## # Standard library +import tempfile import unittest from logging import DEBUG, getLogger from pathlib import Path +from traceback import format_exception # 3rd party +import feedparser from mkdocs.config import load_config # package @@ -41,6 +44,24 @@ class TestRssPluginIntegrationsMaterialBlog(BaseTest): """Test integration of Material Blog plugin with RSS plugin.""" # -- TESTS --------------------------------------------------------- + def test_plugin_config_social_cards_enabled_but_integration_disabled(self): + # default reference + cfg_mkdocs = load_config( + str( + Path( + "tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml" + ).resolve() + ) + ) + + integration_social_cards = IntegrationMaterialBlog( + mkdocs_config=cfg_mkdocs, + switch_force=cfg_mkdocs.plugins.get("rss").config.use_material_blog, + ) + self.assertTrue(integration_social_cards.IS_THEME_MATERIAL) + self.assertTrue(integration_social_cards.IS_BLOG_PLUGIN_ENABLED) + self.assertFalse(integration_social_cards.IS_ENABLED) + def test_plugin_config_blog_enabled(self): # default reference cfg_mkdocs = load_config( @@ -52,6 +73,57 @@ def test_plugin_config_blog_enabled(self): 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( + testproject_path="docs", + mkdocs_yml_filepath=Path( + "tests/fixtures/mkdocs_items_material_blog_enabled.yml" + ), + output_path=tmpdirname, + strict=False, + ) + + if cli_result.exception is not None: + e = cli_result.exception + logger.debug(format_exception(type(e), e, e.__traceback__)) + + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # created items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_created.xml") + self.assertEqual(feed_parsed.bozo, 0) + + # updated items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_updated.xml") + self.assertEqual(feed_parsed.bozo, 0) + + with tempfile.TemporaryDirectory() as tmpdirname: + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path( + "tests/fixtures/mkdocs_items_material_blog_enabled_but_integration_disabled.yml" + ), + output_path=tmpdirname, + strict=False, + ) + + if cli_result.exception is not None: + e = cli_result.exception + logger.debug(format_exception(type(e), e, e.__traceback__)) + + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # created items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_created.xml") + self.assertEqual(feed_parsed.bozo, 0) + + # updated items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_updated.xml") + self.assertEqual(feed_parsed.bozo, 0) + # ############################################################################## # ##### Stand alone program ######## From c15778a6ca5b1daf10acffe437648d5511cac36f Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 16:40:02 +0100 Subject: [PATCH 035/158] fix(imports): rm unused imports --- mkdocs_rss_plugin/integrations/theme_material_base.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py index 901abadc..77474129 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_base.py +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -17,8 +17,6 @@ # 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 From 4af14fdd06f4de66672a9196bac82fc6b7898082 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 20:06:28 +0000 Subject: [PATCH 036/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.2 → v0.8.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.2...v0.8.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a90519f8..2d7df7ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.2" + rev: "v0.8.1" hooks: - id: ruff args: From 7569e083227c1accabd1d9d03a031fde1c455187 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 2 Dec 2024 21:47:55 +0100 Subject: [PATCH 037/158] release: bump version to 1.17.0 --- CHANGELOG.md | 13 +++++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d896a9a3..ef4f3bfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.0 - 2024-12-02 + +### Features and enhancements 🎉 + +* refacto(material_integrations): use POO to manage integrations with Material theme framework by @Guts in +* update(chore): use typed dataclasses instead of dict by @Guts in +* feature(integration): make the integration with Material Blog configurable through an option by @Guts in +* Feature: use author name and email from `.authors.yml` set up in Material Blog by @Guts in + +### Tooling 🔧 + +* update(ci): enable manual trigger for build/publish doc by @Guts in + ## 1.16.0 - 2024-10-24 ### Bugs fixes 🐛 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index 03547555..729a366c 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.16.0" +__version__ = "1.17.0" __version_info__ = tuple( [ int(num) if num.isdigit() else num From 1752ef1192345c65b5cfe8f96e9ee623f1d8bfac Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 16 Dec 2024 09:11:29 +0100 Subject: [PATCH 038/158] fix(rss): email and name were inverted in output and so uncompliant Related to: https://github.com/Guts/mkdocs-rss-plugin/issues/250 See: https://validator.w3.org/feed/docs/error/InvalidContact.html --- mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 14929523..1e38de96 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -124,7 +124,7 @@ def author_name_from_id(self, author_id: str) -> str: if author_id in self.blog_plugin_cfg.authors: author_metadata = self.blog_plugin_cfg.authors.get(author_id) if "email" in self.blog_plugin_cfg.authors.get(author_id): - return f"{author_metadata.get('name')} ({author_metadata.get('email')})" + return f"{author_metadata.get('email')} ({author_metadata.get('name')})" else: return author_metadata.get("name") else: From 8e74d3db3ede25720de424b5e6c2a5106a5eae7a Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 16 Dec 2024 09:19:01 +0100 Subject: [PATCH 039/158] update(docs): move integrations page as independant menu --- mkdocs.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index bca3d087..7fc53504 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -59,9 +59,8 @@ markdown_extensions: nav: - Home: index.md - - Settings: - - configuration.md - - integrations.md + - Settings: configuration.md + - integrations.md - Contributing: contributing.md - API: api.md - Changelog: changelog.md From d4677030ab7113f99466fb518b990499a44a6997 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 16 Dec 2024 09:23:03 +0100 Subject: [PATCH 040/158] release: bump version to 1.17.1 --- CHANGELOG.md | 10 ++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef4f3bfb..f28ae2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.1 - 2024-12-16 + +### Bugs fixes 🐛 + +* fix(rss): email and name were inverted in output and so uncompliant by @Guts in . Thanks @stefansli for the floow up in . + +### Documentation 📖 + +* update(docs): move integrations page as independant menu by @Guts in + ## 1.17.0 - 2024-12-02 ### Features and enhancements 🎉 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index 729a366c..aa986524 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.17.0" +__version__ = "1.17.1" __version_info__ = tuple( [ int(num) if num.isdigit() else num From 0c59affb29e2056217efb202f9f3470afcc768f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jan 2025 18:37:30 +0000 Subject: [PATCH 041/158] build(deps): bump codecov/codecov-action from 5.0.7 to 5.1.2 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.0.7 to 5.1.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.0.7...v5.1.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 9de14fd0..c68730d7 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.0.7 + uses: codecov/codecov-action@v5.1.2 with: env_vars: PYTHON flags: unittests From 6cfdfd23e5993e276fe83348aacfefcdb556772a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:18:39 +0000 Subject: [PATCH 042/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.19.0 → v3.19.1](https://github.com/asottile/pyupgrade/compare/v3.19.0...v3.19.1) - [github.com/astral-sh/ruff-pre-commit: v0.8.1 → v0.8.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.1...v0.8.6) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2d7df7ea..c0d810f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + rev: v3.19.1 hooks: - id: pyupgrade args: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.1" + rev: "v0.8.6" hooks: - id: ruff args: From 1947d44fc8fd0b790927134772ef98b3d20653c6 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 25 Feb 2025 13:40:05 +0100 Subject: [PATCH 043/158] fix(upstream): force jsonfeed-util version since it uses a non Python 3.9 syntax, breaking lint and tests see: https://github.com/lukasschwab/jsonfeed/issues/15 --- requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/testing.txt b/requirements/testing.txt index e5947b93..14a76cfa 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -4,7 +4,7 @@ # ------- feedparser>=6.0.11,<6.1 -jsonfeed-util>=1.1.2,<2 +jsonfeed-util>=1.1.2,<1.1.4 mkdocs-material[imaging]>=9.5.47 pytest-cov>=6,<7 validator-collection>=1.5,<1.6 From e37060765019575fe193334099213871b29ea3d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:45:05 +0000 Subject: [PATCH 044/158] build(deps): update mkdocs-git-committers-plugin-2 requirement Updates the requirements on [mkdocs-git-committers-plugin-2](https://github.com/ojacques/mkdocs-git-committers-plugin-2) to permit the latest version. - [Release notes](https://github.com/ojacques/mkdocs-git-committers-plugin-2/releases) - [Commits](https://github.com/ojacques/mkdocs-git-committers-plugin-2/compare/2.4.1...2.5.0) --- updated-dependencies: - dependency-name: mkdocs-git-committers-plugin-2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 73206294..b7f87cdc 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -1,7 +1,7 @@ # Documentation # ----------------------- -mkdocs-git-committers-plugin-2>=2.4.1,<2.5 +mkdocs-git-committers-plugin-2>=2.4.1,<2.6 mkdocs-git-revision-date-localized-plugin>=1.3,<1.4 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 From e596794c280f17e3c4f96daa3e92403e9fbf3d90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:48:56 +0000 Subject: [PATCH 045/158] build(deps-dev): update pre-commit requirement from <4,>=3.7 to >=3.7,<5 Updates the requirements on [pre-commit](https://github.com/pre-commit/pre-commit) to permit the latest version. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v3.7.0...v4.1.0) --- updated-dependencies: - dependency-name: pre-commit dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- requirements/development.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/development.txt b/requirements/development.txt index c2585564..f50d1948 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -8,4 +8,4 @@ flake8-bugbear>=24.10 flake8-builtins>=2.5 flake8-eradicate>=1.5 flake8-isort>=6.1.1 -pre-commit>=3.7,<4 +pre-commit>=3.7,<5 From 0f4f638398b48be06624bfc316be487db48db942 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:19:27 +0000 Subject: [PATCH 046/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.6 → v0.9.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.6...v0.9.4) - [github.com/pycqa/isort: 5.13.2 → 6.0.0](https://github.com/pycqa/isort/compare/5.13.2...6.0.0) - [github.com/psf/black: 24.10.0 → 25.1.0](https://github.com/psf/black/compare/24.10.0...25.1.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c0d810f1..c8301f79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.6" + rev: "v0.9.4" hooks: - id: ruff args: @@ -46,7 +46,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/isort - rev: 5.13.2 + rev: 6.0.0 hooks: - id: isort args: @@ -55,7 +55,7 @@ repos: - --filter-files - repo: https://github.com/psf/black - rev: 24.10.0 + rev: 25.1.0 hooks: - id: black args: From 2127e1caab8c63f7cd2c84e85ac84b559194bb02 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 25 Feb 2025 13:58:57 +0100 Subject: [PATCH 047/158] update(ci): trigger docs build if a documentation dependency has changed --- .github/workflows/documentation.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 0044b8a4..f219175c 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -12,6 +12,7 @@ on: - "*.md" - ".github/workflows/documentation.yml" - ./mkdocs_rss_plugin + - requirements/documentation.txt tags: - "*" From 125c41a1b277efe01e8f749484e0600801b50adb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:59:57 +0000 Subject: [PATCH 048/158] build(deps): bump codecov/codecov-action from 5.1.2 to 5.3.1 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.2 to 5.3.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.1.2...v5.3.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index c68730d7..5f7692b8 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.1.2 + uses: codecov/codecov-action@v5.3.1 with: env_vars: PYTHON flags: unittests From a6a8d9ab06f666853dcb9fa2f3be78702b25518c Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 25 Feb 2025 16:01:14 +0100 Subject: [PATCH 049/158] update(docs): switch mkdocstrings to explicit package for Python --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index b7f87cdc..e337df07 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -5,5 +5,5 @@ mkdocs-git-committers-plugin-2>=2.4.1,<2.6 mkdocs-git-revision-date-localized-plugin>=1.3,<1.4 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 -mkdocstrings[python]>=0.27,<1 +mkdocstrings-python>=1.16.2,<1.17 termynal>=0.12.2,<0.13 From 54502d5cc9b1383773895fa6229d467595d63ed5 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 25 Feb 2025 16:02:22 +0100 Subject: [PATCH 050/158] fix(docs): merge_init_into_class was not good indented --- mkdocs.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 7fc53504..344813d4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -91,13 +91,17 @@ plugins: handlers: python: options: + docstring_options: + ignore_init_summary: false + trim_doctest_flags: true docstring_style: google + find_stubs_package: true heading_level: 3 - ignore_init_summary: false + show_bases: true + show_inheritance_diagram: true + show_root_heading: true show_source: false - merge_init_into_class: true - paths: [.] - show_root_heading: true + merge_init_into_class: true - privacy: enabled: !ENV [MKDOCS_ENABLE_PLUGIN_PRIVACY, true] From b1884519d5bd35e2bd3681e7ac6328b880801005 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 25 Feb 2025 16:35:23 +0100 Subject: [PATCH 051/158] improve(docs): refine docstrings and API page --- docs/api.md | 22 ++++++++++++++++++---- mkdocs_rss_plugin/constants.py | 10 +++++----- mkdocs_rss_plugin/git_manager/ci.py | 9 ++++++++- mkdocs_rss_plugin/models.py | 4 +++- mkdocs_rss_plugin/timezoner.py | 15 +++++++-------- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/docs/api.md b/docs/api.md index 0304646a..a355dc8c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -12,18 +12,32 @@ icon: fontawesome/solid/code ::: mkdocs_rss_plugin.config.RssPluginConfig +::: mkdocs_rss_plugin.config._DateFromMeta + +::: mkdocs_rss_plugin.config._FeedsFilenamesConfig + ---- ::: mkdocs_rss_plugin.constants ----- +## Models ::: mkdocs_rss_plugin.models.PageInformation ----- - -::: mkdocs_rss_plugin.util.Util +::: mkdocs_rss_plugin.models.RssFeedBase ## Integrations +::: mkdocs_rss_plugin.integrations.theme_material_base.IntegrationMaterialThemeBase + +::: mkdocs_rss_plugin.integrations.theme_material_blog_plugin.IntegrationMaterialBlog + ::: mkdocs_rss_plugin.integrations.theme_material_social_plugin.IntegrationMaterialSocialCards + +## Utils + +::: mkdocs_rss_plugin.git_manager.ci.CiHandler + +::: mkdocs_rss_plugin.timezoner + +::: mkdocs_rss_plugin.util.Util diff --git a/mkdocs_rss_plugin/constants.py b/mkdocs_rss_plugin/constants.py index 971802b2..9eae3031 100644 --- a/mkdocs_rss_plugin/constants.py +++ b/mkdocs_rss_plugin/constants.py @@ -14,11 +14,11 @@ # ########## Globals ############# # ################################ -DEFAULT_CACHE_FOLDER = Path(".cache/plugins/rss") -DEFAULT_TEMPLATE_FOLDER = Path(__file__).parent / "templates" -DEFAULT_TEMPLATE_FILENAME = DEFAULT_TEMPLATE_FOLDER / "rss.xml.jinja2" -MKDOCS_LOGGER_NAME = "[RSS-plugin]" -REMOTE_REQUEST_HEADERS = { +DEFAULT_CACHE_FOLDER: Path = Path(".cache/plugins/rss") +DEFAULT_TEMPLATE_FOLDER: Path = Path(__file__).parent / "templates" +DEFAULT_TEMPLATE_FILENAME: Path = DEFAULT_TEMPLATE_FOLDER / "rss.xml.jinja2" +MKDOCS_LOGGER_NAME: str = "[RSS-plugin]" +REMOTE_REQUEST_HEADERS: dict[str, str] = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "User-Agent": f"{__about__.__title__}/{__about__.__version__}", } diff --git a/mkdocs_rss_plugin/git_manager/ci.py b/mkdocs_rss_plugin/git_manager/ci.py index ea220bd3..3ee8dcc2 100644 --- a/mkdocs_rss_plugin/git_manager/ci.py +++ b/mkdocs_rss_plugin/git_manager/ci.py @@ -27,7 +27,14 @@ class CiHandler: - def __init__(self, repo: Git): + """Helper class to handle CI specific warnings.""" + + def __init__(self, repo: Git) -> None: + """Initialize the CI handler. + + Args: + repo (Git): Git repository object + """ self.repo = repo def raise_ci_warnings(self) -> None: diff --git a/mkdocs_rss_plugin/models.py b/mkdocs_rss_plugin/models.py index 93ea01de..e4d1ac3a 100644 --- a/mkdocs_rss_plugin/models.py +++ b/mkdocs_rss_plugin/models.py @@ -20,7 +20,7 @@ @dataclass class PageInformation: - """Data type to set and get page information in order to produce the RSS feed.""" + """Object describing a page information gathered from Mkdocs and used as feed's item.""" abs_path: Optional[Path] = None categories: Optional[list] = None @@ -37,6 +37,8 @@ class PageInformation: @dataclass class RssFeedBase: + """Object describing a feed.""" + author: Optional[str] = None buildDate: Optional[str] = None copyright: Optional[str] = None diff --git a/mkdocs_rss_plugin/timezoner.py b/mkdocs_rss_plugin/timezoner.py index 098f0134..23a75ae1 100644 --- a/mkdocs_rss_plugin/timezoner.py +++ b/mkdocs_rss_plugin/timezoner.py @@ -38,14 +38,13 @@ def set_datetime_zoneinfo( ) -> datetime: """Apply timezone to a naive datetime. - :param input_datetime: offset-naive datetime - :type input_datetime: datetime - :param config_timezone: name of timezone as registered in IANA database, - defaults to "UTC". Example : Europe/Paris. - :type config_timezone: str, optional - - :return: offset-aware datetime - :rtype: datetime + Args: + input_datetime (datetime): offset-naive datetime + config_timezone (str, optional): name of timezone as registered in IANA + database. Defaults to "UTC". Example : Europe/Paris. + + Returns: + datetime: offset-aware datetime """ if input_datetime.tzinfo: return input_datetime From bd03bfaac1ec7e9e6052a2d5db93d35828f94f24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:39:06 +0000 Subject: [PATCH 052/158] build(deps): update termynal requirement Updates the requirements on [termynal](https://github.com/termynal/termynal.py) to permit the latest version. - [Changelog](https://github.com/termynal/termynal.py/blob/main/CHANGELOG.md) - [Commits](https://github.com/termynal/termynal.py/compare/v0.12.2...v0.13.0) --- updated-dependencies: - dependency-name: termynal dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index e337df07..9213a3e4 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -6,4 +6,4 @@ mkdocs-git-revision-date-localized-plugin>=1.3,<1.4 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 mkdocstrings-python>=1.16.2,<1.17 -termynal>=0.12.2,<0.13 +termynal>=0.12.2,<0.14 From 037042878e5bf642438ad63580acc5a40d0d146f Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Tue, 25 Feb 2025 18:30:28 +0900 Subject: [PATCH 053/158] fix(material_social): use cards_dir to build cards url for page --- .../theme_material_social_plugin.py | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index fcdaab9b..4b434ca2 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -89,6 +89,9 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No if self.IS_ENABLED: self.mkdocs_site_url = mkdocs_config.site_url self.mkdocs_site_build_dir = mkdocs_config.site_dir + self.social_cards_dir = self.get_social_cards_dir( + mkdocs_config=mkdocs_config + ) self.social_cards_assets_dir = self.get_social_cards_build_dir( mkdocs_config=mkdocs_config ) @@ -205,15 +208,15 @@ def load_cache_cards_manifest(self) -> Optional[dict]: return self.CARDS_MANIFEST - def get_social_cards_build_dir(self, mkdocs_config: MkDocsConfig) -> Path: - """Get Social Cards folder within Mkdocs site_dir. + def get_social_cards_dir(self, mkdocs_config: MkDocsConfig) -> str: + """Get Social Cards folder relative to Mkdocs site_dir. See: https://squidfunk.github.io/mkdocs-material/plugins/social/#config.cards_dir Args: mkdocs_config (MkDocsConfig): Mkdocs website configuration object. Returns: - str: True if the theme material and the plugin social cards is enabled. + str: The cards_dir if the theme material and the plugin social cards is enabled. """ social_plugin_cfg = mkdocs_config.plugins.get("material/social") @@ -222,7 +225,22 @@ def get_social_cards_build_dir(self, mkdocs_config: MkDocsConfig) -> Path: f"{social_plugin_cfg.config.cards_dir}." ) - return Path(social_plugin_cfg.config.cards_dir).resolve() + return social_plugin_cfg.config.cards_dir + + def get_social_cards_build_dir(self, mkdocs_config: MkDocsConfig) -> Path: + """Get Social Cards folder within Mkdocs site_dir. + See: https://squidfunk.github.io/mkdocs-material/plugins/social/#config.cards_dir + + Args: + mkdocs_config (MkDocsConfig): Mkdocs website configuration object. + + Returns: + Path: Absolute path of the assets dir if the theme material and the plugin + social cards is enabled. + """ + cards_dir = self.get_social_cards_dir(mkdocs_config=mkdocs_config) + + return Path(cards_dir).resolve() def get_social_cards_cache_dir(self, mkdocs_config: MkDocsConfig) -> Path: """Get Social Cards folder within Mkdocs site_dir. @@ -232,7 +250,7 @@ def get_social_cards_cache_dir(self, mkdocs_config: MkDocsConfig) -> Path: mkdocs_config (MkDocsConfig): Mkdocs website configuration object. Returns: - str: True if the theme material and the plugin social cards is enabled. + Path: The cache dir if the theme material and the plugin social cards is enabled. """ social_plugin_cfg = mkdocs_config.plugins.get("material/social") self.social_cards_cache_dir = Path(social_plugin_cfg.config.cache_dir).resolve() @@ -372,19 +390,12 @@ 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 - # if page is a blog post - if ( - self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED - and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) - ): - 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')}" - ) + # As of mkdocs-material 9.6.5, social cards are always stored in the + # matching src path in the build folder, regardless of the page type. + page_social_card = ( + f"{mkdocs_site_url}{self.social_cards_dir}/" + f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}" + ) + logger.debug(f"Use social card url: {page_social_card}") return page_social_card From c4c1aab74fd65cb5a4d6347a46467196774daa12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 11:38:59 +0000 Subject: [PATCH 054/158] build(deps): update jsonfeed-util requirement Updates the requirements on [jsonfeed-util](https://github.com/lukasschwab/jsonfeed) to permit the latest version. - [Release notes](https://github.com/lukasschwab/jsonfeed/releases) - [Commits](https://github.com/lukasschwab/jsonfeed/compare/1.1.2...1.2.0) --- updated-dependencies: - dependency-name: jsonfeed-util dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/testing.txt b/requirements/testing.txt index 14a76cfa..07436a7d 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -4,7 +4,7 @@ # ------- feedparser>=6.0.11,<6.1 -jsonfeed-util>=1.1.2,<1.1.4 +jsonfeed-util>=1.1.2,<1.2.1 mkdocs-material[imaging]>=9.5.47 pytest-cov>=6,<7 validator-collection>=1.5,<1.6 From be63093caedc6e8cac0f4369e7924e6fb8920a2b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 18:11:02 +0000 Subject: [PATCH 055/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.4 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.9.9) - [github.com/pycqa/isort: 6.0.0 → 6.0.1](https://github.com/pycqa/isort/compare/6.0.0...6.0.1) - [github.com/pycqa/flake8: 7.1.1 → 7.1.2](https://github.com/pycqa/flake8/compare/7.1.1...7.1.2) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c8301f79..3726c945 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.4" + rev: "v0.9.9" hooks: - id: ruff args: @@ -46,7 +46,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/isort - rev: 6.0.0 + rev: 6.0.1 hooks: - id: isort args: @@ -62,7 +62,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/flake8 - rev: 7.1.1 + rev: 7.1.2 hooks: - id: flake8 additional_dependencies: From 9c867c61685aaeedca7282c5d1150f05fe37c6ee Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 3 Mar 2025 19:31:09 +0100 Subject: [PATCH 056/158] Update testing.txt Signed-off-by: Julien --- requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/testing.txt b/requirements/testing.txt index 07436a7d..514c8247 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -4,7 +4,7 @@ # ------- feedparser>=6.0.11,<6.1 -jsonfeed-util>=1.1.2,<1.2.1 +jsonfeed-util>=1.2,<2 mkdocs-material[imaging]>=9.5.47 pytest-cov>=6,<7 validator-collection>=1.5,<1.6 From bf6dfd0b43e72bcfaf13425500213f0dea8ec973 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 18:43:27 +0000 Subject: [PATCH 057/158] build(deps): bump codecov/codecov-action from 5.3.1 to 5.4.0 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.1 to 5.4.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.3.1...v5.4.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 5f7692b8..64c97f99 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.3.1 + uses: codecov/codecov-action@v5.4.0 with: env_vars: PYTHON flags: unittests From 4385b38e79874288a4ef5d2e4d35effd32fc6c2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:11:27 +0000 Subject: [PATCH 058/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.11.4) - [github.com/pycqa/flake8: 7.1.2 → 7.2.0](https://github.com/pycqa/flake8/compare/7.1.2...7.2.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3726c945..3338f07e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.9" + rev: "v0.11.4" hooks: - id: ruff args: @@ -62,7 +62,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/flake8 - rev: 7.1.2 + rev: 7.2.0 hooks: - id: flake8 additional_dependencies: From 5a4217e70ffcfe1abffb19b7d30588feda5d9407 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 18:41:50 +0000 Subject: [PATCH 059/158] build(deps): bump codecov/codecov-action from 5.4.0 to 5.4.2 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.0 to 5.4.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.4.0...v5.4.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 64c97f99..888b49c9 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.4.0 + uses: codecov/codecov-action@v5.4.2 with: env_vars: PYTHON flags: unittests From eb5aa84919e77de6e0b98c65b1943fb1a82a32b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 18:01:53 +0000 Subject: [PATCH 060/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.8) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3338f07e..fc756f9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.4" + rev: "v0.11.8" hooks: - id: ruff args: From 2c6e2b92eadc51728868f3abf291e9cfbfe5a90e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 09:23:37 +0000 Subject: [PATCH 061/158] build(deps): update mkdocs-git-revision-date-localized-plugin requirement Updates the requirements on [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin) to permit the latest version. - [Release notes](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/releases) - [Commits](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/compare/v1.3.0...v1.4.5) --- updated-dependencies: - dependency-name: mkdocs-git-revision-date-localized-plugin dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 9213a3e4..313d1b3c 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -2,7 +2,7 @@ # ----------------------- mkdocs-git-committers-plugin-2>=2.4.1,<2.6 -mkdocs-git-revision-date-localized-plugin>=1.3,<1.4 +mkdocs-git-revision-date-localized-plugin>=1.3,<1.5 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 mkdocstrings-python>=1.16.2,<1.17 From 0325f3e9e49ad5965022222412ae5a1e3435709e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 22 May 2025 22:40:23 +0200 Subject: [PATCH 062/158] update(tests): use-case with Material social cards and directory URLs disabled --- ...cial_cards_blog_directory_url_disabled.yml | 18 +++++++ ...test_integrations_material_social_cards.py | 50 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml diff --git a/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml b/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml new file mode 100644 index 00000000..49ff755d --- /dev/null +++ b/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml @@ -0,0 +1,18 @@ +site_name: Test RSS Plugin with social cards, blog plugin and directory URL disabled +site_description: Test RSS with social and blog plugins enabled but directory URLS disabled. Related to https://github.com/Guts/mkdocs-rss-plugin/issues/319. +site_url: https://guts.github.io/mkdocs-rss-plugin + +use_directory_urls: false + +plugins: + - blog: + blog_dir: blog + authors_profiles: true + - rss: + match_path: blog/posts/.* + - social: + enabled: true + cards: true + +theme: + name: material diff --git a/tests/test_integrations_material_social_cards.py b/tests/test_integrations_material_social_cards.py index eab4e1ca..a2baed31 100644 --- a/tests/test_integrations_material_social_cards.py +++ b/tests/test_integrations_material_social_cards.py @@ -25,6 +25,7 @@ from mkdocs.config import load_config # package +from mkdocs_rss_plugin.__about__ import __title_clean__ from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) @@ -136,6 +137,55 @@ def test_plugin_config_social_cards_enabled_with_blog_plugin(self): ) self.assertTrue(integration_social_cards.IS_ENABLED) + def test_plugin_config_social_cards_enabled_with_directory_urls_disabled(self): + """Test case described in https://github.com/Guts/mkdocs-rss-plugin/issues/319.""" + # default reference + cfg_mkdocs = load_config( + str( + Path( + "tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.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.assertIsInstance(integration_social_cards.social_cards_dir, str) + self.assertTrue(integration_social_cards.social_cards_cache_dir.is_dir()) + + with tempfile.TemporaryDirectory( + prefix=f"{__title_clean__.lower()}_", delete=False + ) as tmpdirname: + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path( + "tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml" + ), + output_path=tmpdirname, + strict=False, + ) + print(tmpdirname) + if cli_result.exception is not None: + e = cli_result.exception + logger.debug(format_exception(type(e), e, e.__traceback__)) + + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # created items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_created.xml") + self.assertEqual(feed_parsed.bozo, 0) + for feed_item in feed_parsed.entries: + self.assertTrue(hasattr(feed_item, "enclosures")) + + # updated items + feed_parsed = feedparser.parse(Path(tmpdirname) / "feed_rss_updated.xml") + self.assertEqual(feed_parsed.bozo, 0) + def test_simple_build(self): with tempfile.TemporaryDirectory() as tmpdirname: cli_result = self.build_docs_setup( From 7b4ca6e9cec27361e8f736d0fc4b44f716c4cfe0 Mon Sep 17 00:00:00 2001 From: "Julien M." Date: Fri, 23 May 2025 19:29:25 +0200 Subject: [PATCH 063/158] fix(tests): remove is_dir test since there is a race condition making it failing on CI --- tests/test_integrations_material_social_cards.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_integrations_material_social_cards.py b/tests/test_integrations_material_social_cards.py index a2baed31..d8427b9a 100644 --- a/tests/test_integrations_material_social_cards.py +++ b/tests/test_integrations_material_social_cards.py @@ -155,7 +155,7 @@ def test_plugin_config_social_cards_enabled_with_directory_urls_disabled(self): self.assertTrue(integration_social_cards.IS_SOCIAL_PLUGIN_ENABLED) self.assertTrue(integration_social_cards.IS_SOCIAL_PLUGIN_CARDS_ENABLED) self.assertIsInstance(integration_social_cards.social_cards_dir, str) - self.assertTrue(integration_social_cards.social_cards_cache_dir.is_dir()) + # self.assertTrue(integration_social_cards.social_cards_cache_dir.is_dir()) with tempfile.TemporaryDirectory( prefix=f"{__title_clean__.lower()}_", delete=False From a9a22e79992558ef71b4c55eb624669e6b6b67eb Mon Sep 17 00:00:00 2001 From: "Julien M." Date: Fri, 23 May 2025 19:32:37 +0200 Subject: [PATCH 064/158] release: bump version to 1.17.2 --- CHANGELOG.md | 16 ++++++++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f28ae2d9..dce3b4c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.2 - 2025-05-23 + +### Bugs fixes 🐛 + +* fix(upstream): force jsonfeed-util version since it uses a non Python 3.9 syntax, breaking lint and tests by @Guts in +* Docs: fix mkdocstings config and improve api autodoc by @Guts in +* fix(material_social): use cards_dir to build cards url for page by @kanru in + +### Other Changes + +* Revert 355: restore minimal JSON Feed minimal version by @Guts in + +### New Contributors + +* @kanru made their first contribution in + ## 1.17.1 - 2024-12-16 ### Bugs fixes 🐛 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index aa986524..796d5d12 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.17.1" +__version__ = "1.17.2" __version_info__ = tuple( [ int(num) if num.isdigit() else num From 257186d8851268fe9323a6fe3df101142115d40a Mon Sep 17 00:00:00 2001 From: "Julien M." Date: Fri, 23 May 2025 19:36:58 +0200 Subject: [PATCH 065/158] fix(tests): remove delete param from tempfile.TemporaryDirectory introduced only from Python >= 3.12 --- tests/test_integrations_material_social_cards.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_integrations_material_social_cards.py b/tests/test_integrations_material_social_cards.py index d8427b9a..add2162c 100644 --- a/tests/test_integrations_material_social_cards.py +++ b/tests/test_integrations_material_social_cards.py @@ -158,7 +158,7 @@ def test_plugin_config_social_cards_enabled_with_directory_urls_disabled(self): # self.assertTrue(integration_social_cards.social_cards_cache_dir.is_dir()) with tempfile.TemporaryDirectory( - prefix=f"{__title_clean__.lower()}_", delete=False + prefix=f"{__title_clean__.lower()}_" ) as tmpdirname: cli_result = self.build_docs_setup( testproject_path="docs", From cba58f945b63014aba485bcb827d2fa4082c2b85 Mon Sep 17 00:00:00 2001 From: Luke Hsiao Date: Thu, 29 May 2025 10:13:48 -0700 Subject: [PATCH 066/158] fix: return None if remote image length is unavailable When this plugin is run on a doc site that also uses the social plugin, fetching remote image data can fail. This results in a crash when building the documentation: File "/path/installs/python/3.11.5/lib/python3.11/site-packages/mkdocs_rss_plugin/util.py", line 608, in get_image img_length = self.get_remote_image_length(image_url=img_url) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/path/installs/python/3.11.5/lib/python3.11/site-packages/mkdocs_rss_plugin/util.py", line 710, in get_remote_image_length return int(img_length) ^^^^^^^^^^^^^^^ TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' This patch simply returns None if `img_length` is `None.` Closes: #369 Closes: #353 Signed-off-by: Luke Hsiao --- mkdocs_rss_plugin/util.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index a25cde03..a5aa41c7 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -126,8 +126,7 @@ def __init__( else: self.git_is_valid = False logger.debug( - "Git use is disabled. " - "Only page.meta (YAML frontmatter will be used). " + "Git use is disabled. Only page.meta (YAML frontmatter will be used). " ) # save git enable/disable status @@ -588,13 +587,19 @@ def get_image(self, in_page: Page, base_url: str) -> Optional[tuple[str, str, in img_url = self.social_cards.get_social_card_url_for_page( mkdocs_page=in_page ) - if img_local_cache_path := self.social_cards.get_social_card_cache_path_for_page( - mkdocs_page=in_page + if ( + img_local_cache_path + := self.social_cards.get_social_card_cache_path_for_page( + mkdocs_page=in_page + ) ): img_length = img_local_cache_path.stat().st_size img_type = guess_type(url=img_local_cache_path, strict=False)[0] - elif img_local_build_path := self.social_cards.get_social_card_build_path_for_page( - mkdocs_page=in_page + elif ( + img_local_build_path + := self.social_cards.get_social_card_build_path_for_page( + mkdocs_page=in_page + ) ): img_length = img_local_build_path.stat().st_size img_type = guess_type(url=img_local_build_path, strict=False)[0] @@ -707,7 +712,7 @@ def get_remote_image_length( ) return None - return int(img_length) + return int(img_length) if img_length else None @staticmethod def get_site_url(mkdocs_config: MkDocsConfig) -> Optional[str]: From 6ce8a005829d988fa7cc2a9573c5acb9b7eb1f3a Mon Sep 17 00:00:00 2001 From: Luke Hsiao Date: Thu, 29 May 2025 10:23:27 -0700 Subject: [PATCH 067/158] style: run black formatting --- mkdocs_rss_plugin/util.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index a5aa41c7..1878d296 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -587,19 +587,13 @@ def get_image(self, in_page: Page, base_url: str) -> Optional[tuple[str, str, in img_url = self.social_cards.get_social_card_url_for_page( mkdocs_page=in_page ) - if ( - img_local_cache_path - := self.social_cards.get_social_card_cache_path_for_page( - mkdocs_page=in_page - ) + if img_local_cache_path := self.social_cards.get_social_card_cache_path_for_page( + mkdocs_page=in_page ): img_length = img_local_cache_path.stat().st_size img_type = guess_type(url=img_local_cache_path, strict=False)[0] - elif ( - img_local_build_path - := self.social_cards.get_social_card_build_path_for_page( - mkdocs_page=in_page - ) + elif img_local_build_path := self.social_cards.get_social_card_build_path_for_page( + mkdocs_page=in_page ): img_length = img_local_build_path.stat().st_size img_type = guess_type(url=img_local_build_path, strict=False)[0] From 2a7ae628649a2a48de25c19e0563d2e036334893 Mon Sep 17 00:00:00 2001 From: "Julien M." Date: Fri, 30 May 2025 21:15:37 +0200 Subject: [PATCH 068/158] release: bump version to 1.17.3 --- CHANGELOG.md | 10 ++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce3b4c8..cabd5840 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.3 - 2025-05-30 + +### Bugs fixes 🐛 + +* fix: return None if remote image length is unavailable by @lukehsiao in + +### New Contributors + +* @lukehsiao made their first contribution in + ## 1.17.2 - 2025-05-23 ### Bugs fixes 🐛 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index 796d5d12..4e732868 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.17.2" +__version__ = "1.17.3" __version_info__ = tuple( [ int(num) if num.isdigit() else num From 646e8f8e97d2c849de541d64ea87d1038f28d0af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 18:54:49 +0000 Subject: [PATCH 069/158] build(deps): bump codecov/codecov-action from 5.4.2 to 5.4.3 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.2 to 5.4.3. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.4.2...v5.4.3) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 888b49c9..3d754f55 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.4.2 + uses: codecov/codecov-action@v5.4.3 with: env_vars: PYTHON flags: unittests From 62bbb79726b61cfd763d55f42408fa37a318d5dc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:01:58 +0000 Subject: [PATCH 070/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.19.1 → v3.20.0](https://github.com/asottile/pyupgrade/compare/v3.19.1...v3.20.0) - [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.12) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fc756f9c..9ace2085 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.19.1 + rev: v3.20.0 hooks: - id: pyupgrade args: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.8" + rev: "v0.11.12" hooks: - id: ruff args: From e11bc410106e93973e7795795a343dd748167bfd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:11:13 +0000 Subject: [PATCH 071/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.12 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.12...v0.12.2) - [github.com/pycqa/flake8: 7.2.0 → 7.3.0](https://github.com/pycqa/flake8/compare/7.2.0...7.3.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9ace2085..bfd07d07 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.12" + rev: "v0.12.2" hooks: - id: ruff args: @@ -62,7 +62,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/flake8 - rev: 7.2.0 + rev: 7.3.0 hooks: - id: flake8 additional_dependencies: From d1627a5b180591aa0dd1d28c362e4040de0915f7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:20:05 +0000 Subject: [PATCH 072/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.7) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bfd07d07..ff971c0c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.2" + rev: "v0.12.7" hooks: - id: ruff args: From 2fff07e6d75592af0df443de16661041458f0647 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Tue, 19 Aug 2025 17:12:18 -0400 Subject: [PATCH 073/158] fix: preserve sentence structure across newlines Instead of stripping out the newlines characters, leading to mangled content when rendering full contents, provide a space instead. Fixes #186 Signed-off-by: Mike Fiedler --- mkdocs_rss_plugin/plugin.py | 7 ++++--- tests/test_build.py | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index a169ad47..515f69da 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -432,7 +432,8 @@ def on_post_build(self, config: config_options.Config) -> None: prev_char = "" for char in template.render(feed=asdict(self.feed_created)): if char == "\n": - continue + # convert new lines to spaces to preserve sentence structure + char = " " if char == " " and prev_char == " ": prev_char = char continue @@ -442,8 +443,8 @@ def on_post_build(self, config: config_options.Config) -> None: with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated: for char in template.render(feed=asdict(self.feed_updated)): if char == "\n": - prev_char = char - continue + # convert new lines to spaces to preserve sentence structure + char = " " if char == " " and prev_char == " ": prev_char = char continue diff --git a/tests/test_build.py b/tests/test_build.py index 7f07e479..451d7961 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -405,6 +405,12 @@ def test_simple_build_item_length_unlimited(self): 150, f"Failed item title: {feed_item.title}", ) + # check sentences split across multiple lines retain spacing + if feed_item.title in ["My first blog post", "A second post"]: + self.assertIn( + "Pellentesque nec maximus ex.", + feed_item.summary, + ) def test_simple_build_item_delimiter(self): with tempfile.TemporaryDirectory() as tmpdirname: From 17b09ab931af8fbf2fa7f6f10db761c11e69b903 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 18:10:36 +0000 Subject: [PATCH 074/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.7 → v0.12.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.7...v0.12.11) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff971c0c..0145596a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: ".venv|.direnv|tests/dev/|tests/fixtures/" fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files args: @@ -38,7 +38,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.7" + rev: "v0.12.11" hooks: - id: ruff args: From 2cccc5e58e448184c395d8ae3f068c14ea456943 Mon Sep 17 00:00:00 2001 From: Julien <1596222+Guts@users.noreply.github.com> Date: Tue, 9 Sep 2025 06:14:07 +0200 Subject: [PATCH 075/158] update(tooling): remove encoding pragma remover from git hooks since it's deprecated Signed-off-by: Julien <1596222+Guts@users.noreply.github.com> --- .pre-commit-config.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0145596a..d5e26e60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,9 +18,6 @@ repos: - id: detect-private-key - id: end-of-file-fixer - id: fix-byte-order-marker - - id: fix-encoding-pragma - args: - - --remove - id: trailing-whitespace args: - --markdown-linebreak-ext=md From 4ccea2f62c04582c7de169c682345e6b61f0a7b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 04:17:10 +0000 Subject: [PATCH 076/158] build(deps): bump actions/upload-pages-artifact from 3 to 4 Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index f219175c..098f7e38 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -87,7 +87,7 @@ jobs: if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') with: # Upload entire repository From bf461c95e0176336ab55501b7a646c5f1a96e942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 04:20:55 +0000 Subject: [PATCH 077/158] build(deps): bump codecov/codecov-action from 5.4.3 to 5.5.0 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.3 to 5.5.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.4.3...v5.5.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 3d754f55..c571e43d 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -61,7 +61,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.4.3 + uses: codecov/codecov-action@v5.5.1 with: env_vars: PYTHON flags: unittests From 79f8480e4659fa6b4e6e9b85bddbd902089f8e2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 04:24:19 +0000 Subject: [PATCH 078/158] build(deps): bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-test.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/lint-and-tests.yml | 2 +- .github/workflows/release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index d1cf1e56..e6d8d1b9 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -16,7 +16,7 @@ jobs: docker-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Test Docker Build run: | diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 098f7e38..f7238d02 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -47,7 +47,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Get source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index c571e43d..56dc5942 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -31,7 +31,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Get source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7092767..445ee855 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: discussions: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 From 120dde56897c3b932d895fdaad4a8f07935d71e4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 9 Sep 2025 06:37:45 +0200 Subject: [PATCH 079/158] fix(logs): update references hyperlinks for git depth logs close #375 --- mkdocs_rss_plugin/git_manager/ci.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkdocs_rss_plugin/git_manager/ci.py b/mkdocs_rss_plugin/git_manager/ci.py index 3ee8dcc2..3d5ec17c 100644 --- a/mkdocs_rss_plugin/git_manager/ci.py +++ b/mkdocs_rss_plugin/git_manager/ci.py @@ -52,7 +52,7 @@ def raise_ci_warnings(self) -> None: Running on a gitlab runner might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Make sure to set GIT_DEPTH to 1000 in your .gitlab-ci.yml file. \ - (see https://docs.gitlab.com/ee/user/project/pipelines/settings.html#git-shallow-clone). + (see https://docs.gitlab.com/user/project/repository/monorepos/#use-shallow-clones-in-cicd-processes). """ ) @@ -64,7 +64,7 @@ def raise_ci_warnings(self) -> None: Running on github actions might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Try setting fetch-depth to 0 in your github action \ - (see https://github.com/actions/checkout). + (see https://github.com/actions/checkout?tab=readme-ov-file#fetch-all-history-for-all-tags-and-branches). """ ) @@ -76,7 +76,7 @@ def raise_ci_warnings(self) -> None: Running on bitbucket pipelines might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Try setting "clone: depth" to "full" in your pipeline \ - (see https://support.atlassian.com/bitbucket-cloud/docs/configure-bitbucket-pipelinesyml/ + (see https://support.atlassian.com/bitbucket-cloud/docs/git-clone-behavior/#Depth and search 'depth'). """ ) From d6e82a3a1dbd60567a2b16368239482c3560aa6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:01:01 +0000 Subject: [PATCH 080/158] build(deps): bump actions/setup-python from 5 to 6 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- .github/workflows/lint-and-tests.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index f7238d02..46c5356d 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -52,7 +52,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.11" cache: "pip" diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 56dc5942..139407a0 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} cache: "pip" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 445ee855..e2a3f007 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" cache: "pip" From 6ac1f13704e4f70b87375ccbac359fddcd61ecad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 21:22:40 +0000 Subject: [PATCH 081/158] build(deps): bump actions/labeler from 5 to 6 Bumps [actions/labeler](https://github.com/actions/labeler) from 5 to 6. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pr-auto-labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-auto-labeler.yml b/.github/workflows/pr-auto-labeler.yml index 03c703a8..b2baed5e 100644 --- a/.github/workflows/pr-auto-labeler.yml +++ b/.github/workflows/pr-auto-labeler.yml @@ -6,7 +6,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - uses: actions/labeler@v6 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" sync-labels: true From f06380b95c7e1e1a35966b628b9c142e36050ad0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:43:27 +0000 Subject: [PATCH 082/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.11 → v0.13.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.11...v0.13.3) - [github.com/pycqa/isort: 6.0.1 → 6.1.0](https://github.com/pycqa/isort/compare/6.0.1...6.1.0) - https://github.com/psf/black → https://github.com/psf/black-pre-commit-mirror - [github.com/psf/black-pre-commit-mirror: 25.1.0 → 25.9.0](https://github.com/psf/black-pre-commit-mirror/compare/25.1.0...25.9.0) --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d5e26e60..b8ebb631 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - "--py39-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.11" + rev: "v0.13.3" hooks: - id: ruff args: @@ -43,7 +43,7 @@ repos: - --target-version=py39 - repo: https://github.com/pycqa/isort - rev: 6.0.1 + rev: 6.1.0 hooks: - id: isort args: @@ -51,8 +51,8 @@ repos: - black - --filter-files - - repo: https://github.com/psf/black - rev: 25.1.0 + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 25.9.0 hooks: - id: black args: From eb0c1f3aada71e108d23585d4b213195da260adf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 01:25:51 +0000 Subject: [PATCH 083/158] build(deps): update pytest-cov requirement from <7,>=6 to >=6,<8 Updates the requirements on [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.0.0...v7.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-version: 7.0.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/testing.txt b/requirements/testing.txt index 514c8247..53dcd67a 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -6,5 +6,5 @@ feedparser>=6.0.11,<6.1 jsonfeed-util>=1.2,<2 mkdocs-material[imaging]>=9.5.47 -pytest-cov>=6,<7 +pytest-cov>=6,<8 validator-collection>=1.5,<1.6 From fd2e92f0c69ef62084c500b34ec5125de752fc49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 01:28:33 +0000 Subject: [PATCH 084/158] build(deps): update mkdocstrings-python requirement Updates the requirements on [mkdocstrings-python](https://github.com/mkdocstrings/python) to permit the latest version. - [Release notes](https://github.com/mkdocstrings/python/releases) - [Changelog](https://github.com/mkdocstrings/python/blob/main/CHANGELOG.md) - [Commits](https://github.com/mkdocstrings/python/compare/1.16.2...1.18.2) --- updated-dependencies: - dependency-name: mkdocstrings-python dependency-version: 1.18.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 313d1b3c..7510316e 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -5,5 +5,5 @@ mkdocs-git-committers-plugin-2>=2.4.1,<2.6 mkdocs-git-revision-date-localized-plugin>=1.3,<1.5 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 -mkdocstrings-python>=1.16.2,<1.17 +mkdocstrings-python>=1.16.2,<1.19 termynal>=0.12.2,<0.14 From 0b473622a01f6c0316aab4833d356a86a49a3a36 Mon Sep 17 00:00:00 2001 From: Julien <1596222+Guts@users.noreply.github.com> Date: Fri, 10 Oct 2025 04:56:05 +0200 Subject: [PATCH 085/158] improve(images): add timeout to remote images requests (#391) --- mkdocs_rss_plugin/util.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index 1878d296..fea35218 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -656,6 +656,7 @@ def get_remote_image_length( image_url: str, http_method: str = "HEAD", attempt: int = 0, + req_timeout: tuple[float, float] = (5, 30), ssl_verify: bool = True, ) -> Optional[int]: """Retrieve length for remote images (starting with 'http'). @@ -668,6 +669,8 @@ def get_remote_image_length( http_method (str, optional): HTTP method to use for the request. Defaults to "HEAD". attempt (int, optional): request tries counter. Defaults to 0. + req_timeout (tuple[float, float], optional): (connect, read) timeout in \ + secondes. Defaults to (5, 30). ssl_verify (bool, optional): option to perform SSL verification or not. Defaults to True. @@ -685,7 +688,10 @@ def get_remote_image_length( f"Sending {http_method} request to {image_url}" ) req_response = self.req_session.request( - method=http_method, url=image_url, verify=ssl_verify + method=http_method, + timeout=req_timeout, + url=image_url, + verify=ssl_verify, ) req_response.raise_for_status() img_length = req_response.headers.get("content-length") From 9fe2ad8b33e23cf8bbba2010e5437dec7ba43514 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Oct 2025 05:08:48 +0200 Subject: [PATCH 086/158] fix(material): mkdocs_config.plugins.get("material/blog") can be None Spotted by SonarQube. See https://sonarcloud.io/organizations/geojulien/rules?open=pythonbugs%3AS2259&rule_key=pythonbugs%3AS2259 --- mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 1e38de96..4ac97263 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -87,7 +87,7 @@ def is_blog_plugin_enabled_mkdocs( logger.debug("Installed theme is not 'material'. Integration disabled.") return False - if not mkdocs_config.plugins.get("material/blog"): + if mkdocs_config.plugins.get("material/blog") is None: logger.debug("Material blog plugin is not listed in configuration.") self.IS_BLOG_PLUGIN_ENABLED = False return False From 91242c69476bbf819165d9f818df36e322cd530c Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Oct 2025 05:10:32 +0200 Subject: [PATCH 087/158] update(docs): add SonarQube badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 46b0054f..75089dc9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![PyPI - Downloads](https://img.shields.io/pypi/dm/mkdocs-rss-plugin)](https://pypi.org/project/mkdocs-rss-plugin/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mkdocs-rss-plugin)](https://pypi.org/project/mkdocs-rss-plugin/) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Guts_mkdocs-rss-plugin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Guts_mkdocs-rss-plugin) [![codecov](https://codecov.io/gh/Guts/mkdocs-rss-plugin/branch/main/graph/badge.svg?token=A0XPLKiwiW)](https://codecov.io/gh/Guts/mkdocs-rss-plugin) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![flake8](https://img.shields.io/badge/linter-flake8-green)](https://flake8.pycqa.org/) From 85b60b00b4f21d70e9dc5119fee42bf1e7e9fc31 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Oct 2025 05:29:08 +0200 Subject: [PATCH 088/158] update(tooling): refine excluded authors --- .github/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/release.yml b/.github/release.yml index 70c11e03..7b78f6e6 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -1,8 +1,8 @@ changelog: exclude: authors: - - dependabot - - pre-commit-ci + - dependabot[bot] + - pre-commit-ci[bot] categories: - title: Bugs fixes 🐛 labels: From 67858c53990516b88faa73cb4b158b440a403585 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Oct 2025 05:29:26 +0200 Subject: [PATCH 089/158] release: bump version to 1.17.4 --- CHANGELOG.md | 16 ++++++++++++++++ mkdocs_rss_plugin/__about__.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cabd5840..6670101d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.4 - 2025-10-10 + +### Bugs fixes 🐛 + +* fix(logs): update references hyperlinks for git depth logs by @Guts in +* fix(material): mkdocs_config.plugins.get("material/blog") can be None by @Guts in +* fix: preserve sentence structure across newlines by @miketheman in + +### Features and enhancements 🎉 + +* improve(images): add timeout to remote images requests by @Guts in + +### New Contributors + +* @miketheman made their first contribution in + ## 1.17.3 - 2025-05-30 ### Bugs fixes 🐛 diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index 4e732868..30af9ef3 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -40,7 +40,7 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.17.3" +__version__ = "1.17.4" __version_info__ = tuple( [ int(num) if num.isdigit() else num From 7a29d94c850bc1e485de36a5701fc21527c960dd Mon Sep 17 00:00:00 2001 From: Julien <1596222+Guts@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:38:40 +0200 Subject: [PATCH 090/158] improve(performances): run RSS item image fetching only on filtered pages list (#394) * add(model): create MkdocsPageSubset to store Pages refs accross signals * update(model): move serialization to RSS item as PageInformation method * update(plugin): store subset of Mkdocs page to use later during on_post_build * update(plugin): factorize image fetching and page and RSS item related models * update(plugin): remove older refs to Page by SubsetPage * update(plugin): avoid duplicate image retrieval * fix(plugin): fill created and updated dates just before file creation to avoid "last called is right" effect * update(plugin): factorize RSS feeds i/o depending on pretty print option * update(json_feed): include created as date_published and updated as date_modified * remove(models): delete unued attributes --- .../theme_material_social_plugin.py | 44 +++--- mkdocs_rss_plugin/models.py | 88 ++++++++---- mkdocs_rss_plugin/plugin.py | 79 +++++++---- mkdocs_rss_plugin/templates/rss.xml.jinja2 | 2 +- mkdocs_rss_plugin/util.py | 131 ++++++++++-------- 5 files changed, 207 insertions(+), 137 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 4b434ca2..23a6f831 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -13,7 +13,6 @@ # 3rd party from mkdocs.config.defaults import MkDocsConfig from mkdocs.plugins import get_plugin_logger -from mkdocs.structure.pages import Page # package from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME @@ -23,6 +22,7 @@ from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import ( IntegrationMaterialBlog, ) +from mkdocs_rss_plugin.models import MkdocsPageSubset # conditional try: @@ -167,18 +167,18 @@ def is_social_plugin_and_cards_enabled_mkdocs( return True def is_social_plugin_enabled_page( - self, mkdocs_page: Page, fallback_value: bool = True + self, mkdocs_page: MkdocsPageSubset, fallback_value: bool = True ) -> bool: """Check if the social plugin is enabled or disabled for a specific page. Plugin has to be enabled in Mkdocs configuration before. Args: - mkdocs_page (Page): Mkdocs page object. - fallback_value (bool, optional): fallback value. It might be the + mkdocs_page: Mkdocs page object. + fallback_value: 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. + True if the social cards are enabled for a page. """ return mkdocs_page.meta.get("social", {"cards": fallback_value}).get( "cards", fallback_value @@ -262,17 +262,17 @@ def get_social_cards_cache_dir(self, mkdocs_config: MkDocsConfig) -> Path: return self.social_cards_cache_dir def get_social_card_build_path_for_page( - self, mkdocs_page: Page, mkdocs_site_dir: Optional[str] = None + self, mkdocs_page: MkdocsPageSubset, mkdocs_site_dir: Optional[str] = None ) -> Optional[Path]: """Get social card path in Mkdocs build dir for a specific page. Args: - mkdocs_page (Page): Mkdocs page object. - mkdocs_site_dir (Optional[str], optional): Mkdocs build site dir. If None, the + mkdocs_page: Mkdocs page object. + mkdocs_site_dir: Mkdocs build site dir. If None, the 'class.mkdocs_site_build_dir' is used. is Defaults to None. Returns: - Path: path to the image once published + path 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 @@ -284,12 +284,12 @@ def get_social_card_build_path_for_page( ): expected_built_card_path = Path( f"{mkdocs_site_dir}/{self.social_cards_assets_dir}/" - f"{Path(mkdocs_page.file.dest_uri).parent}.png" + f"{Path(mkdocs_page.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')}" + f"{Path(mkdocs_page.src_uri).with_suffix('.png')}" ) if expected_built_card_path.is_file(): @@ -303,7 +303,9 @@ def get_social_card_build_path_for_page( ) return None - def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Path]: + def get_social_card_cache_path_for_page( + self, mkdocs_page: MkdocsPageSubset + ) -> Optional[Path]: """Get social card path in social plugin cache folder for a specific page. Note: @@ -314,10 +316,10 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat any exposed matching criteria. Args: - mkdocs_page (Page): Mkdocs page object. + mkdocs_page: Mkdocs page object. Returns: - Path: path to the image in local cache folder if it exists + path to the image in local cache folder if it exists """ if self.IS_INSIDERS: @@ -327,11 +329,11 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): expected_cached_card_path = self.social_cards_cache_dir.joinpath( - f"assets/images/social/{Path(mkdocs_page.file.dest_uri).parent}.png" + f"assets/images/social/{Path(mkdocs_page.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')}" + f"assets/images/social/{Path(mkdocs_page.src_uri).with_suffix('.png')}" ) if expected_cached_card_path.is_file(): @@ -374,18 +376,18 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat def get_social_card_url_for_page( self, - mkdocs_page: Page, + mkdocs_page: MkdocsPageSubset, 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 + mkdocs_page: subset of Mkdocs page object. + mkdocs_site_url: Mkdocs site URL. If None, the 'class.mkdocs_site_url' is used. is Defaults to None. Returns: - str: URL to the image once published + URL to the image once published """ if mkdocs_site_url is None and self.mkdocs_site_url: mkdocs_site_url = self.mkdocs_site_url @@ -394,7 +396,7 @@ def get_social_card_url_for_page( # matching src path in the build folder, regardless of the page type. page_social_card = ( f"{mkdocs_site_url}{self.social_cards_dir}/" - f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}" + f"{Path(mkdocs_page.src_uri).with_suffix('.png')}" ) logger.debug(f"Use social card url: {page_social_card}") diff --git a/mkdocs_rss_plugin/models.py b/mkdocs_rss_plugin/models.py index e4d1ac3a..2b458e56 100644 --- a/mkdocs_rss_plugin/models.py +++ b/mkdocs_rss_plugin/models.py @@ -4,11 +4,18 @@ # ########## Libraries ############# # ################################## +# for class autoref typing +from __future__ import annotations + # standard +from collections.abc import MutableMapping from dataclasses import dataclass, field from datetime import datetime from pathlib import Path -from typing import Optional +from typing import Any + +# 3rd party +from mkdocs.structure.pages import Page # package modules from mkdocs_rss_plugin.__about__ import __title__, __version__ @@ -18,39 +25,70 @@ # ################################## +@dataclass +class MkdocsPageSubset: + """Minimal subset of a Mkdocs Page with only necessary attributes for plugin needs.""" + + abs_src_path: str + dest_uri: str + src_uri: str + title: str | None = None + meta: MutableMapping[str, Any] | None = None + + @classmethod + def from_page(cls, page: Page) -> MkdocsPageSubset: + """Create a PageSubset from a Mkdocs page. + + Args: + page: MkDocs Page object + """ + return cls( + abs_src_path=page.file.abs_src_path, + meta=page.meta, + title=page.title, + src_uri=page.file.src_uri, + dest_uri=page.file.dest_uri, + ) + + @dataclass class PageInformation: """Object describing a page information gathered from Mkdocs and used as feed's item.""" - abs_path: Optional[Path] = None - categories: Optional[list] = None - authors: Optional[tuple] = None - created: Optional[datetime] = None - description: Optional[str] = None - guid: Optional[str] = None - image: Optional[str] = None - title: Optional[str] = None - updated: Optional[datetime] = None - url_comments: Optional[str] = None - url_full: Optional[str] = None + abs_path: Path | None = None + categories: list | None = None + authors: tuple | None = None + comments_url: str | None = None + created: datetime | None = None + description: str | None = None + guid: str | None = None + image: tuple[str, str, int] | None = None + link: str | None = None + pub_date: str | None = None + title: str | None = None + updated: datetime | None = None + # private + _mkdocs_page_ref: MkdocsPageSubset | None = field( + default=None, repr=False, compare=False + ) @dataclass class RssFeedBase: """Object describing a feed.""" - author: Optional[str] = None - buildDate: Optional[str] = None - copyright: Optional[str] = None - description: Optional[str] = None + author: str | None = None + buildDate: str | None = None + copyright: str | None = None + description: str | None = None entries: list[PageInformation] = field(default_factory=list) generator: str = f"{__title__} - v{__version__}" - html_url: Optional[str] = None - json_url: Optional[str] = None - language: Optional[str] = None - logo_url: Optional[str] = None - pubDate: Optional[str] = None - repo_url: Optional[str] = None - rss_url: Optional[str] = None - title: Optional[str] = None - ttl: Optional[int] = None + html_url: str | None = None + json_url: str | None = None + language: str | None = None + logo_url: str | None = None + pubDate: str | None = None + repo_url: str | None = None + rss_url: str | None = None + title: str | None = None + ttl: int | None = None diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index 515f69da..bfe05aff 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -9,7 +9,7 @@ from copy import deepcopy from dataclasses import asdict from datetime import datetime -from email.utils import formatdate +from email.utils import format_datetime, formatdate from pathlib import Path from re import compile as re_compile from typing import Literal, Optional @@ -24,7 +24,7 @@ from mkdocs.utils import get_build_timestamp # package modules -from mkdocs_rss_plugin.__about__ import __title__, __uri__, __version__ +from mkdocs_rss_plugin.__about__ import __title__, __version__ from mkdocs_rss_plugin.config import RssPluginConfig from mkdocs_rss_plugin.constants import ( DEFAULT_TEMPLATE_FILENAME, @@ -37,7 +37,7 @@ from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) -from mkdocs_rss_plugin.models import PageInformation, RssFeedBase +from mkdocs_rss_plugin.models import MkdocsPageSubset, PageInformation, RssFeedBase from mkdocs_rss_plugin.util import Util # ############################################################################ @@ -331,6 +331,7 @@ def on_page_content( categories=self.util.get_categories_from_meta( in_page=page, categories_labels=self.config.categories ), + comments_url=page_url_comments, created=page_dates[0], description=self.util.get_description_or_abstract( in_page=page, @@ -338,15 +339,11 @@ def on_page_content( abstract_delimiter=self.config.abstract_delimiter, ), guid=page.canonical_url, - image=self.util.get_image( - in_page=page, - # below let it as old dict get method to handle custom fallback value - base_url=config.get("site_url", __uri__), - ), + link=page_url_full, title=page.title, updated=page_dates[1], - url_comments=page_url_comments, - url_full=page_url_full, + # for later fetch + _mkdocs_page_ref=MkdocsPageSubset.from_page(page), ) ) @@ -385,7 +382,7 @@ def on_post_build(self, config: config_options.Config) -> None: self.feed_created.entries.extend( self.util.filter_pages( pages=self.pages_to_filter, - attribute="created", + filter_attribute="created", length=self.config.length, ) ) @@ -394,30 +391,33 @@ def on_post_build(self, config: config_options.Config) -> None: self.feed_updated.entries.extend( self.util.filter_pages( pages=self.pages_to_filter, - attribute="updated", + filter_attribute="updated", length=self.config.length, ) ) + # load RSS items images (enclosures) + logger.debug( + f"Loading images for {len(self.feed_created.entries)} pages by creation " + f"and {len(self.feed_updated.entries)} pages by update" + ) + processed_refs = set() + self.util.load_images_for_pages( + self.feed_created.entries, config.site_url, processed_refs + ) + self.util.load_images_for_pages( + self.feed_updated.entries, config.site_url, processed_refs + ) + # RSS if self.config.rss_feed_enabled: - # write feeds according to the pretty print option + # Jinja environment depending on the pretty print option if pretty_print: # load Jinja environment and template env = Environment( autoescape=select_autoescape(["html", "xml"]), loader=FileSystemLoader(self.tpl_folder), ) - - template = env.get_template(self.tpl_file.name) - - # write feeds to files - with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created: - fifeed_created.write(template.render(feed=self.feed_created)) - - with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated: - fifeed_updated.write(template.render(feed=self.feed_updated)) - else: # load Jinja environment and template env = Environment( @@ -426,9 +426,19 @@ def on_post_build(self, config: config_options.Config) -> None: lstrip_blocks=True, trim_blocks=True, ) - template = env.get_template(self.tpl_file.name) - # write feeds to files stripping out spaces and new lines - with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created: + template = env.get_template(self.tpl_file.name) + + # -- Feed sorted by creation date + logger.debug("Fill creation dates and dump created feed into RSS template.") + # set pub date as created + for page in self.feed_created.entries: + page.pub_date = format_datetime(dt=page.created) + + # write file + with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created: + if pretty_print: + fifeed_created.write(template.render(feed=self.feed_created)) + else: prev_char = "" for char in template.render(feed=asdict(self.feed_created)): if char == "\n": @@ -440,7 +450,18 @@ def on_post_build(self, config: config_options.Config) -> None: prev_char = char fifeed_created.write(char) - with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated: + # -- Feed sorted by last update date + logger.debug("Fill update dates and dump udpated feed into RSS template.") + # set pub date as updated + for page in self.feed_updated.entries: + page.pub_date = format_datetime(dt=page.updated) + + # write file + with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated: + if pretty_print: + fifeed_updated.write(template.render(feed=self.feed_updated)) + else: + prev_char = "" for char in template.render(feed=asdict(self.feed_updated)): if char == "\n": # convert new lines to spaces to preserve sentence structure @@ -455,14 +476,14 @@ def on_post_build(self, config: config_options.Config) -> None: if self.config.json_feed_enabled: with out_json_created.open(mode="w", encoding="UTF8") as fp: json.dump( - self.util.feed_to_json(asdict(self.feed_created)), + self.util.feed_to_json(self.feed_created), fp, indent=4 if self.config.pretty_print else None, ) with out_json_updated.open(mode="w", encoding="UTF8") as fp: json.dump( - self.util.feed_to_json(asdict(self.feed_updated), updated=True), + self.util.feed_to_json(self.feed_updated), fp, indent=4 if self.config.pretty_print else None, ) diff --git a/mkdocs_rss_plugin/templates/rss.xml.jinja2 b/mkdocs_rss_plugin/templates/rss.xml.jinja2 index 2d63af46..3448588a 100644 --- a/mkdocs_rss_plugin/templates/rss.xml.jinja2 +++ b/mkdocs_rss_plugin/templates/rss.xml.jinja2 @@ -47,7 +47,7 @@ {% endif %} {{ item.description|e }} {% if item.link is not none %}{{ item.link|e }}{% endif %} - {{ item.pubDate }} + {{ item.pub_date }} {% if item.link is not none %}{{ feed.title }}{% endif %} {% if item.comments_url is not none %}{{ item.comments_url|e }}{% endif %} {% if item.guid is not none %}{{ item.guid }}{% endif %} diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index fea35218..afe00791 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -8,11 +8,10 @@ import logging from collections.abc import Iterable from datetime import date, datetime -from email.utils import format_datetime from functools import lru_cache from mimetypes import guess_type from pathlib import Path -from typing import Any, Union +from typing import Any, Literal, Union from urllib.parse import urlencode, urlparse, urlunparse # 3rd party @@ -47,7 +46,7 @@ from mkdocs_rss_plugin.integrations.theme_material_social_plugin import ( IntegrationMaterialSocialCards, ) -from mkdocs_rss_plugin.models import PageInformation +from mkdocs_rss_plugin.models import MkdocsPageSubset, PageInformation, RssFeedBase from mkdocs_rss_plugin.timezoner import set_datetime_zoneinfo # ############################################################################ @@ -551,29 +550,57 @@ def get_description_or_abstract( ) return "" - def get_image(self, in_page: Page, base_url: str) -> Optional[tuple[str, str, int]]: + def load_images_for_pages( + self, + pages: list[PageInformation], + base_url: str, + processed_refs: Optional[set] = None, + ) -> None: + """Load images for a list of pages (mutation in-place). + + Args: + pages: list of PageInformation + base_url: final website base URL + processed_refs: deduplication set + """ + if processed_refs is None: + processed_refs = set() + + for page_info in pages: + if ( + page_info._mkdocs_page_ref + and id(page_info._mkdocs_page_ref) not in processed_refs + ): + logger.debug(f"Get image for '{page_info.title}'") + page_info.image = self.get_image( + in_page=page_info._mkdocs_page_ref, base_url=base_url + ) + processed_refs.add(id(page_info._mkdocs_page_ref)) + + def get_image( + self, in_page: MkdocsPageSubset, base_url: str + ) -> Optional[tuple[str, str, int]]: """Get page's image from page meta or social cards and returns properties. Args: - in_page (Page): page to parse - base_url (str): website URL to resolve absolute URLs for images referenced + in_page: page to parse + base_url: website URL to resolve absolute URLs for images referenced with local path. Returns: - Optional[Tuple[str, str, int]]: (image url, mime type, image length) or None if - there is no image set + (image url, mime type, image length) or None if there is no image set """ if in_page.meta.get("image"): img_url = in_page.meta.get("image").strip() logger.debug( f"Image found ({img_url}) in page.meta.image for page: " - f"{in_page.file.src_uri}" + f"{in_page.src_uri}" ) elif in_page.meta.get("illustration"): img_url = in_page.meta.get("illustration").strip() logger.debug( f"Image found ({img_url}) in page.meta.illustration for page: " - f"{in_page.file.src_uri}" + f"{in_page.src_uri}" ) elif ( isinstance(self.social_cards, IntegrationMaterialSocialCards) @@ -622,7 +649,7 @@ def get_image(self, in_page: Page, base_url: str) -> Optional[tuple[str, str, in # if path, resolve absolute url if not img_url.startswith("http"): img_length = self.get_local_image_length( - page_path=in_page.file.abs_src_path, path_to_append=img_url + page_path=in_page.abs_src_path, path_to_append=img_url ) img_url = self.build_url(base_url=base_url, path=img_url) else: @@ -797,75 +824,57 @@ def guess_locale(self, mkdocs_config: MkDocsConfig) -> Optional[str]: return None @staticmethod - def filter_pages(pages: list[PageInformation], attribute: str, length: int) -> list: - """Filter and return pages into a friendly RSS structure. + def filter_pages( + pages: list[PageInformation], + filter_attribute: Literal["created", "updated"], + length: int, + ) -> list[PageInformation]: + """Filter pages based on an attribute and a max number of items. Args: - pages (list): pages to filter - attribute (str): page attribute as filter variable - length (int): max number of pages to return + pages: pages to filter + filter_attribute: page attribute to use as filter variable + length: max number of pages to return Returns: - list: list of filtered pages + list of filtered pages """ - filtered_pages = [] - for page in sorted( - pages, key=lambda page: getattr(page, attribute), reverse=True - )[:length]: - pub_date: datetime = getattr(page, attribute) - filtered_pages.append( - { - "authors": page.authors, - "categories": page.categories, - "comments_url": page.url_comments, - "description": page.description, - "guid": page.guid, - "image": page.image, - "link": page.url_full, - "pubDate": format_datetime(dt=pub_date), - "pubDate3339": pub_date.isoformat("T"), - "title": page.title, - } - ) - - return filtered_pages + return sorted( + pages, key=lambda page: getattr(page, filter_attribute), reverse=True + )[:length] @staticmethod - def feed_to_json(feed: dict, *, updated: bool = False) -> dict: + def feed_to_json(feed: RssFeedBase) -> dict: """Format internal feed representation as a JSON Feed compliant dict. Args: feed (dict): internal feed structure, i. e. GitRssPlugin.feed_created or feed_updated value - updated (bool, optional): True if this is a feed_updated. Defaults to False. Returns: dict: dict that can be passed to json.dump """ - entry_date_key = "date_modified" if updated else "date_published" - return { - "version": "https://jsonfeed.org/version/1", - "title": feed.get("title"), - "home_page_url": feed.get("html_url"), - "feed_url": feed.get("json_url"), - "description": feed.get("description"), - "icon": feed.get("logo_url"), - "authors": ( - [{"name": feed.get("author")}] if feed.get("author") is not None else [] - ), - "language": str(feed.get("language")), + "version": "https://jsonfeed.org/version/1.1", + "title": feed.title, + "home_page_url": feed.html_url, + "feed_url": feed.json_url, + "description": feed.description, + "icon": feed.logo_url, + "authors": ([{"name": feed.author}] if feed.author is not None else []), + "language": str(feed.language), "items": [ { - "id": item.get("guid"), - "url": item.get("link"), - "title": item.get("title"), - "content_html": item.get("description"), - "image": (item.get("image") or (None,))[0], - entry_date_key: item.get("pubDate3339"), - "authors": [{"name": name} for name in (item.get("authors") or ())], - "tags": item.get("categories"), + "id": item.guid, + "url": item.link, + "title": item.title, + "content_html": item.description, + "image": (item.image or (None,))[0], + "date_modified": item.updated.isoformat("T"), + "date_published": item.created.isoformat("T"), + "authors": [{"name": name} for name in (item.authors or ())], + "tags": item.categories, } - for item in feed.get("entries", ()) + for item in feed.entries ], } From 07b0a6ae19423eb3eea8e02ec302cb411e33784b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 18:00:39 +0000 Subject: [PATCH 091/158] build(deps): bump actions/upload-artifact from 4 to 5 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 46c5356d..7ce365d0 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -75,7 +75,7 @@ jobs: run: mkdocs build --verbose - name: Save build doc as artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: documentation path: site/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2a3f007..46f98da8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,7 +44,7 @@ jobs: --outdir dist/ . - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: python_wheel path: dist/* From efe9818928d515168dc3b60e400b7fd5959a23f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Nov 2025 04:56:26 +0000 Subject: [PATCH 092/158] build(deps): update mkdocs-git-revision-date-localized-plugin requirement Updates the requirements on [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin) to permit the latest version. - [Release notes](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/releases) - [Commits](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/compare/v1.3.0...v1.5.0) --- updated-dependencies: - dependency-name: mkdocs-git-revision-date-localized-plugin dependency-version: 1.5.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/documentation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/documentation.txt b/requirements/documentation.txt index 7510316e..ee671c74 100644 --- a/requirements/documentation.txt +++ b/requirements/documentation.txt @@ -2,7 +2,7 @@ # ----------------------- mkdocs-git-committers-plugin-2>=2.4.1,<2.6 -mkdocs-git-revision-date-localized-plugin>=1.3,<1.5 +mkdocs-git-revision-date-localized-plugin>=1.3,<1.6 mkdocs-material[imaging]>=9.5.47,<10 mkdocs-minify-plugin>=0.8,<0.9 mkdocstrings-python>=1.16.2,<1.19 From 823cb9c238fc12a1d2023ec6785cdb8216881db4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Sun, 2 Nov 2025 17:19:02 +0100 Subject: [PATCH 093/158] update(packaging): remove Python 3.9 support (EOL) and add 3.14 --- .github/workflows/lint-and-tests.yml | 2 +- .pre-commit-config.yaml | 6 +++--- docs/configuration.md | 4 +--- requirements/base.txt | 2 +- setup.py | 7 +++---- tests/fixtures/test-build-min-python.dockerfile | 2 +- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 139407a0..5250652e 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -22,11 +22,11 @@ jobs: fail-fast: false matrix: python-version: - - "3.9" - "3.10" - "3.11" - "3.12" - "3.13" + - "3.14" # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b8ebb631..0e3d5c07 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: hooks: - id: pyupgrade args: - - "--py39-plus" + - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.13.3" @@ -40,7 +40,7 @@ repos: - id: ruff args: - --fix-only - - --target-version=py39 + - --target-version=py310 - repo: https://github.com/pycqa/isort rev: 6.1.0 @@ -56,7 +56,7 @@ repos: hooks: - id: black args: - - --target-version=py39 + - --target-version=py310 - repo: https://github.com/pycqa/flake8 rev: 7.3.0 diff --git a/docs/configuration.md b/docs/configuration.md index 01552338..63a07913 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -399,9 +399,7 @@ At the end, into the RSS you will get: ``` !!! note "Timezone dependencies" - The timezones data depends on the Python version used to build: - - for Python >= 3.9, it uses the standard library and ships [tzdata](https://pypi.org/project/tzdata/) only on Windows which do not provide such data - - for Python < 3.9, [pytz](https://pypi.org/project/pytz/) is shipped. + The timezones data relies on the standard library and ships [tzdata](https://pypi.org/project/tzdata/) only on Windows which do not provide such data. ---- diff --git a/requirements/base.txt b/requirements/base.txt index af8bcd7d..6b57af11 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,4 +5,4 @@ cachecontrol[filecache] >=0.14,<1 GitPython>=3.1.43,<3.2 mkdocs>=1.6.1,<2 requests>=2.31,<3 -tzdata==2024.* ; python_version >= "3.9" and sys_platform == "win32" +tzdata==2024.* ; sys_platform == "win32" diff --git a/setup.py b/setup.py index 87ff97df..6e921712 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,6 @@ # standard library from pathlib import Path -from typing import Union # 3rd party from setuptools import find_packages, setup @@ -26,7 +25,7 @@ # ################################## -def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: +def load_requirements(requirements_files: Path | list[Path]) -> list: """Helper to load requirements list from a path or a list of paths. Args: @@ -79,7 +78,7 @@ def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: # run entry_points={"mkdocs.plugins": ["rss = mkdocs_rss_plugin.plugin:GitRssPlugin"]}, # dependencies - python_requires=">=3.9, <4", + python_requires=">=3.10, <4", extras_require={ # tooling "dev": load_requirements(HERE / "requirements/development.txt"), @@ -93,11 +92,11 @@ def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", diff --git a/tests/fixtures/test-build-min-python.dockerfile b/tests/fixtures/test-build-min-python.dockerfile index bc87b0a3..7e4a5064 100644 --- a/tests/fixtures/test-build-min-python.dockerfile +++ b/tests/fixtures/test-build-min-python.dockerfile @@ -1,5 +1,5 @@ # Reference: https://squidfunk.github.io/mkdocs-material/getting-started/#with-docker -FROM python:3.8.19 +FROM python:3.10.19 COPY . . From 0f7830bff6a2599bd00e8f675ab784808d51b953 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Sun, 2 Nov 2025 17:20:04 +0100 Subject: [PATCH 094/158] update(chore): run pyupgrade with Python 3.10 as minimal version --- .../integrations/theme_material_base.py | 9 +++------ .../integrations/theme_material_blog_plugin.py | 5 +---- .../integrations/theme_material_social_plugin.py | 15 +++++++-------- mkdocs_rss_plugin/plugin.py | 4 ++-- mkdocs_rss_plugin/util.py | 4 ++-- 5 files changed, 15 insertions(+), 22 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py index 77474129..fe92b9dd 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_base.py +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -4,9 +4,6 @@ # ########## Libraries ############# # ################################## -# standard library -from typing import Optional - # 3rd party from mkdocs.config.defaults import MkDocsConfig from mkdocs.plugins import get_plugin_logger @@ -36,7 +33,7 @@ class IntegrationMaterialThemeBase: # attributes IS_THEME_MATERIAL: bool = False - IS_INSIDERS: Optional[bool] = False + IS_INSIDERS: bool | None = False def __init__(self, mkdocs_config: MkDocsConfig) -> None: """Integration instantiation. @@ -51,7 +48,7 @@ def __init__(self, mkdocs_config: MkDocsConfig) -> None: self.IS_INSIDERS = self.is_mkdocs_theme_material_insiders() def is_mkdocs_theme_material( - self, mkdocs_config: Optional[MkDocsConfig] = None + self, mkdocs_config: MkDocsConfig | None = None ) -> bool: """Check if the theme set in mkdocs.yml is material or not. @@ -67,7 +64,7 @@ def is_mkdocs_theme_material( self.IS_THEME_MATERIAL = mkdocs_config.theme.name == "material" return self.IS_THEME_MATERIAL - def is_mkdocs_theme_material_insiders(self) -> Optional[bool]: + def is_mkdocs_theme_material_insiders(self) -> bool | None: """Check if the material theme is community or insiders edition. Returns: diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 4ac97263..f329bdbb 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -7,7 +7,6 @@ # standard library from functools import lru_cache from pathlib import Path -from typing import Optional # 3rd party from mkdocs.config.defaults import MkDocsConfig @@ -69,9 +68,7 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No "disabled in plugin's option in Mkdocs configuration." ) - def is_blog_plugin_enabled_mkdocs( - self, mkdocs_config: Optional[MkDocsConfig] - ) -> bool: + def is_blog_plugin_enabled_mkdocs(self, mkdocs_config: MkDocsConfig | None) -> bool: """Check if blog plugin is installed and enabled. Args: diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 23a6f831..2ec5d361 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -8,7 +8,6 @@ import json from hashlib import md5 from pathlib import Path -from typing import Optional # 3rd party from mkdocs.config.defaults import MkDocsConfig @@ -48,7 +47,7 @@ class IntegrationMaterialSocialCards(IntegrationMaterialThemeBase): IS_ENABLED: bool = True IS_SOCIAL_PLUGIN_ENABLED: bool = True IS_SOCIAL_PLUGIN_CARDS_ENABLED: bool = True - CARDS_MANIFEST: Optional[dict] = None + CARDS_MANIFEST: dict | None = None def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> None: """Integration instantiation. @@ -107,7 +106,7 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No self.site_description = mkdocs_config.site_description or "" def is_social_plugin_enabled_mkdocs( - self, mkdocs_config: Optional[MkDocsConfig] = None + self, mkdocs_config: MkDocsConfig | None = None ) -> bool: """Check if social plugin is installed and enabled. @@ -184,7 +183,7 @@ def is_social_plugin_enabled_page( "cards", fallback_value ) - def load_cache_cards_manifest(self) -> Optional[dict]: + def load_cache_cards_manifest(self) -> dict | None: """Load social cards manifest if the file exists. Returns: @@ -262,8 +261,8 @@ def get_social_cards_cache_dir(self, mkdocs_config: MkDocsConfig) -> Path: return self.social_cards_cache_dir def get_social_card_build_path_for_page( - self, mkdocs_page: MkdocsPageSubset, mkdocs_site_dir: Optional[str] = None - ) -> Optional[Path]: + self, mkdocs_page: MkdocsPageSubset, mkdocs_site_dir: str | None = None + ) -> Path | None: """Get social card path in Mkdocs build dir for a specific page. Args: @@ -305,7 +304,7 @@ def get_social_card_build_path_for_page( def get_social_card_cache_path_for_page( self, mkdocs_page: MkdocsPageSubset - ) -> Optional[Path]: + ) -> Path | None: """Get social card path in social plugin cache folder for a specific page. Note: @@ -377,7 +376,7 @@ def get_social_card_cache_path_for_page( def get_social_card_url_for_page( self, mkdocs_page: MkdocsPageSubset, - mkdocs_site_url: Optional[str] = None, + mkdocs_site_url: str | None = None, ) -> str: """Get social card URL for a specific page in documentation. diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index bfe05aff..8383b805 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -12,7 +12,7 @@ from email.utils import format_datetime, formatdate from pathlib import Path from re import compile as re_compile -from typing import Literal, Optional +from typing import Literal # 3rd party from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -265,7 +265,7 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: @event_priority(priority=-75) def on_page_content( self, html: str, page: Page, config: MkDocsConfig, files: Files - ) -> Optional[str]: + ) -> str | None: """The page_content event is called after the Markdown text is rendered to HTML (but before being passed to a template) and can be used to alter the HTML body of the page. diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index afe00791..f7afdbb2 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -11,7 +11,7 @@ from functools import lru_cache from mimetypes import guess_type from pathlib import Path -from typing import Any, Literal, Union +from typing import Any, Literal from urllib.parse import urlencode, urlparse, urlunparse # 3rd party @@ -172,7 +172,7 @@ def build_url( url_parts[4] = urlencode(args_dict) return urlunparse(url_parts) - def get_value_from_dot_key(self, data: dict, dot_key: Union[str, bool]) -> Any: + def get_value_from_dot_key(self, data: dict, dot_key: str | bool) -> Any: """Retrieves a value from a dictionary using a dot notation key. Args: From 08a6f61f7cfe3fde631d5d7400785c115ec2a28c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:21:10 +0000 Subject: [PATCH 095/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.20.0 → v3.21.0](https://github.com/asottile/pyupgrade/compare/v3.20.0...v3.21.0) - [github.com/astral-sh/ruff-pre-commit: v0.13.3 → v0.14.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.3...v0.14.3) - [github.com/pycqa/isort: 6.1.0 → 7.0.0](https://github.com/pycqa/isort/compare/6.1.0...7.0.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e3d5c07..75d2c6c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,14 +28,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.0 hooks: - id: pyupgrade args: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.13.3" + rev: "v0.14.3" hooks: - id: ruff args: @@ -43,7 +43,7 @@ repos: - --target-version=py310 - repo: https://github.com/pycqa/isort - rev: 6.1.0 + rev: 7.0.0 hooks: - id: isort args: From 82b4b28328a7f162acadbeee915c3c622fdbac19 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 10:28:39 +0100 Subject: [PATCH 096/158] update(chore): switch from setup.* to pyproject.toml --- .github/labeler.yml | 6 +- .github/workflows/docker-test.yml | 6 +- .github/workflows/documentation.yml | 18 +- .github/workflows/lint-and-tests.yml | 16 +- .github/workflows/release.yml | 6 +- .gitignore | 1 + .pre-commit-config.yaml | 6 +- README.md | 24 ++- docs/contributing.md | 73 ++++--- mkdocs_rss_plugin/__about__.py | 42 +++-- pyproject.toml | 178 ++++++++++++++++++ requirements.txt | 3 - requirements/base.txt | 8 - requirements/development.txt | 11 -- requirements/documentation.txt | 9 - requirements/testing.txt | 10 - setup.cfg | 79 -------- setup.py | 107 ----------- .../fixtures/test-build-min-python.dockerfile | 3 +- 19 files changed, 301 insertions(+), 305 deletions(-) create mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100644 requirements/base.txt delete mode 100644 requirements/development.txt delete mode 100644 requirements/documentation.txt delete mode 100644 requirements/testing.txt delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/labeler.yml b/.github/labeler.yml index b13a9b8d..8dafa72a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -13,15 +13,13 @@ ci-cd: dependencies: - changed-files: - any-glob-to-any-file: - - requirements/*.txt - - requirements.txt + - pyproject.toml documentation: - changed-files: - any-glob-to-any-file: - "*.md" - docs/** - - requirements/documentation.txt - head-branch: - ^docs - documentation @@ -37,7 +35,6 @@ packaging: - changed-files: - any-glob-to-any-file: - MANIFEST.in - - setup.py - head-branch: - ^packaging - packaging @@ -52,7 +49,6 @@ tooling: - any-glob-to-any-file: - ".*" - codecov.yml - - setup.cfg - .vscode/**/* - head-branch: - ^tooling diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index e6d8d1b9..f1e4242d 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -4,11 +4,13 @@ name: "🐳 Docker Builder" # events but only for the master branch on: pull_request: - branches: [main] + branches: + - main paths-ignore: - "docs/**" push: - branches: [main] + branches: + - main paths-ignore: - "docs/**" diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 7ce365d0..1b82edd4 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -12,7 +12,7 @@ on: - "*.md" - ".github/workflows/documentation.yml" - ./mkdocs_rss_plugin - - requirements/documentation.txt + - pyproject.toml tags: - "*" @@ -22,19 +22,19 @@ on: paths: - .github/workflows/documentation.yml - docs/ - - requirements/documentation.txt + - pyproject.toml workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read - pages: write id-token: write + pages: write # Allow one concurrent deployment concurrency: - group: "pages" + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true # A workflow run is made up of one or more jobs that can run sequentially or in parallel @@ -56,13 +56,13 @@ jobs: with: python-version: "3.11" cache: "pip" - cache-dependency-path: "requirements/documentation.txt" + cache-dependency-path: pyproject.toml - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade -r requirements.txt - python -m pip install --upgrade -r requirements/documentation.txt + run: python -m pip install --upgrade pip setuptools wheel + + - name: Install project as a package + run: python -m pip install .[docs] - name: Build static website env: diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 5250652e..7ccb2ff0 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -38,14 +38,13 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: "pip" - cache-dependency-path: "requirements/*.txt" + cache-dependency-path: pyproject.toml - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade -r requirements.txt - python -m pip install --upgrade -r requirements/development.txt - python -m pip install --upgrade -r requirements/testing.txt + - name: Upgrade installation dependencies + run: python -m pip install --upgrade pip setuptools wheel + + - name: Install project as a package + run: python -m pip install .[test] - name: Lint with flake8 run: | @@ -54,9 +53,6 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Install project - run: python -m pip install -e . - - name: Run Unit tests run: python -m pytest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 46f98da8..5857f924 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,8 +16,8 @@ jobs: url: https://pypi.org/project/mkdocs-rss-plugin/ permissions: contents: write - id-token: write # IMPORTANT: this permission is mandatory for trusted publishing discussions: write + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: - uses: actions/checkout@v5 @@ -25,9 +25,9 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.x" + python-version: "3.13" cache: "pip" - cache-dependency-path: "requirements/base.txt" + cache-dependency-path: pyproject.toml - name: Install dependencies run: | diff --git a/.gitignore b/.gitignore index f1947752..1fc11861 100644 --- a/.gitignore +++ b/.gitignore @@ -216,5 +216,6 @@ dmypy.json # ################################ **/*.xml +mkdocs_rss_plugin/_version.py site/ tests/fixtures/docs/temp_page_not_in_git_log.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 75d2c6c1..f8235feb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,9 @@ repos: - id: detect-private-key - id: end-of-file-fixer - id: fix-byte-order-marker + - id: name-tests-test + args: + - --pytest-test-first - id: trailing-whitespace args: - --markdown-linebreak-ext=md @@ -37,7 +40,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.14.3" hooks: - - id: ruff + - id: ruff-check args: - --fix-only - --target-version=py310 @@ -66,7 +69,6 @@ repos: - flake8-docstrings<2 language: python args: - - --config=setup.cfg - --select=E9,F63,F7,F82 - --docstring-convention=google diff --git a/README.md b/README.md index 75089dc9..b789a47e 100644 --- a/README.md +++ b/README.md @@ -84,16 +84,24 @@ Following initiative from the author of Material for MkDocs, this plugin provide ## Development -Clone the repository: +Once you cloned the repository: ```sh -# install development dependencies -python -m pip install -U -r requirements/development.txt -# alternatively: pip install -e .[dev] - # install project as editable python -m pip install -e . +# including development dependencies +python -m pip install -e .[dev] + +# including documentation dependencies +python -m pip install -e .[docs] + +# including testing dependencies +python -m pip install -e .[test] + +# all inclusive +python -m pip install -e .[dev,docs,test] + # install git hooks pre-commit install ``` @@ -104,8 +112,7 @@ Then follow the [contribution guidelines](CONTRIBUTING.md). ```sh # install development dependencies -python -m pip install -U -r requirements/testing.txt -# alternatively: pip install -e .[test] +python -m pip install -e .[test] # run tests pytest @@ -115,8 +122,7 @@ pytest ```sh # install dependencies for documentation -python -m pip install -U -r requirements/documentation.txt -# alternatively: pip install -e .[doc] +python -m pip install -e .[docs] # build the documentation mkdocs build diff --git a/docs/contributing.md b/docs/contributing.md index 32121529..347a63d5 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -12,16 +12,24 @@ These are mostly guidelines, not rules. Use your best judgment, and feel free to ## Development -Clone the repository: +Once you cloned the repository: ```sh -# install development dependencies -python -m pip install -U -r requirements/development.txt -# alternatively: pip install -e .[dev] - # install project as editable python -m pip install -e . +# including development dependencies +python -m pip install -e .[dev] + +# including documentation dependencies +python -m pip install -e .[docs] + +# including testing dependencies +python -m pip install -e .[test] + +# all inclusive +python -m pip install -e .[dev,docs,test] + # install git hooks pre-commit install ``` @@ -32,8 +40,7 @@ Then follow the [contribution guidelines](#guidelines). ```sh # install development dependencies -python -m pip install -U -r requirements/testing.txt -# alternatively: pip install -e .[test] +python -m pip install -e .[test] # run tests pytest @@ -43,8 +50,7 @@ pytest ```sh # install dependencies for documentation -python -m pip install -U -r requirements/documentation.txt -# alternatively: pip install -e .[doc] +python -m pip install -e .[docs] # build the documentation mkdocs build @@ -90,10 +96,15 @@ Feel free to use the IDE you love. Here come configurations for some popular IDE ```jsonc { - // Editor - "files.associations": { - "./requirements/*.txt": "pip-requirements" + // JSON + "[json]": { + "editor.bracketPairColorization.enabled": true, + "editor.defaultFormatter": "vscode.json-language-features", + "editor.formatOnSave": true, + "editor.guides.bracketPairs": "active" }, + "json.format.enable": true, + "json.schemaDownload.enable": true, // Markdown "markdown.updateLinksOnFileMove.enabled": "prompt", "markdown.updateLinksOnFileMove.enableForDirectories": true, @@ -104,9 +115,16 @@ Feel free to use the IDE you love. Here come configurations for some popular IDE "editor.bracketPairColorization.enabled": true, "editor.formatOnSave": true, "editor.guides.bracketPairs": "active", - "files.trimTrailingWhitespace": false, + "files.trimTrailingWhitespace": false }, // Python + "python.analysis.autoFormatStrings": true, + "python.analysis.autoImportCompletions": true, + "python.analysis.typeCheckingMode": "basic", + "python.terminal.activateEnvInCurrentTerminal": true, + "python.terminal.activateEnvironment": true, + "python.testing.unittestEnabled": true, + "python.testing.pytestEnabled": true, "[python]": { "editor.codeActionsOnSave": { "source.organizeImports": "explicit" @@ -119,9 +137,24 @@ Feel free to use the IDE you love. Here come configurations for some popular IDE ], "editor.wordWrapColumn": 88, }, - // Extensions + // YAML + "[yaml]": { + "editor.autoIndent": "keep", + "editor.formatOnSave": true, + "editor.insertSpaces": true, + "editor.tabSize": 2, + "diffEditor.ignoreTrimWhitespace": false, + "editor.quickSuggestions": { + "other": true, + "comments": false, + "strings": true + } + }, + // extensions + "autoDocstring.guessTypes": true, + "autoDocstring.docstringFormat": "google-notypes", + "autoDocstring.generateDocstringOnEnter": false, "flake8.args": [ - "--config=setup.cfg", "--verbose" ], "isort.args": [ @@ -129,15 +162,13 @@ Feel free to use the IDE you love. Here come configurations for some popular IDE "black" ], "isort.check": true, - "autoDocstring.guessTypes": true, - "autoDocstring.docstringFormat": "google", - "autoDocstring.generateDocstringOnEnter": false, "yaml.customTags": [ "!ENV scalar", "!ENV sequence", - "tag:yaml.org,2002:python/name:materialx.emoji.to_svg", - "tag:yaml.org,2002:python/name:materialx.emoji.twemoji", + "!relative scalar", + "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", + "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" - ], + ] } ``` diff --git a/mkdocs_rss_plugin/__about__.py b/mkdocs_rss_plugin/__about__.py index 30af9ef3..30b2b286 100644 --- a/mkdocs_rss_plugin/__about__.py +++ b/mkdocs_rss_plugin/__about__.py @@ -12,27 +12,25 @@ # standard library from datetime import date +from importlib import metadata + +_pkg_metadata = metadata.metadata("mkdocs-rss-plugin") or {} + +try: + from ._version import version as __version__ +except ImportError: + __version__ = _pkg_metadata.get("Version", "0.0.0-dev0") + # ############################################################################ # ########## Globals ############# # ################################ -__all__ = [ - "__author__", - "__copyright__", - "__email__", - "__license__", - "__summary__", - "__title__", - "__title_clean__", - "__uri__", - "__version__", - "__version_info__", -] -__author__ = "Julien Moura" + +__author__: str = _pkg_metadata.get("Author-email", "Julien Moura (In Geo Veritas)") __copyright__ = f"2020 - {date.today().year}, {__author__}" __email__ = "dev@ingeoveritas.com" -__license__ = "MIT" +__license__: str = _pkg_metadata.get("License-Expression", "MIT") __summary__ = ( "MkDocs plugin which generates a static RSS feed using git log and page.meta." ) @@ -40,10 +38,24 @@ __title_clean__ = "".join(e for e in __title__ if e.isalnum()) __uri__ = "https://github.com/Guts/mkdocs-rss-plugin/" -__version__ = "1.17.4" +__version_clean__: str = __version__.split(".dev")[0].split("+")[0] __version_info__ = tuple( [ int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split(".") ] ) + + +__all__ = [ + "__author__", + "__copyright__", + "__email__", + "__license__", + "__summary__", + "__title__", + "__title_clean__", + "__uri__", + "__version__", + "__version_info__", +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e1c610fc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,178 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = ["setuptools>=64", "setuptools-scm>=8"] + +[project] +name = "mkdocs-rss-plugin" +description = "MkDocs plugin to generate RSS and JSON feeds using Mkdocs site configuration, git log and Mkdocs pages'meta." +dynamic = ["version"] +readme = "README.md" +license = "MIT" +license-files = ["LICENSE"] +requires-python = ">=3.10" +authors = [{ name = "Julien Moura", email = "dev@ingeoveritas.com" }] +maintainers = [{ name = "Julien Moura", email = "dev@ingeoveritas.com" }] +keywords = [ + "atom", + "documentation", + "feed", + "git", + "json-feed", + "mkdocs", + "plugin", + "rss", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Documentation", + "Topic :: Software Development :: Documentation", + "Topic :: Text Processing :: Markup :: Markdown", +] + +dependencies = [ + "CacheControl[filecache]>=0.14.3,<1", + "GitPython>=3.1.45,<3.2", + "mkdocs>=1.6.1,<2", + "requests>=2.32.5,<3", + "tzdata==2024.* ; sys_platform == 'win32'", +] + +[project.optional-dependencies] +dev = [ + "black>=25.9", + "flake8>=7.1", + "flake8-bugbear>=24.10", + "flake8-builtins>=2.5", + "flake8-eradicate>=1.5", + "flake8-isort>=6.1.1", + "Flake8-pyproject>=1.2.3", + "pre-commit>=4,<5", +] +docs = [ + "mkdocs-git-committers-plugin-2>=2.4.1,<2.6", + "mkdocs-git-revision-date-localized-plugin>=1.3,<1.6", + "mkdocs-material[imaging]>=9.5.47,<10", + "mkdocs-minify-plugin>=0.8,<0.9", + "mkdocstrings-python>=1.16.2,<1.19", + "termynal>=0.12.2,<0.14", +] +test = [ + "feedparser>=6.0.12,<6.1", + "jsonfeed-util>=1.2,<2", + "mkdocs-material[imaging]>=9.6.23", + "pytest-cov>=6.9.1,<8", + "validator-collection>=1.5,<1.6", +] + +[project.entry-points."mkdocs.plugins"] +rss = "mkdocs_rss_plugin.plugin:GitRssPlugin" + +[project.urls] +Changelog = "https://github.com/guts/mkdocs-rss-plugin/blob/main/CHANGELOG.md" +Documentation = "https://guts.github.io/mkdocs-rss-plugin/" +Homepage = "https://guts.github.io/mkdocs-rss-plugin/" +Issues = "https://github.com/guts/mkdocs-rss-plugin/issues/" +releasenotes = "https://github.com/guts/mkdocs-rss-plugin/releases/latest" +Repository = "https://github.com/guts/mkdocs-rss-plugin/" + + +# -- TOOLING CONFIGURATION -- + +# Black configuration +[tool.black] +target-version = ["py310", "py311", "py312", "py313", "py314"] + +# Coverage configuration +[tool.coverage.report] +exclude_also = [ + # Don't complain about abstract methods, they aren't run: + "@(abc\\.)?abstractmethod", + "class .*\\bProtocol\\):", + # Don't complain about missing debug-only code: + "def __repr__", + "if self.debug:", + # Don't complain if non-runnable code isn't run: + "if 0:", + "if __name__ == .__main__.:", + # Don't complain about imports for type checking: + "if TYPE_CHECKING:", + # Don't complain if tests don't hit defensive assertion code: + "raise AssertionError", + "raise NotImplementedError", + # ignore lines marked with a pragma + "pragma: no cover", +] +ignore_errors = true +show_missing = true + +[tool.coverage.run] +branch = true +omit = ["*/tests/*", "*/__pycache__/*", "*/.venv/*", "*/_version.py"] + +[tool.flake8] +count = true +exclude = [ + ".git", + "__pycache__", + "docs/conf.py", + "old", + "build", + "dist", + ".venv*", + "tests", +] +ignore = ["E121", "E123", "E126", "E203", "E226", "E24", "E704", "W503", "W504"] +max-complexity = 15 +max-doc-length = 130 +max-line-length = 100 +statistics = true +tee = true + +[tool.isort] +profile = "black" +ensure_newline_before_comments = true +force_grid_wrap = 0 +include_trailing_comma = true +line_length = 88 +multi_line_output = 3 +use_parentheses = true + +# Pytest configuration +[tool.pytest.ini_options] +addopts = [ + "--junitxml=junit/test-results.xml", + "--cov=mkdocs_rss_plugin", + "--cov-config=pyproject.toml", + "--cov-report=html", + "--cov-report=term", + "--cov-report=xml", + "--ignore=tests/_wip/", +] +junit_family = "xunit2" +minversion = "7.0" +norecursedirs = ".* build dev development dist docs CVS fixtures _darcs {arch} *.egg venv _wip" +python_files = ["test_*.py"] +testpaths = ["tests"] + +# Setuptools configuration +[tool.setuptools] +packages = ["mkdocs_rss_plugin"] + +[tool.setuptools.package-data] +mkdocs_rss_plugin = ["templates/*.jinja2", "templates/**/*.jinja2"] + +# setuptools-scm configuration +[tool.setuptools_scm] +fallback_version = "0.0.0+unknown" +local_scheme = "no-local-version" +version_scheme = "guess-next-dev" +write_to = "mkdocs_rss_plugin/_version.py" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 75766a0b..00000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ --r requirements/base.txt - --e "." diff --git a/requirements/base.txt b/requirements/base.txt deleted file mode 100644 index 6b57af11..00000000 --- a/requirements/base.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Common requirements -# ----------------------- - -cachecontrol[filecache] >=0.14,<1 -GitPython>=3.1.43,<3.2 -mkdocs>=1.6.1,<2 -requests>=2.31,<3 -tzdata==2024.* ; sys_platform == "win32" diff --git a/requirements/development.txt b/requirements/development.txt deleted file mode 100644 index f50d1948..00000000 --- a/requirements/development.txt +++ /dev/null @@ -1,11 +0,0 @@ --r base.txt - -# Development -# ----------------------- -black -flake8>=7.1,<8 -flake8-bugbear>=24.10 -flake8-builtins>=2.5 -flake8-eradicate>=1.5 -flake8-isort>=6.1.1 -pre-commit>=3.7,<5 diff --git a/requirements/documentation.txt b/requirements/documentation.txt deleted file mode 100644 index ee671c74..00000000 --- a/requirements/documentation.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Documentation -# ----------------------- - -mkdocs-git-committers-plugin-2>=2.4.1,<2.6 -mkdocs-git-revision-date-localized-plugin>=1.3,<1.6 -mkdocs-material[imaging]>=9.5.47,<10 -mkdocs-minify-plugin>=0.8,<0.9 -mkdocstrings-python>=1.16.2,<1.19 -termynal>=0.12.2,<0.14 diff --git a/requirements/testing.txt b/requirements/testing.txt deleted file mode 100644 index 53dcd67a..00000000 --- a/requirements/testing.txt +++ /dev/null @@ -1,10 +0,0 @@ --r base.txt - -# Testing -# ------- - -feedparser>=6.0.11,<6.1 -jsonfeed-util>=1.2,<2 -mkdocs-material[imaging]>=9.5.47 -pytest-cov>=6,<8 -validator-collection>=1.5,<1.6 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b2f1294a..00000000 --- a/setup.cfg +++ /dev/null @@ -1,79 +0,0 @@ -# -- Packaging -------------------------------------- -[bdist_wheel] -universal = 1 - -[metadata] -description-file = README.md - -# -- Code quality ------------------------------------ -[flake8] -count = True -docstring-convention = google -exclude = - # No need to traverse our git directory - .git, - # There's no value in checking cache directories - __pycache__, - # The conf file is mostly autogenerated, ignore it - docs/conf.py, - # The old directory contains Flake8 2.0 - old, - # This contains our built documentation - build, - # This contains builds of flake8 that we don't want to check - dist, - # This contains local virtual environments - .venv*, - # do not watch on tests - tests -ignore = E121,E123,E126,E203,E226,E24,E704,W503,W504 -max-complexity = 15 -max-doc-length = 130 -max-line-length = 100 -statistics = True -tee = True - -[isort] -ensure_newline_before_comments = True -force_grid_wrap = 0 -include_trailing_comma = True -line_length = 88 -multi_line_output = 3 -profile = black -use_parentheses = True - -# -- Tests ---------------------------------------------- -[tool:pytest] -addopts = - --junitxml=junit/test-results.xml - --cov-config=setup.cfg - --cov=mkdocs_rss_plugin - --cov-report=html - --cov-report=term - --cov-report=xml - --ignore=tests/_wip/ -junit_family = xunit2 -minversion = 5.0 -norecursedirs = .* build dev development dist docs CVS fixtures _darcs {arch} *.egg venv _wip -python_files = test_*.py -testpaths = tests - -[coverage:run] -disable_warnings=include-ignored -branch = True -include = - mkdocs_rss_plugin/* -omit = - .venv/* - docs/* - *tests* - -[coverage:report] -exclude_lines = - if self.debug: - pragma: no cover - raise NotImplementedError - if __name__ == .__main__.: - -ignore_errors = True -show_missing = True diff --git a/setup.py b/setup.py deleted file mode 100644 index 6e921712..00000000 --- a/setup.py +++ /dev/null @@ -1,107 +0,0 @@ -#! python3 # noqa: E265 - -# ############################################################################ -# ########## Libraries ############# -# ################################## - -# standard library -from pathlib import Path - -# 3rd party -from setuptools import find_packages, setup - -# package (to get version) -from mkdocs_rss_plugin import __about__ - -# ############################################################################ -# ########## Globals ############# -# ################################ - -HERE = Path(__file__).parent -README = (HERE / "README.md").read_text() - -# ############################################################################ -# ########### Functions ############ -# ################################## - - -def load_requirements(requirements_files: Path | list[Path]) -> list: - """Helper to load requirements list from a path or a list of paths. - - Args: - requirements_files (Union[Path, List[Path]]): path or list to paths of - requirements file(s) - - Returns: - list: list of requirements loaded from file(s) - """ - out_requirements = [] - - if isinstance(requirements_files, Path): - requirements_files = [ - requirements_files, - ] - - for requirements_file in requirements_files: - with requirements_file.open(encoding="UTF-8") as f: - out_requirements += [ - line - for line in f.read().splitlines() - if not line.startswith(("#", "-")) and len(line) - ] - - return out_requirements - - -# ############################################################################ -# ########## Setup ############# -# ############################## -setup( - name="mkdocs-rss-plugin", - version=__about__.__version__, - author=__about__.__author__, - author_email=__about__.__email__, - description=__about__.__summary__, - license=__about__.__license__, - long_description=README, - long_description_content_type="text/markdown", - project_urls={ - "Docs": "https://guts.github.io/mkdocs-rss-plugin/", - "Bug Reports": f"{__about__.__uri__}issues/", - "Source": __about__.__uri__, - }, - # packaging - packages=find_packages( - exclude=["contrib", "docs", "*.tests", "*.tests.*", "tests.*", "tests"] - ), - include_package_data=True, - # run - entry_points={"mkdocs.plugins": ["rss = mkdocs_rss_plugin.plugin:GitRssPlugin"]}, - # dependencies - python_requires=">=3.10, <4", - extras_require={ - # tooling - "dev": load_requirements(HERE / "requirements/development.txt"), - "doc": load_requirements(HERE / "requirements/documentation.txt"), - "test": load_requirements(HERE / "requirements/testing.txt"), - }, - install_requires=load_requirements(HERE / "requirements/base.txt"), - # metadata - keywords="mkdocs rss git plugin", - classifiers=[ - "Intended Audience :: Developers", - "Intended Audience :: Information Technology", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: Implementation :: CPython", - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Topic :: Documentation", - "Topic :: Text Processing :: Markup :: Markdown", - ], -) diff --git a/tests/fixtures/test-build-min-python.dockerfile b/tests/fixtures/test-build-min-python.dockerfile index 7e4a5064..1107b648 100644 --- a/tests/fixtures/test-build-min-python.dockerfile +++ b/tests/fixtures/test-build-min-python.dockerfile @@ -4,7 +4,6 @@ FROM python:3.10.19 COPY . . RUN python3 -m pip install --no-cache-dir -U pip setuptools wheel \ - && python3 -m pip install --no-cache-dir -U -r requirements/documentation.txt \ - && python3 -m pip install --no-cache-dir . + && python3 -m pip install --no-cache-dir .[docs] RUN mkdocs build From 4176c946f5ed21e2c2d6ff39811d83989d00db1e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 10:28:55 +0100 Subject: [PATCH 097/158] update(tooling): add Python 3.14 to SonarCloud config --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 9b189759..a38b5a23 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.projectKey=Guts_mkdocs-rss-plugin # only=main # Python versions -sonar.python.version=3.9, 3.10, 3.11, 3.12, 3.13 +sonar.python.version=3.10, 3.11, 3.12, 3.13, 3.14 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. sonar.sources=mkdocs_rss_plugin From de6654248edb39598afe6b5626c32046f3c7789c Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 10:32:03 +0100 Subject: [PATCH 098/158] update(ci): remove flake8 run in GH Actions since it's already un on pre-commit.ci --- .github/workflows/lint-and-tests.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 7ccb2ff0..72685ddf 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -46,13 +46,6 @@ jobs: - name: Install project as a package run: python -m pip install .[test] - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Run Unit tests run: python -m pytest From e7b7e89c0d7c84886ba5069e6416e2bc7f44a88d Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 10:36:12 +0100 Subject: [PATCH 099/158] update(tooling): remove name-tests-test since it's not possible to exclude tests/base.py --- .pre-commit-config.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f8235feb..7f9b7571 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,9 +18,6 @@ repos: - id: detect-private-key - id: end-of-file-fixer - id: fix-byte-order-marker - - id: name-tests-test - args: - - --pytest-test-first - id: trailing-whitespace args: - --markdown-linebreak-ext=md From bf9ec9bf7ab020b5c01be73b1c611d87736ec550 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 10:43:28 +0100 Subject: [PATCH 100/158] update(security): set GH token permissions scopes in CI workflows --- .github/workflows/docker-test.yml | 5 +++++ .github/workflows/lint-and-tests.yml | 4 ++++ .github/workflows/pr-auto-labeler.yml | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index f1e4242d..af528078 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -14,6 +14,11 @@ on: paths-ignore: - "docs/**" +# Sets permissions of the GITHUB_TOKEN +permissions: + contents: read + + jobs: docker-build: runs-on: ubuntu-latest diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 72685ddf..66da5205 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -15,6 +15,10 @@ on: paths-ignore: - "docs/**" +# Sets permissions of the GITHUB_TOKEN +permissions: + contents: read + jobs: lintest: runs-on: ubuntu-latest diff --git a/.github/workflows/pr-auto-labeler.yml b/.github/workflows/pr-auto-labeler.yml index b2baed5e..61899f2c 100644 --- a/.github/workflows/pr-auto-labeler.yml +++ b/.github/workflows/pr-auto-labeler.yml @@ -2,6 +2,10 @@ name: "🏷 PR Labeler" on: - pull_request_target +permissions: + contents: read + pull-requests: write + jobs: triage: runs-on: ubuntu-latest From 32a7b9c78c848d65acfa19faf62bb553d7dba9e3 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 15:17:09 +0100 Subject: [PATCH 101/158] clean(ci): remove last ref to requirements --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5857f924..21336f1a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade -r requirements.txt python -m pip install --upgrade build - name: Build a binary wheel and a source tarball From ecf4a6250eec1bd1d85a3a2172ef535515ada61d Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 16:00:55 +0100 Subject: [PATCH 102/158] update(tooling): sanitize git log --- .mailmap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.mailmap b/.mailmap index 7f09a1de..c1a23db6 100644 --- a/.mailmap +++ b/.mailmap @@ -1,8 +1,14 @@ +Brian Madden +Brian Madden + Dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> <27856297+dependabot-preview[bot]@users.noreply.github.com> Julien M. Julien M. +Julien M. <1596222+Guts@users.noreply.github.com> + +Meysam Azad Y.D.X. <73375426+YDX-2147483647@users.noreply.github.com> Y.D.X. <73375426+YDX-2147483647@users.noreply.github.com> <73375426+YDX-2147483647@users.noreply.github.com> From 582f42264c7f16ac11451066ea0761bd436eb846 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 16:09:17 +0100 Subject: [PATCH 103/158] update(packaging): refine data files include mechanism --- pyproject.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e1c610fc..00f2552d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,10 +165,13 @@ testpaths = ["tests"] # Setuptools configuration [tool.setuptools] -packages = ["mkdocs_rss_plugin"] +include-package-data = true [tool.setuptools.package-data] -mkdocs_rss_plugin = ["templates/*.jinja2", "templates/**/*.jinja2"] +mkdocs_rss_plugin = ["templates/*.jinja2"] + +[tool.setuptools.packages.find] +where = ["mkdocs_rss_plugin"] # setuptools-scm configuration [tool.setuptools_scm] From cfdb5939759d538a157e19ad01db1dbe4bd8ff70 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 16:57:01 +0100 Subject: [PATCH 104/158] fix(packaging): refine setuptools package find --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 00f2552d..04d1f23b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -171,7 +171,9 @@ include-package-data = true mkdocs_rss_plugin = ["templates/*.jinja2"] [tool.setuptools.packages.find] -where = ["mkdocs_rss_plugin"] +include = ["mkdocs_rss_plugin"] +namespaces = false +where = ["."] # setuptools-scm configuration [tool.setuptools_scm] From 0fea1f9829093945e4f1b75850ad2c6e47e6bd6b Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 17:00:11 +0100 Subject: [PATCH 105/158] fix(packaging): rollback support for Python 3.14 --- .github/workflows/lint-and-tests.yml | 1 - pyproject.toml | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 66da5205..d617f943 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -30,7 +30,6 @@ jobs: - "3.11" - "3.12" - "3.13" - - "3.14" # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/pyproject.toml b/pyproject.toml index 04d1f23b..5c4d6e05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,6 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", "Topic :: Documentation", "Topic :: Software Development :: Documentation", "Topic :: Text Processing :: Markup :: Markdown", @@ -89,7 +88,7 @@ Repository = "https://github.com/guts/mkdocs-rss-plugin/" # Black configuration [tool.black] -target-version = ["py310", "py311", "py312", "py313", "py314"] +target-version = ["py310", "py311", "py312", "py313"] # Coverage configuration [tool.coverage.report] From ed9d8e8d4b9a953a3cb3933dcd37bfbcc12d05db Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 16:36:16 +0100 Subject: [PATCH 106/158] fix(xml): escape special chars from site_author () Closes #360 --- mkdocs_rss_plugin/templates/rss.xml.jinja2 | 2 +- .../mkdocs_site_author_to_be_escaped.yml | 49 +++++++++++++++++++ tests/test_build.py | 24 +++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/mkdocs_site_author_to_be_escaped.yml diff --git a/mkdocs_rss_plugin/templates/rss.xml.jinja2 b/mkdocs_rss_plugin/templates/rss.xml.jinja2 index 3448588a..65d97265 100644 --- a/mkdocs_rss_plugin/templates/rss.xml.jinja2 +++ b/mkdocs_rss_plugin/templates/rss.xml.jinja2 @@ -8,7 +8,7 @@ {% if feed.rss_url is not none %}{% endif %} {# Optional elements #} - {% if feed.author is not none %}{{ feed.author }}{% endif %} + {% if feed.author is not none %}{{ feed.author | e }}{% endif %} {% if feed.repo_url is not none %}{{ feed.repo_url }}{% endif %} {% if feed.language is not none %}{{ feed.language }}{% endif %} diff --git a/tests/fixtures/mkdocs_site_author_to_be_escaped.yml b/tests/fixtures/mkdocs_site_author_to_be_escaped.yml new file mode 100644 index 00000000..9e426f64 --- /dev/null +++ b/tests/fixtures/mkdocs_site_author_to_be_escaped.yml @@ -0,0 +1,49 @@ +# Project information +site_name: OpenSavvy Playground +site_author: OpenSavvy & contributors +site_description: Test for sanitization of #360 +site_url: https://example.com/ + +# Repository +repo_name: "guts/mkdocs-rss-plugin" +repo_url: "https://github.com/guts/mkdocs-rss-plugin/" +edit_uri: "blob/main/docs/" + +docs_dir: "docs/" +use_directory_urls: true + +plugins: + - rss: + date_from_meta: + as_creation: "date" + datetime_format: "%Y-%m-%d %H:%M" + default_timezone: "Europe/Paris" + default_time: "22:00" + abstract_chars_count: 160 + abstract_delimiter: + image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + match_path: ".*" + pretty_print: false + url_parameters: + utm_source: "documentation" + utm_medium: "RSS" + utm_campaign: "feed-syndication" + - search + +theme: + name: mkdocs + language: en + +# Extensions to enhance markdown +markdown_extensions: + - admonition + - attr_list + - codehilite + - meta + - toc: + permalink: "#" + +nav: + - "Home": "index.md" + - "Settings": "configuration.md" + - "Changelog": "changelog.md" diff --git a/tests/test_build.py b/tests/test_build.py index 451d7961..48b38209 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -910,6 +910,30 @@ def test_not_git_repo(self): # restore name git_dir_tmp.replace(git_dir) + def test_xml_escaping_in_author(self): + """Test that XML special characters in author field are properly escaped.""" + with tempfile.TemporaryDirectory() as tmpdirname: + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path( + "tests/fixtures/mkdocs_site_author_to_be_escaped.yml" + ), + output_path=tmpdirname, + strict=False, + ) + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + feed_parsed = feedparser.parse(Path(tmpdirname) / OUTPUT_RSS_FEED_CREATED) + self.assertEqual(feed_parsed.bozo, 0, "Feed should parse without errors") + feed_xml = (Path(tmpdirname) / OUTPUT_RSS_FEED_CREATED).read_text( + encoding="utf-8" + ) + + # Verify the author field contains the escaped ampersand + self.assertIn("OpenSavvy & contributors", feed_xml) + self.assertNotIn("OpenSavvy & contributors", feed_xml) + # ############################################################################## # ##### Stand alone program ######## From b7bd81bd4bb4d217c9240f0ec6cbed994d76897d Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 7 Nov 2025 17:07:45 +0100 Subject: [PATCH 107/158] release: bump version to 1.17.5 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6670101d..6533c095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.5 - 2025-11-07 + +### Bugs fixes 🐛 + +* fix(xml): escape special chars from site_author (``) by @Guts in + +### Features and enhancements 🎉 + +* improve(performances): run RSS item image fetching only on filtered pages list by @Guts in + +### Tooling 🔧 + +* Packaging: switch to pyproject by @Guts in +* update(security): set GH token permissions scopes in CI workflows by @Guts in + +### Other Changes + +* Packaging/remove-python-3_9-add-3_14 by @Guts in +* fix(packaging): rollback support for Python 3.14 by @Guts in + ## 1.17.4 - 2025-10-10 ### Bugs fixes 🐛 From 54e179376c8986f5d70a16bfd29c933f3f72265e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 11 Nov 2025 20:37:18 +0100 Subject: [PATCH 108/158] update(chore): bump minimal version of Material for Mkdocs since 9.7.x is the last one --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5c4d6e05..94854ab9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ dev = [ docs = [ "mkdocs-git-committers-plugin-2>=2.4.1,<2.6", "mkdocs-git-revision-date-localized-plugin>=1.3,<1.6", - "mkdocs-material[imaging]>=9.5.47,<10", + "mkdocs-material[imaging]>=9.7,<9.8", "mkdocs-minify-plugin>=0.8,<0.9", "mkdocstrings-python>=1.16.2,<1.19", "termynal>=0.12.2,<0.14", @@ -67,7 +67,7 @@ docs = [ test = [ "feedparser>=6.0.12,<6.1", "jsonfeed-util>=1.2,<2", - "mkdocs-material[imaging]>=9.6.23", + "mkdocs-material[imaging]>=9.7,<9.8", "pytest-cov>=6.9.1,<8", "validator-collection>=1.5,<1.6", ] From 24b915f97caac5c47778ebadb9fc58098c3a36c4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Tue, 11 Nov 2025 21:42:38 +0100 Subject: [PATCH 109/158] update(integrations): remove custom code related to former Material for Mkdocs Insiders edition Since there is no insiders edition anymore. See: https://squidfunk.github.io/mkdocs-material/blog/2025/11/11/insiders-now-free-for-everyone/ --- .../integrations/theme_material_base.py | 21 ------ .../theme_material_social_plugin.py | 72 ++++++------------- 2 files changed, 23 insertions(+), 70 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_base.py b/mkdocs_rss_plugin/integrations/theme_material_base.py index fe92b9dd..0c59da62 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_base.py +++ b/mkdocs_rss_plugin/integrations/theme_material_base.py @@ -33,7 +33,6 @@ class IntegrationMaterialThemeBase: # attributes IS_THEME_MATERIAL: bool = False - IS_INSIDERS: bool | None = False def __init__(self, mkdocs_config: MkDocsConfig) -> None: """Integration instantiation. @@ -45,7 +44,6 @@ def __init__(self, mkdocs_config: MkDocsConfig) -> None: self.mkdocs_config = mkdocs_config self.IS_THEME_MATERIAL = self.is_mkdocs_theme_material() - self.IS_INSIDERS = self.is_mkdocs_theme_material_insiders() def is_mkdocs_theme_material( self, mkdocs_config: MkDocsConfig | None = None @@ -63,22 +61,3 @@ def is_mkdocs_theme_material( self.IS_THEME_MATERIAL = mkdocs_config.theme.name == "material" return self.IS_THEME_MATERIAL - - def is_mkdocs_theme_material_insiders(self) -> bool | None: - """Check if the material theme is community or insiders edition. - - Returns: - bool: True if the theme is Insiders edition. False if community. None if - the Material theme is not installed. - """ - if not self.IS_THEME_MATERIAL: - return None - - if material_version is not None and "insiders" in material_version: - logger.debug("Material theme edition INSIDERS") - self.IS_INSIDERS = True - return True - else: - logger.debug("Material theme edition COMMUNITY") - self.IS_INSIDERS = False - return False diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 2ec5d361..0483bdaa 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -6,7 +6,6 @@ # standard library import json -from hashlib import md5 from pathlib import Path # 3rd party @@ -98,8 +97,7 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No mkdocs_config=mkdocs_config ) - if self.is_mkdocs_theme_material_insiders(): - self.load_cache_cards_manifest() + self.load_cache_cards_manifest() # store some attributes used to compute social card hash self.site_name = mkdocs_config.site_name @@ -307,12 +305,9 @@ def get_social_card_cache_path_for_page( ) -> Path | None: """Get social card path in social plugin cache folder for a specific page. - Note: - As we write this code (June 2024), the cache mechanism in Insiders edition - has stores images directly with the corresponding Page's path and name and - keep a correspondance matrix with hashes in a manifest.json; - the cache mechanism in Community edition uses the hash as file names without - any exposed matching criteria. + The cache mechanism in stores images directly with the + corresponding Page's path and name and keep a correspondance matrix with hashes + in a manifest.json. Args: mkdocs_page: Mkdocs page object. @@ -320,48 +315,27 @@ def get_social_card_cache_path_for_page( Returns: path to the image in local cache folder if it exists """ - if self.IS_INSIDERS: - - # if page is a blog post - if ( - self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED - and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) - ): - expected_cached_card_path = self.social_cards_cache_dir.joinpath( - f"assets/images/social/{Path(mkdocs_page.dest_uri).parent}.png" - ) - else: - expected_cached_card_path = self.social_cards_cache_dir.joinpath( - f"assets/images/social/{Path(mkdocs_page.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"Social card not found in cache folder: {expected_cached_card_path}" - ) - - else: - if "description" in mkdocs_page.meta: - description = mkdocs_page.meta["description"] - else: - description = self.site_description - - page_hash = md5( - "".join( - [ - self.site_name, - str(mkdocs_page.meta.get("title", mkdocs_page.title)), - description, - ] - ).encode("utf-8") + # if page is a blog post + if ( + self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) + ): + expected_cached_card_path = self.social_cards_cache_dir.joinpath( + f"assets/images/social/{Path(mkdocs_page.dest_uri).parent}.png" ) + else: expected_cached_card_path = self.social_cards_cache_dir.joinpath( - f"{page_hash.hexdigest()}.png" + f"assets/images/social/{Path(mkdocs_page.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"Social card not found in cache folder: {expected_cached_card_path}" ) if expected_cached_card_path.is_file(): From e519d85433dab67787ee86739eeb71c182756c6e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 07:29:13 +0100 Subject: [PATCH 110/158] improve(integrations): handle case where social cards cache dir is not relative to build folder --- .../theme_material_social_plugin.py | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 0483bdaa..ad252005 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -250,10 +250,26 @@ def get_social_cards_cache_dir(self, mkdocs_config: MkDocsConfig) -> Path: Path: The cache dir if the theme material and the plugin social cards is enabled. """ social_plugin_cfg = mkdocs_config.plugins.get("material/social") - self.social_cards_cache_dir = Path(social_plugin_cfg.config.cache_dir).resolve() + + if ( + Path(social_plugin_cfg.config.cache_dir) + .resolve() + .is_relative_to(Path(mkdocs_config.config_file_path).parent.resolve()) + ): + self.social_cards_cache_dir = Path( + social_plugin_cfg.config.cache_dir + ).resolve() + else: + self.social_cards_cache_dir = ( + Path(mkdocs_config.config_file_path) + .parent.resolve() + .joinpath(social_plugin_cfg.config.cache_dir) + ) logger.debug( - "Material Social cards cache folder: " f"{self.social_cards_cache_dir}." + "Material Social cards cache folder: " + f"{self.social_cards_cache_dir}. " + f"Already exists: {self.social_cards_cache_dir.is_dir()}" ) return self.social_cards_cache_dir From 5a0cb1b3b5b9492e8c9a16e5875f4b6c50ee5464 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 07:30:08 +0100 Subject: [PATCH 111/158] improve(integrations): remove duplicate logs --- .../integrations/theme_material_social_plugin.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index ad252005..e190e26b 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -354,15 +354,6 @@ def get_social_card_cache_path_for_page( f"Social card not found in cache folder: {expected_cached_card_path}" ) - 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}") - return None - def get_social_card_url_for_page( self, mkdocs_page: MkdocsPageSubset, From 7dc66460ec25ce367dc4a31bcd944d9399cb8cf0 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 08:11:57 +0100 Subject: [PATCH 112/158] fix(integrations): blog post detection was broken Closes #404 --- .../theme_material_blog_plugin.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index f329bdbb..385408f0 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -11,18 +11,19 @@ # 3rd party from mkdocs.config.defaults import MkDocsConfig from mkdocs.plugins import get_plugin_logger -from mkdocs.structure.pages import Page # package from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME from mkdocs_rss_plugin.integrations.theme_material_base import ( IntegrationMaterialThemeBase, ) +from mkdocs_rss_plugin.models import MkdocsPageSubset # conditional try: from material import __version__ as material_version from material.plugins.blog.plugin import BlogPlugin + from material.plugins.blog.structure import Post except ImportError: material_version = None @@ -131,7 +132,7 @@ def author_name_from_id(self, author_id: str) -> str: ) return author_id - def is_page_a_blog_post(self, mkdocs_page: Page) -> bool: + def is_page_a_blog_post(self, mkdocs_page: Post | MkdocsPageSubset) -> bool: """Identifies if the given page is part of Material Blog. Args: @@ -140,6 +141,18 @@ def is_page_a_blog_post(self, mkdocs_page: Page) -> bool: Returns: bool: True if the given page is a Material Blog post. """ - return Path(mkdocs_page.file.src_uri).is_relative_to( - self.blog_plugin_cfg.config.blog_dir - ) + if self.IS_ENABLED and isinstance(mkdocs_page, Post): + logger.info( + f"page '{mkdocs_page.file.src_uri}' identified as Material Blog post." + ) + return True + elif isinstance(mkdocs_page, MkdocsPageSubset) and Path( + mkdocs_page.src_uri + ).is_relative_to(self.blog_plugin_cfg.config.blog_dir): + logger.info( + f"page '{mkdocs_page.src_uri}' identified as Material Blog post " + f"by src_uri matching." + ) + return True + else: + return False From 04aa5d0d12d404fa03744d2c531deb048990a6b9 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 08:56:30 +0100 Subject: [PATCH 113/158] fix(integrations): decrease log level --- mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 385408f0..6ee3da57 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -142,14 +142,14 @@ def is_page_a_blog_post(self, mkdocs_page: Post | MkdocsPageSubset) -> bool: bool: True if the given page is a Material Blog post. """ if self.IS_ENABLED and isinstance(mkdocs_page, Post): - logger.info( + logger.debug( f"page '{mkdocs_page.file.src_uri}' identified as Material Blog post." ) return True elif isinstance(mkdocs_page, MkdocsPageSubset) and Path( mkdocs_page.src_uri ).is_relative_to(self.blog_plugin_cfg.config.blog_dir): - logger.info( + logger.debug( f"page '{mkdocs_page.src_uri}' identified as Material Blog post " f"by src_uri matching." ) From 712e21b09f1e3bb223ec48199ccbe58b26bcfe2e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 08:56:56 +0100 Subject: [PATCH 114/158] update(tests): pretty print blog related fixture --- ...cial_cards_blog_directory_url_disabled.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml b/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml index 49ff755d..acefde92 100644 --- a/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml +++ b/tests/fixtures/mkdocs_item_image_social_cards_blog_directory_url_disabled.yml @@ -5,14 +5,15 @@ site_url: https://guts.github.io/mkdocs-rss-plugin use_directory_urls: false plugins: - - blog: - blog_dir: blog - authors_profiles: true - - rss: - match_path: blog/posts/.* - - social: - enabled: true - cards: true + - blog: + blog_dir: blog + authors_profiles: true + - rss: + match_path: blog/posts/.* + pretty_print: true + - social: + enabled: true + cards: true theme: - name: material + name: material From cf19489cfaf8563f327e4b6b6ffcba5951672dcd Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 08:57:31 +0100 Subject: [PATCH 115/158] improve(integrations): add some debug logs --- .../integrations/theme_material_social_plugin.py | 6 ++++++ mkdocs_rss_plugin/util.py | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index e190e26b..78521145 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -336,10 +336,16 @@ def get_social_card_cache_path_for_page( self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): + logger.debug( + f"Looking for social card in cache for blog post: {mkdocs_page.src_uri}" + ) expected_cached_card_path = self.social_cards_cache_dir.joinpath( f"assets/images/social/{Path(mkdocs_page.dest_uri).parent}.png" ) else: + logger.debug( + f"Looking for social card in cache for page: {mkdocs_page.src_uri}" + ) expected_cached_card_path = self.social_cards_cache_dir.joinpath( f"assets/images/social/{Path(mkdocs_page.src_uri).with_suffix('.png')}" ) diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index f7afdbb2..332a769b 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -571,7 +571,9 @@ def load_images_for_pages( page_info._mkdocs_page_ref and id(page_info._mkdocs_page_ref) not in processed_refs ): - logger.debug(f"Get image for '{page_info.title}'") + logger.debug( + f"Get image for '{page_info.title}' ({page_info.abs_path})" + ) page_info.image = self.get_image( in_page=page_info._mkdocs_page_ref, base_url=base_url ) From ad842c0da0fad3058cfe771931621ac6b3018495 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 13 Nov 2025 09:04:46 +0100 Subject: [PATCH 116/158] release: bump version to 1.17.6 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6533c095..b7e36320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.6 - 2025-11-13 + +### Bugs fixes 🐛 + +* update(chore): bump minimal version of Material for Mkdocs since 9.7.x and fix related bugs by @Guts in +* improve(integrations): refine some logs about Material integrations by @Guts in + ## 1.17.5 - 2025-11-07 ### Bugs fixes 🐛 From 35f61f1289c1649c25ac58354739a19001d8b0fa Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 14 Nov 2025 21:18:12 +0100 Subject: [PATCH 117/158] update(quality): test build without Material for Mkdocs, patching sys modules #408 --- tests/test_no_material.py | 257 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 tests/test_no_material.py diff --git a/tests/test_no_material.py b/tests/test_no_material.py new file mode 100644 index 00000000..371e7362 --- /dev/null +++ b/tests/test_no_material.py @@ -0,0 +1,257 @@ +#! python3 # noqa E265 + +"""Test build without Material theme installed. + +Usage from the repo root folder: + +.. code-block:: python + + # for whole test + python -m unittest tests.test_build_without_material + # for specific test + python -m unittest tests.test_build_without_material.TestBuildWithoutMaterial.test_build_without_material_theme +""" + +# ############################################################################# +# ########## Libraries ############# +# ################################## + +# Standard library +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +# 3rd party +import feedparser + +# test suite +from tests.base import BaseTest + +# ############################################################################# +# ########## Globals ############### +# ################################## + +OUTPUT_RSS_FEED_CREATED = "feed_rss_created.xml" +OUTPUT_RSS_FEED_UPDATED = "feed_rss_updated.xml" +OUTPUT_JSON_FEED_CREATED = "feed_json_created.json" +OUTPUT_JSON_FEED_UPDATED = "feed_json_updated.json" + + +# ############################################################################# +# ########## Classes ############### +# ################################## + + +class TestBuildWithoutMaterial(BaseTest): + """Test MkDocs build with RSS plugin when Material theme is not available.""" + + # -- Standard methods -------------------------------------------------------- + @classmethod + def setUpClass(cls): + """Executed when module is loaded before any test.""" + cls.feed_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png" + + def setUp(self): + """Executed before each test.""" + pass + + def tearDown(self): + """Executed after each test.""" + pass + + @classmethod + def tearDownClass(cls): + """Executed after the last test.""" + pass + + # -- TESTS --------------------------------------------------------- + def test_build_without_material_theme(self): + """Test that the plugin works correctly when Material theme is not installed. + + This test simulates the absence of the Material theme by temporarily + blocking its import, ensuring the RSS plugin gracefully handles the missing + dependency. + """ + # Mock the material module to simulate it not being installed + with patch.dict(sys.modules, {"material": None}): + # Also need to mock the submodules + with patch.dict( + sys.modules, + { + "material.plugins": None, + "material.plugins.blog": None, + "material.plugins.blog.plugin": None, + "material.plugins.blog.structure": None, + }, + ): + with tempfile.TemporaryDirectory() as tmpdirname: + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path("tests/fixtures/mkdocs_minimal.yml"), + output_path=tmpdirname, + strict=True, + ) + + if cli_result.exception is not None: + e = cli_result.exception + return e + + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # Verify RSS feeds were created + self.assertTrue( + Path(tmpdirname).joinpath(OUTPUT_RSS_FEED_CREATED).exists() + ) + self.assertTrue( + Path(tmpdirname).joinpath(OUTPUT_RSS_FEED_UPDATED).exists() + ) + + # Verify feeds are valid + feed_created = feedparser.parse( + Path(tmpdirname) / OUTPUT_RSS_FEED_CREATED + ) + self.assertEqual(feed_created.bozo, 0) + + feed_updated = feedparser.parse( + Path(tmpdirname) / OUTPUT_RSS_FEED_UPDATED + ) + self.assertEqual(feed_updated.bozo, 0) + + def test_build_with_material_config_but_theme_not_installed(self): + """Test build with Material-specific config when the theme is not installed. + + This test uses a configuration file that references Material theme features + (like blog plugin) but simulates the theme not being installed. The plugin + should handle this gracefully without crashing. + """ + with patch.dict(sys.modules, {"material": None}): + with patch.dict( + sys.modules, + { + "material.plugins": None, + "material.plugins.blog": None, + "material.plugins.blog.plugin": None, + "material.plugins.blog.structure": None, + }, + ): + with tempfile.TemporaryDirectory() as tmpdirname: + # Use a config that would normally use Material features + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path("tests/fixtures/mkdocs_complete.yml"), + output_path=tmpdirname, + strict=False, # Don't fail on warnings + ) + + if cli_result.exception is not None: + e = cli_result.exception + return e + + # Build should succeed even without Material + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # Verify feeds were created and are valid + feed_created = feedparser.parse( + Path(tmpdirname) / OUTPUT_RSS_FEED_CREATED + ) + self.assertEqual(feed_created.bozo, 0) + self.assertGreater(len(feed_created.entries), 0) + + def test_page_processing_without_material(self): + """Test that page processing works correctly without Material theme. + + Ensures that pages are processed correctly and their metadata is extracted + even when Material-specific features are not available. + """ + with patch.dict(sys.modules, {"material": None}): + with patch.dict( + sys.modules, + { + "material.plugins": None, + "material.plugins.blog": None, + "material.plugins.blog.plugin": None, + "material.plugins.blog.structure": None, + }, + ): + with tempfile.TemporaryDirectory() as tmpdirname: + # Use complete config which includes pages with authors + cli_result = self.build_docs_setup( + testproject_path="docs", + mkdocs_yml_filepath=Path("tests/fixtures/mkdocs_complete.yml"), + output_path=tmpdirname, + strict=False, # Material theme not available + ) + + self.assertEqual(cli_result.exit_code, 0) + self.assertIsNone(cli_result.exception) + + # Parse the created feed + feed_parsed = feedparser.parse( + Path(tmpdirname) / OUTPUT_RSS_FEED_CREATED + ) + + # Verify feed has entries + self.assertGreater( + len(feed_parsed.entries), + 0, + "Feed should contain at least one entry", + ) + + # Verify entries have required fields + for entry in feed_parsed.entries: + self.assertIn( + "title", + entry, + f"Entry '{entry.get('title', 'UNKNOWN')}' missing title", + ) + self.assertIn( + "link", entry, f"Entry '{entry.title}' missing link" + ) + self.assertIn( + "description", + entry, + f"Entry '{entry.title}' missing description", + ) + self.assertIn( + "published", + entry, + f"Entry '{entry.title}' missing published date", + ) + + # Look for the specific page with complete metadata + page_with_complete_meta = next( + ( + e + for e in feed_parsed.entries + if e.title == "Page with complete meta" + ), + None, + ) + + # This page should exist and have author metadata + self.assertIsNotNone( + page_with_complete_meta, + "Page 'Page with complete meta' should be in the feed. " + f"Available pages: {', '.join([e.title for e in feed_parsed.entries])}", + ) + + self.assertIn( + "author", + page_with_complete_meta, + "Page 'Page with complete meta' should have author metadata", + ) + self.assertIsNotNone( + page_with_complete_meta.description, + "Page 'Page with complete meta' should have a description", + ) + + +# ############################################################################## +# ##### Stand alone program ######## +# ################################## +if __name__ == "__main__": + unittest.main() From dcdeaf3eb8c7c4d3ce294ec9a3a5cb814b285d16 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 14 Nov 2025 21:23:40 +0100 Subject: [PATCH 118/158] fix(integration): imports from Material for Mkdocs blog plugin for type hint was breaking the build when using another theme closes #408 --- .../integrations/theme_material_blog_plugin.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py index 6ee3da57..8c0abcae 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_blog_plugin.py @@ -7,6 +7,7 @@ # standard library from functools import lru_cache from pathlib import Path +from typing import Union # 3rd party from mkdocs.config.defaults import MkDocsConfig @@ -26,7 +27,7 @@ from material.plugins.blog.structure import Post except ImportError: - material_version = None + material_version = BlogPlugin = Post = None # ############################################################################ @@ -132,16 +133,16 @@ def author_name_from_id(self, author_id: str) -> str: ) return author_id - def is_page_a_blog_post(self, mkdocs_page: Post | MkdocsPageSubset) -> bool: + def is_page_a_blog_post(self, mkdocs_page: Union["Post", MkdocsPageSubset]) -> bool: """Identifies if the given page is part of Material Blog. Args: - mkdocs_page (Page): page to identify + mkdocs_page: page to identify Returns: - bool: True if the given page is a Material Blog post. + True if the given page is a Material Blog post. """ - if self.IS_ENABLED and isinstance(mkdocs_page, Post): + if self.IS_ENABLED and Post is not None and isinstance(mkdocs_page, Post): logger.debug( f"page '{mkdocs_page.file.src_uri}' identified as Material Blog post." ) From 1dcb66f8854d1d3ae4e638c39b737cea2e74a0d4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 14 Nov 2025 21:27:50 +0100 Subject: [PATCH 119/158] release: bump version to 1.17.7 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7e36320..e5817949 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.7 - 2025-11-14 + +### Bugs fixes 🐛 + +* fix(integration): imports from Material for Mkdocs blog plugin for type hint was breaking the build when using another theme by @Guts in + ## 1.17.6 - 2025-11-13 ### Bugs fixes 🐛 From c8db5f49e4bbd1abc985a3c0be45a480fe2a4f1c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:31:57 +0000 Subject: [PATCH 120/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.21.0 → v3.21.2](https://github.com/asottile/pyupgrade/compare/v3.21.0...v3.21.2) - [github.com/astral-sh/ruff-pre-commit: v0.14.3 → v0.14.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.3...v0.14.7) - [github.com/psf/black-pre-commit-mirror: 25.9.0 → 25.11.0](https://github.com/psf/black-pre-commit-mirror/compare/25.9.0...25.11.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f9b7571..af99860a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,14 +28,14 @@ repos: - id: python-use-type-annotations - repo: https://github.com/asottile/pyupgrade - rev: v3.21.0 + rev: v3.21.2 hooks: - id: pyupgrade args: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.3" + rev: "v0.14.7" hooks: - id: ruff-check args: @@ -52,7 +52,7 @@ repos: - --filter-files - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.9.0 + rev: 25.11.0 hooks: - id: black args: From 9911a375b826af6b6e661207d66fa5ce62ce3087 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:31:57 +0000 Subject: [PATCH 121/158] build(deps): bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-test.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/lint-and-tests.yml | 2 +- .github/workflows/release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index af528078..3fbf81ca 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -23,7 +23,7 @@ jobs: docker-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Test Docker Build run: | diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 1b82edd4..21eba456 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -47,7 +47,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Get source code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index d617f943..53e1f94a 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -34,7 +34,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Get source code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21336f1a..1f72e11e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 From 84defd8e24dde1b9c5db4b086d1221b7c7cf2a04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 11:01:18 +0000 Subject: [PATCH 122/158] build(deps): update tzdata requirement from ==2024.* to >=2024,<2026 Updates the requirements on [tzdata](https://github.com/python/tzdata) to permit the latest version. - [Release notes](https://github.com/python/tzdata/releases) - [Changelog](https://github.com/python/tzdata/blob/master/NEWS.md) - [Commits](https://github.com/python/tzdata/compare/2024.1rc0...2025.3) --- updated-dependencies: - dependency-name: tzdata dependency-version: '2025.3' dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 94854ab9..92e1b79d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ dependencies = [ "GitPython>=3.1.45,<3.2", "mkdocs>=1.6.1,<2", "requests>=2.32.5,<3", - "tzdata==2024.* ; sys_platform == 'win32'", + "tzdata>=2024,<2026 ; sys_platform == 'win32'", ] [project.optional-dependencies] From 721250c58e24dd043f8701bdca444e026de20864 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 16:19:41 +0000 Subject: [PATCH 123/158] build(deps-dev): update mkdocstrings-python requirement Updates the requirements on [mkdocstrings-python](https://github.com/mkdocstrings/python) to permit the latest version. - [Release notes](https://github.com/mkdocstrings/python/releases) - [Changelog](https://github.com/mkdocstrings/python/blob/main/CHANGELOG.md) - [Commits](https://github.com/mkdocstrings/python/compare/1.16.2...2.0.1) --- updated-dependencies: - dependency-name: mkdocstrings-python dependency-version: 2.0.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 92e1b79d..c65fad34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ docs = [ "mkdocs-git-revision-date-localized-plugin>=1.3,<1.6", "mkdocs-material[imaging]>=9.7,<9.8", "mkdocs-minify-plugin>=0.8,<0.9", - "mkdocstrings-python>=1.16.2,<1.19", + "mkdocstrings-python>=1.16.2,<2.1", "termynal>=0.12.2,<0.14", ] test = [ From ebd5fe9fb44f6dd924b4f4fc25053c10bcc153f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 18:00:51 +0000 Subject: [PATCH 124/158] build(deps): bump actions/upload-artifact from 5 to 6 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 21eba456..b24b0824 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -75,7 +75,7 @@ jobs: run: mkdocs build --verbose - name: Save build doc as artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: documentation path: site/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f72e11e..3b6f0a4b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: --outdir dist/ . - - uses: actions/upload-artifact@v5 + - uses: actions/upload-artifact@v6 with: name: python_wheel path: dist/* From c8e096579d31894d37efefca81c9b4b36a4ea984 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Jan 2026 19:07:52 +0000 Subject: [PATCH 125/158] build(deps): bump codecov/codecov-action from 5.5.1 to 5.5.2 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.5.1 to 5.5.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.5.1...v5.5.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.5.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 53e1f94a..f90610ac 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -53,7 +53,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.5.1 + uses: codecov/codecov-action@v5.5.2 with: env_vars: PYTHON flags: unittests From 17f4fd00f16d1f8f4fc9d978c57d8daea2cc6fde Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 5 Jan 2026 23:02:29 +0100 Subject: [PATCH 126/158] fix(tests): use icon from GH repository since Wikimedia returns HTTP 429 --- README.md | 2 +- docs/configuration.md | 4 ++-- mkdocs.yml | 2 +- tests/fixtures/mkdocs_complete.yml | 2 +- tests/fixtures/mkdocs_complete_no_git.yml | 2 +- tests/fixtures/mkdocs_item_image_social_cards_blog.yml | 4 +++- tests/fixtures/mkdocs_simple.yml | 2 +- tests/fixtures/mkdocs_site_author_to_be_escaped.yml | 2 +- tests/test_build.py | 2 +- tests/test_config.py | 2 +- tests/test_no_material.py | 2 +- tests/test_rss_util.py | 2 +- 12 files changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index b789a47e..a6284525 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ plugins: rss_updated: feed_rss_updated.xml feed_title: "My custom feed title" # MkDocs site_name: will be used if this key is not present feed_ttl: 1440 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true json_feed_enabled: true length: 20 match_path: ".*" diff --git a/docs/configuration.md b/docs/configuration.md index 63a07913..ca612e1c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -489,7 +489,7 @@ Default: `None`. ```yaml plugins: - rss: - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true ``` Output: @@ -497,7 +497,7 @@ Output: ```xml - https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true MkDocs RSS Plugin https://guts.github.io/mkdocs-rss-plugin/ diff --git a/mkdocs.yml b/mkdocs.yml index 344813d4..78d265cc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -116,7 +116,7 @@ plugins: default_timezone: "Europe/Paris" default_time: "22:00" enabled: !ENV [MKDOCS_ENABLE_PLUGIN_RSS, true] - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true json_feed_enabled: true match_path: ".*" pretty_print: true diff --git a/tests/fixtures/mkdocs_complete.yml b/tests/fixtures/mkdocs_complete.yml index 705fdcd3..66684e84 100644 --- a/tests/fixtures/mkdocs_complete.yml +++ b/tests/fixtures/mkdocs_complete.yml @@ -24,7 +24,7 @@ plugins: default_time: "09:30" enabled: true feed_ttl: 1440 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true json_feed_enabled: true length: 20 match_path: ".*" diff --git a/tests/fixtures/mkdocs_complete_no_git.yml b/tests/fixtures/mkdocs_complete_no_git.yml index ddda2b06..16cf0927 100644 --- a/tests/fixtures/mkdocs_complete_no_git.yml +++ b/tests/fixtures/mkdocs_complete_no_git.yml @@ -24,7 +24,7 @@ plugins: default_time: "09:30" enabled: true feed_ttl: 1440 - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true length: 20 pretty_print: false match_path: ".*" diff --git a/tests/fixtures/mkdocs_item_image_social_cards_blog.yml b/tests/fixtures/mkdocs_item_image_social_cards_blog.yml index 26fe268c..d88b1736 100644 --- a/tests/fixtures/mkdocs_item_image_social_cards_blog.yml +++ b/tests/fixtures/mkdocs_item_image_social_cards_blog.yml @@ -5,7 +5,9 @@ site_url: https://guts.github.io/mkdocs-rss-plugin plugins: - blog: blog_dir: blog - - rss + - rss: + match_path: blog/posts/.* + pretty_print: true - social: enabled: true cards: true diff --git a/tests/fixtures/mkdocs_simple.yml b/tests/fixtures/mkdocs_simple.yml index 9f2749cb..80a24294 100644 --- a/tests/fixtures/mkdocs_simple.yml +++ b/tests/fixtures/mkdocs_simple.yml @@ -22,7 +22,7 @@ plugins: default_time: "22:00" abstract_chars_count: 160 abstract_delimiter: - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true match_path: ".*" pretty_print: false url_parameters: diff --git a/tests/fixtures/mkdocs_site_author_to_be_escaped.yml b/tests/fixtures/mkdocs_site_author_to_be_escaped.yml index 9e426f64..c5ec3256 100644 --- a/tests/fixtures/mkdocs_site_author_to_be_escaped.yml +++ b/tests/fixtures/mkdocs_site_author_to_be_escaped.yml @@ -21,7 +21,7 @@ plugins: default_time: "22:00" abstract_chars_count: 160 abstract_delimiter: - image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png + image: https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true match_path: ".*" pretty_print: false url_parameters: diff --git a/tests/test_build.py b/tests/test_build.py index 48b38209..5a58b746 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -50,7 +50,7 @@ class TestBuildRss(BaseTest): def setUpClass(cls): """Executed when module is loaded before any test.""" cls.config_files = sorted(Path("tests/fixtures/").glob("**/*.yml")) - cls.feed_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png" + cls.feed_image = "https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true" def setUp(self): """Executed before each test.""" diff --git a/tests/test_config.py b/tests/test_config.py index 0420b3d9..17200eae 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -42,7 +42,7 @@ class TestConfig(BaseTest): def setUpClass(cls): """Executed when module is loaded before any test.""" 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" + cls.feed_image = "https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true" def setUp(self): """Executed before each test.""" diff --git a/tests/test_no_material.py b/tests/test_no_material.py index 371e7362..8249f351 100644 --- a/tests/test_no_material.py +++ b/tests/test_no_material.py @@ -51,7 +51,7 @@ class TestBuildWithoutMaterial(BaseTest): @classmethod def setUpClass(cls): """Executed when module is loaded before any test.""" - cls.feed_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png" + cls.feed_image = "https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true" def setUp(self): """Executed before each test.""" diff --git a/tests/test_rss_util.py b/tests/test_rss_util.py index 2ee9aeac..e069f453 100644 --- a/tests/test_rss_util.py +++ b/tests/test_rss_util.py @@ -35,7 +35,7 @@ class TestRssUtil(unittest.TestCase): def setUpClass(cls): """Executed when module is loaded before any test.""" cls.config_files = sorted(Path("tests/fixtures/").glob("**/*.yml")) - cls.feed_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png" + cls.feed_image = "https://github.com/Guts/mkdocs-rss-plugin/blob/main/docs/assets/logo_rss_plugin_mkdocs.png?raw=true" cls.plg_utils = Util() def setUp(self): From a2926c15cd7856f027dbd7568272828390efc2e6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:19:45 +0000 Subject: [PATCH 127/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.7 → v0.14.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.7...v0.14.10) - [github.com/psf/black-pre-commit-mirror: 25.11.0 → 25.12.0](https://github.com/psf/black-pre-commit-mirror/compare/25.11.0...25.12.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af99860a..53c05c5b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.7" + rev: "v0.14.10" hooks: - id: ruff-check args: @@ -52,7 +52,7 @@ repos: - --filter-files - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.11.0 + rev: 25.12.0 hooks: - id: black args: From 18c2c348f032741f8aa958c4156e8479c4e4c20d Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 5 Jan 2026 21:51:37 +0100 Subject: [PATCH 128/158] fix(integration): Material Social Card URI was wrong for Material blog posts Bug introduced in #354 --- .../theme_material_social_plugin.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 78521145..44b6c67f 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -378,12 +378,21 @@ 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 - # As of mkdocs-material 9.6.5, social cards are always stored in the - # matching src path in the build folder, regardless of the page type. - page_social_card = ( - f"{mkdocs_site_url}{self.social_cards_dir}/" - f"{Path(mkdocs_page.src_uri).with_suffix('.png')}" - ) + # if page is a blog post + if ( + self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED + and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) + ): + page_social_card = ( + f"{mkdocs_site_url}assets/images/social/" + f"{Path(mkdocs_page.dest_uri).with_suffix('.png')}" + ) + else: + page_social_card = ( + f"{mkdocs_site_url}{self.social_cards_dir}/" + f"{Path(mkdocs_page.src_uri).with_suffix('.png')}" + ) + logger.debug(f"Use social card url: {page_social_card}") return page_social_card From 6608ccb5bd008deb20cacc4d6e4fba3067f75908 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 5 Jan 2026 23:11:06 +0100 Subject: [PATCH 129/158] release: bump version to 1.17.8 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5817949..c614e76d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.8 - 2026-01-05 + +### Bugs fixes 🐛 + +* fix(tests): use icon from GH repository since Wikimedia returns HTTP 429 by @Guts in +* fix(integration): Material Social Card URI was wrong for Material blog posts by @Guts in + ## 1.17.7 - 2025-11-14 ### Bugs fixes 🐛 From 4ed40ead0293a8a08e295b94931c5d2972e20995 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 5 Jan 2026 23:27:25 +0100 Subject: [PATCH 130/158] fix(integration): Material Social Card URI was wrong for Material blog posts when diretcory URL are disabled at Mkdocs level Bug partially fixed in #354 then reintroduced in #418 --- .../theme_material_social_plugin.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index 44b6c67f..71f996d7 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -85,6 +85,7 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No # if enabled, save some config elements if self.IS_ENABLED: + self.mkdocs_use_directory_urls = mkdocs_config.use_directory_urls self.mkdocs_site_url = mkdocs_config.site_url self.mkdocs_site_build_dir = mkdocs_config.site_dir self.social_cards_dir = self.get_social_cards_dir( @@ -99,10 +100,6 @@ def __init__(self, mkdocs_config: MkDocsConfig, switch_force: bool = True) -> No self.load_cache_cards_manifest() - # store some attributes used to compute social card hash - self.site_name = mkdocs_config.site_name - self.site_description = mkdocs_config.site_description or "" - def is_social_plugin_enabled_mkdocs( self, mkdocs_config: MkDocsConfig | None = None ) -> bool: @@ -383,10 +380,17 @@ def get_social_card_url_for_page( self.integration_material_blog.IS_BLOG_PLUGIN_ENABLED and self.integration_material_blog.is_page_a_blog_post(mkdocs_page) ): - page_social_card = ( - f"{mkdocs_site_url}assets/images/social/" - f"{Path(mkdocs_page.dest_uri).with_suffix('.png')}" - ) + if self.mkdocs_use_directory_urls: + # see: https://github.com/Guts/mkdocs-rss-plugin/issues/319 + page_social_card = ( + f"{mkdocs_site_url}{self.social_cards_dir}/" + f"{Path(mkdocs_page.dest_uri).parent.with_suffix('.png')}" + ) + else: + page_social_card = ( + f"{mkdocs_site_url}{self.social_cards_dir}/" + f"{Path(mkdocs_page.dest_uri).with_suffix('.png')}" + ) else: page_social_card = ( f"{mkdocs_site_url}{self.social_cards_dir}/" From 8b3750018fddd193c3d0f85e67d28ca3ef1033a2 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 5 Jan 2026 23:31:22 +0100 Subject: [PATCH 131/158] release: bump version to 1.17.9 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c614e76d..ab03dc19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.17.9 - 2026-01-05 + +### Bugs fixes 🐛 + +* fix(integration): Material Social Card URI was wrong for Material blog posts when diretcory URL are disabled at Mkdocs level by @Guts in + ## 1.17.8 - 2026-01-05 ### Bugs fixes 🐛 From 5b0f1300cefef11645d4fe80c74641aa69781bb0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:14:33 +0000 Subject: [PATCH 132/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.10 → v0.14.14](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.10...v0.14.14) - [github.com/psf/black-pre-commit-mirror: 25.12.0 → 26.1.0](https://github.com/psf/black-pre-commit-mirror/compare/25.12.0...26.1.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53c05c5b..f164f84f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.10" + rev: "v0.14.14" hooks: - id: ruff-check args: @@ -52,7 +52,7 @@ repos: - --filter-files - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.12.0 + rev: 26.1.0 hooks: - id: black args: From b169fde7fd646850fbf011f2501f26b384b57ecf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:14:49 +0000 Subject: [PATCH 133/158] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mkdocs_rss_plugin/git_manager/ci.py | 24 ++++++++---------------- tests/base.py | 6 ++---- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/mkdocs_rss_plugin/git_manager/ci.py b/mkdocs_rss_plugin/git_manager/ci.py index 3d5ec17c..f1594d26 100644 --- a/mkdocs_rss_plugin/git_manager/ci.py +++ b/mkdocs_rss_plugin/git_manager/ci.py @@ -47,52 +47,44 @@ def raise_ci_warnings(self) -> None: # Gitlab Runners if environ.get("GITLAB_CI") and n_commits < 50: # Default is GIT_DEPTH of 50 for gitlab - logger.info( - """ + logger.info(""" Running on a gitlab runner might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Make sure to set GIT_DEPTH to 1000 in your .gitlab-ci.yml file. \ (see https://docs.gitlab.com/user/project/repository/monorepos/#use-shallow-clones-in-cicd-processes). - """ - ) + """) # Github Actions if environ.get("GITHUB_ACTIONS") and n_commits == 1: # Default is fetch-depth of 1 for github actions - logger.info( - """ + logger.info(""" Running on github actions might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Try setting fetch-depth to 0 in your github action \ (see https://github.com/actions/checkout?tab=readme-ov-file#fetch-all-history-for-all-tags-and-branches). - """ - ) + """) # Bitbucket pipelines if environ.get("CI") and n_commits < 50: # Default is fetch-depth of 50 for bitbucket pipelines - logger.info( - """ + logger.info(""" Running on bitbucket pipelines might lead to wrong \ git revision dates due to a shallow git fetch depth. \ Try setting "clone: depth" to "full" in your pipeline \ (see https://support.atlassian.com/bitbucket-cloud/docs/git-clone-behavior/#Depth and search 'depth'). - """ - ) + """) # Azure Devops Pipeline # Does not limit fetch-depth by default if environ.get("Agent.Source.Git.ShallowFetchDepth", 10e99) < n_commits: - logger.info( - """ + logger.info(""" Running on Azure pipelines \ with limited fetch-depth might lead to wrong git revision dates \ due to a shallow git fetch depth. \ Remove any Shallow Fetch settings \ (see https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/pipeline-options-for-git?view=azure-devops#shallow-fetch). - """ - ) + """) def commit_count(self) -> int: """Helper function to determine the number of commits in a repository. diff --git a/tests/base.py b/tests/base.py index a339c765..0f79556f 100644 --- a/tests/base.py +++ b/tests/base.py @@ -131,10 +131,8 @@ def setup_clean_mkdocs_folder( # Create empty 'testproject' folder if testproject_path.exists(): - logging.warning( - """This command does not work on windows. - Refactor your test to use setup_clean_mkdocs_folder() only once""" - ) + logging.warning("""This command does not work on windows. + Refactor your test to use setup_clean_mkdocs_folder() only once""") shutil.rmtree(testproject_path) # Copy correct mkdocs.yml file and our test 'docs/' From 7db06618061032cd5a7874c0db59e7f3982c865b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 18:02:08 +0000 Subject: [PATCH 134/158] build(deps): bump actions/upload-artifact from 6 to 7 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index b24b0824..91889fc2 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -75,7 +75,7 @@ jobs: run: mkdocs build --verbose - name: Save build doc as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: documentation path: site/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b6f0a4b..4f0df4ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: --outdir dist/ . - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: python_wheel path: dist/* From 522ab3c9b4ceefcd5089e80d19763118c1caadb1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:33:32 +0000 Subject: [PATCH 135/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.14 → v0.15.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.14...v0.15.4) - [github.com/pycqa/isort: 7.0.0 → 8.0.1](https://github.com/pycqa/isort/compare/7.0.0...8.0.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f164f84f..cc7c20bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.14" + rev: "v0.15.4" hooks: - id: ruff-check args: @@ -43,7 +43,7 @@ repos: - --target-version=py310 - repo: https://github.com/pycqa/isort - rev: 7.0.0 + rev: 8.0.1 hooks: - id: isort args: From 976beb9798f5d92f25958f1784a6b928d68ce2b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 22:48:48 +0000 Subject: [PATCH 136/158] build(deps): bump actions/deploy-pages from 4 to 5 Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 4 to 5. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 91889fc2..62c05fe1 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -96,4 +96,4 @@ jobs: - name: Deploy to GitHub Pages id: deployment if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 From bab502b0cd19d310fb9fbb257a2514cba93843c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:06:12 +0000 Subject: [PATCH 137/158] build(deps): bump actions/configure-pages from 5 to 6 Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 5 to 6. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 62c05fe1..e11f8ee9 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -83,7 +83,7 @@ jobs: retention-days: 30 - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@v6 if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') - name: Upload artifact From cb10148b8ddeac0cdd8e0c6f82a4f39d88629052 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:29:23 +0000 Subject: [PATCH 138/158] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.4 → v0.15.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.4...v0.15.9) - [github.com/psf/black-pre-commit-mirror: 26.1.0 → 26.3.1](https://github.com/psf/black-pre-commit-mirror/compare/26.1.0...26.3.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cc7c20bb..65ec432b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.15.4" + rev: "v0.15.9" hooks: - id: ruff-check args: @@ -52,7 +52,7 @@ repos: - --filter-files - repo: https://github.com/psf/black-pre-commit-mirror - rev: 26.1.0 + rev: 26.3.1 hooks: - id: black args: From 425d9a8befcf0719226df67537cd03eb5efb0d87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:10:20 +0000 Subject: [PATCH 139/158] build(deps-dev): update termynal requirement Updates the requirements on [termynal](https://github.com/termynal/termynal.py) to permit the latest version. - [Changelog](https://github.com/termynal/termynal.py/blob/main/CHANGELOG.md) - [Commits](https://github.com/termynal/termynal.py/compare/v0.12.2...v0.14.0) --- updated-dependencies: - dependency-name: termynal dependency-version: 0.14.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c65fad34..88a69367 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ docs = [ "mkdocs-material[imaging]>=9.7,<9.8", "mkdocs-minify-plugin>=0.8,<0.9", "mkdocstrings-python>=1.16.2,<2.1", - "termynal>=0.12.2,<0.14", + "termynal>=0.12.2,<0.15", ] test = [ "feedparser>=6.0.12,<6.1", From aa548aaf596d1c960cdc523ff908492ccb4a8c11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:15:57 +0000 Subject: [PATCH 140/158] build(deps): bump codecov/codecov-action from 5.5.2 to 6.0.0 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.5.2 to 6.0.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.5.2...v6.0.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-and-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index f90610ac..2f5cb7c0 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -53,7 +53,7 @@ jobs: run: python -m pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5.5.2 + uses: codecov/codecov-action@v6.0.0 with: env_vars: PYTHON flags: unittests From 1a9e0da72eaf3525cabc88d6154f462f622d5a65 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 9 Apr 2026 19:12:56 +0200 Subject: [PATCH 141/158] update(packaging): declare plugin compatible with ProperDocs See: https://github.com/orgs/ProperDocs/discussions/33 --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 88a69367..823419a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,8 @@ classifiers = [ dependencies = [ "CacheControl[filecache]>=0.14.3,<1", "GitPython>=3.1.45,<3.2", - "mkdocs>=1.6.1,<2", + "mkdocs==1.6.1", + "properdocs >=1.6.5,<2", "requests>=2.32.5,<3", "tzdata>=2024,<2026 ; sys_platform == 'win32'", ] From 1a3d3a1860f3e01f59340ac384a8d3fcf666b9b7 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 9 Apr 2026 22:22:57 +0200 Subject: [PATCH 142/158] update(packaging): support Python 3.14 --- .github/workflows/lint-and-tests.yml | 1 + pyproject.toml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 2f5cb7c0..37495729 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -30,6 +30,7 @@ jobs: - "3.11" - "3.12" - "3.13" + - "3.14" # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/pyproject.toml b/pyproject.toml index 823419a0..e78a9c79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Documentation", "Topic :: Software Development :: Documentation", "Topic :: Text Processing :: Markup :: Markdown", @@ -89,7 +90,7 @@ Repository = "https://github.com/guts/mkdocs-rss-plugin/" # Black configuration [tool.black] -target-version = ["py310", "py311", "py312", "py313"] +target-version = ["py310", "py311", "py312", "py313", "py314"] # Coverage configuration [tool.coverage.report] From 74802660d7da5b9e2bbd8a07032c04a894e69f8e Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 9 Apr 2026 22:15:38 +0200 Subject: [PATCH 143/158] feature(rss): add option to set a stylesheet with a special 'auto' value to use the XSL shipped with the plugin --- docs/configuration.md | 32 ++++ mkdocs.yml | 1 + mkdocs_rss_plugin/config.py | 1 + mkdocs_rss_plugin/models.py | 1 + mkdocs_rss_plugin/plugin.py | 24 +++ mkdocs_rss_plugin/templates/default.xsl | 188 +++++++++++++++++++++ mkdocs_rss_plugin/templates/rss.xml.jinja2 | 1 + 7 files changed, 248 insertions(+) create mode 100644 mkdocs_rss_plugin/templates/default.xsl diff --git a/docs/configuration.md b/docs/configuration.md index ca612e1c..c95b99da 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -550,6 +550,38 @@ Default: `False`. ---- +### :material-brush-variant: `stylesheet`: define a XSL stylesheet { #stylesheet } + +Use a XSL stylesheet to customize how the RSS feed looks like. `auto` is a special value to use the stylesheet shipped with the plugin. + +```yaml +plugins: + - rss: + stylesheet: auto +``` + +If you're willing to work on your own stylesheet, set the URL or relative path: + +```yaml +plugins: + - rss: + stylesheet: https://docs.example.org/rss_stylesheet.xsl +``` + +Note that it's recommended to host the stylesheet on the same website / domain to make CORS happy. + +If you prefer to disable the stylesheet, you set it to `""`: + +```yaml +plugins: + - rss: + stylesheet: "" +``` + +Default: `auto`. + +---- + ### :material-track-light: `url_parameters`: additional URL parameters { #url_parameters } This option allows you to add parameters to the URLs of the RSS feed items. It works as a dictionary of keys/values that is passed to [Python *urllib.parse.urlencode*](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlencode). diff --git a/mkdocs.yml b/mkdocs.yml index 78d265cc..b1c13e69 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,6 +121,7 @@ plugins: match_path: ".*" pretty_print: true rss_feed_enabled: true + stylesheet: "" url_parameters: utm_source: "documentation" utm_medium: "RSS" diff --git a/mkdocs_rss_plugin/config.py b/mkdocs_rss_plugin/config.py index bc37a95a..8f0327f4 100644 --- a/mkdocs_rss_plugin/config.py +++ b/mkdocs_rss_plugin/config.py @@ -58,6 +58,7 @@ class RssPluginConfig(Config): match_path = config_options.Type(str, default=".*") pretty_print = config_options.Type(bool, default=False) rss_feed_enabled = config_options.Type(bool, default=True) + stylesheet = config_options.Type(str, default="auto") url_parameters = config_options.Optional(config_options.Type(dict)) use_git = config_options.Type(bool, default=True) use_material_blog = config_options.Type(bool, default=True) diff --git a/mkdocs_rss_plugin/models.py b/mkdocs_rss_plugin/models.py index 2b458e56..6c433abb 100644 --- a/mkdocs_rss_plugin/models.py +++ b/mkdocs_rss_plugin/models.py @@ -90,5 +90,6 @@ class RssFeedBase: pubDate: str | None = None repo_url: str | None = None rss_url: str | None = None + stylesheet: str | None = None title: str | None = None ttl: int | None = None diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index 8383b805..1a1a2a34 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -12,6 +12,7 @@ from email.utils import format_datetime, formatdate from pathlib import Path from re import compile as re_compile +from shutil import copyfile from typing import Literal # 3rd party @@ -175,6 +176,23 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: if self.config.image: base_feed.logo_url = self.config.image + # feed stylesheet (XSL) + print(f"Config stylesheet: {self.config.stylesheet}") + if self.config.stylesheet: + if self.config.stylesheet == "auto": + base_feed.stylesheet = "rss.xsl" + logger.debug( + f"Shipped stylesheet will be referenced in RSS feeds: {self.config.stylesheet}" + ) + else: + + base_feed.stylesheet = self.config.stylesheet + logger.debug( + f"Stylesheet will be referenced in RSS feeds: {self.config.stylesheet}" + ) + else: + logger.debug("No stylesheet will be referenced in RSS feeds.") + # pattern to match pages included in output self.match_path_pattern = re_compile(self.config.match_path) @@ -378,6 +396,12 @@ def on_post_build(self, config: config_options.Config) -> None: self.config.feeds_filenames.json_updated ) + # stylesheet for RSS feed + if self.config.stylesheet == "auto": + xsl_source = self.tpl_folder.joinpath("default.xsl") + xsl_dest = Path(config.site_dir).joinpath("rss.xsl") + copyfile(xsl_source, xsl_dest) + # created items self.feed_created.entries.extend( self.util.filter_pages( diff --git a/mkdocs_rss_plugin/templates/default.xsl b/mkdocs_rss_plugin/templates/default.xsl new file mode 100644 index 00000000..e56bc178 --- /dev/null +++ b/mkdocs_rss_plugin/templates/default.xsl @@ -0,0 +1,188 @@ + + + + + + + + + + + <xsl:value-of select="rss/channel/title"/> + + + + + + +
+ + + + + + 64 + + + +

+ +

+ +

+ +

+ +

+ + + + + Visit website + +

+
+ + + By + + + + — Published: + + + + + — Updated: + + + +
+
+ + + +
+ +

+ + + + + + +

+ +
+ + Par + + + — + +
+ + + + + + + + + + +

+ +

+ +
+ + + + + +
+ +
+ +
+ + + +
+ +
diff --git a/mkdocs_rss_plugin/templates/rss.xml.jinja2 b/mkdocs_rss_plugin/templates/rss.xml.jinja2 index 65d97265..53286720 100644 --- a/mkdocs_rss_plugin/templates/rss.xml.jinja2 +++ b/mkdocs_rss_plugin/templates/rss.xml.jinja2 @@ -1,4 +1,5 @@ +{% if feed.stylesheet is not none %}{% endif -%} {# Mandatory elements #} From ac4fb39119803997f968dbc54cebe8f646c0a6c0 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 9 Apr 2026 22:19:31 +0200 Subject: [PATCH 144/158] add(tests): add test cases for stylesheet option --- mkdocs.yml | 2 +- tests/fixtures/mkdocs_stylesheet_disabled.yml | 12 ++++++++++++ tests/test_config.py | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/mkdocs_stylesheet_disabled.yml diff --git a/mkdocs.yml b/mkdocs.yml index b1c13e69..34a4df07 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ plugins: match_path: ".*" pretty_print: true rss_feed_enabled: true - stylesheet: "" + stylesheet: auto url_parameters: utm_source: "documentation" utm_medium: "RSS" diff --git a/tests/fixtures/mkdocs_stylesheet_disabled.yml b/tests/fixtures/mkdocs_stylesheet_disabled.yml new file mode 100644 index 00000000..704638c1 --- /dev/null +++ b/tests/fixtures/mkdocs_stylesheet_disabled.yml @@ -0,0 +1,12 @@ +site_name: Test RSS Plugin - Disable stylesheet +# site_description: Test RSS Plugin +site_url: https://guts.github.io/mkdocs-rss-plugin + +use_directory_urls: true + +plugins: + - rss: + stylesheet: "" + +theme: + name: mkdocs diff --git a/tests/test_config.py b/tests/test_config.py index 17200eae..77d7aa4b 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -88,6 +88,7 @@ def test_plugin_config_defaults(self): "rss_updated": "feed_rss_updated.xml", }, "pretty_print": False, + "stylesheet": "auto", "rss_feed_enabled": True, "url_parameters": None, "use_git": True, @@ -134,6 +135,7 @@ def test_plugin_config_image(self): "rss_updated": "feed_rss_updated.xml", }, "pretty_print": False, + "stylesheet": "auto", "rss_feed_enabled": True, "url_parameters": None, "use_git": True, From d321a8aa2cbafecf03f74605c39f8c0fda011a71 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Thu, 9 Apr 2026 22:43:40 +0200 Subject: [PATCH 145/158] release: bump version to 1.18.0 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab03dc19..ca1081ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## 1.18.0 - 2026-04-09 + +### Features and enhancements 🎉 + +* feature(rss): add option to set a stylesheet by @Guts in +* update(packaging): declare plugin compatible with ProperDocs by @Guts in +* update(packaging): support Python 3.14 by @Guts in + ## 1.17.9 - 2026-01-05 ### Bugs fixes 🐛 From ee9186934dc13cca2e458d26d3c20f9e9b8367f4 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Apr 2026 14:05:47 +0200 Subject: [PATCH 146/158] remove(plugin): debug print statement --- mkdocs_rss_plugin/plugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index 1a1a2a34..666ba481 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -177,7 +177,6 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig: base_feed.logo_url = self.config.image # feed stylesheet (XSL) - print(f"Config stylesheet: {self.config.stylesheet}") if self.config.stylesheet: if self.config.stylesheet == "auto": base_feed.stylesheet = "rss.xsl" From fb4e566d4a63b20b3e6ea1950b3816ea67606a5a Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Fri, 10 Apr 2026 14:07:20 +0200 Subject: [PATCH 147/158] improve(stylesheet): fix left align spotted on Firefox Mobile --- mkdocs_rss_plugin/templates/default.xsl | 28 ++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/mkdocs_rss_plugin/templates/default.xsl b/mkdocs_rss_plugin/templates/default.xsl index e56bc178..3a11d00c 100644 --- a/mkdocs_rss_plugin/templates/default.xsl +++ b/mkdocs_rss_plugin/templates/default.xsl @@ -10,15 +10,21 @@ + <xsl:value-of select="rss/channel/title"/>