From d390d77879bfcde32a5653e4796e6e09656c64dc Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 2 Aug 2026 14:51:10 +0800 Subject: [PATCH] fix: remove the pull merge box from UI when the refreshed page doesn't contain it (#38742) On the PR view page, the "merge box" is refreshed periodically. If the PR changes (e.g.: merged and the head branch has been deleted), then the merge box doesn't exist in the refresh response. For such case, the merge box should also be removed from the UI. --- web_src/js/features/repo-issue-pull.ts | 7 ++++++- web_src/js/utils/dom.ts | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/web_src/js/features/repo-issue-pull.ts b/web_src/js/features/repo-issue-pull.ts index 77948c4edd..34cc4ed199 100644 --- a/web_src/js/features/repo-issue-pull.ts +++ b/web_src/js/features/repo-issue-pull.ts @@ -52,7 +52,12 @@ function initRepoPullMergeBoxRefresh(el: Element) { const pullLink = el.getAttribute('data-pull-link')!; const resp = await GET(`${pullLink}/merge_box`); if (!resp.ok) return; - const newEl = createElementFromHTML(await resp.text()); + const respText = (await resp.text()).trim(); + if (!respText) { + el.remove(); // merge box might not exist if the PR has changed (e.g.: merged and the head branch has been deleted) + return; + } + const newEl = createElementFromHTML(respText); const scrollTop = el.querySelector('.commit-status-list')?.scrollTop; el.replaceWith(newEl); // don't morph, do full replacement to make sure data-global-init and Vue components are re-initialized if (scrollTop) newEl.querySelector('.commit-status-list')?.scrollTo({top: scrollTop, behavior: 'instant'}); diff --git a/web_src/js/utils/dom.ts b/web_src/js/utils/dom.ts index 3fa865645d..71b6b7506f 100644 --- a/web_src/js/utils/dom.ts +++ b/web_src/js/utils/dom.ts @@ -267,10 +267,10 @@ export function isElemVisible(el: HTMLElement): boolean { export function createElementFromHTML(htmlString: string): T { htmlString = htmlString.trim(); + if (!htmlString.startsWith('<')) throw new Error(`Invalid HTML element string: ${htmlString}`); const isLetter = (code: number) => (code >= 65 && code <= 90) || (code >= 97 && code <= 122); const startsWithTag = (s: string, tag: string) => { - return s.startsWith('<') && - s.substring(1, 1 + tag.length).toLowerCase() === tag.toLowerCase() && + return s.substring(1, 1 + tag.length).toLowerCase() === tag.toLowerCase() && !isLetter(s[1 + tag.length].charCodeAt(0)); }; // There is no way to create some elements without a proper parent, jQuery's approach: https://github.com/jquery/jquery/blob/main/src/manipulation/wrapMap.js