# retoor <retoor@molodetz.nl>
from __future__ import annotations
import re
from markupsafe import Markup
CITATION = re.compile(r"\[\s*(\d+)\s*(?:-\s*(\d+)\s*)?\]")
SKIP_BLOCK = re.compile(
r"(<a\b[^>]*>.*?</a>|<code\b[^>]*>.*?</code>|<pre\b[^>]*>.*?</pre>)",
re.DOTALL | re.IGNORECASE,
)
def _linkify(text: str, source_count: int) -> str:
def replace(match: re.Match) -> str:
start = int(match.group(1))
end = int(match.group(2)) if match.group(2) else start
if end < start:
return match.group(0)
numbers = [n for n in range(start, end + 1) if 1 <= n <= source_count]
if not numbers:
return match.group(0)
return "".join(
f'<a class="ds-cite" href="#ds-source-{n}" data-cite="{n}">[{n}]</a>'
for n in numbers
)
return CITATION.sub(replace, text)
def link_citations(html, source_count: int) -> Markup:
if not html or source_count <= 0:
return Markup(html or "")
segments = SKIP_BLOCK.split(str(html))
rendered = [
segment if index % 2 == 1 else _linkify(segment, source_count)
for index, segment in enumerate(segments)
]
return Markup("".join(rendered))