From e29ceec9065d40c316a908073c5fd44067e0e65c Mon Sep 17 00:00:00 2001 From: istarkov Date: Mon, 4 Nov 2024 06:59:34 +0000 Subject: [PATCH 1/2] fix: XML Node with title tag nested in any other XML Node breaks document --- .../.webstudio/data.json | 36 ++++++++++++++++--- .../__generated__/$resources.sitemap.xml.ts | 12 +++---- .../__generated__/[sitemap.xml]._index.tsx | 3 +- .../app/routes/[sitemap.xml]._index.tsx | 6 +++- fixtures/webstudio-remix-vercel/package.json | 2 +- packages/cli/src/prebuild.ts | 9 +++-- .../defaults/app/route-templates/xml.tsx | 6 +++- 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/fixtures/webstudio-remix-vercel/.webstudio/data.json b/fixtures/webstudio-remix-vercel/.webstudio/data.json index c589c57cfe81..76686e2b5664 100644 --- a/fixtures/webstudio-remix-vercel/.webstudio/data.json +++ b/fixtures/webstudio-remix-vercel/.webstudio/data.json @@ -1,10 +1,10 @@ { "build": { - "id": "1710e6a3-6f3b-44c9-8e4f-4176be77673e", + "id": "5646b5e6-a161-4fbc-8312-6e2852e1d4b3", "projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d", - "version": 341, - "createdAt": "2024-10-28T17:19:04.754+00:00", - "updatedAt": "2024-10-28T17:19:04.754+00:00", + "version": 345, + "createdAt": "2024-11-04T04:15:27.144+00:00", + "updatedAt": "2024-11-04T04:15:27.144+00:00", "pages": { "meta": { "siteName": "KittyGuardedZone", @@ -2601,6 +2601,16 @@ "type": "string", "value": "http://www.w3.org/1999/xhtml" } + ], + [ + "kQb_yRWDNAsug8p2lhSxN", + { + "id": "kQb_yRWDNAsug8p2lhSxN", + "instanceId": "wLYkMGH-OJP4SnFB4F-bs", + "name": "tag", + "type": "string", + "value": "title" + } ] ], "dataSources": [ @@ -4075,6 +4085,10 @@ { "type": "id", "value": "bBAE2vpcCLzlcin29wQYA" + }, + { + "type": "id", + "value": "wLYkMGH-OJP4SnFB4F-bs" } ] } @@ -4124,6 +4138,20 @@ "component": "XmlNode", "children": [] } + ], + [ + "wLYkMGH-OJP4SnFB4F-bs", + { + "type": "instance", + "id": "wLYkMGH-OJP4SnFB4F-bs", + "component": "XmlNode", + "children": [ + { + "type": "text", + "value": "Hello" + } + ] + } ] ], "deployment": { diff --git a/fixtures/webstudio-remix-vercel/app/__generated__/$resources.sitemap.xml.ts b/fixtures/webstudio-remix-vercel/app/__generated__/$resources.sitemap.xml.ts index ee0f83296c51..d771f93ec29d 100644 --- a/fixtures/webstudio-remix-vercel/app/__generated__/$resources.sitemap.xml.ts +++ b/fixtures/webstudio-remix-vercel/app/__generated__/$resources.sitemap.xml.ts @@ -1,26 +1,26 @@ export const sitemap = [ { path: "/", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, { path: "/_route_with_symbols_", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, { path: "/form", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, { path: "/heading-with-id", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, { path: "/resources", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, { path: "/nested/nested-page", - lastModified: "2024-10-28", + lastModified: "2024-11-04", }, ]; diff --git a/fixtures/webstudio-remix-vercel/app/__generated__/[sitemap.xml]._index.tsx b/fixtures/webstudio-remix-vercel/app/__generated__/[sitemap.xml]._index.tsx index 810befd78c35..090bbbbc801a 100644 --- a/fixtures/webstudio-remix-vercel/app/__generated__/[sitemap.xml]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/__generated__/[sitemap.xml]._index.tsx @@ -25,7 +25,7 @@ export const pageFontAssets: FontAsset[] = []; export const pageBackgroundImageAssets: ImageAsset[] = []; -const Body = (props: any) => props.children; +const Body = (props: any) => {props.children}; const Heading = (props: any) => null; const Page = ({ system: system }: { system: any }) => { @@ -73,6 +73,7 @@ const Page = ({ system: system }: { system: any }) => { hreflang={"en"} href={"custom-en-location"} /> + {"Hello"} diff --git a/fixtures/webstudio-remix-vercel/app/routes/[sitemap.xml]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[sitemap.xml]._index.tsx index 78ace187c30d..49a6d5ec41f7 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[sitemap.xml]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[sitemap.xml]._index.tsx @@ -60,7 +60,7 @@ export const loader = async (arg: LoaderFunctionArgs) => { // typecheck arg.context.EXCLUDE_FROM_SEARCH satisfies boolean; - const text = renderToString( + let text = renderToString( { ); + // Xml is wrapped with to prevent React from hoisting elements like , , and out of their intended scope during rendering. + // More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083 + text = text.replace(/^/g, "").replace(/<\/svg>$/g, ""); + return new Response(`\n${text}`, { headers: { "Content-Type": "application/xml" }, }); diff --git a/fixtures/webstudio-remix-vercel/package.json b/fixtures/webstudio-remix-vercel/package.json index 5c2590858c96..29c88715e664 100644 --- a/fixtures/webstudio-remix-vercel/package.json +++ b/fixtures/webstudio-remix-vercel/package.json @@ -6,7 +6,7 @@ "typecheck": "tsc", "cli": "NODE_OPTIONS='--conditions=webstudio --import=tsx' webstudio", "fixtures:link": "pnpm cli link --link https://p-cddc1d44-af37-4cb6-a430-d300cf6f932d-dot-${BUILDER_HOST:-main.development.webstudio.is}'?authToken=1cdc6026-dd5b-4624-b89b-9bd45e9bcc3d'", - "fixtures:sync": "pnpm cli sync --buildId 1710e6a3-6f3b-44c9-8e4f-4176be77673e && pnpm prettier --write ./.webstudio/", + "fixtures:sync": "pnpm cli sync --buildId 5646b5e6-a161-4fbc-8312-6e2852e1d4b3 && pnpm prettier --write ./.webstudio/", "fixtures:build": "pnpm cli build --template vercel --template internal --preview && pnpm prettier --write ./app/ ./package.json ./tsconfig.json" }, "private": true, diff --git a/packages/cli/src/prebuild.ts b/packages/cli/src/prebuild.ts index d05ed914d19e..1eaf937b50d5 100644 --- a/packages/cli/src/prebuild.ts +++ b/packages/cli/src/prebuild.ts @@ -550,7 +550,6 @@ export const prebuild = async (options: { // In case of xml it's the only component we are supporting componentImports = `import { XmlNode } from "@webstudio-is/sdk-components-react";\n`; - // Passthrough (render children) for Body, do not render all other components xmlPresentationComponents += Array.from(componentsSet) .map(([shortName, component]) => scope.getName(component, shortName) @@ -558,8 +557,12 @@ export const prebuild = async (options: { .filter((scopedName) => scopedName !== "XmlNode") .map((scopedName) => scopedName === "Body" - ? `const ${scopedName} = (props: any) => props.children;` - : `const ${scopedName} = (props: any) => null;` + ? // Using prevents React from hoisting elements like , , and + // out of their intended scope during rendering. + // More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083 + `const ${scopedName} = (props: any) => {props.children};` + : // Do not render all other components + `const ${scopedName} = (props: any) => null;` ) .join("\n"); } diff --git a/packages/cli/templates/defaults/app/route-templates/xml.tsx b/packages/cli/templates/defaults/app/route-templates/xml.tsx index 91e625bc9b3b..4a54d734e8a7 100644 --- a/packages/cli/templates/defaults/app/route-templates/xml.tsx +++ b/packages/cli/templates/defaults/app/route-templates/xml.tsx @@ -56,7 +56,7 @@ export const loader = async (arg: LoaderFunctionArgs) => { // typecheck arg.context.EXCLUDE_FROM_SEARCH satisfies boolean; - const text = renderToString( + let text = renderToString( { ); + // Xml is wrapped with to prevent React from hoisting elements like , , and out of their intended scope during rendering. + // More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083 + text = text.replace(/^/g, "").replace(/<\/svg>$/g, ""); + return new Response(`\n${text}`, { headers: { "Content-Type": "application/xml" }, }); From b0b1fe72378de53a109d9e0d06f08e93c9d8ef20 Mon Sep 17 00:00:00 2001 From: istarkov Date: Mon, 4 Nov 2024 07:10:18 +0000 Subject: [PATCH 2/2] Fix sitemap --- .../app/__generated__/[sitemap.xml]._index.tsx | 2 +- .../app/routes/[sitemap.xml]._index.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fixtures/webstudio-custom-template/app/__generated__/[sitemap.xml]._index.tsx b/fixtures/webstudio-custom-template/app/__generated__/[sitemap.xml]._index.tsx index e04972f988b1..6f494dfccef1 100644 --- a/fixtures/webstudio-custom-template/app/__generated__/[sitemap.xml]._index.tsx +++ b/fixtures/webstudio-custom-template/app/__generated__/[sitemap.xml]._index.tsx @@ -25,7 +25,7 @@ export const pageFontAssets: FontAsset[] = []; export const pageBackgroundImageAssets: ImageAsset[] = []; -const Body = (props: any) => props.children; +const Body = (props: any) => {props.children}; const Page = ({ system: system }: { system: any }) => { let sitemapxml = useResource("sitemapxml_1"); diff --git a/fixtures/webstudio-custom-template/app/routes/[sitemap.xml]._index.tsx b/fixtures/webstudio-custom-template/app/routes/[sitemap.xml]._index.tsx index 78ace187c30d..49a6d5ec41f7 100644 --- a/fixtures/webstudio-custom-template/app/routes/[sitemap.xml]._index.tsx +++ b/fixtures/webstudio-custom-template/app/routes/[sitemap.xml]._index.tsx @@ -60,7 +60,7 @@ export const loader = async (arg: LoaderFunctionArgs) => { // typecheck arg.context.EXCLUDE_FROM_SEARCH satisfies boolean; - const text = renderToString( + let text = renderToString( { ); + // Xml is wrapped with to prevent React from hoisting elements like , , and out of their intended scope during rendering. + // More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083 + text = text.replace(/^/g, "").replace(/<\/svg>$/g, ""); + return new Response(`\n${text}`, { headers: { "Content-Type": "application/xml" }, });