feat: Add and optimize SUI CompileAsComponent support

This commit is contained in:
Max 2024-07-05 16:19:57 +08:00
parent a435b1ad6e
commit cf45040a1c
5 changed files with 155 additions and 19 deletions

View file

@ -160,6 +160,18 @@ func (page *Page) parse(ctx *BuildContext, doc *goquery.Document, option *BuildO
page.Translations = append(page.Translations, translations...)
}
name, has := sel.Attr("is")
if has {
// Check if Just-In-Time Component ( "is" has variable )
if ctx.isJitComponent(name) {
sel.SetAttr("s:jit", "true")
sel.SetAttr("s:root", public.Root)
ctx.addJitComponent(name)
return false
}
return true
}
tagName := sel.Get(0).Data
if tagName == "page" {
return true
@ -169,16 +181,6 @@ func (page *Page) parse(ctx *BuildContext, doc *goquery.Document, option *BuildO
return false
}
name, has := sel.Attr("is")
if has {
// Just in time component
if ctx.isJitComponent(name) {
sel.SetAttr("s:jit", "true")
sel.SetAttr("s:root", public.Root)
ctx.addJitComponent(name)
return false
}
}
return has
})

View file

@ -66,6 +66,27 @@ func (page *Page) Compile(ctx *BuildContext, option *BuildOption) (string, error
return html, nil
}
// CompileAsComponent compile the page as component
func (page *Page) CompileAsComponent(ctx *BuildContext, option *BuildOption) (string, error) {
opt := *option
opt.IgnoreDocument = true
opt.WithWrapper = true
doc, warnings, err := page.Build(ctx, &opt)
if err != nil {
return "", err
}
if warnings != nil && len(warnings) > 0 {
for _, warning := range warnings {
log.Warn("Compile page %s/%s/%s: %s", page.SuiID, page.TemplateID, page.Route, warning)
}
}
page.ReplaceDocument(doc)
return doc.Find("body").Html()
}
// CompileJS compile the javascript
func (page *Page) CompileJS(source []byte, minify bool) ([]byte, []string, error) {
scripts := []string{}

View file

@ -61,16 +61,14 @@ func (tmpl *Template) Build(option *core.BuildOption) error {
// loaed pages
tmpl.loaded = map[string]core.IPage{}
for _, page := range pages {
perr := page.Load()
err := page.Load()
if err != nil {
err = multierror.Append(perr)
continue
return err
}
perr = page.Build(ctx, option)
if perr != nil {
err = multierror.Append(perr)
continue
err = page.Build(ctx, option)
if err != nil {
return err
}
tmpl.loaded[page.Get().Route] = page
}
@ -180,7 +178,6 @@ func (page *Page) Build(globalCtx *core.GlobalBuildContext, option *core.BuildOp
option.AssetRoot = filepath.Join(root, "assets")
}
log.Trace("Build the page %s AssetRoot: %s", page.Route, option.AssetRoot)
html, err := page.Page.Compile(ctx, option)
if err != nil {
return err
@ -229,7 +226,60 @@ func (page *Page) Build(globalCtx *core.GlobalBuildContext, option *core.BuildOp
// BuildAsComponent build the page as component
func (page *Page) BuildAsComponent(globalCtx *core.GlobalBuildContext, option *core.BuildOption) error {
return page.writeJitHTML([]byte("<div>"+page.Route+" {{ type }} {{ bind }} </div>"), option.Data)
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, err := page.Page.CompileAsComponent(ctx, option)
if err != nil {
return err
}
// Save the html
err = page.writeJitHTML([]byte(html), option.Data)
if err != nil {
return err
}
// Save the locale files
err = page.writeLocaleFiles(option.Data)
if err != nil {
return err
}
// Jit Components
if globalCtx == nil {
jitComponents, err := page.tmpl.GlobRoutes(ctx.GetJitComponents(), true)
if err != nil {
return 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
}
}
err = p.BuildAsComponent(globalCtx, option)
if err != nil {
err = multierror.Append(err)
}
}
}
return err
}
func (page *Page) publicFile(data map[string]interface{}) string {

View file

@ -1,8 +1,12 @@
package local
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/yao/sui/core"
)
@ -19,4 +23,61 @@ func TestTemplateBuild(t *testing.T) {
if err != nil {
t.Fatalf("Components error: %v", err)
}
index := "/index.sui"
// Check SUI
root := application.App.Root()
public := tmpl.(*Template).local.GetPublic()
path := filepath.Join(root, "public", public.Root)
assert.FileExists(t, filepath.Join(path, index))
content, err := os.ReadFile(filepath.Join(path, index))
if err != nil {
t.Fatalf("ReadFile error: %v", err)
}
assert.Contains(t, string(content), "body")
assert.Contains(t, string(content), `<script src="/unit-test/assets/js/import.js"></script>`)
assert.Contains(t, string(content), `<script name="config" type="json">`)
assert.Contains(t, string(content), `<script name="data" type="json">`)
assert.Contains(t, string(content), `<script name="global" type="json">`)
}
func TestTemplateBuildAsComponent(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Web.GetTemplate("default")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
err = tmpl.Build(&core.BuildOption{SSR: true})
if err != nil {
t.Fatalf("Components error: %v", err)
}
cselect := "/flowbite/components/edit/select.jit"
cinput := "/flowbite/components/edit/input.jit"
// Check JIT
root := application.App.Root()
public := tmpl.(*Template).local.GetPublic()
path := filepath.Join(root, "public", public.Root)
assert.FileExists(t, filepath.Join(path, cselect))
assert.FileExists(t, filepath.Join(path, cinput))
content, err := os.ReadFile(filepath.Join(path, cselect))
if err != nil {
t.Fatalf("ReadFile error: %v", err)
}
assert.NotContains(t, string(content), "body")
assert.NotContains(t, string(content), `<script name="config" type="json">`)
assert.NotContains(t, string(content), `<script name="data" type="json">`)
assert.NotContains(t, string(content), `<script name="global" type="json">`)
assert.Contains(t, string(content), "function Init()")
assert.Contains(t, string(content), `type="flowbite-edit-select"`)
}

View file

@ -98,6 +98,7 @@ func prepare(t *testing.T) TestCase {
if err != nil {
t.Fatalf("New error: %v", err)
}
core.SUIs["web"] = web
testDSL, err := core.Load("/suis/test.sui.yao", "test")
if err != nil {
@ -108,6 +109,7 @@ func prepare(t *testing.T) TestCase {
if err != nil {
t.Fatalf("New error: %v", err)
}
core.SUIs["test"] = test
return TestCase{
Test: test,
Web: web,