diff --git a/_data/settings.yaml b/_data/settings.yaml index e91dd2cd..9323459d 100644 --- a/_data/settings.yaml +++ b/_data/settings.yaml @@ -5,23 +5,19 @@ appearance_color: - light - dark - auto -appearance_skin_light: +appearance_color_switcher: type: radio - default: default + default: enable options: - - default - - air - - aqua - - contrast - - dark - - dirt - - neon - - mint - - plum - - sunrise -appearance_skin_dark: - type: radio - default: dark + - enable + - disable +appearance_skin: + type: multi-radio + children: + light: + default: default + dark: + default: dark options: - default - air diff --git a/_layouts/default.html b/_layouts/default.html index e691d2a6..f820331a 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -12,7 +12,7 @@ {% if site.preview and site.preview.pr-number %} -
当前站点为预览构建而非官方文档。如需反馈问题,请前往 #{{ site.preview.pr-number }} 留言。
+
当前站点为预览构建而非官方文档。如需反馈问题,请前往 #{{ site.preview.pr-number }} 留言。
{% endif %} {% include_cached skip-links.html %} diff --git a/_layouts/settings.html b/_layouts/settings.html index af675a0c..96bc81bb 100644 --- a/_layouts/settings.html +++ b/_layouts/settings.html @@ -1,46 +1,57 @@ --- -layout: document +layout: single --- -{% for group in page.data %} - -{% capture notice %} - -## {{ group.title }} - +{%- for group in page.data %} +

{{ 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' %}
- +

+ {{ value.title }}
+ {{ value.description }} +

+ {% if setting.type == 'radio' %} + {% for option in setting.options %} + + {% endfor %} + {% elsif setting.type == 'multi-radio' %} + + + + + {% for item in setting.children %} + {% capture item_name %}{{ item[0] }}{% endcapture %} + + {% endfor %} + + + + {% for option in setting.options %} + + + {% for item in setting.children %} + + {% endfor %} + + {% endfor %} + +
{{ value.title }}{{ value.children[item_name] }}
{{ value.options[option] }}
+ {% endif %}
+{% endfor %} +{% endfor %} -{% endif %} -{% endfor %} -{% endcapture %} -{{ notice | markdownify }} -{% endfor %} + + diff --git a/_sass/minimal-mistakes-plus.scss b/_sass/minimal-mistakes-plus.scss index 1d6d0b45..344a3ca8 100644 --- a/_sass/minimal-mistakes-plus.scss +++ b/_sass/minimal-mistakes-plus.scss @@ -11,14 +11,16 @@ blockquote { word-break: break-word; } -.notice ul:first-child { - margin-top: 0; -} - -.task-list-item label { - display: inline +.preview { + top: 0; + z-index: 999; + padding: 0.4em; + position: sticky; + margin: 0 !important; } -.m0 { - margin: 0 !important; +table.setting-multi-radio td { + border: 0; + text-align: center; + border-left: 1px solid mix(#000, $border-color, 25%); } diff --git a/assets/js/settings.js b/assets/js/settings.js index 13e6e59f..b4674c33 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -1,76 +1,36 @@ --- 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); - } +(function () { + const PREFIX = "HMCL_DOCS_SETTINGS_", data = {}, bus = new EventTarget(), configs = /*{%comment%}*/{}/*{%endcomment%}*/ /**{{'/'}}{{ site.data.settings | jsonify }}/**/; + window.addEventListener("storage", ({ key, newValue }) => key !== null && key.startsWith(PREFIX) && newValue !== data[key] && bus.dispatchEvent(new CustomEvent(key, { detail: (data[key] = newValue) }))); + for (const [key, config] of Object.entries(configs)) { + if (config.children === undefined) continue; + for (const [childKey, child] of Object.entries(config.children)) { + configs[`${key}.${childKey}`] = { ...config, ...child }; } - }); - - 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); - } - } + } + const formatKey = (key) => PREFIX + key.toUpperCase().replaceAll(".", "_"); + window.settings = { + set(key, value) { + const name = formatKey(key); + localStorage.setItem(name, (data[name] = String(value))); + bus.dispatchEvent(new CustomEvent(name, { detail: data[name] })); }, - - 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]; + get(key) { + const name = formatKey(key); + if (data[name] !== undefined) return data[name]; + const value = localStorage.getItem(name); + if (value !== null) return data[name] = value; + const config = configs[key]; + if (config === undefined || typeof config.default !== "string") return null; + return config.default; }, - - refresh: function (key) { - if (config[key] === undefined) return; - settings.set(key, settings.get(key, config[key].default)); + onChange(key, handler) { + const value = this.get(key); + if (value === null) return; + handler(value); + bus.addEventListener(formatKey(key), (event) => handler(event.detail)); }, - - 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 9a202792..6cece472 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -4,11 +4,14 @@ layout: null window.addEventListener("DOMContentLoaded", function () { var skinLink = document.getElementById("skin"); var darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)"); + function applySkin(skin) { + skinLink.href = "{{ '/assets/css/skins/' | relative_url }}" + skin + ".css"; + } function applyDarkSkin() { - skinLink.href = "{{ '/assets/css/skins/' | relative_url }}" + settings.get("appearance_skin_dark", "dark") + ".css"; + applySkin(settings.get("appearance_skin.dark")); } function applyLightSkin() { - skinLink.href = "{{ '/assets/css/skins/' | relative_url }}" + settings.get("appearance_skin_light", "default") + ".css"; + applySkin(settings.get("appearance_skin.light")); } function autoSchemeHandler() { if (darkModeQuery.matches) { @@ -61,10 +64,15 @@ window.addEventListener("DOMContentLoaded", function () { } } settings.onChange("appearance_color", applyTheme); - settings.onChange("appearance_skin_dark", function () { - settings.refresh("appearance_color"); + settings.onChange("appearance_skin.dark", function () { + applyTheme(settings.get("appearance_color")); + }); + settings.onChange("appearance_skin.light", function () { + applyTheme(settings.get("appearance_color")); }); - settings.onChange("appearance_skin_light", function () { - settings.refresh("appearance_color"); + settings.onChange("appearance_color_switcher", function (value) { + if (modeSwitcher !== null) { + modeSwitcher.style.display = value === "enable" ? "" : "none"; + } }); }); diff --git a/settings.yaml b/settings.yaml index d8d79aed..fb8dacd2 100644 --- a/settings.yaml +++ b/settings.yaml @@ -12,23 +12,18 @@ data: light: 亮色 dark: 暗色 auto: 自动 - appearance_skin_light: - title: 亮色皮肤 - description: 亮色模式下应用的皮肤。 + appearance_color_switcher: + title: 颜色模式快捷开关 + description: 用于快捷切换站点主题颜色模式的开关,位于页面右上角。 options: - default: 默认 - air: 天空 - aqua: 水蓝 - contrast: 高对比 + enable: 启用 + disable: 禁用 + appearance_skin: + title: 皮肤 + description: 各颜色模式下应用的皮肤。 + children: + light: 亮色 dark: 暗色 - dirt: 泥土 - neon: 霓虹 - mint: 薄荷 - plum: 梅紫 - sunrise: 日出 - appearance_skin_dark: - title: 暗色皮肤 - description: 暗色模式下应用的皮肤。 options: default: 默认 air: 天空