Skip to content

Commit

Permalink
feat: automatically forward block props to children of BlocksRenderer
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasio committed Jul 12, 2024
1 parent 68db922 commit 0e6e5e3
Show file tree
Hide file tree
Showing 30 changed files with 202 additions and 124 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/core/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'whatwg-fetch';
import 'isomorphic-fetch';
import { TextDecoder, TextEncoder } from 'util';
import { server } from './test/server';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"msw": "^0.35.0",
"ts-jest": "^29.0.3",
"typescript": "^5.4.5",
"whatwg-fetch": "^3.6.2",
"isomorphic-fetch": "^3.0.0",
"tsc-esm-fix": "^2.20.27",
"@types/react": "^18",
"@types/react-dom": "^18"
Expand Down
92 changes: 92 additions & 0 deletions packages/core/src/dom/parseBlockAttributes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Element } from 'html-react-parser';
import { FrameworkError, warn } from '../utils';

export interface IDataWPBlock {
[key: string]: unknown;
}

const BLOCK_MISSING = '_HEADLESS_/_MISSING__BLOCK_';

export const DEFAULT_BLOCK_ELEMENT = new Element('div', {
'data-wp-block': JSON.stringify({}),
'data-wp-block-name': BLOCK_MISSING,
});

/**
* Parses Json without throwing errors
*
* @param json Serialized JSON
* @returns JSON object
*/
function safeParsing(json): Record<string, any> {
let parsed = {};

try {
parsed = JSON.parse(json);
} catch (e) {
// do nothing
}

return parsed;
}

/**
* Represents a parsed block, i.e a block parsed from `data-wp-block` and `data-wp-block-name` attributes
*/
export type ParsedBlock = {
/**
* The Block attributes
*/
attributes: IDataWPBlock;

/**
* The Block name
*/
name: string;

/**
* The Block class name
*/
className: string;
};

/**
* Returns the block name and attributes
*
* @param node DomNode
*
* @returns
*/
export function parseBlockAttributes(node?: Element): ParsedBlock {
if (typeof node === 'undefined') {
throw new FrameworkError('You are calling `parseBlockAttributes` on a undefined node');
}

if (
typeof node.attribs['data-wp-block-name'] === 'undefined' &&
typeof node.attribs['data-wp-block'] === 'undefined'
) {
warn(
'[parseBlockAttributes] You are using the `parseBlockAttributes` hook in a node that is not a block.',
);
}

const blockName = node.attribs['data-wp-block-name'] || '';

if (blockName === BLOCK_MISSING) {
if (typeof node === 'undefined') {
throw new FrameworkError('You are calling `parseBlockAttributes` on a undefined node');
}
}

const attrs: IDataWPBlock = node.attribs['data-wp-block']
? safeParsing(node.attribs['data-wp-block'])
: {};

if (attrs.style) {
attrs.styleConfig = attrs.style;
delete attrs.style;
}

return { attributes: attrs, name: blockName, className: node.attribs.class };
}
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/AudioBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Element, Text } from 'html-react-parser';
import { isBlock } from '../../dom';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';

/**
* The interface for components rendered by {@link AudioBlock}
Expand Down Expand Up @@ -56,7 +57,7 @@ export interface IAudioBlock extends IBlock<AudioBlockProps> {}
*
*/
export function AudioBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ButtonBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { isBlock } from '../../dom';
import { IBlock } from '../components';
import { IBlockAttributes } from './types';

import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';

/**
* The interface for components rendered by {@link ButtonBlock}
Expand Down Expand Up @@ -60,7 +61,7 @@ export interface IButtonBlock extends IBlock<ButtonBlockProps> {}
*
*/
export function ButtonBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ButtonsBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface ButtonsBlockProps extends IBlockAttributes {}
Expand All @@ -26,7 +27,7 @@ export interface IButtonsBlock extends IBlock<ButtonsBlockProps> {}
* @param props Component properties
*/
export function ButtonsBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { IBlockAttributes } from './types';

Expand Down Expand Up @@ -30,7 +31,7 @@ export interface ICodeBlock extends IBlock<CodeBlockProps> {}
* @param props Component properties
*/
export function CodeBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ColumnBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { IBlockAttributes } from './types';

Expand All @@ -9,7 +10,7 @@ export interface ColumnBlockProps extends IBlockAttributes {}
export interface IColumnBlock extends IBlock<ColumnBlockProps> {}

export function ColumnBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ColumnsBlocks.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { IBlockAttributes } from './types';

Expand All @@ -9,7 +10,7 @@ export interface ColumnsBlockProps extends IBlockAttributes {}
export interface IColumnsBlock extends IBlock<ColumnsBlockProps> {}

export function ColumnsBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/CoverBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { IBlockAttributes } from './types';

Expand All @@ -22,7 +23,7 @@ export interface CoverBlockProps extends IBlockAttributes {
export interface ICoverBlock extends IBlock<CoverBlockProps> {}

export function CoverBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/DebugBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { lazy } from 'react';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';

const ObjectInspector = lazy(() =>
import('react-inspector').then(({ ObjectInspector }) => ({ default: ObjectInspector })),
);
export const DebugBlock = ({ children, domNode: node = defaultElement, ...props }) => {
export const DebugBlock = ({ children, domNode: node = DEFAULT_BLOCK_ELEMENT, ...props }) => {
const { attributes } = useBlock(node);
return (
<div
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/FileBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface FileBlockProps extends IBlockAttributes {
Expand All @@ -12,7 +13,7 @@ export interface FileBlockProps extends IBlockAttributes {
export interface IFileBlock extends IBlock<FileBlockProps> {}

export function FileBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/GroupBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlockByName } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface GroupBlockProps extends IBlockAttributes {
Expand All @@ -15,7 +16,7 @@ export interface GroupBlockProps extends IBlockAttributes {
export interface IGroupBlock extends IBlock<GroupBlockProps> {}

export function GroupBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/HeadingBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlockByName } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface HeadingBlockProps extends IBlockAttributes {
Expand All @@ -10,7 +11,7 @@ export interface HeadingBlockProps extends IBlockAttributes {
export interface IHeadingBlock extends IBlock<HeadingBlockProps> {}

export function HeadingBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ImageBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Element } from 'html-react-parser';
import { isBlockByName } from '../../dom';
import { IBlock } from '../components';
import { defaultElement, useBlock } from './hooks';
import { useBlock } from './hooks';
import { useBlockAttributes } from './hooks/useBlockAttributes';
import { IBlockAttributes } from './types';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';

export interface ImageBlockProps extends IBlockAttributes {
width?: number;
Expand All @@ -17,7 +18,7 @@ export interface ImageBlockProps extends IBlockAttributes {
export interface IImageBlock extends IBlock<ImageBlockProps> {}

export function ImageBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ListBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlockByName } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface ListBlockProps extends IBlockAttributes {
Expand All @@ -10,7 +11,7 @@ export interface ListBlockProps extends IBlockAttributes {
export interface IListBlock extends IBlock<ListBlockProps> {}

export function ListBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/MediaTextBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isBlock } from '../../dom';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';

export interface MediaTextBlockProps extends IBlockAttributes {
Expand All @@ -20,7 +21,7 @@ export interface MediaTextBlockProps extends IBlockAttributes {
export interface IMediaTextBlock extends IBlock<MediaTextBlockProps> {}

export function MediaTextBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
children,
component: Component,
style,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/react/blocks/ParagraphBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Element } from 'html-react-parser';
import { isBlockByName } from '../../dom';
import { IBlock } from '../components';
import { defaultElement, useBlock, useBlockAttributes } from './hooks';
import { useBlock, useBlockAttributes } from './hooks';
import { IBlockAttributes } from './types';
import { DEFAULT_BLOCK_ELEMENT } from '../../dom/parseBlockAttributes';

export interface ParagraphBlockProps extends IBlockAttributes {
dropCap?: boolean;
Expand All @@ -11,7 +12,7 @@ export interface ParagraphBlockProps extends IBlockAttributes {
export interface IParagraphBlock extends IBlock<ParagraphBlockProps> {}

export function ParagraphBlock({
domNode: node = defaultElement,
domNode: node = DEFAULT_BLOCK_ELEMENT,
component: Component,
children,
style,
Expand Down
Loading

0 comments on commit 0e6e5e3

Please sign in to comment.