hematite 0.1.9 → 0.1.10

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: 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