From 52fef742918671cb53fbcb6ced7c1ca2043fbccb Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 28 May 2026 08:14:52 +0200 Subject: [PATCH] fix(frontend): resolve Vite assets by manifest source path (#37836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In dev mode `/api/swagger` returned HTTP 500 (`Failed to locate local path for managed asset URI: css/swagger.css`): the backend synthesised asset keys from the Vite entry name instead of reading the manifest, which only worked by coincidence and broke once a source file name diverged from its entry name. This keys the manifest by its source path (e.g. `web_src/js/index.ts`) and resolves entries directly — hashed `file` in prod, dev-server source in dev. A new `AssetCSSLinks` helper renders a JS entry's stylesheet `` tags from the manifest (the entry's CSS plus the CSS of its statically-imported chunks). Fixes: https://github.com/go-gitea/gitea/issues/37830 Fixes: https://github.com/go-gitea/gitea/pull/37832 Fixes: https://github.com/go-gitea/gitea/pull/37876 Signed-off-by: silverwind Co-authored-by: prakhar0x01 Co-authored-by: Nicolas Co-authored-by: Claude (Opus 4.7) Co-authored-by: Giteabot --- modules/markup/external/frontend.go | 2 +- modules/markup/render.go | 2 +- modules/public/manifest.go | 120 +++++++++++++--------- modules/public/manifest_test.go | 64 ++++++------ modules/public/vitedev.go | 30 ++---- modules/templates/helper.go | 3 +- services/webtheme/webtheme.go | 2 +- templates/base/footer.tmpl | 2 +- templates/base/head_script.tmpl | 4 +- templates/base/head_style.tmpl | 2 +- templates/devtest/devtest-header.tmpl | 2 +- templates/swagger/openapi-viewer.tmpl | 6 +- tests/integration/markup_external_test.go | 8 +- vite.config.ts | 1 - web_src/js/swagger.ts | 2 - 15 files changed, 122 insertions(+), 128 deletions(-) diff --git a/modules/markup/external/frontend.go b/modules/markup/external/frontend.go index 26e83ec99a0..34fa2715f78 100644 --- a/modules/markup/external/frontend.go +++ b/modules/markup/external/frontend.go @@ -90,6 +90,6 @@ func (p *frontendRenderer) Render(ctx *markup.RenderContext, input io.Reader, ou `, p.name, ctx.RenderOptions.RelativePath, contentEncoding, contentString, - public.AssetURI("js/external-render-frontend.js")) + public.AssetURI("web_src/js/external-render-frontend.ts")) return err } diff --git a/modules/markup/render.go b/modules/markup/render.go index 44bdcd0791b..6f43434485d 100644 --- a/modules/markup/render.go +++ b/modules/markup/render.go @@ -243,7 +243,7 @@ func RenderWithRenderer(ctx *RenderContext, renderer Renderer, input io.Reader, return RenderIFrame(ctx, &extOpts, output) } // else: this is a standalone page, fallthrough to the real rendering, and add extra JS/CSS - extraScriptSrc := public.AssetURI("js/external-render-helper.js") + extraScriptSrc := public.AssetURI("web_src/js/external-render-helper.ts") extraLinkHref := ctx.RenderOptions.StandalonePageOptions.CurrentWebTheme.PublicAssetURI() // " -{{ctx.ScriptImport "js/iife.js"}} +{{ctx.ScriptImport "web_src/js/iife.ts"}} diff --git a/templates/base/head_style.tmpl b/templates/base/head_style.tmpl index 4a4fb9d96f8..dba782f9bb9 100644 --- a/templates/base/head_style.tmpl +++ b/templates/base/head_style.tmpl @@ -1,2 +1,2 @@ - +{{AssetCSSLinks "web_src/js/index.ts" "web_src/css/index.css"}} diff --git a/templates/devtest/devtest-header.tmpl b/templates/devtest/devtest-header.tmpl index c9d7b3047fe..ad153364e04 100644 --- a/templates/devtest/devtest-header.tmpl +++ b/templates/devtest/devtest-header.tmpl @@ -1,4 +1,4 @@ {{template "base/head" ctx.RootData}} - +
{{template "base/alert" ctx.RootData}}
diff --git a/templates/swagger/openapi-viewer.tmpl b/templates/swagger/openapi-viewer.tmpl index 792364157d7..2e3e9bf1499 100644 --- a/templates/swagger/openapi-viewer.tmpl +++ b/templates/swagger/openapi-viewer.tmpl @@ -4,14 +4,14 @@ {{ctx.HeadMetaContentSecurityPolicy}} Gitea API - {{/* HINT: SWAGGER-CSS-IMPORT: import swagger styles ahead to avoid UI flicker (e.g.: the swagger-back-link element) */}} - + {{/* HINT: SWAGGER-CSS-IMPORT: load swagger styles ahead to avoid flicker (e.g. the swagger-back-link) */}} + {{AssetCSSLinks "web_src/js/swagger.ts" "web_src/css/swagger-standalone.css"}} {{/* TODO: add Help & Glossary to help users understand the API, and explain some concepts like "Owner" */}} {{svg "octicon-reply"}}{{ctx.Locale.Tr "return_to_gitea"}}
- {{ctx.ScriptImport "js/swagger.js" "module"}} + {{ctx.ScriptImport "web_src/js/swagger.ts" "module"}} diff --git a/tests/integration/markup_external_test.go b/tests/integration/markup_external_test.go index 458fa239486..9217fd7e5a7 100644 --- a/tests/integration/markup_external_test.go +++ b/tests/integration/markup_external_test.go @@ -109,8 +109,8 @@ func TestExternalMarkupRenderer(t *testing.T) { assert.Equal(t, "frame-src 'self'; sandbox allow-scripts allow-popups", respSub.Header().Get("Content-Security-Policy")) // FIXME: actually here is a bug (legacy design problem), the "PostProcess" will escape "`+ - ``+ + ``+ + ``+ `
<script></script>
`, respSub.Body.String(), ) @@ -137,8 +137,8 @@ func TestExternalMarkupRenderer(t *testing.T) { req := NewRequest(t, "GET", "/user2/repo1/render/branch/master/html.no-sanitizer?a=1%2f2") respSub := MakeRequest(t, req, http.StatusOK) assert.Equal(t, - ``+ - ``+ + ``+ + ``+ ``, respSub.Body.String(), ) diff --git a/vite.config.ts b/vite.config.ts index 53717813a10..e077fed6aec 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -267,7 +267,6 @@ export default defineConfig(commonViteOpts({ manifest: true, rolldownOptions: { input: { - // FIXME: INCORRECT-VITE-MANIFEST-PARSER: the "css importing" logic in backend is wrong index: join(import.meta.dirname, 'web_src/js/index.ts'), swagger: join(import.meta.dirname, 'web_src/js/swagger.ts'), 'external-render-frontend': join(import.meta.dirname, 'web_src/js/external-render-frontend.ts'), diff --git a/web_src/js/swagger.ts b/web_src/js/swagger.ts index ee0fd289367..c73002a6f13 100644 --- a/web_src/js/swagger.ts +++ b/web_src/js/swagger.ts @@ -1,5 +1,3 @@ -// FIXME: INCORRECT-VITE-MANIFEST-PARSER: it just happens to work for current dependencies -// If this module depends on another one and that one imports "swagger.css", then {{AssetURI "css/swagger.css"}} won't work import '../css/swagger-standalone.css'; import {initSwaggerUI} from './render/swagger.ts';