hematite 0.0.8 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/_config.yml +2 -1
- data/_includes/footer.html +6 -0
- data/_includes/nav/header.html +5 -0
- data/_includes/nav/page_navigation.html +1 -1
- data/_includes/nav/sidebar.html +16 -2
- data/_layouts/default.html +2 -0
- data/_sass/_colors.scss +49 -38
- data/_sass/_elements.scss +58 -4
- data/_sass/_layout.scss +3 -3
- data/_sass/_nav.scss +32 -2
- data/_sass/_sizes.scss +4 -2
- data/_sass/hematite.scss +5 -1
- data/assets/html/settings.html +103 -0
- data/assets/js/Settings.mjs +181 -0
- data/assets/js/main.mjs +4 -0
- data/assets/js/sidebar.mjs +14 -2
- data/assets/string_data/en.mjs +22 -0
- data/assets/string_data/es.mjs +19 -0
- data/assets/style.scss +2 -6
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5f6a0cdf074d0025f0cf3031037a4dc365af38f99aa811578f3d88f0c356175
|
4
|
+
data.tar.gz: 533d5d2c8897c2985977971c5a6ca66552df1edee4bae22c9184750e97478007
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be650d2182b5d2dccdc6bccc3837691246f94bf8271bda4343cd923e7da5eb2c9fa3ddc960f35d2711c13cf51b574f3b27eddd47f31afc3c8688e231ab22afe7
|
7
|
+
data.tar.gz: 7ebc7f1a7902040eb224a1adb08da8115207303e028e4bad22d608f061e11a3f5450da65c2e572da68a10317c835ba73469d1ebef1c7a9f2a182a5567eb4f80f
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Hematite
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/hematite.svg)](https://badge.fury.io/rb/hematite)
|
2
3
|
|
3
4
|
![The dark variant of the Hematite Theme, showing a calendar](./screenshot.png)
|
4
5
|
|
@@ -50,7 +51,8 @@ Your theme is setup just like a normal Jekyll site! To test your theme, run `bun
|
|
50
51
|
When your theme is released, only the files in `_layouts`, `_includes`, `_sass` and `assets` tracked with Git will be bundled.
|
51
52
|
To add a custom directory to your theme-gem, please edit the regexp in `Hematite.gemspec` accordingly.
|
52
53
|
|
53
|
-
**Note:** All user-facing strings
|
54
|
+
**Note:** All user-facing strings that are distributed with the theme should go in
|
55
|
+
[assets/string_data](https://github.com/personalizedrefrigerator/jekyll-hematite-theme/tree/main/assets/string_data) to permit future localization.
|
54
56
|
|
55
57
|
## License
|
56
58
|
|
data/_config.yml
CHANGED
@@ -33,6 +33,7 @@ hematite:
|
|
33
33
|
month_first: true
|
34
34
|
|
35
35
|
sidebar:
|
36
|
-
footer_html: 'This page was made with the Hematite Theme. <a href="https://github.com/personalizedrefrigerator/jekyll-hematite-theme">Contribute on GitHub
|
36
|
+
footer_html: 'This page was made with the Hematite Theme. <a href="https://github.com/personalizedrefrigerator/jekyll-hematite-theme">Contribute on GitHub.</a>'
|
37
|
+
show_settings_btn: true
|
37
38
|
|
38
39
|
|
data/_includes/nav/sidebar.html
CHANGED
@@ -18,8 +18,22 @@
|
|
18
18
|
</ul>
|
19
19
|
|
20
20
|
<footer>
|
21
|
-
|
22
|
-
{
|
21
|
+
<div>
|
22
|
+
{% if site.hematite.sidebar.footer_html %}
|
23
|
+
{{ site.hematite.sidebar.footer_html }}
|
24
|
+
{% endif %}
|
25
|
+
</div>
|
26
|
+
{% if site.hematite.sidebar.show_settings_btn %}
|
27
|
+
<center>
|
28
|
+
<!-- Localized by JS -->
|
29
|
+
<a id="sidebar_settings_btn" class="settings-btn"
|
30
|
+
{% if site.permalink == 'pretty' %}
|
31
|
+
href="{{ 'assets/html/settings' | relative_url }}"
|
32
|
+
{% else %}
|
33
|
+
href="{{ 'assets/html/settings.html' | relative_url }}"
|
34
|
+
{% endif %}
|
35
|
+
></a>
|
36
|
+
</center>
|
23
37
|
{% endif %}
|
24
38
|
</footer>
|
25
39
|
</nav>
|
data/_layouts/default.html
CHANGED
data/_sass/_colors.scss
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
:root {
|
1
|
+
:root:not(.darkTheme), :root.lightTheme {
|
2
2
|
--primary-text-color: black;
|
3
3
|
--secondary-text-color: black;
|
4
4
|
--text-color-faint: #444;
|
@@ -16,16 +16,10 @@
|
|
16
16
|
|
17
17
|
--shadow-color-light: rgba(0, 0, 0, 0.6);
|
18
18
|
--line-color-light: #eee;
|
19
|
+
--line-color-normal: #888;
|
19
20
|
--code-background-color: #fafafa;
|
20
|
-
}
|
21
21
|
|
22
|
-
@media screen {
|
23
|
-
:root {
|
24
|
-
--code-background-color: #f9f5f5;
|
25
|
-
}
|
26
|
-
}
|
27
22
|
|
28
|
-
:root {
|
29
23
|
// Syntax highlighting
|
30
24
|
--syntax-keyword-fg: #d00;
|
31
25
|
--syntax-string-fg: #c07;
|
@@ -37,37 +31,54 @@
|
|
37
31
|
--syntax-normal-fg: black;
|
38
32
|
}
|
39
33
|
|
34
|
+
@media screen {
|
35
|
+
:root:not(.darkTheme), :root.lightTheme {
|
36
|
+
--code-background-color: #f9f5f5;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
@mixin dark-theme-colors {
|
41
|
+
--primary-text-color: white;
|
42
|
+
--secondary-text-color: white;
|
43
|
+
--text-color-faint: #ccc;
|
44
|
+
--link-color: #fa0;
|
45
|
+
--visited-link-color: #f0a;
|
46
|
+
|
47
|
+
--selected-item-fg-color: white;
|
48
|
+
--selected-item-bg-color: #530033;
|
49
|
+
|
50
|
+
--primary-background-color: black;
|
51
|
+
--secondary-background-color: #111;
|
52
|
+
--code-background-color: #222;
|
53
|
+
--line-color-light: #222;
|
54
|
+
--line-color-normal: #aaa;
|
55
|
+
|
56
|
+
--color-alert-background: #300;
|
57
|
+
--color-alert-foreground: white;
|
58
|
+
|
59
|
+
--shadow-color-light: rgba(200, 200, 200, 0.5);
|
60
|
+
|
61
|
+
|
62
|
+
// Syntax highlighting
|
63
|
+
--syntax-keyword-fg: pink;
|
64
|
+
--syntax-string-fg: #cfc;
|
65
|
+
--syntax-number-fg: #eef;
|
66
|
+
--syntax-bracket-fg: #faf;
|
67
|
+
--syntax-operator-fg: #aff;
|
68
|
+
--syntax-comment-fg: #aef;
|
69
|
+
--syntax-name-fg: #edf;
|
70
|
+
--syntax-normal-fg: white;
|
71
|
+
}
|
72
|
+
|
40
73
|
@media screen and (prefers-color-scheme: dark) {
|
41
|
-
:root {
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
--selected-item-bg-color: #530033;
|
50
|
-
|
51
|
-
--primary-background-color: black;
|
52
|
-
--secondary-background-color: #111;
|
53
|
-
--code-background-color: #222;
|
54
|
-
--line-color-light: #222;
|
55
|
-
|
56
|
-
--color-alert-background: #300;
|
57
|
-
--color-alert-foreground: white;
|
58
|
-
|
59
|
-
--shadow-color-light: rgba(200, 200, 200, 0.5);
|
60
|
-
|
61
|
-
|
62
|
-
// Syntax highlighting
|
63
|
-
--syntax-keyword-fg: pink;
|
64
|
-
--syntax-string-fg: #cfc;
|
65
|
-
--syntax-number-fg: #eef;
|
66
|
-
--syntax-bracket-fg: #faf;
|
67
|
-
--syntax-operator-fg: #aff;
|
68
|
-
--syntax-comment-fg: #aef;
|
69
|
-
--syntax-name-fg: #edf;
|
70
|
-
--syntax-normal-fg: white;
|
74
|
+
:root:not(.lightTheme) {
|
75
|
+
@include dark-theme-colors;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
@media screen {
|
80
|
+
:root.darkTheme {
|
81
|
+
@include dark-theme-colors;
|
71
82
|
}
|
72
83
|
}
|
73
84
|
|
data/_sass/_elements.scss
CHANGED
@@ -33,15 +33,19 @@ button[disabled] {
|
|
33
33
|
cursor: not-allowed;
|
34
34
|
}
|
35
35
|
|
36
|
-
input {
|
36
|
+
input, select, textarea {
|
37
37
|
color: var(--secondary-text-color);
|
38
38
|
background-color: var(--secondary-background-color);
|
39
|
-
border: 1px solid var(--line-color-
|
39
|
+
border: 1px solid var(--line-color-normal);
|
40
40
|
border-radius: 4px;
|
41
41
|
padding: 5px;
|
42
42
|
|
43
|
-
font-family:
|
44
|
-
font-size:
|
43
|
+
font-family: var(--main-font-family);
|
44
|
+
font-size: var(--main-font-size);
|
45
|
+
}
|
46
|
+
|
47
|
+
select {
|
48
|
+
cursor: pointer;
|
45
49
|
}
|
46
50
|
|
47
51
|
input::placeholder {
|
@@ -112,6 +116,15 @@ input::placeholder {
|
|
112
116
|
box-shadow: inset -1px -1px 4px var(--shadow-color-light);
|
113
117
|
}
|
114
118
|
}
|
119
|
+
|
120
|
+
table td {
|
121
|
+
border: 1px solid var(--line-color-light);
|
122
|
+
}
|
123
|
+
|
124
|
+
fieldset {
|
125
|
+
border-color: var(--line-color-normal);
|
126
|
+
margin-bottom: 30px;
|
127
|
+
}
|
115
128
|
}
|
116
129
|
|
117
130
|
// Markdown parsers may put `code` elements inside of `pre`
|
@@ -123,3 +136,44 @@ input::placeholder {
|
|
123
136
|
// Let the `pre` handle the padding
|
124
137
|
padding: 0;
|
125
138
|
}
|
139
|
+
|
140
|
+
a.settings-btn {
|
141
|
+
color: var(--text-color-faint);
|
142
|
+
border-radius: 4px;
|
143
|
+
padding: 3px;
|
144
|
+
transition: box-shadow 0.5s ease, border 0.5s ease;
|
145
|
+
border: 1px solid transparent;
|
146
|
+
|
147
|
+
&:hover {
|
148
|
+
box-shadow: 0 0 4px var(--shadow-color-light);
|
149
|
+
border: 1px solid var(--line-color-light);
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
// Invert while trying to preserve color hue.
|
154
|
+
@mixin img-invert {
|
155
|
+
filter: invert(1) hue-rotate(180deg);
|
156
|
+
}
|
157
|
+
|
158
|
+
@media (prefers-color-scheme: dark) {
|
159
|
+
:root:not(.lightTheme) main img.auto-invert {
|
160
|
+
@include img-invert;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
:root.darkTheme main img.auto-invert {
|
165
|
+
@include img-invert;
|
166
|
+
}
|
167
|
+
|
168
|
+
// Users can `include' this to invert images automatically in dark mode.
|
169
|
+
@mixin auto-invert-images {
|
170
|
+
@media (prefers-color-scheme: dark) {
|
171
|
+
:root:not(.lightTheme) main img:not(.no-invert) {
|
172
|
+
@include img-invert;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
:root.darkTheme main img:not(.no-invert) {
|
177
|
+
@include img-invert;
|
178
|
+
}
|
179
|
+
}
|
data/_sass/_layout.scss
CHANGED
@@ -34,8 +34,8 @@ body {
|
|
34
34
|
padding-bottom: 140px;
|
35
35
|
margin: 0;
|
36
36
|
|
37
|
-
font-size:
|
38
|
-
font-family:
|
37
|
+
font-size: var(--main-font-size);
|
38
|
+
font-family: var(--main-font-family);
|
39
39
|
color: var(--primary-text-color);
|
40
40
|
}
|
41
41
|
|
@@ -109,7 +109,7 @@ nav#post_next_prev {
|
|
109
109
|
background-color: var(--color-alert-background);
|
110
110
|
color: var(--color-alert-foreground);
|
111
111
|
|
112
|
-
font-family:
|
112
|
+
font-family: var(--main-font-family);
|
113
113
|
font-size: 14pt;
|
114
114
|
|
115
115
|
padding: 20px;
|
data/_sass/_nav.scss
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
$header-z-index: 100;
|
4
4
|
|
5
|
-
header {
|
5
|
+
body > header {
|
6
6
|
position: sticky;
|
7
7
|
top: 0;
|
8
8
|
z-index: $header-z-index;
|
@@ -41,6 +41,33 @@ header {
|
|
41
41
|
}
|
42
42
|
}
|
43
43
|
|
44
|
+
:root.minimizedNavHeader body > header {
|
45
|
+
> *:not(#toggle_sidebar_btn) {
|
46
|
+
opacity: 0;
|
47
|
+
display: inline-block;
|
48
|
+
transition: opacity 0.5s ease;
|
49
|
+
}
|
50
|
+
|
51
|
+
word-wrap: break-word;
|
52
|
+
width: var(--header-height);
|
53
|
+
padding: 0;
|
54
|
+
transition: width 0.5s ease;
|
55
|
+
|
56
|
+
position: fixed;
|
57
|
+
|
58
|
+
// The minimizedNavHeader class is added after page load. Make the
|
59
|
+
// transition less jarring.
|
60
|
+
animation: fade-in 0.5s ease 1;
|
61
|
+
}
|
62
|
+
|
63
|
+
:root.minimizedNavHeader.hasOpenSidebar body > header {
|
64
|
+
> *:not(#toggle_sidebar_btn) {
|
65
|
+
opacity: 1;
|
66
|
+
}
|
67
|
+
|
68
|
+
width: calc(var(--nav-width) + #{2 * $navbar-padding});
|
69
|
+
}
|
70
|
+
|
44
71
|
nav.sidebar {
|
45
72
|
position: fixed;
|
46
73
|
top: var(--header-height);
|
@@ -58,7 +85,7 @@ nav.sidebar {
|
|
58
85
|
color: var(--primary-text-color);
|
59
86
|
background-color: var(--primary-background-color);
|
60
87
|
box-shadow: 0 0 2px var(--shadow-color-light);
|
61
|
-
padding:
|
88
|
+
padding: $navbar-padding;
|
62
89
|
|
63
90
|
z-index: $header-z-index - 1;
|
64
91
|
|
@@ -79,6 +106,9 @@ nav.sidebar {
|
|
79
106
|
input {
|
80
107
|
flex-grow: 1;
|
81
108
|
flex-shrink: 1;
|
109
|
+
|
110
|
+
// Allow it to shrink
|
111
|
+
min-width: 20px;
|
82
112
|
}
|
83
113
|
}
|
84
114
|
|
data/_sass/_sizes.scss
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
|
2
|
-
// Macro-like variables
|
3
2
|
$site-content-preferred-width: 700px;
|
4
|
-
$font-size-main: 12pt;
|
5
3
|
$content-main-padding: 30px;
|
4
|
+
$navbar-padding: 10px;
|
6
5
|
|
7
6
|
// CSS variables
|
8
7
|
:root {
|
8
|
+
// We want these variables to be changable dynamically,
|
9
|
+
// so they're CSS variables.
|
10
|
+
--main-font-size: 12pt;
|
9
11
|
--nav-font-size: 22pt;
|
10
12
|
--header-height: 30pt;
|
11
13
|
--nav-width: 300px;
|
data/_sass/hematite.scss
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
@charset "utf-8";
|
2
2
|
|
3
|
-
|
3
|
+
:root {
|
4
|
+
--serif-font-family: 'FoulisGreek', 'EB Garamond', 'TeX Gyre Bonum', serif;
|
5
|
+
--sans-font-family: 'URW Gothic, Book', 'TeX Gyre Adventor', 'Ubuntu', sans-serif;
|
6
|
+
--main-font-family: var(--serif-font-family);
|
7
|
+
}
|
4
8
|
|
5
9
|
@import "_colors";
|
6
10
|
@import "_sizes";
|
@@ -0,0 +1,103 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: Settings
|
4
|
+
noindex: true
|
5
|
+
---
|
6
|
+
|
7
|
+
<noscript>JavaScript is required to view this page's content!</noscript>
|
8
|
+
|
9
|
+
<!-- So they can be localized, much of this page is filled by JavaScript -->
|
10
|
+
<h1 id="settings_header">page_settings_header</h1>
|
11
|
+
<p id="settings_description">page_settings_description</p>
|
12
|
+
|
13
|
+
<!-- Organization inspired by https://www.w3.org/WAI/tutorials/forms/grouping/ -->
|
14
|
+
<fieldset>
|
15
|
+
<legend id="font_legend">settings_font_legend</legend>
|
16
|
+
<div>
|
17
|
+
<label id="font_family_lbl" for="font_family">settings_font_family_label</label>
|
18
|
+
<select id="font_family"></select>
|
19
|
+
</div>
|
20
|
+
<div>
|
21
|
+
<label id="font_size_lbl" for="font_size">settings_font_size_label</label>
|
22
|
+
<select id="font_size">
|
23
|
+
</select>
|
24
|
+
</div>
|
25
|
+
</fieldset>
|
26
|
+
|
27
|
+
<fieldset>
|
28
|
+
<legend id="theme_legend">page_theme_legend</legend>
|
29
|
+
<div>
|
30
|
+
<label id="page_theme_lbl" for="page_theme">settings_theme_label</label>
|
31
|
+
<select id="page_theme"></select>
|
32
|
+
</div>
|
33
|
+
<div>
|
34
|
+
<label id="page_minimize_header_lbl" for="minimize_page_hdr">settings_minimize_header</label>
|
35
|
+
<input type="checkbox" id="minimize_page_hdr"/>
|
36
|
+
</fieldset>
|
37
|
+
|
38
|
+
<script type="module">
|
39
|
+
import Settings from "{{ 'assets/js/Settings.mjs' | relative_url }}";
|
40
|
+
import { stringLookup } from "{{ 'assets/js/strings.mjs' | relative_url }}";
|
41
|
+
|
42
|
+
let settingsTextElemIDs = [
|
43
|
+
`settings_header`, `settings_description`, `font_legend`,
|
44
|
+
`font_family_lbl`, `font_size_lbl`, `theme_legend`,
|
45
|
+
`page_theme_lbl`, `page_minimize_header_lbl`,
|
46
|
+
];
|
47
|
+
|
48
|
+
// Localize all descriptive settings elements (each should contian the
|
49
|
+
// name of its localization key).
|
50
|
+
for (const id of settingsTextElemIDs) {
|
51
|
+
let elem = document.querySelector(`#${id}`);
|
52
|
+
elem.innerText = stringLookup(elem.innerText);
|
53
|
+
}
|
54
|
+
|
55
|
+
let fontSizeSelect = document.querySelector("#font_size");
|
56
|
+
let fontFamilySelect = document.querySelector("#font_family");
|
57
|
+
let pageThemeSelect = document.querySelector("#page_theme");
|
58
|
+
let minimizeHeaderCheckbox = document.querySelector("#minimize_page_hdr");
|
59
|
+
|
60
|
+
pageThemeSelect.innerHTML =
|
61
|
+
`
|
62
|
+
<option value='${Settings.THEME_AUTO}'>${stringLookup('page_theme_auto')}</option>
|
63
|
+
<option value='${Settings.THEME_DARK}'>${stringLookup('page_theme_dark')}</option>
|
64
|
+
<option value='${Settings.THEME_LIGHT}'>${stringLookup('page_theme_light')}</option>
|
65
|
+
`;
|
66
|
+
|
67
|
+
fontFamilySelect.innerHTML =
|
68
|
+
`
|
69
|
+
<option value='${Settings.FONT_DEFAULT}'>${stringLookup('page_font_default')}</option>
|
70
|
+
<option value='${Settings.FONT_SERIF}'>${stringLookup('page_font_serif')}</option>
|
71
|
+
<option value='${Settings.FONT_SANS}'>${stringLookup('page_font_sans')}</option>
|
72
|
+
`;
|
73
|
+
|
74
|
+
fontSizeSelect.innerHTML =
|
75
|
+
`
|
76
|
+
<option value='${Settings.FONT_SIZE_DEFAULT}'>${stringLookup('page_font_default')}</option>
|
77
|
+
<option value='${Settings.FONT_SIZE_SMALL}'>${stringLookup('page_font_small')}</option>
|
78
|
+
<option value='${Settings.FONT_SIZE_MEDIUM}'>${stringLookup('page_font_medium')}</option>
|
79
|
+
<option value='${Settings.FONT_SIZE_LARGE}'>${stringLookup('page_font_large')}</option>
|
80
|
+
`;
|
81
|
+
|
82
|
+
fontSizeSelect.oninput = () => {
|
83
|
+
Settings.setFontSize(fontSizeSelect.value);
|
84
|
+
};
|
85
|
+
|
86
|
+
fontFamilySelect.oninput = () => {
|
87
|
+
Settings.setFontFamily(fontFamilySelect.value);
|
88
|
+
};
|
89
|
+
|
90
|
+
pageThemeSelect.oninput = () => {
|
91
|
+
Settings.setTheme(pageThemeSelect.value);
|
92
|
+
};
|
93
|
+
|
94
|
+
minimizeHeaderCheckbox.oninput = () => {
|
95
|
+
Settings.setHeaderMinimized(minimizeHeaderCheckbox.checked);
|
96
|
+
};
|
97
|
+
|
98
|
+
pageThemeSelect.value = Settings.getTheme();
|
99
|
+
fontFamilySelect.value = Settings.getFontFamily();
|
100
|
+
fontSizeSelect.value = Settings.getFontSize();
|
101
|
+
minimizeHeaderCheckbox.checked = Settings.getHeaderMinimized();
|
102
|
+
|
103
|
+
</script>
|
@@ -0,0 +1,181 @@
|
|
1
|
+
---
|
2
|
+
---
|
3
|
+
import AsyncUtil from "./AsyncUtil.mjs";
|
4
|
+
import AnimationUtil from "./AnimationUtil.mjs";
|
5
|
+
|
6
|
+
const THEME_TRANSITION_TIME = 500; // ms
|
7
|
+
|
8
|
+
class Settings {
|
9
|
+
THEME_AUTO = 'auto';
|
10
|
+
THEME_DARK = 'dark';
|
11
|
+
THEME_LIGHT = 'light';
|
12
|
+
|
13
|
+
FONT_DEFAULT = 'default';
|
14
|
+
FONT_SANS = 'sans';
|
15
|
+
FONT_SERIF = 'serif';
|
16
|
+
|
17
|
+
FONT_SIZE_SMALL = 'small';
|
18
|
+
FONT_SIZE_MEDIUM = 'medium';
|
19
|
+
FONT_SIZE_LARGE = 'large';
|
20
|
+
FONT_SIZE_DEFAULT = 'default';
|
21
|
+
|
22
|
+
FONT_SIZE_KEY_ = 'hematite-setting-font-size';
|
23
|
+
FONT_FAMILY_KEY_ = 'hematite-setting-font-family';
|
24
|
+
THEME_KEY_ = 'hematite-setting-theme';
|
25
|
+
HEADER_MINIMIZED_KEY_ = 'hematite-setting-minimize-header';
|
26
|
+
|
27
|
+
constructor() {
|
28
|
+
}
|
29
|
+
|
30
|
+
getSetting_(key) {
|
31
|
+
return localStorage.getItem(key);
|
32
|
+
}
|
33
|
+
|
34
|
+
setSetting_(key, val) {
|
35
|
+
localStorage.setItem(key, val);
|
36
|
+
this.applySettings();
|
37
|
+
}
|
38
|
+
|
39
|
+
getTheme() {
|
40
|
+
return this.getSetting_(this.THEME_KEY_) ?? this.THEME_AUTO;
|
41
|
+
}
|
42
|
+
|
43
|
+
getFontFamily() {
|
44
|
+
return this.getSetting_(this.FONT_FAMILY_KEY_) ?? this.FONT_DEFAULT;
|
45
|
+
}
|
46
|
+
|
47
|
+
getFontSize() {
|
48
|
+
return this.getSetting_(this.FONT_SIZE_KEY_) ?? this.FONT_SIZE_DEFAULT;
|
49
|
+
}
|
50
|
+
|
51
|
+
getHeaderMinimized() {
|
52
|
+
let minimizedStr = this.getSetting_(this.HEADER_MINIMIZED_KEY_) ?? {{ site.hematite.minimize_header | default: "false" | jsonify }};
|
53
|
+
return minimizedStr == "true";
|
54
|
+
}
|
55
|
+
|
56
|
+
setFontSize(sizeOption) {
|
57
|
+
this.setSetting_(this.FONT_SIZE_KEY_, sizeOption);
|
58
|
+
}
|
59
|
+
|
60
|
+
setFontFamily(familyOption) {
|
61
|
+
this.setSetting_(this.FONT_FAMILY_KEY_, familyOption);
|
62
|
+
}
|
63
|
+
|
64
|
+
setTheme(themeOption) {
|
65
|
+
this.setSetting_(this.THEME_KEY_, themeOption);
|
66
|
+
}
|
67
|
+
|
68
|
+
setHeaderMinimized(minimize) {
|
69
|
+
this.setSetting_(this.HEADER_MINIMIZED_KEY_, `${minimize}`);
|
70
|
+
}
|
71
|
+
|
72
|
+
getFontSizePt_() {
|
73
|
+
let fontSizeOption = this.getFontSize();
|
74
|
+
|
75
|
+
if (fontSizeOption == this.FONT_SIZE_SMALL) {
|
76
|
+
return {{ site.hematite.user_config.font_size_small | default: "9" }};
|
77
|
+
}
|
78
|
+
|
79
|
+
if (fontSizeOption == this.FONT_SIZE_MEDIUM) {
|
80
|
+
return {{ site.hematite.user_config.font_size_medium | default: "13" }};
|
81
|
+
}
|
82
|
+
|
83
|
+
if (fontSizeOption == this.FONT_SIZE_LARGE) {
|
84
|
+
return {{ site.hematite.user_config.font_size_large | default: "16" }};
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
usingNonDefaultFontFamily_() {
|
89
|
+
return this.getFontFamily() != this.FONT_DEFAULT;
|
90
|
+
}
|
91
|
+
|
92
|
+
usingNonDefaultFontSize_() {
|
93
|
+
return this.getFontSize() != this.FONT_SIZE_DEFAULT;
|
94
|
+
}
|
95
|
+
|
96
|
+
forcingDarkTheme_() {
|
97
|
+
return this.getTheme() == this.THEME_DARK;
|
98
|
+
}
|
99
|
+
|
100
|
+
forcingLightTheme_() {
|
101
|
+
return this.getTheme() == this.THEME_LIGHT;
|
102
|
+
}
|
103
|
+
|
104
|
+
async applySettings() {
|
105
|
+
document.documentElement.classList.add("changingTheme");
|
106
|
+
|
107
|
+
// Clean up previous changes. We might be re-applying styles.
|
108
|
+
document.documentElement.classList.remove("lightTheme");
|
109
|
+
document.documentElement.classList.remove("darkTheme");
|
110
|
+
|
111
|
+
if (!this.style_) {
|
112
|
+
this.style_ = document.createElement("style");
|
113
|
+
} else {
|
114
|
+
this.style_.remove();
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
let styleHTML =
|
119
|
+
`
|
120
|
+
:root.changingTheme * {
|
121
|
+
transition: ${THEME_TRANSITION_TIME}ms ease all;
|
122
|
+
}
|
123
|
+
`;
|
124
|
+
|
125
|
+
// Font family
|
126
|
+
if (this.usingNonDefaultFontFamily_()) {
|
127
|
+
styleHTML +=
|
128
|
+
`
|
129
|
+
:root {
|
130
|
+
--main-font-family: var(--${this.getFontFamily()}-font-family);
|
131
|
+
}
|
132
|
+
`;
|
133
|
+
}
|
134
|
+
|
135
|
+
// Font size
|
136
|
+
if (this.usingNonDefaultFontSize_()) {
|
137
|
+
styleHTML +=
|
138
|
+
`
|
139
|
+
:root {
|
140
|
+
--main-font-size: ${this.getFontSizePt_()}pt;
|
141
|
+
}
|
142
|
+
`;
|
143
|
+
}
|
144
|
+
|
145
|
+
this.style_.innerHTML = styleHTML;
|
146
|
+
document.documentElement.appendChild(this.style_);
|
147
|
+
|
148
|
+
// Theme
|
149
|
+
if (this.forcingDarkTheme_()) {
|
150
|
+
document.documentElement.classList.add("darkTheme");
|
151
|
+
}
|
152
|
+
else if (this.forcingLightTheme_()) {
|
153
|
+
document.documentElement.classList.add("lightTheme");
|
154
|
+
}
|
155
|
+
|
156
|
+
if (this.getHeaderMinimized()) {
|
157
|
+
// Run roughly in parallel
|
158
|
+
(async () => {
|
159
|
+
let header = document.querySelector("body > header");
|
160
|
+
if (header) {
|
161
|
+
await AnimationUtil.collapseOutVert(header, THEME_TRANSITION_TIME / 2);
|
162
|
+
}
|
163
|
+
|
164
|
+
document.documentElement.classList.add("minimizedNavHeader");
|
165
|
+
|
166
|
+
// Animate the header.
|
167
|
+
if (header) {
|
168
|
+
await AnimationUtil.expandInVert(header, THEME_TRANSITION_TIME / 2);
|
169
|
+
}
|
170
|
+
})();
|
171
|
+
}
|
172
|
+
else {
|
173
|
+
document.documentElement.classList.remove("minimizedNavHeader");
|
174
|
+
}
|
175
|
+
|
176
|
+
await AsyncUtil.waitMillis(THEME_TRANSITION_TIME);
|
177
|
+
document.documentElement.classList.remove("changingTheme");
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
export default (new Settings());
|
data/assets/js/main.mjs
CHANGED
@@ -3,6 +3,7 @@ import { generateHeaderLinks } from "./linkButtonGenerator.mjs";
|
|
3
3
|
import handleSidebar from "./sidebar.mjs";
|
4
4
|
import handleSearch from "./search.mjs";
|
5
5
|
import autoExpandDropdowns from "./dropdownExpander.mjs";
|
6
|
+
import Settings from "./Settings.mjs";
|
6
7
|
|
7
8
|
// After loading elements, images, css, etc.
|
8
9
|
addEventListener("load", () => {
|
@@ -17,3 +18,6 @@ addEventListener("load", () => {
|
|
17
18
|
addEventListener("DOMContentLoaded", () => {
|
18
19
|
handleSidebar();
|
19
20
|
});
|
21
|
+
|
22
|
+
// Apply user-specified settings
|
23
|
+
Settings.applySettings();
|
data/assets/js/sidebar.mjs
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { stringLookup } from "./strings.mjs";
|
2
2
|
import { announceForAccessibility } from "./PageAlert.mjs";
|
3
3
|
|
4
|
+
|
4
5
|
function handleSidebar() {
|
5
6
|
const toggleBtn = document.querySelector(`button#toggle_sidebar_btn`);
|
6
7
|
const sidebar = document.querySelector(`nav#sidebar`);
|
@@ -16,11 +17,11 @@ function handleSidebar() {
|
|
16
17
|
const setSidebarOpen = (open) => {
|
17
18
|
if (!open) {
|
18
19
|
sidebar.classList.remove(`open`);
|
19
|
-
document.
|
20
|
+
document.documentElement.classList.remove(`hasOpenSidebar`);
|
20
21
|
}
|
21
22
|
else {
|
22
23
|
sidebar.classList.add(`open`);
|
23
|
-
document.
|
24
|
+
document.documentElement.classList.add(`hasOpenSidebar`);
|
24
25
|
}
|
25
26
|
};
|
26
27
|
|
@@ -91,6 +92,17 @@ function handleSidebar() {
|
|
91
92
|
}
|
92
93
|
});
|
93
94
|
}
|
95
|
+
|
96
|
+
localizeSettingsBtn();
|
97
|
+
}
|
98
|
+
|
99
|
+
// Localize the text in the sidebar's settings button, if it exists.
|
100
|
+
function localizeSettingsBtn() {
|
101
|
+
let sidebarBtn = document.querySelector("#sidebar_settings_btn");
|
102
|
+
|
103
|
+
if (sidebarBtn) {
|
104
|
+
sidebarBtn.innerText = stringLookup(`open_settings_btn`);
|
105
|
+
}
|
94
106
|
}
|
95
107
|
|
96
108
|
export { handleSidebar };
|
data/assets/string_data/en.mjs
CHANGED
@@ -30,4 +30,26 @@ export default {
|
|
30
30
|
all_tags_header: 'All Tags',
|
31
31
|
prev_post: '← {0}',
|
32
32
|
next_post: '{0} →',
|
33
|
+
|
34
|
+
open_settings_btn: 'Site Settings',
|
35
|
+
page_settings_header: 'Settings',
|
36
|
+
page_settings_description:
|
37
|
+
'Here, you can change settings that affect how this page looks. Changes'
|
38
|
+
+ ' save automatically.',
|
39
|
+
settings_font_legend: 'Font Options',
|
40
|
+
settings_font_family_label: 'Font Family: ',
|
41
|
+
settings_font_size_label: 'Font Size: ',
|
42
|
+
settings_theme_label: 'Page Theme: ',
|
43
|
+
page_theme_legend: 'Theme Options',
|
44
|
+
|
45
|
+
page_font_sans: 'Sans',
|
46
|
+
page_font_serif: 'Serif',
|
47
|
+
page_font_default: 'Default',
|
48
|
+
page_font_small: 'Small',
|
49
|
+
page_font_medium: 'Medium',
|
50
|
+
page_font_large: 'Large',
|
51
|
+
page_theme_auto: 'Automatic',
|
52
|
+
page_theme_dark: 'Dark Theme',
|
53
|
+
page_theme_light: 'Light Theme',
|
54
|
+
settings_minimize_header: 'Hide Header: '
|
33
55
|
};
|
data/assets/string_data/es.mjs
CHANGED
@@ -31,4 +31,23 @@ export default {
|
|
31
31
|
all_tags_header: 'Todas las etiquetas',
|
32
32
|
prev_post: '← {0}',
|
33
33
|
next_post: '{0} →',
|
34
|
+
|
35
|
+
open_settings_btn: 'Ajustes de este sitio',
|
36
|
+
page_settings_header: 'Ajustes',
|
37
|
+
page_settings_description: 'Aquí, puede cambiar algunos aspectos de este sitio.'
|
38
|
+
+ ' Cuando una ajuste cambia, lo debe estar guardado.',
|
39
|
+
settings_font_legend: 'Ajustes de fuente',
|
40
|
+
settings_font_family_label: 'Familia de fuente: ',
|
41
|
+
settings_font_size_label: 'Tamoño de fuente: ',
|
42
|
+
settings_theme_label: 'Color de la pagina: ',
|
43
|
+
page_theme_legend: 'Ajustes de tema',
|
44
|
+
|
45
|
+
page_font_default: 'Inicial',
|
46
|
+
page_font_small: 'Pequeño',
|
47
|
+
page_font_medium: 'Media',
|
48
|
+
page_font_large: 'Grande',
|
49
|
+
page_theme_auto: 'Automático',
|
50
|
+
page_theme_dark: 'Oscuro',
|
51
|
+
page_theme_light: 'Brillante',
|
52
|
+
settings_minimize_header: 'Título escondido: '
|
34
53
|
};
|
data/assets/style.scss
CHANGED
@@ -6,10 +6,6 @@ styles: true
|
|
6
6
|
@import "hematite";
|
7
7
|
|
8
8
|
{% if site.hematite.auto_invert_imgs %}
|
9
|
-
//
|
10
|
-
@
|
11
|
-
main img:not(.no-invert) {
|
12
|
-
filter: invert(1) hue-rotate(180deg);
|
13
|
-
}
|
14
|
-
}
|
9
|
+
// In dark mode, invert the brightness of images
|
10
|
+
@include auto-invert-images;
|
15
11
|
{% endif %}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hematite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henry Heino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05-
|
11
|
+
date: 2022-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -34,9 +34,11 @@ files:
|
|
34
34
|
- LICENSE.txt
|
35
35
|
- README.md
|
36
36
|
- _config.yml
|
37
|
+
- _includes/footer.html
|
37
38
|
- _includes/img/hamburger_menu.svg
|
38
39
|
- _includes/img/search_icon.svg
|
39
40
|
- _includes/katex_includes.html
|
41
|
+
- _includes/nav/header.html
|
40
42
|
- _includes/nav/page_navigation.html
|
41
43
|
- _includes/nav/pages_list.html
|
42
44
|
- _includes/nav/pinned_page.html
|
@@ -56,11 +58,13 @@ files:
|
|
56
58
|
- _sass/_sizes.scss
|
57
59
|
- _sass/hematite.scss
|
58
60
|
- assets/html/all_tags.html
|
61
|
+
- assets/html/settings.html
|
59
62
|
- assets/img/favicon.svg
|
60
63
|
- assets/js/AnimationUtil.mjs
|
61
64
|
- assets/js/AsyncUtil.mjs
|
62
65
|
- assets/js/DateUtil.mjs
|
63
66
|
- assets/js/PageAlert.mjs
|
67
|
+
- assets/js/Settings.mjs
|
64
68
|
- assets/js/UrlHelper.mjs
|
65
69
|
- assets/js/assertions.mjs
|
66
70
|
- assets/js/dropdownExpander.mjs
|