-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcolor-schema.js
286 lines (256 loc) · 8.79 KB
/
color-schema.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/* global Fluid */
/**
* Modified from https://blog.skk.moe/post/hello-darkmode-my-old-friend/
*/
(function(window, document) {
var rootElement = document.documentElement;
var colorSchemaStorageKey = 'Fluid_Color_Scheme';
var colorSchemaMediaQueryKey = '--color-mode';
var userColorSchemaAttributeName = 'data-user-color-scheme';
var defaultColorSchemaAttributeName = 'data-default-color-scheme';
var colorToggleButtonSelector = '#color-toggle-btn';
var colorToggleIconSelector = '#color-toggle-icon';
var iframeSelector = 'iframe';
function setLS(k, v) {
try {
localStorage.setItem(k, v);
} catch (e) {}
}
function removeLS(k) {
try {
localStorage.removeItem(k);
} catch (e) {}
}
function getLS(k) {
try {
return localStorage.getItem(k);
} catch (e) {
return null;
}
}
function getSchemaFromHTML() {
var res = rootElement.getAttribute(defaultColorSchemaAttributeName);
if (typeof res === 'string') {
return res.replace(/["'\s]/g, '');
}
return null;
}
function getSchemaFromCSSMediaQuery() {
var res = getComputedStyle(rootElement).getPropertyValue(
colorSchemaMediaQueryKey
);
if (typeof res === 'string') {
return res.replace(/["'\s]/g, '');
}
return null;
}
function resetSchemaAttributeAndLS() {
rootElement.setAttribute(userColorSchemaAttributeName, getDefaultColorSchema());
removeLS(colorSchemaStorageKey);
}
var validColorSchemaKeys = {
dark : true,
light: true
};
function getDefaultColorSchema() {
// 取默认字段的值
var schema = getSchemaFromHTML();
// 如果明确指定了 schema 则返回
if (validColorSchemaKeys[schema]) {
return schema;
}
// 默认优先按 prefers-color-scheme
schema = getSchemaFromCSSMediaQuery();
if (validColorSchemaKeys[schema]) {
return schema;
}
// 否则按本地时间是否大于 18 点或凌晨 0 ~ 6 点
var hours = new Date().getHours();
if (hours >= 18 || (hours >= 0 && hours <= 6)) {
return 'dark';
}
return 'light';
}
function applyCustomColorSchemaSettings(schema) {
// 接受从「开关」处传来的模式,或者从 localStorage 读取,否则按默认设置值
var current = schema || getLS(colorSchemaStorageKey) || getDefaultColorSchema();
if (current === getDefaultColorSchema()) {
// 当用户切换的显示模式和默认模式相同时,则恢复为自动模式
resetSchemaAttributeAndLS();
} else if (validColorSchemaKeys[current]) {
rootElement.setAttribute(
userColorSchemaAttributeName,
current
);
} else {
// 特殊情况重置
resetSchemaAttributeAndLS();
return;
}
// 根据当前模式设置图标
setButtonIcon(current);
// 设置代码高亮
setHighlightCSS(current);
// 设置其他应用
setApplications(current);
}
var invertColorSchemaObj = {
dark : 'light',
light: 'dark'
};
function getIconClass(scheme) {
return 'icon-' + scheme;
}
function toggleCustomColorSchema() {
var currentSetting = getLS(colorSchemaStorageKey);
if (validColorSchemaKeys[currentSetting]) {
// 从 localStorage 中读取模式,并取相反的模式
currentSetting = invertColorSchemaObj[currentSetting];
} else if (currentSetting === null) {
// 当 localStorage 中没有相关值,或者 localStorage 抛了 Error
// 先按照按钮的状态进行切换
var iconElement = document.querySelector(colorToggleIconSelector);
if (iconElement) {
currentSetting = iconElement.getAttribute('data');
}
if (!iconElement || !validColorSchemaKeys[currentSetting]) {
// 当 localStorage 中没有相关值,或者 localStorage 抛了 Error,则读取默认值并切换到相反的模式
currentSetting = invertColorSchemaObj[getSchemaFromCSSMediaQuery()];
}
} else {
return;
}
// 将相反的模式写入 localStorage
setLS(colorSchemaStorageKey, currentSetting);
return currentSetting;
}
function setButtonIcon(schema) {
if (validColorSchemaKeys[schema]) {
// 切换图标
var icon = getIconClass('dark');
if (schema) {
icon = getIconClass(schema);
}
var iconElement = document.querySelector(colorToggleIconSelector);
if (iconElement) {
iconElement.setAttribute(
'class',
'iconfont ' + icon
);
iconElement.setAttribute(
'data',
invertColorSchemaObj[schema]
);
} else {
// 如果图标不存在则说明图标还没加载出来,等到页面全部加载再尝试切换
Fluid.utils.waitElementLoaded(colorToggleIconSelector, function() {
var iconElement = document.querySelector(colorToggleIconSelector);
if (iconElement) {
iconElement.setAttribute(
'class',
'iconfont ' + icon
);
iconElement.setAttribute(
'data',
invertColorSchemaObj[schema]
);
}
});
}
if (document.documentElement.getAttribute('data-user-color-scheme')) {
var color = getComputedStyle(document.documentElement).getPropertyValue('--navbar-bg-color').trim()
document.querySelector('meta[name="theme-color"]').setAttribute('content', color)
}
}
}
function setHighlightCSS(schema) {
// 启用对应的代码高亮的样式
var lightCss = document.getElementById('highlight-css');
var darkCss = document.getElementById('highlight-css-dark');
if (schema === 'dark') {
if (darkCss) {
darkCss.removeAttribute('disabled');
}
if (lightCss) {
lightCss.setAttribute('disabled', '');
}
} else {
if (lightCss) {
lightCss.removeAttribute('disabled');
}
if (darkCss) {
darkCss.setAttribute('disabled', '');
}
}
setTimeout(function() {
// 设置代码块组件样式
document.querySelectorAll('.markdown-body pre').forEach((pre) => {
var cls = Fluid.utils.getBackgroundLightness(pre) >= 0 ? 'code-widget-light' : 'code-widget-dark';
var widget = pre.querySelector('.code-widget-light, .code-widget-dark');
if (widget) {
widget.classList.remove('code-widget-light', 'code-widget-dark');
widget.classList.add(cls);
}
});
}, 200);
}
function setApplications(schema) {
// 设置 remark42 评论主题
if (window.REMARK42) {
window.REMARK42.changeTheme(schema);
}
// 设置 cusdis 评论主题
if (window.CUSDIS) {
window.CUSDIS.setTheme(schema);
}
// 设置 utterances 评论主题
var utterances = document.querySelector('.utterances-frame');
if (utterances) {
var utterancesTheme = schema === 'dark' ? window.UtterancesThemeDark : window.UtterancesThemeLight;
const message = {
type : 'set-theme',
theme: utterancesTheme
};
utterances.contentWindow.postMessage(message, 'https://utteranc.es');
}
// 设置 giscus 评论主题
var giscus = document.querySelector('iframe.giscus-frame');
if (giscus) {
var giscusTheme = schema === 'dark' ? window.GiscusThemeDark : window.GiscusThemeLight;
const message = {
setConfig: {
theme: giscusTheme,
}
};
giscus.style.cssText += 'color-scheme: normal;';
giscus.contentWindow.postMessage({ 'giscus': message }, 'https://giscus.app');
}
}
// 当页面加载时,将显示模式设置为 localStorage 中自定义的值(如果有的话)
applyCustomColorSchemaSettings();
Fluid.utils.waitElementLoaded(colorToggleIconSelector, function() {
applyCustomColorSchemaSettings();
var button = document.querySelector(colorToggleButtonSelector);
if (button) {
// 当用户点击切换按钮时,获得新的显示模式、写入 localStorage、并在页面上生效
button.addEventListener('click', function() {
applyCustomColorSchemaSettings(toggleCustomColorSchema());
});
var icon = document.querySelector(colorToggleIconSelector);
if (icon) {
// 光标悬停在按钮上时,切换图标
button.addEventListener('mouseenter', function() {
var current = icon.getAttribute('data');
icon.classList.replace(getIconClass(invertColorSchemaObj[current]), getIconClass(current));
});
button.addEventListener('mouseleave', function() {
var current = icon.getAttribute('data');
icon.classList.replace(getIconClass(current), getIconClass(invertColorSchemaObj[current]));
});
}
}
});
Fluid.utils.waitElementLoaded(iframeSelector, function() {
applyCustomColorSchemaSettings();
});
})(window, document);