Skip to content

Commit

Permalink
Merge pull request #656 from trheyi/main
Browse files Browse the repository at this point in the history
refactor: Update build process to include SUI CompileAsComponent supp…
  • Loading branch information
trheyi committed Jul 5, 2024
2 parents 1a623fe + a4f2836 commit 6f49ae3
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 83 deletions.
164 changes: 88 additions & 76 deletions sui/api/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,88 +86,16 @@ func (r *Request) Render() (string, int, error) {

if c == nil {

// The page is not cached
message := fmt.Sprintf("[SUI] The page %s is not cached. file=%s DisableCache=%v", r.Request.URL.Path, r.File, r.Request.DisableCache())
go fmt.Println(color.YellowString(message))
go log.Warn(message)

// Read the file
content, err := application.App.Read(r.File)
var status int
var err error
c, status, err = r.MakeCache()
if err != nil {
return "", 404, err
return "", status, err
}

doc, err := core.NewDocument(content)
if err != nil {
return "", 500, err
}

guard := ""
guardRedirect := ""
configText := ""
cacheStore := ""
cacheTime := 0
dateCacheTime := 0

configSel := doc.Find("script[name=config]")
if configSel != nil && configSel.Length() > 0 {
configText = configSel.Text()
configSel.Remove()

var conf core.PageConfig
err := jsoniter.UnmarshalFromString(configText, &conf)
if err != nil {
return "", 500, fmt.Errorf("config error, please re-complie the page %s", err.Error())
}

// Redirect the page (should refector before release)
// guard=cookie-jwt:redirect-url redirect to the url if not authorized
// guard=cookie-jwt return {code: 403, message: "Not Authorized"}
guard = conf.Guard
if strings.Contains(conf.Guard, ":") {
parts := strings.Split(conf.Guard, ":")
guard = parts[0]
guardRedirect = parts[1]
}

// Cache store
cacheStore = conf.CacheStore
cacheTime = conf.Cache
dateCacheTime = conf.DataCache
}

dataText := ""
dataSel := doc.Find("script[name=data]")
if dataSel != nil && dataSel.Length() > 0 {
dataText = dataSel.Text()
dataSel.Remove()
}

globalDataText := ""
globalDataSel := doc.Find("script[name=global]")
if globalDataSel != nil && globalDataSel.Length() > 0 {
globalDataText = globalDataSel.Text()
globalDataSel.Remove()
}

html, err := doc.Html()
if err != nil {
return "", 500, fmt.Errorf("parse error, please re-complie the page %s", err.Error())
}

// Save to The Cache
c = &core.Cache{
Data: dataText,
Global: globalDataText,
HTML: html,
Guard: guard,
GuardRedirect: guardRedirect,
Config: configText,
CacheStore: cacheStore,
CacheTime: time.Duration(cacheTime) * time.Second,
DataCacheTime: time.Duration(dateCacheTime) * time.Second,
}
go core.SetCache(r.File, c)
go log.Trace("[SUI] The page %s is cached file=%s", r.Request.URL.Path, r.File)
}

Expand Down Expand Up @@ -249,6 +177,90 @@ func (r *Request) Render() (string, int, error) {
return html, 200, nil
}

// MakeCache is the cache for the page API.
func (r *Request) MakeCache() (*core.Cache, int, error) {

// Read the file
content, err := application.App.Read(r.File)
if err != nil {
return nil, 404, err
}

doc, err := core.NewDocument(content)
if err != nil {
return nil, 500, err
}

guard := ""
guardRedirect := ""
configText := ""
cacheStore := ""
cacheTime := 0
dateCacheTime := 0

configSel := doc.Find("script[name=config]")
if configSel != nil && configSel.Length() > 0 {
configText = configSel.Text()
configSel.Remove()

var conf core.PageConfig
err := jsoniter.UnmarshalFromString(configText, &conf)
if err != nil {
return nil, 500, fmt.Errorf("config error, please re-complie the page %s", err.Error())
}

// Redirect the page (should refector before release)
// guard=cookie-jwt:redirect-url redirect to the url if not authorized
// guard=cookie-jwt return {code: 403, message: "Not Authorized"}
guard = conf.Guard
if strings.Contains(conf.Guard, ":") {
parts := strings.Split(conf.Guard, ":")
guard = parts[0]
guardRedirect = parts[1]
}

// Cache store
cacheStore = conf.CacheStore
cacheTime = conf.Cache
dateCacheTime = conf.DataCache
}

dataText := ""
dataSel := doc.Find("script[name=data]")
if dataSel != nil && dataSel.Length() > 0 {
dataText = dataSel.Text()
dataSel.Remove()
}

globalDataText := ""
globalDataSel := doc.Find("script[name=global]")
if globalDataSel != nil && globalDataSel.Length() > 0 {
globalDataText = globalDataSel.Text()
globalDataSel.Remove()
}

html, err := doc.Html()
if err != nil {
return nil, 500, fmt.Errorf("parse error, please re-complie the page %s", err.Error())
}

// Save to The Cache
cache := &core.Cache{
Data: dataText,
Global: globalDataText,
HTML: html,
Guard: guard,
GuardRedirect: guardRedirect,
Config: configText,
CacheStore: cacheStore,
CacheTime: time.Duration(cacheTime) * time.Second,
DataCacheTime: time.Duration(dateCacheTime) * time.Second,
}

go core.SetCache(r.File, cache)
return cache, 200, nil
}

// Guard the page
func (r *Request) Guard(c *core.Cache) (int, error) {

Expand Down
100 changes: 100 additions & 0 deletions sui/api/request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package api

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/yao/sui/core"
)

func TestMakeCache(t *testing.T) {
prepare(t)
defer clean()
r := makeRequest("/unit-test/index.sui", t)
c, status, err := r.MakeCache()
if err != nil {
t.Fatal(err)
}

assert.Equal(t, http.StatusOK, status)
assert.Contains(t, c.HTML, "The advanced test cases")
}

func TestRender(t *testing.T) {
prepare(t)
defer clean()

parser, html, data := makeParser("/unit-test/index.sui", t)
result, err := parser.Render(html)
if err != nil {
t.Fatal(err)
}

assert.Contains(t, result, "The advanced test cases")
assert.NotNil(t, data["$global"])
assert.NotNil(t, data["foo"])
assert.NotNil(t, data["items"])

// fmt.Println(result)
}

func makeParser(route string, t *testing.T) (*core.TemplateParser, string, core.Data) {
r := makeRequest(route, t)
c, _, err := r.MakeCache()
if err != nil {
t.Fatal(err)
}

data := r.Request.NewData()
if c.Data != "" {
err = r.Request.ExecStringMerge(data, c.Data)
if err != nil {
t.Fatal(err)
}
}

if c.Global != "" {
global, err := r.Request.ExecString(c.Global)
if err != nil {
t.Fatal(err)
}
data["$global"] = global
}

// 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,
Request: true,
}

// Parse the template
return core.NewTemplateParser(data, &option), c.HTML, data
}

func makeRequest(path string, t *testing.T) *Request {
req, err := http.NewRequest(http.MethodGet, path, nil)
if err != nil {
t.Fatal(err)
}

w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req

r, status, err := NewRequestContext(c)
if err != nil {
t.Fatal(err)
}

if status != http.StatusOK {
t.Fatalf("Status: %d", status)
}
return r
}
10 changes: 10 additions & 0 deletions sui/api/sui_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ func prepare(t *testing.T) {
if err != nil {
t.Fatal(err)
}

advanced, err := core.SUIs["test"].GetTemplate("advanced")
if err != nil {
t.Fatal(err)
}

err = advanced.Build(&core.BuildOption{SSR: true})
if err != nil {
t.Fatal(err)
}
}

func clean() {
Expand Down
22 changes: 16 additions & 6 deletions sui/core/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ func (page *Page) Build(ctx *BuildContext, option *BuildOption) (*goquery.Docume
doc.Selection.Find("body").AppendHtml("\n" + `<script src="` + script + `"></script>` + "\n")
}
}
doc.Selection.Find("body").AppendHtml(fmt.Sprintf("\n"+`<script type="text/javascript">`+"\n%s\n"+`</script>`+"\n%s\n", strings.Join(ctx.scripts, "\n"), code))
componentScripts := ""
if len(ctx.scripts) > 0 {
componentScripts = fmt.Sprintf("\n"+`<script type="text/javascript" name="components">`+"\n%s\n"+`</script>`+"\n", strings.Join(ctx.scripts, "\n"))
}
doc.Selection.Find("body").AppendHtml(fmt.Sprintf("\n%s\n%s\n", componentScripts, code))
return doc, warnings, nil
}

Expand Down Expand Up @@ -373,7 +377,7 @@ func (page *Page) BuildScript(ctx *BuildContext, option *BuildOption, namespace
// if the script is a component and not the first import
if option.ComponentName != "" && ctx.components[option.ComponentName] {
ctx.scripts = append(ctx.scripts, instanceCode)
return fmt.Sprintf("<script type=\"text/javascript\">\n%s\n</script>\n", instanceCode), []string{}, nil
return fmt.Sprintf("<script type=\"text/javascript\" name=\"%s\">\n%s\n</script>\n", option.ComponentName, instanceCode), []string{}, nil
}

// TypeScript
Expand Down Expand Up @@ -402,12 +406,15 @@ func (page *Page) BuildScript(ctx *BuildContext, option *BuildOption, namespace
}

if option.Namespace == "" {
return fmt.Sprintf("<script type=\"text/javascript\">\n%s\n</script>\n", code), scripts, nil
if strings.TrimSpace(string(code)) == "" {
return "", scripts, nil
}
return fmt.Sprintf("<script type=\"text/javascript\" name=\"page\">\n%s\n</script>\n", code), scripts, nil
}

componentCode := fmt.Sprintf("function %s(){\n%s\n}\n%s\n", option.ComponentName, addTabToEachLine(string(code)), instanceCode)
ctx.scripts = append(ctx.scripts, componentCode)
return fmt.Sprintf("<script type=\"text/javascript\">%s</script>\n", componentCode), scripts, nil
return fmt.Sprintf("<script type=\"text/javascript\" name=\"%s\">%s</script>\n", option.ComponentName, componentCode), scripts, nil
}

// JavaScript
Expand All @@ -434,12 +441,15 @@ func (page *Page) BuildScript(ctx *BuildContext, option *BuildOption, namespace
}

if option.Namespace == "" {
return fmt.Sprintf("<script type=\"text/javascript\">\n%s\n</script>\n", code), scripts, nil
if strings.TrimSpace(string(code)) == "" {
return "", scripts, nil
}
return fmt.Sprintf("<script type=\"text/javascript\" name=\"page\">\n%s\n</script>\n", code), scripts, nil
}

componentCode := fmt.Sprintf("function %s(){\n%s\n}\n%s\n", option.ComponentName, addTabToEachLine(string(code)), instanceCode)
ctx.scripts = append(ctx.scripts, componentCode)
return fmt.Sprintf("<script type=\"text/javascript\">%s</script>\n", componentCode), scripts, nil
return fmt.Sprintf("<script type=\"text/javascript\" name=\"%s\" >%s</script>\n", option.ComponentName, componentCode), scripts, nil
}

func addTabToEachLine(input string, prefix ...string) string {
Expand Down
1 change: 0 additions & 1 deletion sui/core/fs_test.go

This file was deleted.

0 comments on commit 6f49ae3

Please sign in to comment.