mkdocs-document-dates 3.1__tar.gz → 3.1.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.1 → mkdocs_document_dates-3.1.1}/PKG-INFO +10 -12
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/README.md +9 -11
- mkdocs_document_dates-3.1.1/mkdocs_document_dates/__init__.py +6 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/cache_manager.py +16 -0
- mkdocs_document_dates-3.1.1/mkdocs_document_dates/hooks_installer.py +126 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/plugin.py +24 -22
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/PKG-INFO +10 -12
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/setup.py +28 -2
- mkdocs_document_dates-3.1/mkdocs_document_dates/__init__.py +0 -11
- mkdocs_document_dates-3.1/mkdocs_document_dates/hooks_installer.py +0 -128
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/LICENSE +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/config/user.config.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/config/user.config.js +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/core/core.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/core/core.js +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/ar.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/de.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/en.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/es.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/fr.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/ja.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/ko.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/ru.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/zh.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/languages/zh_tw.json +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/SOURCES.txt +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mkdocs-document-dates
|
3
|
-
Version: 3.1
|
3
|
+
Version: 3.1.1
|
4
4
|
Summary: An easy-to-use, lightweight MkDocs plugin for displaying the exact creation time, last modification time and author info of markdown documents.
|
5
5
|
Home-page: https://github.com/jaywhj/mkdocs-document-dates
|
6
6
|
Author: Aaron Wang
|
@@ -120,35 +120,33 @@ email: e-name@gmail.com
|
|
120
120
|
|
121
121
|
## Customization
|
122
122
|
|
123
|
-
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value
|
123
|
+
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value):
|
124
124
|
|
125
125
|
- Style & Theme: `docs/assets/document_dates/user.config.css`
|
126
126
|
- Properties & Animations: `docs/assets/document_dates/user.config.js`
|
127
127
|
- Localized languages: `docs/assets/document_dates/languages/` , refer to the template file `en.json` for any additions or modifications
|
128
128
|
|
129
|
-
Note: Due to the redesign of the configuration file update mechanism, the configuration file starting with document-dates.config in the previous version has been canceled and replaced by user.config
|
130
|
-
|
131
129
|
## Other Tips
|
132
130
|
|
133
131
|
- In order to get the exact creation time, a separate cache file is used to store the creation time of the file, located in the doc folder (hidden by default), please don't delete it:
|
134
|
-
- `docs/.dates_cache.jsonl`, cache file
|
135
|
-
- `docs/.gitattributes`,
|
136
|
-
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it
|
137
|
-
|
138
|
-
|
132
|
+
- `docs/.dates_cache.jsonl`, cache file
|
133
|
+
- `docs/.gitattributes`, merge mechanism for cache file in case of multi-person collaboration
|
134
|
+
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it. In addition, the installation of Git Hooks is automatically triggered when the plugin is installed, without any manual intervention!
|
135
|
+
|
136
|
+
<br />
|
139
137
|
|
140
138
|
## Development Stories (Optional)
|
141
139
|
|
142
|
-
A dispensable, insignificant little plug-in, friends who have
|
140
|
+
A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
|
143
141
|
|
144
142
|
- **Origin**:
|
145
143
|
- Because [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin), a great project. When I used it at the end of 2024, I found that I couldn't use it locally because my mkdocs documentation was not included in git management, then I don't understand why not read the file system time, but to use the git time, and raised an issue to the author, but didn't get a reply for about a week (the author had a reply later, nice guy, I guess he was busy at the time), and then I thought, there is nothing to do during the Chinese New Year, and now AI is so hot, why not with the help of the AI try it out for myself, it was born, born in February 2025
|
146
144
|
- **Iteration**:
|
147
145
|
- After development, I understood why not use filesystem time, because files will be rebuilt when they go through git checkout or clone, resulting in the loss of original timestamp information, and there are many solutions:
|
148
146
|
- Method 1: Use the last git commit time as the last update time, and the first git commit time as the creation (there is a margin of error, but it's acceptable), mkdocs-git-revision-date-localized-plugin does this
|
149
|
-
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter.
|
147
|
+
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter. Storing in Front Matter makes sense and is simple, but this will modify the source content of the document, although it doesn't have any impact on the body, but I still want to ensure the originality of the data!
|
150
148
|
- **Difficulty**:
|
151
|
-
1. When to read and store
|
149
|
+
1. When to read and store original time? This is just a plugin for mkdocs, with very limited access and permissions, mkdocs provides only build and serve, so in case a user commits directly without executing build or serve (e.g., when using a CI/CD build system), then you won't be able to retrieve the time information of the file, not to mention caching it!
|
152
150
|
- Let's take a straight shot: the Git Hooks mechanism was found, prompted by the AI, which can trigger a custom script when a specific action occurs, such as every time commit is performed
|
153
151
|
2. How can I ensure that a single cache file does not conflict when collaborating with multi-person?
|
154
152
|
- My solution: use JSONL (JSON Lines) instead of JSON, and with the merge strategy 'merge=union'
|
@@ -97,35 +97,33 @@ email: e-name@gmail.com
|
|
97
97
|
|
98
98
|
## Customization
|
99
99
|
|
100
|
-
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value
|
100
|
+
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value):
|
101
101
|
|
102
102
|
- Style & Theme: `docs/assets/document_dates/user.config.css`
|
103
103
|
- Properties & Animations: `docs/assets/document_dates/user.config.js`
|
104
104
|
- Localized languages: `docs/assets/document_dates/languages/` , refer to the template file `en.json` for any additions or modifications
|
105
105
|
|
106
|
-
Note: Due to the redesign of the configuration file update mechanism, the configuration file starting with document-dates.config in the previous version has been canceled and replaced by user.config
|
107
|
-
|
108
106
|
## Other Tips
|
109
107
|
|
110
108
|
- In order to get the exact creation time, a separate cache file is used to store the creation time of the file, located in the doc folder (hidden by default), please don't delete it:
|
111
|
-
- `docs/.dates_cache.jsonl`, cache file
|
112
|
-
- `docs/.gitattributes`,
|
113
|
-
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it
|
114
|
-
|
115
|
-
|
109
|
+
- `docs/.dates_cache.jsonl`, cache file
|
110
|
+
- `docs/.gitattributes`, merge mechanism for cache file in case of multi-person collaboration
|
111
|
+
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it. In addition, the installation of Git Hooks is automatically triggered when the plugin is installed, without any manual intervention!
|
112
|
+
|
113
|
+
<br />
|
116
114
|
|
117
115
|
## Development Stories (Optional)
|
118
116
|
|
119
|
-
A dispensable, insignificant little plug-in, friends who have
|
117
|
+
A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
|
120
118
|
|
121
119
|
- **Origin**:
|
122
120
|
- Because [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin), a great project. When I used it at the end of 2024, I found that I couldn't use it locally because my mkdocs documentation was not included in git management, then I don't understand why not read the file system time, but to use the git time, and raised an issue to the author, but didn't get a reply for about a week (the author had a reply later, nice guy, I guess he was busy at the time), and then I thought, there is nothing to do during the Chinese New Year, and now AI is so hot, why not with the help of the AI try it out for myself, it was born, born in February 2025
|
123
121
|
- **Iteration**:
|
124
122
|
- After development, I understood why not use filesystem time, because files will be rebuilt when they go through git checkout or clone, resulting in the loss of original timestamp information, and there are many solutions:
|
125
123
|
- Method 1: Use the last git commit time as the last update time, and the first git commit time as the creation (there is a margin of error, but it's acceptable), mkdocs-git-revision-date-localized-plugin does this
|
126
|
-
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter.
|
124
|
+
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter. Storing in Front Matter makes sense and is simple, but this will modify the source content of the document, although it doesn't have any impact on the body, but I still want to ensure the originality of the data!
|
127
125
|
- **Difficulty**:
|
128
|
-
1. When to read and store
|
126
|
+
1. When to read and store original time? This is just a plugin for mkdocs, with very limited access and permissions, mkdocs provides only build and serve, so in case a user commits directly without executing build or serve (e.g., when using a CI/CD build system), then you won't be able to retrieve the time information of the file, not to mention caching it!
|
129
127
|
- Let's take a straight shot: the Git Hooks mechanism was found, prompted by the AI, which can trigger a custom script when a specific action occurs, such as every time commit is performed
|
130
128
|
2. How can I ensure that a single cache file does not conflict when collaborating with multi-person?
|
131
129
|
- My solution: use JSONL (JSON Lines) instead of JSON, and with the merge strategy 'merge=union'
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/cache_manager.py
RENAMED
@@ -53,6 +53,18 @@ def get_file_creation_time(file_path):
|
|
53
53
|
logging.error(f"Failed to get file creation time for {file_path}: {e}")
|
54
54
|
return datetime.now()
|
55
55
|
|
56
|
+
def get_git_first_commit_time(file_path):
|
57
|
+
try:
|
58
|
+
# git log --reverse --format="%aI" --date=iso -- {file_path} | head -n 1
|
59
|
+
result = subprocess.run(['git', 'log', '--reverse', '--format=%aI', '--', file_path], capture_output=True, text=True)
|
60
|
+
if result.returncode == 0:
|
61
|
+
commits = result.stdout.strip().split('\n')
|
62
|
+
if commits and commits[0]:
|
63
|
+
return datetime.fromisoformat(commits[0]).replace(tzinfo=None)
|
64
|
+
except Exception as e:
|
65
|
+
logging.info(f"Error getting git first commit time for {file_path}: {e}")
|
66
|
+
return None
|
67
|
+
|
56
68
|
def setup_gitattributes(docs_dir):
|
57
69
|
gitattributes_path = docs_dir / '.gitattributes'
|
58
70
|
union_config_line = ".dates_cache.jsonl merge=union"
|
@@ -180,6 +192,10 @@ def update_cache():
|
|
180
192
|
project_updated = True
|
181
193
|
elif full_path.exists():
|
182
194
|
created_time = get_file_creation_time(full_path)
|
195
|
+
if not jsonl_cache_file.exists() and not json_cache_file.exists():
|
196
|
+
git_time = get_git_first_commit_time(full_path)
|
197
|
+
if git_time is not None:
|
198
|
+
created_time = min(created_time, git_time)
|
183
199
|
jsonl_dates_cache[rel_path] = {
|
184
200
|
"created": created_time.isoformat()
|
185
201
|
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import logging
|
4
|
+
import subprocess
|
5
|
+
from pathlib import Path
|
6
|
+
import platform
|
7
|
+
|
8
|
+
# 配置日志等级 (INFO WARNING ERROR)
|
9
|
+
logging.basicConfig(
|
10
|
+
level=logging.WARNING,
|
11
|
+
format='%(levelname)s: %(message)s'
|
12
|
+
)
|
13
|
+
|
14
|
+
def get_config_dir():
|
15
|
+
if platform.system().lower().startswith('win'):
|
16
|
+
return Path(os.getenv('APPDATA', str(Path.home() / 'AppData' / 'Roaming')))
|
17
|
+
else:
|
18
|
+
return Path.home() / '.config'
|
19
|
+
|
20
|
+
def check_python_version(interpreter):
|
21
|
+
try:
|
22
|
+
result = subprocess.run(
|
23
|
+
[interpreter, "-c", "import sys; print(sys.version_info >= (3, 7))"],
|
24
|
+
capture_output=True, text=True, check=False
|
25
|
+
)
|
26
|
+
if result.returncode == 0 and result.stdout.strip() == 'True':
|
27
|
+
return True
|
28
|
+
else:
|
29
|
+
logging.warning(f"Low python version, requires python_requires >=3.7")
|
30
|
+
return False
|
31
|
+
except Exception as e:
|
32
|
+
logging.debug(f"Failed to check {interpreter}: {str(e)}")
|
33
|
+
return False
|
34
|
+
|
35
|
+
def detect_python_interpreter():
|
36
|
+
# 检查可能的Python解释器
|
37
|
+
python_interpreters = ['python3', 'python']
|
38
|
+
|
39
|
+
for interpreter in python_interpreters:
|
40
|
+
if check_python_version(interpreter):
|
41
|
+
return f'#!/usr/bin/env {interpreter}'
|
42
|
+
|
43
|
+
# 如果都失败了,使用当前运行的Python解释器
|
44
|
+
return f'#!{sys.executable}'
|
45
|
+
|
46
|
+
def check_git_available():
|
47
|
+
try:
|
48
|
+
subprocess.run(['git', '--version'], check=True, capture_output=True, encoding='utf-8')
|
49
|
+
return True
|
50
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
51
|
+
logging.warning("Git not detected, skip hooks installation")
|
52
|
+
return False
|
53
|
+
|
54
|
+
def setup_hooks_directory():
|
55
|
+
config_dir = get_config_dir() / 'mkdocs-document-dates' / 'hooks'
|
56
|
+
try:
|
57
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
58
|
+
os.chmod(config_dir, 0o755)
|
59
|
+
return config_dir
|
60
|
+
except PermissionError:
|
61
|
+
logging.error(f"No permission to create directory: {config_dir}")
|
62
|
+
return None
|
63
|
+
except Exception as e:
|
64
|
+
logging.error(f"Failed to create directory {config_dir}: {str(e)}")
|
65
|
+
return None
|
66
|
+
|
67
|
+
def install_hook_file(source_hook, target_dir):
|
68
|
+
target_hook_path = target_dir / source_hook.name
|
69
|
+
try:
|
70
|
+
# 读取并更新hook文件内容
|
71
|
+
with open(source_hook, 'r', encoding='utf-8') as f_in:
|
72
|
+
content = f_in.read()
|
73
|
+
|
74
|
+
# 更新shebang行
|
75
|
+
shebang = detect_python_interpreter()
|
76
|
+
if content.startswith('#!'):
|
77
|
+
content = shebang + os.linesep + content[content.find('\n'):]
|
78
|
+
else:
|
79
|
+
content = shebang + os.linesep + content
|
80
|
+
|
81
|
+
# 写入并设置权限
|
82
|
+
with open(target_hook_path, 'w', encoding='utf-8') as f_out:
|
83
|
+
f_out.write(content)
|
84
|
+
os.chmod(target_hook_path, 0o755)
|
85
|
+
return True
|
86
|
+
except Exception as e:
|
87
|
+
logging.error(f"Failed to create hook file {target_hook_path}: {str(e)}")
|
88
|
+
return False
|
89
|
+
|
90
|
+
def configure_git_hooks(hooks_dir):
|
91
|
+
try:
|
92
|
+
subprocess.run(
|
93
|
+
['git', 'config', '--global', 'core.hooksPath', str(hooks_dir)],
|
94
|
+
check=True, capture_output=True, encoding='utf-8'
|
95
|
+
)
|
96
|
+
logging.info(f"Git hooks successfully installed in: {hooks_dir}")
|
97
|
+
return True
|
98
|
+
except subprocess.CalledProcessError as e:
|
99
|
+
logging.error(f"Failed to set git hooks path: {str(e)}")
|
100
|
+
return False
|
101
|
+
|
102
|
+
def install():
|
103
|
+
try:
|
104
|
+
# 检查git是否可用
|
105
|
+
if not check_git_available():
|
106
|
+
return False
|
107
|
+
|
108
|
+
# 创建hooks目录
|
109
|
+
hooks_dir = setup_hooks_directory()
|
110
|
+
if not hooks_dir:
|
111
|
+
return False
|
112
|
+
|
113
|
+
# 安装hook文件
|
114
|
+
source_hook = Path(__file__).parent / 'hooks' / 'pre-commit'
|
115
|
+
if not install_hook_file(source_hook, hooks_dir):
|
116
|
+
return False
|
117
|
+
|
118
|
+
# 配置git hooks路径
|
119
|
+
return configure_git_hooks(hooks_dir)
|
120
|
+
|
121
|
+
except Exception as e:
|
122
|
+
logging.error(f"Unexpected error during hooks installation: {str(e)}")
|
123
|
+
return False
|
124
|
+
|
125
|
+
if __name__ == '__main__':
|
126
|
+
install()
|
@@ -56,8 +56,18 @@ class DocumentDatesPlugin(BasePlugin):
|
|
56
56
|
super().__init__()
|
57
57
|
self.translations = {}
|
58
58
|
self.dates_cache = {}
|
59
|
+
self.is_git_repo = False
|
59
60
|
|
60
61
|
def on_config(self, config):
|
62
|
+
|
63
|
+
# 检查是否为 Git 仓库
|
64
|
+
try:
|
65
|
+
check_git = subprocess.run(['git', 'rev-parse', '--is-inside-work-tree'], capture_output=True, text=True)
|
66
|
+
if check_git.returncode == 0:
|
67
|
+
self.is_git_repo = True
|
68
|
+
except subprocess.CalledProcessError as e:
|
69
|
+
logging.info(f"Not a Git repository: {str(e)}")
|
70
|
+
|
61
71
|
docs_dir_path = Path(config['docs_dir'])
|
62
72
|
|
63
73
|
# 加载 json 语言文件
|
@@ -265,19 +275,16 @@ class DocumentDatesPlugin(BasePlugin):
|
|
265
275
|
return None
|
266
276
|
|
267
277
|
def _get_git_first_commit_time(self, file_path):
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
result = subprocess.run(
|
273
|
-
['git', 'log', '--reverse', '--format=%aI', '--', file_path],
|
274
|
-
capture_output=True, text=True)
|
278
|
+
if self.is_git_repo:
|
279
|
+
try:
|
280
|
+
# git log --reverse --format="%aI" --date=iso -- {file_path} | head -n 1
|
281
|
+
result = subprocess.run(['git', 'log', '--reverse', '--format=%aI', '--', file_path], capture_output=True, text=True)
|
275
282
|
if result.returncode == 0:
|
276
283
|
commits = result.stdout.strip().split('\n')
|
277
284
|
if commits and commits[0]:
|
278
285
|
return datetime.fromisoformat(commits[0]).replace(tzinfo=None)
|
279
|
-
|
280
|
-
|
286
|
+
except Exception as e:
|
287
|
+
logging.info(f"Error getting git first commit time for {file_path}: {e}")
|
281
288
|
return None
|
282
289
|
|
283
290
|
def _get_file_creation_time(self, file_path, rel_path):
|
@@ -310,20 +317,18 @@ class DocumentDatesPlugin(BasePlugin):
|
|
310
317
|
def _get_file_modification_time(self, file_path):
|
311
318
|
"""
|
312
319
|
# 从git获取最后修改时间
|
313
|
-
|
314
|
-
|
315
|
-
check_git = subprocess.run(['git', 'rev-parse', '--is-inside-work-tree'],
|
316
|
-
capture_output=True, text=True)
|
317
|
-
if check_git.returncode == 0:
|
320
|
+
if self.is_git_repo:
|
321
|
+
try:
|
318
322
|
# 获取文件最后修改时间
|
319
323
|
cmd = f'git log -1 --format="%aI" --date=iso -- "{file_path}"'
|
320
324
|
process = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
321
325
|
if process.returncode == 0 and process.stdout.strip():
|
322
326
|
git_time = process.stdout.strip()
|
323
327
|
return datetime.fromisoformat(git_time).replace(tzinfo=None)
|
324
|
-
|
325
|
-
|
328
|
+
except Exception as e:
|
329
|
+
logging.warning(f"Failed to get git modification time: {str(e)}")
|
326
330
|
"""
|
331
|
+
|
327
332
|
# 从文件系统获取最后修改时间
|
328
333
|
stat = os.stat(file_path)
|
329
334
|
return datetime.fromtimestamp(stat.st_mtime)
|
@@ -366,13 +371,10 @@ class DocumentDatesPlugin(BasePlugin):
|
|
366
371
|
return None
|
367
372
|
|
368
373
|
def _get_git_authors(self, file_path: str) -> Union[Author, List[Author], None]:
|
374
|
+
if not self.is_git_repo:
|
375
|
+
return None
|
376
|
+
|
369
377
|
try:
|
370
|
-
# 先检查是否是 Git 仓库
|
371
|
-
check_git = subprocess.run(['git', 'rev-parse', '--is-inside-work-tree'],
|
372
|
-
capture_output=True, text=True)
|
373
|
-
if check_git.returncode != 0:
|
374
|
-
return None
|
375
|
-
|
376
378
|
# # 检查文件是否在 Git 中
|
377
379
|
# check_file = subprocess.run(f'git ls-files --error-unmatch {file_path}',
|
378
380
|
# shell=True, capture_output=True, text=True)
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.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.1
|
3
|
+
Version: 3.1.1
|
4
4
|
Summary: An easy-to-use, lightweight MkDocs plugin for displaying the exact creation time, last modification time and author info of markdown documents.
|
5
5
|
Home-page: https://github.com/jaywhj/mkdocs-document-dates
|
6
6
|
Author: Aaron Wang
|
@@ -120,35 +120,33 @@ email: e-name@gmail.com
|
|
120
120
|
|
121
121
|
## Customization
|
122
122
|
|
123
|
-
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value
|
123
|
+
The plugin supports deep customization, such as icon style, font style, theme color, animation type, dividing line, etc. All of it can be customized by modifying the code in the corresponding file (I've already written the code and comments, you just need to turn on the switch and change the value):
|
124
124
|
|
125
125
|
- Style & Theme: `docs/assets/document_dates/user.config.css`
|
126
126
|
- Properties & Animations: `docs/assets/document_dates/user.config.js`
|
127
127
|
- Localized languages: `docs/assets/document_dates/languages/` , refer to the template file `en.json` for any additions or modifications
|
128
128
|
|
129
|
-
Note: Due to the redesign of the configuration file update mechanism, the configuration file starting with document-dates.config in the previous version has been canceled and replaced by user.config
|
130
|
-
|
131
129
|
## Other Tips
|
132
130
|
|
133
131
|
- In order to get the exact creation time, a separate cache file is used to store the creation time of the file, located in the doc folder (hidden by default), please don't delete it:
|
134
|
-
- `docs/.dates_cache.jsonl`, cache file
|
135
|
-
- `docs/.gitattributes`,
|
136
|
-
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it
|
137
|
-
|
138
|
-
|
132
|
+
- `docs/.dates_cache.jsonl`, cache file
|
133
|
+
- `docs/.gitattributes`, merge mechanism for cache file in case of multi-person collaboration
|
134
|
+
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (every time executes a git commit), and the cached file is automatically committed along with it. In addition, the installation of Git Hooks is automatically triggered when the plugin is installed, without any manual intervention!
|
135
|
+
|
136
|
+
<br />
|
139
137
|
|
140
138
|
## Development Stories (Optional)
|
141
139
|
|
142
|
-
A dispensable, insignificant little plug-in, friends who have
|
140
|
+
A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
|
143
141
|
|
144
142
|
- **Origin**:
|
145
143
|
- Because [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin), a great project. When I used it at the end of 2024, I found that I couldn't use it locally because my mkdocs documentation was not included in git management, then I don't understand why not read the file system time, but to use the git time, and raised an issue to the author, but didn't get a reply for about a week (the author had a reply later, nice guy, I guess he was busy at the time), and then I thought, there is nothing to do during the Chinese New Year, and now AI is so hot, why not with the help of the AI try it out for myself, it was born, born in February 2025
|
146
144
|
- **Iteration**:
|
147
145
|
- After development, I understood why not use filesystem time, because files will be rebuilt when they go through git checkout or clone, resulting in the loss of original timestamp information, and there are many solutions:
|
148
146
|
- Method 1: Use the last git commit time as the last update time, and the first git commit time as the creation (there is a margin of error, but it's acceptable), mkdocs-git-revision-date-localized-plugin does this
|
149
|
-
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter.
|
147
|
+
- Method 2: You can cache the original time, and then read the cache subsequently. The cache can be in Front Matter of the source document or in a separate file, I chose the latter. Storing in Front Matter makes sense and is simple, but this will modify the source content of the document, although it doesn't have any impact on the body, but I still want to ensure the originality of the data!
|
150
148
|
- **Difficulty**:
|
151
|
-
1. When to read and store
|
149
|
+
1. When to read and store original time? This is just a plugin for mkdocs, with very limited access and permissions, mkdocs provides only build and serve, so in case a user commits directly without executing build or serve (e.g., when using a CI/CD build system), then you won't be able to retrieve the time information of the file, not to mention caching it!
|
152
150
|
- Let's take a straight shot: the Git Hooks mechanism was found, prompted by the AI, which can trigger a custom script when a specific action occurs, such as every time commit is performed
|
153
151
|
2. How can I ensure that a single cache file does not conflict when collaborating with multi-person?
|
154
152
|
- My solution: use JSONL (JSON Lines) instead of JSON, and with the merge strategy 'merge=union'
|
@@ -1,5 +1,28 @@
|
|
1
1
|
from setuptools import setup, find_packages
|
2
|
-
import
|
2
|
+
from setuptools.command.install import install
|
3
|
+
import atexit
|
4
|
+
|
5
|
+
def trigger_hook_install():
|
6
|
+
try:
|
7
|
+
import os
|
8
|
+
import sys
|
9
|
+
# 动态添加包路径确保导入成功
|
10
|
+
package_path = os.path.abspath(os.path.dirname(__file__))
|
11
|
+
if package_path not in sys.path:
|
12
|
+
sys.path.insert(0, package_path)
|
13
|
+
|
14
|
+
# from mkdocs_document_dates.hooks_installer import install
|
15
|
+
# install()
|
16
|
+
# import mkdocs_document_dates
|
17
|
+
__import__('mkdocs_document_dates')
|
18
|
+
except Exception as e:
|
19
|
+
print(f"Warning: Failed to install Git hooks: {e}")
|
20
|
+
|
21
|
+
class CustomInstallCommand(install):
|
22
|
+
def run(self):
|
23
|
+
# 注册在安装结束时执行 trigger_hook_install
|
24
|
+
atexit.register(trigger_hook_install)
|
25
|
+
install.run(self)
|
3
26
|
|
4
27
|
try:
|
5
28
|
with open("README.md", "r", encoding="utf-8") as fh:
|
@@ -7,7 +30,7 @@ try:
|
|
7
30
|
except FileNotFoundError:
|
8
31
|
long_description = "An easy-to-use, lightweight MkDocs plugin for displaying the exact creation time, last modification time and author info of markdown documents."
|
9
32
|
|
10
|
-
VERSION = '3.1'
|
33
|
+
VERSION = '3.1.1'
|
11
34
|
|
12
35
|
setup(
|
13
36
|
name="mkdocs-document-dates",
|
@@ -26,6 +49,9 @@ setup(
|
|
26
49
|
"License :: OSI Approved :: MIT License",
|
27
50
|
"Operating System :: OS Independent",
|
28
51
|
],
|
52
|
+
cmdclass={
|
53
|
+
'install': CustomInstallCommand,
|
54
|
+
},
|
29
55
|
entry_points={
|
30
56
|
'mkdocs.plugins': [
|
31
57
|
'document-dates = mkdocs_document_dates.plugin:DocumentDatesPlugin',
|
@@ -1,11 +0,0 @@
|
|
1
|
-
"""MkDocs Document Dates Plugin."""
|
2
|
-
|
3
|
-
from .hooks_installer import install
|
4
|
-
|
5
|
-
# 在包被导入时自动执行 hooks 安装
|
6
|
-
try:
|
7
|
-
result = install()
|
8
|
-
if not result:
|
9
|
-
print("Tip: Git hooks installation was skipped (probably because Git was not detected or not in the Git repository)")
|
10
|
-
except Exception as e:
|
11
|
-
print(f"Warning: Git hooks installation failed: {e}")
|
@@ -1,128 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import sys
|
3
|
-
import logging
|
4
|
-
import subprocess
|
5
|
-
from pathlib import Path
|
6
|
-
import platform
|
7
|
-
|
8
|
-
# 配置日志等级 (INFO WARNING ERROR)
|
9
|
-
logging.basicConfig(
|
10
|
-
level=logging.WARNING,
|
11
|
-
format='%(levelname)s: %(message)s'
|
12
|
-
)
|
13
|
-
|
14
|
-
def get_config_dir():
|
15
|
-
if platform.system().lower().startswith('win'):
|
16
|
-
return Path(os.getenv('APPDATA', str(Path.home() / 'AppData' / 'Roaming')))
|
17
|
-
else:
|
18
|
-
return Path.home() / '.config'
|
19
|
-
|
20
|
-
def check_python_version(interpreter):
|
21
|
-
try:
|
22
|
-
result = subprocess.run(
|
23
|
-
[interpreter, "-c", "import sys; print(sys.version_info >= (3, 7))"],
|
24
|
-
capture_output=True, text=True, check=False
|
25
|
-
)
|
26
|
-
if result.returncode == 0 and result.stdout.strip() == 'True':
|
27
|
-
return True
|
28
|
-
else:
|
29
|
-
logging.warning(f"Low python version, requires python_requires >=3.7")
|
30
|
-
return False
|
31
|
-
except Exception as e:
|
32
|
-
logging.debug(f"Failed to check {interpreter}: {str(e)}")
|
33
|
-
return False
|
34
|
-
|
35
|
-
def detect_python_interpreter():
|
36
|
-
# 检查可能的Python解释器
|
37
|
-
python_interpreters = ['python3', 'python']
|
38
|
-
|
39
|
-
for interpreter in python_interpreters:
|
40
|
-
if check_python_version(interpreter):
|
41
|
-
return f'#!/usr/bin/env {interpreter}'
|
42
|
-
|
43
|
-
# 如果都失败了,使用当前运行的Python解释器
|
44
|
-
return f'#!{sys.executable}'
|
45
|
-
|
46
|
-
def install():
|
47
|
-
try:
|
48
|
-
# 检查 git 是否可用
|
49
|
-
try:
|
50
|
-
subprocess.run(['git', '--version'], check=True, capture_output=True, encoding='utf-8')
|
51
|
-
except (subprocess.CalledProcessError, FileNotFoundError):
|
52
|
-
logging.warning("Git not detected, skip hooks installation")
|
53
|
-
return False
|
54
|
-
|
55
|
-
# 准备配置目录
|
56
|
-
config_dir = get_config_dir() / 'mkdocs-document-dates' / 'hooks'
|
57
|
-
try:
|
58
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
59
|
-
except PermissionError:
|
60
|
-
logging.error(f"No permission to create directory: {config_dir}")
|
61
|
-
return False
|
62
|
-
except Exception as e:
|
63
|
-
logging.error(f"Failed to create directory {config_dir}: {str(e)}")
|
64
|
-
return False
|
65
|
-
|
66
|
-
# 检测Python解释器并获取合适的shebang行
|
67
|
-
shebang = detect_python_interpreter()
|
68
|
-
logging.info(f"Using shebang: {shebang}")
|
69
|
-
|
70
|
-
# 安装钩子文件
|
71
|
-
hooks_installed = False
|
72
|
-
source_hooks_dir = Path(__file__).parent / 'hooks'
|
73
|
-
for hook_file in source_hooks_dir.glob('*'):
|
74
|
-
if hook_file.is_file() and not hook_file.name.startswith('.'):
|
75
|
-
target_hook_path = config_dir / hook_file.name
|
76
|
-
try:
|
77
|
-
# 读取源文件内容
|
78
|
-
with open(hook_file, 'r', encoding='utf-8') as f_in:
|
79
|
-
content = f_in.read()
|
80
|
-
|
81
|
-
# 修改shebang行
|
82
|
-
if content.startswith('#!'):
|
83
|
-
content = shebang + os.linesep + content[content.find('\n'):]
|
84
|
-
else:
|
85
|
-
content = shebang + os.linesep + content
|
86
|
-
|
87
|
-
# 直接写入目标文件
|
88
|
-
with open(target_hook_path, 'w', encoding='utf-8') as f_out:
|
89
|
-
f_out.write(content)
|
90
|
-
|
91
|
-
# 设置执行权限
|
92
|
-
os.chmod(target_hook_path, 0o755)
|
93
|
-
hooks_installed = True
|
94
|
-
logging.info(f"Created hook with custom shebang: {hook_file.name}")
|
95
|
-
except Exception as e:
|
96
|
-
logging.error(f"Failed to create file {target_hook_path}: {str(e)}")
|
97
|
-
return False
|
98
|
-
|
99
|
-
if not hooks_installed:
|
100
|
-
logging.warning("No hook files found, the hooks installation failed")
|
101
|
-
return False
|
102
|
-
|
103
|
-
# 设置目录权限
|
104
|
-
try:
|
105
|
-
os.chmod(config_dir, 0o755)
|
106
|
-
except OSError as e:
|
107
|
-
logging.warning(f"Failed to set directory permissions: {str(e)}")
|
108
|
-
|
109
|
-
# 配置全局 git hooks 路径
|
110
|
-
try:
|
111
|
-
subprocess.run(
|
112
|
-
['git', 'config', '--global', 'core.hooksPath', str(config_dir)],
|
113
|
-
check=True,
|
114
|
-
capture_output=True,
|
115
|
-
encoding='utf-8'
|
116
|
-
)
|
117
|
-
logging.info(f"Git hooks successfully installed in: {config_dir}")
|
118
|
-
return True
|
119
|
-
except subprocess.CalledProcessError as e:
|
120
|
-
logging.error(f"Failed to set git hooks path: {str(e)}")
|
121
|
-
return False
|
122
|
-
|
123
|
-
except Exception as e:
|
124
|
-
logging.error(f"Unexpected error during hooks installation: {str(e)}")
|
125
|
-
return False
|
126
|
-
|
127
|
-
if __name__ == '__main__':
|
128
|
-
install()
|
File without changes
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/hooks/pre-commit
RENAMED
File without changes
|
File without changes
|
File without changes
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/core/core.css
RENAMED
File without changes
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates/static/core/core.js
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
|
{mkdocs_document_dates-3.1 → mkdocs_document_dates-3.1.1}/mkdocs_document_dates.egg-info/SOURCES.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|