Skip to content

Commit

Permalink
begin work for assets download on a
Browse files Browse the repository at this point in the history
  • Loading branch information
chdeskur committed Jan 24, 2025
1 parent 7089a18 commit 37aaf02
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 17 deletions.
42 changes: 39 additions & 3 deletions packages/fern-docs/ui/src/components/FernLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,33 @@ import {
ReactElement,
forwardRef,
useEffect,
useMemo,
useState,
type ComponentProps,
} from "react";
import { format, parse, resolve, type UrlObject } from "url";
import { useMemoOne } from "use-memo-one";
import { SLUG_ATOM, useDomain } from "../atoms";
import { FILES_ATOM, SLUG_ATOM, useDomain } from "../atoms";
import { selectHref } from "../hooks/useHref";
import { getFernEmbedSrc } from "../mdx/common/util";

interface FernLinkProps extends ComponentProps<typeof Link> {
showExternalLinkIcon?: boolean;
isDownload?: boolean;
}

export const FernLink = forwardRef<HTMLAnchorElement, FernLinkProps>(
({ showExternalLinkIcon = false, ...props }, ref): ReactElement => {
(
{ showExternalLinkIcon = false, isDownload = false, ...props },
ref
): ReactElement => {
const url = toUrlObject(props.href);
const isExternalUrl = checkIsExternalUrl(url);

// if the url is relative, we will need to invoke useRouter to resolve the relative url
// since useRouter injects the router context, it will cause a re-render any time the route changes.
// to avoid unnecessary re-renders, we will isolate the useRouter call to a separate component.
if (!isExternalUrl && checkIsRelativeUrl(url)) {
if (!isExternalUrl && !isDownload && checkIsRelativeUrl(url)) {
return <FernRelativeLink ref={ref} {...props} />;
}

Expand All @@ -52,6 +58,10 @@ export const FernLink = forwardRef<HTMLAnchorElement, FernLinkProps>(
);
}

if (isDownload) {
return <FernEmbedLink ref={ref} url={url} {...props} />;
}

return <Link ref={ref} {...props} />;
}
);
Expand Down Expand Up @@ -124,6 +134,32 @@ const FernExternalLink = forwardRef<HTMLAnchorElement, FernExternalLinkProps>(

FernExternalLink.displayName = "FernExternalLink";

interface FernEmbedLinkProps extends Omit<ComponentProps<"a">, "href"> {
url: UrlObject;
}

const FernEmbedLink = forwardRef<HTMLAnchorElement, FernEmbedLinkProps>(
({ url, ...props }, ref) => {
const files = useAtomValue(FILES_ATOM);

console.log("found embed link", url);

const fernEmbedSrc = useMemo(
() => getFernEmbedSrc(formatUrlString(url), files),
[files, url]
);
const urlString = checkIsExternalUrl(url)
? formatUrlString(url)
: fernEmbedSrc?.url.toString();

console.log("urlString", urlString);

return <a ref={ref} {...props} href={urlString} />;
}
);

FernEmbedLink.displayName = "FernEmbedLink";

const LinkWith404Fallback = forwardRef<HTMLAnchorElement, LinkProps>(
(props, ref) => {
return <Link ref={ref} {...props} />;
Expand Down
19 changes: 19 additions & 0 deletions packages/fern-docs/ui/src/mdx/common/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DocsV1Read, FdrAPI } from "@fern-api/fdr-sdk";

/**
* The interface that the user-provided `CodeBlocks` children should adhere to.
*/
Expand All @@ -12,6 +14,23 @@ export type ExpectedCodeBlockChildren = {
};
};

export const getFernEmbedSrc = (
src: string | null | undefined,
files: Record<string, DocsV1Read.File_>
): DocsV1Read.File_ | undefined => {
if (src == null) {
return undefined;
}

// if src starts with `file:`, assume it's a referenced file; fallback to src if not found
if (src.startsWith("file:")) {
const fileId = FdrAPI.FileId(src.slice(5));
return files[fileId] ?? { type: "url", url: FdrAPI.Url(src) };
}

return { type: "url", url: FdrAPI.Url(src) };
};

// export function stringHasMarkdown(s: string): boolean {
// s = s.trim();

Expand Down
16 changes: 2 additions & 14 deletions packages/fern-docs/ui/src/mdx/components/html/embed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,15 @@ import { ComponentProps } from "react";

import { FC } from "react";

import { DocsV1Read, FdrAPI } from "@fern-api/fdr-sdk";
import { useAtomValue } from "jotai";
import { useMemo } from "react";
import { FILES_ATOM } from "../../../atoms/files";
import { getFernEmbedSrc } from "../../common/util";

export const Embed: FC<ComponentProps<"embed">> = ({ src, ...rest }) => {
const files = useAtomValue(FILES_ATOM);

const fernEmbedSrc = useMemo((): DocsV1Read.File_ | undefined => {
if (src == null) {
return undefined;
}

// if src starts with `file:`, assume it's a referenced file; fallback to src if not found
if (src.startsWith("file:")) {
const fileId = FdrAPI.FileId(src.slice(5));
return files[fileId] ?? { type: "url", url: FdrAPI.Url(src) };
}

return { type: "url", url: FdrAPI.Url(src) };
}, [files, src]);
const fernEmbedSrc = useMemo(() => getFernEmbedSrc(src, files), [files, src]);

return (
<embed
Expand Down
4 changes: 4 additions & 0 deletions packages/fern-docs/ui/src/mdx/components/html/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,17 @@ export const A: FC<AnchorHTMLAttributes<HTMLAnchorElement>> = ({
const hideExternalLinkIcon =
isValidElement(children) &&
(children.type === "img" || isImageElement(children));
const isDownload = rest.download != null;

console.log("isDownload: ", isDownload);

return (
<FernLink
className={cnCombined}
href={href ?? {}}
{...rest}
showExternalLinkIcon={!hideExternalLinkIcon}
isDownload={isDownload}
>
<NoZoom>{children}</NoZoom>
</FernLink>
Expand Down
2 changes: 2 additions & 0 deletions packages/fern-docs/ui/src/mdx/plugins/rehypeFernComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export function rehypeFernComponents(): (tree: Root) => void {
// node.name = "Table";
} else if (node.name === "embed") {
node.name = "Embed";
} else if (node.name === "a") {
node.name = "A";
}
}
});
Expand Down

0 comments on commit 37aaf02

Please sign in to comment.