From 78ad0ae6f1d4659849e6b0b2d76d32c1958d2776 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Jan 2022 12:20:50 +0530 Subject: [PATCH] Edit book: Fix renaming of classes that start/end with non word characters not working --- src/calibre/ebooks/oeb/polish/css.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/calibre/ebooks/oeb/polish/css.py b/src/calibre/ebooks/oeb/polish/css.py index bdae002c33..386f962b23 100644 --- a/src/calibre/ebooks/oeb/polish/css.py +++ b/src/calibre/ebooks/oeb/polish/css.py @@ -502,12 +502,16 @@ def rename_class_in_rule_list(css_rules, old_name, new_name): # this regex will not match class names inside attribute value selectors # and it will match id selectors that contain .old_name but its the best # that can be done without implementing a full parser for CSS selectors - pat = re.compile(rf'(?<=\.){re.escape(old_name)}\b') + pat = re.compile(rf'(?<=\.){re.escape(old_name)}(?:\W|$)') + + def repl(m): + return m.group().replace(old_name, new_name) + changed = False for rule in css_rules: if rule.type == rule.STYLE_RULE: old = rule.selectorText - q = pat.sub(new_name, old) + q = pat.sub(repl, old) if q != old: changed = True rule.selectorText = q @@ -519,11 +523,15 @@ def rename_class_in_rule_list(css_rules, old_name, new_name): def rename_class_in_doc(container, root, old_name, new_name): changed = False - pat = re.compile(rf'\b{re.escape(old_name)}\b') + pat = re.compile(rf'(?:^|\W){re.escape(old_name)}(?:\W|$)') + + def repl(m): + return m.group().replace(old_name, new_name) + for elem in root.xpath('//*[@class]'): old = elem.get('class') if old: - new = pat.sub(new_name, old) + new = pat.sub(repl, old) if new != old: changed = True elem.set('class', new)