rewrite data-*url attributes, where Gitea hands URLs to its own JavaScript

The dashboard heatmap reads its endpoint from data-heatmap-url:
document.querySelector('#user-heatmap').getAttribute('data-heatmap-url').
Unprefixed it fetched from the PLATFORM's origin, got the SPA's index.html and
reported "Unexpected token '<'" while parsing JSON — the last error left after
everything visible was rendering correctly.

data-url carries the language switcher's links and had the same problem.

Matched on the `url` suffix rather than by listing attribute names, because the
list is Gitea's to change.

Found by reading Gitea's own bundle rather than by reasoning about what it
probably does — which is what the three previous attempts at this error were.
This commit is contained in:
officer
2026-08-19 09:38:08 +00:00
parent 413b7ac0e9
commit fe67de0281
2 changed files with 28 additions and 2 deletions
+10 -2
View File
@@ -58,8 +58,16 @@ const isForeign = (path: string): boolean => path.startsWith('//') || /^[a-z][a-
export function rewriteAttributes(html: string, base: string): string {
const skip = (path: string) => isForeign(path) || path === base || path.startsWith(`${base}/`);
return html
.replace(/(href|src|action)=("|')(\/[^"']*)\2/gi, (match, attr: string, quote: string, path: string) =>
skip(path) ? match : `${attr}=${quote}${prefixed(base, path)}${quote}`,
// `data-*url` alongside the obvious three. Gitea hands URLs to its own JavaScript through data
// attributes — `data-heatmap-url` is where the dashboard heatmap gets its endpoint, and `data-url`
// carries the language switcher's links. Missing them meant the heatmap fetched from the PLATFORM's
// origin, got the SPA's index.html, and reported `Unexpected token '<'` while parsing JSON.
//
// Matched on the `url` suffix rather than by listing names, because the list is Gitea's to change.
.replace(
/(href|src|action|data-[a-z-]*url)=("|')(\/[^"']*)\2/gi,
(match, attr: string, quote: string, path: string) =>
skip(path) ? match : `${attr}=${quote}${prefixed(base, path)}${quote}`,
)
.replace(/url\((\/[^)"']*)\)/g, (match, path: string) => (skip(path) ? match : `url(${prefixed(base, path)})`));
}