hematite 0.1.13 → 0.1.14

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: 5428a81a66f2c162d5db506a782443ab49ec31a2a2b67a02dec1cab941828768
4
- data.tar.gz: 4a54bb491b61987364791315c6b4024b6fc019a3ba42f5488f43fb7f9c9ff704
3
+ metadata.gz: e7d0e540229aa59560164e505b1f9c56bfc06410483f121f0f37de4b35f14648
4
+ data.tar.gz: e134ec448a27e0e1ab0b6c6fb058a71248d9a59c182956a6b873834c150eb120
5
5
  SHA512:
6
- metadata.gz: '08188e55d1fc0e2f342a186ac1cc57c0226fe7b138cdb5e2f622716b29f4a5cf41768220f9dafb3971d2081dfef5cbee1cb8f485cd6e041589b6a3472a63204f'
7
- data.tar.gz: 1ddbfb8aa3b14052e0befc9e5dc6b59f1486705dc5f82033337a08a085368e27b6b1a51601db7e26b9578af0fafe74c0b3951a0e3fcda496ff5de23b35ad4b88
6
+ metadata.gz: f0629528aa7d95d26b68b488a2b5110625471856310273f74db557a8b543db35ccb072af00ffed6195d61e7eef1ed50ac755f55b034fe4c6fa41c22c7e0d35df
7
+ data.tar.gz: 31c8354bfa13a6ce9fb8531835c367214a6419d20ddb5246092271f2caf81fded7e0aba03db2e52e0166b40500d1bb2a4b0f4d31856feb94375c840f095b4f79
data/_sass/_nav.scss CHANGED
@@ -124,7 +124,6 @@ nav.sidebar {
124
124
  transform: scale(0, 1) translate(-30px, 0);
125
125
 
126
126
  color: var(--primary-text-color);
127
- background-color: var(--primary-background-color);
128
127
  box-shadow: 0 0 2px var(--shadow-color-light);
129
128
  padding: $navbar-padding;
130
129
 
@@ -138,6 +137,15 @@ nav.sidebar {
138
137
  transform-origin: left;
139
138
  transition: opacity 0.5s ease, transform 0.5s ease, width 0.5s ease;
140
139
 
140
+ // Work around a rendering bug in Safari — apply the background color to both
141
+ // the results pane and the container.
142
+ //
143
+ // Without this, Safari may display elements of pinned-pages in the same
144
+ // location as the search results.
145
+ &, .search-results {
146
+ background-color: var(--primary-background-color);
147
+ }
148
+
141
149
 
142
150
  // Container with search box and button
143
151
  > .search-container {
@@ -25,6 +25,7 @@ h1, h2, h3 {
25
25
  }
26
26
 
27
27
  body.mdSourceView {
28
+ padding-top: 50px;
28
29
  background: white;
29
30
  color: black;
30
31
  }
@@ -0,0 +1,37 @@
1
+
2
+ import { assertEq } from "./assertions.mjs";
3
+
4
+ let htmlReplacements = [
5
+ [ /[&]/g, '&' ],
6
+ [ /[<]/g, '&lt;' ],
7
+ [ /[>]/g, '&gt;' ],
8
+ ];
9
+
10
+ var EscapeHelper = {
11
+ escapeHTML(text) {
12
+ for (const item of htmlReplacements) {
13
+ text = text.replace(item[0], item[1]);
14
+ }
15
+
16
+ return text;
17
+ },
18
+ // Escape for usage within a regex expression
19
+ escapeRegex(text) {
20
+ return text.replace(/([\*\(\).\[\]\{\}\^\$\-\=\;\:\'\"\\])/g, '\\$1'); //'
21
+ },
22
+ // Escape text for usage within a replacement pattern
23
+ // E.g. "foobar".replaceAll("foo", text);
24
+ escapeReplacePattern(text) {
25
+ return text.replace(/\$/g, '$$$$');
26
+ }
27
+ };
28
+
29
+ assertEq("Test escape <", EscapeHelper.escapeHTML('<'), '&lt;');
30
+ assertEq("Test escape multiple <", EscapeHelper.escapeHTML('<a></a>'), '&lt;a&gt;&lt;/a&gt;');
31
+ assertEq("Test escape >", EscapeHelper.escapeHTML('>'), '&gt;');
32
+ assertEq("Test escape identity", EscapeHelper.escapeHTML('Hello, world.'), 'Hello, world.');
33
+ assertEq("Test regex escape simple", EscapeHelper.escapeRegex(".*"), "\\.\\*");
34
+ assertEq("Test regex more complicated escape", EscapeHelper.escapeRegex("This, is a test... :)"), "This, is a test\\.\\.\\. \\:\\)");
35
+ assertEq("Test replace pattern escape", EscapeHelper.escapeReplacePattern("0$ and 24 cents"), "0$$ and 24 cents");
36
+
37
+ export default EscapeHelper;
@@ -37,6 +37,12 @@ function createTagLinks(page) {
37
37
  let label = document.querySelector("#post_tags > #tag_header_lbl");
38
38
  label.innerText = stringLookup(`tags`);
39
39
 
40
+ // Don't show the tag container if there aren't any tags
41
+ if (!page.tags || page.tags.length == 0) {
42
+ container.style.display = "none";
43
+ return;
44
+ }
45
+
40
46
  for (const tag of page.tags) {
41
47
  let tagElem = document.createElement("a");
42
48
  tagElem.style.display = "inline-block";
@@ -47,11 +53,6 @@ function createTagLinks(page) {
47
53
 
48
54
  container.appendChild(tagElem);
49
55
  }
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
- }
55
56
  }
56
57
 
57
58
  function fillDate(page) {
data/assets/js/search.mjs CHANGED
@@ -7,6 +7,7 @@ import { expandContainingDropdowns } from "./dropdownExpander.mjs";
7
7
  import AnimationUtil from "./AnimationUtil.mjs";
8
8
  import AsyncUtil from "./AsyncUtil.mjs";
9
9
  import UrlHelper from "./UrlHelper.mjs";
10
+ import EscapeHelper from "./EscapeHelper.mjs";
10
11
 
11
12
  const PAGE_DATA_URL = `{{ "/assets/search_data.json" | relative_url }}`;
12
13
  const MATCHING_TITLE_PRIORITY_INCREMENT = 15;
@@ -177,6 +178,7 @@ class Searcher {
177
178
  results.push({
178
179
  index,
179
180
  context,
181
+ matchIndex: matchLoc,
180
182
  pageData,
181
183
  });
182
184
 
@@ -305,17 +307,35 @@ function handleSearch(searcher) {
305
307
 
306
308
  searchResults.replaceChildren(descriptionElem);
307
309
 
310
+ // Adds HTML to bold/italicize all results in [context].
311
+ // [context] is HTML-escaped before adding to the result.
312
+ const boldResults = (context) => {
313
+ let result = "";
314
+ let queryRegex = new RegExp(`(${EscapeHelper.escapeRegex(query)})`, `ig`);
315
+ let contextHTML = "";
316
+ let lastIdx = 0;
317
+ for (const match of context.matchAll(queryRegex)) {
318
+ result += EscapeHelper.escapeHTML(context.substring(lastIdx, match.index));
319
+ result += "<b><i>" + EscapeHelper.escapeHTML(match[0]) + "</i></b>";
320
+ lastIdx = match.index + match[0].length;
321
+ }
322
+ result += EscapeHelper.escapeHTML(context.substring(lastIdx));
323
+
324
+ return result;
325
+ };
326
+
308
327
  for (const result of results) {
309
328
  let link = document.createElement("a");
310
- let context = document.createElement("div");
311
- context.classList.add('context');
329
+ let contextElem = document.createElement("div");
330
+ contextElem.classList.add('context');
312
331
 
313
332
  link.innerText = result.pageData.title ?? stringLookup(`untitled`);
314
333
  link.href =
315
334
  result.pageData.url + `?query=${escape(query)},index=${result.index}`;
316
- context.innerText = result.context;
317
335
 
318
- link.appendChild(context);
336
+ contextElem.innerHTML = boldResults(result.context);
337
+
338
+ link.appendChild(contextElem);
319
339
  searchResults.appendChild(link);
320
340
  }
321
341
 
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.13
4
+ version: 0.1.14
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-29 00:00:00.000000000 Z
11
+ date: 2022-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -75,6 +75,7 @@ files:
75
75
  - assets/js/AnimationUtil.mjs
76
76
  - assets/js/AsyncUtil.mjs
77
77
  - assets/js/DateUtil.mjs
78
+ - assets/js/EscapeHelper.mjs
78
79
  - assets/js/PageAlert.mjs
79
80
  - assets/js/Settings.mjs
80
81
  - assets/js/UrlHelper.mjs