mkdocs-document-dates 3.8.2__tar.gz → 3.8.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 (43) hide show
  1. {mkdocs_document_dates-3.8.2/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.8.6}/PKG-INFO +2 -1
  2. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/plugin.py +66 -31
  3. mkdocs_document_dates-3.8.2/mkdocs_document_dates/static/config/user.config.css → mkdocs_document_dates-3.8.6/mkdocs_document_dates/static/config/config.css +1 -1
  4. mkdocs_document_dates-3.8.2/mkdocs_document_dates/static/config/user.config.js → mkdocs_document_dates-3.8.6/mkdocs_document_dates/static/config/config.js +1 -1
  5. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/default.config.js +1 -1
  6. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/utils.py +62 -14
  7. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6/mkdocs_document_dates.egg-info}/PKG-INFO +2 -1
  8. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates.egg-info/SOURCES.txt +2 -2
  9. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates.egg-info/requires.txt +1 -0
  10. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/pyproject.toml +3 -2
  11. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/setup.py +4 -2
  12. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/LICENSE +0 -0
  13. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/MANIFEST.in +0 -0
  14. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/README.md +0 -0
  15. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/__init__.py +0 -0
  16. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/cache_manager.py +0 -0
  17. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/hooks/pre-commit +0 -0
  18. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/hooks_installer.py +0 -0
  19. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/.DS_Store +0 -0
  20. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/core.css +0 -0
  21. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/core.js +0 -0
  22. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/md5.min.js +0 -0
  23. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
  24. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
  25. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/core/utils.js +0 -0
  26. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
  27. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
  28. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/templates/recently_updated_detail.html +0 -0
  29. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/templates/recently_updated_grid.html +0 -0
  30. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/templates/recently_updated_group.html +0 -0
  31. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/templates/recently_updated_list.html +0 -0
  32. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
  33. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/light.css +0 -0
  34. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/material.css +0 -0
  35. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
  36. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/scale.css +0 -0
  37. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
  38. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
  39. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
  40. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
  41. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
  42. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
  43. {mkdocs_document_dates-3.8.2 → mkdocs_document_dates-3.8.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-document-dates
3
- Version: 3.8.2
3
+ Version: 3.8.6
4
4
  Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
5
5
  Author-email: Aaron Wang <aaronwqt@gmail.com>
6
6
  License-Expression: MIT
@@ -14,6 +14,7 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: mkdocs<=1.6.1,>=1.6
16
16
  Requires-Dist: properdocs>=1.6.5
17
+ Requires-Dist: babel>=2.16
17
18
  Dynamic: license-file
18
19
 
19
20
  # mkdocs-document-dates
@@ -9,6 +9,7 @@ from mkdocs.config import config_options
9
9
  from mkdocs.structure.pages import Page
10
10
  from mkdocs.utils import get_relative_url
11
11
  from urllib.parse import urlparse
12
+ from babel.dates import format_datetime
12
13
  from .utils import compile_exclude_patterns, is_excluded, get_recently_updated_files, load_dates_and_authors
13
14
 
14
15
  logger = logging.getLogger("mkdocs.plugins.document_dates")
@@ -54,7 +55,7 @@ class DocumentDatesPlugin(BasePlugin):
54
55
 
55
56
  # 加载 author 配置
56
57
  authors_file = None
57
- for name in ("authors.yml", "authors.yaml"):
58
+ for name in ('authors.yml', 'authors.yaml'):
58
59
  candidate = docs_dir_path / name
59
60
  if candidate.exists():
60
61
  authors_file = candidate
@@ -71,17 +72,7 @@ class DocumentDatesPlugin(BasePlugin):
71
72
  if authors_file:
72
73
  self._load_authors_from_yaml(authors_file)
73
74
 
74
- # 复制配置文件到用户目录(如果不存在)
75
- dest_dir = docs_dir_path / 'assets' / 'document_dates'
76
- dest_dir.mkdir(parents=True, exist_ok=True)
77
- config_files = ['user.config.css', 'user.config.js']
78
- for config_file in config_files:
79
- source_config = Path(__file__).parent / 'static' / 'config' / config_file
80
- target_config = dest_dir / config_file
81
- if not target_config.exists():
82
- shutil.copy2(source_config, target_config)
83
-
84
- # 添加离线 Google Fonts Icons: https://fonts.google.com/icons
75
+ # 添加离线 Google Fonts Icons, https://fonts.google.com/icons
85
76
  # material_icons_url = 'https://fonts.googleapis.com/icon?family=Material+Icons'
86
77
  material_icons_url = 'assets/document_dates/fonts/material-icons.css'
87
78
  config['extra_css'].append(material_icons_url)
@@ -118,23 +109,36 @@ class DocumentDatesPlugin(BasePlugin):
118
109
  tippy_css_dir = Path(__file__).parent / 'static' / 'tippy'
119
110
  for css_file in tippy_css_dir.glob('*.css'):
120
111
  config['extra_css'].append(f'assets/document_dates/tippy/{css_file.name}')
121
-
122
- # 添加自定义 CSS 文件
123
- config['extra_css'].extend([
124
- 'assets/document_dates/core/core.css',
125
- 'assets/document_dates/user.config.css'
126
- ])
127
-
112
+
113
+ # User override config
114
+ override_dir = docs_dir_path / 'assets' / 'document_dates'
115
+ override_css = override_dir / 'config.css'
116
+ override_js = override_dir / 'config.js'
117
+
118
+ # Plugin CSS
119
+ config['extra_css'].append('assets/document_dates/core/core.css')
120
+
121
+ # 用户 override CSS(可选)
122
+ if override_css.exists():
123
+ config['extra_css'].append('assets/document_dates/config.css')
124
+
128
125
  # 按顺序添加 Tippy JS 文件
129
126
  js_core_files = ['popper.min.js', 'tippy.umd.min.js']
130
127
  for js_file in js_core_files:
131
128
  config['extra_javascript'].append(f'assets/document_dates/tippy/{js_file}')
132
-
133
- # 添加自定义 JS 文件
129
+
130
+ # Plugin JS
134
131
  config['extra_javascript'].extend([
135
132
  'assets/document_dates/core/md5.min.js',
136
133
  'assets/document_dates/core/default.config.js',
137
- 'assets/document_dates/user.config.js',
134
+ ])
135
+
136
+ # 用户 override JS(可选)
137
+ if override_js.exists():
138
+ config['extra_javascript'].append('assets/document_dates/config.js')
139
+
140
+ # core runtime
141
+ config['extra_javascript'].extend([
138
142
  'assets/document_dates/core/utils.js',
139
143
  'assets/document_dates/core/core.js'
140
144
  ])
@@ -185,10 +189,14 @@ class DocumentDatesPlugin(BasePlugin):
185
189
  # 检查是否需要排除
186
190
  if is_excluded(rel_path, self._exclude_patterns):
187
191
  return markdown
188
-
192
+
193
+ # 增强鲁棒性,碰到异常数据提前返回
194
+ if not created or not updated:
195
+ return markdown
196
+
189
197
  # 生成日期和作者信息 HTML
190
198
  info_html = self._generate_html_info(page.meta, created, updated, authors)
191
-
199
+
192
200
  # 将信息写入 markdown
193
201
  return self._insert_date_info(markdown, info_html)
194
202
 
@@ -367,11 +375,38 @@ class DocumentDatesPlugin(BasePlugin):
367
375
 
368
376
 
369
377
  def _formatting_date(self, date: datetime):
370
- if self.config['type'] == 'timeago':
371
- return ""
372
- elif self.config['type'] == 'datetime':
373
- return date.strftime(f"{self.config['date_format']} {self.config['time_format']}")
374
- return date.strftime(self.config['date_format'])
378
+ locale = self.config.get('locale', 'en')
379
+
380
+ # 兼容旧 strftime 配置,转换为 Babel/ICU 格式
381
+ date_format = (
382
+ self.config['date_format']
383
+ .replace('%Y', 'yyyy')
384
+ .replace('%y', 'yy')
385
+ .replace('%m', 'MM')
386
+ .replace('%d', 'dd')
387
+ .replace('%B', 'MMMM')
388
+ .replace('%b', 'MMM')
389
+ )
390
+
391
+ time_format = (
392
+ self.config['time_format']
393
+ .replace('%H', 'HH')
394
+ .replace('%I', 'hh')
395
+ .replace('%M', 'mm')
396
+ .replace('%S', 'ss')
397
+ .replace('%p', 'a')
398
+ )
399
+
400
+ if self.config['type'] == 'datetime':
401
+ fmt = f"{date_format} {time_format}"
402
+ else:
403
+ fmt = date_format
404
+
405
+ return format_datetime(
406
+ date,
407
+ format=fmt,
408
+ locale=locale
409
+ )
375
410
 
376
411
  def _generate_html_info(self, meta, created: datetime, updated: datetime, authors=None):
377
412
  try:
@@ -391,11 +426,11 @@ class DocumentDatesPlugin(BasePlugin):
391
426
  html_parts.append(f"<div class='document-dates-plugin' locale='{self.config['locale']}'>")
392
427
 
393
428
  def build_time_icon(time_obj: datetime, icon: str):
394
- formatted = time_obj.strftime(self.config['date_format'])
429
+ formatted = self._formatting_date(time_obj)
395
430
  return (
396
431
  f"<span class='dd-item' data-tippy-content data-tippy-raw='{formatted}'>"
397
432
  f"<span class='material-icons' data-icon='{icon}'></span>"
398
- f"<time datetime='{time_obj.astimezone().isoformat()}'>{self._formatting_date(time_obj)}</time>"
433
+ f"<time datetime='{time_obj.astimezone().isoformat()}'>{formatted}</time>"
399
434
  f"</span>"
400
435
  )
401
436
 
@@ -69,7 +69,7 @@
69
69
  font-size: 12px;
70
70
  } */
71
71
 
72
- /* Demo of the custom theme 'sorrel' and 'sublime', you can configure it in user.config.js (optional) */
72
+ /* Demo of the custom theme 'sorrel' and 'sublime', you can configure it in config.js (optional) */
73
73
  /*
74
74
  .tippy-box[data-theme~='sorrel'] {
75
75
  background-color: #F7E6E2;
@@ -14,7 +14,7 @@ Part 1:
14
14
  /*
15
15
  TooltipConfig.setConfig({
16
16
  theme: {
17
- // configurable: light material, or custom theme in user.config.css, for example: sorrel sublime tomato
17
+ // configurable: light material, or custom theme in config.css, for example: sorrel sublime tomato
18
18
  light: 'light',
19
19
  dark: 'material'
20
20
  },
@@ -2,7 +2,7 @@
2
2
  Tooltip 配置
3
3
  */
4
4
  const ttDefaultConfig = {
5
- // 可配置: light material, 或在 user.config.css 中自定义的主题
5
+ // 可配置: light material, 或在 config.css 中自定义的主题
6
6
  theme: {
7
7
  light: 'light',
8
8
  dark: 'material'
@@ -103,6 +103,24 @@ def load_git_first_commit_date(file_path) -> datetime:
103
103
  logger.info(f"Error load git first commit date for {file_path}: {e}")
104
104
  return datetime.now(timezone.utc)
105
105
 
106
+ COAUTHOR_RE = re.compile(
107
+ r'^Co-authored-by:\s*(.+?) <([^<>]+)>$',
108
+ re.MULTILINE | re.IGNORECASE
109
+ )
110
+ def parse_commit_authors(name, email, body):
111
+ authors = [(name, email)]
112
+ seen = {(name, email)}
113
+
114
+ for co_name, co_email in COAUTHOR_RE.findall(body):
115
+ author = (co_name, co_email)
116
+ if author in seen:
117
+ continue
118
+
119
+ seen.add(author)
120
+ authors.append(author)
121
+
122
+ return authors
123
+
106
124
  def load_git_metadata(docs_dir_path: Path):
107
125
  dates_cache = {}
108
126
  try:
@@ -110,28 +128,53 @@ def load_git_metadata(docs_dir_path: Path):
110
128
  ['git', 'rev-parse', '--show-toplevel'],
111
129
  cwd=docs_dir_path, encoding='utf-8'
112
130
  ).strip())
113
- rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
131
+ rel_docs_path = docs_dir_path.relative_to(git_root)
114
132
 
115
- cmd = ['git', '-c', 'core.quotepath=false', 'log', '--reverse', '--no-merges', '--use-mailmap', '--name-only', '--format=%aN|%aE|%at', f'--relative={rel_docs_path}', '--', '*.md']
133
+ relative_arg = (
134
+ '--relative'
135
+ if rel_docs_path == Path('.')
136
+ else f'--relative={rel_docs_path.as_posix()}'
137
+ )
138
+ cmd = [
139
+ 'git',
140
+ '-c', 'core.quotepath=false',
141
+ 'log',
142
+ '--reverse',
143
+ '--no-merges',
144
+ '--use-mailmap',
145
+ '--name-only',
146
+ '-z',
147
+ '--format=%aN%x1f%aE%x1f%at%x1f%B%x00',
148
+ relative_arg,
149
+ '--',
150
+ '*.md'
151
+ ]
116
152
  process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
117
153
  if process.returncode == 0:
118
154
  authors_dict = defaultdict(dict)
119
155
  first_commit = {}
120
156
  current_commit = None
121
- for line in process.stdout.splitlines():
122
- line = line.strip()
123
- if not line:
157
+
158
+ records = process.stdout.split('\x00')
159
+ for item in records:
160
+ item = item.strip()
161
+ if not item:
124
162
  continue
125
- if '|' in line:
126
- # 使用元组,更轻量
127
- current_commit = tuple(line.split('|', 2))
128
- elif line.endswith('.md') and current_commit:
129
- name, email, created = current_commit
163
+
164
+ parts = item.split('\x1f', 3)
165
+ if len(parts) == 4:
166
+ name, email, created, body = parts
167
+ authors = parse_commit_authors(name, email, body)
168
+ current_commit = (authors, int(created))
169
+ elif item.endswith('.md') and current_commit:
170
+ authors, created = current_commit
130
171
  # 使用 defaultdict(dict)结构,处理有序与去重
131
172
  # a.巧用 Python 字典的 setdefault 特性来去重(setdefault 为不存在的键提供初始值,不会覆盖已有值)
132
173
  # b.巧用 Python 字典的插入顺序特性来保留内容插入顺序(Python 3.7+ 字典会保持插入顺序)
133
- authors_dict[line].setdefault((name, email), None)
134
- first_commit.setdefault(line, int(created))
174
+ for author in authors:
175
+ authors_dict[item].setdefault(author, None)
176
+
177
+ first_commit.setdefault(item, created)
135
178
 
136
179
  # 构建最终的缓存数据
137
180
  for file_path in first_commit:
@@ -154,9 +197,14 @@ def load_git_last_updated_dates(docs_dir_path: Path):
154
197
  ['git', 'rev-parse', '--show-toplevel'],
155
198
  cwd=docs_dir_path, encoding='utf-8'
156
199
  ).strip())
157
- rel_docs_path = docs_dir_path.relative_to(git_root).as_posix()
200
+ rel_docs_path = docs_dir_path.relative_to(git_root)
158
201
 
159
- cmd = ['git', '-c', 'core.quotepath=false', 'log', '--no-merges', '--use-mailmap', '--format=%aN|%aE|%at', '--name-only', f'--relative={rel_docs_path}', '--', '*.md']
202
+ relative_arg = (
203
+ '--relative'
204
+ if rel_docs_path == Path('.')
205
+ else f'--relative={rel_docs_path.as_posix()}'
206
+ )
207
+ cmd = ['git', '-c', 'core.quotepath=false', 'log', '--no-merges', '--use-mailmap', '--format=%aN|%aE|%at', '--name-only', relative_arg, '--', '*.md']
160
208
  process = subprocess.run(cmd, cwd=docs_dir_path, capture_output=True, encoding='utf-8')
161
209
  if process.returncode == 0:
162
210
  result = subprocess.run(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-document-dates
3
- Version: 3.8.2
3
+ Version: 3.8.6
4
4
  Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
5
5
  Author-email: Aaron Wang <aaronwqt@gmail.com>
6
6
  License-Expression: MIT
@@ -14,6 +14,7 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: mkdocs<=1.6.1,>=1.6
16
16
  Requires-Dist: properdocs>=1.6.5
17
+ Requires-Dist: babel>=2.16
17
18
  Dynamic: license-file
18
19
 
19
20
  # mkdocs-document-dates
@@ -16,8 +16,8 @@ mkdocs_document_dates.egg-info/requires.txt
16
16
  mkdocs_document_dates.egg-info/top_level.txt
17
17
  mkdocs_document_dates/hooks/pre-commit
18
18
  mkdocs_document_dates/static/.DS_Store
19
- mkdocs_document_dates/static/config/user.config.css
20
- mkdocs_document_dates/static/config/user.config.js
19
+ mkdocs_document_dates/static/config/config.css
20
+ mkdocs_document_dates/static/config/config.js
21
21
  mkdocs_document_dates/static/core/core.css
22
22
  mkdocs_document_dates/static/core/core.js
23
23
  mkdocs_document_dates/static/core/default.config.js
@@ -1,2 +1,3 @@
1
1
  mkdocs<=1.6.1,>=1.6
2
2
  properdocs>=1.6.5
3
+ babel>=2.16
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mkdocs-document-dates"
7
- version = "3.8.2"
7
+ version = "3.8.6"
8
8
  description = "A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.7"
@@ -12,7 +12,8 @@ license = "MIT"
12
12
  authors = [{ name = "Aaron Wang", email = "aaronwqt@gmail.com" }]
13
13
  dependencies = [
14
14
  "mkdocs>=1.6,<=1.6.1",
15
- "properdocs>=1.6.5"
15
+ "properdocs>=1.6.5",
16
+ "babel>=2.16"
16
17
  ]
17
18
  classifiers = [
18
19
  "Programming Language :: Python :: 3",
@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
4
4
  def legacy_setup():
5
5
  setup(
6
6
  name="mkdocs-document-dates",
7
- version="3.8.2",
7
+ version="3.8.6",
8
8
  author="Aaron Wang",
9
9
  author_email="aaronwqt@gmail.com",
10
10
  license="MIT",
@@ -15,7 +15,9 @@ def legacy_setup():
15
15
  packages=find_packages(),
16
16
  include_package_data=True,
17
17
  install_requires=[
18
- "mkdocs>=1.1.0",
18
+ "mkdocs>=1.6,<=1.6.1",
19
+ "properdocs>=1.6.5",
20
+ "babel>=2.16"
19
21
  ],
20
22
  classifiers=[
21
23
  "Programming Language :: Python :: 3",