fix: process dynamically added content via htmx (#10572)

When new content is added via JS and htmx is not used for this change,
htmx need to be informed that DOM changes happened and that it needs to
reprocess the DOM (or at least the changed parts).

When a diff is really large, it is hidden by default. The user can press
a button to load the diff, which then will be added via JS.
The diff contains buttons to expand it, which are using htmx behind the
scenes. Therefore a reprocessing via htmx needs to be triggered after
adding the large diff.

Fixes #10570

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10572
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-committed-by: Beowulf <beowulf@beocode.eu>
(cherry picked from commit 82624a2a8c)
This commit is contained in:
Beowulf 2025-12-29 20:54:49 +01:00 committed by forgejo-backport-action
parent 763547f43f
commit 30389f3f8a
3 changed files with 72 additions and 0 deletions

View file

@ -6,6 +6,7 @@ package e2e
import (
"fmt"
"os"
"strconv"
"strings"
"testing"
"time"
@ -144,6 +145,34 @@ body:
addCommitToBranch(t, user, repo, "test-branch", "test-branch", "test-README.md", commit2Sha,
readStringFile(t, "tests/e2e/declarative-repo/long-diff-test/3-README.md"))
}),
newRepo(t, 2, "huge-diff-test", nil, []FileChanges{{
Filename: "glossary.po",
Versions: []string{
func() string {
var sb strings.Builder
sb.Write([]byte("0"))
for i := 1; i < 2000; i++ {
sb.WriteString(strconv.Itoa(i))
sb.WriteByte('\n')
}
return sb.String()
}(),
},
}}, func(user *user_model.User, repo *repo_model.Repository) {
addCommitToBranch(t, user, repo, "main", "main-2", "glossary.po", "",
func() string {
var sb strings.Builder
sb.Write([]byte("0"))
for i := 1; i < 2000; i++ {
sb.WriteString(strconv.Itoa(i))
if i%12 == 0 {
sb.WriteString("Blub")
}
sb.WriteByte('\n')
}
return sb.String()
}())
}),
// add your repo declarations here
}

View file

@ -0,0 +1,41 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
// @watch start
// templates/repo/diff/**
// web_src/css/review.css
// web_src/js/features/repo-diff.js
// @watch end
import {expect} from '@playwright/test';
import {test} from './utils_e2e.ts';
test.use({user: 'user2'});
test('Expand Large diff', async ({page}) => {
let response = await page.goto('/user2/huge-diff-test/src/branch/main-2', {waitUntil: 'domcontentloaded'});
expect(response?.status()).toBe(200);
const commitUrl = await page.locator('.commit-summary a').getAttribute('href');
response = await page.goto(commitUrl, {waitUntil: 'domcontentloaded'});
expect(response?.status()).toBe(200);
const loadDiff = page.locator('.diff-load-button');
const expandDiff = page.locator('.code-expander-button');
const diffLines = page.locator('.file-body tbody > tr');
await expect(loadDiff).toBeVisible();
loadDiff.click();
await page.waitForLoadState('load');
await expect(expandDiff).toHaveCount(167);
await expect(diffLines).toHaveCount(1495);
await expandDiff.first().click();
await page.waitForLoadState('load');
await expect(expandDiff).toHaveCount(166);
await expect(diffLines).toHaveCount(1502);
});

View file

@ -1,4 +1,5 @@
import $ from 'jquery';
import htmx from 'htmx.org';
import {initCompReactionSelector} from './comp/ReactionSelector.js';
import {initRepoIssueContentHistory} from './repo-issue-content.js';
import {initDiffFileTree} from './repo-diff-filetree.js';
@ -151,6 +152,7 @@ function onShowMoreFiles() {
initViewedCheckboxListenerFor();
countAndUpdateViewedFiles();
initImageDiff();
htmx.process(document.body);
}
export async function loadMoreFiles(url) {