[feat] add SUI template.render process

This commit is contained in:
Max 2024-08-10 16:58:38 +08:00
parent f531b32634
commit 80779bb0fc
7 changed files with 183 additions and 5 deletions

View file

@ -399,9 +399,6 @@ func (r *Request) scriptGuardExec(c *gin.Context, name string, args []interface{
message := err.Error()
if strings.HasPrefix(message, "Exception|") {
parts := strings.Split(message, ": ")
fmt.Println(parts)
if len(parts) > 1 {
codestr := strings.TrimPrefix(parts[0], "Exception|")
message := parts[1]

View file

@ -20,13 +20,15 @@ func init() {
process.RegisterGroup("sui", map[string]process.Handler{
"setting": Setting,
"render": Render,
"run": Run,
"render": Render, // do not use this in script or flow, this is an internal method. Use the template.render instead
"run": Run, // do not use this in script or flow, this is an internal method. Use the template.run instead
"template.get": TemplateGet,
"template.find": TemplateFind,
"template.asset": TemplateAsset,
"template.assetupload": TemplateAssetUpload,
"template.render": TemplateRender,
// "template.run": TemplateRun,
"locale.get": LocaleGet,
"theme.get": ThemeGet,

View file

@ -5,6 +5,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/sui/core"
)
@ -115,3 +116,61 @@ func (r *Request) renderHTML(c *core.Cache, name string, html string, data core.
return html, nil
}
// TemplateRender render the template asset
func TemplateRender(process *process.Process) interface{} {
process.ValidateArgNums(4)
sui := get(process)
tmpl, err := sui.GetTemplate(process.ArgsString(1))
if err != nil {
exception.New(err.Error(), 500).Throw()
}
root, err := sui.PublicRootWithSid(process.Sid)
if err != nil {
exception.New(err.Error(), 500).Throw()
}
source := process.ArgsString(2)
page := tmpl.CreatePage(source)
route := page.Get().Route
doc, _, err := page.Get().Build(core.NewBuildContext(nil), &core.BuildOption{
PublicRoot: root,
IgnoreDocument: true,
JitMode: true,
})
if err != nil {
exception.New(err.Error(), 500).Throw()
return nil
}
data := process.ArgsMap(3)
opt := process.ArgsMap(4, map[string]interface{}{})
option := core.ParserOption{
Theme: opt["theme"],
Locale: opt["locale"],
Debug: false,
DisableCache: true,
Route: route,
Root: root,
Script: nil,
Imports: nil,
Request: nil,
}
parser := core.NewTemplateParser(core.Data(data), &option)
sel := doc.Find("body")
err = parser.RenderSelection(sel)
if err != nil {
exception.New(err.Error(), 500).Throw()
}
sel.Find("[sui-hide]").Remove()
parser.Tidy(sel)
html, err := sel.Html()
if err != nil {
exception.New(err.Error(), 500).Throw()
}
return html
}

62
sui/api/render_test.go Normal file
View file

@ -0,0 +1,62 @@
package api
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou/process"
)
func TestTemplateRender(t *testing.T) {
prepare(t)
defer clean()
args := []any{"test", "advanced", "<div> {{ name}} </div>", map[string]any{"name": "test"}}
p, err := process.Of("sui.template.render", args...)
if err != nil {
t.Fatal(err)
}
res, err := p.Exec()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "<div> test </div>", res)
}
func TestTemplateRenderWithComponent(t *testing.T) {
prepare(t)
defer clean()
source := `
<div>
<h2>Component Render {{ name }} </h2>
<div style="display: flex; gap: 20px">
<div s:for="{{ ['foo', 'bar'] }}">
<Component
is="/backend/{{ item }}"
world="World"
hello="{{ hello }}"
index="{{ index }}"
pets="{{ ['cat', 'dog'] }}"
>
{{ upper(item) }} {{ name }}
</Component>
</div>
</div>
</div>
`
args := []any{"test", "advanced", source, map[string]any{"name": "test"}, map[string]any{"theme": "dark"}}
p, err := process.Of("sui.template.render", args...)
if err != nil {
t.Fatal(err)
}
res, err := p.Exec()
if err != nil {
t.Fatal(err)
}
assert.Contains(t, res, "Component Render test")
assert.Contains(t, res, "FOO test")
assert.Contains(t, res, "BAR test")
}

View file

@ -37,6 +37,7 @@ type ITemplate interface {
PageTree(route string) ([]*PageTreeNode, error)
Page(route string) (IPage, error)
PageExist(route string) bool
CreatePage(html string) IPage
CreateEmptyPage(route string, setting *PageSetting) (IPage, error)
RemovePage(route string) error
GetPageFromAsset(asset string) (IPage, error)

View file

@ -5,6 +5,7 @@ import (
"path/filepath"
"strings"
"github.com/google/uuid"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
@ -268,6 +269,30 @@ func (page *Page) SaveAs(route string, setting *core.PageSetting) (core.IPage, e
return page.tmpl.Page(route)
}
// CreatePage create a new page by the source
func (tmpl *Template) CreatePage(source string) core.IPage {
name := uuid.New().String()
route := "/" + uuid.New().String()
return &Page{
tmpl: tmpl,
Page: &core.Page{
Route: route,
TemplateID: tmpl.ID,
SuiID: tmpl.local.ID,
Path: filepath.Join(tmpl.Root, route),
Name: name,
Codes: core.SourceCodes{
HTML: core.Source{File: fmt.Sprintf("%s.html", name), Code: source},
CSS: core.Source{File: fmt.Sprintf("%s.css", name)},
JS: core.Source{File: fmt.Sprintf("%s.js", name)},
TS: core.Source{File: fmt.Sprintf("%s.ts", name)},
LESS: core.Source{File: fmt.Sprintf("%s.less", name)},
CONF: core.Source{File: fmt.Sprintf("%s.config", name)},
},
},
}
}
// CreateEmptyPage create a new empty
func (tmpl *Template) CreateEmptyPage(route string, setting *core.PageSetting) (core.IPage, error) {
if tmpl.PageExist(route) {

View file

@ -590,3 +590,35 @@ func TestPageAssetStyle(t *testing.T) {
assert.NotEmpty(t, asset.Content)
assert.Equal(t, "text/css; charset=utf-8", asset.Type)
}
func TestCreatePage(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Test.GetTemplate("advanced")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
page := tmpl.CreatePage("<div>Test</div>")
if page == nil {
t.Fatalf("CreatePage error")
}
doc, _, err := page.Get().Build(core.NewBuildContext(nil), &core.BuildOption{
PublicRoot: tmpl.GetRoot(),
IgnoreDocument: true,
JitMode: true,
})
if err != nil {
t.Fatalf("Compile error: %v", err)
}
sel := doc.Find("body")
html, err := sel.Html()
if err != nil {
t.Fatalf("Html error: %v", err)
}
assert.Equal(t, "<div>Test</div>", html)
}