How to work with nodes hierarchically (newbie question)


#1

Hello,

I am trying to create a small editor that would parse a text file and depending on the start of the line would create three types of nodes ( chapters, articles and paragraphs).

If the node starts with Chapter … it will become a chapter if it starts with Article … it will become an article if it is neither a chapter or an article it will be a paragraph

All articles and paragraphs after a chapter will belong to the chapter (will be children of that chapter) All paragraphs after an article will belong to that article.

So a text like:

Chapter 1
Article 1
first paragraph
second paragraph
Article 2
first paragraph
Chapter 2
Article 3

will be structured like:

Chapter 1
     Article 1
         first paragraph
         second paragraph
     Article 2
         first paragraph
Chapter 2
     Article 3

For testing purposes I want to create a command that appends a node to the ‘current node’ (i.e. the node containing the $head ) and a command that inserts a child in the current node.

I am having trouble understanding how to do this.

I can get the node that is under the cursor but I’m not really sure how to insert a node inside or after the current node.

I can see that Transaction has an insert method that requires a position.

I have trouble understanding how to get the position after a given Node and how to get the position that would create a first child of a given Node.

Any suggestions are appreciated, thanks.


#2

Take a closer look at the ResolvedPos class (of which $head is an instance). It represents a point in the document tree, and allows relatively easy access to the stack of nodes that the point is inside of. From your description, you probably want something like $head.after() (the position after the node that the position is in).


#3

@marijn, thank you for the explanation.

After re reading the user guide, i finally understood that I was going the wrong way about it.

I was trying to use nodes as some kind of ‘pointers’ into the document and insert content after/before a node.

Now I understand that this is not conceptually possible since nodes are shared by various versions and can also appear in multiple places in a document and therefore cannot represent a document position.

As suggested using $to.after from the selection I now calculate a NodeSelection and with it I can ‘navigate’ to the appropriate position and insert content, after, before, inside… of the ‘selected’ node.

Thanks, again. Radu W.


#4

I actually did this too, except I accepted that as a small obstacle to account for, there are some ways to reliably calculate the changes into a multi-depth iterator. I just read the resolvedPos.path and extract it’s nodes and positions as a pointer to the position, then iterator through the tree structure and keep the position at the start of the lowest depth node. Of course this comes with problems. The greatest flaw is the lack of support for inline within the same depth as non-inline. Thus, I have came up with some very hacky solutions to continue to keep that code as stable as possible.