mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
feat(search): use dexie.js instead of localStorage (#2464)
This commit is contained in:
parent
7cbd5322d0
commit
42f25482fa
6
package-lock.json
generated
6
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dexie": "^4.0.8",
|
||||
"medium-zoom": "^1.1.0",
|
||||
"opencollective-postinstall": "^2.0.2",
|
||||
"prismjs": "^1.29.0",
|
||||
@ -5929,6 +5930,11 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dexie": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.8.tgz",
|
||||
"integrity": "sha512-1G6cJevS17KMDK847V3OHvK2zei899GwpDiqfEXHP1ASvme6eWJmAp9AU4s1son2TeGkWmC0g3y8ezOBPnalgQ=="
|
||||
},
|
||||
"node_modules/diff-sequences": {
|
||||
"version": "29.6.3",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
"*.js": "eslint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"dexie": "^4.0.8",
|
||||
"medium-zoom": "^1.1.0",
|
||||
"opencollective-postinstall": "^2.0.2",
|
||||
"prismjs": "^1.29.0",
|
||||
|
||||
@ -2,8 +2,33 @@ import {
|
||||
getAndRemoveConfig,
|
||||
getAndRemoveDocsifyIgnoreConfig,
|
||||
} from '../../core/render/utils.js';
|
||||
import Dexie from 'dexie';
|
||||
|
||||
let INDEXS = {};
|
||||
let INDEXES = {};
|
||||
|
||||
const db = new Dexie('docsify');
|
||||
db.version(1).stores({
|
||||
search: 'slug, title, body, path, indexKey',
|
||||
expires: 'key, value',
|
||||
});
|
||||
|
||||
async function saveData(maxAge, expireKey) {
|
||||
INDEXES = Object.values(INDEXES).flatMap(innerData =>
|
||||
Object.values(innerData),
|
||||
);
|
||||
await db.search.bulkPut(INDEXES);
|
||||
await db.expires.put({ key: expireKey, value: Date.now() + maxAge });
|
||||
}
|
||||
|
||||
async function getData(key, isExpireKey = false) {
|
||||
if (isExpireKey) {
|
||||
const item = await db.expires.get(key);
|
||||
return item ? item.value : 0;
|
||||
}
|
||||
|
||||
const item = await db.search.where({ indexKey: key }).toArray();
|
||||
return item ? item : null;
|
||||
}
|
||||
|
||||
const LOCAL_STORAGE = {
|
||||
EXPIRE_KEY: 'docsify.search.expires',
|
||||
@ -73,12 +98,7 @@ function getListData(token) {
|
||||
return token.text;
|
||||
}
|
||||
|
||||
function saveData(maxAge, expireKey, indexKey) {
|
||||
localStorage.setItem(expireKey, Date.now() + maxAge);
|
||||
localStorage.setItem(indexKey, JSON.stringify(INDEXS));
|
||||
}
|
||||
|
||||
export function genIndex(path, content = '', router, depth) {
|
||||
export function genIndex(path, content = '', router, depth, indexKey) {
|
||||
const tokens = window.marked.lexer(content);
|
||||
const slugify = window.Docsify.slugify;
|
||||
const index = {};
|
||||
@ -101,7 +121,13 @@ export function genIndex(path, content = '', router, depth) {
|
||||
title = getAndRemoveDocsifyIgnoreConfig(str).content;
|
||||
}
|
||||
|
||||
index[slug] = { slug, title: title, body: '' };
|
||||
index[slug] = {
|
||||
slug,
|
||||
title: title,
|
||||
body: '',
|
||||
path: path,
|
||||
indexKey: indexKey,
|
||||
};
|
||||
} else {
|
||||
if (tokenIndex === 0) {
|
||||
slug = router.toURL(path);
|
||||
@ -109,6 +135,8 @@ export function genIndex(path, content = '', router, depth) {
|
||||
slug,
|
||||
title: path !== '/' ? path.slice(1) : 'Home Page',
|
||||
body: token.text || '',
|
||||
path: path,
|
||||
indexKey: indexKey,
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,6 +157,9 @@ export function genIndex(path, content = '', router, depth) {
|
||||
|
||||
index[slug].body = token.text || '';
|
||||
}
|
||||
|
||||
index[slug].path = path;
|
||||
index[slug].indexKey = indexKey;
|
||||
}
|
||||
});
|
||||
slugify.clear();
|
||||
@ -148,13 +179,6 @@ export function ignoreDiacriticalMarks(keyword) {
|
||||
*/
|
||||
export function search(query) {
|
||||
const matchingResults = [];
|
||||
let data = [];
|
||||
Object.keys(INDEXS).forEach(key => {
|
||||
data = [
|
||||
...data,
|
||||
...Object.keys(INDEXS[key]).map(page => INDEXS[key][page]),
|
||||
];
|
||||
});
|
||||
|
||||
query = query.trim();
|
||||
let keywords = query.split(/[\s\-,\\/]+/);
|
||||
@ -162,7 +186,7 @@ export function search(query) {
|
||||
keywords = [query, ...keywords];
|
||||
}
|
||||
|
||||
for (const post of data) {
|
||||
for (const post of INDEXES) {
|
||||
let matchesScore = 0;
|
||||
let resultStr = '';
|
||||
let handlePostTitle = '';
|
||||
@ -235,7 +259,7 @@ export function search(query) {
|
||||
return matchingResults.sort((r1, r2) => r2.score - r1.score);
|
||||
}
|
||||
|
||||
export function init(config, vm) {
|
||||
export async function init(config, vm) {
|
||||
const isAuto = config.paths === 'auto';
|
||||
const paths = isAuto ? getAllPaths(vm.router) : config.paths;
|
||||
|
||||
@ -269,12 +293,12 @@ export function init(config, vm) {
|
||||
const expireKey = resolveExpireKey(config.namespace) + namespaceSuffix;
|
||||
const indexKey = resolveIndexKey(config.namespace) + namespaceSuffix;
|
||||
|
||||
const isExpired = localStorage.getItem(expireKey) < Date.now();
|
||||
const isExpired = (await getData(expireKey, true)) < Date.now();
|
||||
|
||||
INDEXS = JSON.parse(localStorage.getItem(indexKey));
|
||||
INDEXES = await getData(indexKey);
|
||||
|
||||
if (isExpired) {
|
||||
INDEXS = {};
|
||||
INDEXES = {};
|
||||
} else if (!isAuto) {
|
||||
return;
|
||||
}
|
||||
@ -283,14 +307,25 @@ export function init(config, vm) {
|
||||
let count = 0;
|
||||
|
||||
paths.forEach(path => {
|
||||
if (INDEXS[path]) {
|
||||
const pathExists = Array.isArray(INDEXES)
|
||||
? INDEXES.some(obj => obj.path === path)
|
||||
: false;
|
||||
if (pathExists) {
|
||||
return count++;
|
||||
}
|
||||
|
||||
Docsify.get(vm.router.getFile(path), false, vm.config.requestHeaders).then(
|
||||
result => {
|
||||
INDEXS[path] = genIndex(path, result, vm.router, config.depth);
|
||||
len === ++count && saveData(config.maxAge, expireKey, indexKey);
|
||||
async result => {
|
||||
INDEXES[path] = genIndex(
|
||||
path,
|
||||
result,
|
||||
vm.router,
|
||||
config.depth,
|
||||
indexKey,
|
||||
);
|
||||
if (len === ++count) {
|
||||
await saveData(config.maxAge, expireKey);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -20,7 +20,6 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
const docsifyInitConfig = {
|
||||
config: {
|
||||
name: 'Docsify Name',
|
||||
themeColor: 'red',
|
||||
},
|
||||
markdown: {
|
||||
coverpage: `
|
||||
@ -58,8 +57,6 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
scriptURLs: [
|
||||
// docsifyInit() route
|
||||
'data-test-scripturls.js',
|
||||
// Server route
|
||||
'/dist/plugins/search.js',
|
||||
],
|
||||
style: `
|
||||
body {
|
||||
@ -76,7 +73,6 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
|
||||
// Verify config options
|
||||
expect(typeof window.$docsify).toBe('object');
|
||||
expect(window.$docsify).toHaveProperty('themeColor', 'red');
|
||||
expect(document.querySelector('.app-name').textContent).toContain(
|
||||
'Docsify Name',
|
||||
);
|
||||
@ -101,7 +97,6 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
|
||||
// Verify docsifyInitConfig.scriptURLs were executed
|
||||
expect(document.body.hasAttribute('data-test-scripturls')).toBe(true);
|
||||
expect(document.querySelector('.search input[type="search"]')).toBeTruthy();
|
||||
|
||||
// Verify docsifyInitConfig.script was added to the DOM
|
||||
expect(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user