"""Shared utilities for novoyuuparosk-auto-wiki pipelines."""
import html
import os
import re
import subprocess
from urllib.parse import urlparse
import mwclient
AUTO_BANNER_PREFIX = "{{Auto-generated"
# A ```columns fenced block is passed through Pandoc verbatim as
#
…
; columns within it are separated by a line of ===.
_COLUMNS_BLOCK_RE = re.compile(r'(.*?)
', re.DOTALL)
_COLUMN_SEP_RE = re.compile(r"^\s*===\s*$", re.MULTILINE)
def strip_first_h1(text: str) -> str:
"""Remove the first '# Heading' line and any immediately following blank line."""
lines = text.split("\n")
for i, line in enumerate(lines):
if line.strip().startswith("# "):
del lines[i]
if i < len(lines) and lines[i].strip() == "":
del lines[i]
break
return "\n".join(lines)
def expand_columns(wikitext: str) -> str:
"""Expand ```columns fenced blocks into a flex row of columns.
Authors write a fenced code block tagged ``columns``; Pandoc passes its body
through verbatim as ``…
`` (line breaks and blank
lines preserved, inline markup entity-escaped). Columns within the block are
separated by a line containing only ``===``. Each column is wrapped in
so its line breaks survive MediaWiki parsing, and content is
HTML-unescaped so inline markup written in the fence (e.g. …) renders
rather than appearing as literal text.
"""
def render(match: re.Match) -> str:
body = html.unescape(match.group(1))
columns = _COLUMN_SEP_RE.split(body)
poems = "".join("\n" + col.strip("\n") + "\n" for col in columns)
return '' + poems + "
"
return _COLUMNS_BLOCK_RE.sub(render, wikitext)
def markdown_to_wikitext(body: str) -> str:
result = subprocess.run(
["pandoc", "-f", "markdown", "-t", "mediawiki"],
input=body,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError(f"pandoc failed: {result.stderr.strip()}")
return expand_columns(result.stdout)
def connect_wiki() -> mwclient.Site:
api_url = os.environ["WIKI_API_URL"]
parsed = urlparse(api_url)
host = parsed.netloc
path = parsed.path[: parsed.path.rfind("/") + 1] or "/"
site = mwclient.Site(host, path=path, scheme=parsed.scheme)
site.login(os.environ["WIKI_BOT_USER"], os.environ["WIKI_BOT_PASSWORD"])
return site