Skip to content
File

Blob: src/sites/island-hosts/island-host.tsx

typescript31 lines
1import type { ReactNode } from "react";
2import type { IslandName, IslandPropsByName } from "@/shared/sites/island-schemas";
3 
4export interface SiteIslandHostProps<K extends IslandName> {
5 name: K;
6 props: IslandPropsByName[K];
7 children: ReactNode;
8}
9 
10export function SiteIslandHost<K extends IslandName>({ name, props, children }: SiteIslandHostProps<K>) {
11 return (
12 <div data-island={name}>
13 <template data-island-props="" dangerouslySetInnerHTML={{ __html: serializeProps(props) }} />
14 <div data-island-root="">{children}</div>
15 </div>
16 );
17}
18 
19const ESCAPE_PATTERN = /[&<>\u2028\u2029]/g;
20const ESCAPES: Record<string, string> = {
21 "&": "\\u0026",
22 "<": "\\u003c",
23 ">": "\\u003e",
24 "\u2028": "\\u2028",
25 "\u2029": "\\u2029",
26};
27 
28export function serializeProps(value: unknown): string {
29 return JSON.stringify(value).replace(ESCAPE_PATTERN, (char) => ESCAPES[char] ?? char);
30}