Skip to content

Commit

Permalink
Added "recent posts" page instead of showing some on the main page
Browse files Browse the repository at this point in the history
  • Loading branch information
McDic committed May 13, 2024
1 parent 87f8585 commit d593186
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 99 deletions.
4 changes: 1 addition & 3 deletions custom_plugin_blog/mkdocs_material_mcdic/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ class McDicBlogPluginGitDateConfig(Config):
"""

format = ConfigOptions.Type(str, default="%Y/%b/%d %H:%M:%S %Z")
# 5 posts are always displayed in index
minimum_display = ConfigOptions.Type(int, default=5)
old_criteria = ConfigOptions.Type(int, default=7) # Default 1 week


class McDicBlogPluginConfig(Config):
Expand All @@ -31,3 +28,4 @@ class McDicBlogPluginConfig(Config):
enabled = ConfigOptions.Type(bool, default=True)
post_views = ConfigOptions.SubConfig(McDicBlogPluginPostViewsConfig)
git_dates = ConfigOptions.SubConfig(McDicBlogPluginGitDateConfig)
historical_batch = ConfigOptions.Type(int, default=10)
1 change: 1 addition & 0 deletions custom_plugin_blog/mkdocs_material_mcdic/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@
r"^posts\/[a-zA-Z\-]+\/[a-zA-Z\-]*[0-9]+\.md$"
)
RE_POSTINDEX_FINDER: typing.Final[re.Pattern] = re.compile(r"^series\/[a-zA-Z\-]+\.md$")
RE_RECENTPOSTS_FINDER: typing.Final[re.Pattern] = re.compile(r"^recent\/[0-9]+\.md$")
204 changes: 108 additions & 96 deletions custom_plugin_blog/mkdocs_material_mcdic/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ def __init__(self) -> None:
self._build_mode: typing.Literal["gh-deploy", "serve", "build"]
self._root_found_on_nav: bool = False
self._series_section: Section = Section("Series", [])
self._recent_section: Section = Section("Recent Posts", [])
self._non_recent_posts_age: timedelta = timedelta(days=1)
self._temp_dir: tempfile.TemporaryDirectory
self._cached_sorted_pages_by_date: list[Page] = []

def _make_new_tempdir(self) -> None:
"""
Expand Down Expand Up @@ -109,6 +111,15 @@ def _is_series_index_page(self, page: Page) -> bool:
and Path(page.file.abs_src_path).is_relative_to(self._temp_dir.name)
)

def _is_recent_posts_page(self, page: Page) -> bool:
"""
Return if given `page` is a recent posts page.
"""
return bool(
constants.RE_RECENTPOSTS_FINDER.match(page.file.src_path)
and Path(page.file.abs_src_path).is_relative_to(self._temp_dir.name)
)

@staticmethod
def aggregate_views(obj0: ViewDataValue, *objs: ViewDataValue) -> ViewDataValue:
"""
Expand Down Expand Up @@ -145,6 +156,37 @@ def get_category(
else:
return page.title.split(".")[0].split(" ")[0]

def _link_recent_pages(self, files: Files):
"""
Link prev/next pages between recent pages.
"""

target_pages: list[tuple[int, Page]] = []
for file in files.documentation_pages():
page = file.page
if page is not None and self._is_recent_posts_page(page):
index = int(file.src_path.split("/")[-1].replace(".md", ""))
target_pages.append((index, page))

target_pages_sorted: list[Page] = [page for _i, page in sorted(target_pages)]
for i, page in enumerate(target_pages_sorted):
if i > 0:
page.previous_page = target_pages_sorted[i - 1]
if i + 1 < len(target_pages):
page.next_page = target_pages_sorted[i + 1]

self._recent_section.children = []
for page in target_pages_sorted:
self._recent_section.children.append(page)
page.parent = self._recent_section

for file in files.documentation_pages():
page = file.page
if page is not None and page.is_index:
target_pages_sorted[0].previous_page = page
page.next_page = target_pages_sorted[0]
break

def _load_series_by_categories(self, files: Files):
"""
Load series by categories.
Expand Down Expand Up @@ -310,13 +352,6 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig | None:
"""
Validate configs in this step.
"""
if self.config.git_dates.minimum_display < 0:
raise PluginError(
"Config's minimum_display_recent_posts should be non-negative"
)
elif self.config.git_dates.old_criteria < 1:
raise PluginError("Config's non_recent_posts_age should be positive")
self._non_recent_posts_age = timedelta(self.config.git_dates.old_criteria)
return None

@event_priority(constants.EARLY_EVENT_PRIORITY)
Expand All @@ -338,8 +373,10 @@ def on_files(self, files: Files, *, config: MkDocsConfig) -> Files | None:

# Manipulate individual series post
used_series: set[str] = set()
posts_num: int = 0
for file in files.documentation_pages():
if constants.RE_POST_FINDER.match(file.src_path):
posts_num += 1
_, series, filename = file.src_path.split("/")
index: int = int(filename.replace(series, "").replace(".md", ""))
file.dest_uri = f"series/{series}/{index}/index.html"
Expand All @@ -357,6 +394,11 @@ def on_files(self, files: Files, *, config: MkDocsConfig) -> Files | None:
)
)

# Create recent posts page
assert posts_num > 0
for i in range((posts_num - 1) // self.config.historical_batch + 1):
files.append(self._create_tempfile(config, "recent", f"{i+1}.md"))

# Move root file to back
root_file = files.get_file_from_path(constants.INDEX_SRC_URI)
if root_file is None:
Expand Down Expand Up @@ -435,7 +477,7 @@ def datestr(d: str | None, commit: str | None) -> str:

def _modify_markdown_on_series_index_page(
self, markdown: str, series: str, files: Files, config: MkDocsConfig
):
) -> str:
"""
Return a modified markdown text of series index page.
"""
Expand All @@ -455,93 +497,55 @@ def _modify_markdown_on_series_index_page(
joinlist.extend(self._get_page_excerpt(post, config))
return "\n\n".join(joinlist)

def _modify_markdown_on_root_page(
self, markdown: str, files: Files, config: MkDocsConfig
) -> str:
def _get_sorted_pages_by_date(self, files: Files) -> list[Page]:
"""
Return a modified markdown text of root page.
Initially I tried following;
```python
self.set_page_additional_meta_contents(
root_page, "root_page_only", "recent_posts", value=posts
)
```
```jinja
{% if page.is_index %}
<h2> Recently Updated Posts </h2>
{% for post in page.meta.additional_contents.root_page_only.recent_posts %}
<hr>
<h3> {{ post.title }} </h3>
{{ post.content }}
{% endfor %}
{% endif %}
```
and then I noticed this way is not compatible
with side navigation at all.
"""
now = datetime.now(tz=pytz.UTC)
posts: list[Page] = sorted(
(
file.page
for file in files.documentation_pages()
if file.page is not None and self._is_blog_post_page(file.page)
),
reverse=True,
key=(
lambda post: (
dict_get(
post.meta, "date", "updated_raw", default=constants.MIN_DATETIME
),
dict_get(post.meta, "date", "original_raw")
or dict_get(
post.meta, "date", "created_raw", default=constants.MIN_DATETIME
),
post.title,
)
),
)
joinlist: list[str] = [markdown]
for i, post in enumerate(posts):
if post.markdown is None:
raise PluginError(
(
'Post "%s" doesn\'t have any markdown yet, '
"when the root page is expected to be "
"processed at last"
Create a sorted pages by updated/created date, and cache/return it.
If this is already cached, return it without doing anything.
"""
if not self._cached_sorted_pages_by_date:
self._cached_sorted_pages_by_date = sorted(
(
file.page
for file in files.documentation_pages()
if file.page is not None and self._is_blog_post_page(file.page)
),
reverse=True,
key=(
lambda post: (
dict_get(
post.meta,
"date",
"updated_raw",
default=constants.MIN_DATETIME,
),
dict_get(post.meta, "date", "original_raw")
or dict_get(
post.meta,
"date",
"created_raw",
default=constants.MIN_DATETIME,
),
post.title,
)
% (post.title,)
)
elif (
i >= self.config.git_dates.minimum_display
and dict_get(
post.meta, "date", "updated_raw", default=constants.MIN_DATETIME
)
+ self._non_recent_posts_age
< now
):
posts = posts[:i]
break

joinlist.append(
constants.INDEX_RECENTLY_UPDATED_POSTS
% (
self.config.git_dates.minimum_display,
self.config.git_dates.old_criteria,
)
)
for post in posts:
logger.debug(
"Embedding %s(date=%s) on index..",
post.title,
dict_get(post.meta, "date", "updated_raw", default=None),
),
)
joinlist.append("---")
joinlist.extend(self._get_page_excerpt(post, config))
return self._cached_sorted_pages_by_date

logger.debug("Created joinlist for index page")
def _modify_markdown_on_recent_posts_page(
self, index: int, markdown: str, files: Files, config: MkDocsConfig
) -> str:
"""
Return a modified markdown text for recent posts page.
"""
sorted_pages = self._get_sorted_pages_by_date(files)
prev_index = (index - 1) * self.config.historical_batch
next_index = prev_index + self.config.historical_batch
if next_index > len(sorted_pages):
next_index = len(sorted_pages)
joinlist = ["# Recent Posts #%d..#%d" % (prev_index + 1, next_index)]
for page in sorted_pages[prev_index:next_index]:
joinlist.extend(self._get_page_excerpt(page, config))
joinlist.append("---")
return "\n\n".join(joinlist)

@event_priority(constants.LATE_EVENT_PRIORITY)
Expand Down Expand Up @@ -619,17 +623,20 @@ def on_page_markdown(
% (page.title, constants.EXCERPT_DIVIDER)
)

# If post index?
# If series index?
elif self._is_series_index_page(page):
page.meta["no_comments"] = True
series: str = page.file.src_uri.split("/")[-1].replace(".md", "").upper()
return self._modify_markdown_on_series_index_page(
markdown, series, files, config
)

# If root index page?
elif page.is_index:
return self._modify_markdown_on_root_page(markdown, files, config)
elif self._is_recent_posts_page(page):
index = int(page.file.src_uri.split("/")[-1].replace(".md", ""))
page.meta["no_comments"] = True
return self._modify_markdown_on_recent_posts_page(
index, markdown, files, config
)

# If it is migrated?
elif dict_get(page.meta, "date", "original"):
Expand All @@ -653,7 +660,11 @@ def _modify_nav_on_root_page(self, section: Navigation | Section):
raise PluginError("Found duplicated root page entries")
logger.debug("Entry of root page found: %s", item)
self._root_found_on_nav = True
iterable.insert(i + 1, self._series_section)
iterable.insert(i + 1, self._recent_section)
self._recent_section.parent = (
section if isinstance(section, Section) else None
)
iterable.insert(i + 2, self._series_section)
self._series_section.parent = (
section if isinstance(section, Section) else None
)
Expand Down Expand Up @@ -684,6 +695,7 @@ def on_env(
- Alter global navigation and prev/next page buttons of each page.
"""
self._load_series_by_categories(files)
self._link_recent_pages(files)
return None

@event_priority(constants.LATE_EVENT_PRIORITY)
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ Please note that most articles here are written in Korean.

**Every article in this blog is owned by Minsung Kim and**
**licensed by [CC BY-NC 4.0 DEED](https://creativecommons.org/licenses/by-nc/4.0/deed).**

To read recent posts in this blog, please go [here](../recent/1).
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ plugins:
forced_update: false
git_dates:
format: "%b %d, %Y"
historical_batch: 10
- git-revision-date-localized:
enabled: false
enable_creation_date: true
Expand Down

0 comments on commit d593186

Please sign in to comment.