diff --git a/at_rule.go b/at_rule.go index 11b31ca..2fe2640 100644 --- a/at_rule.go +++ b/at_rule.go @@ -17,7 +17,7 @@ func (ar *atRule) WriteTo(w io.Writer) (int64, error) { bf.WriteString(strings.TrimSpace(ar.ln.s)) - if len(ar.sels) == 0 && len(ar.decs) == 0 { + if len(ar.sels) == 0 && len(ar.decs) == 0 && !ar.hasMixinDecs() && !ar.hasMixinSels() { bf.WriteString(semicolon) n, err := w.Write(bf.Bytes()) return int64(n), err @@ -25,16 +25,25 @@ func (ar *atRule) WriteTo(w io.Writer) (int64, error) { bf.WriteString(openBrace) - for _, dec := range ar.decs { - // Writing to the bytes.Buffer never returns an error. - dec.WriteTo(bf) - } + // Writing to the bytes.Buffer never returns an error. + ar.writeDecsTo(bf, nil) for _, sel := range ar.sels { // Writing to the bytes.Buffer never returns an error. sel.WriteTo(bf) } + // Write the mixin's selectors. + for _, mi := range ar.mixins { + sels, prms := mi.selsParams() + + for _, sl := range sels { + sl.parent = ar + // Writing to the bytes.Buffer never returns an error. + sl.writeTo(bf, prms) + } + } + bf.WriteString(closeBrace) n, err := w.Write(bf.Bytes()) diff --git a/e2e_test.go b/e2e_test.go index d2133c5..f53ed26 100644 --- a/e2e_test.go +++ b/e2e_test.go @@ -11,7 +11,7 @@ import ( func Test_e2e(t *testing.T) { var wg sync.WaitGroup - for i := 1; i <= 10; i++ { + for i := 1; i <= 11; i++ { idx := strconv.Itoa(i) gcssPath := "test/e2e/actual/" + strings.Repeat("0", 4-len(idx)) + idx + ".gcss" diff --git a/element_base.go b/element_base.go index 3c41a84..c1f79d0 100644 --- a/element_base.go +++ b/element_base.go @@ -1,5 +1,10 @@ package gcss +import ( + "bytes" + "io" +) + // elementBase holds the common fields of an element. type elementBase struct { ln *line @@ -41,7 +46,7 @@ func (eBase *elementBase) Context() *context { return eBase.ctx } -// hasMixinDecs returns true if the selector has a mixin +// hasMixinDecs returns true if the element has a mixin // which has declarations. func (eBase *elementBase) hasMixinDecs() bool { for _, mi := range eBase.mixins { @@ -53,6 +58,43 @@ func (eBase *elementBase) hasMixinDecs() bool { return false } +// hasMixinSels returns true if the element has a mixin +// which has selectors. +func (eBase *elementBase) hasMixinSels() bool { + for _, mi := range eBase.mixins { + if sels, _ := mi.selsParams(); len(sels) > 0 { + return true + } + } + + return false +} + +// writeDecsTo writes the element's declarations to w. +func (eBase *elementBase) writeDecsTo(w io.Writer, params map[string]string) (int64, error) { + bf := new(bytes.Buffer) + + // Write the declarations. + for _, dec := range eBase.decs { + // Writing to the bytes.Buffer never returns an error. + dec.writeTo(bf, params) + } + + // Write the mixin's declarations. + for _, mi := range eBase.mixins { + decs, prms := mi.decsParams() + + for _, dec := range decs { + // Writing to the bytes.Buffer never returns an error. + dec.writeTo(bf, prms) + } + } + + n, err := w.Write(bf.Bytes()) + + return int64(n), err +} + // newElementBase creates and returns an element base. func newElementBase(ln *line, parent element) elementBase { return elementBase{ diff --git a/selector.go b/selector.go index ae0dabe..1824b3a 100644 --- a/selector.go +++ b/selector.go @@ -27,20 +27,8 @@ func (sel *selector) writeTo(w io.Writer, params map[string]string) (int64, erro bf.WriteString(sel.names()) bf.WriteString(openBrace) - for _, dec := range sel.decs { - // Writing to the bytes.Buffer never returns an error. - dec.writeTo(bf, params) - } - - // Write the mixin's declarations. - for _, mi := range sel.mixins { - decs, prms := mi.decsParams() - - for _, dec := range decs { - // Writing to the bytes.Buffer never returns an error. - dec.writeTo(bf, prms) - } - } + // Writing to the bytes.Buffer never returns an error. + sel.writeDecsTo(bf, params) bf.WriteString(closeBrace) } diff --git a/test/e2e/actual/0011.gcss b/test/e2e/actual/0011.gcss new file mode 100644 index 0000000..7f62faf --- /dev/null +++ b/test/e2e/actual/0011.gcss @@ -0,0 +1,55 @@ +// At-rules which include mixins +$color: black + +$mixin-for-media-1($font-size) + font-size: $font-size + +$mixin-for-media-2($background) + html + background: $background + color: $color + +$mixin-for-media-3() + h1 + color: red + +$mixin-for-page($margin) + margin: $margin + +$mixin-for-font-face() + font-family: "Example Font" + src: url("http://www.example.com/fonts/example") + +@media screen, projection + $mixin-for-media-1(13px) + $mixin-for-media-2(red) + body + max-width: 35em + margin: 0 auto + $mixin-for-media-3() + +@media screen, projection + $mixin-for-media-2(red) + +@media print + $mixin-for-media-1(13px) + $mixin-for-media-2(red) + body + max-width: 35em + margin: 0 auto + $mixin-for-media-3() + +@page + $mixin-for-page(2.5cm) + +@page :left + $mixin-for-page(2.5cm) + +@page :right + $mixin-for-page(2.5cm) + +@page :first + $mixin-for-page(2.5cm) + +@font-face + $mixin-for-font-face() diff --git a/test/e2e/expected/0011.css b/test/e2e/expected/0011.css new file mode 100644 index 0000000..91bb9dd --- /dev/null +++ b/test/e2e/expected/0011.css @@ -0,0 +1 @@ +@media screen, projection{font-size:13px;body{max-width:35em;margin:0 auto;}body h1{color:red;}html{background:red;color:black;}}@media screen, projection{html{background:red;color:black;}}@media print{font-size:13px;body{max-width:35em;margin:0 auto;}body h1{color:red;}html{background:red;color:black;}}@page{margin:2.5cm;}@page :left{margin:2.5cm;}@page :right{margin:2.5cm;}@page :first{margin:2.5cm;}@font-face{font-family:"Example Font";src:url("http://www.example.com/fonts/example");}