228 lines
6.4 KiB
JavaScript
Raw Normal View History

import treeService from './tree.js';
2022-08-05 16:44:26 +02:00
import linkContextMenuService from "../menus/link_context_menu.js";
2022-12-01 13:07:23 +01:00
import appContext from "../components/app_context.js";
2021-04-16 23:01:56 +02:00
import froca from "./froca.js";
import utils from "./utils.js";
2017-11-04 17:07:03 -04:00
function getNotePathFromUrl(url) {
2022-11-28 23:39:23 +01:00
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
2017-11-04 17:07:03 -04:00
return notePathMatch === null ? null : notePathMatch[1];
}
2017-11-04 17:07:03 -04:00
2019-12-28 21:10:02 +01:00
async function createNoteLink(notePath, options = {}) {
2020-01-03 10:48:36 +01:00
if (!notePath || !notePath.trim()) {
logError("Missing note path");
2020-01-03 10:48:36 +01:00
return $("<span>").text("[missing note]");
}
if (!notePath.startsWith("root")) {
// all note paths should start with "root/" (except for "root" itself)
// used e.g. to find internal links
notePath = `root/${notePath}`;
}
2019-12-28 21:10:02 +01:00
let noteTitle = options.title;
const showTooltip = options.showTooltip === undefined ? true : options.showTooltip;
const showNotePath = options.showNotePath === undefined ? false : options.showNotePath;
const showNoteIcon = options.showNoteIcon === undefined ? false : options.showNoteIcon;
const referenceLink = options.referenceLink === undefined ? false : options.referenceLink;
2019-12-28 21:10:02 +01:00
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
2017-11-04 17:07:03 -04:00
if (!noteTitle) {
2020-01-25 09:56:08 +01:00
noteTitle = await treeService.getNoteTitle(noteId, parentNoteId);
}
const $container = $("<span>");
if (showNoteIcon) {
const note = await froca.getNote(noteId);
$container
.append($("<span>").addClass(`bx ${note.getIcon()}`))
.append(" ");
}
const $noteLink = $("<a>", {
href: `#${notePath}`,
text: noteTitle
}).attr('data-action', 'note')
.attr('data-note-path', notePath);
2019-12-28 21:10:02 +01:00
if (!showTooltip) {
2019-10-01 21:41:20 +02:00
$noteLink.addClass("no-tooltip-preview");
}
if (referenceLink) {
$noteLink.addClass("reference-link");
}
$container.append($noteLink);
2019-12-28 21:10:02 +01:00
if (showNotePath) {
2020-08-24 23:33:27 +02:00
const resolvedNotePathSegments = await treeService.resolveNotePathToSegments(notePath);
if (notePath) {
2020-08-24 23:33:27 +02:00
resolvedNotePathSegments.pop(); // remove last element
2020-08-24 23:33:27 +02:00
const parentNotePath = resolvedNotePathSegments.join("/").trim();
if (parentNotePath) {
$container.append($("<small>").text(` (${await treeService.getNotePathTitle(parentNotePath)})`));
}
}
}
2019-12-28 21:10:02 +01:00
return $container;
}
2023-04-11 17:45:51 +02:00
function parseNotePathAndScope($link) {
let notePath = $link.attr("data-note-path");
2023-04-11 17:45:51 +02:00
if (!notePath) {
const url = $link.attr('href');
2017-11-04 17:07:03 -04:00
2023-04-11 17:45:51 +02:00
notePath = url ? getNotePathFromUrl(url) : null;
}
2017-11-04 17:07:03 -04:00
2023-04-03 23:47:24 +02:00
const viewScope = {
2023-04-11 17:45:51 +02:00
viewMode: $link.attr('data-view-mode') || 'default',
2023-04-03 23:47:24 +02:00
attachmentId: $link.attr('data-attachment-id'),
};
return {
notePath,
2023-04-11 17:45:51 +02:00
noteId: treeService.getNoteIdFromNotePath(notePath),
2023-04-03 23:47:24 +02:00
viewScope
};
}
2017-12-09 14:11:35 -05:00
function goToLink(evt) {
const $link = $(evt.target).closest("a,.block-link");
2023-04-11 17:45:51 +02:00
const hrefLink = $link.attr('href');
2022-07-29 00:32:28 +02:00
2023-04-11 17:45:51 +02:00
if (hrefLink?.startsWith("data:")) {
2022-07-29 00:32:28 +02:00
return true;
}
evt.preventDefault();
evt.stopPropagation();
2023-04-11 17:45:51 +02:00
const { notePath, viewScope } = parseNotePathAndScope($link);
const ctrlKey = utils.isCtrlKey(evt);
2023-04-03 23:47:24 +02:00
const isLeftClick = evt.which === 1;
const isMiddleClick = evt.which === 2;
const openInNewTab = (isLeftClick && ctrlKey) || isMiddleClick;
if (notePath) {
2023-04-03 23:47:24 +02:00
if (openInNewTab) {
appContext.tabManager.openTabWithNoteWithHoisting(notePath, { viewScope });
2019-05-08 19:10:45 +02:00
}
2023-04-03 23:47:24 +02:00
else if (isLeftClick) {
const ntxId = $(evt.target).closest("[data-ntx-id]").attr("data-ntx-id");
2021-05-21 22:44:08 +02:00
2021-05-22 12:26:45 +02:00
const noteContext = ntxId
? appContext.tabManager.getNoteContextById(ntxId)
2021-05-22 12:35:41 +02:00
: appContext.tabManager.getActiveContext();
2021-05-21 22:44:08 +02:00
2023-04-03 23:47:24 +02:00
noteContext.setNote(notePath, { viewScope }).then(() => {
2021-05-22 12:35:41 +02:00
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
2021-05-21 22:44:08 +02:00
}
});
2019-05-08 19:10:45 +02:00
}
}
2023-04-11 17:45:51 +02:00
else if (hrefLink) {
// this branch handles external links
const isWithinCKLinkDialog = $link.hasClass("ck-link-actions__preview");
const isOutsideCKEditor = $link.closest("[contenteditable]").length === 0;
2023-04-11 17:45:51 +02:00
if (openInNewTab || isWithinCKLinkDialog || isOutsideCKEditor) {
if (hrefLink.toLowerCase().startsWith('http')) {
window.open(hrefLink, '_blank');
}
else if (hrefLink.toLowerCase().startsWith('file:') && utils.isElectron()) {
const electron = utils.dynamicRequire('electron');
electron.shell.openPath(hrefLink);
}
}
}
return true;
}
function linkContextMenu(e) {
const $link = $(e.target).closest("a");
2023-04-11 17:45:51 +02:00
const { notePath, viewScope } = parseNotePathAndScope($link);
if (!notePath) {
return;
}
e.preventDefault();
2023-04-03 23:47:24 +02:00
linkContextMenuService.openContextMenu(notePath, e, viewScope, null);
}
async function loadReferenceLinkTitle(noteId, $el) {
2021-04-16 22:57:37 +02:00
const note = await froca.getNote(noteId, true);
let title;
if (!note) {
title = '[missing]';
}
else {
2020-12-18 22:35:40 +01:00
title = note.isDeleted ? `${note.title} (deleted)` : note.title;
}
if (note) {
$el.addClass(note.getColorClass());
}
$el.text(title);
2022-09-24 22:38:20 +02:00
if (note) {
$el.prepend($("<span>").addClass(note.getIcon()));
}
}
2020-08-19 17:59:55 +02:00
$(document).on('click', "a", goToLink);
$(document).on('auxclick', "a", goToLink); // to handle middle button
$(document).on('contextmenu', 'a', linkContextMenu);
$(document).on('dblclick', "a", e => {
e.preventDefault();
e.stopPropagation();
const $link = $(e.target).closest("a");
const address = $link.attr('href');
if (address && address.startsWith('http')) {
window.open(address, '_blank');
}
});
$(document).on('mousedown', 'a', e => {
if (e.which === 2) {
// prevent paste on middle click
// https://github.com/zadam/trilium/issues/2995
// https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event#preventing_default_actions
e.preventDefault();
return false;
}
});
export default {
getNotePathFromUrl,
createNoteLink,
goToLink,
2023-04-11 17:45:51 +02:00
loadReferenceLinkTitle,
parseNotePathAndScope
};