TypeCellOS / BlockNote

A React Rich Text Editor that's block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.
https://www.blocknotejs.org/
Mozilla Public License 2.0
5.89k stars 381 forks source link

Update `resolveFileUrl` to take more context params #886

Closed softmarshmallow closed 1 day ago

softmarshmallow commented 4 days ago

The resolveFileUrl is lacking params since it only takes url as input. The purpose of this to make a custom logic for resolving file or to add a security layer to files, yet BlockNote also provides "Embed URL" feature, wich this is where it conflicts.

In my case, the url will be a relative path to a certain bucket (not a url), if it were a url, I would have just chekced the host name to check if the image is from a service origin or a external web image url.

To handle this, I need to work with my own image url in a dirty way, e.g. JSON.stringfy({path: "...", type: "image-from-my-service"}) from uploadFile and if (JSON.parse(url).type === "image-from-my-service") { myImageResolver() } else { return url }

It would be nice to have a full-blcok-context in resolveFileUrl or just pass a return value from uploadFile, Record<string, any>


  const editor = useCreateBlockNote({
    uploadFile: uploader
      ? async (file) => {
          const { path } = await uploader(file);
          return path!;
        }
      : undefined,
    resolveFileUrl: resolver
      ? async (url) => {
          // OK, but the embeded url should not be handled here?? - how do I do that in a clean way?
          const resolved = await resolver?.({
            path: url,
          });
          return resolved!.publicUrl;
        }
      : undefined,
  });

Current solution - Not the best way to do things.

    uploadFile: uploader
      ? async (file) => {
          const { path } = await uploader(file);
          // https://github.com/TypeCellOS/BlockNote/issues/886
          return "grida-tmp://" + path!;
        }
      : undefined,
    resolveFileUrl: resolver
      ? async (url) => {
          if (url.startsWith("grida-tmp://")) {
            const resolved = await resolver?.({
              path: url,
            });
            return resolved!.publicUrl;
          } else {
            return url;
          }
        }
      : undefined,

Reference:

https://github.com/TypeCellOS/BlockNote/issues/885

YousefED commented 1 day ago

If I get it correctly, you'd prefer to have other props for file-related blocks where you can store "source" metadata. Currently, this is only done in the URL.

I agree this would be nice. We considered it, but it's a bit cumbersome to do this in a generic way. For now, we decided to stick on custom URLs so we keep the API simple, but it's still possible to do the more advanced use-case that you require (indeed, with your resolveFileUrl implementation)