mkdocs-document-dates 3.4.1__tar.gz → 3.4.5__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.4.1/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.4.5}/PKG-INFO +7 -8
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/README.md +6 -7
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/cache_manager.py +2 -2
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks_installer.py +14 -3
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/plugin.py +20 -16
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/utils.py +88 -52
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5/mkdocs_document_dates.egg-info}/PKG-INFO +7 -8
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/setup.py +1 -1
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/LICENSE +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/MANIFEST.in +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/__init__.py +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/config/user.config.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/config/user.config.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/core.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/core.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/default.config.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/utils.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/templates/recently_updated.html +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/SOURCES.txt +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/pyproject.toml +0 -0
- {mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/setup.cfg +0 -0
{mkdocs_document_dates-3.4.1/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.4.5}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mkdocs-document-dates
|
3
|
-
Version: 3.4.
|
3
|
+
Version: 3.4.5
|
4
4
|
Summary: A new generation MkDocs plugin for displaying exact creation time, last update time, authors, email of documents
|
5
5
|
Home-page: https://github.com/jaywhj/mkdocs-document-dates
|
6
6
|
Author: Aaron Wang
|
@@ -36,14 +36,14 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
36
36
|
|
37
37
|
## Features
|
38
38
|
|
39
|
-
- [x] Always
|
39
|
+
- [x] Always displays **exact** meta information of the document and works in any environment (no Git, Git environments, Docker containers, all CI/CD build systems, etc.)
|
40
40
|
- [x] Support for manually specifying time and author in `Front Matter`
|
41
41
|
- [x] Support for multiple time formats (date, datetime, timeago)
|
42
42
|
- [x] Support for multiple author modes (avatar, text, hidden)
|
43
43
|
- [x] Flexible display position (top or bottom)
|
44
44
|
- [x] Elegant styling (fully customizable)
|
45
45
|
- [x] Smart Tooltip Hover Tips
|
46
|
-
- [x]
|
46
|
+
- [x] Support list display of recently updated documents
|
47
47
|
- [x] Multi-language support, localization support, intelligent recognition of user language, automatic adaptation
|
48
48
|
- [x] Cross-platform support (Windows, macOS, Linux)
|
49
49
|
- [x] **Ultimate build efficiency**: O(1), no need to set env vars to distinguish runs
|
@@ -53,7 +53,6 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
53
53
|
| git-revision-date-localized | > 3 s | > 30 s | O(n) |
|
54
54
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
55
55
|
|
56
|
-
|
57
56
|
## Installation
|
58
57
|
|
59
58
|
```bash
|
@@ -77,9 +76,9 @@ plugins:
|
|
77
76
|
position: top # Display position: top(after title) bottom(end of document)
|
78
77
|
type: date # Date type: date datetime timeago, default: date
|
79
78
|
exclude: # List of excluded files
|
80
|
-
- temp.md
|
81
|
-
-
|
82
|
-
date_format: '%Y-%m-%d' # Date format strings
|
79
|
+
- temp.md # Example: exclude the specified file
|
80
|
+
- blog/* # Example: exclude all files in blog folder, including subfolders
|
81
|
+
date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
|
83
82
|
time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
|
84
83
|
show_author: true # Author display mode: true(avatar) text(text) false(hidden)
|
85
84
|
recently-updated: true # Whether to turn on recently updated data, default: false
|
@@ -96,7 +95,7 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
96
95
|
- [Add Localization Language](https://jaywhj.netlify.app/document-dates-en#Add-Localization-Language): More localization languages for `timeago` and `tooltip`
|
97
96
|
- [Use Template Variables](https://jaywhj.netlify.app/document-dates-en#Use-Template-Variables): Can be used to optimize `sitemap.xml` for site SEO, can be used to re-customize plug-ins, etc.
|
98
97
|
- [Add Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Add-Recently-Updated-Module): Enable list of recently updated documents
|
99
|
-
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms
|
98
|
+
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms, and how to use it in Docker
|
100
99
|
- [Development Stories](https://jaywhj.netlify.app/document-dates-en#Development-Stories): Describes the origin of the plug-in, the difficulties and solutions encountered in development, and the principles and directions of product design
|
101
100
|
|
102
101
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
@@ -10,14 +10,14 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
10
10
|
|
11
11
|
## Features
|
12
12
|
|
13
|
-
- [x] Always
|
13
|
+
- [x] Always displays **exact** meta information of the document and works in any environment (no Git, Git environments, Docker containers, all CI/CD build systems, etc.)
|
14
14
|
- [x] Support for manually specifying time and author in `Front Matter`
|
15
15
|
- [x] Support for multiple time formats (date, datetime, timeago)
|
16
16
|
- [x] Support for multiple author modes (avatar, text, hidden)
|
17
17
|
- [x] Flexible display position (top or bottom)
|
18
18
|
- [x] Elegant styling (fully customizable)
|
19
19
|
- [x] Smart Tooltip Hover Tips
|
20
|
-
- [x]
|
20
|
+
- [x] Support list display of recently updated documents
|
21
21
|
- [x] Multi-language support, localization support, intelligent recognition of user language, automatic adaptation
|
22
22
|
- [x] Cross-platform support (Windows, macOS, Linux)
|
23
23
|
- [x] **Ultimate build efficiency**: O(1), no need to set env vars to distinguish runs
|
@@ -27,7 +27,6 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
27
27
|
| git-revision-date-localized | > 3 s | > 30 s | O(n) |
|
28
28
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
29
29
|
|
30
|
-
|
31
30
|
## Installation
|
32
31
|
|
33
32
|
```bash
|
@@ -51,9 +50,9 @@ plugins:
|
|
51
50
|
position: top # Display position: top(after title) bottom(end of document)
|
52
51
|
type: date # Date type: date datetime timeago, default: date
|
53
52
|
exclude: # List of excluded files
|
54
|
-
- temp.md
|
55
|
-
-
|
56
|
-
date_format: '%Y-%m-%d' # Date format strings
|
53
|
+
- temp.md # Example: exclude the specified file
|
54
|
+
- blog/* # Example: exclude all files in blog folder, including subfolders
|
55
|
+
date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
|
57
56
|
time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
|
58
57
|
show_author: true # Author display mode: true(avatar) text(text) false(hidden)
|
59
58
|
recently-updated: true # Whether to turn on recently updated data, default: false
|
@@ -70,7 +69,7 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
70
69
|
- [Add Localization Language](https://jaywhj.netlify.app/document-dates-en#Add-Localization-Language): More localization languages for `timeago` and `tooltip`
|
71
70
|
- [Use Template Variables](https://jaywhj.netlify.app/document-dates-en#Use-Template-Variables): Can be used to optimize `sitemap.xml` for site SEO, can be used to re-customize plug-ins, etc.
|
72
71
|
- [Add Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Add-Recently-Updated-Module): Enable list of recently updated documents
|
73
|
-
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms
|
72
|
+
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms, and how to use it in Docker
|
74
73
|
- [Development Stories](https://jaywhj.netlify.app/document-dates-en#Development-Stories): Describes the origin of the plug-in, the difficulties and solutions encountered in development, and the principles and directions of product design
|
75
74
|
|
76
75
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
{mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/cache_manager.py
RENAMED
@@ -11,7 +11,7 @@ def find_mkdocs_projects():
|
|
11
11
|
try:
|
12
12
|
git_root = Path(subprocess.check_output(
|
13
13
|
['git', 'rev-parse', '--show-toplevel'],
|
14
|
-
|
14
|
+
encoding='utf-8'
|
15
15
|
).strip())
|
16
16
|
|
17
17
|
# 遍历 git_root 及子目录, 寻找 mkdocs.yml 文件
|
@@ -65,7 +65,7 @@ def update_cache():
|
|
65
65
|
|
66
66
|
# 获取docs目录下已跟踪(tracked)的markdown文件
|
67
67
|
cmd = ["git", "ls-files", "*.md"]
|
68
|
-
result = subprocess.run(cmd, cwd=docs_dir, capture_output=True,
|
68
|
+
result = subprocess.run(cmd, cwd=docs_dir, capture_output=True, encoding='utf-8')
|
69
69
|
tracked_files = result.stdout.splitlines() if result.stdout else []
|
70
70
|
|
71
71
|
if not tracked_files:
|
{mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks_installer.py
RENAMED
@@ -12,13 +12,20 @@ def get_config_dir():
|
|
12
12
|
if platform.system().lower().startswith('win'):
|
13
13
|
return Path(os.getenv('APPDATA', str(Path.home() / 'AppData' / 'Roaming')))
|
14
14
|
else:
|
15
|
-
|
15
|
+
# 优先级:XDG_CONFIG_HOME > $HOME/.config > cwd/.config
|
16
|
+
xdg_config = os.getenv('XDG_CONFIG_HOME')
|
17
|
+
if xdg_config:
|
18
|
+
return Path(xdg_config)
|
19
|
+
home = os.getenv('HOME')
|
20
|
+
if home:
|
21
|
+
return Path(home) / '.config'
|
22
|
+
return Path.cwd() / '.config'
|
16
23
|
|
17
24
|
def check_python_version(interpreter):
|
18
25
|
try:
|
19
26
|
result = subprocess.run(
|
20
27
|
[interpreter, "-c", "import sys; print(sys.version_info >= (3, 7))"],
|
21
|
-
capture_output=True,
|
28
|
+
capture_output=True, encoding='utf-8')
|
22
29
|
if result.returncode == 0 and result.stdout.strip().lower() == 'true':
|
23
30
|
return True
|
24
31
|
else:
|
@@ -44,7 +51,11 @@ def setup_hooks_directory():
|
|
44
51
|
os.chmod(config_dir, 0o755)
|
45
52
|
return config_dir
|
46
53
|
except PermissionError:
|
47
|
-
logger.error(
|
54
|
+
logger.error(
|
55
|
+
f"No permission to create directory: {config_dir}\n"
|
56
|
+
"If running inside Docker, please set environment variable HOME=/docs "
|
57
|
+
"or XDG_CONFIG_HOME to a writable path."
|
58
|
+
)
|
48
59
|
except Exception as e:
|
49
60
|
logger.error(f"Failed to create directory {config_dir}: {str(e)}")
|
50
61
|
return None
|
@@ -9,7 +9,7 @@ from mkdocs.plugins import BasePlugin
|
|
9
9
|
from mkdocs.config import config_options
|
10
10
|
from mkdocs.structure.pages import Page
|
11
11
|
from urllib.parse import urlparse
|
12
|
-
from .utils import get_file_creation_time, load_git_cache, read_jsonl_cache,is_excluded,
|
12
|
+
from .utils import get_file_creation_time, load_git_cache, read_jsonl_cache,is_excluded, get_recently_updated_files
|
13
13
|
|
14
14
|
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
15
15
|
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
@@ -41,8 +41,8 @@ class DocumentDatesPlugin(BasePlugin):
|
|
41
41
|
('time_format', config_options.Type(str, default='%H:%M:%S')),
|
42
42
|
('position', config_options.Type(str, default='top')),
|
43
43
|
('exclude', config_options.Type(list, default=[])),
|
44
|
-
('created_field_names', config_options.Type(list, default=['created', 'date'
|
45
|
-
('modified_field_names', config_options.Type(list, default=['modified', 'updated'
|
44
|
+
('created_field_names', config_options.Type(list, default=['created', 'date'])),
|
45
|
+
('modified_field_names', config_options.Type(list, default=['modified', 'updated'])),
|
46
46
|
('show_author', config_options.Choice((True, False, 'text'), default=True)),
|
47
47
|
('recently-updated', config_options.Type((dict, bool), default={}))
|
48
48
|
)
|
@@ -50,6 +50,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
50
50
|
def __init__(self):
|
51
51
|
super().__init__()
|
52
52
|
self.dates_cache = {}
|
53
|
+
self.last_updated_dates = {}
|
53
54
|
self.authors_yml = {}
|
54
55
|
self.github_username = None
|
55
56
|
self.recent_docs_html = None
|
@@ -145,10 +146,9 @@ class DocumentDatesPlugin(BasePlugin):
|
|
145
146
|
|
146
147
|
def on_nav(self, nav, config, files):
|
147
148
|
recently_updated_config = self.config.get('recently-updated')
|
148
|
-
if
|
149
|
-
|
149
|
+
if recently_updated_config:
|
150
|
+
self.recent_enable = True
|
150
151
|
|
151
|
-
self.recent_enable = True
|
152
152
|
# 兼容 true 配置
|
153
153
|
if recently_updated_config is True:
|
154
154
|
recently_updated_config = {}
|
@@ -156,19 +156,20 @@ class DocumentDatesPlugin(BasePlugin):
|
|
156
156
|
# 获取配置
|
157
157
|
exclude_list = recently_updated_config.get('exclude', [])
|
158
158
|
limit = recently_updated_config.get('limit', 10)
|
159
|
-
template_path = recently_updated_config.get(
|
159
|
+
template_path = recently_updated_config.get('template')
|
160
160
|
|
161
|
-
#
|
162
|
-
|
161
|
+
# 获取最近更新日期和最近更新的文档数据
|
162
|
+
docs_dir = Path(config['docs_dir'])
|
163
|
+
self.last_updated_dates, recently_updated_docs = get_recently_updated_files(docs_dir, files, exclude_list, limit, self.recent_enable)
|
163
164
|
|
164
165
|
# 将数据注入到 config['extra'] 中供全局访问
|
165
166
|
if 'extra' not in config:
|
166
167
|
config['extra'] = {}
|
167
|
-
config['extra']['recently_updated_docs'] =
|
168
|
+
config['extra']['recently_updated_docs'] = recently_updated_docs
|
168
169
|
|
169
170
|
# 渲染HTML
|
170
|
-
|
171
|
-
|
171
|
+
if self.recent_enable:
|
172
|
+
self.recent_docs_html = self._render_recently_updated_html(docs_dir, template_path, recently_updated_docs)
|
172
173
|
|
173
174
|
return nav
|
174
175
|
|
@@ -210,7 +211,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
210
211
|
if not created:
|
211
212
|
created = self._get_file_creation_time(file_path, rel_path)
|
212
213
|
if not modified:
|
213
|
-
modified = self._get_file_modification_time(file_path)
|
214
|
+
modified = self._get_file_modification_time(file_path, rel_path)
|
214
215
|
|
215
216
|
# 获取作者信息
|
216
217
|
authors = self._get_author_info(rel_path, page, config)
|
@@ -221,8 +222,8 @@ class DocumentDatesPlugin(BasePlugin):
|
|
221
222
|
page.meta['document_dates_authors'] = authors
|
222
223
|
|
223
224
|
# 占位符替换
|
224
|
-
if self.recent_enable and '<!-- RECENTLY_UPDATED_DOCS -->' in markdown:
|
225
|
-
markdown = markdown.replace('<!-- RECENTLY_UPDATED_DOCS -->', self.recent_docs_html or '')
|
225
|
+
if self.recent_enable and '\n<!-- RECENTLY_UPDATED_DOCS -->' in markdown:
|
226
|
+
markdown = markdown.replace('\n<!-- RECENTLY_UPDATED_DOCS -->', self.recent_docs_html or '')
|
226
227
|
|
227
228
|
# 检查是否需要排除
|
228
229
|
if is_excluded(rel_path, self.config['exclude']):
|
@@ -293,7 +294,10 @@ class DocumentDatesPlugin(BasePlugin):
|
|
293
294
|
# 从文件系统获取
|
294
295
|
return get_file_creation_time(file_path).astimezone()
|
295
296
|
|
296
|
-
def _get_file_modification_time(self, file_path):
|
297
|
+
def _get_file_modification_time(self, file_path, rel_path):
|
298
|
+
# 优先从缓存中读取
|
299
|
+
if rel_path in self.last_updated_dates:
|
300
|
+
return datetime.fromtimestamp(self.last_updated_dates[rel_path]).astimezone()
|
297
301
|
# 从文件系统获取最后修改时间
|
298
302
|
stat = os.stat(file_path)
|
299
303
|
return datetime.fromtimestamp(stat.st_mtime).astimezone()
|
@@ -1,11 +1,13 @@
|
|
1
1
|
import os
|
2
2
|
import platform
|
3
3
|
import json
|
4
|
+
import heapq
|
4
5
|
import logging
|
5
6
|
import subprocess
|
6
7
|
from pathlib import Path
|
7
8
|
from datetime import datetime
|
8
9
|
from collections import defaultdict
|
10
|
+
from mkdocs.structure.files import Files
|
9
11
|
|
10
12
|
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
11
13
|
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
@@ -27,7 +29,7 @@ def get_git_first_commit_time(file_path):
|
|
27
29
|
try:
|
28
30
|
# git log --reverse --format="%aI" -- {file_path} | head -n 1
|
29
31
|
cmd_list = ['git', 'log', '--reverse', '--format=%aI', '--', file_path]
|
30
|
-
process = subprocess.run(cmd_list, capture_output=True,
|
32
|
+
process = subprocess.run(cmd_list, capture_output=True, encoding='utf-8')
|
31
33
|
if process.returncode == 0 and process.stdout.strip():
|
32
34
|
first_line = process.stdout.partition('\n')[0].strip()
|
33
35
|
return datetime.fromisoformat(first_line)
|
@@ -38,18 +40,15 @@ def get_git_first_commit_time(file_path):
|
|
38
40
|
def load_git_cache(docs_dir_path: Path):
|
39
41
|
dates_cache = {}
|
40
42
|
try:
|
41
|
-
|
42
|
-
|
43
|
+
git_root = Path(subprocess.check_output(
|
44
|
+
['git', 'rev-parse', '--show-toplevel'],
|
45
|
+
cwd=docs_dir_path, encoding='utf-8'
|
46
|
+
).strip())
|
47
|
+
rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
|
48
|
+
|
49
|
+
cmd = ['git', 'log', '--reverse', '--no-merges', '--use-mailmap', '--name-only', '--format=%aN|%aE|%aI', f'--relative={rel_docs_path}', '--', '*.md']
|
50
|
+
process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
|
43
51
|
if process.returncode == 0:
|
44
|
-
git_root = Path(subprocess.check_output(
|
45
|
-
['git', 'rev-parse', '--show-toplevel'],
|
46
|
-
cwd=docs_dir_path,
|
47
|
-
text=True, encoding='utf-8'
|
48
|
-
).strip())
|
49
|
-
docs_prefix = docs_dir_path.relative_to(git_root).as_posix()
|
50
|
-
docs_prefix_with_slash = docs_prefix + '/'
|
51
|
-
prefix_len = len(docs_prefix_with_slash)
|
52
|
-
|
53
52
|
authors_dict = defaultdict(dict)
|
54
53
|
first_commit = {}
|
55
54
|
current_commit = None
|
@@ -59,24 +58,21 @@ def load_git_cache(docs_dir_path: Path):
|
|
59
58
|
if not line:
|
60
59
|
continue
|
61
60
|
if '|' in line:
|
62
|
-
name, email, created = line.split('|', 2)
|
63
61
|
# 使用元组,更轻量
|
64
|
-
current_commit = (
|
62
|
+
current_commit = tuple(line.split('|', 2))
|
65
63
|
elif line.endswith('.md') and current_commit:
|
66
|
-
if line.startswith(docs_prefix_with_slash):
|
67
|
-
line = line[prefix_len:]
|
68
|
-
# 解构元组,避免字典查找
|
69
64
|
name, email, created = current_commit
|
70
|
-
#
|
65
|
+
# 使用 defaultdict(dict)结构,有序去重,保持作者首次出现的顺序
|
66
|
+
# a.巧用 Python 字典的 setdefault 特性来去重(setdefault 为不存在的键提供初始值,不会覆盖已有值)
|
67
|
+
# b.巧用 Python 3.7+ 字典的插入顺序特性来保留内容插入顺序(Python 3.7+ 字典会保持插入顺序)
|
71
68
|
authors_dict[line].setdefault((name, email), None)
|
72
|
-
|
73
|
-
first_commit[line] = created
|
69
|
+
first_commit.setdefault(line, created)
|
74
70
|
|
75
71
|
# 构建最终的缓存数据
|
76
72
|
for file_path in first_commit:
|
77
73
|
authors_list = [
|
78
74
|
{'name': name, 'email': email}
|
79
|
-
for name, email in authors_dict[file_path].keys()
|
75
|
+
for name, email in authors_dict[file_path].keys() # 这里的 keys() 是有序的
|
80
76
|
]
|
81
77
|
dates_cache[file_path] = {
|
82
78
|
'created': first_commit[file_path],
|
@@ -103,43 +99,83 @@ def get_file_creation_time(file_path):
|
|
103
99
|
logger.error(f"Failed to get file creation time for {file_path}: {e}")
|
104
100
|
return datetime.now()
|
105
101
|
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
102
|
+
def get_recently_updated_files(docs_dir_path: Path, files: Files, exclude_list: list, limit: int = 10, recent_enable: bool = False):
|
103
|
+
doc_mtime_map = {}
|
104
|
+
try:
|
105
|
+
# 1. 获取 git 信息,只记录已跟踪的文件首次出现的信息(最近一次提交时间)
|
106
|
+
git_root = Path(subprocess.check_output(
|
107
|
+
['git', 'rev-parse', '--show-toplevel'],
|
108
|
+
cwd=docs_dir_path, encoding='utf-8'
|
109
|
+
).strip())
|
110
|
+
rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
|
111
|
+
|
112
|
+
cmd = ['git', 'log', '--no-merges', '--use-mailmap', '--format=%aN|%aE|%at', '--name-only', f'--relative={rel_docs_path}', '--', '*.md']
|
113
|
+
process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
|
114
|
+
if process.returncode == 0:
|
115
|
+
result = subprocess.run(
|
116
|
+
["git", "ls-files", "*.md"],
|
117
|
+
cwd=docs_dir_path, capture_output=True, encoding='utf-8'
|
118
|
+
)
|
119
|
+
tracked_files = set(result.stdout.splitlines()) if result.stdout else set()
|
120
|
+
|
121
|
+
ts = None
|
122
|
+
for line in process.stdout.splitlines():
|
123
|
+
line = line.strip()
|
124
|
+
if not line:
|
125
|
+
continue
|
126
|
+
if '|' in line: # commit header
|
127
|
+
ts = float(line.split('|')[2])
|
128
|
+
elif line.endswith('.md') and line in tracked_files and ts:
|
129
|
+
# 只记录第一次出现的文件,即最近一次提交(setdefault 机制不会覆盖已有值)
|
130
|
+
doc_mtime_map.setdefault(line, ts)
|
131
|
+
except Exception as e:
|
132
|
+
logger.info(f"Error getting git tracked files in {docs_dir_path}: {e}")
|
133
|
+
|
134
|
+
# 2. 构建所有文档的元数据
|
135
|
+
recently_updated_results = []
|
136
|
+
if recent_enable:
|
137
|
+
files_meta = []
|
138
|
+
for file in files:
|
139
|
+
if not file.src_path.endswith('.md'):
|
122
140
|
continue
|
123
|
-
|
124
|
-
|
125
|
-
|
141
|
+
rel_path = getattr(file, 'src_uri', file.src_path)
|
142
|
+
if os.sep != '/':
|
143
|
+
rel_path = rel_path.replace(os.sep, '/')
|
144
|
+
if is_excluded(rel_path, exclude_list):
|
145
|
+
continue
|
146
|
+
|
147
|
+
# 获取文档标题和 URL
|
148
|
+
if file.page:
|
149
|
+
# 过滤没有配置进导航里的文档
|
150
|
+
if not file.page.title:
|
151
|
+
continue
|
152
|
+
title, url = file.page.title, file.page.url
|
153
|
+
else:
|
154
|
+
title, url = file.name, file.url
|
155
|
+
|
156
|
+
# 获取 git 记录的 mtime,没有则 fallback 到文件系统 mtime
|
157
|
+
mtime = doc_mtime_map.get(rel_path, os.path.getmtime(file.abs_src_path))
|
158
|
+
|
159
|
+
# 存储信息
|
160
|
+
files_meta.append((mtime, rel_path, title, url))
|
161
|
+
doc_mtime_map[rel_path] = mtime
|
126
162
|
|
127
|
-
|
128
|
-
|
163
|
+
# 3. 构建最近更新列表
|
164
|
+
if files_meta:
|
165
|
+
# heapq 取 top limit
|
166
|
+
top_results = heapq.nlargest(limit, files_meta, key=lambda x: x[0])
|
167
|
+
recently_updated_results = [
|
168
|
+
(datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S"), *rest)
|
169
|
+
for mtime, *rest in top_results
|
170
|
+
]
|
129
171
|
|
130
|
-
|
131
|
-
temp_results.sort(key=lambda x: x[0], reverse=True)
|
132
|
-
results = [
|
133
|
-
(datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S"), *rest)
|
134
|
-
for mtime, *rest in temp_results
|
135
|
-
]
|
136
|
-
return results[:limit]
|
172
|
+
return doc_mtime_map, recently_updated_results
|
137
173
|
|
138
174
|
def read_json_cache(cache_file: Path):
|
139
175
|
dates_cache = {}
|
140
176
|
if cache_file.exists():
|
141
177
|
try:
|
142
|
-
with open(cache_file,
|
178
|
+
with open(cache_file, 'r', encoding='utf-8') as f:
|
143
179
|
dates_cache = json.load(f)
|
144
180
|
except (IOError, json.JSONDecodeError) as e:
|
145
181
|
logger.warning(f"Error reading from '.dates_cache.json': {str(e)}")
|
@@ -149,7 +185,7 @@ def read_jsonl_cache(jsonl_file: Path):
|
|
149
185
|
dates_cache = {}
|
150
186
|
if jsonl_file.exists():
|
151
187
|
try:
|
152
|
-
with open(jsonl_file,
|
188
|
+
with open(jsonl_file, 'r', encoding='utf-8') as f:
|
153
189
|
for line in f:
|
154
190
|
try:
|
155
191
|
entry = json.loads(line.strip())
|
@@ -166,7 +202,7 @@ def write_jsonl_cache(jsonl_file: Path, dates_cache, tracked_files):
|
|
166
202
|
try:
|
167
203
|
# 使用临时文件写入,然后替换原文件,避免写入过程中的问题
|
168
204
|
temp_file = jsonl_file.with_suffix('.jsonl.tmp')
|
169
|
-
with open(temp_file,
|
205
|
+
with open(temp_file, 'w', encoding='utf-8') as f:
|
170
206
|
for file_path in tracked_files:
|
171
207
|
if file_path in dates_cache:
|
172
208
|
entry = {file_path: dates_cache[file_path]}
|
{mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5/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.4.
|
3
|
+
Version: 3.4.5
|
4
4
|
Summary: A new generation MkDocs plugin for displaying exact creation time, last update time, authors, email of documents
|
5
5
|
Home-page: https://github.com/jaywhj/mkdocs-document-dates
|
6
6
|
Author: Aaron Wang
|
@@ -36,14 +36,14 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
36
36
|
|
37
37
|
## Features
|
38
38
|
|
39
|
-
- [x] Always
|
39
|
+
- [x] Always displays **exact** meta information of the document and works in any environment (no Git, Git environments, Docker containers, all CI/CD build systems, etc.)
|
40
40
|
- [x] Support for manually specifying time and author in `Front Matter`
|
41
41
|
- [x] Support for multiple time formats (date, datetime, timeago)
|
42
42
|
- [x] Support for multiple author modes (avatar, text, hidden)
|
43
43
|
- [x] Flexible display position (top or bottom)
|
44
44
|
- [x] Elegant styling (fully customizable)
|
45
45
|
- [x] Smart Tooltip Hover Tips
|
46
|
-
- [x]
|
46
|
+
- [x] Support list display of recently updated documents
|
47
47
|
- [x] Multi-language support, localization support, intelligent recognition of user language, automatic adaptation
|
48
48
|
- [x] Cross-platform support (Windows, macOS, Linux)
|
49
49
|
- [x] **Ultimate build efficiency**: O(1), no need to set env vars to distinguish runs
|
@@ -53,7 +53,6 @@ A new generation MkDocs plugin for displaying exact **creation time, last update
|
|
53
53
|
| git-revision-date-localized | > 3 s | > 30 s | O(n) |
|
54
54
|
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
55
55
|
|
56
|
-
|
57
56
|
## Installation
|
58
57
|
|
59
58
|
```bash
|
@@ -77,9 +76,9 @@ plugins:
|
|
77
76
|
position: top # Display position: top(after title) bottom(end of document)
|
78
77
|
type: date # Date type: date datetime timeago, default: date
|
79
78
|
exclude: # List of excluded files
|
80
|
-
- temp.md
|
81
|
-
-
|
82
|
-
date_format: '%Y-%m-%d' # Date format strings
|
79
|
+
- temp.md # Example: exclude the specified file
|
80
|
+
- blog/* # Example: exclude all files in blog folder, including subfolders
|
81
|
+
date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
|
83
82
|
time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
|
84
83
|
show_author: true # Author display mode: true(avatar) text(text) false(hidden)
|
85
84
|
recently-updated: true # Whether to turn on recently updated data, default: false
|
@@ -96,7 +95,7 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
96
95
|
- [Add Localization Language](https://jaywhj.netlify.app/document-dates-en#Add-Localization-Language): More localization languages for `timeago` and `tooltip`
|
97
96
|
- [Use Template Variables](https://jaywhj.netlify.app/document-dates-en#Use-Template-Variables): Can be used to optimize `sitemap.xml` for site SEO, can be used to re-customize plug-ins, etc.
|
98
97
|
- [Add Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Add-Recently-Updated-Module): Enable list of recently updated documents
|
99
|
-
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms
|
98
|
+
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms, and how to use it in Docker
|
100
99
|
- [Development Stories](https://jaywhj.netlify.app/document-dates-en#Development-Stories): Describes the origin of the plug-in, the difficulties and solutions encountered in development, and the principles and directions of product design
|
101
100
|
|
102
101
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
File without changes
|
File without changes
|
{mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/__init__.py
RENAMED
File without changes
|
{mkdocs_document_dates-3.4.1 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks/pre-commit
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
|