webstudio 0.151.0 → 0.163.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -68,16 +68,16 @@ var isFileExists = async (filePath) => {
68
68
  return false;
69
69
  }
70
70
  };
71
- var ensureFileInPath = async (filePath, content) => {
71
+ var createFileIfNotExists = async (filePath, content) => {
72
72
  const dir = dirname(filePath);
73
- await ensureFolderExists(dir);
73
+ await createFolderIfNotExists(dir);
74
74
  try {
75
75
  await access(filePath, constants.F_OK);
76
76
  } catch {
77
77
  await writeFile(filePath, content || "", "utf8");
78
78
  }
79
79
  };
80
- var ensureFolderExists = async (folderPath) => {
80
+ var createFolderIfNotExists = async (folderPath) => {
81
81
  try {
82
82
  await access(folderPath, constants.F_OK);
83
83
  } catch {
@@ -142,7 +142,7 @@ var link = async (options) => {
142
142
  const localConfig = {
143
143
  projectId
144
144
  };
145
- await ensureFileInPath(
145
+ await createFileIfNotExists(
146
146
  join2(cwd(), LOCAL_CONFIG_FILE),
147
147
  JSON.stringify(localConfig, null, 2)
148
148
  );
@@ -231,7 +231,7 @@ var sync = async (options) => {
231
231
  project;
232
232
  spinner.text = "Saving project data to config file";
233
233
  const localBuildFilePath = join3(cwd2(), LOCAL_DATA_FILE);
234
- await ensureFileInPath(localBuildFilePath);
234
+ await createFileIfNotExists(localBuildFilePath);
235
235
  await writeFile3(localBuildFilePath, JSON.stringify(project, null, 2), "utf8");
236
236
  spinner.succeed("Project data synced successfully");
237
237
  };
@@ -265,7 +265,7 @@ import {
265
265
  normalizeProps,
266
266
  generateRemixRoute,
267
267
  generateRemixParams,
268
- collectionComponent
268
+ isCoreComponent
269
269
  } from "@webstudio-is/react-sdk";
270
270
  import {
271
271
  createScope,
@@ -288,7 +288,7 @@ var downloadAsset = async (url, name, assetBaseUrl) => {
288
288
  try {
289
289
  await access2(assetPath);
290
290
  } catch {
291
- await ensureFolderExists(dirname2(assetPath));
291
+ await createFolderIfNotExists(dirname2(assetPath));
292
292
  try {
293
293
  const response = await fetch(url);
294
294
  if (!response.ok) {
@@ -480,7 +480,7 @@ var prebuild = async (options) => {
480
480
  };
481
481
  componentsByPage[page.id] = /* @__PURE__ */ new Set();
482
482
  for (const [_instanceId, instance] of instances) {
483
- if (instance.component === collectionComponent) {
483
+ if (isCoreComponent(instance.component)) {
484
484
  continue;
485
485
  }
486
486
  componentsByPage[page.id].add(instance.component);
@@ -546,6 +546,8 @@ var prebuild = async (options) => {
546
546
  const assets = new Map(siteData.assets.map((asset) => [asset.id, asset]));
547
547
  spinner.text = "Generating css file";
548
548
  const { cssText, classesMap } = generateCss({
549
+ instances: new Map(siteData.build.instances),
550
+ props: new Map(siteData.build.props),
549
551
  assets,
550
552
  breakpoints: new Map(siteData.build?.breakpoints),
551
553
  styles: new Map(siteData.build?.styles),
@@ -555,11 +557,18 @@ var prebuild = async (options) => {
555
557
  assetBaseUrl,
556
558
  atomic: siteData.build.pages.compiler?.atomicStyles ?? true
557
559
  });
558
- await ensureFileInPath(join4(generatedDir, "index.css"), cssText);
560
+ await createFileIfNotExists(join4(generatedDir, "index.css"), cssText);
559
561
  spinner.text = "Generating routes and pages";
560
- const routeTemplatePath = normalize(join4(cwd3(), "app/routes/template.tsx"));
562
+ const routeTemplatesDir = join4(cwd3(), "app/route-templates");
563
+ const routeTemplatePath = normalize(join4(routeTemplatesDir, "html.tsx"));
564
+ const routeXmlTemplatePath = normalize(join4(routeTemplatesDir, "xml.tsx"));
565
+ const defaultSiteMapXmlPath = normalize(
566
+ join4(routeTemplatesDir, "default-sitemap.tsx")
567
+ );
561
568
  const routeFileTemplate = await readFile4(routeTemplatePath, "utf8");
562
- await rm(routeTemplatePath);
569
+ const routeXmlFileTemplate = await readFile4(routeXmlTemplatePath, "utf8");
570
+ const defaultSiteMapTemplate = await readFile4(defaultSiteMapXmlPath, "utf8");
571
+ await rm(routeTemplatesDir, { recursive: true, force: true });
563
572
  for (const [pageId, pageComponents] of Object.entries(componentsByPage)) {
564
573
  const scope = createScope([
565
574
  // manually maintained list of occupied identifiers
@@ -592,14 +601,36 @@ var prebuild = async (options) => {
592
601
  namespaces.get(namespace)?.add([shortName, component]);
593
602
  }
594
603
  let componentImports = "";
604
+ let xmlPresentationComponents = "";
605
+ const pageData = siteDataByPage[pageId];
606
+ const documentType = pageData.page.meta.documentType ?? "html";
595
607
  for (const [namespace, componentsSet] of namespaces.entries()) {
596
- const specifiers = Array.from(componentsSet).map(
597
- ([shortName, component]) => `${shortName} as ${scope.getName(component, shortName)}`
598
- ).join(", ");
599
- componentImports += `import { ${specifiers} } from "${namespace}";
608
+ switch (documentType) {
609
+ case "html":
610
+ {
611
+ const specifiers = Array.from(componentsSet).map(
612
+ ([shortName, component]) => `${shortName} as ${scope.getName(component, shortName)}`
613
+ ).join(", ");
614
+ componentImports += `import { ${specifiers} } from "${namespace}";
600
615
  `;
616
+ }
617
+ break;
618
+ case "xml":
619
+ {
620
+ componentImports = `import { XmlNode } from "@webstudio-is/sdk-components-react";
621
+ `;
622
+ xmlPresentationComponents += Array.from(componentsSet).map(
623
+ ([shortName, component]) => scope.getName(component, shortName)
624
+ ).filter((scopedName) => scopedName !== "XmlNode").map(
625
+ (scopedName) => scopedName === "Body" ? `const ${scopedName} = (props: any) => props.children;` : `const ${scopedName} = () => null;`
626
+ ).join("\n");
627
+ }
628
+ break;
629
+ default: {
630
+ documentType;
631
+ }
632
+ }
601
633
  }
602
- const pageData = siteDataByPage[pageId];
603
634
  const pageFontAssets = fontAssetsByPage[pageId];
604
635
  const pageBackgroundImageAssets = backgroundImageAssetsByPage[pageId];
605
636
  const rootInstanceId = pageData.page.rootInstanceId;
@@ -639,82 +670,88 @@ var prebuild = async (options) => {
639
670
  const favIconAsset = assets.get(projectMeta?.faviconAssetId ?? "");
640
671
  const socialImageAsset = assets.get(pageMeta.socialImageAssetId ?? "");
641
672
  const pageExports = `/* eslint-disable */
642
- /* This is a auto generated file for building the project */
643
-
673
+ /* This is a auto generated file for building the project */
644
674
 
645
- import { Fragment, useState } from "react";
646
- import type { FontAsset, ImageAsset } from "@webstudio-is/sdk";
647
- import { useResource } from "@webstudio-is/react-sdk";
648
- ${componentImports}
649
675
 
650
- export const siteName = ${JSON.stringify(projectMeta?.siteName)};
676
+ import { Fragment, useState } from "react";
677
+ import type { FontAsset, ImageAsset } from "@webstudio-is/sdk";
678
+ import { useResource } from "@webstudio-is/react-sdk";
679
+ ${componentImports}
651
680
 
652
- export const favIconAsset: ImageAsset | undefined =
653
- ${JSON.stringify(favIconAsset)};
681
+ export const siteName = ${JSON.stringify(projectMeta?.siteName)};
654
682
 
655
- export const socialImageAsset: ImageAsset | undefined =
656
- ${JSON.stringify(socialImageAsset)};
683
+ export const favIconAsset: ImageAsset | undefined =
684
+ ${JSON.stringify(favIconAsset)};
657
685
 
658
- // Font assets on current page (can be preloaded)
659
- export const pageFontAssets: FontAsset[] =
660
- ${JSON.stringify(pageFontAssets)}
686
+ export const socialImageAsset: ImageAsset | undefined =
687
+ ${JSON.stringify(socialImageAsset)};
661
688
 
662
- export const pageBackgroundImageAssets: ImageAsset[] =
663
- ${JSON.stringify(pageBackgroundImageAssets)}
689
+ // Font assets on current page (can be preloaded)
690
+ export const pageFontAssets: FontAsset[] =
691
+ ${JSON.stringify(pageFontAssets)}
664
692
 
693
+ export const pageBackgroundImageAssets: ImageAsset[] =
694
+ ${JSON.stringify(pageBackgroundImageAssets)}
665
695
 
696
+ ${xmlPresentationComponents}
666
697
 
667
- ${pageComponent}
698
+ ${pageComponent}
668
699
 
669
- export { Page }
670
- `;
700
+ export { Page }
701
+ `;
671
702
  const serverExports = `/* eslint-disable */
672
- /* This is a auto generated file for building the project */
703
+ /* This is a auto generated file for building the project */
673
704
 
674
705
 
675
- import type { PageMeta } from "@webstudio-is/sdk";
676
- ${generateResourcesLoader({
706
+ import type { PageMeta } from "@webstudio-is/sdk";
707
+ ${generateResourcesLoader({
677
708
  scope,
678
709
  page: pageData.page,
679
710
  dataSources,
680
711
  resources
681
712
  })}
682
713
 
683
- ${generatePageMeta({
714
+ ${generatePageMeta({
684
715
  globalScope: scope,
685
716
  page: pageData.page,
686
717
  dataSources
687
718
  })}
688
719
 
689
- ${generateFormsProperties(props)}
720
+ ${generateFormsProperties(props)}
690
721
 
691
- ${generateRemixParams(pageData.page.path)}
722
+ ${generateRemixParams(pageData.page.path)}
692
723
 
693
- export const projectId = "${siteData.build.projectId}";
724
+ export const projectId = "${siteData.build.projectId}";
694
725
 
695
- export const contactEmail = ${JSON.stringify(contactEmail)};
726
+ export const contactEmail = ${JSON.stringify(contactEmail)};
696
727
 
697
- export const customCode = ${JSON.stringify(projectMeta?.code?.trim() ?? "")};
698
- `;
728
+ export const customCode = ${JSON.stringify(
729
+ projectMeta?.code?.trim() ?? ""
730
+ )};
731
+ `;
699
732
  const pagePath = getPagePath(pageData.page.id, siteData.build.pages);
700
733
  const remixRoute = generateRemixRoute(pagePath);
701
734
  const fileName = `${remixRoute}.tsx`;
702
- const routeFileContent = routeFileTemplate.replace(
735
+ const routeFileContent = (documentType === "html" ? routeFileTemplate : routeXmlFileTemplate).replace(
703
736
  /".*\/__generated__\/_index"/,
704
737
  `"../__generated__/${remixRoute}"`
705
738
  ).replace(
706
739
  /".*\/__generated__\/_index.server"/,
707
740
  `"../__generated__/${remixRoute}.server"`
708
741
  );
709
- await ensureFileInPath(join4(routesDir, fileName), routeFileContent);
710
- await ensureFileInPath(join4(generatedDir, fileName), pageExports);
711
- await ensureFileInPath(
742
+ await createFileIfNotExists(join4(routesDir, fileName), routeFileContent);
743
+ await createFileIfNotExists(join4(generatedDir, fileName), pageExports);
744
+ await createFileIfNotExists(
712
745
  join4(generatedDir, `${remixRoute}.server.tsx`),
713
746
  serverExports
714
747
  );
715
748
  }
716
- await writeFile4(
717
- join4(generatedDir, "[sitemap.xml].ts"),
749
+ await createFileIfNotExists(
750
+ join4(routesDir, "[sitemap.xml]._index.tsx"),
751
+ defaultSiteMapTemplate.replace(/".*\/__generated__\//, `"../__generated__/`)
752
+ );
753
+ await createFileIfNotExists(
754
+ join4(generatedDir, "$resources.sitemap.xml.ts"),
718
755
  `
719
756
  export const sitemap = ${JSON.stringify(
720
757
  getStaticSiteMapXml(siteData.build.pages, siteData.build.updatedAt),
@@ -731,11 +768,11 @@ export const customCode = ${JSON.stringify(projectMeta?.code?.trim() ?? "")};
731
768
  const redirectFileName = `${redirectPagePath}.ts`;
732
769
  const content = `import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
733
770
 
734
- export const loader = (arg: LoaderFunctionArgs) => {
735
- return redirect("${redirect.new}", ${redirect.status ?? 301});
736
- };
737
- `;
738
- await ensureFileInPath(join4(routesDir, redirectFileName), content);
771
+ export const loader = (arg: LoaderFunctionArgs) => {
772
+ return redirect("${redirect.new}", ${redirect.status ?? 301});
773
+ };
774
+ `;
775
+ await createFileIfNotExists(join4(routesDir, redirectFileName), content);
739
776
  }
740
777
  }
741
778
  spinner.text = "Downloading fonts and images";
@@ -820,7 +857,7 @@ var initFlow = async (options) => {
820
857
  if (folderName === void 0) {
821
858
  throw new Error("Folder name is required");
822
859
  }
823
- await ensureFolderExists(join5(cwd4(), folderName));
860
+ await createFolderIfNotExists(join5(cwd4(), folderName));
824
861
  chdir(join5(cwd4(), folderName));
825
862
  }
826
863
  const { projectLink } = await prompt({
@@ -912,7 +949,7 @@ import makeCLI from "yargs";
912
949
  // package.json
913
950
  var package_default = {
914
951
  name: "webstudio",
915
- version: "0.151.0",
952
+ version: "0.163.0",
916
953
  description: "Webstudio CLI",
917
954
  author: "Webstudio <github@webstudio.is>",
918
955
  homepage: "https://webstudio.is",
@@ -983,7 +1020,7 @@ var package_default = {
983
1020
  // src/cli.ts
984
1021
  var main = async () => {
985
1022
  try {
986
- await ensureFileInPath(GLOBAL_CONFIG_FILE, "{}");
1023
+ await createFileIfNotExists(GLOBAL_CONFIG_FILE, "{}");
987
1024
  const cmd = makeCLI(hideBin(argv)).strict().fail(function(msg, err, yargs) {
988
1025
  if (err) {
989
1026
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webstudio",
3
- "version": "0.151.0",
3
+ "version": "0.163.0",
4
4
  "description": "Webstudio CLI",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -28,13 +28,13 @@
28
28
  "title-case": "^4.1.0",
29
29
  "yargs": "^17.7.2",
30
30
  "zod": "^3.22.4",
31
- "@webstudio-is/http-client": "0.151.0",
32
- "@webstudio-is/react-sdk": "0.151.0",
33
- "@webstudio-is/image": "0.151.0",
34
- "@webstudio-is/sdk": "0.151.0",
35
- "@webstudio-is/sdk-components-react-radix": "0.151.0",
36
- "@webstudio-is/sdk-components-react-remix": "0.151.0",
37
- "@webstudio-is/sdk-components-react": "0.151.0"
31
+ "@webstudio-is/http-client": "0.163.0",
32
+ "@webstudio-is/react-sdk": "0.163.0",
33
+ "@webstudio-is/image": "0.163.0",
34
+ "@webstudio-is/sdk": "0.163.0",
35
+ "@webstudio-is/sdk-components-react-radix": "0.163.0",
36
+ "@webstudio-is/sdk-components-react": "0.163.0",
37
+ "@webstudio-is/sdk-components-react-remix": "0.163.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@netlify/remix-adapter": "^2.3.1",
@@ -56,7 +56,7 @@
56
56
  "typescript": "5.4.5",
57
57
  "vite": "^5.2.11",
58
58
  "wrangler": "^3.48.0",
59
- "@webstudio-is/form-handlers": "0.151.0",
59
+ "@webstudio-is/form-handlers": "0.163.0",
60
60
  "@webstudio-is/tsconfig": "1.0.7"
61
61
  },
62
62
  "scripts": {
@@ -2,7 +2,6 @@ import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
2
2
 
3
3
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
4
  // @ts-ignore - the server build file is generated by `remix vite:build`
5
- // eslint-disable-next-line import/no-unresolved
6
5
  import * as build from "../build/server";
7
6
 
8
7
  export const onRequest = createPagesFunctionHandler({ build });
@@ -1,5 +1,5 @@
1
1
  import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
2
- import { sitemap } from "../__generated__/[sitemap.xml]";
2
+ import { sitemap } from "../../../../__generated__/$resources.sitemap.xml";
3
3
 
4
4
  export const loader = (arg: LoaderFunctionArgs) => {
5
5
  const host =
@@ -11,7 +11,11 @@ import {
11
11
  } from "@remix-run/server-runtime";
12
12
  import { useLoaderData } from "@remix-run/react";
13
13
  import { ReactSdkContext } from "@webstudio-is/react-sdk";
14
- import { n8nHandler, getFormId } from "@webstudio-is/form-handlers";
14
+ import {
15
+ n8nHandler,
16
+ formIdFieldName,
17
+ formBotFieldName,
18
+ } from "@webstudio-is/form-handlers";
15
19
  import {
16
20
  Page,
17
21
  siteName,
@@ -240,66 +244,86 @@ const getMethod = (value: string | undefined) => {
240
244
  }
241
245
  };
242
246
 
243
- export const action = async ({ request, context }: ActionFunctionArgs) => {
244
- const formData = await request.formData();
247
+ export const action = async ({
248
+ request,
249
+ context,
250
+ }: ActionFunctionArgs): Promise<
251
+ { success: true } | { success: false; errors: string[] }
252
+ > => {
253
+ try {
254
+ const formData = await request.formData();
245
255
 
246
- const formId = getFormId(formData);
247
- if (formId === undefined) {
248
- // We're throwing rather than returning { success: false }
249
- // because this isn't supposed to happen normally: bug or malicious user
250
- throw json("Form not found", { status: 404 });
251
- }
256
+ const formId = formData.get(formIdFieldName);
252
257
 
253
- const formProperties = formsProperties.get(formId);
258
+ if (formId == null || typeof formId !== "string") {
259
+ throw new Error("No form id in FormData");
260
+ }
254
261
 
255
- // form properties are not defined when defaults are used
256
- const { action, method } = formProperties ?? {};
262
+ const formBotValue = formData.get(formBotFieldName);
257
263
 
258
- if (contactEmail === undefined) {
259
- return { success: false };
260
- }
264
+ if (formBotValue == null || typeof formBotValue !== "string") {
265
+ throw new Error("Form bot field not found");
266
+ }
261
267
 
262
- // wrapped in try/catch just in cases new URL() throws
263
- // (should not happen)
264
- let pageUrl: URL;
265
- try {
266
- pageUrl = new URL(request.url);
268
+ const submitTime = parseInt(formBotValue, 16);
269
+ // Assumes that the difference between the server time and the form submission time,
270
+ // including any client-server time drift, is within a 5-minute range.
271
+ // Note: submitTime might be NaN because formBotValue can be any string used for logging purposes.
272
+ // Example: `formBotValue: jsdom`, or `formBotValue: headless-env`
273
+ if (
274
+ Number.isNaN(submitTime) ||
275
+ Math.abs(Date.now() - submitTime) > 1000 * 60 * 5
276
+ ) {
277
+ throw new Error(`Form bot value invalid ${formBotValue}`);
278
+ }
279
+
280
+ const formProperties = formsProperties.get(formId);
281
+
282
+ // form properties are not defined when defaults are used
283
+ const { action, method } = formProperties ?? {};
284
+
285
+ if (contactEmail === undefined) {
286
+ throw new Error("Contact email not found");
287
+ }
288
+
289
+ const pageUrl = new URL(request.url);
267
290
  pageUrl.host = getRequestHost(request);
268
- } catch {
269
- return { success: false };
270
- }
271
291
 
272
- if (action !== undefined) {
273
- try {
274
- // Test that action is full URL
275
- new URL(action);
276
- } catch {
277
- return json(
278
- {
279
- success: false,
280
- error: "Invalid action URL, must be valid http/https protocol",
281
- },
282
- { status: 200 }
283
- );
292
+ if (action !== undefined) {
293
+ try {
294
+ // Test that action is full URL
295
+ new URL(action);
296
+ } catch {
297
+ throw new Error(
298
+ "Invalid action URL, must be valid http/https protocol"
299
+ );
300
+ }
284
301
  }
285
- }
286
302
 
287
- const formInfo = {
288
- formData,
289
- projectId,
290
- action: action ?? null,
291
- method: getMethod(method),
292
- pageUrl: pageUrl.toString(),
293
- toEmail: contactEmail,
294
- fromEmail: pageUrl.hostname + "@webstudio.email",
295
- } as const;
296
-
297
- const result = await n8nHandler({
298
- formInfo,
299
- hookUrl: context.N8N_FORM_EMAIL_HOOK,
300
- });
303
+ const formInfo = {
304
+ formData,
305
+ projectId,
306
+ action: action ?? null,
307
+ method: getMethod(method),
308
+ pageUrl: pageUrl.toString(),
309
+ toEmail: contactEmail,
310
+ fromEmail: pageUrl.hostname + "@webstudio.email",
311
+ } as const;
312
+
313
+ const result = await n8nHandler({
314
+ formInfo,
315
+ hookUrl: context.N8N_FORM_EMAIL_HOOK,
316
+ });
301
317
 
302
- return result;
318
+ return result;
319
+ } catch (error) {
320
+ console.error(error);
321
+
322
+ return {
323
+ success: false,
324
+ errors: [error instanceof Error ? error.message : "Unknown error"],
325
+ };
326
+ }
303
327
  };
304
328
 
305
329
  const Outlet = () => {
@@ -0,0 +1,61 @@
1
+ /* eslint-disable camelcase */
2
+ import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
3
+ import { ReactSdkContext } from "@webstudio-is/react-sdk";
4
+ import { Page } from "../../../../__generated__/_index";
5
+ import {
6
+ loadResources,
7
+ getPageMeta,
8
+ getRemixParams,
9
+ } from "../../../../__generated__/_index.server";
10
+
11
+ import { assetBaseUrl, imageBaseUrl, imageLoader } from "../constants.mjs";
12
+ import { renderToString } from "react-dom/server";
13
+
14
+ export const loader = async (arg: LoaderFunctionArgs) => {
15
+ const url = new URL(arg.request.url);
16
+ const host =
17
+ arg.request.headers.get("x-forwarded-host") ||
18
+ arg.request.headers.get("host") ||
19
+ "";
20
+ url.host = host;
21
+ url.protocol = "https";
22
+
23
+ const params = getRemixParams(arg.params);
24
+
25
+ const system = {
26
+ params,
27
+ search: Object.fromEntries(url.searchParams),
28
+ origin: url.origin,
29
+ };
30
+
31
+ const resources = await loadResources({ system });
32
+ const pageMeta = getPageMeta({ system, resources });
33
+
34
+ if (pageMeta.redirect) {
35
+ const status =
36
+ pageMeta.status === 301 || pageMeta.status === 302
37
+ ? pageMeta.status
38
+ : 302;
39
+ return redirect(pageMeta.redirect, status);
40
+ }
41
+
42
+ // typecheck
43
+ arg.context.EXCLUDE_FROM_SEARCH satisfies boolean;
44
+
45
+ const text = renderToString(
46
+ <ReactSdkContext.Provider
47
+ value={{
48
+ imageLoader,
49
+ assetBaseUrl,
50
+ imageBaseUrl,
51
+ resources,
52
+ }}
53
+ >
54
+ <Page system={system} />
55
+ </ReactSdkContext.Provider>
56
+ );
57
+
58
+ return new Response(`<?xml version="1.0" encoding="UTF-8"?>\n${text}`, {
59
+ headers: { "Content-Type": "application/xml" },
60
+ });
61
+ };
@@ -11,13 +11,13 @@
11
11
  "@remix-run/node": "2.9.1",
12
12
  "@remix-run/react": "2.9.1",
13
13
  "@remix-run/server-runtime": "2.9.1",
14
- "@webstudio-is/react-sdk": "0.151.0",
15
- "@webstudio-is/sdk-components-react-radix": "0.151.0",
16
- "@webstudio-is/sdk-components-react-remix": "0.151.0",
17
- "@webstudio-is/sdk-components-react": "0.151.0",
18
- "@webstudio-is/form-handlers": "0.151.0",
19
- "@webstudio-is/image": "0.151.0",
20
- "@webstudio-is/sdk": "0.151.0",
14
+ "@webstudio-is/react-sdk": "0.163.0",
15
+ "@webstudio-is/sdk-components-react-radix": "0.163.0",
16
+ "@webstudio-is/sdk-components-react-remix": "0.163.0",
17
+ "@webstudio-is/sdk-components-react": "0.163.0",
18
+ "@webstudio-is/form-handlers": "0.163.0",
19
+ "@webstudio-is/image": "0.163.0",
20
+ "@webstudio-is/sdk": "0.163.0",
21
21
  "isbot": "^3.6.8",
22
22
  "react": "18.3.0-canary-14898b6a9-20240318",
23
23
  "react-dom": "18.3.0-canary-14898b6a9-20240318"
@@ -1,9 +0,0 @@
1
- /**
2
- * The only intent of this file is to support typings inside ../routes/[sitemap.xml].tsx for easier development.
3
- **/
4
- export const sitemap = [
5
- {
6
- path: "",
7
- lastModified: "2021-10-13T12:00:00.000Z",
8
- },
9
- ];