From 1f21c65a99532241480777d38b94b1373b76b5af Mon Sep 17 00:00:00 2001 From: x1arch Date: Fri, 21 Nov 2025 16:51:25 +0000 Subject: [PATCH] update share path to .../parent/noteid --- apps/server/src/share/content_renderer.ts | 37 +++++++++---------- apps/server/src/share/routes.ts | 22 ++++++++--- apps/server/src/share/shaca/entities/snote.ts | 6 +++ packages/share-theme/src/templates/page.ejs | 2 +- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/apps/server/src/share/content_renderer.ts b/apps/server/src/share/content_renderer.ts index 3e9e8db18..819f7bbe6 100644 --- a/apps/server/src/share/content_renderer.ts +++ b/apps/server/src/share/content_renderer.ts @@ -47,15 +47,14 @@ function addContentAccessQuery(note: SNote | BNote, secondEl?:boolean) { return "" } -function getSharedSubTreeRoot(note: SNote | BNote | undefined): Subroot { +export function getSharedSubTreeRoot(note: SNote | BNote | undefined, parentId: string | undefined = undefined): Subroot { if (!note || note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { // share root itself is not shared return {}; } - // every path leads to share root, but which one to choose? - // for the sake of simplicity, URLs are not note paths - const parentBranch = note.getParentBranches()[0]; + const parentBranches = note.getParentBranches() + const parentBranch = (parentId ? parentBranches.find((pb: SBranch | BBranch) => pb.parentNoteId === parentId) : undefined) || parentBranches[0]; if (note instanceof BNote) { return { @@ -71,7 +70,7 @@ function getSharedSubTreeRoot(note: SNote | BNote | undefined): Subroot { }; } - return getSharedSubTreeRoot(parentBranch.getParentNote()); + return getSharedSubTreeRoot(parentBranch.getParentNote(), parentId); } export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath: string, ancestors: string[]) { @@ -98,7 +97,7 @@ export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath } export function renderNoteContent(note: SNote) { - const subRoot = getSharedSubTreeRoot(note); + const subRoot = getSharedSubTreeRoot(note, note.parentId); const ancestors: string[] = []; let notePointer = note; @@ -114,23 +113,23 @@ export function renderNoteContent(note: SNote) { // Determine CSS to load. const cssToLoad: string[] = []; if (!note.isLabelTruthy("shareOmitDefaultCss")) { - cssToLoad.push(`assets/styles.css`); - cssToLoad.push(`assets/scripts.css`); + cssToLoad.push(`../assets/styles.css`); + cssToLoad.push(`../assets/scripts.css`); } for (const cssRelation of note.getRelations("shareCss")) { - cssToLoad.push(`api/notes/${cssRelation.value}/download${addContentAccessQuery(note)}`); + cssToLoad.push(`../api/notes/${cssRelation.value}/download${addContentAccessQuery(note)}`); } // Determine JS to load. const jsToLoad: string[] = [ - "assets/scripts.js" + "../assets/scripts.js" ]; for (const jsRelation of note.getRelations("shareJs")) { - jsToLoad.push(`api/notes/${jsRelation.value}/download${addContentAccessQuery(note)}`); + jsToLoad.push(`../api/notes/${jsRelation.value}/download${addContentAccessQuery(note)}`); } const customLogoId = note.getRelation("shareLogo")?.value; - const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png${addContentAccessQuery(note)}` : `../${assetUrlFragment}/images/icon-color.svg`; + const logoUrl = customLogoId ? `../api/images/${customLogoId}/image.png${addContentAccessQuery(note)}` : `../../${assetUrlFragment}/images/icon-color.svg`; return renderNoteContentInternal(note, { subRoot, @@ -140,7 +139,7 @@ export function renderNoteContent(note: SNote) { logoUrl, ancestors, isStatic: false, - faviconUrl: note.hasRelation("shareFavicon") ? `api/notes/${note.getRelationValue("shareFavicon")}/download${addContentAccessQuery(note)}` : `../favicon.ico` + faviconUrl: note.hasRelation("shareFavicon") ? `../api/notes/${note.getRelationValue("shareFavicon")}/download${addContentAccessQuery(note)}` : `../../favicon.ico` }); } @@ -365,7 +364,7 @@ function handleAttachmentLink(linkEl: HTMLElement, href: string, getNote: GetNot const attachment = getAttachment(attachmentId); if (attachment) { - linkEl.setAttribute("href", `api/attachments/${attachmentId}/download${addContentAccessQuery(note)}`); + linkEl.setAttribute("href", `../api/attachments/${attachmentId}/download${addContentAccessQuery(note)}`); linkEl.classList.add(`attachment-link`); linkEl.classList.add(`role-${attachment.role}`); linkEl.childNodes.length = 0; @@ -381,7 +380,7 @@ function handleAttachmentLink(linkEl: HTMLElement, href: string, getNote: GetNot const linkedNote = getNote(noteId); if (linkedNote) { const isExternalLink = linkedNote.hasLabel("shareExternalLink"); - const href = isExternalLink ? linkedNote.getLabelValue("shareExternalLink") : `./${linkedNote.shareId}`; + const href = isExternalLink ? linkedNote.getLabelValue("shareExternalLink") : `../${linkedNote.shareId}`; if (href) { linkEl.setAttribute("href", href); } @@ -438,7 +437,7 @@ function renderMermaid(result: Result, note: SNote | BNote) { } result.content = ` - +
Chart source @@ -447,14 +446,14 @@ function renderMermaid(result: Result, note: SNote | BNote) { } function renderImage(result: Result, note: SNote | BNote) { - result.content = ``; + result.content = ``; } function renderFile(note: SNote | BNote, result: Result) { if (note.mime === "application/pdf") { - result.content = ``; + result.content = ``; } else { - result.content = ``; + result.content = ``; } } diff --git a/apps/server/src/share/routes.ts b/apps/server/src/share/routes.ts index 925843b0d..f6a9646c5 100644 --- a/apps/server/src/share/routes.ts +++ b/apps/server/src/share/routes.ts @@ -8,7 +8,7 @@ import searchService from "../services/search/services/search.js"; import SearchContext from "../services/search/search_context.js"; import type SNote from "./shaca/entities/snote.js"; import type SAttachment from "./shaca/entities/sattachment.js"; -import { getDefaultTemplatePath, renderNoteContent } from "./content_renderer.js"; +import { getDefaultTemplatePath, getSharedSubTreeRoot, renderNoteContent } from "./content_renderer.js"; import utils from "../services/utils.js"; function addNoIndexHeader(note: SNote, res: Response) { @@ -180,17 +180,29 @@ function register(router: Router) { renderNote(shaca.shareRootNote, req, res); }); + router.get("/share/:parentShareId/:shareId", (req, res) => { + shacaLoader.ensureLoad(); + + const { parentShareId, shareId } = req.params; + + const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; + if (note){ + note.parentId = parentShareId + note.initContentAccessor() + } + + renderNote(note, req, res); + }); + router.get("/share/:shareId", (req, res) => { shacaLoader.ensureLoad(); const { shareId } = req.params; const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; - if (note){ - note.initContentAccessor() - } + const parent = getSharedSubTreeRoot(note) - renderNote(note, req, res); + res.redirect(`${parent?.note?.noteId}/${shareId}`) }); router.get("/share/api/notes/:noteId", (req, res) => { diff --git a/apps/server/src/share/shaca/entities/snote.ts b/apps/server/src/share/shaca/entities/snote.ts index 31c871551..9ad38add3 100644 --- a/apps/server/src/share/shaca/entities/snote.ts +++ b/apps/server/src/share/shaca/entities/snote.ts @@ -20,6 +20,7 @@ const isCredentials = (attr: SAttribute) => attr.type === "label" && attr.name = class SNote extends AbstractShacaEntity { noteId: string; + parentId?: string | undefined; title: string; type: string; mime: string; @@ -40,6 +41,7 @@ class SNote extends AbstractShacaEntity { super(); this.noteId = noteId; + this.parentId = undefined; this.title = isProtected ? "[protected]" : title; this.type = type; this.mime = mime; @@ -70,6 +72,10 @@ class SNote extends AbstractShacaEntity { } } + getParentId() { + return this.parentId; + } + getParentBranches() { return this.parentBranches; } diff --git a/packages/share-theme/src/templates/page.ejs b/packages/share-theme/src/templates/page.ejs index b9cf38c30..f098c4c39 100644 --- a/packages/share-theme/src/templates/page.ejs +++ b/packages/share-theme/src/templates/page.ejs @@ -157,7 +157,7 @@ content = content.replaceAll(headingRe, (...match) => { <% content = content .replace(/${t( `src="${url}${addContentAccessQuery(url.includes('?'))}"`); + .replace(/src="(api\/[^"]+)"/g, (m, url) => `src="../${url}${addContentAccessQuery(url.includes('?'))}"`); %> <%- content %> <% } %>