refactor: Copy slots in BuildAsComponent method
This commit is contained in:
parent
6542c6e46b
commit
57e72a698d
4 changed files with 108 additions and 21 deletions
|
|
@ -63,6 +63,7 @@ func (page *Page) Build(ctx *BuildContext, option *BuildOption) (*goquery.Docume
|
|||
|
||||
// BuildAsComponent build the page as component
|
||||
func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, option *BuildOption) (string, error) {
|
||||
|
||||
if page.parent == nil {
|
||||
return "", fmt.Errorf("The parent page is not set")
|
||||
}
|
||||
|
|
@ -111,19 +112,50 @@ func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, op
|
|||
first := body.Children().First()
|
||||
|
||||
page.copyProps(ctx, sel, first, attrs...)
|
||||
page.copySlots(ctx, sel, first)
|
||||
page.buildComponents(doc, ctx, &opt)
|
||||
data := Data{"$props": page.Attrs}
|
||||
data.ReplaceSelectionUse(slotRe, first)
|
||||
html, err = body.Html()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Update the component
|
||||
data := Data{"$props": page.Attrs}
|
||||
html, _ = data.ReplaceUse(slotRe, html)
|
||||
sel.ReplaceWithHtml(html)
|
||||
return html, nil
|
||||
}
|
||||
|
||||
func (page *Page) copySlots(ctx *BuildContext, from *goquery.Selection, to *goquery.Selection) error {
|
||||
slots := from.Find("slot")
|
||||
if slots.Length() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < slots.Length(); i++ {
|
||||
slot := slots.Eq(i)
|
||||
name, has := slot.Attr("name")
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the slot
|
||||
slotSel := to.Find(fmt.Sprintf("slot[name='%s']", name))
|
||||
|
||||
if slotSel.Length() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy the slot
|
||||
html, err := slot.Html()
|
||||
if err != nil {
|
||||
ctx.warnings = append(ctx.warnings, err.Error())
|
||||
continue
|
||||
}
|
||||
slotSel.SetHtml(html)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (page *Page) copyProps(ctx *BuildContext, from *goquery.Selection, to *goquery.Selection, extra ...html.Attribute) error {
|
||||
attrs := from.Get(0).Attr
|
||||
prefix := "s:prop"
|
||||
|
|
@ -135,28 +167,29 @@ func (page *Page) copyProps(ctx *BuildContext, from *goquery.Selection, to *goqu
|
|||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(attr.Key, "...[{") {
|
||||
if strings.HasPrefix(attr.Key, "...$props") {
|
||||
data := Data{"$props": page.parent.Attrs}
|
||||
|
||||
val, err := data.Exec(attr.Key[3:])
|
||||
val, err := data.Exec(fmt.Sprintf("{{ %s }}", attr.Key[3:]))
|
||||
if err != nil {
|
||||
ctx.warnings = append(ctx.warnings, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
switch value := val.(type) {
|
||||
case map[string]string:
|
||||
for key, value := range value {
|
||||
page.Attrs[key] = value
|
||||
key = fmt.Sprintf("%s:%s", prefix, key)
|
||||
to.SetAttr(key, value)
|
||||
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
val := attr.Val
|
||||
if strings.HasPrefix(attr.Key, `...\$props`) {
|
||||
val = fmt.Sprintf("{{ $props.%s }}", attr.Key[9:])
|
||||
}
|
||||
|
||||
if strings.HasPrefix(attr.Key, "...") {
|
||||
val = attr.Key[3:]
|
||||
}
|
||||
|
|
@ -194,6 +227,12 @@ func (page *Page) buildComponents(doc *goquery.Document, ctx *BuildContext, opti
|
|||
return
|
||||
}
|
||||
|
||||
// Slot tag
|
||||
tagName := sel.Get(0).Data
|
||||
if tagName == "slot" {
|
||||
return
|
||||
}
|
||||
|
||||
sel.SetAttr("parsed", "true")
|
||||
|
||||
// Check if Just-In-Time Component ( "is" has variable )
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package core
|
|||
// NewBuildContext create a new build context
|
||||
func NewBuildContext(global *GlobalBuildContext) *BuildContext {
|
||||
return &BuildContext{
|
||||
components: map[string]bool{},
|
||||
components: map[string]string{},
|
||||
sequence: 1,
|
||||
scripts: []ScriptNode{},
|
||||
scriptUnique: map[string]bool{},
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/expr-lang/expr/vm"
|
||||
"github.com/yaoapp/gou/process"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
// If set the map value, should keep the space at the end of the statement
|
||||
|
|
@ -86,16 +88,7 @@ func (data Data) ExecString(stmt string) (string, error) {
|
|||
|
||||
// Replace replace the statement
|
||||
func (data Data) Replace(value string) (string, bool) {
|
||||
hasStmt := false
|
||||
res := stmtRe.ReplaceAllStringFunc(value, func(stmt string) string {
|
||||
hasStmt = true
|
||||
res, err := data.ExecString(stmt)
|
||||
if err != nil {
|
||||
log.Warn("Replace %s: %s", stmt, err)
|
||||
}
|
||||
return res
|
||||
})
|
||||
return res, hasStmt
|
||||
return data.ReplaceUse(stmtRe, value)
|
||||
}
|
||||
|
||||
// ReplaceUse replace the statement use the regexp
|
||||
|
|
@ -112,6 +105,61 @@ func (data Data) ReplaceUse(re *regexp.Regexp, value string) (string, bool) {
|
|||
return res, hasStmt
|
||||
}
|
||||
|
||||
// ReplaceSelection replace the statement in the selection
|
||||
func (data Data) ReplaceSelection(sel *goquery.Selection) bool {
|
||||
return data.ReplaceSelectionUse(stmtRe, sel)
|
||||
}
|
||||
|
||||
// ReplaceSelectionUse replace the statement in the selection use the regexp
|
||||
func (data Data) ReplaceSelectionUse(re *regexp.Regexp, sel *goquery.Selection) bool {
|
||||
hasStmt := false
|
||||
for _, node := range sel.Nodes {
|
||||
ok := data.replaceNodeUse(re, node)
|
||||
if ok {
|
||||
hasStmt = true
|
||||
}
|
||||
}
|
||||
return hasStmt
|
||||
}
|
||||
|
||||
func (data Data) replaceNodeUse(re *regexp.Regexp, node *html.Node) bool {
|
||||
hasStmt := false
|
||||
switch node.Type {
|
||||
case html.TextNode:
|
||||
v, ok := data.ReplaceUse(re, node.Data)
|
||||
node.Data = v
|
||||
if ok {
|
||||
hasStmt = true
|
||||
}
|
||||
break
|
||||
|
||||
case html.ElementNode:
|
||||
for i := range node.Attr {
|
||||
// Keepwords
|
||||
if strings.HasPrefix(node.Attr[i].Key, "s:") || node.Attr[i].Key == "is" {
|
||||
continue
|
||||
}
|
||||
|
||||
v, ok := data.ReplaceUse(re, node.Attr[i].Val)
|
||||
node.Attr[i].Val = v
|
||||
if ok {
|
||||
hasStmt = true
|
||||
}
|
||||
}
|
||||
|
||||
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
||||
ok := data.replaceNodeUse(re, c)
|
||||
if ok {
|
||||
hasStmt = true
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return hasStmt
|
||||
|
||||
}
|
||||
|
||||
func _process(args ...any) (interface{}, error) {
|
||||
|
||||
if len(args) < 1 {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ type Page struct {
|
|||
|
||||
// BuildContext is the struct for the build context
|
||||
type BuildContext struct {
|
||||
components map[string]bool
|
||||
components map[string]string
|
||||
jitComponents map[string]bool
|
||||
sequence int
|
||||
doc *goquery.Document
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue