""" Automate OpenStreetMap wiki editing. """ import re from pathlib import Path from typing import Optional from map_machine.doc.collections import Collection from map_machine.map_configuration import MapConfiguration from map_machine.osm.osm_reader import Tags from map_machine.pictogram.icon import Icon, ShapeExtractor from map_machine.scheme import Scheme from map_machine.workspace import Workspace WORKSPACE: Workspace = Workspace(Path("temp")) SCHEME: Scheme = Scheme(WORKSPACE.DEFAULT_SCHEME_PATH) EXTRACTOR: ShapeExtractor = ShapeExtractor( WORKSPACE.ICONS_PATH, WORKSPACE.ICONS_CONFIG_PATH ) HEADER_PATTERN: re.Pattern = re.compile("==?=?.*==?=?") SEE_ALSO_HEADER_PATTERN: re.Pattern = re.compile("==\\s*See also\\s*==") EXAMPLE_HEADER_PATTERN: re.Pattern = re.compile("==\\s*Example.*==") RENDERING_HEADER_PATTERN: re.Pattern = re.compile( "===\\s*\\[\\[Röntgen]] icons\\s*===" ) class WikiTable: """SVG table with icon combinations.""" def __init__(self, collection: Collection, page_name: str): self.collection: Collection = collection self.page_name: str = page_name def generate_wiki_table(self) -> tuple[str, list[Icon]]: """ Generate Röntgen icon table for the OpenStreetMap wiki page. """ icons: list[Icon] = [] text: str = '{| class="wikitable"\n' if self.collection.column_key is not None: text += f"! {{{{Key|{self.collection.column_key}}}}}" else: text += "! Tag || Icon" if not self.collection.column_values: self.collection.column_values = [""] else: for column_value in self.collection.column_values: text += " ||" if column_value: text += ( f" {{{{vert header|{{{{TagValue|" f"{self.collection.column_key}|{column_value}}}}}}}}}" ) text += "\n" processed: set[str] = set() for row_value in self.collection.row_values: text += "|-\n" if row_value: text += f"| {{{{Tag|{self.collection.row_key}|{row_value}}}}}\n" else: text += "|\n" for column_value in self.collection.column_values: current_tags: Tags = dict(self.collection.tags) | { self.collection.row_key: row_value } if column_value: current_tags |= {self.collection.column_key: column_value} icon, _ = SCHEME.get_icon( EXTRACTOR, current_tags, processed, MapConfiguration() ) if not icon: print("Icon was not constructed.") text += ( "| " f"[[Image:Röntgen {icon.main_icon.get_name()}.svg|32px]]\n" ) icons.append(icon.main_icon) text += "|}\n" return text, icons def generate_new_text( old_text: str, table: WikiTable, ) -> tuple[Optional[str], list[Icon]]: """ Generate Röntgen icon table for the OpenStreetMap wiki page. :param old_text: previous wiki page text :param table: wiki table generator :return: new wiki page text """ wiki_text: str icons = [] if table.collection.row_key: wiki_text, icons = table.generate_wiki_table() else: processed = set() icon, _ = SCHEME.get_icon( EXTRACTOR, table.collection.tags, processed, MapConfiguration() ) if not icon.main_icon.is_default(): wiki_text = ( f"[[Image:Röntgen {icon.main_icon.get_name()}.svg|32px]]\n" ) icons.append(icon.main_icon) elif icon.extra_icons: wiki_text = ( f"Röntgen icon set has additional icon for the tag: " f"[[Image:Röntgen {icon.extra_icons[0].get_name()}.svg|32px]]." f"\n" ) icons.append(icon.extra_icons[0]) else: wiki_text = "" lines: list[str] = old_text.split("\n") start: Optional[int] = None end: int = -1 for index, line in enumerate(lines): if HEADER_PATTERN.match(line): if start is not None: end = index break if RENDERING_HEADER_PATTERN.match(line): start = index if start is not None: return ( "\n".join(lines[: start + 2]) + "\n" + wiki_text + "\n" + "\n".join(lines[end:]) ), icons example_header: Optional[int] = None for index, line in enumerate(lines): if EXAMPLE_HEADER_PATTERN.match(line) or SEE_ALSO_HEADER_PATTERN.match( line ): example_header = index break if example_header is not None: return ( "\n".join(lines[:example_header]) + "\n" + "== Rendering ==\n\n=== [[Röntgen]] icons ===\n\n" + wiki_text + "\n" + "\n".join(lines[example_header:]) ), icons return None, []