Refactor content reference resolution to use context.getContentRef method across components

This commit is contained in:
Nicolas Dorseuil
2025-06-16 10:12:40 +02:00
parent 7b4908c8fd
commit 82ed911cd8
10 changed files with 34 additions and 55 deletions
@@ -1,19 +1,17 @@
import { type DocumentBlockContentRef, SiteInsightsLinkPosition } from '@gitbook/api';
import { Card } from '@/components/primitives';
import { type ResolvedContentRef, resolveContentRef } from '@/lib/references';
import type { ResolvedContentRef } from '@/lib/references';
import type { BlockProps } from './Block';
export async function BlockContentRef(props: BlockProps<DocumentBlockContentRef>) {
const { block, context, style } = props;
const resolved = context.contentContext
? await resolveContentRef(block.data.ref, context.contentContext, {
resolveAnchorText: true,
iconStyle: ['text-xl', 'text-tint'],
})
: null;
const resolved = await context.getContentRef(block.data.ref, {
resolveAnchorText: true,
iconStyle: ['text-xl', 'text-tint'],
});
if (!resolved) {
return null;
@@ -1,7 +1,5 @@
import type { DocumentBlockDrawing } from '@gitbook/api';
import { resolveContentRef } from '@/lib/references';
import { Image } from '../utils';
import type { BlockProps } from './Block';
import { Caption } from './Caption';
@@ -9,11 +7,12 @@ import { imageBlockSizes } from './Images';
export async function Drawing(props: BlockProps<DocumentBlockDrawing>) {
const { block, context } = props;
if (!block.data.ref) {
return null;
}
const resolved = await context.getContentRef(block.data.ref);
const resolved =
block.data.ref && context.contentContext
? await resolveContentRef(block.data.ref, context.contentContext)
: null;
if (!resolved) {
return null;
}
@@ -1,7 +1,6 @@
import { type DocumentBlockFile, SiteInsightsLinkPosition } from '@gitbook/api';
import { getSimplifiedContentType } from '@/lib/files';
import { resolveContentRef } from '@/lib/references';
import { tcls } from '@/lib/tailwind';
import { Link } from '../primitives';
@@ -12,9 +11,8 @@ import { FileIcon } from './FileIcon';
export async function File(props: BlockProps<DocumentBlockFile>) {
const { block, context } = props;
const contentRef = context.contentContext
? await resolveContentRef(block.data.ref, context.contentContext)
: null;
const contentRef = await context.getContentRef(block.data.ref);
const file = contentRef?.file;
if (!file) {
@@ -1,7 +1,6 @@
import type { DocumentBlockImage, DocumentBlockImages, JSONDocument, Length } from '@gitbook/api';
import { Image, type ImageResponsiveSize } from '@/components/utils';
import { resolveContentRef } from '@/lib/references';
import { type ClassValue, tcls } from '@/lib/tailwind';
import type { BlockProps } from './Block';
@@ -66,10 +65,8 @@ async function ImageBlock(props: {
const { block, context, isEstimatedOffscreen } = props;
const [src, darkSrc] = await Promise.all([
context.contentContext ? resolveContentRef(block.data.ref, context.contentContext) : null,
block.data.refDark && context.contentContext
? resolveContentRef(block.data.refDark, context.contentContext)
: null,
context.getContentRef(block.data.ref),
block.data.refDark ? context.getContentRef(block.data.refDark) : null,
]);
if (!src) {
@@ -1,4 +1,3 @@
import { resolveContentRef } from '@/lib/references';
import * as api from '@gitbook/api';
import { Button } from '../primitives';
import type { InlineProps } from './Inline';
@@ -10,7 +9,7 @@ export async function InlineButton(props: InlineProps<api.DocumentInlineButton>)
throw new Error('InlineButton requires a contentContext');
}
const resolved = await resolveContentRef(inline.data.ref, context.contentContext);
const resolved = await context.getContentRef(inline.data.ref);
if (!resolved) {
return null;
@@ -2,7 +2,7 @@ import type { DocumentInlineImage } from '@gitbook/api';
import type { GitBookBaseContext } from '@v2/lib/context';
import assertNever from 'assert-never';
import { type ResolvedContentRef, resolveContentRef } from '@/lib/references';
import type { ResolvedContentRef } from '@/lib/references';
import { tcls } from '@/lib/tailwind';
import { Image } from '../utils';
@@ -13,10 +13,8 @@ export async function InlineImage(props: InlineProps<DocumentInlineImage>) {
const { size = 'original' } = inline.data;
const [src, darkSrc] = await Promise.all([
context.contentContext ? resolveContentRef(inline.data.ref, context.contentContext) : null,
inline.data.refDark && context.contentContext
? resolveContentRef(inline.data.refDark, context.contentContext)
: null,
context.getContentRef(inline.data.ref),
inline.data.refDark ? context.getContentRef(inline.data.refDark) : null,
]);
if (!src) {
@@ -1,18 +1,15 @@
import { type DocumentInlineMention, SiteInsightsLinkPosition } from '@gitbook/api';
import { StyledLink } from '@/components/primitives';
import { resolveContentRef } from '@/lib/references';
import type { InlineProps } from './Inline';
export async function Mention(props: InlineProps<DocumentInlineMention>) {
const { inline, context } = props;
const resolved = context.contentContext
? await resolveContentRef(inline.data.ref, context.contentContext, {
resolveAnchorText: true,
})
: null;
const resolved = await context.getContentRef(inline.data.ref, {
resolveAnchorText: true,
});
if (!resolved) {
return null;
@@ -18,6 +18,7 @@ export async function ReusableContent(props: BlockProps<DocumentBlockReusableCon
? context.contentContext.dataFetcher.withToken({ apiToken: block.meta.token })
: context.contentContext.dataFetcher;
// TODO: prefetch the reusable content as well
const resolved = await resolveContentRef(block.data.ref, {
...context.contentContext,
dataFetcher,
@@ -12,7 +12,6 @@ import { StyledLink } from '@/components/primitives';
import { Image } from '@/components/utils';
import { getNodeFragmentByName } from '@/lib/document';
import { getSimplifiedContentType } from '@/lib/files';
import { resolveContentRef } from '@/lib/references';
import { tcls } from '@/lib/tailwind';
import { filterOutNullable } from '@/lib/typescript';
@@ -145,15 +144,10 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
case 'files': {
const files = await Promise.all(
(value as string[]).map((fileId) =>
context.contentContext
? resolveContentRef(
{
kind: 'file',
file: fileId,
},
context.contentContext
)
: null
context.getContentRef({
kind: 'file',
file: fileId,
})
)
);
@@ -217,13 +211,12 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
}
case 'content-ref': {
const contentRef = value ? (value as ContentRef) : null;
const resolved =
contentRef && context.contentContext
? await resolveContentRef(contentRef, context.contentContext, {
resolveAnchorText: true,
iconStyle: ['mr-2', 'text-tint-subtle'],
})
: null;
const resolved = contentRef
? await context.getContentRef(contentRef, {
resolveAnchorText: true,
iconStyle: ['mr-2', 'text-tint-subtle'],
})
: null;
return (
<Tag
className={tcls('text-base', 'text-balance', 'flex', 'items-center')}
@@ -258,9 +251,7 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
kind: 'user',
user: userId,
};
const resolved = context.contentContext
? await resolveContentRef(contentRef, context.contentContext)
: null;
const resolved = await context.getContentRef(contentRef);
if (!resolved) {
return null;
}
@@ -34,6 +34,7 @@ export function FooterLinksGroup(props: {
async function FooterLink(props: { link: CustomizationContentLink; context: GitBookAnyContext }) {
const { link, context } = props;
// TODO: prefetch content ref outside of the main document
const resolved = await resolveContentRef(link.to, context);
if (!resolved) {