Add s:render feature for data update rendering (dev)
This commit is contained in:
parent
743339d3d4
commit
a07c1ece51
6 changed files with 158 additions and 19 deletions
|
|
@ -10,6 +10,26 @@ var dsl = []byte(`
|
|||
"guard": "bearer-jwt",
|
||||
"group": "__yao/sui/v1",
|
||||
"paths": [
|
||||
{
|
||||
"label": "Render",
|
||||
"description": "Render the frontend page",
|
||||
"path": "/render/*route",
|
||||
"method": "POST",
|
||||
"guard": "-",
|
||||
"process": "sui.Render",
|
||||
"in": [":context", "$param.route", ":payload"],
|
||||
"out": { "status": 200, "type": "text/html; charset=utf-8" }
|
||||
},
|
||||
{
|
||||
"label": "Run",
|
||||
"description": "Run the backend script, with Api prefix method",
|
||||
"path": "/run/*route",
|
||||
"guard": "-",
|
||||
"method": "POST",
|
||||
"process": "sui.Run",
|
||||
"in": [":context", "$param.route", ":payload"],
|
||||
"out": { "status": 200, "type": "application/json" }
|
||||
},
|
||||
{
|
||||
"path": "/:id/setting",
|
||||
"method": "GET",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ func init() {
|
|||
process.RegisterGroup("sui", map[string]process.Handler{
|
||||
"setting": Setting,
|
||||
|
||||
"render": Render,
|
||||
"run": Run,
|
||||
|
||||
"template.get": TemplateGet,
|
||||
"template.find": TemplateFind,
|
||||
"template.asset": TemplateAsset,
|
||||
|
|
|
|||
104
sui/api/render.go
Normal file
104
sui/api/render.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/gou/process"
|
||||
"github.com/yaoapp/yao/sui/core"
|
||||
)
|
||||
|
||||
// Render the frontend page
|
||||
func Render(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(3)
|
||||
ctx, ok := process.Args[0].(*gin.Context)
|
||||
if !ok {
|
||||
return "The context is required"
|
||||
}
|
||||
|
||||
ctx.Header("Content-Type", "text/html; charset=utf-8")
|
||||
route := process.ArgsString(1)
|
||||
payload := process.ArgsMap(2)
|
||||
|
||||
if route == "" {
|
||||
return "The route is required"
|
||||
}
|
||||
|
||||
if payload["name"] == nil {
|
||||
return "The render name is required"
|
||||
}
|
||||
|
||||
ctx.Request.URL.Path = route
|
||||
r, _, err := NewRequestContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<div class='text-danger'> %s </div>", err.Error())
|
||||
}
|
||||
|
||||
c, _, err := r.MakeCache()
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<div class='text-danger'> %s </div>", err.Error())
|
||||
}
|
||||
|
||||
if c == nil {
|
||||
return fmt.Sprintf("<div class='text-danger'> Cache not found </div>")
|
||||
}
|
||||
|
||||
data, ok := payload["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Sprintf("<div class='text-danger'> Data not found </div>")
|
||||
}
|
||||
|
||||
name, ok := payload["name"].(string)
|
||||
if !ok {
|
||||
return fmt.Sprintf("<div class='text-danger'> Name not found </div>")
|
||||
}
|
||||
|
||||
html, err := r.renderHTML(c, name, c.HTML, core.Data(data))
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<div class='text-danger'> %s </div>", err.Error())
|
||||
}
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
func (r *Request) renderHTML(c *core.Cache, name string, html string, data core.Data) (string, error) {
|
||||
|
||||
doc, err := core.NewDocument([]byte(html))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Document error: %w", err)
|
||||
}
|
||||
|
||||
sel := doc.Find(fmt.Sprintf("[s\\:render='%s']", name))
|
||||
if sel.Length() == 0 {
|
||||
return "", fmt.Errorf("Render %s not found", name)
|
||||
}
|
||||
|
||||
// Set the page request data
|
||||
option := core.ParserOption{
|
||||
Theme: r.Request.Theme,
|
||||
Locale: r.Request.Locale,
|
||||
Debug: r.Request.DebugMode(),
|
||||
DisableCache: r.Request.DisableCache(),
|
||||
Route: r.Request.URL.Path,
|
||||
Root: c.Root,
|
||||
Script: c.Script,
|
||||
Imports: c.Imports,
|
||||
Request: r.Request,
|
||||
}
|
||||
|
||||
// Parse the template
|
||||
parser := core.NewTemplateParser(data, &option)
|
||||
err = parser.RenderSelection(sel)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Parser error: %w", err)
|
||||
}
|
||||
|
||||
sel.Find("[sui-hide]").Remove()
|
||||
parser.Tidy(sel)
|
||||
html, err = sel.Html()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Html error: %w", err)
|
||||
}
|
||||
|
||||
return html, nil
|
||||
}
|
||||
8
sui/api/run.go
Normal file
8
sui/api/run.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package api
|
||||
|
||||
import "github.com/yaoapp/gou/process"
|
||||
|
||||
// Run the backend script, with Api prefix method
|
||||
func Run(process *process.Process) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -284,13 +284,15 @@ const pageEventScriptTmpl = `
|
|||
|
||||
const compEventScriptTmpl = `
|
||||
if (document.querySelector("[s\\:event=%s]")) {
|
||||
document.querySelector("[s\\:event=%s]").addEventListener("%s", function (event) {
|
||||
const dataKeys = %s;
|
||||
const jsonKeys = %s;
|
||||
const root = __sui_component_root(this, "%s");
|
||||
handler = new %s(root).%s;
|
||||
const target = event.target || null;
|
||||
__sui_event_handler(event, dataKeys, jsonKeys, target, root, handler);
|
||||
let elms = document.querySelectorAll("[s\\:event=%s]");
|
||||
elms.forEach(function (element) {
|
||||
element.addEventListener("%s", function (event) {
|
||||
const dataKeys = %s;
|
||||
const jsonKeys = %s;
|
||||
const root = __sui_component_root(element, "%s");
|
||||
handler = new %s(root).%s;
|
||||
__sui_event_handler(event, dataKeys, jsonKeys, element, root, handler);
|
||||
});
|
||||
});
|
||||
}
|
||||
`
|
||||
|
|
|
|||
|
|
@ -68,17 +68,19 @@ var keepWords = map[string]bool{
|
|||
}
|
||||
|
||||
var allowUsePropAttrs = map[string]bool{
|
||||
"s:if": true,
|
||||
"s:elif": true,
|
||||
"s:for": true,
|
||||
"s:event": true,
|
||||
"s:if": true,
|
||||
"s:elif": true,
|
||||
"s:for": true,
|
||||
"s:event": true,
|
||||
"s:render": true,
|
||||
}
|
||||
|
||||
var keepAttrs = map[string]bool{
|
||||
"s:ns": true,
|
||||
"s:cn": true,
|
||||
"s:ready": true,
|
||||
"s:event": true,
|
||||
"s:ns": true,
|
||||
"s:cn": true,
|
||||
"s:ready": true,
|
||||
"s:event": true,
|
||||
"s:render": true,
|
||||
}
|
||||
|
||||
// NewTemplateParser create a new template parser
|
||||
|
|
@ -157,7 +159,7 @@ func (parser *TemplateParser) Render(html string) (string, error) {
|
|||
if parser.option != nil && (parser.option.Request != nil || parser.option.Preview) {
|
||||
// Remove the sui-hide attribute
|
||||
doc.Find("[sui-hide]").Remove()
|
||||
parser.tidy(doc.Selection)
|
||||
parser.Tidy(doc.Selection)
|
||||
}
|
||||
|
||||
// fmt.Println(doc.Html())
|
||||
|
|
@ -837,13 +839,13 @@ func (parser *TemplateParser) show(sel *goquery.Selection) {
|
|||
// sel.SetAttr("style", style)
|
||||
}
|
||||
|
||||
func (parser *TemplateParser) tidy(s *goquery.Selection) {
|
||||
func (parser *TemplateParser) Tidy(s *goquery.Selection) {
|
||||
|
||||
s.Contents().Each(func(i int, child *goquery.Selection) {
|
||||
|
||||
node := child.Get(0)
|
||||
if _, exist := child.Attr("s:jit"); node.Data == "slot" || exist {
|
||||
parser.tidy(child)
|
||||
parser.Tidy(child)
|
||||
parser.removeWrapper(child)
|
||||
return
|
||||
}
|
||||
|
|
@ -872,7 +874,7 @@ func (parser *TemplateParser) tidy(s *goquery.Selection) {
|
|||
}
|
||||
|
||||
node.Attr = attrs
|
||||
parser.tidy(child)
|
||||
parser.Tidy(child)
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue