mkdocs-document-dates 3.7.4__tar.gz → 3.8.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mkdocs_document_dates-3.7.4/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.8.1}/PKG-INFO +5 -3
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/README.md +4 -2
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/cache_manager.py +41 -30
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/plugin.py +54 -66
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/utils.py +79 -38
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1/mkdocs_document_dates.egg-info}/PKG-INFO +5 -3
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/pyproject.toml +1 -1
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/setup.py +1 -1
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/LICENSE +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/MANIFEST.in +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/__init__.py +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/hooks_installer.py +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/.DS_Store +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/config/user.config.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/config/user.config.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/core.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/core.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/default.config.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/md5.min.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/core/utils.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/templates/recently_updated_detail.html +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/templates/recently_updated_grid.html +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/templates/recently_updated_group.html +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/templates/recently_updated_list.html +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates.egg-info/SOURCES.txt +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/setup.cfg +0 -0
{mkdocs_document_dates-3.7.4/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.8.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs-document-dates
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.1
|
|
4
4
|
Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
|
|
5
5
|
Author-email: Aaron Wang <aaronwqt@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,6 +44,8 @@ A new generation MkDocs plugin for displaying exact **creation date, last update
|
|
|
44
44
|
| git-revision-date-localized<br />git-authors | > 3 s | > 30 s | O(n) |
|
|
45
45
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
|
46
46
|
|
|
47
|
+
> It's 20-500 times faster than `git-revision-date-localized` and `git-authors`
|
|
48
|
+
|
|
47
49
|
## Installation
|
|
48
50
|
|
|
49
51
|
```bash
|
|
@@ -82,8 +84,8 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
82
84
|
- [Structure and Style](https://jaywhj.netlify.app/document-dates-en#Structure-and-Style): You can freely configure the plugin's display structure in mkdocs.yml or Front Matter. You can quickly set the plugin styles through preset entrances, such as icons, themes, colors, fonts, animations, dividing line and so on
|
|
83
85
|
- [Template Variables](https://jaywhj.netlify.app/document-dates-en#Template-Variables): Can be used to optimize `sitemap.xml` for site SEO
|
|
84
86
|
- [Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Recently-Updated-Module): Enable list of recently updated documents (in descending order of update date), this is ideal for sites with a large number of documents, so that readers can quickly see what's new
|
|
85
|
-
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
86
|
-
- [
|
|
87
|
+
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
88
|
+
- [Developer API](https://jaywhj.netlify.app/document-dates-en#Developer-API): Provides a date data API for developers, making it easy to retrieve exact dates in other plugins or hooks
|
|
87
89
|
|
|
88
90
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
89
91
|
|
|
@@ -26,6 +26,8 @@ A new generation MkDocs plugin for displaying exact **creation date, last update
|
|
|
26
26
|
| git-revision-date-localized<br />git-authors | > 3 s | > 30 s | O(n) |
|
|
27
27
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
|
28
28
|
|
|
29
|
+
> It's 20-500 times faster than `git-revision-date-localized` and `git-authors`
|
|
30
|
+
|
|
29
31
|
## Installation
|
|
30
32
|
|
|
31
33
|
```bash
|
|
@@ -64,8 +66,8 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
64
66
|
- [Structure and Style](https://jaywhj.netlify.app/document-dates-en#Structure-and-Style): You can freely configure the plugin's display structure in mkdocs.yml or Front Matter. You can quickly set the plugin styles through preset entrances, such as icons, themes, colors, fonts, animations, dividing line and so on
|
|
65
67
|
- [Template Variables](https://jaywhj.netlify.app/document-dates-en#Template-Variables): Can be used to optimize `sitemap.xml` for site SEO
|
|
66
68
|
- [Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Recently-Updated-Module): Enable list of recently updated documents (in descending order of update date), this is ideal for sites with a large number of documents, so that readers can quickly see what's new
|
|
67
|
-
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
68
|
-
- [
|
|
69
|
+
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
70
|
+
- [Developer API](https://jaywhj.netlify.app/document-dates-en#Developer-API): Provides a date data API for developers, making it easy to retrieve exact dates in other plugins or hooks
|
|
69
71
|
|
|
70
72
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
71
73
|
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/cache_manager.py
RENAMED
|
@@ -10,13 +10,19 @@ from .utils import read_jsonl_cache, write_jsonl_cache, load_file_creation_date,
|
|
|
10
10
|
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
|
11
11
|
_LOGGING_CONFIGURED = False
|
|
12
12
|
|
|
13
|
+
CONFIG_PRIORITY = {
|
|
14
|
+
"mkdocs.yml": 0,
|
|
15
|
+
"properdocs.yml": 1,
|
|
16
|
+
"mkdocs.yaml": 2,
|
|
17
|
+
"properdocs.yaml": 3,
|
|
18
|
+
}
|
|
13
19
|
|
|
14
20
|
def _default_log_file() -> Path:
|
|
15
21
|
try:
|
|
16
22
|
git_root = Path(subprocess.check_output(
|
|
17
|
-
[
|
|
23
|
+
["git", "rev-parse", "--show-toplevel"],
|
|
18
24
|
env=_clean_git_env(),
|
|
19
|
-
encoding=
|
|
25
|
+
encoding="utf-8"
|
|
20
26
|
).strip())
|
|
21
27
|
base_dir = git_root
|
|
22
28
|
except Exception:
|
|
@@ -82,20 +88,29 @@ def _clean_git_env():
|
|
|
82
88
|
|
|
83
89
|
return env
|
|
84
90
|
|
|
85
|
-
def find_mkdocs_projects():
|
|
86
|
-
projects =
|
|
91
|
+
def find_mkdocs_projects() -> dict[Path, Path]:
|
|
92
|
+
projects = {}
|
|
87
93
|
|
|
88
94
|
try:
|
|
89
95
|
git_root = Path(subprocess.check_output(
|
|
90
|
-
[
|
|
96
|
+
["git", "rev-parse", "--show-toplevel"],
|
|
91
97
|
env=_clean_git_env(),
|
|
92
|
-
encoding=
|
|
98
|
+
encoding="utf-8"
|
|
93
99
|
).strip())
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
for pattern in ("*.yml", "*.yaml"):
|
|
102
|
+
for config_file in git_root.rglob(pattern):
|
|
103
|
+
name = config_file.name.lower()
|
|
104
|
+
if name not in CONFIG_PRIORITY:
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
project_dir = config_file.parent
|
|
108
|
+
existing = projects.get(project_dir)
|
|
109
|
+
if existing is None:
|
|
110
|
+
projects[project_dir] = config_file
|
|
111
|
+
continue
|
|
112
|
+
if CONFIG_PRIORITY[name] < CONFIG_PRIORITY[existing.name.lower()]:
|
|
113
|
+
projects[project_dir] = config_file
|
|
99
114
|
|
|
100
115
|
if not projects:
|
|
101
116
|
logger.warning("No MkDocs/ProperDocs projects found in the repository")
|
|
@@ -105,19 +120,19 @@ def find_mkdocs_projects():
|
|
|
105
120
|
except Exception as e:
|
|
106
121
|
logger.error(f"Unexpected error while searching for projects: {e}")
|
|
107
122
|
|
|
108
|
-
return
|
|
123
|
+
return projects
|
|
109
124
|
|
|
110
125
|
def setup_gitattributes(docs_dir: Path):
|
|
111
126
|
try:
|
|
112
|
-
gitattributes_path = docs_dir /
|
|
127
|
+
gitattributes_path = docs_dir / ".gitattributes"
|
|
113
128
|
union_merge_line = ".dates_cache.jsonl merge=union"
|
|
114
129
|
# custom_merge_line = ".dates_cache.json merge=custom_json_merge"
|
|
115
|
-
content = gitattributes_path.read_text(encoding=
|
|
130
|
+
content = gitattributes_path.read_text(encoding="utf-8") if gitattributes_path.exists() else ""
|
|
116
131
|
if union_merge_line not in content:
|
|
117
|
-
if content and not content.endswith(
|
|
118
|
-
content +=
|
|
132
|
+
if content and not content.endswith("\n"):
|
|
133
|
+
content += "\n"
|
|
119
134
|
content += f"{union_merge_line}\n"
|
|
120
|
-
gitattributes_path.write_text(content, encoding=
|
|
135
|
+
gitattributes_path.write_text(content, encoding="utf-8")
|
|
121
136
|
subprocess.run(["git", "add", str(gitattributes_path)], cwd=docs_dir, env=_clean_git_env(), check=True)
|
|
122
137
|
logger.info(f"Updated .gitattributes file: {gitattributes_path}")
|
|
123
138
|
return True
|
|
@@ -134,18 +149,14 @@ def update_cache():
|
|
|
134
149
|
configure_file_logging(_default_log_file())
|
|
135
150
|
|
|
136
151
|
global_updated = False
|
|
137
|
-
for project_dir in find_mkdocs_projects():
|
|
152
|
+
for project_dir, mkdocs_yml in find_mkdocs_projects().items():
|
|
138
153
|
try:
|
|
139
154
|
project_updated = False
|
|
140
155
|
|
|
141
|
-
docs_dir = project_dir /
|
|
156
|
+
docs_dir = project_dir / "docs"
|
|
142
157
|
|
|
143
158
|
# 从 mkdocs.yml 中读取 docs_dir 配置覆盖默认值
|
|
144
159
|
try:
|
|
145
|
-
mkdocs_yml = project_dir / "properdocs.yml"
|
|
146
|
-
if not mkdocs_yml.exists():
|
|
147
|
-
mkdocs_yml = project_dir / "mkdocs.yml"
|
|
148
|
-
|
|
149
160
|
mkdocs_config = yaml.load(
|
|
150
161
|
mkdocs_yml.read_text(encoding="utf-8"),
|
|
151
162
|
Loader=yaml.BaseLoader,
|
|
@@ -156,16 +167,16 @@ def update_cache():
|
|
|
156
167
|
except (IOError, OSError, yaml.YAMLError) as e:
|
|
157
168
|
logger.warning(f"Failed to read docs_dir: {e}")
|
|
158
169
|
|
|
159
|
-
if not docs_dir.
|
|
170
|
+
if not docs_dir.is_dir():
|
|
160
171
|
logger.info(f"Document directory does not exist: {docs_dir}")
|
|
161
172
|
continue
|
|
162
173
|
|
|
163
174
|
# 设置.gitattributes文件
|
|
164
|
-
global_updated
|
|
175
|
+
global_updated |= setup_gitattributes(docs_dir)
|
|
165
176
|
|
|
166
177
|
# 获取docs目录下已跟踪(tracked)的markdown文件
|
|
167
|
-
cmd = ["git", "ls-files", "*.md"]
|
|
168
|
-
result = subprocess.run(cmd, cwd=docs_dir, env=_clean_git_env(), capture_output=True, encoding=
|
|
178
|
+
cmd = ["git", "-c", "core.quotepath=false", "ls-files", "*.md"]
|
|
179
|
+
result = subprocess.run(cmd, cwd=docs_dir, env=_clean_git_env(), capture_output=True, encoding="utf-8")
|
|
169
180
|
tracked_files = result.stdout.splitlines() if result.stdout else []
|
|
170
181
|
|
|
171
182
|
if not tracked_files:
|
|
@@ -173,7 +184,7 @@ def update_cache():
|
|
|
173
184
|
continue
|
|
174
185
|
|
|
175
186
|
# 读取 JSONL 缓存
|
|
176
|
-
jsonl_cache_file = docs_dir /
|
|
187
|
+
jsonl_cache_file = docs_dir / ".dates_cache.jsonl"
|
|
177
188
|
jsonl_dates_cache = read_jsonl_cache(jsonl_cache_file)
|
|
178
189
|
|
|
179
190
|
# 根据 git已跟踪的文件来更新
|
|
@@ -185,13 +196,13 @@ def update_cache():
|
|
|
185
196
|
|
|
186
197
|
full_path = docs_dir / rel_path
|
|
187
198
|
if full_path.exists():
|
|
188
|
-
created_time = load_file_creation_date(full_path)
|
|
199
|
+
created_time = load_file_creation_date(full_path)
|
|
189
200
|
if not jsonl_cache_file.exists():
|
|
190
201
|
git_time = load_git_first_commit_date(full_path)
|
|
191
202
|
if git_time:
|
|
192
203
|
created_time = min(created_time, git_time)
|
|
193
204
|
jsonl_dates_cache[rel_path] = {
|
|
194
|
-
"created": created_time.
|
|
205
|
+
"created": int(created_time.timestamp())
|
|
195
206
|
}
|
|
196
207
|
project_updated = True
|
|
197
208
|
except Exception as e:
|
|
@@ -204,7 +215,7 @@ def update_cache():
|
|
|
204
215
|
|
|
205
216
|
# 如果有更新,写入 JSONL 缓存文件
|
|
206
217
|
if project_updated or not jsonl_cache_file.exists():
|
|
207
|
-
global_updated
|
|
218
|
+
global_updated |= write_jsonl_cache(jsonl_cache_file, jsonl_dates_cache, tracked_files)
|
|
208
219
|
except subprocess.CalledProcessError as e:
|
|
209
220
|
logger.error(f"Failed to execute git command: {e}")
|
|
210
221
|
continue
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import yaml
|
|
3
2
|
import shutil
|
|
4
3
|
import logging
|
|
5
4
|
from jinja2 import ChoiceLoader, FileSystemLoader
|
|
6
|
-
from datetime import datetime
|
|
5
|
+
from datetime import datetime, timezone
|
|
7
6
|
from pathlib import Path
|
|
8
7
|
from mkdocs.plugins import BasePlugin, event_priority
|
|
9
8
|
from mkdocs.config import config_options
|
|
10
9
|
from mkdocs.structure.pages import Page
|
|
11
10
|
from mkdocs.utils import get_relative_url
|
|
12
11
|
from urllib.parse import urlparse
|
|
13
|
-
from .utils import
|
|
12
|
+
from .utils import compile_exclude_patterns, is_excluded, get_recently_updated_files, load_dates_and_authors
|
|
14
13
|
|
|
15
14
|
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
|
16
15
|
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
@@ -45,18 +44,23 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
45
44
|
super().__init__()
|
|
46
45
|
|
|
47
46
|
self.data_cached = {}
|
|
48
|
-
self.last_updated_dates = {}
|
|
49
47
|
self.authors_yml = {}
|
|
50
48
|
self.recent_docs_html = None
|
|
51
49
|
self.recent_enable = False
|
|
52
50
|
self._exclude_patterns = []
|
|
53
51
|
|
|
54
52
|
def on_config(self, config):
|
|
55
|
-
docs_dir_path = Path(config
|
|
53
|
+
docs_dir_path = Path(config.docs_dir)
|
|
56
54
|
|
|
57
55
|
# 加载 author 配置
|
|
58
|
-
authors_file =
|
|
59
|
-
|
|
56
|
+
authors_file = None
|
|
57
|
+
for name in ("authors.yml", "authors.yaml"):
|
|
58
|
+
candidate = docs_dir_path / name
|
|
59
|
+
if candidate.exists():
|
|
60
|
+
authors_file = candidate
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
if authors_file is None:
|
|
60
64
|
try:
|
|
61
65
|
blog_config = config.plugins.get(f"{config.theme.name}/blog").config
|
|
62
66
|
authors_file_resolved = blog_config.authors_file.format(blog=blog_config.blog_dir)
|
|
@@ -65,20 +69,6 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
65
69
|
pass
|
|
66
70
|
self._load_authors_from_yaml(authors_file)
|
|
67
71
|
|
|
68
|
-
# 加载文档 git 元数据(日期 & 作者)
|
|
69
|
-
self.data_cached = load_git_metadata(docs_dir_path)
|
|
70
|
-
# 加载 jsonl 缓存数据
|
|
71
|
-
jsonl_cache_file = docs_dir_path / '.dates_cache.jsonl'
|
|
72
|
-
if jsonl_cache_file.exists():
|
|
73
|
-
jsonl_cache = read_jsonl_cache(jsonl_cache_file)
|
|
74
|
-
for filename, new_info in jsonl_cache.items():
|
|
75
|
-
if filename in self.data_cached:
|
|
76
|
-
self.data_cached[filename].update(new_info)
|
|
77
|
-
|
|
78
|
-
# 加载文档最近更新时间(日期)
|
|
79
|
-
self.last_updated_dates = load_git_last_updated_dates(docs_dir_path)
|
|
80
|
-
|
|
81
|
-
|
|
82
72
|
# 复制配置文件到用户目录(如果不存在)
|
|
83
73
|
dest_dir = docs_dir_path / 'assets' / 'document_dates'
|
|
84
74
|
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -151,32 +141,41 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
151
141
|
|
|
152
142
|
return config
|
|
153
143
|
|
|
144
|
+
@event_priority(50)
|
|
145
|
+
def on_files(self, files, config):
|
|
146
|
+
self.data_cached = load_dates_and_authors(Path(config.docs_dir), files)
|
|
147
|
+
return files
|
|
148
|
+
|
|
154
149
|
@event_priority(50)
|
|
155
150
|
def on_page_markdown(self, markdown, page: Page, config, files):
|
|
156
151
|
# 获取相对路径,src_uri 总是以"/"分隔
|
|
157
|
-
rel_path = getattr(page.file, 'src_uri'
|
|
158
|
-
|
|
159
|
-
rel_path = rel_path.replace(os.sep, '/')
|
|
160
|
-
file_path = page.file.abs_src_path
|
|
161
|
-
|
|
152
|
+
rel_path = getattr(page.file, 'src_uri')
|
|
153
|
+
|
|
162
154
|
# 优先获取 page.meta 中的数据
|
|
163
155
|
created = self._load_meta_date(page.meta, self.config['created_field_names'])
|
|
164
156
|
updated = self._load_meta_date(page.meta, self.config['updated_field_names'])
|
|
165
157
|
authors = self._load_meta_author(page.meta, page.url)
|
|
166
158
|
|
|
167
|
-
#
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
159
|
+
# 如果 meta 数据存在,则存储
|
|
160
|
+
cache = self.data_cached.setdefault(rel_path, {})
|
|
161
|
+
if created:
|
|
162
|
+
cache['created'] = created
|
|
163
|
+
else:
|
|
164
|
+
created = cache.get('created')
|
|
165
|
+
|
|
166
|
+
if updated:
|
|
167
|
+
cache['updated'] = updated
|
|
168
|
+
else:
|
|
169
|
+
updated = cache.get('updated')
|
|
170
|
+
|
|
172
171
|
if not authors:
|
|
173
172
|
authors = self._load_author_cached(rel_path, page, config)
|
|
174
173
|
|
|
175
|
-
#
|
|
174
|
+
# 注入数据到模板 (utc datetime -> local datetime)
|
|
176
175
|
page.meta["document_dates"] = {
|
|
177
176
|
"dates": {
|
|
178
|
-
"created": created.isoformat(),
|
|
179
|
-
"updated": updated.isoformat(),
|
|
177
|
+
"created": created.astimezone().isoformat() if created else None,
|
|
178
|
+
"updated": updated.astimezone().isoformat() if updated else None,
|
|
180
179
|
},
|
|
181
180
|
"authors": authors
|
|
182
181
|
}
|
|
@@ -206,13 +205,13 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
206
205
|
limit = recently_updated_config.get('limit', 10)
|
|
207
206
|
|
|
208
207
|
# 获取站点 URL 路径前缀
|
|
209
|
-
site_url = config.get("site_url"
|
|
208
|
+
site_url = config.get("site_url") or ""
|
|
210
209
|
base_path = urlparse(site_url).path.rstrip("/")
|
|
211
210
|
prefix = f"{base_path}/" if base_path else "/"
|
|
212
211
|
|
|
213
212
|
# 获取最近更新的文档数据
|
|
214
213
|
recent_exclude_patterns = compile_exclude_patterns(exclude_list)
|
|
215
|
-
recently_updated_docs = get_recently_updated_files(self.
|
|
214
|
+
recently_updated_docs = get_recently_updated_files(self.data_cached, files, recent_exclude_patterns, limit, self.recent_enable, prefix)
|
|
216
215
|
|
|
217
216
|
# 将数据注入到 config['extra'] 中供全局访问
|
|
218
217
|
if not config.get('extra', {}).get("recently_updated_docs", {}):
|
|
@@ -290,42 +289,31 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
290
289
|
for field in field_names:
|
|
291
290
|
if field in meta:
|
|
292
291
|
try:
|
|
293
|
-
#
|
|
292
|
+
# 移除首尾可能存在的单双引号
|
|
294
293
|
date_str = str(meta[field]).strip("'\"")
|
|
295
|
-
|
|
294
|
+
dt = datetime.fromisoformat(date_str)
|
|
295
|
+
# 如果没时区,则当成本地时间,再转 UTC
|
|
296
|
+
if dt.tzinfo is None:
|
|
297
|
+
local_tz = datetime.now().astimezone().tzinfo
|
|
298
|
+
dt = dt.replace(tzinfo=local_tz)
|
|
299
|
+
return dt.astimezone(timezone.utc)
|
|
300
|
+
# return datetime.fromisoformat(date_str).astimezone()
|
|
296
301
|
except Exception:
|
|
297
302
|
continue
|
|
298
303
|
return None
|
|
299
304
|
|
|
300
|
-
def _load_created_cached(self, file_path, rel_path):
|
|
301
|
-
# 优先从缓存中读取
|
|
302
|
-
if rel_path in self.data_cached:
|
|
303
|
-
return datetime.fromisoformat(self.data_cached[rel_path]['created'])
|
|
304
|
-
# 从文件系统获取
|
|
305
|
-
return load_file_creation_date(file_path).astimezone()
|
|
306
|
-
|
|
307
|
-
def _load_updated_cached(self, file_path, rel_path):
|
|
308
|
-
# 优先从缓存中读取
|
|
309
|
-
if rel_path in self.last_updated_dates:
|
|
310
|
-
return datetime.fromtimestamp(self.last_updated_dates[rel_path]).astimezone()
|
|
311
|
-
# 从文件系统获取最后修改时间
|
|
312
|
-
stat = os.stat(file_path)
|
|
313
|
-
return datetime.fromtimestamp(stat.st_mtime).astimezone()
|
|
314
|
-
|
|
315
|
-
|
|
316
305
|
def _load_author_cached(self, rel_path, page, config):
|
|
317
306
|
# 1. git author
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return authors
|
|
307
|
+
authors_list = self.data_cached.get(rel_path, {}).get('authors', None)
|
|
308
|
+
if authors_list:
|
|
309
|
+
authors = []
|
|
310
|
+
for data in authors_list:
|
|
311
|
+
full_author = self.authors_yml.get(data['name'])
|
|
312
|
+
if full_author:
|
|
313
|
+
authors.append(self._repair_author(full_author, page.url))
|
|
314
|
+
else:
|
|
315
|
+
authors.append(Author(**data))
|
|
316
|
+
return authors
|
|
329
317
|
|
|
330
318
|
# 2. site_author 或 PC username
|
|
331
319
|
name = config.get('site_author') or Path.home().name
|
|
@@ -407,7 +395,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
407
395
|
return (
|
|
408
396
|
f"<span class='dd-item' data-tippy-content data-tippy-raw='{formatted}'>"
|
|
409
397
|
f"<span class='material-icons' data-icon='{icon}'></span>"
|
|
410
|
-
f"<time datetime='{time_obj.isoformat()}'>{self._formatting_date(time_obj)}</time>"
|
|
398
|
+
f"<time datetime='{time_obj.astimezone().isoformat()}'>{self._formatting_date(time_obj)}</time>"
|
|
411
399
|
f"</span>"
|
|
412
400
|
)
|
|
413
401
|
|
|
@@ -9,7 +9,7 @@ import re
|
|
|
9
9
|
import math
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
from operator import itemgetter
|
|
12
|
-
from datetime import datetime
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
13
|
from collections import defaultdict
|
|
14
14
|
from mkdocs.structure.files import Files
|
|
15
15
|
|
|
@@ -17,6 +17,44 @@ logger = logging.getLogger("mkdocs.plugins.document_dates")
|
|
|
17
17
|
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def load_dates_and_authors(docs_dir_path: Path, files: Files):
|
|
21
|
+
|
|
22
|
+
# git 创建日期
|
|
23
|
+
created_data = load_git_metadata(docs_dir_path)
|
|
24
|
+
|
|
25
|
+
# 覆盖 jsonl 创建日期
|
|
26
|
+
jsonl_cache_file = docs_dir_path / '.dates_cache.jsonl'
|
|
27
|
+
if jsonl_cache_file.exists():
|
|
28
|
+
jsonl_cache = read_jsonl_cache(jsonl_cache_file)
|
|
29
|
+
for filename, new_info in jsonl_cache.items():
|
|
30
|
+
if filename in created_data:
|
|
31
|
+
created_data[filename].update(new_info)
|
|
32
|
+
|
|
33
|
+
# git 更新日期
|
|
34
|
+
updated_data = load_git_last_updated_dates(docs_dir_path)
|
|
35
|
+
|
|
36
|
+
for file in files:
|
|
37
|
+
if file.inclusion.is_excluded():
|
|
38
|
+
continue
|
|
39
|
+
if not file.src_path.endswith('.md'):
|
|
40
|
+
continue
|
|
41
|
+
rel_path = getattr(file, 'src_uri')
|
|
42
|
+
|
|
43
|
+
# created: timestamp -> datetime
|
|
44
|
+
cache = created_data.setdefault(rel_path, {})
|
|
45
|
+
created_ts = cache.get('created')
|
|
46
|
+
cache['created'] = (
|
|
47
|
+
datetime.fromtimestamp(created_ts, tz=timezone.utc)
|
|
48
|
+
if created_ts is not None
|
|
49
|
+
else load_file_creation_date(file.abs_src_path)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# updated: timestamp -> datetime
|
|
53
|
+
mtime = updated_data.get(rel_path, os.path.getmtime(file.abs_src_path))
|
|
54
|
+
created_data[rel_path]['updated'] = datetime.fromtimestamp(mtime, tz=timezone.utc)
|
|
55
|
+
|
|
56
|
+
return created_data
|
|
57
|
+
|
|
20
58
|
def compile_exclude_patterns(exclude_list):
|
|
21
59
|
if not exclude_list:
|
|
22
60
|
return []
|
|
@@ -36,34 +74,34 @@ def is_excluded(path, patterns):
|
|
|
36
74
|
return True
|
|
37
75
|
return False
|
|
38
76
|
|
|
39
|
-
def load_file_creation_date(file_path):
|
|
77
|
+
def load_file_creation_date(file_path) -> datetime:
|
|
40
78
|
try:
|
|
41
79
|
stat = os.stat(file_path)
|
|
42
80
|
system = platform.system().lower()
|
|
43
81
|
if system.startswith('win'): # Windows
|
|
44
|
-
return datetime.fromtimestamp(stat.st_ctime)
|
|
82
|
+
return datetime.fromtimestamp(stat.st_ctime, tz=timezone.utc)
|
|
45
83
|
elif system == 'darwin': # macOS
|
|
46
84
|
try:
|
|
47
|
-
return datetime.fromtimestamp(stat.st_birthtime)
|
|
85
|
+
return datetime.fromtimestamp(stat.st_birthtime, tz=timezone.utc)
|
|
48
86
|
except AttributeError:
|
|
49
|
-
return datetime.fromtimestamp(stat.st_ctime)
|
|
87
|
+
return datetime.fromtimestamp(stat.st_ctime, tz=timezone.utc)
|
|
50
88
|
else: # Linux, 没有创建时间,使用修改时间
|
|
51
|
-
return datetime.fromtimestamp(stat.st_mtime)
|
|
89
|
+
return datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc)
|
|
52
90
|
except (OSError, ValueError) as e:
|
|
53
91
|
logger.error(f"Failed to load file creation date for {file_path}: {e}")
|
|
54
|
-
return datetime.now()
|
|
92
|
+
return datetime.now(timezone.utc)
|
|
55
93
|
|
|
56
|
-
def load_git_first_commit_date(file_path):
|
|
94
|
+
def load_git_first_commit_date(file_path) -> datetime:
|
|
57
95
|
try:
|
|
58
96
|
# git log --reverse --format="%aI" -- {file_path} | head -n 1
|
|
59
|
-
cmd_list = ['git', 'log', '--reverse', '--format=%
|
|
97
|
+
cmd_list = ['git', 'log', '--reverse', '--format=%at', '--', file_path]
|
|
60
98
|
process = subprocess.run(cmd_list, capture_output=True, encoding='utf-8')
|
|
61
99
|
if process.returncode == 0 and process.stdout.strip():
|
|
62
|
-
first_line = process.stdout.partition('\n')[0].strip()
|
|
63
|
-
return datetime.
|
|
100
|
+
first_line = int(process.stdout.partition('\n')[0].strip())
|
|
101
|
+
return datetime.fromtimestamp(first_line, tz=timezone.utc)
|
|
64
102
|
except Exception as e:
|
|
65
103
|
logger.info(f"Error load git first commit date for {file_path}: {e}")
|
|
66
|
-
return
|
|
104
|
+
return datetime.now(timezone.utc)
|
|
67
105
|
|
|
68
106
|
def load_git_metadata(docs_dir_path: Path):
|
|
69
107
|
dates_cache = {}
|
|
@@ -74,7 +112,7 @@ def load_git_metadata(docs_dir_path: Path):
|
|
|
74
112
|
).strip())
|
|
75
113
|
rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
|
|
76
114
|
|
|
77
|
-
cmd = ['git', 'log', '--reverse', '--no-merges', '--use-mailmap', '--name-only', '--format=%aN|%aE|%
|
|
115
|
+
cmd = ['git', '-c', 'core.quotepath=false', 'log', '--reverse', '--no-merges', '--use-mailmap', '--name-only', '--format=%aN|%aE|%at', f'--relative={rel_docs_path}', '--', '*.md']
|
|
78
116
|
process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
|
|
79
117
|
if process.returncode == 0:
|
|
80
118
|
authors_dict = defaultdict(dict)
|
|
@@ -93,7 +131,7 @@ def load_git_metadata(docs_dir_path: Path):
|
|
|
93
131
|
# a.巧用 Python 字典的 setdefault 特性来去重(setdefault 为不存在的键提供初始值,不会覆盖已有值)
|
|
94
132
|
# b.巧用 Python 字典的插入顺序特性来保留内容插入顺序(Python 3.7+ 字典会保持插入顺序)
|
|
95
133
|
authors_dict[line].setdefault((name, email), None)
|
|
96
|
-
first_commit.setdefault(line, created)
|
|
134
|
+
first_commit.setdefault(line, int(created))
|
|
97
135
|
|
|
98
136
|
# 构建最终的缓存数据
|
|
99
137
|
for file_path in first_commit:
|
|
@@ -118,11 +156,11 @@ def load_git_last_updated_dates(docs_dir_path: Path):
|
|
|
118
156
|
).strip())
|
|
119
157
|
rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
|
|
120
158
|
|
|
121
|
-
cmd = ['git', 'log', '--no-merges', '--use-mailmap', '--format=%aN|%aE|%at', '--name-only', f'--relative={rel_docs_path}', '--', '*.md']
|
|
159
|
+
cmd = ['git', '-c', 'core.quotepath=false', 'log', '--no-merges', '--use-mailmap', '--format=%aN|%aE|%at', '--name-only', f'--relative={rel_docs_path}', '--', '*.md']
|
|
122
160
|
process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
|
|
123
161
|
if process.returncode == 0:
|
|
124
162
|
result = subprocess.run(
|
|
125
|
-
[
|
|
163
|
+
['git', '-c', 'core.quotepath=false', 'ls-files', '*.md'],
|
|
126
164
|
cwd=docs_dir_path, capture_output=True, encoding='utf-8'
|
|
127
165
|
)
|
|
128
166
|
# 只记录已跟踪的文件(还有已删除、重命名、不再跟踪)
|
|
@@ -134,7 +172,7 @@ def load_git_last_updated_dates(docs_dir_path: Path):
|
|
|
134
172
|
if not line:
|
|
135
173
|
continue
|
|
136
174
|
if '|' in line:
|
|
137
|
-
ts =
|
|
175
|
+
ts = int(line.split('|')[2])
|
|
138
176
|
elif line.endswith('.md') and line in tracked_files and ts:
|
|
139
177
|
# 只记录第一次出现的文件,即最近一次提交(setdefault 机制不会覆盖已有值)
|
|
140
178
|
doc_mtime_map.setdefault(line, ts)
|
|
@@ -153,14 +191,13 @@ def get_recently_updated_files(existing_dates: dict, files: Files, exclude_list:
|
|
|
153
191
|
continue
|
|
154
192
|
if not file.src_path.endswith('.md'):
|
|
155
193
|
continue
|
|
156
|
-
rel_path = getattr(file, 'src_uri'
|
|
157
|
-
if os.sep != '/':
|
|
158
|
-
rel_path = rel_path.replace(os.sep, '/')
|
|
194
|
+
rel_path = getattr(file, 'src_uri')
|
|
159
195
|
if is_excluded(rel_path, exclude_list):
|
|
160
196
|
continue
|
|
161
197
|
|
|
162
198
|
# 优先从现有数据获取 mtime,如果不存在则 fallback 到文件系统 mtime
|
|
163
|
-
|
|
199
|
+
exist_updated: datetime = existing_dates.get(rel_path, {}).get('updated')
|
|
200
|
+
mtime = exist_updated.timestamp() if exist_updated else os.path.getmtime(file.abs_src_path)
|
|
164
201
|
|
|
165
202
|
# 获取文档其它信息
|
|
166
203
|
title = file.page.title if file.page and file.page.title else file.name
|
|
@@ -193,23 +230,17 @@ def get_recently_updated_files(existing_dates: dict, files: Files, exclude_list:
|
|
|
193
230
|
"readtime": readtime,
|
|
194
231
|
"tags": tags,
|
|
195
232
|
})
|
|
196
|
-
# existing_map[rel_path] = mtime
|
|
197
233
|
|
|
198
234
|
# 构建最近更新列表
|
|
199
235
|
if files_meta:
|
|
200
|
-
fmt_full = "%Y-%m-%d %H:%M:%S"
|
|
201
|
-
fmt_date = "%Y-%m-%d"
|
|
202
236
|
# heapq 取 top limit
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
for doc in top_results:
|
|
206
|
-
dt = datetime.fromtimestamp(doc["updated_ts"])
|
|
237
|
+
recently_updated_results = heapq.nlargest(limit, files_meta, key=itemgetter("updated_ts"))
|
|
207
238
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
239
|
+
for doc in recently_updated_results:
|
|
240
|
+
# timestamp -> utc datetime -> local datetime
|
|
241
|
+
dt = datetime.fromtimestamp(doc["updated_ts"], tz=timezone.utc).astimezone()
|
|
242
|
+
doc["updated_dt"] = dt.isoformat()
|
|
243
|
+
doc["updated"] = dt.date().isoformat()
|
|
213
244
|
|
|
214
245
|
return recently_updated_results
|
|
215
246
|
|
|
@@ -223,10 +254,16 @@ def read_jsonl_cache(jsonl_file: Path):
|
|
|
223
254
|
entry = json.loads(line.strip())
|
|
224
255
|
if entry and isinstance(entry, dict) and len(entry) == 1:
|
|
225
256
|
file_path, file_info = next(iter(entry.items()))
|
|
226
|
-
|
|
227
|
-
|
|
257
|
+
if isinstance(file_info, dict):
|
|
258
|
+
created = file_info.get('created')
|
|
259
|
+
if isinstance(created, str):
|
|
260
|
+
file_info['created'] = int(datetime.fromisoformat(created).timestamp())
|
|
261
|
+
elif isinstance(created, (int, float)):
|
|
262
|
+
file_info['created'] = int(created)
|
|
263
|
+
dates_cache[file_path] = file_info
|
|
264
|
+
except (json.JSONDecodeError, StopIteration, ValueError, TypeError,) as e:
|
|
228
265
|
logger.warning(f"Skipping invalid JSONL line: {e}")
|
|
229
|
-
except
|
|
266
|
+
except OSError as e:
|
|
230
267
|
logger.warning(f"Error reading from '.dates_cache.jsonl': {str(e)}")
|
|
231
268
|
return dates_cache
|
|
232
269
|
|
|
@@ -237,7 +274,11 @@ def write_jsonl_cache(jsonl_file: Path, dates_cache, tracked_files):
|
|
|
237
274
|
with open(temp_file, 'w', encoding='utf-8') as f:
|
|
238
275
|
for file_path in tracked_files:
|
|
239
276
|
if file_path in dates_cache:
|
|
240
|
-
|
|
277
|
+
file_info = dates_cache[file_path].copy()
|
|
278
|
+
created = file_info.get('created')
|
|
279
|
+
if created is not None:
|
|
280
|
+
file_info['created'] = datetime.fromtimestamp(created, tz=timezone.utc).isoformat()
|
|
281
|
+
entry = {file_path: file_info}
|
|
241
282
|
f.write(json.dumps(entry, ensure_ascii=False) + '\n')
|
|
242
283
|
|
|
243
284
|
# 替换原文件
|
|
@@ -247,7 +288,7 @@ def write_jsonl_cache(jsonl_file: Path, dates_cache, tracked_files):
|
|
|
247
288
|
subprocess.run(["git", "add", str(jsonl_file)], check=True)
|
|
248
289
|
logger.info(f"Successfully updated JSONL cache file: {jsonl_file}")
|
|
249
290
|
return True
|
|
250
|
-
except
|
|
291
|
+
except OSError as e:
|
|
251
292
|
logger.warning(f"Failed to write JSONL cache file {jsonl_file}: {e}")
|
|
252
293
|
except Exception as e:
|
|
253
294
|
logger.warning(f"Failed to add JSONL cache file to git: {e}")
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1/mkdocs_document_dates.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs-document-dates
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.1
|
|
4
4
|
Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
|
|
5
5
|
Author-email: Aaron Wang <aaronwqt@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,6 +44,8 @@ A new generation MkDocs plugin for displaying exact **creation date, last update
|
|
|
44
44
|
| git-revision-date-localized<br />git-authors | > 3 s | > 30 s | O(n) |
|
|
45
45
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
|
46
46
|
|
|
47
|
+
> It's 20-500 times faster than `git-revision-date-localized` and `git-authors`
|
|
48
|
+
|
|
47
49
|
## Installation
|
|
48
50
|
|
|
49
51
|
```bash
|
|
@@ -82,8 +84,8 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
82
84
|
- [Structure and Style](https://jaywhj.netlify.app/document-dates-en#Structure-and-Style): You can freely configure the plugin's display structure in mkdocs.yml or Front Matter. You can quickly set the plugin styles through preset entrances, such as icons, themes, colors, fonts, animations, dividing line and so on
|
|
83
85
|
- [Template Variables](https://jaywhj.netlify.app/document-dates-en#Template-Variables): Can be used to optimize `sitemap.xml` for site SEO
|
|
84
86
|
- [Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Recently-Updated-Module): Enable list of recently updated documents (in descending order of update date), this is ideal for sites with a large number of documents, so that readers can quickly see what's new
|
|
85
|
-
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
86
|
-
- [
|
|
87
|
+
- [Localization Language](https://jaywhj.netlify.app/document-dates-en#Localization-Language): More localization languages for `timeago` and `tooltip`
|
|
88
|
+
- [Developer API](https://jaywhj.netlify.app/document-dates-en#Developer-API): Provides a date data API for developers, making it easy to retrieve exact dates in other plugins or hooks
|
|
87
89
|
|
|
88
90
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
89
91
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mkdocs-document-dates"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.8.1"
|
|
8
8
|
description = "A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.7"
|
|
File without changes
|
|
File without changes
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/__init__.py
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/hooks/pre-commit
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/hooks_installer.py
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.7.4 → mkdocs_document_dates-3.8.1}/mkdocs_document_dates/static/.DS_Store
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|