diff --git a/README.md b/README.md index 20aa668..966a547 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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). \ No newline at end of file diff --git a/docs/available-variables.md b/docs/available-variables.md index b23c42b..04eeb0e 100644 --- a/docs/available-variables.md +++ b/docs/available-variables.md @@ -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). | @@ -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` @@ -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: diff --git a/mkdocs.yml b/mkdocs.yml index ab61ca8..5859daa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -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 \ No newline at end of file diff --git a/src/mkdocs_git_revision_date_localized_plugin/plugin.py b/src/mkdocs_git_revision_date_localized_plugin/plugin.py index eea5727..f0bc549 100644 --- a/src/mkdocs_git_revision_date_localized_plugin/plugin.py +++ b/src/mkdocs_git_revision_date_localized_plugin/plugin.py @@ -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') ) @@ -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, ) @@ -221,6 +221,8 @@ def on_page_markdown( # Add to page meta information, for developers # Include variants without the CSS 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 @@ -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": @@ -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, ) @@ -279,6 +283,8 @@ def on_page_markdown( # Add to page meta information, for developers # Include variants without the CSS 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(): diff --git a/src/mkdocs_git_revision_date_localized_plugin/util.py b/src/mkdocs_git_revision_date_localized_plugin/util.py index 3e2fb14..10b1bd3 100644 --- a/src/mkdocs_git_revision_date_localized_plugin/util.py +++ b/src/mkdocs_git_revision_date_localized_plugin/util.py @@ -16,7 +16,7 @@ NoSuchPathError, ) -from typing import Any, Dict, List +from typing import Dict, List, Tuple logger = logging.getLogger("mkdocs.plugins") @@ -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. @@ -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 @@ -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 @@ -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, @@ -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 "" diff --git a/tests/test_builds.py b/tests/test_builds.py index e9b9fc8..f873aa3 100644 --- a/tests/test_builds.py +++ b/tests/test_builds.py @@ -255,11 +255,12 @@ def validate_build(testproject_path, plugin_config: dict = {}): assert re.search(r"renders as\:\s[|\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, ) @@ -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, @@ -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 ) @@ -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(