Problem with HTML headings parsing in parseDOM

Hello,

I’m trying to parse HTML headings with simple ProseMirror schema that should add attributes whenever specific heading is present.

Whenever I add

                {
                        tag: 'h2[class]',
                        getAttrs: d => {
                                const type = d.getAttribute('class');
                                return availableClasses.indexOf(type) > -1
                                        ? {
                                                        class: type
                                          }
                                        : false;
                        }
                },

to parseDOM the output is without proper heading level.

[
  {
    "type": "paragraph",
    "content": [
      {
        "type": "text",
        "marks": [
          {
            "type": "styled",
            "attrs": {
              "class": "headline2"
            }
          }
        ],
        "text": "Here text from heading"
      },
      {
        "type": "text",
        "text": "Here text from paragraph           "
      }
    ]
  }
]

but when it’s not present everything is parsed fine without attributes

[
  {
    "type": "heading",
    "attrs": {
      "level": 2
    },
    "content": [
      {
        "type": "text",
        "text": "Here text from heading"
      }
    ]
  },
  {
    "type": "paragraph",
    "content": [
      {
        "type": "text",
        "text": "Here text from paragraph"
      }
    ]
  }
]

What I need to have though is

[
  {
    "type": "heading",
    "attrs": {
      "level": 2
    },
    "content": [
      {
        "marks": [
          {
            "type": "styled",
            "attrs": {
              "class": "headline2"
            }
          }
        ],
        "type": "text",
        "text": "Here text from heading"
      }
    ]
  },
  {
    "type": "paragraph",
    "content": [
      {
        "type": "text",
        "text": "Here text from paragraph"
      }
    ]
  }
]

From docs ProseMirror Reference manual it looks like everything should be fine and this getAttrs only add custom attributes. I’m following example from ProseMirror dino example but in it I don’t see anything about HTML parsing.

Am I doing something wrong here?

My codepen can be found here

Any suggestion would help. Thanks in advance!

As described in the prosemirror reference docs, when getAttrs return false, the entire parse rule won’t match. Therefore prosemirror will go on to the next match. If you want to use the default attributes (body1 in your codepen), return null or undefined.

So, with your current code, when the class is present, your parse rule gets accepted. But it uses type: text because, by default, block nodes (like headings) do not allow any marks: https://prosemirror.net/docs/ref/#model.NodeSpec.marks

When the class is not present, your mark parse rule fails, and the highest node level that matches with it is heading, with attributes level 2 in the basic schema:

So my suggestion, since you want different behavior than the basic schema here, is just to copy the basic schema code, and modify the parse rules for the heading node to what you want. In this case, it seems you want to allow parsing the “styled” mark (which is what you named it in your code) for heading nodes.

heading: {
  attrs: {level: {default: 1}},
  marks: “styled” // or “_” if you want to allow all marks
  ...
}
1 Like

Good point. Thanks to your help I managed to get it working!