How to wrap a node in a parent node

Excuse the noob q, but very new to PM. I have a scenario where I need to wrap a node in a parent and that parent should not be editable.

Whenever a user hits a shortcut, I need to wrap in a block containing parenthesis. The parenthesis should not be allowed to be removed.

like:

(this is my content)

which would equate to something like

<p><span>(</span>hello world<span>)</span></p>

I can obviously use CSS pseudo-selectors using ::before / ::after but would like to understand how to achieve this in PM.

Below is my nodeSpec for the schema and was hoping to be able to achieve this in toDOM. Currently, this will output:

<p class="parenthetical" s-type="parenthetical">hello world</p>

I need:

<p class="parenthetical" s-type="parenthetical"><span>(</span>hello world<span>)</span></p>

Current spec:

const element = 'p';
const type = 'parenthetical';

const nodeSpec = {
    parenthetical: {
        inline: false,
        group: 'block',
        marks: "_",
        content: 'text*',
        toDOM() {
            return [element, {class: type, 's-type': type}, 0]
        },
        parseDOM: [{
            tag: `${element}[${type}]`,
            getAttrs: dom => {
                return dom.getAttribute('s-type') === type;
            }
        }]
    }
}

export default nodeSpec;

I would strongly recommend using pseudo-selectors. You can do something like

return [element,
  ["span", {contenteditable: false}, "("],
  ["span", 0],
  ["span", {contenteditable: false}, ")"]]

but that will without a doubt cause you to run into all kinds of issues, since browsers don’t really handle this type of mixing of editable and uneditable content very well.

Thanks @marijn - that snippet is useful. Is there perhaps a way to wrap the 3 elements in a parent element?

The first first element in the outermost array would be a parent to the remaining three. Check out https://prosemirror.net/docs/ref/#model.DOMOutputSpec for more info.