Skip to content

Commit e24cedd

Browse files
committed
update(plugin): factorize image fetching and page and RSS item related models
1 parent 53b1890 commit e24cedd

File tree

5 files changed

+151
-98
lines changed

5 files changed

+151
-98
lines changed

mkdocs_rss_plugin/integrations/theme_material_social_plugin.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from mkdocs_rss_plugin.integrations.theme_material_blog_plugin import (
2424
IntegrationMaterialBlog,
2525
)
26+
from mkdocs_rss_plugin.models import MkdocsPageSubset
2627

2728
# conditional
2829
try:
@@ -167,18 +168,18 @@ def is_social_plugin_and_cards_enabled_mkdocs(
167168
return True
168169

169170
def is_social_plugin_enabled_page(
170-
self, mkdocs_page: Page, fallback_value: bool = True
171+
self, mkdocs_page: MkdocsPageSubset, fallback_value: bool = True
171172
) -> bool:
172173
"""Check if the social plugin is enabled or disabled for a specific page. Plugin
173174
has to be enabled in Mkdocs configuration before.
174175
175176
Args:
176-
mkdocs_page (Page): Mkdocs page object.
177-
fallback_value (bool, optional): fallback value. It might be the
177+
mkdocs_page: Mkdocs page object.
178+
fallback_value: fallback value. It might be the
178179
'plugins.social.cards.enabled' option in Mkdocs config. Defaults to True.
179180
180181
Returns:
181-
bool: True if the social cards are enabled for a page.
182+
True if the social cards are enabled for a page.
182183
"""
183184
return mkdocs_page.meta.get("social", {"cards": fallback_value}).get(
184185
"cards", fallback_value
@@ -374,18 +375,18 @@ def get_social_card_cache_path_for_page(self, mkdocs_page: Page) -> Optional[Pat
374375

375376
def get_social_card_url_for_page(
376377
self,
377-
mkdocs_page: Page,
378+
mkdocs_page: MkdocsPageSubset,
378379
mkdocs_site_url: Optional[str] = None,
379380
) -> str:
380381
"""Get social card URL for a specific page in documentation.
381382
382383
Args:
383-
mkdocs_page (Page): Mkdocs page object.
384-
mkdocs_site_url (Optional[str], optional): Mkdocs site URL. If None, the
384+
mkdocs_page: subset of Mkdocs page object.
385+
mkdocs_site_url: Mkdocs site URL. If None, the
385386
'class.mkdocs_site_url' is used. is Defaults to None.
386387
387388
Returns:
388-
str: URL to the image once published
389+
URL to the image once published
389390
"""
390391
if mkdocs_site_url is None and self.mkdocs_site_url:
391392
mkdocs_site_url = self.mkdocs_site_url
@@ -394,7 +395,7 @@ def get_social_card_url_for_page(
394395
# matching src path in the build folder, regardless of the page type.
395396
page_social_card = (
396397
f"{mkdocs_site_url}{self.social_cards_dir}/"
397-
f"{Path(mkdocs_page.file.src_uri).with_suffix('.png')}"
398+
f"{Path(mkdocs_page.src_uri).with_suffix('.png')}"
398399
)
399400
logger.debug(f"Use social card url: {page_social_card}")
400401

mkdocs_rss_plugin/models.py

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
# ########## Libraries #############
55
# ##################################
66

7+
# for class autoref typing
8+
from __future__ import annotations
79

810
# standard
911
from collections.abc import MutableMapping
1012
from dataclasses import dataclass, field
1113
from datetime import datetime
12-
from email.utils import format_datetime
1314
from pathlib import Path
14-
from typing import Any, Literal, Optional
15+
from typing import Any
1516

1617
# 3rd party
1718
from mkdocs.structure.pages import Page
@@ -28,19 +29,21 @@
2829
class MkdocsPageSubset:
2930
"""Minimal subset of a Mkdocs Page with only necessary attributes for plugin needs."""
3031

32+
abs_src_path: str
3133
dest_uri: str
3234
src_uri: str
33-
title: Optional[str] = None
34-
meta: Optional[MutableMapping[str, Any]] = None
35+
title: str | None = None
36+
meta: MutableMapping[str, Any] | None = None
3537

3638
@classmethod
37-
def from_page(cls, page: Page) -> "MkdocsPageSubset":
39+
def from_page(cls, page: Page) -> MkdocsPageSubset:
3840
"""Create a PageSubset from a Mkdocs page.
3941
4042
Args:
4143
page: MkDocs Page object
4244
"""
4345
return cls(
46+
abs_src_path=page.file.abs_src_path,
4447
meta=page.meta,
4548
title=page.title,
4649
src_uri=page.file.src_uri,
@@ -52,34 +55,40 @@ def from_page(cls, page: Page) -> "MkdocsPageSubset":
5255
class PageInformation:
5356
"""Object describing a page information gathered from Mkdocs and used as feed's item."""
5457

55-
abs_path: Optional[Path] = None
56-
categories: Optional[list] = None
57-
authors: Optional[tuple] = None
58-
created: Optional[datetime] = None
59-
description: Optional[str] = None
60-
guid: Optional[str] = None
61-
image: Optional[str] = None
62-
title: Optional[str] = None
63-
updated: Optional[datetime] = None
64-
url_comments: Optional[str] = None
65-
url_full: Optional[str] = None
66-
_mkdocs_page_ref: Optional[MkdocsPageSubset] = field(
58+
abs_path: Path | None = None
59+
categories: list | None = None
60+
authors: tuple | None = None
61+
comments_url: str | None = None
62+
created: datetime | None = None
63+
description: str | None = None
64+
guid: str | None = None
65+
image: tuple[str, str, int] | None = None
66+
link: str | None = None
67+
pub_date: str | None = None
68+
pub_date_3339: str | None = None
69+
title: str | None = None
70+
updated: datetime | None = None
71+
# private
72+
_mkdocs_page_ref: MkdocsPageSubset | None = field(
6773
default=None, repr=False, compare=False
6874
)
6975

70-
def as_rss_item(self, date_type: Literal["created", "updated"]) -> dict:
71-
"""Return the object as a dictionary formatted for RSS item."""
72-
pub_date: datetime = getattr(self, date_type)
76+
def as_rss_item(self) -> dict:
77+
"""Return the object as a dictionary formatted for RSS item.
78+
79+
Returns:
80+
page as RSS item dict
81+
"""
7382
return {
7483
"authors": self.authors,
7584
"categories": self.categories,
76-
"comments_url": self.url_comments,
85+
"comments_url": self.comments_url,
7786
"description": self.description,
7887
"guid": self.guid,
7988
"image": self.image,
80-
"link": self.url_full,
81-
"pubDate": format_datetime(dt=pub_date),
82-
"pubDate3339": pub_date.isoformat("T"),
89+
"link": self.link,
90+
"pub_date": self.pub_date,
91+
"pubd_date_3339": self.pub_date_3339,
8392
"title": self.title,
8493
}
8594

@@ -88,18 +97,18 @@ def as_rss_item(self, date_type: Literal["created", "updated"]) -> dict:
8897
class RssFeedBase:
8998
"""Object describing a feed."""
9099

91-
author: Optional[str] = None
92-
buildDate: Optional[str] = None
93-
copyright: Optional[str] = None
94-
description: Optional[str] = None
100+
author: str | None = None
101+
buildDate: str | None = None
102+
copyright: str | None = None
103+
description: str | None = None
95104
entries: list[PageInformation] = field(default_factory=list)
96105
generator: str = f"{__title__} - v{__version__}"
97-
html_url: Optional[str] = None
98-
json_url: Optional[str] = None
99-
language: Optional[str] = None
100-
logo_url: Optional[str] = None
101-
pubDate: Optional[str] = None
102-
repo_url: Optional[str] = None
103-
rss_url: Optional[str] = None
104-
title: Optional[str] = None
105-
ttl: Optional[int] = None
106+
html_url: str | None = None
107+
json_url: str | None = None
108+
language: str | None = None
109+
logo_url: str | None = None
110+
pubDate: str | None = None
111+
repo_url: str | None = None
112+
rss_url: str | None = None
113+
title: str | None = None
114+
ttl: int | None = None

mkdocs_rss_plugin/plugin.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from copy import deepcopy
1010
from dataclasses import asdict
1111
from datetime import datetime
12-
from email.utils import formatdate
12+
from email.utils import format_datetime, formatdate
1313
from pathlib import Path
1414
from re import compile as re_compile
1515
from typing import Literal, Optional
@@ -24,7 +24,7 @@
2424
from mkdocs.utils import get_build_timestamp
2525

2626
# package modules
27-
from mkdocs_rss_plugin.__about__ import __title__, __uri__, __version__
27+
from mkdocs_rss_plugin.__about__ import __title__, __version__
2828
from mkdocs_rss_plugin.config import RssPluginConfig
2929
from mkdocs_rss_plugin.constants import (
3030
DEFAULT_TEMPLATE_FILENAME,
@@ -331,22 +331,18 @@ def on_page_content(
331331
categories=self.util.get_categories_from_meta(
332332
in_page=page, categories_labels=self.config.categories
333333
),
334+
comments_url=page_url_comments,
334335
created=page_dates[0],
335336
description=self.util.get_description_or_abstract(
336337
in_page=page,
337338
chars_count=self.config.abstract_chars_count,
338339
abstract_delimiter=self.config.abstract_delimiter,
339340
),
340341
guid=page.canonical_url,
341-
image=self.util.get_image(
342-
in_page=page,
343-
# below let it as old dict get method to handle custom fallback value
344-
base_url=config.get("site_url", __uri__),
345-
),
342+
link=page_url_full,
346343
title=page.title,
347344
updated=page_dates[1],
348-
url_comments=page_url_comments,
349-
url_full=page_url_full,
345+
# for later fetch
350346
_mkdocs_page_ref=MkdocsPageSubset.from_page(page),
351347
)
352348
)
@@ -400,6 +396,32 @@ def on_post_build(self, config: config_options.Config) -> None:
400396
)
401397
)
402398

399+
# load RSS items images (enclosures)
400+
logger.debug(
401+
f"Loading images for {len(self.feed_created.entries)} pages by creation "
402+
f"and {len(self.feed_updated.entries)} pages by update"
403+
)
404+
405+
for page in self.feed_created.entries:
406+
# set pub date
407+
page.pub_date = format_datetime(dt=page.created)
408+
page.pub_date_3339 = page.created.isoformat("T")
409+
# fetch image
410+
if page.image is None:
411+
page.image = self.util.get_image(
412+
in_page=page._mkdocs_page_ref, base_url=config.site_url
413+
)
414+
415+
for page in self.feed_updated.entries:
416+
# set pub date
417+
page.pub_date = format_datetime(dt=page.updated)
418+
page.pub_date_3339 = page.updated.isoformat("T")
419+
# fetch image
420+
if page.image is None:
421+
page.image = self.util.get_image(
422+
in_page=page._mkdocs_page_ref, base_url=config.site_url
423+
)
424+
403425
# RSS
404426
if self.config.rss_feed_enabled:
405427
# write feeds according to the pretty print option
@@ -456,14 +478,14 @@ def on_post_build(self, config: config_options.Config) -> None:
456478
if self.config.json_feed_enabled:
457479
with out_json_created.open(mode="w", encoding="UTF8") as fp:
458480
json.dump(
459-
self.util.feed_to_json(asdict(self.feed_created)),
481+
self.util.feed_to_json(self.feed_created),
460482
fp,
461483
indent=4 if self.config.pretty_print else None,
462484
)
463485

464486
with out_json_updated.open(mode="w", encoding="UTF8") as fp:
465487
json.dump(
466-
self.util.feed_to_json(asdict(self.feed_updated), updated=True),
488+
self.util.feed_to_json(self.feed_updated, updated=True),
467489
fp,
468490
indent=4 if self.config.pretty_print else None,
469491
)

mkdocs_rss_plugin/templates/rss.xml.jinja2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
{% endif %}
4848
<description>{{ item.description|e }}</description>
4949
{% if item.link is not none %}<link>{{ item.link|e }}</link>{% endif %}
50-
<pubDate>{{ item.pubDate }}</pubDate>
50+
<pubDate>{{ item.pub_date }}</pubDate>
5151
{% if item.link is not none %}<source url="{{ feed.rss_url }}">{{ feed.title }}</source>{% endif %}
5252
{% if item.comments_url is not none %}<comments>{{ item.comments_url|e }}</comments>{% endif %}
5353
{% if item.guid is not none %}<guid isPermaLink="true">{{ item.guid }}</guid>{% endif %}

0 commit comments

Comments
 (0)