mirror of
https://github.com/kou029w/quot.git
synced 2025-01-18 16:08:03 +00:00
rich text support (experimental)
This commit is contained in:
parent
23e6bf327b
commit
9af143f6ce
5 changed files with 50 additions and 28 deletions
|
@ -12,7 +12,7 @@ async function views(fastify: FastifyInstance) {
|
|||
},
|
||||
{
|
||||
bundle: true,
|
||||
minify: true,
|
||||
minify: process.env.NODE_ENV !== "development",
|
||||
entryPoints: [entryPoint],
|
||||
define: {
|
||||
"import.meta.env.QUOT_API_ENDPOINT": JSON.stringify(
|
||||
|
|
14
app/package-lock.json
generated
14
app/package-lock.json
generated
|
@ -11,7 +11,7 @@
|
|||
"@exampledev/new.css": "^1.1.3",
|
||||
"@fastify/http-proxy": "^8.2.2",
|
||||
"@lexical/history": "^0.4.1",
|
||||
"@lexical/plain-text": "^0.4.1",
|
||||
"@lexical/rich-text": "^0.4.1",
|
||||
"@tsconfig/node18-strictest-esm": "^1.0.1",
|
||||
"esbuild": "^0.15.7",
|
||||
"esbuild-register": "^3.3.3",
|
||||
|
@ -149,10 +149,10 @@
|
|||
"lexical": "0.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@lexical/plain-text": {
|
||||
"node_modules/@lexical/rich-text": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.4.1.tgz",
|
||||
"integrity": "sha512-cNFLXhOfR0coUFGA6aPGcHr6a+Y9ZrkETMM78+XV9J8iVsKij4/katFhsqACQDna4vSfXuqjTitCRtiFaDevDg==",
|
||||
"resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.4.1.tgz",
|
||||
"integrity": "sha512-EI4ul3y1hqMp0VS/4D8aOyR41ysz1KaYgkm6PyrRXEMyK8uKmVubJP83RkOU2fWkTVtdrMjM6aeT1qX849LetA==",
|
||||
"peerDependencies": {
|
||||
"@lexical/clipboard": "0.4.1",
|
||||
"@lexical/selection": "0.4.1",
|
||||
|
@ -1207,10 +1207,10 @@
|
|||
"@lexical/utils": "0.4.1"
|
||||
}
|
||||
},
|
||||
"@lexical/plain-text": {
|
||||
"@lexical/rich-text": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.4.1.tgz",
|
||||
"integrity": "sha512-cNFLXhOfR0coUFGA6aPGcHr6a+Y9ZrkETMM78+XV9J8iVsKij4/katFhsqACQDna4vSfXuqjTitCRtiFaDevDg==",
|
||||
"resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.4.1.tgz",
|
||||
"integrity": "sha512-EI4ul3y1hqMp0VS/4D8aOyR41ysz1KaYgkm6PyrRXEMyK8uKmVubJP83RkOU2fWkTVtdrMjM6aeT1qX849LetA==",
|
||||
"requires": {}
|
||||
},
|
||||
"@lexical/selection": {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"@exampledev/new.css": "^1.1.3",
|
||||
"@fastify/http-proxy": "^8.2.2",
|
||||
"@lexical/history": "^0.4.1",
|
||||
"@lexical/plain-text": "^0.4.1",
|
||||
"@lexical/rich-text": "^0.4.1",
|
||||
"@tsconfig/node18-strictest-esm": "^1.0.1",
|
||||
"esbuild": "^0.15.7",
|
||||
"esbuild-register": "^3.3.3",
|
||||
|
|
|
@ -8,3 +8,12 @@
|
|||
border-top-color: var(--nc-bg-3);
|
||||
box-shadow: 0 1px var(--nc-bg-3);
|
||||
}
|
||||
|
||||
.editor :is(h1, h2, h3, h4, h5, h6) {
|
||||
padding: unset;
|
||||
font-size: unset;
|
||||
}
|
||||
|
||||
.editor p {
|
||||
margin: unset;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
import {
|
||||
$createLineBreakNode,
|
||||
$createParagraphNode,
|
||||
$createTextNode,
|
||||
$getRoot,
|
||||
$isElementNode,
|
||||
createEditor,
|
||||
} from "lexical";
|
||||
import { registerHistory, createEmptyHistoryState } from "@lexical/history";
|
||||
import { registerPlainText } from "@lexical/plain-text";
|
||||
import {
|
||||
$createHeadingNode,
|
||||
HeadingNode,
|
||||
registerRichText,
|
||||
} from "@lexical/rich-text";
|
||||
import { onCleanup, onMount } from "solid-js";
|
||||
import type Pages from "../../protocol/pages";
|
||||
import "./editor.css";
|
||||
|
||||
const editor = createEditor();
|
||||
const editor = createEditor({ nodes: [HeadingNode] });
|
||||
|
||||
function ref(el: HTMLElement) {
|
||||
editor.setRootElement(el);
|
||||
|
@ -25,25 +29,34 @@ export default (props: {
|
|||
}) => {
|
||||
const initialEditorState = () => {
|
||||
const root = $getRoot();
|
||||
if (root.getFirstChild()) return;
|
||||
const paragraphNode = $createParagraphNode();
|
||||
const text = props.text
|
||||
.split("\n")
|
||||
.flatMap((line) => [$createTextNode(line), $createLineBreakNode()])
|
||||
.slice(0, -1);
|
||||
paragraphNode.append(...text);
|
||||
root.append(paragraphNode);
|
||||
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);
|
||||
}
|
||||
};
|
||||
onCleanup(registerPlainText(editor, initialEditorState));
|
||||
onCleanup(registerRichText(editor, initialEditorState));
|
||||
onCleanup(registerHistory(editor, createEmptyHistoryState(), 333));
|
||||
onMount(() => {
|
||||
onCleanup(
|
||||
editor.registerTextContentListener((text) => {
|
||||
const [title] = text.split("\n");
|
||||
onCleanup(
|
||||
editor.registerUpdateListener(() =>
|
||||
editor.update(() => {
|
||||
const root = $getRoot();
|
||||
const lines = root
|
||||
.getChildren()
|
||||
.map(
|
||||
(line) =>
|
||||
`${" ".repeat(
|
||||
$isElementNode(line) ? line.getIndent() : 0
|
||||
)}${line.getTextContent()}`
|
||||
);
|
||||
const title = lines[0];
|
||||
const text = lines.join("\n");
|
||||
props.onUpdatePage({ id: props.id, title: title ?? "", text });
|
||||
})
|
||||
);
|
||||
editor.focus();
|
||||
});
|
||||
)
|
||||
);
|
||||
onMount(() => editor.focus());
|
||||
return <article ref={ref} class="editor" contenteditable />;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue