hematite 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b5c50c658bf984e5c096e0279fd2372b06c5d3fad9bb56eb3984c2218fe1aab
4
- data.tar.gz: d945cf8f34d17d8b9dc6468e6f2c54d2a19708890d4d54f5411d60b3c3b190df
3
+ metadata.gz: 7d562db0ed2225f8650bd5c5f4a463b484254df5c5b6324eb7b2febf6f072e0d
4
+ data.tar.gz: 415dee3a5e09d9e84f0f2abb907f613bf68edf2a5224816995462148155415ad
5
5
  SHA512:
6
- metadata.gz: 7a28e7505ec67d3e900d7fe85cd8d7cacd6dde237aca06a7b0f27146959d14f06d2760d2f478676513fe076e18432ef33b7bda54038816eb88801b81bab754d8
7
- data.tar.gz: 3506d2b3ee5aa0dd81343e8f9a2b08633348ff6692de35a42851498c91a33c12c207729c0971458aff51a1924fc0f83a792bbc3b75052405263a357f0d7717b2
6
+ metadata.gz: f36ce4207f588d36389548a4755140b78738731be85582c8208e7092940254613e5241417825c7a47d0322b606be5958fd46ed593d971e5dc70ecd9b5a506357
7
+ data.tar.gz: daf31b575712939d9de6b0fd0c0500727736fd2da81e9e70c7eff7b2229c07f269ad3394c2231542c9594b2c65dccf08ebfa261ab1d42a10ac12782d9ccf82bf
data/_config.yml CHANGED
@@ -2,7 +2,8 @@
2
2
  # Settings for the demo site.
3
3
  # `jekyll serve` does not auto-reload this file.
4
4
 
5
- title: Hematite Theme
5
+ title: The Hematite Theme
6
+ short_title: Hematite Theme
6
7
  description: A Jekyll theme intended for course websites
7
8
  permalink: pretty
8
9
 
@@ -2,4 +2,9 @@
2
2
  This is the header that appears in the navigation bar (at the top of the page)!
3
3
  Customize it here.
4
4
  {% endcomment %}
5
- <a href="{{ "/" | absolute_url }}">{{ site.title | default "Untitled Site" }}</a>
5
+ <a id="long_title" href="{{ "/" | absolute_url }}">
6
+ {{ site.title | default: "Untitled Site" }}
7
+ </a>
8
+ <a id="short_title" href="{{ "/" | absolute_url }}">
9
+ {{ site.short_title | default: site.title | default: "Untitiled" }}
10
+ </a>
@@ -0,0 +1,5 @@
1
+
2
+ @font-face {
3
+ font-family: FoulisGreek;
4
+ src: url({{ assets/fonts/FoulisGreek.ttf | absolute_path }});
5
+ }
@@ -35,9 +35,11 @@ layout: default
35
35
  const WRAPPING_DIV_EXP = /^\s*[<]div.*[>]((?:.|[\n\r])*)[<]\/div[>]\s*$/;
36
36
 
37
37
  import slideshow from "{{ 'assets/js/layout/remark_slideshow.mjs' | relative_url }}";
38
+ import { stringLookup } from "{{ 'assets/js/strings.mjs' | relative_url }}";
38
39
 
39
40
  let presentationFrame = document.querySelector("#presentation_frame");
40
41
  presentationFrame.src = {{ frame_resource_url | jsonify }};
42
+ presentationFrame.title = stringLookup('presentation_frame_title');
41
43
  window.presentationFrameLoaded = false;
42
44
 
43
45
 
@@ -111,6 +113,7 @@ layout: default
111
113
  `);
112
114
 
113
115
  presentationWin.initPresentation = (async () => {
116
+ presentationDoc.title = presentationFrame.title;
114
117
  await slideshow.start(presentationFrame.contentWindow, config);
115
118
 
116
119
  // Ensure that mermaid has already been run!
data/_sass/_elements.scss CHANGED
@@ -64,6 +64,10 @@ input::placeholder {
64
64
  padding: 6px;
65
65
  }
66
66
 
67
+ main pre {
68
+ overflow-x: auto;
69
+ }
70
+
67
71
  .main-container details {
68
72
  summary {
69
73
  cursor: pointer;
@@ -142,6 +146,17 @@ input::placeholder {
142
146
  padding-left: 20px;
143
147
  color: var(--text-color-faint);
144
148
  }
149
+
150
+ main {
151
+ // Some elements can grow larger than the available space.
152
+ // Allow scrolling.
153
+ @media screen {
154
+ .scrollable-container {
155
+ overflow-x: auto;
156
+ display: block;
157
+ }
158
+ }
159
+ }
145
160
  }
146
161
 
147
162
  // Markdown parsers may put `code` elements inside of `pre`
data/_sass/_nav.scss CHANGED
@@ -29,6 +29,10 @@ body > header {
29
29
  align-items: center;
30
30
  }
31
31
 
32
+ #short_title {
33
+ display: none;
34
+ }
35
+
32
36
  #toggle_sidebar_btn {
33
37
  margin-right: 10px;
34
38
  background-color: var(--primary-background-color);
@@ -38,9 +42,33 @@ body > header {
38
42
  #toggle_sidebar_btn {
39
43
  display: none;
40
44
  }
45
+
46
+ box-shadow: none;
47
+ border-bottom: 1px solid var(--line-color-light);
41
48
  }
42
49
  }
43
50
 
51
+ @mixin only-short-title {
52
+ body > header {
53
+ #long_title {
54
+ display: none !important;
55
+ color: red;
56
+ }
57
+
58
+ #short_title {
59
+ display: block;
60
+ }
61
+ }
62
+ }
63
+
64
+ :root.minimizedNavHeader {
65
+ @include only-short-title;
66
+ }
67
+
68
+ @media screen and (max-width: $site-content-preferred-width) {
69
+ @include only-short-title;
70
+ }
71
+
44
72
  :root {
45
73
  --header-effective-height: var(--header-height);
46
74
  }
Binary file
@@ -0,0 +1,8 @@
1
+ This directory includes fonts under OpenSource licenses. As the Hematite theme is distributed under the MIT, all fonts distributed with it must be free for commercial use.
2
+
3
+ This directory includes the following fonts:
4
+ * FoulisGreek
5
+ * by the JUnicode project
6
+ * https://www.fontspace.com/foulis-greek-font-f38341
7
+ * https://junicode.sourceforge.io/greek.html
8
+
@@ -11,16 +11,16 @@ noindex: true
11
11
  <style>
12
12
  /* Stylesheet mostly taken from https://github.com/gnab/remark/wiki#getting-started */
13
13
  @import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
14
- @import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
14
+ @import url(https://fonts.googleapis.com/css?family=Droid+Sans:400,700,400italic);
15
15
  @import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
16
16
 
17
- body { font-family: 'Droid Serif'; }
17
+ body { font-family: 'Droid Sans', sans-serif; }
18
18
  h1, h2, h3 {
19
19
  font-family: 'Yanone Kaffeesatz';
20
20
  font-weight: normal;
21
21
  }
22
22
 
23
- .remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
23
+ .remark-code, .remark-inline-code { font-family: 'Ubuntu Mono', monospace; }
24
24
 
25
25
  /* Show hidden slides to allow preprocessors (e.g. mermaid) to
26
26
  properly account for container size.
@@ -49,6 +49,11 @@ nav:hover, nav:focus-within {
49
49
  opacity: 1;
50
50
  }
51
51
 
52
+ /* Fix contrast issue */
53
+ .remark-slide-number {
54
+ opacity: 0.8;
55
+ }
56
+
52
57
  @media print {
53
58
  nav {
54
59
  display: none;
@@ -57,11 +57,14 @@ function expandBasedOnURL() {
57
57
  }
58
58
 
59
59
  let targetElem = document.querySelector(hash);
60
- let currentElem = targetElem;
61
60
 
62
- expandContainingDropdowns(targetElem);
63
-
64
- targetElem.focus();
61
+ if (targetElem) {
62
+ expandContainingDropdowns(targetElem);
63
+ targetElem.focus();
64
+ }
65
+ else {
66
+ console.warn(`Hash`, hash, `does not correspond to an element.`);
67
+ }
65
68
  };
66
69
 
67
70
  doExpansion(location.href);
@@ -47,6 +47,11 @@ function createTagLinks(page) {
47
47
 
48
48
  container.appendChild(tagElem);
49
49
  }
50
+
51
+ // Don't show the tag container if there aren't any tags
52
+ if (page.tags.length == 0) {
53
+ container.style.display = "none";
54
+ }
50
55
  }
51
56
 
52
57
  function fillDate(page) {
@@ -2,6 +2,8 @@ import { getUrlQuery, Searcher } from "../search.mjs";
2
2
  import { stringLookup } from "../strings.mjs";
3
3
  import UrlHelper from "../UrlHelper.mjs";
4
4
 
5
+ const GESTURE_MIN_TOUCH_MOVE_DIST = 40; // px
6
+
5
7
  function isInPresenterMode(targetDoc) {
6
8
  return targetDoc.body.classList.contains("remark-presenter-mode");
7
9
  }
@@ -13,7 +15,6 @@ function focusSearchResult(targetWin, query, targetMatchNo, slideshow, searcher)
13
15
  let currentSlideNo = slide.getSlideIndex() + 1;
14
16
 
15
17
  matchesFound += searcher.getNumberOfMatches(query, targetText);
16
- console.log("Considering ", targetText, " with ", matchesFound, "matches found so far");
17
18
 
18
19
  if (matchesFound > targetMatchNo) {
19
20
  slideshow.gotoSlide(currentSlideNo);
@@ -22,20 +23,27 @@ function focusSearchResult(targetWin, query, targetMatchNo, slideshow, searcher)
22
23
 
23
24
  // Now search the notes!
24
25
  if (slide.notes) {
25
- targetText = slide.notes.join("\n");
26
- matchesFound += searcher.getNumberOfMatches(query, targetText);
27
- if (matchesFound > targetMatchNo) {
28
- slideshow.gotoSlide(currentSlideNo);
29
-
30
- if (!isInPresenterMode(targetWin.document)) {
31
- slideshow.togglePresenterMode();
26
+ try {
27
+ targetText = (slide.notes.join ?? (() => slide.notes))("\n");
28
+ matchesFound += searcher.getNumberOfMatches(query, targetText);
29
+ if (matchesFound > targetMatchNo) {
30
+ slideshow.gotoSlide(currentSlideNo);
31
+
32
+ if (!isInPresenterMode(targetWin.document)) {
33
+ slideshow.togglePresenterMode();
34
+ }
35
+ return;
32
36
  }
33
- return;
37
+ }
38
+ catch (e) {
39
+ console.error(`Unable to search through notes for slide`, slide, `Error: `, e);
40
+ console.log("Continuing...");
34
41
  }
35
42
  }
36
43
  }
37
44
 
38
- console.log("Found ", matchesFound, " matches, which is less than the target of ", targetMatchNo);
45
+ console.log("Found ", matchesFound,
46
+ " matches, which is less than the target of ", targetMatchNo, ". Remaining on last slide.");
39
47
  slideshow.gotoLastSlide();
40
48
  return -1;
41
49
  }
@@ -70,6 +78,9 @@ function focusSlideFromHash(slideshow) {
70
78
  }
71
79
 
72
80
  async function main(targetWindow, config) {
81
+ // True if touch navigation is enabled.
82
+ let usingCustomTouchNav = false;
83
+
73
84
  if (!targetWindow.remark) {
74
85
  // Wait for page load if remark isn't available yet.
75
86
  await (new Promise(resolve => {
@@ -77,22 +88,32 @@ async function main(targetWindow, config) {
77
88
  }));
78
89
  }
79
90
 
91
+ // Customize touchscreen navigation — the default remark
92
+ // navigation can break buttons, zooming.
93
+ if (config?.navigation?.touch === true
94
+ || config?.navigation?.touch === undefined) {
95
+ config ??= {};
96
+ config.navigation ??= {};
97
+ config.navigation.touch = false;
98
+
99
+ usingCustomTouchNav = true;
100
+ }
101
+
80
102
  // See https://remarkjs.com/#8
81
103
  let slideshow = targetWindow.remark.create(config);
104
+ targetWindow.focus();
82
105
 
83
106
  // For debugging
84
107
  window.slideshow_debug = slideshow;
85
108
 
86
- targetWindow.focus();
87
-
88
109
  addExtendedControls(targetWindow, slideshow);
89
110
  focusSearchResultFromUrl(targetWindow, slideshow);
111
+ focusSlideFromHash(slideshow);
90
112
 
113
+ // Create a URL state we can navigate back to/restore to
91
114
  targetWindow.history.replaceState(null, targetWindow.location.href);
92
115
  let targetWinHistory = targetWindow.history.state;
93
116
 
94
- focusSlideFromHash(slideshow);
95
-
96
117
  window.addEventListener('hashchange', () => {
97
118
  focusSlideFromHash(slideshow);
98
119
  });
@@ -111,6 +132,44 @@ async function main(targetWindow, config) {
111
132
  UrlHelper.withReplacedHash(targetWindow.location.href, hashId));
112
133
  window.location.hash = hashId;
113
134
  });
135
+
136
+ // Add custom touch events to listen for navigation.
137
+ if (usingCustomTouchNav) {
138
+ let elemContainer = targetWindow.document.body;
139
+ let initialPos = {};
140
+ let handlingGesture = false;
141
+
142
+ elemContainer.addEventListener('pointerdown', evt => {
143
+ if (evt.pointerType == 'touch') {
144
+ // Only handle single-touch gestures
145
+ handlingGesture = evt.isPrimary;
146
+ initialPos = {
147
+ x: evt.clientX,
148
+ y: evt.clientY,
149
+ };
150
+
151
+ if (handlingGesture) {
152
+ evt.preventDefault();
153
+ }
154
+ }
155
+ });
156
+
157
+ elemContainer.addEventListener('pointerup', evt => {
158
+ if (evt.pointerType == 'touch' && handlingGesture) {
159
+ let dx = evt.clientX - initialPos.x;
160
+
161
+ if (Math.abs(dx) < GESTURE_MIN_TOUCH_MOVE_DIST) {
162
+ return;
163
+ }
164
+
165
+ if (dx < 0) {
166
+ slideshow.gotoNextSlide();
167
+ } else {
168
+ slideshow.gotoPreviousSlide();
169
+ }
170
+ }
171
+ });
172
+ }
114
173
  }
115
174
 
116
175
  /// Apply minor adjustments to the default remark layout
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 makeElemsScrollable from "./scrollables.mjs";
6
7
  import Settings from "./Settings.mjs";
7
8
 
8
9
  // After loading elements, images, css, etc.
@@ -17,6 +18,7 @@ addEventListener("load", () => {
17
18
  // After loading elements, but before loading elements like images.
18
19
  addEventListener("DOMContentLoaded", () => {
19
20
  handleSidebar();
21
+ makeElemsScrollable();
20
22
  });
21
23
 
22
24
  // Apply user-specified settings
@@ -0,0 +1,29 @@
1
+ /// Wrap elements that can be too wide in scrollable containers
2
+
3
+ const SCROLLABLE_CONTAINER_CLSS = "scrollable-container";
4
+
5
+ function makeScrollable() {
6
+ // Make tables scrollable
7
+ let elems = document.querySelectorAll("main > table");
8
+
9
+ for (const elem of elems) {
10
+ let container = document.createElement("div");
11
+ elem.parentElement.insertBefore(container, elem);
12
+ elem.remove();
13
+
14
+ container.classList.add(SCROLLABLE_CONTAINER_CLSS);
15
+ container.appendChild(elem);
16
+ }
17
+
18
+ // Make display math scrollable
19
+ elems = document.querySelectorAll("main > span > .katex-display");
20
+ for (const elem of elems) {
21
+ let container = elem.parentElement;
22
+
23
+ if (container.children.length == 1) {
24
+ container.classList.add(SCROLLABLE_CONTAINER_CLSS);
25
+ }
26
+ }
27
+ }
28
+
29
+ export default makeScrollable;
@@ -53,6 +53,7 @@ export default {
53
53
  page_theme_light: 'Light Theme',
54
54
  settings_minimize_header: 'Hide Header: ',
55
55
 
56
+ presentation_frame_title: 'Presentation slides',
56
57
  btn_next_slide: 'Go to next slide',
57
58
  btn_prev_slide: 'Go to previous slide',
58
59
  btn_print: 'Print',
@@ -51,6 +51,7 @@ export default {
51
51
  page_theme_light: 'Brillante',
52
52
  settings_minimize_header: 'Título escondido: ',
53
53
 
54
+ presentation_frame_title: 'Diapositivas de la presentación',
54
55
  btn_next_slide: 'Vaya a la diapositiva proxima',
55
56
  btn_prev_slide: 'Vaya a la diapositiva anterior',
56
57
  btn_print: 'Imprima',
data/assets/style.scss CHANGED
@@ -5,6 +5,8 @@ styles: true
5
5
 
6
6
  @import "hematite";
7
7
 
8
+ {% include scss/_fonts.scss %}
9
+
8
10
  {% if site.hematite.auto_invert_imgs %}
9
11
  // In dark mode, invert the brightness of images
10
12
  @include auto-invert-images;
@@ -5,6 +5,7 @@ styles: true
5
5
 
6
6
  // Only syntax highlighting. Useful for layouts like remark presentation.
7
7
 
8
+ {% include scss/_fonts.scss %}
8
9
  @import "_colors";
9
10
  @import "_hljs";
10
11
  @import "_rogue";
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.1.9
4
+ version: 0.1.10
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-25 00:00:00.000000000 Z
11
+ date: 2022-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -45,6 +45,7 @@ files:
45
45
  - _includes/nav/pages_list.html
46
46
  - _includes/nav/pinned_page.html
47
47
  - _includes/nav/sidebar.html
48
+ - _includes/scss/_fonts.scss
48
49
  - _includes/settings.html
49
50
  - _layouts/calendar.html
50
51
  - _layouts/default.html
@@ -63,6 +64,8 @@ files:
63
64
  - _sass/_rogue.scss
64
65
  - _sass/_sizes.scss
65
66
  - _sass/hematite.scss
67
+ - assets/fonts/FoulisGreek.ttf
68
+ - assets/fonts/README.txt
66
69
  - assets/html/all_tags.html
67
70
  - assets/html/remark_presentation_frame.html
68
71
  - assets/html/settings.html
@@ -81,6 +84,7 @@ files:
81
84
  - assets/js/layout/remark_slideshow.mjs
82
85
  - assets/js/linkButtonGenerator.mjs
83
86
  - assets/js/main.mjs
87
+ - assets/js/scrollables.mjs
84
88
  - assets/js/search.mjs
85
89
  - assets/js/sidebar.mjs
86
90
  - assets/js/string_data.mjs