-
Notifications
You must be signed in to change notification settings - Fork 1
/
2024-08-29-my-blog-search-function.html
174 lines (161 loc) · 7.66 KB
/
2024-08-29-my-blog-search-function.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="description" content="This post records why and how I made the current blog search function.">
<link rel="alternate"
type="application/rss+xml"
href="https://chenyo.me/rss.xml"
title="RSS feed for https://chenyo.me">
<title>My blog search function</title>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'],['\\(','\\)']]}});
</script>
<meta name="author" content="chenyo">
<meta name="referrer" content="no-referrer">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/style.css" type="text/css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/>
<link rel="favicon" type="image/x-icon" href="favicon.ico">
<script src="assets/search.js"></script></head>
<body>
<div id="preamble" class="status">
<header>
<h1><a href="https://chenyo.me">Chenyo's org-static-blog</a></h1>
<nav>
<a href="https://chenyo.me">Home</a>
<a href="archive.html">Archive</a>
<a href="tags.html">Tags</a>
<div id="search-container">
<input type="text" id="search-input" placeholder="Search anywhere...">
<i class="fas fa-search search-icon"></i>
</div>
</nav>
</header></div>
<div id="content">
<div class="post-date">29 Aug 2024</div><h1 class="post-title"><a href="https://chenyo.me/2024-08-29-my-blog-search-function.html">My blog search function</a></h1>
<nav id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org661ba02">1. What happened</a></li>
<li><a href="#org34b8b6c">2. What is not enough with existing search functions?</a></li>
<li><a href="#org7d870de">3. What does the search function do in this blog?</a></li>
<li><a href="#org7754ea2">4. How is it implemented?</a></li>
<li><a href="#org0123076">5. How can it be improved?</a></li>
</ul>
</div>
</nav>
<div id="outline-container-org661ba02" class="outline-2">
<h2 id="org661ba02"><span class="section-number-2">1.</span> What happened</h2>
<div class="outline-text-2" id="text-1">
<p>
Two months ago, I started to use the current blog to keep track of my study and personal notes.
</p>
<p>
This blog uses <a href="https://github.com/bastibe/org-static-blog">bastibe/org-static-blog</a>, which is a convenient Emacs package to publish a static blog from Org-mode files.
</p>
<p>
When I first started, this blog had no styling at all.
With the help of Claude, I gradually decorated it with the theme and fonts of my choice.
</p>
<p>
During this process, my husband made a feature request: a blog search function.
</p>
</div>
</div>
<div id="outline-container-org34b8b6c" class="outline-2">
<h2 id="org34b8b6c"><span class="section-number-2">2.</span> What is not enough with existing search functions?</h2>
<div class="outline-text-2" id="text-2">
<p>
Most default search tools provided by popular static website frameworks do not return complete search results and their context.
</p>
<p>
For instance, I am learning database design.
Assume I cannot remember what a “slotted page” is but I know I have noted it before.
If I enter “slotted” in the search box of a Jekyll-based blog, it will provide me with 2 post links implying these posts contain this keyword.
In the best case, it also highlights the first occurrence of “slotted” in each post with its context.
</p>
<p>
This does not really meet my needs.
I would like to see all notes I have made for “slotted” to better refresh my memory, but the current results force me to click each post and perform a local search myself to achieve this goal.
</p>
<p>
I understand that modern search tools consider scalability and intelligence.
However, for a personal blog, we can achieve greater breadth.
</p>
</div>
</div>
<div id="outline-container-org7d870de" class="outline-2">
<h2 id="org7d870de"><span class="section-number-2">3.</span> What does the search function do in this blog?</h2>
<div class="outline-text-2" id="text-3">
<figure id="org4ce5770">
<img src="./static/blog-search.gif" alt="blog-search.gif" align="center" width="700px" style="border: 1px solid black;">
<figcaption><span class="figure-number">Figure 1: </span>A blog search example</figcaption>
</figure>
<p>
The current search function searches for all occurrences of the given search input and highlights each occurrence in an item surrounded by its context, e.g., 50 characters before and after the input.
If multiple occurrences are close to each other, they are displayed once in the same item.
Clicking each item opens a new tab and jumps to the closest header before the input.
</p>
<p>
In this way, I can immediately see all results and their context on one page, and I only click an item when the short context is not sufficient.
</p>
</div>
</div>
<div id="outline-container-org7754ea2" class="outline-2">
<h2 id="org7754ea2"><span class="section-number-2">4.</span> How is it implemented?</h2>
<div class="outline-text-2" id="text-4">
<p>
I implemented the search function along with all styling with the help of Cursor.
The full logic can be found in <a href="https://github.com/chenyo-17/org-static-blog/blob/main/assets/search.js">search.js</a>.
</p>
<p>
In short, every time I build the blog, a list of all post links is stored in <a href="https://github.com/chenyo-17/org-static-blog/blob/main/assets/post-list.json">post-list.json</a>.
When the page is loaded, for each post link, the blog caches the full post content and all header indices.
When a search input is detected, the search function iterates through each post to find each occurrence and the closest header.
It then wraps the occurrence with certain context and prepares the link by appending the header tag to the post link.
</p>
</div>
</div>
<div id="outline-container-org0123076" class="outline-2">
<h2 id="org0123076"><span class="section-number-2">5.</span> How can it be improved?</h2>
<div class="outline-text-2" id="text-5">
<p>
The current search function is simple and sub-optimal.
It always re-stores all posts when the page is reloaded and is not lazy at all.
The search is also neither fuzzy nor the most efficient.
</p>
<p>
It just works well so far for a personal blog with about 30 posts.
</p>
<p>
In addition, after I finished the implementation, my husband made another feature request: can you also highlight all occurrences in the opened link?
</p>
</div>
</div>
<div class="taglist"><a href="https://chenyo.me/tags.html">Tags</a>: <a href="https://chenyo.me/tag-personal.html">personal</a> <a href="https://chenyo.me/tag-blog.html">blog</a> </div></div>
<div id="postamble" class="status"><div id="search-results"></div>
<footer>
<div class="footer-content">
<div class="footer-left">
<p>© 2024 chenyo. Some rights reserved.</p>
<a rel="license" href="http://creativecommons.org/licenses/by-nc/4.0/">
<img alt="Creative Commons License" style="border-width: 0"
src="https://i.creativecommons.org/l/by-nc/4.0/88x31.png"/>
</a>
</div>
<div class="social-links">
<a href="https://t.me/chenyo17" target="_blank" rel="noopener noreferrer">
<i class="fab fa-telegram"></i>
</a>
<a href="https://github.com/chenyo-17" target="_blank" rel="noopener noreferrer">
<i class="fab fa-github"></i>
</a>
</div>
</footer></div>
</body>
</html>