mirror of
https://github.com/zadam/trilium.git
synced 2026-01-01 20:24:25 +01:00
feat(client/right_pane): jump to heading
This commit is contained in:
parent
b6506a9331
commit
64ca04ad07
@ -22,7 +22,7 @@ interface HeadingsWithNesting extends RawHeading {
|
||||
}
|
||||
|
||||
export interface HeadingContext {
|
||||
// scrollToHeading(heading: RawHeading): void;
|
||||
scrollToHeading(heading: RawHeading): void;
|
||||
headings: RawHeading[];
|
||||
}
|
||||
|
||||
@ -43,14 +43,11 @@ export default function TableOfContents() {
|
||||
|
||||
function PdfTableOfContents() {
|
||||
const data = useGetContextData("toc");
|
||||
console.log("Rendering with data", data);
|
||||
|
||||
return (
|
||||
<AbstractTableOfContents
|
||||
headings={data?.headings || []}
|
||||
scrollToHeading={heading => {
|
||||
|
||||
}}
|
||||
scrollToHeading={data?.scrollToHeading || (() => {})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import FBlob from "../../../entities/fblob";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import server from "../../../services/server";
|
||||
import { useViewModeConfig } from "../../collections/NoteList";
|
||||
import { useSetContextData, useTriliumOption } from "../../react/hooks";
|
||||
import { useTriliumOption } from "../../react/hooks";
|
||||
|
||||
const VARIABLE_WHITELIST = new Set([
|
||||
"root-background",
|
||||
@ -40,12 +40,22 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: {
|
||||
if (event.data.type === "pdfjs-viewer-toc") {
|
||||
if (event.data.data) {
|
||||
// Convert PDF outline to HeadingContext format
|
||||
const headings = convertPdfOutlineToHeadings(event.data.data);
|
||||
noteContext.setContextData("toc", {
|
||||
headings: convertPdfOutlineToHeadings(event.data.data)
|
||||
headings,
|
||||
scrollToHeading: (heading) => {
|
||||
iframeRef.current?.contentWindow?.postMessage({
|
||||
type: "trilium-scroll-to-heading",
|
||||
headingId: heading.id
|
||||
}, "*");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// No ToC available, use empty headings
|
||||
noteContext.setContextData("toc", { headings: [] });
|
||||
noteContext.setContextData("toc", {
|
||||
headings: [],
|
||||
scrollToHeading: () => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -135,25 +145,36 @@ function cssVarsToString(vars) {
|
||||
interface PdfOutlineItem {
|
||||
title: string;
|
||||
level: number;
|
||||
dest: any;
|
||||
dest: unknown;
|
||||
id: string;
|
||||
items: PdfOutlineItem[];
|
||||
}
|
||||
|
||||
function convertPdfOutlineToHeadings(outline: PdfOutlineItem[], parentLevel = 0) {
|
||||
const headings: any[] = [];
|
||||
interface PdfHeading {
|
||||
level: number;
|
||||
text: string;
|
||||
id: string;
|
||||
element: null;
|
||||
}
|
||||
|
||||
for (const item of outline) {
|
||||
headings.push({
|
||||
level: parentLevel + 1,
|
||||
text: item.title,
|
||||
id: `pdf-outline-${headings.length}`,
|
||||
element: null // PDFs don't have DOM elements
|
||||
});
|
||||
function convertPdfOutlineToHeadings(outline: PdfOutlineItem[]): PdfHeading[] {
|
||||
const headings: PdfHeading[] = [];
|
||||
|
||||
if (item.items && item.items.length > 0) {
|
||||
headings.push(...convertPdfOutlineToHeadings(item.items, parentLevel + 1));
|
||||
function flatten(items: PdfOutlineItem[]) {
|
||||
for (const item of items) {
|
||||
headings.push({
|
||||
level: item.level + 1,
|
||||
text: item.title,
|
||||
id: item.id,
|
||||
element: null // PDFs don't have DOM elements
|
||||
});
|
||||
|
||||
if (item.items && item.items.length > 0) {
|
||||
flatten(item.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flatten(outline);
|
||||
return headings;
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ async function main() {
|
||||
app.eventBus.on("documentloaded", () => {
|
||||
manageSave();
|
||||
extractAndSendToc();
|
||||
setupScrollToHeading();
|
||||
});
|
||||
await app.initializedPromise;
|
||||
};
|
||||
@ -91,27 +92,71 @@ async function extractAndSendToc() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert PDF.js outline format to a simpler structure
|
||||
const toc = convertOutlineToToc(outline);
|
||||
// Store outline items with their destinations for later scrolling
|
||||
const outlineMap = new Map();
|
||||
const toc = convertOutlineToToc(outline, 0, outlineMap);
|
||||
|
||||
// Store the map globally so setupScrollToHeading can access it
|
||||
(window as any).TRILIUM_OUTLINE_MAP = outlineMap;
|
||||
|
||||
window.parent.postMessage({
|
||||
type: "pdfjs-viewer-toc",
|
||||
data: toc
|
||||
}, "*");
|
||||
} catch (error) {
|
||||
window.parent.postMessage({
|
||||
type: "pdfjs-viewer-toc",
|
||||
data: null
|
||||
}, "*");
|
||||
}
|
||||
}
|
||||
|
||||
function convertOutlineToToc(outline: any[], level = 0): any[] {
|
||||
return outline.map(item => ({
|
||||
title: item.title,
|
||||
level: level,
|
||||
dest: item.dest,
|
||||
items: item.items && item.items.length > 0 ? convertOutlineToToc(item.items, level + 1) : []
|
||||
}));
|
||||
function convertOutlineToToc(outline: any[], level = 0, outlineMap?: Map<string, any>, parentId = ""): any[] {
|
||||
return outline.map((item, index) => {
|
||||
const id = parentId ? `${parentId}-${index}` : `pdf-outline-${index}`;
|
||||
|
||||
if (outlineMap) {
|
||||
outlineMap.set(id, item);
|
||||
}
|
||||
|
||||
return {
|
||||
title: item.title,
|
||||
level: level,
|
||||
dest: item.dest,
|
||||
id: id,
|
||||
items: item.items && item.items.length > 0 ? convertOutlineToToc(item.items, level + 1, outlineMap, id) : []
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
console.log("Custom script loaded");
|
||||
|
||||
function setupScrollToHeading() {
|
||||
window.addEventListener("message", async (event) => {
|
||||
if (event.data?.type === "trilium-scroll-to-heading") {
|
||||
const headingId = event.data.headingId;
|
||||
const outlineMap = (window as any).TRILIUM_OUTLINE_MAP as Map<string, any>;
|
||||
|
||||
if (!outlineMap) return;
|
||||
|
||||
const outlineItem = outlineMap.get(headingId);
|
||||
if (!outlineItem || !outlineItem.dest) return;
|
||||
|
||||
const app = window.PDFViewerApplication;
|
||||
|
||||
// Navigate to the destination
|
||||
try {
|
||||
const dest = typeof outlineItem.dest === 'string'
|
||||
? await app.pdfDocument.getDestination(outlineItem.dest)
|
||||
: outlineItem.dest;
|
||||
|
||||
if (dest) {
|
||||
app.pdfLinkService.goToDestination(dest);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error navigating to heading:", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user