diff --git a/content/blog/javascript.ca.md b/content/blog/javascript.ca.md index d24273c..1f4930b 100644 --- a/content/blog/javascript.ca.md +++ b/content/blog/javascript.ca.md @@ -1,7 +1,7 @@ +++ title = "Sense JavaScript obligatori" date = 2023-01-06 -updated = 2023-09-01 +updated = 2023-10-06 description = "JavaScript només s'utilitza quan HTML i CSS no són suficients." [taxonomies] @@ -16,8 +16,8 @@ Aquest tema no requereix JavaScript obligatori. Opcionalment, pot carregar una q ## Opcions habilitades globalment -- L'**interruptor de mode clar/fosc** es pot habilitar configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~900 bytes de JavaScript). - +- L'**interruptor de mode clar/fosc** es pot habilitar configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~1KB de JavaScript). + - **Decodificació de correu electrònic** (~400 bytes). Per protegir contra robots de correu brossa, pots configurar `encode_plaintext_email = true`. Si el teu lloc web està en un repositori públic, considera utilitzar el teu `email` com una cadena codificada en base64[^1]. ## Opcions que es poden sobreescriure de forma jeràrquica diff --git a/content/blog/javascript.es.md b/content/blog/javascript.es.md index a65fdef..27e44fd 100644 --- a/content/blog/javascript.es.md +++ b/content/blog/javascript.es.md @@ -1,7 +1,7 @@ +++ title = "Sin JavaScript obligatorio" date = 2023-01-06 -updated = 2023-09-01 +updated = 2023-10-06 description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes." [taxonomies] @@ -16,8 +16,8 @@ Este tema no requiere JavaScript de manera obligatoria. Opcionalmente, puede car ## Opciones habilitadas globalmente -- El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~900 bytes de JavaScript). - +- El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~1KB de JavaScript). + - **Descodificación de correo electrónico** (~400 bytes). Para proteger contra bots que recopilan correos electrónicos desde tu sitio web, puedes configurar `encode_plaintext_email = true`. Si tu sitio está en un repositorio público, para mayor protección, considera configurar tu `email` como una cadena codificada en base64[^1]. ## Opciones que se pueden sobreescribir de forma jerárquica diff --git a/content/blog/javascript.md b/content/blog/javascript.md index f90fdaf..e67cf83 100644 --- a/content/blog/javascript.md +++ b/content/blog/javascript.md @@ -1,7 +1,7 @@ +++ title = "No mandatory JavaScript" date = 2023-01-06 -updated = 2023-09-01 +updated = 2023-10-06 description = "JavaScript is only used when HTML and CSS aren't enough." [taxonomies] @@ -16,7 +16,7 @@ This theme has no mandatory JavaScript. Optionally, it can load a minimal amount ## Globally enabled settings -- The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~900 bytes of JavaScript). +- The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~1KB of JavaScript). - **E-mail decoding** (~400 bytes). To protect against spambots scraping your e-mail from your website, you can set `encode_plaintext_email = true`. If your site is on a public repository, for extra protection, consider setting your `email` as a base64-encoded string[^1] directly. diff --git a/i18n/ca.toml b/i18n/ca.toml index 6c7a718..07280be 100644 --- a/i18n/ca.toml +++ b/i18n/ca.toml @@ -26,6 +26,7 @@ language_selection = "Selecció d'idioma" toggle_mode = "Canvia el mode $MODE" # $MODE will be replaced by a value (or both) below. dark = "obscur" light = "clar" +reset_mode = "Restableix el mode als valors predeterminats del sistema" # Post metadata. draft = "ESBORRANY" diff --git a/i18n/de.toml b/i18n/de.toml index e28ba98..d6db4f0 100644 --- a/i18n/de.toml +++ b/i18n/de.toml @@ -30,6 +30,7 @@ language_selection = "Sprachauswahl" toggle_mode = "Wechsle in den $MODE Modus" # $MODE will be replaced by a value (or both) below. dark = "dunkel" light = "hell" +reset_mode = "Modus auf Betriebssystemstandard zurücksetzen" # Post metadata. draft = "ENTWURF" diff --git a/i18n/en.toml b/i18n/en.toml index df2bf94..aedd4be 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -26,6 +26,7 @@ language_selection = "Language selection" toggle_mode = "Toggle $MODE mode" # $MODE will be replaced by a value (or both) below. dark = "dark" light = "light" +reset_mode = "Reset mode to OS default" # Post metadata. draft = "DRAFT" diff --git a/i18n/es.toml b/i18n/es.toml index b62ebe6..e5d3128 100644 --- a/i18n/es.toml +++ b/i18n/es.toml @@ -26,6 +26,7 @@ language_selection = "Selección de idioma" toggle_mode = "Cambiar a modo $MODE" # $MODE will be replaced by a value (or both) below. dark = "oscuro" light = "claro" +reset_mode = "Restablecer modo a configuración predeterminada del SO" # Post metadata. draft = "BORRADOR" diff --git a/i18n/fr.toml b/i18n/fr.toml index 4958474..b7fbe2f 100644 --- a/i18n/fr.toml +++ b/i18n/fr.toml @@ -30,6 +30,7 @@ language_selection = "Sélection de la langue" toggle_mode = "Basculer en mode $MODE" # $MODE will be replaced by a value (or both) below. dark = "sombre" light = "clair" +reset_mode = "Réinitialiser le mode aux paramètres par défaut du système" # Post metadata. draft = "BROUILLON" diff --git a/i18n/hi.toml b/i18n/hi.toml index e48961e..7c88135 100644 --- a/i18n/hi.toml +++ b/i18n/hi.toml @@ -28,6 +28,7 @@ language_selection = "भाषा चयन" toggle_mode = "$MODE मोड में टॉगल करें" # $MODE will be replaced by a value (or both) below. dark = "अंधेरा" light = "रोशनी" +reset_mode = "मोड को ओएस डिफ़ॉल्ट पर रीसेट करें" # Post metadata. draft = "मसौदा" diff --git a/i18n/it.toml b/i18n/it.toml index 23a6a2f..20e90ad 100644 --- a/i18n/it.toml +++ b/i18n/it.toml @@ -26,6 +26,7 @@ language_selection = "Selezione della lingua" toggle_mode = "Passa alla modalità $MODE" # $MODE will be replaced by a value (or both) below. dark = "scuro" light = "chiaro" +reset_mode = "Reimposta la modalità alle impostazioni predefinite del sistema operativo" # Post metadata. draft = "BOZZA" diff --git a/i18n/ja.toml b/i18n/ja.toml index 18b102d..d011131 100644 --- a/i18n/ja.toml +++ b/i18n/ja.toml @@ -30,6 +30,7 @@ language_selection = "言語選択" toggle_mode = "$MODE モードに切り替え" # $MODE will be replaced by a value (or both) below. dark = "暗い" light = "明るい" +reset_mode = "モードをOSデフォルトにリセット" # Post metadata. draft = "ドラフト" diff --git a/i18n/ko.toml b/i18n/ko.toml index a28e854..7a05a7a 100644 --- a/i18n/ko.toml +++ b/i18n/ko.toml @@ -30,6 +30,7 @@ language_selection = "언어 선택" toggle_mode = "$MODE 모드로 전환" # $MODE will be replaced by a value (or both) below. dark = "어두운" light = "밝은" +reset_mode = "모드를 OS 기본값으로 재설정" # Post metadata. draft = "임시 저장" diff --git a/i18n/pt-PT.toml b/i18n/pt-PT.toml index 91ea16e..f94d892 100644 --- a/i18n/pt-PT.toml +++ b/i18n/pt-PT.toml @@ -26,6 +26,7 @@ language_selection = "Seleção de idioma" toggle_mode = "Alternar para o modo $MODE" # $MODE will be replaced by a value (or both) below. dark = "escuro" light = "claro" +reset_mode = "Repor o modo para o padrão do SO" # Post metadata. draft = "RASCUNHO" diff --git a/i18n/ru.toml b/i18n/ru.toml index 7d910a1..a806978 100644 --- a/i18n/ru.toml +++ b/i18n/ru.toml @@ -26,6 +26,7 @@ language_selection = "Выбор языка" toggle_mode = "Переключить на режим $MODE" # $MODE will be replaced by a value (or both) below. dark = "тёмный" light = "светлый" +reset_mode = "Сбросить режим к настройкам ОС по умолчанию" # Post metadata. draft = "ЧЕРНОВИК" diff --git a/i18n/uk.toml b/i18n/uk.toml index 927feae..d8a61b7 100644 --- a/i18n/uk.toml +++ b/i18n/uk.toml @@ -30,6 +30,7 @@ language_selection = "Вибір мови" toggle_mode = "Перемкнути в режим $MODE" # $MODE will be replaced by a value (or both) below. dark = "темний" light = "світлий" +reset_mode = "Скинути режим до типових параметрів ОС" # Post metadata. draft = "ЧЕРНЕТКА" diff --git a/i18n/zh-Hans.toml b/i18n/zh-Hans.toml index 7d5afc6..beeb41c 100644 --- a/i18n/zh-Hans.toml +++ b/i18n/zh-Hans.toml @@ -24,8 +24,9 @@ all_posts = "所有文章" all_tags = "所有标签" language_selection = "语言选择" # Machine translated. toggle_mode = "切换到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated. -dark = "暗" # Machine translated. +dark = "暗" # Machine translated. light = "亮" # Machine translated. +reset_mode = "重置为操作系统默认模式" # Machine translated. # Post metadata. draft = "草稿" diff --git a/i18n/zh-Hant.toml b/i18n/zh-Hant.toml index 7ef6b02..c9e38d1 100644 --- a/i18n/zh-Hant.toml +++ b/i18n/zh-Hant.toml @@ -26,6 +26,7 @@ language_selection = "語言選擇" # Machine translated. toggle_mode = "切換到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated. dark = "暗" # Machine translated. light = "亮" # Machine translated. +reset_mode = "重置為操作系統預設模式" # Machine translated. # Post metadata. draft = "草稿" diff --git a/sass/parts/_theme-switch.scss b/sass/parts/_theme-switch.scss index 195df29..6751a78 100644 --- a/sass/parts/_theme-switch.scss +++ b/sass/parts/_theme-switch.scss @@ -11,3 +11,32 @@ background: var(--meta-color); } } + +.theme-switcher-wrapper { + position: relative; +} + +.theme-resetter { + -webkit-mask: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" %3E%3Cpath d="M295.87-193.869v-78.001h291.152q43.63 0 72.369-33.424 28.739-33.423 28.739-79.271t-28.739-79.391Q630.652-497.5 587.022-497.5H343.913l87.478 87.478-55.652 55.153L193.869-536.5l181.87-181.631 55.652 55.653-87.478 86.978h243.109q75.435 0 127.272 56.522 51.837 56.521 51.837 134.174 0 77.652-51.837 134.293-51.837 56.642-127.272 56.642H295.87Z"/%3E%3C/svg%3E'); + position: absolute; + top: -0.6rem; + right: -0.6rem; + visibility: hidden; + opacity: 0; + transition: opacity 0.3s ease, visibility 0.3s ease; + transition-delay: 0.5s; + cursor: pointer; + background: var(--text-color); + width: 0.8rem; + height: 0.8rem; +} + +.theme-switcher-wrapper:hover .theme-resetter.has-custom-theme { + visibility: visible; + opacity: 1; + transition: opacity 0.1s ease, visibility 0.1s ease; + transition-delay: 0s; + &:hover { + background: var(--meta-color); + } +} diff --git a/static/js/themeSwitcher.js b/static/js/themeSwitcher.js index 0cff465..d6a0be5 100644 --- a/static/js/themeSwitcher.js +++ b/static/js/themeSwitcher.js @@ -1,10 +1,11 @@ -// Get the theme switcher button element. +// Get the theme switcher button elements. const themeSwitcher = document.querySelector(".theme-switcher"); +const themeResetter = document.querySelector(".theme-resetter"); // Retrieve theme from either the localStorage or the data-theme attribute on the document element. let currentTheme = localStorage.getItem("theme") || document.documentElement.getAttribute('data-theme'); -// Function to set theme +// Function to set theme. function setTheme(theme, saveToLocalStorage = false) { document.documentElement.setAttribute("data-theme", theme); currentTheme = theme; @@ -13,6 +14,12 @@ function setTheme(theme, saveToLocalStorage = false) { if (saveToLocalStorage) { localStorage.setItem("theme", theme); + themeResetter.classList.add("has-custom-theme"); + themeResetter.setAttribute("aria-hidden", "false"); + } else { + localStorage.removeItem("theme"); + themeResetter.classList.remove("has-custom-theme"); + themeResetter.setAttribute("aria-hidden", "true"); } // Dispatch a custom event for comment systems. @@ -22,6 +29,12 @@ function setTheme(theme, saveToLocalStorage = false) { window.dispatchEvent(event); } +function resetTheme() { + const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + const defaultTheme = isSystemDark ? "dark" : "light"; + setTheme(defaultTheme); +} + // Function to switch between dark and light themes. function switchTheme() { // Set the new theme based on the current theme. @@ -31,6 +44,8 @@ function switchTheme() { // Initialize the theme switcher button. themeSwitcher.addEventListener("click", switchTheme, false); +themeResetter.addEventListener("click", resetTheme, false); + themeSwitcher.setAttribute("role", "button"); let togglePressed = currentTheme === "dark" ? "true" : "false"; themeSwitcher.setAttribute("aria-pressed", togglePressed); @@ -40,3 +55,9 @@ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e = const newTheme = e.matches ? "dark" : "light"; setTheme(newTheme); }); + +if (localStorage.getItem("theme")) { + themeResetter.classList.add("has-custom-theme"); +} else { + themeResetter.classList.remove("has-custom-theme"); +} diff --git a/static/js/themeSwitcher.min.js b/static/js/themeSwitcher.min.js index 63a311e..f925a28 100644 --- a/static/js/themeSwitcher.min.js +++ b/static/js/themeSwitcher.min.js @@ -1 +1 @@ -const themeSwitcher=document.querySelector(".theme-switcher");let currentTheme=localStorage.getItem("theme")||document.documentElement.getAttribute("data-theme");function setTheme(e,t=!1){document.documentElement.setAttribute("data-theme",e),currentTheme=e;let r="dark"===e?"true":"false";themeSwitcher.setAttribute("aria-pressed",r),t&&localStorage.setItem("theme",e);const h=new CustomEvent("themeChanged",{detail:{theme:e}});window.dispatchEvent(h)}function switchTheme(){setTheme("dark"===currentTheme?"light":"dark",!0)}themeSwitcher.addEventListener("click",switchTheme,!1),themeSwitcher.setAttribute("role","button");let togglePressed="dark"===currentTheme?"true":"false";themeSwitcher.setAttribute("aria-pressed",togglePressed),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(e=>{setTheme(e.matches?"dark":"light")})); +const themeSwitcher=document.querySelector(".theme-switcher"),themeResetter=document.querySelector(".theme-resetter");let currentTheme=localStorage.getItem("theme")||document.documentElement.getAttribute("data-theme");function setTheme(e,t=!1){document.documentElement.setAttribute("data-theme",e);var r="dark"===(currentTheme=e)?"true":"false",r=(themeSwitcher.setAttribute("aria-pressed",r),t?(localStorage.setItem("theme",e),themeResetter.classList.add("has-custom-theme"),themeResetter.setAttribute("aria-hidden","false")):(localStorage.removeItem("theme"),themeResetter.classList.remove("has-custom-theme"),themeResetter.setAttribute("aria-hidden","true")),new CustomEvent("themeChanged",{detail:{theme:e}}));window.dispatchEvent(r)}function resetTheme(){setTheme(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")}function switchTheme(){setTheme("dark"===currentTheme?"light":"dark",!0)}themeSwitcher.addEventListener("click",switchTheme,!1),themeResetter.addEventListener("click",resetTheme,!1),themeSwitcher.setAttribute("role","button");let togglePressed="dark"===currentTheme?"true":"false";themeSwitcher.setAttribute("aria-pressed",togglePressed),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{setTheme(e.matches?"dark":"light")}),localStorage.getItem("theme")?themeResetter.classList.add("has-custom-theme"):themeResetter.classList.remove("has-custom-theme"); diff --git a/templates/partials/theme_switcher.html b/templates/partials/theme_switcher.html index b87bfff..5e1f0dc 100644 --- a/templates/partials/theme_switcher.html +++ b/templates/partials/theme_switcher.html @@ -3,16 +3,27 @@ {%- set toggle_str = macros_translate::translate(key='toggle_mode', default='Toggle $MODE mode', language_strings=language_strings) -%} {%- set dark_str = macros_translate::translate(key='dark', default='dark', language_strings=language_strings) -%} {%- set light_str = macros_translate::translate(key='light', default='light', language_strings=language_strings) -%} - + {%- set combined_mode_str = dark_str ~ "/" ~ light_str -%} {%- set title_label = toggle_str | replace(from="$MODE", to=combined_mode_str) -%} {%- set aria_label = toggle_str | replace(from="$MODE", to=dark_str) -%} - -