Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions _data/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<body class="layout--{{ page.layout | default: layout.layout }}{% if page.classes or layout.classes %}{{ page.classes | default: layout.classes | join: ' ' | prepend: ' ' }}{% endif %}" dir="{% if site.rtl %}rtl{% else %}ltr{% endif %}">
{% if site.preview and site.preview.pr-number %}
<div class="notice--warning text-center m0" style="position: sticky; top: 0; z-index: 999; padding: 0.4em;">当前站点为预览构建而非官方文档。如需反馈问题,请前往 <a href="https://github.com/HMCL-dev/HMCL-docs/pull/{{ site.preview.pr-number }}">#{{ site.preview.pr-number }}</a> 留言。</div>
<div class="notice--warning text-center preview">当前站点为预览构建而非官方文档。如需反馈问题,请前往 <a href="https://github.com/HMCL-dev/HMCL-docs/pull/{{ site.preview.pr-number }}">#{{ site.preview.pr-number }}</a> 留言。</div>
{% endif %}

{% include_cached skip-links.html %}
Expand Down
79 changes: 45 additions & 34 deletions _layouts/settings.html
Original file line number Diff line number Diff line change
@@ -1,46 +1,57 @@
---
layout: document
layout: single
---

{% for group in page.data %}

{% capture notice %}

## {{ group.title }}

{%- for group in page.data %}
<h2 id="{{ group.title }}">{{ group.title }}</h2>
{% for pair in group.settings %}
{% assign name = pair[0] %}
{% assign value = pair[1] %}
{% assign setting = site.data.settings[name] %}

{% if setting.type == 'radio' %}
<div class="notice">
<ul class="task-list">
<li><strong>{{ value.title }}</strong></li>
<li>{{ value.description }}</li>
{% for option in setting.options %}
<li class="task-list-item">
<input type="radio" class="task-list-item-checkbox" name="{{ name }}" value="{{ option }}" id="{{ name }}_{{ option }}"{% if setting.default == option %} checked{% endif %}><label for="{{ name }}_{{ option }}">{{ value.options[option] }}</label>
</li>
{% endfor %}
</ul>
<p>
<strong>{{ value.title }}</strong><br>
{{ value.description }}
</p>
{% if setting.type == 'radio' %}
{% for option in setting.options %}
<label>
<input type="radio"{% if setting.default == option %} checked{% endif %} class="setting-item" name="{{ name }}" value="{{ option }}">
{{ value.options[option] }}
</label>
{% endfor %}
{% elsif setting.type == 'multi-radio' %}
<table class="setting-multi-radio">
<thead>
<tr>
<th>{{ value.title }}</th>
{% for item in setting.children %}
{% capture item_name %}{{ item[0] }}{% endcapture %}
<th>{{ value.children[item_name] }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for option in setting.options %}
<tr>
<th>{{ value.options[option] }}</th>
{% for item in setting.children %}
<td><input class="setting-item"{% if item[1].default == option %} checked{% endif %} type="radio" name="{{ name }}.{{ item[0] }}" value="{{ option }}"></td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% endfor %}
{% endfor %}

<script>
settings.onChange("{{ name }}", function (newValue, oldValue) {
var list = document.getElementsByName("{{ name }}");
for (var i = 0; i < list.length; i++) {
list[i].checked = list[i].value === newValue;
list[i].onchange = function () {
if (this.checked) {
settings.set(this.name, this.value);
}
}
}
});
for (const settingItem of document.getElementsByClassName("setting-item")) {
settingItem.addEventListener("change", ({ target }) => settings.set(target.name, target.value));
settings.onChange(settingItem.name, (value) => settingItem.type === "radio" && (settingItem.checked = settingItem.value === value));
}
</script>
{% endif %}
{% endfor %}
{% endcapture %}
{{ notice | markdownify }}
{% endfor %}

<style>.notice label input { display: inline }</style>
18 changes: 10 additions & 8 deletions _sass/minimal-mistakes-plus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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%);
}
96 changes: 28 additions & 68 deletions assets/js/settings.js
Original file line number Diff line number Diff line change
@@ -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);
})();
20 changes: 14 additions & 6 deletions assets/js/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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";
}
});
});
25 changes: 10 additions & 15 deletions settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: 天空
Expand Down