mkdocs-document-dates 3.5.2__tar.gz → 3.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. {mkdocs_document_dates-3.5.2/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.6.1}/PKG-INFO +8 -4
  2. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/README.md +7 -3
  3. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/plugin.py +13 -22
  4. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/core.js +84 -14
  5. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/utils.js +12 -0
  6. mkdocs_document_dates-3.6.1/mkdocs_document_dates/static/templates/recently_updated_detail.html +99 -0
  7. mkdocs_document_dates-3.6.1/mkdocs_document_dates/static/templates/recently_updated_grid.html +106 -0
  8. mkdocs_document_dates-3.6.1/mkdocs_document_dates/static/templates/recently_updated_group.html +208 -0
  9. mkdocs_document_dates-3.5.2/mkdocs_document_dates/static/templates/recently_updated.html → mkdocs_document_dates-3.6.1/mkdocs_document_dates/static/templates/recently_updated_list.html +23 -15
  10. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/utils.py +220 -9
  11. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1/mkdocs_document_dates.egg-info}/PKG-INFO +8 -4
  12. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates.egg-info/SOURCES.txt +4 -1
  13. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/setup.py +1 -1
  14. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/LICENSE +0 -0
  15. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/MANIFEST.in +0 -0
  16. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/__init__.py +0 -0
  17. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/cache_manager.py +0 -0
  18. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/hooks/pre-commit +0 -0
  19. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/hooks_installer.py +0 -0
  20. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/config/user.config.css +0 -0
  21. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/config/user.config.js +0 -0
  22. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/core.css +1 -1
  23. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/default.config.js +0 -0
  24. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/md5.min.js +0 -0
  25. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
  26. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
  27. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
  28. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
  29. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
  30. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/light.css +0 -0
  31. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/material.css +0 -0
  32. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
  33. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/scale.css +0 -0
  34. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
  35. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
  36. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
  37. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
  38. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
  39. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates.egg-info/requires.txt +0 -0
  40. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
  41. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/pyproject.toml +0 -0
  42. {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-document-dates
3
- Version: 3.5.2
3
+ Version: 3.6.1
4
4
  Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
5
5
  Home-page: https://github.com/jaywhj/mkdocs-document-dates
6
6
  Author: Aaron Wang
@@ -67,7 +67,7 @@ plugins:
67
67
  - document-dates
68
68
  ```
69
69
 
70
- Or, full configuration:
70
+ Or, common configuration:
71
71
 
72
72
  ```yaml
73
73
  plugins:
@@ -77,8 +77,6 @@ plugins:
77
77
  exclude: # List of excluded files
78
78
  - temp.md # Example: exclude the specified file
79
79
  - blog/* # Example: exclude all files in blog folder, including subfolders
80
- date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
81
- time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
82
80
  ```
83
81
 
84
82
  ## Customization Settings
@@ -97,6 +95,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
97
95
 
98
96
  See the documentation for details: https://jaywhj.netlify.app/document-dates-en
99
97
 
98
+ ![recently-updated](recently-updated-en.gif)
99
+
100
+ ## Other Projects
101
+
102
+ - [**MaterialX**](https://github.com/jaywhj/mkdocs-materialx), the next generation of mkdocs-material, is based on `mkdocs-material-9.7.0` and is named `X`. I'll be maintaining this branch continuously (since mkdocs-material will stop being maintained).
103
+ Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
100
104
 
101
105
  <br />
102
106
 
@@ -41,7 +41,7 @@ plugins:
41
41
  - document-dates
42
42
  ```
43
43
 
44
- Or, full configuration:
44
+ Or, common configuration:
45
45
 
46
46
  ```yaml
47
47
  plugins:
@@ -51,8 +51,6 @@ plugins:
51
51
  exclude: # List of excluded files
52
52
  - temp.md # Example: exclude the specified file
53
53
  - blog/* # Example: exclude all files in blog folder, including subfolders
54
- date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
55
- time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
56
54
  ```
57
55
 
58
56
  ## Customization Settings
@@ -71,6 +69,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
71
69
 
72
70
  See the documentation for details: https://jaywhj.netlify.app/document-dates-en
73
71
 
72
+ ![recently-updated](recently-updated-en.gif)
73
+
74
+ ## Other Projects
75
+
76
+ - [**MaterialX**](https://github.com/jaywhj/mkdocs-materialx), the next generation of mkdocs-material, is based on `mkdocs-material-9.7.0` and is named `X`. I'll be maintaining this branch continuously (since mkdocs-material will stop being maintained).
77
+ Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
74
78
 
75
79
  <br />
76
80
 
@@ -10,7 +10,7 @@ from mkdocs.config import config_options
10
10
  from mkdocs.structure.pages import Page
11
11
  from mkdocs.utils import get_relative_url
12
12
  from urllib.parse import urlparse
13
- from .utils import get_file_creation_time, load_git_metadata, load_git_last_updated_date, read_jsonl_cache,is_excluded, get_recently_updated_files
13
+ from .utils import get_file_creation_time, load_git_metadata, load_git_last_updated_date, read_jsonl_cache, compile_exclude_patterns, is_excluded, get_recently_updated_files
14
14
 
15
15
  logger = logging.getLogger("mkdocs.plugins.document_dates")
16
16
  logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
@@ -46,9 +46,9 @@ class DocumentDatesPlugin(BasePlugin):
46
46
  self.dates_cache = {}
47
47
  self.last_updated_dates = {}
48
48
  self.authors_yml = {}
49
- self.github_username = None
50
49
  self.recent_docs_html = None
51
50
  self.recent_enable = False
51
+ self._exclude_patterns = []
52
52
 
53
53
  def on_config(self, config):
54
54
  docs_dir_path = Path(config['docs_dir'])
@@ -139,6 +139,8 @@ class DocumentDatesPlugin(BasePlugin):
139
139
  'assets/document_dates/core/core.js'
140
140
  ])
141
141
 
142
+ self._exclude_patterns = compile_exclude_patterns(self.config['exclude'])
143
+
142
144
  return config
143
145
 
144
146
  def on_page_markdown(self, markdown, page: Page, config, files):
@@ -165,7 +167,7 @@ class DocumentDatesPlugin(BasePlugin):
165
167
  page.meta['document_dates_authors'] = authors
166
168
 
167
169
  # 检查是否需要排除
168
- if is_excluded(rel_path, self.config['exclude']):
170
+ if is_excluded(rel_path, self._exclude_patterns):
169
171
  return markdown
170
172
 
171
173
  # 生成日期和作者信息 HTML
@@ -186,10 +188,10 @@ class DocumentDatesPlugin(BasePlugin):
186
188
  # 获取配置
187
189
  exclude_list = recently_updated_config.get('exclude', [])
188
190
  limit = recently_updated_config.get('limit', 10)
189
- template_path = recently_updated_config.get('template')
190
191
 
191
192
  # 获取最近更新的文档数据
192
- recently_updated_docs = get_recently_updated_files(self.last_updated_dates, files, exclude_list, limit, self.recent_enable)
193
+ recent_exclude_patterns = compile_exclude_patterns(exclude_list)
194
+ recently_updated_docs = get_recently_updated_files(self.last_updated_dates, files, recent_exclude_patterns, limit, self.recent_enable)
193
195
 
194
196
  # 将数据注入到 config['extra'] 中供全局访问
195
197
  if 'extra' not in config:
@@ -198,8 +200,7 @@ class DocumentDatesPlugin(BasePlugin):
198
200
 
199
201
  # 渲染HTML
200
202
  if self.recent_enable:
201
- docs_dir = Path(config['docs_dir'])
202
- self.recent_docs_html = self._render_recently_updated_html(docs_dir, template_path, recently_updated_docs)
203
+ self.recent_docs_html = self._render_recently_updated_html(recently_updated_docs)
203
204
 
204
205
  return env
205
206
 
@@ -233,20 +234,10 @@ class DocumentDatesPlugin(BasePlugin):
233
234
  logger.info(f"Error parsing .authors.yml: {e}")
234
235
 
235
236
 
236
- def _render_recently_updated_html(self, docs_dir, template_path, recently_updated_data):
237
- # 获取自定义模板路径
238
- if template_path:
239
- user_full_path = docs_dir / template_path
240
-
241
- # 选择模板路径
242
- if template_path and user_full_path.is_file():
243
- template_dir = user_full_path.parent
244
- template_file = user_full_path.name
245
- else:
246
- # 默认模板路径
247
- default_template_path = Path(__file__).parent / 'static' / 'templates' / 'recently_updated.html'
248
- template_dir = default_template_path.parent
249
- template_file = default_template_path.name
237
+ def _render_recently_updated_html(self, recently_updated_data):
238
+ default_template_path = Path(__file__).parent / 'static' / 'templates' / 'recently_updated_group.html'
239
+ template_dir = default_template_path.parent
240
+ template_file = default_template_path.name
250
241
 
251
242
  # 加载模板
252
243
  env = Environment(
@@ -490,4 +481,4 @@ class DocumentDatesPlugin(BasePlugin):
490
481
 
491
482
  pos = next_newline + 1
492
483
 
493
- return '', length
484
+ return '', length
@@ -144,25 +144,30 @@ const iconKeyMap = {
144
144
  doc_author: 'author',
145
145
  doc_authors: 'authors'
146
146
  };
147
+
148
+ function applyTimeagoToTimes(timeNodes, rawLocale) {
149
+ if (typeof timeago === 'undefined') {
150
+ return;
151
+ }
152
+ if (!timeNodes || !timeNodes.length) {
153
+ return;
154
+ }
155
+ const tLocale = ddUtils.resolveTimeagoLocale(rawLocale);
156
+ timeNodes.forEach(timeEl => {
157
+ const dt = timeEl.getAttribute('datetime');
158
+ if (dt) {
159
+ timeEl.textContent = timeago.format(dt, tLocale);
160
+ }
161
+ });
162
+ }
163
+
147
164
  // 处理数据加载
148
165
  function processDataLoading() {
149
166
  document.querySelectorAll('.document-dates-plugin').forEach(ddpEl => {
150
- // 获取 locale,优先级:用户主动选择 > 服务端显式配置 > 用户浏览器语言 > 站点HTML语言 > 默认英语
151
- const rawLocale =
152
- ddUtils.getSavedLanguage() ||
153
- ddpEl.getAttribute('locale') ||
154
- navigator.language ||
155
- navigator.userLanguage ||
156
- document.documentElement.lang ||
157
- 'en';
167
+ const rawLocale = ddUtils.getCurrentLocale(ddpEl);
158
168
 
159
169
  // 处理 time 元素(使用 timeago 时)
160
- if (typeof timeago !== 'undefined') {
161
- const tLocale = ddUtils.resolveTimeagoLocale(rawLocale);
162
- ddpEl.querySelectorAll('time').forEach(timeEl => {
163
- timeEl.textContent = timeago.format(timeEl.getAttribute('datetime'), tLocale);
164
- });
165
- }
170
+ applyTimeagoToTimes(ddpEl.querySelectorAll('time'), rawLocale);
166
171
 
167
172
  // 动态处理 tooltip 内容
168
173
  const langData = TooltipLanguage.get(rawLocale);
@@ -178,6 +183,10 @@ function processDataLoading() {
178
183
  }
179
184
  });
180
185
  });
186
+
187
+ // 处理其他 timeago 时间
188
+ const rawLocale = ddUtils.getCurrentLocale();
189
+ applyTimeagoToTimes(document.querySelectorAll('time.dd-timeago'), rawLocale);
181
190
  }
182
191
 
183
192
  // 供外部使用:更新文档日期和 tippy 内容到指定语言(可持久化)
@@ -359,6 +368,65 @@ function handleDocumentDatesAutoWrap() {
359
368
  });
360
369
  }
361
370
 
371
+ // 最近更新 - 布局切换器 (Layout Switcher)
372
+ function initLayoutSwitcher() {
373
+ const grids = document.querySelectorAll('.article-grid');
374
+ if (!grids.length) return;
375
+
376
+ const savedLayout = localStorage.getItem('dd_recent_docs_layout') || 'grid';
377
+
378
+ grids.forEach(grid => {
379
+ // 应用初始布局
380
+ grid.classList.toggle('is-list', savedLayout === 'list');
381
+ grid.classList.toggle('is-detail', savedLayout === 'detail');
382
+
383
+
384
+ // 查找或创建切换器容器
385
+ let switcher = grid.previousElementSibling;
386
+ if (!switcher || !switcher.classList.contains('article-layout-switcher')) {
387
+ // 如果模板中没写,可以动态注入,但建议写在模板里以保证 UI 一致性
388
+ return;
389
+ }
390
+ const listBtn = switcher.querySelector('.layout-list-btn');
391
+ const detailBtn = switcher.querySelector('.layout-detail-btn');
392
+ const gridBtn = switcher.querySelector('.layout-grid-btn');
393
+
394
+ const updateActiveBtn = (layout) => {
395
+ if (listBtn) listBtn.classList.toggle('is-active', layout === 'list');
396
+ if (detailBtn) detailBtn.classList.toggle('is-active', layout === 'detail');
397
+ if (gridBtn) gridBtn.classList.toggle('is-active', layout === 'grid');
398
+ };
399
+ updateActiveBtn(savedLayout);
400
+
401
+
402
+ const setLayout = (layout) => {
403
+ grid.classList.remove('is-list', 'is-detail');
404
+ if (layout !== 'grid') {
405
+ grid.classList.add(`is-${layout}`);
406
+ }
407
+ localStorage.setItem('dd_recent_docs_layout', layout);
408
+ updateActiveBtn(layout);
409
+ };
410
+ if (listBtn) {
411
+ listBtn.onclick = () => {
412
+ setLayout('list');
413
+ listBtn.blur();
414
+ };
415
+ }
416
+ if (detailBtn) {
417
+ detailBtn.onclick = () => {
418
+ setLayout('detail');
419
+ detailBtn.blur();
420
+ };
421
+ }
422
+ if (gridBtn) {
423
+ gridBtn.onclick = () => {
424
+ setLayout('grid');
425
+ gridBtn.blur();
426
+ };
427
+ }
428
+ });
429
+ }
362
430
 
363
431
  /*
364
432
  入口
@@ -367,6 +435,7 @@ let datesAutoWrapObserver = null;
367
435
  function initPluginFeatures() {
368
436
  tippyManager.initialize();
369
437
  processDataLoading();
438
+ initLayoutSwitcher();
370
439
  AvatarService.init().then(() => {
371
440
  loadAvatars();
372
441
  });
@@ -381,6 +450,7 @@ function initPluginFeatures() {
381
450
  });
382
451
  });
383
452
  document.querySelectorAll('.document-dates-plugin').forEach(ddpEl => datesAutoWrapObserver.observe(ddpEl));
453
+ setTimeout(handleDocumentDatesAutoWrap, 100);
384
454
  }
385
455
 
386
456
  // 兼容 Material 主题的 'navigation.instant' 属性
@@ -44,6 +44,18 @@ window.ddUtils = {
44
44
  }
45
45
  },
46
46
 
47
+ // 获取当前语言环境,优先级:用户选择 > 元素配置 > 浏览器语言 > 页面语言 > 默认 'en'
48
+ getCurrentLocale(el) {
49
+ return (
50
+ this.getSavedLanguage() ||
51
+ (el ? el.getAttribute('locale') : null) ||
52
+ navigator.language ||
53
+ navigator.userLanguage ||
54
+ document.documentElement.lang ||
55
+ 'en'
56
+ );
57
+ },
58
+
47
59
  // 清除保存的语言设置
48
60
  clearLanguage() {
49
61
  try {
@@ -0,0 +1,99 @@
1
+ <style>
2
+ .article-card {
3
+ border: 1px solid rgba(142, 142, 142, 0.2);
4
+ border-radius: 8px;
5
+ padding: 16px;
6
+ margin: 20px auto;
7
+ font-family: sans-serif;
8
+ box-sizing: border-box;
9
+ display: flex;
10
+ flex-direction: column;
11
+ }
12
+
13
+ /* --- 第一行:标题与时间 --- */
14
+ .card-header {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ text-decoration: none;
19
+ }
20
+ .card-title {
21
+ font-weight: 700;
22
+ line-height: 1.4;
23
+ color: var(--md-typeset-color, #1c1c1c);
24
+ margin-right: 16px;
25
+ }
26
+ .card-date {
27
+ font-size: 0.84em;
28
+ color: rgba(100, 100, 100, 0.4);
29
+ white-space: nowrap;
30
+ margin-right: 10px;
31
+ }
32
+ .card-header:hover .card-title {
33
+ color: var(--md-accent-fg-color, blue);
34
+ text-decoration: underline;
35
+ }
36
+
37
+ /* --- 第二行:摘要与封面图 --- */
38
+ .card-body {
39
+ display: flex;
40
+ justify-content: space-between;
41
+ align-items: center;
42
+ margin-top: 12px;
43
+ }
44
+ .card-summary {
45
+ flex: 1;
46
+ color: rgba(142, 142, 142, 1);
47
+ font-size: 0.7rem;
48
+ line-height: 1.6;
49
+ letter-spacing: 0.02rem;
50
+ word-break: break-all;
51
+
52
+ /* 3 行文字截断,超出显示省略号 */
53
+ display: -webkit-box;
54
+ -webkit-box-orient: vertical;
55
+ -webkit-line-clamp: 3;
56
+ overflow: hidden;
57
+ }
58
+ .card-cover {
59
+ width: 120px;
60
+ height: 80px;
61
+ border-radius: 8px;
62
+ flex-shrink: 0;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: center;
66
+ overflow: hidden;
67
+ margin-left: 10px;
68
+ }
69
+ .card-cover a {
70
+ display: block;
71
+ width: 100%;
72
+ height: 100%;
73
+ }
74
+ .card-cover img {
75
+ width: 100%;
76
+ height: 100%;
77
+ object-fit: cover;
78
+ margin: 0 !important;
79
+ }
80
+ </style>
81
+
82
+ <div>
83
+ {%- for mtime, rel_path, title, url, cover, summary in recent_docs %}
84
+ <div class="article-card">
85
+ <a class="card-header" href="{{ url }}" target="_blank">
86
+ <div class="card-title">{{ title }}</div>
87
+ <time class="dd-timeago card-date" datetime="{{ mtime }}">{{ mtime[:10] }}</time>
88
+ </a>
89
+ <div class="card-body">
90
+ <div class="card-summary">{{ summary }}</div>
91
+ {%- if cover %}
92
+ <div class="card-cover">
93
+ <img src="{{ cover }}" alt="{{ title }}">
94
+ </div>
95
+ {%- endif %}
96
+ </div>
97
+ </div>
98
+ {%- endfor %}
99
+ </div>
@@ -0,0 +1,106 @@
1
+ <style>
2
+ /* --- 网格布局容器 --- */
3
+ .article-grid {
4
+ display: grid;
5
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
6
+ gap: 20px;
7
+ margin: 20px 0;
8
+ }
9
+
10
+ .article-card {
11
+ border: 1px solid rgba(142, 142, 142, 0.2);
12
+ border-radius: 8px;
13
+ padding: 16px;
14
+ font-family: sans-serif;
15
+ box-sizing: border-box;
16
+ display: flex;
17
+ flex-direction: column;
18
+ }
19
+
20
+ /* --- 第一行:标题与时间 --- */
21
+ .card-header {
22
+ display: flex;
23
+ justify-content: space-between;
24
+ align-items: center;
25
+ text-decoration: none;
26
+ }
27
+ .card-title {
28
+ font-weight: 700;
29
+ line-height: 1.4;
30
+ color: var(--md-typeset-color, #1c1c1c);
31
+ margin-right: 16px;
32
+ }
33
+ .card-date {
34
+ font-size: 0.84em;
35
+ color: rgba(100, 100, 100, 0.4);
36
+ white-space: nowrap;
37
+ margin-right: 10px;
38
+ }
39
+ .card-header:hover .card-title {
40
+ color: var(--md-accent-fg-color, blue);
41
+ text-decoration: underline;
42
+ }
43
+
44
+ /* --- 第二行:摘要与封面图 --- */
45
+ .card-body {
46
+ display: flex;
47
+ justify-content: space-between;
48
+ align-items: center;
49
+ margin-top: 12px;
50
+ }
51
+ .card-summary {
52
+ flex: 1;
53
+ color: rgba(142, 142, 142, 1);
54
+ font-size: 0.7rem;
55
+ line-height: 1.6;
56
+ letter-spacing: 0.02rem;
57
+ word-break: break-all;
58
+
59
+ /* 3 行文字截断,超出显示省略号 */
60
+ display: -webkit-box;
61
+ -webkit-box-orient: vertical;
62
+ -webkit-line-clamp: 3;
63
+ overflow: hidden;
64
+ }
65
+ .card-cover {
66
+ width: 120px;
67
+ height: 80px;
68
+ border-radius: 8px;
69
+ flex-shrink: 0;
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ overflow: hidden;
74
+ margin-left: 10px;
75
+ }
76
+ .card-cover a {
77
+ display: block;
78
+ width: 100%;
79
+ height: 100%;
80
+ }
81
+ .card-cover img {
82
+ width: 100%;
83
+ height: 100%;
84
+ object-fit: cover;
85
+ margin: 0 !important;
86
+ }
87
+ </style>
88
+
89
+ <div class="article-grid">
90
+ {%- for mtime, rel_path, title, url, cover, summary in recent_docs %}
91
+ <div class="article-card">
92
+ <a class="card-header" href="{{ url }}" target="_blank">
93
+ <div class="card-title">{{ title }}</div>
94
+ <time class="dd-timeago card-date" datetime="{{ mtime }}">{{ mtime[:10] }}</time>
95
+ </a>
96
+ <div class="card-body">
97
+ <div class="card-summary">{{ summary }}</div>
98
+ {%- if cover %}
99
+ <div class="card-cover">
100
+ <img src="{{ cover }}" alt="{{ title }}">
101
+ </div>
102
+ {%- endif %}
103
+ </div>
104
+ </div>
105
+ {%- endfor %}
106
+ </div>
@@ -0,0 +1,208 @@
1
+ <style>
2
+ .article-layout-switcher {
3
+ display: flex;
4
+ justify-content: flex-end;
5
+ /* margin-bottom: 20px; */
6
+ }
7
+ .article-layout-switcher button + button {
8
+ margin-left: 8px;
9
+ }
10
+ .article-layout-switcher button {
11
+ background: transparent;
12
+ border: none;
13
+ cursor: pointer;
14
+ padding: 4px;
15
+ border-radius: 4px;
16
+ display: flex;
17
+ align-items: center;
18
+ color: var(--md-typeset-color, #1c1c1c);
19
+ opacity: 0.4;
20
+ transition: all 0.2s;
21
+ }
22
+ .article-layout-switcher button:hover {
23
+ background: rgba(142, 142, 142, 0.1);
24
+ opacity: 0.8;
25
+ }
26
+ .article-layout-switcher button.is-active {
27
+ opacity: 1;
28
+ color: var(--md-accent-fg-color, blue);
29
+ background: rgba(142, 142, 142, 0.1);
30
+ }
31
+ .article-layout-switcher .material-icons {
32
+ font-size: 20px;
33
+ }
34
+
35
+ /* --- 网格模式 (默认) --- */
36
+ .article-grid {
37
+ display: grid;
38
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
39
+ gap: 20px;
40
+ margin: 20px 0;
41
+ /* transition: all 0.2s ease; */
42
+ }
43
+
44
+ /* --- 详情模式 (is-detail) --- */
45
+ .article-grid.is-detail {
46
+ grid-template-columns: 1fr;
47
+ margin-left: auto;
48
+ margin-right: auto;
49
+ }
50
+
51
+ /* --- 列表模式 (is-list) --- */
52
+ .article-grid.is-list {
53
+ margin-left: auto;
54
+ margin-right: auto;
55
+
56
+ border: 1px solid rgba(142, 142, 142, 0.2);
57
+ border-radius: 8px;
58
+ row-gap: 0;
59
+ padding: 11px;
60
+ }
61
+ .article-grid.is-list .card-body {
62
+ display: none;
63
+ }
64
+ .article-grid.is-list .article-card {
65
+ border: none;
66
+ border-radius: 0;
67
+ padding: 8px;
68
+ }
69
+ .article-grid.is-list .card-title {
70
+ font-weight: 400;
71
+ color: var(--md-typeset-a-color, #0077cc);
72
+
73
+ white-space: nowrap;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ min-width: 0;
77
+ }
78
+ .article-grid.is-list .card-date {
79
+ margin-right: 0;
80
+ }
81
+
82
+
83
+ .article-card {
84
+ border: 1px solid rgba(142, 142, 142, 0.2);
85
+ border-radius: 8px;
86
+ padding: 16px;
87
+ font-family: sans-serif;
88
+ box-sizing: border-box;
89
+ display: flex;
90
+ flex-direction: column;
91
+ }
92
+
93
+ /* --- 第一行:标题与时间 --- */
94
+ .card-header {
95
+ display: flex;
96
+ justify-content: space-between;
97
+ align-items: center;
98
+ text-decoration: none;
99
+ }
100
+ .card-title {
101
+ font-weight: 700;
102
+ line-height: 1.4;
103
+ color: var(--md-typeset-color, #1c1c1c);
104
+ margin-right: 12px;
105
+ }
106
+ .card-date {
107
+ font-size: 0.84em;
108
+ color: rgba(100, 100, 100, 0.4);
109
+ white-space: nowrap;
110
+ margin-right: 10px;
111
+ }
112
+ .card-header:hover {
113
+ text-decoration: none !important;
114
+ }
115
+ .card-header:hover .card-title {
116
+ color: var(--md-accent-fg-color, blue);
117
+ text-decoration: underline;
118
+ }
119
+
120
+ /* --- 第二行:摘要与封面图 --- */
121
+ .card-body {
122
+ display: flex;
123
+ justify-content: space-between;
124
+ align-items: center;
125
+ margin-top: 12px;
126
+ }
127
+ .card-summary {
128
+ flex: 1;
129
+ color: rgba(142, 142, 142, 1);
130
+ font-size: 0.7rem;
131
+ line-height: 1.6;
132
+ letter-spacing: 0.02rem;
133
+ word-break: break-all;
134
+
135
+ /* 3 行文字截断,超出显示省略号 */
136
+ display: -webkit-box;
137
+ -webkit-box-orient: vertical;
138
+ -webkit-line-clamp: 3;
139
+ overflow: hidden;
140
+ }
141
+ .card-cover {
142
+ width: 120px;
143
+ height: 80px;
144
+ border-radius: 8px;
145
+ flex-shrink: 0;
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ overflow: hidden;
150
+ margin-left: 10px;
151
+ transition: filter 0.3s ease;
152
+
153
+ /* Safari 圆角闪烁修复 */
154
+ transform: translateZ(0); /* 建立独立合成层 */
155
+ will-change: transform; /* 提前告诉浏览器 */
156
+ -webkit-mask-image: -webkit-radial-gradient(white, black); /* 强制圆角裁剪走 mask 管线 */
157
+ isolation: isolate;
158
+ }
159
+ .card-cover:hover {
160
+ filter: brightness(0.8);
161
+ }
162
+ .card-cover a {
163
+ display: block;
164
+ width: 100%;
165
+ height: 100%;
166
+ }
167
+ .card-cover img {
168
+ width: 100%;
169
+ height: 100%;
170
+ object-fit: cover;
171
+ margin: 0 !important;
172
+
173
+ /* 避免 layer 升降级 */
174
+ transform: scale(1.1) translateZ(0);
175
+ transition: transform 0.4s ease-out;
176
+ /* 防 Safari 重绘抖动 */
177
+ backface-visibility: hidden;
178
+ will-change: transform;
179
+ }
180
+ .card-cover:hover img {
181
+ transform: scale(1.1) translateX(4px) translateZ(0);
182
+ }
183
+ </style>
184
+
185
+ <div class="article-layout-switcher">
186
+ <button class="layout-list-btn"><span class="material-icons">view_list</span></button>
187
+ <button class="layout-detail-btn"><span class="material-icons">view_day</span></button>
188
+ <button class="layout-grid-btn"><span class="material-icons">view_module</span></button>
189
+ </div>
190
+
191
+ <div class="article-grid">
192
+ {%- for mtime, rel_path, title, url, cover, summary in recent_docs %}
193
+ <div class="article-card">
194
+ <a class="card-header" href="{{ url }}" target="_blank">
195
+ <div class="card-title">{{ title }}</div>
196
+ <time class="dd-timeago card-date" datetime="{{ mtime }}">{{ mtime[:10] }}</time>
197
+ </a>
198
+ <div class="card-body">
199
+ <div class="card-summary">{{ summary }}</div>
200
+ {%- if cover %}
201
+ <div class="card-cover">
202
+ <img src="{{ cover }}" alt="{{ title }}">
203
+ </div>
204
+ {%- endif %}
205
+ </div>
206
+ </div>
207
+ {%- endfor %}
208
+ </div>
@@ -1,24 +1,24 @@
1
1
  <style>
2
2
  .recently-updated {
3
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);
4
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5
+ padding: 11px;
6
+ border: 1px solid rgba(142, 142, 142, 0.2);
9
7
  border-radius: 8px;
10
8
  font-family: system-ui, sans-serif;
11
9
  }
10
+
11
+ /* 屏幕宽度 675px 及以下时切换为 1 列 */
12
+ @media screen and (max-width: 675px) {
13
+ .recently-updated {
14
+ grid-template-columns: 1fr;
15
+ }
16
+ }
12
17
  .recently-updated-item {
13
18
  display: flex;
14
19
  align-items: center;
15
- }
16
- .recently-updated-item span {
17
- font-size: 0.84em;
18
- color: rgba(142, 142, 142, 0.5);
19
- margin-right: 4px;
20
- flex-shrink: 0;
21
- width: 90px;
20
+ justify-content: space-between;
21
+ margin: 5px;
22
22
  }
23
23
  .recently-updated-item a {
24
24
  overflow: hidden;
@@ -26,17 +26,25 @@
26
26
  white-space: nowrap;
27
27
  color: #0077cc;
28
28
  text-decoration: none;
29
- transition: color 0.2s ease;
29
+ margin-left: 6px;
30
30
  }
31
31
  .recently-updated-item a:hover {
32
32
  text-decoration: underline;
33
33
  }
34
+ .recently-updated-item time {
35
+ font-size: 0.84em;
36
+ color: rgba(142, 142, 142, 0.4);
37
+ margin: 0 6px;
38
+ flex-shrink: 0;
39
+ text-align: right;
40
+ }
34
41
  </style>
42
+
35
43
  <div class="recently-updated">
36
- {%- for mtime, rel_path, title, url in recent_docs %}
44
+ {%- for mtime, rel_path, title, url, cover, summary in recent_docs %}
37
45
  <div class="recently-updated-item">
38
- <span>{{ mtime[:10] }}</span>
39
46
  <a href="{{ url }}" target="_blank">{{ title }}</a>
47
+ <time class="dd-timeago" datetime="{{ mtime }}">{{ mtime[:10] }}</time>
40
48
  </div>
41
49
  {%- endfor %}
42
50
  </div>
@@ -4,6 +4,8 @@ import json
4
4
  import heapq
5
5
  import logging
6
6
  import subprocess
7
+ import fnmatch
8
+ import re
7
9
  from pathlib import Path
8
10
  from datetime import datetime
9
11
  from collections import defaultdict
@@ -13,15 +15,22 @@ logger = logging.getLogger("mkdocs.plugins.document_dates")
13
15
  logger.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, CRITICAL
14
16
 
15
17
 
16
- def is_excluded(path, exclude_list):
18
+ def compile_exclude_patterns(exclude_list):
17
19
  if not exclude_list:
20
+ return []
21
+ return [re.compile(fnmatch.translate(pattern)) for pattern in exclude_list]
22
+
23
+ def is_excluded(path, patterns):
24
+ if not patterns:
18
25
  return False
19
- for pattern in exclude_list:
20
- if pattern.endswith('*'):
21
- if path.startswith(pattern.partition('*')[0]):
26
+ first = patterns[0]
27
+ if isinstance(first, re.Pattern):
28
+ for regex in patterns:
29
+ if regex.match(path):
22
30
  return True
23
- else:
24
- if path == pattern:
31
+ else:
32
+ for pattern in patterns:
33
+ if fnmatch.fnmatch(path, pattern):
25
34
  return True
26
35
  return False
27
36
 
@@ -132,7 +141,8 @@ def load_git_last_updated_date(docs_dir_path: Path):
132
141
 
133
142
  return doc_mtime_map
134
143
 
135
- def get_recently_updated_files(existing_map: dict, files: Files, exclude_list: list, limit: int = 10, recent_enable: bool = False):
144
+ # 建议在 on_page_markdown 之后的全局事件中调用,因为需要读取 page.meta 中的信息
145
+ def get_recently_updated_files(existing_dates: dict, files: Files, exclude_list: list, limit: int = 10, recent_enable: bool = False):
136
146
  recently_updated_results = []
137
147
  if recent_enable:
138
148
  files_meta = []
@@ -148,14 +158,23 @@ def get_recently_updated_files(existing_map: dict, files: Files, exclude_list: l
148
158
  continue
149
159
 
150
160
  # 优先从现有数据获取 mtime,如果不存在则 fallback 到文件系统 mtime
151
- mtime = existing_map.get(rel_path, os.path.getmtime(file.abs_src_path))
161
+ mtime = existing_dates.get(rel_path, os.path.getmtime(file.abs_src_path))
152
162
 
153
163
  # 获取文档标题和 URL
154
164
  title = file.page.title if file.page and file.page.title else file.name
155
165
  url = file.page.url if file.page and file.page.url else file.url
156
166
 
167
+ cover = ''
168
+ summary = ''
169
+ # authors = []
170
+ if file.page:
171
+ cover = file.page.meta.get('cover', '')
172
+ # authors = file.page.meta.get('document_dates_authors', [])
173
+ if file.page.file:
174
+ summary = extract_summary(file.page.file.content_string)
175
+
157
176
  # 存储信息
158
- files_meta.append((mtime, rel_path, title, url))
177
+ files_meta.append((mtime, rel_path, title, url, cover, summary))
159
178
  # existing_map[rel_path] = mtime
160
179
 
161
180
  # 构建最近更新列表
@@ -208,3 +227,195 @@ def write_jsonl_cache(jsonl_file: Path, dates_cache, tracked_files):
208
227
  except Exception as e:
209
228
  logger.warning(f"Failed to add JSONL cache file to git: {e}")
210
229
  return False
230
+
231
+
232
+ # ===== Extract Summary =====
233
+ #
234
+ # -------- block skip --------
235
+ # Fence
236
+ FENCE_RE = re.compile(r"^\s*([`~]{3,})")
237
+
238
+ # HTML comment
239
+ HTML_COMMENT_START = re.compile(r'<!--', re.I)
240
+ HTML_COMMENT_END = re.compile(r'-->', re.I)
241
+
242
+ # HTML
243
+ HTML_TAG_OPEN = re.compile(r'<\s*([a-zA-Z][\w\-]*)\b', re.I)
244
+ HTML_TAG_CLOSE_TEMPLATE = r"</\s*{}\s*>"
245
+ HTML_VOID_TAGS = {
246
+ "area", "base", "br", "col", "embed", "hr",
247
+ "img", "input", "link", "meta", "param",
248
+ "source", "track", "wbr"
249
+ }
250
+ HTML_VOID_CLOSE_RE = re.compile(r">", re.I)
251
+
252
+ # -------- inline skip --------
253
+ H1_TITLE = re.compile(r'^\s*# .+$', re.MULTILINE)
254
+ SINGLE_LINE_HTML_NOISE = re.compile(r'^</?[a-z][\w-]*[^>]*>$', re.I)
255
+ TABLE_ROW_RE = re.compile(r"^\s*\|.*\|\s*$")
256
+ INLINE_SKIP_RE = re.compile(
257
+ r"""
258
+ ^\s*> | # quote
259
+ ^\s*(?:!!!|\?\?\?) | # admonition
260
+ ^\s*=== | # tab
261
+ ^\s*\[.+?\]: # reference link, including footnote
262
+ """,
263
+ re.X,
264
+ )
265
+
266
+ # -------- inline replace --------
267
+ IMAGE_RE = re.compile(r'!\[[^\]]*\]\([^)]+\)')
268
+ LINK_RE = re.compile(r'\[([^\]]+)\]\([^)]+\)')
269
+ BRACE_RE = re.compile(r"\{[^}]*\}")
270
+ MD_SYNTAX_RE = re.compile(r'[`*_>#]+')
271
+
272
+ def clean_markdown(md: str) -> list:
273
+
274
+ lines = md.splitlines()
275
+ result = []
276
+
277
+ state = "NORMAL"
278
+ fence = ""
279
+ html_close_re = None
280
+ frontmatter_parsed = False
281
+ h1_parsed = False
282
+ math_delim = ""
283
+
284
+ for line in lines:
285
+ stripped = line.strip()
286
+ if not stripped:
287
+ continue
288
+
289
+ # ==================================================
290
+ # 1. Frontmatter
291
+ # ==================================================
292
+ if not frontmatter_parsed:
293
+ if state == "FRONTMATTER":
294
+ if stripped in ("---", "+++"):
295
+ state = "NORMAL"
296
+ frontmatter_parsed = True
297
+ continue
298
+
299
+ if state == "NORMAL" and stripped in ("---", "+++"):
300
+ state = "FRONTMATTER"
301
+ continue
302
+
303
+ # ==================================================
304
+ # 2. Fence Block
305
+ # ==================================================
306
+ if state == "FENCE":
307
+ if stripped.startswith(fence):
308
+ state = "NORMAL"
309
+ continue
310
+
311
+ if state == "NORMAL":
312
+ m = FENCE_RE.match(stripped)
313
+ if m:
314
+ fence = m.group(1)
315
+ state = "FENCE"
316
+ continue
317
+
318
+ # ==================================================
319
+ # 3. HTML Comment
320
+ # ==================================================
321
+ if state == "COMMENT":
322
+ if HTML_COMMENT_END.search(stripped):
323
+ state = "NORMAL"
324
+ continue
325
+
326
+ if state == "NORMAL" and HTML_COMMENT_START.search(stripped):
327
+ state = "COMMENT"
328
+ if HTML_COMMENT_END.search(stripped):
329
+ state = "NORMAL"
330
+ continue
331
+
332
+ # ==================================================
333
+ # 4. HTML Block
334
+ # ==================================================
335
+ if state == "HTML_BLOCK":
336
+ if html_close_re and html_close_re.search(stripped):
337
+ state = "NORMAL"
338
+ html_close_re = None
339
+ continue
340
+
341
+ if state == "NORMAL":
342
+ m = HTML_TAG_OPEN.match(stripped)
343
+ if m:
344
+ tag = m.group(1).lower()
345
+ is_void = tag in HTML_VOID_TAGS
346
+
347
+ # void tag:单行且以 > 结尾,视为直接结束,忽略该行
348
+ if stripped.endswith('>') and is_void:
349
+ continue
350
+
351
+ # 非 void tag:进入 HTML_BLOCK
352
+ state = "HTML_BLOCK"
353
+ if is_void:
354
+ html_close_re = HTML_VOID_CLOSE_RE
355
+ else:
356
+ html_close_re = re.compile(HTML_TAG_CLOSE_TEMPLATE.format(re.escape(tag)), re.I)
357
+
358
+ # same-line close: <div>...</div>
359
+ if html_close_re.search(stripped):
360
+ state = "NORMAL"
361
+ html_close_re = None
362
+
363
+ continue
364
+
365
+ # ==================================================
366
+ # 5. Math Block
367
+ # ==================================================
368
+ if state == "MATH":
369
+ if stripped == math_delim:
370
+ state = "NORMAL"
371
+ continue
372
+
373
+ if state == "NORMAL" and stripped in ("$$", "\\["):
374
+ math_delim = "$$" if stripped == "$$" else "\\]"
375
+ state = "MATH"
376
+ continue
377
+
378
+ # ==================================================
379
+ # 6. Inline Skip
380
+ # ==================================================
381
+ if state == "NORMAL":
382
+ if TABLE_ROW_RE.match(stripped):
383
+ continue
384
+ if INLINE_SKIP_RE.match(stripped):
385
+ continue
386
+ # 单行 HTML 噪音兜底
387
+ if SINGLE_LINE_HTML_NOISE.match(stripped):
388
+ continue
389
+ if not h1_parsed:
390
+ if H1_TITLE.match(stripped):
391
+ h1_parsed = True
392
+ continue
393
+ if stripped.startswith(('---', '***')):
394
+ continue
395
+
396
+ # ==================================================
397
+ # 7. Inline Replace
398
+ # ==================================================
399
+ text = stripped
400
+ text = IMAGE_RE.sub("", text)
401
+ text = LINK_RE.sub(r"\1", text)
402
+ text = BRACE_RE.sub("", text)
403
+
404
+ text = text.strip()
405
+ if text:
406
+ result.append(text)
407
+
408
+ # 提前熔断
409
+ if len(result) >= 10:
410
+ break
411
+
412
+ # 锁定 Frontmatter 状态,防止后续 --- 干扰
413
+ frontmatter_parsed = True
414
+
415
+ return result
416
+ # return "\n".join(result)
417
+
418
+ def extract_summary(markdown_text: str) -> str:
419
+ md_list = clean_markdown(markdown_text)
420
+ text = " ".join(md_list)
421
+ return MD_SYNTAX_RE.sub('', text).strip()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-document-dates
3
- Version: 3.5.2
3
+ Version: 3.6.1
4
4
  Summary: A new generation MkDocs plugin for displaying exact creation date, last updated date, authors, email of documents
5
5
  Home-page: https://github.com/jaywhj/mkdocs-document-dates
6
6
  Author: Aaron Wang
@@ -67,7 +67,7 @@ plugins:
67
67
  - document-dates
68
68
  ```
69
69
 
70
- Or, full configuration:
70
+ Or, common configuration:
71
71
 
72
72
  ```yaml
73
73
  plugins:
@@ -77,8 +77,6 @@ plugins:
77
77
  exclude: # List of excluded files
78
78
  - temp.md # Example: exclude the specified file
79
79
  - blog/* # Example: exclude all files in blog folder, including subfolders
80
- date_format: '%Y-%m-%d' # Date format strings (e.g., %Y-%m-%d, %b %d, %Y)
81
- time_format: '%H:%M:%S' # Time format strings (valid only if type=datetime)
82
80
  ```
83
81
 
84
82
  ## Customization Settings
@@ -97,6 +95,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
97
95
 
98
96
  See the documentation for details: https://jaywhj.netlify.app/document-dates-en
99
97
 
98
+ ![recently-updated](recently-updated-en.gif)
99
+
100
+ ## Other Projects
101
+
102
+ - [**MaterialX**](https://github.com/jaywhj/mkdocs-materialx), the next generation of mkdocs-material, is based on `mkdocs-material-9.7.0` and is named `X`. I'll be maintaining this branch continuously (since mkdocs-material will stop being maintained).
103
+ Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
100
104
 
101
105
  <br />
102
106
 
@@ -26,7 +26,10 @@ mkdocs_document_dates/static/core/timeago.min.js
26
26
  mkdocs_document_dates/static/core/utils.js
27
27
  mkdocs_document_dates/static/fonts/material-icons.css
28
28
  mkdocs_document_dates/static/fonts/materialicons.woff2
29
- mkdocs_document_dates/static/templates/recently_updated.html
29
+ mkdocs_document_dates/static/templates/recently_updated_detail.html
30
+ mkdocs_document_dates/static/templates/recently_updated_grid.html
31
+ mkdocs_document_dates/static/templates/recently_updated_group.html
32
+ mkdocs_document_dates/static/templates/recently_updated_list.html
30
33
  mkdocs_document_dates/static/tippy/backdrop.css
31
34
  mkdocs_document_dates/static/tippy/light.css
32
35
  mkdocs_document_dates/static/tippy/material.css
@@ -23,7 +23,7 @@ class CustomInstallCommand(install):
23
23
  install.run(self)
24
24
 
25
25
 
26
- VERSION = '3.5.2'
26
+ VERSION = '3.6.1'
27
27
 
28
28
  setup(
29
29
  name="mkdocs-document-dates",
@@ -143,8 +143,8 @@
143
143
  display: block;
144
144
 
145
145
  /* Fix bug in Safari: rounded corners may blink to show square corners */
146
- will-change: transform;
147
146
  transform: translateZ(0);
147
+ will-change: transform;
148
148
  }
149
149
  .avatar-wrapper:hover {
150
150
  transform: scale(1.08);