
# Media

`media` opens images, video and audio files in a tab of their own, using `<img>`, `<video>` and
`<audio>` to show them instead of the text editor.

```ts
import { media } from "codelet/extensions/media";
import { FileSystem, Workbench } from "codelet/workbench";

const workbench = new Workbench({
  parent: document.getElementById("app")!,
  fs: new FileSystem({ "/logo.svg": "<svg>...</svg>" }),
  extensions: [media],
});
```

`media` takes no options.

## Try it

Click `notes.txt` for an ordinary text tab, then `logo.svg` — it opens in a media tab instead,
rendered with `<img>`.

::codelet-playground{mode="workbench" extensions="media" active="logo.svg" height="420"}

```txt [notes.txt]
This one opens as text.
logo.svg opens in a media tab instead.
```

```svg [logo.svg]
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="#6366f1" />
</svg>
```

::

## File types

`media` registers a custom editor for each extension below, grouped into three kinds. Opening a
file with one of these extensions opens it in the matching tab instead of the text editor.

| Kind  | Extensions                                                                |
| ----- | ------------------------------------------------------------------------- |
| Image | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.avif`, `.bmp`, `.ico`, `.svg` |
| Video | `.mp4`, `.webm`, `.ogv`, `.mov`                                           |
| Audio | `.mp3`, `.wav`, `.ogg`, `.oga`, `.flac`, `.m4a`, `.aac`                   |

## How a file gets there

A `FileSystem` holds every file as text, so the bytes of a `.png` are never in the tree as such.
Dropping an image, video or audio file from the desktop onto the explorer writes it in as a
`data:` URI instead — codelet does that conversion for you, and `media` is what reads the result
back and shows it. The [remote extension](/extensions/remote) does the same for a binary file
mirrored from a real filesystem, as a URL pointing back at the server rather than a `data:` URI.

::note
A drop that isn't valid UTF-8 text is capped at 16 MiB — base64 runs about a third longer than
the bytes it encodes, and stays in memory for the life of the page. See
[Binary files](/guide/files#binary-files) for the full rule, including what happens to a file no
extension claims.
::

## What a file's contents must be

`media` reads a file's text and treats it as one of:

- A `data:` or `blob:` URI, or an `http(s)://` URL, used as-is.
- A page-relative path (starting with `/`, `./` or `../`), resolved against the page's own URL.
- Base64 with no `data:` header, wrapped into a `data:` URI using the MIME type for the file's
  extension.
- For `.svg` files specifically, the raw SVG markup itself — a workbench does hold an SVG's
  actual contents as text.

If none of these match, the tab shows a message instead of a broken preview.

## Getting back to the text

A media tab replaces the text editor for these files, not the file itself — the text is still
there underneath. `View: Reopen Editor With…`, from the command palette, opens the same file as
plain text.

:read-more{to="/extensions"}
