commit
37918c0dfb
19 changed files with 476 additions and 25 deletions
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/socket"
|
||||
"github.com/yaoapp/yao/store"
|
||||
sui "github.com/yaoapp/yao/sui/api"
|
||||
"github.com/yaoapp/yao/task"
|
||||
"github.com/yaoapp/yao/websocket"
|
||||
"github.com/yaoapp/yao/widget"
|
||||
|
|
@ -196,6 +197,12 @@ func Load(cfg config.Config) (err error) {
|
|||
printErr(cfg.Mode, "Widget", err)
|
||||
}
|
||||
|
||||
// Load SUI
|
||||
err = sui.Load(cfg)
|
||||
if err != nil {
|
||||
printErr(cfg.Mode, "SUI", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -27,6 +27,8 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/bytedance/sonic v1.10.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -39,8 +39,12 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4=
|
||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
|
|
@ -653,10 +657,12 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
|
|
|
|||
33
sui/api/api.go
Normal file
33
sui/api/api.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package api
|
||||
|
||||
import "github.com/yaoapp/gou/api"
|
||||
|
||||
var dsl = []byte(`
|
||||
{
|
||||
"name": "SUI API",
|
||||
"description": "The API for SUI",
|
||||
"version": "1.0.0",
|
||||
"guard": "-",
|
||||
"group": "__yao/sui/v1",
|
||||
"paths": [
|
||||
{
|
||||
"path": "/:id/template/find/:template_id",
|
||||
"method": "GET",
|
||||
"process": "sui.Template.Find",
|
||||
"in": ["$param.id", "$param.template_id"],
|
||||
"out": { "status": 200, "type": "application/json" }
|
||||
},{
|
||||
"path": "/:id/template/get",
|
||||
"method": "GET",
|
||||
"process": "sui.Template.Get",
|
||||
"in": ["$param.id"],
|
||||
"out": { "status": 200, "type": "application/json" }
|
||||
}
|
||||
],
|
||||
}
|
||||
`)
|
||||
|
||||
func registerAPI() error {
|
||||
_, err := api.LoadSource("<sui.v1>.yao", dsl, "sui.v1")
|
||||
return err
|
||||
}
|
||||
47
sui/api/process.go
Normal file
47
sui/api/process.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/yaoapp/gou/process"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/yao/sui/core"
|
||||
)
|
||||
|
||||
func init() {
|
||||
process.RegisterGroup("sui", map[string]process.Handler{
|
||||
"template.get": TemplateGet,
|
||||
"template.find": TemplateFind,
|
||||
})
|
||||
}
|
||||
|
||||
// TemplateGet handle the get Template request
|
||||
// Process sui.<ID>.templates
|
||||
func TemplateGet(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(1)
|
||||
sui := get(process)
|
||||
templates, err := sui.GetTemplates()
|
||||
if err != nil {
|
||||
exception.New(err.Error(), 500).Throw()
|
||||
}
|
||||
return templates
|
||||
}
|
||||
|
||||
// TemplateFind handle the find Template request
|
||||
func TemplateFind(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(2)
|
||||
sui := get(process)
|
||||
template, err := sui.GetTemplate(process.ArgsString(1))
|
||||
if err != nil {
|
||||
exception.New(err.Error(), 500).Throw()
|
||||
}
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
// get the sui
|
||||
func get(process *process.Process) core.SUI {
|
||||
sui, has := core.SUIs[process.ArgsString(0)]
|
||||
if !has {
|
||||
exception.New("the sui %s does not exist", 404, process.ID).Throw()
|
||||
}
|
||||
return sui
|
||||
}
|
||||
57
sui/api/process_test.go
Normal file
57
sui/api/process_test.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou/process"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/sui/core"
|
||||
"github.com/yaoapp/yao/sui/storages/local"
|
||||
)
|
||||
|
||||
func TestTemplateGet(t *testing.T) {
|
||||
load(t)
|
||||
defer clean()
|
||||
|
||||
// test demo
|
||||
p, err := process.Of("sui.template.get", "demo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := p.Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, []core.ITemplate{}, res)
|
||||
assert.Equal(t, 3, len(res.([]core.ITemplate)))
|
||||
}
|
||||
|
||||
func TestTemplateFind(t *testing.T) {
|
||||
load(t)
|
||||
defer clean()
|
||||
|
||||
// test demo
|
||||
p, err := process.Of("sui.template.find", "demo", "tech-blue")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := p.Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, &local.Template{}, res)
|
||||
assert.Equal(t, "tech-blue", res.(*local.Template).ID)
|
||||
}
|
||||
|
||||
func load(t *testing.T) {
|
||||
prepare(t)
|
||||
err := Load(config.Conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package sui
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -13,9 +13,6 @@ import (
|
|||
"github.com/yaoapp/yao/sui/storages/local"
|
||||
)
|
||||
|
||||
// SUIs the loaded SUI instances
|
||||
var SUIs = map[string]core.SUI{}
|
||||
|
||||
// New create a new sui
|
||||
func New(dsl *core.DSL) (core.SUI, error) {
|
||||
|
||||
|
|
@ -39,7 +36,7 @@ func New(dsl *core.DSL) (core.SUI, error) {
|
|||
// Load load the sui
|
||||
func Load(cfg config.Config) error {
|
||||
exts := []string{"*.sui.yao", "*.sui.jsonc", "*.sui.json"}
|
||||
return application.App.Walk("suis", func(root, file string, isdir bool) error {
|
||||
err := application.App.Walk("suis", func(root, file string, isdir bool) error {
|
||||
if isdir {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -52,6 +49,12 @@ func Load(cfg config.Config) error {
|
|||
}
|
||||
return nil
|
||||
}, exts...)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return registerAPI()
|
||||
}
|
||||
|
||||
func loadFile(file string, id string) (core.SUI, error) {
|
||||
|
|
@ -66,6 +69,6 @@ func loadFile(file string, id string) (core.SUI, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
SUIs[id] = sui
|
||||
return SUIs[id], nil
|
||||
core.SUIs[id] = sui
|
||||
return core.SUIs[id], nil
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
package sui
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/sui/core"
|
||||
"github.com/yaoapp/yao/test"
|
||||
)
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ func TestLoad(t *testing.T) {
|
|||
|
||||
func check(t *testing.T) {
|
||||
ids := map[string]bool{}
|
||||
for id := range SUIs {
|
||||
for id := range core.SUIs {
|
||||
ids[id] = true
|
||||
}
|
||||
assert.True(t, ids["azure"])
|
||||
4
sui/core/compile.go
Normal file
4
sui/core/compile.go
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
package core
|
||||
|
||||
// Compile the page
|
||||
func (page *Page) Compile() {}
|
||||
11
sui/core/data.go
Normal file
11
sui/core/data.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package core
|
||||
|
||||
// Data get the data
|
||||
func (page *Page) Data(request *Request) (map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// RenderHTML render for the html
|
||||
func (page *Page) renderData(html string, data map[string]interface{}, warnings []string) (string, error) {
|
||||
return html, nil
|
||||
}
|
||||
|
|
@ -1,5 +1,15 @@
|
|||
package core
|
||||
|
||||
// SUIs the loaded SUI instances
|
||||
var SUIs = map[string]SUI{}
|
||||
|
||||
// SUI is the interface for the SUI
|
||||
type SUI interface {
|
||||
GetTemplates() ([]ITemplate, error)
|
||||
GetTemplate(name string) (ITemplate, error)
|
||||
UploadTemplate(src string, dst string) (ITemplate, error)
|
||||
}
|
||||
|
||||
// ITemplate is the interface for the ITemplate
|
||||
type ITemplate interface {
|
||||
Pages() ([]IPage, error)
|
||||
|
|
@ -19,6 +29,7 @@ type ITemplate interface {
|
|||
// IPage is the interface for the page
|
||||
type IPage interface {
|
||||
Load() error
|
||||
RenderEditor(request *Request) (*ResponseEditor, error)
|
||||
|
||||
// Render()
|
||||
|
||||
|
|
|
|||
19
sui/core/page.go
Normal file
19
sui/core/page.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package core
|
||||
|
||||
// GetHTML get the html
|
||||
func (page *Page) GetHTML() {}
|
||||
|
||||
// GetScript get the script
|
||||
func (page *Page) GetScript() {}
|
||||
|
||||
// GetStyle get the style
|
||||
func (page *Page) GetStyle() {}
|
||||
|
||||
// GetData get the data
|
||||
func (page *Page) GetData() {}
|
||||
|
||||
// SaveTemp save the temp
|
||||
func (page *Page) SaveTemp() {}
|
||||
|
||||
// Save the page
|
||||
func (page *Page) Save() {}
|
||||
129
sui/core/render.go
Normal file
129
sui/core/render.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
// Render render the page
|
||||
func (page *Page) Render() {}
|
||||
|
||||
// RenderEditor render for the editor
|
||||
func (page *Page) RenderEditor(request *Request) (*ResponseEditor, error) {
|
||||
|
||||
html := page.Codes.HTML.Code
|
||||
res := &ResponseEditor{
|
||||
HTML: "",
|
||||
CSS: page.Codes.CSS.Code,
|
||||
Scripts: []string{},
|
||||
Styles: []string{},
|
||||
Warnings: []string{},
|
||||
}
|
||||
|
||||
// Get The scripts and styles
|
||||
// Global scripts
|
||||
scripts, err := page.GlobalScripts()
|
||||
if err != nil {
|
||||
res.Warnings = append(res.Warnings, err.Error())
|
||||
}
|
||||
res.Scripts = append(res.Scripts, scripts...)
|
||||
|
||||
// Global styles
|
||||
styles, err := page.GlobalStyles()
|
||||
if err != nil {
|
||||
res.Warnings = append(res.Warnings, err.Error())
|
||||
}
|
||||
res.Styles = append(res.Styles, styles...)
|
||||
|
||||
// Page Styles
|
||||
if page.Codes.CSS.Code != "" {
|
||||
res.Styles = append(res.Styles, filepath.Join("@pages", page.Route, page.Name+".css"))
|
||||
}
|
||||
|
||||
// Render the HTML with the data
|
||||
// Page Scripts
|
||||
if page.Codes.JS.Code != "" {
|
||||
res.Scripts = append(res.Scripts, filepath.Join("@pages", page.Route, page.Name+".js"))
|
||||
}
|
||||
if page.Codes.TS.Code != "" {
|
||||
res.Scripts = append(res.Scripts, filepath.Join("@pages", page.Route, page.Name+".ts"))
|
||||
}
|
||||
|
||||
data, err := page.Data(request)
|
||||
if err != nil {
|
||||
res.Warnings = append(res.Warnings, err.Error())
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
res.HTML = html
|
||||
return res, nil
|
||||
}
|
||||
|
||||
if html != "" {
|
||||
html, err := page.renderData(html, data, res.Warnings)
|
||||
if err != nil {
|
||||
res.Warnings = append(res.Warnings, err.Error())
|
||||
}
|
||||
res.HTML = html
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// RenderPreview render for the preview
|
||||
func (page *Page) RenderPreview() {}
|
||||
|
||||
// GlobalScripts get the global scripts
|
||||
func (page *Page) GlobalScripts() ([]string, error) {
|
||||
if page.Document == nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
doc, err := NewDocument(page.Document)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
// Global scripts
|
||||
scripts := []string{}
|
||||
doc.Find("script").Each(func(i int, s *goquery.Selection) {
|
||||
src, _ := s.Attr("src")
|
||||
if src != "" {
|
||||
scripts = append(scripts, src)
|
||||
}
|
||||
})
|
||||
|
||||
return scripts, nil
|
||||
}
|
||||
|
||||
// GlobalStyles get the global styles
|
||||
func (page *Page) GlobalStyles() ([]string, error) {
|
||||
|
||||
if page.Document == nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
doc, err := NewDocument(page.Document)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
// Global styles
|
||||
styles := []string{}
|
||||
doc.Find("link[rel=stylesheet]").Each(func(i int, s *goquery.Selection) {
|
||||
href, _ := s.Attr("href")
|
||||
if href != "" {
|
||||
styles = append(styles, href)
|
||||
}
|
||||
})
|
||||
|
||||
return styles, nil
|
||||
}
|
||||
|
||||
func (page *Page) document() []byte {
|
||||
if page.Document != nil {
|
||||
return page.Document
|
||||
}
|
||||
return DocumentDefault
|
||||
}
|
||||
|
|
@ -1,12 +1,5 @@
|
|||
package core
|
||||
|
||||
// SUI is the interface for the SUI
|
||||
type SUI interface {
|
||||
GetTemplates() ([]ITemplate, error)
|
||||
GetTemplate(name string) (ITemplate, error)
|
||||
UploadTemplate(src string, dst string) (ITemplate, error)
|
||||
}
|
||||
|
||||
// DSL the struct for the DSL
|
||||
type DSL struct {
|
||||
ID string `json:"-"`
|
||||
|
|
@ -21,6 +14,7 @@ type Page struct {
|
|||
Name string `json:"name,omitempty"`
|
||||
Path string `json:"-"`
|
||||
Codes SourceCodes `json:"-"`
|
||||
Document []byte `json:"-"`
|
||||
}
|
||||
|
||||
// Component is the struct for the component
|
||||
|
|
@ -47,6 +41,7 @@ type Template struct {
|
|||
Descrption string `json:"description"`
|
||||
Screenshots []string `json:"screenshots"`
|
||||
Themes []SelectOption `json:"themes"`
|
||||
Document []byte `json:"-"`
|
||||
}
|
||||
|
||||
// Theme is the struct for the theme
|
||||
|
|
@ -61,6 +56,27 @@ type SelectOption struct {
|
|||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// Request is the struct for the request
|
||||
type Request struct {
|
||||
Method string `json:"method"`
|
||||
Payload map[string]interface{} `json:"payload,omitempty"`
|
||||
Query map[string][]string `json:"query,omitempty"`
|
||||
Params map[string]string `json:"params,omitempty"`
|
||||
Headers []string `json:"headers,omitempty"`
|
||||
Body []byte `json:"body,omitempty"`
|
||||
Theme string `json:"theme,omitempty"`
|
||||
Locale string `json:"locale,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseEditor is the struct for the response
|
||||
type ResponseEditor struct {
|
||||
HTML string `json:"html,omitempty"`
|
||||
CSS string `json:"css,omitempty"`
|
||||
Scripts []string `json:"scripts,omitempty"`
|
||||
Styles []string `json:"styles,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// SourceCodes is the struct for the page codes
|
||||
type SourceCodes struct {
|
||||
HTML Source `json:"-"`
|
||||
|
|
@ -89,3 +105,34 @@ type Storage struct {
|
|||
Driver string `json:"driver"`
|
||||
Option map[string]interface{} `json:"option,omitempty"`
|
||||
}
|
||||
|
||||
// DocumentDefault is the default document
|
||||
var DocumentDefault = []byte(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ $REQ.locale || 'en' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{{ $DATA.head.title || '' }}</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="{{ $DATA.head.description || '' }}"
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="{{ $DATA.head.keywords || '' }}"
|
||||
/>
|
||||
<meta name="author" content="Yao" />
|
||||
<meta name="website" content="https://yaoapps.com" />
|
||||
<meta name="email" content="friends@iqka.com" />
|
||||
<meta name="version" content="2.0.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
</head>
|
||||
<body>
|
||||
{{ __page }}
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
|
|
|
|||
18
sui/core/utils.go
Normal file
18
sui/core/utils.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
// NewDocument create a new document
|
||||
func NewDocument(html []byte) (*goquery.Document, error) {
|
||||
return goquery.NewDocumentFromReader(bytes.NewReader(html))
|
||||
}
|
||||
|
||||
// NewDocumentString create a new document
|
||||
func NewDocumentString(html string) (*goquery.Document, error) {
|
||||
return goquery.NewDocumentFromReader(strings.NewReader(html))
|
||||
}
|
||||
|
|
@ -130,6 +130,16 @@ func (local *Local) getTemplate(id string, path string) (*Template, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// load the __document.html
|
||||
documentFile := filepath.Join(path, "__document.html")
|
||||
if local.fs.IsFile(documentFile) {
|
||||
documentBytes, err := local.fs.ReadFile(documentFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpl.Document = documentBytes
|
||||
}
|
||||
|
||||
return &tmpl, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ func TestGetTemplates(t *testing.T) {
|
|||
}
|
||||
|
||||
if len(dempTmpls) < 3 {
|
||||
t.Fatalf("The demo templates less than %v", len(dempTmpls))
|
||||
t.Fatalf("The demo templates less than 3 (%v<3)", len(dempTmpls))
|
||||
}
|
||||
|
||||
assert.Equal(t, "tech-blue", dempTmpls[0].(*Template).ID)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ func (tmpl *Template) getPage(route, file string) (core.IPage, error) {
|
|||
Page: &core.Page{
|
||||
Route: route,
|
||||
Path: path,
|
||||
Name: name,
|
||||
Codes: core.SourceCodes{
|
||||
HTML: core.Source{File: fmt.Sprintf("%s%s", name, filepath.Ext(file))},
|
||||
CSS: core.Source{File: fmt.Sprintf("%s.css", name)},
|
||||
|
|
@ -117,12 +118,14 @@ func (page *Page) Load() error {
|
|||
|
||||
} else {
|
||||
jsFile := filepath.Join(page.Path, page.Codes.JS.File)
|
||||
if exist, _ := page.tmpl.local.fs.Exists(jsFile); exist {
|
||||
jsCode, err := page.tmpl.local.fs.ReadFile(jsFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
page.Codes.JS.Code = string(jsCode)
|
||||
}
|
||||
}
|
||||
|
||||
// Read the HTML code
|
||||
htmlFile := filepath.Join(page.Path, page.Codes.HTML.File)
|
||||
|
|
@ -155,5 +158,7 @@ func (page *Page) Load() error {
|
|||
page.Codes.DATA.Code = string(dataCode)
|
||||
}
|
||||
|
||||
// Set the page document
|
||||
page.Document = page.tmpl.Document
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/yao/sui/core"
|
||||
)
|
||||
|
||||
func TestTemplatePages(t *testing.T) {
|
||||
|
|
@ -113,3 +114,43 @@ func TestTemplatePageJS(t *testing.T) {
|
|||
_, err = tmpl.Page("/the/page/could/not/be/found")
|
||||
assert.Contains(t, err.Error(), "Page /the/page/could/not/be/found not found")
|
||||
}
|
||||
|
||||
func TestPageRenderEditor(t *testing.T) {
|
||||
|
||||
tests := prepare(t)
|
||||
defer clean()
|
||||
|
||||
tmpl, err := tests.Demo.GetTemplate("tech-blue")
|
||||
if err != nil {
|
||||
t.Fatalf("GetTemplate error: %v", err)
|
||||
}
|
||||
|
||||
page, err := tmpl.Page("/index")
|
||||
if err != nil {
|
||||
t.Fatalf("Page error: %v", err)
|
||||
}
|
||||
|
||||
r := &core.Request{Method: "GET"}
|
||||
res, err := page.RenderEditor(r)
|
||||
if err != nil {
|
||||
t.Fatalf("RenderEditor error: %v", err)
|
||||
}
|
||||
|
||||
assert.NotEmpty(t, res.HTML)
|
||||
assert.NotEmpty(t, res.CSS)
|
||||
assert.NotEmpty(t, res.Scripts)
|
||||
assert.NotEmpty(t, res.Styles)
|
||||
assert.Equal(t, 4, len(res.Scripts))
|
||||
assert.Equal(t, 5, len(res.Styles))
|
||||
|
||||
assert.Equal(t, "@assets/libs/tiny-slider/min/tiny-slider.js", res.Scripts[0])
|
||||
assert.Equal(t, "@assets/libs/feather-icons/feather.min.js", res.Scripts[1])
|
||||
assert.Equal(t, "@assets/js/plugins.init.js", res.Scripts[2])
|
||||
assert.Equal(t, "@pages/index/index.js", res.Scripts[3])
|
||||
|
||||
assert.Equal(t, "@assets/libs/tiny-slider/tiny-slider.css", res.Styles[0])
|
||||
assert.Equal(t, "@assets/libs/@iconscout/unicons/css/line.css", res.Styles[1])
|
||||
assert.Equal(t, "@assets/libs/@mdi/font/css/materialdesignicons.min.css", res.Styles[2])
|
||||
assert.Equal(t, "@assets/css/tailwind.css", res.Styles[3])
|
||||
assert.Equal(t, "@pages/index/index.css", res.Styles[4])
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue