2022-08-28 17:49:49 +09:00
|
|
|
import {
|
|
|
|
$createParagraphNode,
|
|
|
|
$createTextNode,
|
|
|
|
$getRoot,
|
2022-09-07 17:03:54 +09:00
|
|
|
$isElementNode,
|
2022-08-28 17:49:49 +09:00
|
|
|
createEditor,
|
|
|
|
} from "lexical";
|
2022-09-07 00:47:55 +09:00
|
|
|
import { registerHistory, createEmptyHistoryState } from "@lexical/history";
|
2022-09-07 17:03:54 +09:00
|
|
|
import {
|
|
|
|
$createHeadingNode,
|
|
|
|
HeadingNode,
|
|
|
|
registerRichText,
|
|
|
|
} from "@lexical/rich-text";
|
2022-08-28 17:49:49 +09:00
|
|
|
import { onCleanup, onMount } from "solid-js";
|
2022-09-01 23:54:20 +09:00
|
|
|
import type Pages from "../../protocol/pages";
|
2022-08-23 09:49:34 +09:00
|
|
|
import "./editor.css";
|
|
|
|
|
2022-09-07 17:03:54 +09:00
|
|
|
const editor = createEditor({ nodes: [HeadingNode] });
|
2022-08-28 17:49:49 +09:00
|
|
|
|
|
|
|
function ref(el: HTMLElement) {
|
|
|
|
editor.setRootElement(el);
|
|
|
|
}
|
|
|
|
|
2022-08-24 12:49:02 +09:00
|
|
|
export default (props: {
|
2022-08-24 09:50:35 +09:00
|
|
|
id: number;
|
2022-08-28 17:49:49 +09:00
|
|
|
title: string;
|
|
|
|
text: string;
|
2022-08-24 12:49:02 +09:00
|
|
|
onUpdatePage: (content: Pages.RequestContentPage) => void;
|
2022-08-28 17:49:49 +09:00
|
|
|
}) => {
|
|
|
|
const initialEditorState = () => {
|
|
|
|
const root = $getRoot();
|
2022-09-07 17:03:54 +09:00
|
|
|
for (const [i, text] of props.text.split("\n").entries()) {
|
|
|
|
const line = i === 0 ? $createHeadingNode("h2") : $createParagraphNode();
|
|
|
|
const indent = text.match(/^\s*/)?.[0]?.length ?? 0;
|
|
|
|
line.setIndent(indent);
|
|
|
|
line.append($createTextNode(text.slice(indent)));
|
|
|
|
root.append(line);
|
|
|
|
}
|
2022-08-28 17:49:49 +09:00
|
|
|
};
|
2022-09-07 17:03:54 +09:00
|
|
|
onCleanup(registerRichText(editor, initialEditorState));
|
2022-09-07 00:47:55 +09:00
|
|
|
onCleanup(registerHistory(editor, createEmptyHistoryState(), 333));
|
2022-09-07 17:03:54 +09:00
|
|
|
onCleanup(
|
|
|
|
editor.registerUpdateListener(() =>
|
|
|
|
editor.update(() => {
|
|
|
|
const root = $getRoot();
|
2022-09-07 17:25:15 +09:00
|
|
|
const lines = root.getChildren().map((line, i) => {
|
|
|
|
if (i === 0) return line.getTextContent().trim();
|
|
|
|
const indent = $isElementNode(line) ? line.getIndent() : 0;
|
|
|
|
return `${" ".repeat(indent)}${line.getTextContent()}`;
|
|
|
|
});
|
2022-09-07 17:03:54 +09:00
|
|
|
const title = lines[0];
|
|
|
|
const text = lines.join("\n");
|
2022-08-28 17:49:49 +09:00
|
|
|
props.onUpdatePage({ id: props.id, title: title ?? "", text });
|
|
|
|
})
|
2022-09-07 17:03:54 +09:00
|
|
|
)
|
|
|
|
);
|
|
|
|
onMount(() => editor.focus());
|
2022-08-28 17:49:49 +09:00
|
|
|
return <article ref={ref} class="editor" contenteditable />;
|
|
|
|
};
|