astro-accelerator 0.0.101 → 0.0.103

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.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.101",
2
+ "version": "0.0.103",
3
3
  "author": "Steve Fenton",
4
4
  "name": "astro-accelerator",
5
5
  "description": "A super-lightweight, accessible, SEO-friendly starter project for Astro",
@@ -14,11 +14,11 @@ html {
14
14
  outline: 0;
15
15
  padding: 0;
16
16
  vertical-align: baseline;
17
- }
17
+ }
18
18
 
19
- html {
19
+ html {
20
20
  scroll-padding-top: 5em;
21
- }
21
+ }
22
22
 
23
23
  body {
24
24
  background-color: var(--aft);
@@ -642,6 +642,34 @@ form.site-search button {
642
642
  font-family: var(--code-font);
643
643
  }
644
644
 
645
+ .result-headings li {
646
+ display: none;
647
+ }
648
+
649
+ .result-headings li:nth-child(-n+3) {
650
+ display: block;
651
+ }
652
+
653
+ .result-headings:has(li:nth-child(n+4))::after {
654
+ content: 'See more >';
655
+ color: var(--fore-link);
656
+ text-decoration: underline;
657
+ }
658
+
659
+ .result-headings:focus-within li {
660
+ display: block;
661
+ }
662
+
663
+ .result-headings:focus-within::after {
664
+ display: none;
665
+ }
666
+
667
+ .show-more {
668
+ padding: 0.5em 1em;
669
+ background-color: var(--fore-link);
670
+ color: var(--aft-link-alt);
671
+ }
672
+
645
673
  @media (max-width: 860px) {
646
674
  form.site-search div {
647
675
  grid-template-columns: repeat(1, auto);
@@ -5,40 +5,52 @@ import { raiseEvent } from './modules/events.js';
5
5
  import { contains, containsWord, sanitise, explode, highlight } from './modules/string.js';
6
6
 
7
7
  /**
8
- type Heading = {
9
- text: string;
10
- safeText: string;
11
- slug: string;
12
- }
13
-
14
- type SearchEntry = {
15
- score: number;
16
- title: string;
17
- safeTitle: string;
18
- description: string;
19
- safeDescription: string;
20
- headings: Heading[];
21
- tags: string;
22
- url: string;
23
- date: string;
24
- matchedHeadings: Heading[];
25
- }
8
+ @typedef {
9
+ {
10
+ text: string;
11
+ safeText: string;
12
+ slug: string;
13
+ }
14
+ } Heading
15
+
16
+ @typedef {
17
+ {
18
+ foundWords: number;
19
+ score: number;
20
+ title: string;
21
+ keywords: string;
22
+ safeTitle: string;
23
+ description: string;
24
+ safeDescription: string;
25
+ headings: Heading[];
26
+ tags: string[];
27
+ url: string;
28
+ date: string;
29
+ matchedHeadings: Heading[];
30
+ }
31
+ } SearchEntry
26
32
  */
27
33
 
28
- var dataUrl = qs('#site-search').dataset.sourcedata;
29
- var haystack = /** @type {SearchEntry} */ [];
34
+ /** @type {SearchEntry[]} */
35
+ var haystack = [];
30
36
  var currentQuery = '';
37
+ var dataUrl = qs('#site-search').dataset.sourcedata;
31
38
 
32
39
  var ready = false;
33
40
  var scrolled = false;
34
41
 
35
42
  /**
36
- *
43
+ * Search term `s` and number of results `r`
37
44
  * @param {string} s
45
+ * @param {number|null} [r=12]
38
46
  * @returns
39
47
  */
40
- function search(s) {
41
- const needles = /** @type {SearchEntry} */ [];
48
+ function search(s, r) {
49
+ const numberOfResults = r ?? 12;
50
+ console.log('search', s, numberOfResults);
51
+
52
+ /** @type {SearchEntry[]} */
53
+ const needles = [];
42
54
 
43
55
  // Clean the input
44
56
  const cleanQuery = sanitise(s);
@@ -52,7 +64,7 @@ function search(s) {
52
64
  currentQuery = cleanQuery;
53
65
  const queryTerms = explode(currentQuery);
54
66
 
55
- s.length > 0 && haystack.forEach( (item) => {
67
+ cleanQuery.length > 0 && haystack.forEach( (item) => {
56
68
 
57
69
  let foundWords = 0;
58
70
  item.score = 0;
@@ -152,7 +164,7 @@ function search(s) {
152
164
  const ol = document.createElement('ol');
153
165
  ol.className = 'site-search-results';
154
166
 
155
- const limit = Math.min(needles.length, 12);
167
+ const limit = Math.min(needles.length, numberOfResults);
156
168
 
157
169
  // @ts-ignore
158
170
  const siteUrl = new URL(site_url);
@@ -176,25 +188,30 @@ function search(s) {
176
188
  markers.className = 'result-text';
177
189
  markers.innerHTML = highlight(needle.description, queryTerms);
178
190
 
179
- const headings = document.createElement('ul');
180
- markers.className = 'result-headings';
181
- console.log(needle.matchedHeadings);
182
- needle.matchedHeadings
183
- .forEach(h => {
184
- const item = document.createElement('li');
185
- const link = document.createElement('a');
186
- link.href = url + '#' + h.slug;
187
- link.innerHTML = highlight(h.text, queryTerms);
188
- item.appendChild(link);
189
- headings.append(item);
190
- });
191
-
192
191
  const li = document.createElement('li');
192
+ li.dataset.score = (Math.round((needle.score/ total) * 100)).toString();
193
193
  li.appendChild(a);
194
194
  li.appendChild(path);
195
195
  li.appendChild(markers);
196
- li.append(headings);
197
- li.dataset.score = (Math.round((needle.score/ total) * 100)).toString();
196
+
197
+ if (needle.matchedHeadings.length > 0) {
198
+ const headings = document.createElement('ul');
199
+ headings.className = 'result-headings';
200
+
201
+ headings.tabIndex = 0;
202
+
203
+ needle.matchedHeadings
204
+ .forEach(h => {
205
+ const item = document.createElement('li');
206
+ const link = document.createElement('a');
207
+ link.href = url + '#' + h.slug;
208
+ link.innerHTML = highlight(h.text, queryTerms);
209
+ item.appendChild(link);
210
+ headings.append(item);
211
+ });
212
+
213
+ li.appendChild(headings);
214
+ }
198
215
 
199
216
  ol.appendChild(li);
200
217
  }
@@ -204,14 +221,30 @@ function search(s) {
204
221
  ? results.dataset.emptytitle || 'No Results'
205
222
  : results.dataset.title || 'Results';
206
223
 
224
+ const more = document.createElement('button');
225
+ more.className = 'show-more';
226
+ more.type = 'button';
227
+ more.innerHTML = 'See more';
228
+ more.addEventListener('click', function() {
229
+ currentQuery = '';
230
+ const newTotal = numberOfResults + 12;
231
+ console.log('More', newTotal);
232
+ search(s, newTotal);
233
+ })
234
+
207
235
  results.innerHTML = '';
208
236
  results.appendChild(h2);
209
237
  results.appendChild(ol);
210
238
 
239
+ if (needles.length > numberOfResults) {
240
+ results.appendChild(more);
241
+ }
242
+
211
243
  const address = window.location.href.split('?')[0];
212
244
  window.history.pushState({}, '', address + '?q=' + encodeURIComponent(cleanQuery));
213
245
  }
214
246
 
247
+ /** @type {Number} */
215
248
  var debounceTimer;
216
249
 
217
250
  function debounceSearch() {
@@ -248,9 +281,11 @@ fetch(dataUrl)
248
281
  item.headings.forEach(h => h.safeText = sanitise(h.text));
249
282
  }
250
283
 
251
- var siteSearch = qs('#site-search');
284
+ /** @type {HTMLFormElement} */
285
+ const siteSearch = qs('#site-search');
252
286
 
253
- var siteSearchQuery = qs('#site-search-query');
287
+ /** @type {HTMLInputElement} */
288
+ const siteSearchQuery = qs('#site-search-query');
254
289
 
255
290
  if (siteSearch == null || siteSearchQuery == null) {
256
291
  throw new Error('Cannot find #site-search or #site-search-query');
@@ -276,7 +311,7 @@ fetch(dataUrl)
276
311
 
277
312
  const params = new URLSearchParams(window.location.search);
278
313
  if (params.has('q')) {
279
- siteSearchQuery.value = params.get('q');
314
+ siteSearchQuery.value = params.get('q') ?? '';
280
315
  }
281
316
 
282
317
  debounceSearch();