How to make Textblock element schema

I’m confused about how to define schema for a Textblock element. I have a document with a strictly defined schema in which many of the parts are singleton text blocks. These blocks are distinguished by their semantic meaning, not their format. I’ve been trying to represent them in the DOM as <p> blocks with the semantic type identified by an id attribute (e.g. <p id=“summary”>Some text</p>) and in the object model as Textblocks with text content and no child nodes. One example of a failed schema definition I’ve tried is this:

  summary: {
    isTextblock: true,
    parseDOM: [{tag: "#summary"}],
    toDOM(node) {
      return ["p", {id: "summary"}, [node.text, 0]]
    }
  },

I have not found any examples of this kind of element in the project sources. Much trial-and-error with the attributes and parseDOM/fromDOM in the schema hasn’t yielded any winning combination.

Any sage advice would be greatly appreciated.

Could it be that the problem is that you have a regular paragraph type, whose parseDOM matches p tags, defined earlier in the schema? If you set a priority of 100 on your parse rule, does it solve the problem?

I did have a <p> rule, but it’s after the one that’s failing. Changing the priority as you describe doesn’t change the behavior.

I think that the problem lies in my not knowing how to manage the “content hole”. The parseDOM() function isn’t reading the content of the tag in my template for the document. When the toDOM() function gets called it generates HTML like this

  

Can you advise about how to write the parseDOM so that it will load the text content of my Textblock?

Thank you very much for your help. ProseMirror seems to be an amazing tool, so I’m anxious to learn how to utilize it.

On the object side, the summary type shows up like this:

    Node$1
        attrs:Object
        childCount:(...)
        content:Fragment$2
            childCount:(...)
            content:Array[0]
                length:0
                __proto__:Array[0]
                firstChild:(...)
                lastChild:(...)
                size:0
            __proto__:Object
            firstChild:(...)
            isBlock:true
            isInline:(...)
            isLeaf:true
            isText:false
            isTextblock:false
            lastChild:(...)
            marks:Array[0]
            nodeSize:(...)
            textContent:(...)
            type:NodeType$1
            attrs:Object
            contentExpr:ContentExpr$1
                elements:Array[0]
                    inlineContent:false
                    isLeaf:(...)
                nodeType:NodeType$1
                __proto__:Object
            defaultAttrs:Object
            isBlock:true
            isInline:(...)
            isLeaf:(...)
            isText:false
            isTextblock:(...)
            name:"summary"
            schema:Schema$1
            spec:Object
            __proto__:Object
        __proto__:Object

The puzzling thing is that the isTextblock attribute shows up as false. The text content of the <p> element never seems to be captured by the associated node during parseDOM().

Once again, thank you for your help.

I may have been overcomplicating things. This schema seems to get me what I want:

  summary: {
    content: "text*",
    parseDOM: [{tag: "#summary"}],
    toDOM() {
      return ["p", {id: "summary"}, 0]
    }
  },

Does this look like a legitimate schema to use?

Yes, it looks like your toDOM was the problem, and your revised version looks better.

I’m sorry, but I was mistaken that the schema from my previous post gave the proper result. In fact the content gets wrapped in an extra “undefined” tag like this:

  

SUMMARY TEXT

This behavior seems specific to block elements, as I have a similar schema for an inline element

  tag: {
    content: "text?",
    parseDOM: [{tag: ".tag"}],
    toDOM() {
      return ["span", {class: "tag"} ,0]
    }
  },

and the span elements get rendered to the DOM as

  Tag1

with their content directly contained in the span tag.

For reference, the text schema used in both definitions is defined as

  text: {
      inline: true,
      text: true,
      toDOM(node) { return node.text }
  }

Is there some way that I can get text to be directly contained within a block type tag such as <p>?

That almost certainly means you are returning an array with undefined as first element somewhere in a toDOM method.