Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions services/context/context_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ package context

import (
"context"
"fmt"
"html"
"html/template"
"net/http"
"strconv"
"strings"
"sync"
"time"

"code.gitea.io/gitea/modules/httplib"
Expand Down Expand Up @@ -91,31 +89,14 @@ func (c TemplateContext) AppFullLink(link ...string) template.URL {
return template.URL(s + "/" + strings.TrimPrefix(link[0], "/"))
}

var globalVars = sync.OnceValue(func() (ret struct {
scriptImportRemainingPart string
},
) {
// add onerror handler to alert users when the script fails to load:
// * for end users: there were many users reporting that "UI doesn't work", actually they made mistakes in their config
// * for developers: help them to remember to run "make watch-frontend" to build frontend assets
// the message will be directly put in the onerror JS code's string
onScriptErrorPrompt := `Please make sure the asset files can be accessed.`
if !setting.IsProd {
onScriptErrorPrompt += `\n\nFor development, run: make watch-frontend.`
}
onScriptErrorJS := fmt.Sprintf(`alert('Failed to load asset file from ' + this.src + '. %s')`, onScriptErrorPrompt)
ret.scriptImportRemainingPart = `onerror="` + html.EscapeString(onScriptErrorJS) + `"></script>`
return ret
})

func (c TemplateContext) ScriptImport(path string, typ ...string) template.HTML {
if len(typ) > 0 {
if typ[0] == "module" {
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" type="module" src="` + html.EscapeString(public.AssetURI(path)) + `" ` + globalVars().scriptImportRemainingPart)
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" type="module" src="` + html.EscapeString(public.AssetURI(path)) + `"></script>`)
}
panic("unsupported script type: " + typ[0])
}
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" src="` + html.EscapeString(public.AssetURI(path)) + `" ` + globalVars().scriptImportRemainingPart)
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" src="` + html.EscapeString(public.AssetURI(path)) + `"></script>`)
}

func (c TemplateContext) CspScriptNonce() (ret string) {
Expand Down
3 changes: 3 additions & 0 deletions templates/base/footer.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@
{{template "base/footer_content" .}}
{{ctx.ScriptImport "js/index.js" "module"}}
{{template "custom/footer" .}}
<script nonce="{{ctx.CspScriptNonce}}" type="module">
if (!window.config?.frontendInited) alert("Frontend is not initialized, check console errors or asset files.")
</script>
</body>
</html>
1 change: 1 addition & 0 deletions web_src/js/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ interface Window {
enableTimeTracking: boolean,
mermaidMaxSourceCharacters: number,
i18n: Record<string, string>,
frontendInited: boolean,
},
$: JQueryStatic,
jQuery: JQueryStatic,
Expand Down
2 changes: 2 additions & 0 deletions web_src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,5 @@ const initDur = performance.now() - initStartTime;
if (initDur > 500) {
console.error(`slow init functions took ${initDur.toFixed(3)}ms`);
}

window.config.frontendInited = true;
1 change: 1 addition & 0 deletions web_src/js/vitest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ window.config = {
enableTimeTracking: true,
mermaidMaxSourceCharacters: 5000,
i18n: {},
frontendInited: false,
};

window.testModules = {};
Expand Down