Allow \n in text nodes

I’m trying to set up my schema so that \ns are allowed in regular text nodes (not via hardbreak, just regular \n characters). I tried setting :whitespace and :code to true (both and individually), and when I insert a \n it is rendered, but then when I type another character, the next transaction removes it and replaces it with a space.

Is this removing-after-the-fact behavior controlled via parseDom.preserveWhitespace “full”? If so, how can I apply this strategy to regular text nodes (without a tag?). If not, how else can ProseMirror be configured not to replace \ns?

Many thanks!

You’ll want to set preserveWhiteSpace in the parse rule of the parent node of these text nodes that you want to allow newlines in.

Ah, that makes sense, thank you!

This still strips them, though, any idea what I might be doing wrong? (neither preserveWhiteSpace nor preserveWhitespace work for me). I also tried :tag “*” and a few other variations.

  "nodes": {
    "doc": {
      "content": "text*",
      "parseDOM": [{"preserveWhitespace": "full"}]
    "text": {"whitespace": "pre"}

The document doesn’t get parsed with a parse rule, so attaching parse rules to it (especially without a tag, which wouldn’t take effect even on another node) doesn’t work.

So I would need to wrap in a block node (eg a paragraph) and then add the parserule to that? would I have to double nest to be able to add a tag to the parserule?

Do you really want to allow line breaks in arbitrary paragraphs? Or is this about some specific part of your document structure. You definitely don’t want to add extra node types for this, but rather adjust the parse rules for the appropriate textblock node types.

this “document” actually represents flat text without actual paragraphs (think a comment on the side of a google doc – also other cases that are harder to explain)

it does have marks (b/i/u, links, etc.), hence prosemirror

Oh, right, I see what you mean now. But that should actually work (and does work, when I try it with code like below).

import {Schema} from "prosemirror-model"
import {EditorView} from "prosemirror-view"
import {EditorState} from "prosemirror-state"
import {exampleSetup} from "prosemirror-example-setup"

let schema = new Schema({
  nodes: {
    doc: {content: "text*", whitespace: "pre"},
    text: {}

let state = EditorState.create({
  doc: schema.node("doc", null, [schema.text("foo\nbar")]),
  plugins: exampleSetup({schema})

let view = new EditorView(document.body, {state})

That works! Thank you so much for the prompt support!