Skip to content

Commit

Permalink
fix: merge class and class:list values (withastro#748)
Browse files Browse the repository at this point in the history
* fix: merge class and class:list values

* more test cases

* changeset

* address code suggestions

* Update internal/printer/printer_test.go

Co-authored-by: Happydev <[email protected]>

---------

Co-authored-by: Nate Moore <[email protected]>
Co-authored-by: Happydev <[email protected]>
  • Loading branch information
3 people authored Mar 14, 2023
1 parent 9cf927b commit 2658ed4
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-cheetahs-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/compiler': patch
---

Correctly apply style when `class` and `class:list` are both used
28 changes: 28 additions & 0 deletions internal/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,34 @@ import { Container, Col, Row } from 'react-bootstrap';
code: `${$$maybeRenderHead($$result)}<div class:list="something"${$$spreadAttributes(Astro.props,"Astro.props")}></div>`,
},
},
{
name: "class list",
source: `<div class:list={['one', 'variable']} />`,
want: want{
code: `${$$maybeRenderHead($$result)}<div${$$addAttribute(['one', 'variable'], "class:list")}></div>`,
},
},
{
name: "class and class list simple array",
source: `<div class="two" class:list={['one', 'variable']} />`,
want: want{
code: `${$$maybeRenderHead($$result)}<div${$$addAttribute(['two', ['one', 'variable']], "class:list")}></div>`,
},
},
{
name: "class and class list object",
source: `<div class="two three" class:list={['hello goodbye', { hello: true, world: true }]} />`,
want: want{
code: `${$$maybeRenderHead($$result)}<div${$$addAttribute(['two three', ['hello goodbye', { hello: true, world: true }]], "class:list")}></div>`,
},
},
{
name: "class and class list set",
source: `<div class="two three" class:list={[ new Set([{hello: true, world: true}]) ]} />`,
want: want{
code: `${$$maybeRenderHead($$result)}<div${$$addAttribute(['two three', [ new Set([{hello: true, world: true}]) ]], "class:list")}></div>`,
},
},
{
name: "spread without style or class",
source: `<div {...Astro.props} />`,
Expand Down
30 changes: 30 additions & 0 deletions internal/transform/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func Transform(doc *astro.Node, opts TransformOptions, h *handler.Handler) *astr
didAddDefinedVars = didAdd
}
}
mergeClassList(doc, n, &opts)
})
if len(definedVars) > 0 && !didAddDefinedVars {
for _, style := range doc.Styles {
Expand Down Expand Up @@ -498,3 +499,32 @@ func walk(doc *astro.Node, cb func(*astro.Node)) {
}
f(doc)
}

// This function merges the values of `class=""` and `class:list=""` in `class:list`
func mergeClassList(doc *astro.Node, n *astro.Node, opts *TransformOptions) {
var classListAttrValue string
var classListAttrIndex int = -1
var classAttrValue string
var classAttrIndex int = -1
for i, a := range n.Attr {
if a.Key == "class:list" {
classListAttrValue = a.Val
classListAttrIndex = i
}
if a.Key == "class" {
classAttrValue = a.Val
classAttrIndex = i
}
}
if classListAttrIndex >= 0 && classAttrIndex >= 0 {
// we append the prepend the value of class to class:list
n.Attr[classListAttrIndex].Val = fmt.Sprintf("['%s', %s]", classAttrValue, classListAttrValue)
// Now that the value of `class` is carried by `class:list`, we can remove the `class` node from the AST.
// Doing so will allow us to generate valid HTML at runtime
n.Attr = remove(n.Attr, classAttrIndex)
}
}

func remove(slice []astro.Attribute, s int) []astro.Attribute {
return append(slice[:s], slice[s+1:]...)
}

0 comments on commit 2658ed4

Please sign in to comment.