1 // Taken from https://github.com/gbxyz/webidx/tree/main
2 // BSD 3-Clause License
3 // Copyright (c) 2024, Gavin Brown
4 // Full license: https://github.com/gbxyz/webidx/blob/a28a984d38fd546d1bec4d6a4a5a47ab86cb08f8/LICENSE
5 // Note: File has been modified since originally copied.
8 const webidx = window.webidx;
10 webidx.search = async function (params) {
15 webidx.sql = await window.initSqlJs({locateFile: file => `/libs/${file}`});
18 if (webidx.hasOwnProperty('db')) {
19 return webidx.query(params.query);
20 } else if (webidx.loadingPromise) {
21 await webidx.loadingPromise;
22 await new Promise((res, rej) => setTimeout(res, 10));
23 return webidx.query(params.query);
25 webidx.loadingPromise = webidx.loadDB(params);
27 webidx.loadingPromise.then(() => {
28 webidx.loadingPromise = null;
31 return webidx.loadingPromise
35 webidx.loadDB = function (params) {
36 return new Promise((res, rej) => {
37 var xhr = new XMLHttpRequest();
39 xhr.open('GET', params.dbfile);
40 xhr.timeout = params.timeout ?? 5000;
41 xhr.responseType = 'arraybuffer';
43 xhr.ontimeout = function() {
44 rej('Unable to load index, please refresh the page.');
47 xhr.onload = function() {
48 webidx.initializeDB(this.response);
49 const results = webidx.query(params.query);
57 webidx.initializeDB = function (arrayBuffer) {
58 webidx.db = new webidx.sql.Database(new Uint8Array(arrayBuffer));
63 webidx.wordQuery = webidx.db.prepare("SELECT `id` FROM `words` WHERE (`word`=:word)");
64 webidx.idxQuery = webidx.db.prepare("SELECT `page_id` FROM `index` WHERE (`word`=:word)");
65 webidx.pageQuery = webidx.db.prepare("SELECT `url`,`title` FROM `pages` WHERE (`id`=:id)");
68 webidx.getWordID = function (word) {
69 webidx.wordQuery.bind([word]);
70 webidx.wordQuery.step();
71 var word_id = webidx.wordQuery.get().shift();
73 webidx.wordQuery.reset();
78 webidx.getPagesHavingWord = function (word_id) {
81 webidx.idxQuery.bind([word_id]);
83 while (webidx.idxQuery.step()) {
84 pages.push(webidx.idxQuery.get().shift());
87 webidx.idxQuery.reset();
92 webidx.getPage = function (page_id) {
93 webidx.pageQuery.bind([page_id]);
95 webidx.pageQuery.step();
97 var page = webidx.pageQuery.getAsObject();
99 webidx.pageQuery.reset();
104 webidx.query = function (query) {
106 // split the search term into words
108 var words = query.toLowerCase().split(" ");
111 // this array maps page ID to rank
116 // iterate over each word
118 while (words.length > 0) {
119 var word = words.shift();
122 if (0 == word.indexOf("-")) {
124 word = word.substring(1);
127 var word_id = webidx.getWordID(word);
130 // if the word isn't present, ignore it
133 var pages = webidx.getPagesHavingWord(word_id);
135 pages.forEach(function (page_id) {
137 if (pageRank[page_id]) {
138 pageRank[page_id] -= 65535;
141 pageRank[page_id] = -65535;
146 if (pageRank[page_id]) {
150 pageRank[page_id] = 1;
159 // transform the results into a format that can be sorted
161 var sortedPages = [];
163 pageRank.forEach(function (rank, page_id) {
165 sortedPages.push({rank: rank, page_id: page_id});
170 // sort the results in descending rank order
172 sortedPages.sort(function(a, b) {
173 return b.rank - a.rank;
177 // this will be populated with the actual pages
182 // get page data for each result
184 sortedPages.forEach(function(result) {
185 pages.push(webidx.getPage(result.page_id));
191 webidx.regExpQuote = function (str) {
192 return str.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');