minimal-mistakes-jekyll 4.25.1 → 4.26.0

Sign up to get free protection for your applications and to get access to all the features.
data/_includes/seo.html CHANGED
@@ -1,24 +1,13 @@
1
1
  <!-- begin _includes/seo.html -->
2
- {%- if site.url -%}
3
- {%- assign seo_url = site.url | append: site.baseurl -%}
4
- {%- endif -%}
5
- {%- assign seo_url = seo_url | default: site.github.url -%}
2
+ {%- assign title_separator = site.title_separator | default: '-' -%}
6
3
 
7
- {% assign title_separator = site.title_separator | default: '-' | replace: '|', '&#124;' %}
4
+ {%- assign page_title = page.title | default: site.title | replace: '|', '&#124;' -%}
5
+ {%- assign seo_title = page_title | append: " " | append: title_separator | append: " " | append: site.title | replace: '|', '&#124;' -%}
8
6
 
9
- {%- if page.title -%}
10
- {%- assign seo_title = page.title | append: " " | append: title_separator | append: " " | append: site.title -%}
11
- {%- endif -%}
7
+ {%- assign page_title = page_title | markdownify | strip_html | strip_newlines | escape_once -%}
8
+ {%- assign seo_title = seo_title | markdownify | strip_html | strip_newlines | escape_once -%}
12
9
 
13
- {%- if seo_title -%}
14
- {%- assign seo_title = seo_title | markdownify | strip_html | strip_newlines | escape_once -%}
15
- {%- endif -%}
16
-
17
- {% if page.canonical_url %}
18
- {%- assign canonical_url = page.canonical_url %}
19
- {% else %}
20
- {%- assign canonical_url = page.url | replace: "index.html", "" | absolute_url %}
21
- {% endif %}
10
+ {%- assign canonical_url = page.canonical_url | default: page.url | replace: "/index.html", "/" | absolute_url %}
22
11
 
23
12
  {%- assign seo_description = page.description | default: page.excerpt | default: site.description -%}
24
13
  {%- if seo_description -%}
@@ -32,14 +21,9 @@
32
21
  {%- assign author_twitter = author.twitter | replace: "@", "" -%}
33
22
  {%- endif -%}
34
23
 
35
- {%- assign page_large_image = page.header.og_image | default: page.header.overlay_image | default: page.header.image | absolute_url -%}
36
- {%- assign page_large_image = page_large_image | escape -%}
37
-
38
- {%- assign page_teaser_image = page.header.teaser | default: site.og_image | absolute_url -%}
39
- {%- assign page_teaser_image = page_teaser_image | escape -%}
40
-
41
- {%- assign site_og_image = site.og_image | absolute_url -%}
42
- {%- assign site_og_image = site_og_image | escape -%}
24
+ {%- assign page_large_image = page.header.og_image | default: page.header.overlay_image | default: page.header.image | absolute_url | escape -%}
25
+ {%- assign page_teaser_image = page.header.teaser | default: site.og_image | absolute_url | escape -%}
26
+ {%- assign site_og_image = site.og_image | absolute_url | escape -%}
43
27
 
44
28
  {%- if page.date -%}
45
29
  {%- assign og_type = "article" -%}
@@ -47,7 +31,7 @@
47
31
  {%- assign og_type = "website" -%}
48
32
  {%- endif -%}
49
33
 
50
- <title>{{ seo_title | default: site.title }}{% if paginator %}{% unless paginator.page == 1 %} {{ title_separator }} {{ site.data.ui-text[site.locale].page | default: "Page" }} {{ paginator.page }}{% endunless %}{% endif %}</title>
34
+ <title>{{ seo_title }}{% if paginator %}{% unless paginator.page == 1 %} {{ title_separator }} {{ site.data.ui-text[site.locale].page | default: "Page" }} {{ paginator.page }}{% endunless %}{% endif %}</title>
51
35
  <meta name="description" content="{{ seo_description }}">
52
36
 
53
37
  {% if author.name %}
@@ -60,7 +44,7 @@
60
44
  <meta property="og:type" content="{{ og_type }}">
61
45
  <meta property="og:locale" content="{{ site.locale | replace: "-", "_" | default: "en_US" }}">
62
46
  <meta property="og:site_name" content="{{ site.title }}">
63
- <meta property="og:title" content="{{ page.title | default: site.title | markdownify | strip_html | strip_newlines | escape_once }}">
47
+ <meta property="og:title" content="{{ page_title }}">
64
48
  <meta property="og:url" content="{{ canonical_url }}">
65
49
 
66
50
  {% if seo_description %}
@@ -75,7 +59,7 @@
75
59
 
76
60
  {% if site.twitter.username %}
77
61
  <meta name="twitter:site" content="@{{ site.twitter.username | replace: "@", "" }}">
78
- <meta name="twitter:title" content="{{ page.title | default: site.title | markdownify | strip_html | strip_newlines | escape_once }}">
62
+ <meta name="twitter:title" content="{{ page_title }}">
79
63
  <meta name="twitter:description" content="{{ seo_description }}">
80
64
  <meta name="twitter:url" content="{{ canonical_url }}">
81
65
 
@@ -121,21 +105,9 @@
121
105
  <link rel="next" href="{{ paginator.next_page_path | absolute_url }}">
122
106
  {% endif %}
123
107
 
124
- <script type="application/ld+json">
125
- {
126
- "@context": "https://schema.org",
127
- {% if site.social.type == "Organization" %}
128
- "@type": "Organization",
129
- "url": {{ '/' | absolute_url | jsonify }}{% if site.og_image %},
130
- "logo": {{ site_og_image | jsonify }}{% endif %}
131
- {% else %}
132
- "@type": "Person",
133
- "name": {{ site.social.name | default: site.name | jsonify }},
134
- "url": {{ '/' | absolute_url |jsonify }}{% if site.social.links %},
135
- "sameAs": {{ site.social.links | jsonify }}{% endif %}
136
- {% endif %}
137
- }
138
- </script>
108
+ {% if page.url == '/' %}
109
+ {% include schema.html %}
110
+ {% endif %}
139
111
 
140
112
  {% if site.google_site_verification %}
141
113
  <meta name="google-site-verification" content="{{ site.google_site_verification }}" />
@@ -23,4 +23,4 @@ layout: default
23
23
  {% endunless %}
24
24
  {{ content }}
25
25
  </div>
26
- </div>
26
+ </div>
@@ -4,40 +4,4 @@ layout: archive
4
4
 
5
5
  {{ content }}
6
6
 
7
- {% assign categories_max = 0 %}
8
- {% for category in site.categories %}
9
- {% if category[1].size > categories_max %}
10
- {% assign categories_max = category[1].size %}
11
- {% endif %}
12
- {% endfor %}
13
-
14
- <ul class="taxonomy__index">
15
- {% for i in (1..categories_max) reversed %}
16
- {% for category in site.categories %}
17
- {% if category[1].size == i %}
18
- <li>
19
- <a href="#{{ category[0] | slugify }}">
20
- <strong>{{ category[0] }}</strong> <span class="taxonomy__count">{{ i }}</span>
21
- </a>
22
- </li>
23
- {% endif %}
24
- {% endfor %}
25
- {% endfor %}
26
- </ul>
27
-
28
- {% assign entries_layout = page.entries_layout | default: 'list' %}
29
- {% for i in (1..categories_max) reversed %}
30
- {% for category in site.categories %}
31
- {% if category[1].size == i %}
32
- <section id="{{ category[0] | slugify }}" class="taxonomy__section">
33
- <h2 class="archive__subtitle">{{ category[0] }}</h2>
34
- <div class="entries-{{ entries_layout }}">
35
- {% for post in category.last %}
36
- {% include archive-single.html type=entries_layout %}
37
- {% endfor %}
38
- </div>
39
- <a href="#page-title" class="back-to-top">{{ site.data.ui-text[site.locale].back_to_top | default: 'Back to Top' }} &uarr;</a>
40
- </section>
41
- {% endif %}
42
- {% endfor %}
43
- {% endfor %}
7
+ {% include posts-taxonomy.html taxonomies=site.categories %}
data/_layouts/single.html CHANGED
@@ -21,8 +21,8 @@ layout: default
21
21
  <div id="main" role="main">
22
22
  {% include sidebar.html %}
23
23
 
24
- <article class="page h-entry" itemscope itemtype="https://schema.org/CreativeWork">
25
- {% if page.title %}<meta itemprop="headline" content="{{ page.title | markdownify | strip_html | strip_newlines | escape_once }}">{% endif %}
24
+ <article class="page" itemscope itemtype="https://schema.org/CreativeWork">
25
+ {% if page.title %}<meta itemprop="headline" content="{{ page.title | replace: '|', '&#124;' | markdownify | strip_html | strip_newlines | escape_once }}">{% endif %}
26
26
  {% if page.excerpt %}<meta itemprop="description" content="{{ page.excerpt | markdownify | strip_html | strip_newlines | escape_once }}">{% endif %}
27
27
  {% if page.date %}<meta itemprop="datePublished" content="{{ page.date | date_to_xmlschema }}">{% endif %}
28
28
  {% if page.last_modified_at %}<meta itemprop="dateModified" content="{{ page.last_modified_at | date_to_xmlschema }}">{% endif %}
@@ -30,14 +30,16 @@ layout: default
30
30
  <div class="page__inner-wrap">
31
31
  {% unless page.header.overlay_color or page.header.overlay_image %}
32
32
  <header>
33
- {% if page.title %}<h1 id="page-title" class="page__title p-name" itemprop="headline">
34
- <a href="{{ page.url | absolute_url }}" class="u-url" itemprop="url">{{ page.title | markdownify | remove: "<p>" | remove: "</p>" }}</a>
35
- </h1>{% endif %}
33
+ {% if page.title -%}
34
+ <h1 id="page-title" class="page__title" itemprop="headline">
35
+ <a href="{{ page.url | absolute_url }}" itemprop="url">{{ page.title | markdownify | remove: "<p>" | remove: "</p>" }}</a>
36
+ </h1>
37
+ {%- endif %}
36
38
  {% include page__meta.html %}
37
39
  </header>
38
40
  {% endunless %}
39
41
 
40
- <section class="page__content e-content" itemprop="text">
42
+ <section class="page__content" itemprop="text">
41
43
  {% if page.toc %}
42
44
  <aside class="sidebar__right {% if page.toc_sticky %}sticky{% endif %}">
43
45
  <nav class="toc">
data/_layouts/tags.html CHANGED
@@ -4,40 +4,4 @@ layout: archive
4
4
 
5
5
  {{ content }}
6
6
 
7
- {% assign tags_max = 0 %}
8
- {% for tag in site.tags %}
9
- {% if tag[1].size > tags_max %}
10
- {% assign tags_max = tag[1].size %}
11
- {% endif %}
12
- {% endfor %}
13
-
14
- <ul class="taxonomy__index">
15
- {% for i in (1..tags_max) reversed %}
16
- {% for tag in site.tags %}
17
- {% if tag[1].size == i %}
18
- <li>
19
- <a href="#{{ tag[0] | slugify }}">
20
- <strong>{{ tag[0] }}</strong> <span class="taxonomy__count">{{ i }}</span>
21
- </a>
22
- </li>
23
- {% endif %}
24
- {% endfor %}
25
- {% endfor %}
26
- </ul>
27
-
28
- {% assign entries_layout = page.entries_layout | default: 'list' %}
29
- {% for i in (1..tags_max) reversed %}
30
- {% for tag in site.tags %}
31
- {% if tag[1].size == i %}
32
- <section id="{{ tag[0] | slugify | downcase }}" class="taxonomy__section">
33
- <h2 class="archive__subtitle">{{ tag[0] }}</h2>
34
- <div class="entries-{{ entries_layout }}">
35
- {% for post in tag.last %}
36
- {% include archive-single.html type=entries_layout %}
37
- {% endfor %}
38
- </div>
39
- <a href="#page-title" class="back-to-top">{{ site.data.ui-text[site.locale].back_to_top | default: 'Back to Top' }} &uarr;</a>
40
- </section>
41
- {% endif %}
42
- {% endfor %}
43
- {% endfor %}
7
+ {% include posts-taxonomy.html taxonomies=site.tags %}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Minimal Mistakes Jekyll Theme 4.25.1 by Michael Rose
2
+ * Minimal Mistakes Jekyll Theme 4.26.0 by Michael Rose
3
3
  * Copyright 2013-2024 Michael Rose - mademistakes.com | @mmistakes
4
4
  * Free for personal and commercial use under the MIT license
5
5
  * https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
@@ -591,3 +591,60 @@ a.reversefootnote {
591
591
  position: static;
592
592
  }
593
593
  }
594
+
595
+ /*
596
+ Copy <pre> block to clipboard
597
+ ========================================================================== */
598
+
599
+ // a <textarea> to hold text for document.execCommand("copy")
600
+ .clipboard-helper {
601
+ // Prevent zooming on iOS
602
+ font-size: 12pt !important;
603
+ border: 0 !important;
604
+ padding: 0 !important;
605
+ margin: 0 !important;
606
+ outline: none !important;
607
+ position: absolute;
608
+ }
609
+
610
+ pre {
611
+ .clipboard-copy-button {
612
+ display: block;
613
+ position: absolute;
614
+ top: 0.6em;
615
+ right: 0.5em;
616
+ z-index: 1;
617
+ background: none;
618
+ border: none;
619
+ outline: none;
620
+ border-radius: 0.1em;
621
+ padding: 0.2em 0.5em;
622
+ color: white;
623
+ opacity: 0.4;
624
+ transition: color 0.25s linear -0.25s, opacity 0.25s linear;
625
+
626
+ &:hover {
627
+ color: #ffffca;
628
+ }
629
+
630
+ &::before {
631
+ content: '';
632
+ position: absolute;
633
+ top: 0;
634
+ right: 0;
635
+ bottom: 0;
636
+ left: 0;
637
+ z-index: 2;
638
+ }
639
+
640
+ @at-root {
641
+ .no-copy & {
642
+ display: none;
643
+ }
644
+ }
645
+ }
646
+
647
+ &:hover .clipboard-copy-button {
648
+ opacity: 1;
649
+ }
650
+ }
data/assets/js/_main.js CHANGED
@@ -2,39 +2,18 @@
2
2
  jQuery plugin settings and other scripts
3
3
  ========================================================================== */
4
4
 
5
- $(function() {
5
+ $(document).ready(function () {
6
6
  // FitVids init
7
7
  $("#main").fitVids();
8
8
 
9
- // Sticky sidebar
10
- var stickySideBar = function() {
11
- var show =
12
- $(".author__urls-wrapper").find("button").length === 0
13
- ? $(window).width() > 1024 // width should match $large Sass variable
14
- : !$(".author__urls-wrapper").find("button").is(":visible");
15
- if (show) {
16
- // fix
17
- $(".sidebar").addClass("sticky");
18
- } else {
19
- // unfix
20
- $(".sidebar").removeClass("sticky");
21
- }
22
- };
23
-
24
- stickySideBar();
25
-
26
- $(window).resize(function() {
27
- stickySideBar();
28
- });
29
-
30
9
  // Follow menu drop down
31
- $(".author__urls-wrapper").find("button").on("click", function() {
10
+ $(".author__urls-wrapper button").on("click", function () {
32
11
  $(".author__urls").toggleClass("is--visible");
33
12
  $(".author__urls-wrapper").find("button").toggleClass("open");
34
13
  });
35
14
 
36
15
  // Close search screen with Esc key
37
- $(document).keyup(function(e) {
16
+ $(document).keyup(function (e) {
38
17
  if (e.keyCode === 27) {
39
18
  if ($(".initial-content").hasClass("is--hidden")) {
40
19
  $(".search-content").toggleClass("is--visible");
@@ -44,12 +23,12 @@ $(function() {
44
23
  });
45
24
 
46
25
  // Search toggle
47
- $(".search__toggle").on("click", function() {
26
+ $(".search__toggle").on("click", function () {
48
27
  $(".search-content").toggleClass("is--visible");
49
28
  $(".initial-content").toggleClass("is--hidden");
50
29
  // set focus on input
51
- setTimeout(function() {
52
- $(".search-content").find("input").focus();
30
+ setTimeout(function () {
31
+ $(".search-content input").focus();
53
32
  }, 400);
54
33
  });
55
34
 
@@ -58,11 +37,11 @@ $(function() {
58
37
  offset: 20,
59
38
  speed: 400,
60
39
  speedAsDuration: true,
61
- durationMax: 500
40
+ durationMax: 500,
62
41
  });
63
42
 
64
43
  // Gumshoe scroll spy init
65
- if($("nav.toc").length > 0) {
44
+ if ($("nav.toc").length > 0) {
66
45
  var spy = new Gumshoe("nav.toc a", {
67
46
  // Active classes
68
47
  navClass: "active", // applied to the nav list item
@@ -77,10 +56,27 @@ $(function() {
77
56
  reflow: true, // if true, listen for reflows
78
57
 
79
58
  // Event support
80
- events: true // if true, emit custom events
59
+ events: true, // if true, emit custom events
81
60
  });
82
61
  }
83
62
 
63
+ // Auto scroll sticky ToC with content
64
+ document.addEventListener("gumshoeActivate", function (event) {
65
+ var target = event.target;
66
+ var scrollOptions = { behavior: "auto", block: "nearest", inline: "start" };
67
+
68
+ var tocElement = document.querySelector("aside.sidebar__right.sticky");
69
+ if (!tocElement) return;
70
+ if (window.getComputedStyle(tocElement).position !== "sticky") return;
71
+
72
+ if (target.parentElement.classList.contains("toc__menu") && target == target.parentElement.firstElementChild) {
73
+ // Scroll to top instead
74
+ document.querySelector("nav.toc header").scrollIntoView(scrollOptions);
75
+ } else {
76
+ target.scrollIntoView(scrollOptions);
77
+ }
78
+ });
79
+
84
80
  // add lightbox class to all image links
85
81
  $(
86
82
  "a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif'],a[href$='.webp']"
@@ -99,38 +95,120 @@ $(function() {
99
95
  gallery: {
100
96
  enabled: true,
101
97
  navigateByImgClick: true,
102
- preload: [0, 1] // Will preload 0 - before current, and 1 after the current image
98
+ preload: [0, 1], // Will preload 0 - before current, and 1 after the current image
103
99
  },
104
100
  image: {
105
- tError: '<a href="%url%">Image #%curr%</a> could not be loaded.'
101
+ tError: '<a href="%url%">Image #%curr%</a> could not be loaded.',
106
102
  },
107
103
  removalDelay: 500, // Delay in milliseconds before popup is removed
108
104
  // Class that is added to body when popup is open.
109
105
  // make it unique to apply your CSS animations just to this exact popup
110
106
  mainClass: "mfp-zoom-in",
111
107
  callbacks: {
112
- beforeOpen: function() {
108
+ beforeOpen: function () {
113
109
  // just a hack that adds mfp-anim class to markup
114
110
  this.st.image.markup = this.st.image.markup.replace(
115
111
  "mfp-figure",
116
112
  "mfp-figure mfp-with-anim"
117
113
  );
118
- }
114
+ },
119
115
  },
120
116
  closeOnContentClick: true,
121
- midClick: true // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source.
117
+ midClick: true, // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source.
122
118
  });
123
119
 
124
120
  // Add anchors for headings
125
- $('.page__content').find('h1, h2, h3, h4, h5, h6').each(function() {
126
- var id = $(this).attr('id');
127
- if (id) {
128
- var anchor = document.createElement("a");
129
- anchor.className = 'header-link';
130
- anchor.href = '#' + id;
131
- anchor.innerHTML = '<span class=\"sr-only\">Permalink</span><i class=\"fas fa-link\"></i>';
132
- anchor.title = "Permalink";
133
- $(this).append(anchor);
121
+ document
122
+ .querySelector(".page__content")
123
+ .querySelectorAll("h1, h2, h3, h4, h5, h6")
124
+ .forEach(function (element) {
125
+ var id = element.getAttribute("id");
126
+ if (id) {
127
+ var anchor = document.createElement("a");
128
+ anchor.className = "header-link";
129
+ anchor.href = "#" + id;
130
+ anchor.innerHTML =
131
+ '<span class="sr-only">Permalink</span><i class="fas fa-link"></i>';
132
+ anchor.title = "Permalink";
133
+ element.appendChild(anchor);
134
+ }
135
+ });
136
+
137
+ // Add copy button for <pre> blocks
138
+ var copyText = function (text) {
139
+ if (document.queryCommandEnabled("copy") && navigator.clipboard) {
140
+ navigator.clipboard.writeText(text).then(
141
+ () => true,
142
+ () => console.error("Failed to copy text to clipboard: " + text)
143
+ );
144
+ return true;
145
+ } else {
146
+ var isRTL = document.documentElement.getAttribute("dir") === "rtl";
147
+
148
+ var textarea = document.createElement("textarea");
149
+ textarea.className = "clipboard-helper";
150
+ textarea.style[isRTL ? "right" : "left"] = "-9999px";
151
+ // Move element to the same position vertically
152
+ var yPosition = window.pageYOffset || document.documentElement.scrollTop;
153
+ textarea.style.top = yPosition + "px";
154
+
155
+ textarea.setAttribute("readonly", "");
156
+ textarea.value = text;
157
+ document.body.appendChild(textarea);
158
+
159
+ var success = true;
160
+ try {
161
+ textarea.select();
162
+ success = document.execCommand("copy");
163
+ } catch (e) {
164
+ success = false;
165
+ }
166
+ textarea.parentNode.removeChild(textarea);
167
+ return success;
134
168
  }
135
- });
169
+ };
170
+
171
+ var copyButtonEventListener = function (event) {
172
+ var thisButton = event.target;
173
+
174
+ // Locate the <code> element
175
+ var codeBlock = thisButton.nextElementSibling;
176
+ while (codeBlock && codeBlock.tagName.toLowerCase() !== "code") {
177
+ codeBlock = codeBlock.nextElementSibling;
178
+ }
179
+ if (!codeBlock) {
180
+ // No <code> found - wtf?
181
+ console.warn(thisButton);
182
+ throw new Error("No code block found for this button.");
183
+ }
184
+
185
+ // Skip line numbers if present (i.e. {% highlight lineno %})
186
+ var realCodeBlock = codeBlock.querySelector("td.code, td.rouge-code");
187
+ if (realCodeBlock) {
188
+ codeBlock = realCodeBlock;
189
+ }
190
+ var result = copyText(codeBlock.innerText);
191
+ // Restore the focus to the button
192
+ thisButton.focus();
193
+ return result;
194
+ };
195
+
196
+ if (window.enable_copy_code_button) {
197
+ document
198
+ .querySelectorAll(".page__content pre > code")
199
+ .forEach(function (element, index, parentList) {
200
+ // Locate the <pre> element
201
+ var container = element.parentElement;
202
+ // Sanity check - don't add an extra button if there's already one
203
+ if (container.firstElementChild.tagName.toLowerCase() !== "code") {
204
+ return;
205
+ }
206
+ var copyButton = document.createElement("button");
207
+ copyButton.title = "Copy to clipboard";
208
+ copyButton.className = "clipboard-copy-button";
209
+ copyButton.innerHTML = '<span class="sr-only">Copy code</span><i class="far fa-copy"></i>';
210
+ copyButton.addEventListener("click", copyButtonEventListener);
211
+ container.prepend(copyButton);
212
+ });
213
+ }
136
214
  });