Start rendering images

This commit is contained in:
Samy Pessé
2023-10-29 09:05:48 -04:00
parent 873570543f
commit cca37bc9e8
2 changed files with 82 additions and 8 deletions
+63 -7
View File
@@ -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
View File
@@ -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;
}