Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[add] sui page render (dev) #506

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions sui/api/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package api

import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

"github.com/gin-gonic/gin"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
)

Expand Down Expand Up @@ -37,15 +40,61 @@ func NewRequestContext(c *gin.Context) (*Request, int, error) {
Body: body,
Payload: payload,
Referer: c.Request.Referer(),
Headers: c.Request.Header,
Headers: url.Values(c.Request.Header),
Params: params,
},
}, 200, nil
}

// Render is the response for the page API.
func (r *Request) Render() (string, int, error) {
return r.File, 200, nil

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

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

dataText := ""
dataSel := doc.Find("script[name=data]")
if dataSel != nil && dataSel.Length() > 0 {
dataText = dataSel.Text()
dataSel.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.SetCache(r.File, html, dataText)
log.Trace("The page %s is cached", r.File)
}

var err error
data := core.Data{}
if c.Data != "" {
data, err = r.Request.ExecString(c.Data)
if err != nil {
return "", 500, fmt.Errorf("data error, please re-complie the page %s", err.Error())
}
}

parser := core.NewTemplateParser(data, nil)
html, err := parser.Render(c.HTML)
if err != nil {
return "", 500, fmt.Errorf("render error, please re-complie the page %s", err.Error())
}

return html, 200, nil
}

func parserPath(c *gin.Context) (string, map[string]string, error) {
Expand All @@ -57,7 +106,7 @@ func parserPath(c *gin.Context) (string, map[string]string, error) {
return "", nil, fmt.Errorf("no route matchers")
}

fileParts := []string{application.App.Root(), "public"}
fileParts := []string{string(os.PathSeparator), "public"}

// Match the sui
matchers := core.RouteExactMatchers[parts[0]]
Expand Down Expand Up @@ -101,7 +150,7 @@ func parserPath(c *gin.Context) (string, map[string]string, error) {

} else if matcher.Regex != nil {
if matcher.Regex.MatchString(part) {
file := matcher.Ref.(string)
file := matcher.Ref
key := strings.TrimRight(strings.TrimLeft(file, "["), "]")
params[key] = part
fileParts = append(fileParts, file)
Expand Down
15 changes: 7 additions & 8 deletions sui/core/compile.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package core

import (
"fmt"
"regexp"

"github.com/evanw/esbuild/pkg/api"
Expand Down Expand Up @@ -30,13 +29,13 @@ func (page *Page) Compile(option *BuildOption) (string, error) {
)
}

// add the route data
doc.Find("body").AppendHtml(`<script name="route" type="json">` + "\n" +
fmt.Sprintf(
`{"sui": "%s", "template": "%s", "route": "%s"}`,
page.SuiID, page.TemplateID, page.Route,
) +
"\n</script>\n")
// // add the route data
// doc.Find("body").AppendHtml(`<script name="route" type="json">` + "\n" +
// fmt.Sprintf(
// `{"sui": "%s", "template": "%s", "route": "%s"}`,
// page.SuiID, page.TemplateID, page.Route,
// ) +
// "\n</script>\n")

html, err := doc.Html()
if err != nil {
Expand Down
73 changes: 73 additions & 0 deletions sui/core/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ import (
"github.com/yaoapp/kun/any"
)

// Cache the cache
type Cache struct {
Data string
HTML string
}

// Caches the caches
var Caches = map[string]*Cache{}

// ExecString get the data
func (r *Request) ExecString(data string) (Data, error) {
var res Data
Expand Down Expand Up @@ -50,6 +59,39 @@ func (r *Request) Exec(m Data) error {
func (r *Request) execValue(value interface{}) (interface{}, error) {
switch v := value.(type) {
case string:

if strings.HasPrefix(v, "$query.") {
key := strings.TrimLeft(v, "$query.")
if r.Query.Has(key) {
return r.Query.Get(key), nil
}
return "", nil
}

if strings.HasPrefix(v, "$header.") {
key := strings.TrimLeft(v, "$header.")
if r.Headers.Has(key) {
return r.Headers.Get(key), nil
}
return "", nil
}

if strings.HasPrefix(v, "$param.") {
key := strings.TrimLeft(v, "$param.")
if value, has := r.Params[key]; has {
return value, nil
}
return "", nil
}

if strings.HasPrefix(v, "$payload.") {
key := strings.TrimLeft(v, "$payload.")
if value, has := r.Payload[key]; has {
return value, nil
}
return "", nil
}

if strings.HasPrefix(v, "$") {
return r.call(strings.TrimLeft(v, "$"))
}
Expand Down Expand Up @@ -127,6 +169,10 @@ func (r *Request) call(p interface{}) (interface{}, error) {
return nil, err
}

if r.Sid != "" {
process.WithSID(r.Sid)
}

return process.Exec()
}

Expand Down Expand Up @@ -183,3 +229,30 @@ func (r *Request) parseArgs(args []interface{}) ([]interface{}, error) {

return args, nil
}

// SetCache set the cache
func SetCache(file string, html string, data string) *Cache {
Caches[file] = &Cache{
Data: data,
HTML: html,
}
return Caches[file]
}

// GetCache get the cache
func GetCache(file string) *Cache {
if cache, has := Caches[file]; has {
return cache
}
return nil
}

// RemoveCache remove the cache
func RemoveCache(file string) {
delete(Caches, file)
}

// CleanCache clean the cache
func CleanCache() {
Caches = map[string]*Cache{}
}
5 changes: 2 additions & 3 deletions sui/core/sui.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func (sui *DSL) WithSid(sid string) {

// PublicRootMatcher returns the public root matcher
func (sui *DSL) PublicRootMatcher() *Matcher {
var ref SUI = sui
pub := sui.GetPublic()
if varRe.MatchString(pub.Root) {
if pub.Matcher != "" {
Expand All @@ -41,9 +40,9 @@ func (sui *DSL) PublicRootMatcher() *Matcher {
}
return &Matcher{Regex: re}
}
return &Matcher{Regex: RouteRegexp, Ref: ref}
return &Matcher{Regex: RouteRegexp}
}
return &Matcher{Exact: pub.Root, Ref: ref}
return &Matcher{Exact: pub.Root}
}

// PublicRoot returns the public root path
Expand Down
5 changes: 3 additions & 2 deletions sui/core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ type Request struct {
Payload map[string]interface{} `json:"payload,omitempty"`
Query url.Values `json:"query,omitempty"`
Params map[string]string `json:"params,omitempty"`
Headers map[string][]string `json:"headers,omitempty"`
Headers url.Values `json:"headers,omitempty"`
Body interface{} `json:"body,omitempty"`
Sid string `json:"sid,omitempty"`
Theme string `json:"theme,omitempty"`
Locale string `json:"locale,omitempty"`
}
Expand Down Expand Up @@ -266,7 +267,7 @@ type Matcher struct {
Regex *regexp.Regexp `json:"regex,omitempty"`
Exact string `json:"exact,omitempty"`
Parent string `json:"-"`
Ref interface{} `json:"-"`
Ref string `json:"-"`
}

// DocumentDefault is the default document
Expand Down
25 changes: 10 additions & 15 deletions sui/storages/local/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,28 +99,23 @@ func (page *Page) publicFile() string {
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(application.App.Root(), "public", root, page.Route)
return filepath.Join("/", "public", root, page.Route)
}

// writeHTMLTo write the html to file
func (page *Page) writeHTML(html []byte) error {
htmlFile := fmt.Sprintf("%s.sui", page.publicFile())
dir := filepath.Dir(htmlFile)
htmlFileAbs := filepath.Join(application.App.Root(), htmlFile)
dir := filepath.Dir(htmlFileAbs)
if exist, _ := os.Stat(dir); exist == nil {
os.MkdirAll(dir, os.ModePerm)
}
return os.WriteFile(htmlFile, html, 0644)
}

// writeHTMLTo write the html to file
func (page *Page) writeData() error {
if page.Codes.DATA.Code == "" {
return nil
}
dataFile := fmt.Sprintf("%s.json", page.publicFile())
dir := filepath.Dir(dataFile)
if exist, _ := os.Stat(dir); exist == nil {
os.MkdirAll(dir, os.ModePerm)
err := os.WriteFile(htmlFileAbs, html, 0644)
if err != nil {
return err
}
return os.WriteFile(dataFile, []byte(page.Codes.DATA.Code), 0644)

core.RemoveCache(htmlFile)
log.Trace("The page %s is removed", htmlFile)
return nil
}