tags and HTML attributes).
"""
import re
from markupsafe import Markup, escape
from flask import url_for as flask_url_for
from database import User
# If plain text (no HTML block tags), convert newlines to HTML
if '' not in html and '
{p.replace(chr(10), "
")}
' for p in paragraphs if p.strip())
# Lekki markdown: **bold** → bold.
# Safe bo audyt (2026-04): tylko 1 wydarzenie używa `**` (świadomie, event #60).
# Działamy po wrappingu HTML, ale `**` nie występuje w tagach ani URL-ach, więc
# nie psuje innych treści. Nie rozszerzamy na *italic* / __bold__ / listy / linki,
# by nie zmieniać istniejącego wyglądu (vide #45 z `•` zamiast `-`).
html = re.sub(r'\*\*([^*\n]+)\*\*', r'\1', html)
# Build replacement maps — persons (all users with a name)
members = db.query(User.id, User.name).filter(
User.name.isnot(None),
).all()
members = sorted(members, key=lambda m: len(m.name), reverse=True)
# person_map: exact name → url
# person_fuzzy: list of (pattern, display_name, url) for declined Polish names
person_map = {}
person_fuzzy = []
for m in members:
if m.name in person_map:
continue
url = flask_url_for('public.user_profile', user_id=m.id)
person_map[m.name] = url
# Build fuzzy pattern for Polish name declensions: "Iwona Spaleniak" → "Iwon\w+ Spaleniak"
parts = m.name.split()
if len(parts) >= 2:
first = parts[0]
rest = ' '.join(parts[1:])
# Stem: keep at least 3 chars, cut last 1-2 chars depending on length
stem_len = max(3, len(first) - 2)
stem = re.escape(first[:stem_len])
fuzzy_pattern = r'\b' + stem + r'\w*\s+' + re.escape(rest) + r'\b'
person_fuzzy.append((fuzzy_pattern, m.name, url))
# Build replacement maps — companies
from database import Company
companies = db.query(Company.name, Company.slug).filter(
Company.slug.isnot(None),
Company.name.isnot(None),
Company.status == 'active',
).all()
companies = sorted(companies, key=lambda c: len(c.name), reverse=True)
# Skip company names that are common Polish/English words — too many false positives
_common_words = {'Portal', 'Joker', 'Wakat'}
company_map = {}
for c in companies:
if c.name in _common_words:
continue
company_map[c.name] = flask_url_for('public.company_detail_by_slug', slug=c.slug)
def enrich_text_node(text):
"""Apply person/company linking and URL linkification to a plain text fragment."""
# 1. Auto-link URLs
url_pattern = r'(https?://[^\s<>"\']+|(?"\']+|(?"\']*)'
def url_replacer(m):
url = m.group(0)
href = url if url.startswith('http') else 'https://' + url
return f'