How do I define a Schema NodeSpec requiring a set number of elements within?

I’m still trying to wrap my head around the way Prosemirror is structured. Sorry if I’m going about this in completely the wrong manner.

I would like ProseMirror to recognize the structure that we have in our documents. They are currently represented as just two separate paragraph tags enclosed within a div with a special attribute and class.

In my HTML, I have a DOM structure like so:

<div data-label="property-label" class="orgProperty">
    <p>:Name:</p><p>Item 1</p>
</div>

In my schema definition, I defined the NodeSpec? like so:

org_property: {
      defining: true,
      priority: 60,
      content: "paragraph{2}",
      parseDOM: [{tag: 'div.orgProperty[data-label="property-label"]'}],
      toDOM() { return ["div", {"data-label": "property-label", "class": "orgProperty"}, 0] }
    }

Currently, when prosemirror parses this structure, it will turn the HTML it into the following:

<p>:Name:</p>
<p>Item</p>

It basically just strips out the enclosing div. I’m using the ProseMirror dino example as a starting point… My thought was that I needed to create a NodeSpec defining the enclosing div. The div will always have two paragraph tags within. Is there anything obvious that I’m doing incorrectly?

The code you pasted looks good, but it seems the parser isn’t matching that node type for some reason. Did you confirm that the schema you are using is the right one, and has that node type in it?

Here is a screenshot of the schema object right before the dino example creates the EditorView() instance.

I see org_property is in the listing of nodes. Is there something special that I need to check on the org_property NodeType?

The constant dinoSchema is used directly after my console.log(dinoSchema) line to create and assign window.view, so I’m pretty sure the EditorView() is using the same schema with the correct NodeType.

If it helps, here is a full code example of this issue I am facing:

You failed to specify a way in which the org_property node can actually be part of the document—it doesn’t appear in any content expression, and it’s not part of any group that does appear in content expressions.

Interesting… So just because I added a node to the schema doesn’t mean that it’s allowed within the document?

So it order for a org_property to appear, it must be in a content expression under another node in the schema or assigned a group which must also be used in another content expression?

Would it be correct to modify the doc node’s content expression to match a org_property node?

Yes, if the top level is the only place you want this to appear, doing something like "(block | org_property)+" in doc would work.

1 Like

I just encountered the same issue.

I tried the schema

new Schema({
  nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block")
    .append({org_property: {
      defining: true,
      priority: 60,
      content: "paragraph{2}",
      parseDOM: [{tag: 'div.orgProperty[data-label="property-label"]'}],
      toDOM() { return ["div", {"data-label": "property-label", "class": "orgProperty"}, 0] }
    }}),
  marks: schema.spec.marks,
  doc: {
    content: "(block | org_property)+"
  }
})

But the dom structure

<div data-label="property-label" class="orgProperty">
    <p>:Name:</p><p>Item 1</p>
</div>

is stilled parsed into

<p>:Name:</p>
<p>Item</p>

Your doc: {content: "(block | org_property)+"} text is just going to get ignored (doc doesn’t mean anything in a schema spec). You probably want to replace the doc node spec under nodes instead.

Oops. I am new to prosemirror. But I like it. Thank you.