Skip to content

Commit 9b8fde2

Browse files
authored
Add dark mode switch 32 (#37)
Solves: #32 #27 Signed-off-by: Hofi <[email protected]>
2 parents 26ae5c1 + 8d29527 commit 9b8fde2

25 files changed

+595
-105
lines changed

LICENSE.lunr

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (C) 2013 by Oliver Nightingale
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

_config.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
remote_theme: mmistakes/[email protected]
44
#theme: minimal-mistakes-jekyll
55
minimal_mistakes_skin: "midnight" # "default", "air", "aqua", "contrast", "dark", "dirt", "midnight", "mint", "neon", "plum", "sunrise"
6+
skin_switchable: true
67

78
# Disable caching of content to disk in order to skip creating a .jekyll-cache or similar directory
89
disable_disk_cache: true
@@ -68,10 +69,11 @@ exclude:
6869
- Gemfile.lock
6970
- node_modules
7071
# Shell we add to the generated _site as well?
71-
- LICENSE.minimal-mistakes
72-
- LICENSE.midnight
72+
- LICENSE.*
7373

7474
# Sass/SCSS
75+
# If you are using Sass @import statements, you’ll need to ensure that your sass_dir is set to the base directory that contains your Sass files
76+
# https://jekyllrb.com/docs/assets/#sassscss
7577
sass:
7678
sass_dir: _sass/minimal-mistakes
7779
style: compressed # https://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style
@@ -204,10 +206,15 @@ kramdown:
204206
atom_feed:
205207
hide: true
206208

209+
# https://jch.penibelst.de/
207210
compress_html:
211+
profile: true
208212
clippings: all
209-
ignore:
210-
envs: development # disable compression in dev environment
213+
endings: all
214+
ignore:
215+
# do not use yet, too slow and can cause issues in the final output
216+
# envs: [ development ] disable compression in a given environment
217+
envs: all
211218

212219
# These are introduced with our customized theme source, not part of mmistakes/minimal-mistakes
213220

_includes/head.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@
66
<link href="{% if site.atom_feed.path %}{{ site.atom_feed.path }}{% else %}{{ '/feed.xml' | relative_url }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ site.title }} Feed">
77
{% endunless %}
88

9-
<!-- https://t.co/dKP3o1e -->
109
<meta name="viewport" content="width=device-width, initial-scale=1.0">
1110

12-
<script>
13-
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
14-
</script>
11+
<script>document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';</script>
12+
13+
{% include skins.html %}
1514

16-
<!-- For all browsers -->
17-
<link rel="stylesheet" href="{{ '/assets/css/main.css' | relative_url }}">
1815
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
1916
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
2017

_includes/masthead.html

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
<div class="masthead__inner-wrap">
55
<div class="masthead__menu">
66
<nav id="site-nav" class="greedy-nav">
7+
78
{% unless logo_path == empty %}
89
<a class="site-logo" href="{{ '/' | relative_url }}"><img src="{{ logo_path | relative_url }}" alt="{{ site.masthead_title | default: site.title }}"></a>
910
{% endunless %}
1011
<a class="site-title" href="{{ '/' | relative_url }}">
1112
{{ site.masthead_title | default: site.title }}
1213
{% if site.subtitle %}<span class="site-subtitle">{{ site.subtitle }}</span>{% endif %}
1314
</a>
15+
1416
<ul class="visible-links">
1517
{% if site.masthead.hide_navigator == false %}
1618
{%- for link in site.data.navigation.main -%}
@@ -20,17 +22,33 @@
2022
{%- endfor -%}
2123
{% endif %}
2224
</ul>
25+
2326
{% if site.search == true %}
24-
<button class="search__toggle" type="button">
25-
<span id="searchHint" class="">{{ site.data.ui-text[site.locale].search_label | default: "Toggle search (Shift + Ctrl + F or ESC to close)" }}</span>
26-
<i class="fas fa-search"></i>
27+
{% comment %}<!-- search__toggle is kept fir bacjward compatibility -->{% endcomment %}
28+
<button id="search-button" class="masthead_button search__toggle" type="button">
29+
<span id="search_hint" class="">{{ site.data.ui-text[site.locale].search_label | default: "Toggle search (Shift + Ctrl + F or ESC to close)" }}</span>
30+
<i class="masthead_button_icon fas fa-search" style="font-size: 120%;"></i>
31+
</button>
32+
{% endif %}
33+
34+
{% if site.skin_switchable == true %}
35+
<i class="masthead_button_small_img fa fa-sun"></i>
36+
<button id="skin-button" class="masthead_button_with_side_image" type="button">
37+
<i class="masthead_button_icon fa fa-toggle-off" style="font-size: 150%;"></i>
2738
</button>
39+
<i class="masthead_button_small_img fa fa-moon"></i>
2840
{% endif %}
41+
42+
<button id="settings-button" class="masthead_button_last" type="button">
43+
<i class="masthead_button_icon fas fa-user-cog" style="font-size: 110%;"></i>
44+
</button>
45+
2946
<button class="greedy-nav__toggle hidden" type="button">
3047
<span class="visually-hidden">{{ site.data.ui-text[site.locale].menu_label | default: "Toggle menu" }}</span>
3148
<div class="navicon"></div>
3249
</button>
3350
<ul class="hidden-links hidden"></ul>
51+
3452
</nav>
3553
</div>
3654
</div>

_includes/search/algolia-search-scripts.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ <h2 class="archive__item-title" itemprop="headline"><a href="{{ site.baseurl }}$
5353

5454
// Starting the search only when toggle is clicked
5555
$(document).ready(function () {
56-
$(".search__toggle").on("click", function() {
56+
$("#search-button").on("click", function() {
5757
if(!search.started) {
5858
search.start();
5959
}

_includes/search/search_form.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<label class="sr-only" for="search">
77
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
88
</label>
9-
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
9+
<input type="search" id="search" class="search-input" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
1010
<a class="search-help content-tooltip full-content-tooltip nav-link" href="/lunr_search_help.html">[ Hover or click for search help ]</a>
1111
</form>
1212
<div id="results" class="results"></div>
@@ -15,7 +15,7 @@
1515
<label class="sr-only" for="cse-search-input-box-id">
1616
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
1717
</label>
18-
<input type="search" id="cse-search-input-box-id" class="search-input" tabindex="-1" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
18+
<input type="search" id="cse-search-input-box-id" class="search-input" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
1919
</form>
2020
<div id="results" class="results">
2121
<gcse:searchresults-only></gcse:searchresults-only>

_includes/skins.html

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{% comment %}
2+
<!-- Dynamic loading of the user selected skin stylesheet -->
3+
{% endcomment %}
4+
5+
{% comment %}<!-- NOTE: the 'default' skin is in the 'main.css', see the main.scss file for details -->{% endcomment %}
6+
<link rel="stylesheet" id="skinedStylesheet" href="{{ '/assets/css/main.css' | relative_url }}">
7+
8+
<style>
9+
#full-page-container.full-page-container {
10+
position: fixed;
11+
top: 0;
12+
left: 0;
13+
width: 100%;
14+
height: 100%;
15+
display: contents;
16+
}
17+
18+
#full-page-container.hidden {
19+
visibility: hidden;
20+
display: none;
21+
}
22+
</style>
23+
24+
<script async="false">
25+
26+
const docRoot = '{{ site.baseurl }}';
27+
const darkSkin = 'midnight';
28+
const lightSkin = 'default';
29+
30+
function docPrefix() {
31+
return (docRoot != '' ? docRoot + '/' : '');
32+
}
33+
34+
function setCookie(name, value, days) {
35+
var expires = "";
36+
if (days) {
37+
var date = new Date();
38+
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
39+
expires = "; expires=" + date.toUTCString();
40+
}
41+
document.cookie = name + "=" + (value || "") + expires + "; path=/; SameSite=Strict";
42+
}
43+
44+
function getCookie(name, defaultValue = null) {
45+
var nameEQ = name + "=";
46+
var ca = document.cookie.split(';');
47+
for (var i = 0; i < ca.length; i++) {
48+
var c = ca[i];
49+
while (c.charAt(0) == ' ') {
50+
c = c.substring(1, c.length);
51+
}
52+
if (c.indexOf(nameEQ) == 0) {
53+
return c.substring(nameEQ.length, c.length);
54+
}
55+
}
56+
return defaultValue;
57+
}
58+
59+
(function () {
60+
function setSkin(skin) {
61+
const stylesheet = document.getElementById('skinedStylesheet');
62+
//stylesheet.onload = saveChanges;
63+
stylesheet.href = docPrefix() + '/assets/css/main' + (skin == 'default' ? '' : '_' + skin) + '.css';
64+
setCookie('skin', skin, 365 * 100);
65+
}
66+
67+
function toggleSkin(event) {
68+
if (getCookie('skin', 'default') == darkSkin) {
69+
event.target.classList.remove('fa-toggle-on');
70+
event.target.classList.add('fa-toggle-off');
71+
setSkin(lightSkin);
72+
}
73+
else {
74+
event.target.classList.remove('fa-toggle-off');
75+
event.target.classList.add('fa-toggle-on');
76+
setSkin(darkSkin);
77+
}
78+
event.currentTarget.blur();
79+
}
80+
81+
function toggleIcon(target, off) {
82+
if (off) {
83+
target.classList.remove('fa-toggle-on');
84+
target.classList.add('fa-toggle-off');
85+
}
86+
else {
87+
target.classList.remove('fa-toggle-off');
88+
target.classList.add('fa-toggle-on');
89+
}
90+
}
91+
92+
function toggleSkin(event) {
93+
var off = getCookie('skin', 'default') == darkSkin;
94+
95+
if (off)
96+
setSkin(lightSkin);
97+
else
98+
setSkin(darkSkin);
99+
toggleIcon(event.target, off);
100+
101+
event.currentTarget.blur();
102+
}
103+
104+
/* As of the dynamic skin stylsheet loading, it is better to wait for the finish of the whole page content load and rendering to avoid apperance of
105+
half rendered content parts (it is better to see an empty content even if it might appear in a different bacground color that the skin has)
106+
*/
107+
window.addEventListener("load", function () {
108+
function saveChanges() {
109+
const htmlStyle = window.getComputedStyle(document.documentElement);
110+
const backgroundColor = htmlStyle.backgroundColor;
111+
setCookie('skin-background-color', backgroundColor, 365 * 100);
112+
};
113+
114+
var container = document.getElementById("full-page-container");
115+
if (container)
116+
container.classList.remove('hidden');
117+
118+
// Why this is not working?!?!
119+
//document.body.style.removeProperty("backgroundColor");
120+
document.body.style.backgroundColor = "";
121+
if (storedSkin !== 'default')
122+
toggleIcon($('#skin-button').find('.masthead_button_icon')[0], false);
123+
124+
$("#skin-button").on("click", toggleSkin);
125+
126+
saveChanges();
127+
});
128+
129+
document.addEventListener("DOMContentLoaded", function () {
130+
const skinBackgroundColor = getCookie('skin-background-color');
131+
if (skinBackgroundColor)
132+
document.body.style.backgroundColor = skinBackgroundColor;
133+
});
134+
135+
const storedSkin = getCookie('skin', 'default');
136+
if (storedSkin !== 'default')
137+
setSkin(storedSkin);
138+
139+
})();
140+
</script>

_js/custom/navigation.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
========================================================================== */
44

55
$(function () {
6-
// FIXME: How to get the real base URL (without using Liquid and Front Matter) ?!?!
7-
const docRoot = '';
86
const notFoundPageName = '404.html';
97
const contentID = 'article';
108

@@ -175,7 +173,7 @@ $(function () {
175173
error => {
176174
if (error == "Error: 404") {
177175
var baseURL = window.location.origin;
178-
var notFoundURL = baseURL + '/' + (docRoot != '' ? docRoot + '/' : '') + notFoundPageName;
176+
var notFoundURL = baseURL + '/' + docPrefix() + notFoundPageName;
179177

180178
updateContentFromUrl(notFoundURL);
181179
}
@@ -467,7 +465,7 @@ $(function () {
467465
}
468466

469467
function shouldHideTooltip(activeTarget) {
470-
return ((tooltipTarget == null || activeTarget != tooltipTarget) && (tooltip == null || (activeTarget != tooltip && activeTarget.closest('.tooltip') == null)));
468+
return ((tooltipTarget == null || activeTarget != tooltipTarget) && (tooltip == null || (activeTarget != tooltip && activeTarget != null && activeTarget.closest('.tooltip') == null)));
471469
}
472470

473471
function hideTooltip(withDelay) {
@@ -563,7 +561,7 @@ $(function () {
563561
}
564562
});
565563

566-
document.addEventListener("mouseover", function (event) {
564+
document.addEventListener('mouseover', function (event) {
567565
elementUnderCursor = event.target;
568566
});
569567

@@ -601,22 +599,22 @@ $(function () {
601599
// -------------
602600

603601
// Close search screen with Esc key or toggle with predefined hotKey
604-
$(document).on("keyup", function (event) {
602+
$(document).on('keyup', function (event) {
605603
// Define the desired hotkey (in this case, Ctrl + Shift + F)
606604
var searchHotkey = { ctrlKey: true, shiftKey: true, key: 'F' };
607605

608606
if (event.keyCode === 27) {
609607
if ($(".initial-content").hasClass("is--hidden"))
610-
toggleSearch();
608+
toggleSearch(event);
611609
}
612610
else if (event.ctrlKey === searchHotkey.ctrlKey &&
613611
event.shiftKey === searchHotkey.shiftKey &&
614612
event.key === searchHotkey.key) {
615-
toggleSearch();
613+
toggleSearch(event);
616614
}
617615
});
618616

619-
function toggleSearch() {
617+
function toggleSearch(event) {
620618
$(".search-content").toggleClass("is--visible");
621619
$(".initial-content").toggleClass("is--hidden");
622620

@@ -635,9 +633,11 @@ $(function () {
635633

636634
if (tooltipTarget)
637635
hideTooltip(true);
636+
// NOTE: event.target is not always the toggle here, use it directly instead of the event
637+
$("#search-button").trigger('blur');
638638
}
639639

640-
$(".search__toggle").on("click", toggleSearch);
640+
$("#search-button").on('click', toggleSearch);
641641

642642
// -------------
643643
// Startup

0 commit comments

Comments
 (0)