hematite 0.0.9 → 0.0.12

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: 3d623b260279dabc636598983bebf15e547d963ead82e21b5e8357572597bb48
4
- data.tar.gz: 00bba21df3b38ea1db9bf57d631b3ce2da97c5f077c0680831550192cc4c58d7
3
+ metadata.gz: 8ba3735a0bf64aa9c895fc9622e0370b0827c80386469ccb4c5172058f91db97
4
+ data.tar.gz: e6f824c10b0febde44d427ee0528681f756cc59bff67a3362e256d77d5be3650
5
5
  SHA512:
6
- metadata.gz: 51bc1b4fbea55a7bf316d03ac9c291c3f233ab7e91fe163dd3412f23518e3f4b247c3aeafd0cc1b72bb941ec3f721b90dc949bed6cfb3572ee8a4b6ae5fff182
7
- data.tar.gz: fe620903b815435c84c0a2d45b3edb1ca10c9d2727eb129ca24c0837b55adbf5fc384086feb0228b164084616419048fec8df8c62138ad976d4a8db990a1d79b
6
+ metadata.gz: 958067abc2e83cbecc509dc7c31c2eb711c2116ea201a27c28f6a89bc0f0a6658d34532433596b989178ab070d686c2a5de0d26781ff6b92d73fdc6416f9608f
7
+ data.tar.gz: e01cb8c28899e24135e832ef89543c9266e66db13d9a53f40327d6c32b6d8ed815d5da7247a63fd88ca94dc762180ab752fb8494c2d9e31d3ae2ed13fdda6297
data/_config.yml CHANGED
@@ -1,9 +1,6 @@
1
1
 
2
2
  # Settings for the demo site.
3
3
  # `jekyll serve` does not auto-reload this file.
4
- #
5
- # See https://leo3418.github.io/collections/multilingual-jekyll-site/localize-strings
6
- # for how localization works.
7
4
 
8
5
  title: Hematite Theme
9
6
  description: A Jekyll theme intended for course websites
@@ -12,6 +9,9 @@ permalink: pretty
12
9
  hematite:
13
10
  auto_invert_imgs: true
14
11
 
12
+ # Set to true to minimize the header by default
13
+ minimize_header: false
14
+
15
15
  # Date options are as specified here:
16
16
  # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
17
17
  date_format:
@@ -0,0 +1,101 @@
1
+ <!--
2
+ See assets/html/settings.html. This file can be included
3
+ in your own settings page and add your settings to it!
4
+ -->
5
+
6
+ <!-- So they can be localized, much of this page is filled by JavaScript -->
7
+ <!-- Organization inspired by https://www.w3.org/WAI/tutorials/forms/grouping/ -->
8
+ <fieldset>
9
+ <legend id="font_legend">settings_font_legend</legend>
10
+ <div>
11
+ <label id="font_family_lbl" for="font_family">settings_font_family_label</label>
12
+ <select id="font_family"></select>
13
+ </div>
14
+ <div>
15
+ <label id="font_size_lbl" for="font_size">settings_font_size_label</label>
16
+ <select id="font_size">
17
+ </select>
18
+ </div>
19
+ </fieldset>
20
+
21
+ <fieldset>
22
+ <legend id="theme_legend">page_theme_legend</legend>
23
+ <div>
24
+ <label id="page_theme_lbl" for="page_theme">settings_theme_label</label>
25
+ <select id="page_theme"></select>
26
+ </div>
27
+ <div>
28
+ <label id="page_minimize_header_lbl" for="minimize_page_hdr">settings_minimize_header</label>
29
+ <input type="checkbox" id="minimize_page_hdr"/>
30
+ </div>
31
+ </fieldset>
32
+
33
+ <script type="module">
34
+ import Settings from "{{ 'assets/js/Settings.mjs' | relative_url }}";
35
+ import { stringLookup } from "{{ 'assets/js/strings.mjs' | relative_url }}";
36
+
37
+ let settingsTextElemIDs = [
38
+ `settings_header`, `settings_description`, `font_legend`,
39
+ `font_family_lbl`, `font_size_lbl`, `theme_legend`,
40
+ `page_theme_lbl`, `page_minimize_header_lbl`,
41
+ ];
42
+
43
+ // Localize all descriptive settings elements (each should contian the
44
+ // name of its localization key).
45
+ for (const id of settingsTextElemIDs) {
46
+ let elem = document.querySelector(`#${id}`);
47
+
48
+ if (elem) {
49
+ elem.innerText = stringLookup(elem.innerText);
50
+ }
51
+ }
52
+
53
+ let fontSizeSelect = document.querySelector("#font_size");
54
+ let fontFamilySelect = document.querySelector("#font_family");
55
+ let pageThemeSelect = document.querySelector("#page_theme");
56
+ let minimizeHeaderCheckbox = document.querySelector("#minimize_page_hdr");
57
+
58
+ pageThemeSelect.innerHTML =
59
+ `
60
+ <option value='${Settings.THEME_AUTO}'>${stringLookup('page_theme_auto')}</option>
61
+ <option value='${Settings.THEME_DARK}'>${stringLookup('page_theme_dark')}</option>
62
+ <option value='${Settings.THEME_LIGHT}'>${stringLookup('page_theme_light')}</option>
63
+ `;
64
+
65
+ fontFamilySelect.innerHTML =
66
+ `
67
+ <option value='${Settings.FONT_DEFAULT}'>${stringLookup('page_font_default')}</option>
68
+ <option value='${Settings.FONT_SERIF}'>${stringLookup('page_font_serif')}</option>
69
+ <option value='${Settings.FONT_SANS}'>${stringLookup('page_font_sans')}</option>
70
+ `;
71
+
72
+ fontSizeSelect.innerHTML =
73
+ `
74
+ <option value='${Settings.FONT_SIZE_DEFAULT}'>${stringLookup('page_font_default')}</option>
75
+ <option value='${Settings.FONT_SIZE_SMALL}'>${stringLookup('page_font_small')}</option>
76
+ <option value='${Settings.FONT_SIZE_MEDIUM}'>${stringLookup('page_font_medium')}</option>
77
+ <option value='${Settings.FONT_SIZE_LARGE}'>${stringLookup('page_font_large')}</option>
78
+ `;
79
+
80
+ fontSizeSelect.oninput = () => {
81
+ Settings.setFontSize(fontSizeSelect.value);
82
+ };
83
+
84
+ fontFamilySelect.oninput = () => {
85
+ Settings.setFontFamily(fontFamilySelect.value);
86
+ };
87
+
88
+ pageThemeSelect.oninput = () => {
89
+ Settings.setTheme(pageThemeSelect.value);
90
+ };
91
+
92
+ minimizeHeaderCheckbox.oninput = () => {
93
+ Settings.setHeaderMinimized(minimizeHeaderCheckbox.checked);
94
+ };
95
+
96
+ pageThemeSelect.value = Settings.getTheme();
97
+ fontFamilySelect.value = Settings.getFontFamily();
98
+ fontSizeSelect.value = Settings.getFontSize();
99
+ minimizeHeaderCheckbox.checked = Settings.getHeaderMinimized();
100
+
101
+ </script>
data/_sass/_elements.scss CHANGED
@@ -149,3 +149,31 @@ a.settings-btn {
149
149
  border: 1px solid var(--line-color-light);
150
150
  }
151
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/_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: grow-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
 
data/_sass/_sizes.scss CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  $site-content-preferred-width: 700px;
3
3
  $content-main-padding: 30px;
4
+ $navbar-padding: 10px;
4
5
 
5
6
  // CSS variables
6
7
  :root {
@@ -6,89 +6,7 @@ noindex: true
6
6
 
7
7
  <noscript>JavaScript is required to view this page's content!</noscript>
8
8
 
9
- <!-- So they can be localized, much of this page is filled by JavaScript -->
10
9
  <h1 id="settings_header">page_settings_header</h1>
11
10
  <p id="settings_description">page_settings_description</p>
12
11
 
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
- </fieldset>
34
-
35
- <script type="module">
36
- import Settings from "{{ 'assets/js/Settings.mjs' | relative_url }}";
37
- import { stringLookup } from "{{ 'assets/js/strings.mjs' | relative_url }}";
38
-
39
- let settingsTextElemIDs = [
40
- `settings_header`, `settings_description`, `font_legend`,
41
- `font_family_lbl`, `font_size_lbl`, `theme_legend`,
42
- `page_theme_lbl`,
43
- ];
44
-
45
- // Localize all descriptive settings elements (each should contian the
46
- // name of its localization key).
47
- for (const id of settingsTextElemIDs) {
48
- let elem = document.querySelector(`#${id}`);
49
- elem.innerText = stringLookup(elem.innerText);
50
- }
51
-
52
- let fontSizeSelect = document.querySelector("#font_size");
53
- let fontFamilySelect = document.querySelector("#font_family");
54
- let pageThemeSelect = document.querySelector("#page_theme");
55
-
56
- pageThemeSelect.innerHTML =
57
- `
58
- <option value='${Settings.THEME_AUTO}'>${stringLookup('page_theme_auto')}</option>
59
- <option value='${Settings.THEME_DARK}'>${stringLookup('page_theme_dark')}</option>
60
- <option value='${Settings.THEME_LIGHT}'>${stringLookup('page_theme_light')}</option>
61
- `;
62
-
63
- fontFamilySelect.innerHTML =
64
- `
65
- <option value='${Settings.FONT_DEFAULT}'>${stringLookup('page_font_default')}</option>
66
- <option value='${Settings.FONT_SERIF}'>${stringLookup('page_font_serif')}</option>
67
- <option value='${Settings.FONT_SANS}'>${stringLookup('page_font_sans')}</option>
68
- `;
69
-
70
- fontSizeSelect.innerHTML =
71
- `
72
- <option value='${Settings.FONT_SIZE_DEFAULT}'>${stringLookup('page_font_default')}</option>
73
- <option value='${Settings.FONT_SIZE_SMALL}'>${stringLookup('page_font_small')}</option>
74
- <option value='${Settings.FONT_SIZE_MEDIUM}'>${stringLookup('page_font_medium')}</option>
75
- <option value='${Settings.FONT_SIZE_LARGE}'>${stringLookup('page_font_large')}</option>
76
- `;
77
-
78
- fontSizeSelect.oninput = () => {
79
- Settings.setFontSize(fontSizeSelect.value);
80
- };
81
-
82
- fontFamilySelect.oninput = () => {
83
- Settings.setFontFamily(fontFamilySelect.value);
84
- };
85
-
86
- pageThemeSelect.oninput = () => {
87
- Settings.setTheme(pageThemeSelect.value);
88
- };
89
-
90
- pageThemeSelect.value = Settings.getTheme();
91
- fontFamilySelect.value = Settings.getFontFamily();
92
- fontSizeSelect.value = Settings.getFontSize();
93
-
94
- </script>
12
+ {% include settings.html %}
@@ -1,5 +1,9 @@
1
1
  ---
2
2
  ---
3
+ import AsyncUtil from "./AsyncUtil.mjs";
4
+ import AnimationUtil from "./AnimationUtil.mjs";
5
+
6
+ const THEME_TRANSITION_TIME = 500; // ms
3
7
 
4
8
  class Settings {
5
9
  THEME_AUTO = 'auto';
@@ -18,6 +22,7 @@ class Settings {
18
22
  FONT_SIZE_KEY_ = 'hematite-setting-font-size';
19
23
  FONT_FAMILY_KEY_ = 'hematite-setting-font-family';
20
24
  THEME_KEY_ = 'hematite-setting-theme';
25
+ HEADER_MINIMIZED_KEY_ = 'hematite-setting-minimize-header';
21
26
 
22
27
  constructor() {
23
28
  }
@@ -43,6 +48,12 @@ class Settings {
43
48
  return this.getSetting_(this.FONT_SIZE_KEY_) ?? this.FONT_SIZE_DEFAULT;
44
49
  }
45
50
 
51
+ getHeaderMinimized() {
52
+ let minimizedStr = this.getSetting_(this.HEADER_MINIMIZED_KEY_)
53
+ ?? {{ site.hematite.user_config.minimize_header | default: site.hematite.minimize_header | default: "false" | jsonify }};
54
+ return minimizedStr == "true";
55
+ }
56
+
46
57
  setFontSize(sizeOption) {
47
58
  this.setSetting_(this.FONT_SIZE_KEY_, sizeOption);
48
59
  }
@@ -55,6 +66,10 @@ class Settings {
55
66
  this.setSetting_(this.THEME_KEY_, themeOption);
56
67
  }
57
68
 
69
+ setHeaderMinimized(minimize) {
70
+ this.setSetting_(this.HEADER_MINIMIZED_KEY_, `${minimize}`);
71
+ }
72
+
58
73
  getFontSizePt_() {
59
74
  let fontSizeOption = this.getFontSize();
60
75
 
@@ -87,7 +102,9 @@ class Settings {
87
102
  return this.getTheme() == this.THEME_LIGHT;
88
103
  }
89
104
 
90
- applySettings() {
105
+ async applySettings() {
106
+ document.documentElement.classList.add("changingTheme");
107
+
91
108
  // Clean up previous changes. We might be re-applying styles.
92
109
  document.documentElement.classList.remove("lightTheme");
93
110
  document.documentElement.classList.remove("darkTheme");
@@ -99,7 +116,12 @@ class Settings {
99
116
  }
100
117
 
101
118
 
102
- let styleHTML = '';
119
+ let styleHTML =
120
+ `
121
+ :root.changingTheme * {
122
+ transition: ${THEME_TRANSITION_TIME}ms ease all;
123
+ }
124
+ `;
103
125
 
104
126
  // Font family
105
127
  if (this.usingNonDefaultFontFamily_()) {
@@ -121,6 +143,9 @@ class Settings {
121
143
  `;
122
144
  }
123
145
 
146
+ this.style_.innerHTML = styleHTML;
147
+ document.documentElement.appendChild(this.style_);
148
+
124
149
  // Theme
125
150
  if (this.forcingDarkTheme_()) {
126
151
  document.documentElement.classList.add("darkTheme");
@@ -129,8 +154,29 @@ class Settings {
129
154
  document.documentElement.classList.add("lightTheme");
130
155
  }
131
156
 
132
- this.style_.innerHTML = styleHTML;
133
- document.documentElement.appendChild(this.style_);
157
+ if (this.getHeaderMinimized()) {
158
+ // Run roughly in parallel
159
+ (async () => {
160
+ let header = document.querySelector("body > header");
161
+ if (header) {
162
+ await AnimationUtil.collapseOutVert(header, THEME_TRANSITION_TIME / 2);
163
+ }
164
+
165
+ document.documentElement.classList.add("minimizedNavHeader");
166
+
167
+ if (header) {
168
+ // Re-show the header
169
+ // Rely on a CSS animation for animating the header's return.
170
+ await AnimationUtil.expandInVert(header, 0);
171
+ }
172
+ })();
173
+ }
174
+ else {
175
+ document.documentElement.classList.remove("minimizedNavHeader");
176
+ }
177
+
178
+ await AsyncUtil.waitMillis(THEME_TRANSITION_TIME);
179
+ document.documentElement.classList.remove("changingTheme");
134
180
  }
135
181
  }
136
182
 
data/assets/js/main.mjs CHANGED
@@ -17,7 +17,7 @@ addEventListener("load", () => {
17
17
  // After loading elements, but before loading elements like images.
18
18
  addEventListener("DOMContentLoaded", () => {
19
19
  handleSidebar();
20
-
21
- // Apply user-specified settings
22
- Settings.applySettings();
23
20
  });
21
+
22
+ // Apply user-specified settings
23
+ Settings.applySettings();
@@ -17,11 +17,11 @@ function handleSidebar() {
17
17
  const setSidebarOpen = (open) => {
18
18
  if (!open) {
19
19
  sidebar.classList.remove(`open`);
20
- document.scrollingElement?.classList.remove(`hasOpenSidebar`);
20
+ document.documentElement.classList.remove(`hasOpenSidebar`);
21
21
  }
22
22
  else {
23
23
  sidebar.classList.add(`open`);
24
- document.scrollingElement?.classList.add(`hasOpenSidebar`);
24
+ document.documentElement.classList.add(`hasOpenSidebar`);
25
25
  }
26
26
  };
27
27
 
@@ -51,4 +51,5 @@ export default {
51
51
  page_theme_auto: 'Automatic',
52
52
  page_theme_dark: 'Dark Theme',
53
53
  page_theme_light: 'Light Theme',
54
+ settings_minimize_header: 'Hide Header: '
54
55
  };
@@ -49,4 +49,5 @@ export default {
49
49
  page_theme_auto: 'Automático',
50
50
  page_theme_dark: 'Oscuro',
51
51
  page_theme_light: 'Brillante',
52
+ settings_minimize_header: 'Título escondido: '
52
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hematite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henry Heino
@@ -43,6 +43,7 @@ files:
43
43
  - _includes/nav/pages_list.html
44
44
  - _includes/nav/pinned_page.html
45
45
  - _includes/nav/sidebar.html
46
+ - _includes/settings.html
46
47
  - _layouts/calendar.html
47
48
  - _layouts/default.html
48
49
  - _layouts/home.html