Skip to content

Commit 2ddde87

Browse files
authored
Merge pull request #50 from PegasisForever/git_creation_date_localized
Add {{git_creation_date_localized}}
2 parents 654a126 + f3595b7 commit 2ddde87

File tree

6 files changed

+159
-26
lines changed

6 files changed

+159
-26
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ plugins:
120120
timezone: Europe/Amsterdam
121121
locale: en
122122
fallback_to_build_date: false
123+
enable_creation_date: true
123124
exclude:
124125
- index.md
125126
```
@@ -152,6 +153,10 @@ Default is `None`. Specify a two letter [ISO639](https://en.wikipedia.org/wiki/L
152153

153154
Default is `false`. If set to `true` the plugin will use the time at `mkdocs build` instead of the file's last git revision date *when git is not available*. This means the revision date can be incorrect, but this can be acceptable if you want your project to also successfully build in environments with no access to GIT.
154155

156+
### `enable_creation_date`
157+
158+
Default is `false`. If set to `true`, you will be able to use `{{git_creation_date_localized}}` in markdown files and `page.meta.git_creation_date_localized` in page templates.
159+
155160
### `exclude`
156161

157162
Default is empty. Specify a list of page source paths (one per line) that should not have a revision date included (excluded from processing by this plugin). This can be useful for example to remove the revision date from the front page. The source path of a page is relative to your `docs/` folder. You can also use [globs](https://docs.python.org/3/library/glob.html) instead of full source paths. To exclude `docs/subfolder/page.md` specify in your `mkdocs.yml` a line under `exclude:` with `- subfolder/page.md`. Some examples:

mkdocs_git_revision_date_localized_plugin/plugin.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class GitRevisionDateLocalizedPlugin(BasePlugin):
3737
("type", config_options.Type(str, default="date")),
3838
("timezone", config_options.Type(str, default="UTC")),
3939
("exclude", config_options.Type(list, default=[])),
40+
("enable_creation_date", config_options.Type(bool, default=False)),
4041
)
4142

4243
def on_config(self, config: config_options.Config, **kwargs) -> Dict[str, Any]:
@@ -147,11 +148,15 @@ def on_page_markdown(
147148
logging.debug("Excluding page " + page.file.src_path)
148149
return markdown
149150

151+
# revision date
150152
revision_dates = self.util.get_revision_date_for_file(
151-
path=page.file.abs_src_path,
153+
commit_timestamp=self.util.get_git_commit_timestamp(
154+
path=page.file.abs_src_path,
155+
is_first_commit=False,
156+
fallback_to_build_date=self.config.get("fallback_to_build_date"),
157+
),
152158
locale=self.config.get("locale", "en"),
153159
time_zone=self.config.get("time_zone", "UTC"),
154-
fallback_to_build_date=self.config.get("fallback_to_build_date"),
155160
)
156161
revision_date = revision_dates[self.config["type"]]
157162

@@ -162,13 +167,39 @@ def on_page_markdown(
162167
revision_date += revision_dates["iso_date"]
163168

164169
page.meta["git_revision_date_localized"] = revision_date
165-
return re.sub(
170+
markdown = re.sub(
166171
r"\{\{\s*[page\.meta\.]*git_revision_date_localized\s*\}\}",
167172
revision_date,
168173
markdown,
169174
flags=re.IGNORECASE,
170175
)
171176

177+
# Creation date
178+
if self.config.get("enable_creation_date"):
179+
creation_dates = self.util.get_creation_date_for_file(
180+
commit_timestamp=self.util.get_git_commit_timestamp(
181+
path=page.file.abs_src_path,
182+
is_first_commit=True,
183+
fallback_to_build_date=self.config.get("fallback_to_build_date"),
184+
),
185+
locale=self.config.get("locale", "en"),
186+
time_zone=self.config.get("time_zone", "UTC"),
187+
)
188+
creation_date = creation_dates[self.config["type"]]
189+
190+
if self.config["type"] == "timeago":
191+
creation_date += creation_dates["iso_date"]
192+
193+
page.meta["git_creation_date_localized"] = creation_date
194+
markdown = re.sub(
195+
r"\{\{\s*[page\.meta\.]*git_creation_date_localized\s*\}\}",
196+
creation_date,
197+
markdown,
198+
flags=re.IGNORECASE,
199+
)
200+
201+
return markdown
202+
172203
def on_post_build(self, config: Dict[str, Any], **kwargs) -> None:
173204
"""
174205
Run on post build.

mkdocs_git_revision_date_localized_plugin/util.py

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from babel.dates import format_date, get_timezone
1010
from git import (
1111
Repo,
12+
Git,
1213
GitCommandError,
1314
GitCommandNotFound,
1415
InvalidGitRepositoryError,
@@ -32,7 +33,7 @@ def __init__(self, config={}):
3233
self.config = config
3334
self.repo_cache = {}
3435

35-
def _get_repo(self, path: str):
36+
def _get_repo(self, path: str) -> Git:
3637
if not os.path.isdir(path):
3738
path = os.path.dirname(path)
3839

@@ -78,35 +79,41 @@ def _date_formats(
7879
% (loc_revision_date.isoformat(), locale),
7980
}
8081

81-
def get_revision_date_for_file(
82-
self,
83-
path: str,
84-
locale: str = "en",
85-
time_zone: str = "UTC",
86-
fallback_to_build_date: bool = False,
87-
) -> Dict[str, str]:
82+
def get_git_commit_timestamp(
83+
self,
84+
path: str,
85+
is_first_commit: bool,
86+
fallback_to_build_date: bool = False,
87+
) -> int:
8888
"""
89-
Determine localized date variants for a given file.
89+
Get a list of commit dates in unix timestamp, starts with the most recent commit.
9090
9191
Args:
92+
is_first_commit (bool): if true, get the timestamp of the first commit,
93+
else, get that of the most recent commit.
9294
path (str): Location of a markdown file that is part of a Git repository.
93-
locale (str, optional): Locale code of language to use. Defaults to 'en'.
94-
timezone (str): Timezone database name (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
9595
9696
Returns:
97-
dict: Localized date variants.
97+
list: commit dates in unix timestamp, starts with the most recent commit.
9898
"""
99-
unix_timestamp = None
99+
100+
commit_timestamp = ""
100101

101102
# perform git log operation
102103
try:
103104
if not self.fallback_enabled:
104105
# Retrieve author date in UNIX format (%at)
105106
# https://git-scm.com/docs/git-log#Documentation/git-log.txt-ematem
106107
realpath = os.path.realpath(path)
107-
unix_timestamp = self._get_repo(realpath).log(
108-
realpath, n=1, date="short", format="%at"
109-
)
108+
git = self._get_repo(realpath)
109+
if is_first_commit:
110+
commit_timestamp = git.log(
111+
realpath, date="short", format="%at", diff_filter="A"
112+
)
113+
else:
114+
commit_timestamp = git.log(
115+
realpath, date="short", format="%at", n=1
116+
)
110117
except (InvalidGitRepositoryError, NoSuchPathError) as err:
111118
if fallback_to_build_date:
112119
logger.warning(
@@ -147,16 +154,36 @@ def get_revision_date_for_file(
147154
raise err
148155

149156
# create timestamp
150-
if not unix_timestamp:
151-
unix_timestamp = time.time()
157+
if commit_timestamp == "":
158+
commit_timestamp = time.time()
152159
if not self.fallback_enabled:
153160
logger.warning(
154161
"[git-revision-date-localized-plugin] '%s' has no git logs, using current timestamp"
155162
% path
156163
)
157164

165+
return int(commit_timestamp)
166+
167+
def get_revision_date_for_file(
168+
self,
169+
commit_timestamp: int,
170+
locale: str = "en",
171+
time_zone: str = "UTC",
172+
) -> Dict[str, str]:
173+
"""
174+
Determine localized date variants for a given file.
175+
176+
Args:
177+
commit_timestamp (int): most recent commit date in unix timestamp.
178+
locale (str, optional): Locale code of language to use. Defaults to 'en'.
179+
time_zone (str): Timezone database name (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
180+
181+
Returns:
182+
dict: Localized date variants.
183+
"""
184+
158185
date_formats = self._date_formats(
159-
unix_timestamp=unix_timestamp, time_zone=time_zone, locale=locale
186+
unix_timestamp=commit_timestamp, time_zone=time_zone, locale=locale
160187
)
161188

162189
# Wrap in <span> for styling
@@ -167,3 +194,34 @@ def get_revision_date_for_file(
167194
)
168195

169196
return date_formats
197+
198+
def get_creation_date_for_file(
199+
self,
200+
commit_timestamp: int,
201+
locale: str = "en",
202+
time_zone: str = "UTC",
203+
) -> Dict[str, str]:
204+
"""
205+
Determine localized date variants for a given file.
206+
207+
Args:
208+
commit_timestamp (int): the first commit date in unix timestamp.
209+
locale (str, optional): Locale code of language to use. Defaults to 'en'.
210+
time_zone (str): Timezone database name (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
211+
212+
Returns:
213+
dict: Localized date variants.
214+
"""
215+
216+
date_formats = self._date_formats(
217+
unix_timestamp=commit_timestamp, time_zone=time_zone, locale=locale
218+
)
219+
220+
# Wrap in <span> for styling
221+
for date_type, date_string in date_formats.items():
222+
date_formats[date_type] = (
223+
'<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-%s">%s</span>'
224+
% (date_type, date_string)
225+
)
226+
227+
return date_formats
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# test page
22

33
Tag <mark>\{\{ git_revision_date_localized \}\}</mark> renders as: {{ git_revision_date_localized }}
4+
5+
Tag <mark>\{\{ git_creation_date_localized \}\}</mark> renders as: {{ git_creation_date_localized }}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
site_name: test gitrevisiondatelocalized_plugin
2+
use_directory_urls: true
3+
4+
plugins:
5+
- search
6+
- git-revision-date-localized:
7+
enable_creation_date: True

tests/test_builds.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ def setup_commit_history(testproject_path):
120120
os.chdir(testproject_path)
121121

122122
try:
123+
repo.git.add("docs/page_with_tag.md")
124+
repo.git.commit(message="add homepage", author=author, date="1500854705 -0700")
125+
123126
repo.git.add("mkdocs.yml")
124127
repo.git.commit(message="add mkdocs", author=author)
125128

@@ -139,8 +142,12 @@ def setup_commit_history(testproject_path):
139142
repo.git.commit(message="second page", author=author)
140143
repo.git.add("docs/index.md")
141144
repo.git.commit(message="homepage", author=author)
145+
146+
file_name = os.path.join(testproject_path, "docs/page_with_tag.md")
147+
with open(file_name, "a") as the_file:
148+
the_file.write("awa\n")
142149
repo.git.add("docs/page_with_tag.md")
143-
repo.git.commit(message="homepage", author=author)
150+
repo.git.commit(message="update homepage", author=author)
144151
os.chdir(cwd)
145152
except:
146153
os.chdir(cwd)
@@ -195,13 +202,31 @@ def validate_build(testproject_path, plugin_config: dict = {}):
195202

196203
repo = Util(str(testproject_path / "docs"))
197204
date_formats = repo.get_revision_date_for_file(
198-
path=str(testproject_path / "docs/page_with_tag.md"),
205+
commit_timestamp=repo.get_git_commit_timestamp(
206+
path=str(testproject_path / "docs/page_with_tag.md"),
207+
is_first_commit=False,
208+
fallback_to_build_date=plugin_config.get("fallback_to_build_date"),
209+
),
199210
locale=plugin_config.get("locale"), # type: ignore
200-
fallback_to_build_date=plugin_config.get("fallback_to_build_date"), # type: ignore
201211
)
202212

203213
searches = [x in contents for x in date_formats.values()]
204-
assert any(searches), "No correct date formats output was found"
214+
assert any(searches), "No correct revision date formats output was found"
215+
216+
if plugin_config.get("enable_creation_date"):
217+
commit_timestamp=repo.get_git_commit_timestamp(
218+
path=str(testproject_path / "docs/page_with_tag.md"),
219+
is_first_commit=True,
220+
fallback_to_build_date=plugin_config.get("fallback_to_build_date"),
221+
)
222+
assert commit_timestamp == 1500854705
223+
date_formats = repo.get_revision_date_for_file(
224+
commit_timestamp=commit_timestamp,
225+
locale=plugin_config.get("locale"), # type: ignore
226+
)
227+
228+
searches = [x in contents for x in date_formats.values()]
229+
assert any(searches), "No correct creation date formats output was found"
205230

206231

207232
def validate_mkdocs_file(temp_path: str, mkdocs_yml_file: str):
@@ -270,6 +295,11 @@ def test_build_no_options(tmp_path):
270295
validate_mkdocs_file(tmp_path, "tests/fixtures/basic_project/mkdocs.yml")
271296

272297

298+
def test_build_creation_date(tmp_path):
299+
# Enable plugin with no extra options set
300+
validate_mkdocs_file(tmp_path, "tests/fixtures/basic_project/mkdocs_creation_date.yml")
301+
302+
273303
def test_build_locale_plugin(tmp_path):
274304
# Enable plugin with plugin locale set to 'nl'
275305
validate_mkdocs_file(

0 commit comments

Comments
 (0)