on master help sign in
build: add search back-end, api endpoint, autobuild
commite76c258f1511fe48613bee0562062ba12195093f authorMatilde Park <matilde@tlon.io> dateTue 22 Jun 2021, 18:20 (5 years ago) parent004f287
4 files changed+84−3
.gitignore+1 lib/cache.js+69 package.json+4−3 pages/api/search.js+10
.gitignore+1
@@ -14,6 +14,7 @@
1414
1515# production
1616/build
17+/cache
1718
1819# misc
1920.DS_Store
lib/cache.jsnew file+69
@@ -0,0 +1,69 @@
1+const fs = require("fs");
2+const path = require("path");
3+const matter = require("gray-matter");
4+const toml = require("@iarna/toml");
5+
6+const options = {
7+ engines: {
8+ toml: toml.parse.bind(toml),
9+ },
10+ language: "toml",
11+ delimiters: "+++",
12+};
13+
14+const index = [];
15+
16+function buildSearchIndex(dir) {
17+ const dirName = dir.split("/").slice(-1).join("");
18+ let metadata = {
19+ data: {
20+ title: dirName.charAt(0).toUpperCase() + dirName.slice(1),
21+ },
22+ };
23+
24+ try {
25+ metadata = matter(fs.readFileSync(path.join(dir, "_index.md")), options);
26+ } catch (err) {}
27+
28+ const children = fs.readdirSync(dir, { withFileTypes: true });
29+ const pages = children.filter((f) => f.isFile() && f.name !== "_index.md");
30+ const subdirs = children.filter((f) => f.isDirectory());
31+
32+ index.push(
33+ ...pages.map((page) => {
34+ const { data: pageData, content: pageContent } = matter(
35+ fs.readFileSync(path.join(dir, page.name)),
36+ options
37+ );
38+ return {
39+ title: pageData.title,
40+ base: page.name,
41+ slug: page.name.replace(/.md$/, ""),
42+ content: pageContent,
43+ parent: metadata.data.title,
44+ };
45+ })
46+ );
47+
48+ Object.fromEntries(
49+ subdirs.map((subdir) => [
50+ subdir.name,
51+ buildSearchIndex(path.join(dir, subdir.name)),
52+ ])
53+ );
54+}
55+
56+buildSearchIndex(path.join(process.cwd(), "content"));
57+
58+const fileContents = `export const index = ${JSON.stringify(index)}`;
59+
60+try {
61+ fs.readdirSync("cache");
62+} catch (err) {
63+ fs.mkdirSync("cache");
64+}
65+
66+fs.writeFile("cache/data.js", fileContents, function (err) {
67+ if (err) return console.error(err);
68+ console.log("Site index created.");
69+});
package.json+4−3
@@ -3,10 +3,11 @@
33 "version": "0.1.0",
44 "private": true,
55 "scripts": {
6− "dev": "next dev",
7− "build": "next build",
6+ "dev": "npm run cache-posts && next dev",
7+ "build": "npm run cache-posts && next build",
88 "start": "next start",
9− "prepare": "husky install"
9+ "prepare": "husky install",
10+ "cache-posts": "node lib/cache.js"
1011 },
1112 "dependencies": {
1213 "@iarna/toml": "^2.2.5",
pages/api/search.jsnew file+10
@@ -0,0 +1,10 @@
1+import { index } from "../../cache/data";
2+import FuzzySearch from "fuzzy-search";
3+
4+export default (req, res) => {
5+ const searcher = new FuzzySearch(index, ["title"], { sort: true });
6+ const results = searcher.search(req.query.q);
7+ res.statusCode = 200;
8+ res.setHeader("Content-Type", "application/json");
9+ res.end(JSON.stringify({ results }));
10+};