Dark theme via DarkReader (#595)

* Initial commit for dark theme.

* Use DarkReader.auto() to watch for system theme.

* Tunning default parameters.

* Allow configurable number of recent posts.

* Added invisible element to hack theme initialization.

* Added default value.

* Use Darkreader CDN.

* Cleanup to keep darkreader in as few files as possible.

* Renamed darkmode.js to darkmode-darkreader.js.

* Bring back the initialization.

* Added provider property.

* Added theme selector to the posts navbar.

* Removed extra line breaks.

* Changed darkreader CDN to local copy.

* Renamed to darkMode.

* Fixed CodeQL failures.

* Added icons.

* Renamed function.

* Added SVG inversion.

* Used icons for selection.

* Toggle initial dark only in the dynamic navbar.

Co-authored-by: donfiguerres <donfiguerres@github.com>
Co-authored-by: Emruz Hossain <hossainemruz@gmail.com>
This commit is contained in:
donfiguerres 2022-06-10 23:18:49 +08:00 committed by GitHub
parent 869eba97a2
commit 65049cfbb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 5791 additions and 1 deletions

View file

@ -15,6 +15,11 @@
<!--=================== icons ==============================-->
<link rel="stylesheet" href="{{ "/fontawesome/css/all.min.css" | relURL }}"/>
<!--=================== dark mode ==========================-->
{{ if site.Params.darkMode.enable }}
<link rel="stylesheet" href="{{ "/css/colortheme/colortheme.css" | relURL }}"/>
{{ end }}
<!--================= fab-icon =========================-->
{{/* add favicon only if the site author has provided the the favicon */}}
{{ if site.Params.logo.favicon }}

View file

@ -47,6 +47,9 @@
{{ if .IsTranslated }}
{{ partial "navigators/lang-selector-2.html" . }}
{{ end }}
{{ if site.Params.darkMode.enable }}
{{ partial "navigators/theme-selector.html" . }}
{{ end }}
</ul>
</div>
</div>

View file

@ -66,7 +66,7 @@
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="top-nav-items">
<div class="collapse navbar-collapse dynamic-navbar" id="top-nav-items">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="#home">{{ i18n "home" }}</a>
@ -124,6 +124,9 @@
{{ if .IsTranslated }}
{{ partial "navigators/lang-selector.html" . }}
{{ end }}
{{ if site.Params.darkMode.enable }}
{{ partial "navigators/theme-selector.html" . }}
{{ end }}
</ul>
</div>
</div>

View file

@ -0,0 +1,20 @@
<li class="nav-item dropdown">
<!-- This is for initializing the color scheme selection for new visitors. See /js/darkmode.js -->
<div id="theme-initialization" style="display: none;"
default-theme="{{ site.Params.darkMode.default }}"></div>
<a class="nav-link dropdown-toggle" href="#" id="themeSelector" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img id="navbar-theme-icon-svg" src="{{ "/icons/moon-svgrepo-com.svg" }}" width=20>
</a>
<div class="dropdown-menu dropdown-menu-icons-only" aria-labelledby="themeSelector">
<a class="dropdown-item nav-link" href="#" onclick="enableLightTheme()">
<img class="menu-icon-center" src="{{ "/icons/sun-svgrepo-com.svg" }}" width=20>
</a>
<a class="dropdown-item nav-link" href="#" onclick="enableDarkTheme()">
<img class="menu-icon-center" src="{{ "/icons/moon-svgrepo-com.svg" }}" width=20>
</a>
<a class="dropdown-item nav-link" href="#" onclick="useSystemTheme()">
<img class="menu-icon-center" src="{{ "/icons/computer-svgrepo-com.svg" }}" width=20>
</a>
</div>
</li>

View file

@ -5,3 +5,10 @@
<script type="text/javascript" src="{{ "/js/navbar.js" | relURL }}"></script>
<script type="text/javascript" src="{{ "/js/plyr.js" | relURL }}"></script>
<script type="text/javascript" src="{{ "/js/main.js" | relURL }}"></script>
{{ if site.Params.darkMode.enable }}
{{ if eq site.Params.darkMode.provider "darkreader" }}
<script type="text/javascript" src="{{ "/js/darkreader.js" | relURL }}"></script>
<script type="text/javascript" src="{{ "/js/darkmode-darkreader.js" | relURL }}"></script>
{{ end }}
{{ end }}

View file

@ -0,0 +1,20 @@
/* Note: No need to invert when the screen is small because the navbar is
collapsed to a hamburger menu. */
@media only screen and (min-width: 1200px) {
.dynamic-navbar .navbar-icon-svg-dark {
filter: invert(1);
};
}
@media only screen and (min-width: 1200px) {
.dropdown-menu-icons-only {
width: 25px;
min-width: 3rem;
}
}
.menu-icon-center {
display: block;
margin-left: auto;
margin-right: auto;
}

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 364 364" style="enable-background:new 0 0 364 364;" xml:space="preserve">
<g>
<path d="M350,60.5h-50c-7.72,0-14,6.28-14,14v225c0,7.72,6.28,14,14,14h50c7.72,0,14-6.28,14-14v-225
C364,66.78,357.72,60.5,350,60.5z M325.864,166.5c-11.23,0-20.333-9.104-20.333-20.333s9.104-20.333,20.333-20.333
s20.333,9.104,20.333,20.333S337.094,166.5,325.864,166.5z"/>
<path d="M230,50.5H30c-16.542,0-30,13.458-30,30v149c0,16.542,13.458,30,30,30h79v21.765c0,0.665-0.466,1.235-0.847,1.235H52.351
C46.092,282.5,41,287.329,41,293.265v9.235c0,5.962,5.198,11,11.351,11h156.604c6.091,0,11.046-4.935,11.046-11v-9.235
c0-6.037-4.852-10.765-11.046-10.765h-55.803c-0.517,0-1.151-0.681-1.151-1.235V259.5h78c16.542,0,30-13.458,30-30v-149
C260,63.958,246.542,50.5,230,50.5z M230,80.5l0.017,133H30v-133H230z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 206.622 206.622" style="enable-background:new 0 0 206.622 206.622;" xml:space="preserve">
<g>
<g>
<g>
<path d="M155.287,58.38c-6.703-7.189-14.65-12.775-23.62-16.603c-1.299-0.552-2.8-0.291-3.83,0.672
c-1.034,0.963-1.4,2.443-0.94,3.777c8.128,23.444,1.654,49.524-16.485,66.441c-18.146,16.918-44.614,21.557-67.43,11.812
c-1.288-0.55-2.8-0.291-3.83,0.672c-1.034,0.963-1.4,2.443-0.94,3.777c3.197,9.218,8.215,17.535,14.918,24.72
c12.721,13.643,29.996,21.517,48.64,22.168c0.836,0.03,1.668,0.043,2.5,0.043c17.728,0,34.54-6.611,47.571-18.764
c13.647-12.724,21.517-29.998,22.168-48.643C174.658,89.807,168.011,72.025,155.287,58.38z M166.883,108.203
c-0.585,16.74-7.655,32.251-19.905,43.675c-12.25,11.423-28.223,17.425-44.959,16.809c-16.743-0.583-32.252-7.652-43.674-19.904
c-4.21-4.511-7.678-9.519-10.363-14.947c23.47,6.872,49.127,0.987,67.291-15.952c18.167-16.941,25.828-42.13,20.608-66.02
c5.23,3.057,9.984,6.867,14.19,11.382C161.496,75.496,167.465,91.464,166.883,108.203z"/>
<path d="M167.607,163.757c-1.393-1.393-3.649-1.393-5.042,0s-1.393,3.649,0,5.042l7.563,7.563
c0.696,0.696,1.609,1.045,2.521,1.045c0.912,0,1.825-0.348,2.521-1.045c1.393-1.393,1.393-3.649,0-5.042L167.607,163.757z"/>
<path d="M170.128,30.259l-7.563,7.565c-1.393,1.393-1.393,3.651,0,5.042c0.696,0.696,1.609,1.045,2.521,1.045
s1.825-0.348,2.521-1.045l7.563-7.565c1.393-1.393,1.393-3.651,0-5.042C173.777,28.866,171.521,28.866,170.128,30.259z"/>
<path d="M103.311,188.793c-1.971,0-3.566,1.597-3.566,3.566v10.697c0,1.969,1.595,3.566,3.566,3.566
c1.971,0,3.566-1.597,3.566-3.566v-10.697C106.877,190.39,105.282,188.793,103.311,188.793z"/>
<path d="M201.371,99.745h-10.697c-1.971,0-3.566,1.597-3.566,3.566c0,1.969,1.595,3.566,3.566,3.566h10.697
c1.971,0,3.566-1.597,3.566-3.566C204.937,101.342,203.341,99.745,201.371,99.745z"/>
<path d="M39.015,42.866c0.696,0.696,1.609,1.045,2.521,1.045s1.825-0.348,2.521-1.045c1.393-1.391,1.393-3.649,0-5.042
l-7.563-7.565c-1.393-1.393-3.649-1.393-5.042,0c-1.393,1.391-1.393,3.649,0,5.042L39.015,42.866z"/>
<path d="M39.015,163.757l-7.563,7.563c-1.393,1.393-1.393,3.649,0,5.042c0.696,0.696,1.609,1.045,2.521,1.045
c0.912,0,1.825-0.348,2.521-1.045l7.563-7.563c1.393-1.393,1.393-3.649,0-5.042C42.664,162.364,40.408,162.364,39.015,163.757z"
/>
<path d="M103.311,17.829c1.971,0,3.566-1.597,3.566-3.566V3.566c0-1.969-1.595-3.566-3.566-3.566
c-1.971,0-3.566,1.597-3.566,3.566v10.697C99.745,16.232,101.34,17.829,103.311,17.829z"/>
<path d="M15.949,99.745H5.251c-1.971,0-3.566,1.597-3.566,3.566c0,1.969,1.595,3.566,3.566,3.566h10.697
c1.971,0,3.566-1.597,3.566-3.566C19.514,101.342,17.919,99.745,15.949,99.745z"/>
</g>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<g id="Sun">
<path d="M32.1318512,18.2793007c-7.7119007,0-13.9863014,6.2743988-13.9863014,13.9862976
s6.2744007,13.9864006,13.9863014,13.9864006s13.9862976-6.274498,13.9862976-13.9864006
S39.84375,18.2793007,32.1318512,18.2793007z M32.1318512,44.2793007c-6.6245003,0-12.0137005-5.3897018-12.0137005-12.0137024
s5.3892002-12.0135975,12.0137005-12.0135975s12.0136986,5.3895988,12.0136986,12.0135975
S38.7563515,44.2793007,32.1318512,44.2793007z"/>
<path d="M32.0000496,13.1688995c0.5522003,0,1-0.4471998,1-1V1c0-0.5527-0.4477997-1-1-1c-0.5522995,0-1,0.4473-1,1v11.1688995
C31.0000496,12.7216997,31.4477501,13.1688995,32.0000496,13.1688995z"/>
<path d="M32.0000496,50.830101c-0.5522995,0-1,0.4472008-1,1V63c0,0.5527,0.4477005,1,1,1c0.5522003,0,1-0.4473,1-1V51.830101
C33.0000496,51.2773018,32.5522499,50.830101,32.0000496,50.830101z"/>
<path d="M62.263649,30.4452991H51.09375c-0.5522003,0-1,0.4473-1,1s0.4477997,1.0000019,1,1.0000019h11.169899
c0.5522995,0,1-0.4473019,1-1.0000019S62.8159485,30.4452991,62.263649,30.4452991z"/>
<path d="M13.90625,31.4452991c0-0.5527-0.447794-1-0.999999-1H1.7363508c-0.5523,0-1,0.4473-1,1s0.4477,1.0000019,1,1.0000019
H12.906251C13.458456,32.4453011,13.90625,31.9979992,13.90625,31.4452991z"/>
<path d="M45.1801491,19.8778992c0.2559013,0,0.5116997-0.097599,0.7070999-0.2929001l7.8988991-7.8984995
c0.3906021-0.3905993,0.3906021-1.0233994,0-1.4139996c-0.3905983-0.3907003-1.0234985-0.3907003-1.4140968,0l-7.8989029,7.8984003
c-0.3905983,0.3906002-0.3905983,1.0233994,0,1.4140987C44.668457,19.7803001,44.9243507,19.8778992,45.1801491,19.8778992z"/>
<path d="M45.887249,45.2030983c-0.3906975-0.3905983-1.0234985-0.3905983-1.4141006,0
c-0.3905983,0.3907013-0.3905983,1.0235023,0,1.4141006l7.8989029,7.8973999
c0.1952972,0.1954002,0.4511986,0.2929993,0.7070999,0.2929993c0.2557983,0,0.5116997-0.097599,0.7069969-0.2929993
c0.3906021-0.3905983,0.3906021-1.0233994,0-1.4139977L45.887249,45.2030983z"/>
<path d="M18.112751,19.5849991c0.1954002,0.1953011,0.4511986,0.2929001,0.7070999,0.2929001
c0.2558002,0,0.5116997-0.097599,0.7069988-0.2929001c0.3906059-0.3906994,0.3906059-1.0234985,0-1.4140987L11.6289501,10.2725
c-0.3906994-0.3907003-1.0234947-0.3907003-1.4140997,0c-0.3906002,0.3906002-0.3906002,1.0234003,0,1.4139996
L18.112751,19.5849991z"/>
<path d="M19.5712509,45.2700996c-0.0177002-0.0208015-0.024601-0.0471992-0.0444012-0.0670013
c-0.3906002-0.3905983-1.0233936-0.3905983-1.4140987,0l-3.9401007,3.9400024l-4.0341949,3.8446999
c-0.3999052,0.3811989-0.415205,1.0139008-0.0339994,1.4137993c0.0192947,0.0203018,0.045495,0.0278015,0.066,0.0460014
c0.0176945,0.0208969,0.0245943,0.0472984,0.0443945,0.0669975c0.1953001,0.1954002,0.4512005,0.2929993,0.7069998,0.2929993
c0.2559004,0,0.5117006-0.097599,0.7070999-0.2929993l3.9401007-3.9398994l4.0341997-3.8446999
c0.3999004-0.3811989,0.415205-1.0139008,0.0340004-1.4137993C19.6179504,45.2958984,19.5917511,45.2882996,19.5712509,45.2700996z
"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,59 @@
const DARK = "dark";
const LIGHT = "light";
const SYSTEM = "system";
const COLOR_THEME = "color-theme";
const DARK_OPTIONS = {
brightness: 100,
contrast: 100,
sepia: 0
};
const SVG_INVERT = {invert: ['img[src$=".svg"]']};
const NAVBAR_ICON_ID = "navbar-theme-icon-svg";
const DARK_ICON = "/icons/moon-svgrepo-com.svg";
const LIGHT_ICON = "/icons/sun-svgrepo-com.svg";
const SYSTEM_ICON = "/icons/computer-svgrepo-com.svg";
function enableDarkTheme() {
localStorage.setItem(COLOR_THEME, DARK);
DarkReader.enable(DARK_OPTIONS, SVG_INVERT);
document.getElementById(NAVBAR_ICON_ID).src = DARK_ICON;
}
function enableLightTheme() {
localStorage.setItem(COLOR_THEME, LIGHT);
DarkReader.disable();
document.getElementById(NAVBAR_ICON_ID).src = LIGHT_ICON;
}
function useSystemTheme() {
localStorage.setItem(COLOR_THEME, SYSTEM);
DarkReader.auto(DARK_OPTIONS, SVG_INVERT);
document.getElementById(NAVBAR_ICON_ID).src = SYSTEM_ICON;
}
function initializeColorTheme() {
// We're using the themeInitialization attributes as a 'hack' for setting up
// the default color scheme because we don't want to complicate this further
// by creating custom javascript output in Hugo.
let themeInitialization = document.getElementById("theme-initialization");
let defaultColorScheme = themeInitialization.getAttribute('default-theme');
// If the user has already selected a preferred theme then use that instead
// of the default theme. Also, the default theme gets loaded to localStorage
// on the first visit.
let colorTheme = localStorage.getItem(COLOR_THEME);
if (colorTheme == null || colorTheme.length == 0) {
colorTheme = defaultColorScheme;
}
// Enable the color theme
if (colorTheme == DARK) {
enableDarkTheme();
} else if (colorTheme == SYSTEM) {
useSystemTheme();
} else {
// We use light theme for the two conditions below.
// 1. the selected theme is light
// 2. no default theme is found - fall back to original behavior
enableLightTheme();
}
}
initializeColorTheme()

5488
static/js/darkreader.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,9 @@ const updateNavBar = () => {
$('#navbar-toggler').removeClass('navbar-dark');
$('#navbar-toggler').addClass('navbar-light');
// color theme selector a.k.a. dark mode
$('#navbar-theme-icon-svg').removeClass('navbar-icon-svg-dark');
// get the main logo from hidden img tag
let mainLogo = document.getElementById("main-logo")
if (mainLogo !== null) {
@ -22,6 +25,9 @@ const updateNavBar = () => {
$('#navbar-toggler').removeClass('navbar-light');
$('#navbar-toggler').addClass('navbar-dark');
// color theme selector a.k.a. dark mode
$('#navbar-theme-icon-svg').addClass('navbar-icon-svg-dark');
// get the inverted logo from hidden img tag
let invertedLogo = document.getElementById("inverted-logo")
if (invertedLogo !== null) {