[assets] configurable URL for static resources (#7911)

* static url

* add cors support for static resources

* [assets] work on the migration to configurable url for assets

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* [misc] fix whitespace

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* [assets] fix the loading of the manifest.json

It is generated dynamically, and as such can not be served by the cdn.

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* Revert "add cors support for static resources"

This reverts commit 42f964fd181dbb8b139808b9be623470d4f0e40f

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* [docs] add the STATIC_URL_PREFIX option

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* [docs] reverse-proxy: nginx: add two setups for STATIC_URL_PREFIX

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>

* [assets] migrate the url of a new asset to the static url prefix

REF: f2a3abc683
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
This commit is contained in:
Jakob Ackermann 2019-10-22 14:11:01 +02:00 committed by Lunny Xiao
parent d0c7a08d75
commit 00629fea95
21 changed files with 211 additions and 129 deletions

View file

@ -185,6 +185,8 @@ FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
PROTOCOL = http PROTOCOL = http
DOMAIN = localhost DOMAIN = localhost
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/ ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
; when STATIC_URL_PREFIX is empty it will follow APP_URL
STATIC_URL_PREFIX =
; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket. ; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
HTTP_ADDR = 0.0.0.0 HTTP_ADDR = 0.0.0.0
HTTP_PORT = 3000 HTTP_PORT = 3000

View file

@ -138,6 +138,13 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
- `ROOT_URL`: **%(PROTOCOL)s://%(DOMAIN)s:%(HTTP\_PORT)s/**: - `ROOT_URL`: **%(PROTOCOL)s://%(DOMAIN)s:%(HTTP\_PORT)s/**:
Overwrite the automatically generated public URL. Overwrite the automatically generated public URL.
This is useful if the internal and the external URL don't match (e.g. in Docker). This is useful if the internal and the external URL don't match (e.g. in Docker).
- `STATIC_URL_PREFIX`: **\<empty\>**:
Overwrite this option to request static resources from a different URL.
This includes CSS files, images, JS files and web fonts.
Avatar images are dynamic resources and still served by gitea.
The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`.
Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective.
The static files are located in the `public/` directory of the gitea source repository.
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address. - `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket - If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings. defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.

View file

@ -44,6 +44,74 @@ server {
Then set `[server] ROOT_URL = http://git.example.com/git/` in your configuration. Then set `[server] ROOT_URL = http://git.example.com/git/` in your configuration.
## Using Nginx as a reverse proxy and serve static resources directly
We can tune the performance in splitting requests into categories static and dynamic.
CSS files, JavaScript files, images and web fonts are static content.
The front page, a repository view or issue list is dynamic content.
Nginx can serve static resources directly and proxy only the dynamic requests to gitea.
Nginx is optimized for serving static content, while the proxying of large responses might be the opposite of that
(see https://serverfault.com/q/587386).
Download a snap shot of the gitea source repository to `/path/to/gitea/`.
We are only interested in the `public/` directory and you can delete the rest.
Depending on the scale of your user base, you might want to split the traffic to two distinct servers,
or use a cdn for the static files.
### using a single node and a single domain
Set `[server] STATIC_URL_PREFIX = /_/static` in your configuration.
```
server {
listen 80;
server_name git.example.com;
location /_/static {
alias /path/to/gitea/public;
}
location / {
proxy_pass http://localhost:3000;
}
}
```
### using two nodes and two domains
Set `[server] STATIC_URL_PREFIX = http://cdn.example.com/gitea` in your configuration.
```
# application server running gitea
server {
listen 80;
server_name git.example.com;
location / {
proxy_pass http://localhost:3000;
}
}
```
```
# static content delivery server
server {
listen 80;
server_name cdn.example.com;
location /gitea {
alias /path/to/gitea/public;
}
location / {
return 404;
}
}
```
## Using Apache HTTPD as a reverse proxy ## Using Apache HTTPD as a reverse proxy
If you want Apache HTTPD to serve your Gitea instance, you can add the following to your Apache HTTPD configuration (usually located at `/etc/apache2/httpd.conf` in Ubuntu): If you want Apache HTTPD to serve your Gitea instance, you can add the following to your Apache HTTPD configuration (usually located at `/etc/apache2/httpd.conf` in Ubuntu):

View file

@ -99,6 +99,7 @@ var (
LetsEncryptEmail string LetsEncryptEmail string
GracefulRestartable bool GracefulRestartable bool
GracefulHammerTime time.Duration GracefulHammerTime time.Duration
StaticURLPrefix string
SSH = struct { SSH = struct {
Disabled bool `ini:"DISABLE_SSH"` Disabled bool `ini:"DISABLE_SSH"`
@ -573,7 +574,7 @@ func NewContext() {
defaultAppURL += ":" + HTTPPort defaultAppURL += ":" + HTTPPort
} }
AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL) AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL)
AppURL = strings.TrimRight(AppURL, "/") + "/" AppURL = strings.TrimSuffix(AppURL, "/") + "/"
// Check if has app suburl. // Check if has app suburl.
appURL, err := url.Parse(AppURL) appURL, err := url.Parse(AppURL)
@ -583,6 +584,7 @@ func NewContext() {
// Suburl should start with '/' and end without '/', such as '/{subpath}'. // Suburl should start with '/' and end without '/', such as '/{subpath}'.
// This value is empty if site does not have sub-url. // This value is empty if site does not have sub-url.
AppSubURL = strings.TrimSuffix(appURL.Path, "/") AppSubURL = strings.TrimSuffix(appURL.Path, "/")
StaticURLPrefix = strings.TrimSuffix(sec.Key("STATIC_URL_PREFIX").MustString(AppSubURL), "/")
AppSubURLDepth = strings.Count(AppSubURL, "/") AppSubURLDepth = strings.Count(AppSubURL, "/")
// Check if Domain differs from AppURL domain than update it to AppURL's domain // Check if Domain differs from AppURL domain than update it to AppURL's domain
// TODO: Can be replaced with url.Hostname() when minimal GoLang version is 1.8 // TODO: Can be replaced with url.Hostname() when minimal GoLang version is 1.8

View file

@ -48,6 +48,9 @@ func NewFuncMap() []template.FuncMap {
"AppSubUrl": func() string { "AppSubUrl": func() string {
return setting.AppSubURL return setting.AppSubURL
}, },
"StaticUrlPrefix": func() string {
return setting.StaticURLPrefix
},
"AppUrl": func() string { "AppUrl": func() string {
return setting.AppURL return setting.AppURL
}, },

View file

@ -11,19 +11,19 @@
{{end}} {{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{AppSubUrl}}/img/gitea-sm.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{AppSubUrl}}/img/gogs.ico"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{AppSubUrl}}/img/slack.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{AppSubUrl}}/img/discord.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{AppSubUrl}}/img/dingtalk.ico"> <img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.ico">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{AppSubUrl}}/img/telegram.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{AppSubUrl}}/img/msteams.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -12,38 +12,38 @@
{{template "base/footer_content" .}} {{template "base/footer_content" .}}
<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1"></script>
<script src="{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1"></script>
<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
{{if .RequireSimpleMDE}} {{if .RequireSimpleMDE}}
<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/codemirror/mode/meta.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script>
<script> <script>
CodeMirror.modeURL = "{{AppSubUrl}}/vendor/plugins/codemirror/mode/%N/%N.js"; CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js";
</script> </script>
{{end}} {{end}}
{{if .RequireGitGraph}} {{if .RequireGitGraph}}
<!-- graph --> <!-- graph -->
<script src="{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/gitgraph/gitgraph.js"></script>
<script src="{{AppSubUrl}}/js/draw.js"></script> <script src="{{StaticUrlPrefix}}/js/draw.js"></script>
{{end}} {{end}}
<!-- Third-party libraries --> <!-- Third-party libraries -->
{{if .RequireHighlightJS}} {{if .RequireHighlightJS}}
<script src="{{AppSubUrl}}/vendor/plugins/highlight/highlight.pack.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/highlight/highlight.pack.js"></script>
{{end}} {{end}}
{{if .RequireMinicolors}} {{if .RequireMinicolors}}
<script src="{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script>
{{end}} {{end}}
{{if .RequireDatetimepicker}} {{if .RequireDatetimepicker}}
<script src="{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js"></script>
{{end}} {{end}}
{{if .RequireDropzone}} {{if .RequireDropzone}}
<script src="{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/dropzone/dropzone.js"></script>
{{end}} {{end}}
{{if .RequireU2F}} {{if .RequireU2F}}
<script src="{{AppSubUrl}}/vendor/plugins/u2f/index.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script>
{{end}} {{end}}
{{if .EnableCaptcha}} {{if .EnableCaptcha}}
{{if eq .CaptchaType "recaptcha"}} {{if eq .CaptchaType "recaptcha"}}
@ -51,7 +51,7 @@
{{end}} {{end}}
{{end}} {{end}}
{{if .RequireTribute}} {{if .RequireTribute}}
<script src="{{AppSubUrl}}/vendor/plugins/tribute/tribute.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script>
<script> <script>
var issuesTribute = new Tribute({ var issuesTribute = new Tribute({
values: [ values: [
@ -101,7 +101,7 @@
return ':' + item.original + ':'; return ':' + item.original + ':';
}, },
menuItemTemplate: function (item) { menuItemTemplate: function (item) {
return '<img class="emoji" src="{{AppSubUrl}}/vendor/plugins/emojify/images/' + item.original + '.png"/>' + item.original; return '<img class="emoji" src="{{StaticUrlPrefix}}/vendor/plugins/emojify/images/' + item.original + '.png"/>' + item.original;
} }
}] }]
}); });
@ -115,16 +115,16 @@
} }
</script> </script>
{{end}} {{end}}
<script src="{{AppSubUrl}}/vendor/plugins/emojify/emojify.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/emojify/emojify.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/clipboard/clipboard.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/clipboard/clipboard.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/vue/vue.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/vue/vue.min.js"></script>
<!-- JavaScript --> <!-- JavaScript -->
<script src="{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/semantic/semantic.min.js"></script>
<script src="{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}"></script> <script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script>
{{if .EnableHeatmap}} {{if .EnableHeatmap}}
<script src="{{AppSubUrl}}/vendor/plugins/moment/moment.min.js" charset="utf-8"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/moment/moment.min.js" charset="utf-8"></script>
<script src="{{AppSubUrl}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.browser.js" charset="utf-8"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.browser.js" charset="utf-8"></script>
<script type="text/javascript"> <script type="text/javascript">
initHeatmap('user-heatmap', '{{.HeatmapUser}}'); initHeatmap('user-heatmap', '{{.HeatmapUser}}');
</script> </script>

View file

@ -16,7 +16,7 @@
{{end}} {{end}}
</div> </div>
</div> </div>
<a href="{{AppSubUrl}}/vendor/librejs.html" data-jslicense="1">JavaScript licenses</a> <a href="{{StaticUrlPrefix}}/vendor/librejs.html" data-jslicense="1">JavaScript licenses</a>
{{if .EnableSwagger}}<a href="{{AppSubUrl}}/api/swagger">API</a>{{end}} {{if .EnableSwagger}}<a href="{{AppSubUrl}}/api/swagger">API</a>{{end}}
<a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.i18n.Tr "website"}}</a> <a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.i18n.Tr "website"}}</a>
{{if (or .ShowFooterVersion .PageIsAdmin)}}<span class="version">{{GoVer}}</span>{{end}} {{if (or .ShowFooterVersion .PageIsAdmin)}}<span class="version">{{GoVer}}</span>{{end}}

View file

@ -70,35 +70,35 @@
THE SOFTWARE. THE SOFTWARE.
--- ---
Licensing information for additional javascript libraries can be found at: Licensing information for additional javascript libraries can be found at:
{{AppSubUrl}}/vendor/librejs.html {{StaticUrlPrefix}}/vendor/librejs.html
@licend The above is the entire license notice @licend The above is the entire license notice
for the JavaScript code in this page. for the JavaScript code in this page.
*/`}} */`}}
</script> </script>
<link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" /> <link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png" />
<link rel="mask-icon" href="{{AppSubUrl}}/img/gitea-safari.svg" color="#609926"> <link rel="mask-icon" href="{{StaticUrlPrefix}}/img/gitea-safari.svg" color="#609926">
<link rel="preload" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css" as="style" onload="this.rel='stylesheet'"> <link rel="preload" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css"></noscript> <noscript><link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css"></noscript>
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/octicons/octicons.min.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/octicons/octicons.min.css">
{{if .RequireSimpleMDE}} {{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
{{end}} {{end}}
{{if .RequireGitGraph}} {{if .RequireGitGraph}}
<!-- graph --> <!-- graph -->
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/gitgraph/gitgraph.css">
{{end}} {{end}}
{{if .RequireTribute}} {{if .RequireTribute}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/tribute/tribute.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
{{end}} {{end}}
<!-- Stylesheet --> <!-- Stylesheet -->
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/semantic/semantic.min.css">
<link rel="stylesheet" href="{{AppSubUrl}}/css/index.css?v={{MD5 AppVer}}"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
<noscript> <noscript>
<style> <style>
.dropdown:hover > .menu { display: block; } .dropdown:hover > .menu { display: block; }
@ -107,25 +107,25 @@
</noscript> </noscript>
{{if .RequireHighlightJS}} {{if .RequireHighlightJS}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/highlight/github.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/highlight/github.css">
{{end}} {{end}}
{{if .RequireMinicolors}} {{if .RequireMinicolors}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
{{end}} {{end}}
{{if .RequireDatetimepicker}} {{if .RequireDatetimepicker}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css">
{{end}} {{end}}
{{if .RequireDropzone}} {{if .RequireDropzone}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/dropzone/dropzone.css">
{{end}} {{end}}
{{if .EnableHeatmap}} {{if .EnableHeatmap}}
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.css">
{{end}} {{end}}
<style class="list-search-style"></style> <style class="list-search-style"></style>
<script src="{{AppSubUrl}}/vendor/plugins/promise-polyfill/polyfill.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/promise-polyfill/polyfill.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/loadCSS.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/cssrelpreload/loadCSS.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js"></script> <script src="{{StaticUrlPrefix}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js"></script>
{{if .PageIsUserProfile}} {{if .PageIsUserProfile}}
<meta property="og:title" content="{{.Owner.Name}}" /> <meta property="og:title" content="{{.Owner.Name}}" />
<meta property="og:type" content="profile" /> <meta property="og:type" content="profile" />
@ -144,16 +144,16 @@
{{else}} {{else}}
<meta property="og:title" content="{{AppName}}"> <meta property="og:title" content="{{AppName}}">
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:image" content="{{AppUrl}}img/gitea-lg.png" /> <meta property="og:image" content="{{StaticUrlPrefix}}img/gitea-lg.png" />
<meta property="og:url" content="{{AppUrl}}" /> <meta property="og:url" content="{{AppUrl}}" />
<meta property="og:description" content="{{MetaDescription}}"> <meta property="og:description" content="{{MetaDescription}}">
{{end}} {{end}}
{{if .IsSigned }} {{if .IsSigned }}
{{ if ne .SignedUser.Theme "gitea" }} {{ if ne .SignedUser.Theme "gitea" }}
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css">
{{end}} {{end}}
{{else if ne DefaultTheme "gitea"}} {{else if ne DefaultTheme "gitea"}}
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css"> <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css">
{{end}} {{end}}
{{template "custom/header" .}} {{template "custom/header" .}}
</head> </head>

View file

@ -1,7 +1,7 @@
<div class="ui container" id="navbar"> <div class="ui container" id="navbar">
<div class="item brand" style="justify-content: space-between;"> <div class="item brand" style="justify-content: space-between;">
<a href="{{AppSubUrl}}/"> <a href="{{AppSubUrl}}/">
<img class="ui mini image" src="{{AppSubUrl}}/img/gitea-sm.png"> <img class="ui mini image" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
</a> </a>
<div class="ui basic icon button mobile-only" id="navbar-expand-toggle"> <div class="ui basic icon button mobile-only" id="navbar-expand-toggle">
<i class="sidebar icon"></i> <i class="sidebar icon"></i>

2
templates/home.tmpl vendored
View file

@ -3,7 +3,7 @@
<div class="ui stackable middle very relaxed page grid"> <div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column"> <div class="sixteen wide center aligned centered column">
<div> <div>
<img class="logo" src="{{AppSubUrl}}/img/gitea-lg.png" /> <img class="logo" src="{{StaticUrlPrefix}}/img/gitea-lg.png" />
</div> </div>
<div class="hero"> <div class="hero">
<h1 class="ui icon header title"> <h1 class="ui icon header title">

View file

@ -10,19 +10,19 @@
{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}} {{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{AppSubUrl}}/img/gitea-sm.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{AppSubUrl}}/img/gogs.ico"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{AppSubUrl}}/img/slack.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{AppSubUrl}}/img/discord.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{AppSubUrl}}/img/dingtalk.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.png">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{AppSubUrl}}/img/telegram.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{AppSubUrl}}/img/msteams.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -3,22 +3,22 @@
"name": "Gitea - Git with a cup of tea", "name": "Gitea - Git with a cup of tea",
"icons": [ "icons": [
{ {
"src": "{{AppSubUrl}}/img/gitea-lg.png", "src": "{{StaticUrlPrefix}}/img/gitea-lg.png",
"type": "image/png", "type": "image/png",
"sizes": "880x880" "sizes": "880x880"
}, },
{ {
"src": "{{AppSubUrl}}/img/gitea-sm.png", "src": "{{StaticUrlPrefix}}/img/gitea-sm.png",
"type": "image/png", "type": "image/png",
"sizes": "120x120" "sizes": "120x120"
}, },
{ {
"src": "{{AppSubUrl}}/img/gitea-512.png", "src": "{{StaticUrlPrefix}}/img/gitea-512.png",
"type": "image/png", "type": "image/png",
"sizes": "512x512" "sizes": "512x512"
}, },
{ {
"src": "{{AppSubUrl}}/img/gitea-192.png", "src": "{{StaticUrlPrefix}}/img/gitea-192.png",
"type": "image/png", "type": "image/png",
"sizes": "192x192" "sizes": "192x192"
} }

View file

@ -1,55 +1,55 @@
var STATIC_CACHE = 'static-cache-v1'; var STATIC_CACHE = 'static-cache-v1';
var urlsToCache = [ var urlsToCache = [
// js // js
'{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js', '{{StaticUrlPrefix}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js',
'{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1', '{{StaticUrlPrefix}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1',
'{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1', '{{StaticUrlPrefix}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1',
'{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js', '{{StaticUrlPrefix}}/vendor/plugins/semantic/semantic.min.js',
'{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}', '{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}',
'{{AppSubUrl}}/js/draw.js', '{{StaticUrlPrefix}}/js/draw.js',
'{{AppSubUrl}}/vendor/plugins/clipboard/clipboard.min.js', '{{StaticUrlPrefix}}/vendor/plugins/clipboard/clipboard.min.js',
'{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.js', '{{StaticUrlPrefix}}/vendor/plugins/gitgraph/gitgraph.js',
'{{AppSubUrl}}/vendor/plugins/vue/vue.min.js', '{{StaticUrlPrefix}}/vendor/plugins/vue/vue.min.js',
'{{AppSubUrl}}/vendor/plugins/emojify/emojify.min.js', '{{StaticUrlPrefix}}/vendor/plugins/emojify/emojify.min.js',
'{{AppSubUrl}}/vendor/plugins/cssrelpreload/loadCSS.min.js', '{{StaticUrlPrefix}}/vendor/plugins/cssrelpreload/loadCSS.min.js',
'{{AppSubUrl}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js', '{{StaticUrlPrefix}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js',
'{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.js', '{{StaticUrlPrefix}}/vendor/plugins/dropzone/dropzone.js',
'{{AppSubUrl}}/vendor/plugins/highlight/highlight.pack.js', '{{StaticUrlPrefix}}/vendor/plugins/highlight/highlight.pack.js',
'{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js', '{{StaticUrlPrefix}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js',
'{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js', '{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js',
'{{AppSubUrl}}/vendor/plugins/codemirror/addon/mode/loadmode.js', '{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js',
'{{AppSubUrl}}/vendor/plugins/codemirror/mode/meta.js', '{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js',
'{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js', '{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js',
// css // css
'{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css', '{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css',
'{{AppSubUrl}}/vendor/assets/octicons/octicons.min.css', '{{StaticUrlPrefix}}/vendor/assets/octicons/octicons.min.css',
'{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.css', '{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css',
'{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.css', '{{StaticUrlPrefix}}/vendor/plugins/gitgraph/gitgraph.css',
'{{AppSubUrl}}/vendor/plugins/tribute/tribute.css', '{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css',
'{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.css', '{{StaticUrlPrefix}}/vendor/plugins/semantic/semantic.min.css',
'{{AppSubUrl}}/css/index.css?v={{MD5 AppVer}}', '{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}',
'{{AppSubUrl}}/vendor/plugins/highlight/github.css', '{{StaticUrlPrefix}}/vendor/plugins/highlight/github.css',
'{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css', '{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css',
'{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css', '{{StaticUrlPrefix}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css',
'{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css', '{{StaticUrlPrefix}}/vendor/plugins/dropzone/dropzone.css',
{{if .IsSigned }} {{if .IsSigned }}
{{ if ne .SignedUser.Theme "gitea" }} {{ if ne .SignedUser.Theme "gitea" }}
'{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css', '{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css',
{{end}} {{end}}
{{else if ne DefaultTheme "gitea"}} {{else if ne DefaultTheme "gitea"}}
'{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css', '{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css',
{{end}} {{end}}
// img // img
'{{AppSubUrl}}/img/gitea-sm.png', '{{StaticUrlPrefix}}/img/gitea-sm.png',
'{{AppSubUrl}}/img/gitea-lg.png', '{{StaticUrlPrefix}}/img/gitea-lg.png',
// fonts // fonts
'{{AppSubUrl}}/vendor/plugins/semantic/themes/default/assets/fonts/icons.woff2', '{{StaticUrlPrefix}}/vendor/plugins/semantic/themes/default/assets/fonts/icons.woff2',
'{{AppSubUrl}}/vendor/assets/octicons/octicons.woff2?ef21c39f0ca9b1b5116e5eb7ac5eabe6', '{{StaticUrlPrefix}}/vendor/assets/octicons/octicons.woff2?ef21c39f0ca9b1b5116e5eb7ac5eabe6',
'{{AppSubUrl}}/vendor/assets/lato-fonts/lato-v14-latin-regular.woff2', '{{StaticUrlPrefix}}/vendor/assets/lato-fonts/lato-v14-latin-regular.woff2',
'{{AppSubUrl}}/vendor/assets/lato-fonts/lato-v14-latin-700.woff2' '{{StaticUrlPrefix}}/vendor/assets/lato-fonts/lato-v14-latin-700.woff2'
]; ];
self.addEventListener('install', function (event) { self.addEventListener('install', function (event) {

View file

@ -9,7 +9,7 @@
<div class="ui stackable middle very relaxed page grid"> <div class="ui stackable middle very relaxed page grid">
<div id="repo_migrating" class="sixteen wide center aligned centered column" repo="{{.Repo.Repository.FullName}}"> <div id="repo_migrating" class="sixteen wide center aligned centered column" repo="{{.Repo.Repository.FullName}}">
<div> <div>
<img src="{{AppSubUrl}}/img/loading.png"/> <img src="{{StaticUrlPrefix}}/img/loading.png"/>
</div> </div>
</div> </div>
</div> </div>

View file

@ -6,25 +6,25 @@
<div class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_webhook"}}</div> <div class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_webhook"}}</div>
<div class="menu"> <div class="menu">
<a class="item" href="{{.BaseLink}}/gitea/new"> <a class="item" href="{{.BaseLink}}/gitea/new">
<img class="img-10" src="{{AppSubUrl}}/img/gitea-sm.png">Gitea <img class="img-10" src="{{StaticUrlPrefix}}/img/gitea-sm.png">Gitea
</a> </a>
<a class="item" href="{{.BaseLink}}/gogs/new"> <a class="item" href="{{.BaseLink}}/gogs/new">
<img class="img-10" src="{{AppSubUrl}}/img/gogs.ico">Gogs <img class="img-10" src="{{StaticUrlPrefix}}/img/gogs.ico">Gogs
</a> </a>
<a class="item" href="{{.BaseLink}}/slack/new"> <a class="item" href="{{.BaseLink}}/slack/new">
<img class="img-10" src="{{AppSubUrl}}/img/slack.png">Slack <img class="img-10" src="{{StaticUrlPrefix}}/img/slack.png">Slack
</a> </a>
<a class="item" href="{{.BaseLink}}/discord/new"> <a class="item" href="{{.BaseLink}}/discord/new">
<img class="img-10" src="{{AppSubUrl}}/img/discord.png">Discord <img class="img-10" src="{{StaticUrlPrefix}}/img/discord.png">Discord
</a> </a>
<a class="item" href="{{.BaseLink}}/dingtalk/new"> <a class="item" href="{{.BaseLink}}/dingtalk/new">
<img class="img-10" src="{{AppSubUrl}}/img/dingtalk.ico">Dingtalk <img class="img-10" src="{{StaticUrlPrefix}}/img/dingtalk.ico">Dingtalk
</a> </a>
<a class="item" href="{{.BaseLink}}/telegram/new"> <a class="item" href="{{.BaseLink}}/telegram/new">
<img class="img-10" src="{{AppSubUrl}}/img/telegram.png">Telegram <img class="img-10" src="{{StaticUrlPrefix}}/img/telegram.png">Telegram
</a> </a>
<a class="item" href="{{.BaseLink}}/msteams/new"> <a class="item" href="{{.BaseLink}}/msteams/new">
<img class="img-10" src="{{AppSubUrl}}/img/msteams.png">Microsoft Teams <img class="img-10" src="{{StaticUrlPrefix}}/img/msteams.png">Microsoft Teams
</a> </a>
</div> </div>
</div> </div>

View file

@ -8,19 +8,19 @@
{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}} {{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{AppSubUrl}}/img/gitea-sm.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{AppSubUrl}}/img/gogs.ico"> <img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{AppSubUrl}}/img/slack.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{AppSubUrl}}/img/discord.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{AppSubUrl}}/img/dingtalk.ico"> <img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.ico">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{AppSubUrl}}/img/telegram.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{AppSubUrl}}/img/msteams.png"> <img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -67,7 +67,7 @@
<strong>{{.i18n.Tr "repo.audio_not_supported_in_browser"}}</strong> <strong>{{.i18n.Tr "repo.audio_not_supported_in_browser"}}</strong>
</audio> </audio>
{{else if .IsPDFFile}} {{else if .IsPDFFile}}
<iframe width="100%" height="600px" src="{{AppSubUrl}}/vendor/plugins/pdfjs/web/viewer.html?file={{EscapePound $.RawFileLink}}"></iframe> <iframe width="100%" height="600px" src="{{StaticUrlPrefix}}/vendor/plugins/pdfjs/web/viewer.html?file={{EscapePound $.RawFileLink}}"></iframe>
{{else}} {{else}}
<a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a> <a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
{{end}} {{end}}

View file

@ -1,7 +1,7 @@
{{template "base/head" .}} {{template "base/head" .}}
{{if .IsRepo}}<div class="repository">{{template "repo/header" .}}</div>{{end}} {{if .IsRepo}}<div class="repository">{{template "repo/header" .}}</div>{{end}}
<div class="ui container center"> <div class="ui container center">
<p style="margin-top: 100px"><img src="{{AppSubUrl}}/img/404.png" alt="404"/></p> <p style="margin-top: 100px"><img src="{{StaticUrlPrefix}}/img/404.png" alt="404"/></p>
<div class="ui divider"></div> <div class="ui divider"></div>
<br> <br>
{{if .ShowFooterVersion}}<p>Application Version: {{AppVer}}</p>{{end}} {{if .ShowFooterVersion}}<p>Application Version: {{AppVer}}</p>{{end}}

View file

@ -1,6 +1,6 @@
{{template "base/head" .}} {{template "base/head" .}}
<div class="ui container center"> <div class="ui container center">
<p style="margin-top: 100px"><img src="{{AppSubUrl}}/img/500.png" alt="500"/></p> <p style="margin-top: 100px"><img src="{{StaticUrlPrefix}}/img/500.png" alt="500"/></p>
<div class="ui divider"></div> <div class="ui divider"></div>
<br> <br>
{{if .ErrorMsg}}<p>An error has occurred :</p> {{if .ErrorMsg}}<p>An error has occurred :</p>

View file

@ -4,9 +4,9 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Swagger UI</title> <title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="{{AppSubUrl}}/vendor/assets/swagger-ui/swagger-ui.css" > <link rel="stylesheet" type="text/css" href="{{StaticUrlPrefix}}/vendor/assets/swagger-ui/swagger-ui.css" >
<link rel="icon" type="image/png" href="{{AppSubUrl}}/vendor/assets/swagger-ui/favicon-32x32.png" sizes="32x32" /> <link rel="icon" type="image/png" href="{{StaticUrlPrefix}}/vendor/assets/swagger-ui/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="{{AppSubUrl}}/vendor/assets/swagger-ui/favicon-16x16.png" sizes="16x16" /> <link rel="icon" type="image/png" href="{{StaticUrlPrefix}}/vendor/assets/swagger-ui/favicon-16x16.png" sizes="16x16" />
<style> <style>
html html
{ {
@ -65,8 +65,8 @@
<div id="swagger-ui"></div> <div id="swagger-ui"></div>
<script src="{{AppSubUrl}}/vendor/assets/swagger-ui/swagger-ui-bundle.js"> </script> <script src="{{StaticUrlPrefix}}/vendor/assets/swagger-ui/swagger-ui-bundle.js"> </script>
<script src="{{AppSubUrl}}/vendor/assets/swagger-ui/swagger-ui-standalone-preset.js"> </script> <script src="{{StaticUrlPrefix}}/vendor/assets/swagger-ui/swagger-ui-standalone-preset.js"> </script>
<script> <script>
window.onload = function() { window.onload = function() {