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
|
file: .gitpod.dockerfile
|
||||||
|
|
||||||
tasks:
|
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
|
init: npm install
|
||||||
command: npm run start-server
|
command: npm run start-server
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM node:16.13.0-alpine
|
FROM node:16.13.1-alpine
|
||||||
|
|
||||||
# Create app directory
|
# Create app directory
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
PKG_DIR=dist/trilium-linux-x64-server
|
PKG_DIR=dist/trilium-linux-x64-server
|
||||||
NODE_VERSION=16.13.0
|
NODE_VERSION=16.13.1
|
||||||
|
|
||||||
if [ "$1" != "DONTCOPY" ]
|
if [ "$1" != "DONTCOPY" ]
|
||||||
then
|
then
|
||||||
|
@ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
n exec 16.13.0 npm run webpack
|
n exec 16.13.1 npm run webpack
|
||||||
|
|
||||||
DIR=$1
|
DIR=$1
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ cp -r electron.js $DIR/
|
|||||||
cp webpack-* $DIR/
|
cp webpack-* $DIR/
|
||||||
|
|
||||||
# run in subshell (so we return to original 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
|
# cleanup of useless files in dependencies
|
||||||
rm -r $DIR/node_modules/image-q/demo
|
rm -r $DIR/node_modules/image-q/demo
|
||||||
|
@ -23,6 +23,7 @@ const TPL = `
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.backlinks-count {
|
.backlinks-count {
|
||||||
@ -56,6 +57,15 @@ const TPL = `
|
|||||||
opacity: 80%;
|
opacity: 80%;
|
||||||
font-size: 90%;
|
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>
|
</style>
|
||||||
|
|
||||||
<div class="backlinks-ticker">
|
<div class="backlinks-ticker">
|
||||||
@ -136,8 +146,12 @@ export default class BacklinksWidget extends NoteContextAwareWidget {
|
|||||||
showTooltip: false
|
showTooltip: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.$items.append("<br/>");
|
if (backlink.relationName) {
|
||||||
|
this.$items.append($("<p>").text("relation: " + backlink.relationName));
|
||||||
|
}
|
||||||
|
else {
|
||||||
this.$items.append(...backlink.excerpts);
|
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) {
|
function getBacklinks(req) {
|
||||||
const {noteId} = req.params;
|
const {noteId} = req.params;
|
||||||
const note = becca.getNote(noteId);
|
const note = becca.getNote(noteId);
|
||||||
@ -192,104 +283,21 @@ function getBacklinks(req) {
|
|||||||
|
|
||||||
let backlinks = note.getTargetRelations();
|
let backlinks = note.getTargetRelations();
|
||||||
|
|
||||||
if (backlinks.length > 50) {
|
let backlinksWithExcerptCount = 0;
|
||||||
backlinks = backlinks.slice(0, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
return backlinks.map(backlink => {
|
return backlinks.map(backlink => {
|
||||||
const sourceNote = backlink.note;
|
const sourceNote = backlink.note;
|
||||||
|
|
||||||
const html = sourceNote.getContent();
|
if (sourceNote.type !== 'text' || backlinksWithExcerptCount > 50) {
|
||||||
const dom = new JSDOM(html);
|
return {
|
||||||
|
noteId: sourceNote.noteId,
|
||||||
const excerpts = [];
|
relationName: backlink.name
|
||||||
|
};
|
||||||
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";
|
backlinksWithExcerptCount++;
|
||||||
linkEl.style.backgroundColor = "yellow";
|
|
||||||
|
|
||||||
const LIMIT = 200;
|
const excerpts = findExcerpts(sourceNote, noteId);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
noteId: sourceNote.noteId,
|
noteId: sourceNote.noteId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user