mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	backlinks improvements, #2349
This commit is contained in:
		
							parent
							
								
									bbceb6251a
								
							
						
					
					
						commit
						630d9f2e45
					
				| @ -2,7 +2,7 @@ image: | ||||
|   file: .gitpod.dockerfile | ||||
| 
 | ||||
| tasks: | ||||
|     - before: nvm install 16.13.0 && nvm use 16.13.0 | ||||
|     - before: nvm install 16.13.1 && nvm use 16.13.1 | ||||
|       init: npm install | ||||
|       command: npm run start-server | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| FROM node:16.13.0-alpine | ||||
| FROM node:16.13.1-alpine | ||||
| 
 | ||||
| # Create app directory | ||||
| WORKDIR /usr/src/app | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| PKG_DIR=dist/trilium-linux-x64-server | ||||
| NODE_VERSION=16.13.0 | ||||
| NODE_VERSION=16.13.1 | ||||
| 
 | ||||
| if [ "$1" != "DONTCOPY" ] | ||||
| then | ||||
|  | ||||
| @ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| n exec 16.13.0 npm run webpack | ||||
| n exec 16.13.1 npm run webpack | ||||
| 
 | ||||
| DIR=$1 | ||||
| 
 | ||||
| @ -27,7 +27,7 @@ cp -r electron.js $DIR/ | ||||
| cp webpack-* $DIR/ | ||||
| 
 | ||||
| # run in subshell (so we return to original dir) | ||||
| (cd $DIR && n exec 16.13.0 npm install --only=prod) | ||||
| (cd $DIR && n exec 16.13.1 npm install --only=prod) | ||||
| 
 | ||||
| # cleanup of useless files in dependencies | ||||
| rm -r $DIR/node_modules/image-q/demo | ||||
|  | ||||
| @ -23,6 +23,7 @@ const TPL = ` | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|             z-index: 10; | ||||
|         } | ||||
|          | ||||
|         .backlinks-count { | ||||
| @ -56,6 +57,15 @@ const TPL = ` | ||||
|             opacity: 80%; | ||||
|             font-size: 90%; | ||||
|         } | ||||
|          | ||||
|         .backlink-excerpt .backlink-link { /* the actual backlink */ | ||||
|             font-weight: bold; | ||||
|             background-color: yellow; | ||||
|         } | ||||
|          | ||||
|         /* relation map has already buttons in that position */ | ||||
|         .type-relation-map .backlinks-ticker { top: 50px; } | ||||
|         .type-relation-map .backlinks-items { top: 100px; } | ||||
|     </style> | ||||
|      | ||||
|     <div class="backlinks-ticker"> | ||||
| @ -136,8 +146,12 @@ export default class BacklinksWidget extends NoteContextAwareWidget { | ||||
|                 showTooltip: false | ||||
|             })); | ||||
| 
 | ||||
|             this.$items.append("<br/>"); | ||||
|             this.$items.append(...backlink.excerpts); | ||||
|             if (backlink.relationName) { | ||||
|                 this.$items.append($("<p>").text("relation: " + backlink.relationName)); | ||||
|             } | ||||
|             else { | ||||
|                 this.$items.append(...backlink.excerpts); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -182,6 +182,97 @@ function removeImages(document) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const EXCERPT_CHAR_LIMIT = 200; | ||||
| 
 | ||||
| function findExcerpts(sourceNote, referencedNoteId) { | ||||
|     const html = sourceNote.getContent(); | ||||
|     const document = new JSDOM(html).window.document; | ||||
| 
 | ||||
|     const excerpts = []; | ||||
| 
 | ||||
|     removeImages(document); | ||||
| 
 | ||||
|     for (const linkEl of document.querySelectorAll("a")) { | ||||
|         const href = linkEl.getAttribute("href"); | ||||
| 
 | ||||
|         if (!href || !href.endsWith(referencedNoteId)) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         linkEl.classList.add("backlink-link"); | ||||
| 
 | ||||
|         let centerEl = linkEl; | ||||
| 
 | ||||
|         while (centerEl.tagName !== 'BODY' && centerEl.parentElement.textContent.length <= EXCERPT_CHAR_LIMIT) { | ||||
|             centerEl = centerEl.parentElement; | ||||
|         } | ||||
| 
 | ||||
|         const excerptEls = [centerEl]; | ||||
|         let excerptLength = centerEl.textContent.length; | ||||
|         let left = centerEl; | ||||
|         let right = centerEl; | ||||
| 
 | ||||
|         while (excerptLength < EXCERPT_CHAR_LIMIT) { | ||||
|             let added = false; | ||||
| 
 | ||||
|             const prev = left.previousElementSibling; | ||||
| 
 | ||||
|             if (prev) { | ||||
|                 const prevText = prev.textContent; | ||||
| 
 | ||||
|                 if (prevText.length + excerptLength > EXCERPT_CHAR_LIMIT) { | ||||
|                     const prefix = prevText.substr(prevText.length - (EXCERPT_CHAR_LIMIT - excerptLength)); | ||||
| 
 | ||||
|                     const textNode = document.createTextNode("…" + prefix); | ||||
|                     excerptEls.unshift(textNode); | ||||
| 
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 left = prev; | ||||
|                 excerptEls.unshift(left); | ||||
|                 excerptLength += prevText.length; | ||||
|                 added = true; | ||||
|             } | ||||
| 
 | ||||
|             const next = right.nextElementSibling; | ||||
| 
 | ||||
|             if (next) { | ||||
|                 const nextText = next.textContent; | ||||
| 
 | ||||
|                 if (nextText.length + excerptLength > EXCERPT_CHAR_LIMIT) { | ||||
|                     const suffix = nextText.substr(nextText.length - (EXCERPT_CHAR_LIMIT - excerptLength)); | ||||
| 
 | ||||
|                     const textNode = document.createTextNode(suffix + "…"); | ||||
|                     excerptEls.push(textNode); | ||||
| 
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 right = next; | ||||
|                 excerptEls.push(right); | ||||
|                 excerptLength += nextText.length; | ||||
|                 added = true; | ||||
|             } | ||||
| 
 | ||||
|             if (!added) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const excerptWrapper = document.createElement('div'); | ||||
|         excerptWrapper.classList.add("ck-content"); | ||||
|         excerptWrapper.classList.add("backlink-excerpt"); | ||||
| 
 | ||||
|         for (const childEl of excerptEls) { | ||||
|             excerptWrapper.appendChild(childEl); | ||||
|         } | ||||
| 
 | ||||
|         excerpts.push(excerptWrapper.outerHTML); | ||||
|     } | ||||
|     return excerpts; | ||||
| } | ||||
| 
 | ||||
| function getBacklinks(req) { | ||||
|     const {noteId} = req.params; | ||||
|     const note = becca.getNote(noteId); | ||||
| @ -192,105 +283,22 @@ function getBacklinks(req) { | ||||
| 
 | ||||
|     let backlinks = note.getTargetRelations(); | ||||
| 
 | ||||
|     if (backlinks.length > 50) { | ||||
|         backlinks = backlinks.slice(0, 50); | ||||
|     } | ||||
|     let backlinksWithExcerptCount = 0; | ||||
| 
 | ||||
|     return backlinks.map(backlink => { | ||||
|         const sourceNote = backlink.note; | ||||
| 
 | ||||
|         const html = sourceNote.getContent(); | ||||
|         const dom = new JSDOM(html); | ||||
| 
 | ||||
|         const excerpts = []; | ||||
| 
 | ||||
|         const document = dom.window.document; | ||||
| 
 | ||||
|         removeImages(document); | ||||
| 
 | ||||
|         for (const linkEl of document.querySelectorAll("a")) { | ||||
|             const href = linkEl.getAttribute("href"); | ||||
| 
 | ||||
|             if (!href || !href.includes(noteId)) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             linkEl.style.fontWeight = "bold"; | ||||
|             linkEl.style.backgroundColor = "yellow"; | ||||
| 
 | ||||
|             const LIMIT = 200; | ||||
|             let centerEl = linkEl; | ||||
| 
 | ||||
|             while (centerEl.tagName !== 'BODY' && centerEl.parentElement.textContent.length < LIMIT) { | ||||
|                 centerEl = centerEl.parentElement; | ||||
|             } | ||||
| 
 | ||||
|             const sub = [centerEl]; | ||||
|             let counter = centerEl.textContent.length; | ||||
|             let left = centerEl; | ||||
|             let right = centerEl; | ||||
| 
 | ||||
|             while (true) { | ||||
|                 let added = false; | ||||
| 
 | ||||
|                 const prev = left.previousElementSibling; | ||||
| 
 | ||||
|                 if (prev) { | ||||
|                     const prevText = prev.textContent; | ||||
| 
 | ||||
|                     if (prevText.length + counter > LIMIT) { | ||||
|                         const prefix = prevText.substr(prevText.length - (LIMIT - counter)); | ||||
| 
 | ||||
|                         const textNode = document.createTextNode("…" + prefix); | ||||
|                         sub.unshift(textNode); | ||||
| 
 | ||||
|                         break; | ||||
|                     } | ||||
| 
 | ||||
|                     left = prev; | ||||
|                     sub.unshift(left); | ||||
|                     counter += prevText.length; | ||||
|                     added = true; | ||||
|                 } | ||||
| 
 | ||||
|                 const next = right.nextElementSibling; | ||||
| 
 | ||||
|                 if (next) { | ||||
|                     const nextText = next.textContent; | ||||
| 
 | ||||
|                     if (nextText.length + counter > LIMIT) { | ||||
|                         const suffix = nextText.substr(nextText.length - (LIMIT - counter)); | ||||
| 
 | ||||
|                         const textNode = document.createTextNode(suffix + "…"); | ||||
|                         sub.push(textNode); | ||||
| 
 | ||||
|                         break; | ||||
|                     } | ||||
| 
 | ||||
|                     right = next; | ||||
|                     sub.push(right); | ||||
|                     counter += nextText.length; | ||||
|                     added = true; | ||||
|                 } | ||||
| 
 | ||||
|                 if (!added) { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             const div = document.createElement('div'); | ||||
|             div.classList.add("ck-content"); | ||||
|             div.classList.add("backlink-excerpt"); | ||||
| 
 | ||||
|             for (const childEl of sub) { | ||||
|                 div.appendChild(childEl); | ||||
|             } | ||||
| 
 | ||||
|             const subHtml = div.outerHTML; | ||||
| 
 | ||||
|             excerpts.push(subHtml); | ||||
|         if (sourceNote.type !== 'text' || backlinksWithExcerptCount > 50) { | ||||
|             return { | ||||
|                 noteId: sourceNote.noteId, | ||||
|                 relationName: backlink.name | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         backlinksWithExcerptCount++; | ||||
| 
 | ||||
|         const excerpts = findExcerpts(sourceNote, noteId); | ||||
| 
 | ||||
|         return { | ||||
|             noteId: sourceNote.noteId, | ||||
|             excerpts | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam