[]previous and next page

Same output on the server

The server renderer applies the same rules and adds protections for untrusted values.

For agentsUpdated

The server renderer applies the same rules and adds protections for untrusted values. Class values are clsx-resolved, style names are validated, and a style value that could end its own declaration is dropped:

src/server-style.tsxtsx
import { renderToString } from "@shadow-js/web/server";

export function Box(props: { hostile: string }) {
  return (
    <div
      class={["a", false, { b: false, c: true }]}
      style={{ color: "red", "--gap": "4px", marginTop: 2, background: props.hostile }}
    />
  );
}

console.log(renderToString(() => <Box hostile="red; position: fixed" />).replace(/ data-hk="[^"]*"/, ""));
console.log(renderToString(() => <div style={{ color: "red", width: "1px}body{x:y" }} />).replace(/ data-hk="[^"]*"/, ""));
Expected output
<div class=

The first call shows the camelCase-to-kebab conversion, custom properties and a number given a pixel unit; the value red; position: fixed is not in the output because it contains a ; outside quotes and parentheses. The second drops } for the same reason. An invalid property name throws a TypeError (INVALID_STYLE_PROPERTY). On the client a value is written through CSSStyleDeclaration.setProperty, which cannot add a second declaration.