Skip to content

Commit 0399d55

Browse files
TheOtterlordlouisescherbluwyMoustaphaDev
authored
Reverse order of styles & scripts (#1055)
Co-authored-by: Louis Escher <louisescher@proton.me> Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com> Co-authored-by: Happydev <81974850+MoustaphaDev@users.noreply.github.com>
1 parent f167a98 commit 0399d55

File tree

11 files changed

+85
-31
lines changed

11 files changed

+85
-31
lines changed

.changeset/olive-beds-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@astrojs/compiler": minor
3+
---
4+
5+
Add an experimental flag `experimentalScriptOrder` that corrects the order styles & scripts are rendered within a component. When enabled, the order styles & scripts are rendered will be consistent with the order they are defined.

cmd/astro-wasm/astro-wasm.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ func makeTransformOptions(options js.Value) transform.TransformOptions {
138138
renderScript = true
139139
}
140140

141+
experimentalScriptOrder := false
142+
if jsBool(options.Get("experimentalScriptOrder")) {
143+
experimentalScriptOrder = true
144+
}
145+
141146
return transform.TransformOptions{
142147
Filename: filename,
143148
NormalizedFilename: normalizedFilename,
@@ -152,6 +157,7 @@ func makeTransformOptions(options js.Value) transform.TransformOptions {
152157
TransitionsAnimationURL: transitionsAnimationURL,
153158
AnnotateSourceFile: annotateSourceFile,
154159
RenderScript: renderScript,
160+
ExperimentalScriptOrder: experimentalScriptOrder,
155161
}
156162
}
157163

@@ -336,7 +342,7 @@ func Transform() any {
336342
}
337343

338344
// Hoist styles and scripts to the top-level
339-
transform.ExtractStyles(doc)
345+
transform.ExtractStyles(doc, &transformOptions)
340346

341347
// Pre-process styles
342348
// Important! These goroutines need to be spawned from this file or they don't work

internal/printer/__printer_js__/multiple_define_vars_on_style.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const $$metadata = $$createMetadata(import.meta.url, { modules: [], hydra
3434
3535
const $$Component = $$createComponent(($$result, $$props, $$slots) => {
3636
37-
const $$definedVars = $$defineStyleVars([{color:'red'},{color:'green'}]);
37+
const $$definedVars = $$defineStyleVars([{color:'green'},{color:'red'}]);
3838
return $$render`${$$maybeRenderHead($$result)}<h1 class="astro-6oxbqcst"${$$addAttribute($$definedVars, "style")}>foo</h1><h2 class="astro-6oxbqcst"${$$addAttribute($$definedVars, "style")}>bar</h2>`;
3939
}, undefined, undefined);
4040
export default $$Component;

internal/printer/__printer_js__/script_multiple__renderScript__true_.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
createMetadata as $$createMetadata
3131
} from "http://localhost:3000/";
3232
33-
export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [{ type: 'inline', value: `console.log("World");` }, { type: 'inline', value: `console.log("Hello");` }] });
33+
export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [{ type: 'inline', value: `console.log("Hello");` }, { type: 'inline', value: `console.log("World");` }] });
3434
3535
const $$Index = $$createComponent(($$result, $$props, $$slots) => {
3636

internal/printer/printer_css_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ func TestPrinterCSS(t *testing.T) {
8787
}
8888

8989
hash := astro.HashString(code)
90-
transform.ExtractStyles(doc)
91-
transform.Transform(doc, transform.TransformOptions{Scope: hash, ScopedStyleStrategy: scopedStyleStrategy}, handler.NewHandler(code, "/test.astro")) // note: we want to test Transform in context here, but more advanced cases could be tested separately
90+
opts := transform.TransformOptions{Scope: hash, ScopedStyleStrategy: scopedStyleStrategy, ExperimentalScriptOrder: true}
91+
transform.ExtractStyles(doc, &opts)
92+
transform.Transform(doc, opts, handler.NewHandler(code, "/test.astro")) // note: we want to test Transform in context here, but more advanced cases could be tested separately
9293
result := PrintCSS(code, doc, transform.TransformOptions{
9394
Scope: "astro-XXXX",
9495
InternalURL: "http://localhost:3000/",

internal/printer/printer_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,12 +2098,13 @@ const meta = { title: 'My App' };
20982098
}
20992099

21002100
hash := astro.HashString(code)
2101-
transform.ExtractStyles(doc)
21022101
// combine from tt.transformOptions
21032102
transformOptions := transform.TransformOptions{
2104-
Scope: hash,
2105-
RenderScript: tt.transformOptions.RenderScript,
2103+
Scope: hash,
2104+
RenderScript: tt.transformOptions.RenderScript,
2105+
ExperimentalScriptOrder: true,
21062106
}
2107+
transform.ExtractStyles(doc, &transformOptions)
21072108
transform.Transform(doc, transformOptions, h) // note: we want to test Transform in context here, but more advanced cases could be tested separately
21082109

21092110
result := PrintToJS(code, doc, 0, transform.TransformOptions{

internal/transform/transform.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type TransformOptions struct {
3434
PreprocessStyle interface{}
3535
AnnotateSourceFile bool
3636
RenderScript bool
37+
ExperimentalScriptOrder bool
3738
}
3839

3940
func Transform(doc *astro.Node, opts TransformOptions, h *handler.Handler) *astro.Node {
@@ -115,7 +116,7 @@ func Transform(doc *astro.Node, opts TransformOptions, h *handler.Handler) *astr
115116
return doc
116117
}
117118

118-
func ExtractStyles(doc *astro.Node) {
119+
func ExtractStyles(doc *astro.Node, opts *TransformOptions) {
119120
walk(doc, func(n *astro.Node) {
120121
if n.Type == astro.ElementNode && n.DataAtom == a.Style {
121122
if HasSetDirective(n) || HasInlineDirective(n) {
@@ -125,8 +126,12 @@ func ExtractStyles(doc *astro.Node) {
125126
if !IsHoistable(n, false) {
126127
return
127128
}
128-
// prepend node to maintain authored order
129-
doc.Styles = append([]*astro.Node{n}, doc.Styles...)
129+
// append node to maintain authored order
130+
if opts.ExperimentalScriptOrder {
131+
doc.Styles = append(doc.Styles, n)
132+
} else {
133+
doc.Styles = append([]*astro.Node{n}, doc.Styles...)
134+
}
130135
}
131136
})
132137
// Important! Remove styles from original location *after* walking the doc
@@ -435,9 +440,13 @@ func ExtractScript(doc *astro.Node, n *astro.Node, opts *TransformOptions, h *ha
435440
}
436441
}
437442

438-
// prepend node to maintain authored order
443+
// append node to maintain authored order
439444
if shouldAdd {
440-
doc.Scripts = append([]*astro.Node{n}, doc.Scripts...)
445+
if opts.ExperimentalScriptOrder {
446+
doc.Scripts = append(doc.Scripts, n)
447+
} else {
448+
doc.Scripts = append([]*astro.Node{n}, doc.Scripts...)
449+
}
441450
n.HandledScript = true
442451
}
443452
} else {

internal/transform/transform_test.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ func TestTransformScoping(t *testing.T) {
182182
if err != nil {
183183
t.Error(err)
184184
}
185-
ExtractStyles(doc)
186185
var scopeStyle string
187186
if tt.scopeStyle == "attribute" {
188187
scopeStyle = "attribute"
@@ -191,7 +190,9 @@ func TestTransformScoping(t *testing.T) {
191190
} else {
192191
scopeStyle = "where"
193192
}
194-
Transform(doc, TransformOptions{Scope: "xxxxxx", ScopedStyleStrategy: scopeStyle}, handler.NewHandler(tt.source, "/test.astro"))
193+
transformOptions := TransformOptions{Scope: "xxxxxx", ScopedStyleStrategy: scopeStyle}
194+
ExtractStyles(doc, &transformOptions)
195+
Transform(doc, transformOptions, handler.NewHandler(tt.source, "/test.astro"))
195196
astro.PrintToSource(&b, doc.LastChild.FirstChild.NextSibling.FirstChild)
196197
got := b.String()
197198
if tt.want != got {
@@ -211,8 +212,9 @@ func FuzzTransformScoping(f *testing.F) {
211212
if err != nil {
212213
t.Skip("Invalid parse, skipping rest of fuzz test")
213214
}
214-
ExtractStyles(doc)
215-
Transform(doc, TransformOptions{Scope: "xxxxxx"}, handler.NewHandler(source, "/test.astro"))
215+
transformOptions := TransformOptions{Scope: "xxxxxx"}
216+
ExtractStyles(doc, &transformOptions)
217+
Transform(doc, transformOptions, handler.NewHandler(source, "/test.astro"))
216218
var b strings.Builder
217219
astro.PrintToSource(&b, doc.LastChild.FirstChild.NextSibling.FirstChild)
218220
got := b.String()
@@ -297,10 +299,11 @@ func TestFullTransform(t *testing.T) {
297299
if err != nil {
298300
t.Error(err)
299301
}
300-
ExtractStyles(doc)
302+
transformOptions := TransformOptions{}
303+
ExtractStyles(doc, &transformOptions)
301304
// Clear doc.Styles to avoid scoping behavior, we're not testing that here
302305
doc.Styles = make([]*astro.Node, 0)
303-
Transform(doc, TransformOptions{}, handler.NewHandler(tt.source, "/test.astro"))
306+
Transform(doc, transformOptions, handler.NewHandler(tt.source, "/test.astro"))
304307
astro.PrintToSource(&b, doc)
305308
got := strings.TrimSpace(b.String())
306309
if tt.want != got {
@@ -345,10 +348,11 @@ func TestTransformTrailingSpace(t *testing.T) {
345348
if err != nil {
346349
t.Error(err)
347350
}
348-
ExtractStyles(doc)
351+
transformOptions := TransformOptions{}
352+
ExtractStyles(doc, &transformOptions)
349353
// Clear doc.Styles to avoid scoping behavior, we're not testing that here
350354
doc.Styles = make([]*astro.Node, 0)
351-
Transform(doc, TransformOptions{}, handler.NewHandler(tt.source, "/test.astro"))
355+
Transform(doc, transformOptions, handler.NewHandler(tt.source, "/test.astro"))
352356
astro.PrintToSource(&b, doc)
353357
got := b.String()
354358
if tt.want != got {
@@ -463,12 +467,13 @@ func TestCompactTransform(t *testing.T) {
463467
if err != nil {
464468
t.Error(err)
465469
}
466-
ExtractStyles(doc)
470+
transformOptions := TransformOptions{
471+
Compact: true,
472+
}
473+
ExtractStyles(doc, &transformOptions)
467474
// Clear doc.Styles to avoid scoping behavior, we're not testing that here
468475
doc.Styles = make([]*astro.Node, 0)
469-
Transform(doc, TransformOptions{
470-
Compact: true,
471-
}, &handler.Handler{})
476+
Transform(doc, transformOptions, &handler.Handler{})
472477
astro.PrintToSource(&b, doc)
473478
got := strings.TrimSpace(b.String())
474479
if tt.want != got {

packages/compiler/src/shared/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface TransformOptions {
6565
* @experimental
6666
*/
6767
renderScript?: boolean;
68+
experimentalScriptOrder?: boolean;
6869
}
6970

7071
export type ConvertToTSXOptions = Pick<
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { transform } from '@astrojs/compiler';
2+
import { test } from 'uvu';
3+
import * as assert from 'uvu/assert';
4+
5+
test('outputs scripts in expected order', async () => {
6+
const result = await transform(
7+
`
8+
<script>console.log(1)</script>
9+
<script>console.log(2)</script>`,
10+
{
11+
experimentalScriptOrder: true,
12+
}
13+
);
14+
15+
const scripts = result.scripts;
16+
17+
// for typescript
18+
if (scripts[0].type === 'external') throw new Error('Script is external');
19+
if (scripts[1].type === 'external') throw new Error('Script is external');
20+
21+
assert.match(scripts[0].code, 'console.log(1)');
22+
assert.match(scripts[1].code, 'console.log(2)');
23+
});
24+
25+
test.run();

0 commit comments

Comments
 (0)