Conversion: Transform styles: When using regular expressions fix substitution groups not working

Fixes #1825764 [Problem with regex Pattern Matching in Transform Style](https://bugs.launchpad.net/calibre/+bug/1825764)
This commit is contained in:
Kovid Goyal 2019-04-28 14:11:58 +05:30
parent fda49f12d5
commit e99c7fd296
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -75,10 +75,13 @@ class StyleDeclaration(object):
dec._setSeq(seq) dec._setSeq(seq)
self.changed = True self.changed = True
def change_property(self, prop, parent_prop, val): def change_property(self, prop, parent_prop, val, match_pat=None):
if parent_prop is not None: if parent_prop is not None:
self.expand_property(parent_prop) self.expand_property(parent_prop)
if match_pat is None:
prop.value = val prop.value = val
else:
prop.value = match_pat.sub(val, prop.value)
self.changed = True self.changed = True
def append_properties(self, props): def append_properties(self, props):
@ -167,6 +170,7 @@ class Rule(object):
def __init__(self, property='color', match_type='*', query='', action='remove', action_data=''): def __init__(self, property='color', match_type='*', query='', action='remove', action_data=''):
self.property_name = property.lower() self.property_name = property.lower()
self.action, self.action_data = action, action_data self.action, self.action_data = action, action_data
self.match_pat = None
if self.action == 'append': if self.action == 'append':
decl = safe_parser().parseStyle(self.action_data) decl = safe_parser().parseStyle(self.action_data)
self.appended_properties = list(all_properties(decl)) self.appended_properties = list(all_properties(decl))
@ -179,11 +183,11 @@ class Rule(object):
elif match_type == '*': elif match_type == '*':
self.property_matches = lambda x: True self.property_matches = lambda x: True
elif 'matches' in match_type: elif 'matches' in match_type:
q = compile_pat(query) self.match_pat = compile_pat(query)
if match_type.startswith('not_'): if match_type.startswith('not_'):
self.property_matches = lambda x: q.match(x) is None self.property_matches = lambda x: self.match_pat.match(x) is None
else: else:
self.property_matches = lambda x: q.match(x) is not None self.property_matches = lambda x: self.match_pat.match(x) is not None
else: else:
value, unit = parse_css_length_or_number(query) value, unit = parse_css_length_or_number(query)
op = getattr(operator, operator_map[match_type]) op = getattr(operator, operator_map[match_type])
@ -197,7 +201,7 @@ class Rule(object):
if self.action == 'remove': if self.action == 'remove':
declaration.remove_property(prop, parent_prop) declaration.remove_property(prop, parent_prop)
elif self.action == 'change': elif self.action == 'change':
declaration.change_property(prop, parent_prop, self.action_data) declaration.change_property(prop, parent_prop, self.action_data, self.match_pat)
elif self.action == 'append': elif self.action == 'append':
declaration.append_properties(self.appended_properties) declaration.append_properties(self.appended_properties)
else: else:
@ -385,8 +389,15 @@ def test(return_tests=False): # {{{
def test_matching(self): def test_matching(self):
def m(match_type='*', query=''): def m(match_type='*', query='', action_data=''):
self.ae(apply_rule(css, property=prop, match_type=match_type, query=query), ecss) action = 'change' if action_data else 'remove'
self.ae(apply_rule(
css, property=prop, match_type=match_type, query=query, action=action, action_data=action_data
), ecss)
prop = 'font-size'
css, ecss = 'font-size: 1.2rem', 'font-size: 1.2em'
m('matches', query='(.+)rem', action_data=r'\1em')
prop = 'color' prop = 'color'
css, ecss = 'color: red; margin: 0', 'margin: 0' css, ecss = 'color: red; margin: 0', 'margin: 0'
@ -446,6 +457,7 @@ def test(return_tests=False): # {{{
m('line-height: 2', 'line-height: 1', '/', '2') m('line-height: 2', 'line-height: 1', '/', '2')
prop = 'border-top-width' prop = 'border-top-width'
m('border-width: 1', 'border-bottom-width: 1;\nborder-left-width: 1;\nborder-right-width: 1;\nborder-top-width: 3', '*', '3') m('border-width: 1', 'border-bottom-width: 1;\nborder-left-width: 1;\nborder-right-width: 1;\nborder-top-width: 3', '*', '3')
prop = 'font-size'
def test_export_import(self): def test_export_import(self):
rule = {'property':'a', 'match_type':'*', 'query':'some text', 'action':'remove', 'action_data':'color: red; a: b'} rule = {'property':'a', 'match_type':'*', 'query':'some text', 'action':'remove', 'action_data':'color: red; a: b'}