File
The file plugin adds Notion's file block, an attachment uploaded through your upload function or linked, shown with its name and size.
createFilePlugin() adds Notion’s file block: an empty panel (your empty snippet, createMediaEmptyPlugin({ empty })) until the block has a file, then the file’s name and size, linking to it, with an editable caption. Files are uploaded through the upload function you provide, or linked. It is not a default plugin: list it.
<script lang="ts">
import { Edytor, createFilePlugin, createUploadsPlugin } from 'edytor';
// Optional: the view's uploader (an Upload button, and pasted or dropped files).
const uploads = createUploadsPlugin({
upload: async (file) => {
const body = new FormData();
body.append('file', file);
const response = await fetch('/api/uploads', { method: 'POST', body });
return (await response.json()).url;
}
});
</script>
<Edytor plugins={[uploads, createFilePlugin()]} />
A slash menu then lists “File” under Media. Without the uploads plugin (createUploadsPlugin({ upload })), files are linked only.
Options
createFilePlugin(options) takes a FilePluginOptions; the empty block is drawn by the view’s media empty plugin, its Upload by the uploads plugin.
row?Snippet<[FileRowPayload]>
The row of a file block with a source, replacing Notion's (a paperclip, the name and the size). The first file plugin listed in a view gives it.
Snippet<[FileRowPayload]>row receives a FileRowPayload: block (undefined in a suggestion’s preview), src, name, size (bytes, when it was uploaded), sizeLabel (that size in the view’s words, '' without one) and link, the attachment of your a, as a menu’s row takes its own: target="_blank", rel="noopener noreferrer nofollow", draggable="false" and download (the name). Render its href={file.src} yourself, so a server-rendered readonly view links too. It is drawn inside the block’s void wrapper ([data-edytor-file]), above the caption.
<script lang="ts">
import { Edytor, createFilePlugin, type FileRowPayload } from 'edytor';
const files = createFilePlugin({ row });
</script>
{#snippet row(file: FileRowPayload)}
<a class="attachment" href={file.src} {@attach file.link}>
<span>{file.name}</span>
{#if file.sizeLabel}<small>{file.sizeLabel}</small>{/if}
</a>
{/snippet}
<Edytor plugins={[files]} />
The kind
| Kind | Element | Data | Preset |
|---|---|---|---|
file |
figure |
{ src: string, name: string, size?: number } |
File (📎, group Media, keywords attachment, upload, pdf) |
An upload stores the URL upload answers with the picked file’s name and size (bytes), as one data write, only when the block is still there, a file block and without a source (a source a collaborator set while the upload ran stays); a link stores its URL with the name read from its last path segment. A source is accepted only when it is an http:/https: URL with a host or a blob: URL of one (safeMediaSrc), never data:: a file stored inline would be sent in every update. The rendered link has target="_blank", rel="noopener noreferrer nofollow" and download set to the name.
The block is void like the image, and its only text is the caption. The command id is block.file. Its role is in defaultSemantics. In a readonly view the empty block is a passive placeholder, so a viewer never runs upload. With upload, pasted and dropped files no other kind takes (a PDF, an archive; an image goes to the image block, a video or audio file to theirs when those kinds upload) become file blocks, shown uploading with a progress bar, one undo step for the paste; see Pasted and dropped files.
Clipboard
- Copying exports
<figure data-edytor-file><a href="…">name</a><figcaption>caption</figcaption></figure>; the plain text is the URL, then the caption. - Pasting that HTML back imports a file block.
Styling
| Selector | Matches |
|---|---|
[data-edytor-type='file'] |
The figure |
[data-edytor-file] |
The link’s wrapper |
[data-edytor-file-name] |
The name |
[data-edytor-file-size] |
The size (5 B, 1.2 MB) |
The row’s look (its shade, the hover, the muted size) is the Notion theme’s. The empty state uses the shared media selectors (see Embed).