From 8e8a39b832086ef6e8446e335579fda08cbf9a6e Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Thu, 16 Apr 2026 19:06:44 +0200 Subject: [PATCH] fix(note): linkify URLs in locked notes so markdown links stay clickable After #7004 made isLock actually disable markdown parsing, locked notes showed `[text](url)` as raw text. Pipe the locked-path content through RenderLinksPipe so URLs and markdown links remain clickable without re-enabling full markdown rendering. Fixes #7013 --- e2e/tests/notes/note-checklist-link.spec.ts | 57 +++++++++++++++++++ .../features/note/note/note.component.html | 7 ++- src/app/features/note/note/note.component.ts | 2 + 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 e2e/tests/notes/note-checklist-link.spec.ts diff --git a/e2e/tests/notes/note-checklist-link.spec.ts b/e2e/tests/notes/note-checklist-link.spec.ts new file mode 100644 index 0000000000..afa4adcc2f --- /dev/null +++ b/e2e/tests/notes/note-checklist-link.spec.ts @@ -0,0 +1,57 @@ +import { test, expect } from '../../fixtures/test.fixture'; + +test.describe('Issue #7013 — link in checklist in project note', () => { + test('unlocked note: link in checklist renders as tag', async ({ + page, + workViewPage, + notePage, + testPrefix, + }) => { + await workViewPage.waitForTaskList(); + + const unique = `${testPrefix}-7013`; + const noteContent = `- [ ] [${unique}-link](https://example.com)`; + + await notePage.addNote(noteContent); + + const note = page.locator('note', { hasText: `${unique}-link` }).first(); + await expect(note).toBeVisible(); + + const anchor = note.locator(`a:has-text("${unique}-link")`); + await expect(anchor).toBeVisible(); + const href = await anchor.getAttribute('href'); + expect(href).toContain('example.com'); + }); + + test('locked note: link in checklist still renders as tag', async ({ + page, + workViewPage, + notePage, + testPrefix, + }) => { + await workViewPage.waitForTaskList(); + + const unique = `${testPrefix}-7013-locked`; + const noteContent = `- [ ] [${unique}-link](https://example.com)`; + + await notePage.addNote(noteContent); + + const note = page.locator('note', { hasText: `${unique}-link` }).first(); + await expect(note).toBeVisible(); + + // Toggle lock via context menu ("Disable Markdown Parsing") + await note.hover(); + const menuBtn = note.locator('button:has(mat-icon:has-text("more_vert"))'); + await menuBtn.click(); + const lockBtn = page + .locator('.mat-mdc-menu-content button') + .filter({ has: page.locator('mat-icon:has-text("lock_open")') }); + await lockBtn.click(); + + // Locked path should still linkify URLs via RenderLinksPipe + const anchor = note.locator(`a:has-text("${unique}-link")`); + await expect(anchor).toBeVisible(); + const href = await anchor.getAttribute('href'); + expect(href).toContain('example.com'); + }); +}); diff --git a/src/app/features/note/note/note.component.html b/src/app/features/note/note/note.component.html index 6410df5ea6..d697c5c87c 100644 --- a/src/app/features/note/note/note.component.html +++ b/src/app/features/note/note/note.component.html @@ -18,9 +18,10 @@
- {{ isLongNote ? resolvedShortenedContent() : resolvedContent() }} -
+ [innerHTML]=" + (isLongNote ? resolvedShortenedContent() : resolvedContent()) | renderLinks + " + > } @else {