@witchcraft/editor
    Preparing search index...

    Type Alias IFileInsertHandler<TFile, TAttrs, T, TKey>

    Helps handle the saving/uploading of files. Provides a way to adjust the insert position and takes care of keeping track of uploading/saving vs uploaded/saved files.

    See FileInsertHandler for a partial implementation you can customize to create the interface.

    type IFileInsertHandler<
        TFile extends File,
        TAttrs extends Record<string, unknown> = Record<string, unknown>,
        T extends
            { attrs: TAttrs; file: TFile; previewSrc?: string } = {
            attrs: TAttrs;
            file: TFile;
            previewSrc?: string;
        },
        TKey = string,
    > = {
        filterFile: (file: File) => TFile | undefined;
        generateId: () => string;
        generatePreview: (
            file: TFile,
            id: TKey,
            editor: Editor,
        ) => Promise<string | undefined>;
        insertAsyncPlaceholder: (
            file: TFile,
            editor: Editor,
            insertPos: number,
            originalPos?: number,
        ) => TKey | undefined;
        insertFiles: (files: File[], editor: Editor, pos?: number) => Promise<void>;
        insertPosition: (
            file: TFile,
            editor: Editor,
            pos?: number,
        ) => number | undefined;
        onSaveError: (
            file: TFile,
            editor: Editor,
            pos: number | undefined,
            error: Error,
            loadingKey: TKey,
        ) => void;
        replacePlaceholder: (
            editor: Editor,
            pos: number,
            attrs: Record<string, unknown>,
            loadingKey: TKey,
        ) => void;
        saveFile: (
            file: TFile,
            id: TKey,
            editor: Editor,
            previewSrc: string | undefined,
        ) => Promise<T | undefined>;
    }

    Type Parameters

    • TFile extends File
    • TAttrs extends Record<string, unknown> = Record<string, unknown>
    • T extends { attrs: TAttrs; file: TFile; previewSrc?: string } = { attrs: TAttrs; file: TFile; previewSrc?: string }
    • TKey = string

    Implemented by

    Index
    filterFile: (file: File) => TFile | undefined

    Return the file (or whatever type you'd like) to allow the extension to handle it.

    If the function doesn't return anything, the file will be ignored. No placeholder will be created. The event will still be preventDefaulted.

    This can be used to filter out mime types you can't handle with a library like mime. Mime type filtering is not handled by the extension since it can be complicated.

    generateId: () => string

    Should generate a unique id for placeholders and batches.

    generatePreview: (
        file: TFile,
        id: TKey,
        editor: Editor,
    ) => Promise<string | undefined>

    Generate a preview for the placeholder widget before saving starts.

    If a preview is returned, it should be used to update the placeholder widget immediately, allowing the user to see a preview image as the file saves. It should also be passed to saveFile.

    insertAsyncPlaceholder: (
        file: TFile,
        editor: Editor,
        insertPos: number,
        originalPos?: number,
    ) => TKey | undefined

    Given a file, should add a placeholder decoration with the id set to a unique key. It should return this key if it added the placeholder.

    Using the file name is not a good idea as it's not guaranteed to be unique if the user inserts the same item twice.

    insertFiles: (files: File[], editor: Editor, pos?: number) => Promise<void>

    Should handle the entire file insertion lifecycle: filter, insert placeholders, save files concurrently, replace placeholders.

    See the default implementation as this requires special care if you allow dropping multiple files at once.

    Because widgets are 0 width and we can have multiple widgets in the same position, we cannot use a widget's position to replace nodes if you want to preserve order.

    For example, suppose we drop 10 files at once producing:

    some text [...widgets at position 10]
    ^10

    Now the last file loads first and we replace it:

    some text [file 10][...widgets at position 11]
    

    Next file will not be inserted at the correct position now ever and the widget order does not help us.

    The default implementation handles this by tracking the ids of the files it inserted, their positions for each insert "batch" internally, and searching outwards from the placeholder position to find the right insertion point.

    insertPosition: (
        file: TFile,
        editor: Editor,
        pos?: number,
    ) => number | undefined

    Where to insert the placeholder.

    If no position is returned, no node should be inserted.

    onSaveError: (
        file: TFile,
        editor: Editor,
        pos: number | undefined,
        error: Error,
        loadingKey: TKey,
    ) => void

    This can be used to remove the placeholder on errors.

    replacePlaceholder: (
        editor: Editor,
        pos: number,
        attrs: Record<string, unknown>,
        loadingKey: TKey,
    ) => void

    After saving/uploading the file, if it's successful, this is passed the node attributes returned by saveFile and the position of the placeholder.

    Replace the placeholder with the final node (e.g. an image) and remove the decoration.

    Note this can require special logic if you allow dropping multiple files at once. See IFileInsertHandler.insertFiles

    saveFile: (
        file: TFile,
        id: TKey,
        editor: Editor,
        previewSrc: string | undefined,
    ) => Promise<T | undefined>

    Should load/save/upload the file and return the node attributes.

    The attrs object returned should be spread onto the file node. The previewSrc is the result of generatePreview.

    The id and editor are provided in case you're uploading the file or doing some other heavy operation and want to update the placeholder as soon as you can upload the file.