hexo-theme-stellar 1.42.0 → 1.43.0
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.
- package/.claude/skills/stellar-theme-dev/SKILL.md +2 -0
- package/CHANGELOG.md +42 -0
- package/THIRD-PARTY-NOTICES.md +28 -0
- package/_config.yml +20 -10
- package/_data/icons.yml +10 -9
- package/languages/en.yml +11 -0
- package/languages/zh-CN.yml +11 -0
- package/languages/zh-TW.yml +11 -0
- package/layout/_partial/comments/artalk/layout.ejs +1 -1
- package/layout/_partial/comments/beaudar/layout.ejs +1 -1
- package/layout/_partial/comments/giscus/layout.ejs +1 -1
- package/layout/_partial/comments/twikoo/layout.ejs +1 -1
- package/layout/_partial/comments/utterances/layout.ejs +1 -1
- package/layout/_partial/comments/waline/layout.ejs +1 -1
- package/layout/_partial/components/collection-item.ejs +44 -0
- package/layout/_partial/components/collection.ejs +26 -0
- package/layout/_partial/components/widget-frame.ejs +35 -0
- package/layout/_partial/cover/wiki_cover.ejs +82 -26
- package/layout/_partial/dropdown.ejs +62 -0
- package/layout/_partial/head.ejs +9 -0
- package/layout/_partial/main/navbar/breadcrumb/blog.ejs +1 -1
- package/layout/_partial/main/post_list/archive_item.ejs +12 -0
- package/layout/_partial/main/post_list/topic_card.ejs +21 -9
- package/layout/_partial/main/post_list/wiki_card.ejs +49 -10
- package/layout/_partial/scripts/bootstrap.ejs +3 -1
- package/layout/_partial/scripts/defines.ejs +2 -8
- package/layout/_partial/scripts/lazyload.ejs +0 -3
- package/layout/_partial/scripts.ejs +1 -0
- package/layout/_partial/sidebar/index_leftbar.ejs +12 -2
- package/layout/_partial/sidebar/logo.ejs +1 -1
- package/layout/_partial/sidebar/menu.ejs +21 -23
- package/layout/_partial/widgets/components/linklist.ejs +23 -21
- package/layout/_partial/widgets/linklist.ejs +7 -12
- package/layout/_partial/widgets/recent.ejs +52 -41
- package/layout/_partial/widgets/related.ejs +47 -36
- package/layout/_partial/widgets/tagtree.ejs +70 -54
- package/layout/_partial/widgets/toc.ejs +37 -62
- package/layout/_partial/widgets/tree.ejs +38 -51
- package/layout/_plugins/index.ejs +25 -0
- package/layout/_plugins/mermaid.ejs +3 -4
- package/layout/archive.ejs +11 -20
- package/layout/collection-preview.ejs +60 -0
- package/layout/index_topic.ejs +12 -6
- package/layout/index_wiki.ejs +49 -3
- package/layout/layout.ejs +4 -3
- package/package.json +1 -1
- package/scripts/events/index.js +0 -2
- package/scripts/filters/lib/img_lazyload.js +184 -40
- package/scripts/generators/stellar-icons.js +1 -1
- package/scripts/lib/subtitle.js +5 -1
- package/scripts/tags/index.js +1 -0
- package/scripts/tags/lib/about.js +1 -1
- package/scripts/tags/lib/albums.js +1 -1
- package/scripts/tags/lib/banner.js +1 -1
- package/scripts/tags/lib/dropdown.js +64 -0
- package/scripts/tags/lib/friends.js +1 -1
- package/scripts/tags/lib/gallery.js +3 -3
- package/scripts/tags/lib/image.js +1 -1
- package/scripts/tags/lib/posters.js +1 -1
- package/scripts/tags/lib/sites.js +8 -4
- package/source/css/_common/base.styl +4 -4
- package/source/css/_common/blockquote.styl +2 -2
- package/source/css/_common/dropdown.styl +132 -0
- package/source/css/_common/html.styl +1 -1
- package/source/css/_common/loading.styl +5 -2
- package/source/css/_common/title.styl +8 -8
- package/source/css/_components/collection.styl +188 -0
- package/source/css/_components/layout.styl +1 -1
- package/source/css/_components/list.styl +44 -46
- package/source/css/_components/md.styl +3 -3
- package/source/css/_components/page-transition.styl +22 -0
- package/source/css/_components/pages/archives.styl +19 -18
- package/source/css/_components/pages/article-indent.styl +2 -2
- package/source/css/_components/pages/article-story.styl +9 -5
- package/source/css/_components/pages/collection-preview.styl +68 -0
- package/source/css/_components/pages/notebook.styl +11 -9
- package/source/css/_components/partial/article-footer.styl +7 -4
- package/source/css/_components/partial/cover.styl +280 -1
- package/source/css/_components/partial/related.styl +10 -6
- package/source/css/_components/sidebar/footer.styl +65 -12
- package/source/css/_components/sidebar/nav-area.styl +6 -1
- package/source/css/_components/sidebar/search.styl +6 -2
- package/source/css/_components/tag-plugins/chat.styl +1 -1
- package/source/css/_components/tag-plugins/folders.styl +4 -4
- package/source/css/_components/tag-plugins/folding.styl +3 -3
- package/source/css/_components/tag-plugins/hashtag.styl +2 -3
- package/source/css/_components/tag-plugins/mdrender.styl +1 -1
- package/source/css/_components/tag-plugins/note.styl +4 -4
- package/source/css/_components/tag-plugins/poetry.styl +5 -5
- package/source/css/_components/tag-plugins/quot.styl +1 -2
- package/source/css/_components/tag-plugins/quote.styl +1 -1
- package/source/css/_components/tag-plugins/tabs.styl +2 -2
- package/source/css/_components/tag-plugins/timeline.styl +4 -4
- package/source/css/_components/widgets/ghrepo.styl +4 -0
- package/source/css/_components/widgets/markdown.styl +1 -14
- package/source/css/_components/widgets/timeline.styl +2 -2
- package/source/css/_components/widgets/toc.styl +22 -20
- package/source/css/_components/widgets/widgets.styl +13 -1
- package/source/css/_components/wiki-card.styl +209 -0
- package/source/css/_custom.styl +22 -20
- package/source/css/_plugins/lazyload.styl +8 -5
- package/source/css/comments/utterances.styl +2 -2
- package/source/css/comments/waline.styl +24 -0
- package/source/css/plugins/mermaid.styl +31 -12
- package/source/js/icons.js +1 -1
- package/source/js/main.js +62 -6
- package/source/js/plugins/adaptive-text.js +46 -2
- package/source/js/plugins/dropdown.js +435 -0
- package/source/js/plugins/galaxy.js +423 -0
- package/source/js/search/algolia-search.js +1 -1
- package/source/js/search/local-search.js +1 -1
- package/source/js/services/ghinfo.js +31 -3
- package/source/js/services/siteinfo.js +26 -0
- package/source/js/services/sites.js +6 -2
- package/source/js/services.js +5 -2
- package/source/js/tagtree.js +7 -7
- package/source/js/utils.js +1 -1
- package/layout/_partial/widgets/components/link.ejs +0 -21
- package/source/css/_components/sidebar/menu.styl +0 -77
- package/source/css/_components/widgets/components.styl +0 -68
- package/source/css/_components/widgets/list.styl +0 -46
- package/source/css/_components/widgets/related.styl +0 -40
|
@@ -1,44 +1,100 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutWikiCover() {
|
|
3
3
|
var el = '';
|
|
4
|
-
const proj = theme.wiki.tree[page.wiki]
|
|
5
|
-
if (proj == undefined) {
|
|
6
|
-
return el;
|
|
7
|
-
}
|
|
8
|
-
if (proj.homepage.path !== page.path) {
|
|
4
|
+
const proj = theme.wiki.tree[page.wiki];
|
|
5
|
+
if (proj == undefined || proj.homepage.path !== page.path) {
|
|
9
6
|
return el;
|
|
10
7
|
}
|
|
11
8
|
if (proj.coverpage == undefined || proj.coverpage === false || proj.coverpage === '[]') {
|
|
12
9
|
return el;
|
|
13
10
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
|
|
12
|
+
var background = proj.background;
|
|
13
|
+
var preview = proj.preview || {};
|
|
14
|
+
var commands = Array.isArray(preview.commands) ? preview.commands.filter(function (item) {
|
|
15
|
+
return item && item.codes;
|
|
16
|
+
}) : [];
|
|
17
|
+
var hasPreview = (preview.type === 'image' && preview.src) || commands.length > 0;
|
|
18
|
+
var title = proj.headline || proj.title || page.title;
|
|
19
|
+
var desc = proj.description || page.description;
|
|
20
|
+
var repo = proj.repo;
|
|
21
|
+
var actions = Array.isArray(proj.actions) ? proj.actions.filter(function (item) {
|
|
22
|
+
return item && item.title && item.url;
|
|
23
|
+
}) : [];
|
|
24
|
+
var isGalaxy = background === 'galaxy';
|
|
25
|
+
var isImageBackground = background && !isGalaxy;
|
|
26
|
+
var projectName = proj.name || proj.title || page.wiki;
|
|
27
|
+
var adaptiveTextAttr = '';
|
|
28
|
+
if (isImageBackground) {
|
|
29
|
+
adaptiveTextAttr = ' data-text-adaptive="split" style="--cover-url:url(\'' + escape_html(background.replace(/'/g, '%27')) + '\')"';
|
|
30
|
+
} else if (isGalaxy) {
|
|
31
|
+
adaptiveTextAttr = ' data-text-adaptive="split" style="--adaptive-background:#000000"';
|
|
20
32
|
}
|
|
21
|
-
el += '<div class="l_cover wiki">';
|
|
22
|
-
el += '<article class="cover-wrap md-text">';
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
el += '<div class="l_cover wiki wiki-hero' + (hasPreview ? '' : ' without-preview') + '">';
|
|
35
|
+
el += '<div class="wiki-cover-background' + (isGalaxy ? ' galaxy' : '') + (isImageBackground ? ' image' : '') + '" aria-hidden="true">';
|
|
36
|
+
if (isGalaxy) {
|
|
37
|
+
el += '<canvas></canvas>';
|
|
38
|
+
} else if (isImageBackground) {
|
|
39
|
+
el += '<img class="wiki-cover-background-image" src="' + escape_html(background) + '" alt="" />';
|
|
40
|
+
el += '<img class="wiki-cover-background-blur" src="' + escape_html(background) + '" alt="" />';
|
|
41
|
+
}
|
|
42
|
+
el += '<div class="wiki-cover-background-overlay"></div></div>';
|
|
43
|
+
el += '<div class="wiki-cover-layout"' + adaptiveTextAttr + '>';
|
|
44
|
+
el += '<nav class="wiki-navbar" aria-label="' + escape_html(config.title) + '">';
|
|
45
|
+
el += '<a class="wiki-navbar-home" href="' + escape_html(pretty_url('/')) + '">' + escape_html(config.title) + '</a>';
|
|
46
|
+
el += '</nav>';
|
|
47
|
+
el += '<article class="cover-wrap wiki-cover-content">';
|
|
48
|
+
el += '<section class="wiki-cover-intro">';
|
|
49
|
+
if (repo) {
|
|
50
|
+
el += '<a class="wiki-cover-release ds-ghinfo is-loading" data-project-name="' + escape_html(projectName) + '" data-repo="' + escape_html(repo) + '" data-api="https://' + theme.api_host.ghapi + '/repos/' + escape_html(repo) + '/tags" index="0" target="_blank" rel="external nofollow noopener noreferrer">';
|
|
51
|
+
el += '<span class="wiki-cover-release-value"><span type="text" id="latest-tag-name"></span></span></a>';
|
|
26
52
|
}
|
|
27
|
-
if (title
|
|
28
|
-
el += '<
|
|
29
|
-
el += '<span>' + title + '</span>';
|
|
30
|
-
el += '</div>';
|
|
53
|
+
if (title) {
|
|
54
|
+
el += '<h1 class="cover-title" data-text-adaptive="contrast">' + escape_html(title) + '</h1>';
|
|
31
55
|
}
|
|
32
|
-
if (desc
|
|
56
|
+
if (desc) {
|
|
33
57
|
el += '<div class="description">' + desc + '</div>';
|
|
34
58
|
}
|
|
35
|
-
el += '<div class="
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
el += '</
|
|
40
|
-
|
|
59
|
+
el += '<div class="wiki-cover-actions">';
|
|
60
|
+
if (repo) {
|
|
61
|
+
el += '<a class="button wiki-cover-source" href="https://github.com/' + escape_html(repo) + '" target="_blank" rel="external nofollow noopener noreferrer">' + icon('default:github') + '<span>' + escape_html(__('btn.source')) + '</span></a>';
|
|
62
|
+
}
|
|
63
|
+
el += '<a class="button" href="#start">' + icon('default:documents') + '<span>' + escape_html(__('btn.docs')) + '</span></a>';
|
|
64
|
+
actions.forEach(function (item) {
|
|
65
|
+
el += '<a class="button" href="' + escape_html(item.url) + '" target="_blank" rel="external nofollow noopener noreferrer">';
|
|
66
|
+
if (item.icon) {
|
|
67
|
+
el += icon(item.icon);
|
|
68
|
+
}
|
|
69
|
+
el += '<span>' + escape_html(item.title) + '</span></a>';
|
|
70
|
+
});
|
|
71
|
+
el += '</div></section>';
|
|
72
|
+
if (hasPreview) {
|
|
73
|
+
el += '<section class="wiki-cover-preview" aria-label="' + escape_html(__('meta.project_preview')) + '">';
|
|
74
|
+
if (preview.type === 'image' && preview.src) {
|
|
75
|
+
el += '<img src="' + escape_html(preview.src) + '" alt="' + escape_html(preview.alt || '') + '" />';
|
|
76
|
+
} else if (commands.length > 0) {
|
|
77
|
+
el += '<div class="wiki-cover-terminal">';
|
|
78
|
+
el += '<div class="wiki-cover-terminal-toolbar"><div class="wiki-cover-terminal-tabs" role="tablist" aria-label="' + escape_html(__('meta.install_method')) + '">';
|
|
79
|
+
commands.forEach(function (item, index) {
|
|
80
|
+
el += '<button type="button" role="tab" aria-selected="' + (index === 0 ? 'true' : 'false') + '" class="' + (index === 0 ? 'active' : '') + '" data-codes="' + escape_html(item.codes) + '">' + escape_html(item.label || __('meta.command', index + 1)) + '</button>';
|
|
81
|
+
});
|
|
82
|
+
el += '</div><button type="button" class="wiki-cover-copy" data-copy-message="' + escape_html(__('message.copied')) + '" aria-label="' + escape_html(__('btn.copy')) + '">' + icon('copy:copy') + '<span>' + escape_html(__('btn.copy')) + '</span></button></div>';
|
|
83
|
+
el += '<pre><code>' + terminalCodes(commands[0].codes) + '</code></pre>';
|
|
84
|
+
el += '</div>';
|
|
85
|
+
}
|
|
86
|
+
el += '</section>';
|
|
87
|
+
}
|
|
88
|
+
el += '</article></div></div>';
|
|
41
89
|
return el;
|
|
42
90
|
}
|
|
91
|
+
|
|
92
|
+
function terminalCodes(codes) {
|
|
93
|
+
return String(codes || '').split(/\r?\n/).filter(function (line) {
|
|
94
|
+
return line.trim().length > 0;
|
|
95
|
+
}).map(function (line) {
|
|
96
|
+
return '<span>' + escape_html(line) + '</span>';
|
|
97
|
+
}).join('');
|
|
98
|
+
}
|
|
43
99
|
%>
|
|
44
100
|
<%- layoutWikiCover() %>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const dropdownItem = typeof item !== 'undefined' && item ? item : {}
|
|
3
|
+
const items = Array.isArray(dropdownItem.items) ? dropdownItem.items.filter(child => child && child.title && child.url) : []
|
|
4
|
+
const classes = ['dropdown']
|
|
5
|
+
const dropdownRootClass = typeof rootClass === 'string' ? rootClass : ''
|
|
6
|
+
if (dropdownRootClass) {
|
|
7
|
+
classes.push(dropdownRootClass)
|
|
8
|
+
}
|
|
9
|
+
const triggerClasses = ['dropdown-trigger']
|
|
10
|
+
const dropdownTriggerClass = typeof triggerClass === 'string' ? triggerClass : ''
|
|
11
|
+
if (dropdownTriggerClass) {
|
|
12
|
+
triggerClasses.push(dropdownTriggerClass)
|
|
13
|
+
}
|
|
14
|
+
const dropdownDirection = typeof direction === 'string' ? direction : ''
|
|
15
|
+
const dropdownShowTitle = typeof showTitle === 'undefined' || showTitle !== false
|
|
16
|
+
|
|
17
|
+
function linkAttrs(child) {
|
|
18
|
+
const url = String(child.url)
|
|
19
|
+
var attrs = ' href="' + escape_html(url_for(url)) + '"'
|
|
20
|
+
if (url.includes('://')) {
|
|
21
|
+
attrs += ' target="_blank" rel="external nofollow noopener noreferrer"'
|
|
22
|
+
} else {
|
|
23
|
+
attrs += ' rel="noopener noreferrer"'
|
|
24
|
+
}
|
|
25
|
+
return attrs
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function layoutDiv() {
|
|
29
|
+
if (!dropdownItem.icon || items.length === 0) {
|
|
30
|
+
return ''
|
|
31
|
+
}
|
|
32
|
+
const title = dropdownItem.title ? escape_html(dropdownItem.title) : ''
|
|
33
|
+
var el = '<details class="' + classes.join(' ') + '"'
|
|
34
|
+
if (dropdownDirection) {
|
|
35
|
+
el += ' direction="' + escape_html(dropdownDirection) + '"'
|
|
36
|
+
}
|
|
37
|
+
el += '>'
|
|
38
|
+
el += '<summary class="' + triggerClasses.join(' ') + '"'
|
|
39
|
+
if (title) {
|
|
40
|
+
el += ' title="' + title + '" aria-label="' + title + '"'
|
|
41
|
+
}
|
|
42
|
+
el += '>'
|
|
43
|
+
// dropdown 首次展开时需要立即显示图标,使用内联 SVG 避免 /js/icons.js 异步替换造成闪烁。
|
|
44
|
+
el += icon(dropdownItem.icon, 'no-lazy', true)
|
|
45
|
+
if (dropdownShowTitle && dropdownItem.title) {
|
|
46
|
+
el += '<span>' + title + '</span>'
|
|
47
|
+
}
|
|
48
|
+
el += '</summary>'
|
|
49
|
+
el += '<div class="dropdown-menu ui-collection" data-ui-surface="glass" data-layout="list" data-variant="nav" data-density="compact">'
|
|
50
|
+
for (let child of items) {
|
|
51
|
+
el += '<a class="dropdown-item ui-collection__item"' + linkAttrs(child) + '>'
|
|
52
|
+
if (child.icon) {
|
|
53
|
+
el += '<span class="ui-collection__leading">' + icon(child.icon, 'no-lazy', true) + '</span>'
|
|
54
|
+
}
|
|
55
|
+
el += '<span class="ui-collection__content"><span class="ui-collection__title">' + escape_html(child.title) + '</span></span>'
|
|
56
|
+
el += '</a>'
|
|
57
|
+
}
|
|
58
|
+
el += '</div></details>'
|
|
59
|
+
return el
|
|
60
|
+
}
|
|
61
|
+
%>
|
|
62
|
+
<%- layoutDiv() %>
|
package/layout/_partial/head.ejs
CHANGED
|
@@ -237,6 +237,15 @@ function generate_canonical() {
|
|
|
237
237
|
const raw = theme.icons && theme.icons[key];
|
|
238
238
|
if (raw) vars.push(` ${name}: url("data:image/svg+xml,${encodeURIComponent(raw)}");`);
|
|
239
239
|
}
|
|
240
|
+
// 加载占位:由 icons.yml 的 default:loading 提供(内联 SVG 编码为 data URI,URL 直用)
|
|
241
|
+
const loadingRaw = theme.icons && theme.icons['default:loading'];
|
|
242
|
+
if (loadingRaw) {
|
|
243
|
+
if (loadingRaw.trim().startsWith('<svg')) {
|
|
244
|
+
vars.push(` --icon-loading: url("data:image/svg+xml,${encodeURIComponent(loadingRaw)}");`);
|
|
245
|
+
} else {
|
|
246
|
+
vars.push(` --icon-loading: url("${loadingRaw}");`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
240
249
|
return vars.length > 0 ? `:root {\n${vars.join('\n')}\n}` : '';
|
|
241
250
|
})();
|
|
242
251
|
%>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%
|
|
2
|
+
var item = post || {};
|
|
3
|
+
var href = pretty_url(item.link || item.path || '/');
|
|
4
|
+
var itemDate = item.date ? date(item.date, 'MM-DD') : '';
|
|
5
|
+
var itemTitle = item.title || (item.date ? date(item.date, config.date_format) : '');
|
|
6
|
+
%>
|
|
7
|
+
<div class="archive-list">
|
|
8
|
+
<a class="post fs14" href="<%- escape_html(href) %>">
|
|
9
|
+
<% if (itemDate) { %><time><%- escape_html(itemDate) %></time><% } %>
|
|
10
|
+
<span><%- escape_html(itemTitle) %></span>
|
|
11
|
+
</a>
|
|
12
|
+
</div>
|
|
@@ -17,17 +17,29 @@ function layoutDiv() {
|
|
|
17
17
|
background: bg,
|
|
18
18
|
post: latest
|
|
19
19
|
});
|
|
20
|
-
//
|
|
20
|
+
// 其他文章(排除最新,默认展示 3 条,剩余文章可展开)
|
|
21
21
|
if (topic.pages && topic.pages.length > 1) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
el += '
|
|
28
|
-
el += '</a>';
|
|
22
|
+
var otherPosts = topic.pages.slice(1);
|
|
23
|
+
var visiblePosts = otherPosts.slice(0, 3);
|
|
24
|
+
var hiddenPosts = otherPosts.slice(3);
|
|
25
|
+
el += '<div class="topic-posts">';
|
|
26
|
+
visiblePosts.forEach(function(post) {
|
|
27
|
+
el += partial('_partial/main/post_list/archive_item', {post: post});
|
|
29
28
|
});
|
|
30
|
-
|
|
29
|
+
if (hiddenPosts.length > 0) {
|
|
30
|
+
el += '<details class="topic-posts-more">';
|
|
31
|
+
el += '<summary class="topic-posts-toggle">';
|
|
32
|
+
el += '<span class="when-closed">' + escape_html(__('btn.expand_posts', hiddenPosts.length)) + '</span>';
|
|
33
|
+
el += '<span class="when-open">' + escape_html(__('btn.collapse_posts')) + '</span>';
|
|
34
|
+
el += icon('default:arrow-right', '', true);
|
|
35
|
+
el += '</summary>';
|
|
36
|
+
el += '<div class="topic-posts-extra">';
|
|
37
|
+
hiddenPosts.forEach(function(post) {
|
|
38
|
+
el += partial('_partial/main/post_list/archive_item', {post: post});
|
|
39
|
+
});
|
|
40
|
+
el += '</div>';
|
|
41
|
+
el += '</details>';
|
|
42
|
+
}
|
|
31
43
|
el += '</div>';
|
|
32
44
|
}
|
|
33
45
|
el += '</article>';
|
|
@@ -1,21 +1,60 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv() {
|
|
3
3
|
var el = '';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
var cover = proj.cover;
|
|
5
|
+
var projectIcon = proj.icon;
|
|
6
|
+
var caption = subtitle(proj);
|
|
7
|
+
var headline = proj.headline || proj.title || proj.name || '';
|
|
8
|
+
el += '<article class="wiki-card-content">';
|
|
9
|
+
el += '<div class="wiki-card-cover' + (cover ? '' : ' no-cover') + '" position="bottom"';
|
|
10
|
+
if (cover) {
|
|
11
|
+
el += ' style="--cover-url:url(\'' + escape_html(cover.replace(/'/g, '%27')) + '\')">';
|
|
12
|
+
el += '<img src="' + escape_html(cover) + '" alt=""/>';
|
|
13
|
+
} else {
|
|
14
|
+
el += '>';
|
|
15
|
+
}
|
|
16
|
+
el += '<div class="wiki-card-info" position="bottom"';
|
|
17
|
+
if (cover) {
|
|
18
|
+
el += ' data-text-adaptive="split"';
|
|
19
|
+
}
|
|
20
|
+
el += '>';
|
|
21
|
+
el += '<div class="wiki-card-summary">';
|
|
7
22
|
if (proj.tags && proj.tags.length > 0) {
|
|
8
|
-
el += '<div class="
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
el += '<div class="wiki-tags wiki-meta">';
|
|
24
|
+
for (var i = 0; i < proj.tags.length; i++) {
|
|
25
|
+
var tag = proj.tags[i];
|
|
26
|
+
el += '<span>' + escape_html(tag) + '</span>';
|
|
27
|
+
}
|
|
28
|
+
el += '</div>';
|
|
29
|
+
}
|
|
30
|
+
el += '<h2 class="headline">' + escape_html(headline) + '</h2>';
|
|
31
|
+
if (proj.available || proj.repo) {
|
|
32
|
+
el += '<div class="wiki-meta">';
|
|
33
|
+
if (proj.available) {
|
|
34
|
+
el += '<span class="wiki-available">' + icon('default:platforms') + '<span class="label">' + escape_html(__('meta.available')) + '</span><span class="value">' + escape_html(proj.available) + '</span></span>';
|
|
35
|
+
}
|
|
36
|
+
if (proj.repo) {
|
|
37
|
+
el += '<span class="wiki-stars data-service ds-ghinfo" data-api="https://' + theme.api_host.ghapi + '/repos/' + escape_html(proj.repo) + '">';
|
|
38
|
+
el += icon('default:fire') + '<span type="text" id="stargazers_count"></span>';
|
|
39
|
+
el += '</span>';
|
|
40
|
+
}
|
|
12
41
|
el += '</div>';
|
|
13
42
|
}
|
|
14
|
-
el += '
|
|
15
|
-
|
|
16
|
-
|
|
43
|
+
el += '</div>';
|
|
44
|
+
el += '<div class="wiki-project">';
|
|
45
|
+
el += '<div class="project-icon">';
|
|
46
|
+
if (projectIcon) {
|
|
47
|
+
el += '<img src="' + escape_html(projectIcon) + '" alt=""/>';
|
|
48
|
+
} else {
|
|
49
|
+
el += icon('default:documents');
|
|
17
50
|
}
|
|
18
51
|
el += '</div>';
|
|
52
|
+
el += '<div class="project-text"><div class="project-name">' + escape_html(proj.name || proj.title || '') + '</div>';
|
|
53
|
+
if (caption.length > 0) {
|
|
54
|
+
el += '<div class="project-subtitle">' + escape_html(caption) + '</div>';
|
|
55
|
+
}
|
|
56
|
+
el += '</div></div>';
|
|
57
|
+
el += '</div></div>';
|
|
19
58
|
el += '</article>';
|
|
20
59
|
return el;
|
|
21
60
|
}
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
if (typeof utils === 'object') return;
|
|
25
25
|
// utils 未就绪时补载;加载成功后由 utils.js 内部补跑插件队列
|
|
26
26
|
var s = document.createElement('script');
|
|
27
|
-
s.src =
|
|
27
|
+
// 用 setAttribute 赋值 src,避免被基于 `s.src = "..."` 的正则
|
|
28
|
+
// (图片懒加载 / 脚本延迟优化器)误改写
|
|
29
|
+
s.setAttribute('src', '<%- url_for('/js/utils.js') %>?v=<%- stellar_info('version') %>');
|
|
28
30
|
s.async = false;
|
|
29
31
|
s.onerror = function () {
|
|
30
32
|
console.error('[Stellar] 无法加载 /js/utils.js,已启用内容兜底显示(sr-fallback)');
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
}
|
|
18
18
|
(function() {
|
|
19
19
|
const scrollHandler = () => {
|
|
20
|
-
const wikiCover = document.querySelector('#l_cover .l_cover.wiki');
|
|
21
|
-
const startEl = document.getElementById('start');
|
|
22
20
|
// 存在有效锚点时,等待布局稳定后滚动到目标
|
|
23
21
|
// (浏览器原生锚点滚动发生在布局完成前,长文章的懒加载图片/异步组件会把目标顶偏)
|
|
24
22
|
const hash = window.location.hash;
|
|
@@ -137,11 +135,8 @@
|
|
|
137
135
|
return;
|
|
138
136
|
}
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
} else {
|
|
143
|
-
window.scrollTo(0, 0);
|
|
144
|
-
}
|
|
138
|
+
// 没有锚点时始终保持页面顶部;Wiki Hero 只在用户显式访问 #start 时定位正文。
|
|
139
|
+
window.scrollTo(0, 0);
|
|
145
140
|
};
|
|
146
141
|
if (document.readyState !== 'loading') scrollHandler();
|
|
147
142
|
else document.addEventListener('DOMContentLoaded', scrollHandler);
|
|
@@ -174,7 +169,6 @@
|
|
|
174
169
|
const def = {
|
|
175
170
|
avatar: `<%- theme.default.avatar %>`,
|
|
176
171
|
cover: `<%- theme.default.cover %>`,
|
|
177
|
-
loading: `<%- theme.default.loading || (theme.icons && theme.icons['default:loading-placeholder']) %>`,
|
|
178
172
|
data_cache: <%- JSON.stringify(theme.data_cache || {}) %>,
|
|
179
173
|
};
|
|
180
174
|
const deps = {
|
|
@@ -48,6 +48,7 @@ function tagtreeWidgetOnPage() {
|
|
|
48
48
|
<script defer src="<%- url_for('/js/stellar-icons.js') %>?v=<%- stellar_info('version') %>"></script>
|
|
49
49
|
<!-- 非首屏图标异步加载:占位符替换依赖构建期生成的 js/icons/{ns}.json -->
|
|
50
50
|
<script defer src="<%- url_for('/js/icons.js') %>?v=<%- stellar_info('version') %>" data-version="<%- stellar_info('version') %>"></script>
|
|
51
|
+
<script defer src="<%- url_for('/js/plugins/dropdown.js') %>?v=<%- stellar_info('version') %>"></script>
|
|
51
52
|
<script src="<%- url_for(`${theme.stellar.main_js}?v=${stellar_info('version')}`) %>" defer></script>
|
|
52
53
|
<script defer src="<%- url_for('/js/theme.js') %>?v=<%- stellar_info('version') %>"></script>
|
|
53
54
|
|
|
@@ -125,10 +125,20 @@ function layoutFooterDiv() {
|
|
|
125
125
|
return ''
|
|
126
126
|
}
|
|
127
127
|
var el = '<footer class="footer dis-select">';
|
|
128
|
-
el += '<div class="social-wrap">';
|
|
128
|
+
el += '<div class="social-wrap" style="--item-grad:url(#footer-social-icon-grad)">';
|
|
129
|
+
el += partial('grad-def', {id: 'footer-social-icon-grad'})
|
|
129
130
|
for (let id of Object.keys(social)) {
|
|
130
131
|
let item = social[id];
|
|
131
|
-
if (
|
|
132
|
+
if (id === 'spacer') {
|
|
133
|
+
el += '<span class="social-spacer" aria-hidden="true"></span>';
|
|
134
|
+
} else if (item?.type === 'dropdown') {
|
|
135
|
+
el += partial('../dropdown', {
|
|
136
|
+
item: item,
|
|
137
|
+
rootClass: 'social-dropdown',
|
|
138
|
+
triggerClass: 'social',
|
|
139
|
+
showTitle: false
|
|
140
|
+
})
|
|
141
|
+
} else if (item?.icon && (item.url || item.onclick)) {
|
|
132
142
|
el += '<a class="social"';
|
|
133
143
|
if (item.title) {
|
|
134
144
|
el += ' title="' + escape_html(item.title) + '"';
|
|
@@ -50,7 +50,7 @@ function layoutBack() {
|
|
|
50
50
|
var el = ''
|
|
51
51
|
el += `<div class="wiki-home-wrap">`
|
|
52
52
|
el += `<a class="wiki-home cap" href="${pretty_url(theme.site_tree.index_wiki.base_dir)}">`
|
|
53
|
-
el += icon('default:
|
|
53
|
+
el += icon('default:arrow-left', '', true)
|
|
54
54
|
el += `<span>${__('btn.all_wiki')}</span>`
|
|
55
55
|
el += `</a>`
|
|
56
56
|
el += `</div>`
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv() {
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (item == undefined || item.id == null || item.url == null) {
|
|
3
|
+
var entries = []
|
|
4
|
+
for (var menuItem of (theme.menubar.items || [])) {
|
|
5
|
+
if (menuItem == null || menuItem.id == null || menuItem.url == null || menuItem.title == null) {
|
|
7
6
|
continue
|
|
8
7
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
entries.push({
|
|
9
|
+
href: pretty_url(menuItem.url),
|
|
10
|
+
title: __(menuItem.title),
|
|
11
|
+
icon: menuItem.icon,
|
|
12
|
+
theme: menuItem.theme,
|
|
13
|
+
active: menuItem.id == page.menu_id,
|
|
14
|
+
className: menuItem.theme?.length > 0 ? 'is-themed' : '',
|
|
15
|
+
gradientId: 'menu-grad-' + menuItem.id
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
var body = partial('_partial/components/collection', {options: {
|
|
19
|
+
layout: 'list',
|
|
20
|
+
variant: 'nav',
|
|
21
|
+
items: entries
|
|
22
|
+
}})
|
|
23
|
+
if ((body || '').trim().length === 0) {
|
|
24
|
+
return ''
|
|
26
25
|
}
|
|
27
|
-
|
|
28
|
-
return el
|
|
26
|
+
return `<nav class="menu dis-select${where == 'main' ? ' mobile-hidden' : ''}">${body}</nav>`
|
|
29
27
|
}
|
|
30
28
|
%>
|
|
31
29
|
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv(linklist) {
|
|
3
|
-
var links = linklist.items
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
var links = Array.isArray(linklist.items) ? linklist.items : []
|
|
4
|
+
var view = linklist.view === 'grid' ? 'grid' : 'list'
|
|
5
|
+
var columns = view === 'grid' ? (linklist.columns || 2) : 1
|
|
6
|
+
var showTitle = linklist.show_title !== false
|
|
7
|
+
var entries = []
|
|
8
|
+
for (var link of links) {
|
|
9
|
+
if (!link || !link.url || !link.title) {
|
|
10
|
+
continue
|
|
11
|
+
}
|
|
12
|
+
entries.push({
|
|
13
|
+
href: link.url,
|
|
14
|
+
title: link.title,
|
|
15
|
+
icon: link.icon,
|
|
16
|
+
active: pretty_url(link.url) == pretty_url(page.path),
|
|
17
|
+
showTitle: showTitle,
|
|
18
|
+
gradientRef: 'leftbar-active-icon-grad'
|
|
19
|
+
})
|
|
6
20
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
style += `style="grid-template-columns:repeat(${columns},1fr);"`
|
|
14
|
-
}
|
|
15
|
-
var align = 'center'
|
|
16
|
-
if (columns == 1 && links.length > 1) {
|
|
17
|
-
align = 'left'
|
|
18
|
-
}
|
|
19
|
-
el += `<div class="linklist ${align}${columns > 1 ? ' multi' : ''}" ${style}>`
|
|
20
|
-
for (let link of links) {
|
|
21
|
-
el += partial('link', {item: link, columns: columns})
|
|
22
|
-
}
|
|
23
|
-
el += `</div>`
|
|
24
|
-
return el
|
|
21
|
+
return partial('_partial/components/collection', {options: {
|
|
22
|
+
layout: view,
|
|
23
|
+
variant: showTitle ? 'nav' : 'icon',
|
|
24
|
+
columns: columns,
|
|
25
|
+
items: entries
|
|
26
|
+
}})
|
|
25
27
|
}
|
|
26
28
|
%>
|
|
27
29
|
<%- layoutDiv(item) %>
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv() {
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
el += '<div class="widget-body fs14">';
|
|
11
|
-
el += partial('components/linklist', {item: item})
|
|
12
|
-
el += '</div>';
|
|
13
|
-
el += '</widget>';
|
|
14
|
-
return el;
|
|
3
|
+
var body = partial('components/linklist', {item: item})
|
|
4
|
+
return partial('_partial/components/widget-frame', {
|
|
5
|
+
className: 'link-list-widget',
|
|
6
|
+
title: item.title,
|
|
7
|
+
body: body,
|
|
8
|
+
reveal: false
|
|
9
|
+
})
|
|
15
10
|
}
|
|
16
11
|
%>
|
|
17
12
|
<%- layoutDiv() %>
|