on master help sign in
Merge pull request #1674 from urbit/mp/index-headings

search: index and search through page headings

commit42d913303a848c231d0ea5af63e17c4ca33f4e81 authormatildepark <matilde.park@urbit.org> dateTue 26 Jul 2022, 15:19 (4 years ago) parent775ca666affbae
3 files changed+45−1
components/Search.js+15 lib/cache.js+8 pages/api/search.js+22−1
components/Search.js+15
@@ -282,6 +282,11 @@ class Search extends Component {
282282 }`}
283283 >
284284 {item.content.content}
285+ {item?.content?.foundOnPage && (
286+ <span className="italic block">
287+ Found in page content
288+ </span>
289+ )}
285290 </p>
286291 </div>
287292 </li>
@@ -323,6 +328,11 @@ class Search extends Component {
323328 }`}
324329 >
325330 {item.content.content}
331+ {item?.content?.foundOnPage && (
332+ <span className="italic block">
333+ Found in page content
334+ </span>
335+ )}
326336 </p>
327337 </div>
328338 </li>
@@ -364,6 +374,11 @@ class Search extends Component {
364374 }`}
365375 >
366376 {item.content.content}
377+ {item?.content?.foundOnPage && (
378+ <span className="italic block">
379+ Found in page content
380+ </span>
381+ )}
367382 </p>
368383 </div>
369384 </li>
lib/cache.js+8
@@ -2,6 +2,7 @@ const fs = require("fs");
22const path = require("path");
33const matter = require("gray-matter");
44const toml = require("@iarna/toml");
5+const markdoc = require("@markdoc/markdoc");
56
67const options = {
78 engines: {
@@ -37,6 +38,8 @@ function buildSearchIndex(dir) {
3738 fs.readFileSync(path.join(dir, page.name)),
3839 options
3940 );
41+ const parsed = markdoc.parse(pageContent);
42+ const transform = markdoc.transform(parsed);
4043 return {
4144 title: pageData.title,
4245 base: page.name,
@@ -46,6 +49,11 @@ function buildSearchIndex(dir) {
4649 page.name.replace(/.md$/, "")
4750 ),
4851 content: pageData.description || "",
52+ headings: transform.children
53+ .filter((e) => e.name === "h2" || e.name === "h3")
54+ .map((e) => e.children)
55+ .flat()
56+ .filter((e) => typeof e === "string"),
4957 parent: metadata.data.title,
5058 };
5159 })
pages/api/search.js+22−1
@@ -8,7 +8,28 @@ export default (req, res) => {
88 e?.slug.includes(req.query.q.toLowerCase()) ||
99 e?.parent.toLowerCase().includes(req.query.q.toLowerCase())
1010 );
11− const sorted = levenSort(results, req.q, ["title", "slug", "parent"]);
11+
12+ results.push(
13+ ...index
14+ .filter((e) => !results.includes(e))
15+ .filter((e) => {
16+ let found = false;
17+ e.headings.forEach((heading) => {
18+ if (heading.toLowerCase().includes(req.query.q.toLowerCase())) {
19+ found = true;
20+ }
21+ });
22+ return found;
23+ })
24+ .map((e) => ({ ...e, foundOnPage: true }))
25+ );
26+
27+ const sorted = levenSort(results, req.q, [
28+ "title",
29+ "slug",
30+ "parent",
31+ "headings",
32+ ]);
1233 res.statusCode = 200;
1334 res.setHeader("Content-Type", "application/json");
1435 res.end(JSON.stringify({ results: sorted }));