|
# 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))
|