hexo-theme-gnix 5.0.9 → 5.0.11
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/package.json +1 -1
- package/source/css/default.css +24 -2
- package/source/js/shiki/shiki.js +3 -3
- package/source/js/theme-selector.js +47 -52
package/package.json
CHANGED
package/source/css/default.css
CHANGED
|
@@ -868,11 +868,33 @@ body {
|
|
|
868
868
|
margin: 1em auto;
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
+
button.physical-btn,
|
|
872
|
+
kbd {
|
|
873
|
+
display: inline-block;
|
|
874
|
+
padding: 0.1em 0.3em;
|
|
875
|
+
font-family: var(--font-mono);
|
|
876
|
+
font-size: 0.85em;
|
|
877
|
+
color: var(--subtext0);
|
|
878
|
+
user-select: none;
|
|
879
|
+
background: linear-gradient(180deg, var(--base) 0%, var(--mantle) 100%);
|
|
880
|
+
border: 1px solid var(--surface0);
|
|
881
|
+
border-bottom-width: 3px;
|
|
882
|
+
border-bottom-color: var(--surface0);
|
|
883
|
+
border-radius: 6px;
|
|
884
|
+
position: relative;
|
|
885
|
+
top: -3px;
|
|
886
|
+
transition:
|
|
887
|
+
top 0.1s ease,
|
|
888
|
+
border-bottom-width 0.1s ease,
|
|
889
|
+
box-shadow 0.1s ease;
|
|
890
|
+
|
|
891
|
+
&:active {
|
|
892
|
+
top: 0px;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
871
895
|
ol {
|
|
872
896
|
list-style-position: outside;
|
|
873
897
|
padding-left: 2em;
|
|
874
|
-
margin-top: 0;
|
|
875
|
-
margin-bottom: 0;
|
|
876
898
|
}
|
|
877
899
|
|
|
878
900
|
ul {
|
package/source/js/shiki/shiki.js
CHANGED
|
@@ -57,7 +57,7 @@ const FeatureHandlers = {
|
|
|
57
57
|
const expandBtn = figure.querySelector(SELECTORS.expandBtn);
|
|
58
58
|
const pre = figure.querySelector(SELECTORS.preShiki);
|
|
59
59
|
const isExpanded = figure.classList.contains("expanded");
|
|
60
|
-
const showLines = parseInt(figure.dataset.
|
|
60
|
+
const showLines = parseInt(figure.dataset.maxLines || "10", 10);
|
|
61
61
|
|
|
62
62
|
if (isExpanded) {
|
|
63
63
|
const computedStyle = getComputedStyle(pre);
|
|
@@ -88,7 +88,7 @@ function handleToolbarClick(event) {
|
|
|
88
88
|
const classList = target.classList;
|
|
89
89
|
|
|
90
90
|
const handlers = {
|
|
91
|
-
|
|
91
|
+
expand: () => FeatureHandlers.expandCode(this),
|
|
92
92
|
"copy-button": () => FeatureHandlers.copy(this, target),
|
|
93
93
|
"toggle-wrap": () => FeatureHandlers.toggleWrap(this),
|
|
94
94
|
};
|
|
@@ -138,7 +138,7 @@ function addHighlightTool() {
|
|
|
138
138
|
// Initialize collapsed state for collapsible code blocks
|
|
139
139
|
if (figure.dataset.collapsible === "true") {
|
|
140
140
|
const pre = figure.querySelector(SELECTORS.preShiki);
|
|
141
|
-
const showLines = parseInt(figure.dataset.
|
|
141
|
+
const showLines = parseInt(figure.dataset.maxLines || "10", 10);
|
|
142
142
|
|
|
143
143
|
if (pre) {
|
|
144
144
|
// 确保元素已经渲染完成后再设置高度
|
|
@@ -18,20 +18,25 @@
|
|
|
18
18
|
let previewTheme = null;
|
|
19
19
|
let originalTheme = null;
|
|
20
20
|
let isModalOpen = false;
|
|
21
|
+
let modal = null;
|
|
22
|
+
let themeOptions = [];
|
|
21
23
|
|
|
22
24
|
function getThemePreference() {
|
|
23
25
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
24
26
|
return stored && stored in THEME_MAP ? stored : DEFAULT_THEME;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
function resolveTheme(theme) {
|
|
30
|
+
return theme === "system"
|
|
31
|
+
? colorSchemeMediaQuery.matches
|
|
32
|
+
? "mocha"
|
|
33
|
+
: "nord"
|
|
34
|
+
: theme;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
function applyTheme(theme, persist = false) {
|
|
28
38
|
const html = document.documentElement;
|
|
29
|
-
const resolvedTheme =
|
|
30
|
-
theme === "system"
|
|
31
|
-
? colorSchemeMediaQuery.matches
|
|
32
|
-
? "mocha"
|
|
33
|
-
: "nord"
|
|
34
|
-
: theme;
|
|
39
|
+
const resolvedTheme = resolveTheme(theme);
|
|
35
40
|
html.setAttribute("data-theme", resolvedTheme);
|
|
36
41
|
html.classList.remove("night", "light");
|
|
37
42
|
html.classList.add(THEME_MAP[resolvedTheme]);
|
|
@@ -41,82 +46,73 @@
|
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
|
|
49
|
+
function previewThemeOnOption(option, index) {
|
|
50
|
+
if (index === currentIndex) {
|
|
51
|
+
option.classList.add("is-focused");
|
|
52
|
+
option.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
53
|
+
|
|
54
|
+
const theme = option.getAttribute("data-theme-option");
|
|
55
|
+
if (theme !== previewTheme) {
|
|
56
|
+
previewTheme = theme;
|
|
57
|
+
applyTheme(theme);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
option.classList.remove("is-focused");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function updateFocus() {
|
|
65
|
+
themeOptions.forEach(previewThemeOnOption);
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
function openModal() {
|
|
45
|
-
|
|
69
|
+
modal = document.getElementById("theme-selector-modal");
|
|
46
70
|
if (!modal || isModalOpen) return;
|
|
47
71
|
|
|
48
72
|
isModalOpen = true;
|
|
49
73
|
originalTheme = getThemePreference();
|
|
74
|
+
themeOptions = modal.querySelectorAll(".theme-option");
|
|
50
75
|
|
|
51
|
-
// Find current theme index
|
|
52
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
53
76
|
themeOptions.forEach((option, index) => {
|
|
54
77
|
const theme = option.getAttribute("data-theme-option");
|
|
55
78
|
if (theme === originalTheme) {
|
|
56
79
|
currentIndex = index;
|
|
57
|
-
}
|
|
58
|
-
// Update active state
|
|
59
|
-
if (theme === originalTheme) {
|
|
60
80
|
option.classList.add("is-active");
|
|
61
81
|
} else {
|
|
62
82
|
option.classList.remove("is-active");
|
|
63
83
|
}
|
|
64
84
|
});
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
updateFocus(themeOptions);
|
|
86
|
+
updateFocus();
|
|
68
87
|
modal.classList.add("is-active");
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
function closeModal(apply = false) {
|
|
72
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
73
91
|
if (!modal || !isModalOpen) return;
|
|
74
92
|
|
|
75
93
|
isModalOpen = false;
|
|
76
94
|
|
|
77
95
|
if (apply && previewTheme) {
|
|
78
|
-
// Apply the selected theme
|
|
79
96
|
applyTheme(previewTheme, true);
|
|
80
97
|
} else if (previewTheme && previewTheme !== originalTheme) {
|
|
81
|
-
// Restore original theme if cancelled
|
|
82
98
|
applyTheme(originalTheme);
|
|
83
99
|
}
|
|
84
100
|
|
|
85
101
|
modal.classList.remove("is-active");
|
|
102
|
+
themeOptions.forEach((option) => {
|
|
103
|
+
option.classList.remove("is-active");
|
|
104
|
+
option.classList.remove("is-focused");
|
|
105
|
+
});
|
|
106
|
+
|
|
86
107
|
previewTheme = null;
|
|
87
108
|
originalTheme = null;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
91
|
-
for (const t of themeOptions) {
|
|
92
|
-
t.classList.remove("is-active");
|
|
93
|
-
t.classList.remove("is-focused");
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function updateFocus(themeOptions) {
|
|
98
|
-
themeOptions.forEach((option, index) => {
|
|
99
|
-
if (index === currentIndex) {
|
|
100
|
-
option.classList.add("is-focused");
|
|
101
|
-
option.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
102
|
-
|
|
103
|
-
// Preview theme on focus
|
|
104
|
-
const theme = option.getAttribute("data-theme-option");
|
|
105
|
-
if (theme !== previewTheme) {
|
|
106
|
-
previewTheme = theme;
|
|
107
|
-
applyTheme(theme);
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
option.classList.remove("is-focused");
|
|
111
|
-
}
|
|
112
|
-
});
|
|
109
|
+
modal = null;
|
|
110
|
+
themeOptions = [];
|
|
113
111
|
}
|
|
114
112
|
|
|
115
113
|
function handleKeyboard(event) {
|
|
116
114
|
if (!isModalOpen) return;
|
|
117
115
|
|
|
118
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
119
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
120
116
|
const maxIndex = themeOptions.length - 1;
|
|
121
117
|
|
|
122
118
|
switch (event.key) {
|
|
@@ -125,7 +121,7 @@
|
|
|
125
121
|
case "Down":
|
|
126
122
|
event.preventDefault();
|
|
127
123
|
currentIndex = currentIndex < maxIndex ? currentIndex + 1 : 0;
|
|
128
|
-
updateFocus(
|
|
124
|
+
updateFocus();
|
|
129
125
|
break;
|
|
130
126
|
|
|
131
127
|
case "k":
|
|
@@ -133,7 +129,7 @@
|
|
|
133
129
|
case "Up":
|
|
134
130
|
event.preventDefault();
|
|
135
131
|
currentIndex = currentIndex > 0 ? currentIndex - 1 : maxIndex;
|
|
136
|
-
updateFocus(
|
|
132
|
+
updateFocus();
|
|
137
133
|
break;
|
|
138
134
|
|
|
139
135
|
case "Enter":
|
|
@@ -150,8 +146,10 @@
|
|
|
150
146
|
}
|
|
151
147
|
|
|
152
148
|
// 监听系统主题改变
|
|
153
|
-
colorSchemeMediaQuery.addEventListener("change", (
|
|
154
|
-
|
|
149
|
+
colorSchemeMediaQuery.addEventListener("change", () => {
|
|
150
|
+
if (getThemePreference() === "system") {
|
|
151
|
+
applyTheme("system", true);
|
|
152
|
+
}
|
|
155
153
|
});
|
|
156
154
|
|
|
157
155
|
// 处理 modal 点击事件(关闭背景)
|
|
@@ -168,11 +166,8 @@
|
|
|
168
166
|
event.preventDefault();
|
|
169
167
|
event.stopPropagation();
|
|
170
168
|
|
|
171
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
172
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
173
169
|
currentIndex = index;
|
|
174
|
-
updateFocus(
|
|
175
|
-
// Small delay before closing to show selection
|
|
170
|
+
updateFocus();
|
|
176
171
|
setTimeout(() => closeModal(true), 150);
|
|
177
172
|
};
|
|
178
173
|
|