hexo-theme-stellar 1.40.0 → 1.42.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 +1 -2
- package/CHANGELOG.md +90 -0
- package/CONTRIBUTING.md +2 -1
- package/README.md +50 -21
- package/README_EN.md +113 -0
- package/_config.yml +40 -12
- package/_data/icons.yml +248 -37
- package/languages/en.yml +6 -0
- package/languages/zh-CN.yml +6 -0
- package/languages/zh-TW.yml +6 -0
- package/layout/_partial/comments/artalk/script.ejs +25 -8
- package/layout/_partial/comments/beaudar/script.ejs +1 -0
- package/layout/_partial/comments/twikoo/script.ejs +1 -0
- package/layout/_partial/comments/utterances/script.ejs +1 -0
- package/layout/_partial/comments/waline/script.ejs +1 -0
- package/layout/_partial/cover/index.ejs +0 -3
- package/layout/_partial/head.ejs +43 -7
- package/layout/_partial/main/article/article_tags.ejs +16 -0
- package/layout/_partial/main/navbar/article_banner.ejs +33 -20
- package/layout/_partial/main/notebook/note_card.ejs +1 -1
- package/layout/_partial/main/notebook/paginator.ejs +2 -2
- package/layout/_partial/main/pin_slider.ejs +61 -30
- package/layout/_partial/main/post_list/latest_post_card.ejs +25 -0
- package/layout/_partial/main/post_list/paginator.ejs +2 -2
- package/layout/_partial/main/post_list/post_card.ejs +16 -64
- package/layout/_partial/main/post_list/topic_card.ejs +26 -5
- package/layout/_partial/menubtn.ejs +2 -2
- package/layout/_partial/scripts/bootstrap.ejs +35 -0
- package/layout/_partial/scripts/defines.ejs +27 -2
- package/layout/_partial/scripts.ejs +39 -7
- package/layout/_partial/sidebar/logo.ejs +1 -1
- package/layout/_partial/sidebar/menu.ejs +1 -1
- package/layout/_partial/sidebar/search.ejs +1 -1
- package/layout/_partial/widgets/author.ejs +1 -1
- package/layout/_partial/widgets/components/link.ejs +2 -2
- package/layout/_partial/widgets/ghuser.ejs +1 -1
- package/layout/_partial/widgets/related.ejs +1 -1
- package/layout/_partial/widgets/toc.ejs +3 -3
- package/layout/_partial/widgets/tree.ejs +1 -1
- package/layout/_plugins/adaptive_text.ejs +11 -0
- package/layout/_plugins/copycode.ejs +2 -2
- package/layout/_plugins/fancybox.ejs +4 -2
- package/layout/_plugins/mermaid.ejs +3 -2
- package/layout/_plugins/scrollreveal.ejs +22 -16
- package/layout/_plugins/search/local_search.ejs +4 -3
- package/layout/_plugins/swiper.ejs +2 -1
- package/layout/categories.ejs +1 -1
- package/layout/index.ejs +10 -2
- package/layout/index_topic.ejs +4 -4
- package/layout/page.ejs +3 -0
- package/layout/tags.ejs +1 -0
- package/package.json +3 -3
- package/scripts/events/lib/doc_tree.js +12 -208
- package/scripts/events/lib/notebooks.js +8 -148
- package/scripts/events/lib/utils.js +10 -1
- package/scripts/filters/index.js +1 -0
- package/scripts/filters/lib/img_lazyload.js +4 -0
- package/scripts/filters/lib/img_onerror.js +4 -0
- package/scripts/filters/lib/md_table.js +46 -0
- package/scripts/generators/search.js +12 -18
- package/scripts/generators/stellar-icons.js +47 -0
- package/scripts/helpers/ai_label.js +29 -0
- package/scripts/helpers/icon.js +2 -2
- package/scripts/helpers/json_ld.js +10 -13
- package/scripts/helpers/related_posts.js +0 -7
- package/scripts/helpers/seo.js +9 -0
- package/scripts/helpers/subtitle.js +8 -0
- package/scripts/lib/ai_label.js +55 -0
- package/scripts/lib/doc_tree.js +267 -0
- package/scripts/lib/notebooks.js +181 -0
- package/scripts/lib/search_index.js +82 -0
- package/scripts/lib/seo.js +79 -0
- package/scripts/lib/subtitle.js +24 -0
- package/scripts/tags/lib/about.js +2 -2
- package/scripts/tags/lib/albums.js +1 -1
- package/scripts/tags/lib/banner.js +5 -4
- package/scripts/tags/lib/chat.js +49 -49
- package/scripts/tags/lib/copy.js +1 -1
- package/scripts/tags/lib/friends.js +1 -1
- package/scripts/tags/lib/gallery.js +1 -1
- package/scripts/tags/lib/hashtag.js +1 -1
- package/scripts/tags/lib/image.js +3 -3
- package/scripts/tags/lib/posters.js +1 -1
- package/scripts/tags/lib/sites.js +2 -2
- package/source/css/_common/base.styl +5 -9
- package/source/css/_common/cover-overlay.styl +111 -0
- package/source/css/_common/device.styl +3 -3
- package/source/css/_common/title.styl +17 -0
- package/source/css/_components/layout.styl +9 -13
- package/source/css/_components/list.styl +135 -64
- package/source/css/_components/main.styl +2 -2
- package/source/css/_components/md-table.styl +23 -0
- package/source/css/_components/pages/archives.styl +5 -22
- package/source/css/_components/pages/article-story.styl +5 -14
- package/source/css/_components/partial/article-banner.styl +61 -37
- package/source/css/_components/partial/article-tags.styl +13 -0
- package/source/css/_components/partial/bread-nav.styl +19 -12
- package/source/css/_components/partial/navbar.styl +11 -3
- package/source/css/_components/partial/post-panel.styl +76 -0
- package/source/css/_components/pin-slider.styl +38 -41
- package/source/css/_components/sidebar/footer.styl +1 -1
- package/source/css/_components/sidebar/logo.styl +2 -2
- package/source/css/_components/sidebar/search.styl +25 -5
- package/source/css/_components/sidebar/sidebar.styl +7 -7
- package/source/css/_components/tag-plugins/banner.styl +53 -11
- package/source/css/_components/tag-plugins/friends_posts.styl +5 -86
- package/source/css/_components/tag-plugins/gallery.styl +3 -0
- package/source/css/_components/tag-plugins/read/paper.styl +3 -3
- package/source/css/_components/tag-plugins/read/reel.styl +4 -4
- package/source/css/_components/tag-plugins/table.styl +16 -11
- package/source/css/_components/tag-plugins/timeline.styl +4 -0
- package/source/css/_components/widgets/components.styl +6 -0
- package/source/css/_components/widgets/list.styl +6 -0
- package/source/css/_components/widgets/timeline.styl +2 -2
- package/source/css/_components/widgets/toc.styl +13 -7
- package/source/css/_components/widgets/widgets.styl +8 -7
- package/source/css/_custom.styl +9 -21
- package/source/css/_defines/func.styl +28 -3
- package/source/css/_plugins/index.styl +0 -18
- package/source/css/_plugins/lazyload.styl +1 -0
- package/source/css/{_plugins/comments → comments}/artalk.styl +4 -0
- package/source/css/{_plugins/comments → comments}/twikoo.styl +4 -0
- package/source/css/{_plugins → plugins}/mermaid.styl +3 -0
- package/source/css/{_plugins → plugins}/swiper.styl +5 -1
- package/source/js/color.js +325 -0
- package/source/js/icons.js +60 -0
- package/source/js/main.js +115 -1
- package/source/js/plugins/adaptive-text.js +146 -0
- package/source/js/search/highlight.js +82 -0
- package/source/js/search/local-search.js +294 -103
- package/source/js/services/friends_and_posts.js +1 -1
- package/source/js/services/timeline.js +1 -1
- package/source/js/services/weibo.js +3 -3
- package/source/js/services.js +179 -0
- package/source/js/tagtree.js +29 -0
- package/source/js/theme.js +61 -0
- package/{layout/_partial/scripts/utils.ejs → source/js/utils.js} +27 -11
- package/layout/_partial/cover/post_cover.ejs +0 -37
- package/layout/_partial/scripts/services.ejs +0 -178
- package/layout/_partial/scripts/sidebar.ejs +0 -25
- package/layout/_partial/scripts/tagtree.ejs +0 -29
- package/layout/_partial/scripts/theme.ejs +0 -67
- /package/source/css/{_plugins/comments → comments}/beaudar.styl +0 -0
- /package/source/css/{_plugins/comments → comments}/utterances.styl +0 -0
- /package/source/css/{_plugins/comments → comments}/waline.styl +0 -0
- /package/source/css/{_plugins → plugins}/fancybox.styl +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
@import '../_defines/const'
|
|
2
|
+
@import '../_custom'
|
|
3
|
+
@import '../_defines/func'
|
|
4
|
+
|
|
1
5
|
:root
|
|
2
6
|
--swiper-theme-color: var(--theme) !important
|
|
3
7
|
.swiper
|
|
@@ -53,4 +57,4 @@ div.swiper-slide
|
|
|
53
57
|
transform: translateX(-1px)
|
|
54
58
|
|
|
55
59
|
.swiper-button-next:after
|
|
56
|
-
transform: translateX(1px)
|
|
60
|
+
transform: translateX(1px)
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
// 文字自适应颜色通用能力(挂载 window.stellar.color)
|
|
2
|
+
// 由 layout/_plugins/adaptive-text.ejs 按需懒加载;也可供其他组件直接调用。
|
|
3
|
+
// 样式1(contrast):背景深色 → 白色文字,背景浅色 → 深色文字。
|
|
4
|
+
// 样式2(theme):以背景图平均色为基色,背景偏暗 → lighten 到高亮度,
|
|
5
|
+
// 背景偏亮 → darken 到低亮度(保留色相与饱和度)。
|
|
6
|
+
(function () {
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var color = {};
|
|
10
|
+
|
|
11
|
+
// 颜色字符串 → {r,g,b,a}(a 为 0~1 透明度,默认 1);
|
|
12
|
+
// 支持 #rgb/#rrggbb/#rrggbbaa、rgb()/rgba()、hsl()/hsla()(逗号与空格/斜杠语法)。
|
|
13
|
+
// 解析失败返回 null。
|
|
14
|
+
color.parse = function (input) {
|
|
15
|
+
if (input == null) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
var str = String(input).trim();
|
|
19
|
+
var a = 1;
|
|
20
|
+
if (str.charAt(0) === '#') {
|
|
21
|
+
var hex = str.slice(1);
|
|
22
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
23
|
+
hex = hex.split('').map(function (c) {
|
|
24
|
+
return c + c;
|
|
25
|
+
}).join('');
|
|
26
|
+
}
|
|
27
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
28
|
+
var r = parseInt(hex.slice(0, 2), 16);
|
|
29
|
+
var g = parseInt(hex.slice(2, 4), 16);
|
|
30
|
+
var b = parseInt(hex.slice(4, 6), 16);
|
|
31
|
+
if (hex.length === 8) {
|
|
32
|
+
a = parseInt(hex.slice(6, 8), 16) / 255;
|
|
33
|
+
}
|
|
34
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
|
|
35
|
+
return { r: r, g: g, b: b, a: a };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
var m = str.match(/rgba?\(\s*([\d.]+)\s*[,\s]\s*([\d.]+)\s*[,\s]\s*([\d.]+)(?:\s*[,\s/]\s*([\d.]+%?))?\s*\)/i);
|
|
41
|
+
if (m) {
|
|
42
|
+
var r2 = Number(m[1]);
|
|
43
|
+
var g2 = Number(m[2]);
|
|
44
|
+
var b2 = Number(m[3]);
|
|
45
|
+
if (!isNaN(r2) && !isNaN(g2) && !isNaN(b2)) {
|
|
46
|
+
if (m[4] != null) {
|
|
47
|
+
a = m[4].charAt(m[4].length - 1) === '%' ? Number(m[4].slice(0, -1)) / 100 : Number(m[4]);
|
|
48
|
+
}
|
|
49
|
+
return { r: r2, g: g2, b: b2, a: a };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
var hm = str.match(/hsla?\(\s*([\d.]+)(?:deg)?\s*[,\s]\s*([\d.]+%?)\s*[,\s]\s*([\d.]+%?)(?:\s*[,\s/]\s*([\d.]+%?))?\s*\)/i);
|
|
53
|
+
if (hm) {
|
|
54
|
+
var hue = Number(hm[1]);
|
|
55
|
+
var sat = hm[2].charAt(hm[2].length - 1) === '%' ? Number(hm[2].slice(0, -1)) / 100 : Number(hm[2]);
|
|
56
|
+
var lig = hm[3].charAt(hm[3].length - 1) === '%' ? Number(hm[3].slice(0, -1)) / 100 : Number(hm[3]);
|
|
57
|
+
if (!isNaN(hue) && !isNaN(sat) && !isNaN(lig)) {
|
|
58
|
+
if (hm[4] != null) {
|
|
59
|
+
a = hm[4].charAt(hm[4].length - 1) === '%' ? Number(hm[4].slice(0, -1)) / 100 : Number(hm[4]);
|
|
60
|
+
}
|
|
61
|
+
var h = ((hue % 360) + 360) % 360 / 360;
|
|
62
|
+
var rgb = hslToRgb(h, Math.max(0, Math.min(1, sat)), Math.max(0, Math.min(1, lig)));
|
|
63
|
+
return { r: rgb.r, g: rgb.g, b: rgb.b, a: a };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// WCAG 相对亮度(0~1)
|
|
70
|
+
color.luminance = function (rgb) {
|
|
71
|
+
if (rgb == null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
var linearize = function (v) {
|
|
75
|
+
v = v / 255;
|
|
76
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
77
|
+
};
|
|
78
|
+
return 0.2126 * linearize(rgb.r) + 0.7152 * linearize(rgb.g) + 0.0722 * linearize(rgb.b);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// 亮度是否偏暗,threshold 默认 0.5
|
|
82
|
+
color.isDark = function (rgb, threshold) {
|
|
83
|
+
var lum = color.luminance(rgb);
|
|
84
|
+
if (lum == null) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return lum < (threshold == null ? 0.5 : threshold);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
function rgbToHsl(rgb) {
|
|
91
|
+
var r = rgb.r / 255;
|
|
92
|
+
var g = rgb.g / 255;
|
|
93
|
+
var b = rgb.b / 255;
|
|
94
|
+
var max = Math.max(r, g, b);
|
|
95
|
+
var min = Math.min(r, g, b);
|
|
96
|
+
var h = 0;
|
|
97
|
+
var s = 0;
|
|
98
|
+
var l = (max + min) / 2;
|
|
99
|
+
if (max !== min) {
|
|
100
|
+
var d = max - min;
|
|
101
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
102
|
+
switch (max) {
|
|
103
|
+
case r:
|
|
104
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
105
|
+
break;
|
|
106
|
+
case g:
|
|
107
|
+
h = (b - r) / d + 2;
|
|
108
|
+
break;
|
|
109
|
+
default:
|
|
110
|
+
h = (r - g) / d + 4;
|
|
111
|
+
}
|
|
112
|
+
h /= 6;
|
|
113
|
+
}
|
|
114
|
+
return { h: h, s: s, l: l };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function hslToRgb(h, s, l) {
|
|
118
|
+
if (s === 0) {
|
|
119
|
+
var gray = Math.round(l * 255);
|
|
120
|
+
return { r: gray, g: gray, b: gray };
|
|
121
|
+
}
|
|
122
|
+
var hue2rgb = function (p, q, t) {
|
|
123
|
+
if (t < 0) {
|
|
124
|
+
t += 1;
|
|
125
|
+
}
|
|
126
|
+
if (t > 1) {
|
|
127
|
+
t -= 1;
|
|
128
|
+
}
|
|
129
|
+
if (t < 1 / 6) {
|
|
130
|
+
return p + (q - p) * 6 * t;
|
|
131
|
+
}
|
|
132
|
+
if (t < 1 / 2) {
|
|
133
|
+
return q;
|
|
134
|
+
}
|
|
135
|
+
if (t < 2 / 3) {
|
|
136
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
137
|
+
}
|
|
138
|
+
return p;
|
|
139
|
+
};
|
|
140
|
+
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
141
|
+
var p = 2 * l - q;
|
|
142
|
+
return {
|
|
143
|
+
r: Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
|
|
144
|
+
g: Math.round(hue2rgb(p, q, h) * 255),
|
|
145
|
+
b: Math.round(hue2rgb(p, q, h - 1 / 3) * 255)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function rgbString(rgb) {
|
|
150
|
+
return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 设定 HSL 明度目标(0~1),保留色相与饱和度
|
|
154
|
+
color.withLightness = function (rgb, lightness) {
|
|
155
|
+
if (rgb == null) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
var hsl = rgbToHsl(rgb);
|
|
159
|
+
var target = Math.max(0, Math.min(1, lightness));
|
|
160
|
+
return rgbString(hslToRgb(hsl.h, hsl.s, target));
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 浅色化:把明度调整到 lightness(默认 0.85)
|
|
164
|
+
color.lighten = function (rgb, lightness) {
|
|
165
|
+
return color.withLightness(rgb, lightness == null ? 0.85 : lightness);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// 深色化:把明度调整到 lightness(默认 0.3)
|
|
169
|
+
color.darken = function (rgb, lightness) {
|
|
170
|
+
return color.withLightness(rgb, lightness == null ? 0.3 : lightness);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// 主题色饱和度增强:平均色被大面积中性色盖过时饱和度极低(色相仍有效),
|
|
174
|
+
// 把低饱和度抬升到最低可见值(保留色相),让主题文字带出图片的主色倾向;
|
|
175
|
+
// 完全中性(无可靠色相)与已足够饱和的颜色不做处理。
|
|
176
|
+
color.enhanceSaturation = function (rgb, options) {
|
|
177
|
+
if (rgb == null) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
var opts = options || {};
|
|
181
|
+
var minS = opts.minSaturation == null ? 0.3 : opts.minSaturation;
|
|
182
|
+
var boostBelow = opts.boostBelow == null ? 0.2 : opts.boostBelow;
|
|
183
|
+
var epsilon = opts.neutralEpsilon == null ? 0.02 : opts.neutralEpsilon;
|
|
184
|
+
var hsl = rgbToHsl(rgb);
|
|
185
|
+
if (hsl.s >= boostBelow || hsl.s < epsilon) {
|
|
186
|
+
return { r: rgb.r, g: rgb.g, b: rgb.b, a: rgb.a == null ? 1 : rgb.a };
|
|
187
|
+
}
|
|
188
|
+
var out = hslToRgb(hsl.h, Math.max(hsl.s, minS), hsl.l);
|
|
189
|
+
return { r: out.r, g: out.g, b: out.b, a: rgb.a == null ? 1 : rgb.a };
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// 自适应文字颜色
|
|
193
|
+
// bg:{r,g,b} 或颜色字符串
|
|
194
|
+
// options:
|
|
195
|
+
// style 'theme'(默认)/ 'contrast'
|
|
196
|
+
// threshold 明暗判定阈值,默认按 effectiveThreshold(彩色背景 0.65 / 中性背景 0.6,
|
|
197
|
+
// 偏向采纳浅色文字,避免中灰背景频繁翻转)
|
|
198
|
+
// lightColor 样式1 深色背景时的文字色,默认 #ffffff
|
|
199
|
+
// darkColor 样式1 浅色背景时的文字色,默认 #111111
|
|
200
|
+
// lightLightness 样式2 深色背景时的目标明度,默认 0.85
|
|
201
|
+
// darkLightness 样式2 浅色背景时的目标明度,默认 0.3
|
|
202
|
+
// saturationScale 样式2 饱和度缩放(0~1,默认 1):调小更接近黑白,仅保留一点主色倾向
|
|
203
|
+
color.adaptiveTextColor = function (bg, options) {
|
|
204
|
+
var opts = options || {};
|
|
205
|
+
var rgb = (bg != null && typeof bg === 'object') ? bg : color.parse(bg);
|
|
206
|
+
if (rgb == null) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
var style = opts.style || 'theme';
|
|
210
|
+
var threshold = opts.threshold == null ? color.effectiveThreshold(rgb) : opts.threshold;
|
|
211
|
+
var dark = color.isDark(rgb, threshold);
|
|
212
|
+
if (style === 'contrast') {
|
|
213
|
+
return dark ? (opts.lightColor || '#ffffff') : (opts.darkColor || '#111111');
|
|
214
|
+
}
|
|
215
|
+
var base = color.enhanceSaturation(rgb);
|
|
216
|
+
var hsl = rgbToHsl(base);
|
|
217
|
+
if (opts.saturationScale != null) {
|
|
218
|
+
hsl.s = hsl.s * Math.max(0, Math.min(1, opts.saturationScale));
|
|
219
|
+
}
|
|
220
|
+
var target = dark
|
|
221
|
+
? (opts.lightLightness == null ? 0.85 : opts.lightLightness)
|
|
222
|
+
: (opts.darkLightness == null ? 0.3 : opts.darkLightness);
|
|
223
|
+
return rgbString(hslToRgb(hsl.h, hsl.s, target));
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// 有效明暗阈值:彩色背景(饱和度 > 0.2)更偏向浅色文字,阈值上浮 0.05;
|
|
227
|
+
// 中性灰背景保持基础阈值,避免浅灰图配浅字。
|
|
228
|
+
color.effectiveThreshold = function (rgb, base) {
|
|
229
|
+
var threshold = base == null ? 0.6 : base;
|
|
230
|
+
var hsl = rgbToHsl(rgb);
|
|
231
|
+
return hsl.s > 0.2 ? threshold + 0.05 : threshold;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// 按平均透明度向背景色混合:透明像素不再把平均色拉向黑色,
|
|
235
|
+
// 而是按实际渲染背景合成(options.background 为 {r,g,b} 或颜色字符串)。
|
|
236
|
+
// 不传背景或完全不透明时返回原 RGB。
|
|
237
|
+
color.blendToBackground = function (rgb, background) {
|
|
238
|
+
if (rgb == null) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
var alpha = rgb.a == null ? 255 : rgb.a;
|
|
242
|
+
if (!background || alpha >= 255) {
|
|
243
|
+
return { r: rgb.r, g: rgb.g, b: rgb.b };
|
|
244
|
+
}
|
|
245
|
+
var bgRgb = (background != null && typeof background === 'object') ? background : color.parse(background);
|
|
246
|
+
if (bgRgb == null) {
|
|
247
|
+
return { r: rgb.r, g: rgb.g, b: rgb.b };
|
|
248
|
+
}
|
|
249
|
+
var k = alpha / 255;
|
|
250
|
+
var inv = 1 - k;
|
|
251
|
+
return {
|
|
252
|
+
r: Math.round(rgb.r * k + bgRgb.r * inv),
|
|
253
|
+
g: Math.round(rgb.g * k + bgRgb.g * inv),
|
|
254
|
+
b: Math.round(rgb.b * k + bgRgb.b * inv)
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// 背景图平均色:等比缩至最长边 ≤ size(默认 64px)后 canvas 取 RGB 均值与平均透明度。
|
|
259
|
+
// 按 URL 缓存原始均值(含透明度);CORS、解码失败等异常返回 null(由调用方回退 CSS 默认色)。
|
|
260
|
+
var averageCache = {};
|
|
261
|
+
|
|
262
|
+
color.getAverageColor = function (src, options) {
|
|
263
|
+
var opts = options || {};
|
|
264
|
+
var size = opts.size || 64;
|
|
265
|
+
if (averageCache[src]) {
|
|
266
|
+
return averageCache[src].then(function (raw) {
|
|
267
|
+
return color.blendToBackground(raw, opts.background);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
var promise = new Promise(function (resolve) {
|
|
271
|
+
var img = new Image();
|
|
272
|
+
img.crossOrigin = 'anonymous';
|
|
273
|
+
img.onload = function () {
|
|
274
|
+
try {
|
|
275
|
+
var w = img.naturalWidth || img.width;
|
|
276
|
+
var h = img.naturalHeight || img.height;
|
|
277
|
+
if (!w || !h) {
|
|
278
|
+
resolve(null);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
var scale = Math.min(1, size / Math.max(w, h));
|
|
282
|
+
var cw = Math.max(1, Math.round(w * scale));
|
|
283
|
+
var ch = Math.max(1, Math.round(h * scale));
|
|
284
|
+
var canvas = document.createElement('canvas');
|
|
285
|
+
canvas.width = cw;
|
|
286
|
+
canvas.height = ch;
|
|
287
|
+
var ctx = canvas.getContext('2d');
|
|
288
|
+
ctx.drawImage(img, 0, 0, cw, ch);
|
|
289
|
+
var data = ctx.getImageData(0, 0, cw, ch).data;
|
|
290
|
+
var total = cw * ch;
|
|
291
|
+
var r = 0;
|
|
292
|
+
var g = 0;
|
|
293
|
+
var b = 0;
|
|
294
|
+
var a = 0;
|
|
295
|
+
for (var i = 0; i < data.length; i += 4) {
|
|
296
|
+
r += data[i];
|
|
297
|
+
g += data[i + 1];
|
|
298
|
+
b += data[i + 2];
|
|
299
|
+
a += data[i + 3];
|
|
300
|
+
}
|
|
301
|
+
resolve({
|
|
302
|
+
r: Math.round(r / total),
|
|
303
|
+
g: Math.round(g / total),
|
|
304
|
+
b: Math.round(b / total),
|
|
305
|
+
a: Math.round(a / total)
|
|
306
|
+
});
|
|
307
|
+
} catch (e) {
|
|
308
|
+
resolve(null);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
img.onerror = function () {
|
|
312
|
+
resolve(null);
|
|
313
|
+
};
|
|
314
|
+
img.src = src;
|
|
315
|
+
});
|
|
316
|
+
averageCache[src] = promise;
|
|
317
|
+
return promise.then(function (raw) {
|
|
318
|
+
return color.blendToBackground(raw, opts.background);
|
|
319
|
+
});
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
var root = typeof window !== 'undefined' ? window : {};
|
|
323
|
+
root.stellar = root.stellar || {};
|
|
324
|
+
root.stellar.color = color;
|
|
325
|
+
})();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* icons.js | 非首屏图标异步加载
|
|
3
|
+
*
|
|
4
|
+
* 服务端 icon() 对非首屏 SVG 图标输出 <svg class="icon" data-icon="ns:key"> 占位符,
|
|
5
|
+
* 本脚本按命名空间拉取构建期生成的 js/icons/{ns}.json,成功后原位替换为完整内联 SVG,
|
|
6
|
+
* 最终 DOM 与全量内联一致,现有 CSS 钩子(搜索三态、菜单渐变、chat 着色等)不受影响。
|
|
7
|
+
* 首屏关键图标(搜索、菜单、leftbar/rightbar、goback)由模板内联,不经过本脚本。
|
|
8
|
+
*/
|
|
9
|
+
(function () {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const nodes = Array.prototype.slice.call(document.querySelectorAll('svg.icon[data-icon]'));
|
|
13
|
+
if (nodes.length === 0) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const groups = {};
|
|
18
|
+
nodes.forEach((node) => {
|
|
19
|
+
const key = node.getAttribute('data-icon');
|
|
20
|
+
const idx = key.indexOf(':');
|
|
21
|
+
if (idx < 1) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const ns = key.slice(0, idx);
|
|
25
|
+
if (!groups[ns]) {
|
|
26
|
+
groups[ns] = [];
|
|
27
|
+
}
|
|
28
|
+
groups[ns].push(node);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const script = document.currentScript;
|
|
32
|
+
const version = (script && script.getAttribute('data-version')) || '';
|
|
33
|
+
const root = (typeof ctx !== 'undefined' && ctx.root) || '/';
|
|
34
|
+
|
|
35
|
+
Object.keys(groups).forEach((ns) => {
|
|
36
|
+
const url = root + 'js/icons/' + ns + '.json' + (version ? '?v=' + version : '');
|
|
37
|
+
fetch(url)
|
|
38
|
+
.then((res) => {
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
throw new Error('HTTP ' + res.status);
|
|
41
|
+
}
|
|
42
|
+
return res.json();
|
|
43
|
+
})
|
|
44
|
+
.then((data) => {
|
|
45
|
+
const set = data && data[ns];
|
|
46
|
+
groups[ns].forEach((node) => {
|
|
47
|
+
const key = node.getAttribute('data-icon');
|
|
48
|
+
const svg = set && set[key];
|
|
49
|
+
if (typeof svg === 'string' && svg.length > 0) {
|
|
50
|
+
node.outerHTML = svg;
|
|
51
|
+
} else {
|
|
52
|
+
console.warn('[stellar] icon not found: ' + key);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
})
|
|
56
|
+
.catch((err) => {
|
|
57
|
+
console.warn('[stellar] icons load failed: ' + ns, err);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
})();
|
package/source/js/main.js
CHANGED
|
@@ -97,6 +97,30 @@ const hud = {
|
|
|
97
97
|
|
|
98
98
|
const l_body = document.querySelector('.l_body');
|
|
99
99
|
|
|
100
|
+
const sidebar = {
|
|
101
|
+
leftbar: () => {
|
|
102
|
+
if (l_body) {
|
|
103
|
+
l_body.toggleAttribute('leftbar');
|
|
104
|
+
l_body.removeAttribute('rightbar');
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
rightbar: () => {
|
|
108
|
+
if (l_body) {
|
|
109
|
+
l_body.toggleAttribute('rightbar');
|
|
110
|
+
l_body.removeAttribute('leftbar');
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
dismiss: () => {
|
|
114
|
+
if (l_body) {
|
|
115
|
+
l_body.removeAttribute('leftbar');
|
|
116
|
+
l_body.removeAttribute('rightbar');
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
toggleTOC: () => {
|
|
120
|
+
document.querySelector('#data-toc').classList.toggle('collapse');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
// 通用平滑滚动(自定义动画,TOC / 回到顶部 / 参与讨论共用)
|
|
101
125
|
let scrollAnim = null;
|
|
102
126
|
function cancelSmoothScroll() {
|
|
@@ -217,6 +241,40 @@ function bindTocClick(widget) {
|
|
|
217
241
|
});
|
|
218
242
|
}
|
|
219
243
|
|
|
244
|
+
// 通用页内锚点平滑滚动(标题左侧 headerlink、{% navbar %} 页内导航、脚注回链等)
|
|
245
|
+
// 已被其他处理器拦截的点击(TOC、tabs、wiki #start 等)通过 defaultPrevented 跳过,避免重复滚动
|
|
246
|
+
function bindAnchorClick() {
|
|
247
|
+
document.addEventListener('click', function (e) {
|
|
248
|
+
const link = e.target.closest('a[href^="#"]');
|
|
249
|
+
if (!link || e.defaultPrevented) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const href = link.getAttribute('href');
|
|
253
|
+
if (!href || href.indexOf('#') !== 0) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
let id = href.slice(1);
|
|
257
|
+
try {
|
|
258
|
+
id = decodeURIComponent(id);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
// 片段含非法编码时按原样查找
|
|
261
|
+
}
|
|
262
|
+
const target = id && document.getElementById(id);
|
|
263
|
+
if (!target) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
e.preventDefault();
|
|
267
|
+
// #start 锚点贴顶滚动,不预留 offset;其余锚点与 TOC 点击滚动保持一致(32px)
|
|
268
|
+
const offset = id === 'start' ? 0 : 32;
|
|
269
|
+
const targetY = target.getBoundingClientRect().top + window.scrollY - offset;
|
|
270
|
+
smoothScrollTo(targetY);
|
|
271
|
+
if (window.history && window.history.pushState) {
|
|
272
|
+
window.history.pushState(null, '', href);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
bindAnchorClick();
|
|
277
|
+
|
|
220
278
|
// 远程 md 渲染完成后由页面层重建右栏 TOC
|
|
221
279
|
document.addEventListener('stellar:mdrender', function (e) {
|
|
222
280
|
rebuildToc(e.detail && e.detail.target);
|
|
@@ -295,7 +353,7 @@ const init = {
|
|
|
295
353
|
window.history.pushState(null, "", href);
|
|
296
354
|
}
|
|
297
355
|
}
|
|
298
|
-
sidebar.dismiss();
|
|
356
|
+
window.sidebar.dismiss();
|
|
299
357
|
});
|
|
300
358
|
},
|
|
301
359
|
wikiStart: () => {
|
|
@@ -367,6 +425,61 @@ const init = {
|
|
|
367
425
|
}
|
|
368
426
|
} catch (e) {}
|
|
369
427
|
},
|
|
428
|
+
navbarPin: () => {
|
|
429
|
+
// 列表页 navbar top 背景条状态切换:未吸顶为卡片样式(var(--card) + 文章卡片同款阴影),
|
|
430
|
+
// 吸顶后恢复玻璃效果。在吸顶边界切换 .pinned 类,视觉由 CSS 控制。
|
|
431
|
+
// 吸顶判定直接测 navbar 的实际视口位置,而非用 scrollY 推算:
|
|
432
|
+
// 移动端浏览器顶栏伸缩会改变 scrollY(展开顶栏时 scrollY 减小),
|
|
433
|
+
// 即使 navbar 仍吸顶也可能跌破阈值,导致玻璃效果误消失。
|
|
434
|
+
const navbars = document.querySelectorAll('.navbar.top');
|
|
435
|
+
if (navbars.length === 0) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
// 视口顶部允许的偏差(px),吸收亚像素/取整误差
|
|
439
|
+
const TOLERANCE = 2;
|
|
440
|
+
let states = [];
|
|
441
|
+
function update() {
|
|
442
|
+
states.forEach((state) => {
|
|
443
|
+
const top = state.navbar.getBoundingClientRect().top;
|
|
444
|
+
state.bar.classList.toggle('pinned', top <= state.stickyTop + TOLERANCE);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
function measure() {
|
|
448
|
+
states = [];
|
|
449
|
+
navbars.forEach((navbar) => {
|
|
450
|
+
const bar = navbar.querySelector('.navbar-blur');
|
|
451
|
+
if (bar == null) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// getComputedStyle().top 自动兼容桌面 var(--gap-page) 与移动端 8pt
|
|
455
|
+
const stickyTop = parseFloat(getComputedStyle(navbar).top) || 16;
|
|
456
|
+
states.push({
|
|
457
|
+
navbar: navbar,
|
|
458
|
+
bar: bar,
|
|
459
|
+
stickyTop: stickyTop
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
update();
|
|
463
|
+
}
|
|
464
|
+
let ticking = false;
|
|
465
|
+
window.addEventListener('scroll', () => {
|
|
466
|
+
if (ticking) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
ticking = true;
|
|
470
|
+
utils.requestAnimationFrame(() => {
|
|
471
|
+
update();
|
|
472
|
+
ticking = false;
|
|
473
|
+
});
|
|
474
|
+
}, { passive: true });
|
|
475
|
+
// 顶栏伸缩不一定触发 scroll,兜底监听 visualViewport 尺寸变化
|
|
476
|
+
if (window.visualViewport) {
|
|
477
|
+
window.visualViewport.addEventListener('resize', update);
|
|
478
|
+
}
|
|
479
|
+
window.addEventListener('resize', measure);
|
|
480
|
+
window.addEventListener('pageshow', measure);
|
|
481
|
+
measure();
|
|
482
|
+
},
|
|
370
483
|
relativeDate: (selector) => {
|
|
371
484
|
selector.forEach(item => {
|
|
372
485
|
const $this = item
|
|
@@ -509,6 +622,7 @@ stellar.initPage = function () {
|
|
|
509
622
|
init.sidebar();
|
|
510
623
|
init.wikiStart();
|
|
511
624
|
init.leftbarScroll();
|
|
625
|
+
init.navbarPin();
|
|
512
626
|
init.relativeDate(document.querySelectorAll('#post-meta time'));
|
|
513
627
|
init.registerTabsTag();
|
|
514
628
|
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// 文字自适应颜色 DOM 插件
|
|
2
|
+
// 扫描 [data-text-adaptive] 元素,解析背景来源(--cover-url → --bg-url →
|
|
3
|
+
// background-image → background-color),调用 stellar.color 计算文字颜色,
|
|
4
|
+
// 写入内联 --text-banner 与 --text-banner-theme。
|
|
5
|
+
// 属性值:
|
|
6
|
+
// theme(默认) 背景图平均色 lighten/darken(两种变量同色)
|
|
7
|
+
// contrast 黑白对比(两种变量同色)
|
|
8
|
+
// split 大字(标题/headline)用 contrast,小字(caption/subtitle/面包屑等)用 theme
|
|
9
|
+
// 用户显式覆盖优先:元素已有内联 --text-banner 或内联 color 时跳过。
|
|
10
|
+
// 由 layout/_plugins/adaptive-text.ejs 在页面存在目标元素时懒加载。
|
|
11
|
+
|
|
12
|
+
function parseCssUrl(value) {
|
|
13
|
+
if (!value) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
var m = String(value).trim().match(/url\((['"]?)(.*?)\1\)/i);
|
|
17
|
+
return m ? m[2] : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveBackground(el) {
|
|
21
|
+
var style = window.getComputedStyle(el);
|
|
22
|
+
var cover = parseCssUrl(style.getPropertyValue('--cover-url'));
|
|
23
|
+
if (cover) {
|
|
24
|
+
return { type: 'image', url: cover };
|
|
25
|
+
}
|
|
26
|
+
var pinCover = parseCssUrl(style.getPropertyValue('--pin-cover-url'));
|
|
27
|
+
if (pinCover) {
|
|
28
|
+
return { type: 'image', url: pinCover };
|
|
29
|
+
}
|
|
30
|
+
var bg = parseCssUrl(style.getPropertyValue('--bg-url'));
|
|
31
|
+
if (bg) {
|
|
32
|
+
return { type: 'image', url: bg };
|
|
33
|
+
}
|
|
34
|
+
var bgImage = style.backgroundImage;
|
|
35
|
+
if (bgImage && bgImage !== 'none') {
|
|
36
|
+
var url = parseCssUrl(bgImage);
|
|
37
|
+
if (url && url !== 'none') {
|
|
38
|
+
return { type: 'image', url: url };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
var bgColor = style.backgroundColor;
|
|
42
|
+
if (bgColor && bgColor !== 'transparent' && !/rgba\(0,\s*0,\s*0,\s*0\)/.test(bgColor)) {
|
|
43
|
+
var rgb = stellar.color.parse(bgColor);
|
|
44
|
+
if (rgb) {
|
|
45
|
+
return { type: 'color', rgb: rgb };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 解析图片背后的实际背景色(用于透明图的平均色合成):
|
|
52
|
+
// 从元素自身沿祖先向上找第一个不透明 background-color(半透明视为继续向上),
|
|
53
|
+
// 最终兜底到 body 的 var(--background),仍无则白色。
|
|
54
|
+
function resolveBackdrop(el) {
|
|
55
|
+
var node = el;
|
|
56
|
+
while (node && node.nodeType === 1) {
|
|
57
|
+
var rgb = stellar.color.parse(window.getComputedStyle(node).backgroundColor);
|
|
58
|
+
if (rgb && rgb.a >= 1) {
|
|
59
|
+
return { r: rgb.r, g: rgb.g, b: rgb.b };
|
|
60
|
+
}
|
|
61
|
+
node = node.parentElement;
|
|
62
|
+
}
|
|
63
|
+
return { r: 255, g: 255, b: 255 };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 单样式模式:--text-banner 与 --text-banner-theme 取同一颜色,保持容器内文字一致
|
|
67
|
+
function setTextColor(el, styleName, rgb) {
|
|
68
|
+
var result = stellar.color.adaptiveTextColor(rgb, { style: styleName });
|
|
69
|
+
if (result) {
|
|
70
|
+
el.style.setProperty('--text-banner', result);
|
|
71
|
+
el.style.setProperty('--text-banner-theme', result);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// split 模式:大字用低饱和 theme(接近黑白,保留一点主色倾向),小字用完整 theme
|
|
76
|
+
function setSplitTextColors(el, rgb) {
|
|
77
|
+
// 大字更接近黑白:只保留 5% 饱和度(值越大越接近完整主题色,越小越接近黑白,0 为纯灰)
|
|
78
|
+
var large = stellar.color.adaptiveTextColor(rgb, { style: 'theme', saturationScale: 0.05 });
|
|
79
|
+
var theme = stellar.color.adaptiveTextColor(rgb, { style: 'theme' });
|
|
80
|
+
if (large) {
|
|
81
|
+
el.style.setProperty('--text-banner', large);
|
|
82
|
+
}
|
|
83
|
+
if (theme) {
|
|
84
|
+
el.style.setProperty('--text-banner-theme', theme);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function applyToElement(el) {
|
|
89
|
+
// 用户显式覆盖优先:首次处理时元素已有内联 --text-banner 或内联 color 则跳过
|
|
90
|
+
// (插件自身写入的变量不视为用户覆盖,主题切换重算时需重新应用)
|
|
91
|
+
var isFirst = !appliedElements.has(el);
|
|
92
|
+
if (isFirst && (el.style.getPropertyValue('--text-banner') || el.style.color)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
var bg = resolveBackground(el);
|
|
96
|
+
if (!bg) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
var styleName = el.getAttribute('data-text-adaptive') || 'theme';
|
|
100
|
+
var apply = function (rgb) {
|
|
101
|
+
if (styleName === 'split') {
|
|
102
|
+
setSplitTextColors(el, rgb);
|
|
103
|
+
} else {
|
|
104
|
+
setTextColor(el, styleName, rgb);
|
|
105
|
+
}
|
|
106
|
+
appliedElements.add(el);
|
|
107
|
+
};
|
|
108
|
+
if (bg.type === 'color') {
|
|
109
|
+
apply(bg.rgb);
|
|
110
|
+
} else {
|
|
111
|
+
var backdrop = resolveBackdrop(el);
|
|
112
|
+
stellar.color.getAverageColor(bg.url, { background: backdrop }).then(function (rgb) {
|
|
113
|
+
if (rgb) {
|
|
114
|
+
apply(rgb);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var adaptiveTextElements = [];
|
|
121
|
+
var appliedElements = new WeakSet();
|
|
122
|
+
|
|
123
|
+
function applyAdaptiveText(elements) {
|
|
124
|
+
if (!window.stellar || !window.stellar.color || !elements || elements.length === 0) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
adaptiveTextElements = Array.prototype.slice.call(elements);
|
|
128
|
+
for (var i = 0; i < elements.length; i++) {
|
|
129
|
+
applyToElement(elements[i]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 主题明暗切换时重算:透明背景图的合成背景随 data-theme 变化,颜色需重新计算
|
|
134
|
+
if (window.MutationObserver && document.documentElement) {
|
|
135
|
+
new MutationObserver(function () {
|
|
136
|
+
applyAdaptiveText(adaptiveTextElements);
|
|
137
|
+
if (typeof window.refreshPinNavColor === 'function') {
|
|
138
|
+
window.refreshPinNavColor();
|
|
139
|
+
}
|
|
140
|
+
}).observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 供轮播箭头等场景复用:解析元素背后实际渲染背景色
|
|
144
|
+
window.resolveAdaptiveBackdrop = resolveBackdrop;
|
|
145
|
+
|
|
146
|
+
window.applyAdaptiveText = applyAdaptiveText;
|