- Update NewGlobalBuildContext to accept a template parameter for improved context management. - Refactor component handling in Compile method to include JIT components, enhancing dynamic component loading. - Modify TemplateRender to utilize the updated global context, improving template processing. - Adjust component attribute parsing to use "s:route" for better clarity in component identification.
803 lines
20 KiB
Go
803 lines
20 KiB
Go
package local
|
|
|
|
import (
|
|
"fmt"
|
|
"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"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Build the template
|
|
func (tmpl *Template) Build(option *core.BuildOption) ([]string, error) {
|
|
var err error
|
|
warnings := []string{}
|
|
defer func() {
|
|
if option.ExecScripts {
|
|
tmpl.ExecBuildCompleteScripts()
|
|
}
|
|
}()
|
|
|
|
// Execute the build before hook
|
|
if option.ExecScripts {
|
|
res := tmpl.ExecBeforeBuildScripts()
|
|
scriptsErrorMessages := []string{}
|
|
for _, r := range res {
|
|
if r.Error != nil {
|
|
scriptsErrorMessages = append(scriptsErrorMessages, fmt.Sprintf("%s: %s", r.Script.Content, r.Error.Error()))
|
|
}
|
|
}
|
|
if len(scriptsErrorMessages) > 0 {
|
|
return warnings, fmt.Errorf("Build scripts error: %s", strings.Join(scriptsErrorMessages, ";\n"))
|
|
}
|
|
|
|
err = tmpl.Reload()
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
}
|
|
|
|
root, err := tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("SyncAssets: Get the public root error: %s. use %s", err.Error(), tmpl.local.DSL.Public.Root)
|
|
root = tmpl.local.DSL.Public.Root
|
|
}
|
|
|
|
if option.AssetRoot == "" {
|
|
option.AssetRoot = filepath.Join(root, "assets")
|
|
}
|
|
|
|
// Write the global script
|
|
err = tmpl.writeGlobalScript(option.Data)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Sync the assets
|
|
if err = tmpl.SyncAssets(option); err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Build all pages
|
|
ctx := core.NewGlobalBuildContext(tmpl)
|
|
pages, err := tmpl.Pages()
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// loaed pages
|
|
tmpl.loaded = map[string]core.IPage{}
|
|
publicRoot, err := tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("Get the public root error: %s. use %s", err.Error(), publicRoot)
|
|
}
|
|
option.PublicRoot = publicRoot
|
|
for _, page := range pages {
|
|
err := page.Load()
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
messages, err := page.Build(ctx, option)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
|
|
tmpl.loaded[page.Get().Route] = page
|
|
}
|
|
|
|
// Build jit components for the global <route> -> <name>.sui.lib
|
|
jitComponents, err := tmpl.GlobRoutes(ctx.GetJitComponents(), true)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
for _, route := range jitComponents {
|
|
page, has := tmpl.loaded[route]
|
|
if !has {
|
|
// err = multierror.Append(fmt.Errorf("The page %s is not loaded", route))
|
|
log.Warn("The page %s is not loaded", route)
|
|
continue
|
|
}
|
|
|
|
messages, err := page.BuildAsComponent(ctx, option)
|
|
if err != nil {
|
|
err = multierror.Append(err)
|
|
}
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
}
|
|
|
|
// Add sui lib to the global
|
|
err = tmpl.UpdateJSSDK(option)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Execute the build after hook
|
|
if option.ExecScripts {
|
|
res := tmpl.ExecAfterBuildScripts()
|
|
scriptsErrorMessages := []string{}
|
|
for _, r := range res {
|
|
if r.Error != nil {
|
|
scriptsErrorMessages = append(scriptsErrorMessages, fmt.Sprintf("%s: %s", r.Script.Content, r.Error.Error()))
|
|
}
|
|
}
|
|
if len(scriptsErrorMessages) > 0 {
|
|
return warnings, fmt.Errorf("Build scripts error: %s", strings.Join(scriptsErrorMessages, ";\n"))
|
|
}
|
|
}
|
|
|
|
return warnings, err
|
|
}
|
|
|
|
// Trans the template
|
|
func (tmpl *Template) Trans(option *core.BuildOption) ([]string, error) {
|
|
var err error
|
|
warnings := []string{}
|
|
|
|
ctx := core.NewGlobalBuildContext(tmpl)
|
|
pages, err := tmpl.Pages()
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// loaed pages
|
|
for _, page := range pages {
|
|
err := page.Load()
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
messages, err := page.Trans(ctx, option)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
}
|
|
|
|
return warnings, nil
|
|
}
|
|
|
|
// SyncAssetFile sync the assets
|
|
func (tmpl *Template) SyncAssetFile(file string, option *core.BuildOption) error {
|
|
|
|
// get source abs path
|
|
sourceRoot := filepath.Join(tmpl.local.fs.Root(), tmpl.Root, "__assets")
|
|
if exist, _ := os.Stat(sourceRoot); exist == nil {
|
|
return nil
|
|
}
|
|
|
|
//get target abs path
|
|
root, err := tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("SyncAssets: Get the public root error: %s. use %s", err.Error(), tmpl.local.DSL.Public.Root)
|
|
root = tmpl.local.DSL.Public.Root
|
|
}
|
|
|
|
targetRoot := filepath.Join(application.App.Root(), "public", root, "assets")
|
|
sourceFile := filepath.Join(sourceRoot, file)
|
|
targetFile := filepath.Join(targetRoot, file)
|
|
|
|
// create the target directory
|
|
if exist, _ := os.Stat(targetFile); exist == nil {
|
|
os.MkdirAll(filepath.Dir(targetFile), os.ModePerm)
|
|
}
|
|
|
|
return copy(sourceFile, targetFile)
|
|
}
|
|
|
|
// UpdateJSSDK update the js sdk
|
|
func (tmpl *Template) UpdateJSSDK(option *core.BuildOption) error {
|
|
|
|
jsCode, sourceMap, err := core.LibSUI()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// get source abs path
|
|
root, err := tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("SyncAssets: Get the public root error: %s. use %s", err.Error(), tmpl.local.DSL.Public.Root)
|
|
root = tmpl.local.DSL.Public.Root
|
|
}
|
|
|
|
targetRoot := filepath.Join(application.App.Root(), "public", root, "assets")
|
|
|
|
file := filepath.Join(targetRoot, "libsui.min.js")
|
|
mapFile := filepath.Join(targetRoot, "libsui.min.js.map")
|
|
|
|
// create the target directory
|
|
if exist, _ := os.Stat(targetRoot); exist == nil {
|
|
os.MkdirAll(targetRoot, os.ModePerm)
|
|
}
|
|
|
|
// write the js sdk
|
|
// add source map url
|
|
jsCode = append(jsCode, []byte("\n//# sourceMappingURL=libsui.min.js.map")...)
|
|
err = os.WriteFile(file, jsCode, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// write the source map
|
|
err = os.WriteFile(mapFile, sourceMap, 0644)
|
|
return nil
|
|
}
|
|
|
|
func (tmpl *Template) writeGlobalScript(data map[string]interface{}) error {
|
|
file, source, err := tmpl.backendScriptSource("__global.backend")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if source == nil {
|
|
return nil
|
|
}
|
|
|
|
name := filepath.Base(file)
|
|
ext := filepath.Ext(name)
|
|
root, err := tmpl.local.DSL.PublicRoot(data)
|
|
if err != nil {
|
|
log.Error("WriteGlobalScript: Get the public root error: %s. use %s", err.Error(), tmpl.local.DSL.Public.Root)
|
|
root = tmpl.local.DSL.Public.Root
|
|
}
|
|
target := filepath.Join(application.App.Root(), "public", root, fmt.Sprintf("__global%s", ext))
|
|
dir := filepath.Dir(target)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
return os.WriteFile(target, source, 0644)
|
|
}
|
|
|
|
// SyncAssets sync the assets
|
|
func (tmpl *Template) SyncAssets(option *core.BuildOption) error {
|
|
|
|
// get source abs path
|
|
sourceRoot := filepath.Join(tmpl.local.fs.Root(), tmpl.Root, "__assets")
|
|
if exist, _ := os.Stat(sourceRoot); exist == nil {
|
|
return nil
|
|
}
|
|
|
|
//get target abs path
|
|
root, err := tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("SyncAssets: Get the public root error: %s. use %s", err.Error(), tmpl.local.DSL.Public.Root)
|
|
root = tmpl.local.DSL.Public.Root
|
|
}
|
|
targetRoot := filepath.Join(application.App.Root(), "public", root, "assets")
|
|
|
|
if exist, _ := os.Stat(targetRoot); exist == nil {
|
|
os.MkdirAll(targetRoot, os.ModePerm)
|
|
}
|
|
os.RemoveAll(targetRoot)
|
|
|
|
return copyDirectory(sourceRoot, targetRoot)
|
|
}
|
|
|
|
func (tmpl *Template) getLocaleGlobal(name string) core.Locale {
|
|
global := core.Locale{
|
|
Keys: map[string]string{},
|
|
Messages: map[string]string{},
|
|
}
|
|
file := filepath.Join(tmpl.Root, "__locales", name, "__global.yml")
|
|
exist, err := tmpl.local.fs.Exists(file)
|
|
if err != nil {
|
|
log.Error(`[SUI] Check the global locale file error: %s`, err.Error())
|
|
return global
|
|
}
|
|
|
|
if !exist {
|
|
return global
|
|
}
|
|
|
|
raw, err := tmpl.local.fs.ReadFile(file)
|
|
if err != nil {
|
|
log.Error(`[SUI] Read the global locale file error: %s`, err.Error())
|
|
return global
|
|
}
|
|
|
|
err = yaml.Unmarshal(raw, &global)
|
|
if err != nil {
|
|
log.Error(`[SUI] Parse the global locale file error: %s`, err.Error())
|
|
return global
|
|
}
|
|
|
|
return global
|
|
}
|
|
|
|
func (tmpl *Template) getLocale(name string, route string, pageOnly ...bool) core.Locale {
|
|
file := filepath.Join(tmpl.Root, "__locales", name, fmt.Sprintf("%s.yml", route))
|
|
global := tmpl.getLocaleGlobal(name)
|
|
|
|
// Check the locale file
|
|
exist, err := tmpl.local.fs.Exists(file)
|
|
if err != nil {
|
|
return global
|
|
}
|
|
|
|
if !exist {
|
|
return global
|
|
}
|
|
|
|
locale := core.Locale{
|
|
Name: name,
|
|
Keys: map[string]string{},
|
|
Messages: map[string]string{},
|
|
ScriptMessages: map[string]string{},
|
|
Direction: global.Direction,
|
|
Timezone: global.Timezone,
|
|
Formatter: global.Formatter,
|
|
}
|
|
|
|
raw, err := tmpl.local.fs.ReadFile(file)
|
|
if err != nil {
|
|
log.Error(`[SUI] Read the locale file error: %s`, err.Error())
|
|
return global
|
|
}
|
|
|
|
err = yaml.Unmarshal(raw, &locale)
|
|
if err != nil {
|
|
log.Error(`[SUI] Parse the locale file error: %s`, err.Error())
|
|
return global
|
|
}
|
|
|
|
if len(pageOnly) == 0 || !pageOnly[0] {
|
|
|
|
// Merge the global
|
|
for key, message := range global.Keys {
|
|
if _, ok := locale.Keys[key]; !ok {
|
|
locale.Keys[key] = message
|
|
}
|
|
}
|
|
|
|
for key, message := range global.Messages {
|
|
if _, ok := locale.Messages[key]; !ok {
|
|
locale.Messages[key] = message
|
|
}
|
|
}
|
|
}
|
|
|
|
return locale
|
|
}
|
|
|
|
// Build is the struct for the public
|
|
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 == "" {
|
|
root, err = page.tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("Get the public root error: %s. use %s", err.Error(), page.tmpl.local.DSL.Public.Root)
|
|
}
|
|
}
|
|
|
|
if option.AssetRoot == "" {
|
|
option.AssetRoot = filepath.Join(root, "assets")
|
|
}
|
|
page.Root = root
|
|
|
|
html, config, warnings, err := page.Page.Compile(ctx, option)
|
|
if err != nil {
|
|
return warnings, fmt.Errorf("Compile the page %s error: %s", page.Route, err.Error())
|
|
}
|
|
|
|
// Save the html
|
|
err = page.writeHTML([]byte(html), option.Data)
|
|
if err != nil {
|
|
return warnings, fmt.Errorf("Write the page %s error: %s", page.Route, err.Error())
|
|
}
|
|
|
|
// Save the backend script file
|
|
err = page.writeBackendScript(option.Data)
|
|
if err != nil {
|
|
return warnings, fmt.Errorf("Write the backend script file error: %s", err.Error())
|
|
}
|
|
|
|
// Save the locale files
|
|
err = page.writeLocaleFiles(ctx, option.Data)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Save the config file
|
|
err = page.writeConfig([]byte(config), option.Data)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Jit Components
|
|
if globalCtx == nil {
|
|
jitComponents, err := page.tmpl.GlobRoutes(ctx.GetJitComponents(), true)
|
|
if err != nil {
|
|
return warnings, fmt.Errorf("Glob the jit components error: %s", err.Error())
|
|
}
|
|
|
|
for _, route := range jitComponents {
|
|
p := page.tmpl.loaded[route]
|
|
if p == nil {
|
|
p, err = page.tmpl.Page(route)
|
|
if err != nil {
|
|
err = multierror.Append(err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
messages, err := p.BuildAsComponent(globalCtx, option)
|
|
if err != nil {
|
|
err = multierror.Append(err)
|
|
}
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return warnings, fmt.Errorf("Build the page %s error: %s", page.Route, err.Error())
|
|
}
|
|
}
|
|
|
|
return warnings, nil
|
|
|
|
}
|
|
|
|
// BuildAsComponent build the page as component
|
|
func (page *Page) BuildAsComponent(globalCtx *core.GlobalBuildContext, option *core.BuildOption) ([]string, error) {
|
|
|
|
warnings := []string{}
|
|
ctx := core.NewBuildContext(globalCtx)
|
|
if option.AssetRoot == "" {
|
|
root, err := page.tmpl.local.DSL.PublicRoot(option.Data)
|
|
if err != nil {
|
|
log.Error("SyncAssets: Get the public root error: %s. use %s", err.Error(), page.tmpl.local.DSL.Public.Root)
|
|
root = page.tmpl.local.DSL.Public.Root
|
|
}
|
|
option.AssetRoot = filepath.Join(root, "assets")
|
|
}
|
|
|
|
html, messages, err := page.Page.CompileAsComponent(ctx, option)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
|
|
// Save the html
|
|
err = page.writeJitHTML([]byte(html), option.Data)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Save the locale files
|
|
err = page.writeLocaleFiles(ctx, option.Data)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
// Jit Components
|
|
if globalCtx == nil {
|
|
jitComponents, err := page.tmpl.GlobRoutes(ctx.GetJitComponents(), true)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
for _, route := range jitComponents {
|
|
var err error
|
|
p := page.tmpl.loaded[route]
|
|
if p == nil {
|
|
p, err = page.tmpl.Page(route)
|
|
if err != nil {
|
|
err = multierror.Append(err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
messages, err := p.BuildAsComponent(globalCtx, option)
|
|
if err != nil {
|
|
err = multierror.Append(err)
|
|
}
|
|
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
}
|
|
}
|
|
|
|
return warnings, err
|
|
}
|
|
|
|
// Trans the page
|
|
func (page *Page) Trans(globalCtx *core.GlobalBuildContext, option *core.BuildOption) ([]string, error) {
|
|
warnings := []string{}
|
|
ctx := core.NewBuildContext(globalCtx)
|
|
|
|
_, _, messages, err := page.Page.Compile(ctx, option)
|
|
if err != nil {
|
|
return warnings, err
|
|
}
|
|
|
|
if len(messages) > 0 {
|
|
warnings = append(warnings, messages...)
|
|
}
|
|
|
|
// Tranlate the locale files
|
|
err = page.writeLocaleSource(ctx, option)
|
|
return warnings, err
|
|
}
|
|
|
|
func (page *Page) publicFile(data map[string]interface{}) string {
|
|
root, err := page.tmpl.local.DSL.PublicRoot(data)
|
|
if err != nil {
|
|
log.Error("publicFile: Get the public root error: %s. use %s", err.Error(), page.tmpl.local.DSL.Public.Root)
|
|
root = page.tmpl.local.DSL.Public.Root
|
|
}
|
|
return filepath.Join("/", "public", root, page.Route)
|
|
}
|
|
|
|
func (page *Page) localeFiles(data map[string]interface{}) map[string]string {
|
|
root, err := page.tmpl.local.DSL.PublicRoot(data)
|
|
if err != nil {
|
|
log.Error("publicFile: Get the public root error: %s. use %s", err.Error(), page.tmpl.local.DSL.Public.Root)
|
|
root = page.tmpl.local.DSL.Public.Root
|
|
}
|
|
|
|
roots := map[string]string{}
|
|
locales := page.tmpl.Locales()
|
|
for _, locale := range locales {
|
|
if locale.Default {
|
|
continue
|
|
}
|
|
target := filepath.Join("/", "public", root, ".locales", locale.Value, fmt.Sprintf("%s.yml", page.Route))
|
|
roots[locale.Value] = target
|
|
}
|
|
return roots
|
|
}
|
|
|
|
func (page *Page) writeLocaleSource(ctx *core.BuildContext, option *core.BuildOption) error {
|
|
|
|
locales := page.tmpl.Locales()
|
|
translations := ctx.GetTranslations()
|
|
|
|
if option.Locales != nil && len(option.Locales) > 0 {
|
|
locales = []core.SelectOption{}
|
|
for _, lc := range option.Locales {
|
|
label := language.Make(lc).String()
|
|
locales = append(locales, core.SelectOption{Value: lc, Label: label})
|
|
}
|
|
}
|
|
|
|
prefix := core.TranslationKeyPrefix(page.Route)
|
|
for _, lc := range locales {
|
|
if lc.Default {
|
|
continue
|
|
}
|
|
|
|
locale := page.tmpl.getLocale(lc.Value, page.Route, true)
|
|
locale.MergeTranslations(translations, prefix)
|
|
|
|
// Call the hook
|
|
var keys any = locale.Keys
|
|
var messages any = locale.Messages
|
|
if page.tmpl.Translator != "" {
|
|
p, err := process.Of(page.tmpl.Translator, lc.Value, locale, page.Route, page.TemplateID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
res, err := p.Exec()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pres, ok := res.(map[string]interface{})
|
|
if !ok {
|
|
return fmt.Errorf("The translator %s should return a locale", page.tmpl.Translator)
|
|
}
|
|
|
|
keys = pres["keys"]
|
|
messages = pres["messages"]
|
|
}
|
|
|
|
if keys == nil && messages == nil {
|
|
return nil
|
|
}
|
|
|
|
// Save to file
|
|
file := filepath.Join(page.tmpl.Root, "__locales", lc.Value, fmt.Sprintf("%s.yml", page.Route))
|
|
content, err := yaml.Marshal(map[string]interface{}{
|
|
"keys": keys,
|
|
"messages": messages,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = page.tmpl.local.fs.WriteFile(file, content, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (page *Page) writeLocaleFiles(ctx *core.BuildContext, data map[string]interface{}) error {
|
|
|
|
if ctx == nil {
|
|
return nil
|
|
}
|
|
|
|
components := ctx.GetComponents()
|
|
translations := ctx.GetTranslations()
|
|
if len(translations) == 0 && len(components) == 0 {
|
|
return nil
|
|
}
|
|
prefix := core.TranslationKeyPrefix(page.Route)
|
|
files := page.localeFiles(data)
|
|
for name, file := range files {
|
|
locale := page.tmpl.getLocale(name, page.Route)
|
|
locale.MergeTranslations(translations, prefix)
|
|
|
|
// Merge the components locale
|
|
for _, route := range components {
|
|
compLocale := page.tmpl.getLocale(name, route, true)
|
|
compLocale.ParseKeys()
|
|
locale.Merge(compLocale)
|
|
}
|
|
|
|
// Remove messages
|
|
locale.Messages = map[string]string{}
|
|
raw, err := yaml.Marshal(locale)
|
|
if err != nil {
|
|
log.Error(`[SUI] Marshal the locale file error: %s`, err.Error())
|
|
return err
|
|
}
|
|
|
|
fileAbs := filepath.Join(application.App.Root(), file)
|
|
dir := filepath.Dir(fileAbs)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
|
|
err = os.WriteFile(fileAbs, raw, 0644)
|
|
if err != nil {
|
|
log.Error(`[SUI] Write the locale file error: %s`, err.Error())
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (page *Page) backendScriptSource() (string, []byte, error) {
|
|
backendFile := filepath.Join(page.Path, fmt.Sprintf("%s.backend.ts", page.Name))
|
|
if exist, _ := page.tmpl.local.fs.Exists(backendFile); !exist {
|
|
backendFile = filepath.Join(page.Path, fmt.Sprintf("%s.backend.js", page.Name))
|
|
}
|
|
|
|
if exist, _ := page.tmpl.local.fs.Exists(backendFile); !exist {
|
|
return "", nil, nil
|
|
}
|
|
|
|
source, err := page.tmpl.local.fs.ReadFile(backendFile)
|
|
if err != nil {
|
|
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()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if source == nil {
|
|
return nil
|
|
}
|
|
|
|
ext := filepath.Ext(file)
|
|
scriptFile := fmt.Sprintf("%s.backend%s", page.publicFile(data), ext)
|
|
scriptFileAbs := filepath.Join(application.App.Root(), scriptFile)
|
|
dir := filepath.Dir(scriptFileAbs)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
|
|
err = os.WriteFile(scriptFileAbs, []byte(source), 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
core.RemoveCache(scriptFile)
|
|
return nil
|
|
}
|
|
|
|
// writeHTMLTo write the html to file
|
|
func (page *Page) writeHTML(html []byte, data map[string]interface{}) error {
|
|
htmlFile := fmt.Sprintf("%s.sui", page.publicFile(data))
|
|
htmlFileAbs := filepath.Join(application.App.Root(), htmlFile)
|
|
dir := filepath.Dir(htmlFileAbs)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
err := os.WriteFile(htmlFileAbs, html, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
core.RemoveCache(htmlFile)
|
|
return nil
|
|
}
|
|
|
|
// writeHTMLTo write the html to file
|
|
func (page *Page) writeConfig(config []byte, data map[string]interface{}) error {
|
|
configFile := fmt.Sprintf("%s.cfg", page.publicFile(data))
|
|
configFileAbs := filepath.Join(application.App.Root(), configFile)
|
|
dir := filepath.Dir(configFileAbs)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
err := os.WriteFile(configFileAbs, config, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// writeHTMLTo write the html to file
|
|
func (page *Page) writeJitHTML(html []byte, data map[string]interface{}) error {
|
|
htmlFile := fmt.Sprintf("%s.jit", page.publicFile(data))
|
|
htmlFileAbs := filepath.Join(application.App.Root(), htmlFile)
|
|
dir := filepath.Dir(htmlFileAbs)
|
|
if exist, _ := os.Stat(dir); exist == nil {
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
}
|
|
err := os.WriteFile(htmlFileAbs, html, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
core.RemoveCache(htmlFile)
|
|
return nil
|
|
}
|