From 618ea3a8ea8155e80e61f6a4718f6661d6297997 Mon Sep 17 00:00:00 2001 From: Mihkel Eidast Date: Tue, 10 Aug 2021 00:36:12 +0300 Subject: [PATCH] Fix nested client load directive (#1030) * escape in string literals * add changeset --- .changeset/fair-dogs-tie.md | 5 +++++ .../astro/src/internal/__astro_component.ts | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .changeset/fair-dogs-tie.md diff --git a/.changeset/fair-dogs-tie.md b/.changeset/fair-dogs-tie.md new file mode 100644 index 0000000000..caf00c7550 --- /dev/null +++ b/.changeset/fair-dogs-tie.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Properly escapes script tags with nested client:load directives when passing Astro components into framework components via props. Browsers interpret script end tags in strings as script end tags, resulting in syntax errors. diff --git a/packages/astro/src/internal/__astro_component.ts b/packages/astro/src/internal/__astro_component.ts index 9470e5b147..0543df203b 100644 --- a/packages/astro/src/internal/__astro_component.ts +++ b/packages/astro/src/internal/__astro_component.ts @@ -1,12 +1,26 @@ import type { Renderer, AstroComponentMetadata } from '../@types/astro'; import hash from 'shorthash'; import { valueToEstree, Value } from 'estree-util-value-to-estree'; -import { generate } from 'astring'; +import { generate, GENERATOR, Generator } from 'astring'; import * as astroHtml from './renderer-html'; // A more robust version alternative to `JSON.stringify` that can handle most values // see https://github.com/remcohaszing/estree-util-value-to-estree#readme -const serialize = (value: Value) => generate(valueToEstree(value)); +const customGenerator: Generator = { + ...GENERATOR, + Literal(node, state) { + if (node.raw != null) { + // escape closing script tags in strings so browsers wouldn't interpret them as + // closing the actual end tag in HTML + state.write(node.raw.replace('', '<\\/script>')); + } else { + GENERATOR.Literal(node, state); + } + }, +}; +const serialize = (value: Value) => generate(valueToEstree(value), { + generator: customGenerator, +}); export interface RendererInstance { source: string | null;