mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 19:49:01 +01:00 
			
		
		
		
	feat(export/share): functional full-text search
This commit is contained in:
		
							parent
							
								
									f8c61ecde9
								
							
						
					
					
						commit
						cf8089b07f
					
				| @ -9,12 +9,15 @@ import type BNote from "../../../becca/entities/bnote.js"; | ||||
| import type BBranch from "../../../becca/entities/bbranch.js"; | ||||
| import { getShareThemeAssetDir } from "../../../routes/assets"; | ||||
| import { convert as convertToText } from "html-to-text"; | ||||
| import becca from "../../../becca/becca"; | ||||
| 
 | ||||
| const shareThemeAssetDir = getShareThemeAssetDir(); | ||||
| 
 | ||||
| interface SearchIndexEntry { | ||||
|     id: string; | ||||
|     title: string; | ||||
|     content: string; | ||||
|     path: string; | ||||
| } | ||||
| 
 | ||||
| export default class ShareThemeExportProvider extends ZipExportProvider { | ||||
| @ -72,9 +75,14 @@ export default class ShareThemeExportProvider extends ZipExportProvider { | ||||
|             } | ||||
| 
 | ||||
|             // Prepare search index.
 | ||||
|             this.searchIndex.set(note?.noteId, { | ||||
|                 title: title, | ||||
|                 content: searchContent | ||||
|             this.searchIndex.set(note.noteId, { | ||||
|                 id: note.noteId, | ||||
|                 title, | ||||
|                 content: searchContent, | ||||
|                 path: note.getBestNotePath() | ||||
|                     .map(noteId => noteId !== "root" && becca.getNote(noteId)?.title) | ||||
|                     .filter(noteId => noteId) | ||||
|                     .join(" / ") | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -22,12 +22,14 @@ | ||||
|   ], | ||||
|   "license": "Apache-2.0", | ||||
|   "dependencies": { | ||||
|     "boxicons": "2.1.4", | ||||
|     "fuse.js": "7.1.0", | ||||
|     "katex": "0.16.25", | ||||
|     "mermaid": "11.12.0", | ||||
|     "boxicons": "2.1.4" | ||||
|     "mermaid": "11.12.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@digitak/esrun": "3.2.26", | ||||
|     "@triliumnext/ckeditor5": "workspace:*", | ||||
|     "@types/swagger-ui": "5.21.1", | ||||
|     "@typescript-eslint/eslint-plugin": "8.46.2", | ||||
|     "@typescript-eslint/parser": "8.46.2", | ||||
| @ -35,7 +37,6 @@ | ||||
|     "esbuild": "0.25.11", | ||||
|     "eslint": "9.38.0", | ||||
|     "highlight.js": "11.11.1", | ||||
|     "typescript": "5.9.3", | ||||
|     "@triliumnext/ckeditor5": "workspace:*" | ||||
|     "typescript": "5.9.3" | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,6 @@ import debounce from "../common/debounce"; | ||||
| import parents from "../common/parents"; | ||||
| import parseHTML from "../common/parsehtml"; | ||||
| 
 | ||||
| 
 | ||||
| interface SearchResults { | ||||
|     results: SearchResult[]; | ||||
| } | ||||
| @ -10,7 +9,7 @@ interface SearchResults { | ||||
| interface SearchResult { | ||||
|     id: string; | ||||
|     title: string; | ||||
|     score: number; | ||||
|     score?: number; | ||||
|     path: string; | ||||
| } | ||||
| 
 | ||||
| @ -30,12 +29,10 @@ export default function setupSearch() { | ||||
| 
 | ||||
|     searchInput.addEventListener("keyup", debounce(async () => { | ||||
|         // console.log("CHANGE EVENT");
 | ||||
|         const ancestor = document.body.dataset.ancestorNoteId; | ||||
|         const query = searchInput.value; | ||||
|         if (query.length < 3) return; | ||||
|         const resp = await fetch(`api/notes?search=${query}&ancestorNoteId=${ancestor}`); | ||||
|         const json = await resp.json() as SearchResults; | ||||
|         const results = json.results.slice(0, 5); | ||||
|         const resp = await fetchResults(query); | ||||
|         const results = resp.results.slice(0, 5); | ||||
|         const lines = [`<div class="search-results">`]; | ||||
|         for (const result of results) { | ||||
|             lines.push(buildResultItem(result)); | ||||
| @ -62,3 +59,29 @@ export default function setupSearch() { | ||||
|         if (existing) existing.remove(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| async function fetchResults(query: string): Promise<SearchResults> { | ||||
|     if ((window as any).glob.isStatic) { | ||||
|         const linkHref = document.head.querySelector("link[rel=stylesheet]")?.getAttribute("href"); | ||||
|         const rootUrl = linkHref?.split("/").slice(0, -2).join("/"); | ||||
|         const searchIndex = await (await fetch(`${rootUrl}/search-index.json`)).json(); | ||||
|         const Fuse = (await import("fuse.js")).default; | ||||
|         const fuse = new Fuse(searchIndex, { | ||||
|             keys: [ | ||||
|                 "title", | ||||
|                 "content" | ||||
|             ] | ||||
|         }); | ||||
| 
 | ||||
|         const results = fuse.search<SearchResult>(query); | ||||
|         const processedResults = results.map(({ item, score }) => ({ | ||||
|             ...item, | ||||
|             score | ||||
|         })); | ||||
|         return { results: processedResults }; | ||||
|     } else { | ||||
|         const ancestor = document.body.dataset.ancestorNoteId; | ||||
|         const resp = await fetch(`api/notes?search=${query}&ancestorNoteId=${ancestor}`); | ||||
|         return await resp.json() as SearchResults; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -54,6 +54,11 @@ | ||||
|         } | ||||
|     %> | ||||
|     <title><%= pageTitle %></title> | ||||
|     <script> | ||||
|         window.glob = { | ||||
|             isStatic: <%= !!isStatic %> | ||||
|         }; | ||||
|     </script> | ||||
|     <!-- HTML Meta Tags --> | ||||
|     <meta name="description" content="<%= note.getLabelValue("shareDescription") %>"> | ||||
|     <!-- Facebook Meta Tags --> | ||||
| @ -114,7 +119,7 @@ content = content.replaceAll(headingRe, (...match) => { | ||||
|                       <svg class="light-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M6.993 12c0 2.761 2.246 5.007 5.007 5.007s5.007-2.246 5.007-5.007S14.761 6.993 12 6.993 6.993 9.239 6.993 12zM12 8.993c1.658 0 3.007 1.349 3.007 3.007S13.658 15.007 12 15.007 8.993 13.658 8.993 12 10.342 8.993 12 8.993zM10.998 19h2v3h-2zm0-17h2v3h-2zm-9 9h3v2h-3zm17 0h3v2h-3zM4.219 18.363l2.12-2.122 1.415 1.414-2.12 2.122zM16.24 6.344l2.122-2.122 1.414 1.414-2.122 2.122zM6.342 7.759 4.22 5.637l1.415-1.414 2.12 2.122zm13.434 10.605-1.414 1.414-2.122-2.122 1.414-1.414z"></path></svg> | ||||
|                     </label> | ||||
|                 </div> | ||||
|                 <% if (hasTree && !isStatic) { %> | ||||
|                 <% if (hasTree) { %> | ||||
|                     <div class="search-item"> | ||||
|                         <svg class="search-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M10 18a7.952 7.952 0 0 0 4.897-1.688l4.396 4.396 1.414-1.414-4.396-4.396A7.952 7.952 0 0 0 18 10c0-4.411-3.589-8-8-8s-8 3.589-8 8 3.589 8 8 8zm0-14c3.309 0 6 2.691 6 6s-2.691 6-6 6-6-2.691-6-6 2.691-6 6-6z"></path></svg> | ||||
|                         <input type="text" class="search-input" placeholder="<%= t("share_theme.search_placeholder") %>"> | ||||
|  | ||||
							
								
								
									
										25
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @ -1335,6 +1335,9 @@ importers: | ||||
|       boxicons: | ||||
|         specifier: 2.1.4 | ||||
|         version: 2.1.4 | ||||
|       fuse.js: | ||||
|         specifier: 7.1.0 | ||||
|         version: 7.1.0 | ||||
|       katex: | ||||
|         specifier: 0.16.25 | ||||
|         version: 0.16.25 | ||||
| @ -8097,6 +8100,10 @@ packages: | ||||
|   functions-have-names@1.2.3: | ||||
|     resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} | ||||
| 
 | ||||
|   fuse.js@7.1.0: | ||||
|     resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} | ||||
|     engines: {node: '>=10'} | ||||
| 
 | ||||
|   futoin-hkdf@1.5.3: | ||||
|     resolution: {integrity: sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==} | ||||
|     engines: {node: '>=8'} | ||||
| @ -15040,8 +15047,6 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-core': 47.1.0 | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-code-block@47.1.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)': | ||||
|     dependencies: | ||||
| @ -15103,8 +15108,6 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       '@ckeditor/ckeditor5-watchdog': 47.1.0 | ||||
|       es-toolkit: 1.39.5 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-dev-build-tools@43.1.0(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)': | ||||
|     dependencies: | ||||
| @ -15269,8 +15272,6 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|       es-toolkit: 1.39.5 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-editor-classic@47.1.0': | ||||
|     dependencies: | ||||
| @ -15298,8 +15299,6 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|       es-toolkit: 1.39.5 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-editor-multi-root@47.1.0': | ||||
|     dependencies: | ||||
| @ -15552,6 +15551,8 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-ui': 47.1.0 | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-line-height@47.1.0': | ||||
|     dependencies: | ||||
| @ -15794,6 +15795,8 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-ui': 47.1.0 | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-restricted-editing@47.1.0': | ||||
|     dependencies: | ||||
| @ -15838,6 +15841,8 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-ui': 47.1.0 | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@ckeditor/ckeditor5-slash-command@47.1.0': | ||||
|     dependencies: | ||||
| @ -16046,6 +16051,8 @@ snapshots: | ||||
|       '@ckeditor/ckeditor5-utils': 47.1.0 | ||||
|       ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) | ||||
|       es-toolkit: 1.39.5 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
| 
 | ||||
|   '@codemirror/autocomplete@6.18.6': | ||||
|     dependencies: | ||||
| @ -23661,6 +23668,8 @@ snapshots: | ||||
| 
 | ||||
|   functions-have-names@1.2.3: {} | ||||
| 
 | ||||
|   fuse.js@7.1.0: {} | ||||
| 
 | ||||
|   futoin-hkdf@1.5.3: {} | ||||
| 
 | ||||
|   fuzzy@0.1.3: {} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran