mkdocs-document-dates 3.1.5__tar.gz → 3.2__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.2/MANIFEST.in +2 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/PKG-INFO +36 -17
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/README.md +35 -15
- mkdocs_document_dates-3.2/mkdocs_document_dates/cache_manager.py +126 -0
- mkdocs_document_dates-3.2/mkdocs_document_dates/hooks_installer.py +109 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/plugin.py +93 -208
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/config/user.config.css +6 -6
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/core/core.css +8 -7
- mkdocs_document_dates-3.2/mkdocs_document_dates/utils.py +147 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/PKG-INFO +36 -17
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/SOURCES.txt +2 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/setup.py +2 -5
- mkdocs_document_dates-3.1.5/mkdocs_document_dates/cache_manager.py +0 -233
- mkdocs_document_dates-3.1.5/mkdocs_document_dates/hooks_installer.py +0 -126
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/LICENSE +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/__init__.py +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/config/user.config.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/core/core.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/core/timeago-load.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/ar.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/de.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/en.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/es.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/fr.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/ja.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/ko.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/ru.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/zh.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/languages/zh_TW.json +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.1.5 → mkdocs_document_dates-3.2}/setup.cfg +0 -0
@@ -1,13 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mkdocs-document-dates
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.2
|
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
|
7
7
|
Author-email: aaronwqt@gmail.com
|
8
8
|
License: MIT
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
11
10
|
Classifier: Operating System :: OS Independent
|
12
11
|
Requires-Python: >=3.7
|
13
12
|
Description-Content-Type: text/markdown
|
@@ -38,14 +37,11 @@ An easy-to-use, lightweight MkDocs plugin for displaying the <mark>exact</mark>
|
|
38
37
|
- Always display exact meta-info of the document for any environment (no-Git, Git, all CI/CD build systems, etc)
|
39
38
|
- Support for manually specifying time and author in `Front Matter`
|
40
39
|
- Support for multiple time formats (date, datetime, timeago)
|
41
|
-
- Support for document exclusion mode
|
42
40
|
- Flexible display position (top or bottom)
|
43
41
|
- Elegant styling (fully customizable)
|
44
42
|
- Supports Tooltip Hover Tips
|
45
43
|
- Intelligent repositioning to always float optimally in view
|
46
44
|
- Supports automatic theme switching following Material's light/dark color scheme
|
47
|
-
- Support for customizing themes, styles, animations
|
48
|
-
- Compatible with mouse, keyboard and **touch** (mobile) to trigger hover
|
49
45
|
- Multi-language support, cross-platform support (Windows, macOS, Linux)
|
50
46
|
|
51
47
|
## Showcases
|
@@ -80,9 +76,7 @@ plugins:
|
|
80
76
|
exclude: # List of excluded files
|
81
77
|
- temp.md # Exclude specific file
|
82
78
|
- private/* # Exclude all files in private directory, including subdirectories
|
83
|
-
|
84
79
|
show_author: true # Show author or not, default: true
|
85
|
-
|
86
80
|
```
|
87
81
|
|
88
82
|
## Specify time manually
|
@@ -123,18 +117,18 @@ email: e-name@gmail.com
|
|
123
117
|
|
124
118
|
## Customization
|
125
119
|
|
126
|
-
The plugin supports deep customization, such as **icon style,
|
120
|
+
The plugin supports deep customization, such as **icon style, theme color, font, animation, dividing line**, etc. Everything is customizable (I've already written the code, you just need to turn on the uncomment switch):
|
127
121
|
|
128
|
-
|
|
122
|
+
| Category: | Location: |
|
129
123
|
| :----------------------: | ---------------------------------------- |
|
130
124
|
| **Style & Theme** | `docs/assets/document_dates/user.config.css` |
|
131
125
|
| **Properties & Functions** | `docs/assets/document_dates/user.config.js` |
|
132
126
|
| **Localized languages** | `docs/assets/document_dates/languages/` <br />refer to the template file `en.json` for any additions or modifications |
|
133
127
|
|
134
|
-
**Tip**: when `type: timeago` is set, timeago.js is enabled to render time
|
128
|
+
**Tip**: when `type: timeago` is set, timeago.js is enabled to render dynamic time, `timeago.min.js` only contains English and Chinese by default, if you need to load other languages, you can configure it as below (choose one):
|
135
129
|
|
136
130
|
- In `user.config.js`, refer to [the demo commented out](https://github.com/jaywhj/mkdocs-document-dates/blob/main/mkdocs_document_dates/static/config/user.config.js) at the bottom, translate it into your local language
|
137
|
-
- In `mkdocs.yml`,
|
131
|
+
- In `mkdocs.yml`, configure the full version of `timeago.full.min.js` to load all languages at once
|
138
132
|
```yaml
|
139
133
|
extra_javascript:
|
140
134
|
- assets/document_dates/core/timeago.full.min.js
|
@@ -150,12 +144,37 @@ The plugin supports deep customization, such as **icon style, font style, theme
|
|
150
144
|

|
151
145
|
|
152
146
|

|
153
|
-

|
154
147
|

|
155
148
|
|
149
|
+
## Used in templates
|
150
|
+
|
151
|
+
You can access the meta-info of a document in a template using the following variables:
|
152
|
+
|
153
|
+
- page.meta.document_dates_created
|
154
|
+
- page.meta.document_dates_modified
|
155
|
+
- page.meta.document_dates_authors
|
156
|
+
|
157
|
+
For example like this:
|
158
|
+
|
159
|
+
```jinja2
|
160
|
+
<div><span>{{ page.meta.document_dates_created }}</span></div>
|
161
|
+
<div><span>{{ page.meta.document_dates_modified }}</span></div>
|
162
|
+
{% set authors = page.meta.document_dates_authors %}
|
163
|
+
{% if authors %}
|
164
|
+
<div>
|
165
|
+
{% for author in authors %}
|
166
|
+
{% if author.email %}<a href="mailto:{{ author.email }}">{{ author.name }}</a>
|
167
|
+
{% else %}<span>{{ author.name }}</span>{% endif %}
|
168
|
+
{% endfor %}
|
169
|
+
</div>
|
170
|
+
{% endif %}
|
171
|
+
```
|
172
|
+
|
173
|
+
**Full example**: set the correct lastmod for [sitemap.xml](https://github.com/jaywhj/mkdocs-document-dates/blob/main/sitemap.xml) so that search engines can better handle SEO and thus increase your site's exposure (override path: `docs/overrides/sitemap.xml`)
|
174
|
+
|
156
175
|
## Other Tips
|
157
176
|
|
158
|
-
- In order to always get the exact creation time, a separate cache file is used to store the creation time of the document, located in the docs folder (hidden by default), please don't
|
177
|
+
- In order to always get the exact creation time, a separate cache file is used to store the creation time of the document, located in the docs folder (hidden by default), please don't remove it:
|
159
178
|
- `docs/.dates_cache.jsonl`, cache file
|
160
179
|
- `docs/.gitattributes`, merge mechanism for cache file
|
161
180
|
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (on each 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!
|
@@ -167,11 +186,11 @@ The plugin supports deep customization, such as **icon style, font style, theme
|
|
167
186
|
A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
|
168
187
|
|
169
188
|
- **Origin**:
|
170
|
-
- 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, I don't understand why not read the file system time, but to use the git time, and the filesystem time is
|
189
|
+
- 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, I don't understand why not read the file system time, but to use the git time, and the filesystem time is exact, then 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
|
171
190
|
- **Iteration**:
|
172
|
-
- 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
|
173
|
-
- Method 1: Use the last git commit time as the last update time
|
174
|
-
- Method 2:
|
191
|
+
- 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. There are many solutions:
|
192
|
+
- Method 1: Use the last git commit time as the last update time and the first git commit time as the creation time, mkdocs-git-revision-date-localized-plugin does this. (This way, there will be a margin of error and dependency on git)
|
193
|
+
- Method 2: Cache the original time in advance, and then read the cache subsequently (The time is exact and no dependency on any environment). 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 easier, 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!
|
175
194
|
- **Difficulty**:
|
176
195
|
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!
|
177
196
|
- 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 git action occurs, such as every time commit is performed
|
@@ -11,14 +11,11 @@ An easy-to-use, lightweight MkDocs plugin for displaying the <mark>exact</mark>
|
|
11
11
|
- Always display exact meta-info of the document for any environment (no-Git, Git, all CI/CD build systems, etc)
|
12
12
|
- Support for manually specifying time and author in `Front Matter`
|
13
13
|
- Support for multiple time formats (date, datetime, timeago)
|
14
|
-
- Support for document exclusion mode
|
15
14
|
- Flexible display position (top or bottom)
|
16
15
|
- Elegant styling (fully customizable)
|
17
16
|
- Supports Tooltip Hover Tips
|
18
17
|
- Intelligent repositioning to always float optimally in view
|
19
18
|
- Supports automatic theme switching following Material's light/dark color scheme
|
20
|
-
- Support for customizing themes, styles, animations
|
21
|
-
- Compatible with mouse, keyboard and **touch** (mobile) to trigger hover
|
22
19
|
- Multi-language support, cross-platform support (Windows, macOS, Linux)
|
23
20
|
|
24
21
|
## Showcases
|
@@ -53,9 +50,7 @@ plugins:
|
|
53
50
|
exclude: # List of excluded files
|
54
51
|
- temp.md # Exclude specific file
|
55
52
|
- private/* # Exclude all files in private directory, including subdirectories
|
56
|
-
|
57
53
|
show_author: true # Show author or not, default: true
|
58
|
-
|
59
54
|
```
|
60
55
|
|
61
56
|
## Specify time manually
|
@@ -96,18 +91,18 @@ email: e-name@gmail.com
|
|
96
91
|
|
97
92
|
## Customization
|
98
93
|
|
99
|
-
The plugin supports deep customization, such as **icon style,
|
94
|
+
The plugin supports deep customization, such as **icon style, theme color, font, animation, dividing line**, etc. Everything is customizable (I've already written the code, you just need to turn on the uncomment switch):
|
100
95
|
|
101
|
-
|
|
96
|
+
| Category: | Location: |
|
102
97
|
| :----------------------: | ---------------------------------------- |
|
103
98
|
| **Style & Theme** | `docs/assets/document_dates/user.config.css` |
|
104
99
|
| **Properties & Functions** | `docs/assets/document_dates/user.config.js` |
|
105
100
|
| **Localized languages** | `docs/assets/document_dates/languages/` <br />refer to the template file `en.json` for any additions or modifications |
|
106
101
|
|
107
|
-
**Tip**: when `type: timeago` is set, timeago.js is enabled to render time
|
102
|
+
**Tip**: when `type: timeago` is set, timeago.js is enabled to render dynamic time, `timeago.min.js` only contains English and Chinese by default, if you need to load other languages, you can configure it as below (choose one):
|
108
103
|
|
109
104
|
- In `user.config.js`, refer to [the demo commented out](https://github.com/jaywhj/mkdocs-document-dates/blob/main/mkdocs_document_dates/static/config/user.config.js) at the bottom, translate it into your local language
|
110
|
-
- In `mkdocs.yml`,
|
105
|
+
- In `mkdocs.yml`, configure the full version of `timeago.full.min.js` to load all languages at once
|
111
106
|
```yaml
|
112
107
|
extra_javascript:
|
113
108
|
- assets/document_dates/core/timeago.full.min.js
|
@@ -123,12 +118,37 @@ The plugin supports deep customization, such as **icon style, font style, theme
|
|
123
118
|

|
124
119
|
|
125
120
|

|
126
|
-

|
127
121
|

|
128
122
|
|
123
|
+
## Used in templates
|
124
|
+
|
125
|
+
You can access the meta-info of a document in a template using the following variables:
|
126
|
+
|
127
|
+
- page.meta.document_dates_created
|
128
|
+
- page.meta.document_dates_modified
|
129
|
+
- page.meta.document_dates_authors
|
130
|
+
|
131
|
+
For example like this:
|
132
|
+
|
133
|
+
```jinja2
|
134
|
+
<div><span>{{ page.meta.document_dates_created }}</span></div>
|
135
|
+
<div><span>{{ page.meta.document_dates_modified }}</span></div>
|
136
|
+
{% set authors = page.meta.document_dates_authors %}
|
137
|
+
{% if authors %}
|
138
|
+
<div>
|
139
|
+
{% for author in authors %}
|
140
|
+
{% if author.email %}<a href="mailto:{{ author.email }}">{{ author.name }}</a>
|
141
|
+
{% else %}<span>{{ author.name }}</span>{% endif %}
|
142
|
+
{% endfor %}
|
143
|
+
</div>
|
144
|
+
{% endif %}
|
145
|
+
```
|
146
|
+
|
147
|
+
**Full example**: set the correct lastmod for [sitemap.xml](https://github.com/jaywhj/mkdocs-document-dates/blob/main/sitemap.xml) so that search engines can better handle SEO and thus increase your site's exposure (override path: `docs/overrides/sitemap.xml`)
|
148
|
+
|
129
149
|
## Other Tips
|
130
150
|
|
131
|
-
- In order to always get the exact creation time, a separate cache file is used to store the creation time of the document, located in the docs folder (hidden by default), please don't
|
151
|
+
- In order to always get the exact creation time, a separate cache file is used to store the creation time of the document, located in the docs folder (hidden by default), please don't remove it:
|
132
152
|
- `docs/.dates_cache.jsonl`, cache file
|
133
153
|
- `docs/.gitattributes`, merge mechanism for cache file
|
134
154
|
- The Git Hooks mechanism is used to automatically trigger the storing of the cache (on each 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!
|
@@ -140,11 +160,11 @@ The plugin supports deep customization, such as **icon style, font style, theme
|
|
140
160
|
A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
|
141
161
|
|
142
162
|
- **Origin**:
|
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, I don't understand why not read the file system time, but to use the git time, and the filesystem time is
|
163
|
+
- 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, I don't understand why not read the file system time, but to use the git time, and the filesystem time is exact, then 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
|
144
164
|
- **Iteration**:
|
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
|
146
|
-
- Method 1: Use the last git commit time as the last update time
|
147
|
-
- Method 2:
|
165
|
+
- 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. There are many solutions:
|
166
|
+
- Method 1: Use the last git commit time as the last update time and the first git commit time as the creation time, mkdocs-git-revision-date-localized-plugin does this. (This way, there will be a margin of error and dependency on git)
|
167
|
+
- Method 2: Cache the original time in advance, and then read the cache subsequently (The time is exact and no dependency on any environment). 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 easier, 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!
|
148
168
|
- **Difficulty**:
|
149
169
|
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!
|
150
170
|
- 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 git action occurs, such as every time commit is performed
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import logging
|
2
|
+
import subprocess
|
3
|
+
from pathlib import Path
|
4
|
+
from .utils import read_json_cache, read_jsonl_cache, write_jsonl_cache, get_file_creation_time, get_git_first_commit_time
|
5
|
+
|
6
|
+
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
7
|
+
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
8
|
+
|
9
|
+
def find_mkdocs_projects():
|
10
|
+
projects = []
|
11
|
+
try:
|
12
|
+
git_root = Path(subprocess.check_output(
|
13
|
+
['git', 'rev-parse', '--show-toplevel'],
|
14
|
+
text=True, encoding='utf-8'
|
15
|
+
).strip())
|
16
|
+
|
17
|
+
# 遍历 git_root 及子目录, 寻找 mkdocs.yml 文件
|
18
|
+
for config_file in git_root.rglob('mkdocs.y*ml'):
|
19
|
+
if config_file.name.lower() in ('mkdocs.yml', 'mkdocs.yaml'):
|
20
|
+
projects.append(config_file.parent)
|
21
|
+
|
22
|
+
if not projects:
|
23
|
+
logger.warning("No MkDocs projects found in the repository")
|
24
|
+
except subprocess.CalledProcessError as e:
|
25
|
+
logger.error(f"Failed to find the Git repository root: {e}")
|
26
|
+
except Exception as e:
|
27
|
+
logger.error(f"Unexpected error while searching for MkDocs projects: {e}")
|
28
|
+
|
29
|
+
return projects
|
30
|
+
|
31
|
+
def setup_gitattributes(docs_dir: Path):
|
32
|
+
try:
|
33
|
+
gitattributes_path = docs_dir / '.gitattributes'
|
34
|
+
union_merge_line = ".dates_cache.jsonl merge=union"
|
35
|
+
# custom_merge_line = ".dates_cache.json merge=custom_json_merge"
|
36
|
+
content = gitattributes_path.read_text(encoding='utf-8') if gitattributes_path.exists() else ""
|
37
|
+
if union_merge_line not in content:
|
38
|
+
if content and not content.endswith('\n'):
|
39
|
+
content += '\n'
|
40
|
+
content += f"{union_merge_line}\n"
|
41
|
+
gitattributes_path.write_text(content, encoding='utf-8')
|
42
|
+
subprocess.run(["git", "add", str(gitattributes_path)], check=True)
|
43
|
+
logger.info(f"Updated .gitattributes file: {gitattributes_path}")
|
44
|
+
return True
|
45
|
+
except (IOError, OSError) as e:
|
46
|
+
logger.error(f"Failed to read/write .gitattributes file: {e}")
|
47
|
+
except Exception as e:
|
48
|
+
logger.error(f"Failed to add .gitattributes to git: {e}")
|
49
|
+
return False
|
50
|
+
|
51
|
+
def update_cache():
|
52
|
+
global_updated = False
|
53
|
+
|
54
|
+
for project_dir in find_mkdocs_projects():
|
55
|
+
try:
|
56
|
+
project_updated = False
|
57
|
+
|
58
|
+
docs_dir = project_dir / 'docs'
|
59
|
+
if not docs_dir.exists():
|
60
|
+
logger.error(f"Document directory does not exist: {docs_dir}")
|
61
|
+
continue
|
62
|
+
|
63
|
+
# 设置.gitattributes文件
|
64
|
+
global_updated = setup_gitattributes(docs_dir)
|
65
|
+
|
66
|
+
# 获取docs目录下已跟踪(tracked)的markdown文件
|
67
|
+
cmd = ["git", "ls-files", "*.md"]
|
68
|
+
result = subprocess.run(cmd, cwd=docs_dir, capture_output=True, text=True)
|
69
|
+
tracked_files = result.stdout.splitlines() if result.stdout else []
|
70
|
+
|
71
|
+
if not tracked_files:
|
72
|
+
logger.info(f"No tracked markdown files found in {docs_dir}")
|
73
|
+
continue
|
74
|
+
|
75
|
+
# 读取旧的JSON缓存文件(如果存在)
|
76
|
+
json_cache_file = docs_dir / '.dates_cache.json'
|
77
|
+
json_dates_cache = read_json_cache(json_cache_file)
|
78
|
+
|
79
|
+
# 读取新的JSONL缓存文件(如果存在)
|
80
|
+
jsonl_cache_file = docs_dir / '.dates_cache.jsonl'
|
81
|
+
jsonl_dates_cache = read_jsonl_cache(jsonl_cache_file)
|
82
|
+
|
83
|
+
# 根据 git已跟踪的文件来更新
|
84
|
+
for rel_path in tracked_files:
|
85
|
+
try:
|
86
|
+
# 如果文件已在JSONL缓存中,跳过
|
87
|
+
if rel_path in jsonl_dates_cache:
|
88
|
+
continue
|
89
|
+
|
90
|
+
full_path = docs_dir / rel_path
|
91
|
+
# 处理新文件或迁移旧JSON缓存
|
92
|
+
if rel_path in json_dates_cache:
|
93
|
+
jsonl_dates_cache[rel_path] = json_dates_cache[rel_path]
|
94
|
+
project_updated = True
|
95
|
+
elif full_path.exists():
|
96
|
+
created_time = get_file_creation_time(full_path)
|
97
|
+
if not jsonl_cache_file.exists() and not json_cache_file.exists():
|
98
|
+
git_time = get_git_first_commit_time(full_path)
|
99
|
+
if git_time:
|
100
|
+
created_time = min(created_time, git_time)
|
101
|
+
jsonl_dates_cache[rel_path] = {
|
102
|
+
"created": created_time.isoformat()
|
103
|
+
}
|
104
|
+
project_updated = True
|
105
|
+
except Exception as e:
|
106
|
+
logger.error(f"Error processing file {rel_path}: {e}")
|
107
|
+
continue
|
108
|
+
|
109
|
+
# 标记删除不再跟踪的文件
|
110
|
+
if len(jsonl_dates_cache) > len(tracked_files):
|
111
|
+
project_updated = True
|
112
|
+
|
113
|
+
# 如果有更新,写入JSONL缓存文件
|
114
|
+
if project_updated or not jsonl_cache_file.exists():
|
115
|
+
global_updated = write_jsonl_cache(jsonl_cache_file, jsonl_dates_cache, tracked_files)
|
116
|
+
except subprocess.CalledProcessError as e:
|
117
|
+
logger.error(f"Failed to execute git command: {e}")
|
118
|
+
continue
|
119
|
+
except Exception as e:
|
120
|
+
logger.error(f"Error processing project directory {project_dir}: {e}")
|
121
|
+
continue
|
122
|
+
return global_updated
|
123
|
+
|
124
|
+
|
125
|
+
if __name__ == "__main__":
|
126
|
+
update_cache()
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import logging
|
4
|
+
import subprocess
|
5
|
+
from pathlib import Path
|
6
|
+
import platform
|
7
|
+
|
8
|
+
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
9
|
+
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
10
|
+
|
11
|
+
def get_config_dir():
|
12
|
+
if platform.system().lower().startswith('win'):
|
13
|
+
return Path(os.getenv('APPDATA', str(Path.home() / 'AppData' / 'Roaming')))
|
14
|
+
else:
|
15
|
+
return Path.home() / '.config'
|
16
|
+
|
17
|
+
def check_python_version(interpreter):
|
18
|
+
try:
|
19
|
+
result = subprocess.run(
|
20
|
+
[interpreter, "-c", "import sys; print(sys.version_info >= (3, 7))"],
|
21
|
+
capture_output=True, text=True)
|
22
|
+
if result.returncode == 0 and result.stdout.strip().lower() == 'true':
|
23
|
+
return True
|
24
|
+
else:
|
25
|
+
logger.warning(f"Low python version, requires python_requires >=3.7")
|
26
|
+
except Exception as e:
|
27
|
+
logger.info(f"Failed to check {interpreter}: {str(e)}")
|
28
|
+
return False
|
29
|
+
|
30
|
+
def detect_python_interpreter():
|
31
|
+
# 检查可能的Python解释器
|
32
|
+
python_interpreters = ['python3', 'python']
|
33
|
+
for interpreter in python_interpreters:
|
34
|
+
if check_python_version(interpreter):
|
35
|
+
return f'#!/usr/bin/env {interpreter}'
|
36
|
+
|
37
|
+
# 如果都失败了,使用当前运行的Python解释器
|
38
|
+
return f'#!{sys.executable}'
|
39
|
+
|
40
|
+
def setup_hooks_directory():
|
41
|
+
config_dir = get_config_dir() / 'mkdocs-document-dates' / 'hooks'
|
42
|
+
try:
|
43
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
44
|
+
os.chmod(config_dir, 0o755)
|
45
|
+
return config_dir
|
46
|
+
except PermissionError:
|
47
|
+
logger.error(f"No permission to create directory: {config_dir}")
|
48
|
+
except Exception as e:
|
49
|
+
logger.error(f"Failed to create directory {config_dir}: {str(e)}")
|
50
|
+
return None
|
51
|
+
|
52
|
+
def install_hook_file(source_dir: Path, target_dir: Path):
|
53
|
+
try:
|
54
|
+
shebang = detect_python_interpreter()
|
55
|
+
for item in source_dir.iterdir():
|
56
|
+
# 跳过隐藏文件和目录
|
57
|
+
if item.name.startswith('.') or not item.is_file():
|
58
|
+
continue
|
59
|
+
# 添加 shebang 行
|
60
|
+
content = item.read_text(encoding='utf-8')
|
61
|
+
if content.startswith('#!'):
|
62
|
+
content = shebang + os.linesep + content[content.find('\n')+1:]
|
63
|
+
else:
|
64
|
+
content = shebang + os.linesep + content
|
65
|
+
|
66
|
+
target_hook_path = target_dir / item.name
|
67
|
+
target_hook_path.write_text(content, encoding='utf-8')
|
68
|
+
os.chmod(target_hook_path, 0o755)
|
69
|
+
|
70
|
+
return True
|
71
|
+
except Exception as e:
|
72
|
+
logger.error(f"Failed to create hook file {target_hook_path}: {str(e)}")
|
73
|
+
return False
|
74
|
+
|
75
|
+
def configure_git_hooks(hooks_dir):
|
76
|
+
try:
|
77
|
+
# 配置自定义合并驱动
|
78
|
+
# script_path = hooks_dir / 'json_merge_driver.py'
|
79
|
+
# subprocess.run(['git', 'config', '--global', 'merge.custom_json_merge.name', 'Custom JSON merge driver'], check=True)
|
80
|
+
# subprocess.run(['git', 'config', '--global', 'merge.custom_json_merge.driver', f'"{sys.executable}" "{script_path}" %O %A %B'], check=True)
|
81
|
+
|
82
|
+
subprocess.run(['git', 'config', '--global', 'core.hooksPath', str(hooks_dir)], check=True)
|
83
|
+
logger.info(f"Git hooks successfully installed in: {hooks_dir}")
|
84
|
+
return True
|
85
|
+
except Exception:
|
86
|
+
logger.warning("Git not detected, using plugin in a no-Git environment")
|
87
|
+
return False
|
88
|
+
|
89
|
+
def install():
|
90
|
+
try:
|
91
|
+
# 创建hooks目录
|
92
|
+
target_dir = setup_hooks_directory()
|
93
|
+
if not target_dir:
|
94
|
+
return False
|
95
|
+
|
96
|
+
# 安装hook文件
|
97
|
+
source_dir = Path(__file__).parent / 'hooks'
|
98
|
+
if not install_hook_file(source_dir, target_dir):
|
99
|
+
return False
|
100
|
+
|
101
|
+
# 配置git hooks路径
|
102
|
+
return configure_git_hooks(target_dir)
|
103
|
+
|
104
|
+
except Exception as e:
|
105
|
+
logger.error(f"Unexpected error during hooks installation: {str(e)}")
|
106
|
+
return False
|
107
|
+
|
108
|
+
if __name__ == '__main__':
|
109
|
+
install()
|