mkdocs-document-dates 3.5.2__tar.gz → 3.6.0__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.5.2/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.6.0}/PKG-INFO +7 -1
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/README.md +6 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/plugin.py +5 -18
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/core.css +0 -1
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/core.js +92 -15
- mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_detail.html +99 -0
- mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_grid.html +106 -0
- mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_group.html +186 -0
- mkdocs_document_dates-3.5.2/mkdocs_document_dates/static/templates/recently_updated.html → mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_list.html +23 -15
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/utils.py +205 -3
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0/mkdocs_document_dates.egg-info}/PKG-INFO +7 -1
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates.egg-info/SOURCES.txt +4 -1
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/setup.py +1 -1
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/LICENSE +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/MANIFEST.in +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/__init__.py +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/cache_manager.py +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/hooks/pre-commit +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/hooks_installer.py +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/config/user.config.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/config/user.config.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/default.config.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/md5.min.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/timeago.full.min.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/timeago.min.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/core/utils.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/fonts/material-icons.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/fonts/materialicons.woff2 +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/backdrop.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/light.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/material.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/popper.min.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/scale.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/shift-away.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/tippy.css +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/static/tippy/tippy.umd.min.js +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates.egg-info/dependency_links.txt +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates.egg-info/entry_points.txt +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates.egg-info/requires.txt +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates.egg-info/top_level.txt +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/pyproject.toml +0 -0
- {mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/setup.cfg +0 -0
{mkdocs_document_dates-3.5.2/mkdocs_document_dates.egg-info → mkdocs_document_dates-3.6.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs-document-dates
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.0
|
|
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
|
|
@@ -97,6 +97,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
97
97
|
|
|
98
98
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
99
99
|
|
|
100
|
+
<br />
|
|
101
|
+
|
|
102
|
+
## Other Projects
|
|
103
|
+
|
|
104
|
+
- [**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).
|
|
105
|
+
Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
|
|
100
106
|
|
|
101
107
|
<br />
|
|
102
108
|
|
|
@@ -71,6 +71,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
71
71
|
|
|
72
72
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
73
73
|
|
|
74
|
+
<br />
|
|
75
|
+
|
|
76
|
+
## Other Projects
|
|
77
|
+
|
|
78
|
+
- [**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).
|
|
79
|
+
Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
|
|
74
80
|
|
|
75
81
|
<br />
|
|
76
82
|
|
|
@@ -46,7 +46,6 @@ 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
|
|
52
51
|
|
|
@@ -186,7 +185,6 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
186
185
|
# 获取配置
|
|
187
186
|
exclude_list = recently_updated_config.get('exclude', [])
|
|
188
187
|
limit = recently_updated_config.get('limit', 10)
|
|
189
|
-
template_path = recently_updated_config.get('template')
|
|
190
188
|
|
|
191
189
|
# 获取最近更新的文档数据
|
|
192
190
|
recently_updated_docs = get_recently_updated_files(self.last_updated_dates, files, exclude_list, limit, self.recent_enable)
|
|
@@ -198,8 +196,7 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
198
196
|
|
|
199
197
|
# 渲染HTML
|
|
200
198
|
if self.recent_enable:
|
|
201
|
-
|
|
202
|
-
self.recent_docs_html = self._render_recently_updated_html(docs_dir, template_path, recently_updated_docs)
|
|
199
|
+
self.recent_docs_html = self._render_recently_updated_html(recently_updated_docs)
|
|
203
200
|
|
|
204
201
|
return env
|
|
205
202
|
|
|
@@ -233,20 +230,10 @@ class DocumentDatesPlugin(BasePlugin):
|
|
|
233
230
|
logger.info(f"Error parsing .authors.yml: {e}")
|
|
234
231
|
|
|
235
232
|
|
|
236
|
-
def _render_recently_updated_html(self,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
|
233
|
+
def _render_recently_updated_html(self, recently_updated_data):
|
|
234
|
+
default_template_path = Path(__file__).parent / 'static' / 'templates' / 'recently_updated_group.html'
|
|
235
|
+
template_dir = default_template_path.parent
|
|
236
|
+
template_file = default_template_path.name
|
|
250
237
|
|
|
251
238
|
# 加载模板
|
|
252
239
|
env = Environment(
|
|
@@ -144,25 +144,37 @@ 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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
'en';
|
|
166
|
+
// 获取 locale,优先级:用户主动选择 > 服务端显式配置 > 用户浏览器语言 > 站点HTML语言 > 默认英语
|
|
167
|
+
const rawLocale =
|
|
168
|
+
ddUtils.getSavedLanguage() ||
|
|
169
|
+
// ddpEl.getAttribute('locale') ||
|
|
170
|
+
navigator.language ||
|
|
171
|
+
navigator.userLanguage ||
|
|
172
|
+
document.documentElement.lang ||
|
|
173
|
+
'en';
|
|
158
174
|
|
|
175
|
+
document.querySelectorAll('.document-dates-plugin').forEach(ddpEl => {
|
|
159
176
|
// 处理 time 元素(使用 timeago 时)
|
|
160
|
-
|
|
161
|
-
const tLocale = ddUtils.resolveTimeagoLocale(rawLocale);
|
|
162
|
-
ddpEl.querySelectorAll('time').forEach(timeEl => {
|
|
163
|
-
timeEl.textContent = timeago.format(timeEl.getAttribute('datetime'), tLocale);
|
|
164
|
-
});
|
|
165
|
-
}
|
|
177
|
+
applyTimeagoToTimes(ddpEl.querySelectorAll('time'), rawLocale);
|
|
166
178
|
|
|
167
179
|
// 动态处理 tooltip 内容
|
|
168
180
|
const langData = TooltipLanguage.get(rawLocale);
|
|
@@ -178,6 +190,9 @@ function processDataLoading() {
|
|
|
178
190
|
}
|
|
179
191
|
});
|
|
180
192
|
});
|
|
193
|
+
|
|
194
|
+
// 处理其他 timeago 时间
|
|
195
|
+
applyTimeagoToTimes(document.querySelectorAll('time.dd-timeago'), rawLocale);
|
|
181
196
|
}
|
|
182
197
|
|
|
183
198
|
// 供外部使用:更新文档日期和 tippy 内容到指定语言(可持久化)
|
|
@@ -359,6 +374,66 @@ function handleDocumentDatesAutoWrap() {
|
|
|
359
374
|
});
|
|
360
375
|
}
|
|
361
376
|
|
|
377
|
+
// 最近更新 - 布局切换器 (Layout Switcher)
|
|
378
|
+
function initLayoutSwitcher() {
|
|
379
|
+
const grids = document.querySelectorAll('.article-grid');
|
|
380
|
+
if (!grids.length) return;
|
|
381
|
+
|
|
382
|
+
const savedLayout = localStorage.getItem('dd_recent_docs_layout') || 'grid';
|
|
383
|
+
|
|
384
|
+
grids.forEach(grid => {
|
|
385
|
+
// 应用初始布局
|
|
386
|
+
grid.classList.toggle('is-list', savedLayout === 'list');
|
|
387
|
+
grid.classList.toggle('is-detail', savedLayout === 'detail');
|
|
388
|
+
|
|
389
|
+
// 查找或创建切换器容器
|
|
390
|
+
let switcher = grid.previousElementSibling;
|
|
391
|
+
if (!switcher || !switcher.classList.contains('article-layout-switcher')) {
|
|
392
|
+
// 如果模板中没写,可以动态注入,但建议写在模板里以保证 UI 一致性
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const listBtn = switcher.querySelector('.layout-list-btn');
|
|
397
|
+
const detailBtn = switcher.querySelector('.layout-detail-btn');
|
|
398
|
+
const gridBtn = switcher.querySelector('.layout-grid-btn');
|
|
399
|
+
|
|
400
|
+
const updateActiveBtn = (layout) => {
|
|
401
|
+
if (listBtn) listBtn.classList.toggle('is-active', layout === 'list');
|
|
402
|
+
if (detailBtn) detailBtn.classList.toggle('is-active', layout === 'detail');
|
|
403
|
+
if (gridBtn) gridBtn.classList.toggle('is-active', layout === 'grid');
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
updateActiveBtn(savedLayout);
|
|
407
|
+
|
|
408
|
+
const setLayout = (layout) => {
|
|
409
|
+
grid.classList.remove('is-list', 'is-detail');
|
|
410
|
+
if (layout !== 'grid') {
|
|
411
|
+
grid.classList.add(`is-${layout}`);
|
|
412
|
+
}
|
|
413
|
+
localStorage.setItem('dd_recent_docs_layout', layout);
|
|
414
|
+
updateActiveBtn(layout);
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
if (listBtn) {
|
|
418
|
+
listBtn.onclick = () => {
|
|
419
|
+
setLayout('list');
|
|
420
|
+
listBtn.blur();
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
if (detailBtn) {
|
|
424
|
+
detailBtn.onclick = () => {
|
|
425
|
+
setLayout('detail');
|
|
426
|
+
detailBtn.blur();
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
if (gridBtn) {
|
|
430
|
+
gridBtn.onclick = () => {
|
|
431
|
+
setLayout('grid');
|
|
432
|
+
gridBtn.blur();
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
362
437
|
|
|
363
438
|
/*
|
|
364
439
|
入口
|
|
@@ -367,6 +442,7 @@ let datesAutoWrapObserver = null;
|
|
|
367
442
|
function initPluginFeatures() {
|
|
368
443
|
tippyManager.initialize();
|
|
369
444
|
processDataLoading();
|
|
445
|
+
initLayoutSwitcher();
|
|
370
446
|
AvatarService.init().then(() => {
|
|
371
447
|
loadAvatars();
|
|
372
448
|
});
|
|
@@ -381,6 +457,7 @@ function initPluginFeatures() {
|
|
|
381
457
|
});
|
|
382
458
|
});
|
|
383
459
|
document.querySelectorAll('.document-dates-plugin').forEach(ddpEl => datesAutoWrapObserver.observe(ddpEl));
|
|
460
|
+
setTimeout(handleDocumentDatesAutoWrap, 100);
|
|
384
461
|
}
|
|
385
462
|
|
|
386
463
|
// 兼容 Material 主题的 'navigation.instant' 属性
|
mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_detail.html
ADDED
|
@@ -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>
|
mkdocs_document_dates-3.6.0/mkdocs_document_dates/static/templates/recently_updated_group.html
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.article-layout-switcher {
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: flex-end;
|
|
5
|
+
margin-bottom: 12px;
|
|
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: #0077cc;
|
|
72
|
+
/* color: var(--md-typeset-color, #1c1c1c); */
|
|
73
|
+
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
text-overflow: ellipsis;
|
|
77
|
+
min-width: 0;
|
|
78
|
+
}
|
|
79
|
+
.article-grid.is-list .card-date {
|
|
80
|
+
margin-right: 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
.article-card {
|
|
85
|
+
border: 1px solid rgba(142, 142, 142, 0.2);
|
|
86
|
+
border-radius: 8px;
|
|
87
|
+
padding: 16px;
|
|
88
|
+
font-family: sans-serif;
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* --- 第一行:标题与时间 --- */
|
|
95
|
+
.card-header {
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: space-between;
|
|
98
|
+
align-items: center;
|
|
99
|
+
text-decoration: none;
|
|
100
|
+
}
|
|
101
|
+
.card-title {
|
|
102
|
+
font-weight: 700;
|
|
103
|
+
line-height: 1.4;
|
|
104
|
+
color: var(--md-typeset-color, #1c1c1c);
|
|
105
|
+
margin-right: 12px;
|
|
106
|
+
}
|
|
107
|
+
.card-date {
|
|
108
|
+
font-size: 0.84em;
|
|
109
|
+
color: rgba(100, 100, 100, 0.4);
|
|
110
|
+
white-space: nowrap;
|
|
111
|
+
margin-right: 10px;
|
|
112
|
+
}
|
|
113
|
+
.card-header:hover .card-title {
|
|
114
|
+
color: var(--md-accent-fg-color, blue);
|
|
115
|
+
text-decoration: underline;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* --- 第二行:摘要与封面图 --- */
|
|
119
|
+
.card-body {
|
|
120
|
+
display: flex;
|
|
121
|
+
justify-content: space-between;
|
|
122
|
+
align-items: center;
|
|
123
|
+
margin-top: 12px;
|
|
124
|
+
}
|
|
125
|
+
.card-summary {
|
|
126
|
+
flex: 1;
|
|
127
|
+
color: rgba(142, 142, 142, 1);
|
|
128
|
+
font-size: 0.7rem;
|
|
129
|
+
line-height: 1.6;
|
|
130
|
+
letter-spacing: 0.02rem;
|
|
131
|
+
word-break: break-all;
|
|
132
|
+
|
|
133
|
+
/* 3 行文字截断,超出显示省略号 */
|
|
134
|
+
display: -webkit-box;
|
|
135
|
+
-webkit-box-orient: vertical;
|
|
136
|
+
-webkit-line-clamp: 3;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
}
|
|
139
|
+
.card-cover {
|
|
140
|
+
width: 120px;
|
|
141
|
+
height: 80px;
|
|
142
|
+
border-radius: 8px;
|
|
143
|
+
flex-shrink: 0;
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
overflow: hidden;
|
|
148
|
+
margin-left: 10px;
|
|
149
|
+
}
|
|
150
|
+
.card-cover a {
|
|
151
|
+
display: block;
|
|
152
|
+
width: 100%;
|
|
153
|
+
height: 100%;
|
|
154
|
+
}
|
|
155
|
+
.card-cover img {
|
|
156
|
+
width: 100%;
|
|
157
|
+
height: 100%;
|
|
158
|
+
object-fit: cover;
|
|
159
|
+
margin: 0 !important;
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
162
|
+
|
|
163
|
+
<div class="article-layout-switcher">
|
|
164
|
+
<button class="layout-list-btn" title="List View"><span class="material-icons">view_list</span></button>
|
|
165
|
+
<button class="layout-detail-btn" title="Detail View"><span class="material-icons">view_day</span></button>
|
|
166
|
+
<button class="layout-grid-btn" title="Grid View"><span class="material-icons">view_module</span></button>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div class="article-grid">
|
|
170
|
+
{%- for mtime, rel_path, title, url, cover, summary in recent_docs %}
|
|
171
|
+
<div class="article-card">
|
|
172
|
+
<a class="card-header" href="{{ url }}" target="_blank">
|
|
173
|
+
<div class="card-title">{{ title }}</div>
|
|
174
|
+
<time class="dd-timeago card-date" datetime="{{ mtime }}">{{ mtime[:10] }}</time>
|
|
175
|
+
</a>
|
|
176
|
+
<div class="card-body">
|
|
177
|
+
<div class="card-summary">{{ summary }}</div>
|
|
178
|
+
{%- if cover %}
|
|
179
|
+
<div class="card-cover">
|
|
180
|
+
<img src="{{ cover }}" alt="{{ title }}">
|
|
181
|
+
</div>
|
|
182
|
+
{%- endif %}
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
{%- endfor %}
|
|
186
|
+
</div>
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
<style>
|
|
2
2
|
.recently-updated {
|
|
3
3
|
display: grid;
|
|
4
|
-
grid-template-columns: repeat(
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,7 @@ import json
|
|
|
4
4
|
import heapq
|
|
5
5
|
import logging
|
|
6
6
|
import subprocess
|
|
7
|
+
import re
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from datetime import datetime
|
|
9
10
|
from collections import defaultdict
|
|
@@ -132,7 +133,7 @@ def load_git_last_updated_date(docs_dir_path: Path):
|
|
|
132
133
|
|
|
133
134
|
return doc_mtime_map
|
|
134
135
|
|
|
135
|
-
def get_recently_updated_files(
|
|
136
|
+
def get_recently_updated_files(existing_dates: dict, files: Files, exclude_list: list, limit: int = 10, recent_enable: bool = False):
|
|
136
137
|
recently_updated_results = []
|
|
137
138
|
if recent_enable:
|
|
138
139
|
files_meta = []
|
|
@@ -148,14 +149,23 @@ def get_recently_updated_files(existing_map: dict, files: Files, exclude_list: l
|
|
|
148
149
|
continue
|
|
149
150
|
|
|
150
151
|
# 优先从现有数据获取 mtime,如果不存在则 fallback 到文件系统 mtime
|
|
151
|
-
mtime =
|
|
152
|
+
mtime = existing_dates.get(rel_path, os.path.getmtime(file.abs_src_path))
|
|
152
153
|
|
|
153
154
|
# 获取文档标题和 URL
|
|
154
155
|
title = file.page.title if file.page and file.page.title else file.name
|
|
155
156
|
url = file.page.url if file.page and file.page.url else file.url
|
|
156
157
|
|
|
158
|
+
cover = ''
|
|
159
|
+
summary = ''
|
|
160
|
+
# authors = []
|
|
161
|
+
if file.page:
|
|
162
|
+
cover = file.page.meta.get('cover', '')
|
|
163
|
+
# authors = file.page.meta.get('document_dates_authors', [])
|
|
164
|
+
if file.page.file:
|
|
165
|
+
summary = extract_summary(file.page.file.content_string)
|
|
166
|
+
|
|
157
167
|
# 存储信息
|
|
158
|
-
files_meta.append((mtime, rel_path, title, url))
|
|
168
|
+
files_meta.append((mtime, rel_path, title, url, cover, summary))
|
|
159
169
|
# existing_map[rel_path] = mtime
|
|
160
170
|
|
|
161
171
|
# 构建最近更新列表
|
|
@@ -208,3 +218,195 @@ def write_jsonl_cache(jsonl_file: Path, dates_cache, tracked_files):
|
|
|
208
218
|
except Exception as e:
|
|
209
219
|
logger.warning(f"Failed to add JSONL cache file to git: {e}")
|
|
210
220
|
return False
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# ===== Extract Summary =====
|
|
224
|
+
#
|
|
225
|
+
# -------- block skip --------
|
|
226
|
+
# Fence
|
|
227
|
+
FENCE_RE = re.compile(r"^\s*([`~]{3,})")
|
|
228
|
+
|
|
229
|
+
# HTML comment
|
|
230
|
+
HTML_COMMENT_START = re.compile(r'<!--', re.I)
|
|
231
|
+
HTML_COMMENT_END = re.compile(r'-->', re.I)
|
|
232
|
+
|
|
233
|
+
# HTML
|
|
234
|
+
HTML_TAG_OPEN = re.compile(r'<\s*([a-zA-Z][\w\-]*)\b', re.I)
|
|
235
|
+
HTML_TAG_CLOSE_TEMPLATE = r"</\s*{}\s*>"
|
|
236
|
+
HTML_VOID_TAGS = {
|
|
237
|
+
"area", "base", "br", "col", "embed", "hr",
|
|
238
|
+
"img", "input", "link", "meta", "param",
|
|
239
|
+
"source", "track", "wbr"
|
|
240
|
+
}
|
|
241
|
+
HTML_VOID_CLOSE_RE = re.compile(r">", re.I)
|
|
242
|
+
|
|
243
|
+
# -------- inline skip --------
|
|
244
|
+
H1_TITLE = re.compile(r'^\s*# .+$', re.MULTILINE)
|
|
245
|
+
SINGLE_LINE_HTML_NOISE = re.compile(r'^</?[a-z][\w-]*[^>]*>$', re.I)
|
|
246
|
+
TABLE_ROW_RE = re.compile(r"^\s*\|.*\|\s*$")
|
|
247
|
+
INLINE_SKIP_RE = re.compile(
|
|
248
|
+
r"""
|
|
249
|
+
^\s*> | # quote
|
|
250
|
+
^\s*(?:!!!|\?\?\?) | # admonition
|
|
251
|
+
^\s*=== | # tab
|
|
252
|
+
^\s*\[.+?\]: # reference link, including footnote
|
|
253
|
+
""",
|
|
254
|
+
re.X,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# -------- inline replace --------
|
|
258
|
+
IMAGE_RE = re.compile(r'!\[[^\]]*\]\([^)]+\)')
|
|
259
|
+
LINK_RE = re.compile(r'\[([^\]]+)\]\([^)]+\)')
|
|
260
|
+
BRACE_RE = re.compile(r"\{[^}]*\}")
|
|
261
|
+
MD_SYNTAX_RE = re.compile(r'[`*_>#]+')
|
|
262
|
+
|
|
263
|
+
def clean_markdown(md: str) -> list:
|
|
264
|
+
|
|
265
|
+
lines = md.splitlines()
|
|
266
|
+
result = []
|
|
267
|
+
|
|
268
|
+
state = "NORMAL"
|
|
269
|
+
fence = ""
|
|
270
|
+
html_close_re = None
|
|
271
|
+
frontmatter_parsed = False
|
|
272
|
+
h1_parsed = False
|
|
273
|
+
math_delim = ""
|
|
274
|
+
|
|
275
|
+
for line in lines:
|
|
276
|
+
stripped = line.strip()
|
|
277
|
+
if not stripped:
|
|
278
|
+
continue
|
|
279
|
+
|
|
280
|
+
# ==================================================
|
|
281
|
+
# 1. Frontmatter
|
|
282
|
+
# ==================================================
|
|
283
|
+
if not frontmatter_parsed:
|
|
284
|
+
if state == "FRONTMATTER":
|
|
285
|
+
if stripped in ("---", "+++"):
|
|
286
|
+
state = "NORMAL"
|
|
287
|
+
frontmatter_parsed = True
|
|
288
|
+
continue
|
|
289
|
+
|
|
290
|
+
if state == "NORMAL" and stripped in ("---", "+++"):
|
|
291
|
+
state = "FRONTMATTER"
|
|
292
|
+
continue
|
|
293
|
+
|
|
294
|
+
# ==================================================
|
|
295
|
+
# 2. Fence Block
|
|
296
|
+
# ==================================================
|
|
297
|
+
if state == "FENCE":
|
|
298
|
+
if stripped.startswith(fence):
|
|
299
|
+
state = "NORMAL"
|
|
300
|
+
continue
|
|
301
|
+
|
|
302
|
+
if state == "NORMAL":
|
|
303
|
+
m = FENCE_RE.match(stripped)
|
|
304
|
+
if m:
|
|
305
|
+
fence = m.group(1)
|
|
306
|
+
state = "FENCE"
|
|
307
|
+
continue
|
|
308
|
+
|
|
309
|
+
# ==================================================
|
|
310
|
+
# 3. HTML Comment
|
|
311
|
+
# ==================================================
|
|
312
|
+
if state == "COMMENT":
|
|
313
|
+
if HTML_COMMENT_END.search(stripped):
|
|
314
|
+
state = "NORMAL"
|
|
315
|
+
continue
|
|
316
|
+
|
|
317
|
+
if state == "NORMAL" and HTML_COMMENT_START.search(stripped):
|
|
318
|
+
state = "COMMENT"
|
|
319
|
+
if HTML_COMMENT_END.search(stripped):
|
|
320
|
+
state = "NORMAL"
|
|
321
|
+
continue
|
|
322
|
+
|
|
323
|
+
# ==================================================
|
|
324
|
+
# 4. HTML Block
|
|
325
|
+
# ==================================================
|
|
326
|
+
if state == "HTML_BLOCK":
|
|
327
|
+
if html_close_re and html_close_re.search(stripped):
|
|
328
|
+
state = "NORMAL"
|
|
329
|
+
html_close_re = None
|
|
330
|
+
continue
|
|
331
|
+
|
|
332
|
+
if state == "NORMAL":
|
|
333
|
+
m = HTML_TAG_OPEN.match(stripped)
|
|
334
|
+
if m:
|
|
335
|
+
tag = m.group(1).lower()
|
|
336
|
+
is_void = tag in HTML_VOID_TAGS
|
|
337
|
+
|
|
338
|
+
# void tag:单行且以 > 结尾,视为直接结束,忽略该行
|
|
339
|
+
if stripped.endswith('>') and is_void:
|
|
340
|
+
continue
|
|
341
|
+
|
|
342
|
+
# 非 void tag:进入 HTML_BLOCK
|
|
343
|
+
state = "HTML_BLOCK"
|
|
344
|
+
if is_void:
|
|
345
|
+
html_close_re = HTML_VOID_CLOSE_RE
|
|
346
|
+
else:
|
|
347
|
+
html_close_re = re.compile(HTML_TAG_CLOSE_TEMPLATE.format(re.escape(tag)), re.I)
|
|
348
|
+
|
|
349
|
+
# same-line close: <div>...</div>
|
|
350
|
+
if html_close_re.search(stripped):
|
|
351
|
+
state = "NORMAL"
|
|
352
|
+
html_close_re = None
|
|
353
|
+
|
|
354
|
+
continue
|
|
355
|
+
|
|
356
|
+
# ==================================================
|
|
357
|
+
# 5. Math Block
|
|
358
|
+
# ==================================================
|
|
359
|
+
if state == "MATH":
|
|
360
|
+
if stripped == math_delim:
|
|
361
|
+
state = "NORMAL"
|
|
362
|
+
continue
|
|
363
|
+
|
|
364
|
+
if state == "NORMAL" and stripped in ("$$", "\\["):
|
|
365
|
+
math_delim = "$$" if stripped == "$$" else "\\]"
|
|
366
|
+
state = "MATH"
|
|
367
|
+
continue
|
|
368
|
+
|
|
369
|
+
# ==================================================
|
|
370
|
+
# 6. Inline Skip
|
|
371
|
+
# ==================================================
|
|
372
|
+
if state == "NORMAL":
|
|
373
|
+
if TABLE_ROW_RE.match(stripped):
|
|
374
|
+
continue
|
|
375
|
+
if INLINE_SKIP_RE.match(stripped):
|
|
376
|
+
continue
|
|
377
|
+
# 单行 HTML 噪音兜底
|
|
378
|
+
if SINGLE_LINE_HTML_NOISE.match(stripped):
|
|
379
|
+
continue
|
|
380
|
+
if not h1_parsed:
|
|
381
|
+
if H1_TITLE.match(stripped):
|
|
382
|
+
h1_parsed = True
|
|
383
|
+
continue
|
|
384
|
+
if stripped.startswith(('---', '***')):
|
|
385
|
+
continue
|
|
386
|
+
|
|
387
|
+
# ==================================================
|
|
388
|
+
# 7. Inline Replace
|
|
389
|
+
# ==================================================
|
|
390
|
+
text = stripped
|
|
391
|
+
text = IMAGE_RE.sub("", text)
|
|
392
|
+
text = LINK_RE.sub(r"\1", text)
|
|
393
|
+
text = BRACE_RE.sub("", text)
|
|
394
|
+
|
|
395
|
+
text = text.strip()
|
|
396
|
+
if text:
|
|
397
|
+
result.append(text)
|
|
398
|
+
|
|
399
|
+
# 提前熔断
|
|
400
|
+
if len(result) >= 10:
|
|
401
|
+
break
|
|
402
|
+
|
|
403
|
+
# 锁定 Frontmatter 状态,防止后续 --- 干扰
|
|
404
|
+
frontmatter_parsed = True
|
|
405
|
+
|
|
406
|
+
return result
|
|
407
|
+
# return "\n".join(result)
|
|
408
|
+
|
|
409
|
+
def extract_summary(markdown_text: str) -> str:
|
|
410
|
+
md_list = clean_markdown(markdown_text)
|
|
411
|
+
text = " ".join(md_list)
|
|
412
|
+
return MD_SYNTAX_RE.sub('', text).strip()
|
{mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0/mkdocs_document_dates.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs-document-dates
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.0
|
|
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
|
|
@@ -97,6 +97,12 @@ In addition to the above basic configuration, the plug-in also provides a wealth
|
|
|
97
97
|
|
|
98
98
|
See the documentation for details: https://jaywhj.netlify.app/document-dates-en
|
|
99
99
|
|
|
100
|
+
<br />
|
|
101
|
+
|
|
102
|
+
## Other Projects
|
|
103
|
+
|
|
104
|
+
- [**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).
|
|
105
|
+
Updates have been released that refactor and add a lot of new features, see https://github.com/jaywhj/mkdocs-materialx/releases/
|
|
100
106
|
|
|
101
107
|
<br />
|
|
102
108
|
|
|
@@ -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/
|
|
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
|
|
File without changes
|
|
File without changes
|
{mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/__init__.py
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/cache_manager.py
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/hooks/pre-commit
RENAMED
|
File without changes
|
{mkdocs_document_dates-3.5.2 → mkdocs_document_dates-3.6.0}/mkdocs_document_dates/hooks_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|