mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
getting rid of attributes like data-note-path in favor of the whole nav state in URLs
This commit is contained in:
parent
291f0e79d9
commit
f85209a72f
@ -9,6 +9,7 @@ import TabManager from "./tab_manager.js";
|
|||||||
import treeService from "../services/tree.js";
|
import treeService from "../services/tree.js";
|
||||||
import Component from "./component.js";
|
import Component from "./component.js";
|
||||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||||
|
import linkService from "../services/link.js";
|
||||||
import MobileScreenSwitcherExecutor from "./mobile_screen_switcher.js";
|
import MobileScreenSwitcherExecutor from "./mobile_screen_switcher.js";
|
||||||
import MainTreeExecutors from "./main_tree_executors.js";
|
import MainTreeExecutors from "./main_tree_executors.js";
|
||||||
import toast from "../services/toast.js";
|
import toast from "../services/toast.js";
|
||||||
@ -158,14 +159,9 @@ $(window).on('beforeunload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(window).on('hashchange', function() {
|
$(window).on('hashchange', function() {
|
||||||
if (treeService.isNotePathInAddress()) {
|
const {notePath, ntxId, viewScope} = linkService.parseNavigationStateFromUrl(window.location.href);
|
||||||
const {notePath, ntxId, viewScope} = treeService.parseNavigationStateFromAddress();
|
|
||||||
|
|
||||||
if (!notePath && !ntxId) {
|
|
||||||
console.log(`Invalid hash value "${document.location.hash}", ignoring.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (notePath || ntxId) {
|
||||||
appContext.tabManager.switchToNoteContext(ntxId, notePath, viewScope);
|
appContext.tabManager.switchToNoteContext(ntxId, notePath, viewScope);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -52,14 +52,13 @@ export default class TabManager extends Component {
|
|||||||
|
|
||||||
async loadTabs() {
|
async loadTabs() {
|
||||||
try {
|
try {
|
||||||
const noteContextsToOpen = appContext.isMainWindow
|
const noteContextsToOpen = (appContext.isMainWindow && options.getJson('openNoteContexts')) || [];
|
||||||
? (options.getJson('openNoteContexts') || [])
|
|
||||||
: [];
|
|
||||||
|
|
||||||
// preload all notes at once
|
// preload all notes at once
|
||||||
await froca.getNotes([
|
await froca.getNotes([
|
||||||
...noteContextsToOpen.map(tab => treeService.getNoteIdFromNotePath(tab.notePath)),
|
...noteContextsToOpen.flatMap(tab =>
|
||||||
...noteContextsToOpen.map(tab => tab.hoistedNoteId),
|
[ treeService.getNoteIdFromNotePath(tab.notePath), tab.hoistedNoteId]
|
||||||
|
),
|
||||||
], true);
|
], true);
|
||||||
|
|
||||||
const filteredNoteContexts = noteContextsToOpen.filter(openTab => {
|
const filteredNoteContexts = noteContextsToOpen.filter(openTab => {
|
||||||
@ -81,7 +80,7 @@ export default class TabManager extends Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// resolve before opened tabs can change this
|
// resolve before opened tabs can change this
|
||||||
const parsedFromUrl = treeService.parseNavigationStateFromAddress();
|
const parsedFromUrl = linkService.parseNavigationStateFromUrl(window.location.href);
|
||||||
|
|
||||||
if (filteredNoteContexts.length === 0) {
|
if (filteredNoteContexts.length === 0) {
|
||||||
parsedFromUrl.ntxId = parsedFromUrl.ntxId || NoteContext.generateNtxId(); // generate already here, so that we later know which one to activate
|
parsedFromUrl.ntxId = parsedFromUrl.ntxId || NoteContext.generateNtxId(); // generate already here, so that we later know which one to activate
|
||||||
@ -109,8 +108,8 @@ export default class TabManager extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// if there's notePath in the URL, make sure it's open and active
|
// if there's a notePath in the URL, make sure it's open and active
|
||||||
// (useful, for e.g. opening clipped notes from clipper or opening link in an extra window)
|
// (useful, for e.g., opening clipped notes from clipper or opening link in an extra window)
|
||||||
if (parsedFromUrl.notePath) {
|
if (parsedFromUrl.notePath) {
|
||||||
await appContext.tabManager.switchToNoteContext(
|
await appContext.tabManager.switchToNoteContext(
|
||||||
parsedFromUrl.ntxId,
|
parsedFromUrl.ntxId,
|
||||||
|
@ -56,8 +56,7 @@ async function createNoteLink(noteId) {
|
|||||||
|
|
||||||
return $("<a>", {
|
return $("<a>", {
|
||||||
href: `#root/${noteId}`,
|
href: `#root/${noteId}`,
|
||||||
class: 'reference-link',
|
class: 'reference-link'
|
||||||
'data-note-path': noteId
|
|
||||||
})
|
})
|
||||||
.text(note.title);
|
.text(note.title);
|
||||||
}
|
}
|
||||||
|
@ -19,21 +19,17 @@ async function createNoteLink(notePath, options = {}) {
|
|||||||
|
|
||||||
if (!notePath.startsWith("root")) {
|
if (!notePath.startsWith("root")) {
|
||||||
// all note paths should start with "root/" (except for "root" itself)
|
// all note paths should start with "root/" (except for "root" itself)
|
||||||
// used e.g., to find internal links
|
// used, e.g., to find internal links
|
||||||
notePath = `root/${notePath}`;
|
notePath = `root/${notePath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let noteTitle = options.title;
|
|
||||||
const showTooltip = options.showTooltip === undefined ? true : options.showTooltip;
|
const showTooltip = options.showTooltip === undefined ? true : options.showTooltip;
|
||||||
const showNotePath = options.showNotePath === undefined ? false : options.showNotePath;
|
const showNotePath = options.showNotePath === undefined ? false : options.showNotePath;
|
||||||
const showNoteIcon = options.showNoteIcon === undefined ? false : options.showNoteIcon;
|
const showNoteIcon = options.showNoteIcon === undefined ? false : options.showNoteIcon;
|
||||||
const referenceLink = options.referenceLink === undefined ? false : options.referenceLink;
|
const referenceLink = options.referenceLink === undefined ? false : options.referenceLink;
|
||||||
|
|
||||||
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
|
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromNotePath(notePath);
|
||||||
|
const noteTitle = options.title || await treeService.getNoteTitle(noteId, parentNoteId);
|
||||||
if (!noteTitle) {
|
|
||||||
noteTitle = await treeService.getNoteTitle(noteId, parentNoteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const $container = $("<span>");
|
const $container = $("<span>");
|
||||||
|
|
||||||
@ -45,11 +41,15 @@ async function createNoteLink(notePath, options = {}) {
|
|||||||
.append(" ");
|
.append(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hash = calculateHash({
|
||||||
|
notePath,
|
||||||
|
viewScope: options.viewScope
|
||||||
|
});
|
||||||
|
|
||||||
const $noteLink = $("<a>", {
|
const $noteLink = $("<a>", {
|
||||||
href: `#${notePath}`,
|
href: hash,
|
||||||
text: noteTitle
|
text: noteTitle
|
||||||
}).attr('data-action', 'note')
|
});
|
||||||
.attr('data-note-path', notePath);
|
|
||||||
|
|
||||||
if (!showTooltip) {
|
if (!showTooltip) {
|
||||||
$noteLink.addClass("no-tooltip-preview");
|
$noteLink.addClass("no-tooltip-preview");
|
||||||
@ -78,27 +78,6 @@ async function createNoteLink(notePath, options = {}) {
|
|||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseNotePathAndScope($link) {
|
|
||||||
let notePath = $link.attr("data-note-path");
|
|
||||||
|
|
||||||
if (!notePath) {
|
|
||||||
const url = $link.attr('href');
|
|
||||||
|
|
||||||
notePath = url ? getNotePathFromUrl(url) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewScope = {
|
|
||||||
viewMode: $link.attr('data-view-mode') || 'default',
|
|
||||||
attachmentId: $link.attr('data-attachment-id'),
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
notePath,
|
|
||||||
noteId: treeService.getNoteIdFromNotePath(notePath),
|
|
||||||
viewScope
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateHash({notePath, ntxId, hoistedNoteId, viewScope = {}}) {
|
function calculateHash({notePath, ntxId, hoistedNoteId, viewScope = {}}) {
|
||||||
notePath = notePath || "";
|
notePath = notePath || "";
|
||||||
const params = [
|
const params = [
|
||||||
@ -128,9 +107,50 @@ function calculateHash({notePath, ntxId, hoistedNoteId, viewScope = {}}) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseNavigationStateFromUrl(url) {
|
||||||
|
const hashIdx = url?.indexOf('#');
|
||||||
|
if (hashIdx === -1) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const hash = url?.substr(hashIdx + 1); // strip also the initial '#'
|
||||||
|
const [notePath, paramString] = hash.split("?");
|
||||||
|
const viewScope = {
|
||||||
|
viewMode: 'default'
|
||||||
|
};
|
||||||
|
let ntxId = null;
|
||||||
|
let hoistedNoteId = null;
|
||||||
|
|
||||||
|
if (paramString) {
|
||||||
|
for (const pair of paramString.split("&")) {
|
||||||
|
let [name, value] = pair.split("=");
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
value = decodeURIComponent(value);
|
||||||
|
|
||||||
|
if (name === 'ntxId') {
|
||||||
|
ntxId = value;
|
||||||
|
} else if (name === 'hoistedNoteId') {
|
||||||
|
hoistedNoteId = value;
|
||||||
|
} else if (['viewMode', 'attachmentId'].includes(name)) {
|
||||||
|
viewScope[name] = value;
|
||||||
|
} else {
|
||||||
|
console.warn(`Unrecognized hash parameter '${name}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
notePath,
|
||||||
|
noteId: treeService.getNoteIdFromNotePath(notePath),
|
||||||
|
ntxId,
|
||||||
|
hoistedNoteId,
|
||||||
|
viewScope
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function goToLink(evt) {
|
function goToLink(evt) {
|
||||||
const $link = $(evt.target).closest("a,.block-link");
|
const $link = $(evt.target).closest("a,.block-link");
|
||||||
const hrefLink = $link.attr('href');
|
const hrefLink = $link.attr('href') || $link.attr('data-href');
|
||||||
|
|
||||||
if (hrefLink?.startsWith("data:")) {
|
if (hrefLink?.startsWith("data:")) {
|
||||||
return true;
|
return true;
|
||||||
@ -139,7 +159,7 @@ function goToLink(evt) {
|
|||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
|
||||||
const { notePath, viewScope } = parseNotePathAndScope($link);
|
const { notePath, viewScope } = parseNavigationStateFromUrl(hrefLink);
|
||||||
|
|
||||||
const ctrlKey = utils.isCtrlKey(evt);
|
const ctrlKey = utils.isCtrlKey(evt);
|
||||||
const isLeftClick = evt.which === 1;
|
const isLeftClick = evt.which === 1;
|
||||||
@ -186,8 +206,9 @@ function goToLink(evt) {
|
|||||||
|
|
||||||
function linkContextMenu(e) {
|
function linkContextMenu(e) {
|
||||||
const $link = $(e.target).closest("a");
|
const $link = $(e.target).closest("a");
|
||||||
|
const url = $link.attr("href") || $link.attr("data-href");
|
||||||
|
|
||||||
const { notePath, viewScope } = parseNotePathAndScope($link);
|
const { notePath, viewScope } = parseNavigationStateFromUrl(url);
|
||||||
|
|
||||||
if (!notePath) {
|
if (!notePath) {
|
||||||
return;
|
return;
|
||||||
@ -252,6 +273,6 @@ export default {
|
|||||||
createNoteLink,
|
createNoteLink,
|
||||||
goToLink,
|
goToLink,
|
||||||
loadReferenceLinkTitle,
|
loadReferenceLinkTitle,
|
||||||
parseNotePathAndScope,
|
calculateHash,
|
||||||
calculateHash
|
parseNavigationStateFromUrl
|
||||||
};
|
};
|
||||||
|
@ -114,8 +114,7 @@ function initNoteAutocomplete($el, options) {
|
|||||||
.prop("title", "Show recent notes");
|
.prop("title", "Show recent notes");
|
||||||
|
|
||||||
const $goToSelectedNoteButton = $("<a>")
|
const $goToSelectedNoteButton = $("<a>")
|
||||||
.addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right")
|
.addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right");
|
||||||
.attr("data-action", "note");
|
|
||||||
|
|
||||||
const $sideButtons = $("<div>")
|
const $sideButtons = $("<div>")
|
||||||
.addClass("input-group-append")
|
.addClass("input-group-append")
|
||||||
|
@ -54,9 +54,9 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type === 'code') {
|
else if (type === 'code') {
|
||||||
const fullNote = await server.get(`notes/${note.noteId}`);
|
const blob = await note.getBlob({ preview: options.trim });
|
||||||
|
|
||||||
$renderedContent.append($("<pre>").text(trim(fullNote.content, options.trim)));
|
$renderedContent.append($("<pre>").text(trim(blob.content, options.trim)));
|
||||||
}
|
}
|
||||||
else if (type === 'image') {
|
else if (type === 'image') {
|
||||||
const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");
|
const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");
|
||||||
|
@ -268,7 +268,7 @@ class NoteListRenderer {
|
|||||||
|
|
||||||
const {$renderedAttributes} = await attributeRenderer.renderNormalAttributes(note);
|
const {$renderedAttributes} = await attributeRenderer.renderNormalAttributes(note);
|
||||||
const notePath = this.parentNote.type === 'search'
|
const notePath = this.parentNote.type === 'search'
|
||||||
? note.noteId // for search note parent we want to display non-search path
|
? note.noteId // for search note parent, we want to display a non-search path
|
||||||
: `${this.parentNote.noteId}/${note.noteId}`;
|
: `${this.parentNote.noteId}/${note.noteId}`;
|
||||||
|
|
||||||
const $card = $('<div class="note-book-card">')
|
const $card = $('<div class="note-book-card">')
|
||||||
@ -288,7 +288,7 @@ class NoteListRenderer {
|
|||||||
if (this.viewType === 'grid') {
|
if (this.viewType === 'grid') {
|
||||||
$card
|
$card
|
||||||
.addClass("block-link")
|
.addClass("block-link")
|
||||||
.attr("data-note-path", notePath)
|
.attr("data-href", `#${notePath}`)
|
||||||
.on('click', e => linkService.goToLink(e));
|
.on('click', e => linkService.goToLink(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ async function mouseEnterHandler() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { notePath, noteId, viewScope } = linkService.parseNotePathAndScope($link);
|
const url = $link.attr("href") || $link.attr("data-href");
|
||||||
|
const { notePath, noteId, viewScope } = linkService.parseNavigationStateFromUrl(url);
|
||||||
|
|
||||||
if (!notePath || viewScope.viewMode !== 'default') {
|
if (!notePath || viewScope.viewMode !== 'default') {
|
||||||
return;
|
return;
|
||||||
|
@ -279,50 +279,6 @@ async function getNoteTitleWithPathAsSuffix(notePath) {
|
|||||||
return $titleWithPath;
|
return $titleWithPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseNavigationStateFromAddress() {
|
|
||||||
const str = document.location.hash?.substr(1) || ""; // strip initial #
|
|
||||||
|
|
||||||
const [notePath, paramString] = str.split("?");
|
|
||||||
const viewScope = {
|
|
||||||
viewMode: 'default'
|
|
||||||
};
|
|
||||||
let ntxId = null;
|
|
||||||
let hoistedNoteId = null;
|
|
||||||
|
|
||||||
if (paramString) {
|
|
||||||
for (const pair of paramString.split("&")) {
|
|
||||||
let [name, value] = pair.split("=");
|
|
||||||
name = decodeURIComponent(name);
|
|
||||||
value = decodeURIComponent(value);
|
|
||||||
|
|
||||||
if (name === 'ntxId') {
|
|
||||||
ntxId = value;
|
|
||||||
} else if (name === 'hoistedNoteId') {
|
|
||||||
hoistedNoteId = value;
|
|
||||||
} else if (['viewMode', 'attachmentId'].includes(name)) {
|
|
||||||
viewScope[name] = value;
|
|
||||||
} else {
|
|
||||||
console.warn(`Unrecognized hash parameter '${name}'.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
notePath,
|
|
||||||
ntxId,
|
|
||||||
hoistedNoteId,
|
|
||||||
viewScope
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotePathInAddress() {
|
|
||||||
const {notePath, ntxId} = parseNavigationStateFromAddress();
|
|
||||||
|
|
||||||
return notePath.startsWith("root")
|
|
||||||
// empty string is for empty/uninitialized tab
|
|
||||||
|| (notePath === '' && !!ntxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotePathInHiddenSubtree(notePath) {
|
function isNotePathInHiddenSubtree(notePath) {
|
||||||
return notePath?.includes("root/_hidden");
|
return notePath?.includes("root/_hidden");
|
||||||
}
|
}
|
||||||
@ -338,7 +294,5 @@ export default {
|
|||||||
getNoteTitle,
|
getNoteTitle,
|
||||||
getNotePathTitle,
|
getNotePathTitle,
|
||||||
getNoteTitleWithPathAsSuffix,
|
getNoteTitleWithPathAsSuffix,
|
||||||
parseNavigationStateFromAddress,
|
|
||||||
isNotePathInAddress,
|
|
||||||
isNotePathInHiddenSubtree
|
isNotePathInHiddenSubtree
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@ import BasicWidget from "./basic_widget.js";
|
|||||||
import server from "../services/server.js";
|
import server from "../services/server.js";
|
||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import imageService from "../services/image.js";
|
import imageService from "../services/image.js";
|
||||||
|
import linkService from "../services/link.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="attachment-detail">
|
<div class="attachment-detail">
|
||||||
@ -15,6 +16,7 @@ const TPL = `
|
|||||||
.attachment-title-line {
|
.attachment-title-line {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
gap: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-details {
|
.attachment-details {
|
||||||
@ -54,10 +56,10 @@ const TPL = `
|
|||||||
|
|
||||||
<div class="attachment-detail-wrapper">
|
<div class="attachment-detail-wrapper">
|
||||||
<div class="attachment-title-line">
|
<div class="attachment-title-line">
|
||||||
|
<div class="attachment-actions-container"></div>
|
||||||
<h4 class="attachment-title"></h4>
|
<h4 class="attachment-title"></h4>
|
||||||
<div class="attachment-details"></div>
|
<div class="attachment-details"></div>
|
||||||
<div style="flex: 1 1;"></div>
|
<div style="flex: 1 1;"></div>
|
||||||
<div class="attachment-actions-container"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="attachment-deletion-warning alert alert-info"></div>
|
<div class="attachment-deletion-warning alert alert-info"></div>
|
||||||
@ -84,7 +86,7 @@ export default class AttachmentDetailWidget extends BasicWidget {
|
|||||||
super.doRender();
|
super.doRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
async refresh() {
|
||||||
this.$widget.find('.attachment-detail-wrapper')
|
this.$widget.find('.attachment-detail-wrapper')
|
||||||
.empty()
|
.empty()
|
||||||
.append(
|
.append(
|
||||||
@ -97,11 +99,13 @@ export default class AttachmentDetailWidget extends BasicWidget {
|
|||||||
|
|
||||||
if (!this.isFullDetail) {
|
if (!this.isFullDetail) {
|
||||||
this.$wrapper.find('.attachment-title').append(
|
this.$wrapper.find('.attachment-title').append(
|
||||||
$('<a href="javascript:">')
|
await linkService.createNoteLink(this.attachment.parentId, {
|
||||||
.attr("data-note-path", this.attachment.parentId)
|
title: this.attachment.title,
|
||||||
.attr("data-view-mode", "attachments")
|
viewScope: {
|
||||||
.attr("data-attachment-id", this.attachment.attachmentId)
|
viewMode: 'attachments',
|
||||||
.text(this.attachment.title)
|
attachmentId: this.attachment.attachmentId
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.$wrapper.find('.attachment-title')
|
this.$wrapper.find('.attachment-title')
|
||||||
|
@ -701,9 +701,8 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
createNoteLink(noteId) {
|
createNoteLink(noteId) {
|
||||||
return $("<a>", {
|
return $("<a>", {
|
||||||
href: `#${noteId}`,
|
href: `#root/${noteId}`,
|
||||||
class: 'reference-link',
|
class: 'reference-link'
|
||||||
'data-note-path': noteId
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
|
|
||||||
if (dateNoteId) {
|
if (dateNoteId) {
|
||||||
$newDay.addClass('calendar-date-exists');
|
$newDay.addClass('calendar-date-exists');
|
||||||
$newDay.attr("data-note-path", dateNoteId);
|
$newDay.attr("href", `#root/dateNoteId`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isEqual(this.date, this.activeDate)) {
|
if (this.isEqual(this.date, this.activeDate)) {
|
||||||
|
@ -55,7 +55,7 @@ export default class HistoryNavigationButton extends ButtonFromNoteWidget {
|
|||||||
for (const idx in this.webContents.history) {
|
for (const idx in this.webContents.history) {
|
||||||
const url = this.webContents.history[idx];
|
const url = this.webContents.history[idx];
|
||||||
const [_, notePathWithTab] = url.split('#');
|
const [_, notePathWithTab] = url.split('#');
|
||||||
// broken: use treeService.parseNavigationStateFromAddress();
|
// broken: use linkService.parseNavigationStateFromUrl();
|
||||||
const [notePath, ntxId] = notePathWithTab.split('-');
|
const [notePath, ntxId] = notePathWithTab.split('-');
|
||||||
|
|
||||||
const title = await treeService.getNotePathTitle(notePath);
|
const title = await treeService.getNotePathTitle(notePath);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import TypeWidget from "./type_widget.js";
|
import TypeWidget from "./type_widget.js";
|
||||||
import server from "../../services/server.js";
|
import server from "../../services/server.js";
|
||||||
import AttachmentDetailWidget from "../attachment_detail.js";
|
import AttachmentDetailWidget from "../attachment_detail.js";
|
||||||
|
import linkService from "../../services/link.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="attachment-detail note-detail-printable">
|
<div class="attachment-detail note-detail-printable">
|
||||||
@ -10,6 +11,8 @@ const TPL = `
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<div class="links-wrapper"></div>
|
||||||
|
|
||||||
<div class="attachment-wrapper"></div>
|
<div class="attachment-wrapper"></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
@ -29,6 +32,8 @@ export default class AttachmentDetailTypeWidget extends TypeWidget {
|
|||||||
this.$wrapper.empty();
|
this.$wrapper.empty();
|
||||||
this.children = [];
|
this.children = [];
|
||||||
|
|
||||||
|
linkService.createNoteLink(this.noteId, {});
|
||||||
|
|
||||||
const attachment = await server.get(`attachments/${this.attachmentId}/?includeContent=true`);
|
const attachment = await server.get(`attachments/${this.attachmentId}/?includeContent=true`);
|
||||||
|
|
||||||
if (!attachment) {
|
if (!attachment) {
|
||||||
|
@ -33,7 +33,7 @@ function sanitize(dirtyHtml) {
|
|||||||
'en-media' // for ENEX import
|
'en-media' // for ENEX import
|
||||||
],
|
],
|
||||||
allowedAttributes: {
|
allowedAttributes: {
|
||||||
'a': [ 'href', 'class', 'data-note-path' ],
|
'a': [ 'href', 'class' ],
|
||||||
'img': [ 'src' ],
|
'img': [ 'src' ],
|
||||||
'section': [ 'class', 'data-note-id' ],
|
'section': [ 'class', 'data-note-id' ],
|
||||||
'figure': [ 'class' ],
|
'figure': [ 'class' ],
|
||||||
|
@ -376,20 +376,6 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
|
|||||||
return `href="#root/${target.noteId}"`;
|
return `href="#root/${target.noteId}"`;
|
||||||
});
|
});
|
||||||
|
|
||||||
content = content.replace(/data-note-path="([^"]*)"/g, (match, notePath) => {
|
|
||||||
const noteId = notePath.split("/").pop();
|
|
||||||
|
|
||||||
let targetNoteId;
|
|
||||||
|
|
||||||
if (noteId === 'root' || noteId.startsWith("_")) { // named noteIds stay identical across instances
|
|
||||||
targetNoteId = noteId;
|
|
||||||
} else {
|
|
||||||
targetNoteId = noteIdMap[noteId];
|
|
||||||
}
|
|
||||||
|
|
||||||
return `data-note-path="root/${targetNoteId}"`;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (noteMeta) {
|
if (noteMeta) {
|
||||||
const includeNoteLinks = (noteMeta.attributes || [])
|
const includeNoteLinks = (noteMeta.attributes || [])
|
||||||
.filter(attr => attr.type === 'relation' && attr.name === 'includeNoteLink');
|
.filter(attr => attr.type === 'relation' && attr.name === 'includeNoteLink');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user