Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,12 @@

# mkdocs-git-revision-date-localized-plugin

[MkDocs](https://www.mkdocs.org/) plugin that enables displaying the date of the last git modification of a page. The plugin uses [babel](https://github.com/python-babel/babel/tree/master/babel) and [timeago.js](https://github.com/hustcc/timeago.js) to provide different localized date formats. Initial fork from [mkdocs-git-revision-date-plugin](https://github.com/zhaoterryy/mkdocs-git-revision-date-plugin).
[MkDocs](https://www.mkdocs.org/) plugin that enables displaying the date of the last git modification of a page. The plugin uses [babel](https://github.com/python-babel/babel/tree/master/babel) and [timeago.js](https://github.com/hustcc/timeago.js) to provide different localized date formats. Works with [`mkdocs-material`](https://squidfunk.github.io/mkdocs-material/), see [adding a git repository](https://squidfunk.github.io/mkdocs-material/setup/adding-a-git-repository/).

![demo](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/raw/master/demo_screencast.gif)

(*Example when used together with the [mkdocs-material](https://github.com/squidfunk/mkdocs-material) theme*)

Other related MkDocs plugins:

- [mkdocs-git-authors-plugin](https://github.com/timvink/mkdocs-git-authors-plugin) for displaying the authors from git
- [mkdocs-git-committers-plugin](https://github.com/byrnereese/mkdocs-git-committers-plugin) for displaying authors' github user profiles
- [mkdocs-document-dates](https://github.com/jaywhj/mkdocs-document-dates) for displaying dates based on file creation and modification dates.

## Setup

Install the plugin using `pip3` with the following command:
Expand Down Expand Up @@ -69,3 +63,10 @@ See [timvink.github.io/mkdocs-git-revision-date-localized-plugin](https://timvin
## Contributing

Contributions are very welcome! Please read [CONTRIBUTING.md](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/blob/master/CONTRIBUTING.md) before putting in any work.

## Related MkDocs plugins:

- [mkdocs-git-authors-plugin](https://github.com/timvink/mkdocs-git-authors-plugin) for displaying the authors from git
- [mkdocs-git-committers-plugin-2](https://github.com/ojacques/mkdocs-git-committers-plugin-2) for displaying authors' github user profiles
- [mkdocs-document-dates](https://github.com/jaywhj/mkdocs-document-dates) for displaying dates based on file creation and modification dates.
- Initial fork from [mkdocs-git-revision-date-plugin](https://github.com/zhaoterryy/mkdocs-git-revision-date-plugin).
16 changes: 14 additions & 2 deletions docs/available-variables.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Available variables

This plugin offers the following variables:
This plugin offers the following timestamp variables:

| timestamp | description |
| variable | description |
|:-----------|:------------|
| `git_revision_date_localized` | Last git commit that touched a file. Enabled by default. |
| `git_creation_date_localized` | First git commit that touched a file. Enable in [options](options.md). |
Expand Down Expand Up @@ -33,6 +33,9 @@ To allow for more flexibility when overriding a theme there are also variables f
- `page.meta.git_revision_date_localized_raw_iso_datetime`
- `page.meta.git_revision_date_localized_raw_timeago`
- `page.meta.git_revision_date_localized_raw_custom`

Their are also available on the entire site level:

- `page.meta.git_site_revision_date_localized_raw_datetime`
- `page.meta.git_site_revision_date_localized_raw_iso_date`
- `page.meta.git_site_revision_date_localized_raw_date`
Expand All @@ -49,6 +52,15 @@ And if you've enabled creation date in the config:
- `page.meta.git_creation_date_localized_raw_timeago`
- `page.meta.git_creation_date_localized_raw_custom`

We also expose the git hash and the git tag (empty if not tag associated with the commit):

- `page.meta.git_revision_date_localized_hash`
- `page.meta.git_revision_date_localized_tag`
- `page.meta.git_site_revision_date_localized_hash`
- `page.meta.git_site_revision_date_localized_tag`
- `page.meta.git_creation_date_localized_hash`
- `page.meta.git_creation_date_localized_tag`

!!! warning "timeago.js dependency"

The `*_timeago` variables require the [timeago.js](https://timeago.org/) dependency. This is automatically injected when the [option](options.md) `type: timeago` is set. Alternatively, you can add [timeago.js](https://timeago.org/) using the [`extra_javascript`](https://www.mkdocs.org/user-guide/configuration/#extra_javascript) option of MkDocs:
Expand Down
4 changes: 2 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ markdown_extensions:
- pymdownx.tabbed:
alternate_style: true
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
options:
custom_icons:
- site/overrides/.icons
16 changes: 11 additions & 5 deletions src/mkdocs_git_revision_date_localized_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def on_config(self, config: config_options.Config, **kwargs) -> Dict[str, Any]:
self.util = Util(config=self.config, mkdocs_dir=os.path.abspath(os.path.dirname(config.get('config_file_path'))))

# Save last commit timestamp for entire site
self.last_site_revision_timestamp = self.util.get_git_commit_timestamp(
self.last_site_revision_hash, self.last_site_revision_timestamp = self.util.get_git_commit_timestamp(
config.get('docs_dir')
)

Expand Down Expand Up @@ -201,9 +201,9 @@ def on_page_markdown(
# Retrieve git commit timestamp
# Except for generated pages (f.e. by mkdocs-gen-files plugin)
if getattr(page.file, "generated_by", None):
last_revision_timestamp = int(time.time())
last_revision_hash, last_revision_timestamp = "", int(time.time())
else:
last_revision_timestamp = self.util.get_git_commit_timestamp(
last_revision_hash, last_revision_timestamp = self.util.get_git_commit_timestamp(
path=page.file.abs_src_path,
is_first_commit=False,
)
Expand All @@ -221,6 +221,8 @@ def on_page_markdown(
# Add to page meta information, for developers
# Include variants without the CSS <span> elements (raw date strings)
page.meta["git_revision_date_localized"] = revision_date
page.meta["git_revision_date_localized_hash"] = last_revision_hash
page.meta["git_revision_date_localized_tag"] = self.util.get_tag_name_for_commit(last_revision_hash)
revision_dates_raw = self.util.get_date_formats_for_timestamp(last_revision_timestamp, locale=locale, add_spans=False)
for date_type, date_string in revision_dates_raw.items():
page.meta["git_revision_date_localized_raw_%s" % date_type] = date_string
Expand All @@ -234,6 +236,8 @@ def on_page_markdown(
)

# Also add site last updated information, for developers
page.meta["git_site_revision_date_localized_hash"] = self.last_site_revision_hash
page.meta["git_site_revision_date_localized_tag"] = self.util.get_tag_name_for_commit(self.last_site_revision_hash)
site_dates = self.util.get_date_formats_for_timestamp(self.last_site_revision_timestamp, locale=locale, add_spans=True)
site_date = site_dates[self.config["type"]]
if self.config["type"] == "timeago":
Expand All @@ -260,9 +264,9 @@ def on_page_markdown(
# Retrieve git commit timestamp
# Except for generated pages (f.e. by mkdocs-gen-files plugin)
if getattr(page.file, "generated_by", None):
first_revision_timestamp = int(time.time())
first_revision_hash, first_revision_timestamp = "", int(time.time())
else:
first_revision_timestamp = self.util.get_git_commit_timestamp(
first_revision_hash, first_revision_timestamp = self.util.get_git_commit_timestamp(
path=page.file.abs_src_path,
is_first_commit=True,
)
Expand All @@ -279,6 +283,8 @@ def on_page_markdown(

# Add to page meta information, for developers
# Include variants without the CSS <span> elements (raw date strings)
page.meta["git_creation_date_localized_hash"] = first_revision_hash
page.meta["git_creation_date_localized_tag"] = self.util.get_tag_name_for_commit(first_revision_hash)
page.meta["git_creation_date_localized"] = creation_date
creation_dates_raw = self.util.get_date_formats_for_timestamp(first_revision_timestamp, locale=locale, add_spans=False)
for date_type, date_string in creation_dates_raw.items():
Expand Down
43 changes: 37 additions & 6 deletions src/mkdocs_git_revision_date_localized_plugin/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
NoSuchPathError,
)

from typing import Any, Dict, List
from typing import Dict, List, Tuple

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

Expand Down Expand Up @@ -53,7 +53,7 @@ def get_git_commit_timestamp(
self,
path: str,
is_first_commit: bool = False
) -> int:
) -> Tuple[str, int]:
"""
Get a list of commit dates in unix timestamp, starts with the most recent commit.

Expand All @@ -64,9 +64,10 @@ def get_git_commit_timestamp(
is_first_commit (bool): retrieve commit timestamp when file was created.

Returns:
int: commit date in unix timestamp, starts with the most recent commit.
tuple[str, int]: commit hash and commit date in unix timestamp.
"""
commit_timestamp = ""
commit_hash = ""
n_ignored_commits = 0

# Determine the logging level
Expand Down Expand Up @@ -118,8 +119,8 @@ def get_git_commit_timestamp(
if not line:
commit_timestamp = ""
break
commit, commit_timestamp = line.split(" ")
if not any(commit.startswith(x) for x in self.ignored_commits):
commit_hash, commit_timestamp = line.split(" ")
if not any(commit_hash.startswith(x) for x in self.ignored_commits):
break
else:
n_ignored_commits += 1
Expand Down Expand Up @@ -195,7 +196,7 @@ def get_git_commit_timestamp(
msg += f" (ignored {n_ignored_commits} commits)"
log(msg)

return int(commit_timestamp)
return commit_hash, int(commit_timestamp)

def get_date_formats_for_timestamp(
self,
Expand Down Expand Up @@ -261,3 +262,33 @@ def parse_git_ignore_revs(filename: str) -> List[str]:
logger.error(f"An error occurred while reading the file {filename}: {e}")

return result

def get_tag_name_for_commit(self, commit_hash: str) -> str:
"""
Get the tag name for a specific commit.

Args:
commit_hash (str): The commit hash to find tags for

Returns:
str: Tag name if found, otherwise empty string
"""
if not commit_hash:
return ""

try:
for path, git in self.repo_cache.items():
try:
# Check if there's a tag pointing to this commit
tags = git.tag('--points-at', commit_hash, format='%(refname:short)')
if tags:
# Return first tag if multiple tags exist for the commit
return tags.split('\n')[0]
except GitCommandError:
# Continue checking other repositories in cache
continue

return "" # No tag found for this commit
except Exception as e:
logger.debug(f"Error getting tag for commit {commit_hash}: {str(e)}")
return ""
16 changes: 7 additions & 9 deletions tests/test_builds.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,12 @@ def validate_build(testproject_path, plugin_config: dict = {}):
assert re.search(r"renders as\:\s[<span>|\w].+", contents)

repo = Util(config=plugin_config, mkdocs_dir=testproject_path)
date_formats = repo.get_date_formats_for_timestamp(
commit_timestamp=repo.get_git_commit_timestamp(
commit_hash, commit_timestamp =repo.get_git_commit_timestamp(
path=str(testproject_path / "docs/page_with_tag.md"),
is_first_commit=False,
),
)
date_formats = repo.get_date_formats_for_timestamp(
commit_timestamp,
locale=plugin_config['locale'],
add_spans=True,
)
Expand All @@ -268,10 +269,7 @@ def validate_build(testproject_path, plugin_config: dict = {}):
assert any(searches), "No correct revision date formats output was found"

if plugin_config.get("enable_creation_date"):
commit_timestamp=repo.get_git_commit_timestamp(
path=str(testproject_path / "docs/page_with_tag.md"),
is_first_commit=True,
)
commit_hash, commit_timestamp = repo.get_git_commit_timestamp(path=str(testproject_path / "docs/page_with_tag.md"),is_first_commit=True,)
assert commit_timestamp == 1500854705
date_formats = repo.get_date_formats_for_timestamp(
commit_timestamp=commit_timestamp,
Expand All @@ -283,7 +281,7 @@ def validate_build(testproject_path, plugin_config: dict = {}):
assert any(searches), "No correct creation date formats output was found"

if os.path.exists(str(testproject_path / "docs/subfolder/page_with_renamed.md")):
commit_timestamp=repo.get_git_commit_timestamp(
commit_hash, commit_timestamp=repo.get_git_commit_timestamp(
path=str(testproject_path / "docs/subfolder/page_with_renamed.md"),
is_first_commit=True
)
Expand All @@ -303,7 +301,7 @@ def validate_mkdocs_file(temp_path: str, mkdocs_yml_file: str):
)
setup_commit_history(testproject_path)
result = build_docs_setup(testproject_path)
assert result.exit_code == 0, "'mkdocs build' command failed"
assert result.exit_code == 0, f"'mkdocs build' command failed with output:\n{result.stdout}"

# validate build with locale retrieved from mkdocs config file
validate_build(
Expand Down
Loading