1
1
from html .parser import HTMLParser as _HTMLParser
2
2
3
- from typing import List , Tuple , Any , Dict , Union , Optional , TypeVar , Generic , Callable
3
+ from typing import List , Tuple , Any , Dict , TypeVar , Generic , Callable
4
4
5
5
6
6
_R = TypeVar ("_R" , bound = Any ) # Var reference
@@ -41,18 +41,18 @@ def handle():
41
41
return idom.node("button", "Use" eventHandlers=events)
42
42
"""
43
43
44
- __slots__ = ("__current " ,)
44
+ __slots__ = ("_current " ,)
45
45
46
46
def __init__ (self , value : _R ) -> None :
47
- self .__current = value
47
+ self ._current = value
48
48
49
49
def set (self , new : _R ) -> _R :
50
- old = self .__current
51
- self .__current = new
50
+ old = self ._current
51
+ self ._current = new
52
52
return old
53
53
54
54
def get (self ) -> _R :
55
- return self .__current
55
+ return self ._current
56
56
57
57
def __eq__ (self , other : Any ) -> bool :
58
58
if isinstance (other , Var ):
@@ -64,38 +64,46 @@ def __repr__(self) -> str:
64
64
return "Var(%r)" % self .get ()
65
65
66
66
67
- _ModelOrStr = Union [Dict [str , Any ], str ]
68
- _ModelTransform = Callable [[_ModelOrStr ], None ]
67
+ _ModelTransform = Callable [[Dict [str , Any ]], Any ]
69
68
70
69
71
- def html_to_vdom (
72
- source : str , transform : Optional [_ModelTransform ] = None
73
- ) -> List [Dict [str , Any ]]:
70
+ def html_to_vdom (source : str , * transforms : _ModelTransform ) -> Dict [str , Any ]:
74
71
"""Transform HTML into a DOM model
75
72
76
73
Parameters:
77
74
source:
78
75
The raw HTML as a string
79
- transform :
80
- A function for transforming each model as it is created. For example,
81
- you might use a transform function to add highlighting to a ``<code/>``
82
- block.
76
+ transforms :
77
+ Functions of the form ``transform(old) -> new`` where ``old`` is a VDOM
78
+ dictionary which will be replaced by ``new``. You might use a transform
79
+ function to add highlighting to a ``<code/>`` block.
83
80
"""
84
- parser = HtmlParser (transform )
81
+ parser = HtmlParser ()
85
82
parser .feed (source )
86
- return parser .model ()
83
+ root = parser .model ()
84
+ to_visit = [root ]
85
+ while to_visit :
86
+ node = to_visit .pop (0 )
87
+ if isinstance (node , dict ) and "children" in node :
88
+ transformed = []
89
+ for child in node ["children" ]:
90
+ if isinstance (child , dict ):
91
+ for t in transforms :
92
+ child = t (child )
93
+ if child is not None :
94
+ transformed .append (child )
95
+ to_visit .append (child )
96
+ node ["children" ] = transformed
97
+ if "attributes" in node and not node ["attributes" ]:
98
+ del node ["attributes" ]
99
+ if "children" in node and not node ["children" ]:
100
+ del node ["children" ]
101
+ return root
87
102
88
103
89
104
class HtmlParser (_HTMLParser ):
90
- def __init__ (self , transform : Optional [_ModelTransform ] = None ):
91
- super ().__init__ ()
92
- if transform is not None :
93
- self ._transform = transform
94
-
95
- def model (self ) -> List [Dict [str , Any ]]:
96
- root : Dict [str , Any ] = self ._node_stack [0 ]
97
- root_children : List [Dict [str , Any ]] = root ["children" ]
98
- return root_children
105
+ def model (self ) -> Dict [str , Any ]:
106
+ return self ._node_stack [0 ]
99
107
100
108
def feed (self , data : str ) -> None :
101
109
self ._node_stack .append (self ._make_node ("div" , {}))
@@ -112,12 +120,7 @@ def handle_starttag(self, tag: str, attrs: List[Tuple[str, str]]) -> None:
112
120
self ._node_stack .append (new )
113
121
114
122
def handle_endtag (self , tag : str ) -> None :
115
- node = self ._node_stack .pop (- 1 )
116
- self ._transform (node )
117
- if not node ["attributes" ]:
118
- del node ["attributes" ]
119
- if not node ["children" ]:
120
- del node ["children" ]
123
+ del self ._node_stack [- 1 ]
121
124
122
125
def handle_data (self , data : str ) -> None :
123
126
self ._node_stack [- 1 ]["children" ].append (data )
@@ -134,7 +137,3 @@ def _make_node(tag: str, attrs: Dict[str, Any]) -> Dict[str, Any]:
134
137
style_dict [camel_case_key ] = v
135
138
attrs ["style" ] = style_dict
136
139
return {"tagName" : tag , "attributes" : attrs , "children" : []}
137
-
138
- @staticmethod
139
- def _transform (node : Dict [str , Any ]) -> None :
140
- ...
0 commit comments