feat(markdown): basic percentage-based scroll

This commit is contained in:
Elian Doran
2026-04-17 06:38:12 +03:00
parent 6d2496599f
commit 1ec270dba2

View File

@@ -1,9 +1,9 @@
import "./Markdown.css";
import DOMPurify from "dompurify";
import { Marked } from "marked";
import { useMemo, useState } from "preact/hooks";
import { useEffect, useMemo, useRef, useState } from "preact/hooks";
import { SanitizedHtml } from "../../react/RawHtml";
import SplitEditor from "../helpers/SplitEditor";
import { TypeWidgetProps } from "../type_widget";
@@ -11,14 +11,40 @@ const marked = new Marked({ breaks: true, gfm: true });
export default function Markdown(props: TypeWidgetProps) {
const [ content, setContent ] = useState("");
const html = useMemo(() => marked.parse(content) as string, [ content ]);
const html = useMemo(() => DOMPurify.sanitize(marked.parse(content) as string), [ content ]);
const previewRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const split = previewRef.current?.closest(".note-detail-split");
const preview = split?.querySelector<HTMLElement>(".note-detail-split-preview");
const editor = split?.querySelector<HTMLElement>(".cm-scroller");
if (!preview || !editor) return;
function onScroll() {
if (!preview || !editor) return;
const editorMax = editor.scrollHeight - editor.clientHeight;
const previewMax = preview.scrollHeight - preview.clientHeight;
if (editorMax <= 0 || previewMax <= 0) return;
preview.scrollTop = (editor.scrollTop / editorMax) * previewMax;
}
editor.addEventListener("scroll", onScroll, { passive: true });
return () => editor.removeEventListener("scroll", onScroll);
}, [ html ]);
return (
<SplitEditor
noteType="code"
{...props}
onContentChanged={setContent}
previewContent={<SanitizedHtml className="markdown-preview" html={html} />}
previewContent={(
<div
ref={previewRef}
className="markdown-preview"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: html }}
/>
)}
/>
);
}