From 5c4d02c89eddefa8089bb4fa5940351d43fbf4d4 Mon Sep 17 00:00:00 2001
From: neveler <55753029+neveler@users.noreply.github.com>
Date: Wed, 3 Dec 2025 16:13:21 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=BE=E7=BD=AE=E9=A1=B5?=
=?UTF-8?q?=20(#362)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
_config.yml | 3 +-
_data/navigation.yml | 2 +
_data/settings.yaml | 35 ++++++++++
_includes/head/custom.html | 1 +
_layouts/settings.html | 46 +++++++++++++
_sass/minimal-mistakes-plus.scss | 40 ++++++-----
assets/css/main.scss | 16 ++---
assets/css/skins/air.scss | 8 +++
assets/css/skins/aqua.scss | 8 +++
assets/css/skins/contrast.scss | 8 +++
assets/css/{ => skins}/dark.scss | 16 ++---
assets/css/skins/default.scss | 2 +
assets/css/skins/dirt.scss | 8 +++
assets/css/skins/mint.scss | 8 +++
assets/css/skins/neon.scss | 8 +++
assets/css/skins/plum.scss | 8 +++
assets/css/skins/sunrise.scss | 8 +++
assets/js/settings.js | 76 ++++++++++++++++++++
assets/js/theme.js | 115 +++++++++++++++++++------------
settings.yaml | 43 ++++++++++++
20 files changed, 380 insertions(+), 79 deletions(-)
create mode 100644 _data/settings.yaml
create mode 100644 _layouts/settings.html
create mode 100644 assets/css/skins/air.scss
create mode 100644 assets/css/skins/aqua.scss
create mode 100644 assets/css/skins/contrast.scss
rename assets/css/{ => skins}/dark.scss (68%)
create mode 100644 assets/css/skins/default.scss
create mode 100644 assets/css/skins/dirt.scss
create mode 100644 assets/css/skins/mint.scss
create mode 100644 assets/css/skins/neon.scss
create mode 100644 assets/css/skins/plum.scss
create mode 100644 assets/css/skins/sunrise.scss
create mode 100644 assets/js/settings.js
create mode 100644 settings.yaml
diff --git a/_config.yml b/_config.yml
index 5b074d3..1cce97c 100644
--- a/_config.yml
+++ b/_config.yml
@@ -139,8 +139,6 @@ defaults:
# Theme Settings
theme: minimal-mistakes-jekyll
-minimal_mistakes_skin: default # "air", "aqua", "contrast", "dark", "dirt", "neon", "mint", "plum", "sunrise"
-minimal_mistakes_skin_dark: dark
# Site Settings
locale: zh
@@ -309,6 +307,7 @@ compress_html:
envs: development
head_scripts:
+ - /assets/js/settings.js
- /assets/js/theme.js
after_footer_scripts:
- /assets/js/plugins/jquery.auto-redirect.js
diff --git a/_data/navigation.yml b/_data/navigation.yml
index 40fe95c..563031e 100644
--- a/_data/navigation.yml
+++ b/_data/navigation.yml
@@ -1,6 +1,8 @@
main:
- title: 常见问题
url: /faq.html
+ - title: 设置
+ url: /settings.html
docs:
- title: 问题集合
diff --git a/_data/settings.yaml b/_data/settings.yaml
new file mode 100644
index 0000000..e91dd2c
--- /dev/null
+++ b/_data/settings.yaml
@@ -0,0 +1,35 @@
+appearance_color:
+ type: radio
+ default: light
+ options:
+ - light
+ - dark
+ - auto
+appearance_skin_light:
+ type: radio
+ default: default
+ options:
+ - default
+ - air
+ - aqua
+ - contrast
+ - dark
+ - dirt
+ - neon
+ - mint
+ - plum
+ - sunrise
+appearance_skin_dark:
+ type: radio
+ default: dark
+ options:
+ - default
+ - air
+ - aqua
+ - contrast
+ - dark
+ - dirt
+ - neon
+ - mint
+ - plum
+ - sunrise
diff --git a/_includes/head/custom.html b/_includes/head/custom.html
index 9f365f2..55de750 100644
--- a/_includes/head/custom.html
+++ b/_includes/head/custom.html
@@ -1 +1,2 @@
+
diff --git a/_layouts/settings.html b/_layouts/settings.html
new file mode 100644
index 0000000..af675a0
--- /dev/null
+++ b/_layouts/settings.html
@@ -0,0 +1,46 @@
+---
+layout: document
+---
+
+{% for group in page.data %}
+
+{% capture notice %}
+
+## {{ group.title }}
+
+{% for pair in group.settings %}
+{% assign name = pair[0] %}
+{% assign value = pair[1] %}
+{% assign setting = site.data.settings[name] %}
+
+{% if setting.type == 'radio' %}
+
+
+
+{% endif %}
+{% endfor %}
+{% endcapture %}
+{{ notice | markdownify }}
+{% endfor %}
diff --git a/_sass/minimal-mistakes-plus.scss b/_sass/minimal-mistakes-plus.scss
index f0eaae1..1d6d0b4 100644
--- a/_sass/minimal-mistakes-plus.scss
+++ b/_sass/minimal-mistakes-plus.scss
@@ -1,16 +1,24 @@
-@import "minimal-mistakes";
-
-blockquote {
- margin-inline: 0;
- font-style: normal;
-}
-
-a, span, code, kbd, pre, em, strong, b, i {
- overflow-wrap: break-word;
- word-wrap: break-word;
- word-break: break-word;
-}
-
-.m0 {
- margin: 0 !important;
-}
+@import "minimal-mistakes";
+
+blockquote {
+ margin-inline: 0;
+ font-style: normal;
+}
+
+* {
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ word-break: break-word;
+}
+
+.notice ul:first-child {
+ margin-top: 0;
+}
+
+.task-list-item label {
+ display: inline
+}
+
+.m0 {
+ margin: 0 !important;
+}
diff --git a/assets/css/main.scss b/assets/css/main.scss
index cd37abb..0f4452f 100644
--- a/assets/css/main.scss
+++ b/assets/css/main.scss
@@ -1,8 +1,8 @@
----
----
-
-@charset "utf-8";
-
-$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-@import "minimal-mistakes/skins/{{ site.minimal_mistakes_skin | default: 'default' }}";
-@import "minimal-mistakes-plus";
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/default";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/air.scss b/assets/css/skins/air.scss
new file mode 100644
index 0000000..581fb34
--- /dev/null
+++ b/assets/css/skins/air.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/air";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/aqua.scss b/assets/css/skins/aqua.scss
new file mode 100644
index 0000000..2a03a4d
--- /dev/null
+++ b/assets/css/skins/aqua.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/aqua";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/contrast.scss b/assets/css/skins/contrast.scss
new file mode 100644
index 0000000..474cc29
--- /dev/null
+++ b/assets/css/skins/contrast.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/contrast";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/dark.scss b/assets/css/skins/dark.scss
similarity index 68%
rename from assets/css/dark.scss
rename to assets/css/skins/dark.scss
index 8ad895b..b7bb9c2 100644
--- a/assets/css/dark.scss
+++ b/assets/css/skins/dark.scss
@@ -1,8 +1,8 @@
----
----
-
-@charset "utf-8";
-
-$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-@import "minimal-mistakes/skins/{{ site.minimal_mistakes_skin_dark | default: 'dark' }}";
-@import "minimal-mistakes-plus";
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/dark";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/default.scss b/assets/css/skins/default.scss
new file mode 100644
index 0000000..a845151
--- /dev/null
+++ b/assets/css/skins/default.scss
@@ -0,0 +1,2 @@
+---
+---
diff --git a/assets/css/skins/dirt.scss b/assets/css/skins/dirt.scss
new file mode 100644
index 0000000..1b711f5
--- /dev/null
+++ b/assets/css/skins/dirt.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/dirt";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/mint.scss b/assets/css/skins/mint.scss
new file mode 100644
index 0000000..7385126
--- /dev/null
+++ b/assets/css/skins/mint.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/mint";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/neon.scss b/assets/css/skins/neon.scss
new file mode 100644
index 0000000..4ba4097
--- /dev/null
+++ b/assets/css/skins/neon.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/neon";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/plum.scss b/assets/css/skins/plum.scss
new file mode 100644
index 0000000..b40391c
--- /dev/null
+++ b/assets/css/skins/plum.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/plum";
+@import "minimal-mistakes-plus";
diff --git a/assets/css/skins/sunrise.scss b/assets/css/skins/sunrise.scss
new file mode 100644
index 0000000..9c33069
--- /dev/null
+++ b/assets/css/skins/sunrise.scss
@@ -0,0 +1,8 @@
+---
+---
+
+@charset "utf-8";
+
+$sans-serif: -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+@import "minimal-mistakes/skins/sunrise";
+@import "minimal-mistakes-plus";
diff --git a/assets/js/settings.js b/assets/js/settings.js
new file mode 100644
index 0000000..13e6e59
--- /dev/null
+++ b/assets/js/settings.js
@@ -0,0 +1,76 @@
+---
+layout: null
+---
+(function (global) {
+ var PREFIX = "HMCL_DOCS_SETTINGS_";
+ var data = {};
+ var events = {};
+ var config = /*{%comment%}*/{}/*{%endcomment%}*//**{{'/'}}{{ site.data.settings | jsonify }}/**/;
+
+ global.addEventListener("storage", function (event) {
+ if (!event.key) return;
+ if (event.key.indexOf(PREFIX) !== 0) return;
+
+ var handlers = events[event.key];
+ if (!handlers) return;
+
+ var newValue = event.newValue;
+ var oldValue = event.oldValue;
+ if (oldValue === newValue) return;
+
+ data[event.key] = newValue;
+ for (var i = 0; i < handlers.length; i++) {
+ if (typeof handlers[i] === "function") {
+ handlers[i](newValue, oldValue);
+ }
+ }
+ });
+
+ var settings = {
+ set: function (key, value) {
+ if (config[key] === undefined) return;
+ var strKey = (PREFIX + key).toUpperCase();
+ var newValue = value + "";
+ data[strKey] = newValue;
+ localStorage.setItem(strKey, newValue);
+ var handlers = events[strKey];
+ if (!handlers) return;
+
+ for (var i = 0; i < handlers.length; i++) {
+ if (typeof handlers[i] === "function") {
+ handlers[i](newValue);
+ }
+ }
+ },
+
+ get: function (key, defaultValue) {
+ if (config[key] === undefined) return;
+ var strKey = (PREFIX + key).toUpperCase();
+ data.hasOwnProperty(strKey) || (data[strKey] = localStorage.getItem(strKey));
+ if (typeof defaultValue === "string" && data[strKey] === null) {
+ return defaultValue;
+ }
+ return data[strKey];
+ },
+
+ refresh: function (key) {
+ if (config[key] === undefined) return;
+ settings.set(key, settings.get(key, config[key].default));
+ },
+
+ onChange: function (key, handler) {
+ if (config[key] === undefined) return;
+ if (typeof handler !== "function") return;
+ var strKey = (PREFIX + key).toUpperCase();
+ if (config[key].type === "radio") {
+ handler(settings.get(key, config[key].default));
+ }
+ if (!events[strKey]) {
+ events[strKey] = [handler];
+ } else {
+ events[strKey].push(handler);
+ }
+ }
+ };
+ global.settings = settings;
+})(window);
diff --git a/assets/js/theme.js b/assets/js/theme.js
index 9782247..9a20279 100644
--- a/assets/js/theme.js
+++ b/assets/js/theme.js
@@ -1,45 +1,70 @@
----
-layout: null
----
-var darkTheme = document.createElement("link");
-darkTheme.rel = "stylesheet alternate";
-darkTheme.href = "{{ '/assets/css/dark.css' | relative_url }}";
-document.head.appendChild(darkTheme);
-window.addEventListener("DOMContentLoaded", function () {
- var list = document.querySelector(".masthead .visible-links");
- if (!list) return;
- var mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
- function handler() {
- darkTheme.rel = mediaQuery.matches ? "stylesheet" : "stylesheet alternate";
- }
- var current = 0;
- var modes = ["light", "dark", "auto"];
- var modeNames = ["亮色", "暗色", "自动"];
- var switcher = document.createElement("a");
- switcher.className = "masthead__menu-item";
- switcher.innerText = modeNames[current];
- switcher.href = "javascript:;";
- switcher.onclick = function () {
- themeApply(current + 1);
- }
- list.appendChild(switcher);
- function themeApply(index) {
- index = (Number(index) || 0) % modes.length;
- if (index === current) return;
- if (modes[current] === "auto") mediaQuery.removeEventListener("change", handler);
- current = index;
- var mode = modes[current];
- switcher.innerText = modeNames[current];
- localStorage.setItem("theme", current);
- if (mode === "light") darkTheme.rel = "stylesheet alternate";
- else if (mode === "dark") darkTheme.rel = "stylesheet";
- else {
- mediaQuery.addEventListener("change", handler);
- handler();
- }
- }
- themeApply(localStorage.getItem("theme"));
- window.addEventListener("storage", function (event) {
- event.key === "theme" && themeApply(event.newValue);
- });
-});
\ No newline at end of file
+---
+layout: null
+---
+window.addEventListener("DOMContentLoaded", function () {
+ var skinLink = document.getElementById("skin");
+ var darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)");
+ function applyDarkSkin() {
+ skinLink.href = "{{ '/assets/css/skins/' | relative_url }}" + settings.get("appearance_skin_dark", "dark") + ".css";
+ }
+ function applyLightSkin() {
+ skinLink.href = "{{ '/assets/css/skins/' | relative_url }}" + settings.get("appearance_skin_light", "default") + ".css";
+ }
+ function autoSchemeHandler() {
+ if (darkModeQuery.matches) {
+ applyDarkSkin();
+ } else {
+ applyLightSkin();
+ }
+ }
+ var activeModeIndex = 0;
+ var modeKeys = ["light", "dark", "auto"];
+ var modeLabels = ["亮色", "暗色", "自动"];
+
+ var menuList = document.querySelector(".masthead .visible-links");
+ var modeSwitcher = null;
+ if (menuList) {
+ modeSwitcher = document.createElement("a");
+ modeSwitcher.className = "masthead__menu-item";
+ modeSwitcher.textContent = modeLabels[activeModeIndex];
+ modeSwitcher.href = "javascript:;";
+ modeSwitcher.onclick = function () {
+ var nextIndex = (activeModeIndex + 1) % modeKeys.length;
+ settings.set("appearance_color", modeKeys[nextIndex]);
+ }
+ menuList.appendChild(modeSwitcher);
+ }
+ function applyTheme(mode) {
+ var newIndex = modeKeys.indexOf(mode);
+ if (newIndex < 0) newIndex = 0;
+
+ if (modeKeys[activeModeIndex] === "auto") {
+ darkModeQuery.removeEventListener("change", autoSchemeHandler);
+ }
+
+ activeModeIndex = newIndex;
+ var resolvedMode = modeKeys[activeModeIndex];
+
+ if (modeSwitcher) {
+ modeSwitcher.textContent = modeLabels[activeModeIndex];
+ }
+
+ if (resolvedMode === "light") {
+ applyLightSkin();
+ }
+ else if (resolvedMode === "dark") {
+ applyDarkSkin();
+ }
+ else {
+ darkModeQuery.addEventListener("change", autoSchemeHandler);
+ autoSchemeHandler();
+ }
+ }
+ settings.onChange("appearance_color", applyTheme);
+ settings.onChange("appearance_skin_dark", function () {
+ settings.refresh("appearance_color");
+ });
+ settings.onChange("appearance_skin_light", function () {
+ settings.refresh("appearance_color");
+ });
+});
diff --git a/settings.yaml b/settings.yaml
new file mode 100644
index 0000000..d8d79ae
--- /dev/null
+++ b/settings.yaml
@@ -0,0 +1,43 @@
+---
+title: 设置
+layout: settings
+permalink: /settings.html
+data:
+ - title: 外观
+ settings:
+ appearance_color:
+ title: 颜色模式
+ description: 用于切换站点主题颜色模式。
+ options:
+ light: 亮色
+ dark: 暗色
+ auto: 自动
+ appearance_skin_light:
+ title: 亮色皮肤
+ description: 亮色模式下应用的皮肤。
+ options:
+ default: 默认
+ air: 天空
+ aqua: 水蓝
+ contrast: 高对比
+ dark: 暗色
+ dirt: 泥土
+ neon: 霓虹
+ mint: 薄荷
+ plum: 梅紫
+ sunrise: 日出
+ appearance_skin_dark:
+ title: 暗色皮肤
+ description: 暗色模式下应用的皮肤。
+ options:
+ default: 默认
+ air: 天空
+ aqua: 水蓝
+ contrast: 高对比
+ dark: 暗色
+ dirt: 泥土
+ neon: 霓虹
+ mint: 薄荷
+ plum: 梅紫
+ sunrise: 日出
+---