mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-22 18:43:29 +00:00
Start rendering images
This commit is contained in:
@@ -1,15 +1,71 @@
|
||||
import Image from 'next/image'
|
||||
|
||||
import { BlockProps } from './Block';
|
||||
import { Blocks } from './Blocks';
|
||||
import { ContentRefContext, resolveContentRef } from '@/lib/references';
|
||||
import { ClassValue, tcls } from '@/lib/tailwind';
|
||||
import { getNodeFragmentByName, isNodeEmpty } from '@/lib/document';
|
||||
import { Inlines } from './Inlines';
|
||||
|
||||
export function Images(props: BlockProps<any>) {
|
||||
const { block, style, ...contextProps } = props;
|
||||
|
||||
return (
|
||||
<Blocks
|
||||
{...contextProps}
|
||||
tag="div"
|
||||
nodes={block.nodes}
|
||||
style={[style, 'w-full', 'max-w-full', 'bg-slate-200', 'rounded', 'h-56']}
|
||||
/>
|
||||
<div className={tcls(
|
||||
'w-full',
|
||||
'flex',
|
||||
'flex-row',
|
||||
block.data.align === 'center' && 'justify-center',
|
||||
block.data.align === 'right' && 'justify-end',
|
||||
block.data.align === 'left' && 'justify-start',
|
||||
style,
|
||||
block.data.fullWidth ? 'max-w-full' : null,
|
||||
)}>
|
||||
{block.nodes.map((node: any, i: number) => (
|
||||
<ImageBlock
|
||||
key={node.key}
|
||||
block={node}
|
||||
style={[i > 0 && 'mt-4', style]}
|
||||
siblings={block.nodes.length}
|
||||
{...contextProps}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
async function ImageBlock(props: {
|
||||
block: any;
|
||||
style: ClassValue;
|
||||
context: ContentRefContext;
|
||||
siblings: number;
|
||||
}) {
|
||||
const { block, context, siblings } = props;
|
||||
|
||||
const [src, darkSrc] = await Promise.all([
|
||||
resolveContentRef(block.data.ref, context),
|
||||
block.data.darkRef ? resolveContentRef(block.data.darkRef, context) : null
|
||||
]);
|
||||
|
||||
if (!src) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const caption = getNodeFragmentByName(block, 'caption');
|
||||
|
||||
const image = (
|
||||
<img alt={block.data.alt} src={src.href} className={tcls('rounded')} />
|
||||
);
|
||||
|
||||
if (!caption || isNodeEmpty(caption)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
return (
|
||||
<picture className={tcls('relative')}>
|
||||
{image}
|
||||
<figcaption className={tcls('text-sm', 'text-center', 'mt-2', 'text-slate-500')}>
|
||||
<Inlines nodes={caption.nodes[0].nodes} context={context} />
|
||||
</figcaption>
|
||||
</picture>
|
||||
);
|
||||
}
|
||||
|
||||
+19
-1
@@ -9,7 +9,7 @@ export interface DocumentSection {
|
||||
*/
|
||||
export function hasFullWidthBlock(document: any): boolean {
|
||||
return document.nodes.some((node) => {
|
||||
return node.data.fullWidth || node.type === 'images';
|
||||
return node.data.fullWidth;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ export function getNodeText(node: any): string {
|
||||
switch (node.object) {
|
||||
case 'text':
|
||||
return node.leaves.map((leaf) => leaf.text).join('');
|
||||
case 'fragment':
|
||||
case 'block':
|
||||
case 'inline':
|
||||
return node.nodes.map((child) => getNodeText(child)).join('');
|
||||
@@ -65,3 +66,20 @@ export function getNodeFragmentByType(node: any, type: string): any {
|
||||
const fragment = node.fragments?.find((child: any) => child.type === type);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fragment by its `fragment` name in a node.
|
||||
*/
|
||||
export function getNodeFragmentByName(node: any, name: string): any {
|
||||
const fragment = node.fragments?.find((child: any) => child.fragment === name);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a node is empty.
|
||||
*/
|
||||
export function isNodeEmpty(node: any): boolean {
|
||||
const text = getNodeText(node);
|
||||
return text.trim().length === 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user