github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/lib/remark-plugins/imageUriReplacer.ts (about)

     1  import { visit } from "unist-util-visit";
     2  import type { Node } from "unist";
     3  import {objects} from "../api";
     4  
     5  type ImageUriReplacerOptions = {
     6    repo: string;
     7    ref: string;
     8    path: string;
     9    presign: boolean;
    10  };
    11  
    12  const ABSOLUTE_URL_REGEX = /^(https?):\/\/.*/;
    13  const qs = (queryParts: { [key: string]: string }) => {
    14    const parts = Object.keys(queryParts).map((key) => [key, queryParts[key]]);
    15    return new URLSearchParams(parts).toString();
    16  };
    17  export const getImageUrl = async (
    18    repo: string,
    19    ref: string,
    20    path: string,
    21    presign: boolean,
    22  ): Promise<string> => {
    23    if (presign) {
    24      try {
    25        const obj = await objects.getStat(repo, ref, path, true);
    26        return obj.physical_address;
    27      } catch(e) {
    28        console.error("failed to fetch presigned URL", e);
    29        return ""
    30      }
    31    }
    32  
    33    const query = qs({ path });
    34    return `/api/v1/repositories/${encodeURIComponent(
    35      repo
    36    )}/refs/${encodeURIComponent(ref)}/objects?${query}`;
    37  };
    38  
    39  const imageUriReplacer =
    40    (options: ImageUriReplacerOptions) => async (tree: Node) => {
    41      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    42      const promises: any[] = [];
    43      visit(tree, "image", visitor);
    44      await Promise.all(promises);
    45  
    46      function visitor(node: Node & { url: string }) {
    47        if (node.url.startsWith("lakefs://")) {
    48          const [repo, ref, ...imgPath] = node.url.split("/").slice(2);
    49          const p = getImageUrl(repo, ref, imgPath.join("/"), options.presign).then((url) => node.url = url);
    50          promises.push(p);
    51        } else if (!node.url.match(ABSOLUTE_URL_REGEX)) {
    52          // If the image is not an absolute URL, we assume it's a relative path
    53          // relative to repo and ref
    54          if (node.url.startsWith("/")) {
    55              node.url = node.url.slice(1);
    56          }
    57          // relative to MD file location
    58          if (node.url.startsWith("./")) {
    59            node.url = `${options.path.split("/").slice(0, -1)}/${node.url.slice(
    60              2
    61            )}`;
    62          }
    63          const p = getImageUrl(options.repo, options.ref, node.url, options.presign).then((url) => node.url = url);
    64          promises.push(p);
    65        }
    66      }
    67    };
    68  
    69  export default imageUriReplacer;