Skip to content

Commit d453b65

Browse files
committed
fix: Sitemap Index - Unexpected Server Error
1 parent 85147c8 commit d453b65

File tree

9 files changed

+87
-22
lines changed

9 files changed

+87
-22
lines changed

fixtures/webstudio-custom-template/app/routes/[sitemap.xml]._index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { renderToString } from "react-dom/server";
22
import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
33
import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
4-
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
4+
import {
5+
ReactSdkContext,
6+
xmlNodeTagSuffix,
7+
} from "@webstudio-is/react-sdk/runtime";
58
import { Page } from "../__generated__/[sitemap.xml]._index";
69
import {
710
getPageMeta,
@@ -76,6 +79,10 @@ export const loader = async (arg: LoaderFunctionArgs) => {
7679
// More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083
7780
text = text.replace(/^<svg>/g, "").replace(/<\/svg>$/g, "");
7881

82+
// React has issues rendering certain elements, such as errors when a <link> element has children.
83+
// To render XML, we wrap it with an <svg> tag and add a suffix to avoid React's default behavior on these elements.
84+
text = text.replaceAll(xmlNodeTagSuffix, "");
85+
7986
return new Response(`<?xml version="1.0" encoding="UTF-8"?>\n${text}`, {
8087
headers: { "Content-Type": "application/xml" },
8188
});

fixtures/webstudio-remix-vercel/.webstudio/data.json

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"build": {
3-
"id": "0ff71ecc-db91-41d0-ba52-26d2fc6c196d",
3+
"id": "63389378-e2a2-4e25-8c98-3e408bcfc4c4",
44
"projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d",
5-
"version": 396,
6-
"createdAt": "2024-12-05T12:47:15.161+00:00",
7-
"updatedAt": "2024-12-05T12:47:15.161+00:00",
5+
"version": 401,
6+
"createdAt": "2025-01-04T10:58:00.47+00:00",
7+
"updatedAt": "2025-01-04T10:58:00.47+00:00",
88
"pages": {
99
"meta": {
1010
"siteName": "KittyGuardedZone",
@@ -2867,6 +2867,16 @@
28672867
"type": "string",
28682868
"value": "1733402818245"
28692869
}
2870+
],
2871+
[
2872+
"wb8XS5grnnYTgGAotvCfZ",
2873+
{
2874+
"id": "wb8XS5grnnYTgGAotvCfZ",
2875+
"instanceId": "WCz4oAOyt2V-prz3LIAes",
2876+
"name": "tag",
2877+
"type": "string",
2878+
"value": "link"
2879+
}
28702880
]
28712881
],
28722882
"dataSources": [
@@ -4354,6 +4364,10 @@
43544364
{
43554365
"type": "id",
43564366
"value": "wLYkMGH-OJP4SnFB4F-bs"
4367+
},
4368+
{
4369+
"type": "id",
4370+
"value": "WCz4oAOyt2V-prz3LIAes"
43574371
}
43584372
]
43594373
}
@@ -4842,6 +4856,20 @@
48424856
"component": "XmlTime",
48434857
"children": []
48444858
}
4859+
],
4860+
[
4861+
"WCz4oAOyt2V-prz3LIAes",
4862+
{
4863+
"type": "instance",
4864+
"id": "WCz4oAOyt2V-prz3LIAes",
4865+
"component": "XmlNode",
4866+
"children": [
4867+
{
4868+
"type": "text",
4869+
"value": "https://webstudio.is"
4870+
}
4871+
]
4872+
}
48454873
]
48464874
],
48474875
"deployment": {

fixtures/webstudio-remix-vercel/app/__generated__/$resources.sitemap.xml.ts

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fixtures/webstudio-remix-vercel/app/__generated__/[sitemap.xml]._index.tsx

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fixtures/webstudio-remix-vercel/app/routes/[sitemap.xml]._index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { renderToString } from "react-dom/server";
22
import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
33
import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
4-
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
4+
import {
5+
ReactSdkContext,
6+
xmlNodeTagSuffix,
7+
} from "@webstudio-is/react-sdk/runtime";
58
import { Page } from "../__generated__/[sitemap.xml]._index";
69
import {
710
getPageMeta,
@@ -76,6 +79,10 @@ export const loader = async (arg: LoaderFunctionArgs) => {
7679
// More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083
7780
text = text.replace(/^<svg>/g, "").replace(/<\/svg>$/g, "");
7881

82+
// React has issues rendering certain elements, such as errors when a <link> element has children.
83+
// To render XML, we wrap it with an <svg> tag and add a suffix to avoid React's default behavior on these elements.
84+
text = text.replaceAll(xmlNodeTagSuffix, "");
85+
7986
return new Response(`<?xml version="1.0" encoding="UTF-8"?>\n${text}`, {
8087
headers: { "Content-Type": "application/xml" },
8188
});

fixtures/webstudio-remix-vercel/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"typecheck": "tsc",
77
"cli": "NODE_OPTIONS='--conditions=webstudio --import=tsx' webstudio",
88
"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'",
9-
"fixtures:sync": "pnpm cli sync --buildId 0ff71ecc-db91-41d0-ba52-26d2fc6c196d && pnpm prettier --write ./.webstudio/",
9+
"fixtures:sync": "pnpm cli sync --buildId 63389378-e2a2-4e25-8c98-3e408bcfc4c4 && pnpm prettier --write ./.webstudio/",
1010
"fixtures:build": "pnpm cli build --template vercel --template internal && pnpm prettier --write ./app/ ./package.json ./tsconfig.json"
1111
},
1212
"private": true,

packages/cli/templates/defaults/app/route-templates/xml.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { renderToString } from "react-dom/server";
22
import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
33
import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
4-
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
4+
import {
5+
ReactSdkContext,
6+
xmlNodeTagSuffix,
7+
} from "@webstudio-is/react-sdk/runtime";
58
import { Page } from "__CLIENT__";
69
import { getPageMeta, getRemixParams, getResources } from "__SERVER__";
710
import { assetBaseUrl, imageLoader } from "__CONSTANTS__";
@@ -72,6 +75,10 @@ export const loader = async (arg: LoaderFunctionArgs) => {
7275
// More details: https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L3083
7376
text = text.replace(/^<svg>/g, "").replace(/<\/svg>$/g, "");
7477

78+
// React has issues rendering certain elements, such as errors when a <link> element has children.
79+
// To render XML, we wrap it with an <svg> tag and add a suffix to avoid React's default behavior on these elements.
80+
text = text.replaceAll(xmlNodeTagSuffix, "");
81+
7582
return new Response(`<?xml version="1.0" encoding="UTF-8"?>\n${text}`, {
7683
headers: { "Content-Type": "application/xml" },
7784
});

packages/react-sdk/src/runtime.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ export * from "./context";
22
export * from "./hook";
33
export * from "./variable-state";
44

5+
/**
6+
* React has issues rendering certain elements, such as errors when a <link> element has children.
7+
* To render XML, we wrap it with an <svg> tag and add a suffix to avoid React's default behavior on these elements.
8+
*/
9+
export const xmlNodeTagSuffix =
10+
"-ws-xml-node-fb77f896-8e96-40b9-b8f8-90a4e70d724a";
11+
512
export const getIndexWithinAncestorFromComponentProps = (
613
props: Record<string, unknown>
714
) => {

packages/sdk-components-react/src/xml-node.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
1+
import {
2+
ReactSdkContext,
3+
xmlNodeTagSuffix,
4+
} from "@webstudio-is/react-sdk/runtime";
25
import {
36
Children,
47
createElement,
@@ -33,22 +36,27 @@ export const XmlNode = forwardRef<ElementRef<"div">, Props>(
3336
.filter(([key]) => key !== "tabIndex")
3437
.filter(([, value]) => typeof value !== "function");
3538

39+
const elementName = tag
40+
// Must start from letter or underscore
41+
.replace(/^[^\p{L}_]+/u, "")
42+
// Clear all non letter, number, underscore, dot, and dash
43+
.replaceAll(/[^\p{L}\p{N}\-._:]+/gu, "")
44+
.trim();
45+
3646
if (renderer === undefined) {
3747
const attrProps = Object.fromEntries(attributeEntries);
38-
return createElement(tag, attrProps, children);
48+
return createElement(
49+
`${elementName}${xmlNodeTagSuffix}`,
50+
attrProps,
51+
children
52+
);
3953
}
4054

4155
const childrenArray = Children.toArray(children);
4256
const isTextChild =
4357
childrenArray.length > 0 &&
4458
childrenArray.every((child) => typeof child === "string");
4559

46-
const elementName = tag
47-
// Must start from letter or underscore
48-
.replace(/^[^\p{L}_]+/u, "")
49-
// Clear all non letter, number, underscore, dot, and dash
50-
.replaceAll(/[^\p{L}\p{N}\-._:]+/gu, "");
51-
5260
const attributes = attributeEntries.map(
5361
([key, value]) => `${key}=${JSON.stringify(value)}`
5462
);

0 commit comments

Comments
 (0)