mkdocs-document-dates 3.4__tar.gz → 3.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mkdocs_document_dates-3.4.5/PKG-INFO +101 -0
- mkdocs_document_dates-3.4.5/README.md +75 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/cache_manager.py +2 -2
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks_installer.py +14 -3
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/plugin.py +115 -62
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/config/user.config.js +1 -1
- mkdocs_document_dates-3.4.5/mkdocs_document_dates/static/templates/recently_updated.html +42 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/utils.py +88 -52
- mkdocs_document_dates-3.4.5/mkdocs_document_dates.egg-info/PKG-INFO +101 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/SOURCES.txt +2 -0
- mkdocs_document_dates-3.4.5/pyproject.toml +4 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/setup.py +2 -1
- mkdocs_document_dates-3.4/PKG-INFO +0 -240
- mkdocs_document_dates-3.4/README.md +0 -214
- mkdocs_document_dates-3.4/mkdocs_document_dates.egg-info/PKG-INFO +0 -240
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/LICENSE +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/MANIFEST.in +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/__init__.py +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/config/user.config.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/core.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/core.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/default.config.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/core/utils.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/setup.cfg +0 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mkdocs-document-dates
|
3
|
+
Version: 3.4.5
|
4
|
+
Summary: A new generation MkDocs plugin for displaying exact creation time, last update time, authors, email of documents
|
5
|
+
Home-page: https://github.com/jaywhj/mkdocs-document-dates
|
6
|
+
Author: Aaron Wang
|
7
|
+
Author-email: aaronwqt@gmail.com
|
8
|
+
License: MIT
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Requires-Python: >=3.7
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
License-File: LICENSE
|
14
|
+
Requires-Dist: mkdocs>=1.1.0
|
15
|
+
Dynamic: author
|
16
|
+
Dynamic: author-email
|
17
|
+
Dynamic: classifier
|
18
|
+
Dynamic: description
|
19
|
+
Dynamic: description-content-type
|
20
|
+
Dynamic: home-page
|
21
|
+
Dynamic: license
|
22
|
+
Dynamic: license-file
|
23
|
+
Dynamic: requires-dist
|
24
|
+
Dynamic: requires-python
|
25
|
+
Dynamic: summary
|
26
|
+
|
27
|
+
# mkdocs-document-dates
|
28
|
+
|
29
|
+
English | [简体中文](README_zh.md)
|
30
|
+
|
31
|
+
<br />
|
32
|
+
|
33
|
+
A new generation MkDocs plugin for displaying exact **creation time, last update time, authors, email** of documents
|
34
|
+
|
35
|
+

|
36
|
+
|
37
|
+
## Features
|
38
|
+
|
39
|
+
- [x] Always displays **exact** meta information of the document and works in any environment (no Git, Git environments, Docker containers, all CI/CD build systems, etc.)
|
40
|
+
- [x] Support for manually specifying time and author in `Front Matter`
|
41
|
+
- [x] Support for multiple time formats (date, datetime, timeago)
|
42
|
+
- [x] Support for multiple author modes (avatar, text, hidden)
|
43
|
+
- [x] Flexible display position (top or bottom)
|
44
|
+
- [x] Elegant styling (fully customizable)
|
45
|
+
- [x] Smart Tooltip Hover Tips
|
46
|
+
- [x] Support list display of recently updated documents
|
47
|
+
- [x] Multi-language support, localization support, intelligent recognition of user language, automatic adaptation
|
48
|
+
- [x] Cross-platform support (Windows, macOS, Linux)
|
49
|
+
- [x] **Ultimate build efficiency**: O(1), no need to set env vars to distinguish runs
|
50
|
+
|
51
|
+
| PK of Build Efficiency: | 100 md: | 1000 md: | Time Complexity: |
|
52
|
+
| --------------------------- | :-----: | :------: | :----------: |
|
53
|
+
| git-revision-date-localized | > 3 s | > 30 s | O(n) |
|
54
|
+
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
```bash
|
59
|
+
pip install mkdocs-document-dates
|
60
|
+
```
|
61
|
+
|
62
|
+
## Configuration
|
63
|
+
|
64
|
+
Just add the plugin to your `mkdocs.yml`:
|
65
|
+
|
66
|
+
```yaml
|
67
|
+
plugins:
|
68
|
+
- document-dates
|
69
|
+
```
|
70
|
+
|
71
|
+
Or, full configuration:
|
72
|
+
|
73
|
+
```yaml
|
74
|
+
plugins:
|
75
|
+
- document-dates:
|
76
|
+
position: top # Display position: top(after title) bottom(end of document)
|
77
|
+
type: date # Date type: date datetime timeago, default: date
|
78
|
+
exclude: # List of excluded files
|
79
|
+
- temp.md # Example: exclude the specified file
|
80
|
+
- blog/* # Example: exclude all files in blog folder, including subfolders
|
81
|
+
date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
|
82
|
+
time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
|
83
|
+
show_author: true # Author display mode: true(avatar) text(text) false(hidden)
|
84
|
+
recently-updated: true # Whether to turn on recently updated data, default: false
|
85
|
+
```
|
86
|
+
|
87
|
+
## Customization Settings
|
88
|
+
|
89
|
+
In addition to the above basic configuration, the plug-in also provides a wealth of customization options to meet a variety of individual needs:
|
90
|
+
|
91
|
+
- [Specify Datetime](https://jaywhj.netlify.app/document-dates-en#Specify-Datetime): You can manually specify the creation time and last update time for each document
|
92
|
+
- [Specify Author](https://jaywhj.netlify.app/document-dates-en#Specify-Author): You can manually specify the author information for each document
|
93
|
+
- [Specify Avatar](https://jaywhj.netlify.app/document-dates-en#Specify-Avatar): You can manually specify the avatar for each author
|
94
|
+
- [Set Plugin Style](https://jaywhj.netlify.app/document-dates-en#Set-Plugin-Style): Such as icons, themes, colors, fonts, animations, dividing line, etc.
|
95
|
+
- [Add Localization Language](https://jaywhj.netlify.app/document-dates-en#Add-Localization-Language): More localization languages for `timeago` and `tooltip`
|
96
|
+
- [Use Template Variables](https://jaywhj.netlify.app/document-dates-en#Use-Template-Variables): Can be used to optimize `sitemap.xml` for site SEO, can be used to re-customize plug-ins, etc.
|
97
|
+
- [Add Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Add-Recently-Updated-Module): Enable list of recently updated documents
|
98
|
+
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms, and how to use it in Docker
|
99
|
+
- [Development Stories](https://jaywhj.netlify.app/document-dates-en#Development-Stories): Describes the origin of the plug-in, the difficulties and solutions encountered in development, and the principles and directions of product design
|
100
|
+
|
101
|
+
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# mkdocs-document-dates
|
2
|
+
|
3
|
+
English | [简体中文](README_zh.md)
|
4
|
+
|
5
|
+
<br />
|
6
|
+
|
7
|
+
A new generation MkDocs plugin for displaying exact **creation time, last update time, authors, email** of documents
|
8
|
+
|
9
|
+

|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
- [x] Always displays **exact** meta information of the document and works in any environment (no Git, Git environments, Docker containers, all CI/CD build systems, etc.)
|
14
|
+
- [x] Support for manually specifying time and author in `Front Matter`
|
15
|
+
- [x] Support for multiple time formats (date, datetime, timeago)
|
16
|
+
- [x] Support for multiple author modes (avatar, text, hidden)
|
17
|
+
- [x] Flexible display position (top or bottom)
|
18
|
+
- [x] Elegant styling (fully customizable)
|
19
|
+
- [x] Smart Tooltip Hover Tips
|
20
|
+
- [x] Support list display of recently updated documents
|
21
|
+
- [x] Multi-language support, localization support, intelligent recognition of user language, automatic adaptation
|
22
|
+
- [x] Cross-platform support (Windows, macOS, Linux)
|
23
|
+
- [x] **Ultimate build efficiency**: O(1), no need to set env vars to distinguish runs
|
24
|
+
|
25
|
+
| PK of Build Efficiency: | 100 md: | 1000 md: | Time Complexity: |
|
26
|
+
| --------------------------- | :-----: | :------: | :----------: |
|
27
|
+
| git-revision-date-localized | > 3 s | > 30 s | O(n) |
|
28
|
+
| document-dates | < 0.1 s | < 0.15 s | O(1) |
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
```bash
|
33
|
+
pip install mkdocs-document-dates
|
34
|
+
```
|
35
|
+
|
36
|
+
## Configuration
|
37
|
+
|
38
|
+
Just add the plugin to your `mkdocs.yml`:
|
39
|
+
|
40
|
+
```yaml
|
41
|
+
plugins:
|
42
|
+
- document-dates
|
43
|
+
```
|
44
|
+
|
45
|
+
Or, full configuration:
|
46
|
+
|
47
|
+
```yaml
|
48
|
+
plugins:
|
49
|
+
- document-dates:
|
50
|
+
position: top # Display position: top(after title) bottom(end of document)
|
51
|
+
type: date # Date type: date datetime timeago, default: date
|
52
|
+
exclude: # List of excluded files
|
53
|
+
- temp.md # Example: exclude the specified file
|
54
|
+
- blog/* # Example: exclude all files in blog folder, including subfolders
|
55
|
+
date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
|
56
|
+
time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
|
57
|
+
show_author: true # Author display mode: true(avatar) text(text) false(hidden)
|
58
|
+
recently-updated: true # Whether to turn on recently updated data, default: false
|
59
|
+
```
|
60
|
+
|
61
|
+
## Customization Settings
|
62
|
+
|
63
|
+
In addition to the above basic configuration, the plug-in also provides a wealth of customization options to meet a variety of individual needs:
|
64
|
+
|
65
|
+
- [Specify Datetime](https://jaywhj.netlify.app/document-dates-en#Specify-Datetime): You can manually specify the creation time and last update time for each document
|
66
|
+
- [Specify Author](https://jaywhj.netlify.app/document-dates-en#Specify-Author): You can manually specify the author information for each document
|
67
|
+
- [Specify Avatar](https://jaywhj.netlify.app/document-dates-en#Specify-Avatar): You can manually specify the avatar for each author
|
68
|
+
- [Set Plugin Style](https://jaywhj.netlify.app/document-dates-en#Set-Plugin-Style): Such as icons, themes, colors, fonts, animations, dividing line, etc.
|
69
|
+
- [Add Localization Language](https://jaywhj.netlify.app/document-dates-en#Add-Localization-Language): More localization languages for `timeago` and `tooltip`
|
70
|
+
- [Use Template Variables](https://jaywhj.netlify.app/document-dates-en#Use-Template-Variables): Can be used to optimize `sitemap.xml` for site SEO, can be used to re-customize plug-ins, etc.
|
71
|
+
- [Add Recently Updated Module](https://jaywhj.netlify.app/document-dates-en#Add-Recently-Updated-Module): Enable list of recently updated documents
|
72
|
+
- [Other Tips](https://jaywhj.netlify.app/document-dates-en#Other-Tips): Introduction to technical principles, caching mechanisms, and how to use it in Docker
|
73
|
+
- [Development Stories](https://jaywhj.netlify.app/document-dates-en#Development-Stories): Describes the origin of the plug-in, the difficulties and solutions encountered in development, and the principles and directions of product design
|
74
|
+
|
75
|
+
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
{mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/cache_manager.py
RENAMED
@@ -11,7 +11,7 @@ def find_mkdocs_projects():
|
|
11
11
|
try:
|
12
12
|
git_root = Path(subprocess.check_output(
|
13
13
|
['git', 'rev-parse', '--show-toplevel'],
|
14
|
-
|
14
|
+
encoding='utf-8'
|
15
15
|
).strip())
|
16
16
|
|
17
17
|
# 遍历 git_root 及子目录, 寻找 mkdocs.yml 文件
|
@@ -65,7 +65,7 @@ def update_cache():
|
|
65
65
|
|
66
66
|
# 获取docs目录下已跟踪(tracked)的markdown文件
|
67
67
|
cmd = ["git", "ls-files", "*.md"]
|
68
|
-
result = subprocess.run(cmd, cwd=docs_dir, capture_output=True,
|
68
|
+
result = subprocess.run(cmd, cwd=docs_dir, capture_output=True, encoding='utf-8')
|
69
69
|
tracked_files = result.stdout.splitlines() if result.stdout else []
|
70
70
|
|
71
71
|
if not tracked_files:
|
{mkdocs_document_dates-3.4 → mkdocs_document_dates-3.4.5}/mkdocs_document_dates/hooks_installer.py
RENAMED
@@ -12,13 +12,20 @@ def get_config_dir():
|
|
12
12
|
if platform.system().lower().startswith('win'):
|
13
13
|
return Path(os.getenv('APPDATA', str(Path.home() / 'AppData' / 'Roaming')))
|
14
14
|
else:
|
15
|
-
|
15
|
+
# 优先级:XDG_CONFIG_HOME > $HOME/.config > cwd/.config
|
16
|
+
xdg_config = os.getenv('XDG_CONFIG_HOME')
|
17
|
+
if xdg_config:
|
18
|
+
return Path(xdg_config)
|
19
|
+
home = os.getenv('HOME')
|
20
|
+
if home:
|
21
|
+
return Path(home) / '.config'
|
22
|
+
return Path.cwd() / '.config'
|
16
23
|
|
17
24
|
def check_python_version(interpreter):
|
18
25
|
try:
|
19
26
|
result = subprocess.run(
|
20
27
|
[interpreter, "-c", "import sys; print(sys.version_info >= (3, 7))"],
|
21
|
-
capture_output=True,
|
28
|
+
capture_output=True, encoding='utf-8')
|
22
29
|
if result.returncode == 0 and result.stdout.strip().lower() == 'true':
|
23
30
|
return True
|
24
31
|
else:
|
@@ -44,7 +51,11 @@ def setup_hooks_directory():
|
|
44
51
|
os.chmod(config_dir, 0o755)
|
45
52
|
return config_dir
|
46
53
|
except PermissionError:
|
47
|
-
logger.error(
|
54
|
+
logger.error(
|
55
|
+
f"No permission to create directory: {config_dir}\n"
|
56
|
+
"If running inside Docker, please set environment variable HOME=/docs "
|
57
|
+
"or XDG_CONFIG_HOME to a writable path."
|
58
|
+
)
|
48
59
|
except Exception as e:
|
49
60
|
logger.error(f"Failed to create directory {config_dir}: {str(e)}")
|
50
61
|
return None
|
@@ -2,13 +2,14 @@ import os
|
|
2
2
|
import yaml
|
3
3
|
import shutil
|
4
4
|
import logging
|
5
|
+
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
5
6
|
from datetime import datetime
|
6
7
|
from pathlib import Path
|
7
8
|
from mkdocs.plugins import BasePlugin
|
8
9
|
from mkdocs.config import config_options
|
9
10
|
from mkdocs.structure.pages import Page
|
10
11
|
from urllib.parse import urlparse
|
11
|
-
from .utils import get_file_creation_time, load_git_cache, read_jsonl_cache,is_excluded,
|
12
|
+
from .utils import get_file_creation_time, load_git_cache, read_jsonl_cache,is_excluded, get_recently_updated_files
|
12
13
|
|
13
14
|
logger = logging.getLogger("mkdocs.plugins.document_dates")
|
14
15
|
logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
@@ -40,17 +41,20 @@ class DocumentDatesPlugin(BasePlugin):
|
|
40
41
|
('time_format', config_options.Type(str, default='%H:%M:%S')),
|
41
42
|
('position', config_options.Type(str, default='top')),
|
42
43
|
('exclude', config_options.Type(list, default=[])),
|
43
|
-
('created_field_names', config_options.Type(list, default=['created', 'date'
|
44
|
-
('modified_field_names', config_options.Type(list, default=['modified', 'updated'
|
45
|
-
('show_author', config_options.
|
44
|
+
('created_field_names', config_options.Type(list, default=['created', 'date'])),
|
45
|
+
('modified_field_names', config_options.Type(list, default=['modified', 'updated'])),
|
46
|
+
('show_author', config_options.Choice((True, False, 'text'), default=True)),
|
46
47
|
('recently-updated', config_options.Type((dict, bool), default={}))
|
47
48
|
)
|
48
49
|
|
49
50
|
def __init__(self):
|
50
51
|
super().__init__()
|
51
52
|
self.dates_cache = {}
|
53
|
+
self.last_updated_dates = {}
|
52
54
|
self.authors_yml = {}
|
53
55
|
self.github_username = None
|
56
|
+
self.recent_docs_html = None
|
57
|
+
self.recent_enable = False
|
54
58
|
|
55
59
|
def on_config(self, config):
|
56
60
|
docs_dir_path = Path(config['docs_dir'])
|
@@ -70,7 +74,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
70
74
|
|
71
75
|
# 加载 git 缓存
|
72
76
|
self.dates_cache = load_git_cache(docs_dir_path)
|
73
|
-
#
|
77
|
+
# 覆盖 jsonl 文件缓存
|
74
78
|
jsonl_cache_file = docs_dir_path / '.dates_cache.jsonl'
|
75
79
|
if jsonl_cache_file.exists():
|
76
80
|
jsonl_cache = read_jsonl_cache(jsonl_cache_file)
|
@@ -78,35 +82,9 @@ class DocumentDatesPlugin(BasePlugin):
|
|
78
82
|
if filename in self.dates_cache:
|
79
83
|
self.dates_cache[filename].update(new_info)
|
80
84
|
|
81
|
-
|
82
|
-
Tippy.js, for Tooltip
|
83
|
-
# core
|
84
|
-
https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js
|
85
|
-
https://unpkg.com/tippy.js@6/dist/tippy.umd.min.js
|
86
|
-
https://unpkg.com/tippy.js@6/dist/tippy.css
|
87
|
-
# animations
|
88
|
-
https://unpkg.com/tippy.js@6/animations/scale.css
|
89
|
-
# animations: Material filling effect
|
90
|
-
https://unpkg.com/tippy.js@6/dist/backdrop.css
|
91
|
-
https://unpkg.com/tippy.js@6/animations/shift-away.css
|
92
|
-
# themes
|
93
|
-
https://unpkg.com/tippy.js@6/themes/light.css
|
94
|
-
https://unpkg.com/tippy.js@6/themes/material.css
|
95
|
-
"""
|
96
|
-
# 复制静态资源到用户目录
|
85
|
+
# 复制配置文件到用户目录(如果不存在)
|
97
86
|
dest_dir = docs_dir_path / 'assets' / 'document_dates'
|
98
87
|
dest_dir.mkdir(parents=True, exist_ok=True)
|
99
|
-
|
100
|
-
for dir_name in ['tippy', 'core', 'fonts']:
|
101
|
-
source_dir = Path(__file__).parent / 'static' / dir_name
|
102
|
-
target_dir = dest_dir / dir_name
|
103
|
-
# shutil.copytree(source_dir, target_dir, dirs_exist_ok=True)
|
104
|
-
target_dir.mkdir(parents=True, exist_ok=True)
|
105
|
-
for item in source_dir.iterdir():
|
106
|
-
if item.is_file():
|
107
|
-
shutil.copy2(item, target_dir / item.name)
|
108
|
-
|
109
|
-
# 复制配置文件模板到用户目录(如果不存在)
|
110
88
|
config_files = ['user.config.css', 'user.config.js']
|
111
89
|
for config_file in config_files:
|
112
90
|
source_config = Path(__file__).parent / 'static' / 'config' / config_file
|
@@ -114,35 +92,49 @@ class DocumentDatesPlugin(BasePlugin):
|
|
114
92
|
if not target_config.exists():
|
115
93
|
shutil.copy2(source_config, target_config)
|
116
94
|
|
117
|
-
#
|
95
|
+
# 添加离线 Google Fonts Icons: https://fonts.google.com/icons
|
118
96
|
# material_icons_url = 'https://fonts.googleapis.com/icon?family=Material+Icons'
|
119
97
|
material_icons_url = 'assets/document_dates/fonts/material-icons.css'
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
# 加载 timeago.js
|
98
|
+
config['extra_css'].append(material_icons_url)
|
99
|
+
|
100
|
+
# 添加 timeago.js
|
124
101
|
# https://cdn.jsdelivr.net/npm/timeago.js@4.0.2/dist/timeago.min.js
|
125
102
|
# https://cdnjs.cloudflare.com/ajax/libs/timeago.js/4.0.2/timeago.full.min.js
|
126
103
|
if self.config['type'] == 'timeago':
|
127
104
|
config['extra_javascript'].insert(0, 'assets/document_dates/core/timeago.min.js')
|
128
105
|
|
129
|
-
|
130
|
-
|
106
|
+
"""
|
107
|
+
Tippy.js, for Tooltip
|
108
|
+
# core
|
109
|
+
https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js
|
110
|
+
https://unpkg.com/tippy.js@6/dist/tippy.umd.min.js
|
111
|
+
https://unpkg.com/tippy.js@6/dist/tippy.css
|
112
|
+
# animations
|
113
|
+
https://unpkg.com/tippy.js@6/animations/scale.css
|
114
|
+
# animations: Material filling effect
|
115
|
+
https://unpkg.com/tippy.js@6/dist/backdrop.css
|
116
|
+
https://unpkg.com/tippy.js@6/animations/shift-away.css
|
117
|
+
# themes
|
118
|
+
https://unpkg.com/tippy.js@6/themes/light.css
|
119
|
+
https://unpkg.com/tippy.js@6/themes/material.css
|
120
|
+
"""
|
121
|
+
# 添加 Tippy CSS 文件
|
122
|
+
tippy_css_dir = Path(__file__).parent / 'static' / 'tippy'
|
131
123
|
for css_file in tippy_css_dir.glob('*.css'):
|
132
124
|
config['extra_css'].append(f'assets/document_dates/tippy/{css_file.name}')
|
133
125
|
|
134
|
-
#
|
126
|
+
# 添加自定义 CSS 文件
|
135
127
|
config['extra_css'].extend([
|
136
128
|
'assets/document_dates/core/core.css',
|
137
129
|
'assets/document_dates/user.config.css'
|
138
130
|
])
|
139
131
|
|
140
|
-
#
|
132
|
+
# 按顺序添加 Tippy JS 文件
|
141
133
|
js_core_files = ['popper.min.js', 'tippy.umd.min.js']
|
142
134
|
for js_file in js_core_files:
|
143
135
|
config['extra_javascript'].append(f'assets/document_dates/tippy/{js_file}')
|
144
136
|
|
145
|
-
#
|
137
|
+
# 添加自定义 JS 文件
|
146
138
|
config['extra_javascript'].extend([
|
147
139
|
'assets/document_dates/core/default.config.js',
|
148
140
|
'assets/document_dates/user.config.js',
|
@@ -154,8 +146,8 @@ class DocumentDatesPlugin(BasePlugin):
|
|
154
146
|
|
155
147
|
def on_nav(self, nav, config, files):
|
156
148
|
recently_updated_config = self.config.get('recently-updated')
|
157
|
-
if
|
158
|
-
|
149
|
+
if recently_updated_config:
|
150
|
+
self.recent_enable = True
|
159
151
|
|
160
152
|
# 兼容 true 配置
|
161
153
|
if recently_updated_config is True:
|
@@ -164,17 +156,48 @@ class DocumentDatesPlugin(BasePlugin):
|
|
164
156
|
# 获取配置
|
165
157
|
exclude_list = recently_updated_config.get('exclude', [])
|
166
158
|
limit = recently_updated_config.get('limit', 10)
|
159
|
+
template_path = recently_updated_config.get('template')
|
167
160
|
|
168
|
-
#
|
169
|
-
|
161
|
+
# 获取最近更新日期和最近更新的文档数据
|
162
|
+
docs_dir = Path(config['docs_dir'])
|
163
|
+
self.last_updated_dates, recently_updated_docs = get_recently_updated_files(docs_dir, files, exclude_list, limit, self.recent_enable)
|
170
164
|
|
171
165
|
# 将数据注入到 config['extra'] 中供全局访问
|
172
166
|
if 'extra' not in config:
|
173
167
|
config['extra'] = {}
|
174
|
-
config['extra']['recently_updated_docs'] =
|
168
|
+
config['extra']['recently_updated_docs'] = recently_updated_docs
|
169
|
+
|
170
|
+
# 渲染HTML
|
171
|
+
if self.recent_enable:
|
172
|
+
self.recent_docs_html = self._render_recently_updated_html(docs_dir, template_path, recently_updated_docs)
|
175
173
|
|
176
174
|
return nav
|
177
175
|
|
176
|
+
def _render_recently_updated_html(self, docs_dir, template_path, recently_updated_data):
|
177
|
+
# 获取自定义模板路径
|
178
|
+
if template_path:
|
179
|
+
user_full_path = docs_dir / template_path
|
180
|
+
|
181
|
+
# 选择模板路径
|
182
|
+
if template_path and user_full_path.is_file():
|
183
|
+
template_dir = user_full_path.parent
|
184
|
+
template_file = user_full_path.name
|
185
|
+
else:
|
186
|
+
# 默认模板路径
|
187
|
+
default_template_path = Path(__file__).parent / 'static' / 'templates' / 'recently_updated.html'
|
188
|
+
template_dir = default_template_path.parent
|
189
|
+
template_file = default_template_path.name
|
190
|
+
|
191
|
+
# 加载模板
|
192
|
+
env = Environment(
|
193
|
+
loader=FileSystemLoader(str(template_dir)),
|
194
|
+
autoescape=select_autoescape(["html", "xml"])
|
195
|
+
)
|
196
|
+
template = env.get_template(template_file)
|
197
|
+
|
198
|
+
# 渲染模板
|
199
|
+
return template.render(recent_docs=recently_updated_data)
|
200
|
+
|
178
201
|
def on_page_markdown(self, markdown, page: Page, config, files):
|
179
202
|
# 获取相对路径,src_uri 总是以"/"分隔
|
180
203
|
rel_path = getattr(page.file, 'src_uri', page.file.src_path)
|
@@ -188,7 +211,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
188
211
|
if not created:
|
189
212
|
created = self._get_file_creation_time(file_path, rel_path)
|
190
213
|
if not modified:
|
191
|
-
modified = self._get_file_modification_time(file_path)
|
214
|
+
modified = self._get_file_modification_time(file_path, rel_path)
|
192
215
|
|
193
216
|
# 获取作者信息
|
194
217
|
authors = self._get_author_info(rel_path, page, config)
|
@@ -198,6 +221,10 @@ class DocumentDatesPlugin(BasePlugin):
|
|
198
221
|
page.meta['document_dates_modified'] = modified.isoformat()
|
199
222
|
page.meta['document_dates_authors'] = authors
|
200
223
|
|
224
|
+
# 占位符替换
|
225
|
+
if self.recent_enable and '\n<!-- RECENTLY_UPDATED_DOCS -->' in markdown:
|
226
|
+
markdown = markdown.replace('\n<!-- RECENTLY_UPDATED_DOCS -->', self.recent_docs_html or '')
|
227
|
+
|
201
228
|
# 检查是否需要排除
|
202
229
|
if is_excluded(rel_path, self.config['exclude']):
|
203
230
|
return markdown
|
@@ -208,6 +235,16 @@ class DocumentDatesPlugin(BasePlugin):
|
|
208
235
|
# 将信息写入 markdown
|
209
236
|
return self._insert_date_info(markdown, info_html)
|
210
237
|
|
238
|
+
def on_post_build(self, config):
|
239
|
+
site_dest_dir = Path(config['site_dir']) / 'assets' / 'document_dates'
|
240
|
+
for dir_name in ['tippy', 'core', 'fonts']:
|
241
|
+
source_dir = Path(__file__).parent / 'static' / dir_name
|
242
|
+
target_dir = site_dest_dir / dir_name
|
243
|
+
# shutil.copytree(source_dir, target_dir, dirs_exist_ok=True)
|
244
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
245
|
+
for item in source_dir.iterdir():
|
246
|
+
if item.is_file():
|
247
|
+
shutil.copy2(item, target_dir / item.name)
|
211
248
|
|
212
249
|
def _extract_github_username(self, url):
|
213
250
|
try:
|
@@ -257,7 +294,10 @@ class DocumentDatesPlugin(BasePlugin):
|
|
257
294
|
# 从文件系统获取
|
258
295
|
return get_file_creation_time(file_path).astimezone()
|
259
296
|
|
260
|
-
def _get_file_modification_time(self, file_path):
|
297
|
+
def _get_file_modification_time(self, file_path, rel_path):
|
298
|
+
# 优先从缓存中读取
|
299
|
+
if rel_path in self.last_updated_dates:
|
300
|
+
return datetime.fromtimestamp(self.last_updated_dates[rel_path]).astimezone()
|
261
301
|
# 从文件系统获取最后修改时间
|
262
302
|
stat = os.stat(file_path)
|
263
303
|
return datetime.fromtimestamp(stat.st_mtime).astimezone()
|
@@ -348,9 +388,9 @@ class DocumentDatesPlugin(BasePlugin):
|
|
348
388
|
if self.config['show_author'] and authors:
|
349
389
|
def get_author_tooltip(author):
|
350
390
|
if author.url:
|
351
|
-
return f'
|
391
|
+
return f'<a href="{author.url}" target="_blank">{author.name}</a>'
|
352
392
|
elif author.email:
|
353
|
-
return f'
|
393
|
+
return f'<a href="mailto:{author.email}">{author.name}</a>'
|
354
394
|
return author.name
|
355
395
|
|
356
396
|
def get_avatar_img_url(author):
|
@@ -360,19 +400,32 @@ class DocumentDatesPlugin(BasePlugin):
|
|
360
400
|
return f"https://avatars.githubusercontent.com/{self.github_username}"
|
361
401
|
return ""
|
362
402
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
img_url = get_avatar_img_url(author)
|
403
|
+
if self.config['show_author'] == 'text':
|
404
|
+
# 显示文本模式
|
405
|
+
tooltip_text = ', '.join(get_author_tooltip(author) for author in authors)
|
406
|
+
author_text = ', '.join(author.name for author in authors)
|
407
|
+
icon = 'doc_author' if len(authors) == 1 else 'doc_authors'
|
369
408
|
html_parts.append(
|
370
|
-
f"<
|
371
|
-
f"<span class='
|
372
|
-
f"
|
373
|
-
f"</
|
409
|
+
f"<span data-tippy-content data-tippy-raw='{tooltip_text}'>"
|
410
|
+
f"<span class='material-icons' data-icon='{icon}'></span>"
|
411
|
+
f"{author_text}"
|
412
|
+
f"</span>"
|
374
413
|
)
|
375
|
-
|
414
|
+
else:
|
415
|
+
# 显示头像模式(默认)
|
416
|
+
icon = 'doc_author' if len(authors) == 1 else 'doc_authors'
|
417
|
+
html_parts.append(f"<span class='material-icons' data-icon='{icon}'></span>")
|
418
|
+
html_parts.append("<div class='avatar-group'>")
|
419
|
+
for author in authors:
|
420
|
+
tooltip = get_author_tooltip(author)
|
421
|
+
img_url = get_avatar_img_url(author)
|
422
|
+
html_parts.append(
|
423
|
+
f"<div class='avatar-wrapper' data-name='{author.name}' data-tippy-content data-tippy-raw='{tooltip}'>"
|
424
|
+
f"<span class='avatar-text'></span>"
|
425
|
+
f"<img class='avatar' src='{img_url}' />"
|
426
|
+
f"</div>"
|
427
|
+
)
|
428
|
+
html_parts.append("</div>")
|
376
429
|
|
377
430
|
html_parts.append("</div></div>")
|
378
431
|
return ''.join(html_parts)
|
@@ -33,7 +33,7 @@ TooltipConfig.setConfig({
|
|
33
33
|
|
34
34
|
/*
|
35
35
|
Part 2:
|
36
|
-
Demonstrates how to register a local language
|
36
|
+
Demonstrates how to register a local language for 'timeago.js',
|
37
37
|
then you can configure the localeStr you just registered anywhere!
|
38
38
|
*/
|
39
39
|
/*
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<style>
|
2
|
+
.recently-updated {
|
3
|
+
display: grid;
|
4
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
5
|
+
gap: 10px;
|
6
|
+
margin: 0;
|
7
|
+
padding: 16px;
|
8
|
+
border: 1px solid rgba(142, 142, 142, 0.15);
|
9
|
+
border-radius: 4px;
|
10
|
+
font-family: system-ui, sans-serif;
|
11
|
+
}
|
12
|
+
.recently-updated-item {
|
13
|
+
display: flex;
|
14
|
+
align-items: center;
|
15
|
+
}
|
16
|
+
.recently-updated-item span {
|
17
|
+
font-size: 0.85em;
|
18
|
+
color: rgba(142, 142, 142, 0.5);
|
19
|
+
margin-right: 8px;
|
20
|
+
flex-shrink: 0;
|
21
|
+
width: 90px;
|
22
|
+
}
|
23
|
+
.recently-updated-item a {
|
24
|
+
overflow: hidden;
|
25
|
+
text-overflow: ellipsis;
|
26
|
+
white-space: nowrap;
|
27
|
+
color: #0077cc;
|
28
|
+
text-decoration: none;
|
29
|
+
transition: color 0.2s ease;
|
30
|
+
}
|
31
|
+
.recently-updated-item a:hover {
|
32
|
+
text-decoration: underline;
|
33
|
+
}
|
34
|
+
</style>
|
35
|
+
<div class="recently-updated">
|
36
|
+
{%- for mtime, rel_path, title, url in recent_docs %}
|
37
|
+
<div class="recently-updated-item">
|
38
|
+
<span>{{ mtime[:10] }}</span>
|
39
|
+
<a href="{{ url }}" target="_blank">{{ title }}</a>
|
40
|
+
</div>
|
41
|
+
{%- endfor %}
|
42
|
+
</div>
|