I’m new to ProseMirror, and trying to replace what is currently a form’s textarea with a ProseMirror editor. To get started, I’d like to read the contents of the existing textarea and initialize a ProseMirror editor. So I’d like to parse the plain text textContent of the textarea into a very bare schema (paragraph, inline text, and hard_break). Is there some existing code I should use / be aware of?
I looked into what happens / how it is parsed if simply pasting the plain text from the textarea, and it appears to be this code: prosemirror-view/clipboard.ts at facde1aea2ef79ba197e49ecab64a08a8bb14e12 · ProseMirror/prosemirror-view · GitHub — it turns each line break into a new paragraph, but I’d instead want a single line break to become a br (hard_break) and two line breaks (a blank line) to indicate a new paragraph. So this code would be need to be suitably modified and also used as clipboardTextParser or clipboardParser, correct? Or can this be achieved with some combination of existing code and options (preserveWhitespace: "full" ?)
For what it’s worth, I just went ahead and did the ad-hoc parsing, with the following code. Comments welcome, especially if I’m doing something wrong:
// Parse a string (the contents of the textarea) into a HTML element.
// Only recognizes blank lines as <p> separators, and line breaks as <br>.
function domFromText(text: string): HTMLDivElement {
const dom = document.createElement("div");
text.split(/(?:\r\n?|\n){2,}/).forEach(block => {
let p = dom.appendChild(document.createElement("p"));
if (block) {
block.split(/(?:\r\n?|\n)/).forEach(line => {
if (line) {
if (p.hasChildNodes()) p.appendChild(document.createElement('br'));
p.appendChild(document.createTextNode(line));
}
});
}
dom.appendChild(p);
});
return dom;
};
function fromText(text: string): Node {
const dom = domFromText(text);
return DOMParser.fromSchema(almostTrivialSchema).parse(dom, { preserveWhitespace: "full" });
}
// Create a new ProseMirror editor with the contents of the textarea, and hide the textarea.
const $textarea = document.querySelector('textarea')!;
const view = new EditorView(document.querySelector("#editor"), {
state: EditorState.create({
schema: almostTrivialSchema,
doc: fromText($textarea.textContent!),
plugins: plugins(almostTrivialSchema)
})
});
And for the other direction:
// Serialize the EditorState into a plain text string.
function toText(): string {
return view.state.doc.textBetween(
0, // from
view.state.doc.content.size, // to
"\n\n", // blockSeparator
"\n", // leafNode HACK: Figure out how to do this only for `hard_break` nodes and no other.
);
}