File size: 3,249 Bytes
c4a298e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""Shared helpers for templateify services (daily + special events)."""
import logging
from typing import Callable, Dict, List

from bs4 import BeautifulSoup
from bs4.element import NavigableString, Tag

logger = logging.getLogger(__name__)


class TemplateifyHelpers:
    """Holds soup/tokens state and provides shared templateify operations."""

    def __init__(self, soup: BeautifulSoup) -> None:
        self.soup = soup
        self.tokens: List[Dict[str, str]] = []
        self._seen: set = set()

    def register(self, name: str, description: str) -> None:
        if name not in self._seen:
            self.tokens.append({"name": name, "description": description})
            self._seen.add(name)

    def set_text(self, selector: str, token: str, description: str) -> None:
        node = self.soup.select_one(selector)
        if not node:
            return
        node.clear()
        node.append(token)
        self.register(token, description)

    def set_attr(self, parent: Tag, selector: str, attr: str, token: str, description: str) -> None:
        node = parent.select_one(selector)
        if not node:
            return
        node[attr] = token
        self.register(token, description)

    def set_child_text(self, parent: Tag, selector: str, token: str, description: str) -> None:
        node = parent.select_one(selector)
        if not node:
            return
        node.clear()
        node.append(token)
        self.register(token, description)

    def loopify(self, selector: str, loop_name: str, transformer: Callable[[Tag], None], description: str) -> None:
        nodes = self.soup.select(selector)
        if not nodes:
            return
        template_node = nodes[0]
        for extra in nodes[1:]:
            extra.decompose()
        transformer(template_node)
        self.register(loop_name, description)

        # Determine which element to wrap (the node, or its parent anchor)
        if template_node.parent and template_node.parent.name == "a":
            target = template_node.parent
        else:
            target = template_node

        parent = target.parent
        if not parent:
            logger.warning(f"Template node {selector} has no parent, cannot wrap in loop")
            return
        try:
            idx = parent.index(target)
            parent.insert(idx, NavigableString(f"{{{{#{loop_name}}}}}"))
            parent.insert(idx + 2, NavigableString(f"{{{{/{loop_name}}}}}"))
        except ValueError:
            logger.warning(f"Could not find index for {selector}, node may have been moved")

    def wrap_images_in_anchors(self, header_alt: str = "Polygraph by Polymarket", footer_alt: str = "Polymarket", link_url: str = "https://poly.market/0d7VvzI") -> None:
        """Wrap header and footer logo images in anchor tags if not already linked."""
        for alt_text in (header_alt, footer_alt):
            for table in self.soup.find_all("table", role="presentation"):
                img = table.find("img", alt=alt_text)
                if img and not img.find_parent("a"):
                    link = self.soup.new_tag("a", href=link_url, target="_blank", rel="noopener noreferrer")
                    img.wrap(link)
                    break