mkdocs-document-dates 3.1.3__tar.gz → 3.1.6__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.
Files changed (44) hide show
  1. mkdocs_document_dates-3.1.6/MANIFEST.in +2 -0
  2. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/PKG-INFO +73 -38
  3. mkdocs_document_dates-3.1.6/README.md +184 -0
  4. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/cache_manager.py +74 -81
  5. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/hooks_installer.py +2 -14
  6. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/plugin.py +102 -156
  7. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/config/user.config.css +7 -11
  8. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/config/user.config.js +10 -5
  9. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/core/core.css +8 -7
  10. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/core/core.js +26 -77
  11. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates.egg-info/PKG-INFO +73 -38
  12. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates.egg-info/SOURCES.txt +1 -0
  13. mkdocs_document_dates-3.1.6/mkdocs_document_dates.egg-info/requires.txt +1 -0
  14. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/setup.py +3 -5
  15. mkdocs_document_dates-3.1.3/README.md +0 -149
  16. mkdocs_document_dates-3.1.3/mkdocs_document_dates.egg-info/requires.txt +0 -1
  17. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/LICENSE +0 -0
  18. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/__init__.py +0 -0
  19. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/hooks/pre-commit +0 -0
  20. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/core/timeago-load.js +0 -0
  21. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
  22. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
  23. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/ar.json +0 -0
  24. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/de.json +0 -0
  25. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/en.json +0 -0
  26. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/es.json +0 -0
  27. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/fr.json +0 -0
  28. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/ja.json +0 -0
  29. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/ko.json +0 -0
  30. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/ru.json +0 -0
  31. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/zh.json +0 -0
  32. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/languages/zh_TW.json +0 -0
  33. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
  34. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/light.css +0 -0
  35. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/material.css +0 -0
  36. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
  37. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/scale.css +0 -0
  38. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
  39. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
  40. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
  41. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
  42. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
  43. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
  44. {mkdocs_document_dates-3.1.3 → mkdocs_document_dates-3.1.6}/setup.cfg +0 -0
@@ -0,0 +1,2 @@
1
+ global-exclude tests/*
2
+ global-exclude tests/**/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-document-dates
3
- Version: 3.1.3
3
+ Version: 3.1.6
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
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.7
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: mkdocs>=1.0.0
15
+ Requires-Dist: mkdocs>=1.1.0
16
16
  Dynamic: author
17
17
  Dynamic: author-email
18
18
  Dynamic: classifier
@@ -35,17 +35,14 @@ An easy-to-use, lightweight MkDocs plugin for displaying the <mark>exact</mark>
35
35
 
36
36
  ## Features
37
37
 
38
- - Work in any environment, for Git-less environments, CI/CD environments (e.g. GitHub Actions), one-person collaboration, multi-person collaboration, etc
39
- - Support for manually specifying time and author info in `Front Matter`
38
+ - Always display exact meta-info of the document for any environment (no-Git, Git, all CI/CD build systems, etc)
39
+ - Support for manually specifying time and author in `Front Matter`
40
40
  - Support for multiple time formats (date, datetime, timeago)
41
- - Support for document exclusion mode
42
41
  - Flexible display position (top or bottom)
43
42
  - Elegant styling (fully customizable)
44
43
  - Supports Tooltip Hover Tips
45
44
  - Intelligent repositioning to always float optimally in view
46
45
  - 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
46
  - Multi-language support, cross-platform support (Windows, macOS, Linux)
50
47
 
51
48
  ## Showcases
@@ -74,23 +71,20 @@ plugins:
74
71
  - document-dates:
75
72
  position: top # Display position: top (after title) bottom (end of document), default: bottom
76
73
  type: date # Date type: date datetime timeago, default: date
77
- locale: en # Localization: zh zh_TW en es fr de ar ja ko ru, default: en
78
- date_format: '%Y-%m-%d' # Date format, supports all python datetime format strings, e.g., %Y-%m-%d, %b %d, %Y, etc
79
- time_format: '%H:%M:%S' # Time format (valid only if type=datetime)
74
+ locale: en # Localization: en zh zh_TW es fr de ar ja ko ru, default: en
75
+ date_format: '%Y-%m-%d' # Date format strings, e.g., %Y-%m-%d, %b %d, %Y, etc
76
+ time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
80
77
  exclude: # List of excluded files
81
78
  - temp.md # Exclude specific file
82
79
  - private/* # Exclude all files in private directory, including subdirectories
83
- - drafts/*.md # Exclude all markdown files in the current directory drafts, but not subdirectories
84
-
85
- show_author: true # Show author or not: true false, default: true
86
-
80
+ show_author: true # Show author or not, default: true
87
81
  ```
88
82
 
89
83
  ## Specify time manually
90
84
 
91
85
  The plugin will automatically get the exact time of the document, will automatically cache the creation time, but of course, you can also specify it manually in `Front Matter`
92
86
 
93
- Priority: `Front Matter` > `Cache Files` > `File System Timestamps`
87
+ Priority order: `Front Matter` > `Cache Files` > `File System Timestamps`
94
88
 
95
89
  ```yaml
96
90
  ---
@@ -108,7 +102,7 @@ modified: 2025-02-23
108
102
 
109
103
  The plugin will automatically get the author of the document, will parse the email and make a link, also you can specify it manually in `Front Matter`
110
104
 
111
- Priority: `Front Matter` > `Git Author Info` > `PC Username`
105
+ Priority order: `Front Matter` > `Git Author` > `site_author (mkdocs.yml)` > `PC Username`
112
106
 
113
107
  ```yaml
114
108
  ---
@@ -124,26 +118,67 @@ email: e-name@gmail.com
124
118
 
125
119
  ## Customization
126
120
 
127
- 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):
121
+ The plugin supports deep customization, such as **icon style, font style, theme color, animation type, dividing line**, etc. Everything is customizable (I've already written the code, you just need to turn on the uncomment switch):
122
+
123
+ | Function: | Location: |
124
+ | :----------------------: | ---------------------------------------- |
125
+ | **Style & Theme** | `docs/assets/document_dates/user.config.css` |
126
+ | **Properties & Functions** | `docs/assets/document_dates/user.config.js` |
127
+ | **Localized languages** | `docs/assets/document_dates/languages/` <br />refer to the template file `en.json` for any additions or modifications |
128
+
129
+ **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):
130
+
131
+ - 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
132
+ - In `mkdocs.yml`, add the following two lines to configure the full version of `timeago.full.min.js` to load all languages at once
133
+ ```yaml
134
+ extra_javascript:
135
+ - assets/document_dates/core/timeago.full.min.js
136
+ - assets/document_dates/core/timeago-load.js
137
+ ```
138
+
139
+ **Demo Images**:
140
+
141
+ ![01-default-w](mkdocs_document_dates/demo_images/01-default-w.png)
142
+ ![02-change-icon](mkdocs_document_dates/demo_images/02-change-icon.png)
143
+ ![02-change-icon-color](mkdocs_document_dates/demo_images/02-change-icon-color.png)
144
+ ![04-default-pop-up](mkdocs_document_dates/demo_images/04-default-pop-up.png)
145
+ ![05-change-theme](mkdocs_document_dates/demo_images/05-change-theme.png)
146
+
147
+ ![06-change-theme](mkdocs_document_dates/demo_images/06-change-theme.png)
148
+ ![08-pop-up-from-bottom](mkdocs_document_dates/demo_images/08-pop-up-from-bottom.png)
149
+
150
+ ## Used in templates
151
+
152
+ You can access the meta-info of a document in a template using the following variables:
153
+
154
+ - page.meta.document_dates_created
155
+ - page.meta.document_dates_modified
156
+ - page.meta.document_dates_authors
157
+
158
+ For example like this:
159
+
160
+ ```jinja2
161
+ <div><span>{{ page.meta.document_dates_created }}</span></div>
162
+ <div><span>{{ page.meta.document_dates_modified }}</span></div>
163
+ {% set authors = page.meta.document_dates_authors %}
164
+ {% if authors %}
165
+ <div>
166
+ {% for author in authors %}
167
+ {% if author.email %}<a href="mailto:{{ author.email }}">{{ author.name }}</a>
168
+ {% else %}<span>{{ author.name }}</span>{% endif %}
169
+ {% endfor %}
170
+ </div>
171
+ {% endif %}
172
+ ```
128
173
 
129
- - Style & Theme: `docs/assets/document_dates/user.config.css`
130
- - Properties & Animations: `docs/assets/document_dates/user.config.js`
131
- - Localized languages: `docs/assets/document_dates/languages/` , refer to the template file `en.json` for any additions or modifications
132
- - timeago.js localization: `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):
133
- - 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
134
- - In `mkdocs.yml`, add the following two lines to configure the full version of `timeago.full.min.js` to load all languages at once
135
- ```yaml
136
- extra_javascript:
137
- - assets/document_dates/core/timeago.full.min.js
138
- - assets/document_dates/core/timeago-load.js
139
- ```
174
+ **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`)
140
175
 
141
176
  ## Other Tips
142
177
 
143
- - 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:
178
+ - 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:
144
179
  - `docs/.dates_cache.jsonl`, cache file
145
180
  - `docs/.gitattributes`, merge mechanism for cache file
146
- - 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!
181
+ - 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!
147
182
 
148
183
  <br />
149
184
 
@@ -152,11 +187,11 @@ The plugin supports deep customization, such as icon style, font style, theme co
152
187
  A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
153
188
 
154
189
  - **Origin**:
155
- - 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
190
+ - 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
156
191
  - **Iteration**:
157
- - 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:
158
- - 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
159
- - 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!
192
+ - 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:
193
+ - 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)
194
+ - 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!
160
195
  - **Difficulty**:
161
196
  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!
162
197
  - 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
@@ -167,10 +202,10 @@ A dispensable, insignificant little plug-in, friends who have time can take a lo
167
202
  4. How can I ensure that a single cache file does not conflict when collaborating with multi-person?
168
203
  - Workaround: use JSONL (JSON Lines) instead of JSON, and with the merge strategy 'merge=union'
169
204
  - **Improve**:
170
- - Since it has been re-developed, it will be designed in the direction of **excellent products**, and the pursuit of the ultimate **ease of use, simplicity and personalization**
171
- - Ease of use: don't let users do things manually if you can, e.g., auto-install Git Hooks, auto-cache, auto-commit, provide customized templates, etc
172
- - Simplicity: no unnecessary configurations, the less the simpler, e.g. git account information, repo information, etc., are not required
173
- - Personalization: almost everything can be customized, whether it's icons, styles, themes, or features, it's all fully customizable
205
+ - Since it's a newly developed plugin, it will be designed in the direction of **excellent products**, and the pursuit of the ultimate **ease of use, simplicity and personalization**
206
+ - **Ease of use**: don't let users do things manually if you can, e.g., auto-install Git Hooks, auto-cache, auto-commit, provide customized templates, etc
207
+ - **Simplicity**: no unnecessary configuration, no Git dependencies, no CI/CD configuration dependencies, no other package dependencies
208
+ - **Personalization**: almost everything can be customized, whether it's icons, styles, themes, or features, it's all fully customizable
174
209
  - In addition, it has good compatibility and extensibility, and works well in WIN7, mobile devices, old Safari, etc
175
210
  - **The Last Secret**:
176
211
  - Programming is a hobby, and I'm a marketer of 8 years (Feel free to leave a comment)
@@ -0,0 +1,184 @@
1
+ # mkdocs-document-dates
2
+
3
+ English | [简体中文](README_zh.md)
4
+
5
+
6
+
7
+ An easy-to-use, lightweight MkDocs plugin for displaying the <mark>exact</mark> creation time, last modification time and author info of markdown documents.
8
+
9
+ ## Features
10
+
11
+ - Always display exact meta-info of the document for any environment (no-Git, Git, all CI/CD build systems, etc)
12
+ - Support for manually specifying time and author in `Front Matter`
13
+ - Support for multiple time formats (date, datetime, timeago)
14
+ - Flexible display position (top or bottom)
15
+ - Elegant styling (fully customizable)
16
+ - Supports Tooltip Hover Tips
17
+ - Intelligent repositioning to always float optimally in view
18
+ - Supports automatic theme switching following Material's light/dark color scheme
19
+ - Multi-language support, cross-platform support (Windows, macOS, Linux)
20
+
21
+ ## Showcases
22
+
23
+ ![render](render.gif)
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install mkdocs-document-dates
29
+ ```
30
+
31
+ ## Configuration
32
+
33
+ Just add the plugin to your `mkdocs.yml`:
34
+
35
+ ```yaml
36
+ plugins:
37
+ - document-dates
38
+ ```
39
+
40
+ Or, personalize the configuration:
41
+
42
+ ```yaml
43
+ plugins:
44
+ - document-dates:
45
+ position: top # Display position: top (after title) bottom (end of document), default: bottom
46
+ type: date # Date type: date datetime timeago, default: date
47
+ locale: en # Localization: en zh zh_TW es fr de ar ja ko ru, default: en
48
+ date_format: '%Y-%m-%d' # Date format strings, e.g., %Y-%m-%d, %b %d, %Y, etc
49
+ time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
50
+ exclude: # List of excluded files
51
+ - temp.md # Exclude specific file
52
+ - private/* # Exclude all files in private directory, including subdirectories
53
+ show_author: true # Show author or not, default: true
54
+ ```
55
+
56
+ ## Specify time manually
57
+
58
+ The plugin will automatically get the exact time of the document, will automatically cache the creation time, but of course, you can also specify it manually in `Front Matter`
59
+
60
+ Priority order: `Front Matter` > `Cache Files` > `File System Timestamps`
61
+
62
+ ```yaml
63
+ ---
64
+ created: 2023-01-01
65
+ modified: 2025-02-23
66
+ ---
67
+
68
+ # Document Title
69
+ ```
70
+
71
+ - `created` can be replaced with: `created, date, creation`
72
+ - `modified` can be replaced with: `modified, updated, last_modified, last_updated`
73
+
74
+ ## Specify author manually
75
+
76
+ The plugin will automatically get the author of the document, will parse the email and make a link, also you can specify it manually in `Front Matter`
77
+
78
+ Priority order: `Front Matter` > `Git Author` > `site_author (mkdocs.yml)` > `PC Username`
79
+
80
+ ```yaml
81
+ ---
82
+ author: any-name
83
+ email: e-name@gmail.com
84
+ ---
85
+
86
+ # Document Title
87
+ ```
88
+
89
+ - `author` can be replaced with: `author, name`
90
+ - `email` can be replaced with: `email, mail`
91
+
92
+ ## Customization
93
+
94
+ The plugin supports deep customization, such as **icon style, font style, theme color, animation type, dividing line**, etc. Everything is customizable (I've already written the code, you just need to turn on the uncomment switch):
95
+
96
+ | Function: | Location: |
97
+ | :----------------------: | ---------------------------------------- |
98
+ | **Style & Theme** | `docs/assets/document_dates/user.config.css` |
99
+ | **Properties & Functions** | `docs/assets/document_dates/user.config.js` |
100
+ | **Localized languages** | `docs/assets/document_dates/languages/` <br />refer to the template file `en.json` for any additions or modifications |
101
+
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):
103
+
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
105
+ - In `mkdocs.yml`, add the following two lines to configure the full version of `timeago.full.min.js` to load all languages at once
106
+ ```yaml
107
+ extra_javascript:
108
+ - assets/document_dates/core/timeago.full.min.js
109
+ - assets/document_dates/core/timeago-load.js
110
+ ```
111
+
112
+ **Demo Images**:
113
+
114
+ ![01-default-w](mkdocs_document_dates/demo_images/01-default-w.png)
115
+ ![02-change-icon](mkdocs_document_dates/demo_images/02-change-icon.png)
116
+ ![02-change-icon-color](mkdocs_document_dates/demo_images/02-change-icon-color.png)
117
+ ![04-default-pop-up](mkdocs_document_dates/demo_images/04-default-pop-up.png)
118
+ ![05-change-theme](mkdocs_document_dates/demo_images/05-change-theme.png)
119
+
120
+ ![06-change-theme](mkdocs_document_dates/demo_images/06-change-theme.png)
121
+ ![08-pop-up-from-bottom](mkdocs_document_dates/demo_images/08-pop-up-from-bottom.png)
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
+
149
+ ## Other Tips
150
+
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:
152
+ - `docs/.dates_cache.jsonl`, cache file
153
+ - `docs/.gitattributes`, merge mechanism for cache file
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!
155
+
156
+ <br />
157
+
158
+ ## Development Stories (Optional)
159
+
160
+ A dispensable, insignificant little plug-in, friends who have time can take a look \^\_\^
161
+
162
+ - **Origin**:
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
164
+ - **Iteration**:
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!
168
+ - **Difficulty**:
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!
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
171
+ 2. How to install Git Hooks automatically? When and how are they triggered? Installing packages from PyPI via pip doesn't have a standard post-install hook mechanism
172
+ - Workaround: After analyzing the flow of pip installing packages from PyPI, I found that when compiling and installing through the source package (sdist), setuptools will be called to handle it, so we can find a way to implant the installation script in the process of setuptools, i.e., we can add a custom script in setup.py
173
+ 3. How to design a cross-platform hook? To execute a python script, we need to explicitly specify the python interpreter, and the user's python environment varies depending on the operating system, the way python is installed, and the configuration, so how can we ensure that it works properly in all environments?
174
+ - Solution: I considered using a shell script, but since I'd have to call back to python eventually, it's easier to use a python script. We can detect the user's python environment when the hook is installed, and then dynamically set the hook's shebang line to set the correct python interpreter
175
+ 4. How can I ensure that a single cache file does not conflict when collaborating with multi-person?
176
+ - Workaround: use JSONL (JSON Lines) instead of JSON, and with the merge strategy 'merge=union'
177
+ - **Improve**:
178
+ - Since it's a newly developed plugin, it will be designed in the direction of **excellent products**, and the pursuit of the ultimate **ease of use, simplicity and personalization**
179
+ - **Ease of use**: don't let users do things manually if you can, e.g., auto-install Git Hooks, auto-cache, auto-commit, provide customized templates, etc
180
+ - **Simplicity**: no unnecessary configuration, no Git dependencies, no CI/CD configuration dependencies, no other package dependencies
181
+ - **Personalization**: almost everything can be customized, whether it's icons, styles, themes, or features, it's all fully customizable
182
+ - In addition, it has good compatibility and extensibility, and works well in WIN7, mobile devices, old Safari, etc
183
+ - **The Last Secret**:
184
+ - Programming is a hobby, and I'm a marketer of 8 years (Feel free to leave a comment)
@@ -26,7 +26,7 @@ def find_mkdocs_projects():
26
26
  projects.append(config_file.parent)
27
27
 
28
28
  if not projects:
29
- logging.info("No MkDocs projects found in the repository")
29
+ logging.warning("No MkDocs projects found in the repository")
30
30
  except subprocess.CalledProcessError as e:
31
31
  logging.error(f"Failed to find the Git repository root: {e}")
32
32
  except Exception as e:
@@ -56,9 +56,9 @@ def get_git_first_commit_time(file_path):
56
56
  # git log --reverse --format="%aI" --date=iso -- {file_path} | head -n 1
57
57
  result = subprocess.run(['git', 'log', '--reverse', '--format=%aI', '--', file_path], capture_output=True, text=True)
58
58
  if result.returncode == 0:
59
- commits = result.stdout.strip().split('\n')
60
- if commits and commits[0]:
61
- return datetime.fromisoformat(commits[0]).replace(tzinfo=None)
59
+ first_line = result.stdout.partition('\n')[0].strip()
60
+ if first_line:
61
+ return datetime.fromisoformat(first_line).replace(tzinfo=None)
62
62
  except Exception as e:
63
63
  logging.info(f"Error getting git first commit time for {file_path}: {e}")
64
64
  return None
@@ -67,7 +67,7 @@ def setup_gitattributes(docs_dir):
67
67
  updated = False
68
68
  try:
69
69
  gitattributes_path = docs_dir / '.gitattributes'
70
- union_config_line = ".dates_cache.jsonl merge=union"
70
+ union_config_line = ".dates_cache.jsonl merge=union"
71
71
  if gitattributes_path.exists():
72
72
  with open(gitattributes_path, 'r', encoding='utf-8') as f:
73
73
  content = f.read()
@@ -98,7 +98,7 @@ def read_json_cache(cache_file):
98
98
  with open(cache_file, "r", encoding='utf-8') as f:
99
99
  dates_cache = json.load(f)
100
100
  except (IOError, json.JSONDecodeError) as e:
101
- logging.error(f"Failed to read existing JSON cache file: {e}")
101
+ logging.warning(f"Error reading from '.dates_cache.json': {str(e)}")
102
102
  return dates_cache
103
103
 
104
104
  def read_jsonl_cache(jsonl_file):
@@ -115,7 +115,7 @@ def read_jsonl_cache(jsonl_file):
115
115
  except (json.JSONDecodeError, StopIteration) as e:
116
116
  logging.warning(f"Skipping invalid JSONL line: {e}")
117
117
  except IOError as e:
118
- logging.error(f"Failed to read existing JSONL cache file: {e}")
118
+ logging.warning(f"Error reading from '.dates_cache.jsonl': {str(e)}")
119
119
  return dates_cache
120
120
 
121
121
  def write_jsonl_cache(jsonl_file, dates_cache, tracked_files):
@@ -144,88 +144,81 @@ def write_jsonl_cache(jsonl_file, dates_cache, tracked_files):
144
144
 
145
145
  def update_cache():
146
146
  global_updated = False
147
- try:
148
- for project_dir in find_mkdocs_projects():
149
- try:
150
- project_updated = False
151
147
 
152
- docs_dir = project_dir / 'docs'
153
- if not docs_dir.exists():
154
- logging.error(f"Document directory does not exist: {docs_dir}")
155
- continue
148
+ for project_dir in find_mkdocs_projects():
149
+ try:
150
+ project_updated = False
156
151
 
157
- # 设置.gitattributes文件
158
- gitattributes_updated = setup_gitattributes(docs_dir)
159
- if gitattributes_updated:
160
- global_updated = True
152
+ docs_dir = project_dir / 'docs'
153
+ if not docs_dir.exists():
154
+ logging.error(f"Document directory does not exist: {docs_dir}")
155
+ continue
161
156
 
162
- # 获取docs目录下已跟踪(tracked)的markdown文件
163
- cmd = ["git", "ls-files", "*.md"]
164
- result = subprocess.run(cmd, cwd=docs_dir, capture_output=True, text=True, check=True)
165
- tracked_files = result.stdout.splitlines() if result.stdout else []
166
-
167
- if not tracked_files:
168
- logging.info(f"No tracked markdown files found in {docs_dir}")
169
- continue
157
+ # 设置.gitattributes文件
158
+ gitattributes_updated = setup_gitattributes(docs_dir)
159
+ if gitattributes_updated:
160
+ global_updated = True
170
161
 
171
- # 读取旧的JSON缓存文件(如果存在)
172
- json_cache_file = docs_dir / '.dates_cache.json'
173
- json_dates_cache = read_json_cache(json_cache_file)
162
+ # 获取docs目录下已跟踪(tracked)的markdown文件
163
+ cmd = ["git", "ls-files", "*.md"]
164
+ result = subprocess.run(cmd, cwd=docs_dir, capture_output=True, text=True, check=True)
165
+ tracked_files = result.stdout.splitlines() if result.stdout else []
174
166
 
175
- # 读取新的JSONL缓存文件(如果存在)
176
- jsonl_cache_file = docs_dir / '.dates_cache.jsonl'
177
- jsonl_dates_cache = read_jsonl_cache(jsonl_cache_file)
178
-
179
- # 根据 git已跟踪的文件来更新
180
- for file_path in tracked_files:
181
- try:
182
- rel_path = file_path
183
- full_path = docs_dir / rel_path
184
-
185
- # 如果文件已在JSONL缓存中,跳过
186
- if rel_path in jsonl_dates_cache:
187
- continue
188
-
189
- # 处理新文件或迁移旧JSON缓存
190
- if rel_path in json_dates_cache:
191
- jsonl_dates_cache[rel_path] = json_dates_cache[rel_path]
192
- project_updated = True
193
- elif full_path.exists():
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)
199
- jsonl_dates_cache[rel_path] = {
200
- "created": created_time.isoformat()
201
- }
202
- project_updated = True
203
- except Exception as e:
204
- logging.error(f"Error processing file {file_path}: {e}")
167
+ if not tracked_files:
168
+ logging.info(f"No tracked markdown files found in {docs_dir}")
169
+ continue
170
+
171
+ # 读取旧的JSON缓存文件(如果存在)
172
+ json_cache_file = docs_dir / '.dates_cache.json'
173
+ json_dates_cache = read_json_cache(json_cache_file)
174
+
175
+ # 读取新的JSONL缓存文件(如果存在)
176
+ jsonl_cache_file = docs_dir / '.dates_cache.jsonl'
177
+ jsonl_dates_cache = read_jsonl_cache(jsonl_cache_file)
178
+
179
+ # 根据 git已跟踪的文件来更新
180
+ for rel_path in tracked_files:
181
+ try:
182
+ # 如果文件已在JSONL缓存中,跳过
183
+ if rel_path in jsonl_dates_cache:
205
184
  continue
206
185
 
207
- # 标记删除不再跟踪的文件
208
- files_to_remove = set(jsonl_dates_cache.keys()) - set(tracked_files)
209
- if files_to_remove:
210
- project_updated = True
211
- logging.info(f"Removing {len(files_to_remove)} untracked files from cache")
212
-
213
- # 如果有更新,写入JSONL缓存文件
214
- if project_updated or not jsonl_cache_file.exists():
215
- if write_jsonl_cache(jsonl_cache_file, jsonl_dates_cache, tracked_files):
216
- global_updated = True
217
- else:
218
- logging.info(f"No updates needed for {jsonl_cache_file}")
219
- except subprocess.CalledProcessError as e:
220
- logging.error(f"Failed to execute git command: {e}")
221
- continue
222
- except Exception as e:
223
- logging.error(f"Error processing project directory {project_dir}: {e}")
224
- continue
186
+ full_path = docs_dir / rel_path
187
+ # 处理新文件或迁移旧JSON缓存
188
+ if rel_path in json_dates_cache:
189
+ jsonl_dates_cache[rel_path] = json_dates_cache[rel_path]
190
+ project_updated = True
191
+ elif full_path.exists():
192
+ created_time = get_file_creation_time(full_path)
193
+ if not jsonl_cache_file.exists() and not json_cache_file.exists():
194
+ git_time = get_git_first_commit_time(full_path)
195
+ if git_time:
196
+ created_time = min(created_time, git_time)
197
+ jsonl_dates_cache[rel_path] = {
198
+ "created": created_time.isoformat()
199
+ }
200
+ project_updated = True
201
+ except Exception as e:
202
+ logging.error(f"Error processing file {rel_path}: {e}")
203
+ continue
204
+
205
+ # 标记删除不再跟踪的文件
206
+ files_to_remove = set(jsonl_dates_cache.keys()) - set(tracked_files)
207
+ if files_to_remove:
208
+ project_updated = True
209
+ logging.info(f"Removing {len(files_to_remove)} untracked files from cache")
210
+
211
+ # 如果有更新,写入JSONL缓存文件
212
+ if project_updated or not jsonl_cache_file.exists():
213
+ if write_jsonl_cache(jsonl_cache_file, jsonl_dates_cache, tracked_files):
214
+ global_updated = True
215
+ except subprocess.CalledProcessError as e:
216
+ logging.error(f"Failed to execute git command: {e}")
217
+ continue
218
+ except Exception as e:
219
+ logging.error(f"Error processing project directory {project_dir}: {e}")
220
+ continue
225
221
 
226
- except Exception as e:
227
- logging.error(f"Unexpected error in update_cache: {e}")
228
-
229
222
  return global_updated
230
223
 
231
224
 
@@ -43,14 +43,6 @@ def detect_python_interpreter():
43
43
  # 如果都失败了,使用当前运行的Python解释器
44
44
  return f'#!{sys.executable}'
45
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 Exception:
51
- logging.warning("Git not detected, skip hooks installation")
52
- return False
53
-
54
46
  def setup_hooks_directory():
55
47
  config_dir = get_config_dir() / 'mkdocs-document-dates' / 'hooks'
56
48
  try:
@@ -95,16 +87,12 @@ def configure_git_hooks(hooks_dir):
95
87
  )
96
88
  logging.info(f"Git hooks successfully installed in: {hooks_dir}")
97
89
  return True
98
- except Exception as e:
99
- logging.error(f"Failed to set git hooks path: {str(e)}")
90
+ except Exception:
91
+ logging.warning("Git not detected, failed to set git hooks path")
100
92
  return False
101
93
 
102
94
  def install():
103
95
  try:
104
- # 检查git是否可用
105
- if not check_git_available():
106
- return False
107
-
108
96
  # 创建hooks目录
109
97
  hooks_dir = setup_hooks_directory()
110
98
  if not hooks_dir: