Skip to content

Instantly share code, notes, and snippets.

@eliyas5044
Created July 23, 2023 11:09
Show Gist options
  • Save eliyas5044/a55fc345412783b22414e4873a869fa5 to your computer and use it in GitHub Desktop.
Save eliyas5044/a55fc345412783b22414e4873a869fa5 to your computer and use it in GitHub Desktop.
AstroJS and MeiliSearch
import fs from "fs/promises";
import { JSDOM } from "jsdom";
import path from "path";
import dotenv from "dotenv";
import { MeiliSearch } from "meilisearch";
dotenv.config();
const siteUrl = process.env.PUBLIC_SITE_URL;
const searchUrl = process.env.PUBLIC_MEILISEARCH_URL || "http://localhost:7700";
const searchMasterKey =
process.env.PUBLIC_MEILISEARCH_MASTER_KEY || "MasterKey";
const client = new MeiliSearch({ host: searchUrl, apiKey: searchMasterKey });
// create index `articles`
client.createIndex("articles", { primaryKey: "slug" });
const allBlogData = [];
async function processFile(filePath) {
const htmlString = await fs.readFile(filePath, "utf-8");
// Parse the HTML
const dom = new JSDOM(htmlString);
const doc = dom.window.document;
// Find the required elements and get their content
const linkHref = doc
.querySelector('link[rel="canonical"]')
.getAttribute("href");
const imgSrc = doc.querySelector("img.blog-image")?.src;
const blogTitle = doc.querySelector("h1.blog-title")?.textContent;
const blogSubtitle = doc.querySelector("h2.blog-subtitle")?.textContent;
// Check if the element exists before calling replace()
let blogContent;
const blogContentElement = doc.querySelector("div.blog-content");
if (blogContentElement) {
blogContent = blogContentElement.textContent.replace(/[\n\t]/g, "").trim();
} else {
blogContent = ""; // or any other default value you want
}
// Get the last segment of the href
let lastSegment = linkHref.split("/").filter(Boolean).pop();
// Create an object to store the content
const blogData = {
slug: lastSegment,
url: linkHref,
image: siteUrl + imgSrc,
title: blogTitle,
subtitle: blogSubtitle,
content: blogContent, // Use cleaned version here
};
// Add the blog data to the array
allBlogData.push(blogData);
}
async function processDirectory(directoryPath) {
const entries = await fs.readdir(directoryPath, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(directoryPath, entry.name);
// If the entry is a directory and its name is not purely numeric, process it
if (
entry.isDirectory() &&
!/^[0-9]+$/.test(entry.name) &&
entry.name !== "tag"
) {
await processDirectory(entryPath);
}
// If the entry is a file and its extension is .html, process it
else if (
entry.isFile() &&
path.extname(entryPath) === ".html" &&
entryPath !== "dist/blog/index.html"
) {
await processFile(entryPath);
}
}
}
processDirectory("dist/blog")
.then(async () => {
// try to upload data into Meilisearch index
await client.index("articles").addDocuments(allBlogData);
console.log("Uploaded all data into the search index");
})
.catch((err) => console.error("Failed to process files:", err));
import { MeiliSearch } from "meilisearch";
const searchUrl =
import.meta.env.PUBLIC_MEILISEARCH_URL || "http://localhost:7700";
const searchMasterKey =
import.meta.env.PUBLIC_MEILISEARCH_MASTER_KEY || "MasterKey";
const client = new MeiliSearch({ host: searchUrl, apiKey: searchMasterKey });
// search the index using the input value
const search = await client.index("articles").search(e.target.value, {
attributesToHighlight: ["title", "content"],
highlightPreTag: "<mark>",
highlightPostTag: "</mark>",
attributesToCrop: ['content'],
cropLength: 30,
attributesToRetrieve: ['_formatted', 'url', 'image']
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment