diff --git a/sui/api/guards.go b/sui/api/guards.go
index 9d90ca97..bfde62c1 100644
--- a/sui/api/guards.go
+++ b/sui/api/guards.go
@@ -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]
diff --git a/sui/api/process.go b/sui/api/process.go
index 093f1d09..b116d374 100644
--- a/sui/api/process.go
+++ b/sui/api/process.go
@@ -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,
diff --git a/sui/api/render.go b/sui/api/render.go
index 211d0ccb..278b1d68 100644
--- a/sui/api/render.go
+++ b/sui/api/render.go
@@ -2,9 +2,12 @@ package api
import (
"fmt"
+ "path/filepath"
"github.com/gin-gonic/gin"
+ jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/process"
+ "github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/sui/core"
)
@@ -115,3 +118,90 @@ 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()
+ }
+
+ opt := process.ArgsMap(4, map[string]interface{}{})
+ buildOptionData, ok := opt["data"].(map[string]interface{})
+ if !ok {
+ buildOptionData = map[string]interface{}{}
+ }
+
+ root, err := sui.PublicRoot(buildOptionData)
+ if err != nil {
+ exception.New(err.Error(), 500).Throw()
+ }
+ assetRoot := filepath.Join(root, "assets")
+
+ source := process.ArgsString(2)
+ page := tmpl.CreatePage(source)
+ route := page.Get().Route
+ globalCtx := core.NewGlobalBuildContext()
+ suicode, _, err := page.Get().CompileAsComponent(core.NewBuildContext(globalCtx), &core.BuildOption{
+ PublicRoot: root,
+ AssetRoot: assetRoot,
+ IgnoreDocument: true,
+ Data: buildOptionData,
+ })
+ if err != nil {
+ exception.New(err.Error(), 500).Throw()
+ return nil
+ }
+
+ doc, err := core.NewDocument([]byte(suicode))
+ if err != nil {
+ exception.New(err.Error(), 500).Throw()
+ return nil
+ }
+
+ var imports map[string]string
+ importsSel := doc.Find("script[name=imports]")
+ if importsSel != nil && importsSel.Length() > 0 {
+ importsRaw := importsSel.Text()
+ importsSel.Remove()
+ err := jsoniter.UnmarshalFromString(importsRaw, &imports)
+ if err != nil {
+ exception.New(err.Error(), 500).Throw()
+ return nil
+ }
+ }
+
+ data := process.ArgsMap(3)
+ option := core.ParserOption{
+ Theme: opt["theme"],
+ Locale: opt["locale"],
+ Debug: false,
+ DisableCache: true,
+ Route: route,
+ Root: root,
+ Script: nil,
+ Imports: imports,
+ Request: &core.Request{
+ Theme: opt["theme"],
+ Locale: opt["locale"],
+ },
+ }
+
+ 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
+}
diff --git a/sui/api/render_test.go b/sui/api/render_test.go
new file mode 100644
index 00000000..253d03d4
--- /dev/null
+++ b/sui/api/render_test.go
@@ -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", "
{{ name}}
", 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.Contains(t, res, " test ")
+}
+
+func TestTemplateRenderWithComponent(t *testing.T) {
+ prepare(t)
+ defer clean()
+ source := `
+
+
Component Render {{ name }}
+
+
+
+ {{ upper(item) }} {{ name }}
+
+
+
+
+ `
+ 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")
+}
diff --git a/sui/core/interfaces.go b/sui/core/interfaces.go
index 7149cba7..59eb5ddd 100644
--- a/sui/core/interfaces.go
+++ b/sui/core/interfaces.go
@@ -29,6 +29,7 @@ type SUI interface {
PublicRootMatcher() *Matcher
GetPublic() *Public
PublicRootWithSid(sid string) (string, error)
+ PublicRoot(data map[string]any) (string, error)
}
// ITemplate is the interface for the ITemplate
@@ -37,6 +38,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)
diff --git a/sui/core/script.go b/sui/core/script.go
index 51a89c9b..6f3eb274 100644
--- a/sui/core/script.go
+++ b/sui/core/script.go
@@ -98,6 +98,8 @@ func (script *Script) Call(r *Request, method string, args ...any) (interface{},
}
defer ctx.Close()
+ // Set the sid
+ ctx.Sid = r.Sid
res, err := ctx.Call(method, args...)
if err != nil {
return nil, err
@@ -118,6 +120,8 @@ func (script *Script) BeforeRender(r *Request, props map[string]interface{}) (Da
return nil, nil
}
+ // Set the sid
+ ctx.Sid = r.Sid
res, err := ctx.Call("BeforeRender", r, props)
if err != nil {
return nil, err
diff --git a/sui/storages/local/page.go b/sui/storages/local/page.go
index 841be543..2ed568c3 100644
--- a/sui/storages/local/page.go
+++ b/sui/storages/local/page.go
@@ -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) {
diff --git a/sui/storages/local/page_test.go b/sui/storages/local/page_test.go
index 62badeed..351bbce1 100644
--- a/sui/storages/local/page_test.go
+++ b/sui/storages/local/page_test.go
@@ -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("
Test
")
+ 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, "
Test
", html)
+}