From 3f0aa7a01ec9b6553d4e51e634320c9e112d59a3 Mon Sep 17 00:00:00 2001 From: Giteabot Date: Tue, 13 Oct 2026 23:43:12 -0700 Subject: [PATCH] fix(markup): restore code copy newline strip and fix copying rendered blocks (#39755) (#39765) Backport #39755 by @silverwind 1. Fix JS error when copying Mermaid and Math block sources, regression from https://github.com/go-gitea/gitea/pull/39718. 1. Restore the newline trim which is consistent with the majority of forges and markdown renderers as per https://github.com/go-gitea/gitea/pull/39751#issuecomment-6129002625 and my strong preference. This is the minimal fixes to fix the bug and restore the existing behaviour, more discussions and followups can be had in https://github.com/go-gitea/gitea/pull/39751. Co-authored-by: silverwind --- tests/e2e/mermaid.test.ts | 4 ++++ web_src/js/markup/codecopy.ts | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/e2e/mermaid.test.ts b/tests/e2e/mermaid.test.ts index 1523577eaa7..335220de36a 100644 --- a/tests/e2e/mermaid.test.ts +++ b/tests/e2e/mermaid.test.ts @@ -13,5 +13,9 @@ test('mermaid diagram in issue', async ({page, request}) => { const svg = page.frameLocator('iframe.markup-content-iframe').locator('svg'); await expect(svg).toContainText(/Alpha[\s\S]*Beta[\s\S]*Gamma/); + await svg.hover(); + await page.locator('.code-copy').click(); + await expect.poll(() => page.evaluate(() => navigator.clipboard.readText())).toBe('flowchart LR\n Alpha --> Beta\n Beta --> Gamma'); + await assertNoJsError(page); }); diff --git a/web_src/js/markup/codecopy.ts b/web_src/js/markup/codecopy.ts index 3e373f62a22..00e6306cdc8 100644 --- a/web_src/js/markup/codecopy.ts +++ b/web_src/js/markup/codecopy.ts @@ -1,5 +1,6 @@ import {svg} from '../svg.ts'; -import {createElementFromAttrs, generateElemId, queryElems} from '../utils/dom.ts'; +import {createElementFromAttrs, queryElems} from '../utils/dom.ts'; +import {copyToClipboardWithFeedback} from '../modules/clipboard.ts'; export function makeCodeCopyButton(attrs: Record = {}): HTMLButtonElement { const btn = createElementFromAttrs('button', { @@ -14,9 +15,9 @@ export function makeCodeCopyButton(attrs: Record = {}): HTMLButt export function initMarkupCodeCopy(elMarkup: HTMLElement): void { queryElems(elMarkup, '.code-block code', (el) => { // the code block's content can change (e.g.: debian package page: select different distributions), - // so use "data-clipboard-target" to copy the target's textContent, also always respect the content's end of block newline. - if (!el.getAttribute('id')) el.setAttribute('id', generateElemId('_code_block_')); - const btn = makeCodeCopyButton({'data-clipboard-target': `#${CSS.escape(el.getAttribute('id')!)}`}); + // so read it on click, which also survives math and mermaid replacing the block + const btn = makeCodeCopyButton(); + btn.addEventListener('click', () => copyToClipboardWithFeedback(btn, el.textContent.replace(/\r?\n$/, ''))); // we only want to use `.code-block-container` if it exists, no matter `.code-block` exists or not. const btnContainer = el.closest('.code-block-container') ?? el.closest('.code-block')!; btnContainer.append(btn);