Commit graph

11 commits

Author SHA1 Message Date
wxiaoguang
722dab5286
Make HTML template functions support context (#24056)
# Background

Golang template is not friendly for large projects, and Golang template
team is quite slow, related:
* `https://github.com/golang/go/issues/54450`

Without upstream support, we can also have our solution to make HTML
template functions support context.

It helps a lot, the above Golang template issue `#54450` explains a lot:

1. It makes `{{Locale.Tr}}` could be used in any template, without
passing unclear `(dict "root" . )` anymore.
2. More and more functions need `context`, like `avatar`, etc, we do not
need to do `(dict "Context" $.Context)` anymore.
3. Many request-related functions could be shared by parent&children
templates, like "user setting" / "system setting"

See the test `TestScopedTemplateSetFuncMap`, one template set, two
`Execute` calls with different `CtxFunc`.

# The Solution

Instead of waiting for upstream, this PR re-uses the escaped HTML
template trees, use `AddParseTree` to add related templates/trees to a
new template instance, then the new template instance can have its own
FuncMap , the function calls in the template trees will always use the
new template's FuncMap.

`template.New` / `template.AddParseTree` / `adding-FuncMap` are all
quite fast, so the performance is not affected.

The details:

1. Make a new `html/template/Template` for `all` templates
2. Add template code to the `all` template
3. Freeze the `all` template, reset its exec func map, it shouldn't
execute any template.
4. When a router wants to render a template by its `name`
    1. Find the `name` in `all`
    2. Find all its related sub templates
3. Escape all related templates (just like what the html template
package does)
4. Add the escaped parse-trees of related templates into a new (scoped)
`text/template/Template`
    5. Add context-related func map into the new (scoped) text template
    6. Execute the new (scoped) text template
7. To improve performance, the escaped templates are cached to `template
sets`

# FAQ

## There is a `unsafe` call, is this PR unsafe?

This PR is safe. Golang has strict language definition, it's safe to do
so: https://pkg.go.dev/unsafe#Pointer (1) Conversion of a *T1 to Pointer
to *T2


## What if Golang template supports such feature in the future?

The public structs/interfaces/functions introduced by this PR is quite
simple, the code of `HTMLRender` is not changed too much. It's very easy
to switch to the official mechanism if there would be one.

## Does this PR change the template execution behavior?

No, see the tests (welcome to design more tests if it's necessary)

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2023-04-20 04:08:58 -04:00
wxiaoguang
1c8bc4081a
Show friendly 500 error page to users and developers (#24110)
Close #24104

This also introduces many tests to cover many complex error handling
functions.

### Before

The details are never shown in production.

<details>

![image](https://user-images.githubusercontent.com/2114189/231805004-13214579-4fbe-465a-821c-be75c2749097.png)

</details>

### After

The details could be shown to site admin users. It is safe.

![image](https://user-images.githubusercontent.com/2114189/231803912-d5660994-416f-4b27-a4f1-a4cc962091d4.png)
2023-04-14 13:19:11 +08:00
wxiaoguang
50a72e7a83
Use a general approach to access custom/static/builtin assets (#24022)
The idea is to use a Layered Asset File-system (modules/assetfs/layered.go)

For example: when there are 2 layers: "custom", "builtin", when access
to asset "my/page.tmpl", the Layered Asset File-system will first try to
use "custom" assets, if not found, then use "builtin" assets.

This approach will hugely simplify a lot of code, make them testable.

Other changes:

* Simplify the AssetsHandlerFunc code
* Simplify the `gitea embedded` sub-command code

---------

Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-04-12 18:16:45 +08:00
wxiaoguang
94fde46151
Make bindata static build parse builtin templates correctly (#24003)
Close #24002


Two problems before:

1. The `log.Fatal` is missing after these `wrapFatal` calls, so the
error is not shown to users.
2. `GetTemplateAssetNames` has different behaviors for local files and
builtin assets, for builtin assets, it also returns directories, so we
need to check the extension again.

I have tested with `TAGS="bindata sqlite sqlite_unlock_notify" make
build && ./gitea` , it works well now. Before, the server responds
internal server error (because it doesn't complete the template parsing)
2023-04-08 21:56:50 +08:00
wxiaoguang
fdbd646113
Group template helper functions, remove Printf, improve template error messages (#23982)
Follow #23328 


Major changes:

* Group the function in `templates/help.go` by their purposes. It could
make future work easier.
* Remove the `Printf` helper function, there is already a builtin
`printf`.
* Remove `DiffStatsWidth`, replace with `Eval` in template
* Rename the `NewTextFuncMap` to `mailSubjectTextFuncMap`, it's for
subject text template only, no need to make it support HTML functions.


----

And fine tune template error messages, to make it more friendly to
developers and users.


![image](https://user-images.githubusercontent.com/2114189/230714245-4fd202d1-2b25-41b2-8be5-03c5fee45091.png)


![image](https://user-images.githubusercontent.com/2114189/230714277-66783577-2a03-49d5-8e8c-ceba5e07a2d4.png)

---------

Co-authored-by: silverwind <me@silverwind.io>
2023-04-08 21:15:22 +08:00
wxiaoguang
8f00979f73
Drop "unrolled/render" package (#23965)
None of the features of `unrolled/render` package is used. 

The Golang builtin "html/template" just works well. Then we can improve
our HTML render to resolve the "$.root.locale.Tr" problem as much as
possible.

Next step: we can have a template render pool (by Clone), then we can
inject global functions with dynamic context to every `Execute` calls.
Then we can use `{{Locale.Tr ....}}` directly in all templates , no need
to pass the `$.root.locale` again and again.
2023-04-08 14:21:50 +08:00
zeripath
8f3aaef374
Improve template error reporting (#23396)
There are multiple duplicate reports of errors during template rendering
due to broken custom templates.

Unfortunately the error returned here is somewhat difficult for users to
understand and it doesn't return the context of the error.

This PR attempts to parse the error returned by the template renderer to
add in some further context including the filename of the template AND
the preceding lines within that template file.

Ref #23274

---------

Signed-off-by: Andrew Thornton <art27@cantab.net>
2023-03-20 15:56:48 -05:00
Lunny Xiao
c59e1537a8
Display error log when a modified template has an error so that it could recovery when the error fixed (#22261)
A drawback is the previous generated template has been cached, so you
cannot get error in the UI but only from log

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: delvh <dev.lh@web.de>
2023-01-03 15:17:36 +08:00
flynnnnnnnnnn
e81ccc406b
Implement FSFE REUSE for golang files (#21840)
Change all license headers to comply with REUSE specification.

Fix #16132

Co-authored-by: flynnnnnnnnnn <flynnnnnnnnnn@github>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2022-11-27 18:20:29 +00:00
zeripath
7d2545d183
Add nicer error handling on template compile errors (#21350)
There are repeated issues reported whereby users are unable to interpret
the template errors. This PR adds some (somewhat complex) error handling
to the panic recovery for template renderering but hopefully makes the
interpretation of the error easier.

Reference #21344

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-10-07 22:02:24 +01:00
zeripath
bb0ff77e46
Share HTML template renderers and create a watcher framework (#20218)
The recovery, API, Web and package frameworks all create their own HTML
Renderers. This increases the memory requirements of Gitea
unnecessarily with duplicate templates being kept in memory.

Further the reloading framework in dev mode for these involves locking
and recompiling all of the templates on each load. This will potentially
hide concurrency issues and it is inefficient.

This PR stores the templates renderer in the context and stores this
context in the NormalRoutes, it then creates a fsnotify.Watcher
framework to watch files.

The watching framework is then extended to the mailer templates which
were previously not being reloaded in dev.

Then the locales are simplified to a similar structure.

Fix #20210 
Fix #20211
Fix #20217

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-08-28 10:43:25 +01:00