---
title: Utils
---

# Utils

Helpers for shell post-processing and fragment ids. Imported from `@vincle/flow/utils`.

## composeShell

Chains `transformShell` functions left to right, each receiving the previous
one's output and the active `ShellContext`. Falsy entries are skipped, so an
adapter's own (possibly `undefined`) transform can be passed as is.

```tsx
import { NativeAdapter, createAdapter } from "@vincle/flow/adapters";
import { composeShell, injectIntoHead } from "@vincle/flow/utils";

const metadata = () => (html: string) => injectIntoHead(html, "<title>Home</title>");

const MyAdapter = createAdapter({
  ...NativeAdapter,
  transformShell: composeShell(NativeAdapter.transformShell, metadata()),
});
```

**Signature:**

```tsx
function composeShell(
  ...transforms: Array<((shell: string, ctx: ShellContext) => string) | undefined | null | false>
): (shell: string, ctx: ShellContext) => string;
```

## injectIntoHead

Injects `content` immediately before `</head>`, opening a `<head>` if the
shell has none.

```tsx
import { injectIntoHead } from "@vincle/flow/utils";

const shell = "<html><body>…</body></html>";
const patched = injectIntoHead(shell, `<link rel="stylesheet" href="/app.css">`);
```

```html
<html>
  <head>
    <link rel="stylesheet" href="/app.css" />
  </head>
  <body>
    …
  </body>
</html>
```

**Signature:**

```tsx
function injectIntoHead(html: string, content: string): string;
```

## assertFragmentId

Throws unless `id` is letters, digits, hyphens and underscores, starting with a
letter. `Defer` calls it when registering; call it yourself on ids
from untrusted input.

```tsx
import { assertFragmentId } from "@vincle/flow/utils";

assertFragmentId(userInput, "Slot name"); // throws if invalid
```

**Signature:**

```tsx
function assertFragmentId(id: string, label: string): void;
```

`label` names the caller in the error message.
