1212 Optional ,
1313 Any ,
1414 TypeVar ,
15- Type ,
1615 overload ,
1716 Union ,
1817)
@@ -33,8 +32,7 @@ class SyntaxTreeNode:
3332 """A Markdown syntax tree node.
3433
3534 A class that can be used to construct a tree representation of a linear
36- `markdown-it-py` token stream. Use `SyntaxTreeNode.from_tokens` to
37- initialize instead of the `__init__` method.
35+ `markdown-it-py` token stream.
3836
3937 Each node in the tree represents either:
4038 - root of the Markdown document
@@ -43,10 +41,12 @@ class SyntaxTreeNode:
4341 between
4442 """
4543
46- def __init__ (self ) -> None :
47- """Initialize a root node with no children.
44+ def __init__ (
45+ self , tokens : Sequence [Token ] = (), * , create_root : bool = True
46+ ) -> None :
47+ """Initialize a `SyntaxTreeNode` from a token stream.
4848
49- You probably need `SyntaxTreeNode.from_tokens` instead .
49+ If `create_root` is True, create a root node for the document .
5050 """
5151 # Only nodes representing an unnested token have self.token
5252 self .token : Optional [Token ] = None
@@ -61,6 +61,28 @@ def __init__(self) -> None:
6161 # children (i.e. inline or img)
6262 self ._children : list = []
6363
64+ if create_root :
65+ self ._set_children_from_tokens (tokens )
66+ return
67+
68+ if not tokens :
69+ raise ValueError (
70+ "Can only create root from empty token sequence."
71+ " Set `create_root=True`."
72+ )
73+ elif len (tokens ) == 1 :
74+ inline_token = tokens [0 ]
75+ if inline_token .nesting :
76+ raise ValueError (
77+ "Unequal nesting level at the start and end of token stream."
78+ )
79+ self .token = inline_token
80+ if inline_token .children :
81+ self ._set_children_from_tokens (inline_token .children )
82+ else :
83+ self .nester_tokens = _NesterTokens (tokens [0 ], tokens [- 1 ])
84+ self ._set_children_from_tokens (tokens [1 :- 1 ])
85+
6486 def __repr__ (self ) -> str :
6587 return f"{ type (self ).__name__ } ({ self .type } )"
6688
@@ -77,16 +99,6 @@ def __getitem__(
7799 ) -> Union [_NodeType , List [_NodeType ]]:
78100 return self .children [item ]
79101
80- @classmethod
81- def from_tokens (cls : Type [_NodeType ], tokens : Sequence [Token ]) -> _NodeType :
82- """Instantiate a `SyntaxTreeNode` from a token stream.
83-
84- This is the standard method for instantiating `SyntaxTreeNode`.
85- """
86- root = cls ()
87- root ._set_children_from_tokens (tokens )
88- return root
89-
90102 def to_tokens (self : _NodeType ) -> List [Token ]:
91103 """Recover the linear token stream."""
92104
@@ -186,23 +198,14 @@ def previous_sibling(self: _NodeType) -> Optional[_NodeType]:
186198 return self .siblings [self_index - 1 ]
187199 return None
188200
189- def _make_child (
190- self : _NodeType ,
191- * ,
192- token : Optional [Token ] = None ,
193- nester_tokens : Optional [_NesterTokens ] = None ,
194- ) -> _NodeType :
195- """Make and return a child node for `self`."""
196- if token and nester_tokens or not token and not nester_tokens :
197- raise ValueError ("must specify either `token` or `nester_tokens`" )
198- child = type (self )()
199- if token :
200- child .token = token
201- else :
202- child .nester_tokens = nester_tokens
201+ def _add_child (
202+ self ,
203+ tokens : Sequence [Token ],
204+ ) -> None :
205+ """Make a child node for `self`."""
206+ child = type (self )(tokens , create_root = False )
203207 child .parent = self
204208 self .children .append (child )
205- return child
206209
207210 def _set_children_from_tokens (self , tokens : Sequence [Token ]) -> None :
208211 """Convert the token stream to a tree structure and set the resulting
@@ -211,27 +214,22 @@ def _set_children_from_tokens(self, tokens: Sequence[Token]) -> None:
211214 while reversed_tokens :
212215 token = reversed_tokens .pop ()
213216
214- if token .nesting == 0 :
215- child = self ._make_child (token = token )
216- if token .children :
217- child ._set_children_from_tokens (token .children )
217+ if not token .nesting :
218+ self ._add_child ([token ])
218219 continue
219-
220- assert token . nesting == 1
220+ if token . nesting != 1 :
221+ raise ValueError ( "Invalid token nesting" )
221222
222223 nested_tokens = [token ]
223224 nesting = 1
224- while reversed_tokens and nesting != 0 :
225+ while reversed_tokens and nesting :
225226 token = reversed_tokens .pop ()
226227 nested_tokens .append (token )
227228 nesting += token .nesting
228- if nesting != 0 :
229+ if nesting :
229230 raise ValueError (f"unclosed tokens starting { nested_tokens [0 ]} " )
230231
231- child = self ._make_child (
232- nester_tokens = _NesterTokens (nested_tokens [0 ], nested_tokens [- 1 ])
233- )
234- child ._set_children_from_tokens (nested_tokens [1 :- 1 ])
232+ self ._add_child (nested_tokens )
235233
236234 def pretty (
237235 self , * , indent : int = 2 , show_text : bool = False , _current : int = 0
0 commit comments