hexo-theme-stellar 1.37.0 → 1.38.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/CHANGELOG.md +41 -0
- package/_config.yml +13 -8
- package/languages/en.yml +37 -0
- package/languages/zh-CN.yml +37 -0
- package/languages/zh-TW.yml +37 -0
- package/layout/_partial/comments/layout.ejs +2 -1
- package/layout/_partial/main/navbar/article_banner.ejs +11 -5
- package/layout/_partial/main/post_list/post_card.ejs +1 -1
- package/layout/_partial/scripts/defines.ejs +2 -1
- package/layout/_partial/scripts/utils.ejs +58 -15
- package/layout/_partial/sidebar/grad-def.ejs +26 -0
- package/layout/_partial/sidebar/index_leftbar.ejs +25 -10
- package/layout/_partial/sidebar/logo.ejs +21 -0
- package/layout/_partial/sidebar/menu.ejs +11 -5
- package/layout/_partial/widgets/toc.ejs +12 -8
- package/layout/_plugins/scrollreveal.ejs +17 -2
- package/layout/index.ejs +27 -1
- package/layout/notebooks.ejs +3 -1
- package/layout/notes.ejs +3 -1
- package/package.json +1 -1
- package/scripts/tags/index.js +1 -0
- package/scripts/tags/lib/mbti.js +169 -0
- package/source/css/_common/canonical.styl +9 -10
- package/source/css/_common/highlight.styl +0 -2
- package/source/css/_common/html.styl +2 -1
- package/source/css/_common/svg.styl +9 -1
- package/source/css/_components/list.styl +36 -16
- package/source/css/_components/md.styl +0 -1
- package/source/css/_components/pages/article-story.styl +1 -3
- package/source/css/_components/partial/article-banner.styl +17 -11
- package/source/css/_components/partial/article-footer.styl +0 -1
- package/source/css/_components/partial/navbar.styl +3 -3
- package/source/css/_components/sidebar/logo.styl +26 -0
- package/source/css/_components/sidebar/menu.styl +53 -30
- package/source/css/_components/sidebar/nav-area.styl +1 -1
- package/source/css/_components/sidebar/search.styl +46 -7
- package/source/css/_components/sidebar/sidebar.styl +5 -1
- package/source/css/_components/tag-plugins/banner.styl +2 -1
- package/source/css/_components/tag-plugins/chat.styl +3 -1
- package/source/css/_components/tag-plugins/folding.styl +1 -2
- package/source/css/_components/tag-plugins/friends.styl +1 -0
- package/source/css/_components/tag-plugins/friends_posts.styl +2 -1
- package/source/css/_components/tag-plugins/gallery.styl +1 -2
- package/source/css/_components/tag-plugins/grid.styl +1 -2
- package/source/css/_components/tag-plugins/image.styl +0 -2
- package/source/css/_components/tag-plugins/link.styl +0 -1
- package/source/css/_components/tag-plugins/mbti.styl +80 -0
- package/source/css/_components/tag-plugins/note.styl +1 -2
- package/source/css/_components/tag-plugins/okr.styl +1 -2
- package/source/css/_components/tag-plugins/sites.styl +0 -1
- package/source/css/_components/tag-plugins/timeline.styl +1 -6
- package/source/css/_components/widgets/components.styl +14 -7
- package/source/css/_components/widgets/ghuser.styl +2 -1
- package/source/css/_components/widgets/list.styl +20 -8
- package/source/css/_components/widgets/markdown.styl +4 -1
- package/source/css/_components/widgets/related.styl +6 -4
- package/source/css/_components/widgets/toc.styl +2 -2
- package/source/css/_components/widgets/widgets.styl +6 -9
- package/source/css/_custom.styl +2 -1
- package/source/css/_defines/const.styl +1 -1
- package/source/css/_defines/func.styl +13 -1
- package/source/css/_defines/theme_base.styl +22 -1
- package/source/css/_plugins/comments/artalk.styl +2 -2
- package/source/css/_plugins/comments/twikoo.styl +0 -2
- package/source/css/_plugins/tianli_gpt.styl +3 -0
- package/source/js/main.js +39 -17
- package/source/js/services/memos.js +12 -3
|
@@ -62,6 +62,25 @@ x-set-text-colors($scheme, $p0 = 1, $p1 = 0.8, $p2 = 0.7, $p3 = 0.5, $p4 = 0.4)
|
|
|
62
62
|
--block-border: x-hsla($hue, $sat, $light, $alpha * 1.5)
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
// ========== 通用主题色渐变 ==========
|
|
66
|
+
// 约定:渐变颜色通过 --item-theme 提供,未设置时回退到站点主题色 var(--theme);
|
|
67
|
+
// 淡色变体为 --item-theme-light(默认与白色混合 50%);角度默认取 style.gradient.angle。
|
|
68
|
+
// 注意:局部覆盖 --item-theme 的元素需同时设置 --item-theme-light(如 x-theme-light()),
|
|
69
|
+
// 否则淡色变体仍沿用 :root 上的主题色。
|
|
70
|
+
// 用法示例:
|
|
71
|
+
// .foo
|
|
72
|
+
// --item-theme: #1BCDFC // 可选,默认使用站点主题色
|
|
73
|
+
// background: x-theme-gradient() // 右上角淡色 → 左下角主色,停止点 20% / 60%
|
|
74
|
+
// background: x-theme-gradient(30%, 70%, 25%) // 自定义停止点与淡色比例
|
|
75
|
+
// 图标渐变(SVG):元素内放置 <svg class="grad-def">…<linearGradient …/></svg>,
|
|
76
|
+
// 并设置 --item-grad:url(#渐变id),然后对子元素使用 fill:var(--item-grad)。
|
|
77
|
+
x-theme-light($color = unquote('var(--item-theme)'), $ratio = 50%)
|
|
78
|
+
return unquote('color-mix(in srgb, %s %s, #fff)' % ($color $ratio))
|
|
79
|
+
|
|
80
|
+
x-theme-gradient($color = unquote('var(--item-theme)'), $start = 20%, $end = 60%, $light-ratio = 50%, $angle = convert(hexo-config('style.gradient.angle')) or 225deg)
|
|
81
|
+
$light = x-theme-light($color, $light-ratio)
|
|
82
|
+
return unquote('linear-gradient(%s, %s %s, %s %s)' % ($angle $light $start $color $end))
|
|
83
|
+
|
|
65
84
|
// ---------------- apply theme ----------------
|
|
66
85
|
// 设置浅色模式
|
|
67
86
|
dynamic-theme-light()
|
|
@@ -92,6 +111,9 @@ dynamic-theme-dark()
|
|
|
92
111
|
--accent: $c-accent
|
|
93
112
|
// 链接
|
|
94
113
|
x-set-link-with-color($c-link)
|
|
114
|
+
// 通用渐变颜色(局部可用 --item-theme 覆盖)
|
|
115
|
+
--item-theme: var(--theme)
|
|
116
|
+
--item-theme-light: x-theme-light()
|
|
95
117
|
|
|
96
118
|
// dynamic colors
|
|
97
119
|
dynamic-theme-light()
|
|
@@ -103,4 +125,3 @@ dynamic-theme-dark()
|
|
|
103
125
|
dynamic-theme-light()
|
|
104
126
|
:root[data-theme="dark"]
|
|
105
127
|
dynamic-theme-dark()
|
|
106
|
-
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
padding: 0
|
|
49
49
|
.atk-avatar img
|
|
50
50
|
border-radius: 50%
|
|
51
|
+
corner-shape: round
|
|
51
52
|
width: 36px
|
|
52
53
|
height: 36px
|
|
53
54
|
.atk-comment-wrap>.atk-comment>.atk-main
|
|
@@ -158,7 +159,6 @@
|
|
|
158
159
|
>img
|
|
159
160
|
margin: var(--gap-p) auto
|
|
160
161
|
border-radius: $border-image-s
|
|
161
|
-
corner-shape: superellipse(1.2)
|
|
162
162
|
a>img
|
|
163
163
|
display: inline
|
|
164
164
|
img[atk-emoticon]
|
|
@@ -180,4 +180,4 @@
|
|
|
180
180
|
a
|
|
181
181
|
--at-color-main: var(--link)
|
|
182
182
|
pre>code
|
|
183
|
-
padding: 0
|
|
183
|
+
padding: 0
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
.vemoji, .tk-owo-emotion
|
|
7
7
|
width: unset
|
|
8
8
|
border-radius: $border-image-s
|
|
9
|
-
corner-shape: superellipse(1.2)
|
|
10
9
|
max-height: 24px
|
|
11
10
|
max-width: 100px
|
|
12
11
|
display: inline
|
|
@@ -15,7 +14,6 @@
|
|
|
15
14
|
max-width: 400px
|
|
16
15
|
max-height: 400px
|
|
17
16
|
border-radius: $border-image-s
|
|
18
|
-
corner-shape: superellipse(1.2)
|
|
19
17
|
|
|
20
18
|
.OwO
|
|
21
19
|
.OwO-body
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
#post-ai .ai-cursor
|
|
65
65
|
display inline-block
|
|
66
66
|
border-radius 50%
|
|
67
|
+
corner-shape round
|
|
67
68
|
background var(--ai-cursor)
|
|
68
69
|
width: 12px
|
|
69
70
|
height: 12px
|
|
@@ -167,6 +168,7 @@
|
|
|
167
168
|
background var(--ai-font-color)
|
|
168
169
|
margin-left 7px
|
|
169
170
|
border-radius 50%
|
|
171
|
+
corner-shape round
|
|
170
172
|
display flex
|
|
171
173
|
flex-direction row
|
|
172
174
|
flex-wrap wrap
|
|
@@ -186,6 +188,7 @@
|
|
|
186
188
|
background var(--ai-speech-content)
|
|
187
189
|
height 8px
|
|
188
190
|
border-radius 50%
|
|
191
|
+
corner-shape round
|
|
189
192
|
-webkit-transition .3s
|
|
190
193
|
-moz-transition .3s
|
|
191
194
|
-o-transition .3s
|
package/source/js/main.js
CHANGED
|
@@ -207,6 +207,22 @@ const init = {
|
|
|
207
207
|
sidebar.dismiss();
|
|
208
208
|
});
|
|
209
209
|
},
|
|
210
|
+
wikiStart: () => {
|
|
211
|
+
utils.dom('#l_cover .l_cover.wiki .start-wrap a.button.start').click(function (e) {
|
|
212
|
+
const href = this.getAttribute("href");
|
|
213
|
+
const id = href && href.indexOf("#") === 0 ? decodeURIComponent(href.slice(1)) : null;
|
|
214
|
+
const target = id && document.getElementById(id);
|
|
215
|
+
if (target) {
|
|
216
|
+
e.preventDefault();
|
|
217
|
+
// #start 锚点贴顶滚动,不预留 offset
|
|
218
|
+
const offset = 0;
|
|
219
|
+
smoothScrollTo(target.getBoundingClientRect().top + window.scrollY - offset);
|
|
220
|
+
if (window.history && window.history.pushState) {
|
|
221
|
+
window.history.pushState(null, "", href);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
},
|
|
210
226
|
leftbarScroll: () => {
|
|
211
227
|
const container = document.querySelector('.l_left .widgets');
|
|
212
228
|
if (container == null) {
|
|
@@ -301,13 +317,21 @@ const init = {
|
|
|
301
317
|
|
|
302
318
|
canonicalCheck: () => {
|
|
303
319
|
const canonical = window.canonical;
|
|
320
|
+
// 真实主站域名优先从 encoded(base64)反解,避免被「批量替换域名」的克隆站把提示指向自己
|
|
321
|
+
const getOriginalHost = () => {
|
|
322
|
+
try {
|
|
323
|
+
return atob(canonical.encoded || '') || canonical.originalHost || '';
|
|
324
|
+
} catch (e) {
|
|
325
|
+
return canonical.originalHost || '';
|
|
326
|
+
}
|
|
327
|
+
};
|
|
304
328
|
function originStatusCheck() {
|
|
305
329
|
return new Promise((resolve) => {
|
|
306
|
-
if (
|
|
330
|
+
if (getOriginalHost() === window.location.hostname) {
|
|
307
331
|
resolve(true);
|
|
308
332
|
return;
|
|
309
333
|
}
|
|
310
|
-
const scriptUrl = `https://${
|
|
334
|
+
const scriptUrl = `https://${getOriginalHost()}${window.canonical.param.checklink}`;
|
|
311
335
|
const script = document.createElement('script');
|
|
312
336
|
script.src = scriptUrl;
|
|
313
337
|
script.type = 'text/javascript';
|
|
@@ -322,18 +346,23 @@ const init = {
|
|
|
322
346
|
meta.content = 'noindex, nofollow';
|
|
323
347
|
document.head.appendChild(meta);
|
|
324
348
|
const notice = document.createElement('div');
|
|
325
|
-
const originalURL = `https://${
|
|
326
|
-
|
|
349
|
+
const originalURL = `https://${getOriginalHost()}`;
|
|
350
|
+
let currentURL = originalURL;
|
|
351
|
+
if (canonical.param.permalink && canonical.param.permalink.startsWith("http")) {
|
|
352
|
+
try {
|
|
353
|
+
const permalinkURL = new URL(canonical.param.permalink);
|
|
354
|
+
currentURL = `${originalURL}${permalinkURL.pathname}${permalinkURL.search}`;
|
|
355
|
+
} catch (e) {
|
|
356
|
+
// permalink 异常时退回源站首页
|
|
357
|
+
}
|
|
358
|
+
}
|
|
327
359
|
if (isOfficial) {
|
|
328
|
-
|
|
329
|
-
const closedToday = window.localStorage.getItem('Stellar.canonical.closeTime') === new Date().toDateString()
|
|
330
|
-
if ((closeEnable && closedToday) || !(await originStatusCheck())) return;
|
|
360
|
+
if (!(await originStatusCheck())) return;
|
|
331
361
|
notice.className = 'canonical-tip official';
|
|
332
362
|
notice.innerHTML = `
|
|
333
363
|
<a href="${currentURL}" target="_self" rel="noopener noreferrer">
|
|
334
364
|
本站为官方备用站,仅供应急。点击移步主站<br>${originalURL}
|
|
335
365
|
</a>
|
|
336
|
-
${canonical.closeEnable ? '<button id="canonical-close">' + canonical.closeText || '关闭提示' + '</button>' : ''}
|
|
337
366
|
`;
|
|
338
367
|
} else {
|
|
339
368
|
notice.className = 'canonical-tip unofficial';
|
|
@@ -346,16 +375,8 @@ const init = {
|
|
|
346
375
|
`;
|
|
347
376
|
}
|
|
348
377
|
document.body.appendChild(notice);
|
|
349
|
-
const closeBtn = notice.querySelector('#canonical-close');
|
|
350
|
-
if (closeBtn) {
|
|
351
|
-
closeBtn.addEventListener('click', function () {
|
|
352
|
-
window.localStorage.setItem('Stellar.canonical.closeEnable', "true")
|
|
353
|
-
window.localStorage.setItem('Stellar.canonical.closeTime', new Date().toDateString())
|
|
354
|
-
notice.style.display = 'none';
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
378
|
}
|
|
358
|
-
if (!
|
|
379
|
+
if (!getOriginalHost()) return;
|
|
359
380
|
const currentURL = new URL(window.location.href);
|
|
360
381
|
const currentHost = currentURL.hostname.replace(/^www\./, '');
|
|
361
382
|
if (currentHost == 'localhost') return;
|
|
@@ -395,6 +416,7 @@ window.stellar = window.stellar || {};
|
|
|
395
416
|
stellar.initPage = function () {
|
|
396
417
|
init.toc();
|
|
397
418
|
init.sidebar();
|
|
419
|
+
init.wikiStart();
|
|
398
420
|
init.leftbarScroll();
|
|
399
421
|
init.relativeDate(document.querySelectorAll('#post-meta time'));
|
|
400
422
|
init.registerTabsTag();
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
let user = memos.users.find(user => user.id === parseInt(creatorId));
|
|
49
49
|
if (!user) {
|
|
50
50
|
if (!memos.requests[creatorId]) {
|
|
51
|
-
|
|
51
|
+
// 走统一请求入口,用户详情同样纳入本地缓存(service: memos-user)
|
|
52
|
+
memos.requests[creatorId] = utils.requestWithoutLoading(`${memos.site}/api/v1/users/${creatorId}`, { service: 'memos-user' })
|
|
52
53
|
.then(response => response.json())
|
|
53
54
|
.then(data => {
|
|
54
55
|
if (data.username) {
|
|
@@ -58,6 +59,10 @@
|
|
|
58
59
|
user = null;
|
|
59
60
|
}
|
|
60
61
|
})
|
|
62
|
+
.catch(() => {
|
|
63
|
+
// 用户详情失败时回退默认昵称/头像,不阻塞 memo 渲染
|
|
64
|
+
user = null;
|
|
65
|
+
})
|
|
61
66
|
.finally(() => delete memos.requests[creatorId]);
|
|
62
67
|
}
|
|
63
68
|
await memos.requests[creatorId];
|
|
@@ -78,7 +83,8 @@
|
|
|
78
83
|
let user = memos.users.find(user => user.name.split('/')[1] === creatorId);
|
|
79
84
|
if (!user) {
|
|
80
85
|
if (!memos.requests[creatorId]) {
|
|
81
|
-
|
|
86
|
+
// 走统一请求入口,用户详情同样纳入本地缓存(service: memos-user)
|
|
87
|
+
memos.requests[creatorId] = utils.requestWithoutLoading(`${memos.site}/api/v1/users/${creatorId}`, { service: 'memos-user' })
|
|
82
88
|
.then(response => response.json())
|
|
83
89
|
.then(data => {
|
|
84
90
|
if (data.username) {
|
|
@@ -88,12 +94,15 @@
|
|
|
88
94
|
user = null;
|
|
89
95
|
}
|
|
90
96
|
})
|
|
97
|
+
.catch(() => {
|
|
98
|
+
// 用户详情失败时回退默认昵称/头像,不阻塞 memo 渲染
|
|
99
|
+
user = null;
|
|
100
|
+
})
|
|
91
101
|
.finally(() => delete memos.requests[creatorId]);
|
|
92
102
|
}
|
|
93
103
|
await memos.requests[creatorId];
|
|
94
104
|
user = memos.users.find(user => user.name.split('/')[1] === creatorId);
|
|
95
105
|
}
|
|
96
|
-
console.log(JSON.stringify(user));
|
|
97
106
|
const name = user ? user.displayName || user.username : 'memos';
|
|
98
107
|
const avatarUrl = user?.avatarUrl ? `${memos.site}${user.avatarUrl}` : default_avatar || '';
|
|
99
108
|
return `<div class="user-info">${avatarUrl ? `<img src="${avatarUrl}">` : ''}<span>${name}</span></div>`;
|