import re from pathlib import Path class SvgColorParser: def __init__(self, filepath): self.filepath = Path(filepath) self.content = self.filepath.read_text(encoding="utf-8") self.colors = {} # tag -> hex self.history = [] # list of contents for undo self.redo_history = [] self._parse() def _parse(self): # Find the regardless of attribute order style_match = re.search(r']*?id="current-color-scheme"[^>]*>(.*?)', self.content, re.DOTALL) if style_match: style_content = style_match.group(1) # Find classes e.g. .ColorScheme-Text { color:#232629; } class_matches = re.finditer(r'\.(ColorScheme-[a-zA-Z0-9]+)\s*\{\s*color:\s*(#[a-fA-F0-9]{3,6})', style_content) self.colors = {m.group(1): m.group(2) for m in class_matches} def update_color(self, tag, new_hex): if tag not in self.colors: return old_hex = self.colors[tag] self.history.append(self.content) self.redo_history.clear() # Globally replace the exact hex string, case insensitive # We need to compile a regex for the old hex. hex_pattern = re.compile(re.escape(old_hex), re.IGNORECASE) self.content = hex_pattern.sub(new_hex, self.content) self.colors[tag] = new_hex self.save() self._parse() # re-parse to ensure consistency def save(self): self.filepath.write_text(self.content, encoding="utf-8") def undo(self): if self.history: self.redo_history.append(self.content) self.content = self.history.pop() self.save() self._parse() return True return False def redo(self): if self.redo_history: self.history.append(self.content) self.content = self.redo_history.pop() self.save() self._parse() return True return False