Z31738

{
    "Z1K1": "Z2",
    "Z2K1": {
        "Z1K1": "Z6",
        "Z6K1": "Z31738"
    },
    "Z2K2": {
        "Z1K1": "Z14",
        "Z14K1": "Z31729",
        "Z14K3": {
            "Z1K1": "Z16",
            "Z16K1": "Z610",
            "Z16K2": "def Z31729(Z31729K1):\n    from re import match, search, sub, finditer, IGNORECASE\n    from html.parser import HTMLParser\n    content = Z31729K1.Z89K1.strip()\n    \n    def _has_root_centering(attrs_dict):\n        # Check root element's attributes for centering indicators using dict\n        if not attrs_dict:\n            return False\n        # Check align attribute\n        align = attrs_dict.get('align', *)\n        if align and align.lower() == 'center':\n            return True\n        class_attr = attrs_dict.get('class', *)\n        # Check if the 'center' class is present, which is used on many Wikimedia wikis\n        if class_attr and 'center' in class_attr.lower().split():\n            return True\n        style = attrs_dict.get('style', *)\n        if style:\n            style_clean = sub(r'\\s*:\\s*', ':', style)\n            style_clean = sub(r'\\s*;\\s*', ';', style_clean)\n            if search(r'text-align:center[;\\s]|text-align:center$', style_clean.lower()):\n                return True\n        return False\n    \n    def _has_margin_auto_centering(attrs_dict):\n        # For tags that need margin:auto, check if they already have centering\n        if not attrs_dict:\n            return False\n        align = attrs_dict.get('align', *)\n        if align and align.lower() == 'center':\n            return True\n        class_attr = attrs_dict.get('class', *)\n        if class_attr and 'center' in class_attr.lower().split():\n            return True\n        style = attrs_dict.get('style', *)\n        if style:\n            style_lower = style.lower()\n            # Check for margin:auto\n            if 'margin:auto' in style_lower or 'margin: 0 auto' in style_lower:\n                return True\n        return False\n    \n    def _parse_style(style_text):\n        styles = {}\n        for decl in style_text.split(';'):\n            if ':' in decl:\n                prop, val = decl.split(':', 1)\n                prop = prop.strip()\n                val = val.strip()\n                if prop and val:\n                    styles[prop] = val\n        return styles\n    \n    def _build_style_string(styles_dict):\n        if not styles_dict:\n            return *\n        return '; '.join(f\"{k}: {v}\" for k, v in styles_dict.items()) + ';'\n    \n    def _ensure_center_in_style(style_text):\n        if not style_text:\n            return 'text-align: center;'\n        # Remove any existing text-align rule\n        style_text = sub(r'text-align\\s*:\\s*[^;]+;?', *, style_text, flags=IGNORECASE)\n        out = f'{style_text}; text-align: center;'\n        if out.startswith('; '):\n            out = out.replace('; ', *, 1)\n        return out\n    \n    def _parse_attributes(attrs_text):\n        attrs = {}\n        if not attrs_text:\n            return attrs\n        pattern = r'([a-zA-Z][a-zA-Z0-9_-]*)\\s*=\\s*([\\'\"])(.*?)\\2'\n        for m in finditer(pattern, attrs_text, IGNORECASE):\n            name, _, value = m.groups()\n            attrs[name] = value.strip()\n        remaining = attrs_text\n        for m in finditer(pattern, attrs_text, IGNORECASE):\n            remaining = remaining.replace(m.group(0), *)\n        # Look for standalone attributes\n        bool_pattern = r'\\b([a-zA-Z][a-zA-Z0-9_-]*)\\b'\n        for m in finditer(bool_pattern, remaining):\n            name = m.group(1)\n            if name not in attrs:\n                attrs[name] = None\n        return attrs\n    \n    def _build_attributes_string(attrs_dict):\n        parts = []\n        for name, value in attrs_dict.items():\n            if value is None:\n                parts.append(name)\n            else:\n                # Use double quotes, escape any existing double quotes\n                escaped = value.replace('\"', '\u0026quot;')\n                parts.append(f'{name}=\"{escaped}\"')\n        return ' '.join(parts)\n    \n    def _needs_margin_auto(tag):\n        # These elements are not centered by text-align rules.\n        return tag.lower() in ('table', 'hr', 'img', 'object', 'canvas', 'iframe')\n    \n    def _center_element(tag, attrs_dict):\n        if _needs_margin_auto(tag):\n            styles = _parse_style(attrs_dict.get('style', *))\n            styles['margin'] = 'auto'\n            attrs_dict['style'] = _build_style_string(styles)\n        else:\n            style_text = attrs_dict.get('style', *)\n            attrs_dict['style'] = _ensure_center_in_style(style_text)\n        return attrs_dict\n    \n    class MarginAutoAdder(HTMLParser):\n        def __init__(self):\n            super().__init__()\n            self.output = []\n        \n        def handle_starttag(self, tag, attrs):\n            attrs_dict = dict(attrs)\n            if _needs_margin_auto(tag) and not _has_margin_auto_centering(attrs_dict):\n                styles = _parse_style(attrs_dict.get('style', *))\n                styles['margin'] = 'auto'\n                attrs_dict['style'] = _build_style_string(styles)\n            attr_str = _build_attributes_string(attrs_dict)\n            self.output.append(f'\u003C{tag}{\" \" + attr_str if attr_str else \"\"}\u003E')\n        \n        def handle_endtag(self, tag):\n            self.output.append(f'\u003C/{tag}\u003E')\n        \n        def handle_data(self, data):\n            self.output.append(data)\n        \n        def handle_startendtag(self, tag, attrs):\n            attrs_dict = dict(attrs)\n            if _needs_margin_auto(tag) and not _has_margin_auto_centering(attrs_dict):\n                styles = _parse_style(attrs_dict.get('style', *))\n                styles['margin'] = 'auto'\n                attrs_dict['style'] = _build_style_string(styles)\n            attr_str = _build_attributes_string(attrs_dict)\n            self.output.append(f'\u003C{tag}{\" \" + attr_str if attr_str else \"\"} /\u003E')\n    \n    class RootFinder(HTMLParser):\n        def __init__(self):\n            super().__init__()\n            self.root_tag = None\n            self.root_attrs = {}\n            self.inner_html = None\n            self.depth = 0\n            self.collect = False\n            self.collected_parts = []\n            self.is_single_root = True\n            self.seen_tags = set()\n            self.self_closed = False\n        def handle_starttag(self, tag, attrs):\n            self.depth += 1\n            if self.depth == 1:\n                self.root_tag = tag\n                self.root_attrs = dict(attrs)\n                self.collect = True\n                self.seen_tags.add(tag)\n            elif self.collect:\n                attr_dict = dict(attrs)\n                attr_str = _build_attributes_string(attr_dict)\n                self.collected_parts.append(f'\u003C{tag}{\" \" + attr_str if attr_str else \"\"}\u003E')\n        \n        def handle_endtag(self, tag):\n            self.depth -= 1\n            if self.depth == 0 and tag == self.root_tag:\n                self.inner_html = *.join(self.collected_parts)\n                self.collect = False\n            elif self.collect:\n                self.collected_parts.append(f'\u003C/{tag}\u003E')\n        \n        def handle_data(self, data):\n            if self.collect:\n                self.collected_parts.append(data)\n        \n        def handle_startendtag(self, tag, attrs):\n            if self.depth == 0 and self.root_tag is None:\n                self.root_tag = tag\n                self.root_attrs = dict(attrs)\n                self.inner_html = *\n                self.seen_tags.add(tag)\n                self.self_closed = True\n            elif self.collect:\n                attr_dict = dict(attrs)\n                attr_str = _build_attributes_string(attr_dict)\n                self.collected_parts.append(f'\u003C{tag}{\" \" + attr_str if attr_str else \"\"} /\u003E')\n    \n    hr_pattern = r'^\u003Chr(\\s+[^\u003E]*?)?/?\u003E$'\n    if match(hr_pattern, content, IGNORECASE):\n        hr_match = match(r'^\u003Chr(\\s+[^\u003E]*?)?/?\u003E$', content, IGNORECASE)\n        attrs_text = hr_match.group(1) or *\n        attrs = _parse_attributes(attrs_text)\n        styles = _parse_style(attrs.get('style', *))\n        styles['margin'] = 'auto'\n        attrs['style'] = _build_style_string(styles)\n        attr_str = _build_attributes_string(attrs)\n        out = f'\u003Chr{(\" \" + attr_str) if attr_str else \"\"} /\u003E'\n        return ZObject({\"Z1K1\": \"Z9\", \"Z9K1\": \"Z89\"}, Z89K1=out)\n    \n    finder = RootFinder()\n    finder.feed(content)\n    finder.close()\n\n    if finder.is_single_root and finder.root_tag and finder.inner_html is not None:\n        # First, process the inner HTML to add margin:auto to special tags\n        inner_processed = finder.inner_html\n        if inner_processed.strip():\n            parser = MarginAutoAdder()\n            parser.feed(inner_processed)\n            parser.close()\n            inner_processed = ''.join(parser.output)\n\n        # Then, handle the root element\n        root_attrs = finder.root_attrs.copy()\n        if not _has_root_centering(root_attrs):\n            root_attrs = _center_element(finder.root_tag, root_attrs)\n        attr_str = _build_attributes_string(root_attrs)\n        \n        if finder.self_closed:\n            result = f'\u003C{finder.root_tag}{\" \" + attr_str if attr_str else \"\"} /\u003E'\n        else:\n            result = f'\u003C{finder.root_tag}{\" \" + attr_str if attr_str else \"\"}\u003E{inner_processed}\u003C/{finder.root_tag}\u003E'\n        \n        return ZObject({\"Z1K1\": \"Z9\", \"Z9K1\": \"Z89\"}, Z89K1=result)\n    \n    return ZObject({\"Z1K1\": \"Z9\", \"Z9K1\": \"Z89\"}, Z89K1=content)"
        }
    },
    "Z2K3": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11",
            {
                "Z1K1": "Z11",
                "Z11K1": "Z1002",
                "Z11K2": "center HTML fragment, Python"
            }
        ]
    },
    "Z2K4": {
        "Z1K1": "Z32",
        "Z32K1": [
            "Z31"
        ]
    },
    "Z2K5": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11"
        ]
    }
}