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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca054447d56a7d76f00b864906bce8cc2245ba03d089dca22246060f81142a2e
4
- data.tar.gz: ba039823072585771bfcdd113454a3de8353219c935907b3b95ae9fb5e82cbe5
3
+ metadata.gz: c5f6a0cdf074d0025f0cf3031037a4dc365af38f99aa811578f3d88f0c356175
4
+ data.tar.gz: 533d5d2c8897c2985977971c5a6ca66552df1edee4bae22c9184750e97478007
5
5
  SHA512:
6
- metadata.gz: a7d4189cc538c9fbd161458570fdeca378971746f33e9365e6ebe5b8806a754517424b1655cbd32994b206bcabd92440f5e462d89153584ee499cb4ccb5fa507
7
- data.tar.gz: ca7eb2a71d1b4d6bc342fb2fec21e0bbd3628f78689f0d6728112b1a85842f26f3d90a51e58951e9a69c5871756a9840fc6d224abd600df3559c7bbbf33d276a
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 in JavaScript should go in `assets/js/string_data.mjs` to permit future localization.
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</a>'
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
 
@@ -0,0 +1,6 @@
1
+ {% comment %}
2
+ The contents of this file are included at the bottom of all pages, posts, etc.
3
+
4
+ This is different from the text included at the bottom of the sidebar. Change the sidebar footer
5
+ in your _config.yml.
6
+ {% endcomment %}
@@ -0,0 +1,5 @@
1
+ {% comment %}
2
+ This is the header that appears in the navigation bar (at the top of the page)!
3
+ Customize it here.
4
+ {% endcomment %}
5
+ <a href="{{ "/" | absolute_url }}">{{ site.title | default "Untitled Site" }}</a>
@@ -3,7 +3,7 @@
3
3
  <button class="toggle_sidebar" id="toggle_sidebar_btn">
4
4
  {% include img/hamburger_menu.svg %}
5
5
  </button>
6
- <a href="{{ "/" | absolute_url }}">{{ site.title | default "Untitled Site" }}</a>
6
+ {% include nav/header.html %}
7
7
  <div class="spacer"></div>
8
8
  </header>
9
9
 
@@ -18,8 +18,22 @@
18
18
  </ul>
19
19
 
20
20
  <footer>
21
- {% if site.hematite.sidebar.footer_html %}
22
- {{ site.hematite.sidebar.footer_html }}
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>
@@ -28,6 +28,8 @@ title: Untitled
28
28
  {% if page.layout == "default" %}
29
29
  </main>
30
30
  {% endif %}
31
+
32
+ {% include footer.html %}
31
33
  </div>
32
34
 
33
35
  </body>
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
- --primary-text-color: white;
43
- --secondary-text-color: white;
44
- --text-color-faint: #ccc;
45
- --link-color: #fa0;
46
- --visited-link-color: #f0a;
47
-
48
- --selected-item-fg-color: white;
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-light);
39
+ border: 1px solid var(--line-color-normal);
40
40
  border-radius: 4px;
41
41
  padding: 5px;
42
42
 
43
- font-family: $serif-font;
44
- font-size: $font-size-main;
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: $font-size-main;
38
- font-family: $serif-font;
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: $serif-font;
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: 10px;
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
- $serif-font: 'FoulisGreek', 'EB Garamond', 'TeX Gyre Bonum', serif;
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();
@@ -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.scrollingElement?.classList.remove(`hasOpenSidebar`);
20
+ document.documentElement.classList.remove(`hasOpenSidebar`);
20
21
  }
21
22
  else {
22
23
  sidebar.classList.add(`open`);
23
- document.scrollingElement?.classList.add(`hasOpenSidebar`);
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 };
@@ -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
  };
@@ -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
- // Auto-invert images in dark mode!
10
- @media (prefers-color-scheme: dark) {
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.8
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-19 00:00:00.000000000 Z
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