[v13.0/forgejo] fix: use scrollHeight for rendered iframe if offsetHeight is unavailable (#9713)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/9508 Fixes #9421. Co-authored-by: Bojidar Marinov <bojidar.marinov.bg@gmail.com> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9713 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org> Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
This commit is contained in:
parent
f7603e7356
commit
48914b9465
21 changed files with 125 additions and 5 deletions
|
|
@ -326,7 +326,7 @@ func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Wr
|
|||
if r, ok := renderer.(ExternalRenderer); ok && r.DisplayInIFrame() {
|
||||
// Append a short script to the iframe's contents, which will communicate the scroll height of the embedded document via postMessage, either once loaded (in case the containing page loads first) in response to a postMessage from external.js, in case the iframe loads first
|
||||
// We use '*' as a target origin for postMessage, because can be certain we are embedded on the same domain, due to X-Frame-Options configured elsewhere. (Plus, the offsetHeight of an embedded document is likely not sensitive data anyway.)
|
||||
_, _ = pw.Write([]byte("<script>{let postHeight = () => {window.parent.postMessage({frameHeight: document.documentElement.offsetHeight}, '*')}; window.addEventListener('load', postHeight); window.addEventListener('message', (event) => {if (event.source === window.parent && event.data.requestOffsetHeight) postHeight()});}</script>"))
|
||||
_, _ = pw.Write([]byte("<script>{let postHeight = () => {window.parent.postMessage({frameHeight: document.documentElement.offsetHeight || document.documentElement.scrollHeight}, '*')}; window.addEventListener('load', postHeight); window.addEventListener('message', (event) => {if (event.source === window.parent && event.data.requestOffsetHeight) postHeight()});}</script>"))
|
||||
}
|
||||
_ = pw.Close()
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
|
|||
func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
username := "user2"
|
||||
unadoptedList := []string{path.Join(username, "unadopted1"), path.Join(username, "unadopted2")}
|
||||
unadoptedList := []string{path.Join(username, "rendering-test"), path.Join(username, "unadopted1"), path.Join(username, "unadopted2")}
|
||||
for _, unadopted := range unadoptedList {
|
||||
_ = os.Mkdir(path.Join(setting.RepoRootPath, unadopted+".git"), 0o755)
|
||||
}
|
||||
|
|
@ -77,13 +77,13 @@ func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
|
|||
opts := db.ListOptions{Page: 1, PageSize: 1}
|
||||
repoNames, count, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, unadoptedList[0], repoNames[0])
|
||||
|
||||
opts = db.ListOptions{Page: 2, PageSize: 1}
|
||||
repoNames, count, err = ListUnadoptedRepositories(db.DefaultContext, "", &opts)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Equal(t, unadoptedList[1], repoNames[0])
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ func TestAdoptRepository(t *testing.T) {
|
|||
path.Join(setting.RepoRootPath, username, unadopted+".git"),
|
||||
))
|
||||
|
||||
opts := db.ListOptions{Page: 1, PageSize: 1}
|
||||
opts := db.ListOptions{Page: 2, PageSize: 1}
|
||||
repoNames, _, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, repoNames, path.Join(username, unadopted))
|
||||
|
|
|
|||
6
tests/e2e/fixtures/repo_unit.yml
Normal file
6
tests/e2e/fixtures/repo_unit.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-
|
||||
id: 1001
|
||||
repo_id: 1002
|
||||
type: 1
|
||||
config: "{}"
|
||||
created_unix: 946684810
|
||||
|
|
@ -11,3 +11,18 @@
|
|||
status: 0
|
||||
lfs_size: 8192
|
||||
topics: '[]'
|
||||
|
||||
|
||||
-
|
||||
id: 1002
|
||||
owner_id: 2
|
||||
owner_name: user2
|
||||
lower_name: rendering-test
|
||||
name: rendering-test
|
||||
default_branch: master
|
||||
is_empty: false
|
||||
is_archived: false
|
||||
is_private: false
|
||||
status: 0
|
||||
num_issues: 0
|
||||
topics: '[]'
|
||||
|
|
|
|||
61
tests/e2e/rendering-iframe.test.e2e.ts
Normal file
61
tests/e2e/rendering-iframe.test.e2e.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// @watch start
|
||||
// web_src/js/markup/external.js
|
||||
// @watch end
|
||||
|
||||
import {expect} from '@playwright/test';
|
||||
import {test} from './utils_e2e.ts';
|
||||
|
||||
test('iframe renderer shrinks to shorter page', async ({page}, _workerInfo) => {
|
||||
const previewPath = '/user2/rendering-test/src/branch/master/short.iframehtml';
|
||||
|
||||
const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
const preview = page.locator('iframe.external-render');
|
||||
await expect.poll(async () => {
|
||||
const boundingBox = await preview.boundingBox();
|
||||
return boundingBox.height;
|
||||
}).toBeLessThan(300);
|
||||
});
|
||||
|
||||
test('iframe renderer expands to taller page', async ({page}, _workerInfo) => {
|
||||
const previewPath = '/user2/rendering-test/src/branch/master/tall.iframehtml';
|
||||
|
||||
const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
const preview = page.locator('iframe.external-render');
|
||||
await expect.poll(async () => {
|
||||
const boundingBox = await preview.boundingBox();
|
||||
return boundingBox.height;
|
||||
}).toBeGreaterThan(300);
|
||||
});
|
||||
|
||||
test('iframe renderer expands to taller page with absolutely-positioned body', async ({page}, _workerInfo) => {
|
||||
const previewPath = '/user2/rendering-test/src/branch/master/absolute.iframehtml';
|
||||
|
||||
const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
const preview = page.locator('iframe.external-render');
|
||||
await expect.poll(async () => {
|
||||
const boundingBox = await preview.boundingBox();
|
||||
return boundingBox.height;
|
||||
}).toBeGreaterThan(300);
|
||||
});
|
||||
|
||||
test('iframe renderer remains at default height if script breaks', async ({page}, _workerInfo) => {
|
||||
const previewPath = '/user2/rendering-test/src/branch/master/fail.iframehtml';
|
||||
|
||||
const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
const preview = page.locator('iframe.external-render');
|
||||
await expect.poll(async () => {
|
||||
const boundingBox = await preview.boundingBox();
|
||||
return boundingBox.height;
|
||||
}).toBeCloseTo(300, 0.5);
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/master
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
|
|
@ -0,0 +1 @@
|
|||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
x+)JMU047g040031QHL*но)-IукL+JлMм(имa╦u╖┼-ЩR╨Эеmгv4ЗЩWqь╪ш╙<-13Y╘iЛ?∙и=ЖlK▌╡В/чo⌠z╟╕╙╢8#©╗Y╜Qж╣*rO?тЬ-s╗тo╧ЕUF╗з▓дc╥_J~!\Бx╖Л{╓÷iо√:иsУсK
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
fafaad77cb54665ac800d1bf77e6a55bd355eabc
|
||||
|
|
@ -125,3 +125,11 @@ ENABLED = false
|
|||
|
||||
[cron.check_repo_stats]
|
||||
ENABLED = false
|
||||
|
||||
# For iframe rendering tests
|
||||
[markup.iframehtml]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .iframehtml
|
||||
RENDER_COMMAND = cat
|
||||
RENDER_CONTENT_MODE = iframe
|
||||
NEED_POSTPROCESS = false
|
||||
|
|
|
|||
|
|
@ -139,3 +139,11 @@ ENABLED = false
|
|||
|
||||
[cron.check_repo_stats]
|
||||
ENABLED = false
|
||||
|
||||
# For iframe rendering tests
|
||||
[markup.iframehtml]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .iframehtml
|
||||
RENDER_COMMAND = cat
|
||||
RENDER_CONTENT_MODE = iframe
|
||||
NEED_POSTPROCESS = false
|
||||
|
|
|
|||
|
|
@ -126,3 +126,11 @@ ENABLED = false
|
|||
|
||||
[cron.check_repo_stats]
|
||||
ENABLED = false
|
||||
|
||||
# For iframe rendering tests
|
||||
[markup.iframehtml]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .iframehtml
|
||||
RENDER_COMMAND = cat
|
||||
RENDER_CONTENT_MODE = iframe
|
||||
NEED_POSTPROCESS = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue