mirror of
https://github.com/zadam/trilium.git
synced 2025-12-20 14:24:27 +01:00
feat(toc): basic support for read-only text
This commit is contained in:
parent
41751c205c
commit
b93c80fe7b
@ -390,7 +390,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
|||||||
* If no content could be determined `null` is returned instead.
|
* If no content could be determined `null` is returned instead.
|
||||||
*/
|
*/
|
||||||
async getContentElement() {
|
async getContentElement() {
|
||||||
return this.timeout<JQuery<HTMLElement>>(
|
return this.timeout<JQuery<HTMLElement> | null>(
|
||||||
new Promise((resolve) =>
|
new Promise((resolve) =>
|
||||||
appContext.triggerCommand("executeWithContentElement", {
|
appContext.triggerCommand("executeWithContentElement", {
|
||||||
resolve,
|
resolve,
|
||||||
|
|||||||
@ -1115,3 +1115,19 @@ export function useTextEditor(noteContext: NoteContext | null | undefined) {
|
|||||||
|
|
||||||
return textEditor;
|
return textEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useContentElement(noteContext: NoteContext | null | undefined) {
|
||||||
|
const [ contentElement, setContentElement ] = useState<HTMLElement | null>(null);
|
||||||
|
const requestIdRef = useRef(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const requestId = ++requestIdRef.current;
|
||||||
|
noteContext?.getContentElement().then(contentElement => {
|
||||||
|
// Prevent stale async.
|
||||||
|
if (requestId !== requestIdRef.current) return;
|
||||||
|
setContentElement(contentElement?.[0] ?? null);
|
||||||
|
});
|
||||||
|
}, [ noteContext ]);
|
||||||
|
|
||||||
|
return contentElement;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import clsx from "clsx";
|
|||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
import { useActiveNoteContext, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks";
|
import { useActiveNoteContext, useContentElement, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks";
|
||||||
import Icon from "../react/Icon";
|
import Icon from "../react/Icon";
|
||||||
import RightPanelWidget from "./RightPanelWidget";
|
import RightPanelWidget from "./RightPanelWidget";
|
||||||
|
|
||||||
@ -27,7 +27,9 @@ export default function TableOfContents() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RightPanelWidget title={t("toc.table_of_contents")}>
|
<RightPanelWidget title={t("toc.table_of_contents")}>
|
||||||
{noteType === "text" && !isReadOnly && <EditableTextTableOfContents />}
|
{noteType === "text" && (
|
||||||
|
isReadOnly ? <ReadOnlyTextTableOfContents /> : <EditableTextTableOfContents />
|
||||||
|
)}
|
||||||
</RightPanelWidget>
|
</RightPanelWidget>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -159,3 +161,26 @@ function extractTocFromTextEditor(editor: CKTextEditor) {
|
|||||||
return headings;
|
return headings;
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
function ReadOnlyTextTableOfContents() {
|
||||||
|
const { noteContext } = useActiveNoteContext();
|
||||||
|
const contentEl = useContentElement(noteContext);
|
||||||
|
const headings = extractTocFromStaticHtml(contentEl);
|
||||||
|
|
||||||
|
return <AbstractTableOfContents headings={headings} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractTocFromStaticHtml(el: HTMLElement | null) {
|
||||||
|
if (!el) return [];
|
||||||
|
|
||||||
|
const headings: RawHeading[] = [];
|
||||||
|
for (const headingEl of el.querySelectorAll("h1,h2,h3,h4,h5,h6")) {
|
||||||
|
headings.push({
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
level: parseInt(headingEl.tagName.substring(1), 10),
|
||||||
|
text: headingEl.textContent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return headings;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user