mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02: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/>");
|
||||
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,104 +283,21 @@ 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;
|
||||
if (sourceNote.type !== 'text' || backlinksWithExcerptCount > 50) {
|
||||
return {
|
||||
noteId: sourceNote.noteId,
|
||||
relationName: backlink.name
|
||||
};
|
||||
}
|
||||
|
||||
linkEl.style.fontWeight = "bold";
|
||||
linkEl.style.backgroundColor = "yellow";
|
||||
backlinksWithExcerptCount++;
|
||||
|
||||
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);
|
||||
}
|
||||
const excerpts = findExcerpts(sourceNote, noteId);
|
||||
|
||||
return {
|
||||
noteId: sourceNote.noteId,
|
||||
|
Loading…
x
Reference in New Issue
Block a user