mirror of
https://github.com/zadam/trilium.git
synced 2026-01-01 20:24:25 +01:00
chore(pdf): process PDF outline
This commit is contained in:
parent
e36049cd43
commit
fd7222242a
@ -12,6 +12,7 @@ import server from "../services/server.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils from "../services/utils.js";
|
||||
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import type { HeadingContext } from "../widgets/sidebar/TableOfContents.js";
|
||||
import appContext, { type EventData, type EventListener } from "./app_context.js";
|
||||
import Component from "./component.js";
|
||||
|
||||
@ -22,6 +23,12 @@ export interface SetNoteOpts {
|
||||
|
||||
export type GetTextEditorCallback = (editor: CKTextEditor) => void;
|
||||
|
||||
export interface NoteContextDataMap {
|
||||
toc: HeadingContext;
|
||||
}
|
||||
|
||||
type ContextDataKey = keyof NoteContextDataMap;
|
||||
|
||||
class NoteContext extends Component implements EventListener<"entitiesReloaded"> {
|
||||
ntxId: string | null;
|
||||
hoistedNoteId: string;
|
||||
@ -469,8 +476,9 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
* @param key - Unique identifier for the data type (e.g., "toc", "pdfPages", "codeOutline")
|
||||
* @param value - The data to store (will be cleared when switching notes)
|
||||
*/
|
||||
setContextData<T>(key: string, value: T): void {
|
||||
setContextData<K extends ContextDataKey>(key: K, value: NoteContextDataMap[K]): void {
|
||||
this.contextData.set(key, value);
|
||||
console.trace("Set context data", key, value);
|
||||
// Trigger event so subscribers can react
|
||||
this.triggerEvent("contextDataChanged", {
|
||||
noteContext: this,
|
||||
@ -485,21 +493,21 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
* @param key - The data key to retrieve
|
||||
* @returns The stored data, or undefined if not found
|
||||
*/
|
||||
getContextData<T>(key: string): T | undefined {
|
||||
return this.contextData.get(key) as T | undefined;
|
||||
getContextData<K extends ContextDataKey>(key: K): NoteContextDataMap[K] | undefined {
|
||||
return this.contextData.get(key) as NoteContextDataMap[K] | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if context data exists for a given key.
|
||||
*/
|
||||
hasContextData(key: string): boolean {
|
||||
hasContextData(key: ContextDataKey): boolean {
|
||||
return this.contextData.has(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear specific context data.
|
||||
*/
|
||||
clearContextData(key: string): void {
|
||||
clearContextData(key: ContextDataKey): void {
|
||||
this.contextData.delete(key);
|
||||
this.triggerEvent("contextDataChanged", {
|
||||
noteContext: this,
|
||||
|
||||
@ -21,6 +21,11 @@ interface HeadingsWithNesting extends RawHeading {
|
||||
children: HeadingsWithNesting[];
|
||||
}
|
||||
|
||||
export interface HeadingContext {
|
||||
// scrollToHeading(heading: RawHeading): void;
|
||||
headings: RawHeading[];
|
||||
}
|
||||
|
||||
export default function TableOfContents() {
|
||||
const { note, noteContext } = useActiveNoteContext();
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
@ -38,6 +43,7 @@ export default function TableOfContents() {
|
||||
|
||||
function PdfTableOfContents() {
|
||||
const data = useGetContextData("toc");
|
||||
console.log("Rendering with data", data);
|
||||
|
||||
return (
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
|
||||
@ -39,10 +39,13 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: {
|
||||
|
||||
if (event.data.type === "pdfjs-viewer-toc") {
|
||||
if (event.data.data) {
|
||||
noteContext.setContextData("toc", event.data.data);
|
||||
// Convert PDF outline to HeadingContext format
|
||||
noteContext.setContextData("toc", {
|
||||
headings: convertPdfOutlineToHeadings(event.data.data)
|
||||
});
|
||||
} else {
|
||||
// No ToC available, fallback to note title
|
||||
noteContext.setContextData("toc", note.title);
|
||||
// No ToC available, use empty headings
|
||||
noteContext.setContextData("toc", { headings: [] });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,8 +63,6 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: {
|
||||
}
|
||||
}, [ blob ]);
|
||||
|
||||
// Initial ToC is set to note.title, will be replaced by actual ToC when received
|
||||
useSetContextData(noteContext, "toc", note.title);
|
||||
|
||||
return (historyConfig &&
|
||||
<iframe
|
||||
@ -130,3 +131,29 @@ function cssVarsToString(vars) {
|
||||
.map(([k, v]) => ` ${k}: ${v};`)
|
||||
.join('\n')}\n}`;
|
||||
}
|
||||
|
||||
interface PdfOutlineItem {
|
||||
title: string;
|
||||
level: number;
|
||||
dest: any;
|
||||
items: PdfOutlineItem[];
|
||||
}
|
||||
|
||||
function convertPdfOutlineToHeadings(outline: PdfOutlineItem[], parentLevel = 0) {
|
||||
const headings: any[] = [];
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
if (item.items && item.items.length > 0) {
|
||||
headings.push(...convertPdfOutlineToHeadings(item.items, parentLevel + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return headings;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user