Documentation/Example for folding specific nodes

I’m trying to understand how I can create a foldEffect when I already know which SyntaxNodes I want to fold.

I found that I can iterate the tree:

  const view = editor;
  const from = 0;
  const to = editor.state.doc.length;
  
  let effects = [];
  syntaxTree(view.state).iterate({
      from, to,
      enter: (node) => {
        console.log(node.name, node);
        
        if(node.name == "Object") {
          const range = foldable(view.state, node.from, node.to)
          effects.push(foldEffect.of(range));
        }
      }
    })
  
  if (effects.length) view.dispatch({effects: effects})

but am unclear on what the effect needs to be (the above doesn’t work - it throws an exception and doesn’t fold anything).

image

Thanks!

I don’t think foldable means what you think it means. You pass it the start/end of a line and it will see if the registered fold services provide a foldable range for that line. If you know which range you want to fold, you should not be calling foldable, and definitely not with the extent of a syntax node, which probably does not precisely cover a line.

Thanks. Would you mind pointing me in the right direction?

My usecase is:

  • I have a JSON file that I’m displaying
  • I want to fold nodes initially to make it easier for users to navigate
  • simple example:
{
  "a": {
    "prop":"someValue"
  },
  "b": {
    "otherProp": 5
  },
  "c": 5
}

I’d like to fold all objects - that is, “a” and “b” in this example - after loading this text. “a” and “b” could have arbitrary depth and also arbitrary other child objects.

A folow-up question would be if I can pass additional metadata into SyntaxNodes to map them back to javascript objects - a goal would be that when a user clicks on a button related to “a”, I can focus the right line where “a” starts.

The approach would roughly be to use syntaxTree (or ensureSyntaxTree) to get the parse tree, iterate over it with its iterate method, and collect foldEffects to dispatch.

1 Like