From 4603704bf34a9a049dc01ac4b0ff2fa27e904088 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Mon, 16 May 2022 12:59:38 -0500 Subject: [PATCH] chore: use original "class" scoping technique --- internal/printer/printer_css_test.go | 2 +- internal/printer/printer_test.go | 26 ++++----- internal/transform/scope-css_test.go | 70 +++++++++++------------ internal/transform/scope-html.go | 15 ++--- internal/transform/scope-html_test.go | 36 ++++++------ internal/transform/transform_test.go | 8 +-- lib/esbuild/css_printer/astro_features.go | 2 +- 7 files changed, 80 insertions(+), 79 deletions(-) diff --git a/internal/printer/printer_css_test.go b/internal/printer/printer_css_test.go index 8dc8a14c9..227dcc42d 100644 --- a/internal/printer/printer_css_test.go +++ b/internal/printer/printer_css_test.go @@ -28,7 +28,7 @@ func TestPrinterCSS(t *testing.T) {

Page Title

I’m a page

`, want: want{ - styles: []string{".title:where([data-astro-scope=\"DPOHFLYM\"]){font-family:fantasy;font-size:28px}.body:where([data-astro-scope=\"DPOHFLYM\"]){font-size:1em}"}, + styles: []string{".title:where(.astro-DPOHFLYM){font-family:fantasy;font-size:28px}.body:where(.astro-DPOHFLYM){font-size:1em}"}, }, }, } diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index 8666a19cf..1deecffc4 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -631,9 +631,9 @@ const name = "world";

Page Title

I’m a page

`, want: want{ - styles: []string{"{props:{\"data-astro-id\":\"DPOHFLYM\"},children:`.title:where([data-astro-scope=\"DPOHFLYM\"]){font-family:fantasy;font-size:28px}.body:where([data-astro-scope=\"DPOHFLYM\"]){font-size:1em}`}"}, - code: "\n\n\t\t" + `

Page Title

-

I’m a page

`, + styles: []string{"{props:{\"data-astro-id\":\"DPOHFLYM\"},children:`.title:where(.astro-DPOHFLYM){font-family:fantasy;font-size:28px}.body:where(.astro-DPOHFLYM){font-size:1em}`}"}, + code: "\n\n\t\t" + `

Page Title

+

I’m a page

`, }, }, { @@ -761,7 +761,7 @@ import Counter from '../components/Counter.jsx'`, hydratedComponents: []string{`Counter`}, hydrationDirectives: []string{"visible"}, }, - code: ` + code: ` @@ -769,8 +769,8 @@ import Counter from '../components/Counter.jsx'`, ` + RENDER_HEAD_RESULT + ` -
- ${$$renderComponent($$result,'Counter',Counter,{...(someProps),"client:visible":true,"client:component-hydration":"visible","client:component-path":($$metadata.getPath(Counter)),"client:component-export":($$metadata.getExport(Counter)),"data-astro-scope":"HMNNHVCQ"},{"default": () => $$render` + "`" + `

Hello React!

` + "`" + `,})} +
+ ${$$renderComponent($$result,'Counter',Counter,{...(someProps),"client:visible":true,"client:component-hydration":"visible","client:component-path":($$metadata.getPath(Counter)),"client:component-export":($$metadata.getExport(Counter)),"class":"astro-HMNNHVCQ"},{"default": () => $$render` + "`" + `

Hello React!

` + "`" + `,})}
`, @@ -1246,11 +1246,11 @@ import { Container, Col, Row } from 'react-bootstrap';
`, want: want{ styles: []string{ - "{props:{\"data-astro-id\":\"EX5CHM4O\"},children:`div:where([data-astro-scope=\"EX5CHM4O\"]){color:blue}`}", - "{props:{\"data-astro-id\":\"EX5CHM4O\"},children:`div:where([data-astro-scope=\"EX5CHM4O\"]){color:green}`}", + "{props:{\"data-astro-id\":\"EX5CHM4O\"},children:`div:where(.astro-EX5CHM4O){color:blue}`}", + "{props:{\"data-astro-id\":\"EX5CHM4O\"},children:`div:where(.astro-EX5CHM4O){color:green}`}", "{props:{\"global\":true},children:`div { color: red }`}", }, - code: "\n\n\n\n\n\n\n" + RENDER_HEAD_RESULT + "\n
", + code: "\n\n\n\n\n\n\n" + RENDER_HEAD_RESULT + "\n
", }, }, { @@ -1570,8 +1570,8 @@ const items = ["Dog", "Cat", "Platipus"];
My Text
`, want: want{ - styles: []string{fmt.Sprintf(`{props:{"data-astro-id":"SJ3WYE6H"},children:%s.container:where([data-astro-scope="SJ3WYE6H"]){padding:2rem}%s}`, BACKTICK, BACKTICK)}, - code: `
My Text
`, + styles: []string{fmt.Sprintf(`{props:{"data-astro-id":"SJ3WYE6H"},children:%s.container:where(.astro-SJ3WYE6H){padding:2rem}%s}`, BACKTICK, BACKTICK)}, + code: `
My Text
`, }, }, { @@ -1732,9 +1732,9 @@ const items = ["Dog", "Cat", "Platipus"]; source: "

testing

", staticExtraction: true, want: want{ - code: `

testing

`, + code: `

testing

`, styles: []string{ - "{props:{\"define:vars\":({color:'green'}),\"data-astro-id\":\"VFS5OEMV\"},children:`h1:where([data-astro-scope=\"VFS5OEMV\"]){color:var(--color)}`}", + "{props:{\"define:vars\":({color:'green'}),\"data-astro-id\":\"VFS5OEMV\"},children:`h1:where(.astro-VFS5OEMV){color:var(--color)}`}", }, }, }, diff --git a/internal/transform/scope-css_test.go b/internal/transform/scope-css_test.go index 97a653608..0fa05bffb 100644 --- a/internal/transform/scope-css_test.go +++ b/internal/transform/scope-css_test.go @@ -20,97 +20,97 @@ func TestScopeStyle(t *testing.T) { { name: "class", source: ".class{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]){}", + want: ".class:where(.astro-XXXXXX){}", }, { name: "id", source: "#class{}", - want: "#class:where([data-astro-scope=\"XXXXXX\"]){}", + want: "#class:where(.astro-XXXXXX){}", }, { name: "element", source: "h1{}", - want: "h1:where([data-astro-scope=\"XXXXXX\"]){}", + want: "h1:where(.astro-XXXXXX){}", }, { name: "adjacent sibling", source: ".class+.class{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"])+.class:where([data-astro-scope=\"XXXXXX\"]){}", + want: ".class:where(.astro-XXXXXX)+.class:where(.astro-XXXXXX){}", }, { name: "and selector", source: ".class,.class{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]),.class:where([data-astro-scope=\"XXXXXX\"]){}", + want: ".class:where(.astro-XXXXXX),.class:where(.astro-XXXXXX){}", }, { name: "children universal", source: ".class *{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) :where([data-astro-scope=\"XXXXXX\"]){}", + want: ".class:where(.astro-XXXXXX) :where(.astro-XXXXXX){}", }, { name: "attr", - source: "a[aria-current=\"page\"]{}", - want: "a:where([data-astro-scope=\"XXXXXX\"])[aria-current=page]{}", + source: "a[aria-current=page]{}", + want: "a:where(.astro-XXXXXX)[aria-current=page]{}", }, { name: "attr universal implied", source: "[aria-visible],[aria-hidden]{}", - want: ":where([data-astro-scope=\"XXXXXX\"])[aria-visible],:where([data-astro-scope=\"XXXXXX\"])[aria-hidden]{}", + want: ":where(.astro-XXXXXX)[aria-visible],:where(.astro-XXXXXX)[aria-hidden]{}", }, { name: "universal pseudo state", source: "*:hover{}", - want: ":where([data-astro-scope=\"XXXXXX\"]):hover{}", + want: ":where(.astro-XXXXXX):hover{}", }, { name: "immediate child universal", source: ".class>*{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"])>:where([data-astro-scope=\"XXXXXX\"]){}", + want: ".class:where(.astro-XXXXXX)>:where(.astro-XXXXXX){}", }, { name: "element + pseudo state", source: ".class button:focus{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) button:where([data-astro-scope=\"XXXXXX\"]):focus{}", + want: ".class:where(.astro-XXXXXX) button:where(.astro-XXXXXX):focus{}", }, { name: "element + pseudo element", source: ".class h3::before{}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) h3:where([data-astro-scope=\"XXXXXX\"])::before{}", + want: ".class:where(.astro-XXXXXX) h3:where(.astro-XXXXXX)::before{}", }, { name: "media query", source: "@media screen and (min-width:640px){.class{}}", - want: "@media screen and (min-width:640px){.class:where([data-astro-scope=\"XXXXXX\"]){}}", + want: "@media screen and (min-width:640px){.class:where(.astro-XXXXXX){}}", }, { name: "element + pseudo state + pseudo element", source: "button:focus::before{}", - want: "button:where([data-astro-scope=\"XXXXXX\"]):focus::before{}", + want: "button:where(.astro-XXXXXX):focus::before{}", }, { name: "global children", source: ".class :global(ul li){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) ul li{}", + want: ".class:where(.astro-XXXXXX) ul li{}", }, { name: "global universal", source: ".class :global(*){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) *{}", + want: ".class:where(.astro-XXXXXX) *{}", }, { name: "global with scoped children", source: ":global(section) .class{}", - want: "section .class:where([data-astro-scope=\"XXXXXX\"]){}", + want: "section .class:where(.astro-XXXXXX){}", }, { name: "subsequent siblings + global", source: ".class~:global(a){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"])~a{}", + want: ".class:where(.astro-XXXXXX)~a{}", }, { name: "global nested parens", source: ".class :global(.nav:not(.is-active)){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]) .nav:not(.is-active){}", + want: ".class:where(.astro-XXXXXX) .nav:not(.is-active){}", }, { name: "global nested parens + chained class", @@ -125,27 +125,27 @@ func TestScopeStyle(t *testing.T) { { name: "class chained global", source: ".class:global(.bar){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]).bar{}", // technically this may be incorrect, but would require a lookahead to fix + want: ".class:where(.astro-XXXXXX).bar{}", // technically this may be incorrect, but would require a lookahead to fix }, { name: "chained :not()", source: ".class:not(.is-active):not(.is-disabled){}", - want: ".class:where([data-astro-scope=\"XXXXXX\"]):not(.is-active):not(.is-disabled){}", + want: ".class:where(.astro-XXXXXX):not(.is-active):not(.is-disabled){}", }, { name: "weird chaining", source: ":hover.a:focus{}", // yes this is valid. yes I’m just upset as you are :( - want: ":hover.a:where([data-astro-scope=\"XXXXXX\"]):focus{}", + want: ":hover.a:where(.astro-XXXXXX):focus{}", }, { name: "more weird chaining", source: ":not(.is-disabled).a{}", - want: ":not(.is-disabled).a:where([data-astro-scope=\"XXXXXX\"]){}", + want: ":not(.is-disabled).a:where(.astro-XXXXXX){}", }, { name: "body", source: "body h1{}", - want: "body h1:where([data-astro-scope=\"XXXXXX\"]){}", + want: "body h1:where(.astro-XXXXXX){}", }, { name: "body class", @@ -165,7 +165,7 @@ func TestScopeStyle(t *testing.T) { { name: "escaped characters", source: ".class\\:class:focus{}", - want: ".class\\:class:where([data-astro-scope=\"XXXXXX\"]):focus{}", + want: ".class\\:class:where(.astro-XXXXXX):focus{}", }, // the following tests assert we leave valid CSS alone { @@ -191,17 +191,17 @@ func TestScopeStyle(t *testing.T) { { name: "keyframes start", source: "@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}} h1{} h2{}", - want: "@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}h1:where([data-astro-scope=\"XXXXXX\"]){}h2:where([data-astro-scope=\"XXXXXX\"]){}", + want: "@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}h1:where(.astro-XXXXXX){}h2:where(.astro-XXXXXX){}", }, { name: "keyframes middle", source: "h1{} @keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}} h2{}", - want: "h1:where([data-astro-scope=\"XXXXXX\"]){}@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}h2:where([data-astro-scope=\"XXXXXX\"]){}", + want: "h1:where(.astro-XXXXXX){}@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}h2:where(.astro-XXXXXX){}", }, { name: "keyframes end", source: "h1{} h2{} @keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}", - want: "h1:where([data-astro-scope=\"XXXXXX\"]){}h2:where([data-astro-scope=\"XXXXXX\"]){}@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}", + want: "h1:where(.astro-XXXXXX){}h2:where(.astro-XXXXXX){}@keyframes shuffle{0%{transform:rotate(0deg);color:blue}100%{transform:rotate(360deg)}}", }, { name: "calc", @@ -211,7 +211,7 @@ func TestScopeStyle(t *testing.T) { { name: "grid-template-columns", source: "div{grid-template-columns: [content-start] 1fr [content-end];}", - want: "div:where([data-astro-scope=\"XXXXXX\"]){grid-template-columns:[content-start] 1fr [content-end]}", + want: "div:where(.astro-XXXXXX){grid-template-columns:[content-start] 1fr [content-end]}", }, { name: "charset", @@ -239,7 +239,7 @@ func TestScopeStyle(t *testing.T) { color: blue font-size: 18px; }`, - want: `.foo:where([data-astro-scope="XXXXXX"]){color:blue font-size: 18px}`, + want: `.foo:where(.astro-XXXXXX){color:blue font-size: 18px}`, }, { name: "nesting media", @@ -249,12 +249,12 @@ func TestScopeStyle(t *testing.T) { { name: "nesting combinator", source: "div { & span { color: blue } }", - want: "div:where([data-astro-scope=\"XXXXXX\"]){& span:where([data-astro-scope=\"XXXXXX\"]){color:blue}}", + want: "div:where(.astro-XXXXXX){& span:where(.astro-XXXXXX){color:blue}}", }, { name: "nesting modifier", source: ".header { background-color: white; &.dark { background-color: blue; }}", - want: ".header:where([data-astro-scope=\"XXXXXX\"]){background-color:white;&.dark{background-color:blue}}", + want: ".header:where(.astro-XXXXXX){background-color:white;&.dark{background-color:blue}}", }, { name: "@container", @@ -263,12 +263,12 @@ func TestScopeStyle(t *testing.T) { font-size: 30px; } }`, - want: "@container (min-width: 200px) and (min-height: 200px){h1:where([data-astro-scope=\"XXXXXX\"]){font-size:30px}}", + want: "@container (min-width: 200px) and (min-height: 200px){h1:where(.astro-XXXXXX){font-size:30px}}", }, { name: "@layer", source: "@layer theme, layout, utilities; @layer special { .item { color: rebeccapurple; }}", - want: "@layer theme,layout,utilities;@layer special{.item:where([data-astro-scope=\"XXXXXX\"]){color:rebeccapurple}}", + want: "@layer theme,layout,utilities;@layer special{.item:where(.astro-XXXXXX){color:rebeccapurple}}", }, } for _, tt := range tests { diff --git a/internal/transform/scope-html.go b/internal/transform/scope-html.go index ed266ca36..fc485df1e 100644 --- a/internal/transform/scope-html.go +++ b/internal/transform/scope-html.go @@ -39,13 +39,14 @@ var NeverScopedSelectors map[string]bool = map[string]bool{ } func injectScopedClass(n *astro.Node, opts TransformOptions) { + scopedClass := fmt.Sprintf(`astro-%s`, opts.Scope) for i, attr := range n.Attr { // If we find an existing class attribute, append the scoped class - if attr.Key == "data-astro-scope" { + if attr.Key == "class" { switch attr.Type { case astro.ShorthandAttribute: if n.Component { - attr.Val = fmt.Sprintf(`%s + "%s"`, attr.Key, opts.Scope) + attr.Val = fmt.Sprintf(`%s + "%s"`, attr.Key, scopedClass) attr.Type = astro.ExpressionAttribute n.Attr[i] = attr return @@ -53,17 +54,17 @@ func injectScopedClass(n *astro.Node, opts TransformOptions) { case astro.EmptyAttribute: // instead of an empty string attr.Type = astro.QuotedAttribute - attr.Val = opts.Scope + attr.Val = scopedClass n.Attr[i] = attr return case astro.QuotedAttribute, astro.TemplateLiteralAttribute: // as a plain string - attr.Val = fmt.Sprintf(`%s %s`, attr.Val, opts.Scope) + attr.Val = fmt.Sprintf(`%s %s`, attr.Val, scopedClass) n.Attr[i] = attr return case astro.ExpressionAttribute: // as an expression - attr.Val = fmt.Sprintf(`(%s) + " %s"`, attr.Val, opts.Scope) + attr.Val = fmt.Sprintf(`(%s) + " %s"`, attr.Val, scopedClass) n.Attr[i] = attr return } @@ -71,8 +72,8 @@ func injectScopedClass(n *astro.Node, opts TransformOptions) { } // If we didn't find an existing class attribute, let's add one n.Attr = append(n.Attr, astro.Attribute{ - Key: "data-astro-scope", + Key: "class", Type: astro.QuotedAttribute, - Val: opts.Scope, + Val: scopedClass, }) } diff --git a/internal/transform/scope-html_test.go b/internal/transform/scope-html_test.go index ead538987..f6b82089e 100644 --- a/internal/transform/scope-html_test.go +++ b/internal/transform/scope-html_test.go @@ -18,52 +18,52 @@ func TestScopeHTML(t *testing.T) { { name: "none", source: "
", - want: `
`, + want: `
`, }, { name: "quoted", source: `
`, - want: `
`, + want: `
`, }, { name: "quoted no trim", - source: `
`, - want: `
`, + source: `
`, + want: `
`, }, { name: "expression string", - source: `
`, - want: `
`, + source: `
`, + want: `
`, }, { name: "expression function", - source: `
`, - want: `
`, + source: `
`, + want: `
`, }, { name: "expression dynamic", - source: "
", - want: `
`, + source: "
", + want: `
`, }, { name: "empty", - source: "
", - want: `
`, + source: "
", + want: `
`, }, { name: "template literal", - source: "
", - want: "
", + source: "
", + want: "
", }, { name: "component className not scoped", - source: ``, - want: ``, + source: ``, + want: ``, }, { name: "component className expression", - source: ``, - want: ``, + source: ``, + want: ``, }, } for _, tt := range tests { diff --git a/internal/transform/transform_test.go b/internal/transform/transform_test.go index 709cc8fc7..934b2f689 100644 --- a/internal/transform/transform_test.go +++ b/internal/transform/transform_test.go @@ -20,7 +20,7 @@ func TestTransformScoping(t *testing.T) {
`, - want: `
`, + want: `
`, }, { name: "global empty", @@ -61,7 +61,7 @@ func TestTransformScoping(t *testing.T) {
`, - want: `
`, + want: `
`, }, { name: "global multiple", @@ -79,7 +79,7 @@ func TestTransformScoping(t *testing.T) {
`, - want: `
`, + want: `
`, }, { name: "multiple scoped :global", @@ -88,7 +88,7 @@ func TestTransformScoping(t *testing.T) {
`, - want: `
`, + want: `
`, }, } var b strings.Builder diff --git a/lib/esbuild/css_printer/astro_features.go b/lib/esbuild/css_printer/astro_features.go index 82cb96008..d7fd6d091 100644 --- a/lib/esbuild/css_printer/astro_features.go +++ b/lib/esbuild/css_printer/astro_features.go @@ -8,7 +8,7 @@ import ( ) func (p *printer) printScopedSelector() bool { - p.print(fmt.Sprintf(":where([data-astro-scope=\"%s\"])", p.options.Scope)) + p.print(fmt.Sprintf(":where(.astro-%s)", p.options.Scope)) return true }