I want to create a slate.js
-based editor component that keeps it's state in markdown. Slate.js docs keep repeating how simple serializing and deserializing state into md should be, but they don't provide an actual way to do it.
I tried achieving such editor with remark-slate-transformer
in a very straight-forward way , based on these two examples: remark-slate-transformer, slate:
import React, { useMemo, useState } from "react";
import { createEditor } from "slate";
import { Slate, Editable, withReact } from "slate-react";
import stringify from "remark-stringify";
import unified from "unified";
import markdownParser from "remark-parse";
import { remarkToSlate, slateToRemark } from "remark-slate-transformer";
import { withHistory } from "slate-history";
function markdown2slate(markdown) {
const processor = unified().use(markdownParser).use(remarkToSlate);
return processor.processSync(markdown).result;
}
function slate2markdown(slate) {
const processor = unified().use(slateToRemark).use(stringify);
const ast = processor.runSync({ type: "root", children: slate });
return processor.stringify(ast);
}
export const App = () => {
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
const [value, setValue] = useState("**initialText**");
const onChange = (newVal) => {
setValue(slate2markdown(newVal));
};
const editorValue = markdown2slate(value);
return (
<div className="wrapper">
<Slate editor={editor} value={editorValue} onChange={onChange}>
<Editable />
</Slate>
</div>
);
};
export default App;
sandbox here
But this doesn't work very well. I expect the initial text to appear in bold, but it doesn't. The cursor keeps jumping back to position 0 on every keystroke. Also, when I delete the string (value
becomes ''
), the editor breaks.
What is the correct, hassle-free way of making an editor component with state stored as markdown?