diff --git a/.changeset/gold-bananas-drum.md b/.changeset/gold-bananas-drum.md new file mode 100644 index 000000000..c2fc4a646 --- /dev/null +++ b/.changeset/gold-bananas-drum.md @@ -0,0 +1,5 @@ +--- +'@astrojs/compiler': patch +--- + +Rollbacks the dynamic slot generation feature to rework it diff --git a/internal/printer/print-to-js.go b/internal/printer/print-to-js.go index c37cf2061..c43b0d8b2 100644 --- a/internal/printer/print-to-js.go +++ b/internal/printer/print-to-js.go @@ -69,12 +69,6 @@ type ExtractedStatement struct { Loc loc.Loc } -type NestedSlotChild struct { - SlotProp string - Children []*Node - FirstInGroup bool -} - func printToJs(p *printer, n *Node, cssLen int, opts transform.TransformOptions) PrintResult { printedMaybeHead := false render1(p, n, RenderOptions{ @@ -432,7 +426,7 @@ func render1(p *printer, n *Node, opts RenderOptions) { p.printAttributesToObject(n) } else if isSlot { if len(n.Attr) == 0 { - p.print(DEFAULT_SLOT_PROP) + p.print(`"default"`) } else { slotted := false for _, a := range n.Attr { @@ -445,7 +439,6 @@ func render1(p *printer, n *Node, opts RenderOptions) { p.print(`"` + escapeDoubleQuote(a.Val) + `"`) slotted = true default: - // add ability to use expressions for slot names later p.handler.AppendError(&loc.ErrorWithRange{ Code: loc.ERROR_UNSUPPORTED_SLOT_ATTRIBUTE, Text: "slot[name] must be a static string", @@ -454,7 +447,7 @@ func render1(p *printer, n *Node, opts RenderOptions) { } } if !slotted { - p.print(DEFAULT_SLOT_PROP) + p.print(`"default"`) } } p.print(`]`) @@ -558,8 +551,8 @@ func render1(p *printer, n *Node, opts RenderOptions) { if !isAllWhiteSpace { switch true { case n.CustomElement: - p.print(`,({`) - p.print(fmt.Sprintf(`%s: () => `, DEFAULT_SLOT_PROP)) + p.print(`,{`) + p.print(fmt.Sprintf(`"%s": () => `, "default")) p.printTemplateLiteralOpen() for c := n.FirstChild; c != nil; c = c.NextSibling { render1(p, c, RenderOptions{ @@ -572,9 +565,166 @@ func render1(p *printer, n *Node, opts RenderOptions) { }) } p.printTemplateLiteralClose() - p.print(`,})`) + p.print(`,}`) case isComponent: - handleSlots(p, n, opts, depth) + p.print(`,`) + slottedChildren := make(map[string][]*Node) + conditionalSlottedChildren := make([][]*Node, 0) + for c := n.FirstChild; c != nil; c = c.NextSibling { + slotProp := `"default"` + for _, a := range c.Attr { + if a.Key == "slot" { + if a.Type == QuotedAttribute { + slotProp = fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) + } else if a.Type == ExpressionAttribute { + slotProp = fmt.Sprintf(`[%s]`, a.Val) + } else { + p.handler.AppendError(&loc.ErrorWithRange{ + Code: loc.ERROR_UNSUPPORTED_SLOT_ATTRIBUTE, + Text: "slot[name] must be a static string", + Range: loc.Range{Loc: a.ValLoc, Len: len(a.Val)}, + }) + } + } + } + if c.Expression { + nestedSlots := make([]string, 0) + for c1 := c.FirstChild; c1 != nil; c1 = c1.NextSibling { + for _, a := range c1.Attr { + if a.Key == "slot" { + if a.Type == QuotedAttribute { + nestedSlotProp := fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) + nestedSlots = append(nestedSlots, nestedSlotProp) + } else if a.Type == ExpressionAttribute { + nestedSlotProp := fmt.Sprintf(`[%s]`, a.Val) + nestedSlots = append(nestedSlots, nestedSlotProp) + } else { + panic(`unknown slot attribute type`) + } + } + } + } + + if len(nestedSlots) == 1 { + slotProp = nestedSlots[0] + slottedChildren[slotProp] = append(slottedChildren[slotProp], c) + continue + } else if len(nestedSlots) > 1 { + conditionalChildren := make([]*Node, 0) + child_loop: + for c1 := c.FirstChild; c1 != nil; c1 = c1.NextSibling { + for _, a := range c1.Attr { + if a.Key == "slot" { + if a.Type == QuotedAttribute { + nestedSlotProp := fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) + nestedSlots = append(nestedSlots, nestedSlotProp) + conditionalChildren = append(conditionalChildren, &Node{Type: TextNode, Data: fmt.Sprintf("{%s: () => ", nestedSlotProp), Loc: make([]loc.Loc, 1)}) + conditionalChildren = append(conditionalChildren, c1) + conditionalChildren = append(conditionalChildren, &Node{Type: TextNode, Data: "}", Loc: make([]loc.Loc, 1)}) + continue child_loop + } else if a.Type == ExpressionAttribute { + nestedSlotProp := fmt.Sprintf(`[%s]`, a.Val) + nestedSlots = append(nestedSlots, nestedSlotProp) + conditionalChildren = append(conditionalChildren, &Node{Type: TextNode, Data: fmt.Sprintf("{%s: () => ", nestedSlotProp), Loc: make([]loc.Loc, 1)}) + conditionalChildren = append(conditionalChildren, c1) + conditionalChildren = append(conditionalChildren, &Node{Type: TextNode, Data: "}", Loc: make([]loc.Loc, 1)}) + continue child_loop + } else { + panic(`unknown slot attribute type`) + } + } + } + conditionalChildren = append(conditionalChildren, c1) + } + conditionalSlottedChildren = append(conditionalSlottedChildren, conditionalChildren) + continue + } + } + + // Only slot ElementNodes (except expressions containing only comments) or non-empty TextNodes! + // CommentNode, JSX comments and others should not be slotted + if expressionOnlyHasComment(c) { + continue + } + if c.Type == ElementNode || c.Type == TextNode && !emptyTextNodeWithoutSiblings(c) { + slottedChildren[slotProp] = append(slottedChildren[slotProp], c) + } + } + // fix: sort keys for stable output + slottedKeys := make([]string, 0, len(slottedChildren)) + for k := range slottedChildren { + slottedKeys = append(slottedKeys, k) + } + sort.Strings(slottedKeys) + if len(conditionalSlottedChildren) > 0 { + p.print(`$$mergeSlots(`) + } + p.print(`{`) + numberOfSlots := len(slottedKeys) + if numberOfSlots > 0 { + childrenLoop: + for _, slotProp := range slottedKeys { + children := slottedChildren[slotProp] + + // If there are named slots, the default slot cannot be only whitespace + if numberOfSlots > 1 && slotProp == "\"default\"" { + // Loop over the children and verify that at least one non-whitespace node exists. + foundNonWhitespace := false + for _, child := range children { + if child.Type != TextNode || strings.TrimSpace(child.Data) != "" { + foundNonWhitespace = true + } + } + if !foundNonWhitespace { + continue childrenLoop + } + } + + // If selected, pass through result object on the Astro side + if opts.opts.ResultScopedSlot { + p.print(fmt.Sprintf(`%s: ($$result) => `, slotProp)) + } else { + p.print(fmt.Sprintf(`%s: () => `, slotProp)) + } + + p.printTemplateLiteralOpen() + for _, child := range children { + render1(p, child, RenderOptions{ + isRoot: false, + isExpression: opts.isExpression, + depth: depth + 1, + opts: opts.opts, + cssLen: opts.cssLen, + printedMaybeHead: opts.printedMaybeHead, + }) + } + p.printTemplateLiteralClose() + p.print(`,`) + } + } + p.print(`}`) + if len(conditionalSlottedChildren) > 0 { + for _, children := range conditionalSlottedChildren { + p.print(",") + for _, child := range children { + if child.Type == ElementNode { + p.printTemplateLiteralOpen() + } + render1(p, child, RenderOptions{ + isRoot: false, + isExpression: opts.isExpression, + depth: depth + 1, + opts: opts.opts, + cssLen: opts.cssLen, + printedMaybeHead: opts.printedMaybeHead, + }) + if child.Type == ElementNode { + p.printTemplateLiteralClose() + } + } + } + p.print(`)`) + } case isSlot: p.print(`,`) p.printTemplateLiteralOpen() @@ -638,8 +788,6 @@ func render1(p *printer, n *Node, opts RenderOptions) { } } -const DEFAULT_SLOT_PROP = `"default"` - // Section 12.1.2, "Elements", gives this list of void elements. Void elements // are those that can't have any contents. // nolint @@ -660,313 +808,3 @@ var voidElements = map[string]bool{ "track": true, "wbr": true, } - -func handleSlots(p *printer, n *Node, opts RenderOptions, depth int) { - p.print(`,`) - slottedChildren := make(map[string][]*Node) - hasAnyNestedDynamicSlot := false - nestedSlotChildren := make([]*NestedSlotChild, 0) - - // the highest number of nested slots in an expression - maxNestedSlotsCount := 0 - - for c := n.FirstChild; c != nil; c = c.NextSibling { - slotProp := DEFAULT_SLOT_PROP - for _, a := range c.Attr { - if a.Key == "slot" { - if a.Type == QuotedAttribute { - slotProp = fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) - } else if a.Type == ExpressionAttribute { - slotProp = fmt.Sprintf(`[%s]`, a.Val) - } else if a.Type == TemplateLiteralAttribute { - slotProp = fmt.Sprintf(`[%s%s%s]`, BACKTICK, a.Val, BACKTICK) - } else { - p.handler.AppendError(&loc.ErrorWithRange{ - Code: loc.ERROR_UNSUPPORTED_SLOT_ATTRIBUTE, - Text: "Unsupported slot attribute type", - Range: loc.Range{Loc: a.ValLoc, Len: len(a.Val)}, - }) - } - } - } - if c.Expression { - // Only slot ElementNodes (except expressions containing only comments) or non-empty TextNodes! - // CommentNode, JSX comments and others should not be slotted - if expressionOnlyHasComment(c) { - continue - } - nestedSlotsInExprCount := 0 - hasAnyDynamicSlotsInExpr := false - var slotProp = DEFAULT_SLOT_PROP - for c1 := c.FirstChild; c1 != nil; c1 = c1.NextSibling { - for _, a := range c1.Attr { - if a.Key == "slot" { - if a.Type == QuotedAttribute { - slotProp = fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) - } else if a.Type == ExpressionAttribute { - slotProp = fmt.Sprintf(`[%s]`, a.Val) - hasAnyNestedDynamicSlot, hasAnyDynamicSlotsInExpr = true, true - } else if a.Type == TemplateLiteralAttribute { - slotProp = fmt.Sprintf(`[%s%s%s]`, BACKTICK, a.Val, BACKTICK) - hasAnyNestedDynamicSlot, hasAnyDynamicSlotsInExpr = true, true - } else { - panic(`unknown slot attribute type`) - } - } - } - if c1.Type == ElementNode { - nestedSlotsInExprCount++ - } - } - - if nestedSlotsInExprCount == 1 && !hasAnyDynamicSlotsInExpr { - slottedChildren[slotProp] = append(slottedChildren[slotProp], c) - continue - } else if nestedSlotsInExprCount > 1 || hasAnyDynamicSlotsInExpr { - if nestedSlotsInExprCount > maxNestedSlotsCount { - maxNestedSlotsCount = nestedSlotsInExprCount - } - child_loop: - for c1 := c.FirstChild; c1 != nil; c1 = c1.NextSibling { - foundNamedSlot := false - isFirstInGroup := c1 == c.FirstChild - for _, a := range c1.Attr { - if a.Key == "slot" { - var nestedSlotProp string - var nestedSlotEntry *NestedSlotChild - if a.Type == QuotedAttribute { - nestedSlotProp = fmt.Sprintf(`"%s"`, escapeDoubleQuote(a.Val)) - } else if a.Type == ExpressionAttribute { - nestedSlotProp = fmt.Sprintf(`[%s]`, a.Val) - hasAnyNestedDynamicSlot = true - } else if a.Type == TemplateLiteralAttribute { - hasAnyNestedDynamicSlot = true - nestedSlotProp = fmt.Sprintf(`[%s%s%s]`, BACKTICK, a.Val, BACKTICK) - } else { - panic(`unknown slot attribute type`) - } - foundNamedSlot = true - nestedSlotEntry = &NestedSlotChild{nestedSlotProp, []*Node{c1}, isFirstInGroup} - nestedSlotChildren = append(nestedSlotChildren, nestedSlotEntry) - continue child_loop - } - } - if !foundNamedSlot && c1.Type == ElementNode { - pseudoSlotEntry := &NestedSlotChild{DEFAULT_SLOT_PROP, []*Node{c1}, isFirstInGroup} - nestedSlotChildren = append(nestedSlotChildren, pseudoSlotEntry) - } else { - nestedSlotEntry := &NestedSlotChild{`"@@NON_ELEMENT_ENTRY"`, []*Node{c1}, isFirstInGroup} - nestedSlotChildren = append(nestedSlotChildren, nestedSlotEntry) - } - } - continue - } - } - - if c.Type == ElementNode || c.Type == TextNode && !emptyTextNodeWithoutSiblings(c) { - slottedChildren[slotProp] = append(slottedChildren[slotProp], c) - } - } - // fix: sort keys for stable output - slottedKeys := make([]string, 0, len(slottedChildren)) - for k := range slottedChildren { - slottedKeys = append(slottedKeys, k) - } - sort.Strings(slottedKeys) - - // if any slotted expression contains more than one nested slot (e.g. {true ?
Bar
:
Foo
}
) - // OR if any expression contains a dynamic slot (e.g. {items.map((item)=> (
{item.name}
)}
) - // we need to use $$mergeSlots - shouldPrintMergeSlots := maxNestedSlotsCount > 1 || hasAnyNestedDynamicSlot - if shouldPrintMergeSlots { - p.print(`$$mergeSlots(`) - } - p.print(`({`) - numberOfSlots := len(slottedKeys) - if numberOfSlots > 0 { - childrenLoop: - for _, slotProp := range slottedKeys { - children := slottedChildren[slotProp] - - // If there are named slots, the default slot cannot be only whitespace - if numberOfSlots > 1 && slotProp == DEFAULT_SLOT_PROP { - // Loop over the children and verify that at least one non-whitespace node exists. - foundNonWhitespace := false - for _, child := range children { - if child.Type != TextNode || strings.TrimSpace(child.Data) != "" { - foundNonWhitespace = true - } - } - if !foundNonWhitespace { - continue childrenLoop - } - } - - // If selected, pass through result object on the Astro side - if opts.opts.ResultScopedSlot { - p.print(fmt.Sprintf(`%s: ($$result) => `, slotProp)) - } else { - p.print(fmt.Sprintf(`%s: () => `, slotProp)) - } - - p.printTemplateLiteralOpen() - for _, child := range children { - render1(p, child, RenderOptions{ - isRoot: false, - isExpression: opts.isExpression, - depth: depth + 1, - opts: opts.opts, - cssLen: opts.cssLen, - printedMaybeHead: opts.printedMaybeHead, - }) - } - p.printTemplateLiteralClose() - p.print(`,`) - } - } - p.print(`})`) - // print nested slots - if len(nestedSlotChildren) > 0 { - endSlotIndexes := generateEndSlotIndexes(nestedSlotChildren) - mergeDefaultSlotsAndUpdateIndexes(&nestedSlotChildren, &endSlotIndexes) - hasFoundFirstElementNode := false - for j, nestedSlot := range nestedSlotChildren { - if nestedSlot.FirstInGroup { - p.print(`,`) - } - // whether this is the first element node in the chain - // (used to determine which slot render function to use) - var isFirstElementInChain bool - isLastInChain := endSlotIndexes[j] - if nestedSlot.Children[0].Type == ElementNode && !hasFoundFirstElementNode { - isFirstElementInChain = true - hasFoundFirstElementNode = true - } - renderNestedSlotChild(p, nestedSlot, isFirstElementInChain, isLastInChain, depth, opts) - if isLastInChain { - // reset hasFoundFirstElementNode for the next chain - hasFoundFirstElementNode = false - } - } - } - if shouldPrintMergeSlots { - // close $$mergeSlots call - p.print(`)`) - } -} - -// Helper function to encapsulate nested slot entry rendering -func renderNestedSlotChild(p *printer, nestedSlotChild *NestedSlotChild, isFirstElementInChain bool, isLastInChain bool, depth int, opts RenderOptions) { - if nestedSlotChild.SlotProp == `"@@NON_ELEMENT_ENTRY"` { - for _, child := range nestedSlotChild.Children { - p.print(child.Data) - } - return - } - slotRenderFunction := getSlotRenderFunction(isFirstElementInChain) - slotRenderFunctionNode := &Node{Type: TextNode, Data: fmt.Sprintf(slotRenderFunction, nestedSlotChild.SlotProp), Loc: make([]loc.Loc, 1)} - // print the slot render function - render1(p, slotRenderFunctionNode, RenderOptions{ - isRoot: false, - isExpression: opts.isExpression, - depth: depth + 1, - opts: opts.opts, - cssLen: opts.cssLen, - printedMaybeHead: opts.printedMaybeHead, - }) - - // print the nested slotted children - p.printTemplateLiteralOpen() - for _, child := range nestedSlotChild.Children { - render1(p, child, RenderOptions{ - isRoot: false, - isExpression: false, - depth: depth, - opts: opts.opts, - cssLen: opts.cssLen, - printedMaybeHead: opts.printedMaybeHead, - }) - } - p.printTemplateLiteralClose() - - // when we are at the end of the chain, close the slot render function - if isLastInChain { - p.print(`})`) - } -} - -func generateEndSlotIndexes(nestedSlotChildren []*NestedSlotChild) map[int]bool { - endSlotIndexes := make(map[int]bool) - var latestElementNodeIndex int - - for i, nestedSlot := range nestedSlotChildren { - if nestedSlot.Children[0].Type == ElementNode { - latestElementNodeIndex = i - } else if isNonWhitespaceTextNode(nestedSlot.Children[0]) { - endSlotIndexes[latestElementNodeIndex] = true - } - } - - // Ensure the last element node index is also added to endSlotIndexes - if latestElementNodeIndex < len(nestedSlotChildren) { - endSlotIndexes[latestElementNodeIndex] = true - } - - return endSlotIndexes -} - -func mergeDefaultSlotsAndUpdateIndexes(nestedSlotChildren *[]*NestedSlotChild, endSlotIndexes *map[int]bool) { - bufferedDefaultSlot := &NestedSlotChild{SlotProp: DEFAULT_SLOT_PROP, Children: []*Node{}} - updatedNestedSlotChildren := make([]*NestedSlotChild, 0) - updatedEndSlotIndexes := make(map[int]bool) - - for i, nestedSlot := range *nestedSlotChildren { - if isDefaultSlot(nestedSlot) { - bufferedDefaultSlot.Children = append(bufferedDefaultSlot.Children, nestedSlot.Children...) - } else { - updatedNestedSlotChildren = append(updatedNestedSlotChildren, nestedSlot) - } - - // we reached the end of a slot chain - if (*endSlotIndexes)[i] { - // free up memory, this information is now outdated - // the updated information is stored in updatedEndSlotIndexes - delete(*endSlotIndexes, i) - - if len(bufferedDefaultSlot.Children) > 0 { - // if the buffered default slot contains any children - // add it to the updated nested slot children - updatedNestedSlotChildren = append(updatedNestedSlotChildren, bufferedDefaultSlot) - - // reset the buffered default slot - bufferedDefaultSlot = &NestedSlotChild{SlotProp: DEFAULT_SLOT_PROP, Children: []*Node{}} - } - // record the index of the last slot in the chain - updatedEndSlotIndexes[len(updatedNestedSlotChildren)-1] = true - } - - // free up memory, the actual information of nested slot - // is now stored in updatedNestedSlotChildren - (*nestedSlotChildren)[i] = nil - } - *nestedSlotChildren = updatedNestedSlotChildren - *endSlotIndexes = updatedEndSlotIndexes -} - -func getSlotRenderFunction(isNewSlotObject bool) string { - const FIRST_SLOT_CHILD_FUNCTION = "({%s: () => " - const NEXT_SLOT_CHILD_FUNCTION = ", %s: () => " - - if isNewSlotObject { - return FIRST_SLOT_CHILD_FUNCTION - } - return NEXT_SLOT_CHILD_FUNCTION -} - -func isNonWhitespaceTextNode(n *Node) bool { - return n.Type == TextNode && strings.TrimSpace(n.Data) != "" -} - -func isDefaultSlot(slot *NestedSlotChild) bool { - return slot.SlotProp == DEFAULT_SLOT_PROP -} diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index 9ed3248df..ed24a6827 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -165,14 +165,14 @@ func TestPrinter(t *testing.T) { name: "ternary component", source: `{special ?

Special

:

Not special

}`, want: want{ - code: `${special ? $$render` + BACKTICK + `${$$renderComponent($$result,'ChildDiv',ChildDiv,{},({"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

Special

` + BACKTICK + `,}))}` + BACKTICK + ` : $$render` + BACKTICK + `

Not special

` + BACKTICK + `}`, + code: `${special ? $$render` + BACKTICK + `${$$renderComponent($$result,'ChildDiv',ChildDiv,{},{"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

Special

` + BACKTICK + `,})}` + BACKTICK + ` : $$render` + BACKTICK + `

Not special

` + BACKTICK + `}`, }, }, { name: "ternary layout", source: `{toggleError ?

SITE: {Astro.site}

: <>

SITE: {Astro.site}

}`, want: want{ - code: `${toggleError ? $$render` + BACKTICK + `${$$renderComponent($$result,'BaseLayout',BaseLayout,{},({"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

SITE: ${Astro.site}

` + BACKTICK + `,}))}` + BACKTICK + ` : $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `

SITE: ${Astro.site}

` + BACKTICK + `,}))}` + BACKTICK + `}`, + code: `${toggleError ? $$render` + BACKTICK + `${$$renderComponent($$result,'BaseLayout',BaseLayout,{},{"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

SITE: ${Astro.site}

` + BACKTICK + `,})}` + BACKTICK + ` : $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `

SITE: ${Astro.site}

` + BACKTICK + `,})}` + BACKTICK + `}`, }, }, { @@ -182,164 +182,63 @@ func TestPrinter(t *testing.T) { code: `${$$renderSlot($$result,$$slots["default"])}`, }, }, - { - name: "nested dynamic slots I", - source: `{items.map((item)=>

)}`, - want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),items.map((item)=>({[item.id]: () => $$render`${$$maybeRenderHead($$result)}

`}))))}", - }, - }, - { - name: "nested dynamic slots II", - source: `{items.map((item)=>

)}`, - want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),items.map((item)=>({[item.id]: () => $$render`${$$maybeRenderHead($$result)}

`, [item.id+1]: () => $$render`

`}))))}", - }, - }, - { - name: "nested dynamic slots III", - source: `{items.map((item)=>
hey

There

!
)}
`, - want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),items.map((item)=> ({[item.id]: () => $$render`${$$maybeRenderHead($$result)}

`, [item.id+1]: () => $$render`

`, \"default\": () => $$render`
hey
There
!
`}))))}", - }, - }, - { - name: "nested dynamic slots IV", - source: `{items.map((item)=>
hey

There

!
)}
`, - want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),items.map((item)=> ({[item.id]: () => $$render`${$$maybeRenderHead($$result)}

` , [item.id+1]: () => $$render`

` , \"default\": () => $$render`
hey
There
!
`}))))}", - }, - }, - { - name: "nested dynamic slots V", - source: ` - - {items.map((item) => ( -
hey
-

- There -

-

!
- ))} -
`, - want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),items.map((item) => (\n\t\t({[item.id]: () => $$render`${$$maybeRenderHead($$result)}

`\n\t\t, [item.id + 1]: () => $$render`

`\n\t\t, \"default\": () => $$render`
hey
There
!
`})\n\t))))}", - }, - }, { name: "conditional slot", source: `{value &&
foo
}
`, want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},({\"test\": () => $$render`${value && $$render`${$$maybeRenderHead($$result)}
foo
`}`,}))}", + code: "${$$renderComponent($$result,'Component',Component,{},{\"test\": () => $$render`${value && $$render`${$$maybeRenderHead($$result)}
foo
`}`,})}", }, }, { name: "ternary slot", source: `{Math.random() > 0.5 ?
A
:
B
}
`, want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),Math.random() > 0.5 ? ({\"a\": () => $$render`${$$maybeRenderHead($$result)}
A
`}) : ({\"b\": () => $$render`
B
`})))}", + code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots({},Math.random() > 0.5 ? {\"a\": () => $$render`${$$maybeRenderHead($$result)}
A
`} : {\"b\": () => $$render`
B
`}))}", }, }, { - name: "ternary slot II", - source: ` - { - Astro.request.method === 'GET' ? ( -

Contact Form

-
- - -
- ) : ( -
Got: {formData?.get('name')}
- ) - } -
`, - want: want{ - code: `${$$renderComponent($$result,'Layout',Layout,{},$$mergeSlots(({}), - Astro.request.method === 'GET' ? ( - - ({"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

Contact Form

- - -
` + BACKTICK + `}) - ) : ( - ({"default": () => $$render` + BACKTICK + `
Got: ${formData?.get('name')}
` + BACKTICK + `}) - ) - ))}`, - }, - }, - { - name: "ternary slot with one implicit default", - source: `
- {useSlot - ?
Inside slot with red background
- :
Outside slot without background
- } -
`, - want: want{ - code: `${$$renderComponent($$result,'Main',Main,{},$$mergeSlots(({}),useSlot - ? ({"outside": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
Inside slot with red background
` + BACKTICK + `}) - : ({"default": () => $$render` + BACKTICK + `
Outside slot without background
` + BACKTICK + `}) - ))}`, - }, - }, - { - name: "function expression slots", + name: "function expression slots I", source: "\n{() => { switch (value) {\ncase 'a': return
A
\ncase 'b': return
B
\ncase 'c': return
C
\n}\n}}\n
", want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots(({}),() => { switch (value) {\ncase 'a': return ({\"a\": () => $$render`${$$maybeRenderHead($$result)}
A
`})\ncase 'b': return ({\"b\": () => $$render`
B
`})\ncase 'c': return ({\"c\": () => $$render`
C
`})}\n}))}", + code: "${$$renderComponent($$result,'Component',Component,{},$$mergeSlots({},() => { switch (value) {\ncase 'a': return {\"a\": () => $$render`${$$maybeRenderHead($$result)}
A
`}\ncase 'b': return {\"b\": () => $$render`
B
`}\ncase 'c': return {\"c\": () => $$render`
C
`}}\n}))}", }, }, { - name: "expression slot I", - source: `{true &&
A
}{false &&
B
}
`, + name: "function expression slots II (#959)", + source: ` +
+ + {components.map((component, i) => { + switch(component) { + case "Hero": + return
Hero
+ case "Component2": + return
Component2
+ } + })} +
+
+
`, want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},({\"a\": () => $$render`${true && $$render`${$$maybeRenderHead($$result)}
A
`}`,\"b\": () => $$render`${false && $$render`
B
`}`,}))}", + code: `${$$renderComponent($$result,'Layout',Layout,{"title":"Welcome to Astro."},{"default": () => $$render` + BACKTICK + ` + ${$$maybeRenderHead($$result)}
+ ${$$renderComponent($$result,'Layout',Layout,{"title":"switch bug"},{"default": () => $$render` + BACKTICK + `${components.map((component, i) => { + switch(component) { + case "Hero": + return $$render` + BACKTICK + `
Hero
` + BACKTICK + ` + case "Component2": + return $$render` + BACKTICK + `
Component2
` + BACKTICK + ` + } + })}` + BACKTICK + `,})} +
+` + BACKTICK + `,})}`, }, }, { - name: "expression slot II", - source: ` - {true && A} - {true ? B : null} - {() => C} - {true && Default} -`, + name: "expression slot", + source: `{true &&
A
}{false &&
B
}
`, want: want{ - code: "${$$renderComponent($$result,'Slotted',Slotted,{},({\"a\": () => $$render`${true && $$render`${$$maybeRenderHead($$result)}A`}`,\"b\": () => $$render`${true ? $$render`B` : null}`,\"c\": () => $$render`${() => $$render`C`}`,\"default\": () => $$render`${true && $$render`Default`}`,}))}", - }, - }, - { - name: "expression slot III", - source: ` - {true && A} - {true ? B : null} - {() => C} - {() => { - const value = 0.33; - if (value > 0.25) { - return DefaultAnother - } else if (value > 0.5) { - return Another - } else if (value > 0.75) { - return Other - } - return Yet Another - }} -`, - want: want{ - code: `${$$renderComponent($$result,'Slotted',Slotted,{},$$mergeSlots(({"b": () => $$render` + BACKTICK + `${true ? $$render` + BACKTICK + `${$$maybeRenderHead($$result)}B` + BACKTICK + ` : null}` + BACKTICK + `,"c": () => $$render` + BACKTICK + `${() => $$render` + BACKTICK + `C` + BACKTICK + `}` + BACKTICK + `,}),true && ({["a"]: () => $$render` + BACKTICK + `A` + BACKTICK + `}),() => { - const value = 0.33; - if (value > 0.25) { - return ({"hey": () => $$render` + BACKTICK + `Another` + BACKTICK + `, "default": () => $$render` + BACKTICK + `Default` + BACKTICK + `}) - } else if (value > 0.5) { - return ({"hey": () => $$render` + BACKTICK + `Another` + BACKTICK + `}) - } else if (value > 0.75) { - return ({"default": () => $$render` + BACKTICK + `Other` + BACKTICK + `}) - } - return ({"default": () => $$render` + BACKTICK + `Yet Another` + BACKTICK + `}) - }))}`, + code: "${$$renderComponent($$result,'Component',Component,{},{\"a\": () => $$render`${true && $$render`${$$maybeRenderHead($$result)}
A
`}`,\"b\": () => $$render`${false && $$render`
B
`}`,})}", }, }, { @@ -384,9 +283,9 @@ func TestPrinter(t *testing.T) {

Paragraph 2

`, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + ` + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + ` ${$$maybeRenderHead($$result)}

Paragraph 1

-

Paragraph 2

` + BACKTICK + `,}))}`, +

Paragraph 2

` + BACKTICK + `,})}`, }, }, { @@ -612,7 +511,7 @@ import type data from "test" }, }, { - name: "nested template literal expression I", + name: "nested template literal expression", source: "
", want: want{ code: "${$$maybeRenderHead($$result)}
", @@ -622,7 +521,7 @@ import type data from "test" name: "component in expression with its child expression before its child element", source: "{list.map(() => ({name}))}", want: want{ - code: "${list.map(() => ($$render`${$$renderComponent($$result,'Component',Component,{},({\"default\": () => $$render`${name}`,}))}`))}", + code: "${list.map(() => ($$render`${$$renderComponent($$result,'Component',Component,{},{\"default\": () => $$render`${name}`,})}`))}", }, }, { @@ -651,7 +550,7 @@ import type data from "test" `, want: want{ - code: `${$$renderComponent($$result,'Layout',Layout,{"title":"Welcome to Astro."},({"default": () => $$render` + BACKTICK + ` + code: `${$$renderComponent($$result,'Layout',Layout,{"title":"Welcome to Astro."},{"default": () => $$render` + BACKTICK + ` ${$$maybeRenderHead($$result)}

Welcome to Astro

${ @@ -673,7 +572,7 @@ import type data from "test" }) }
-` + BACKTICK + `,}))}`, +` + BACKTICK + `,})}`, }, }, { @@ -765,7 +664,21 @@ import * as ns from '../components'; name: "slot with quoted attributes", source: `
`, want: want{ - code: `${` + RENDER_COMPONENT + `($$result,'Component',Component,{},({"\"name\"": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
` + BACKTICK + `,}))}`, + code: `${` + RENDER_COMPONENT + `($$result,'Component',Component,{},{"\"name\"": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
` + BACKTICK + `,})}`, + }, + }, + { + name: "#955 ternary slot with text", + source: `Hello{isLeaf ?

Leaf

:

Branch

}world
`, + want: want{ + code: `${` + RENDER_COMPONENT + `($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `Hello${isLeaf ? $$render` + BACKTICK + `${$$maybeRenderHead($$result)}

Leaf

` + BACKTICK + ` : $$render` + BACKTICK + `

Branch

` + BACKTICK + `}world` + BACKTICK + `,})}`, + }, + }, + { + name: "#955 ternary slot with elements", + source: `
{isLeaf ?

Leaf

:

Branch

}
`, + want: want{ + code: `${` + RENDER_COMPONENT + `($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
${isLeaf ? $$render` + BACKTICK + `

Leaf

` + BACKTICK + ` : $$render` + BACKTICK + `

Branch

` + BACKTICK + `}
` + BACKTICK + `,})}`, }, }, { @@ -1095,14 +1008,14 @@ const groups = [[0, 1, 2], [3, 4, 5]]; name: "HTML comment in component inside expression I", source: "{(() => )}", want: want{ - code: "${(() => $$render`${$$renderComponent($$result,'Component',Component,{},({}))}`)}", + code: "${(() => $$render`${$$renderComponent($$result,'Component',Component,{},{})}`)}", }, }, { name: "HTML comment in component inside expression II", source: "{list.map(() => )}", want: want{ - code: "${list.map(() => $$render`${$$renderComponent($$result,'Component',Component,{},({}))}`)}", + code: "${list.map(() => $$render`${$$renderComponent($$result,'Component',Component,{},{})}`)}", }, }, { @@ -1137,7 +1050,7 @@ const groups = [[0, 1, 2], [3, 4, 5]]; name: "nested expressions V", source: `

title

{list.map(group =>

{group.label}

{group.items.map(item => {item})}
)}
`, want: want{ - code: "${$$maybeRenderHead($$result)}

title

${list.map(group => $$render`${$$renderComponent($$result,'Fragment',Fragment,{},({\"default\": () => $$render`

${group.label}

${group.items.map(item => $$render`${item}`)}`,}))}`)}
", + code: "${$$maybeRenderHead($$result)}

title

${list.map(group => $$render`${$$renderComponent($$result,'Fragment',Fragment,{},{\"default\": () => $$render`

${group.label}

${group.items.map(item => $$render`${item}`)}`,})}`)}
", }, }, { @@ -1228,7 +1141,7 @@ import Component from "test"; want: want{ frontmatter: []string{`import Component from "test";`}, metadata: metadata{modules: []string{`{ module: $$module1, specifier: 'test', assert: {} }`}}, - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + "`" + ` ${$$maybeRenderHead($$result)}
Default
` + "`" + `,"named": () => $$render` + "`" + `
Named
` + "`" + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + "`" + ` ${$$maybeRenderHead($$result)}
Default
` + "`" + `,"named": () => $$render` + "`" + `
Named
` + "`" + `,})}`, }, }, { @@ -1244,7 +1157,7 @@ import Component from 'test'; want: want{ frontmatter: []string{`import Component from 'test';`}, metadata: metadata{modules: []string{`{ module: $$module1, specifier: 'test', assert: {} }`}}, - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + "`" + ` ${$$maybeRenderHead($$result)}
Default
` + "`" + `,"named": () => $$render` + "`" + `
Named
` + "`" + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + "`" + ` ${$$maybeRenderHead($$result)}
Default
` + "`" + `,"named": () => $$render` + "`" + `
Named
` + "`" + `,})}`, }, }, { @@ -1254,7 +1167,7 @@ import Component from 'test'; {items.map(item =>
{item}
)} `, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{"data":(data)},({"default": () => $$render` + BACKTICK + `${items.map(item => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
${item}
` + BACKTICK + `)}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{"data":(data)},{"default": () => $$render` + BACKTICK + `${items.map(item => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
${item}
` + BACKTICK + `)}` + BACKTICK + `,})}`, }, }, { @@ -1303,7 +1216,7 @@ const testBool = true; ${testBool ? "Hey" : "Bye"} - ${testBool && ($$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `` + BACKTICK + `,}))}` + BACKTICK + `)} + ${testBool && ($$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `` + BACKTICK + `,})}` + BACKTICK + `)} ` + RENDER_HEAD_RESULT + `
@@ -1324,11 +1237,11 @@ const testBool = true; want: want{ code: `${ props.title && ( - $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + ` + $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + ` ${props.title} - ` + BACKTICK + `,}))}` + BACKTICK + ` + ` + BACKTICK + `,})}` + BACKTICK + ` ) }`, }, @@ -1486,9 +1399,9 @@ const someProps = { ` + RENDER_HEAD_RESULT + `
- ${$$renderComponent($$result,'Counter',Counter,{...(someProps),"client:visible":true,"client:component-hydration":"visible","client:component-path":("../components/Counter.jsx"),"client:component-export":("default"),"class":"astro-hmnnhvcq"},({"default": () => $$render` + "`" + ` + ${$$renderComponent($$result,'Counter',Counter,{...(someProps),"client:visible":true,"client:component-hydration":"visible","client:component-path":("../components/Counter.jsx"),"client:component-export":("default"),"class":"astro-hmnnhvcq"},{"default": () => $$render` + "`" + `

Hello React!

- ` + "`" + `,}))} + ` + "`" + `,})}
`, @@ -1596,7 +1509,7 @@ const name = 'named'; want: want{ frontmatter: []string{`import Component from 'test';`, `const name = 'named';`}, metadata: metadata{modules: []string{`{ module: $$module1, specifier: 'test', assert: {} }`}}, - code: `${$$renderComponent($$result,'Component',Component,{},({[name]: () => $$render` + "`" + `${$$maybeRenderHead($$result)}
Named
` + "`" + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{[name]: () => $$render` + "`" + `${$$maybeRenderHead($$result)}
Named
` + "`" + `,})}`, }, }, { @@ -1607,7 +1520,7 @@ const name = 'named'; C `, want: want{ - code: `${$$renderComponent($$result,'Slotted',Slotted,{},({"a": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}A` + BACKTICK + `,"b": () => $$render` + BACKTICK + `B` + BACKTICK + `,"c": () => $$render` + BACKTICK + `C` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Slotted',Slotted,{},{"a": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}A` + BACKTICK + `,"b": () => $$render` + BACKTICK + `B` + BACKTICK + `,"c": () => $$render` + BACKTICK + `C` + BACKTICK + `,})}`, }, }, { @@ -1966,7 +1879,7 @@ import { Container, Col, Row } from 'react-bootstrap'; want: want{ frontmatter: []string{`import { Container, Col, Row } from 'react-bootstrap';`}, metadata: metadata{modules: []string{`{ module: $$module1, specifier: 'react-bootstrap', assert: {} }`}}, - code: "${$$renderComponent($$result,'Container',Container,{},({\"default\": () => $$render`\n ${$$renderComponent($$result,'Row',Row,{},({\"default\": () => $$render`\n ${$$renderComponent($$result,'Col',Col,{},({\"default\": () => $$render`\n ${$$maybeRenderHead($$result)}

Hi!

\n `,}))}\n `,}))}`,}))}", + code: "${$$renderComponent($$result,'Container',Container,{},{\"default\": () => $$render`\n ${$$renderComponent($$result,'Row',Row,{},{\"default\": () => $$render`\n ${$$renderComponent($$result,'Col',Col,{},{\"default\": () => $$render`\n ${$$maybeRenderHead($$result)}

Hi!

\n `,})}\n `,})}`,})}", }, }, { @@ -2048,49 +1961,49 @@ import { Container, Col, Row } from 'react-bootstrap'; name: "Fragment", source: `
Default
Named
`, want: want{ - code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,}))}`, + code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,})}`, }, }, { name: "Fragment shorthand", source: `<>
Default
Named
`, want: want{ - code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,}))}`, + code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,})}`, }, }, { name: "Fragment shorthand only", source: `<>Hello`, want: want{ - code: `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `Hello` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `Hello` + BACKTICK + `,})}`, }, }, { name: "Fragment literal only", source: `world`, want: want{ - code: `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `world` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `world` + BACKTICK + `,})}`, }, }, { name: "Fragment slotted", source: `<>
Default
Named
`, want: want{ - code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,}))}` + BACKTICK + `,}))}`, + code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,})}` + BACKTICK + `,})}`, }, }, { name: "Fragment slotted with name", source: `
Default
Named
`, want: want{ - code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Component',Component,{},({"named": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{"slot":"named"},({"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,}))}` + BACKTICK + `,}))}`, + code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'Component',Component,{},{"named": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{"slot":"named"},{"default": () => $$render` + BACKTICK + `
Default
Named
` + BACKTICK + `,})}` + BACKTICK + `,})}`, }, }, { name: "Preserve slots inside custom-element", source: `
Name
Default
`, want: want{ - code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'my-element','my-element',{},({"default": () => $$render` + BACKTICK + `
Name
Default
` + BACKTICK + `,}))}`, + code: `${$$maybeRenderHead($$result)}${$$renderComponent($$result,'my-element','my-element',{},{"default": () => $$render` + BACKTICK + `
Name
Default
` + BACKTICK + `,})}`, }, }, { @@ -2381,7 +2294,7 @@ const content = "lol"; - ${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `${Array(7).fill(false).map((entry, index) => $$render` + BACKTICK + `` + BACKTICK + `)}` + BACKTICK + `,}))} + ${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `${Array(7).fill(false).map((entry, index) => $$render` + BACKTICK + `` + BACKTICK + `)}` + BACKTICK + `,})} @@ -2477,7 +2390,7 @@ console.log(tables);`}, ${ tables.map((table: Table) => ( - $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + ` + $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `

${table.title}

AA
@@ -2499,7 +2412,7 @@ console.log(tables);`},
- ` + BACKTICK + `,}))}` + BACKTICK + ` + ` + BACKTICK + `,})}` + BACKTICK + ` )) } @@ -2648,7 +2561,7 @@ const items = ["Dog", "Cat", "Platipus"]; name: "textarea in form", source: `
`, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
` + BACKTICK + `,})}`, }, }, { @@ -2669,7 +2582,7 @@ const items = ["Dog", "Cat", "Platipus"]; name: "slot inside of Base", source: `
Hello
`, want: want{ - code: `${$$renderComponent($$result,'Base',Base,{"title":"Home"},({"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
Hello
` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Base',Base,{"title":"Home"},{"default": () => $$render` + BACKTICK + `${$$maybeRenderHead($$result)}
Hello
` + BACKTICK + `,})}`, }, }, { @@ -2825,7 +2738,7 @@ const items = ["Dog", "Cat", "Platipus"]; name: "Component is:raw", source: "{<% awesome %>}", want: want{ - code: "${$$renderComponent($$result,'Component',Component,{},({\"default\": () => $$render`{<% awesome %>}`,}))}", + code: "${$$renderComponent($$result,'Component',Component,{},{\"default\": () => $$render`{<% awesome %>}`,})}", }, }, { @@ -2887,112 +2800,112 @@ const items = ["Dog", "Cat", "Platipus"]; name: "set:html on Component", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + "`${$$unescapeHTML(content)}`," + `}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + "`${$$unescapeHTML(content)}`," + `})}`, }, }, { name: "set:html on Component with quoted attribute", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${"content"}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${"content"}` + BACKTICK + `,})}`, }, }, { name: "set:html on Component with template literal attribute without variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:html on Component with template literal attribute with variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:text on Component", source: "", want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + "`${content}`," + `}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + "`${content}`," + `})}`, }, }, { name: "set:text on Component with quoted attribute", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `content` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `content` + BACKTICK + `,})}`, }, }, { name: "set:text on Component with template literal attribute without variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:text on Component with template literal attribute with variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'Component',Component,{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Component',Component,{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:html on custom-element", source: "", want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + "`${$$unescapeHTML(content)}`," + `}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + "`${$$unescapeHTML(content)}`," + `})}`, }, }, { name: "set:html on custom-element with quoted attribute", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `${"content"}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `${"content"}` + BACKTICK + `,})}`, }, }, { name: "set:html on custom-element with template literal attribute without variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:html on custom-element with template literal attribute with variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:text on custom-element", source: "", want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + "`${content}`," + `}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + "`${content}`," + `})}`, }, }, { name: "set:text on custom-element with quoted attribute", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `content` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `content` + BACKTICK + `,})}`, }, }, { name: "set:text on custom-element with template literal attribute without variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `content` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { name: "set:text on custom-element with template literal attribute with variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'custom-element','custom-element',{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'custom-element','custom-element',{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { @@ -3204,28 +3117,28 @@ const items = ["Dog", "Cat", "Platipus"]; name: "set:html on Fragment", source: "<i>This should NOT be italic</i>

\"} />", want: want{ - code: "${$$renderComponent($$result,'Fragment',Fragment,{},({\"default\": () => $$render`${$$unescapeHTML(\"

<i>This should NOT be italic</i>

\")}`,}))}", + code: "${$$renderComponent($$result,'Fragment',Fragment,{},{\"default\": () => $$render`${$$unescapeHTML(\"

<i>This should NOT be italic</i>

\")}`,})}", }, }, { name: "set:html on Fragment with quoted attribute", source: "<i>This should NOT be italic</i>

\" />", want: want{ - code: "${$$renderComponent($$result,'Fragment',Fragment,{},({\"default\": () => $$render`${\"

This should NOT be italic

\"}`,}))}", + code: "${$$renderComponent($$result,'Fragment',Fragment,{},{\"default\": () => $$render`${\"

This should NOT be italic

\"}`,})}", }, }, { name: "set:html on Fragment with template literal attribute without variable", source: "<i>This should NOT be italic</i>

` />", want: want{ - code: "${$$renderComponent($$result,'Fragment',Fragment,{},({\"default\": () => $$render`${`

This should NOT be italic

`}`,}))}", + code: "${$$renderComponent($$result,'Fragment',Fragment,{},{\"default\": () => $$render`${`

This should NOT be italic

`}`,})}", }, }, { name: "set:html on Fragment with template literal attribute with variable", source: ``, want: want{ - code: `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,}))}`, + code: `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `${` + BACKTICK + `${content}` + BACKTICK + `}` + BACKTICK + `,})}`, }, }, { @@ -3370,7 +3283,7 @@ const items = ["Dog", "Cat", "Platipus"]; want: want{ code: `${ list.map((i) => ( - $$render` + BACKTICK + `${$$renderComponent($$result,'Component',Component,{},({}))}` + BACKTICK + ` + $$render` + BACKTICK + `${$$renderComponent($$result,'Component',Component,{},{})}` + BACKTICK + ` )) }`, }, @@ -3389,7 +3302,7 @@ const items = ["Dog", "Cat", "Platipus"]; want: want{ code: `${ list.map((i) => ( - $$render` + BACKTICK + `${$$renderComponent($$result,'Component',Component,{},({}))}` + BACKTICK + ` + $$render` + BACKTICK + `${$$renderComponent($$result,'Component',Component,{},{})}` + BACKTICK + ` )) }`, }, @@ -3431,7 +3344,7 @@ const items = ["Dog", "Cat", "Platipus"]; source: `{(` + BACKTICK + `} />{Node.children.map((child) => ())}` + BACKTICK + `} />)}`, filename: "/projects/app/src/components/RenderNode.astro", want: want{ - code: `${($$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `${$$unescapeHTML(` + BACKTICK + `<${Node.tag} ${stringifyAttributes(Node.attributes)}>` + BACKTICK + `)}` + BACKTICK + `,}))}${Node.children.map((child) => ($$render` + BACKTICK + `${$$renderComponent($$result,'Astro.self',Astro.self,{"node":(child)})}` + BACKTICK + `))}${$$renderComponent($$result,'Fragment',Fragment,{},({"default": () => $$render` + BACKTICK + `${$$unescapeHTML(` + BACKTICK + `` + BACKTICK + `)}` + BACKTICK + `,}))}` + BACKTICK + `,}))}` + BACKTICK + `)}`, + code: `${($$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `${$$unescapeHTML(` + BACKTICK + `<${Node.tag} ${stringifyAttributes(Node.attributes)}>` + BACKTICK + `)}` + BACKTICK + `,})}${Node.children.map((child) => ($$render` + BACKTICK + `${$$renderComponent($$result,'Astro.self',Astro.self,{"node":(child)})}` + BACKTICK + `))}${$$renderComponent($$result,'Fragment',Fragment,{},{"default": () => $$render` + BACKTICK + `${$$unescapeHTML(` + BACKTICK + `` + BACKTICK + `)}` + BACKTICK + `,})}` + BACKTICK + `,})}` + BACKTICK + `)}`, }, }, {