Prohibiting document parts from merging

Our documents have exactly 6 parts that should always be there and not be deletable.

In version 0.5.1, I solved this by using a filter transform:

 onFilterTransform(transform) {
    let prohibited = false
    const docParts = ['title', 'metadatasubtitle', 'metadataauthors', 'metadataabstract',
        'metadatakeywords', 'documentcontents']
    let index = 0
    transform.doc.forEach(function(childNode){
        if (index > 5) {
            prohibited = true
        } else if (docParts[index] !== childNode.type.name) {
            prohibited = true
        }
        index++
    })
    if (index < 5) {
        prohibited = true
    }
    return prohibited
}

This worked well.

For version 0.6.0, I tried to adjust it slightly, making use of the childCount property of nodes:

onFilterTransform(transform) {
    let prohibited = false
    const docParts = ['title', 'metadatasubtitle', 'metadataauthors', 'metadataabstract',
        'metadatakeywords', 'documentcontents']
    if (transform.doc.childCount === 6) { // There should always be exactly 6 parts to the document
        let index = 0
        transform.doc.forEach(function(childNode){
            if (docParts[index] !== childNode.type.name) {
                prohibited = true
            }
            index++
        })
    } else {
        prohibited = true
    }
    return prohibited
} 

However, this doesn’t work anymore. If I try to select text from the title and into the document contents and hit “backspace”, it now throws a JS error of “Content can not be wrapped in ancestor title” (title can indeed only take text content), but visually the elements are merged on screen.

What’s the suggested workaround for this?

There is no good way to do this yet. Subscribe to #220 which should have some progress soon.

Ok, will wait for this then. We’ll just stick with version 0.5.1 for now.

@marijn: But should PM really throw an error and show an invalid document if the user tries two elements whose contents aren’t compatible? That seems like a bug to me.

Can you show me a document snippet (preferably using the built-in schema) + cursor position + command that causes the error?

@marijn: The default schema doesn’t seem to have just this. I’ll try with a basic sketch of the situation, elt me know if you need more details.

class Title extends Textblock {
    get contains() {
        return NodeKind.text
    }
}

Document structure:

<title>Some [title</title>
<paragraph>And this] is the first paragraph.<citation/></paragraph>

Where [ = start of selection and ] = end of selection.

User hits backspace, which causes title and paragraph to merge. A JS error is thrown, probably because the title cannot contain the inline citation node.

Opened #299 for this

And I’ve pushed a patch that fixes the issue.

@marijn Thanks! That patch also reenables the transform filter solution for our use case. This was the last issue I found with with the pre-0.6.0 version. It seems we can now do everything we could with version 0.5.1.