public/worker/db.js (219 lines of code) (raw):

importScripts("/dexie.js"); const db = new Dexie(this.name + "_db"); db.version(1).stores({ blog: "++id, content, time", event: "++id, title, desc, time", faq: "++id, q, a, time", doc: "++id, content, version, time", }); const getBlogData = async () => { try { const result = await fetch(`/data/blog/${this.name}.json`); const json = await result.json(); db.blog.clear(); db.blog.bulkAdd(json); } catch (e) {} }; const getEventsData = async () => { try { const result = await fetch(`/data/events/${this.name}.json`); const json = await result.json(); db.event.clear(); db.event.bulkAdd(json); } catch (e) {} }; const getFaqData = async () => { try { const result = await fetch(`/data/faq/${this.name}.json`); const json = await result.json(); db.faq.clear(); db.faq.bulkAdd(json); } catch (e) {} }; const getDocData = async () => { try { const result = await fetch(`/data/doc/${this.name}.json`); const json = await result.json(); db.doc.clear(); db.doc.bulkAdd(json); } catch (e) {} }; const getPreviousIndex = (str, index) => { let i = index; while (str[i] !== " ") { if (i === 0) break; i--; } return i; }; const replaceStr = (str, value, limit, index) => { const regex = new RegExp(`(${value})`, "g"); let slicedStr = ""; if (str.length < limit || limit === 0) { slicedStr = str; } else if (str.length - index < limit) { slicedStr = str.slice(getPreviousIndex(str, str.length - limit)); } else { slicedStr = str.slice(getPreviousIndex(str, index), index + limit); } return slicedStr.replace(regex, (a, b) => { return `<span class="matched-text">${a}</span>`; }); }; const initData = async () => { if (this.loaded) return; await Promise.all([ getDocData(), getFaqData(), getEventsData(), getBlogData(), ]); this.loaded = true; this.postMessage({ loaded: true }); }; const searchEvent = async (value) => { const array = await db.event.orderBy("time").toArray(); const result = []; for (let item of array) { const index = item.title.indexOf(value); if (index !== -1) { result.push({ i: index, title: replaceStr(item.title, value, 100, index), time: new Date(item.time).getTime(), post: item.post, video_url: item.video_url, more: item.more, }); } } return result; }; const searchFaq = async (value) => { const array = await db.faq.orderBy("time").toArray(); const result = []; for (let item of array) { const aI = item.a.indexOf(value); const qI = item.q.indexOf(value); if (aI !== -1 || qI !== -1) { const i = Math.min(aI, qI) !== -1 ? Math.min(aI, qI) : aI === -1 ? qI : aI; result.push({ i, a: replaceStr(item.a, value, 0, aI), q: replaceStr(item.q, value, 0, qI), time: new Date(item.time).getTime(), }); } } return result; }; const searchBlog = async (value) => { const array = await db.blog.orderBy("time").toArray(); const result = []; for (let item of array) { const titleI = item.content.indexOf(value); const contentI = item.content.indexOf(value); if (titleI !== -1 || contentI !== -1) { const i = Math.min(titleI, contentI) !== -1 ? Math.min(titleI, contentI) : titleI === -1 ? contentI : titleI; result.push({ i, title: replaceStr(item.title, value, 100, titleI), desc: replaceStr(item.content, value, 300, contentI), time: new Date(item.time).getTime(), name: item.name, }); } } return result; }; const searchDoc = async (value) => { const array = await db.doc.orderBy("time").toArray(); const result = []; for (let item of array) { const titleI = item.content.indexOf(value); const contentI = item.content.indexOf(value); if (titleI !== -1 || contentI !== -1) { const i = Math.min(titleI, contentI) !== -1 ? Math.min(titleI, contentI) : titleI === -1 ? contentI : titleI; result.push({ i, title: replaceStr(item.title, value, 100, titleI), desc: replaceStr(item.content, value, 300, contentI), time: new Date(item.time).getTime(), link: item.link, version: item.version, }); } } return result; }; const searchData = async (value) => { if (db.isOpen()) { await db.open(); } const [event = [], faq = [], blog = [], doc = []] = await Promise.all([ searchEvent(value), searchFaq(value), searchBlog(value), searchDoc(value), ]); this.postMessage({ type: "search", event, faq, blog, doc, }); }; const searchDocVersion = async (value, version) => { const array = await db.doc .filter((item) => item.version === version) .toArray(); const result = []; for (let item of array) { const titleI = item.content.indexOf(value); const contentI = item.content.indexOf(value); if (titleI !== -1 || contentI !== -1) { const i = Math.min(titleI, contentI) !== -1 ? Math.min(titleI, contentI) : titleI === -1 ? contentI : titleI; result.push({ i, title: replaceStr(item.title, value, 80, titleI), desc: replaceStr(item.content, value, 100, contentI), location: item.location, link: item.link, }); } } this.postMessage({ type: "search-doc", result, }); }; initData(); this.onmessage = ({ data }) => { if (data === "check") { this.postMessage({ loaded: !!this.loaded }); return; } if (data.type === "search" && data.value) { searchData(data.value); } if (data.type === "search-doc" && data.value && data.version) { searchDocVersion(data.value, data.version); } };