1
+ import cobble
2
+
1
3
from ... import html_paths
2
4
from .tokeniser import TokenType
3
- from .token_parser import parse_identifier , parse_string , try_parse_class_name
5
+ from .token_parser import parse_identifier , parse_string
6
+
7
+
8
+ @cobble .data
9
+ class _AttributeOrClassName (object ):
10
+ name = cobble .field ()
11
+ value = cobble .field ()
12
+ append = cobble .field ()
4
13
5
14
6
15
def parse_html_path (tokens ):
@@ -12,51 +21,82 @@ def parse_html_path(tokens):
12
21
13
22
def _parse_html_path_elements (tokens ):
14
23
elements = []
15
-
24
+
16
25
if tokens .peek_token_type () == TokenType .IDENTIFIER :
17
26
elements .append (_parse_element (tokens ))
18
-
27
+
19
28
while tokens .try_skip_many (((TokenType .WHITESPACE , None ), (TokenType .SYMBOL , ">" ))):
20
29
tokens .skip (TokenType .WHITESPACE )
21
30
elements .append (_parse_element (tokens ))
22
-
31
+
23
32
return elements
24
33
25
34
26
35
def _parse_element (tokens ):
27
36
tag_names = _parse_tag_names (tokens )
28
- class_names = _parse_class_names (tokens )
37
+ attributes_list = _parse_attribute_or_class_names (tokens )
29
38
is_fresh = _parse_is_fresh (tokens )
30
39
separator = _parse_separator (tokens )
31
-
40
+
41
+ attributes = {}
42
+ for attribute in attributes_list :
43
+ if attribute .append and attributes .get (attribute .name ):
44
+ attributes [attribute .name ] += " " + attribute .value
45
+ else :
46
+ attributes [attribute .name ] = attribute .value
47
+
32
48
return html_paths .element (
33
49
tag_names ,
34
- class_names = class_names ,
50
+ attributes = attributes ,
35
51
fresh = is_fresh ,
36
52
separator = separator ,
37
53
)
38
54
39
55
40
56
def _parse_tag_names (tokens ):
41
57
tag_names = [parse_identifier (tokens )]
42
-
58
+
43
59
while tokens .try_skip (TokenType .SYMBOL , "|" ):
44
60
tag_names .append (parse_identifier (tokens ))
45
-
61
+
46
62
return tag_names
47
63
48
64
49
- def _parse_class_names (tokens ):
50
- class_names = []
51
-
65
+ def _parse_attribute_or_class_names (tokens ):
66
+ attribute_or_class_names = []
67
+
52
68
while True :
53
- class_name = try_parse_class_name (tokens )
54
- if class_name is None :
69
+ attribute_or_class_name = _try_parse_attribute_or_class_name (tokens )
70
+ if attribute_or_class_name is None :
55
71
break
56
72
else :
57
- class_names .append (class_name )
58
-
59
- return class_names
73
+ attribute_or_class_names .append (attribute_or_class_name )
74
+
75
+ return attribute_or_class_names
76
+
77
+
78
+ def _try_parse_attribute_or_class_name (tokens ):
79
+ if tokens .is_next (TokenType .SYMBOL , "[" ):
80
+ return _parse_attribute (tokens )
81
+ if tokens .is_next (TokenType .SYMBOL , "." ):
82
+ return _parse_class_name (tokens )
83
+ else :
84
+ return None
85
+
86
+
87
+ def _parse_attribute (tokens ):
88
+ tokens .skip (TokenType .SYMBOL , "[" )
89
+ name = parse_identifier (tokens )
90
+ tokens .skip (TokenType .SYMBOL , "=" )
91
+ value = parse_string (tokens )
92
+ tokens .skip (TokenType .SYMBOL , "]" )
93
+ return _AttributeOrClassName (name = name , value = value , append = False )
94
+
95
+
96
+ def _parse_class_name (tokens ):
97
+ tokens .skip (TokenType .SYMBOL , "." )
98
+ class_name = parse_identifier (tokens )
99
+ return _AttributeOrClassName (name = "class" , value = class_name , append = True )
60
100
61
101
62
102
def _parse_is_fresh (tokens ):
0 commit comments