From c0964a4f128750f01b8281238c0af0267f141c06 Mon Sep 17 00:00:00 2001 From: zadam Date: Wed, 22 Dec 2021 10:57:02 +0100 Subject: [PATCH] added shareAlias label --- .../widgets/attribute_widgets/attribute_detail.js | 7 +++++-- src/public/app/widgets/shared_info.js | 13 +++++++++++-- src/services/attributes.js | 1 + src/share/content_renderer.js | 11 ++++++++++- src/share/routes.js | 8 ++++---- src/share/shaca/entities/attribute.js | 4 ++++ src/share/shaca/entities/note.js | 6 ++++++ src/share/shaca/shaca.js | 6 ++++++ src/share/shaca/shaca_loader.js | 2 +- src/views/share/tree_item.ejs | 2 +- 10 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/public/app/widgets/attribute_widgets/attribute_detail.js b/src/public/app/widgets/attribute_widgets/attribute_detail.js index 388c1f8ce..3bc673ba9 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_detail.js +++ b/src/public/app/widgets/attribute_widgets/attribute_detail.js @@ -210,7 +210,9 @@ const ATTR_HELP = { "hoistedInbox": "default inbox location for new notes when hoisted to some ancestor of this note", "sqlConsoleHome": "default location of SQL console notes", "bookmarked": "note with this label will appear in bookmarks", - "bookmarkFolder": "note with this label will appear in bookmarks as folder (allowing access to its children)" + "bookmarkFolder": "note with this label will appear in bookmarks as folder (allowing access to its children)", + "shareHiddenFromTree": "this note is hidden from left navigation tree, but still accessible with its URL", + "shareAlias": "define an alias using which the note will be available under https://your_trilium_host/share/[your_alias]", }, "relation": { "runOnNoteCreation": "executes when note is created on backend", @@ -221,7 +223,8 @@ const ATTR_HELP = { "runOnAttributeChange": "executes when attribute is changed under this note", "template": "attached note's attributes will be inherited even without parent-child relationship. See template for details.", "renderNote": 'notes of type "render HTML note" will be rendered using a code note (HTML or script) and it is necessary to point using this relation to which note should be rendered', - "widget": "target of this relation will be executed and rendered as a widget in the sidebar" + "widget": "target of this relation will be executed and rendered as a widget in the sidebar", + "shareCss": "CSS note which will be injected into the share page. CSS note must be in the shared sub-tree as well. Consider using 'shareHiddenFromTree' label to hide it.", } }; diff --git a/src/public/app/widgets/shared_info.js b/src/public/app/widgets/shared_info.js index 3a8b19c20..646b3c4f5 100644 --- a/src/public/app/widgets/shared_info.js +++ b/src/public/app/widgets/shared_info.js @@ -1,5 +1,6 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js"; import options from "../services/options.js"; +import attributeService from "../services/attributes.js"; const TPL = `
@@ -31,15 +32,23 @@ export default class SharedInfoWidget extends NoteContextAwareWidget { const syncServerHost = options.get("syncServerHost"); let link; + const shareId = note.getOwnedLabelValue('shareAlias') || note.noteId; + if (syncServerHost) { - link = syncServerHost + "/share/" + note.noteId; + link = syncServerHost + "/share/" + shareId; this.$shareText.text("This note is shared publicly on"); } else { - link = location.protocol + '//' + location.host + location.pathname + "share/" + note.noteId; + link = location.protocol + '//' + location.host + location.pathname + "share/" + shareId; this.$shareText.text("This note is shared locally on"); } this.$shareLink.attr("href", link).text(link); } + + entitiesReloadedEvent({loadResults}) { + if (loadResults.getAttributes().find(attr => attr.name.startsWith("share") && attributeService.isAffecting(attr, this.note))) { + this.refresh(); + } + } } diff --git a/src/services/attributes.js b/src/services/attributes.js index 6ace1af13..be538bf65 100644 --- a/src/services/attributes.js +++ b/src/services/attributes.js @@ -53,6 +53,7 @@ const BUILTIN_ATTRIBUTES = [ { type: 'label', name: 'top' }, { type: 'label', name: 'fullContentWidth' }, { type: 'label', name: 'shareHiddenFromTree' }, + { type: 'label', name: 'shareAlias' }, // relation names { type: 'relation', name: 'runOnNoteCreation', isDangerous: true }, diff --git a/src/share/content_renderer.js b/src/share/content_renderer.js index 8fe406d53..576b83beb 100644 --- a/src/share/content_renderer.js +++ b/src/share/content_renderer.js @@ -1,5 +1,6 @@ const {JSDOM} = require("jsdom"); const NO_CONTENT = '

This note has no content.

'; +const shaca = require("./shaca/shaca"); function getChildrenList(note) { if (note.hasChildren()) { @@ -43,7 +44,15 @@ function getContent(note) { if (href?.startsWith("#")) { const notePathSegments = href.split("/"); - linkEl.setAttribute("href", notePathSegments[notePathSegments.length - 1]); + const noteId = notePathSegments[notePathSegments.length - 1]; + const linkedNote = shaca.getNote(noteId); + + if (linkedNote) { + linkEl.setAttribute("href", linkedNote.shareId); + } + else { + linkEl.removeAttribute("href"); + } } } diff --git a/src/share/routes.js b/src/share/routes.js index 1dcaa4c6c..71b7adae7 100644 --- a/src/share/routes.js +++ b/src/share/routes.js @@ -18,14 +18,14 @@ function getSubRoot(note) { } function register(router) { - router.get('/share/:noteId', (req, res, next) => { - const {noteId} = req.params; + router.get('/share/:shareId', (req, res, next) => { + const {shareId} = req.params; shacaLoader.ensureLoad(); - if (noteId in shaca.notes) { - const note = shaca.notes[noteId]; + const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; + if (note) { const content = contentRenderer.getContent(note); const subRoot = getSubRoot(note); diff --git a/src/share/shaca/entities/attribute.js b/src/share/shaca/entities/attribute.js index 8aeba46c5..cf71258a4 100644 --- a/src/share/shaca/entities/attribute.js +++ b/src/share/shaca/entities/attribute.js @@ -39,6 +39,10 @@ class Attribute extends AbstractEntity { linkedChildNote.parents = linkedChildNote.parents.filter(parentNote => parentNote.noteId !== this.noteId); } } + + if (this.type === 'label' && this.name === 'shareAlias' && this.value.trim()) { + this.shaca.aliasToNote[this.value.trim()] = this.note; + } } get isAffectingSubtree() { diff --git a/src/share/shaca/entities/note.js b/src/share/shaca/entities/note.js index 46cfdedc1..1973a499b 100644 --- a/src/share/shaca/entities/note.js +++ b/src/share/shaca/entities/note.js @@ -549,6 +549,12 @@ class Note extends AbstractEntity { return notePaths.some(path => path.includes(ancestorNoteId)); } + + get shareId() { + const sharedAlias = this.getOwnedLabelValue("shareAlias"); + + return sharedAlias || this.noteId; + } } module.exports = Note; diff --git a/src/share/shaca/shaca.js b/src/share/shaca/shaca.js index 6ffaeb936..4ae3ce166 100644 --- a/src/share/shaca/shaca.js +++ b/src/share/shaca/shaca.js @@ -14,6 +14,8 @@ class Shaca { this.childParentToBranch = {}; /** @type {Object.} */ this.attributes = {}; + /** @type {Object.} */ + this.aliasToNote = {}; this.loaded = false; } @@ -22,6 +24,10 @@ class Shaca { return this.notes[noteId]; } + hasNote(noteId) { + return noteId in this.notes; + } + getNotes(noteIds, ignoreMissing = false) { const filteredNotes = []; diff --git a/src/share/shaca/shaca_loader.js b/src/share/shaca/shaca_loader.js index c98c15b9c..f240b2524 100644 --- a/src/share/shaca/shaca_loader.js +++ b/src/share/shaca/shaca_loader.js @@ -48,7 +48,7 @@ function load() { WHERE isDeleted = 0 AND noteId IN (${noteIdStr}) AND ( - (type = 'label' AND name IN ('archived', 'shareHiddenFromTree')) + (type = 'label' AND name IN ('archived', 'shareHiddenFromTree', 'shareAlias')) OR (type = 'relation' AND name IN ('imageLink', 'template', 'shareCss')) )`, []); diff --git a/src/views/share/tree_item.ejs b/src/views/share/tree_item.ejs index b01e0efa5..011a25ed3 100644 --- a/src/views/share/tree_item.ejs +++ b/src/views/share/tree_item.ejs @@ -2,7 +2,7 @@ <% if (activeNote.noteId === note.noteId) { %> <%= note.title %> <% } else { %> - <%= note.title %> + <%= note.title %> <% } %>