diff --git a/sui/api/request.go b/sui/api/request.go
index 90d3f1c7..af060ba7 100644
--- a/sui/api/request.go
+++ b/sui/api/request.go
@@ -167,7 +167,9 @@ func (r *Request) Render() (string, int, error) {
DisableCache: r.Request.DisableCache(),
Route: r.Request.URL.Path,
Root: c.Root,
- Request: true,
+ Script: c.Script,
+ Imports: c.Imports,
+ Request: r.Request,
}
// Parse the template
@@ -249,11 +251,28 @@ func (r *Request) MakeCache() (*core.Cache, int, error) {
globalDataSel.Remove()
}
+ 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 {
+ return nil, 500, fmt.Errorf("imports error, please re-complie the page %s", err.Error())
+ }
+ }
+
html, err := doc.Html()
if err != nil {
return nil, 500, fmt.Errorf("parse error, please re-complie the page %s", err.Error())
}
+ // Backend script
+ script, err := core.LoadScript(r.File)
+ if err != nil {
+ return nil, 500, fmt.Errorf("script error, please re-complie the page %s", err.Error())
+ }
+
// Save to The Cache
cache := &core.Cache{
Data: dataText,
@@ -266,6 +285,8 @@ func (r *Request) MakeCache() (*core.Cache, int, error) {
Root: root,
CacheTime: time.Duration(cacheTime) * time.Second,
DataCacheTime: time.Duration(dataCacheTime) * time.Second,
+ Script: script,
+ Imports: imports,
}
go core.SetCache(r.File, cache)
diff --git a/sui/api/request_test.go b/sui/api/request_test.go
index ea8e0936..d08cffb4 100644
--- a/sui/api/request_test.go
+++ b/sui/api/request_test.go
@@ -71,7 +71,7 @@ func makeParser(route string, t *testing.T) (*core.TemplateParser, string, core.
Debug: r.Request.DebugMode(),
DisableCache: r.Request.DisableCache(),
Route: r.Request.URL.Path,
- Request: true,
+ Request: r.Request,
}
// Parse the template
diff --git a/sui/core/build.go b/sui/core/build.go
index c8136361..4e8b392c 100644
--- a/sui/core/build.go
+++ b/sui/core/build.go
@@ -236,7 +236,7 @@ func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, op
ctx.styles = append(ctx.styles, styles...)
sel.ReplaceWithSelection(body.Contents())
- ctx.components[page.Route] = true
+ ctx.components[component] = page.Route
return source, nil
}
@@ -456,7 +456,6 @@ func (page *Page) buildComponents(doc *goquery.Document, ctx *BuildContext, opti
return warnings, fmt.Errorf("SUI %s not found", page.SuiID)
}
- public := sui.GetPublic()
tmpl, err := sui.GetTemplate(page.TemplateID)
if err != nil {
return warnings, err
@@ -480,7 +479,6 @@ func (page *Page) buildComponents(doc *goquery.Document, ctx *BuildContext, opti
if ctx.isJitComponent(name) {
sel.SetAttr("s:jit", "true")
sel.SetAttr("s:parent", page.namespace)
- sel.SetAttr("s:root", public.Root)
ctx.addJitComponent(name)
return
}
@@ -589,6 +587,16 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
}
injectScript := componentInitScript(arguments)
+ // Get the Constants and Helpers
+ var err error = nil
+ constants := ""
+ if page.Script != nil {
+ constants, err = page.Script.ConstantsToString()
+ if err != nil {
+ return nil, err
+ }
+ }
+
scripts := []ScriptNode{}
if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" {
return scripts, nil
@@ -599,7 +607,6 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
ctx.scriptUnique[component] = true
- var err error = nil
var imports []string = nil
var source []byte = nil
if page.Codes.TS.Code != "" {
@@ -639,6 +646,10 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
})
code := string(source)
+ if constants != "" {
+ code = fmt.Sprintf("this.Constants = %s\n%s", constants, code)
+ }
+
parent := "body"
if !ispage {
parent = "head"
diff --git a/sui/core/cache.go b/sui/core/cache.go
index 544ee3aa..e902be51 100644
--- a/sui/core/cache.go
+++ b/sui/core/cache.go
@@ -4,7 +4,6 @@ import (
"time"
jsoniter "github.com/json-iterator/go"
- v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/gou/store"
"github.com/yaoapp/kun/log"
)
@@ -21,7 +20,8 @@ type Cache struct {
CacheStore string
CacheTime time.Duration
DataCacheTime time.Duration
- Script *v8.Script // the backend script
+ Script *Script
+ Imports map[string]string
}
const (
@@ -73,6 +73,7 @@ func GetCache(file string) *Cache {
// RemoveCache remove the cache
func RemoveCache(file string) {
ch <- &cacheData{file, nil, removeCache}
+ chScript <- &scriptData{file, nil, removeScript}
}
// CleanCache clean the cache
diff --git a/sui/core/compile.go b/sui/core/compile.go
index 83986c33..3624c373 100644
--- a/sui/core/compile.go
+++ b/sui/core/compile.go
@@ -93,14 +93,10 @@ func (page *Page) Compile(ctx *BuildContext, option *BuildOption) (string, []str
}
// Page Components
- components := []string{}
if ctx != nil && ctx.components != nil && len(ctx.components) > 0 {
- for route := range ctx.components {
- components = append(components, route)
- }
+ rawComponents, _ := jsoniter.MarshalToString(ctx.components)
+ body.AppendHtml("\n\n" + `\n\n")
}
- rawComponents, _ := jsoniter.MarshalToString(components)
- body.AppendHtml("\n\n" + `\n\n")
page.ReplaceDocument(doc)
html, err := doc.Html()
diff --git a/sui/core/context.go b/sui/core/context.go
index f8b78b05..c7c1b483 100644
--- a/sui/core/context.go
+++ b/sui/core/context.go
@@ -3,7 +3,7 @@ package core
// NewBuildContext create a new build context
func NewBuildContext(global *GlobalBuildContext) *BuildContext {
return &BuildContext{
- components: map[string]bool{},
+ components: map[string]string{},
sequence: 1,
scripts: []ScriptNode{},
scriptUnique: map[string]bool{},
diff --git a/sui/core/injections.go b/sui/core/injections.go
index afd08b2c..99efe181 100644
--- a/sui/core/injections.go
+++ b/sui/core/injections.go
@@ -186,6 +186,21 @@ const componentInitScriptTmpl = `
this.store = new __sui_store(this.root);
`
+// Inject code
+const backendScriptTmpl = `
+this.__sui_page = '%s';
+this.__sui_constants = {};
+this.__sui_helpers = [];
+
+if (typeof Helpers === 'object') {
+ this.__sui_helpers = Object.keys(Helpers);
+}
+
+if (typeof Constants === 'object') {
+ this.__sui_constants = Constants;
+}
+`
+
func bodyInjectionScript(jsonRaw string, debug bool) string {
jsPrintData := ""
if debug {
@@ -209,3 +224,8 @@ func compEventInjectScript(eventID, eventName, component, dataKeys, jsonKeys, ha
func componentInitScript(root string) string {
return fmt.Sprintf(componentInitScriptTmpl, root)
}
+
+// BackendScript inject the backend script
+func BackendScript(route string) string {
+ return fmt.Sprintf(backendScriptTmpl, route)
+}
diff --git a/sui/core/jit.go b/sui/core/jit.go
index 64737c86..32d3a590 100644
--- a/sui/core/jit.go
+++ b/sui/core/jit.go
@@ -45,7 +45,7 @@ func init() {
}
// parseComponent parse the component
-func (parser *TemplateParser) parseComponent(sel *goquery.Selection) {
+func (parser *TemplateParser) parseJitComponent(sel *goquery.Selection) {
parser.parsed(sel)
comp, props, slots, children, err := parser.getComponent(sel)
if err != nil {
@@ -218,8 +218,8 @@ func (parser *TemplateParser) getComponent(sel *goquery.Selection) (*JitComponen
return comp, props, slots, children, nil
}
-// isComponent check if the selection is a component
-func (parser *TemplateParser) isComponent(sel *goquery.Selection) bool {
+// isJitComponent check if the selection is a component
+func (parser *TemplateParser) isJitComponent(sel *goquery.Selection) bool {
_, exist := sel.Attr("s:jit")
is := sel.AttrOr("is", "")
return exist && is != ""
@@ -314,8 +314,7 @@ func (parser *TemplateParser) componentFile(sel *goquery.Selection, props map[st
data := Data{"$props": props}
route, _ = data.ReplaceUse(slotRe, route)
route, _ = parser.data.Replace(route)
- root := sel.AttrOr("s:root", "/")
- file := filepath.Join(string(os.PathSeparator), "public", root, route+".jit")
+ file := filepath.Join(string(os.PathSeparator), "public", parser.option.Root, route+".jit")
return file, route, nil
}
diff --git a/sui/core/parser.go b/sui/core/parser.go
index 3b6be196..286eba1a 100644
--- a/sui/core/parser.go
+++ b/sui/core/parser.go
@@ -2,6 +2,8 @@ package core
import (
"fmt"
+ "os"
+ "path/filepath"
"strings"
"github.com/PuerkitoBio/goquery"
@@ -40,16 +42,18 @@ type Mapping struct {
// ParserOption parser option
type ParserOption struct {
- Component bool `json:"component,omitempty"`
- Editor bool `json:"editor,omitempty"`
- Preview bool `json:"preview,omitempty"`
- Debug bool `json:"debug,omitempty"`
- DisableCache bool `json:"disableCache,omitempty"`
- Request bool `json:"request,omitempty"`
- Route string `json:"route,omitempty"`
- Theme any `json:"theme,omitempty"`
- Locale any `json:"locale,omitempty"`
- Root string `json:"root,omitempty"`
+ Component bool `json:"component,omitempty"`
+ Editor bool `json:"editor,omitempty"`
+ Preview bool `json:"preview,omitempty"`
+ Debug bool `json:"debug,omitempty"`
+ DisableCache bool `json:"disableCache,omitempty"`
+ Route string `json:"route,omitempty"`
+ Theme any `json:"theme,omitempty"`
+ Locale any `json:"locale,omitempty"`
+ Root string `json:"root,omitempty"`
+ Imports map[string]string `json:"imports,omitempty"`
+ Script *Script `json:"-"` // backend script
+ Request *Request `json:"request,omitempty"`
}
var keepWords = map[string]bool{
@@ -98,9 +102,6 @@ func NewTemplateParser(data Data, option *ParserOption) *TemplateParser {
// Render parses and renders the HTML template
func (parser *TemplateParser) Render(html string) (string, error) {
- // Set the locale
- parser.locale = parser.Locale()
-
if !strings.Contains(html, "%s`, html)
}
@@ -110,13 +111,11 @@ func (parser *TemplateParser) Render(html string) (string, error) {
return "", err
}
- root := doc.Selection.Find("html")
- parser.parseNode(root.Nodes[0])
-
- // Replace the nodes
- for sel, nodes := range parser.replace {
- sel.ReplaceWithNodes(nodes...)
- delete(parser.replace, sel)
+ // Set the locale
+ parser.locale = parser.Locale()
+ err = parser.RenderSelection(doc.Selection)
+ if err != nil {
+ return "", err
}
// Append the head
@@ -149,16 +148,13 @@ func (parser *TemplateParser) Render(html string) (string, error) {
parser.addScripts(body, parser.filterScripts("body", parser.scripts))
}
- // Fmt
- parser.Fmt(doc)
-
// For editor
if parser.option != nil && parser.option.Editor {
return doc.Find("body").Html()
}
// For Request
- if parser.option != nil && (parser.option.Request || parser.option.Preview) {
+ 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)
@@ -169,8 +165,26 @@ func (parser *TemplateParser) Render(html string) (string, error) {
return doc.Html()
}
+// RenderSelection parses and renders the HTML template
+func (parser *TemplateParser) RenderSelection(section *goquery.Selection) error {
+
+ if len(section.Nodes) == 0 {
+ return fmt.Errorf("No nodes found")
+ }
+
+ parser.parseNode(section.Nodes[0])
+ // Replace the nodes
+ for sel, nodes := range parser.replace {
+ sel.ReplaceWithNodes(nodes...)
+ delete(parser.replace, sel)
+ }
+
+ parser.Fmt(section)
+ return nil
+}
+
// Fmt formats the HTML template
-func (parser *TemplateParser) Fmt(doc *goquery.Document) {
+func (parser *TemplateParser) Fmt(doc *goquery.Selection) {
if parser.locale != nil {
sels := doc.Find(`[s\:trans-fmt]`)
sels.Each(func(i int, sel *goquery.Selection) {
@@ -193,10 +207,8 @@ func (parser *TemplateParser) parseNode(node *html.Node) {
}
parser.parseElementNode(sel)
- // Skip children if the node is a loop node
- if _, exist := sel.Attr("s:for"); exist {
- skipChildren = true
- }
+ // Skip children if the node is a loop nodećelement component or JIT component
+ skipChildren = parser.hasForStatement(sel) || parser.isElementComponent(sel) || parser.isJitComponent(sel)
case html.TextNode:
parser.parseTextNode(node)
@@ -228,13 +240,86 @@ func (parser *TemplateParser) parseElementNode(sel *goquery.Selection) {
parser.setStatementNode(sel)
}
- // JIT Compile the element
- if parser.isComponent(sel) {
- parser.parseComponent(sel)
- }
-
// Parse the attributes
parser.parseElementAttrs(sel)
+
+ // if the element is a component
+ if parser.isElementComponent(sel) {
+ parser.parseElementComponent(sel)
+ }
+
+ // JIT Compile the element
+ if parser.isJitComponent(sel) {
+ parser.parseJitComponent(sel)
+ }
+}
+
+func (parser *TemplateParser) parseElementComponent(sel *goquery.Selection) {
+
+ sel.SetAttr("parsed", "true")
+ com := sel.AttrOr("s:cn", "")
+ props := map[string]string{}
+ for _, attr := range sel.Nodes[0].Attr {
+ if !strings.HasPrefix(attr.Key, "s:") && attr.Key != "parsed" {
+ props[attr.Key] = attr.Val
+ }
+ }
+
+ // load the component based on the route
+ var script *Script
+ var err error
+ if parser.option.Imports != nil {
+ if route, has := parser.option.Imports[com]; has {
+ file := filepath.Join(string(os.PathSeparator), "public", parser.option.Root, route)
+ script, err = LoadScript(file)
+ if err != nil {
+ parser.errors = append(parser.errors, err)
+ setError(sel, err)
+ return
+ }
+ }
+ }
+
+ compParser := parser.clone(script)
+
+ // Call the BeforeRender Hook
+ if script != nil {
+ data, err := script.BeforeRender(parser.option.Request, props)
+ if err != nil {
+ parser.errors = append(parser.errors, err)
+ setError(sel, err)
+ return
+ }
+ if data != nil {
+ for k, v := range data {
+ compParser.data[k] = v
+ }
+ }
+ }
+
+ err = compParser.RenderSelection(sel)
+ if err != nil {
+ parser.errors = append(parser.errors, err)
+ setError(sel, err)
+ }
+ parser.sequence = parser.sequence + 1
+}
+
+func (parser *TemplateParser) clone(script *Script) *TemplateParser {
+ var new = *parser
+ new.data = Data{}
+ for k, v := range parser.data {
+ new.data[k] = v
+ }
+ new.option.Script = script
+ return &new
+}
+
+func (parser *TemplateParser) isElementComponent(sel *goquery.Selection) bool {
+ if comp, exist := sel.Attr("s:cn"); exist && comp != "" && sel.Nodes[0].Data != "script" {
+ return true
+ }
+ return false
}
func (parser *TemplateParser) transTextNode(node *html.Node) {
@@ -485,6 +570,12 @@ func (parser *TemplateParser) parseTextNode(node *html.Node) {
}
node.Data = res
}
+func (parser *TemplateParser) hasForStatement(sel *goquery.Selection) bool {
+ if _, exist := sel.Attr("s:for"); exist {
+ return true
+ }
+ return false
+}
func (parser *TemplateParser) forStatementNode(sel *goquery.Selection) {
diff --git a/sui/core/script.go b/sui/core/script.go
new file mode 100644
index 00000000..e16dc8d4
--- /dev/null
+++ b/sui/core/script.go
@@ -0,0 +1,216 @@
+package core
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/google/uuid"
+ jsoniter "github.com/json-iterator/go"
+ "github.com/yaoapp/gou/application"
+ v8 "github.com/yaoapp/gou/runtime/v8"
+ "github.com/yaoapp/gou/runtime/v8/bridge"
+)
+
+// Scripts loaded scripts
+var Scripts = map[string]*Script{}
+
+const (
+ saveScript uint8 = iota
+ removeScript
+)
+
+// Script the script
+type Script struct {
+ *v8.Script
+}
+
+type scriptData struct {
+ file string
+ script *Script
+ cmd uint8
+}
+
+var chScript = make(chan *scriptData, 1)
+
+func init() {
+ go scriptWriter()
+}
+
+func scriptWriter() {
+ for {
+ select {
+ case data := <-chScript:
+ switch data.cmd {
+ case saveScript:
+ Scripts[data.file] = data.script
+ case removeScript:
+ delete(Scripts, data.file)
+ }
+ }
+ }
+}
+
+// LoadScript load the script
+func LoadScript(file string) (*Script, error) {
+
+ if script, has := Scripts[file]; has {
+ return script, nil
+ }
+
+ base := strings.TrimSuffix(file, ".sui")
+ file = base + ".ts"
+ if exist, _ := application.App.Exists(file); !exist {
+ file = base + ".js"
+ }
+
+ if exist, _ := application.App.Exists(file); !exist {
+ return nil, nil
+ }
+
+ source, err := application.App.Read(file)
+ if err != nil {
+ return nil, err
+ }
+
+ v8script, err := v8.MakeScript(source, file, 5*time.Second)
+ if err != nil {
+ return nil, err
+ }
+
+ script := &Script{Script: v8script}
+ chScript <- &scriptData{file, script, saveScript}
+ return script, nil
+}
+
+// Call the script method
+// This will be refactored to improve the performance
+func (script *Script) Call(r *Request, method string, args ...any) (interface{}, error) {
+ ctx, err := script.NewContext(r.Sid, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer ctx.Close()
+
+ res, err := ctx.Call(method, args...)
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+}
+
+// BeforeRender the script method
+func (script *Script) BeforeRender(r *Request, props map[string]string) (Data, error) {
+
+ ctx, err := script.NewContext(r.Sid, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer ctx.Close()
+
+ if !ctx.Global().Has("BeforeRender") {
+ return nil, nil
+ }
+
+ res, err := ctx.Call("BeforeRender", r, props)
+ if err != nil {
+ return nil, err
+ }
+
+ if data, ok := res.(map[string]interface{}); ok {
+ return data, nil
+ }
+
+ return nil, fmt.Errorf("BeforeRender return %v should be Record", res)
+}
+
+// ConstantsToString get the constants from the script
+func (script *Script) ConstantsToString() (string, error) {
+ constants, err := script.Constants()
+ if err != nil {
+ return "", err
+ }
+ raw, err := jsoniter.MarshalToString(constants)
+ if err != nil {
+ return "", err
+ }
+ return raw, nil
+}
+
+// Constants get the constants from the script
+// This will be refactored to improve the performance
+func (script *Script) Constants() (map[string]interface{}, error) {
+ uuid := uuid.New().String()
+ ctx, err := script.NewContext(uuid, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer ctx.Close()
+
+ global := ctx.Global()
+ if global == nil {
+ return nil, fmt.Errorf("global is nil")
+ }
+
+ if !global.Has("__sui_constants") {
+ return nil, nil
+ }
+
+ res, err := global.Get("__sui_constants")
+ if err != nil {
+ return nil, err
+ }
+ defer res.Release()
+
+ goValues, err := bridge.GoValue(res, ctx.Context)
+ if err != nil {
+ return nil, err
+ }
+
+ if constants, ok := goValues.(map[string]interface{}); ok {
+ return constants, nil
+ }
+
+ return nil, fmt.Errorf("constants is %v should be Record", goValues)
+}
+
+// Helpers get the helpers from the script
+// This will be refactored to improve the performance
+func (script *Script) Helpers() ([]string, error) {
+ uuid := uuid.New().String()
+ ctx, err := script.NewContext(uuid, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer ctx.Close()
+
+ global := ctx.Global()
+ if global == nil {
+ return nil, fmt.Errorf("global is nil")
+ }
+
+ if !global.Has("__sui_helpers") {
+ return nil, nil
+ }
+
+ res, err := global.Get("__sui_helpers")
+ if err != nil {
+ return nil, err
+ }
+ defer res.Release()
+
+ goValues, err := bridge.GoValue(res, ctx.Context)
+ if err != nil {
+ return nil, err
+ }
+
+ if helpers, ok := goValues.([]interface{}); ok {
+ methods := []string{}
+ for _, key := range helpers {
+ methods = append(methods, fmt.Sprintf("%v", key))
+ }
+ return methods, nil
+ }
+
+ return nil, fmt.Errorf("helpers is %v should be []string", goValues)
+}
diff --git a/sui/core/types.go b/sui/core/types.go
index fbc61d9c..5d0ed685 100644
--- a/sui/core/types.go
+++ b/sui/core/types.go
@@ -5,7 +5,6 @@ import (
"regexp"
"github.com/PuerkitoBio/goquery"
- v8 "github.com/yaoapp/gou/runtime/v8"
"golang.org/x/net/html"
)
@@ -39,7 +38,7 @@ type Page struct {
Path string `json:"-"`
Root string `json:"-"`
Codes SourceCodes `json:"-"`
- Script *v8.Script `json:"-"` // The backend script name.backend.ts / name.backend.js
+ Script *Script `json:"-"` // The backend script name.backend.ts / name.backend.js
Document []byte `json:"-"`
GlobalData []byte `json:"-"`
Attrs map[string]string `json:"-"`
@@ -60,7 +59,7 @@ type PageProp struct {
// BuildContext is the struct for the build context
type BuildContext struct {
- components map[string]bool
+ components map[string]string
jitComponents map[string]bool
sequence int
doc *goquery.Document
@@ -179,8 +178,8 @@ type Template struct {
GlobalData []byte `json:"-"`
Scripts *TemplateScirpts `json:"scripts,omitempty"`
Translator string `json:"translator,omitempty"`
- BuildScript *v8.Script `json:"-"` // __build.backend.ts / __build.backend.js
- GlobalScript *v8.Script `json:"-"` // __global.backend.ts / __global.backend.js
+ BuildScript *Script `json:"-"` // __build.backend.ts / __build.backend.js
+ GlobalScript *Script `json:"-"` // __global.backend.ts / __global.backend.js
}
// TemplateScirpts is the struct for the template scripts
diff --git a/sui/storages/local/build.go b/sui/storages/local/build.go
index 009280bc..f9800dc9 100644
--- a/sui/storages/local/build.go
+++ b/sui/storages/local/build.go
@@ -5,10 +5,12 @@ import (
"os"
"path/filepath"
"strings"
+ "time"
"github.com/hashicorp/go-multierror"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/process"
+ v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
"golang.org/x/text/language"
@@ -338,7 +340,6 @@ func (tmpl *Template) getLocale(name string, route string, pageOnly ...bool) cor
func (page *Page) Build(globalCtx *core.GlobalBuildContext, option *core.BuildOption) ([]string, error) {
ctx := core.NewBuildContext(globalCtx)
-
var err error = nil
root := option.PublicRoot
if root == "" {
@@ -656,9 +657,29 @@ func (page *Page) backendScriptSource() (string, []byte, error) {
return "", nil, err
}
+ source = []byte(fmt.Sprintf("%s\n%s", source, core.BackendScript(page.Route)))
return backendFile, source, nil
}
+func (page *Page) loadBackendScript() error {
+ file, source, err := page.backendScriptSource()
+ if err != nil {
+ return err
+ }
+
+ if source == nil {
+ return nil
+ }
+ approot := page.tmpl.local.AppRoot()
+ file = filepath.Join(approot, file)
+ script, err := v8.MakeScript(source, file, 5*time.Second)
+ if err != nil {
+ return err
+ }
+ page.Script = &core.Script{Script: script}
+ return nil
+}
+
func (page *Page) writeBackendScript(data map[string]interface{}) error {
file, source, err := page.backendScriptSource()
diff --git a/sui/storages/local/page.go b/sui/storages/local/page.go
index aa8caf7a..841be543 100644
--- a/sui/storages/local/page.go
+++ b/sui/storages/local/page.go
@@ -453,6 +453,13 @@ func (page *Page) Load() error {
// Set the page global data
page.GlobalData = page.tmpl.GlobalData
+
+ // Load the backend script
+ err := page.loadBackendScript()
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/sui/storages/local/template.go b/sui/storages/local/template.go
index 5d2ef00f..52894d72 100644
--- a/sui/storages/local/template.go
+++ b/sui/storages/local/template.go
@@ -103,7 +103,7 @@ func (tmpl *Template) loadBuildScript() error {
if err != nil {
return err
}
- tmpl.BuildScript = script
+ tmpl.BuildScript = &core.Script{Script: script}
return nil
}