## Implementation Plan **Files to modify and changes required:** ### 1. `devplacepy/rendering.py` – lines 141–162 (`_embed_url`) - After retrieving the matched URL, strip trailing punctuation characters from the end: - Use regex `[.,;:!?)\]}\'"]+$` to identify any trailing punctuation. - If a match is found, separate the cleaned URL and the trailing punctuation string. - In the returned HTML, place the cleaned URL inside the `` tag’s `href` and visible text, then append the trailing punctuation as plain text after the closing `` tag. - Also update `_TOKEN_RE` (line 66–69) to avoid changing the regex itself – the fix is applied during rendering, not during token matching. (The current pattern is correct for token extraction; the stripping step is handled downstream.) **Pseudocode for `_embed_url`:** ```python def _embed_url(url, display=None): # Strip trailing punctuation trail = "" match = re.search(r'[.,;:!?)\]}\'"]+$', url) if match: trail = match.group() url = url[:match.start()] escaped = html.escape(url) text = html.escape(display or url) return f'{text}{trail}' ``` ### 2. `devplacepy/static/js/ContentRenderer.js` – lines 161 and `processMedia()` / `urlToEmbed()` (line 243) - In the same function that creates `` tags from bare URLs, apply an identical stripping step before building the anchor. - Add a helper function (e.g., `_stripTrailingPunct(url)`) that returns `{cleaned, trail}` using the same regex `/[.,;:!?)\]}\'"]+$/`. - When constructing the anchor, place the cleaned URL in `href` and text content, then append `trail` as a text node (or string concatenation outside the `` element). **Example in `urlToEmbed()` (line 243):** ```javascript function urlToEmbed(matchedUrl) { const { cleaned, trail } = stripTrailingPunct(matchedUrl); return `${escapeHtml(cleaned)}${trail}`; } ``` ### 3. Add unit tests (at minimum for the server‑side change) - **File:** `tests/unit/rendering.py` - Add a test case that provides a string like `"See https://github.com/user/repo/pull/123."` and verifies the rendered HTML contains `...pull/123.` (period outside). - Also test other trailing punctuation: `,`, `!`, `?`, `)`. - For the client‑side, if a test harness exists (none cited), add a similar test to the existing suite or note that manual verification is acceptable given the proven pattern. ### 4. Remove or update prior unrelated changes (if any were left from earlier attempts) - Ensure no leftover schema or project_link code from attempts #150 persists. The fix is purely in rendering logic. --- ## Definition of Done - [ ] Both `_embed_url` and the client‑side URL renderer strip trailing punctuation from bare URLs, and the punctuation is placed outside the `` element. - [ ] A unit test exists in `tests/unit/rendering.py` that validates the server‑side fix for at least `.`, `,`, `!`, `?`, `)`. - [ ] The project’s test command passes with zero failures when run as: ```bash pip install -e '.[dev]' -q && python -m pytest tests/unit/ tests/api/devrant/rants.py ``` (Replace `{test_files}` with the actual paths; the full suite should pass, but at a minimum the rendering unit tests and the previously‑failing `test_rant_serialization_includes_project` must succeed.) - [ ] No regressions are introduced in the rendering of bare URLs without trailing punctuation, markdown links, or any other existing functionality. - [ ] Manual smoke test: In a running instance, post a comment ending with a bare URL and a period – the rendered link must point to the correct URL and the period must appear after the link, not inside it.