Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a slate.js editor component that keeps its state in markdown

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?

like image 923
Michal Kurz Avatar asked Sep 01 '25 16:09

Michal Kurz


1 Answers

I'm not sure why you would absolutely want to store the editor state as Markdown, but this just cannot and will not work: you can't simply swap Slate internal state to something different than what it expects, its own object model, and expect it to work.

What you can do is to deserialize Markdown content into a Slate state object, feed that to the editor, let Slate do its thing while you edit and then serialize back to Markdown to do whatever you need to do with it, store it, send it, etc.

like image 104
Luc Heinrich Avatar answered Sep 04 '25 06:09

Luc Heinrich