55from typing import TYPE_CHECKING
66from typing import Any
77
8- from django import template
8+ from django .template .base import FilterExpression
9+ from django .template .base import VariableDoesNotExist
910from django .template .context import Context
1011from django .utils .safestring import SafeString
1112from django .utils .safestring import mark_safe
@@ -55,18 +56,21 @@ def render_attrs(self, context: Context) -> SafeString:
5556 @classmethod
5657 def from_node (cls , node : BirdNode ) -> Params :
5758 return cls (
58- attrs = [Param . from_bit ( bit ) for bit in node .attrs ],
59+ attrs = [Param ( key , Value ( value )) for key , value in node .attrs . items () ],
5960 props = [],
6061 )
6162
6263
6364@dataclass
6465class Param :
6566 name : str
66- value : Value
67+ value : Value | str | bool
6768
6869 def render_attr (self , context : Context ) -> str :
69- value = self .value .resolve (context )
70+ if isinstance (self .value , Value ):
71+ value = self .value .resolve (context , is_attr = True )
72+ else :
73+ value = self .value
7074 if value is None :
7175 return ""
7276 name = self .name .replace ("_" , "-" )
@@ -75,47 +79,21 @@ def render_attr(self, context: Context) -> str:
7579 return f'{ name } ="{ value } "'
7680
7781 def render_prop (self , context : Context ) -> str | bool | None :
78- return self .value .resolve (context )
79-
80- @classmethod
81- def from_bit (cls , bit : str ) -> Param :
82- if "=" in bit :
83- name , raw_value = bit .split ("=" , 1 )
84- value = Value (raw_value .strip ())
85- else :
86- name , value = bit , Value (True )
87- return cls (name , value )
82+ return (
83+ self .value .resolve (context ) if isinstance (self .value , Value ) else self .value
84+ )
8885
8986
9087@dataclass
9188class Value :
92- raw : str | bool | None
93-
94- def resolve (self , context : Context | dict [str , Any ]) -> Any :
95- match (self .raw , self .is_quoted ):
96- case (None , _):
97- return None
98-
99- case (str (raw_str ), False ) if raw_str == "False" :
100- return None
101- case (str (raw_str ), False ) if raw_str == "True" :
102- return True
103-
104- case (bool (b ), _):
105- return b if b else None
106-
107- case (str (raw_str ), False ):
108- try :
109- return template .Variable (raw_str ).resolve (context )
110- except template .VariableDoesNotExist :
111- return raw_str
112-
113- case (_, True ):
114- return str (self .raw )[1 :- 1 ]
115-
116- @property
117- def is_quoted (self ) -> bool :
118- if self .raw is None or isinstance (self .raw , bool ):
119- return False
120-
121- return self .raw .startswith (("'" , '"' )) and self .raw .endswith (self .raw [0 ])
89+ raw : FilterExpression
90+
91+ def resolve (self , context : Context | dict [str , Any ], is_attr = False ) -> Any :
92+ if is_attr and self .raw .token == "False" :
93+ return None
94+ if self .raw .is_var :
95+ try :
96+ self .raw .var .resolve (context )
97+ except VariableDoesNotExist :
98+ return self .raw .token
99+ return self .raw .resolve (context )
0 commit comments