diff --git a/.changeset/grumpy-ads-know.md b/.changeset/grumpy-ads-know.md new file mode 100644 index 000000000..b0a1473d4 --- /dev/null +++ b/.changeset/grumpy-ads-know.md @@ -0,0 +1,7 @@ +--- +"@astrojs/compiler": patch +--- + +Fixes an issue with the conditional rendering of scripts. + +**This change updates a v5.0 breaking change when `experimental.directRenderScript` became the default script handling behavior.** If you have already successfully upgraded to Astro v5, you may need to review your script tags again and make sure they still behave as desired after this release. [See the v5 Upgrade Guide for more details.](https://docs.astro.build/en/guides/upgrade-to/v5/#script-tags-are-rendered-directly-as-declared) diff --git a/internal/printer/__printer_js__/script_external_in_expression__renderScript__false_.snap b/internal/printer/__printer_js__/script_external_in_expression__renderScript__false_.snap new file mode 100755 index 000000000..685add517 --- /dev/null +++ b/internal/printer/__printer_js__/script_external_in_expression__renderScript__false_.snap @@ -0,0 +1,41 @@ + +[TestPrinter/script_external_in_expression_(renderScript:_false) - 1] +## Input + +``` +
{} +``` + +## Output + +```js +import { + Fragment, + render as $$render, + createAstro as $$createAstro, + createComponent as $$createComponent, + renderComponent as $$renderComponent, + renderHead as $$renderHead, + maybeRenderHead as $$maybeRenderHead, + unescapeHTML as $$unescapeHTML, + renderSlot as $$renderSlot, + mergeSlots as $$mergeSlots, + addAttribute as $$addAttribute, + spreadAttributes as $$spreadAttributes, + defineStyleVars as $$defineStyleVars, + defineScriptVars as $$defineScriptVars, + renderTransition as $$renderTransition, + createTransitionScope as $$createTransitionScope, + renderScript as $$renderScript, + createMetadata as $$createMetadata +} from "http://localhost:3000/"; + +export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [] }); + +const $$Index = $$createComponent(($$result, $$props, $$slots) => { + +return $$render`${$$maybeRenderHead($$result)}
${$$render``}
`; +}, '/src/pages/index.astro', undefined); +export default $$Index; +``` +--- diff --git a/internal/printer/__printer_js__/script_external_in_expression__renderScript__true_.snap b/internal/printer/__printer_js__/script_external_in_expression__renderScript__true_.snap new file mode 100755 index 000000000..179e57092 --- /dev/null +++ b/internal/printer/__printer_js__/script_external_in_expression__renderScript__true_.snap @@ -0,0 +1,41 @@ + +[TestPrinter/script_external_in_expression_(renderScript:_true) - 1] +## Input + +``` +
{} +``` + +## Output + +```js +import { + Fragment, + render as $$render, + createAstro as $$createAstro, + createComponent as $$createComponent, + renderComponent as $$renderComponent, + renderHead as $$renderHead, + maybeRenderHead as $$maybeRenderHead, + unescapeHTML as $$unescapeHTML, + renderSlot as $$renderSlot, + mergeSlots as $$mergeSlots, + addAttribute as $$addAttribute, + spreadAttributes as $$spreadAttributes, + defineStyleVars as $$defineStyleVars, + defineScriptVars as $$defineScriptVars, + renderTransition as $$renderTransition, + createTransitionScope as $$createTransitionScope, + renderScript as $$renderScript, + createMetadata as $$createMetadata +} from "http://localhost:3000/"; + +export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [{ type: 'external', src: './hello.js' }] }); + +const $$Index = $$createComponent(($$result, $$props, $$slots) => { + +return $$render`${$$maybeRenderHead($$result)}
${$$render`${$$renderScript($$result,"/src/pages/index.astro?astro&type=script&index=0&lang.ts")}`}
`; +}, '/src/pages/index.astro', undefined); +export default $$Index; +``` +--- diff --git a/internal/printer/__printer_js__/script_in_expression__renderScript__false_.snap b/internal/printer/__printer_js__/script_in_expression__renderScript__false_.snap new file mode 100755 index 000000000..79ac613b5 --- /dev/null +++ b/internal/printer/__printer_js__/script_in_expression__renderScript__false_.snap @@ -0,0 +1,41 @@ + +[TestPrinter/script_in_expression_(renderScript:_false) - 1] +## Input + +``` +
{false && } +``` + +## Output + +```js +import { + Fragment, + render as $$render, + createAstro as $$createAstro, + createComponent as $$createComponent, + renderComponent as $$renderComponent, + renderHead as $$renderHead, + maybeRenderHead as $$maybeRenderHead, + unescapeHTML as $$unescapeHTML, + renderSlot as $$renderSlot, + mergeSlots as $$mergeSlots, + addAttribute as $$addAttribute, + spreadAttributes as $$spreadAttributes, + defineStyleVars as $$defineStyleVars, + defineScriptVars as $$defineScriptVars, + renderTransition as $$renderTransition, + createTransitionScope as $$createTransitionScope, + renderScript as $$renderScript, + createMetadata as $$createMetadata +} from "http://localhost:3000/"; + +export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [] }); + +const $$Index = $$createComponent(($$result, $$props, $$slots) => { + +return $$render`${$$maybeRenderHead($$result)}
${false && $$render``}
`; +}, '/src/pages/index.astro', undefined); +export default $$Index; +``` +--- diff --git a/internal/printer/__printer_js__/script_in_expression__renderScript__true_.snap b/internal/printer/__printer_js__/script_in_expression__renderScript__true_.snap new file mode 100755 index 000000000..6a96b9642 --- /dev/null +++ b/internal/printer/__printer_js__/script_in_expression__renderScript__true_.snap @@ -0,0 +1,41 @@ + +[TestPrinter/script_in_expression_(renderScript:_true) - 1] +## Input + +``` +
{true && } +``` + +## Output + +```js +import { + Fragment, + render as $$render, + createAstro as $$createAstro, + createComponent as $$createComponent, + renderComponent as $$renderComponent, + renderHead as $$renderHead, + maybeRenderHead as $$maybeRenderHead, + unescapeHTML as $$unescapeHTML, + renderSlot as $$renderSlot, + mergeSlots as $$mergeSlots, + addAttribute as $$addAttribute, + spreadAttributes as $$spreadAttributes, + defineStyleVars as $$defineStyleVars, + defineScriptVars as $$defineScriptVars, + renderTransition as $$renderTransition, + createTransitionScope as $$createTransitionScope, + renderScript as $$renderScript, + createMetadata as $$createMetadata +} from "http://localhost:3000/"; + +export const $$metadata = $$createMetadata("/src/pages/index.astro", { modules: [], hydratedComponents: [], clientOnlyComponents: [], hydrationDirectives: new Set([]), hoisted: [{ type: 'inline', value: `console.log("hello")` }] }); + +const $$Index = $$createComponent(($$result, $$props, $$slots) => { + +return $$render`${$$maybeRenderHead($$result)}
${true && $$render`${$$renderScript($$result,"/src/pages/index.astro?astro&type=script&index=0&lang.ts")}`}
`; +}, '/src/pages/index.astro', undefined); +export default $$Index; +``` +--- diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index 0089ea34f..12d1ae9ee 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -894,6 +894,34 @@ import Widget2 from '../components/Widget2.astro'; }, filename: "/src/pages/index.astro", }, + { + name: "script external in expression (renderScript: true)", + source: `
{}`, + transformOptions: transform.TransformOptions{ + RenderScript: true, + }, + filename: "/src/pages/index.astro", + }, + { + // maintain the original behavior, though it may be + // unneeded as renderScript is now on by default + name: "script external in expression (renderScript: false)", + source: `
{}`, + filename: "/src/pages/index.astro", + }, + { + name: "script in expression (renderScript: true)", + source: `
{true && }`, + transformOptions: transform.TransformOptions{ + RenderScript: true, + }, + filename: "/src/pages/index.astro", + }, + { + name: "script in expression (renderScript: false)", + source: `
{false && }`, + filename: "/src/pages/index.astro", + }, { name: "script inline (renderScript: true)", source: `
`, @@ -2092,7 +2120,6 @@ const meta = { title: 'My App' }; Kind: test_utils.JsOutput, FolderName: "__printer_js__", }) - }) } } @@ -2215,7 +2242,6 @@ const c = '\'' code := test_utils.Dedent(tt.source) doc, err := astro.ParseWithOptions(strings.NewReader(code), astro.ParseOptionEnableLiteral(true), astro.ParseOptionWithHandler(&handler.Handler{})) - if err != nil { t.Error(err) } diff --git a/internal/transform/transform.go b/internal/transform/transform.go index c411361b9..effa21487 100644 --- a/internal/transform/transform.go +++ b/internal/transform/transform.go @@ -122,7 +122,7 @@ func ExtractStyles(doc *astro.Node) { return } // Ignore styles in svg/noscript/etc - if !IsHoistable(n) { + if !IsHoistable(n, false) { return } // prepend node to maintain authored order @@ -403,7 +403,8 @@ func ExtractScript(doc *astro.Node, n *astro.Node, opts *TransformOptions, h *ha return } // Ignore scripts in svg/noscript/etc - if !IsHoistable(n) { + // In expressions ignore scripts, unless `RenderScript` is true + if !IsHoistable(n, opts.RenderScript) { return } diff --git a/internal/transform/utils.go b/internal/transform/utils.go index 1a5e082ba..1a6bbe5e4 100644 --- a/internal/transform/utils.go +++ b/internal/transform/utils.go @@ -47,10 +47,15 @@ func GetAttr(n *astro.Node, key string) *astro.Attribute { return nil } -func IsHoistable(n *astro.Node) bool { +func IsHoistable(n *astro.Node, renderScriptEnabled bool) bool { parent := n.Closest(func(p *astro.Node) bool { return p.DataAtom == atom.Svg || p.DataAtom == atom.Noscript || p.DataAtom == atom.Template }) + + if renderScriptEnabled && parent != nil && parent.Expression { + return true + } + return parent == nil }