@@ -103,6 +103,20 @@ def delete(property)
103
103
# @param [#to_s] property property name to be replaces
104
104
# @param [Hash<String => [String, Value]>] replacements hash with properties to replace with
105
105
#
106
+ # This function is used to expand and collapse css properties that has
107
+ # short and syntax like `border: 1px solid` is short for `border-width:
108
+ # 1p; border-type: solid;` or `border-width: 1p; border-top-style:
109
+ # solid;border-right-style: solid;border-bottom-style:
110
+ # solid;border-left-style: solid;`
111
+ #
112
+ # This function also respects the order the order the rules was written in. If we had the declaration like
113
+ # border-top-style:solid;
114
+ # border-right-style: solid;
115
+ # border-bottom-style: solid;
116
+ # border-left-style: solid;
117
+ # and want to replace "border-bottom-style" with "border-left-style: dashed;" border-left-style will still be "solid" because the rule that is last take presidency. If you replace "border-bottom-style" with "border-right-style: dashed;", "border-right-style" with be dashed
118
+ #
119
+ #
106
120
# @example
107
121
# declarations = Declarations.new('line-height' => '0.25px', 'font' => 'small-caps', 'font-size' => '12em')
108
122
# declarations.replace_declaration!('font', {'line-height' => '1px', 'font-variant' => 'small-caps', 'font-size' => '24px'})
@@ -112,59 +126,55 @@ def delete(property)
112
126
# {"line-height"=>#<CssParser::RuleSet::Declarations::Value:0x00000000038ac458 @important=false, @value="1px">,
113
127
# "font-variant"=>#<CssParser::RuleSet::Declarations::Value:0x00000000039b3ec8 @important=false, @value="small-caps">,
114
128
# "font-size"=>#<CssParser::RuleSet::Declarations::Value:0x00000000029c2c80 @important=false, @value="12em">}>
115
- def replace_declaration! ( property , replacements , preserve_importance : false )
116
- property = normalize_property ( property )
117
- raise ArgumentError , "property #{ property } does not exist" unless key? ( property )
129
+ def replace_declaration! ( replacing_property , replacements , preserve_importance : false )
130
+ replacing_property = normalize_property ( replacing_property )
131
+ raise ArgumentError , "property #{ replacing_property } does not exist" unless key? ( replacing_property )
118
132
119
133
replacement_declarations = self . class . new ( replacements )
120
134
121
135
if preserve_importance
122
- importance = get_value ( property ) . important
136
+ importance = get_value ( replacing_property ) . important
123
137
replacement_declarations . each_value { |value | value . important = importance }
124
138
end
125
139
126
- replacement_keys = declarations . keys
127
- replacement_values = declarations . values
128
- property_index = replacement_keys . index ( property )
129
-
130
- # We should preserve subsequent declarations of the same properties
131
- # and prior important ones if replacement one is not important
132
- replacements = replacement_declarations . each . with_object ( { } ) do |( key , replacement ) , result |
133
- existing = declarations [ key ]
134
-
135
- # No existing -> set
136
- unless existing
137
- result [ key ] = replacement
138
- next
140
+ # remove declarations where replacement is important but not current
141
+ each do |property , value |
142
+ if replacement_declarations [ property ] &.important && !value . important
143
+ delete ( property )
139
144
end
145
+ end
140
146
141
- # Replacement more important than existing -> replace
142
- if replacement . important && !existing . important
143
- result [ key ] = replacement
144
- replaced_index = replacement_keys . index ( key )
145
- replacement_keys . delete_at ( replaced_index )
146
- replacement_values . delete_at ( replaced_index )
147
- property_index -= 1 if replaced_index < property_index
148
- next
147
+ # remove replacement declarations where current is important but not replacement
148
+ replacement_declarations . each do |property , value |
149
+ if self [ property ] &.important && !value . important
150
+ replacement_declarations . delete ( property )
149
151
end
150
-
151
- # Existing is more important than replacement -> keep
152
- next if !replacement . important && existing . important
153
-
154
- # Existing and replacement importance are the same,
155
- # value which is declared later wins
156
- result [ key ] = replacement if property_index > replacement_keys . index ( key )
157
152
end
158
153
159
- return if replacements . empty?
160
-
161
- replacement_keys . delete_at ( property_index )
162
- replacement_keys . insert ( property_index , *replacements . keys )
154
+ propperties = declarations . keys
155
+ property_index = propperties . index ( replacing_property )
156
+ property_with_higher_precidence =
157
+ propperties [ ( property_index + 1 ) ..] . to_set
158
+ replacement_declarations . each do |property , _value |
159
+ if property_with_higher_precidence . member? ( property )
160
+ replacement_declarations . delete ( property )
161
+ else
162
+ delete ( property )
163
+ end
164
+ end
163
165
164
- replacement_values . delete_at ( property_index )
165
- replacement_values . insert ( property_index , *replacements . values )
166
+ new_declaration = [ ]
167
+ declarations . each do |property , value |
168
+ if property == replacing_property
169
+ replacement_declarations . each do |property , value |
170
+ new_declaration << [ property , value ]
171
+ end
172
+ else
173
+ new_declaration << [ property , value ]
174
+ end
175
+ end
166
176
167
- self . declarations = replacement_keys . zip ( replacement_values ) . to_h
177
+ self . declarations = new_declaration . to_h
168
178
end
169
179
170
180
def to_s ( options = { } )
0 commit comments