Cannot lift a paragraph/inline content if depth <= 2

(this is a follow up of Split at paragraph boundaries leaves empty paragraphs before/after after I realized that split could not help for my purpose described below)

I’m trying to lift the selection as a higher node. That is, changing:

  • simpleAnswer
    • paragraph
      • textStart(selection)textEnd


  • simpleAnswer
    • paragraph
      • textStart
  • simpleAnswer
    • paragraph
      • (selection)
  • simpleAnswer
    • paragraph *textEnd


const fromPos = tr.doc.resolve(;
const toPos = tr.doc.resolve(;
const range = fromPos.blockRange(toPos);
if (range) {
  const depth = liftTarget(range);
  if (depth || depth === 0) {
    tr.lift(range, depth);

However targetLiftDepth is always undefined, I guess because, while the selection has a depth of 2, the range has a depth of 1 (apparently a decrement rule when the selection node has inline content). As a result I guess the lift is considered invalid as it would go below depth 1 (i.e. doc depth 0).

So i cannot devise the proper transform API to use to achieve my goal. I also tried to wrap the selection into a simpleAnswer, but this is interpreted as having a simpleAnswer inside the current one, which is not allowed by my schema.

That looks more like a split (with depth = 2) than a lift—lift moves content to a shallower parent node. This leaves it exactly as deep, if I understand your example correctly.

Yes I wan’t to keep it as deep. I just assumed (wrongly apparently) that lifting a paragraph selection would automatically put it in its own simpleAnswer (according to my schema).

Ok so this leads me back to my original issue on lifting, because lifting with depth 2* does insulate the selection in a paragraph in its own simpleAnswer but I cannot avoid splitting before/after the selection when the selection it at paragraph start/end because otherwise it would keep the text before/after in the same simpleAnswer. So the empty paragraph issue raises again (i.e. if I split from paragraph start the previous simpleAnswer will have an empty paragraph at its end, and conversely, see Split at paragraph boundaries leaves empty paragraphs before/after where you gave me the solution for split at depth 1).

*Sounds obvious when you know it, but there might be some misunderstanding when reading the docs about absolute depth (in document) dans relative depth (as parameters for perform some transformations). Both goes 0 to n, but not in the same direction, and this can be confusing for beginners. Maybe different terms should be employed to clarify things, such as “absolute depth” and “relative depth”. Just to let you know.

Thanks for this comment @Javarome . I was pulling my hair out trying to use split() thinking depth was an absolute number.