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

feat: ComponentScript spread attribute support #595

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.608
0.2.610
33 changes: 25 additions & 8 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1021,15 +1021,25 @@ func isScriptAttribute(name string) bool {

func (g *generator) writeElementScript(indentLevel int, n parser.Element) (err error) {
var scriptExpressions []string
var spreadAttributes []string
for _, attr := range n.Attributes {
scriptExpressions = append(scriptExpressions, getAttributeScripts(attr)...)
scripts, spreads := getAttributeScripts(attr)
scriptExpressions = append(scriptExpressions, scripts...)
spreadAttributes = append(spreadAttributes, spreads...)
}
if len(scriptExpressions) == 0 {
if len(scriptExpressions) == 0 && len(spreadAttributes) == 0 {
return
}

renderFuncString := "RenderScriptItems"
spreadParamString := ""
if len(spreadAttributes) > 0 {
renderFuncString = "RenderScriptItemsWithSpread"
spreadParamString = "[]templ.Attributes{" + strings.Join(spreadAttributes, ", ") + "}, "
}
// Render the scripts before the element if required.
// templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, a, b, c)
if _, err = g.w.WriteIndent(indentLevel, "templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, "+strings.Join(scriptExpressions, ", ")+")\n"); err != nil {
// templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, []Attributes, a, b, c)
if _, err = g.w.WriteIndent(indentLevel, "templ_7745c5c3_Err = templ."+renderFuncString+"(ctx, templ_7745c5c3_Buffer, "+spreadParamString+strings.Join(scriptExpressions, ", ")+")\n"); err != nil {
return err
}
if err = g.writeErrorHandler(indentLevel); err != nil {
Expand All @@ -1038,13 +1048,17 @@ func (g *generator) writeElementScript(indentLevel int, n parser.Element) (err e
return err
}

func getAttributeScripts(attr parser.Attribute) (scripts []string) {
func getAttributeScripts(attr parser.Attribute) (scripts []string, spreads []string) {
if attr, ok := attr.(parser.ConditionalAttribute); ok {
for _, attr := range attr.Then {
scripts = append(scripts, getAttributeScripts(attr)...)
thenScripts, thenSpreads := getAttributeScripts(attr)
scripts = append(scripts, thenScripts...)
spreads = append(spreads, thenSpreads...)
}
for _, attr := range attr.Else {
scripts = append(scripts, getAttributeScripts(attr)...)
elseScripts, elseSpreads := getAttributeScripts(attr)
scripts = append(scripts, elseScripts...)
spreads = append(spreads, elseSpreads...)
}
}
if attr, ok := attr.(parser.ExpressionAttribute); ok {
Expand All @@ -1053,7 +1067,10 @@ func getAttributeScripts(attr parser.Attribute) (scripts []string) {
scripts = append(scripts, attr.Expression.Value)
}
}
return scripts
if attr, ok := attr.(parser.SpreadAttributes); ok {
spreads = append(spreads, attr.Expression.Value)
}
return
}

func (g *generator) writeBoolConstantAttribute(indentLevel int, attr parser.BoolConstantAttribute) (err error) {
Expand Down
30 changes: 27 additions & 3 deletions generator/test-spread-attributes/template_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ func RenderAttributes(ctx context.Context, w io.Writer, attributes Attributes) (
return err
}
}
case ComponentScript:
if err = writeStrings(w, ` `, EscapeString(key), `="`, value.Call, `"`); err != nil {
return err
}
}
}
return nil
Expand Down Expand Up @@ -691,6 +695,20 @@ func (c ComponentScript) Render(ctx context.Context, w io.Writer) error {

// RenderScriptItems renders a <script> element, if the script has not already been rendered.
func RenderScriptItems(ctx context.Context, w io.Writer, scripts ...ComponentScript) (err error) {
return RenderScriptItemsWithSpread(ctx, w, nil, scripts...)
Copy link
Contributor Author

@alehechka alehechka Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mainly only went this route to keep RenderScriptItems unchanged to avoid a breaking change. But if that's not a concern we can just add the extra parameter to this function instead.

}

// RenderScriptItemsWithSpread renders a <script> element, if the script has not already been rendered.
// Includes support for scripts passed from spread attributes { attrs... }.
func RenderScriptItemsWithSpread(ctx context.Context, w io.Writer, attrSlice []Attributes, scripts ...ComponentScript) (err error) {
for _, attrs := range attrSlice {
for _, attr := range attrs {
if script, ok := attr.(ComponentScript); ok {
scripts = append(scripts, script)
}
}
}

if len(scripts) == 0 {
return nil
}
Expand Down