hematite 0.0.6 → 0.0.9

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: 394cf1d6b7f212788ff66ad9dc2c60b1221cf49604145762a0f5db8dd2cd5032
4
- data.tar.gz: cdc7d2cae9907ff2de79bb08ddecb259dbd4e6bf9ee2bc02f06da8cbb43d10e7
3
+ metadata.gz: 3d623b260279dabc636598983bebf15e547d963ead82e21b5e8357572597bb48
4
+ data.tar.gz: 00bba21df3b38ea1db9bf57d631b3ce2da97c5f077c0680831550192cc4c58d7
5
5
  SHA512:
6
- metadata.gz: 58323b2f1fc1a8bc8cd445fd1da5f68ce6fee23ccf68c0b798f1c74452a276d8989585b995967e1bde31c0e38129383074eb7c87e9bfc53e616cf6a5c02b7abf
7
- data.tar.gz: cc70aa6d874e4867c86a4f349aa8d8d0d62891e1a871d6fb0553e1cc039aac02d3fb2bfcc1737b6bf1ee96222a2dfa8bd46d85a94ce0fb7253cfacd9c3d679f6
6
+ metadata.gz: 51bc1b4fbea55a7bf316d03ac9c291c3f233ab7e91fe163dd3412f23518e3f4b247c3aeafd0cc1b72bb941ec3f721b90dc949bed6cfb3572ee8a4b6ae5fff182
7
+ data.tar.gz: fe620903b815435c84c0a2d45b3edb1ca10c9d2727eb129ca24c0837b55adbf5fc384086feb0228b164084616419048fec8df8c62138ad976d4a8db990a1d79b
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
@@ -27,7 +27,13 @@ hematite:
27
27
  # The full year
28
28
  year: numeric
29
29
 
30
+ parsing:
31
+ # True if the date should be parsed MM/DD/YYYY instead of
32
+ # DD/MM/YYYY
33
+ month_first: true
34
+
30
35
  sidebar:
31
- 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
32
38
 
33
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,16 @@ 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
+ }
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
@@ -79,6 +79,9 @@ nav.sidebar {
79
79
  input {
80
80
  flex-grow: 1;
81
81
  flex-shrink: 1;
82
+
83
+ // Allow it to shrink
84
+ min-width: 20px;
82
85
  }
83
86
  }
84
87
 
data/_sass/_sizes.scss CHANGED
@@ -1,11 +1,12 @@
1
1
 
2
- // Macro-like variables
3
2
  $site-content-preferred-width: 700px;
4
- $font-size-main: 12pt;
5
3
  $content-main-padding: 30px;
6
4
 
7
5
  // CSS variables
8
6
  :root {
7
+ // We want these variables to be changable dynamically,
8
+ // so they're CSS variables.
9
+ --main-font-size: 12pt;
9
10
  --nav-font-size: 22pt;
10
11
  --header-height: 30pt;
11
12
  --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,94 @@
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
+ </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>
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  ---
3
3
 
4
+ import { assertEq } from "./assertions.mjs";
5
+
4
6
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
5
7
  const MS_PER_WEEK = MS_PER_DAY * 7;
6
8
 
@@ -94,12 +96,39 @@ var DateUtil = {
94
96
 
95
97
  /// Slightly more intelligent date parsing than new Date(string).
96
98
  parse(text) {
99
+ text = text.trim();
100
+
97
101
  // Remove -th, -rd, -ero suffexes
98
- text = text.replaceAll(/(\d)(?:rd|th|ero)/g,
102
+ text = text.replaceAll(/(\d)(?:rd|st|th|ero)/g,
99
103
  (fullMatch, group0) => group0);
100
- console.log("Parsing", text);
104
+ let res = new Date(0);
105
+
106
+ let shortMatch = text.match(/^(\d+)\/(\d+)\/(\d{2,})$/);
107
+
108
+ // DD/MM/YY+ or MM/DD/YY+
109
+ if (shortMatch) {
110
+ let year = parseInt(shortMatch[3]);
111
+ {% if site.hematite.date_format.parsing.month_first %}
112
+ let month = parseInt(shortMatch[1]);
113
+ let day = parseInt(shortMatch[2]);
114
+ {% else %}
115
+ let month = parseInt(shortMatch[2]);
116
+ let day = parseInt(shortMatch[1]);
117
+ {% endif %}
118
+
119
+ if (shortMatch[3].length >= 4) {
120
+ res.setFullYear(year);
121
+ }
122
+ else if (shortMatch[3].length == 2){
123
+ res.setFullYear(2000 + year);
124
+ }
125
+ res.setMonth(month - 1, day);
126
+ }
127
+ else {
128
+ res = new Date(text);
129
+ }
101
130
 
102
- return new Date(text);
131
+ return res;
103
132
  },
104
133
 
105
134
  /// Returns true iff the given object is a date object.
@@ -120,4 +149,13 @@ var DateUtil = {
120
149
  },
121
150
  };
122
151
 
152
+ assertEq("Check if new Date() is a date",
153
+ DateUtil.isDate(new Date()), true);
154
+ assertEq("Check if dates can be parsed",
155
+ DateUtil.parse("01/01/22").getFullYear(), 2022);
156
+ assertEq("Same day test 1",
157
+ DateUtil.datesAreOnSameDay(DateUtil.parse("01/02/22"), DateUtil.parse("01/02/2022")), true);
158
+ assertEq("Same day test 2",
159
+ DateUtil.datesAreOnSameDay(DateUtil.parse("01/01/22"), DateUtil.parse("January 1st, 2022")), true);
160
+
123
161
  export default DateUtil;
@@ -0,0 +1,137 @@
1
+ ---
2
+ ---
3
+
4
+ class Settings {
5
+ THEME_AUTO = 'auto';
6
+ THEME_DARK = 'dark';
7
+ THEME_LIGHT = 'light';
8
+
9
+ FONT_DEFAULT = 'default';
10
+ FONT_SANS = 'sans';
11
+ FONT_SERIF = 'serif';
12
+
13
+ FONT_SIZE_SMALL = 'small';
14
+ FONT_SIZE_MEDIUM = 'medium';
15
+ FONT_SIZE_LARGE = 'large';
16
+ FONT_SIZE_DEFAULT = 'default';
17
+
18
+ FONT_SIZE_KEY_ = 'hematite-setting-font-size';
19
+ FONT_FAMILY_KEY_ = 'hematite-setting-font-family';
20
+ THEME_KEY_ = 'hematite-setting-theme';
21
+
22
+ constructor() {
23
+ }
24
+
25
+ getSetting_(key) {
26
+ return localStorage.getItem(key);
27
+ }
28
+
29
+ setSetting_(key, val) {
30
+ localStorage.setItem(key, val);
31
+ this.applySettings();
32
+ }
33
+
34
+ getTheme() {
35
+ return this.getSetting_(this.THEME_KEY_) ?? this.THEME_AUTO;
36
+ }
37
+
38
+ getFontFamily() {
39
+ return this.getSetting_(this.FONT_FAMILY_KEY_) ?? this.FONT_DEFAULT;
40
+ }
41
+
42
+ getFontSize() {
43
+ return this.getSetting_(this.FONT_SIZE_KEY_) ?? this.FONT_SIZE_DEFAULT;
44
+ }
45
+
46
+ setFontSize(sizeOption) {
47
+ this.setSetting_(this.FONT_SIZE_KEY_, sizeOption);
48
+ }
49
+
50
+ setFontFamily(familyOption) {
51
+ this.setSetting_(this.FONT_FAMILY_KEY_, familyOption);
52
+ }
53
+
54
+ setTheme(themeOption) {
55
+ this.setSetting_(this.THEME_KEY_, themeOption);
56
+ }
57
+
58
+ getFontSizePt_() {
59
+ let fontSizeOption = this.getFontSize();
60
+
61
+ if (fontSizeOption == this.FONT_SIZE_SMALL) {
62
+ return {{ site.hematite.user_config.font_size_small | default: "9" }};
63
+ }
64
+
65
+ if (fontSizeOption == this.FONT_SIZE_MEDIUM) {
66
+ return {{ site.hematite.user_config.font_size_medium | default: "13" }};
67
+ }
68
+
69
+ if (fontSizeOption == this.FONT_SIZE_LARGE) {
70
+ return {{ site.hematite.user_config.font_size_large | default: "16" }};
71
+ }
72
+ }
73
+
74
+ usingNonDefaultFontFamily_() {
75
+ return this.getFontFamily() != this.FONT_DEFAULT;
76
+ }
77
+
78
+ usingNonDefaultFontSize_() {
79
+ return this.getFontSize() != this.FONT_SIZE_DEFAULT;
80
+ }
81
+
82
+ forcingDarkTheme_() {
83
+ return this.getTheme() == this.THEME_DARK;
84
+ }
85
+
86
+ forcingLightTheme_() {
87
+ return this.getTheme() == this.THEME_LIGHT;
88
+ }
89
+
90
+ applySettings() {
91
+ // Clean up previous changes. We might be re-applying styles.
92
+ document.documentElement.classList.remove("lightTheme");
93
+ document.documentElement.classList.remove("darkTheme");
94
+
95
+ if (!this.style_) {
96
+ this.style_ = document.createElement("style");
97
+ } else {
98
+ this.style_.remove();
99
+ }
100
+
101
+
102
+ let styleHTML = '';
103
+
104
+ // Font family
105
+ if (this.usingNonDefaultFontFamily_()) {
106
+ styleHTML +=
107
+ `
108
+ :root {
109
+ --main-font-family: var(--${this.getFontFamily()}-font-family);
110
+ }
111
+ `;
112
+ }
113
+
114
+ // Font size
115
+ if (this.usingNonDefaultFontSize_()) {
116
+ styleHTML +=
117
+ `
118
+ :root {
119
+ --main-font-size: ${this.getFontSizePt_()}pt;
120
+ }
121
+ `;
122
+ }
123
+
124
+ // Theme
125
+ if (this.forcingDarkTheme_()) {
126
+ document.documentElement.classList.add("darkTheme");
127
+ }
128
+ else if (this.forcingLightTheme_()) {
129
+ document.documentElement.classList.add("lightTheme");
130
+ }
131
+
132
+ this.style_.innerHTML = styleHTML;
133
+ document.documentElement.appendChild(this.style_);
134
+ }
135
+ }
136
+
137
+ export default (new Settings());
@@ -91,8 +91,7 @@ function getCalendarData(elem, formatElemLabels, dateHeaderTag) {
91
91
  }
92
92
 
93
93
  result.sort(AgendaItem.compare);
94
-
95
- return result;
94
+ return joinDuplicateData(result);
96
95
  }
97
96
 
98
97
  /// Adds post data to the given calendar data item.
@@ -127,6 +126,14 @@ function addPostData(data) {
127
126
 
128
127
  data.sort(AgendaItem.compare);
129
128
 
129
+
130
+ return joinDuplicateData(data);
131
+ }
132
+
133
+ /// Ensures that there is only one entry per date (at most),
134
+ /// returns an updated version with agenda items moved such that
135
+ /// this is so.
136
+ function joinDuplicateData(data) {
130
137
  let newData = [];
131
138
  let currentItem;
132
139
 
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", () => {
@@ -16,4 +17,7 @@ addEventListener("load", () => {
16
17
  // After loading elements, but before loading elements like images.
17
18
  addEventListener("DOMContentLoaded", () => {
18
19
  handleSidebar();
20
+
21
+ // Apply user-specified settings
22
+ Settings.applySettings();
19
23
  });
@@ -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`);
@@ -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,25 @@ 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',
33
54
  };
@@ -31,4 +31,22 @@ 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',
34
52
  };
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.6
4
+ version: 0.0.9
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