fix: B2B classifieds submit + forum URL underscore handling
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Two user-reported regressions:

1. B2B classifieds "Dodaj ogłoszenie" button silently no-op'd. Hidden
   Quill description textarea had `required` attribute — browser blocked
   submit but cannot show validation UI on display:none fields. Removed
   `required`, added empty-content guard in submit handler with explicit
   alert.

2. Forum auto-linker truncated Google Maps URLs containing two
   underscores (e.g. forestry_office...g_ep=). Italic regex `_text_`
   matched across the URL, splitting it with <em> tags. Italic/bold
   underscore forms now require non-word boundary so URLs and identifiers
   like my_var_name pass through untouched.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-04-14 13:12:06 +02:00
parent 599e4bde83
commit 3372025458
3 changed files with 27 additions and 12 deletions

View File

@ -120,7 +120,7 @@
<div class="form-group"> <div class="form-group">
<label>Opis *</label> <label>Opis *</label>
<div id="quill-editor" class="quill-container"></div> <div id="quill-editor" class="quill-container"></div>
<textarea id="description" name="description" style="display:none;" required></textarea> <textarea id="description" name="description" style="display:none;"></textarea>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -185,9 +185,14 @@ var quill = new Quill('#quill-editor', {
}); });
quill.root.innerHTML = {{ classified.description|tojson }}; quill.root.innerHTML = {{ classified.description|tojson }};
document.querySelector('form').addEventListener('submit', function() { document.querySelector('form').addEventListener('submit', function(e) {
var html = quill.root.innerHTML; var html = quill.root.innerHTML;
if (html === '<p><br></p>') html = ''; if (html === '<p><br></p>' || quill.getText().trim() === '') {
e.preventDefault();
alert('Wpisz treść ogłoszenia.');
quill.focus();
return;
}
document.getElementById('description').value = html; document.getElementById('description').value = html;
}); });

View File

@ -319,7 +319,7 @@
<div class="form-group"> <div class="form-group">
<label>Opis *</label> <label>Opis *</label>
<div id="quill-editor" class="quill-container"></div> <div id="quill-editor" class="quill-container"></div>
<textarea id="description" name="description" style="display:none;" required></textarea> <textarea id="description" name="description" style="display:none;"></textarea>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -368,10 +368,17 @@ var quill = new Quill('#quill-editor', {
} }
}); });
// Sync Quill content to hidden textarea on form submit // Sync Quill content to hidden textarea on form submit + validate non-empty.
document.querySelector('form').addEventListener('submit', function() { // Note: hidden textarea cannot use `required` (browser cannot show validation
// UI on display:none fields, which silently blocks submit).
document.querySelector('form').addEventListener('submit', function(e) {
var html = quill.root.innerHTML; var html = quill.root.innerHTML;
if (html === '<p><br></p>') html = ''; if (html === '<p><br></p>' || quill.getText().trim() === '') {
e.preventDefault();
alert('Wpisz treść ogłoszenia.');
quill.focus();
return;
}
document.getElementById('description').value = html; document.getElementById('description').value = html;
}); });

View File

@ -56,13 +56,16 @@ def parse_forum_markdown(text, current_user_name=None):
# Inline code (`code`) # Inline code (`code`)
text = re.sub(r'`([^`]+)`', r'<code class="forum-code">\1</code>', text) text = re.sub(r'`([^`]+)`', r'<code class="forum-code">\1</code>', text)
# Bold (**text** or __text__) # Bold (**text** or __text__) — require non-word boundary on `_` form
# so URLs like `forestry_office` don't get partially bolded.
text = re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', text) text = re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', text)
text = re.sub(r'__([^_]+)__', r'<strong>\1</strong>', text) text = re.sub(r'(^|\W)__([^_\n]+?)__(?=\W|$)', r'\1<strong>\2</strong>', text)
# Italic (*text* or _text_) - careful not to match bold # Italic (*text* or _text_) — same boundary rule for `_` to avoid
text = re.sub(r'(?<!\*)\*([^*]+)\*(?!\*)', r'<em>\1</em>', text) # eating underscores inside URLs (e.g. ?g_ep=...) which corrupted forum
text = re.sub(r'(?<!_)_([^_]+)_(?!_)', r'<em>\1</em>', text) # links. The captured leading char is re-emitted.
text = re.sub(r'(?<!\*)\*([^*\n]+?)\*(?!\*)', r'<em>\1</em>', text)
text = re.sub(r'(^|\W)_(?!_)([^_\n]+?)_(?=\W|$)', r'\1<em>\2</em>', text)
# Links [text](url) - only allow http/https # Links [text](url) - only allow http/https
def safe_link(match): def safe_link(match):