Skip to content

@itsy/html/frame ​

ts
import { frame, head, element } from '@itsy/html/frame';
import type { FrameOptions, HeadEntry, FramePart } from '@itsy/html/frame';

frame ​

ts
frame(options: FrameOptions): Html

Writes a full HTML frame

optiontypenotes
langstringRequired. <html lang>. Escaped.
titlestringRequired. Escaped.
descriptionstringEscaped, placed right after the title. A head entry with the same name replaces it.
dir'ltr' | 'rtl' | 'auto'<html dir>.
headFramePart | Iterable<FramePart>After charset, viewport, title and description.
headerRenderableRight after <body>.
contentRenderableInside <main id="maincontent" tabindex="-1">.
mainbooleanfalse writes content with no <main> wrapper. Default true.
footerRenderableAfter <main>, before the scripts.
scriptsFramePart | Iterable<FramePart>Right before </body>.
noncestringAdded to every script and style entry that has none.
attrs{ html?, body?, main? }Extra attributes on the three elements the frame writes. main merges over the default id and tabindex.
ts
head(parts: FramePart | Iterable<FramePart>, options?: { nonce?: string }): Html

The merged head elements, with no <head> wrapper and none of the rest of the document. For a layout that writes <html> itself.

ts
html`<head>${head(parts, { nonce })}</head>`;

The merge is the same one frame() does, so a shared list of head assets behaves identically here.

element ​

ts
element(entry: HeadEntry, nonce?: string): Html

One entry, rendered.

ts
element({ tag: 'link', attrs: { rel: 'icon', href: '/icon.svg' } });
html
<link rel="icon" href="/icon.svg">

Throws code 17 for a tag name that is not legal, and code 18 for a body on a void element.

HeadEntry ​

ts
interface HeadEntry {
  tag: string;
  attrs?: Record<string, AttrValue>;
  body?: Renderable;
  key?: string;
}
  • attrs goes through attrs(), URL guard included — always the default guard, never one from createHtml.
  • body is escaped if it is text, called if it is a function. A <script> or <style> body must be Html, from raw(), or it is code 6.
  • key overrides how the entry is identified for merging.

FramePart is HeadEntry | Html. Ready-made Html is passed through untouched — not merged, not deduplicated, and not given a nonce.

How entries merge ​

Of two entries with the same identity, the later one wins and takes the earlier one's position.

tagidentity
title, basethe tag; only one of each
meta with charsetcharset; only one
metaits name, else property, else http-equiv
link with an icon relrel + type + sizes
link with rel="canonical" or "manifest"the rel; only one of each
linkrel + href
script with srcthe src
anything elseno identity; kept as many times as given

MIT licensed.